Merge branch 'master' of https://github.com/MediaBrowser/Emby
This commit is contained in:
commit
673e2c9d0f
|
@ -829,18 +829,7 @@ namespace Emby.Drawing
|
||||||
// Run the enhancers sequentially in order of priority
|
// Run the enhancers sequentially in order of priority
|
||||||
foreach (var enhancer in imageEnhancers)
|
foreach (var enhancer in imageEnhancers)
|
||||||
{
|
{
|
||||||
var typeName = enhancer.GetType().Name;
|
await enhancer.EnhanceImageAsync(item, inputPath, outputPath, imageType, imageIndex).ConfigureAwait(false);
|
||||||
|
|
||||||
try
|
|
||||||
{
|
|
||||||
await enhancer.EnhanceImageAsync(item, inputPath, outputPath, imageType, imageIndex).ConfigureAwait(false);
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
_logger.ErrorException("{0} failed enhancing {1}", ex, typeName, item.Name);
|
|
||||||
|
|
||||||
throw;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Feed the output into the next enhancer as input
|
// Feed the output into the next enhancer as input
|
||||||
inputPath = outputPath;
|
inputPath = outputPath;
|
||||||
|
|
|
@ -8,6 +8,7 @@ using MediaBrowser.Model.Configuration;
|
||||||
using MediaBrowser.Model.Logging;
|
using MediaBrowser.Model.Logging;
|
||||||
using MediaBrowser.Model.Session;
|
using MediaBrowser.Model.Session;
|
||||||
using System;
|
using System;
|
||||||
|
using System.Collections.Concurrent;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
|
@ -15,6 +16,7 @@ using System.Linq;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using CommonIO;
|
using CommonIO;
|
||||||
|
using MediaBrowser.Model.Dto;
|
||||||
|
|
||||||
namespace MediaBrowser.Api
|
namespace MediaBrowser.Api
|
||||||
{
|
{
|
||||||
|
@ -43,7 +45,13 @@ namespace MediaBrowser.Api
|
||||||
private readonly IFileSystem _fileSystem;
|
private readonly IFileSystem _fileSystem;
|
||||||
private readonly IMediaSourceManager _mediaSourceManager;
|
private readonly IMediaSourceManager _mediaSourceManager;
|
||||||
|
|
||||||
public readonly SemaphoreSlim TranscodingStartLock = new SemaphoreSlim(1, 1);
|
/// <summary>
|
||||||
|
/// The active transcoding jobs
|
||||||
|
/// </summary>
|
||||||
|
private readonly List<TranscodingJob> _activeTranscodingJobs = new List<TranscodingJob>();
|
||||||
|
|
||||||
|
private readonly Dictionary<string, SemaphoreSlim> _transcodingLocks =
|
||||||
|
new Dictionary<string, SemaphoreSlim>();
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Initializes a new instance of the <see cref="ApiEntryPoint" /> class.
|
/// Initializes a new instance of the <see cref="ApiEntryPoint" /> class.
|
||||||
|
@ -66,6 +74,21 @@ namespace MediaBrowser.Api
|
||||||
_sessionManager.PlaybackStart += _sessionManager_PlaybackStart;
|
_sessionManager.PlaybackStart += _sessionManager_PlaybackStart;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public SemaphoreSlim GetTranscodingLock(string outputPath)
|
||||||
|
{
|
||||||
|
lock (_transcodingLocks)
|
||||||
|
{
|
||||||
|
SemaphoreSlim result;
|
||||||
|
if (!_transcodingLocks.TryGetValue(outputPath, out result))
|
||||||
|
{
|
||||||
|
result = new SemaphoreSlim(1, 1);
|
||||||
|
_transcodingLocks[outputPath] = result;
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private void _sessionManager_PlaybackStart(object sender, PlaybackProgressEventArgs e)
|
private void _sessionManager_PlaybackStart(object sender, PlaybackProgressEventArgs e)
|
||||||
{
|
{
|
||||||
if (!string.IsNullOrWhiteSpace(e.PlaySessionId))
|
if (!string.IsNullOrWhiteSpace(e.PlaySessionId))
|
||||||
|
@ -147,11 +170,6 @@ namespace MediaBrowser.Api
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// The active transcoding jobs
|
|
||||||
/// </summary>
|
|
||||||
private readonly List<TranscodingJob> _activeTranscodingJobs = new List<TranscodingJob>();
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Called when [transcode beginning].
|
/// Called when [transcode beginning].
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
@ -187,7 +205,8 @@ namespace MediaBrowser.Api
|
||||||
CancellationTokenSource = cancellationTokenSource,
|
CancellationTokenSource = cancellationTokenSource,
|
||||||
Id = transcodingJobId,
|
Id = transcodingJobId,
|
||||||
PlaySessionId = playSessionId,
|
PlaySessionId = playSessionId,
|
||||||
LiveStreamId = liveStreamId
|
LiveStreamId = liveStreamId,
|
||||||
|
MediaSource = state.MediaSource
|
||||||
};
|
};
|
||||||
|
|
||||||
_activeTranscodingJobs.Add(job);
|
_activeTranscodingJobs.Add(job);
|
||||||
|
@ -256,6 +275,11 @@ namespace MediaBrowser.Api
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
lock (_transcodingLocks)
|
||||||
|
{
|
||||||
|
_transcodingLocks.Remove(path);
|
||||||
|
}
|
||||||
|
|
||||||
if (!string.IsNullOrWhiteSpace(state.Request.DeviceId))
|
if (!string.IsNullOrWhiteSpace(state.Request.DeviceId))
|
||||||
{
|
{
|
||||||
_sessionManager.ClearTranscodingInfo(state.Request.DeviceId);
|
_sessionManager.ClearTranscodingInfo(state.Request.DeviceId);
|
||||||
|
@ -281,6 +305,14 @@ namespace MediaBrowser.Api
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public TranscodingJob GetTranscodingJob(string playSessionId)
|
||||||
|
{
|
||||||
|
lock (_activeTranscodingJobs)
|
||||||
|
{
|
||||||
|
return _activeTranscodingJobs.FirstOrDefault(j => string.Equals(j.PlaySessionId, playSessionId, StringComparison.OrdinalIgnoreCase));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Called when [transcode begin request].
|
/// Called when [transcode begin request].
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
@ -487,6 +519,11 @@ namespace MediaBrowser.Api
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
lock (_transcodingLocks)
|
||||||
|
{
|
||||||
|
_transcodingLocks.Remove(job.Path);
|
||||||
|
}
|
||||||
|
|
||||||
lock (job.ProcessLock)
|
lock (job.ProcessLock)
|
||||||
{
|
{
|
||||||
if (job.TranscodingThrottler != null)
|
if (job.TranscodingThrottler != null)
|
||||||
|
@ -530,7 +567,7 @@ namespace MediaBrowser.Api
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
await _mediaSourceManager.CloseLiveStream(job.LiveStreamId, CancellationToken.None).ConfigureAwait(false);
|
await _mediaSourceManager.CloseLiveStream(job.LiveStreamId).ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
|
@ -656,6 +693,7 @@ namespace MediaBrowser.Api
|
||||||
/// Gets or sets the path.
|
/// Gets or sets the path.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <value>The path.</value>
|
/// <value>The path.</value>
|
||||||
|
public MediaSourceInfo MediaSource { get; set; }
|
||||||
public string Path { get; set; }
|
public string Path { get; set; }
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets or sets the type.
|
/// Gets or sets the type.
|
||||||
|
@ -751,12 +789,12 @@ namespace MediaBrowser.Api
|
||||||
{
|
{
|
||||||
if (KillTimer == null)
|
if (KillTimer == null)
|
||||||
{
|
{
|
||||||
Logger.Debug("Starting kill timer at {0}ms. JobId {1} PlaySessionId {2}", intervalMs, Id, PlaySessionId);
|
//Logger.Debug("Starting kill timer at {0}ms. JobId {1} PlaySessionId {2}", intervalMs, Id, PlaySessionId);
|
||||||
KillTimer = new Timer(callback, this, intervalMs, Timeout.Infinite);
|
KillTimer = new Timer(callback, this, intervalMs, Timeout.Infinite);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Logger.Debug("Changing kill timer to {0}ms. JobId {1} PlaySessionId {2}", intervalMs, Id, PlaySessionId);
|
//Logger.Debug("Changing kill timer to {0}ms. JobId {1} PlaySessionId {2}", intervalMs, Id, PlaySessionId);
|
||||||
KillTimer.Change(intervalMs, Timeout.Infinite);
|
KillTimer.Change(intervalMs, Timeout.Infinite);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -775,7 +813,7 @@ namespace MediaBrowser.Api
|
||||||
{
|
{
|
||||||
var intervalMs = PingTimeout;
|
var intervalMs = PingTimeout;
|
||||||
|
|
||||||
Logger.Debug("Changing kill timer to {0}ms. JobId {1} PlaySessionId {2}", intervalMs, Id, PlaySessionId);
|
//Logger.Debug("Changing kill timer to {0}ms. JobId {1} PlaySessionId {2}", intervalMs, Id, PlaySessionId);
|
||||||
KillTimer.Change(intervalMs, Timeout.Infinite);
|
KillTimer.Change(intervalMs, Timeout.Infinite);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,6 +7,8 @@ using System.Globalization;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
using MediaBrowser.Common.IO;
|
||||||
|
using MediaBrowser.Controller.IO;
|
||||||
|
|
||||||
namespace MediaBrowser.Api.Dlna
|
namespace MediaBrowser.Api.Dlna
|
||||||
{
|
{
|
||||||
|
@ -109,13 +111,15 @@ namespace MediaBrowser.Api.Dlna
|
||||||
private readonly IMediaReceiverRegistrar _mediaReceiverRegistrar;
|
private readonly IMediaReceiverRegistrar _mediaReceiverRegistrar;
|
||||||
|
|
||||||
private const string XMLContentType = "text/xml; charset=UTF-8";
|
private const string XMLContentType = "text/xml; charset=UTF-8";
|
||||||
|
private readonly IMemoryStreamProvider _memoryStreamProvider;
|
||||||
|
|
||||||
public DlnaServerService(IDlnaManager dlnaManager, IContentDirectory contentDirectory, IConnectionManager connectionManager, IMediaReceiverRegistrar mediaReceiverRegistrar)
|
public DlnaServerService(IDlnaManager dlnaManager, IContentDirectory contentDirectory, IConnectionManager connectionManager, IMediaReceiverRegistrar mediaReceiverRegistrar, IMemoryStreamProvider memoryStreamProvider)
|
||||||
{
|
{
|
||||||
_dlnaManager = dlnaManager;
|
_dlnaManager = dlnaManager;
|
||||||
_contentDirectory = contentDirectory;
|
_contentDirectory = contentDirectory;
|
||||||
_connectionManager = connectionManager;
|
_connectionManager = connectionManager;
|
||||||
_mediaReceiverRegistrar = mediaReceiverRegistrar;
|
_mediaReceiverRegistrar = mediaReceiverRegistrar;
|
||||||
|
_memoryStreamProvider = memoryStreamProvider;
|
||||||
}
|
}
|
||||||
|
|
||||||
public object Get(GetDescriptionXml request)
|
public object Get(GetDescriptionXml request)
|
||||||
|
@ -201,7 +205,7 @@ namespace MediaBrowser.Api.Dlna
|
||||||
{
|
{
|
||||||
using (var response = _dlnaManager.GetIcon(request.Filename))
|
using (var response = _dlnaManager.GetIcon(request.Filename))
|
||||||
{
|
{
|
||||||
using (var ms = new MemoryStream())
|
using (var ms = _memoryStreamProvider.CreateNew())
|
||||||
{
|
{
|
||||||
response.Stream.CopyTo(ms);
|
response.Stream.CopyTo(ms);
|
||||||
|
|
||||||
|
|
|
@ -4,6 +4,7 @@ using MediaBrowser.Controller.Net;
|
||||||
using MediaBrowser.Model.Querying;
|
using MediaBrowser.Model.Querying;
|
||||||
using ServiceStack;
|
using ServiceStack;
|
||||||
using System;
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
@ -104,7 +105,13 @@ namespace MediaBrowser.Api
|
||||||
MediaTypes = request.GetMediaTypes(),
|
MediaTypes = request.GetMediaTypes(),
|
||||||
IncludeItemTypes = request.GetIncludeItemTypes(),
|
IncludeItemTypes = request.GetIncludeItemTypes(),
|
||||||
Recursive = true,
|
Recursive = true,
|
||||||
EnableTotalRecordCount = false
|
EnableTotalRecordCount = false,
|
||||||
|
DtoOptions = new Controller.Dto.DtoOptions
|
||||||
|
{
|
||||||
|
Fields = new List<ItemFields> { ItemFields.Genres, ItemFields.Tags },
|
||||||
|
EnableImages = false,
|
||||||
|
EnableUserData = false
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
return query;
|
return query;
|
||||||
|
|
|
@ -200,6 +200,8 @@ namespace MediaBrowser.Api
|
||||||
(!string.IsNullOrWhiteSpace(request.UserId) ? user.RootFolder :
|
(!string.IsNullOrWhiteSpace(request.UserId) ? user.RootFolder :
|
||||||
_libraryManager.RootFolder) : _libraryManager.GetItemById(request.Id);
|
_libraryManager.RootFolder) : _libraryManager.GetItemById(request.Id);
|
||||||
|
|
||||||
|
var dtoOptions = GetDtoOptions(request);
|
||||||
|
|
||||||
var itemsResult = _libraryManager.GetItemList(new InternalItemsQuery(user)
|
var itemsResult = _libraryManager.GetItemList(new InternalItemsQuery(user)
|
||||||
{
|
{
|
||||||
Limit = request.Limit,
|
Limit = request.Limit,
|
||||||
|
@ -207,12 +209,11 @@ namespace MediaBrowser.Api
|
||||||
{
|
{
|
||||||
typeof(Game).Name
|
typeof(Game).Name
|
||||||
},
|
},
|
||||||
SimilarTo = item
|
SimilarTo = item,
|
||||||
|
DtoOptions = dtoOptions
|
||||||
|
|
||||||
}).ToList();
|
}).ToList();
|
||||||
|
|
||||||
var dtoOptions = GetDtoOptions(request);
|
|
||||||
|
|
||||||
var result = new QueryResult<BaseItemDto>
|
var result = new QueryResult<BaseItemDto>
|
||||||
{
|
{
|
||||||
Items = (await _dtoService.GetBaseItemDtos(itemsResult, dtoOptions, user).ConfigureAwait(false)).ToArray(),
|
Items = (await _dtoService.GetBaseItemDtos(itemsResult, dtoOptions, user).ConfigureAwait(false)).ToArray(),
|
||||||
|
|
|
@ -273,7 +273,8 @@ namespace MediaBrowser.Api.Images
|
||||||
{
|
{
|
||||||
var result = await _httpClient.GetResponse(new HttpRequestOptions
|
var result = await _httpClient.GetResponse(new HttpRequestOptions
|
||||||
{
|
{
|
||||||
Url = url
|
Url = url,
|
||||||
|
BufferContent = false
|
||||||
|
|
||||||
}).ConfigureAwait(false);
|
}).ConfigureAwait(false);
|
||||||
|
|
||||||
|
|
|
@ -243,11 +243,7 @@ namespace MediaBrowser.Api
|
||||||
hasBudget.Revenue = request.Revenue;
|
hasBudget.Revenue = request.Revenue;
|
||||||
}
|
}
|
||||||
|
|
||||||
var hasOriginalTitle = item as IHasOriginalTitle;
|
item.OriginalTitle = string.IsNullOrWhiteSpace(request.OriginalTitle) ? null : request.OriginalTitle;
|
||||||
if (hasOriginalTitle != null)
|
|
||||||
{
|
|
||||||
hasOriginalTitle.OriginalTitle = hasOriginalTitle.OriginalTitle;
|
|
||||||
}
|
|
||||||
|
|
||||||
var hasCriticRating = item as IHasCriticRating;
|
var hasCriticRating = item as IHasCriticRating;
|
||||||
if (hasCriticRating != null)
|
if (hasCriticRating != null)
|
||||||
|
@ -278,10 +274,9 @@ namespace MediaBrowser.Api
|
||||||
|
|
||||||
item.Tags = request.Tags;
|
item.Tags = request.Tags;
|
||||||
|
|
||||||
var hasTaglines = item as IHasTaglines;
|
if (request.Taglines != null)
|
||||||
if (hasTaglines != null)
|
|
||||||
{
|
{
|
||||||
hasTaglines.Taglines = request.Taglines;
|
item.Tagline = request.Taglines.FirstOrDefault();
|
||||||
}
|
}
|
||||||
|
|
||||||
var hasShortOverview = item as IHasShortOverview;
|
var hasShortOverview = item as IHasShortOverview;
|
||||||
|
@ -308,8 +303,6 @@ namespace MediaBrowser.Api
|
||||||
item.OfficialRating = string.IsNullOrWhiteSpace(request.OfficialRating) ? null : request.OfficialRating;
|
item.OfficialRating = string.IsNullOrWhiteSpace(request.OfficialRating) ? null : request.OfficialRating;
|
||||||
item.CustomRating = request.CustomRating;
|
item.CustomRating = request.CustomRating;
|
||||||
|
|
||||||
SetProductionLocations(item, request);
|
|
||||||
|
|
||||||
item.PreferredMetadataCountryCode = request.PreferredMetadataCountryCode;
|
item.PreferredMetadataCountryCode = request.PreferredMetadataCountryCode;
|
||||||
item.PreferredMetadataLanguage = request.PreferredMetadataLanguage;
|
item.PreferredMetadataLanguage = request.PreferredMetadataLanguage;
|
||||||
|
|
||||||
|
@ -417,23 +410,5 @@ namespace MediaBrowser.Api
|
||||||
series.AirTime = request.AirTime;
|
series.AirTime = request.AirTime;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void SetProductionLocations(BaseItem item, BaseItemDto request)
|
|
||||||
{
|
|
||||||
var hasProductionLocations = item as IHasProductionLocations;
|
|
||||||
|
|
||||||
if (hasProductionLocations != null)
|
|
||||||
{
|
|
||||||
hasProductionLocations.ProductionLocations = request.ProductionLocations;
|
|
||||||
}
|
|
||||||
|
|
||||||
var person = item as Person;
|
|
||||||
if (person != null)
|
|
||||||
{
|
|
||||||
person.PlaceOfBirth = request.ProductionLocations == null
|
|
||||||
? null
|
|
||||||
: request.ProductionLocations.FirstOrDefault();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,30 +0,0 @@
|
||||||
using MediaBrowser.Controller.Chapters;
|
|
||||||
using MediaBrowser.Controller.Net;
|
|
||||||
using ServiceStack;
|
|
||||||
using System.Linq;
|
|
||||||
|
|
||||||
namespace MediaBrowser.Api.Library
|
|
||||||
{
|
|
||||||
[Route("/Providers/Chapters", "GET")]
|
|
||||||
public class GetChapterProviders : IReturnVoid
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
[Authenticated]
|
|
||||||
public class ChapterService : BaseApiService
|
|
||||||
{
|
|
||||||
private readonly IChapterManager _chapterManager;
|
|
||||||
|
|
||||||
public ChapterService(IChapterManager chapterManager)
|
|
||||||
{
|
|
||||||
_chapterManager = chapterManager;
|
|
||||||
}
|
|
||||||
|
|
||||||
public object Get(GetChapterProviders request)
|
|
||||||
{
|
|
||||||
var result = _chapterManager.GetProviders().ToList();
|
|
||||||
|
|
||||||
return ToOptimizedResult(result);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -835,14 +835,14 @@ namespace MediaBrowser.Api.Library
|
||||||
: (Folder)_libraryManager.RootFolder)
|
: (Folder)_libraryManager.RootFolder)
|
||||||
: _libraryManager.GetItemById(request.Id);
|
: _libraryManager.GetItemById(request.Id);
|
||||||
|
|
||||||
while (GetThemeSongIds(item).Count == 0 && request.InheritFromParent && item.GetParent() != null)
|
while (item.ThemeSongIds.Count == 0 && request.InheritFromParent && item.GetParent() != null)
|
||||||
{
|
{
|
||||||
item = item.GetParent();
|
item = item.GetParent();
|
||||||
}
|
}
|
||||||
|
|
||||||
var dtoOptions = GetDtoOptions(request);
|
var dtoOptions = GetDtoOptions(request);
|
||||||
|
|
||||||
var dtos = GetThemeSongIds(item).Select(_libraryManager.GetItemById)
|
var dtos = item.ThemeSongIds.Select(_libraryManager.GetItemById)
|
||||||
.Where(i => i != null)
|
.Where(i => i != null)
|
||||||
.OrderBy(i => i.SortName)
|
.OrderBy(i => i.SortName)
|
||||||
.Select(i => _dtoService.GetBaseItemDto(i, dtoOptions, user, item));
|
.Select(i => _dtoService.GetBaseItemDto(i, dtoOptions, user, item));
|
||||||
|
@ -879,14 +879,14 @@ namespace MediaBrowser.Api.Library
|
||||||
: (Folder)_libraryManager.RootFolder)
|
: (Folder)_libraryManager.RootFolder)
|
||||||
: _libraryManager.GetItemById(request.Id);
|
: _libraryManager.GetItemById(request.Id);
|
||||||
|
|
||||||
while (GetThemeVideoIds(item).Count == 0 && request.InheritFromParent && item.GetParent() != null)
|
while (item.ThemeVideoIds.Count == 0 && request.InheritFromParent && item.GetParent() != null)
|
||||||
{
|
{
|
||||||
item = item.GetParent();
|
item = item.GetParent();
|
||||||
}
|
}
|
||||||
|
|
||||||
var dtoOptions = GetDtoOptions(request);
|
var dtoOptions = GetDtoOptions(request);
|
||||||
|
|
||||||
var dtos = GetThemeVideoIds(item).Select(_libraryManager.GetItemById)
|
var dtos = item.ThemeVideoIds.Select(_libraryManager.GetItemById)
|
||||||
.Where(i => i != null)
|
.Where(i => i != null)
|
||||||
.OrderBy(i => i.SortName)
|
.OrderBy(i => i.SortName)
|
||||||
.Select(i => _dtoService.GetBaseItemDto(i, dtoOptions, user, item));
|
.Select(i => _dtoService.GetBaseItemDto(i, dtoOptions, user, item));
|
||||||
|
@ -901,30 +901,6 @@ namespace MediaBrowser.Api.Library
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
private List<Guid> GetThemeVideoIds(BaseItem item)
|
|
||||||
{
|
|
||||||
var i = item as IHasThemeMedia;
|
|
||||||
|
|
||||||
if (i != null)
|
|
||||||
{
|
|
||||||
return i.ThemeVideoIds;
|
|
||||||
}
|
|
||||||
|
|
||||||
return new List<Guid>();
|
|
||||||
}
|
|
||||||
|
|
||||||
private List<Guid> GetThemeSongIds(BaseItem item)
|
|
||||||
{
|
|
||||||
var i = item as IHasThemeMedia;
|
|
||||||
|
|
||||||
if (i != null)
|
|
||||||
{
|
|
||||||
return i.ThemeSongIds;
|
|
||||||
}
|
|
||||||
|
|
||||||
return new List<Guid>();
|
|
||||||
}
|
|
||||||
|
|
||||||
private readonly CultureInfo _usCulture = new CultureInfo("en-US");
|
private readonly CultureInfo _usCulture = new CultureInfo("en-US");
|
||||||
|
|
||||||
public object Get(GetYearIndex request)
|
public object Get(GetYearIndex request)
|
||||||
|
|
|
@ -112,6 +112,8 @@ namespace MediaBrowser.Api.Library
|
||||||
/// <value>The name.</value>
|
/// <value>The name.</value>
|
||||||
public string Path { get; set; }
|
public string Path { get; set; }
|
||||||
|
|
||||||
|
public MediaPathInfo PathInfo { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets or sets a value indicating whether [refresh library].
|
/// Gets or sets a value indicating whether [refresh library].
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
@ -119,6 +121,18 @@ namespace MediaBrowser.Api.Library
|
||||||
public bool RefreshLibrary { get; set; }
|
public bool RefreshLibrary { get; set; }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Route("/Library/VirtualFolders/Paths/Update", "POST")]
|
||||||
|
public class UpdateMediaPath : IReturnVoid
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the name.
|
||||||
|
/// </summary>
|
||||||
|
/// <value>The name.</value>
|
||||||
|
public string Name { get; set; }
|
||||||
|
|
||||||
|
public MediaPathInfo PathInfo { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
[Route("/Library/VirtualFolders/Paths", "DELETE")]
|
[Route("/Library/VirtualFolders/Paths", "DELETE")]
|
||||||
public class RemoveMediaPath : IReturnVoid
|
public class RemoveMediaPath : IReturnVoid
|
||||||
{
|
{
|
||||||
|
@ -212,7 +226,12 @@ namespace MediaBrowser.Api.Library
|
||||||
{
|
{
|
||||||
var libraryOptions = request.LibraryOptions ?? new LibraryOptions();
|
var libraryOptions = request.LibraryOptions ?? new LibraryOptions();
|
||||||
|
|
||||||
_libraryManager.AddVirtualFolder(request.Name, request.CollectionType, request.Paths, libraryOptions, request.RefreshLibrary);
|
if (request.Paths != null && request.Paths.Length > 0)
|
||||||
|
{
|
||||||
|
libraryOptions.PathInfos = request.Paths.Select(i => new MediaPathInfo { Path = i }).ToArray();
|
||||||
|
}
|
||||||
|
|
||||||
|
_libraryManager.AddVirtualFolder(request.Name, request.CollectionType, libraryOptions, request.RefreshLibrary);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -308,7 +327,16 @@ namespace MediaBrowser.Api.Library
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
_libraryManager.AddMediaPath(request.Name, request.Path);
|
var mediaPath = request.PathInfo;
|
||||||
|
|
||||||
|
if (mediaPath == null)
|
||||||
|
{
|
||||||
|
mediaPath = new MediaPathInfo
|
||||||
|
{
|
||||||
|
Path = request.Path
|
||||||
|
};
|
||||||
|
}
|
||||||
|
_libraryManager.AddMediaPath(request.Name, mediaPath);
|
||||||
}
|
}
|
||||||
finally
|
finally
|
||||||
{
|
{
|
||||||
|
@ -332,6 +360,20 @@ namespace MediaBrowser.Api.Library
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Posts the specified request.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="request">The request.</param>
|
||||||
|
public void Post(UpdateMediaPath request)
|
||||||
|
{
|
||||||
|
if (string.IsNullOrWhiteSpace(request.Name))
|
||||||
|
{
|
||||||
|
throw new ArgumentNullException("request");
|
||||||
|
}
|
||||||
|
|
||||||
|
_libraryManager.UpdateMediaPath(request.Name, request.PathInfo);
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Deletes the specified request.
|
/// Deletes the specified request.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|
|
@ -12,9 +12,14 @@ using ServiceStack;
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Globalization;
|
using System.Globalization;
|
||||||
|
using System.IO;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
using CommonIO;
|
||||||
|
using MediaBrowser.Api.Playback.Progressive;
|
||||||
|
using MediaBrowser.Controller.Configuration;
|
||||||
|
using MediaBrowser.Server.Implementations.LiveTv.EmbyTV;
|
||||||
|
|
||||||
namespace MediaBrowser.Api.LiveTv
|
namespace MediaBrowser.Api.LiveTv
|
||||||
{
|
{
|
||||||
|
@ -44,6 +49,21 @@ namespace MediaBrowser.Api.LiveTv
|
||||||
[ApiMember(Name = "StartIndex", Description = "Optional. The record index to start at. All items with a lower index will be dropped from the results.", IsRequired = false, DataType = "int", ParameterType = "query", Verb = "GET")]
|
[ApiMember(Name = "StartIndex", Description = "Optional. The record index to start at. All items with a lower index will be dropped from the results.", IsRequired = false, DataType = "int", ParameterType = "query", Verb = "GET")]
|
||||||
public int? StartIndex { get; set; }
|
public int? StartIndex { get; set; }
|
||||||
|
|
||||||
|
[ApiMember(Name = "IsMovie", Description = "Optional filter for movies.", IsRequired = false, DataType = "bool", ParameterType = "query", Verb = "GET,POST")]
|
||||||
|
public bool? IsMovie { get; set; }
|
||||||
|
|
||||||
|
[ApiMember(Name = "IsSeries", Description = "Optional filter for movies.", IsRequired = false, DataType = "bool", ParameterType = "query", Verb = "GET,POST")]
|
||||||
|
public bool? IsSeries { get; set; }
|
||||||
|
|
||||||
|
[ApiMember(Name = "IsNews", Description = "Optional filter for news.", IsRequired = false, DataType = "bool", ParameterType = "query", Verb = "GET,POST")]
|
||||||
|
public bool? IsNews { get; set; }
|
||||||
|
|
||||||
|
[ApiMember(Name = "IsKids", Description = "Optional filter for kids.", IsRequired = false, DataType = "bool", ParameterType = "query", Verb = "GET,POST")]
|
||||||
|
public bool? IsKids { get; set; }
|
||||||
|
|
||||||
|
[ApiMember(Name = "IsSports", Description = "Optional filter for sports.", IsRequired = false, DataType = "bool", ParameterType = "query", Verb = "GET,POST")]
|
||||||
|
public bool? IsSports { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The maximum number of items to return
|
/// The maximum number of items to return
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
@ -85,6 +105,26 @@ namespace MediaBrowser.Api.LiveTv
|
||||||
[ApiMember(Name = "EnableUserData", Description = "Optional, include user data", IsRequired = false, DataType = "boolean", ParameterType = "query", Verb = "GET")]
|
[ApiMember(Name = "EnableUserData", Description = "Optional, include user data", IsRequired = false, DataType = "boolean", ParameterType = "query", Verb = "GET")]
|
||||||
public bool? EnableUserData { get; set; }
|
public bool? EnableUserData { get; set; }
|
||||||
|
|
||||||
|
public string SortBy { get; set; }
|
||||||
|
|
||||||
|
public SortOrder? SortOrder { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the order by.
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>IEnumerable{ItemSortBy}.</returns>
|
||||||
|
public string[] GetOrderBy()
|
||||||
|
{
|
||||||
|
var val = SortBy;
|
||||||
|
|
||||||
|
if (string.IsNullOrEmpty(val))
|
||||||
|
{
|
||||||
|
return new string[] { };
|
||||||
|
}
|
||||||
|
|
||||||
|
return val.Split(',');
|
||||||
|
}
|
||||||
|
|
||||||
public GetChannels()
|
public GetChannels()
|
||||||
{
|
{
|
||||||
AddCurrentProgram = true;
|
AddCurrentProgram = true;
|
||||||
|
@ -159,6 +199,7 @@ namespace MediaBrowser.Api.LiveTv
|
||||||
public bool? IsSeries { get; set; }
|
public bool? IsSeries { get; set; }
|
||||||
public bool? IsKids { get; set; }
|
public bool? IsKids { get; set; }
|
||||||
public bool? IsSports { get; set; }
|
public bool? IsSports { get; set; }
|
||||||
|
public bool? IsNews { get; set; }
|
||||||
|
|
||||||
public GetRecordings()
|
public GetRecordings()
|
||||||
{
|
{
|
||||||
|
@ -275,6 +316,8 @@ namespace MediaBrowser.Api.LiveTv
|
||||||
public string SeriesTimerId { get; set; }
|
public string SeriesTimerId { get; set; }
|
||||||
|
|
||||||
public bool? IsActive { get; set; }
|
public bool? IsActive { get; set; }
|
||||||
|
|
||||||
|
public bool? IsScheduled { get; set; }
|
||||||
}
|
}
|
||||||
|
|
||||||
[Route("/LiveTv/Programs", "GET,POST", Summary = "Gets available live tv epgs..")]
|
[Route("/LiveTv/Programs", "GET,POST", Summary = "Gets available live tv epgs..")]
|
||||||
|
@ -305,6 +348,12 @@ namespace MediaBrowser.Api.LiveTv
|
||||||
[ApiMember(Name = "IsMovie", Description = "Optional filter for movies.", IsRequired = false, DataType = "bool", ParameterType = "query", Verb = "GET,POST")]
|
[ApiMember(Name = "IsMovie", Description = "Optional filter for movies.", IsRequired = false, DataType = "bool", ParameterType = "query", Verb = "GET,POST")]
|
||||||
public bool? IsMovie { get; set; }
|
public bool? IsMovie { get; set; }
|
||||||
|
|
||||||
|
[ApiMember(Name = "IsSeries", Description = "Optional filter for movies.", IsRequired = false, DataType = "bool", ParameterType = "query", Verb = "GET,POST")]
|
||||||
|
public bool? IsSeries { get; set; }
|
||||||
|
|
||||||
|
[ApiMember(Name = "IsNews", Description = "Optional filter for news.", IsRequired = false, DataType = "bool", ParameterType = "query", Verb = "GET,POST")]
|
||||||
|
public bool? IsNews { get; set; }
|
||||||
|
|
||||||
[ApiMember(Name = "IsKids", Description = "Optional filter for kids.", IsRequired = false, DataType = "bool", ParameterType = "query", Verb = "GET,POST")]
|
[ApiMember(Name = "IsKids", Description = "Optional filter for kids.", IsRequired = false, DataType = "bool", ParameterType = "query", Verb = "GET,POST")]
|
||||||
public bool? IsKids { get; set; }
|
public bool? IsKids { get; set; }
|
||||||
|
|
||||||
|
@ -340,6 +389,8 @@ namespace MediaBrowser.Api.LiveTv
|
||||||
[ApiMember(Name = "EnableUserData", Description = "Optional, include user data", IsRequired = false, DataType = "boolean", ParameterType = "query", Verb = "GET")]
|
[ApiMember(Name = "EnableUserData", Description = "Optional, include user data", IsRequired = false, DataType = "boolean", ParameterType = "query", Verb = "GET")]
|
||||||
public bool? EnableUserData { get; set; }
|
public bool? EnableUserData { get; set; }
|
||||||
|
|
||||||
|
public string SeriesTimerId { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Fields to return within the items, in addition to basic information
|
/// Fields to return within the items, in addition to basic information
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
@ -376,15 +427,21 @@ namespace MediaBrowser.Api.LiveTv
|
||||||
[ApiMember(Name = "HasAired", Description = "Optional. Filter by programs that have completed airing, or not.", IsRequired = false, DataType = "bool", ParameterType = "query", Verb = "GET")]
|
[ApiMember(Name = "HasAired", Description = "Optional. Filter by programs that have completed airing, or not.", IsRequired = false, DataType = "bool", ParameterType = "query", Verb = "GET")]
|
||||||
public bool? HasAired { get; set; }
|
public bool? HasAired { get; set; }
|
||||||
|
|
||||||
[ApiMember(Name = "IsSports", Description = "Optional filter for sports.", IsRequired = false, DataType = "bool", ParameterType = "query", Verb = "GET,POST")]
|
[ApiMember(Name = "IsSeries", Description = "Optional filter for movies.", IsRequired = false, DataType = "bool", ParameterType = "query", Verb = "GET,POST")]
|
||||||
public bool? IsSports { get; set; }
|
public bool? IsSeries { get; set; }
|
||||||
|
|
||||||
[ApiMember(Name = "IsMovie", Description = "Optional filter for movies.", IsRequired = false, DataType = "bool", ParameterType = "query", Verb = "GET")]
|
[ApiMember(Name = "IsMovie", Description = "Optional filter for movies.", IsRequired = false, DataType = "bool", ParameterType = "query", Verb = "GET,POST")]
|
||||||
public bool? IsMovie { get; set; }
|
public bool? IsMovie { get; set; }
|
||||||
|
|
||||||
[ApiMember(Name = "IsKids", Description = "Optional filter for kids.", IsRequired = false, DataType = "bool", ParameterType = "query", Verb = "GET")]
|
[ApiMember(Name = "IsNews", Description = "Optional filter for news.", IsRequired = false, DataType = "bool", ParameterType = "query", Verb = "GET,POST")]
|
||||||
|
public bool? IsNews { get; set; }
|
||||||
|
|
||||||
|
[ApiMember(Name = "IsKids", Description = "Optional filter for kids.", IsRequired = false, DataType = "bool", ParameterType = "query", Verb = "GET,POST")]
|
||||||
public bool? IsKids { get; set; }
|
public bool? IsKids { get; set; }
|
||||||
|
|
||||||
|
[ApiMember(Name = "IsSports", Description = "Optional filter for sports.", IsRequired = false, DataType = "bool", ParameterType = "query", Verb = "GET,POST")]
|
||||||
|
public bool? IsSports { get; set; }
|
||||||
|
|
||||||
[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; }
|
||||||
|
|
||||||
|
@ -613,16 +670,30 @@ namespace MediaBrowser.Api.LiveTv
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Route("/LiveTv/LiveStreamFiles/{Id}/stream.{Container}", "GET", Summary = "Gets a live tv channel")]
|
||||||
|
public class GetLiveStreamFile
|
||||||
|
{
|
||||||
|
public string Id { get; set; }
|
||||||
|
public string Container { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
[Route("/LiveTv/LiveRecordings/{Id}/stream", "GET", Summary = "Gets a live tv channel")]
|
||||||
|
public class GetLiveRecordingFile
|
||||||
|
{
|
||||||
|
public string Id { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
public class LiveTvService : BaseApiService
|
public class LiveTvService : BaseApiService
|
||||||
{
|
{
|
||||||
private readonly ILiveTvManager _liveTvManager;
|
private readonly ILiveTvManager _liveTvManager;
|
||||||
private readonly IUserManager _userManager;
|
private readonly IUserManager _userManager;
|
||||||
private readonly IConfigurationManager _config;
|
private readonly IServerConfigurationManager _config;
|
||||||
private readonly IHttpClient _httpClient;
|
private readonly IHttpClient _httpClient;
|
||||||
private readonly ILibraryManager _libraryManager;
|
private readonly ILibraryManager _libraryManager;
|
||||||
private readonly IDtoService _dtoService;
|
private readonly IDtoService _dtoService;
|
||||||
|
private readonly IFileSystem _fileSystem;
|
||||||
|
|
||||||
public LiveTvService(ILiveTvManager liveTvManager, IUserManager userManager, IConfigurationManager config, IHttpClient httpClient, ILibraryManager libraryManager, IDtoService dtoService)
|
public LiveTvService(ILiveTvManager liveTvManager, IUserManager userManager, IServerConfigurationManager config, IHttpClient httpClient, ILibraryManager libraryManager, IDtoService dtoService, IFileSystem fileSystem)
|
||||||
{
|
{
|
||||||
_liveTvManager = liveTvManager;
|
_liveTvManager = liveTvManager;
|
||||||
_userManager = userManager;
|
_userManager = userManager;
|
||||||
|
@ -630,6 +701,41 @@ namespace MediaBrowser.Api.LiveTv
|
||||||
_httpClient = httpClient;
|
_httpClient = httpClient;
|
||||||
_libraryManager = libraryManager;
|
_libraryManager = libraryManager;
|
||||||
_dtoService = dtoService;
|
_dtoService = dtoService;
|
||||||
|
_fileSystem = fileSystem;
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<object> Get(GetLiveRecordingFile request)
|
||||||
|
{
|
||||||
|
var path = EmbyTV.Current.GetActiveRecordingPath(request.Id);
|
||||||
|
|
||||||
|
if (path == null)
|
||||||
|
{
|
||||||
|
throw new FileNotFoundException();
|
||||||
|
}
|
||||||
|
|
||||||
|
var outputHeaders = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);
|
||||||
|
|
||||||
|
outputHeaders["Content-Type"] = Model.Net.MimeTypes.GetMimeType(path);
|
||||||
|
|
||||||
|
var streamSource = new ProgressiveFileCopier(_fileSystem, path, outputHeaders, null, Logger, CancellationToken.None)
|
||||||
|
{
|
||||||
|
AllowEndOfFile = false
|
||||||
|
};
|
||||||
|
return ResultFactory.GetAsyncStreamWriter(streamSource);
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<object> Get(GetLiveStreamFile request)
|
||||||
|
{
|
||||||
|
var directStreamProvider = (await EmbyTV.Current.GetLiveStream(request.Id).ConfigureAwait(false)) as IDirectStreamProvider;
|
||||||
|
var outputHeaders = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);
|
||||||
|
|
||||||
|
outputHeaders["Content-Type"] = Model.Net.MimeTypes.GetMimeType("file." + request.Container);
|
||||||
|
|
||||||
|
var streamSource = new ProgressiveFileCopier(directStreamProvider, outputHeaders, null, Logger, CancellationToken.None)
|
||||||
|
{
|
||||||
|
AllowEndOfFile = false
|
||||||
|
};
|
||||||
|
return ResultFactory.GetAsyncStreamWriter(streamSource);
|
||||||
}
|
}
|
||||||
|
|
||||||
public object Get(GetDefaultListingProvider request)
|
public object Get(GetDefaultListingProvider request)
|
||||||
|
@ -702,7 +808,8 @@ namespace MediaBrowser.Api.LiveTv
|
||||||
|
|
||||||
var response = await _httpClient.Get(new HttpRequestOptions
|
var response = await _httpClient.Get(new HttpRequestOptions
|
||||||
{
|
{
|
||||||
Url = "https://json.schedulesdirect.org/20141201/available/countries"
|
Url = "https://json.schedulesdirect.org/20141201/available/countries",
|
||||||
|
BufferContent = false
|
||||||
|
|
||||||
}).ConfigureAwait(false);
|
}).ConfigureAwait(false);
|
||||||
|
|
||||||
|
@ -786,6 +893,13 @@ namespace MediaBrowser.Api.LiveTv
|
||||||
IsLiked = request.IsLiked,
|
IsLiked = request.IsLiked,
|
||||||
IsDisliked = request.IsDisliked,
|
IsDisliked = request.IsDisliked,
|
||||||
EnableFavoriteSorting = request.EnableFavoriteSorting,
|
EnableFavoriteSorting = request.EnableFavoriteSorting,
|
||||||
|
IsMovie = request.IsMovie,
|
||||||
|
IsSeries = request.IsSeries,
|
||||||
|
IsNews = request.IsNews,
|
||||||
|
IsKids = request.IsKids,
|
||||||
|
IsSports = request.IsSports,
|
||||||
|
SortBy = request.GetOrderBy(),
|
||||||
|
SortOrder = request.SortOrder ?? SortOrder.Ascending,
|
||||||
AddCurrentProgram = request.AddCurrentProgram
|
AddCurrentProgram = request.AddCurrentProgram
|
||||||
|
|
||||||
}, CancellationToken.None).ConfigureAwait(false);
|
}, CancellationToken.None).ConfigureAwait(false);
|
||||||
|
@ -868,9 +982,12 @@ namespace MediaBrowser.Api.LiveTv
|
||||||
query.Limit = request.Limit;
|
query.Limit = request.Limit;
|
||||||
query.SortBy = (request.SortBy ?? String.Empty).Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries);
|
query.SortBy = (request.SortBy ?? String.Empty).Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries);
|
||||||
query.SortOrder = request.SortOrder;
|
query.SortOrder = request.SortOrder;
|
||||||
|
query.IsNews = request.IsNews;
|
||||||
query.IsMovie = request.IsMovie;
|
query.IsMovie = request.IsMovie;
|
||||||
|
query.IsSeries = request.IsSeries;
|
||||||
query.IsKids = request.IsKids;
|
query.IsKids = request.IsKids;
|
||||||
query.IsSports = request.IsSports;
|
query.IsSports = request.IsSports;
|
||||||
|
query.SeriesTimerId = request.SeriesTimerId;
|
||||||
query.Genres = (request.Genres ?? String.Empty).Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries);
|
query.Genres = (request.Genres ?? String.Empty).Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries);
|
||||||
|
|
||||||
var result = await _liveTvManager.GetPrograms(query, GetDtoOptions(request), CancellationToken.None).ConfigureAwait(false);
|
var result = await _liveTvManager.GetPrograms(query, GetDtoOptions(request), CancellationToken.None).ConfigureAwait(false);
|
||||||
|
@ -886,8 +1003,10 @@ namespace MediaBrowser.Api.LiveTv
|
||||||
IsAiring = request.IsAiring,
|
IsAiring = request.IsAiring,
|
||||||
Limit = request.Limit,
|
Limit = request.Limit,
|
||||||
HasAired = request.HasAired,
|
HasAired = request.HasAired,
|
||||||
|
IsSeries = request.IsSeries,
|
||||||
IsMovie = request.IsMovie,
|
IsMovie = request.IsMovie,
|
||||||
IsKids = request.IsKids,
|
IsKids = request.IsKids,
|
||||||
|
IsNews = request.IsNews,
|
||||||
IsSports = request.IsSports,
|
IsSports = request.IsSports,
|
||||||
EnableTotalRecordCount = request.EnableTotalRecordCount
|
EnableTotalRecordCount = request.EnableTotalRecordCount
|
||||||
};
|
};
|
||||||
|
@ -919,6 +1038,7 @@ namespace MediaBrowser.Api.LiveTv
|
||||||
IsInProgress = request.IsInProgress,
|
IsInProgress = request.IsInProgress,
|
||||||
EnableTotalRecordCount = request.EnableTotalRecordCount,
|
EnableTotalRecordCount = request.EnableTotalRecordCount,
|
||||||
IsMovie = request.IsMovie,
|
IsMovie = request.IsMovie,
|
||||||
|
IsNews = request.IsNews,
|
||||||
IsSeries = request.IsSeries,
|
IsSeries = request.IsSeries,
|
||||||
IsKids = request.IsKids,
|
IsKids = request.IsKids,
|
||||||
IsSports = request.IsSports
|
IsSports = request.IsSports
|
||||||
|
@ -975,7 +1095,8 @@ namespace MediaBrowser.Api.LiveTv
|
||||||
{
|
{
|
||||||
ChannelId = request.ChannelId,
|
ChannelId = request.ChannelId,
|
||||||
SeriesTimerId = request.SeriesTimerId,
|
SeriesTimerId = request.SeriesTimerId,
|
||||||
IsActive = request.IsActive
|
IsActive = request.IsActive,
|
||||||
|
IsScheduled = request.IsScheduled
|
||||||
|
|
||||||
}, CancellationToken.None).ConfigureAwait(false);
|
}, CancellationToken.None).ConfigureAwait(false);
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
<Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||||
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
|
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
||||||
|
@ -11,9 +11,10 @@
|
||||||
<AssemblyName>MediaBrowser.Api</AssemblyName>
|
<AssemblyName>MediaBrowser.Api</AssemblyName>
|
||||||
<FileAlignment>512</FileAlignment>
|
<FileAlignment>512</FileAlignment>
|
||||||
<SolutionDir Condition="$(SolutionDir) == '' Or $(SolutionDir) == '*Undefined*'">..\</SolutionDir>
|
<SolutionDir Condition="$(SolutionDir) == '' Or $(SolutionDir) == '*Undefined*'">..\</SolutionDir>
|
||||||
<TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
|
<TargetFrameworkVersion>v4.5.1</TargetFrameworkVersion>
|
||||||
<ReleaseVersion>
|
<ReleaseVersion>
|
||||||
</ReleaseVersion>
|
</ReleaseVersion>
|
||||||
|
<TargetFrameworkProfile />
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
||||||
<DebugSymbols>true</DebugSymbols>
|
<DebugSymbols>true</DebugSymbols>
|
||||||
|
@ -79,7 +80,6 @@
|
||||||
<Compile Include="Dlna\DlnaService.cs" />
|
<Compile Include="Dlna\DlnaService.cs" />
|
||||||
<Compile Include="FilterService.cs" />
|
<Compile Include="FilterService.cs" />
|
||||||
<Compile Include="IHasDtoOptions.cs" />
|
<Compile Include="IHasDtoOptions.cs" />
|
||||||
<Compile Include="Library\ChapterService.cs" />
|
|
||||||
<Compile Include="Playback\MediaInfoService.cs" />
|
<Compile Include="Playback\MediaInfoService.cs" />
|
||||||
<Compile Include="Playback\TranscodingThrottler.cs" />
|
<Compile Include="Playback\TranscodingThrottler.cs" />
|
||||||
<Compile Include="PlaylistService.cs" />
|
<Compile Include="PlaylistService.cs" />
|
||||||
|
@ -198,6 +198,10 @@
|
||||||
<Project>{7EEEB4BB-F3E8-48FC-B4C5-70F0FFF8329B}</Project>
|
<Project>{7EEEB4BB-F3E8-48FC-B4C5-70F0FFF8329B}</Project>
|
||||||
<Name>MediaBrowser.Model</Name>
|
<Name>MediaBrowser.Model</Name>
|
||||||
</ProjectReference>
|
</ProjectReference>
|
||||||
|
<ProjectReference Include="..\MediaBrowser.Server.Implementations\MediaBrowser.Server.Implementations.csproj">
|
||||||
|
<Project>{2e781478-814d-4a48-9d80-bff206441a65}</Project>
|
||||||
|
<Name>MediaBrowser.Server.Implementations</Name>
|
||||||
|
</ProjectReference>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<None Include="packages.config" />
|
<None Include="packages.config" />
|
||||||
|
|
|
@ -156,18 +156,19 @@ namespace MediaBrowser.Api.Movies
|
||||||
itemTypes.Add(typeof(LiveTvProgram).Name);
|
itemTypes.Add(typeof(LiveTvProgram).Name);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var dtoOptions = GetDtoOptions(request);
|
||||||
|
|
||||||
var itemsResult = _libraryManager.GetItemList(new InternalItemsQuery(user)
|
var itemsResult = _libraryManager.GetItemList(new InternalItemsQuery(user)
|
||||||
{
|
{
|
||||||
Limit = request.Limit,
|
Limit = request.Limit,
|
||||||
IncludeItemTypes = itemTypes.ToArray(),
|
IncludeItemTypes = itemTypes.ToArray(),
|
||||||
IsMovie = true,
|
IsMovie = true,
|
||||||
SimilarTo = item,
|
SimilarTo = item,
|
||||||
EnableGroupByMetadataKey = true
|
EnableGroupByMetadataKey = true,
|
||||||
|
DtoOptions = dtoOptions
|
||||||
|
|
||||||
}).ToList();
|
}).ToList();
|
||||||
|
|
||||||
var dtoOptions = GetDtoOptions(request);
|
|
||||||
|
|
||||||
var result = new QueryResult<BaseItemDto>
|
var result = new QueryResult<BaseItemDto>
|
||||||
{
|
{
|
||||||
Items = (await _dtoService.GetBaseItemDtos(itemsResult, dtoOptions, user).ConfigureAwait(false)).ToArray(),
|
Items = (await _dtoService.GetBaseItemDtos(itemsResult, dtoOptions, user).ConfigureAwait(false)).ToArray(),
|
||||||
|
@ -198,7 +199,8 @@ namespace MediaBrowser.Api.Movies
|
||||||
Limit = 7,
|
Limit = 7,
|
||||||
ParentId = parentIdGuid,
|
ParentId = parentIdGuid,
|
||||||
Recursive = true,
|
Recursive = true,
|
||||||
IsPlayed = true
|
IsPlayed = true,
|
||||||
|
DtoOptions = dtoOptions
|
||||||
};
|
};
|
||||||
|
|
||||||
var recentlyPlayedMovies = _libraryManager.GetItemList(query).ToList();
|
var recentlyPlayedMovies = _libraryManager.GetItemList(query).ToList();
|
||||||
|
@ -221,7 +223,8 @@ namespace MediaBrowser.Api.Movies
|
||||||
ExcludeItemIds = recentlyPlayedMovies.Select(i => i.Id.ToString("N")).ToArray(),
|
ExcludeItemIds = recentlyPlayedMovies.Select(i => i.Id.ToString("N")).ToArray(),
|
||||||
EnableGroupByMetadataKey = true,
|
EnableGroupByMetadataKey = true,
|
||||||
ParentId = parentIdGuid,
|
ParentId = parentIdGuid,
|
||||||
Recursive = true
|
Recursive = true,
|
||||||
|
DtoOptions = dtoOptions
|
||||||
|
|
||||||
}).ToList();
|
}).ToList();
|
||||||
|
|
||||||
|
@ -302,7 +305,8 @@ namespace MediaBrowser.Api.Movies
|
||||||
PersonTypes = new[] { PersonType.Director },
|
PersonTypes = new[] { PersonType.Director },
|
||||||
IncludeItemTypes = itemTypes.ToArray(),
|
IncludeItemTypes = itemTypes.ToArray(),
|
||||||
IsMovie = true,
|
IsMovie = true,
|
||||||
EnableGroupByMetadataKey = true
|
EnableGroupByMetadataKey = true,
|
||||||
|
DtoOptions = dtoOptions
|
||||||
|
|
||||||
}).DistinctBy(i => i.GetProviderId(MetadataProviders.Imdb) ?? Guid.NewGuid().ToString("N"))
|
}).DistinctBy(i => i.GetProviderId(MetadataProviders.Imdb) ?? Guid.NewGuid().ToString("N"))
|
||||||
.Take(itemLimit)
|
.Take(itemLimit)
|
||||||
|
@ -339,7 +343,8 @@ namespace MediaBrowser.Api.Movies
|
||||||
Limit = itemLimit + 2,
|
Limit = itemLimit + 2,
|
||||||
IncludeItemTypes = itemTypes.ToArray(),
|
IncludeItemTypes = itemTypes.ToArray(),
|
||||||
IsMovie = true,
|
IsMovie = true,
|
||||||
EnableGroupByMetadataKey = true
|
EnableGroupByMetadataKey = true,
|
||||||
|
DtoOptions = dtoOptions
|
||||||
|
|
||||||
}).DistinctBy(i => i.GetProviderId(MetadataProviders.Imdb) ?? Guid.NewGuid().ToString("N"))
|
}).DistinctBy(i => i.GetProviderId(MetadataProviders.Imdb) ?? Guid.NewGuid().ToString("N"))
|
||||||
.Take(itemLimit)
|
.Take(itemLimit)
|
||||||
|
@ -375,7 +380,8 @@ namespace MediaBrowser.Api.Movies
|
||||||
IncludeItemTypes = itemTypes.ToArray(),
|
IncludeItemTypes = itemTypes.ToArray(),
|
||||||
IsMovie = true,
|
IsMovie = true,
|
||||||
SimilarTo = item,
|
SimilarTo = item,
|
||||||
EnableGroupByMetadataKey = true
|
EnableGroupByMetadataKey = true,
|
||||||
|
DtoOptions = dtoOptions
|
||||||
|
|
||||||
}).ToList();
|
}).ToList();
|
||||||
|
|
||||||
|
|
|
@ -46,7 +46,7 @@ namespace MediaBrowser.Api
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <value>The name.</value>
|
/// <value>The name.</value>
|
||||||
[ApiMember(Name = "PackageType", Description = "Optional package type filter (System/UserInstalled)", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")]
|
[ApiMember(Name = "PackageType", Description = "Optional package type filter (System/UserInstalled)", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")]
|
||||||
public PackageType? PackageType { get; set; }
|
public string PackageType { get; set; }
|
||||||
|
|
||||||
[ApiMember(Name = "TargetSystems", Description = "Optional. Filter by target system type. Allows multiple, comma delimited.", IsRequired = false, DataType = "string", ParameterType = "path", Verb = "GET", AllowMultiple = true)]
|
[ApiMember(Name = "TargetSystems", Description = "Optional. Filter by target system type. Allows multiple, comma delimited.", IsRequired = false, DataType = "string", ParameterType = "path", Verb = "GET", AllowMultiple = true)]
|
||||||
public string TargetSystems { get; set; }
|
public string TargetSystems { get; set; }
|
||||||
|
@ -72,7 +72,7 @@ namespace MediaBrowser.Api
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <value>The name.</value>
|
/// <value>The name.</value>
|
||||||
[ApiMember(Name = "PackageType", Description = "Package type filter (System/UserInstalled)", IsRequired = true, DataType = "string", ParameterType = "query", Verb = "GET")]
|
[ApiMember(Name = "PackageType", Description = "Package type filter (System/UserInstalled)", IsRequired = true, DataType = "string", ParameterType = "query", Verb = "GET")]
|
||||||
public PackageType PackageType { get; set; }
|
public string PackageType { get; set; }
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -149,12 +149,12 @@ namespace MediaBrowser.Api
|
||||||
{
|
{
|
||||||
var result = new List<PackageVersionInfo>();
|
var result = new List<PackageVersionInfo>();
|
||||||
|
|
||||||
if (request.PackageType == PackageType.UserInstalled || request.PackageType == PackageType.All)
|
if (string.Equals(request.PackageType, "UserInstalled", StringComparison.OrdinalIgnoreCase) || string.Equals(request.PackageType, "All", StringComparison.OrdinalIgnoreCase))
|
||||||
{
|
{
|
||||||
result.AddRange(_installationManager.GetAvailablePluginUpdates(_appHost.ApplicationVersion, false, CancellationToken.None).Result.ToList());
|
result.AddRange(_installationManager.GetAvailablePluginUpdates(_appHost.ApplicationVersion, false, CancellationToken.None).Result.ToList());
|
||||||
}
|
}
|
||||||
|
|
||||||
else if (request.PackageType == PackageType.System || request.PackageType == PackageType.All)
|
else if (string.Equals(request.PackageType, "System", StringComparison.OrdinalIgnoreCase) || string.Equals(request.PackageType, "All", StringComparison.OrdinalIgnoreCase))
|
||||||
{
|
{
|
||||||
var updateCheckResult = _appHost.CheckForApplicationUpdate(CancellationToken.None, new Progress<double>()).Result;
|
var updateCheckResult = _appHost.CheckForApplicationUpdate(CancellationToken.None, new Progress<double>()).Result;
|
||||||
|
|
||||||
|
|
|
@ -367,6 +367,8 @@ namespace MediaBrowser.Api.Playback
|
||||||
{
|
{
|
||||||
param += " -crf 23";
|
param += " -crf 23";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
param += " -tune zerolatency";
|
||||||
}
|
}
|
||||||
|
|
||||||
else if (string.Equals(videoEncoder, "libx265", StringComparison.OrdinalIgnoreCase))
|
else if (string.Equals(videoEncoder, "libx265", StringComparison.OrdinalIgnoreCase))
|
||||||
|
@ -461,13 +463,15 @@ namespace MediaBrowser.Api.Playback
|
||||||
var level = NormalizeTranscodingLevel(state.OutputVideoCodec, state.VideoRequest.Level);
|
var level = NormalizeTranscodingLevel(state.OutputVideoCodec, state.VideoRequest.Level);
|
||||||
|
|
||||||
// h264_qsv and h264_nvenc expect levels to be expressed as a decimal. libx264 supports decimal and non-decimal format
|
// h264_qsv and h264_nvenc expect levels to be expressed as a decimal. libx264 supports decimal and non-decimal format
|
||||||
|
// also needed for libx264 due to https://trac.ffmpeg.org/ticket/3307
|
||||||
if (string.Equals(videoEncoder, "h264_qsv", StringComparison.OrdinalIgnoreCase) ||
|
if (string.Equals(videoEncoder, "h264_qsv", StringComparison.OrdinalIgnoreCase) ||
|
||||||
string.Equals(videoEncoder, "h264_nvenc", StringComparison.OrdinalIgnoreCase))
|
string.Equals(videoEncoder, "h264_nvenc", StringComparison.OrdinalIgnoreCase) ||
|
||||||
|
string.Equals(videoEncoder, "libx264", StringComparison.OrdinalIgnoreCase))
|
||||||
{
|
{
|
||||||
switch (level)
|
switch (level)
|
||||||
{
|
{
|
||||||
case "30":
|
case "30":
|
||||||
param += " -level 3";
|
param += " -level 3.0";
|
||||||
break;
|
break;
|
||||||
case "31":
|
case "31":
|
||||||
param += " -level 3.1";
|
param += " -level 3.1";
|
||||||
|
@ -476,7 +480,7 @@ namespace MediaBrowser.Api.Playback
|
||||||
param += " -level 3.2";
|
param += " -level 3.2";
|
||||||
break;
|
break;
|
||||||
case "40":
|
case "40":
|
||||||
param += " -level 4";
|
param += " -level 4.0";
|
||||||
break;
|
break;
|
||||||
case "41":
|
case "41":
|
||||||
param += " -level 4.1";
|
param += " -level 4.1";
|
||||||
|
@ -485,7 +489,7 @@ namespace MediaBrowser.Api.Playback
|
||||||
param += " -level 4.2";
|
param += " -level 4.2";
|
||||||
break;
|
break;
|
||||||
case "50":
|
case "50":
|
||||||
param += " -level 5";
|
param += " -level 5.0";
|
||||||
break;
|
break;
|
||||||
case "51":
|
case "51":
|
||||||
param += " -level 5.1";
|
param += " -level 5.1";
|
||||||
|
@ -767,7 +771,20 @@ namespace MediaBrowser.Api.Playback
|
||||||
if (request.Width.HasValue || request.Height.HasValue || request.MaxHeight.HasValue || request.MaxWidth.HasValue)
|
if (request.Width.HasValue || request.Height.HasValue || request.MaxHeight.HasValue || request.MaxWidth.HasValue)
|
||||||
{
|
{
|
||||||
outputSizeParam = GetOutputSizeParam(state, outputVideoCodec).TrimEnd('"');
|
outputSizeParam = GetOutputSizeParam(state, outputVideoCodec).TrimEnd('"');
|
||||||
outputSizeParam = "," + outputSizeParam.Substring(outputSizeParam.IndexOf("scale", StringComparison.OrdinalIgnoreCase));
|
|
||||||
|
if (string.Equals(outputVideoCodec, "h264_vaapi", StringComparison.OrdinalIgnoreCase))
|
||||||
|
{
|
||||||
|
outputSizeParam = "," + outputSizeParam.Substring(outputSizeParam.IndexOf("format", StringComparison.OrdinalIgnoreCase));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
outputSizeParam = "," + outputSizeParam.Substring(outputSizeParam.IndexOf("scale", StringComparison.OrdinalIgnoreCase));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (string.Equals(outputVideoCodec, "h264_vaapi", StringComparison.OrdinalIgnoreCase) && outputSizeParam.Length == 0)
|
||||||
|
{
|
||||||
|
outputSizeParam = ",format=nv12|vaapi,hwupload";
|
||||||
}
|
}
|
||||||
|
|
||||||
var videoSizeParam = string.Empty;
|
var videoSizeParam = string.Empty;
|
||||||
|
@ -802,10 +819,10 @@ namespace MediaBrowser.Api.Playback
|
||||||
{
|
{
|
||||||
if (state.PlayableStreamFileNames.Count > 0)
|
if (state.PlayableStreamFileNames.Count > 0)
|
||||||
{
|
{
|
||||||
return MediaEncoder.GetProbeSizeArgument(state.PlayableStreamFileNames.ToArray(), state.InputProtocol);
|
return MediaEncoder.GetProbeSizeAndAnalyzeDurationArgument(state.PlayableStreamFileNames.ToArray(), state.InputProtocol);
|
||||||
}
|
}
|
||||||
|
|
||||||
return MediaEncoder.GetProbeSizeArgument(new[] { state.MediaPath }, state.InputProtocol);
|
return MediaEncoder.GetProbeSizeAndAnalyzeDurationArgument(new[] { state.MediaPath }, state.InputProtocol);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -1022,7 +1039,15 @@ namespace MediaBrowser.Api.Playback
|
||||||
var encodingOptions = ApiEntryPoint.Instance.GetEncodingOptions();
|
var encodingOptions = ApiEntryPoint.Instance.GetEncodingOptions();
|
||||||
if (GetVideoEncoder(state).IndexOf("vaapi", StringComparison.OrdinalIgnoreCase) != -1)
|
if (GetVideoEncoder(state).IndexOf("vaapi", StringComparison.OrdinalIgnoreCase) != -1)
|
||||||
{
|
{
|
||||||
arg = "-hwaccel vaapi -hwaccel_output_format vaapi -vaapi_device " + encodingOptions.VaapiDevice + " " + arg;
|
var hasGraphicalSubs = state.SubtitleStream != null && !state.SubtitleStream.IsTextSubtitleStream && state.VideoRequest.SubtitleMethod == SubtitleDeliveryMethod.Encode;
|
||||||
|
var hwOutputFormat = "vaapi";
|
||||||
|
|
||||||
|
if (hasGraphicalSubs)
|
||||||
|
{
|
||||||
|
hwOutputFormat = "yuv420p";
|
||||||
|
}
|
||||||
|
|
||||||
|
arg = "-hwaccel vaapi -hwaccel_output_format " + hwOutputFormat + " -vaapi_device " + encodingOptions.VaapiDevice + " " + arg;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1219,7 +1244,7 @@ namespace MediaBrowser.Api.Playback
|
||||||
|
|
||||||
private void StartThrottler(StreamState state, TranscodingJob transcodingJob)
|
private void StartThrottler(StreamState state, TranscodingJob transcodingJob)
|
||||||
{
|
{
|
||||||
if (EnableThrottling(state) && !string.Equals(state.OutputVideoCodec, "copy", StringComparison.OrdinalIgnoreCase))
|
if (EnableThrottling(state))
|
||||||
{
|
{
|
||||||
transcodingJob.TranscodingThrottler = state.TranscodingThrottler = new TranscodingThrottler(transcodingJob, Logger, ServerConfigurationManager);
|
transcodingJob.TranscodingThrottler = state.TranscodingThrottler = new TranscodingThrottler(transcodingJob, Logger, ServerConfigurationManager);
|
||||||
state.TranscodingThrottler.Start();
|
state.TranscodingThrottler.Start();
|
||||||
|
@ -1832,26 +1857,37 @@ namespace MediaBrowser.Api.Playback
|
||||||
|
|
||||||
state.IsInputVideo = string.Equals(item.MediaType, MediaType.Video, StringComparison.OrdinalIgnoreCase);
|
state.IsInputVideo = string.Equals(item.MediaType, MediaType.Video, StringComparison.OrdinalIgnoreCase);
|
||||||
|
|
||||||
var archivable = item as IArchivable;
|
MediaSourceInfo mediaSource = null;
|
||||||
state.IsInputArchive = archivable != null && archivable.IsArchive;
|
|
||||||
|
|
||||||
MediaSourceInfo mediaSource;
|
|
||||||
if (string.IsNullOrWhiteSpace(request.LiveStreamId))
|
if (string.IsNullOrWhiteSpace(request.LiveStreamId))
|
||||||
{
|
{
|
||||||
var mediaSources = (await MediaSourceManager.GetPlayackMediaSources(request.Id, null, false, new[] { MediaType.Audio, MediaType.Video }, cancellationToken).ConfigureAwait(false)).ToList();
|
TranscodingJob currentJob = !string.IsNullOrWhiteSpace(request.PlaySessionId) ?
|
||||||
|
ApiEntryPoint.Instance.GetTranscodingJob(request.PlaySessionId)
|
||||||
|
: null;
|
||||||
|
|
||||||
mediaSource = string.IsNullOrEmpty(request.MediaSourceId)
|
if (currentJob != null)
|
||||||
? mediaSources.First()
|
|
||||||
: mediaSources.FirstOrDefault(i => string.Equals(i.Id, request.MediaSourceId));
|
|
||||||
|
|
||||||
if (mediaSource == null && string.Equals(request.Id, request.MediaSourceId, StringComparison.OrdinalIgnoreCase))
|
|
||||||
{
|
{
|
||||||
mediaSource = mediaSources.First();
|
mediaSource = currentJob.MediaSource;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mediaSource == null)
|
||||||
|
{
|
||||||
|
var mediaSources = (await MediaSourceManager.GetPlayackMediaSources(request.Id, null, false, new[] { MediaType.Audio, MediaType.Video }, cancellationToken).ConfigureAwait(false)).ToList();
|
||||||
|
|
||||||
|
mediaSource = string.IsNullOrEmpty(request.MediaSourceId)
|
||||||
|
? mediaSources.First()
|
||||||
|
: mediaSources.FirstOrDefault(i => string.Equals(i.Id, request.MediaSourceId));
|
||||||
|
|
||||||
|
if (mediaSource == null && string.Equals(request.Id, request.MediaSourceId, StringComparison.OrdinalIgnoreCase))
|
||||||
|
{
|
||||||
|
mediaSource = mediaSources.First();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
mediaSource = await MediaSourceManager.GetLiveStream(request.LiveStreamId, cancellationToken).ConfigureAwait(false);
|
var liveStreamInfo = await MediaSourceManager.GetLiveStreamWithDirectStreamProvider(request.LiveStreamId, cancellationToken).ConfigureAwait(false);
|
||||||
|
mediaSource = liveStreamInfo.Item1;
|
||||||
|
state.DirectStreamProvider = liveStreamInfo.Item2;
|
||||||
}
|
}
|
||||||
|
|
||||||
var videoRequest = request as VideoStreamRequest;
|
var videoRequest = request as VideoStreamRequest;
|
||||||
|
@ -2294,7 +2330,8 @@ namespace MediaBrowser.Api.Playback
|
||||||
state.TargetRefFrames,
|
state.TargetRefFrames,
|
||||||
state.TargetVideoStreamCount,
|
state.TargetVideoStreamCount,
|
||||||
state.TargetAudioStreamCount,
|
state.TargetAudioStreamCount,
|
||||||
state.TargetVideoCodecTag);
|
state.TargetVideoCodecTag,
|
||||||
|
state.IsTargetAVC);
|
||||||
|
|
||||||
if (mediaProfile != null)
|
if (mediaProfile != null)
|
||||||
{
|
{
|
||||||
|
@ -2429,7 +2466,8 @@ namespace MediaBrowser.Api.Playback
|
||||||
Url = "https://mb3admin.com/admin/service/transcoding/report",
|
Url = "https://mb3admin.com/admin/service/transcoding/report",
|
||||||
CancellationToken = CancellationToken.None,
|
CancellationToken = CancellationToken.None,
|
||||||
LogRequest = false,
|
LogRequest = false,
|
||||||
LogErrors = false
|
LogErrors = false,
|
||||||
|
BufferContent = false
|
||||||
};
|
};
|
||||||
options.RequestContent = JsonSerializer.SerializeToString(dict);
|
options.RequestContent = JsonSerializer.SerializeToString(dict);
|
||||||
options.RequestContentType = "application/json";
|
options.RequestContentType = "application/json";
|
||||||
|
@ -2512,7 +2550,8 @@ namespace MediaBrowser.Api.Playback
|
||||||
state.TargetRefFrames,
|
state.TargetRefFrames,
|
||||||
state.TargetVideoStreamCount,
|
state.TargetVideoStreamCount,
|
||||||
state.TargetAudioStreamCount,
|
state.TargetAudioStreamCount,
|
||||||
state.TargetVideoCodecTag
|
state.TargetVideoCodecTag,
|
||||||
|
state.IsTargetAVC
|
||||||
|
|
||||||
).FirstOrDefault() ?? string.Empty;
|
).FirstOrDefault() ?? string.Empty;
|
||||||
}
|
}
|
||||||
|
@ -2567,6 +2606,7 @@ namespace MediaBrowser.Api.Playback
|
||||||
inputModifier += " " + GetFastSeekCommandLineParameter(state.Request);
|
inputModifier += " " + GetFastSeekCommandLineParameter(state.Request);
|
||||||
inputModifier = inputModifier.Trim();
|
inputModifier = inputModifier.Trim();
|
||||||
|
|
||||||
|
//inputModifier += " -fflags +genpts+ignidx+igndts";
|
||||||
if (state.VideoRequest != null && genPts)
|
if (state.VideoRequest != null && genPts)
|
||||||
{
|
{
|
||||||
inputModifier += " -fflags +genpts";
|
inputModifier += " -fflags +genpts";
|
||||||
|
|
|
@ -87,7 +87,8 @@ namespace MediaBrowser.Api.Playback.Hls
|
||||||
|
|
||||||
if (!FileSystem.FileExists(playlist))
|
if (!FileSystem.FileExists(playlist))
|
||||||
{
|
{
|
||||||
await ApiEntryPoint.Instance.TranscodingStartLock.WaitAsync(cancellationTokenSource.Token).ConfigureAwait(false);
|
var transcodingLock = ApiEntryPoint.Instance.GetTranscodingLock(playlist);
|
||||||
|
await transcodingLock.WaitAsync(cancellationTokenSource.Token).ConfigureAwait(false);
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
if (!FileSystem.FileExists(playlist))
|
if (!FileSystem.FileExists(playlist))
|
||||||
|
@ -104,13 +105,13 @@ namespace MediaBrowser.Api.Playback.Hls
|
||||||
throw;
|
throw;
|
||||||
}
|
}
|
||||||
|
|
||||||
var waitForSegments = state.SegmentLength >= 10 ? 2 : 3;
|
var waitForSegments = state.SegmentLength >= 10 ? 2 : (state.SegmentLength > 3 || !isLive ? 3 : 3);
|
||||||
await WaitForMinimumSegmentCount(playlist, waitForSegments, cancellationTokenSource.Token).ConfigureAwait(false);
|
await WaitForMinimumSegmentCount(playlist, waitForSegments, cancellationTokenSource.Token).ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
finally
|
finally
|
||||||
{
|
{
|
||||||
ApiEntryPoint.Instance.TranscodingStartLock.Release();
|
transcodingLock.Release();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -128,10 +129,9 @@ namespace MediaBrowser.Api.Playback.Hls
|
||||||
var audioBitrate = state.OutputAudioBitrate ?? 0;
|
var audioBitrate = state.OutputAudioBitrate ?? 0;
|
||||||
var videoBitrate = state.OutputVideoBitrate ?? 0;
|
var videoBitrate = state.OutputVideoBitrate ?? 0;
|
||||||
|
|
||||||
var appendBaselineStream = false;
|
|
||||||
var baselineStreamBitrate = 64000;
|
var baselineStreamBitrate = 64000;
|
||||||
|
|
||||||
var playlistText = GetMasterPlaylistFileText(playlist, videoBitrate + audioBitrate, appendBaselineStream, baselineStreamBitrate);
|
var playlistText = GetMasterPlaylistFileText(playlist, videoBitrate + audioBitrate, baselineStreamBitrate);
|
||||||
|
|
||||||
job = job ?? ApiEntryPoint.Instance.OnTranscodeBeginRequest(playlist, TranscodingJobType);
|
job = job ?? ApiEntryPoint.Instance.OnTranscodeBeginRequest(playlist, TranscodingJobType);
|
||||||
|
|
||||||
|
@ -151,9 +151,10 @@ namespace MediaBrowser.Api.Playback.Hls
|
||||||
{
|
{
|
||||||
var text = reader.ReadToEnd();
|
var text = reader.ReadToEnd();
|
||||||
|
|
||||||
|
text = text.Replace("#EXTM3U", "#EXTM3U\n#EXT-X-PLAYLIST-TYPE:EVENT");
|
||||||
|
|
||||||
var newDuration = "#EXT-X-TARGETDURATION:" + segmentLength.ToString(UsCulture);
|
var newDuration = "#EXT-X-TARGETDURATION:" + segmentLength.ToString(UsCulture);
|
||||||
|
|
||||||
// ffmpeg pads the reported length by a full second
|
|
||||||
text = text.Replace("#EXT-X-TARGETDURATION:" + (segmentLength + 1).ToString(UsCulture), newDuration, StringComparison.OrdinalIgnoreCase);
|
text = text.Replace("#EXT-X-TARGETDURATION:" + (segmentLength + 1).ToString(UsCulture), newDuration, StringComparison.OrdinalIgnoreCase);
|
||||||
|
|
||||||
return text;
|
return text;
|
||||||
|
@ -161,7 +162,7 @@ namespace MediaBrowser.Api.Playback.Hls
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private string GetMasterPlaylistFileText(string firstPlaylist, int bitrate, bool includeBaselineStream, int baselineStreamBitrate)
|
private string GetMasterPlaylistFileText(string firstPlaylist, int bitrate, int baselineStreamBitrate)
|
||||||
{
|
{
|
||||||
var builder = new StringBuilder();
|
var builder = new StringBuilder();
|
||||||
|
|
||||||
|
@ -175,14 +176,6 @@ namespace MediaBrowser.Api.Playback.Hls
|
||||||
var playlistUrl = "hls/" + Path.GetFileName(firstPlaylist).Replace(".m3u8", "/stream.m3u8");
|
var playlistUrl = "hls/" + Path.GetFileName(firstPlaylist).Replace(".m3u8", "/stream.m3u8");
|
||||||
builder.AppendLine(playlistUrl);
|
builder.AppendLine(playlistUrl);
|
||||||
|
|
||||||
// Low bitrate stream
|
|
||||||
if (includeBaselineStream)
|
|
||||||
{
|
|
||||||
builder.AppendLine("#EXT-X-STREAM-INF:PROGRAM-ID=1,BANDWIDTH=" + baselineStreamBitrate.ToString(UsCulture));
|
|
||||||
playlistUrl = "hls/" + Path.GetFileName(firstPlaylist).Replace(".m3u8", "-low/stream.m3u8");
|
|
||||||
builder.AppendLine(playlistUrl);
|
|
||||||
}
|
|
||||||
|
|
||||||
return builder.ToString();
|
return builder.ToString();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -190,32 +183,41 @@ namespace MediaBrowser.Api.Playback.Hls
|
||||||
{
|
{
|
||||||
Logger.Debug("Waiting for {0} segments in {1}", segmentCount, playlist);
|
Logger.Debug("Waiting for {0} segments in {1}", segmentCount, playlist);
|
||||||
|
|
||||||
while (true)
|
while (!cancellationToken.IsCancellationRequested)
|
||||||
{
|
{
|
||||||
// Need to use FileShare.ReadWrite because we're reading the file at the same time it's being written
|
try
|
||||||
using (var fileStream = GetPlaylistFileStream(playlist))
|
|
||||||
{
|
{
|
||||||
using (var reader = new StreamReader(fileStream))
|
// Need to use FileShare.ReadWrite because we're reading the file at the same time it's being written
|
||||||
|
using (var fileStream = GetPlaylistFileStream(playlist))
|
||||||
{
|
{
|
||||||
var count = 0;
|
using (var reader = new StreamReader(fileStream))
|
||||||
|
|
||||||
while (!reader.EndOfStream)
|
|
||||||
{
|
{
|
||||||
var line = await reader.ReadLineAsync().ConfigureAwait(false);
|
var count = 0;
|
||||||
|
|
||||||
if (line.IndexOf("#EXTINF:", StringComparison.OrdinalIgnoreCase) != -1)
|
while (!reader.EndOfStream)
|
||||||
{
|
{
|
||||||
count++;
|
var line = await reader.ReadLineAsync().ConfigureAwait(false);
|
||||||
if (count >= segmentCount)
|
|
||||||
|
if (line.IndexOf("#EXTINF:", StringComparison.OrdinalIgnoreCase) != -1)
|
||||||
{
|
{
|
||||||
Logger.Debug("Finished waiting for {0} segments in {1}", segmentCount, playlist);
|
count++;
|
||||||
return;
|
if (count >= segmentCount)
|
||||||
|
{
|
||||||
|
Logger.Debug("Finished waiting for {0} segments in {1}", segmentCount, playlist);
|
||||||
|
return;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
await Task.Delay(100, cancellationToken).ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
await Task.Delay(100, cancellationToken).ConfigureAwait(false);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
catch (IOException)
|
||||||
|
{
|
||||||
|
// May get an error if the file is locked
|
||||||
|
}
|
||||||
|
|
||||||
|
await Task.Delay(50, cancellationToken).ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -171,14 +171,15 @@ namespace MediaBrowser.Api.Playback.Hls
|
||||||
return await GetSegmentResult(state, playlistPath, segmentPath, requestedIndex, job, cancellationToken).ConfigureAwait(false);
|
return await GetSegmentResult(state, playlistPath, segmentPath, requestedIndex, job, cancellationToken).ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
await ApiEntryPoint.Instance.TranscodingStartLock.WaitAsync(cancellationTokenSource.Token).ConfigureAwait(false);
|
var transcodingLock = ApiEntryPoint.Instance.GetTranscodingLock(playlistPath);
|
||||||
|
await transcodingLock.WaitAsync(cancellationTokenSource.Token).ConfigureAwait(false);
|
||||||
var released = false;
|
var released = false;
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
if (FileSystem.FileExists(segmentPath))
|
if (FileSystem.FileExists(segmentPath))
|
||||||
{
|
{
|
||||||
job = ApiEntryPoint.Instance.OnTranscodeBeginRequest(playlistPath, TranscodingJobType);
|
job = ApiEntryPoint.Instance.OnTranscodeBeginRequest(playlistPath, TranscodingJobType);
|
||||||
ApiEntryPoint.Instance.TranscodingStartLock.Release();
|
transcodingLock.Release();
|
||||||
released = true;
|
released = true;
|
||||||
return await GetSegmentResult(state, playlistPath, segmentPath, requestedIndex, job, cancellationToken).ConfigureAwait(false);
|
return await GetSegmentResult(state, playlistPath, segmentPath, requestedIndex, job, cancellationToken).ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
|
@ -242,7 +243,7 @@ namespace MediaBrowser.Api.Playback.Hls
|
||||||
{
|
{
|
||||||
if (!released)
|
if (!released)
|
||||||
{
|
{
|
||||||
ApiEntryPoint.Instance.TranscodingStartLock.Release();
|
transcodingLock.Release();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -906,6 +907,7 @@ namespace MediaBrowser.Api.Playback.Hls
|
||||||
).Trim();
|
).Trim();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO: check libavformat version for 57 50.100 and use -hls_flags split_by_time
|
||||||
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}\"",
|
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),
|
||||||
|
|
|
@ -68,8 +68,6 @@ namespace MediaBrowser.Api.Playback.Hls
|
||||||
[Api(Description = "Gets an Http live streaming segment file. Internal use only.")]
|
[Api(Description = "Gets an Http live streaming segment file. Internal use only.")]
|
||||||
public class GetHlsVideoSegmentLegacy : VideoStreamRequest
|
public class GetHlsVideoSegmentLegacy : VideoStreamRequest
|
||||||
{
|
{
|
||||||
// TODO: Deprecate with new iOS app
|
|
||||||
|
|
||||||
public string PlaylistId { get; set; }
|
public string PlaylistId { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -113,7 +111,7 @@ namespace MediaBrowser.Api.Playback.Hls
|
||||||
var file = request.SegmentId + Path.GetExtension(Request.PathInfo);
|
var file = request.SegmentId + Path.GetExtension(Request.PathInfo);
|
||||||
file = Path.Combine(_config.ApplicationPaths.TranscodingTempPath, file);
|
file = Path.Combine(_config.ApplicationPaths.TranscodingTempPath, file);
|
||||||
|
|
||||||
var normalizedPlaylistId = request.PlaylistId.Replace("-low", string.Empty);
|
var normalizedPlaylistId = request.PlaylistId;
|
||||||
|
|
||||||
var playlistPath = Directory.EnumerateFiles(_config.ApplicationPaths.TranscodingTempPath, "*")
|
var playlistPath = Directory.EnumerateFiles(_config.ApplicationPaths.TranscodingTempPath, "*")
|
||||||
.FirstOrDefault(i => string.Equals(Path.GetExtension(i), ".m3u8", StringComparison.OrdinalIgnoreCase) && i.IndexOf(normalizedPlaylistId, StringComparison.OrdinalIgnoreCase) != -1);
|
.FirstOrDefault(i => string.Equals(Path.GetExtension(i), ".m3u8", StringComparison.OrdinalIgnoreCase) && i.IndexOf(normalizedPlaylistId, StringComparison.OrdinalIgnoreCase) != -1);
|
||||||
|
|
|
@ -113,6 +113,8 @@ namespace MediaBrowser.Api.Playback.Hls
|
||||||
args += GetGraphicalSubtitleParam(state, codec);
|
args += GetGraphicalSubtitleParam(state, codec);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
args += " -flags -global_header";
|
||||||
|
|
||||||
return args;
|
return args;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -107,7 +107,7 @@ namespace MediaBrowser.Api.Playback
|
||||||
{
|
{
|
||||||
var authInfo = AuthorizationContext.GetAuthorizationInfo(Request);
|
var authInfo = AuthorizationContext.GetAuthorizationInfo(Request);
|
||||||
|
|
||||||
var result = await _mediaSourceManager.OpenLiveStream(request, false, CancellationToken.None).ConfigureAwait(false);
|
var result = await _mediaSourceManager.OpenLiveStream(request, true, CancellationToken.None).ConfigureAwait(false);
|
||||||
|
|
||||||
var profile = request.DeviceProfile;
|
var profile = request.DeviceProfile;
|
||||||
if (profile == null)
|
if (profile == null)
|
||||||
|
@ -140,7 +140,7 @@ namespace MediaBrowser.Api.Playback
|
||||||
|
|
||||||
public void Post(CloseMediaSource request)
|
public void Post(CloseMediaSource request)
|
||||||
{
|
{
|
||||||
var task = _mediaSourceManager.CloseLiveStream(request.LiveStreamId, CancellationToken.None);
|
var task = _mediaSourceManager.CloseLiveStream(request.LiveStreamId);
|
||||||
Task.WaitAll(task);
|
Task.WaitAll(task);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -17,6 +17,7 @@ using System.IO;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using CommonIO;
|
using CommonIO;
|
||||||
|
using ServiceStack;
|
||||||
|
|
||||||
namespace MediaBrowser.Api.Playback.Progressive
|
namespace MediaBrowser.Api.Playback.Progressive
|
||||||
{
|
{
|
||||||
|
@ -26,12 +27,10 @@ namespace MediaBrowser.Api.Playback.Progressive
|
||||||
public abstract class BaseProgressiveStreamingService : BaseStreamingService
|
public abstract class BaseProgressiveStreamingService : BaseStreamingService
|
||||||
{
|
{
|
||||||
protected readonly IImageProcessor ImageProcessor;
|
protected readonly IImageProcessor ImageProcessor;
|
||||||
protected readonly IHttpClient HttpClient;
|
|
||||||
|
|
||||||
protected BaseProgressiveStreamingService(IServerConfigurationManager serverConfig, IUserManager userManager, ILibraryManager libraryManager, IIsoManager isoManager, IMediaEncoder mediaEncoder, IFileSystem fileSystem, IDlnaManager dlnaManager, ISubtitleEncoder subtitleEncoder, IDeviceManager deviceManager, IMediaSourceManager mediaSourceManager, IZipClient zipClient, IJsonSerializer jsonSerializer, IImageProcessor imageProcessor, IHttpClient httpClient) : base(serverConfig, userManager, libraryManager, isoManager, mediaEncoder, fileSystem, dlnaManager, subtitleEncoder, deviceManager, mediaSourceManager, zipClient, jsonSerializer)
|
protected BaseProgressiveStreamingService(IServerConfigurationManager serverConfig, IUserManager userManager, ILibraryManager libraryManager, IIsoManager isoManager, IMediaEncoder mediaEncoder, IFileSystem fileSystem, IDlnaManager dlnaManager, ISubtitleEncoder subtitleEncoder, IDeviceManager deviceManager, IMediaSourceManager mediaSourceManager, IZipClient zipClient, IJsonSerializer jsonSerializer, IImageProcessor imageProcessor, IHttpClient httpClient) : base(serverConfig, userManager, libraryManager, isoManager, mediaEncoder, fileSystem, dlnaManager, subtitleEncoder, deviceManager, mediaSourceManager, zipClient, jsonSerializer)
|
||||||
{
|
{
|
||||||
ImageProcessor = imageProcessor;
|
ImageProcessor = imageProcessor;
|
||||||
HttpClient = httpClient;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -122,6 +121,25 @@ namespace MediaBrowser.Api.Playback.Progressive
|
||||||
|
|
||||||
var responseHeaders = new Dictionary<string, string>();
|
var responseHeaders = new Dictionary<string, string>();
|
||||||
|
|
||||||
|
if (request.Static && state.DirectStreamProvider != null)
|
||||||
|
{
|
||||||
|
AddDlnaHeaders(state, responseHeaders, true);
|
||||||
|
|
||||||
|
using (state)
|
||||||
|
{
|
||||||
|
var outputHeaders = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);
|
||||||
|
|
||||||
|
// TODO: Don't hardcode this
|
||||||
|
outputHeaders["Content-Type"] = MediaBrowser.Model.Net.MimeTypes.GetMimeType("file.ts");
|
||||||
|
|
||||||
|
var streamSource = new ProgressiveFileCopier(state.DirectStreamProvider, outputHeaders, null, Logger, CancellationToken.None)
|
||||||
|
{
|
||||||
|
AllowEndOfFile = false
|
||||||
|
};
|
||||||
|
return ResultFactory.GetAsyncStreamWriter(streamSource);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Static remote stream
|
// Static remote stream
|
||||||
if (request.Static && state.InputProtocol == MediaProtocol.Http)
|
if (request.Static && state.InputProtocol == MediaProtocol.Http)
|
||||||
{
|
{
|
||||||
|
@ -129,8 +147,7 @@ namespace MediaBrowser.Api.Playback.Progressive
|
||||||
|
|
||||||
using (state)
|
using (state)
|
||||||
{
|
{
|
||||||
return await GetStaticRemoteStreamResult(state, responseHeaders, isHeadRequest, cancellationTokenSource)
|
return await GetStaticRemoteStreamResult(state, responseHeaders, isHeadRequest, cancellationTokenSource).ConfigureAwait(false);
|
||||||
.ConfigureAwait(false);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -154,6 +171,19 @@ namespace MediaBrowser.Api.Playback.Progressive
|
||||||
|
|
||||||
using (state)
|
using (state)
|
||||||
{
|
{
|
||||||
|
if (state.MediaSource.IsInfiniteStream)
|
||||||
|
{
|
||||||
|
var outputHeaders = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);
|
||||||
|
|
||||||
|
outputHeaders["Content-Type"] = contentType;
|
||||||
|
|
||||||
|
var streamSource = new ProgressiveFileCopier(FileSystem, state.MediaPath, outputHeaders, null, Logger, CancellationToken.None)
|
||||||
|
{
|
||||||
|
AllowEndOfFile = false
|
||||||
|
};
|
||||||
|
return ResultFactory.GetAsyncStreamWriter(streamSource);
|
||||||
|
}
|
||||||
|
|
||||||
TimeSpan? cacheDuration = null;
|
TimeSpan? cacheDuration = null;
|
||||||
|
|
||||||
if (!string.IsNullOrEmpty(request.Tag))
|
if (!string.IsNullOrEmpty(request.Tag))
|
||||||
|
@ -345,7 +375,8 @@ namespace MediaBrowser.Api.Playback.Progressive
|
||||||
return streamResult;
|
return streamResult;
|
||||||
}
|
}
|
||||||
|
|
||||||
await ApiEntryPoint.Instance.TranscodingStartLock.WaitAsync(cancellationTokenSource.Token).ConfigureAwait(false);
|
var transcodingLock = ApiEntryPoint.Instance.GetTranscodingLock(outputPath);
|
||||||
|
await transcodingLock.WaitAsync(cancellationTokenSource.Token).ConfigureAwait(false);
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
TranscodingJob job;
|
TranscodingJob job;
|
||||||
|
@ -376,7 +407,7 @@ namespace MediaBrowser.Api.Playback.Progressive
|
||||||
}
|
}
|
||||||
finally
|
finally
|
||||||
{
|
{
|
||||||
ApiEntryPoint.Instance.TranscodingStartLock.Release();
|
transcodingLock.Release();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -7,6 +7,7 @@ using CommonIO;
|
||||||
using MediaBrowser.Controller.Net;
|
using MediaBrowser.Controller.Net;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using ServiceStack.Web;
|
using ServiceStack.Web;
|
||||||
|
using MediaBrowser.Controller.Library;
|
||||||
|
|
||||||
namespace MediaBrowser.Api.Playback.Progressive
|
namespace MediaBrowser.Api.Playback.Progressive
|
||||||
{
|
{
|
||||||
|
@ -23,6 +24,10 @@ namespace MediaBrowser.Api.Playback.Progressive
|
||||||
private const int BufferSize = 81920;
|
private const int BufferSize = 81920;
|
||||||
|
|
||||||
private long _bytesWritten = 0;
|
private long _bytesWritten = 0;
|
||||||
|
public long StartPosition { get; set; }
|
||||||
|
public bool AllowEndOfFile = true;
|
||||||
|
|
||||||
|
private IDirectStreamProvider _directStreamProvider;
|
||||||
|
|
||||||
public ProgressiveFileCopier(IFileSystem fileSystem, string path, Dictionary<string, string> outputHeaders, TranscodingJob job, ILogger logger, CancellationToken cancellationToken)
|
public ProgressiveFileCopier(IFileSystem fileSystem, string path, Dictionary<string, string> outputHeaders, TranscodingJob job, ILogger logger, CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
|
@ -34,6 +39,15 @@ namespace MediaBrowser.Api.Playback.Progressive
|
||||||
_cancellationToken = cancellationToken;
|
_cancellationToken = cancellationToken;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public ProgressiveFileCopier(IDirectStreamProvider directStreamProvider, Dictionary<string, string> outputHeaders, TranscodingJob job, ILogger logger, CancellationToken cancellationToken)
|
||||||
|
{
|
||||||
|
_directStreamProvider = directStreamProvider;
|
||||||
|
_outputHeaders = outputHeaders;
|
||||||
|
_job = job;
|
||||||
|
_logger = logger;
|
||||||
|
_cancellationToken = cancellationToken;
|
||||||
|
}
|
||||||
|
|
||||||
public IDictionary<string, string> Options
|
public IDictionary<string, string> Options
|
||||||
{
|
{
|
||||||
get
|
get
|
||||||
|
@ -42,17 +56,33 @@ namespace MediaBrowser.Api.Playback.Progressive
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private Stream GetInputStream()
|
||||||
|
{
|
||||||
|
return _fileSystem.GetFileStream(_path, FileMode.Open, FileAccess.Read, FileShare.ReadWrite, true);
|
||||||
|
}
|
||||||
|
|
||||||
public async Task WriteToAsync(Stream outputStream)
|
public async Task WriteToAsync(Stream outputStream)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
if (_directStreamProvider != null)
|
||||||
|
{
|
||||||
|
await _directStreamProvider.CopyToAsync(outputStream, _cancellationToken).ConfigureAwait(false);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
var eofCount = 0;
|
var eofCount = 0;
|
||||||
|
|
||||||
using (var fs = _fileSystem.GetFileStream(_path, FileMode.Open, FileAccess.Read, FileShare.ReadWrite, true))
|
using (var inputStream = GetInputStream())
|
||||||
{
|
{
|
||||||
while (eofCount < 15)
|
if (StartPosition > 0)
|
||||||
{
|
{
|
||||||
var bytesRead = await CopyToAsyncInternal(fs, outputStream, BufferSize, _cancellationToken).ConfigureAwait(false);
|
inputStream.Position = StartPosition;
|
||||||
|
}
|
||||||
|
|
||||||
|
while (eofCount < 15 || !AllowEndOfFile)
|
||||||
|
{
|
||||||
|
var bytesRead = await CopyToAsyncInternal(inputStream, outputStream, BufferSize, _cancellationToken).ConfigureAwait(false);
|
||||||
|
|
||||||
//var position = fs.Position;
|
//var position = fs.Position;
|
||||||
//_logger.Debug("Streamed {0} bytes to position {1} from file {2}", bytesRead, position, path);
|
//_logger.Debug("Streamed {0} bytes to position {1} from file {2}", bytesRead, position, path);
|
||||||
|
|
|
@ -37,6 +37,7 @@ namespace MediaBrowser.Api.Playback
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <value>The log file stream.</value>
|
/// <value>The log file stream.</value>
|
||||||
public Stream LogFileStream { get; set; }
|
public Stream LogFileStream { get; set; }
|
||||||
|
public IDirectStreamProvider DirectStreamProvider { get; set; }
|
||||||
|
|
||||||
public string InputContainer { get; set; }
|
public string InputContainer { get; set; }
|
||||||
|
|
||||||
|
@ -62,7 +63,6 @@ namespace MediaBrowser.Api.Playback
|
||||||
get { return Request is VideoStreamRequest; }
|
get { return Request is VideoStreamRequest; }
|
||||||
}
|
}
|
||||||
public bool IsInputVideo { get; set; }
|
public bool IsInputVideo { get; set; }
|
||||||
public bool IsInputArchive { get; set; }
|
|
||||||
|
|
||||||
public VideoType VideoType { get; set; }
|
public VideoType VideoType { get; set; }
|
||||||
public IsoType? IsoType { get; set; }
|
public IsoType? IsoType { get; set; }
|
||||||
|
@ -88,9 +88,17 @@ namespace MediaBrowser.Api.Playback
|
||||||
return 10;
|
return 10;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!RunTimeTicks.HasValue)
|
||||||
|
{
|
||||||
|
return 3;
|
||||||
|
}
|
||||||
return 6;
|
return 6;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!RunTimeTicks.HasValue)
|
||||||
|
{
|
||||||
|
return 3;
|
||||||
|
}
|
||||||
return 3;
|
return 3;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -217,7 +225,7 @@ namespace MediaBrowser.Api.Playback
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
await _mediaSourceManager.CloseLiveStream(MediaSource.LiveStreamId, CancellationToken.None).ConfigureAwait(false);
|
await _mediaSourceManager.CloseLiveStream(MediaSource.LiveStreamId).ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
|
@ -508,5 +516,18 @@ namespace MediaBrowser.Api.Playback
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public bool? IsTargetAVC
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
if (Request.Static)
|
||||||
|
{
|
||||||
|
return VideoStream == null ? null : VideoStream.IsAVC;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -517,10 +517,6 @@ namespace MediaBrowser.Api.Reports
|
||||||
internalHeader = HeaderMetadata.Album;
|
internalHeader = HeaderMetadata.Album;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case HeaderMetadata.Countries:
|
|
||||||
option.Column = (i, r) => this.GetListAsString(this.GetObject<IHasProductionLocations, List<string>>(i, (x) => x.ProductionLocations));
|
|
||||||
break;
|
|
||||||
|
|
||||||
case HeaderMetadata.Disc:
|
case HeaderMetadata.Disc:
|
||||||
option.Column = (i, r) => i.ParentIndexNumber;
|
option.Column = (i, r) => i.ParentIndexNumber;
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -36,7 +36,6 @@ namespace MediaBrowser.Api.Reports
|
||||||
result = this.GetResultStudios(result, items, topItem);
|
result = this.GetResultStudios(result, items, topItem);
|
||||||
result = this.GetResultPersons(result, items, topItem);
|
result = this.GetResultPersons(result, items, topItem);
|
||||||
result = this.GetResultProductionYears(result, items, topItem);
|
result = this.GetResultProductionYears(result, items, topItem);
|
||||||
result = this.GetResulProductionLocations(result, items, topItem);
|
|
||||||
result = this.GetResultCommunityRatings(result, items, topItem);
|
result = this.GetResultCommunityRatings(result, items, topItem);
|
||||||
result = this.GetResultParentalRatings(result, items, topItem);
|
result = this.GetResultParentalRatings(result, items, topItem);
|
||||||
|
|
||||||
|
@ -100,30 +99,6 @@ namespace MediaBrowser.Api.Reports
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary> Gets resul production locations. </summary>
|
|
||||||
/// <param name="result"> The result. </param>
|
|
||||||
/// <param name="items"> The items. </param>
|
|
||||||
/// <param name="topItem"> The top item. </param>
|
|
||||||
/// <returns> The resul production locations. </returns>
|
|
||||||
private ReportStatResult GetResulProductionLocations(ReportStatResult result, BaseItem[] items, int topItem = 5)
|
|
||||||
{
|
|
||||||
this.GetGroups(result, GetLocalizedHeader(HeaderMetadata.Countries), topItem,
|
|
||||||
items.OfType<IHasProductionLocations>()
|
|
||||||
.Where(x => x.ProductionLocations != null)
|
|
||||||
.SelectMany(x => x.ProductionLocations)
|
|
||||||
.GroupBy(x => x)
|
|
||||||
.OrderByDescending(x => x.Count())
|
|
||||||
.Take(topItem)
|
|
||||||
.Select(x => new ReportStatItem
|
|
||||||
{
|
|
||||||
Name = x.Key.ToString(),
|
|
||||||
Value = x.Count().ToString()
|
|
||||||
})
|
|
||||||
);
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary> Gets result community ratings. </summary>
|
/// <summary> Gets result community ratings. </summary>
|
||||||
/// <param name="result"> The result. </param>
|
/// <param name="result"> The result. </param>
|
||||||
/// <param name="items"> The items. </param>
|
/// <param name="items"> The items. </param>
|
||||||
|
|
|
@ -81,7 +81,8 @@ namespace MediaBrowser.Api
|
||||||
var query = new InternalItemsQuery(user)
|
var query = new InternalItemsQuery(user)
|
||||||
{
|
{
|
||||||
IncludeItemTypes = includeTypes.Select(i => i.Name).ToArray(),
|
IncludeItemTypes = includeTypes.Select(i => i.Name).ToArray(),
|
||||||
Recursive = true
|
Recursive = true,
|
||||||
|
DtoOptions = dtoOptions
|
||||||
};
|
};
|
||||||
|
|
||||||
// ExcludeArtistIds
|
// ExcludeArtistIds
|
||||||
|
|
|
@ -88,8 +88,6 @@ namespace MediaBrowser.Api
|
||||||
var result = new StartupConfiguration
|
var result = new StartupConfiguration
|
||||||
{
|
{
|
||||||
UICulture = _config.Configuration.UICulture,
|
UICulture = _config.Configuration.UICulture,
|
||||||
EnableInternetProviders = _config.Configuration.EnableInternetProviders,
|
|
||||||
SaveLocalMeta = _config.Configuration.SaveLocalMeta,
|
|
||||||
MetadataCountryCode = _config.Configuration.MetadataCountryCode,
|
MetadataCountryCode = _config.Configuration.MetadataCountryCode,
|
||||||
PreferredMetadataLanguage = _config.Configuration.PreferredMetadataLanguage
|
PreferredMetadataLanguage = _config.Configuration.PreferredMetadataLanguage
|
||||||
};
|
};
|
||||||
|
@ -116,15 +114,16 @@ namespace MediaBrowser.Api
|
||||||
config.EnableLocalizedGuids = true;
|
config.EnableLocalizedGuids = true;
|
||||||
config.EnableStandaloneMusicKeys = true;
|
config.EnableStandaloneMusicKeys = true;
|
||||||
config.EnableCaseSensitiveItemIds = true;
|
config.EnableCaseSensitiveItemIds = true;
|
||||||
//config.EnableFolderView = true;
|
config.EnableFolderView = true;
|
||||||
config.SchemaVersion = 109;
|
config.SchemaVersion = 109;
|
||||||
|
config.EnableSimpleArtistDetection = true;
|
||||||
|
config.SkipDeserializationForBasicTypes = true;
|
||||||
|
config.SkipDeserializationForPrograms = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Post(UpdateStartupConfiguration request)
|
public void Post(UpdateStartupConfiguration request)
|
||||||
{
|
{
|
||||||
_config.Configuration.UICulture = request.UICulture;
|
_config.Configuration.UICulture = request.UICulture;
|
||||||
_config.Configuration.EnableInternetProviders = request.EnableInternetProviders;
|
|
||||||
_config.Configuration.SaveLocalMeta = request.SaveLocalMeta;
|
|
||||||
_config.Configuration.MetadataCountryCode = request.MetadataCountryCode;
|
_config.Configuration.MetadataCountryCode = request.MetadataCountryCode;
|
||||||
_config.Configuration.PreferredMetadataLanguage = request.PreferredMetadataLanguage;
|
_config.Configuration.PreferredMetadataLanguage = request.PreferredMetadataLanguage;
|
||||||
_config.SaveConfiguration();
|
_config.SaveConfiguration();
|
||||||
|
@ -215,8 +214,6 @@ namespace MediaBrowser.Api
|
||||||
public class StartupConfiguration
|
public class StartupConfiguration
|
||||||
{
|
{
|
||||||
public string UICulture { get; set; }
|
public string UICulture { get; set; }
|
||||||
public bool EnableInternetProviders { get; set; }
|
|
||||||
public bool SaveLocalMeta { get; set; }
|
|
||||||
public string MetadataCountryCode { get; set; }
|
public string MetadataCountryCode { get; set; }
|
||||||
public string PreferredMetadataLanguage { get; set; }
|
public string PreferredMetadataLanguage { get; set; }
|
||||||
public string LiveTvTunerType { get; set; }
|
public string LiveTvTunerType { get; set; }
|
||||||
|
|
|
@ -148,7 +148,7 @@ namespace MediaBrowser.Api.Subtitles
|
||||||
{
|
{
|
||||||
var item = (Video)_libraryManager.GetItemById(new Guid(request.Id));
|
var item = (Video)_libraryManager.GetItemById(new Guid(request.Id));
|
||||||
|
|
||||||
var mediaSource = await _mediaSourceManager.GetMediaSource(item, request.MediaSourceId, false).ConfigureAwait(false);
|
var mediaSource = await _mediaSourceManager.GetMediaSource(item, request.MediaSourceId, null, false, CancellationToken.None).ConfigureAwait(false);
|
||||||
|
|
||||||
var builder = new StringBuilder();
|
var builder = new StringBuilder();
|
||||||
|
|
||||||
|
|
|
@ -302,6 +302,8 @@ namespace MediaBrowser.Api
|
||||||
(!string.IsNullOrWhiteSpace(request.UserId) ? user.RootFolder :
|
(!string.IsNullOrWhiteSpace(request.UserId) ? user.RootFolder :
|
||||||
_libraryManager.RootFolder) : _libraryManager.GetItemById(request.Id);
|
_libraryManager.RootFolder) : _libraryManager.GetItemById(request.Id);
|
||||||
|
|
||||||
|
var dtoOptions = GetDtoOptions(request);
|
||||||
|
|
||||||
var itemsResult = _libraryManager.GetItemList(new InternalItemsQuery(user)
|
var itemsResult = _libraryManager.GetItemList(new InternalItemsQuery(user)
|
||||||
{
|
{
|
||||||
Limit = request.Limit,
|
Limit = request.Limit,
|
||||||
|
@ -309,12 +311,11 @@ namespace MediaBrowser.Api
|
||||||
{
|
{
|
||||||
typeof(Series).Name
|
typeof(Series).Name
|
||||||
},
|
},
|
||||||
SimilarTo = item
|
SimilarTo = item,
|
||||||
|
DtoOptions = dtoOptions
|
||||||
|
|
||||||
}).ToList();
|
}).ToList();
|
||||||
|
|
||||||
var dtoOptions = GetDtoOptions(request);
|
|
||||||
|
|
||||||
var result = new QueryResult<BaseItemDto>
|
var result = new QueryResult<BaseItemDto>
|
||||||
{
|
{
|
||||||
Items = (await _dtoService.GetBaseItemDtos(itemsResult, dtoOptions, user).ConfigureAwait(false)).ToArray(),
|
Items = (await _dtoService.GetBaseItemDtos(itemsResult, dtoOptions, user).ConfigureAwait(false)).ToArray(),
|
||||||
|
@ -333,6 +334,8 @@ namespace MediaBrowser.Api
|
||||||
|
|
||||||
var parentIdGuid = string.IsNullOrWhiteSpace(request.ParentId) ? (Guid?)null : new Guid(request.ParentId);
|
var parentIdGuid = string.IsNullOrWhiteSpace(request.ParentId) ? (Guid?)null : new Guid(request.ParentId);
|
||||||
|
|
||||||
|
var options = GetDtoOptions(request);
|
||||||
|
|
||||||
var itemsResult = _libraryManager.GetItemList(new InternalItemsQuery(user)
|
var itemsResult = _libraryManager.GetItemList(new InternalItemsQuery(user)
|
||||||
{
|
{
|
||||||
IncludeItemTypes = new[] { typeof(Episode).Name },
|
IncludeItemTypes = new[] { typeof(Episode).Name },
|
||||||
|
@ -342,12 +345,11 @@ namespace MediaBrowser.Api
|
||||||
StartIndex = request.StartIndex,
|
StartIndex = request.StartIndex,
|
||||||
Limit = request.Limit,
|
Limit = request.Limit,
|
||||||
ParentId = parentIdGuid,
|
ParentId = parentIdGuid,
|
||||||
Recursive = true
|
Recursive = true,
|
||||||
|
DtoOptions = options
|
||||||
|
|
||||||
}).ToList();
|
}).ToList();
|
||||||
|
|
||||||
var options = GetDtoOptions(request);
|
|
||||||
|
|
||||||
var returnItems = (await _dtoService.GetBaseItemDtos(itemsResult, options, user).ConfigureAwait(false)).ToArray();
|
var returnItems = (await _dtoService.GetBaseItemDtos(itemsResult, options, user).ConfigureAwait(false)).ToArray();
|
||||||
|
|
||||||
var result = new ItemsResult
|
var result = new ItemsResult
|
||||||
|
|
|
@ -205,6 +205,7 @@ namespace MediaBrowser.Api.UserLibrary
|
||||||
private void SetItemCounts(BaseItemDto dto, ItemCounts counts)
|
private void SetItemCounts(BaseItemDto dto, ItemCounts counts)
|
||||||
{
|
{
|
||||||
dto.ChildCount = counts.ItemCount;
|
dto.ChildCount = counts.ItemCount;
|
||||||
|
dto.ProgramCount = counts.ProgramCount;
|
||||||
dto.SeriesCount = counts.SeriesCount;
|
dto.SeriesCount = counts.SeriesCount;
|
||||||
dto.EpisodeCount = counts.EpisodeCount;
|
dto.EpisodeCount = counts.EpisodeCount;
|
||||||
dto.MovieCount = counts.MovieCount;
|
dto.MovieCount = counts.MovieCount;
|
||||||
|
|
|
@ -99,8 +99,10 @@ namespace MediaBrowser.Api.UserLibrary
|
||||||
private async Task<ItemsResult> GetItems(GetItems request)
|
private async Task<ItemsResult> GetItems(GetItems request)
|
||||||
{
|
{
|
||||||
var user = !string.IsNullOrWhiteSpace(request.UserId) ? _userManager.GetUserById(request.UserId) : null;
|
var user = !string.IsNullOrWhiteSpace(request.UserId) ? _userManager.GetUserById(request.UserId) : null;
|
||||||
|
|
||||||
var result = await GetQueryResult(request, user).ConfigureAwait(false);
|
var dtoOptions = GetDtoOptions(request);
|
||||||
|
|
||||||
|
var result = await GetQueryResult(request, dtoOptions, user).ConfigureAwait(false);
|
||||||
|
|
||||||
if (result == null)
|
if (result == null)
|
||||||
{
|
{
|
||||||
|
@ -112,8 +114,6 @@ namespace MediaBrowser.Api.UserLibrary
|
||||||
throw new InvalidOperationException("GetItemsToSerialize result.Items returned null");
|
throw new InvalidOperationException("GetItemsToSerialize result.Items returned null");
|
||||||
}
|
}
|
||||||
|
|
||||||
var dtoOptions = GetDtoOptions(request);
|
|
||||||
|
|
||||||
var dtoList = await _dtoService.GetBaseItemDtos(result.Items, dtoOptions, user).ConfigureAwait(false);
|
var dtoList = await _dtoService.GetBaseItemDtos(result.Items, dtoOptions, user).ConfigureAwait(false);
|
||||||
|
|
||||||
if (dtoList == null)
|
if (dtoList == null)
|
||||||
|
@ -131,24 +131,31 @@ namespace MediaBrowser.Api.UserLibrary
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets the items to serialize.
|
/// Gets the items to serialize.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="request">The request.</param>
|
private async Task<QueryResult<BaseItem>> GetQueryResult(GetItems request, DtoOptions dtoOptions, User user)
|
||||||
/// <param name="user">The user.</param>
|
|
||||||
/// <returns>IEnumerable{BaseItem}.</returns>
|
|
||||||
private async Task<QueryResult<BaseItem>> GetQueryResult(GetItems request, User user)
|
|
||||||
{
|
{
|
||||||
var item = string.IsNullOrEmpty(request.ParentId) ?
|
var item = string.IsNullOrEmpty(request.ParentId) ?
|
||||||
user == null ? _libraryManager.RootFolder : user.RootFolder :
|
null :
|
||||||
_libraryManager.GetItemById(request.ParentId);
|
_libraryManager.GetItemById(request.ParentId);
|
||||||
|
|
||||||
if (string.Equals(request.IncludeItemTypes, "Playlist", StringComparison.OrdinalIgnoreCase))
|
if (string.Equals(request.IncludeItemTypes, "Playlist", StringComparison.OrdinalIgnoreCase))
|
||||||
{
|
{
|
||||||
//item = user == null ? _libraryManager.RootFolder : user.RootFolder;
|
if (item == null || user != null)
|
||||||
|
{
|
||||||
|
item = _libraryManager.RootFolder.Children.OfType<Folder>().FirstOrDefault(i => string.Equals(i.GetType().Name, "PlaylistsFolder", StringComparison.OrdinalIgnoreCase));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else if (string.Equals(request.IncludeItemTypes, "BoxSet", StringComparison.OrdinalIgnoreCase))
|
else if (string.Equals(request.IncludeItemTypes, "BoxSet", StringComparison.OrdinalIgnoreCase))
|
||||||
{
|
{
|
||||||
item = user == null ? _libraryManager.RootFolder : user.RootFolder;
|
item = user == null ? _libraryManager.RootFolder : user.RootFolder;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (item == null)
|
||||||
|
{
|
||||||
|
item = string.IsNullOrEmpty(request.ParentId) ?
|
||||||
|
user == null ? _libraryManager.RootFolder : user.RootFolder :
|
||||||
|
_libraryManager.GetItemById(request.ParentId);
|
||||||
|
}
|
||||||
|
|
||||||
// Default list type = children
|
// Default list type = children
|
||||||
|
|
||||||
var folder = item as Folder;
|
var folder = item as Folder;
|
||||||
|
@ -159,14 +166,14 @@ namespace MediaBrowser.Api.UserLibrary
|
||||||
|
|
||||||
if (request.Recursive || !string.IsNullOrEmpty(request.Ids) || user == null)
|
if (request.Recursive || !string.IsNullOrEmpty(request.Ids) || user == null)
|
||||||
{
|
{
|
||||||
return await folder.GetItems(GetItemsQuery(request, user)).ConfigureAwait(false);
|
return await folder.GetItems(GetItemsQuery(request, dtoOptions, user)).ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
var userRoot = item as UserRootFolder;
|
var userRoot = item as UserRootFolder;
|
||||||
|
|
||||||
if (userRoot == null)
|
if (userRoot == null)
|
||||||
{
|
{
|
||||||
return await folder.GetItems(GetItemsQuery(request, user)).ConfigureAwait(false);
|
return await folder.GetItems(GetItemsQuery(request, dtoOptions, user)).ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
IEnumerable<BaseItem> items = folder.GetChildren(user, true);
|
IEnumerable<BaseItem> items = folder.GetChildren(user, true);
|
||||||
|
@ -180,7 +187,7 @@ namespace MediaBrowser.Api.UserLibrary
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
private InternalItemsQuery GetItemsQuery(GetItems request, User user)
|
private InternalItemsQuery GetItemsQuery(GetItems request, DtoOptions dtoOptions, User user)
|
||||||
{
|
{
|
||||||
var query = new InternalItemsQuery(user)
|
var query = new InternalItemsQuery(user)
|
||||||
{
|
{
|
||||||
|
@ -241,7 +248,8 @@ namespace MediaBrowser.Api.UserLibrary
|
||||||
AiredDuringSeason = request.AiredDuringSeason,
|
AiredDuringSeason = request.AiredDuringSeason,
|
||||||
AlbumArtistStartsWithOrGreater = request.AlbumArtistStartsWithOrGreater,
|
AlbumArtistStartsWithOrGreater = request.AlbumArtistStartsWithOrGreater,
|
||||||
EnableTotalRecordCount = request.EnableTotalRecordCount,
|
EnableTotalRecordCount = request.EnableTotalRecordCount,
|
||||||
ExcludeItemIds = request.GetExcludeItemIds()
|
ExcludeItemIds = request.GetExcludeItemIds(),
|
||||||
|
DtoOptions = dtoOptions
|
||||||
};
|
};
|
||||||
|
|
||||||
if (!string.IsNullOrWhiteSpace(request.Ids))
|
if (!string.IsNullOrWhiteSpace(request.Ids))
|
||||||
|
|
|
@ -30,6 +30,7 @@ using System.Text;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using CommonIO;
|
using CommonIO;
|
||||||
|
using MediaBrowser.Common.IO;
|
||||||
|
|
||||||
namespace MediaBrowser.Common.Implementations
|
namespace MediaBrowser.Common.Implementations
|
||||||
{
|
{
|
||||||
|
@ -192,6 +193,8 @@ namespace MediaBrowser.Common.Implementations
|
||||||
get { return Environment.OSVersion.VersionString; }
|
get { return Environment.OSVersion.VersionString; }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public IMemoryStreamProvider MemoryStreamProvider { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Initializes a new instance of the <see cref="BaseApplicationHost{TApplicationPathsType}"/> class.
|
/// Initializes a new instance of the <see cref="BaseApplicationHost{TApplicationPathsType}"/> class.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
@ -231,6 +234,8 @@ namespace MediaBrowser.Common.Implementations
|
||||||
|
|
||||||
JsonSerializer = CreateJsonSerializer();
|
JsonSerializer = CreateJsonSerializer();
|
||||||
|
|
||||||
|
MemoryStreamProvider = new MemoryStreamProvider();
|
||||||
|
|
||||||
OnLoggerLoaded(true);
|
OnLoggerLoaded(true);
|
||||||
LogManager.LoggerLoaded += (s, e) => OnLoggerLoaded(false);
|
LogManager.LoggerLoaded += (s, e) => OnLoggerLoaded(false);
|
||||||
|
|
||||||
|
@ -456,6 +461,7 @@ namespace MediaBrowser.Common.Implementations
|
||||||
|
|
||||||
RegisterSingleInstance(JsonSerializer);
|
RegisterSingleInstance(JsonSerializer);
|
||||||
RegisterSingleInstance(XmlSerializer);
|
RegisterSingleInstance(XmlSerializer);
|
||||||
|
RegisterSingleInstance(MemoryStreamProvider);
|
||||||
|
|
||||||
RegisterSingleInstance(LogManager);
|
RegisterSingleInstance(LogManager);
|
||||||
RegisterSingleInstance(Logger);
|
RegisterSingleInstance(Logger);
|
||||||
|
@ -464,7 +470,7 @@ namespace MediaBrowser.Common.Implementations
|
||||||
|
|
||||||
RegisterSingleInstance(FileSystemManager);
|
RegisterSingleInstance(FileSystemManager);
|
||||||
|
|
||||||
HttpClient = new HttpClientManager.HttpClientManager(ApplicationPaths, LogManager.GetLogger("HttpClient"), FileSystemManager);
|
HttpClient = new HttpClientManager.HttpClientManager(ApplicationPaths, LogManager.GetLogger("HttpClient"), FileSystemManager, MemoryStreamProvider);
|
||||||
RegisterSingleInstance(HttpClient);
|
RegisterSingleInstance(HttpClient);
|
||||||
|
|
||||||
NetworkManager = CreateNetworkManager(LogManager.GetLogger("NetworkManager"));
|
NetworkManager = CreateNetworkManager(LogManager.GetLogger("NetworkManager"));
|
||||||
|
|
|
@ -42,6 +42,7 @@ namespace MediaBrowser.Common.Implementations.HttpClientManager
|
||||||
private readonly IApplicationPaths _appPaths;
|
private readonly IApplicationPaths _appPaths;
|
||||||
|
|
||||||
private readonly IFileSystem _fileSystem;
|
private readonly IFileSystem _fileSystem;
|
||||||
|
private readonly IMemoryStreamProvider _memoryStreamProvider;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Initializes a new instance of the <see cref="HttpClientManager" /> class.
|
/// Initializes a new instance of the <see cref="HttpClientManager" /> class.
|
||||||
|
@ -52,7 +53,7 @@ namespace MediaBrowser.Common.Implementations.HttpClientManager
|
||||||
/// <exception cref="System.ArgumentNullException">appPaths
|
/// <exception cref="System.ArgumentNullException">appPaths
|
||||||
/// or
|
/// or
|
||||||
/// logger</exception>
|
/// logger</exception>
|
||||||
public HttpClientManager(IApplicationPaths appPaths, ILogger logger, IFileSystem fileSystem)
|
public HttpClientManager(IApplicationPaths appPaths, ILogger logger, IFileSystem fileSystem, IMemoryStreamProvider memoryStreamProvider)
|
||||||
{
|
{
|
||||||
if (appPaths == null)
|
if (appPaths == null)
|
||||||
{
|
{
|
||||||
|
@ -65,6 +66,7 @@ namespace MediaBrowser.Common.Implementations.HttpClientManager
|
||||||
|
|
||||||
_logger = logger;
|
_logger = logger;
|
||||||
_fileSystem = fileSystem;
|
_fileSystem = fileSystem;
|
||||||
|
_memoryStreamProvider = memoryStreamProvider;
|
||||||
_appPaths = appPaths;
|
_appPaths = appPaths;
|
||||||
|
|
||||||
// http://stackoverflow.com/questions/566437/http-post-returns-the-error-417-expectation-failed-c
|
// http://stackoverflow.com/questions/566437/http-post-returns-the-error-417-expectation-failed-c
|
||||||
|
@ -269,6 +271,7 @@ namespace MediaBrowser.Common.Implementations.HttpClientManager
|
||||||
Url = url,
|
Url = url,
|
||||||
ResourcePool = resourcePool,
|
ResourcePool = resourcePool,
|
||||||
CancellationToken = cancellationToken,
|
CancellationToken = cancellationToken,
|
||||||
|
BufferContent = resourcePool != null
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -293,12 +296,9 @@ namespace MediaBrowser.Common.Implementations.HttpClientManager
|
||||||
/// </exception>
|
/// </exception>
|
||||||
public async Task<HttpResponseInfo> SendAsync(HttpRequestOptions options, string httpMethod)
|
public async Task<HttpResponseInfo> SendAsync(HttpRequestOptions options, string httpMethod)
|
||||||
{
|
{
|
||||||
HttpResponseInfo response;
|
|
||||||
|
|
||||||
if (options.CacheMode == CacheMode.None)
|
if (options.CacheMode == CacheMode.None)
|
||||||
{
|
{
|
||||||
response = await SendAsyncInternal(options, httpMethod).ConfigureAwait(false);
|
return await SendAsyncInternal(options, httpMethod).ConfigureAwait(false);
|
||||||
return response;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
var url = options.Url;
|
var url = options.Url;
|
||||||
|
@ -306,7 +306,7 @@ namespace MediaBrowser.Common.Implementations.HttpClientManager
|
||||||
|
|
||||||
var responseCachePath = Path.Combine(_appPaths.CachePath, "httpclient", urlHash);
|
var responseCachePath = Path.Combine(_appPaths.CachePath, "httpclient", urlHash);
|
||||||
|
|
||||||
response = await GetCachedResponse(responseCachePath, options.CacheLength, url).ConfigureAwait(false);
|
var response = await GetCachedResponse(responseCachePath, options.CacheLength, url).ConfigureAwait(false);
|
||||||
if (response != null)
|
if (response != null)
|
||||||
{
|
{
|
||||||
return response;
|
return response;
|
||||||
|
@ -332,7 +332,7 @@ namespace MediaBrowser.Common.Implementations.HttpClientManager
|
||||||
{
|
{
|
||||||
using (var stream = _fileSystem.GetFileStream(responseCachePath, FileMode.Open, FileAccess.Read, FileShare.Read, true))
|
using (var stream = _fileSystem.GetFileStream(responseCachePath, FileMode.Open, FileAccess.Read, FileShare.Read, true))
|
||||||
{
|
{
|
||||||
var memoryStream = new MemoryStream();
|
var memoryStream = _memoryStreamProvider.CreateNew();
|
||||||
|
|
||||||
await stream.CopyToAsync(memoryStream).ConfigureAwait(false);
|
await stream.CopyToAsync(memoryStream).ConfigureAwait(false);
|
||||||
memoryStream.Position = 0;
|
memoryStream.Position = 0;
|
||||||
|
@ -366,7 +366,7 @@ namespace MediaBrowser.Common.Implementations.HttpClientManager
|
||||||
|
|
||||||
using (var responseStream = response.Content)
|
using (var responseStream = response.Content)
|
||||||
{
|
{
|
||||||
var memoryStream = new MemoryStream();
|
var memoryStream = _memoryStreamProvider.CreateNew();
|
||||||
await responseStream.CopyToAsync(memoryStream).ConfigureAwait(false);
|
await responseStream.CopyToAsync(memoryStream).ConfigureAwait(false);
|
||||||
memoryStream.Position = 0;
|
memoryStream.Position = 0;
|
||||||
|
|
||||||
|
@ -458,7 +458,7 @@ namespace MediaBrowser.Common.Implementations.HttpClientManager
|
||||||
|
|
||||||
using (var stream = httpResponse.GetResponseStream())
|
using (var stream = httpResponse.GetResponseStream())
|
||||||
{
|
{
|
||||||
var memoryStream = new MemoryStream();
|
var memoryStream = _memoryStreamProvider.CreateNew();
|
||||||
|
|
||||||
await stream.CopyToAsync(memoryStream).ConfigureAwait(false);
|
await stream.CopyToAsync(memoryStream).ConfigureAwait(false);
|
||||||
|
|
||||||
|
@ -553,7 +553,8 @@ namespace MediaBrowser.Common.Implementations.HttpClientManager
|
||||||
{
|
{
|
||||||
Url = url,
|
Url = url,
|
||||||
ResourcePool = resourcePool,
|
ResourcePool = resourcePool,
|
||||||
CancellationToken = cancellationToken
|
CancellationToken = cancellationToken,
|
||||||
|
BufferContent = resourcePool != null
|
||||||
|
|
||||||
}, postData);
|
}, postData);
|
||||||
}
|
}
|
||||||
|
@ -563,7 +564,6 @@ namespace MediaBrowser.Common.Implementations.HttpClientManager
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="options">The options.</param>
|
/// <param name="options">The options.</param>
|
||||||
/// <returns>Task{System.String}.</returns>
|
/// <returns>Task{System.String}.</returns>
|
||||||
/// <exception cref="System.ArgumentNullException">progress</exception>
|
|
||||||
public async Task<string> GetTempFile(HttpRequestOptions options)
|
public async Task<string> GetTempFile(HttpRequestOptions options)
|
||||||
{
|
{
|
||||||
var response = await GetTempFileResponse(options).ConfigureAwait(false);
|
var response = await GetTempFileResponse(options).ConfigureAwait(false);
|
||||||
|
|
|
@ -0,0 +1,31 @@
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.IO;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using MediaBrowser.Common.IO;
|
||||||
|
using Microsoft.IO;
|
||||||
|
|
||||||
|
namespace MediaBrowser.Common.Implementations.IO
|
||||||
|
{
|
||||||
|
public class MemoryStreamProvider : IMemoryStreamProvider
|
||||||
|
{
|
||||||
|
readonly RecyclableMemoryStreamManager _manager = new RecyclableMemoryStreamManager();
|
||||||
|
|
||||||
|
public MemoryStream CreateNew()
|
||||||
|
{
|
||||||
|
return _manager.GetStream();
|
||||||
|
}
|
||||||
|
|
||||||
|
public MemoryStream CreateNew(int capacity)
|
||||||
|
{
|
||||||
|
return _manager.GetStream("RecyclableMemoryStream", capacity);
|
||||||
|
}
|
||||||
|
|
||||||
|
public MemoryStream CreateNew(byte[] buffer)
|
||||||
|
{
|
||||||
|
return _manager.GetStream("RecyclableMemoryStream", buffer, 0, buffer.Length);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -72,6 +72,11 @@ namespace MediaBrowser.Common.Implementations.Logging
|
||||||
/// <param name="paramList">The param list.</param>
|
/// <param name="paramList">The param list.</param>
|
||||||
public void Debug(string message, params object[] paramList)
|
public void Debug(string message, params object[] paramList)
|
||||||
{
|
{
|
||||||
|
if (_logManager.LogSeverity == LogSeverity.Info)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
_logger.Debug(message, paramList);
|
_logger.Debug(message, paramList);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -137,6 +142,11 @@ namespace MediaBrowser.Common.Implementations.Logging
|
||||||
/// <param name="additionalContent">Content of the additional.</param>
|
/// <param name="additionalContent">Content of the additional.</param>
|
||||||
public void LogMultiline(string message, LogSeverity severity, StringBuilder additionalContent)
|
public void LogMultiline(string message, LogSeverity severity, StringBuilder additionalContent)
|
||||||
{
|
{
|
||||||
|
if (severity == LogSeverity.Debug && _logManager.LogSeverity == LogSeverity.Info)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
additionalContent.Insert(0, message + Environment.NewLine);
|
additionalContent.Insert(0, message + Environment.NewLine);
|
||||||
|
|
||||||
const char tabChar = '\t';
|
const char tabChar = '\t';
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
<Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||||
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
|
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
||||||
|
@ -14,6 +14,7 @@
|
||||||
<ProductVersion>10.0.0</ProductVersion>
|
<ProductVersion>10.0.0</ProductVersion>
|
||||||
<SchemaVersion>2.0</SchemaVersion>
|
<SchemaVersion>2.0</SchemaVersion>
|
||||||
<TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
|
<TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
|
||||||
|
<TargetFrameworkProfile />
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
||||||
<DebugSymbols>true</DebugSymbols>
|
<DebugSymbols>true</DebugSymbols>
|
||||||
|
@ -23,7 +24,7 @@
|
||||||
<DefineConstants>DEBUG;TRACE</DefineConstants>
|
<DefineConstants>DEBUG;TRACE</DefineConstants>
|
||||||
<ErrorReport>prompt</ErrorReport>
|
<ErrorReport>prompt</ErrorReport>
|
||||||
<WarningLevel>4</WarningLevel>
|
<WarningLevel>4</WarningLevel>
|
||||||
<TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
|
<TargetFrameworkVersion>v4.5.1</TargetFrameworkVersion>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
|
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
|
||||||
<DebugType>none</DebugType>
|
<DebugType>none</DebugType>
|
||||||
|
@ -51,11 +52,15 @@
|
||||||
<SpecificVersion>False</SpecificVersion>
|
<SpecificVersion>False</SpecificVersion>
|
||||||
<HintPath>..\packages\CommonIO.1.0.0.9\lib\net45\CommonIO.dll</HintPath>
|
<HintPath>..\packages\CommonIO.1.0.0.9\lib\net45\CommonIO.dll</HintPath>
|
||||||
</Reference>
|
</Reference>
|
||||||
|
<Reference Include="Microsoft.IO.RecyclableMemoryStream, Version=1.1.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
|
||||||
|
<HintPath>..\packages\Microsoft.IO.RecyclableMemoryStream.1.1.0.0\lib\net45\Microsoft.IO.RecyclableMemoryStream.dll</HintPath>
|
||||||
|
<Private>True</Private>
|
||||||
|
</Reference>
|
||||||
<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, Version=4.0.0.0, Culture=neutral, PublicKeyToken=5120e14c03d0593c, processorArchitecture=MSIL">
|
<Reference Include="NLog, Version=4.0.0.0, Culture=neutral, PublicKeyToken=5120e14c03d0593c, processorArchitecture=MSIL">
|
||||||
<HintPath>..\packages\NLog.4.3.6\lib\net45\NLog.dll</HintPath>
|
<HintPath>..\packages\NLog.4.3.8\lib\net45\NLog.dll</HintPath>
|
||||||
<Private>True</Private>
|
<Private>True</Private>
|
||||||
</Reference>
|
</Reference>
|
||||||
<Reference Include="Patterns.Logging">
|
<Reference Include="Patterns.Logging">
|
||||||
|
@ -65,8 +70,8 @@
|
||||||
<SpecificVersion>False</SpecificVersion>
|
<SpecificVersion>False</SpecificVersion>
|
||||||
<HintPath>..\ThirdParty\SharpCompress\SharpCompress.dll</HintPath>
|
<HintPath>..\ThirdParty\SharpCompress\SharpCompress.dll</HintPath>
|
||||||
</Reference>
|
</Reference>
|
||||||
<Reference Include="SimpleInjector, Version=3.2.0.0, Culture=neutral, PublicKeyToken=984cb50dea722e99, processorArchitecture=MSIL">
|
<Reference Include="SimpleInjector, Version=3.2.2.0, Culture=neutral, PublicKeyToken=984cb50dea722e99, processorArchitecture=MSIL">
|
||||||
<HintPath>..\packages\SimpleInjector.3.2.0\lib\net45\SimpleInjector.dll</HintPath>
|
<HintPath>..\packages\SimpleInjector.3.2.2\lib\net45\SimpleInjector.dll</HintPath>
|
||||||
<Private>True</Private>
|
<Private>True</Private>
|
||||||
</Reference>
|
</Reference>
|
||||||
<Reference Include="System" />
|
<Reference Include="System" />
|
||||||
|
@ -75,6 +80,9 @@
|
||||||
<Reference Include="Microsoft.CSharp" />
|
<Reference Include="Microsoft.CSharp" />
|
||||||
<Reference Include="System.Data" />
|
<Reference Include="System.Data" />
|
||||||
<Reference Include="System.Net" />
|
<Reference Include="System.Net" />
|
||||||
|
<Reference Include="System.Text.Json">
|
||||||
|
<HintPath>..\ThirdParty\fastjsonparser\System.Text.Json.dll</HintPath>
|
||||||
|
</Reference>
|
||||||
<Reference Include="System.Xml" />
|
<Reference Include="System.Xml" />
|
||||||
<Reference Include="ServiceStack.Text">
|
<Reference Include="ServiceStack.Text">
|
||||||
<HintPath>..\ThirdParty\ServiceStack.Text\ServiceStack.Text.dll</HintPath>
|
<HintPath>..\ThirdParty\ServiceStack.Text\ServiceStack.Text.dll</HintPath>
|
||||||
|
@ -93,6 +101,7 @@
|
||||||
<Compile Include="HttpClientManager\HttpClientInfo.cs" />
|
<Compile Include="HttpClientManager\HttpClientInfo.cs" />
|
||||||
<Compile Include="HttpClientManager\HttpClientManager.cs" />
|
<Compile Include="HttpClientManager\HttpClientManager.cs" />
|
||||||
<Compile Include="IO\IsoManager.cs" />
|
<Compile Include="IO\IsoManager.cs" />
|
||||||
|
<Compile Include="IO\MemoryStreamProvider.cs" />
|
||||||
<Compile Include="Logging\LogHelper.cs" />
|
<Compile Include="Logging\LogHelper.cs" />
|
||||||
<Compile Include="Logging\NLogger.cs" />
|
<Compile Include="Logging\NLogger.cs" />
|
||||||
<Compile Include="Logging\NlogManager.cs" />
|
<Compile Include="Logging\NlogManager.cs" />
|
||||||
|
|
|
@ -390,13 +390,13 @@ namespace MediaBrowser.Common.Implementations.ScheduledTasks
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
var localTask = ScheduledTask.Execute(CurrentCancellationTokenSource.Token, progress);
|
|
||||||
|
|
||||||
if (options != null && options.MaxRuntimeMs.HasValue)
|
if (options != null && options.MaxRuntimeMs.HasValue)
|
||||||
{
|
{
|
||||||
CurrentCancellationTokenSource.CancelAfter(options.MaxRuntimeMs.Value);
|
CurrentCancellationTokenSource.CancelAfter(options.MaxRuntimeMs.Value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var localTask = ScheduledTask.Execute(CurrentCancellationTokenSource.Token, progress);
|
||||||
|
|
||||||
await localTask.ConfigureAwait(false);
|
await localTask.ConfigureAwait(false);
|
||||||
|
|
||||||
status = TaskCompletionStatus.Completed;
|
status = TaskCompletionStatus.Completed;
|
||||||
|
|
|
@ -169,7 +169,8 @@ namespace MediaBrowser.Common.Implementations.Security
|
||||||
var options = new HttpRequestOptions()
|
var options = new HttpRequestOptions()
|
||||||
{
|
{
|
||||||
Url = AppstoreRegUrl,
|
Url = AppstoreRegUrl,
|
||||||
CancellationToken = CancellationToken.None
|
CancellationToken = CancellationToken.None,
|
||||||
|
BufferContent = false
|
||||||
};
|
};
|
||||||
options.RequestHeaders.Add("X-Emby-Token", _appHost.SystemId);
|
options.RequestHeaders.Add("X-Emby-Token", _appHost.SystemId);
|
||||||
options.RequestContent = parameters;
|
options.RequestContent = parameters;
|
||||||
|
@ -269,7 +270,8 @@ namespace MediaBrowser.Common.Implementations.Security
|
||||||
Url = MBValidateUrl,
|
Url = MBValidateUrl,
|
||||||
|
|
||||||
// Seeing block length errors
|
// Seeing block length errors
|
||||||
EnableHttpCompression = false
|
EnableHttpCompression = false,
|
||||||
|
BufferContent = false
|
||||||
};
|
};
|
||||||
|
|
||||||
options.SetPostData(data);
|
options.SetPostData(data);
|
||||||
|
|
|
@ -30,7 +30,8 @@ namespace MediaBrowser.Common.Implementations.Updates
|
||||||
Url = url,
|
Url = url,
|
||||||
EnableKeepAlive = false,
|
EnableKeepAlive = false,
|
||||||
CancellationToken = cancellationToken,
|
CancellationToken = cancellationToken,
|
||||||
UserAgent = "Emby/3.0"
|
UserAgent = "Emby/3.0",
|
||||||
|
BufferContent = false
|
||||||
};
|
};
|
||||||
|
|
||||||
if (cacheLength.Ticks > 0)
|
if (cacheLength.Ticks > 0)
|
||||||
|
@ -105,7 +106,8 @@ namespace MediaBrowser.Common.Implementations.Updates
|
||||||
Url = url,
|
Url = url,
|
||||||
EnableKeepAlive = false,
|
EnableKeepAlive = false,
|
||||||
CancellationToken = cancellationToken,
|
CancellationToken = cancellationToken,
|
||||||
UserAgent = "Emby/3.0"
|
UserAgent = "Emby/3.0",
|
||||||
|
BufferContent = false
|
||||||
};
|
};
|
||||||
|
|
||||||
using (var stream = await _httpClient.Get(options).ConfigureAwait(false))
|
using (var stream = await _httpClient.Get(options).ConfigureAwait(false))
|
||||||
|
|
|
@ -148,14 +148,10 @@ namespace MediaBrowser.Common.Implementations.Updates
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets all available packages.
|
/// Gets all available packages.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="cancellationToken">The cancellation token.</param>
|
|
||||||
/// <param name="withRegistration">if set to <c>true</c> [with registration].</param>
|
|
||||||
/// <param name="packageType">Type of the package.</param>
|
|
||||||
/// <param name="applicationVersion">The application version.</param>
|
|
||||||
/// <returns>Task{List{PackageInfo}}.</returns>
|
/// <returns>Task{List{PackageInfo}}.</returns>
|
||||||
public async Task<IEnumerable<PackageInfo>> GetAvailablePackages(CancellationToken cancellationToken,
|
public async Task<IEnumerable<PackageInfo>> GetAvailablePackages(CancellationToken cancellationToken,
|
||||||
bool withRegistration = true,
|
bool withRegistration = true,
|
||||||
PackageType? packageType = null,
|
string packageType = null,
|
||||||
Version applicationVersion = null)
|
Version applicationVersion = null)
|
||||||
{
|
{
|
||||||
var data = new Dictionary<string, string>
|
var data = new Dictionary<string, string>
|
||||||
|
@ -293,7 +289,7 @@ namespace MediaBrowser.Common.Implementations.Updates
|
||||||
return packages;
|
return packages;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected IEnumerable<PackageInfo> FilterPackages(List<PackageInfo> packages, PackageType? packageType, Version applicationVersion)
|
protected IEnumerable<PackageInfo> FilterPackages(List<PackageInfo> packages, string packageType, Version applicationVersion)
|
||||||
{
|
{
|
||||||
foreach (var package in packages)
|
foreach (var package in packages)
|
||||||
{
|
{
|
||||||
|
@ -301,9 +297,9 @@ namespace MediaBrowser.Common.Implementations.Updates
|
||||||
.OrderByDescending(GetPackageVersion).ToList();
|
.OrderByDescending(GetPackageVersion).ToList();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (packageType.HasValue)
|
if (!string.IsNullOrWhiteSpace(packageType))
|
||||||
{
|
{
|
||||||
packages = packages.Where(p => p.type == packageType.Value).ToList();
|
packages = packages.Where(p => string.Equals(p.type, packageType, StringComparison.OrdinalIgnoreCase)).ToList();
|
||||||
}
|
}
|
||||||
|
|
||||||
// If an app version was supplied, filter the versions for each package to only include supported versions
|
// If an app version was supplied, filter the versions for each package to only include supported versions
|
||||||
|
|
|
@ -1,8 +1,9 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<packages>
|
<packages>
|
||||||
<package id="CommonIO" version="1.0.0.9" targetFramework="net45" />
|
<package id="CommonIO" version="1.0.0.9" targetFramework="net45" />
|
||||||
|
<package id="Microsoft.IO.RecyclableMemoryStream" version="1.1.0.0" 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.3.6" targetFramework="net45" />
|
<package id="NLog" version="4.3.8" 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.2.0" targetFramework="net45" />
|
<package id="SimpleInjector" version="3.2.2" targetFramework="net45" />
|
||||||
</packages>
|
</packages>
|
11
MediaBrowser.Common/IO/IMemoryStreamProvider.cs
Normal file
11
MediaBrowser.Common/IO/IMemoryStreamProvider.cs
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
using System.IO;
|
||||||
|
|
||||||
|
namespace MediaBrowser.Common.IO
|
||||||
|
{
|
||||||
|
public interface IMemoryStreamProvider
|
||||||
|
{
|
||||||
|
MemoryStream CreateNew();
|
||||||
|
MemoryStream CreateNew(int capacity);
|
||||||
|
MemoryStream CreateNew(byte[] buffer);
|
||||||
|
}
|
||||||
|
}
|
|
@ -60,6 +60,7 @@
|
||||||
<Compile Include="Extensions\BaseExtensions.cs" />
|
<Compile Include="Extensions\BaseExtensions.cs" />
|
||||||
<Compile Include="Extensions\ResourceNotFoundException.cs" />
|
<Compile Include="Extensions\ResourceNotFoundException.cs" />
|
||||||
<Compile Include="IDependencyContainer.cs" />
|
<Compile Include="IDependencyContainer.cs" />
|
||||||
|
<Compile Include="IO\IMemoryStreamProvider.cs" />
|
||||||
<Compile Include="IO\ProgressStream.cs" />
|
<Compile Include="IO\ProgressStream.cs" />
|
||||||
<Compile Include="IO\StreamDefaults.cs" />
|
<Compile Include="IO\StreamDefaults.cs" />
|
||||||
<Compile Include="Configuration\IApplicationPaths.cs" />
|
<Compile Include="Configuration\IApplicationPaths.cs" />
|
||||||
|
|
|
@ -51,7 +51,7 @@ namespace MediaBrowser.Common.Updates
|
||||||
/// <returns>Task{List{PackageInfo}}.</returns>
|
/// <returns>Task{List{PackageInfo}}.</returns>
|
||||||
Task<IEnumerable<PackageInfo>> GetAvailablePackages(CancellationToken cancellationToken,
|
Task<IEnumerable<PackageInfo>> GetAvailablePackages(CancellationToken cancellationToken,
|
||||||
bool withRegistration = true,
|
bool withRegistration = true,
|
||||||
PackageType? packageType = null,
|
string packageType = null,
|
||||||
Version applicationVersion = null);
|
Version applicationVersion = null);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|
|
@ -134,15 +134,5 @@ namespace MediaBrowser.Controller.Channels
|
||||||
/// <param name="cancellationToken">The cancellation token.</param>
|
/// <param name="cancellationToken">The cancellation token.</param>
|
||||||
/// <returns>BaseItemDto.</returns>
|
/// <returns>BaseItemDto.</returns>
|
||||||
Task<BaseItemDto> GetChannelFolder(string userId, CancellationToken cancellationToken);
|
Task<BaseItemDto> GetChannelFolder(string userId, CancellationToken cancellationToken);
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Downloads the channel item.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="item">The item.</param>
|
|
||||||
/// <param name="destinationPath">The destination path.</param>
|
|
||||||
/// <param name="progress">The progress.</param>
|
|
||||||
/// <param name="cancellationToken">The cancellation token.</param>
|
|
||||||
/// <returns>Task.</returns>
|
|
||||||
Task DownloadChannelItem(BaseItem item, string destinationPath, IProgress<double> progress, CancellationToken cancellationToken);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,19 +0,0 @@
|
||||||
using MediaBrowser.Model.Chapters;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
|
|
||||||
namespace MediaBrowser.Controller.Chapters
|
|
||||||
{
|
|
||||||
public class ChapterResponse
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// Gets or sets the chapters.
|
|
||||||
/// </summary>
|
|
||||||
/// <value>The chapters.</value>
|
|
||||||
public List<RemoteChapterInfo> Chapters { get; set; }
|
|
||||||
|
|
||||||
public ChapterResponse()
|
|
||||||
{
|
|
||||||
Chapters = new List<RemoteChapterInfo>();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,31 +0,0 @@
|
||||||
using MediaBrowser.Controller.Providers;
|
|
||||||
using MediaBrowser.Model.Entities;
|
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
|
|
||||||
namespace MediaBrowser.Controller.Chapters
|
|
||||||
{
|
|
||||||
public class ChapterSearchRequest : IHasProviderIds
|
|
||||||
{
|
|
||||||
public string Language { get; set; }
|
|
||||||
|
|
||||||
public VideoContentType ContentType { get; set; }
|
|
||||||
|
|
||||||
public string MediaPath { get; set; }
|
|
||||||
public string SeriesName { get; set; }
|
|
||||||
public string Name { get; set; }
|
|
||||||
public int? IndexNumber { get; set; }
|
|
||||||
public int? IndexNumberEnd { get; set; }
|
|
||||||
public int? ParentIndexNumber { get; set; }
|
|
||||||
public int? ProductionYear { get; set; }
|
|
||||||
public long? RuntimeTicks { get; set; }
|
|
||||||
public Dictionary<string, string> ProviderIds { get; set; }
|
|
||||||
|
|
||||||
public bool SearchAllProviders { get; set; }
|
|
||||||
|
|
||||||
public ChapterSearchRequest()
|
|
||||||
{
|
|
||||||
ProviderIds = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,6 +1,4 @@
|
||||||
using MediaBrowser.Controller.Entities;
|
using System.Collections.Generic;
|
||||||
using MediaBrowser.Model.Chapters;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using MediaBrowser.Model.Configuration;
|
using MediaBrowser.Model.Configuration;
|
||||||
|
@ -13,12 +11,6 @@ namespace MediaBrowser.Controller.Chapters
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public interface IChapterManager
|
public interface IChapterManager
|
||||||
{
|
{
|
||||||
/// <summary>
|
|
||||||
/// Adds the parts.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="chapterProviders">The chapter providers.</param>
|
|
||||||
void AddParts(IEnumerable<IChapterProvider> chapterProviders);
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets the chapters.
|
/// Gets the chapters.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
@ -35,43 +27,6 @@ namespace MediaBrowser.Controller.Chapters
|
||||||
/// <returns>Task.</returns>
|
/// <returns>Task.</returns>
|
||||||
Task SaveChapters(string itemId, List<ChapterInfo> chapters, CancellationToken cancellationToken);
|
Task SaveChapters(string itemId, List<ChapterInfo> chapters, CancellationToken cancellationToken);
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Searches the specified video.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="video">The video.</param>
|
|
||||||
/// <param name="cancellationToken">The cancellation token.</param>
|
|
||||||
/// <returns>Task{IEnumerable{RemoteChapterResult}}.</returns>
|
|
||||||
Task<IEnumerable<RemoteChapterResult>> Search(Video video, CancellationToken cancellationToken);
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Searches the specified request.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="request">The request.</param>
|
|
||||||
/// <param name="cancellationToken">The cancellation token.</param>
|
|
||||||
/// <returns>Task{IEnumerable{RemoteChapterResult}}.</returns>
|
|
||||||
Task<IEnumerable<RemoteChapterResult>> Search(ChapterSearchRequest request, CancellationToken cancellationToken);
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets the chapters.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="id">The identifier.</param>
|
|
||||||
/// <param name="cancellationToken">The cancellation token.</param>
|
|
||||||
/// <returns>Task{ChapterResponse}.</returns>
|
|
||||||
Task<ChapterResponse> GetChapters(string id, CancellationToken cancellationToken);
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets the providers.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="itemId">The item identifier.</param>
|
|
||||||
/// <returns>IEnumerable{ChapterProviderInfo}.</returns>
|
|
||||||
IEnumerable<ChapterProviderInfo> GetProviders(string itemId);
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets the providers.
|
|
||||||
/// </summary>
|
|
||||||
/// <returns>IEnumerable{ChapterProviderInfo}.</returns>
|
|
||||||
IEnumerable<ChapterProviderInfo> GetProviders();
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets the configuration.
|
/// Gets the configuration.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|
|
@ -1,39 +0,0 @@
|
||||||
using MediaBrowser.Controller.Providers;
|
|
||||||
using MediaBrowser.Model.Chapters;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Threading;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
|
|
||||||
namespace MediaBrowser.Controller.Chapters
|
|
||||||
{
|
|
||||||
public interface IChapterProvider
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// Gets the name.
|
|
||||||
/// </summary>
|
|
||||||
/// <value>The name.</value>
|
|
||||||
string Name { get; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets the supported media types.
|
|
||||||
/// </summary>
|
|
||||||
/// <value>The supported media types.</value>
|
|
||||||
IEnumerable<VideoContentType> SupportedMediaTypes { get; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Searches the specified request.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="request">The request.</param>
|
|
||||||
/// <param name="cancellationToken">The cancellation token.</param>
|
|
||||||
/// <returns>Task{IEnumerable{RemoteChapterResult}}.</returns>
|
|
||||||
Task<IEnumerable<RemoteChapterResult>> Search(ChapterSearchRequest request, CancellationToken cancellationToken);
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets the chapters.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="id">The identifier.</param>
|
|
||||||
/// <param name="cancellationToken">The cancellation token.</param>
|
|
||||||
/// <returns>Task{ChapterResponse}.</returns>
|
|
||||||
Task<ChapterResponse> GetChapters(string id, CancellationToken cancellationToken);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,10 +1,20 @@
|
||||||
using System;
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Net;
|
||||||
|
using MediaBrowser.Model.Events;
|
||||||
|
|
||||||
namespace MediaBrowser.Controller.Dlna
|
namespace MediaBrowser.Controller.Dlna
|
||||||
{
|
{
|
||||||
public interface IDeviceDiscovery
|
public interface IDeviceDiscovery
|
||||||
{
|
{
|
||||||
event EventHandler<SsdpMessageEventArgs> DeviceDiscovered;
|
event EventHandler<GenericEventArgs<UpnpDeviceInfo>> DeviceDiscovered;
|
||||||
event EventHandler<SsdpMessageEventArgs> DeviceLeft;
|
event EventHandler<GenericEventArgs<UpnpDeviceInfo>> DeviceLeft;
|
||||||
|
}
|
||||||
|
|
||||||
|
public class UpnpDeviceInfo
|
||||||
|
{
|
||||||
|
public Uri Location { get; set; }
|
||||||
|
public Dictionary<string, string> Headers { get; set; }
|
||||||
|
public IPEndPoint LocalEndPoint { get; set; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,6 +4,5 @@ namespace MediaBrowser.Controller.Dlna
|
||||||
{
|
{
|
||||||
public interface ISsdpHandler
|
public interface ISsdpHandler
|
||||||
{
|
{
|
||||||
event EventHandler<SsdpMessageEventArgs> MessageReceived;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -34,11 +34,26 @@ namespace MediaBrowser.Controller.Entities
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[IgnoreDataMember]
|
||||||
|
public override bool IsPhysicalRoot
|
||||||
|
{
|
||||||
|
get { return true; }
|
||||||
|
}
|
||||||
|
|
||||||
public override bool CanDelete()
|
public override bool CanDelete()
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[IgnoreDataMember]
|
||||||
|
public override bool SupportsPlayedStatus
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The _virtual children
|
/// The _virtual children
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|
|
@ -23,8 +23,7 @@ namespace MediaBrowser.Controller.Entities.Audio
|
||||||
IHasMusicGenres,
|
IHasMusicGenres,
|
||||||
IHasLookupInfo<SongInfo>,
|
IHasLookupInfo<SongInfo>,
|
||||||
IHasMediaSources,
|
IHasMediaSources,
|
||||||
IThemeMedia,
|
IThemeMedia
|
||||||
IArchivable
|
|
||||||
{
|
{
|
||||||
public List<ChannelMediaInfo> ChannelMediaSources { get; set; }
|
public List<ChannelMediaInfo> ChannelMediaSources { get; set; }
|
||||||
|
|
||||||
|
@ -60,10 +59,19 @@ namespace MediaBrowser.Controller.Entities.Audio
|
||||||
AlbumArtists = new List<string>();
|
AlbumArtists = new List<string>();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[IgnoreDataMember]
|
||||||
|
public override bool SupportsPlayedStatus
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
[IgnoreDataMember]
|
[IgnoreDataMember]
|
||||||
public override bool SupportsAddingToPlaylist
|
public override bool SupportsAddingToPlaylist
|
||||||
{
|
{
|
||||||
get { return LocationType == LocationType.FileSystem && RunTimeTicks.HasValue; }
|
get { return true; }
|
||||||
}
|
}
|
||||||
|
|
||||||
[IgnoreDataMember]
|
[IgnoreDataMember]
|
||||||
|
@ -84,21 +92,6 @@ namespace MediaBrowser.Controller.Entities.Audio
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
[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 override bool CanDownload()
|
public override bool CanDownload()
|
||||||
{
|
{
|
||||||
var locationType = LocationType;
|
var locationType = LocationType;
|
||||||
|
@ -262,7 +255,7 @@ namespace MediaBrowser.Controller.Entities.Audio
|
||||||
Protocol = locationType == LocationType.Remote ? MediaProtocol.Http : MediaProtocol.File,
|
Protocol = locationType == LocationType.Remote ? MediaProtocol.Http : MediaProtocol.File,
|
||||||
MediaStreams = MediaSourceManager.GetMediaStreams(i.Id).ToList(),
|
MediaStreams = MediaSourceManager.GetMediaStreams(i.Id).ToList(),
|
||||||
Name = i.Name,
|
Name = i.Name,
|
||||||
Path = enablePathSubstituion ? GetMappedPath(i.Path, locationType) : i.Path,
|
Path = enablePathSubstituion ? GetMappedPath(i, i.Path, locationType) : i.Path,
|
||||||
RunTimeTicks = i.RunTimeTicks,
|
RunTimeTicks = i.RunTimeTicks,
|
||||||
Container = i.Container,
|
Container = i.Container,
|
||||||
Size = i.Size
|
Size = i.Size
|
||||||
|
|
|
@ -17,6 +17,9 @@ namespace MediaBrowser.Controller.Entities.Audio
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public class MusicAlbum : Folder, IHasAlbumArtist, IHasArtist, IHasMusicGenres, IHasLookupInfo<AlbumInfo>, IMetadataContainer
|
public class MusicAlbum : Folder, IHasAlbumArtist, IHasArtist, IHasMusicGenres, IHasLookupInfo<AlbumInfo>, IMetadataContainer
|
||||||
{
|
{
|
||||||
|
public List<string> AlbumArtists { get; set; }
|
||||||
|
public List<string> Artists { get; set; }
|
||||||
|
|
||||||
public MusicAlbum()
|
public MusicAlbum()
|
||||||
{
|
{
|
||||||
Artists = new List<string>();
|
Artists = new List<string>();
|
||||||
|
@ -48,6 +51,15 @@ namespace MediaBrowser.Controller.Entities.Audio
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[IgnoreDataMember]
|
||||||
|
public override bool SupportsPlayedStatus
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
[IgnoreDataMember]
|
[IgnoreDataMember]
|
||||||
public override bool SupportsCumulativeRunTimeTicks
|
public override bool SupportsCumulativeRunTimeTicks
|
||||||
{
|
{
|
||||||
|
@ -83,8 +95,6 @@ namespace MediaBrowser.Controller.Entities.Audio
|
||||||
get { return false; }
|
get { return false; }
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<string> AlbumArtists { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets the tracks.
|
/// Gets the tracks.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
@ -103,8 +113,6 @@ namespace MediaBrowser.Controller.Entities.Audio
|
||||||
return Tracks;
|
return Tracks;
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<string> Artists { get; set; }
|
|
||||||
|
|
||||||
public override List<string> GetUserDataKeys()
|
public override List<string> GetUserDataKeys()
|
||||||
{
|
{
|
||||||
var list = base.GetUserDataKeys();
|
var list = base.GetUserDataKeys();
|
||||||
|
|
|
@ -16,7 +16,7 @@ namespace MediaBrowser.Controller.Entities.Audio
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Class MusicArtist
|
/// Class MusicArtist
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public class MusicArtist : Folder, IMetadataContainer, IItemByName, IHasMusicGenres, IHasDualAccess, IHasProductionLocations, IHasLookupInfo<ArtistInfo>
|
public class MusicArtist : Folder, IMetadataContainer, IItemByName, IHasMusicGenres, IHasDualAccess, IHasLookupInfo<ArtistInfo>
|
||||||
{
|
{
|
||||||
[IgnoreDataMember]
|
[IgnoreDataMember]
|
||||||
public bool IsAccessedByName
|
public bool IsAccessedByName
|
||||||
|
@ -24,8 +24,6 @@ namespace MediaBrowser.Controller.Entities.Audio
|
||||||
get { return ParentId == Guid.Empty; }
|
get { return ParentId == Guid.Empty; }
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<string> ProductionLocations { get; set; }
|
|
||||||
|
|
||||||
[IgnoreDataMember]
|
[IgnoreDataMember]
|
||||||
public override bool IsFolder
|
public override bool IsFolder
|
||||||
{
|
{
|
||||||
|
@ -50,6 +48,15 @@ namespace MediaBrowser.Controller.Entities.Audio
|
||||||
get { return true; }
|
get { return true; }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[IgnoreDataMember]
|
||||||
|
public override bool SupportsPlayedStatus
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public override bool CanDelete()
|
public override bool CanDelete()
|
||||||
{
|
{
|
||||||
return !IsAccessedByName;
|
return !IsAccessedByName;
|
||||||
|
@ -111,11 +118,6 @@ namespace MediaBrowser.Controller.Entities.Audio
|
||||||
return base.ValidateChildrenInternal(progress, cancellationToken, recursive, refreshChildMetadata, refreshOptions, directoryService);
|
return base.ValidateChildrenInternal(progress, cancellationToken, recursive, refreshChildMetadata, refreshOptions, directoryService);
|
||||||
}
|
}
|
||||||
|
|
||||||
public MusicArtist()
|
|
||||||
{
|
|
||||||
ProductionLocations = new List<string>();
|
|
||||||
}
|
|
||||||
|
|
||||||
public override List<string> GetUserDataKeys()
|
public override List<string> GetUserDataKeys()
|
||||||
{
|
{
|
||||||
var list = base.GetUserDataKeys();
|
var list = base.GetUserDataKeys();
|
||||||
|
|
|
@ -37,6 +37,8 @@ namespace MediaBrowser.Controller.Entities
|
||||||
{
|
{
|
||||||
protected BaseItem()
|
protected BaseItem()
|
||||||
{
|
{
|
||||||
|
ThemeSongIds = new List<Guid>();
|
||||||
|
ThemeVideoIds = new List<Guid>();
|
||||||
Keywords = new List<string>();
|
Keywords = new List<string>();
|
||||||
Tags = new List<string>();
|
Tags = new List<string>();
|
||||||
Genres = new List<string>();
|
Genres = new List<string>();
|
||||||
|
@ -44,6 +46,8 @@ namespace MediaBrowser.Controller.Entities
|
||||||
ProviderIds = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);
|
ProviderIds = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);
|
||||||
LockedFields = new List<MetadataFields>();
|
LockedFields = new List<MetadataFields>();
|
||||||
ImageInfos = new List<ItemImageInfo>();
|
ImageInfos = new List<ItemImageInfo>();
|
||||||
|
InheritedTags = new List<string>();
|
||||||
|
ProductionLocations = new List<string>();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static readonly char[] SlugReplaceChars = { '?', '/', '&' };
|
public static readonly char[] SlugReplaceChars = { '?', '/', '&' };
|
||||||
|
@ -64,6 +68,9 @@ namespace MediaBrowser.Controller.Entities
|
||||||
public static string ThemeSongFilename = "theme";
|
public static string ThemeSongFilename = "theme";
|
||||||
public static string ThemeVideosFolderName = "backdrops";
|
public static string ThemeVideosFolderName = "backdrops";
|
||||||
|
|
||||||
|
public List<Guid> ThemeSongIds { get; set; }
|
||||||
|
public List<Guid> ThemeVideoIds { get; set; }
|
||||||
|
|
||||||
[IgnoreDataMember]
|
[IgnoreDataMember]
|
||||||
public string PreferredMetadataCountryCode { get; set; }
|
public string PreferredMetadataCountryCode { get; set; }
|
||||||
[IgnoreDataMember]
|
[IgnoreDataMember]
|
||||||
|
@ -72,6 +79,8 @@ namespace MediaBrowser.Controller.Entities
|
||||||
public long? Size { get; set; }
|
public long? Size { get; set; }
|
||||||
public string Container { get; set; }
|
public string Container { get; set; }
|
||||||
public string ShortOverview { get; set; }
|
public string ShortOverview { get; set; }
|
||||||
|
[IgnoreDataMember]
|
||||||
|
public string Tagline { get; set; }
|
||||||
|
|
||||||
public List<ItemImageInfo> ImageInfos { get; set; }
|
public List<ItemImageInfo> ImageInfos { get; set; }
|
||||||
|
|
||||||
|
@ -114,6 +123,31 @@ namespace MediaBrowser.Controller.Entities
|
||||||
[IgnoreDataMember]
|
[IgnoreDataMember]
|
||||||
public bool IsInMixedFolder { get; set; }
|
public bool IsInMixedFolder { get; set; }
|
||||||
|
|
||||||
|
[IgnoreDataMember]
|
||||||
|
protected virtual bool SupportsIsInMixedFolderDetection
|
||||||
|
{
|
||||||
|
get { return false; }
|
||||||
|
}
|
||||||
|
|
||||||
|
[IgnoreDataMember]
|
||||||
|
public virtual bool SupportsPlayedStatus
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool DetectIsInMixedFolder()
|
||||||
|
{
|
||||||
|
if (SupportsIsInMixedFolderDetection)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
return IsInMixedFolder;
|
||||||
|
}
|
||||||
|
|
||||||
[IgnoreDataMember]
|
[IgnoreDataMember]
|
||||||
public virtual bool SupportsRemoteImageDownloading
|
public virtual bool SupportsRemoteImageDownloading
|
||||||
{
|
{
|
||||||
|
@ -254,6 +288,19 @@ namespace MediaBrowser.Controller.Entities
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[IgnoreDataMember]
|
||||||
|
public string ExternalSeriesId { get; set; }
|
||||||
|
|
||||||
|
[IgnoreDataMember]
|
||||||
|
public string ExternalSeriesIdLegacy
|
||||||
|
{
|
||||||
|
get { return this.GetProviderId("ProviderExternalSeriesId"); }
|
||||||
|
set
|
||||||
|
{
|
||||||
|
this.SetProviderId("ProviderExternalSeriesId", value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets or sets the etag.
|
/// Gets or sets the etag.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
@ -408,7 +455,7 @@ namespace MediaBrowser.Controller.Entities
|
||||||
|
|
||||||
public virtual bool IsInternetMetadataEnabled()
|
public virtual bool IsInternetMetadataEnabled()
|
||||||
{
|
{
|
||||||
return ConfigurationManager.Configuration.EnableInternetProviders;
|
return LibraryManager.GetLibraryOptions(this).EnableInternetProviders;
|
||||||
}
|
}
|
||||||
|
|
||||||
public virtual bool CanDelete()
|
public virtual bool CanDelete()
|
||||||
|
@ -784,6 +831,9 @@ namespace MediaBrowser.Controller.Entities
|
||||||
[IgnoreDataMember]
|
[IgnoreDataMember]
|
||||||
public int InheritedParentalRatingValue { get; set; }
|
public int InheritedParentalRatingValue { get; set; }
|
||||||
|
|
||||||
|
[IgnoreDataMember]
|
||||||
|
public List<string> InheritedTags { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets or sets the critic rating.
|
/// Gets or sets the critic rating.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
@ -841,6 +891,7 @@ namespace MediaBrowser.Controller.Entities
|
||||||
public List<string> Tags { get; set; }
|
public List<string> Tags { get; set; }
|
||||||
|
|
||||||
public List<string> Keywords { get; set; }
|
public List<string> Keywords { get; set; }
|
||||||
|
public List<string> ProductionLocations { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets or sets the home page URL.
|
/// Gets or sets the home page URL.
|
||||||
|
@ -956,7 +1007,7 @@ namespace MediaBrowser.Controller.Entities
|
||||||
/// Loads the theme songs.
|
/// Loads the theme songs.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <returns>List{Audio.Audio}.</returns>
|
/// <returns>List{Audio.Audio}.</returns>
|
||||||
private IEnumerable<Audio.Audio> LoadThemeSongs(List<FileSystemMetadata> fileSystemChildren, IDirectoryService directoryService)
|
private static IEnumerable<Audio.Audio> LoadThemeSongs(List<FileSystemMetadata> fileSystemChildren, IDirectoryService directoryService)
|
||||||
{
|
{
|
||||||
var files = fileSystemChildren.Where(i => i.IsDirectory)
|
var files = fileSystemChildren.Where(i => i.IsDirectory)
|
||||||
.Where(i => string.Equals(i.Name, ThemeSongsFolderName, StringComparison.OrdinalIgnoreCase))
|
.Where(i => string.Equals(i.Name, ThemeSongsFolderName, StringComparison.OrdinalIgnoreCase))
|
||||||
|
@ -992,7 +1043,7 @@ namespace MediaBrowser.Controller.Entities
|
||||||
/// Loads the video backdrops.
|
/// Loads the video backdrops.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <returns>List{Video}.</returns>
|
/// <returns>List{Video}.</returns>
|
||||||
private IEnumerable<Video> LoadThemeVideos(IEnumerable<FileSystemMetadata> fileSystemChildren, IDirectoryService directoryService)
|
private static IEnumerable<Video> LoadThemeVideos(IEnumerable<FileSystemMetadata> fileSystemChildren, IDirectoryService directoryService)
|
||||||
{
|
{
|
||||||
var files = fileSystemChildren.Where(i => i.IsDirectory)
|
var files = fileSystemChildren.Where(i => i.IsDirectory)
|
||||||
.Where(i => string.Equals(i.Name, ThemeVideosFolderName, StringComparison.OrdinalIgnoreCase))
|
.Where(i => string.Equals(i.Name, ThemeVideosFolderName, StringComparison.OrdinalIgnoreCase))
|
||||||
|
@ -1078,6 +1129,12 @@ namespace MediaBrowser.Controller.Entities
|
||||||
get { return true; }
|
get { return true; }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[IgnoreDataMember]
|
||||||
|
public virtual bool SupportsThemeMedia
|
||||||
|
{
|
||||||
|
get { return false; }
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Refreshes owned items such as trailers, theme videos, special features, etc.
|
/// Refreshes owned items such as trailers, theme videos, special features, etc.
|
||||||
/// Returns true or false indicating if changes were found.
|
/// Returns true or false indicating if changes were found.
|
||||||
|
@ -1096,14 +1153,13 @@ namespace MediaBrowser.Controller.Entities
|
||||||
|
|
||||||
if (LocationType == LocationType.FileSystem && GetParent() != null)
|
if (LocationType == LocationType.FileSystem && GetParent() != null)
|
||||||
{
|
{
|
||||||
var hasThemeMedia = this as IHasThemeMedia;
|
if (SupportsThemeMedia)
|
||||||
if (hasThemeMedia != null)
|
|
||||||
{
|
{
|
||||||
if (!IsInMixedFolder)
|
if (!DetectIsInMixedFolder())
|
||||||
{
|
{
|
||||||
themeSongsChanged = await RefreshThemeSongs(hasThemeMedia, options, fileSystemChildren, cancellationToken).ConfigureAwait(false);
|
themeSongsChanged = await RefreshThemeSongs(this, options, fileSystemChildren, cancellationToken).ConfigureAwait(false);
|
||||||
|
|
||||||
themeVideosChanged = await RefreshThemeVideos(hasThemeMedia, options, fileSystemChildren, cancellationToken).ConfigureAwait(false);
|
themeVideosChanged = await RefreshThemeVideos(this, options, fileSystemChildren, cancellationToken).ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1141,7 +1197,7 @@ namespace MediaBrowser.Controller.Entities
|
||||||
return itemsChanged;
|
return itemsChanged;
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task<bool> RefreshThemeVideos(IHasThemeMedia item, MetadataRefreshOptions options, IEnumerable<FileSystemMetadata> fileSystemChildren, CancellationToken cancellationToken)
|
private static async Task<bool> RefreshThemeVideos(BaseItem item, MetadataRefreshOptions options, IEnumerable<FileSystemMetadata> fileSystemChildren, CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
var newThemeVideos = LoadThemeVideos(fileSystemChildren, options.DirectoryService).ToList();
|
var newThemeVideos = LoadThemeVideos(fileSystemChildren, options.DirectoryService).ToList();
|
||||||
|
|
||||||
|
@ -1172,7 +1228,7 @@ namespace MediaBrowser.Controller.Entities
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Refreshes the theme songs.
|
/// Refreshes the theme songs.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private async Task<bool> RefreshThemeSongs(IHasThemeMedia item, MetadataRefreshOptions options, List<FileSystemMetadata> fileSystemChildren, CancellationToken cancellationToken)
|
private static async Task<bool> RefreshThemeSongs(BaseItem item, MetadataRefreshOptions options, List<FileSystemMetadata> fileSystemChildren, CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
var newThemeSongs = LoadThemeSongs(fileSystemChildren, options.DirectoryService).ToList();
|
var newThemeSongs = LoadThemeSongs(fileSystemChildren, options.DirectoryService).ToList();
|
||||||
var newThemeSongIds = newThemeSongs.Select(i => i.Id).ToList();
|
var newThemeSongIds = newThemeSongs.Select(i => i.Id).ToList();
|
||||||
|
@ -1249,7 +1305,15 @@ namespace MediaBrowser.Controller.Entities
|
||||||
{
|
{
|
||||||
var current = this;
|
var current = this;
|
||||||
|
|
||||||
return current.IsInMixedFolder == newItem.IsInMixedFolder;
|
if (!SupportsIsInMixedFolderDetection)
|
||||||
|
{
|
||||||
|
if (current.IsInMixedFolder != newItem.IsInMixedFolder)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void AfterMetadataRefresh()
|
public void AfterMetadataRefresh()
|
||||||
|
@ -1324,7 +1388,9 @@ namespace MediaBrowser.Controller.Entities
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
return ConfigurationManager.Configuration.SaveLocalMeta;
|
var libraryOptions = LibraryManager.GetLibraryOptions(this);
|
||||||
|
|
||||||
|
return libraryOptions.SaveLocalMetadata;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -2107,14 +2173,11 @@ namespace MediaBrowser.Controller.Entities
|
||||||
return hasChanges;
|
return hasChanges;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected static string GetMappedPath(string path, LocationType locationType)
|
protected static string GetMappedPath(BaseItem item, string path, LocationType locationType)
|
||||||
{
|
{
|
||||||
if (locationType == LocationType.FileSystem || locationType == LocationType.Offline)
|
if (locationType == LocationType.FileSystem || locationType == LocationType.Offline)
|
||||||
{
|
{
|
||||||
foreach (var map in ConfigurationManager.Configuration.PathSubstitutions)
|
return LibraryManager.GetPathAfterNetworkSubstitution(path, item);
|
||||||
{
|
|
||||||
path = LibraryManager.SubstitutePath(path, map.From, map.To);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return path;
|
return path;
|
||||||
|
|
|
@ -38,6 +38,15 @@ namespace MediaBrowser.Controller.Entities
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[IgnoreDataMember]
|
||||||
|
public override bool SupportsPlayedStatus
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public override bool CanDelete()
|
public override bool CanDelete()
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
|
@ -48,24 +57,14 @@ namespace MediaBrowser.Controller.Entities
|
||||||
private static readonly Dictionary<string, LibraryOptions> LibraryOptions = new Dictionary<string, LibraryOptions>();
|
private static readonly Dictionary<string, LibraryOptions> LibraryOptions = new Dictionary<string, LibraryOptions>();
|
||||||
public LibraryOptions GetLibraryOptions()
|
public LibraryOptions GetLibraryOptions()
|
||||||
{
|
{
|
||||||
lock (LibraryOptions)
|
return GetLibraryOptions(Path);
|
||||||
{
|
|
||||||
LibraryOptions options;
|
|
||||||
if (!LibraryOptions.TryGetValue(Path, out options))
|
|
||||||
{
|
|
||||||
options = LoadLibraryOptions();
|
|
||||||
LibraryOptions[Path] = options;
|
|
||||||
}
|
|
||||||
|
|
||||||
return options;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private LibraryOptions LoadLibraryOptions()
|
private static LibraryOptions LoadLibraryOptions(string path)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
var result = XmlSerializer.DeserializeFromFile(typeof(LibraryOptions), GetLibraryOptionsPath(Path)) as LibraryOptions;
|
var result = XmlSerializer.DeserializeFromFile(typeof(LibraryOptions), GetLibraryOptionsPath(path)) as LibraryOptions;
|
||||||
|
|
||||||
if (result == null)
|
if (result == null)
|
||||||
{
|
{
|
||||||
|
@ -100,13 +99,28 @@ namespace MediaBrowser.Controller.Entities
|
||||||
SaveLibraryOptions(Path, options);
|
SaveLibraryOptions(Path, options);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static LibraryOptions GetLibraryOptions(string path)
|
||||||
|
{
|
||||||
|
lock (LibraryOptions)
|
||||||
|
{
|
||||||
|
LibraryOptions options;
|
||||||
|
if (!LibraryOptions.TryGetValue(path, out options))
|
||||||
|
{
|
||||||
|
options = LoadLibraryOptions(path);
|
||||||
|
LibraryOptions[path] = options;
|
||||||
|
}
|
||||||
|
|
||||||
|
return options;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public static void SaveLibraryOptions(string path, LibraryOptions options)
|
public static void SaveLibraryOptions(string path, LibraryOptions options)
|
||||||
{
|
{
|
||||||
lock (LibraryOptions)
|
lock (LibraryOptions)
|
||||||
{
|
{
|
||||||
LibraryOptions[path] = options;
|
LibraryOptions[path] = options;
|
||||||
|
|
||||||
options.SchemaVersion = 2;
|
options.SchemaVersion = 3;
|
||||||
XmlSerializer.SerializeToFile(options, GetLibraryOptionsPath(path));
|
XmlSerializer.SerializeToFile(options, GetLibraryOptionsPath(path));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,13 +22,18 @@ namespace MediaBrowser.Controller.Entities
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Class Folder
|
/// Class Folder
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public class Folder : BaseItem, IHasThemeMedia
|
public class Folder : BaseItem
|
||||||
{
|
{
|
||||||
public static IUserManager UserManager { get; set; }
|
public static IUserManager UserManager { get; set; }
|
||||||
public static IUserViewManager UserViewManager { get; set; }
|
public static IUserViewManager UserViewManager { get; set; }
|
||||||
|
|
||||||
public List<Guid> ThemeSongIds { get; set; }
|
/// <summary>
|
||||||
public List<Guid> ThemeVideoIds { get; set; }
|
/// Gets or sets a value indicating whether this instance is root.
|
||||||
|
/// </summary>
|
||||||
|
/// <value><c>true</c> if this instance is root; otherwise, <c>false</c>.</value>
|
||||||
|
public bool IsRoot { get; set; }
|
||||||
|
|
||||||
|
public virtual List<LinkedChild> LinkedChildren { get; set; }
|
||||||
|
|
||||||
[IgnoreDataMember]
|
[IgnoreDataMember]
|
||||||
public DateTime? DateLastMediaAdded { get; set; }
|
public DateTime? DateLastMediaAdded { get; set; }
|
||||||
|
@ -36,9 +41,12 @@ namespace MediaBrowser.Controller.Entities
|
||||||
public Folder()
|
public Folder()
|
||||||
{
|
{
|
||||||
LinkedChildren = new List<LinkedChild>();
|
LinkedChildren = new List<LinkedChild>();
|
||||||
|
}
|
||||||
|
|
||||||
ThemeSongIds = new List<Guid>();
|
[IgnoreDataMember]
|
||||||
ThemeVideoIds = new List<Guid>();
|
public override bool SupportsThemeMedia
|
||||||
|
{
|
||||||
|
get { return true; }
|
||||||
}
|
}
|
||||||
|
|
||||||
[IgnoreDataMember]
|
[IgnoreDataMember]
|
||||||
|
@ -47,6 +55,21 @@ namespace MediaBrowser.Controller.Entities
|
||||||
get { return false; }
|
get { return false; }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[IgnoreDataMember]
|
||||||
|
public virtual bool IsPhysicalRoot
|
||||||
|
{
|
||||||
|
get { return false; }
|
||||||
|
}
|
||||||
|
|
||||||
|
[IgnoreDataMember]
|
||||||
|
public override bool SupportsPlayedStatus
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets a value indicating whether this instance is folder.
|
/// Gets a value indicating whether this instance is folder.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
@ -117,19 +140,6 @@ namespace MediaBrowser.Controller.Entities
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets or sets a value indicating whether this instance is physical root.
|
|
||||||
/// </summary>
|
|
||||||
/// <value><c>true</c> if this instance is physical root; otherwise, <c>false</c>.</value>
|
|
||||||
public bool IsPhysicalRoot { get; set; }
|
|
||||||
/// <summary>
|
|
||||||
/// Gets or sets a value indicating whether this instance is root.
|
|
||||||
/// </summary>
|
|
||||||
/// <value><c>true</c> if this instance is root; otherwise, <c>false</c>.</value>
|
|
||||||
public bool IsRoot { get; set; }
|
|
||||||
|
|
||||||
public virtual List<LinkedChild> LinkedChildren { get; set; }
|
|
||||||
|
|
||||||
[IgnoreDataMember]
|
[IgnoreDataMember]
|
||||||
protected virtual bool SupportsShortcutChildren
|
protected virtual bool SupportsShortcutChildren
|
||||||
{
|
{
|
||||||
|
@ -178,8 +188,6 @@ namespace MediaBrowser.Controller.Entities
|
||||||
item.SetParent(null);
|
item.SetParent(null);
|
||||||
}
|
}
|
||||||
|
|
||||||
#region Indexing
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Returns the valid set of index by options for this folder type.
|
/// Returns the valid set of index by options for this folder type.
|
||||||
/// Override or extend to modify.
|
/// Override or extend to modify.
|
||||||
|
@ -207,8 +215,6 @@ namespace MediaBrowser.Controller.Entities
|
||||||
get { return GetIndexByOptions(); }
|
get { return GetIndexByOptions(); }
|
||||||
}
|
}
|
||||||
|
|
||||||
#endregion
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets the actual children.
|
/// Gets the actual children.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
@ -801,18 +807,6 @@ namespace MediaBrowser.Controller.Entities
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (query.HasThemeSong.HasValue)
|
|
||||||
{
|
|
||||||
Logger.Debug("Query requires post-filtering due to HasThemeSong");
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (query.HasThemeVideo.HasValue)
|
|
||||||
{
|
|
||||||
Logger.Debug("Query requires post-filtering due to HasThemeVideo");
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Filter by VideoType
|
// Filter by VideoType
|
||||||
if (query.VideoTypes.Length > 0)
|
if (query.VideoTypes.Length > 0)
|
||||||
{
|
{
|
||||||
|
@ -1149,29 +1143,19 @@ namespace MediaBrowser.Controller.Entities
|
||||||
return LinkedChildren
|
return LinkedChildren
|
||||||
.Select(i =>
|
.Select(i =>
|
||||||
{
|
{
|
||||||
var requiresPostFilter = true;
|
|
||||||
|
|
||||||
if (!string.IsNullOrWhiteSpace(i.Path))
|
|
||||||
{
|
|
||||||
requiresPostFilter = false;
|
|
||||||
|
|
||||||
if (!locations.Any(l => FileSystem.ContainsSubPath(l, i.Path)))
|
|
||||||
{
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
var child = GetLinkedChild(i);
|
var child = GetLinkedChild(i);
|
||||||
|
|
||||||
if (requiresPostFilter && child != null)
|
if (child != null)
|
||||||
{
|
{
|
||||||
if (string.IsNullOrWhiteSpace(child.Path))
|
var childLocationType = child.LocationType;
|
||||||
|
if (childLocationType == LocationType.Remote || childLocationType == LocationType.Virtual)
|
||||||
{
|
{
|
||||||
Logger.Debug("Found LinkedChild with null path: {0}", child.Name);
|
if (!child.IsVisibleStandalone(user))
|
||||||
return child;
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
else if (childLocationType == LocationType.FileSystem && !locations.Any(l => FileSystem.ContainsSubPath(l, child.Path)))
|
||||||
if (!locations.Any(l => FileSystem.ContainsSubPath(l, child.Path)))
|
|
||||||
{
|
{
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,19 +8,14 @@ using System.Runtime.Serialization;
|
||||||
|
|
||||||
namespace MediaBrowser.Controller.Entities
|
namespace MediaBrowser.Controller.Entities
|
||||||
{
|
{
|
||||||
public class Game : BaseItem, IHasTrailers, IHasThemeMedia, IHasScreenshots, ISupportsPlaceHolders, IHasLookupInfo<GameInfo>
|
public class Game : BaseItem, IHasTrailers, IHasScreenshots, ISupportsPlaceHolders, IHasLookupInfo<GameInfo>
|
||||||
{
|
{
|
||||||
public List<Guid> ThemeSongIds { get; set; }
|
|
||||||
public List<Guid> ThemeVideoIds { get; set; }
|
|
||||||
|
|
||||||
public Game()
|
public Game()
|
||||||
{
|
{
|
||||||
MultiPartGameFiles = new List<string>();
|
MultiPartGameFiles = new List<string>();
|
||||||
RemoteTrailers = new List<MediaUrl>();
|
RemoteTrailers = new List<MediaUrl>();
|
||||||
LocalTrailerIds = new List<Guid>();
|
LocalTrailerIds = new List<Guid>();
|
||||||
RemoteTrailerIds = new List<Guid>();
|
RemoteTrailerIds = new List<Guid>();
|
||||||
ThemeSongIds = new List<Guid>();
|
|
||||||
ThemeVideoIds = new List<Guid>();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<Guid> LocalTrailerIds { get; set; }
|
public List<Guid> LocalTrailerIds { get; set; }
|
||||||
|
@ -39,6 +34,12 @@ namespace MediaBrowser.Controller.Entities
|
||||||
get { return true; }
|
get { return true; }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[IgnoreDataMember]
|
||||||
|
public override bool SupportsThemeMedia
|
||||||
|
{
|
||||||
|
get { return true; }
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets or sets the remote trailers.
|
/// Gets or sets the remote trailers.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
@ -98,7 +99,7 @@ namespace MediaBrowser.Controller.Entities
|
||||||
|
|
||||||
public override IEnumerable<string> GetDeletePaths()
|
public override IEnumerable<string> GetDeletePaths()
|
||||||
{
|
{
|
||||||
if (!IsInMixedFolder)
|
if (!DetectIsInMixedFolder())
|
||||||
{
|
{
|
||||||
return new[] { System.IO.Path.GetDirectoryName(Path) };
|
return new[] { System.IO.Path.GetDirectoryName(Path) };
|
||||||
}
|
}
|
||||||
|
|
|
@ -26,6 +26,15 @@ namespace MediaBrowser.Controller.Entities
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[IgnoreDataMember]
|
||||||
|
public override bool SupportsPlayedStatus
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets or sets the game system.
|
/// Gets or sets the game system.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|
|
@ -1,8 +0,0 @@
|
||||||
|
|
||||||
namespace MediaBrowser.Controller.Entities
|
|
||||||
{
|
|
||||||
public interface IArchivable
|
|
||||||
{
|
|
||||||
bool IsArchive { get; }
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -150,11 +150,7 @@ namespace MediaBrowser.Controller.Entities
|
||||||
/// <value><c>true</c> if [supports local metadata]; otherwise, <c>false</c>.</value>
|
/// <value><c>true</c> if [supports local metadata]; otherwise, <c>false</c>.</value>
|
||||||
bool SupportsLocalMetadata { get; }
|
bool SupportsLocalMetadata { get; }
|
||||||
|
|
||||||
/// <summary>
|
bool DetectIsInMixedFolder();
|
||||||
/// Gets a value indicating whether this instance is in mixed folder.
|
|
||||||
/// </summary>
|
|
||||||
/// <value><c>true</c> if this instance is in mixed folder; otherwise, <c>false</c>.</value>
|
|
||||||
bool IsInMixedFolder { get; }
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets a value indicating whether this instance is locked.
|
/// Gets a value indicating whether this instance is locked.
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
using System;
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
namespace MediaBrowser.Controller.Entities
|
namespace MediaBrowser.Controller.Entities
|
||||||
{
|
{
|
||||||
|
@ -62,5 +63,7 @@ namespace MediaBrowser.Controller.Entities
|
||||||
|
|
||||||
int? GetInheritedParentalRatingValue();
|
int? GetInheritedParentalRatingValue();
|
||||||
int InheritedParentalRatingValue { get; set; }
|
int InheritedParentalRatingValue { get; set; }
|
||||||
|
List<string> GetInheritedTags();
|
||||||
|
List<string> InheritedTags { get; set; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,34 +0,0 @@
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
|
|
||||||
namespace MediaBrowser.Controller.Entities
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// Interface IHasProductionLocations
|
|
||||||
/// </summary>
|
|
||||||
public interface IHasProductionLocations
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// Gets or sets the production locations.
|
|
||||||
/// </summary>
|
|
||||||
/// <value>The production locations.</value>
|
|
||||||
List<string> ProductionLocations { get; set; }
|
|
||||||
}
|
|
||||||
|
|
||||||
public static class ProductionLocationExtensions
|
|
||||||
{
|
|
||||||
public static void AddProductionLocation(this IHasProductionLocations item, string name)
|
|
||||||
{
|
|
||||||
if (string.IsNullOrWhiteSpace(name))
|
|
||||||
{
|
|
||||||
throw new ArgumentNullException("name");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!item.ProductionLocations.Contains(name, StringComparer.OrdinalIgnoreCase))
|
|
||||||
{
|
|
||||||
item.ProductionLocations.Add(name);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,39 +0,0 @@
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
|
|
||||||
namespace MediaBrowser.Controller.Entities
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// Interface IHasTaglines
|
|
||||||
/// </summary>
|
|
||||||
public interface IHasTaglines
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// Gets or sets the taglines.
|
|
||||||
/// </summary>
|
|
||||||
/// <value>The taglines.</value>
|
|
||||||
List<string> Taglines { get; set; }
|
|
||||||
}
|
|
||||||
|
|
||||||
public static class TaglineExtensions
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// Adds the tagline.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="tagline">The tagline.</param>
|
|
||||||
/// <exception cref="System.ArgumentNullException">tagline</exception>
|
|
||||||
public static void AddTagline(this IHasTaglines item, string tagline)
|
|
||||||
{
|
|
||||||
if (string.IsNullOrWhiteSpace(tagline))
|
|
||||||
{
|
|
||||||
throw new ArgumentNullException("tagline");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!item.Taglines.Contains(tagline, StringComparer.OrdinalIgnoreCase))
|
|
||||||
{
|
|
||||||
item.Taglines.Add(tagline);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,23 +0,0 @@
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
|
|
||||||
namespace MediaBrowser.Controller.Entities
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// Interface IHasThemeMedia
|
|
||||||
/// </summary>
|
|
||||||
public interface IHasThemeMedia
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// Gets or sets the theme song ids.
|
|
||||||
/// </summary>
|
|
||||||
/// <value>The theme song ids.</value>
|
|
||||||
List<Guid> ThemeSongIds { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets or sets the theme video ids.
|
|
||||||
/// </summary>
|
|
||||||
/// <value>The theme video ids.</value>
|
|
||||||
List<Guid> ThemeVideoIds { get; set; }
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -20,5 +20,7 @@ namespace MediaBrowser.Controller.Entities
|
||||||
Task FillUserDataDtoValues(UserItemDataDto dto, UserItemData userData, BaseItemDto itemDto, User user);
|
Task FillUserDataDtoValues(UserItemDataDto dto, UserItemData userData, BaseItemDto itemDto, User user);
|
||||||
|
|
||||||
bool EnableRememberingTrackSelections { get; }
|
bool EnableRememberingTrackSelections { get; }
|
||||||
|
|
||||||
|
bool SupportsPlayedStatus { get; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,6 +2,9 @@
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using MediaBrowser.Model.Configuration;
|
using MediaBrowser.Model.Configuration;
|
||||||
|
using System.Linq;
|
||||||
|
using MediaBrowser.Controller.Dto;
|
||||||
|
using MediaBrowser.Model.Querying;
|
||||||
|
|
||||||
namespace MediaBrowser.Controller.Entities
|
namespace MediaBrowser.Controller.Entities
|
||||||
{
|
{
|
||||||
|
@ -101,6 +104,8 @@ namespace MediaBrowser.Controller.Entities
|
||||||
public bool? IsMovie { get; set; }
|
public bool? IsMovie { get; set; }
|
||||||
public bool? IsSports { get; set; }
|
public bool? IsSports { get; set; }
|
||||||
public bool? IsKids { get; set; }
|
public bool? IsKids { get; set; }
|
||||||
|
public bool? IsNews { get; set; }
|
||||||
|
public bool? IsSeries { get; set; }
|
||||||
|
|
||||||
public int? MinPlayers { get; set; }
|
public int? MinPlayers { get; set; }
|
||||||
public int? MaxPlayers { get; set; }
|
public int? MaxPlayers { get; set; }
|
||||||
|
@ -137,6 +142,7 @@ namespace MediaBrowser.Controller.Entities
|
||||||
public DayOfWeek[] AirDays { get; set; }
|
public DayOfWeek[] AirDays { get; set; }
|
||||||
public SeriesStatus[] SeriesStatuses { get; set; }
|
public SeriesStatus[] SeriesStatuses { get; set; }
|
||||||
public string AlbumArtistStartsWithOrGreater { get; set; }
|
public string AlbumArtistStartsWithOrGreater { get; set; }
|
||||||
|
public string ExternalSeriesId { get; set; }
|
||||||
|
|
||||||
public string[] AlbumNames { get; set; }
|
public string[] AlbumNames { get; set; }
|
||||||
public string[] ArtistNames { get; set; }
|
public string[] ArtistNames { get; set; }
|
||||||
|
@ -149,11 +155,53 @@ namespace MediaBrowser.Controller.Entities
|
||||||
public Dictionary<string, string> ExcludeProviderIds { get; set; }
|
public Dictionary<string, string> ExcludeProviderIds { get; set; }
|
||||||
public bool EnableGroupByMetadataKey { get; set; }
|
public bool EnableGroupByMetadataKey { get; set; }
|
||||||
|
|
||||||
|
public List<Tuple<string, SortOrder>> OrderBy { get; set; }
|
||||||
|
|
||||||
|
public DateTime? MinDateCreated { get; set; }
|
||||||
|
public DateTime? MinDateLastSaved { get; set; }
|
||||||
|
|
||||||
|
public DtoOptions DtoOptions { get; set; }
|
||||||
|
|
||||||
|
public bool HasField(ItemFields name)
|
||||||
|
{
|
||||||
|
var fields = DtoOptions.Fields;
|
||||||
|
|
||||||
|
switch (name)
|
||||||
|
{
|
||||||
|
case ItemFields.ThemeSongIds:
|
||||||
|
case ItemFields.ThemeVideoIds:
|
||||||
|
case ItemFields.ProductionLocations:
|
||||||
|
case ItemFields.Keywords:
|
||||||
|
case ItemFields.Taglines:
|
||||||
|
case ItemFields.ShortOverview:
|
||||||
|
case ItemFields.CustomRating:
|
||||||
|
case ItemFields.DateCreated:
|
||||||
|
case ItemFields.SortName:
|
||||||
|
case ItemFields.Overview:
|
||||||
|
case ItemFields.OfficialRatingDescription:
|
||||||
|
case ItemFields.HomePageUrl:
|
||||||
|
case ItemFields.VoteCount:
|
||||||
|
case ItemFields.DisplayMediaType:
|
||||||
|
case ItemFields.ServiceName:
|
||||||
|
case ItemFields.Genres:
|
||||||
|
case ItemFields.Studios:
|
||||||
|
case ItemFields.Settings:
|
||||||
|
case ItemFields.OriginalTitle:
|
||||||
|
case ItemFields.Tags:
|
||||||
|
case ItemFields.DateLastMediaAdded:
|
||||||
|
case ItemFields.CriticRatingSummary:
|
||||||
|
return fields.Count == 0 || fields.Contains(name);
|
||||||
|
default:
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public InternalItemsQuery()
|
public InternalItemsQuery()
|
||||||
{
|
{
|
||||||
GroupByPresentationUniqueKey = true;
|
GroupByPresentationUniqueKey = true;
|
||||||
EnableTotalRecordCount = true;
|
EnableTotalRecordCount = true;
|
||||||
|
|
||||||
|
DtoOptions = new DtoOptions();
|
||||||
AlbumNames = new string[] { };
|
AlbumNames = new string[] { };
|
||||||
ArtistNames = new string[] { };
|
ArtistNames = new string[] { };
|
||||||
ExcludeArtistIds = new string[] { };
|
ExcludeArtistIds = new string[] { };
|
||||||
|
@ -191,6 +239,7 @@ namespace MediaBrowser.Controller.Entities
|
||||||
TrailerTypes = new TrailerType[] { };
|
TrailerTypes = new TrailerType[] { };
|
||||||
AirDays = new DayOfWeek[] { };
|
AirDays = new DayOfWeek[] { };
|
||||||
SeriesStatuses = new SeriesStatus[] { };
|
SeriesStatuses = new SeriesStatus[] { };
|
||||||
|
OrderBy = new List<Tuple<string, SortOrder>>();
|
||||||
}
|
}
|
||||||
|
|
||||||
public InternalItemsQuery(User user)
|
public InternalItemsQuery(User user)
|
||||||
|
|
|
@ -15,24 +15,17 @@ namespace MediaBrowser.Controller.Entities.Movies
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Class Movie
|
/// Class Movie
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public class Movie : Video, IHasCriticRating, IHasSpecialFeatures, IHasProductionLocations, IHasBudget, IHasTrailers, IHasThemeMedia, IHasTaglines, IHasAwards, IHasMetascore, IHasLookupInfo<MovieInfo>, ISupportsBoxSetGrouping, IHasOriginalTitle
|
public class Movie : Video, IHasCriticRating, IHasSpecialFeatures, IHasBudget, IHasTrailers, IHasAwards, IHasMetascore, IHasLookupInfo<MovieInfo>, ISupportsBoxSetGrouping, IHasOriginalTitle
|
||||||
{
|
{
|
||||||
public List<Guid> SpecialFeatureIds { get; set; }
|
public List<Guid> SpecialFeatureIds { get; set; }
|
||||||
|
|
||||||
public List<Guid> ThemeSongIds { get; set; }
|
|
||||||
public List<Guid> ThemeVideoIds { get; set; }
|
|
||||||
public List<string> ProductionLocations { get; set; }
|
|
||||||
|
|
||||||
public Movie()
|
public Movie()
|
||||||
{
|
{
|
||||||
SpecialFeatureIds = new List<Guid>();
|
SpecialFeatureIds = new List<Guid>();
|
||||||
RemoteTrailers = new List<MediaUrl>();
|
RemoteTrailers = new List<MediaUrl>();
|
||||||
LocalTrailerIds = new List<Guid>();
|
LocalTrailerIds = new List<Guid>();
|
||||||
RemoteTrailerIds = new List<Guid>();
|
RemoteTrailerIds = new List<Guid>();
|
||||||
ThemeSongIds = new List<Guid>();
|
|
||||||
ThemeVideoIds = new List<Guid>();
|
|
||||||
Taglines = new List<string>();
|
Taglines = new List<string>();
|
||||||
ProductionLocations = new List<string>();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public string AwardSummary { get; set; }
|
public string AwardSummary { get; set; }
|
||||||
|
@ -75,13 +68,22 @@ namespace MediaBrowser.Controller.Entities.Movies
|
||||||
set { TmdbCollectionName = value; }
|
set { TmdbCollectionName = value; }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[IgnoreDataMember]
|
||||||
|
protected override bool SupportsIsInMixedFolderDetection
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
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)
|
||||||
{
|
{
|
||||||
var hasChanges = await base.RefreshedOwnedItems(options, fileSystemChildren, cancellationToken).ConfigureAwait(false);
|
var hasChanges = await base.RefreshedOwnedItems(options, fileSystemChildren, cancellationToken).ConfigureAwait(false);
|
||||||
|
|
||||||
// Must have a parent to have special features
|
// Must have a parent to have special features
|
||||||
// In other words, it must be part of the Parent/Child tree
|
// In other words, it must be part of the Parent/Child tree
|
||||||
if (LocationType == LocationType.FileSystem && GetParent() != null && !IsInMixedFolder)
|
if (LocationType == LocationType.FileSystem && GetParent() != null && !DetectIsInMixedFolder())
|
||||||
{
|
{
|
||||||
var specialFeaturesChanged = await RefreshSpecialFeatures(options, fileSystemChildren, cancellationToken).ConfigureAwait(false);
|
var specialFeaturesChanged = await RefreshSpecialFeatures(options, fileSystemChildren, cancellationToken).ConfigureAwait(false);
|
||||||
|
|
||||||
|
@ -119,7 +121,7 @@ namespace MediaBrowser.Controller.Entities.Movies
|
||||||
{
|
{
|
||||||
var info = GetItemLookupInfo<MovieInfo>();
|
var info = GetItemLookupInfo<MovieInfo>();
|
||||||
|
|
||||||
if (!IsInMixedFolder)
|
if (!DetectIsInMixedFolder())
|
||||||
{
|
{
|
||||||
info.Name = System.IO.Path.GetFileName(ContainingFolderPath);
|
info.Name = System.IO.Path.GetFileName(ContainingFolderPath);
|
||||||
}
|
}
|
||||||
|
@ -145,7 +147,7 @@ namespace MediaBrowser.Controller.Entities.Movies
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// Try to get the year from the folder name
|
// Try to get the year from the folder name
|
||||||
if (!IsInMixedFolder)
|
if (!DetectIsInMixedFolder())
|
||||||
{
|
{
|
||||||
info = LibraryManager.ParseName(System.IO.Path.GetFileName(ContainingFolderPath));
|
info = LibraryManager.ParseName(System.IO.Path.GetFileName(ContainingFolderPath));
|
||||||
|
|
||||||
|
|
|
@ -6,7 +6,7 @@ using System.Runtime.Serialization;
|
||||||
|
|
||||||
namespace MediaBrowser.Controller.Entities
|
namespace MediaBrowser.Controller.Entities
|
||||||
{
|
{
|
||||||
public class MusicVideo : Video, IHasArtist, IHasMusicGenres, IHasProductionLocations, IHasBudget, IHasLookupInfo<MusicVideoInfo>
|
public class MusicVideo : Video, IHasArtist, IHasMusicGenres, IHasBudget, IHasLookupInfo<MusicVideoInfo>
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets or sets the budget.
|
/// Gets or sets the budget.
|
||||||
|
@ -19,12 +19,10 @@ namespace MediaBrowser.Controller.Entities
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <value>The revenue.</value>
|
/// <value>The revenue.</value>
|
||||||
public double? Revenue { get; set; }
|
public double? Revenue { get; set; }
|
||||||
public List<string> ProductionLocations { get; set; }
|
|
||||||
public List<string> Artists { get; set; }
|
public List<string> Artists { get; set; }
|
||||||
|
|
||||||
public MusicVideo()
|
public MusicVideo()
|
||||||
{
|
{
|
||||||
ProductionLocations = new List<string>();
|
|
||||||
Artists = new List<string>();
|
Artists = new List<string>();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -37,6 +35,15 @@ namespace MediaBrowser.Controller.Entities
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[IgnoreDataMember]
|
||||||
|
protected override bool SupportsIsInMixedFolderDetection
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public override UnratedItem GetBlockUnratedType()
|
public override UnratedItem GetBlockUnratedType()
|
||||||
{
|
{
|
||||||
return UnratedItem.Music;
|
return UnratedItem.Music;
|
||||||
|
@ -65,7 +72,7 @@ namespace MediaBrowser.Controller.Entities
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// Try to get the year from the folder name
|
// Try to get the year from the folder name
|
||||||
if (!IsInMixedFolder)
|
if (!DetectIsInMixedFolder())
|
||||||
{
|
{
|
||||||
info = LibraryManager.ParseName(System.IO.Path.GetFileName(ContainingFolderPath));
|
info = LibraryManager.ParseName(System.IO.Path.GetFileName(ContainingFolderPath));
|
||||||
|
|
||||||
|
|
|
@ -1,19 +1,11 @@
|
||||||
using MediaBrowser.Model.Drawing;
|
using MediaBrowser.Model.Drawing;
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Runtime.Serialization;
|
using System.Runtime.Serialization;
|
||||||
|
|
||||||
namespace MediaBrowser.Controller.Entities
|
namespace MediaBrowser.Controller.Entities
|
||||||
{
|
{
|
||||||
public class Photo : BaseItem, IHasTaglines
|
public class Photo : BaseItem
|
||||||
{
|
{
|
||||||
public List<string> Taglines { get; set; }
|
|
||||||
|
|
||||||
public Photo()
|
|
||||||
{
|
|
||||||
Taglines = new List<string>();
|
|
||||||
}
|
|
||||||
|
|
||||||
[IgnoreDataMember]
|
[IgnoreDataMember]
|
||||||
public override bool SupportsLocalMetadata
|
public override bool SupportsLocalMetadata
|
||||||
{
|
{
|
||||||
|
@ -37,13 +29,13 @@ namespace MediaBrowser.Controller.Entities
|
||||||
{
|
{
|
||||||
get
|
get
|
||||||
{
|
{
|
||||||
return Album;
|
return AlbumEntity;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
[IgnoreDataMember]
|
[IgnoreDataMember]
|
||||||
public PhotoAlbum Album
|
public PhotoAlbum AlbumEntity
|
||||||
{
|
{
|
||||||
get
|
get
|
||||||
{
|
{
|
||||||
|
|
|
@ -16,6 +16,15 @@ namespace MediaBrowser.Controller.Entities
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[IgnoreDataMember]
|
||||||
|
public override bool SupportsPlayedStatus
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
protected override bool GetBlockUnratedValue(UserPolicy config)
|
protected override bool GetBlockUnratedValue(UserPolicy config)
|
||||||
{
|
{
|
||||||
return config.BlockUnratedItems.Contains(UnratedItem.Other);
|
return config.BlockUnratedItems.Contains(UnratedItem.Other);
|
||||||
|
|
|
@ -154,8 +154,6 @@ namespace MediaBrowser.Controller.Entities.TV
|
||||||
|
|
||||||
Func<BaseItem, bool> filter = i => UserViewBuilder.Filter(i, user, query, UserDataManager, LibraryManager);
|
Func<BaseItem, bool> filter = i => UserViewBuilder.Filter(i, user, query, UserDataManager, LibraryManager);
|
||||||
|
|
||||||
var id = Guid.NewGuid().ToString("N");
|
|
||||||
|
|
||||||
var items = GetEpisodes(user).Where(filter);
|
var items = GetEpisodes(user).Where(filter);
|
||||||
|
|
||||||
var result = PostFilterAndSort(items, query, false, false);
|
var result = PostFilterAndSort(items, query, false, false);
|
||||||
|
|
|
@ -17,17 +17,14 @@ namespace MediaBrowser.Controller.Entities.TV
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Class Series
|
/// Class Series
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public class Series : Folder, IHasTrailers, IHasDisplayOrder, IHasLookupInfo<SeriesInfo>, IHasSpecialFeatures, IMetadataContainer, IHasOriginalTitle
|
public class Series : Folder, IHasTrailers, IHasDisplayOrder, IHasLookupInfo<SeriesInfo>, IMetadataContainer, IHasOriginalTitle
|
||||||
{
|
{
|
||||||
public List<Guid> SpecialFeatureIds { get; set; }
|
|
||||||
|
|
||||||
public int? AnimeSeriesIndex { get; set; }
|
public int? AnimeSeriesIndex { get; set; }
|
||||||
|
|
||||||
public Series()
|
public Series()
|
||||||
{
|
{
|
||||||
AirDays = new List<DayOfWeek>();
|
AirDays = new List<DayOfWeek>();
|
||||||
|
|
||||||
SpecialFeatureIds = new List<Guid>();
|
|
||||||
RemoteTrailers = new List<MediaUrl>();
|
RemoteTrailers = new List<MediaUrl>();
|
||||||
LocalTrailerIds = new List<Guid>();
|
LocalTrailerIds = new List<Guid>();
|
||||||
RemoteTrailerIds = new List<Guid>();
|
RemoteTrailerIds = new List<Guid>();
|
||||||
|
|
|
@ -10,16 +10,12 @@ namespace MediaBrowser.Controller.Entities
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Class Trailer
|
/// Class Trailer
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public class Trailer : Video, IHasCriticRating, IHasProductionLocations, IHasBudget, IHasTaglines, IHasMetascore, IHasOriginalTitle, IHasLookupInfo<TrailerInfo>
|
public class Trailer : Video, IHasCriticRating, IHasBudget, IHasMetascore, IHasOriginalTitle, IHasLookupInfo<TrailerInfo>
|
||||||
{
|
{
|
||||||
public List<string> ProductionLocations { get; set; }
|
|
||||||
|
|
||||||
public Trailer()
|
public Trailer()
|
||||||
{
|
{
|
||||||
RemoteTrailers = new List<MediaUrl>();
|
RemoteTrailers = new List<MediaUrl>();
|
||||||
Taglines = new List<string>();
|
|
||||||
Keywords = new List<string>();
|
Keywords = new List<string>();
|
||||||
ProductionLocations = new List<string>();
|
|
||||||
TrailerTypes = new List<TrailerType> { TrailerType.LocalTrailer };
|
TrailerTypes = new List<TrailerType> { TrailerType.LocalTrailer };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -35,12 +31,6 @@ namespace MediaBrowser.Controller.Entities
|
||||||
get { return TrailerTypes.Contains(TrailerType.LocalTrailer); }
|
get { return TrailerTypes.Contains(TrailerType.LocalTrailer); }
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets or sets the taglines.
|
|
||||||
/// </summary>
|
|
||||||
/// <value>The taglines.</value>
|
|
||||||
public List<string> Taglines { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets or sets the budget.
|
/// Gets or sets the budget.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
@ -64,7 +54,7 @@ namespace MediaBrowser.Controller.Entities
|
||||||
|
|
||||||
info.IsLocalTrailer = TrailerTypes.Contains(TrailerType.LocalTrailer);
|
info.IsLocalTrailer = TrailerTypes.Contains(TrailerType.LocalTrailer);
|
||||||
|
|
||||||
if (!IsInMixedFolder && LocationType == LocationType.FileSystem)
|
if (!DetectIsInMixedFolder() && LocationType == LocationType.FileSystem)
|
||||||
{
|
{
|
||||||
info.Name = System.IO.Path.GetFileName(ContainingFolderPath);
|
info.Name = System.IO.Path.GetFileName(ContainingFolderPath);
|
||||||
}
|
}
|
||||||
|
@ -90,7 +80,7 @@ namespace MediaBrowser.Controller.Entities
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// Try to get the year from the folder name
|
// Try to get the year from the folder name
|
||||||
if (!IsInMixedFolder)
|
if (!DetectIsInMixedFolder())
|
||||||
{
|
{
|
||||||
info = LibraryManager.ParseName(System.IO.Path.GetFileName(ContainingFolderPath));
|
info = LibraryManager.ParseName(System.IO.Path.GetFileName(ContainingFolderPath));
|
||||||
|
|
||||||
|
|
|
@ -33,6 +33,15 @@ namespace MediaBrowser.Controller.Entities
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[IgnoreDataMember]
|
||||||
|
public override bool SupportsPlayedStatus
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private void ClearCache()
|
private void ClearCache()
|
||||||
{
|
{
|
||||||
lock (_childIdsLock)
|
lock (_childIdsLock)
|
||||||
|
|
|
@ -13,7 +13,6 @@ namespace MediaBrowser.Controller.Entities
|
||||||
public class UserView : Folder
|
public class UserView : Folder
|
||||||
{
|
{
|
||||||
public string ViewType { get; set; }
|
public string ViewType { get; set; }
|
||||||
public Guid ParentId { get; set; }
|
|
||||||
public Guid DisplayParentId { get; set; }
|
public Guid DisplayParentId { get; set; }
|
||||||
|
|
||||||
public Guid? UserId { get; set; }
|
public Guid? UserId { get; set; }
|
||||||
|
@ -45,6 +44,15 @@ namespace MediaBrowser.Controller.Entities
|
||||||
return list;
|
return list;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[IgnoreDataMember]
|
||||||
|
public override bool SupportsPlayedStatus
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public override int GetChildCount(User user)
|
public override int GetChildCount(User user)
|
||||||
{
|
{
|
||||||
return GetChildren(user, true).Count();
|
return GetChildren(user, true).Count();
|
||||||
|
|
|
@ -96,7 +96,7 @@ namespace MediaBrowser.Controller.Entities
|
||||||
Limit = query.Limit,
|
Limit = query.Limit,
|
||||||
IsAiring = true
|
IsAiring = true
|
||||||
|
|
||||||
}, CancellationToken.None).ConfigureAwait(false);
|
}, new Dto.DtoOptions(), CancellationToken.None).ConfigureAwait(false);
|
||||||
|
|
||||||
return GetResult(result);
|
return GetResult(result);
|
||||||
}
|
}
|
||||||
|
@ -1497,13 +1497,7 @@ namespace MediaBrowser.Controller.Entities
|
||||||
{
|
{
|
||||||
var filterValue = query.HasThemeSong.Value;
|
var filterValue = query.HasThemeSong.Value;
|
||||||
|
|
||||||
var themeCount = 0;
|
var themeCount = item.ThemeSongIds.Count;
|
||||||
var iHasThemeMedia = item as IHasThemeMedia;
|
|
||||||
|
|
||||||
if (iHasThemeMedia != null)
|
|
||||||
{
|
|
||||||
themeCount = iHasThemeMedia.ThemeSongIds.Count;
|
|
||||||
}
|
|
||||||
var ok = filterValue ? themeCount > 0 : themeCount == 0;
|
var ok = filterValue ? themeCount > 0 : themeCount == 0;
|
||||||
|
|
||||||
if (!ok)
|
if (!ok)
|
||||||
|
@ -1516,13 +1510,7 @@ namespace MediaBrowser.Controller.Entities
|
||||||
{
|
{
|
||||||
var filterValue = query.HasThemeVideo.Value;
|
var filterValue = query.HasThemeVideo.Value;
|
||||||
|
|
||||||
var themeCount = 0;
|
var themeCount = item.ThemeVideoIds.Count;
|
||||||
var iHasThemeMedia = item as IHasThemeMedia;
|
|
||||||
|
|
||||||
if (iHasThemeMedia != null)
|
|
||||||
{
|
|
||||||
themeCount = iHasThemeMedia.ThemeVideoIds.Count;
|
|
||||||
}
|
|
||||||
var ok = filterValue ? themeCount > 0 : themeCount == 0;
|
var ok = filterValue ? themeCount > 0 : themeCount == 0;
|
||||||
|
|
||||||
if (!ok)
|
if (!ok)
|
||||||
|
|
|
@ -25,8 +25,7 @@ namespace MediaBrowser.Controller.Entities
|
||||||
ISupportsPlaceHolders,
|
ISupportsPlaceHolders,
|
||||||
IHasMediaSources,
|
IHasMediaSources,
|
||||||
IHasShortOverview,
|
IHasShortOverview,
|
||||||
IThemeMedia,
|
IThemeMedia
|
||||||
IArchivable
|
|
||||||
{
|
{
|
||||||
[IgnoreDataMember]
|
[IgnoreDataMember]
|
||||||
public string PrimaryVersionId { get; set; }
|
public string PrimaryVersionId { get; set; }
|
||||||
|
@ -45,6 +44,24 @@ namespace MediaBrowser.Controller.Entities
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[IgnoreDataMember]
|
||||||
|
public override bool SupportsPlayedStatus
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[IgnoreDataMember]
|
||||||
|
protected override bool SupportsIsInMixedFolderDetection
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public override string CreatePresentationUniqueKey()
|
public override string CreatePresentationUniqueKey()
|
||||||
{
|
{
|
||||||
if (!string.IsNullOrWhiteSpace(PrimaryVersionId))
|
if (!string.IsNullOrWhiteSpace(PrimaryVersionId))
|
||||||
|
@ -64,6 +81,12 @@ namespace MediaBrowser.Controller.Entities
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[IgnoreDataMember]
|
||||||
|
public override bool SupportsThemeMedia
|
||||||
|
{
|
||||||
|
get { return true; }
|
||||||
|
}
|
||||||
|
|
||||||
public int? TotalBitrate { get; set; }
|
public int? TotalBitrate { get; set; }
|
||||||
public ExtraType? ExtraType { get; set; }
|
public ExtraType? ExtraType { get; set; }
|
||||||
|
|
||||||
|
@ -165,7 +188,7 @@ namespace MediaBrowser.Controller.Entities
|
||||||
[IgnoreDataMember]
|
[IgnoreDataMember]
|
||||||
public override bool SupportsAddingToPlaylist
|
public override bool SupportsAddingToPlaylist
|
||||||
{
|
{
|
||||||
get { return LocationType == LocationType.FileSystem && RunTimeTicks.HasValue; }
|
get { return true; }
|
||||||
}
|
}
|
||||||
|
|
||||||
[IgnoreDataMember]
|
[IgnoreDataMember]
|
||||||
|
@ -197,21 +220,6 @@ namespace MediaBrowser.Controller.Entities
|
||||||
get { return LocalAlternateVersions.Count > 0; }
|
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()
|
public IEnumerable<Guid> GetAdditionalPartIds()
|
||||||
{
|
{
|
||||||
return AdditionalParts.Select(i => LibraryManager.GetNewItemId(i, typeof(Video)));
|
return AdditionalParts.Select(i => LibraryManager.GetNewItemId(i, typeof(Video)));
|
||||||
|
@ -480,7 +488,7 @@ namespace MediaBrowser.Controller.Entities
|
||||||
|
|
||||||
public override IEnumerable<string> GetDeletePaths()
|
public override IEnumerable<string> GetDeletePaths()
|
||||||
{
|
{
|
||||||
if (!IsInMixedFolder)
|
if (!DetectIsInMixedFolder())
|
||||||
{
|
{
|
||||||
return new[] { ContainingFolderPath };
|
return new[] { ContainingFolderPath };
|
||||||
}
|
}
|
||||||
|
@ -600,7 +608,7 @@ namespace MediaBrowser.Controller.Entities
|
||||||
Protocol = locationType == LocationType.Remote ? MediaProtocol.Http : MediaProtocol.File,
|
Protocol = locationType == LocationType.Remote ? MediaProtocol.Http : MediaProtocol.File,
|
||||||
MediaStreams = mediaStreams,
|
MediaStreams = mediaStreams,
|
||||||
Name = GetMediaSourceName(i, mediaStreams),
|
Name = GetMediaSourceName(i, mediaStreams),
|
||||||
Path = enablePathSubstitution ? GetMappedPath(i.Path, locationType) : i.Path,
|
Path = enablePathSubstitution ? GetMappedPath(i, i.Path, locationType) : i.Path,
|
||||||
RunTimeTicks = i.RunTimeTicks,
|
RunTimeTicks = i.RunTimeTicks,
|
||||||
Video3DFormat = i.Video3DFormat,
|
Video3DFormat = i.Video3DFormat,
|
||||||
VideoType = i.VideoType,
|
VideoType = i.VideoType,
|
||||||
|
|
|
@ -506,6 +506,8 @@ namespace MediaBrowser.Controller.Library
|
||||||
/// <returns>QueryResult<BaseItem>.</returns>
|
/// <returns>QueryResult<BaseItem>.</returns>
|
||||||
QueryResult<BaseItem> QueryItems(InternalItemsQuery query);
|
QueryResult<BaseItem> QueryItems(InternalItemsQuery query);
|
||||||
|
|
||||||
|
string GetPathAfterNetworkSubstitution(string path, BaseItem ownerItem = null);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Substitutes the path.
|
/// Substitutes the path.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
@ -554,9 +556,10 @@ namespace MediaBrowser.Controller.Library
|
||||||
/// <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, LibraryOptions options, bool refreshLibrary);
|
void AddVirtualFolder(string name, string collectionType, LibraryOptions options, bool refreshLibrary);
|
||||||
void RemoveVirtualFolder(string name, bool refreshLibrary);
|
void RemoveVirtualFolder(string name, bool refreshLibrary);
|
||||||
void AddMediaPath(string virtualFolderName, string path);
|
void AddMediaPath(string virtualFolderName, MediaPathInfo path);
|
||||||
|
void UpdateMediaPath(string virtualFolderName, MediaPathInfo path);
|
||||||
void RemoveMediaPath(string virtualFolderName, string path);
|
void RemoveMediaPath(string virtualFolderName, string path);
|
||||||
|
|
||||||
QueryResult<Tuple<BaseItem, ItemCounts>> GetGenres(InternalItemsQuery query);
|
QueryResult<Tuple<BaseItem, ItemCounts>> GetGenres(InternalItemsQuery query);
|
||||||
|
|
|
@ -7,6 +7,7 @@ using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
using System.IO;
|
||||||
|
|
||||||
namespace MediaBrowser.Controller.Library
|
namespace MediaBrowser.Controller.Library
|
||||||
{
|
{
|
||||||
|
@ -60,11 +61,8 @@ namespace MediaBrowser.Controller.Library
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets the static media source.
|
/// Gets the static media source.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="item">The item.</param>
|
|
||||||
/// <param name="mediaSourceId">The media source identifier.</param>
|
|
||||||
/// <param name="enablePathSubstitution">if set to <c>true</c> [enable path substitution].</param>
|
|
||||||
/// <returns>MediaSourceInfo.</returns>
|
/// <returns>MediaSourceInfo.</returns>
|
||||||
Task<MediaSourceInfo> GetMediaSource(IHasMediaSources item, string mediaSourceId, bool enablePathSubstitution);
|
Task<MediaSourceInfo> GetMediaSource(IHasMediaSources item, string mediaSourceId, string liveStreamId, bool enablePathSubstitution, CancellationToken cancellationToken);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Opens the media source.
|
/// Opens the media source.
|
||||||
|
@ -82,6 +80,8 @@ namespace MediaBrowser.Controller.Library
|
||||||
/// <param name="cancellationToken">The cancellation token.</param>
|
/// <param name="cancellationToken">The cancellation token.</param>
|
||||||
/// <returns>Task<MediaSourceInfo>.</returns>
|
/// <returns>Task<MediaSourceInfo>.</returns>
|
||||||
Task<MediaSourceInfo> GetLiveStream(string id, CancellationToken cancellationToken);
|
Task<MediaSourceInfo> GetLiveStream(string id, CancellationToken cancellationToken);
|
||||||
|
|
||||||
|
Task<Tuple<MediaSourceInfo, IDirectStreamProvider>> GetLiveStreamWithDirectStreamProvider(string id, CancellationToken cancellationToken);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Pings the media source.
|
/// Pings the media source.
|
||||||
|
@ -95,8 +95,12 @@ namespace MediaBrowser.Controller.Library
|
||||||
/// Closes the media source.
|
/// Closes the media source.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="id">The live stream identifier.</param>
|
/// <param name="id">The live stream identifier.</param>
|
||||||
/// <param name="cancellationToken">The cancellation token.</param>
|
|
||||||
/// <returns>Task.</returns>
|
/// <returns>Task.</returns>
|
||||||
Task CloseLiveStream(string id, CancellationToken cancellationToken);
|
Task CloseLiveStream(string id);
|
||||||
|
}
|
||||||
|
|
||||||
|
public interface IDirectStreamProvider
|
||||||
|
{
|
||||||
|
Task CopyToAsync(Stream stream, CancellationToken cancellationToken);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,6 +3,7 @@ using MediaBrowser.Model.Dto;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
using System;
|
||||||
|
|
||||||
namespace MediaBrowser.Controller.Library
|
namespace MediaBrowser.Controller.Library
|
||||||
{
|
{
|
||||||
|
@ -22,14 +23,13 @@ namespace MediaBrowser.Controller.Library
|
||||||
/// <param name="openToken">The open token.</param>
|
/// <param name="openToken">The open token.</param>
|
||||||
/// <param name="cancellationToken">The cancellation token.</param>
|
/// <param name="cancellationToken">The cancellation token.</param>
|
||||||
/// <returns>Task<MediaSourceInfo>.</returns>
|
/// <returns>Task<MediaSourceInfo>.</returns>
|
||||||
Task<MediaSourceInfo> OpenMediaSource(string openToken, CancellationToken cancellationToken);
|
Task<Tuple<MediaSourceInfo,IDirectStreamProvider>> OpenMediaSource(string openToken, CancellationToken cancellationToken);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Closes the media source.
|
/// Closes the media source.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="liveStreamId">The live stream identifier.</param>
|
/// <param name="liveStreamId">The live stream identifier.</param>
|
||||||
/// <param name="cancellationToken">The cancellation token.</param>
|
|
||||||
/// <returns>Task.</returns>
|
/// <returns>Task.</returns>
|
||||||
Task CloseMediaSource(string liveStreamId, CancellationToken cancellationToken);
|
Task CloseMediaSource(string liveStreamId);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,6 +9,7 @@ using System.Collections.Generic;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using MediaBrowser.Model.Events;
|
using MediaBrowser.Model.Events;
|
||||||
|
using MediaBrowser.Controller.Library;
|
||||||
|
|
||||||
namespace MediaBrowser.Controller.LiveTv
|
namespace MediaBrowser.Controller.LiveTv
|
||||||
{
|
{
|
||||||
|
@ -37,7 +38,7 @@ namespace MediaBrowser.Controller.LiveTv
|
||||||
/// <param name="cancellationToken">The cancellation token.</param>
|
/// <param name="cancellationToken">The cancellation token.</param>
|
||||||
/// <returns>Task{SeriesTimerInfoDto}.</returns>
|
/// <returns>Task{SeriesTimerInfoDto}.</returns>
|
||||||
Task<SeriesTimerInfoDto> GetNewTimerDefaults(string programId, CancellationToken cancellationToken);
|
Task<SeriesTimerInfoDto> GetNewTimerDefaults(string programId, CancellationToken cancellationToken);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Deletes the recording.
|
/// Deletes the recording.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
@ -51,7 +52,7 @@ namespace MediaBrowser.Controller.LiveTv
|
||||||
/// <param name="recording">The recording.</param>
|
/// <param name="recording">The recording.</param>
|
||||||
/// <returns>Task.</returns>
|
/// <returns>Task.</returns>
|
||||||
Task DeleteRecording(BaseItem recording);
|
Task DeleteRecording(BaseItem recording);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Cancels the timer.
|
/// Cancels the timer.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
@ -83,7 +84,7 @@ namespace MediaBrowser.Controller.LiveTv
|
||||||
/// <param name="user">The user.</param>
|
/// <param name="user">The user.</param>
|
||||||
/// <returns>Task{RecordingInfoDto}.</returns>
|
/// <returns>Task{RecordingInfoDto}.</returns>
|
||||||
Task<BaseItemDto> GetRecording(string id, DtoOptions options, CancellationToken cancellationToken, User user = null);
|
Task<BaseItemDto> GetRecording(string id, DtoOptions options, CancellationToken cancellationToken, User user = null);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets the timer.
|
/// Gets the timer.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
@ -125,14 +126,14 @@ namespace MediaBrowser.Controller.LiveTv
|
||||||
/// <param name="cancellationToken">The cancellation token.</param>
|
/// <param name="cancellationToken">The cancellation token.</param>
|
||||||
/// <returns>Task{QueryResult{SeriesTimerInfoDto}}.</returns>
|
/// <returns>Task{QueryResult{SeriesTimerInfoDto}}.</returns>
|
||||||
Task<QueryResult<SeriesTimerInfoDto>> GetSeriesTimers(SeriesTimerQuery query, CancellationToken cancellationToken);
|
Task<QueryResult<SeriesTimerInfoDto>> GetSeriesTimers(SeriesTimerQuery query, CancellationToken cancellationToken);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets the channel.
|
/// Gets the channel.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="id">The identifier.</param>
|
/// <param name="id">The identifier.</param>
|
||||||
/// <returns>Channel.</returns>
|
/// <returns>Channel.</returns>
|
||||||
LiveTvChannel GetInternalChannel(string id);
|
LiveTvChannel GetInternalChannel(string id);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets the recording.
|
/// Gets the recording.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
@ -156,8 +157,8 @@ namespace MediaBrowser.Controller.LiveTv
|
||||||
/// <param name="mediaSourceId">The media source identifier.</param>
|
/// <param name="mediaSourceId">The media source identifier.</param>
|
||||||
/// <param name="cancellationToken">The cancellation token.</param>
|
/// <param name="cancellationToken">The cancellation token.</param>
|
||||||
/// <returns>Task{StreamResponseInfo}.</returns>
|
/// <returns>Task{StreamResponseInfo}.</returns>
|
||||||
Task<MediaSourceInfo> GetChannelStream(string id, string mediaSourceId, CancellationToken cancellationToken);
|
Task<Tuple<MediaSourceInfo, IDirectStreamProvider>> GetChannelStream(string id, string mediaSourceId, CancellationToken cancellationToken);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets the program.
|
/// Gets the program.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
@ -220,9 +221,8 @@ namespace MediaBrowser.Controller.LiveTv
|
||||||
/// Closes the live stream.
|
/// Closes the live stream.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="id">The identifier.</param>
|
/// <param name="id">The identifier.</param>
|
||||||
/// <param name="cancellationToken">The cancellation token.</param>
|
|
||||||
/// <returns>Task.</returns>
|
/// <returns>Task.</returns>
|
||||||
Task CloseLiveStream(string id, CancellationToken cancellationToken);
|
Task CloseLiveStream(string id);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets the guide information.
|
/// Gets the guide information.
|
||||||
|
@ -242,10 +242,8 @@ namespace MediaBrowser.Controller.LiveTv
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets the recommended programs internal.
|
/// Gets the recommended programs internal.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="query">The query.</param>
|
|
||||||
/// <param name="cancellationToken">The cancellation token.</param>
|
|
||||||
/// <returns>Task<QueryResult<LiveTvProgram>>.</returns>
|
/// <returns>Task<QueryResult<LiveTvProgram>>.</returns>
|
||||||
Task<QueryResult<LiveTvProgram>> GetRecommendedProgramsInternal(RecommendedProgramQuery query, CancellationToken cancellationToken);
|
Task<QueryResult<LiveTvProgram>> GetRecommendedProgramsInternal(RecommendedProgramQuery query, DtoOptions options, CancellationToken cancellationToken);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets the live tv information.
|
/// Gets the live tv information.
|
||||||
|
@ -303,18 +301,12 @@ namespace MediaBrowser.Controller.LiveTv
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets the recording media sources.
|
/// Gets the recording media sources.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="id">The identifier.</param>
|
Task<IEnumerable<MediaSourceInfo>> GetRecordingMediaSources(IHasMediaSources item, CancellationToken cancellationToken);
|
||||||
/// <param name="cancellationToken">The cancellation token.</param>
|
|
||||||
/// <returns>Task<IEnumerable<MediaSourceInfo>>.</returns>
|
|
||||||
Task<IEnumerable<MediaSourceInfo>> GetRecordingMediaSources(string id, CancellationToken cancellationToken);
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets the channel media sources.
|
/// Gets the channel media sources.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="id">The identifier.</param>
|
Task<IEnumerable<MediaSourceInfo>> GetChannelMediaSources(IHasMediaSources item, CancellationToken cancellationToken);
|
||||||
/// <param name="cancellationToken">The cancellation token.</param>
|
|
||||||
/// <returns>Task<IEnumerable<MediaSourceInfo>>.</returns>
|
|
||||||
Task<IEnumerable<MediaSourceInfo>> GetChannelMediaSources(string id, CancellationToken cancellationToken);
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Adds the information to recording dto.
|
/// Adds the information to recording dto.
|
||||||
|
@ -331,8 +323,8 @@ namespace MediaBrowser.Controller.LiveTv
|
||||||
/// <param name="fields">The fields.</param>
|
/// <param name="fields">The fields.</param>
|
||||||
/// <param name="user">The user.</param>
|
/// <param name="user">The user.</param>
|
||||||
/// <returns>Task.</returns>
|
/// <returns>Task.</returns>
|
||||||
Task AddInfoToProgramDto(List<Tuple<BaseItem,BaseItemDto>> programs, List<ItemFields> fields, User user = null);
|
Task AddInfoToProgramDto(List<Tuple<BaseItem, BaseItemDto>> programs, List<ItemFields> fields, User user = null);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Saves the tuner host.
|
/// Saves the tuner host.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
@ -395,7 +387,7 @@ namespace MediaBrowser.Controller.LiveTv
|
||||||
Task<List<ChannelInfo>> GetChannelsForListingsProvider(string id, CancellationToken cancellationToken);
|
Task<List<ChannelInfo>> GetChannelsForListingsProvider(string id, CancellationToken cancellationToken);
|
||||||
Task<List<ChannelInfo>> GetChannelsFromListingsProviderData(string id, CancellationToken cancellationToken);
|
Task<List<ChannelInfo>> GetChannelsFromListingsProviderData(string id, CancellationToken cancellationToken);
|
||||||
|
|
||||||
List<IListingsProvider> ListingProviders { get;}
|
List<IListingsProvider> ListingProviders { get; }
|
||||||
|
|
||||||
event EventHandler<GenericEventArgs<TimerEventInfo>> SeriesTimerCancelled;
|
event EventHandler<GenericEventArgs<TimerEventInfo>> SeriesTimerCancelled;
|
||||||
event EventHandler<GenericEventArgs<TimerEventInfo>> TimerCancelled;
|
event EventHandler<GenericEventArgs<TimerEventInfo>> TimerCancelled;
|
||||||
|
|
|
@ -33,6 +33,7 @@ namespace MediaBrowser.Controller.LiveTv
|
||||||
bool CanDelete(User user);
|
bool CanDelete(User user);
|
||||||
|
|
||||||
string SeriesTimerId { get; set; }
|
string SeriesTimerId { get; set; }
|
||||||
|
string TimerId { get; set; }
|
||||||
RecordingStatus Status { get; set; }
|
RecordingStatus Status { get; set; }
|
||||||
DateTime? EndDate { get; set; }
|
DateTime? EndDate { get; set; }
|
||||||
DateTime DateLastSaved { get; set; }
|
DateTime DateLastSaved { get; set; }
|
||||||
|
|
|
@ -4,6 +4,7 @@ using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
using MediaBrowser.Controller.Library;
|
||||||
|
|
||||||
namespace MediaBrowser.Controller.LiveTv
|
namespace MediaBrowser.Controller.LiveTv
|
||||||
{
|
{
|
||||||
|
@ -245,4 +246,14 @@ namespace MediaBrowser.Controller.LiveTv
|
||||||
/// <returns>Task.</returns>
|
/// <returns>Task.</returns>
|
||||||
Task<string> CreateSeriesTimer(SeriesTimerInfo info, CancellationToken cancellationToken);
|
Task<string> CreateSeriesTimer(SeriesTimerInfo info, CancellationToken cancellationToken);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public interface ISupportsDirectStreamProvider
|
||||||
|
{
|
||||||
|
Task<Tuple<MediaSourceInfo, IDirectStreamProvider>> GetChannelStreamWithDirectStreamProvider(string channelId, string streamId, CancellationToken cancellationToken);
|
||||||
|
}
|
||||||
|
|
||||||
|
public interface ISupportsUpdatingDefaults
|
||||||
|
{
|
||||||
|
Task UpdateTimerDefaults(SeriesTimerInfo info, CancellationToken cancellationToken);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,9 +22,8 @@ namespace MediaBrowser.Controller.LiveTv
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets the channels.
|
/// Gets the channels.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="cancellationToken">The cancellation token.</param>
|
|
||||||
/// <returns>Task<IEnumerable<ChannelInfo>>.</returns>
|
/// <returns>Task<IEnumerable<ChannelInfo>>.</returns>
|
||||||
Task<IEnumerable<ChannelInfo>> GetChannels(CancellationToken cancellationToken);
|
Task<IEnumerable<ChannelInfo>> GetChannels(bool enableCache, CancellationToken cancellationToken);
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets the tuner infos.
|
/// Gets the tuner infos.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
@ -38,7 +37,7 @@ namespace MediaBrowser.Controller.LiveTv
|
||||||
/// <param name="streamId">The stream identifier.</param>
|
/// <param name="streamId">The stream identifier.</param>
|
||||||
/// <param name="cancellationToken">The cancellation token.</param>
|
/// <param name="cancellationToken">The cancellation token.</param>
|
||||||
/// <returns>Task<MediaSourceInfo>.</returns>
|
/// <returns>Task<MediaSourceInfo>.</returns>
|
||||||
Task<Tuple<MediaSourceInfo,SemaphoreSlim>> GetChannelStream(string channelId, string streamId, CancellationToken cancellationToken);
|
Task<LiveStream> GetChannelStream(string channelId, string streamId, CancellationToken cancellationToken);
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets the channel stream media sources.
|
/// Gets the channel stream media sources.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
@ -46,8 +45,6 @@ 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
MediaBrowser.Controller/LiveTv/LiveStream.cs
Normal file
45
MediaBrowser.Controller/LiveTv/LiveStream.cs
Normal file
|
@ -0,0 +1,45 @@
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Threading;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using MediaBrowser.Model.Dto;
|
||||||
|
|
||||||
|
namespace MediaBrowser.Controller.LiveTv
|
||||||
|
{
|
||||||
|
public class LiveStream
|
||||||
|
{
|
||||||
|
public MediaSourceInfo OriginalMediaSource { get; set; }
|
||||||
|
public MediaSourceInfo OpenedMediaSource { get; set; }
|
||||||
|
public int ConsumerCount {
|
||||||
|
get { return SharedStreamIds.Count; }
|
||||||
|
}
|
||||||
|
public ITunerHost TunerHost { get; set; }
|
||||||
|
public string OriginalStreamId { get; set; }
|
||||||
|
public bool EnableStreamSharing { get; set; }
|
||||||
|
public string UniqueId = Guid.NewGuid().ToString("N");
|
||||||
|
|
||||||
|
public List<string> SharedStreamIds = new List<string>();
|
||||||
|
|
||||||
|
public LiveStream(MediaSourceInfo mediaSource)
|
||||||
|
{
|
||||||
|
OriginalMediaSource = mediaSource;
|
||||||
|
OpenedMediaSource = mediaSource;
|
||||||
|
EnableStreamSharing = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Task Open(CancellationToken cancellationToken)
|
||||||
|
{
|
||||||
|
return OpenInternal(cancellationToken);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected virtual Task OpenInternal(CancellationToken cancellationToken)
|
||||||
|
{
|
||||||
|
return Task.FromResult(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
public virtual Task Close()
|
||||||
|
{
|
||||||
|
return Task.FromResult(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -20,6 +20,7 @@ namespace MediaBrowser.Controller.LiveTv
|
||||||
[IgnoreDataMember]
|
[IgnoreDataMember]
|
||||||
public bool IsSeries { get; set; }
|
public bool IsSeries { get; set; }
|
||||||
public string SeriesTimerId { get; set; }
|
public string SeriesTimerId { get; set; }
|
||||||
|
public string TimerId { get; set; }
|
||||||
[IgnoreDataMember]
|
[IgnoreDataMember]
|
||||||
public DateTime StartDate { get; set; }
|
public DateTime StartDate { get; set; }
|
||||||
public RecordingStatus Status { get; set; }
|
public RecordingStatus Status { get; set; }
|
||||||
|
@ -112,7 +113,7 @@ namespace MediaBrowser.Controller.LiveTv
|
||||||
|
|
||||||
public override bool CanDelete()
|
public override bool CanDelete()
|
||||||
{
|
{
|
||||||
return true;
|
return Status == RecordingStatus.Completed;
|
||||||
}
|
}
|
||||||
|
|
||||||
public override bool IsAuthorizedToDelete(User user)
|
public override bool IsAuthorizedToDelete(User user)
|
||||||
|
|
|
@ -5,11 +5,12 @@ using MediaBrowser.Model.Entities;
|
||||||
using MediaBrowser.Model.LiveTv;
|
using MediaBrowser.Model.LiveTv;
|
||||||
using MediaBrowser.Model.MediaInfo;
|
using MediaBrowser.Model.MediaInfo;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using System.Globalization;
|
||||||
using System.Runtime.Serialization;
|
using System.Runtime.Serialization;
|
||||||
|
|
||||||
namespace MediaBrowser.Controller.LiveTv
|
namespace MediaBrowser.Controller.LiveTv
|
||||||
{
|
{
|
||||||
public class LiveTvChannel : BaseItem, IHasMediaSources
|
public class LiveTvChannel : BaseItem, IHasMediaSources, IHasProgramAttributes
|
||||||
{
|
{
|
||||||
public override List<string> GetUserDataKeys()
|
public override List<string> GetUserDataKeys()
|
||||||
{
|
{
|
||||||
|
@ -81,10 +82,10 @@ namespace MediaBrowser.Controller.LiveTv
|
||||||
|
|
||||||
if (!string.IsNullOrEmpty(Number))
|
if (!string.IsNullOrEmpty(Number))
|
||||||
{
|
{
|
||||||
double.TryParse(Number, out number);
|
double.TryParse(Number, NumberStyles.Any, CultureInfo.InvariantCulture, out number);
|
||||||
}
|
}
|
||||||
|
|
||||||
return number.ToString("000-") + (Name ?? string.Empty);
|
return number.ToString("00000-") + (Name ?? string.Empty);
|
||||||
}
|
}
|
||||||
|
|
||||||
[IgnoreDataMember]
|
[IgnoreDataMember]
|
||||||
|
@ -137,5 +138,56 @@ namespace MediaBrowser.Controller.LiveTv
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[IgnoreDataMember]
|
||||||
|
public bool IsMovie { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets a value indicating whether this instance is sports.
|
||||||
|
/// </summary>
|
||||||
|
/// <value><c>true</c> if this instance is sports; otherwise, <c>false</c>.</value>
|
||||||
|
[IgnoreDataMember]
|
||||||
|
public bool IsSports { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets a value indicating whether this instance is series.
|
||||||
|
/// </summary>
|
||||||
|
/// <value><c>true</c> if this instance is series; otherwise, <c>false</c>.</value>
|
||||||
|
[IgnoreDataMember]
|
||||||
|
public bool IsSeries { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets a value indicating whether this instance is live.
|
||||||
|
/// </summary>
|
||||||
|
/// <value><c>true</c> if this instance is live; otherwise, <c>false</c>.</value>
|
||||||
|
[IgnoreDataMember]
|
||||||
|
public bool IsLive { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets a value indicating whether this instance is news.
|
||||||
|
/// </summary>
|
||||||
|
/// <value><c>true</c> if this instance is news; otherwise, <c>false</c>.</value>
|
||||||
|
[IgnoreDataMember]
|
||||||
|
public bool IsNews { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets a value indicating whether this instance is kids.
|
||||||
|
/// </summary>
|
||||||
|
/// <value><c>true</c> if this instance is kids; otherwise, <c>false</c>.</value>
|
||||||
|
[IgnoreDataMember]
|
||||||
|
public bool IsKids { get; set; }
|
||||||
|
|
||||||
|
[IgnoreDataMember]
|
||||||
|
public bool IsPremiere { get; set; }
|
||||||
|
|
||||||
|
[IgnoreDataMember]
|
||||||
|
public bool IsRepeat { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the episode title.
|
||||||
|
/// </summary>
|
||||||
|
/// <value>The episode title.</value>
|
||||||
|
[IgnoreDataMember]
|
||||||
|
public string EpisodeTitle { get; set; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,6 +19,7 @@ namespace MediaBrowser.Controller.LiveTv
|
||||||
[IgnoreDataMember]
|
[IgnoreDataMember]
|
||||||
public bool IsSeries { get; set; }
|
public bool IsSeries { get; set; }
|
||||||
public string SeriesTimerId { get; set; }
|
public string SeriesTimerId { get; set; }
|
||||||
|
public string TimerId { get; set; }
|
||||||
[IgnoreDataMember]
|
[IgnoreDataMember]
|
||||||
public DateTime StartDate { get; set; }
|
public DateTime StartDate { get; set; }
|
||||||
public RecordingStatus Status { get; set; }
|
public RecordingStatus Status { get; set; }
|
||||||
|
@ -53,6 +54,24 @@ namespace MediaBrowser.Controller.LiveTv
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[IgnoreDataMember]
|
||||||
|
protected override bool SupportsIsInMixedFolderDetection
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[IgnoreDataMember]
|
||||||
|
public override bool SupportsPlayedStatus
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return Status == RecordingStatus.Completed && base.SupportsPlayedStatus;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
[IgnoreDataMember]
|
[IgnoreDataMember]
|
||||||
public override LocationType LocationType
|
public override LocationType LocationType
|
||||||
{
|
{
|
||||||
|
@ -111,7 +130,7 @@ namespace MediaBrowser.Controller.LiveTv
|
||||||
|
|
||||||
public override bool CanDelete()
|
public override bool CanDelete()
|
||||||
{
|
{
|
||||||
return true;
|
return Status == RecordingStatus.Completed;
|
||||||
}
|
}
|
||||||
|
|
||||||
public override bool IsAuthorizedToDelete(User user)
|
public override bool IsAuthorizedToDelete(User user)
|
||||||
|
|
|
@ -107,6 +107,8 @@ namespace MediaBrowser.Controller.LiveTv
|
||||||
/// <value>The image URL.</value>
|
/// <value>The image URL.</value>
|
||||||
public string ImageUrl { get; set; }
|
public string ImageUrl { get; set; }
|
||||||
|
|
||||||
|
public string LogoImageUrl { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets or sets a value indicating whether this instance has image.
|
/// Gets or sets a value indicating whether this instance has image.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using MediaBrowser.Model.LiveTv;
|
||||||
|
|
||||||
namespace MediaBrowser.Controller.LiveTv
|
namespace MediaBrowser.Controller.LiveTv
|
||||||
{
|
{
|
||||||
|
@ -26,6 +27,8 @@ namespace MediaBrowser.Controller.LiveTv
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public string Name { get; set; }
|
public string Name { get; set; }
|
||||||
|
|
||||||
|
public string ServiceName { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Description of the recording.
|
/// Description of the recording.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
@ -53,6 +56,11 @@ namespace MediaBrowser.Controller.LiveTv
|
||||||
/// <value><c>true</c> if [record any channel]; otherwise, <c>false</c>.</value>
|
/// <value><c>true</c> if [record any channel]; otherwise, <c>false</c>.</value>
|
||||||
public bool RecordAnyChannel { get; set; }
|
public bool RecordAnyChannel { get; set; }
|
||||||
|
|
||||||
|
public int KeepUpTo { get; set; }
|
||||||
|
public KeepUntil KeepUntil { get; set; }
|
||||||
|
|
||||||
|
public bool SkipEpisodesInLibrary { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets or sets a value indicating whether [record new only].
|
/// Gets or sets a value indicating whether [record new only].
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
@ -104,6 +112,8 @@ namespace MediaBrowser.Controller.LiveTv
|
||||||
public SeriesTimerInfo()
|
public SeriesTimerInfo()
|
||||||
{
|
{
|
||||||
Days = new List<DayOfWeek>();
|
Days = new List<DayOfWeek>();
|
||||||
|
SkipEpisodesInLibrary = true;
|
||||||
|
KeepUntil = KeepUntil.UntilDeleted;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,10 +1,17 @@
|
||||||
using MediaBrowser.Model.LiveTv;
|
using MediaBrowser.Model.LiveTv;
|
||||||
using System;
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
namespace MediaBrowser.Controller.LiveTv
|
namespace MediaBrowser.Controller.LiveTv
|
||||||
{
|
{
|
||||||
public class TimerInfo
|
public class TimerInfo
|
||||||
{
|
{
|
||||||
|
public TimerInfo()
|
||||||
|
{
|
||||||
|
Genres = new List<string>();
|
||||||
|
KeepUntil = KeepUntil.UntilDeleted;
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Id of the recording.
|
/// Id of the recording.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
@ -15,7 +22,7 @@ namespace MediaBrowser.Controller.LiveTv
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <value>The series timer identifier.</value>
|
/// <value>The series timer identifier.</value>
|
||||||
public string SeriesTimerId { get; set; }
|
public string SeriesTimerId { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// ChannelId of the recording.
|
/// ChannelId of the recording.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
@ -26,7 +33,7 @@ namespace MediaBrowser.Controller.LiveTv
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <value>The program identifier.</value>
|
/// <value>The program identifier.</value>
|
||||||
public string ProgramId { get; set; }
|
public string ProgramId { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Name of the recording.
|
/// Name of the recording.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
@ -76,11 +83,36 @@ namespace MediaBrowser.Controller.LiveTv
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <value><c>true</c> if this instance is post padding required; otherwise, <c>false</c>.</value>
|
/// <value><c>true</c> if this instance is post padding required; otherwise, <c>false</c>.</value>
|
||||||
public bool IsPostPaddingRequired { get; set; }
|
public bool IsPostPaddingRequired { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets or sets the priority.
|
/// Gets or sets the priority.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <value>The priority.</value>
|
/// <value>The priority.</value>
|
||||||
public int Priority { get; set; }
|
public int Priority { get; set; }
|
||||||
|
|
||||||
|
|
||||||
|
// Program properties
|
||||||
|
public int? SeasonNumber { get; set; }
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the episode number.
|
||||||
|
/// </summary>
|
||||||
|
/// <value>The episode number.</value>
|
||||||
|
public int? EpisodeNumber { get; set; }
|
||||||
|
public bool IsMovie { get; set; }
|
||||||
|
public bool IsKids { get; set; }
|
||||||
|
public bool IsSports { get; set; }
|
||||||
|
public bool IsNews { get; set; }
|
||||||
|
public int? ProductionYear { get; set; }
|
||||||
|
public string EpisodeTitle { get; set; }
|
||||||
|
public DateTime? OriginalAirDate { get; set; }
|
||||||
|
public bool IsProgramSeries { get; set; }
|
||||||
|
public bool IsRepeat { get; set; }
|
||||||
|
public string HomePageUrl { get; set; }
|
||||||
|
public float? CommunityRating { get; set; }
|
||||||
|
public string ShortOverview { get; set; }
|
||||||
|
public string OfficialRating { get; set; }
|
||||||
|
public List<string> Genres { get; set; }
|
||||||
|
public string RecordingPath { get; set; }
|
||||||
|
public KeepUntil KeepUntil { get; set; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -91,10 +91,7 @@
|
||||||
<Compile Include="Channels\InternalChannelItemQuery.cs" />
|
<Compile Include="Channels\InternalChannelItemQuery.cs" />
|
||||||
<Compile Include="Channels\IRequiresMediaInfoCallback.cs" />
|
<Compile Include="Channels\IRequiresMediaInfoCallback.cs" />
|
||||||
<Compile Include="Channels\ISearchableChannel.cs" />
|
<Compile Include="Channels\ISearchableChannel.cs" />
|
||||||
<Compile Include="Chapters\ChapterSearchRequest.cs" />
|
|
||||||
<Compile Include="Chapters\IChapterManager.cs" />
|
<Compile Include="Chapters\IChapterManager.cs" />
|
||||||
<Compile Include="Chapters\IChapterProvider.cs" />
|
|
||||||
<Compile Include="Chapters\ChapterResponse.cs" />
|
|
||||||
<Compile Include="Collections\CollectionCreationOptions.cs" />
|
<Compile Include="Collections\CollectionCreationOptions.cs" />
|
||||||
<Compile Include="Collections\CollectionEvents.cs" />
|
<Compile Include="Collections\CollectionEvents.cs" />
|
||||||
<Compile Include="Collections\ICollectionManager.cs" />
|
<Compile Include="Collections\ICollectionManager.cs" />
|
||||||
|
@ -135,7 +132,6 @@
|
||||||
<Compile Include="Entities\Game.cs" />
|
<Compile Include="Entities\Game.cs" />
|
||||||
<Compile Include="Entities\GameGenre.cs" />
|
<Compile Include="Entities\GameGenre.cs" />
|
||||||
<Compile Include="Entities\GameSystem.cs" />
|
<Compile Include="Entities\GameSystem.cs" />
|
||||||
<Compile Include="Entities\IArchivable.cs" />
|
|
||||||
<Compile Include="Entities\IByReferenceItem.cs" />
|
<Compile Include="Entities\IByReferenceItem.cs" />
|
||||||
<Compile Include="Entities\IHasAspectRatio.cs" />
|
<Compile Include="Entities\IHasAspectRatio.cs" />
|
||||||
<Compile Include="Entities\IHasBudget.cs" />
|
<Compile Include="Entities\IHasBudget.cs" />
|
||||||
|
@ -147,15 +143,12 @@
|
||||||
<Compile Include="Entities\IHasMediaSources.cs" />
|
<Compile Include="Entities\IHasMediaSources.cs" />
|
||||||
<Compile Include="Entities\IHasMetascore.cs" />
|
<Compile Include="Entities\IHasMetascore.cs" />
|
||||||
<Compile Include="Entities\IHasOriginalTitle.cs" />
|
<Compile Include="Entities\IHasOriginalTitle.cs" />
|
||||||
<Compile Include="Entities\IHasProductionLocations.cs" />
|
|
||||||
<Compile Include="Entities\IHasProgramAttributes.cs" />
|
<Compile Include="Entities\IHasProgramAttributes.cs" />
|
||||||
<Compile Include="Entities\IHasScreenshots.cs" />
|
<Compile Include="Entities\IHasScreenshots.cs" />
|
||||||
<Compile Include="Entities\IHasSeries.cs" />
|
<Compile Include="Entities\IHasSeries.cs" />
|
||||||
<Compile Include="Entities\IHasShortOverview.cs" />
|
<Compile Include="Entities\IHasShortOverview.cs" />
|
||||||
<Compile Include="Entities\IHasSpecialFeatures.cs" />
|
<Compile Include="Entities\IHasSpecialFeatures.cs" />
|
||||||
<Compile Include="Entities\IHasStartDate.cs" />
|
<Compile Include="Entities\IHasStartDate.cs" />
|
||||||
<Compile Include="Entities\IHasTaglines.cs" />
|
|
||||||
<Compile Include="Entities\IHasThemeMedia.cs" />
|
|
||||||
<Compile Include="Entities\IHasTrailers.cs" />
|
<Compile Include="Entities\IHasTrailers.cs" />
|
||||||
<Compile Include="Entities\IHasUserData.cs" />
|
<Compile Include="Entities\IHasUserData.cs" />
|
||||||
<Compile Include="Entities\IHiddenFromDisplay.cs" />
|
<Compile Include="Entities\IHiddenFromDisplay.cs" />
|
||||||
|
@ -201,6 +194,7 @@
|
||||||
<Compile Include="Library\UserDataSaveEventArgs.cs" />
|
<Compile Include="Library\UserDataSaveEventArgs.cs" />
|
||||||
<Compile Include="LiveTv\IListingsProvider.cs" />
|
<Compile Include="LiveTv\IListingsProvider.cs" />
|
||||||
<Compile Include="LiveTv\ITunerHost.cs" />
|
<Compile Include="LiveTv\ITunerHost.cs" />
|
||||||
|
<Compile Include="LiveTv\LiveStream.cs" />
|
||||||
<Compile Include="LiveTv\RecordingGroup.cs" />
|
<Compile Include="LiveTv\RecordingGroup.cs" />
|
||||||
<Compile Include="LiveTv\RecordingStatusChangedEventArgs.cs" />
|
<Compile Include="LiveTv\RecordingStatusChangedEventArgs.cs" />
|
||||||
<Compile Include="LiveTv\ILiveTvRecording.cs" />
|
<Compile Include="LiveTv\ILiveTvRecording.cs" />
|
||||||
|
@ -266,7 +260,6 @@
|
||||||
<Compile Include="Playlists\IPlaylistManager.cs" />
|
<Compile Include="Playlists\IPlaylistManager.cs" />
|
||||||
<Compile Include="Playlists\Playlist.cs" />
|
<Compile Include="Playlists\Playlist.cs" />
|
||||||
<Compile Include="Plugins\ILocalizablePlugin.cs" />
|
<Compile Include="Plugins\ILocalizablePlugin.cs" />
|
||||||
<Compile Include="Power\IPowerManagement.cs" />
|
|
||||||
<Compile Include="Providers\AlbumInfo.cs" />
|
<Compile Include="Providers\AlbumInfo.cs" />
|
||||||
<Compile Include="Providers\ArtistInfo.cs" />
|
<Compile Include="Providers\ArtistInfo.cs" />
|
||||||
<Compile Include="Providers\BookInfo.cs" />
|
<Compile Include="Providers\BookInfo.cs" />
|
||||||
|
@ -290,9 +283,7 @@
|
||||||
<Compile Include="Providers\IHasItemChangeMonitor.cs" />
|
<Compile Include="Providers\IHasItemChangeMonitor.cs" />
|
||||||
<Compile Include="Providers\IHasLookupInfo.cs" />
|
<Compile Include="Providers\IHasLookupInfo.cs" />
|
||||||
<Compile Include="Providers\IHasOrder.cs" />
|
<Compile Include="Providers\IHasOrder.cs" />
|
||||||
<Compile Include="Providers\IImageFileSaver.cs" />
|
|
||||||
<Compile Include="Providers\IImageProvider.cs" />
|
<Compile Include="Providers\IImageProvider.cs" />
|
||||||
<Compile Include="Providers\IImageSaver.cs" />
|
|
||||||
<Compile Include="Providers\ILocalImageFileProvider.cs" />
|
<Compile Include="Providers\ILocalImageFileProvider.cs" />
|
||||||
<Compile Include="Providers\ILocalMetadataProvider.cs" />
|
<Compile Include="Providers\ILocalMetadataProvider.cs" />
|
||||||
<Compile Include="Providers\ImageRefreshMode.cs" />
|
<Compile Include="Providers\ImageRefreshMode.cs" />
|
||||||
|
@ -319,7 +310,6 @@
|
||||||
<Compile Include="Providers\SongInfo.cs" />
|
<Compile Include="Providers\SongInfo.cs" />
|
||||||
<Compile Include="Providers\TrailerInfo.cs" />
|
<Compile Include="Providers\TrailerInfo.cs" />
|
||||||
<Compile Include="Providers\VideoContentType.cs" />
|
<Compile Include="Providers\VideoContentType.cs" />
|
||||||
<Compile Include="RelatedMedia\IRelatedMediaProvider.cs" />
|
|
||||||
<Compile Include="Security\AuthenticationInfo.cs" />
|
<Compile Include="Security\AuthenticationInfo.cs" />
|
||||||
<Compile Include="Security\AuthenticationInfoQuery.cs" />
|
<Compile Include="Security\AuthenticationInfoQuery.cs" />
|
||||||
<Compile Include="Security\IAuthenticationRepository.cs" />
|
<Compile Include="Security\IAuthenticationRepository.cs" />
|
||||||
|
|
|
@ -45,9 +45,9 @@ namespace MediaBrowser.Controller.MediaEncoding
|
||||||
/// <param name="offset">The offset.</param>
|
/// <param name="offset">The offset.</param>
|
||||||
/// <param name="cancellationToken">The cancellation token.</param>
|
/// <param name="cancellationToken">The cancellation token.</param>
|
||||||
/// <returns>Task{Stream}.</returns>
|
/// <returns>Task{Stream}.</returns>
|
||||||
Task<string> ExtractVideoImage(string[] inputFiles, MediaProtocol protocol, Video3DFormat? threedFormat, TimeSpan? offset, CancellationToken cancellationToken);
|
Task<string> ExtractVideoImage(string[] inputFiles, string container, MediaProtocol protocol, Video3DFormat? threedFormat, TimeSpan? offset, CancellationToken cancellationToken);
|
||||||
|
|
||||||
Task<string> ExtractVideoImage(string[] inputFiles, MediaProtocol protocol, int? imageStreamIndex, CancellationToken cancellationToken);
|
Task<string> ExtractVideoImage(string[] inputFiles, string container, MediaProtocol protocol, int? imageStreamIndex, CancellationToken cancellationToken);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Extracts the video images on interval.
|
/// Extracts the video images on interval.
|
||||||
|
@ -84,7 +84,7 @@ namespace MediaBrowser.Controller.MediaEncoding
|
||||||
/// <param name="inputFiles">The input files.</param>
|
/// <param name="inputFiles">The input files.</param>
|
||||||
/// <param name="protocol">The protocol.</param>
|
/// <param name="protocol">The protocol.</param>
|
||||||
/// <returns>System.String.</returns>
|
/// <returns>System.String.</returns>
|
||||||
string GetProbeSizeArgument(string[] inputFiles, MediaProtocol protocol);
|
string GetProbeSizeAndAnalyzeDurationArgument(string[] inputFiles, MediaProtocol protocol);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets the input argument.
|
/// Gets the input argument.
|
||||||
|
|
|
@ -15,6 +15,7 @@ namespace MediaBrowser.Controller.MediaEncoding
|
||||||
public IIsoMount MountedIso { get; set; }
|
public IIsoMount MountedIso { get; set; }
|
||||||
public VideoType VideoType { get; set; }
|
public VideoType VideoType { get; set; }
|
||||||
public List<string> PlayableStreamFileNames { get; set; }
|
public List<string> PlayableStreamFileNames { get; set; }
|
||||||
|
public int AnalyzeDurationSections { get; set; }
|
||||||
|
|
||||||
public MediaInfoRequest()
|
public MediaInfoRequest()
|
||||||
{
|
{
|
||||||
|
|
|
@ -120,7 +120,7 @@ namespace MediaBrowser.Controller.Net
|
||||||
|
|
||||||
var cancellationTokenSource = new CancellationTokenSource();
|
var cancellationTokenSource = new CancellationTokenSource();
|
||||||
|
|
||||||
Logger.Info("{1} Begin transmitting over websocket to {0}", message.Connection.RemoteEndPoint, GetType().Name);
|
Logger.Debug("{1} Begin transmitting over websocket to {0}", message.Connection.RemoteEndPoint, GetType().Name);
|
||||||
|
|
||||||
var timer = SendOnTimer ?
|
var timer = SendOnTimer ?
|
||||||
new Timer(TimerCallback, message.Connection, Timeout.Infinite, Timeout.Infinite) :
|
new Timer(TimerCallback, message.Connection, Timeout.Infinite, Timeout.Infinite) :
|
||||||
|
@ -267,7 +267,7 @@ namespace MediaBrowser.Controller.Net
|
||||||
/// <param name="connection">The connection.</param>
|
/// <param name="connection">The connection.</param>
|
||||||
private void DisposeConnection(Tuple<IWebSocketConnection, CancellationTokenSource, Timer, TStateType, SemaphoreSlim> connection)
|
private void DisposeConnection(Tuple<IWebSocketConnection, CancellationTokenSource, Timer, TStateType, SemaphoreSlim> connection)
|
||||||
{
|
{
|
||||||
Logger.Info("{1} stop transmitting over websocket to {0}", connection.Item1.RemoteEndPoint, GetType().Name);
|
Logger.Debug("{1} stop transmitting over websocket to {0}", connection.Item1.RemoteEndPoint, GetType().Name);
|
||||||
|
|
||||||
var timer = connection.Item3;
|
var timer = connection.Item3;
|
||||||
|
|
||||||
|
|
|
@ -11,14 +11,6 @@ namespace MediaBrowser.Controller.Net
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public interface IHttpResultFactory
|
public interface IHttpResultFactory
|
||||||
{
|
{
|
||||||
/// <summary>
|
|
||||||
/// Throws the error.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="statusCode">The status code.</param>
|
|
||||||
/// <param name="errorMessage">The error message.</param>
|
|
||||||
/// <param name="responseHeaders">The response headers.</param>
|
|
||||||
void ThrowError(int statusCode, string errorMessage, IDictionary<string, string> responseHeaders = null);
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets the result.
|
/// Gets the result.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|
|
@ -31,6 +31,15 @@ namespace MediaBrowser.Controller.Playlists
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[IgnoreDataMember]
|
||||||
|
public override bool SupportsPlayedStatus
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return string.Equals(MediaType, "Video", StringComparison.OrdinalIgnoreCase);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
[IgnoreDataMember]
|
[IgnoreDataMember]
|
||||||
public override bool AlwaysScanInternalMetadataPath
|
public override bool AlwaysScanInternalMetadataPath
|
||||||
{
|
{
|
||||||
|
@ -198,15 +207,15 @@ namespace MediaBrowser.Controller.Playlists
|
||||||
|
|
||||||
public override bool IsVisible(User user)
|
public override bool IsVisible(User user)
|
||||||
{
|
{
|
||||||
if (base.IsVisible(user))
|
var userId = user.Id.ToString("N");
|
||||||
{
|
|
||||||
var userId = user.Id.ToString("N");
|
|
||||||
|
|
||||||
return Shares.Any(i => string.Equals(userId, i.UserId, StringComparison.OrdinalIgnoreCase)) ||
|
return Shares.Any(i => string.Equals(userId, i.UserId, StringComparison.OrdinalIgnoreCase)) ||
|
||||||
string.Equals(OwnerUserId, userId, StringComparison.OrdinalIgnoreCase);
|
string.Equals(OwnerUserId, userId, StringComparison.OrdinalIgnoreCase);
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
public override bool IsVisibleStandalone(User user)
|
||||||
|
{
|
||||||
|
return IsVisible(user);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,13 +0,0 @@
|
||||||
using System;
|
|
||||||
|
|
||||||
namespace MediaBrowser.Controller.Power
|
|
||||||
{
|
|
||||||
public interface IPowerManagement
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// Schedules the wake.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="utcTime">The UTC time.</param>
|
|
||||||
void ScheduleWake(DateTime utcTime);
|
|
||||||
}
|
|
||||||
}
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user