Merge remote-tracking branch 'upstream/master' into docker
This commit is contained in:
commit
e01f932f4b
|
@ -122,53 +122,12 @@ namespace MediaBrowser.Api
|
|||
return ToOptimizedResult(result);
|
||||
}
|
||||
|
||||
const string XbmcMetadata = "Xbmc Nfo";
|
||||
const string MediaBrowserMetadata = "Media Browser Xml";
|
||||
|
||||
public void Post(AutoSetMetadataOptions request)
|
||||
{
|
||||
var service = AutoDetectMetadataService();
|
||||
|
||||
Logger.Info("Setting preferred metadata format to " + service);
|
||||
|
||||
var serviceToDisable = string.Equals(service, XbmcMetadata) ?
|
||||
MediaBrowserMetadata :
|
||||
XbmcMetadata;
|
||||
|
||||
_configurationManager.DisableMetadataService(serviceToDisable);
|
||||
_configurationManager.DisableMetadataService("Media Browser Xml");
|
||||
_configurationManager.SaveConfiguration();
|
||||
}
|
||||
|
||||
private string AutoDetectMetadataService()
|
||||
{
|
||||
try
|
||||
{
|
||||
var paths = _libraryManager.GetDefaultVirtualFolders()
|
||||
.SelectMany(i => i.Locations)
|
||||
.Distinct(StringComparer.OrdinalIgnoreCase)
|
||||
.Select(i => new DirectoryInfo(i))
|
||||
.ToList();
|
||||
|
||||
if (paths.SelectMany(i => i.EnumerateFiles("*.xml", SearchOption.AllDirectories))
|
||||
.Any())
|
||||
{
|
||||
return XbmcMetadata;
|
||||
}
|
||||
|
||||
if (paths.SelectMany(i => i.EnumerateFiles("*.xml", SearchOption.AllDirectories))
|
||||
.Any(i => string.Equals(i.Name, "series.xml", StringComparison.OrdinalIgnoreCase) || string.Equals(i.Name, "movie.xml", StringComparison.OrdinalIgnoreCase)))
|
||||
{
|
||||
return MediaBrowserMetadata;
|
||||
}
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
return XbmcMetadata;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Posts the specified configuraiton.
|
||||
/// </summary>
|
||||
|
|
|
@ -44,8 +44,8 @@ namespace MediaBrowser.Api.Devices
|
|||
[ApiMember(Name = "Name", Description = "Name", IsRequired = true, DataType = "string", ParameterType = "query", Verb = "GET")]
|
||||
public string Name { get; set; }
|
||||
|
||||
[ApiMember(Name = "FullPath", Description = "FullPath", IsRequired = true, DataType = "string", ParameterType = "query", Verb = "GET")]
|
||||
public string FullPath { get; set; }
|
||||
[ApiMember(Name = "Id", Description = "Id", IsRequired = true, DataType = "string", ParameterType = "query", Verb = "GET")]
|
||||
public string Id { get; set; }
|
||||
|
||||
public Stream RequestStream { get; set; }
|
||||
}
|
||||
|
@ -132,7 +132,7 @@ namespace MediaBrowser.Api.Devices
|
|||
{
|
||||
var deviceId = Request.QueryString["DeviceId"];
|
||||
var album = Request.QueryString["Album"];
|
||||
var fullPath = Request.QueryString["FullPath"];
|
||||
var id = Request.QueryString["Id"];
|
||||
var name = Request.QueryString["Name"];
|
||||
|
||||
var task = _deviceManager.AcceptCameraUpload(deviceId, request.RequestStream, new LocalFileInfo
|
||||
|
@ -140,7 +140,7 @@ namespace MediaBrowser.Api.Devices
|
|||
MimeType = Request.ContentType,
|
||||
Album = album,
|
||||
Name = name,
|
||||
FullPath = fullPath
|
||||
Id = id
|
||||
});
|
||||
|
||||
Task.WaitAll(task);
|
||||
|
|
|
@ -237,7 +237,7 @@ namespace MediaBrowser.Api
|
|||
|
||||
if (musicVideo != null)
|
||||
{
|
||||
musicVideo.Artist = request.Artists[0];
|
||||
musicVideo.Artists = request.Artists.ToList();
|
||||
musicVideo.Album = request.Album;
|
||||
}
|
||||
|
||||
|
|
|
@ -1,10 +1,20 @@
|
|||
using MediaBrowser.Controller.Dto;
|
||||
using MediaBrowser.Api.UserLibrary;
|
||||
using MediaBrowser.Controller.Channels;
|
||||
using MediaBrowser.Controller.Dto;
|
||||
using MediaBrowser.Controller.Entities;
|
||||
using MediaBrowser.Controller.Entities.Movies;
|
||||
using MediaBrowser.Controller.Library;
|
||||
using MediaBrowser.Controller.Net;
|
||||
using MediaBrowser.Controller.Persistence;
|
||||
using MediaBrowser.Model.Channels;
|
||||
using MediaBrowser.Model.Entities;
|
||||
using MediaBrowser.Model.Querying;
|
||||
using ServiceStack;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace MediaBrowser.Api.Movies
|
||||
{
|
||||
|
@ -16,6 +26,17 @@ namespace MediaBrowser.Api.Movies
|
|||
{
|
||||
}
|
||||
|
||||
[Route("/Trailers", "GET", Summary = "Finds movies and trailers similar to a given trailer.")]
|
||||
public class Getrailers : BaseItemsRequest, IReturn<ItemsResult>
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets or sets the user id.
|
||||
/// </summary>
|
||||
/// <value>The user id.</value>
|
||||
[ApiMember(Name = "UserId", Description = "User Id", IsRequired = false, DataType = "string", ParameterType = "path", Verb = "GET")]
|
||||
public Guid? UserId { get; set; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Class TrailersService
|
||||
/// </summary>
|
||||
|
@ -38,6 +59,7 @@ namespace MediaBrowser.Api.Movies
|
|||
|
||||
private readonly IItemRepository _itemRepo;
|
||||
private readonly IDtoService _dtoService;
|
||||
private readonly IChannelManager _channelManager;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="TrailersService"/> class.
|
||||
|
@ -45,13 +67,14 @@ namespace MediaBrowser.Api.Movies
|
|||
/// <param name="userManager">The user manager.</param>
|
||||
/// <param name="userDataRepository">The user data repository.</param>
|
||||
/// <param name="libraryManager">The library manager.</param>
|
||||
public TrailersService(IUserManager userManager, IUserDataManager userDataRepository, ILibraryManager libraryManager, IItemRepository itemRepo, IDtoService dtoService)
|
||||
public TrailersService(IUserManager userManager, IUserDataManager userDataRepository, ILibraryManager libraryManager, IItemRepository itemRepo, IDtoService dtoService, IChannelManager channelManager)
|
||||
{
|
||||
_userManager = userManager;
|
||||
_userDataRepository = userDataRepository;
|
||||
_libraryManager = libraryManager;
|
||||
_itemRepo = itemRepo;
|
||||
_dtoService = dtoService;
|
||||
_channelManager = channelManager;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -75,5 +98,71 @@ namespace MediaBrowser.Api.Movies
|
|||
|
||||
return ToOptimizedSerializedResultUsingCache(result);
|
||||
}
|
||||
|
||||
public async Task<object> Get(Getrailers request)
|
||||
{
|
||||
var user = request.UserId.HasValue ? _userManager.GetUserById(request.UserId.Value) : null;
|
||||
var result = await GetAllTrailers(user).ConfigureAwait(false);
|
||||
|
||||
IEnumerable<BaseItem> items = result.Items;
|
||||
|
||||
// Apply filters
|
||||
// Run them starting with the ones that are likely to reduce the list the most
|
||||
foreach (var filter in request.GetFilters().OrderByDescending(f => (int)f))
|
||||
{
|
||||
items = ItemsService.ApplyFilter(items, filter, user, _userDataRepository);
|
||||
}
|
||||
|
||||
items = _libraryManager.Sort(items, user, request.GetOrderBy(), request.SortOrder ?? SortOrder.Ascending);
|
||||
|
||||
var itemsArray = items.ToList();
|
||||
|
||||
var pagedItems = ApplyPaging(request, itemsArray);
|
||||
|
||||
var fields = request.GetItemFields().ToList();
|
||||
|
||||
var returnItems = pagedItems.Select(i => _dtoService.GetBaseItemDto(i, fields, user)).ToArray();
|
||||
|
||||
return new ItemsResult
|
||||
{
|
||||
TotalRecordCount = itemsArray.Count,
|
||||
Items = returnItems
|
||||
};
|
||||
}
|
||||
|
||||
private IEnumerable<BaseItem> ApplyPaging(Getrailers request, IEnumerable<BaseItem> items)
|
||||
{
|
||||
// Start at
|
||||
if (request.StartIndex.HasValue)
|
||||
{
|
||||
items = items.Skip(request.StartIndex.Value);
|
||||
}
|
||||
|
||||
// Return limit
|
||||
if (request.Limit.HasValue)
|
||||
{
|
||||
items = items.Take(request.Limit.Value);
|
||||
}
|
||||
|
||||
return items;
|
||||
}
|
||||
|
||||
private async Task<QueryResult<BaseItem>> GetAllTrailers(User user)
|
||||
{
|
||||
var trailerResult = await _channelManager.GetAllMediaInternal(new AllChannelMediaQuery
|
||||
{
|
||||
ContentTypes = new[] { ChannelMediaContentType.MovieExtra },
|
||||
ExtraTypes = new[] { ExtraType.Trailer },
|
||||
UserId = user.Id.ToString("N")
|
||||
|
||||
}, CancellationToken.None).ConfigureAwait(false);
|
||||
|
||||
|
||||
return new QueryResult<BaseItem>
|
||||
{
|
||||
Items = trailerResult.Items,
|
||||
TotalRecordCount = trailerResult.TotalRecordCount
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -714,8 +714,10 @@ namespace MediaBrowser.Api.Playback
|
|||
/// <returns><c>true</c> if the specified stream is H264; otherwise, <c>false</c>.</returns>
|
||||
protected bool IsH264(MediaStream stream)
|
||||
{
|
||||
return stream.Codec.IndexOf("264", StringComparison.OrdinalIgnoreCase) != -1 ||
|
||||
stream.Codec.IndexOf("avc", StringComparison.OrdinalIgnoreCase) != -1;
|
||||
var codec = stream.Codec ?? string.Empty;
|
||||
|
||||
return codec.IndexOf("264", StringComparison.OrdinalIgnoreCase) != -1 ||
|
||||
codec.IndexOf("avc", StringComparison.OrdinalIgnoreCase) != -1;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -1976,6 +1978,7 @@ namespace MediaBrowser.Api.Playback
|
|||
state.TargetPacketLength,
|
||||
state.TargetTimestamp,
|
||||
state.IsTargetAnamorphic,
|
||||
state.IsTargetCabac,
|
||||
state.TargetRefFrames);
|
||||
|
||||
if (mediaProfile != null)
|
||||
|
@ -2065,6 +2068,7 @@ namespace MediaBrowser.Api.Playback
|
|||
state.TargetPacketLength,
|
||||
state.TranscodeSeekInfo,
|
||||
state.IsTargetAnamorphic,
|
||||
state.IsTargetCabac,
|
||||
state.TargetRefFrames
|
||||
|
||||
).FirstOrDefault() ?? string.Empty;
|
||||
|
|
|
@ -367,16 +367,6 @@ namespace MediaBrowser.Api.Playback.Hls
|
|||
{
|
||||
var state = await GetState(request, CancellationToken.None).ConfigureAwait(false);
|
||||
|
||||
if (string.Equals(request.AudioCodec, "copy", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
throw new ArgumentException("Audio codec copy is not allowed here.");
|
||||
}
|
||||
|
||||
if (string.Equals(request.VideoCodec, "copy", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
throw new ArgumentException("Video codec copy is not allowed here.");
|
||||
}
|
||||
|
||||
if (string.IsNullOrEmpty(request.MediaSourceId))
|
||||
{
|
||||
throw new ArgumentException("MediaSourceId is required");
|
||||
|
@ -511,7 +501,7 @@ namespace MediaBrowser.Api.Playback.Hls
|
|||
|
||||
private void AppendPlaylist(StringBuilder builder, string url, int bitrate, string subtitleGroup)
|
||||
{
|
||||
var header = "#EXT-X-STREAM-INF:PROGRAM-ID=1,BANDWIDTH=" + bitrate.ToString(UsCulture);
|
||||
var header = "#EXT-X-STREAM-INF:BANDWIDTH=" + bitrate.ToString(UsCulture);
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(subtitleGroup))
|
||||
{
|
||||
|
@ -638,7 +628,7 @@ namespace MediaBrowser.Api.Playback.Hls
|
|||
// See if we can save come cpu cycles by avoiding encoding
|
||||
if (string.Equals(codec, "copy", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
return IsH264(state.VideoStream) ? "-codec:v:0 copy -bsf:v h264_mp4toannexb" : "-codec:v:0 copy";
|
||||
return state.VideoStream != null && IsH264(state.VideoStream) ? "-codec:v:0 copy -bsf:v h264_mp4toannexb" : "-codec:v:0 copy";
|
||||
}
|
||||
|
||||
var keyFrameArg = string.Format(" -force_key_frames expr:gte(t,n_forced*{0})",
|
||||
|
|
|
@ -139,7 +139,7 @@ namespace MediaBrowser.Api.Playback.Hls
|
|||
// See if we can save come cpu cycles by avoiding encoding
|
||||
if (codec.Equals("copy", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
return IsH264(state.VideoStream) ? "-codec:v:0 copy -bsf:v h264_mp4toannexb" : "-codec:v:0 copy";
|
||||
return state.VideoStream != null && IsH264(state.VideoStream) ? "-codec:v:0 copy -bsf:v h264_mp4toannexb" : "-codec:v:0 copy";
|
||||
}
|
||||
|
||||
var keyFrameArg = string.Format(" -force_key_frames expr:gte(t,n_forced*{0})",
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
using System.Threading;
|
||||
using MediaBrowser.Common.IO;
|
||||
using MediaBrowser.Common.IO;
|
||||
using MediaBrowser.Model.Logging;
|
||||
using ServiceStack.Web;
|
||||
using System;
|
||||
|
@ -49,9 +48,7 @@ namespace MediaBrowser.Api.Playback.Progressive
|
|||
/// <param name="responseStream">The response stream.</param>
|
||||
public void WriteTo(Stream responseStream)
|
||||
{
|
||||
var task = WriteToAsync(responseStream);
|
||||
|
||||
Task.WaitAll(task);
|
||||
WriteToInternal(responseStream);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -59,12 +56,12 @@ namespace MediaBrowser.Api.Playback.Progressive
|
|||
/// </summary>
|
||||
/// <param name="responseStream">The response stream.</param>
|
||||
/// <returns>Task.</returns>
|
||||
public async Task WriteToAsync(Stream responseStream)
|
||||
private void WriteToInternal(Stream responseStream)
|
||||
{
|
||||
try
|
||||
{
|
||||
await new ProgressiveFileCopier(_fileSystem, _job)
|
||||
.StreamFile(Path, responseStream).ConfigureAwait(false);
|
||||
new ProgressiveFileCopier(_fileSystem, _job)
|
||||
.StreamFile(Path, responseStream);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
|
@ -95,16 +92,16 @@ namespace MediaBrowser.Api.Playback.Progressive
|
|||
_job = job;
|
||||
}
|
||||
|
||||
public async Task StreamFile(string path, Stream outputStream)
|
||||
public void StreamFile(string path, Stream outputStream)
|
||||
{
|
||||
var eofCount = 0;
|
||||
long position = 0;
|
||||
|
||||
using (var fs = _fileSystem.GetFileStream(path, FileMode.Open, FileAccess.Read, FileShare.ReadWrite, true))
|
||||
using (var fs = _fileSystem.GetFileStream(path, FileMode.Open, FileAccess.Read, FileShare.ReadWrite, false))
|
||||
{
|
||||
while (eofCount < 15)
|
||||
{
|
||||
await CopyToAsyncInternal(fs, outputStream, 81920, CancellationToken.None).ConfigureAwait(false);
|
||||
CopyToInternal(fs, outputStream, 81920);
|
||||
|
||||
var fsPosition = fs.Position;
|
||||
|
||||
|
@ -118,7 +115,8 @@ namespace MediaBrowser.Api.Playback.Progressive
|
|||
{
|
||||
eofCount++;
|
||||
}
|
||||
await Task.Delay(100).ConfigureAwait(false);
|
||||
var task = Task.Delay(100);
|
||||
Task.WaitAll(task);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -130,13 +128,13 @@ namespace MediaBrowser.Api.Playback.Progressive
|
|||
}
|
||||
}
|
||||
|
||||
private async Task CopyToAsyncInternal(Stream source, Stream destination, int bufferSize, CancellationToken cancellationToken)
|
||||
private void CopyToInternal(Stream source, Stream destination, int bufferSize)
|
||||
{
|
||||
byte[] array = new byte[bufferSize];
|
||||
int count;
|
||||
while ((count = await source.ReadAsync(array, 0, array.Length, cancellationToken).ConfigureAwait(false)) != 0)
|
||||
while ((count = source.Read(array, 0, array.Length)) != 0)
|
||||
{
|
||||
await destination.WriteAsync(array, 0, count, cancellationToken).ConfigureAwait(false);
|
||||
destination.Write(array, 0, count);
|
||||
|
||||
_bytesWritten += count;
|
||||
|
||||
|
|
|
@ -2,7 +2,6 @@
|
|||
using ServiceStack.Web;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace MediaBrowser.Api.Playback
|
||||
{
|
||||
|
@ -41,22 +40,7 @@ namespace MediaBrowser.Api.Playback
|
|||
/// <param name="responseStream">The response stream.</param>
|
||||
public void WriteTo(Stream responseStream)
|
||||
{
|
||||
var task = WriteToAsync(responseStream);
|
||||
|
||||
Task.WaitAll(task);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Writes to async.
|
||||
/// </summary>
|
||||
/// <param name="responseStream">The response stream.</param>
|
||||
/// <returns>Task.</returns>
|
||||
public async Task WriteToAsync(Stream responseStream)
|
||||
{
|
||||
using (_response)
|
||||
{
|
||||
await _response.Content.CopyToAsync(responseStream, 819200).ConfigureAwait(false);
|
||||
}
|
||||
_response.Content.CopyTo(responseStream, 819200);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -97,7 +97,12 @@ namespace MediaBrowser.Api.Playback
|
|||
|
||||
public bool ReadInputAtNativeFramerate
|
||||
{
|
||||
get { return InputProtocol == MediaProtocol.Rtmp || string.Equals(InputContainer, "wtv", StringComparison.OrdinalIgnoreCase); }
|
||||
get {
|
||||
|
||||
return InputProtocol == MediaProtocol.Rtmp ||
|
||||
string.Equals(InputContainer, "wtv", StringComparison.OrdinalIgnoreCase) ||
|
||||
!string.IsNullOrEmpty(LiveTvStreamId);
|
||||
}
|
||||
}
|
||||
|
||||
public TransportStreamTimestamp InputTimestamp { get; set; }
|
||||
|
@ -413,5 +418,18 @@ namespace MediaBrowser.Api.Playback
|
|||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public bool? IsTargetCabac
|
||||
{
|
||||
get
|
||||
{
|
||||
if (Request.Static)
|
||||
{
|
||||
return VideoStream == null ? null : VideoStream.IsCabac;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
using MediaBrowser.Controller.Collections;
|
||||
using System.Threading;
|
||||
using MediaBrowser.Controller.Collections;
|
||||
using MediaBrowser.Controller.Dto;
|
||||
using MediaBrowser.Controller.Entities;
|
||||
using MediaBrowser.Controller.Entities.Audio;
|
||||
|
@ -8,6 +9,7 @@ using MediaBrowser.Controller.Library;
|
|||
using MediaBrowser.Controller.Localization;
|
||||
using MediaBrowser.Controller.Net;
|
||||
using MediaBrowser.Controller.Providers;
|
||||
using MediaBrowser.Model.Channels;
|
||||
using MediaBrowser.Model.Entities;
|
||||
using MediaBrowser.Model.Querying;
|
||||
using ServiceStack;
|
||||
|
|
|
@ -296,6 +296,16 @@ namespace MediaBrowser.Common.Implementations
|
|||
logger.Info("64-Bit Process: {0}", Environment.Is64BitProcess);
|
||||
logger.Info("Program data path: {0}", appPaths.ProgramDataPath);
|
||||
|
||||
Type type = Type.GetType("Mono.Runtime");
|
||||
if (type != null)
|
||||
{
|
||||
MethodInfo displayName = type.GetMethod("GetDisplayName", BindingFlags.NonPublic | BindingFlags.Static);
|
||||
if (displayName != null)
|
||||
{
|
||||
logger.Info("Mono: " + displayName.Invoke(null, null));
|
||||
}
|
||||
}
|
||||
|
||||
logger.Info("Application Path: {0}", appPaths.ApplicationPath);
|
||||
|
||||
logger.Info("*** When reporting issues please include the entire log file. ***".ToUpper());
|
||||
|
|
|
@ -123,7 +123,7 @@ namespace MediaBrowser.Common.Implementations.HttpClientManager
|
|||
}
|
||||
|
||||
request.Method = method;
|
||||
request.Timeout = 20000;
|
||||
request.Timeout = options.TimeoutMs;
|
||||
|
||||
if (!string.IsNullOrEmpty(options.Host))
|
||||
{
|
||||
|
@ -390,7 +390,7 @@ namespace MediaBrowser.Common.Implementations.HttpClientManager
|
|||
|
||||
if (!options.BufferContent)
|
||||
{
|
||||
var response = await httpWebRequest.GetResponseAsync().ConfigureAwait(false);
|
||||
var response = await GetResponseAsync(httpWebRequest, TimeSpan.FromMilliseconds(options.TimeoutMs)).ConfigureAwait(false);
|
||||
|
||||
var httpResponse = (HttpWebResponse)response;
|
||||
|
||||
|
@ -401,7 +401,7 @@ namespace MediaBrowser.Common.Implementations.HttpClientManager
|
|||
return GetResponseInfo(httpResponse, httpResponse.GetResponseStream(), GetContentLength(httpResponse), httpResponse);
|
||||
}
|
||||
|
||||
using (var response = await httpWebRequest.GetResponseAsync().ConfigureAwait(false))
|
||||
using (var response = await GetResponseAsync(httpWebRequest, TimeSpan.FromMilliseconds(options.TimeoutMs)).ConfigureAwait(false))
|
||||
{
|
||||
var httpResponse = (HttpWebResponse)response;
|
||||
|
||||
|
@ -434,21 +434,9 @@ namespace MediaBrowser.Common.Implementations.HttpClientManager
|
|||
|
||||
throw exception;
|
||||
}
|
||||
catch (HttpRequestException ex)
|
||||
{
|
||||
_logger.ErrorException("Error getting response from " + options.Url, ex);
|
||||
|
||||
throw new HttpException(ex.Message, ex);
|
||||
}
|
||||
catch (WebException ex)
|
||||
{
|
||||
throw GetException(ex, options);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.ErrorException("Error getting response from " + options.Url, ex);
|
||||
|
||||
throw;
|
||||
throw GetException(ex, options);
|
||||
}
|
||||
finally
|
||||
{
|
||||
|
@ -636,21 +624,10 @@ namespace MediaBrowser.Common.Implementations.HttpClientManager
|
|||
return GetResponseInfo(httpResponse, tempFile, contentLength);
|
||||
}
|
||||
}
|
||||
catch (OperationCanceledException ex)
|
||||
{
|
||||
throw GetTempFileException(ex, options, tempFile);
|
||||
}
|
||||
catch (HttpRequestException ex)
|
||||
{
|
||||
throw GetTempFileException(ex, options, tempFile);
|
||||
}
|
||||
catch (WebException ex)
|
||||
{
|
||||
throw GetTempFileException(ex, options, tempFile);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
throw GetTempFileException(ex, options, tempFile);
|
||||
DeleteTempFile(tempFile);
|
||||
throw GetException(ex, options);
|
||||
}
|
||||
finally
|
||||
{
|
||||
|
@ -675,45 +652,26 @@ namespace MediaBrowser.Common.Implementations.HttpClientManager
|
|||
|
||||
protected static readonly CultureInfo UsCulture = new CultureInfo("en-US");
|
||||
|
||||
/// <summary>
|
||||
/// Handles the temp file exception.
|
||||
/// </summary>
|
||||
/// <param name="ex">The ex.</param>
|
||||
/// <param name="options">The options.</param>
|
||||
/// <param name="tempFile">The temp file.</param>
|
||||
/// <returns>Task.</returns>
|
||||
/// <exception cref="HttpException"></exception>
|
||||
private Exception GetTempFileException(Exception ex, HttpRequestOptions options, string tempFile)
|
||||
private Exception GetException(Exception ex, HttpRequestOptions options)
|
||||
{
|
||||
var operationCanceledException = ex as OperationCanceledException;
|
||||
var webException = ex as WebException
|
||||
?? ex.InnerException as WebException;
|
||||
|
||||
if (webException != null)
|
||||
{
|
||||
return GetException(webException, options);
|
||||
}
|
||||
|
||||
var operationCanceledException = ex as OperationCanceledException
|
||||
?? ex.InnerException as OperationCanceledException;
|
||||
|
||||
if (operationCanceledException != null)
|
||||
{
|
||||
// Cleanup
|
||||
DeleteTempFile(tempFile);
|
||||
|
||||
return GetCancellationException(options.Url, options.CancellationToken, operationCanceledException);
|
||||
}
|
||||
|
||||
_logger.ErrorException("Error getting response from " + options.Url, ex);
|
||||
|
||||
// Cleanup
|
||||
DeleteTempFile(tempFile);
|
||||
|
||||
var httpRequestException = ex as HttpRequestException;
|
||||
|
||||
if (httpRequestException != null)
|
||||
{
|
||||
return new HttpException(ex.Message, ex);
|
||||
}
|
||||
|
||||
var webException = ex as WebException;
|
||||
|
||||
if (webException != null)
|
||||
{
|
||||
throw GetException(webException, options);
|
||||
}
|
||||
|
||||
return ex;
|
||||
}
|
||||
|
||||
|
@ -843,5 +801,47 @@ namespace MediaBrowser.Common.Implementations.HttpClientManager
|
|||
{
|
||||
return Post(url, postData, null, cancellationToken);
|
||||
}
|
||||
|
||||
private Task<WebResponse> GetResponseAsync(WebRequest request, TimeSpan timeout)
|
||||
{
|
||||
var taskCompletion = new TaskCompletionSource<WebResponse>();
|
||||
|
||||
Task<WebResponse> asyncTask = Task.Factory.FromAsync<WebResponse>(request.BeginGetResponse, request.EndGetResponse, null);
|
||||
|
||||
ThreadPool.RegisterWaitForSingleObject((asyncTask as IAsyncResult).AsyncWaitHandle, TimeoutCallback, request, timeout, true);
|
||||
asyncTask.ContinueWith(task =>
|
||||
{
|
||||
taskCompletion.TrySetResult(task.Result);
|
||||
|
||||
}, TaskContinuationOptions.NotOnFaulted);
|
||||
|
||||
// Handle errors
|
||||
asyncTask.ContinueWith(task =>
|
||||
{
|
||||
if (task.Exception != null)
|
||||
{
|
||||
taskCompletion.TrySetException(task.Exception);
|
||||
}
|
||||
else
|
||||
{
|
||||
taskCompletion.TrySetException(new List<Exception>());
|
||||
}
|
||||
|
||||
}, TaskContinuationOptions.OnlyOnFaulted);
|
||||
|
||||
return taskCompletion.Task;
|
||||
}
|
||||
|
||||
private static void TimeoutCallback(object state, bool timedOut)
|
||||
{
|
||||
if (timedOut)
|
||||
{
|
||||
WebRequest request = (WebRequest)state;
|
||||
if (state != null)
|
||||
{
|
||||
request.Abort();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -94,6 +94,8 @@ namespace MediaBrowser.Common.Net
|
|||
public CacheMode CacheMode { get; set; }
|
||||
public TimeSpan CacheLength { get; set; }
|
||||
|
||||
public int TimeoutMs { get; set; }
|
||||
|
||||
private string GetHeaderValue(string name)
|
||||
{
|
||||
string value;
|
||||
|
@ -115,6 +117,8 @@ namespace MediaBrowser.Common.Net
|
|||
|
||||
LogRequest = true;
|
||||
CacheMode = CacheMode.None;
|
||||
|
||||
TimeoutMs = 20000;
|
||||
}
|
||||
|
||||
public void SetPostData(IDictionary<string,string> values)
|
||||
|
|
|
@ -4,5 +4,7 @@ namespace MediaBrowser.Controller.Connect
|
|||
public class UserLinkResult
|
||||
{
|
||||
public bool IsPending { get; set; }
|
||||
public bool IsNewUserInvitation { get; set; }
|
||||
public string GuestDisplayName { get; set; }
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,8 +1,6 @@
|
|||
using MediaBrowser.Controller.Entities;
|
||||
using MediaBrowser.Model.Dto;
|
||||
using MediaBrowser.Model.Entities;
|
||||
using MediaBrowser.Model.Querying;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace MediaBrowser.Controller.Dto
|
||||
|
@ -12,14 +10,6 @@ namespace MediaBrowser.Controller.Dto
|
|||
/// </summary>
|
||||
public interface IDtoService
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets the user dto.
|
||||
/// </summary>
|
||||
/// <param name="user">The user.</param>
|
||||
/// <returns>UserDto.</returns>
|
||||
[Obsolete]
|
||||
UserDto GetUserDto(User user);
|
||||
|
||||
/// <summary>
|
||||
/// Gets the dto id.
|
||||
/// </summary>
|
||||
|
|
|
@ -226,7 +226,9 @@ namespace MediaBrowser.Controller.Entities.Audio
|
|||
|
||||
public IEnumerable<BaseItem> GetTaggedItems(IEnumerable<BaseItem> inputItems)
|
||||
{
|
||||
return inputItems.OfType<IHasArtist>().Where(i => i.HasArtist(Name)).Cast<BaseItem>();
|
||||
return inputItems.OfType<IHasArtist>()
|
||||
.Where(i => i.HasArtist(Name))
|
||||
.Cast<BaseItem>();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -429,6 +429,12 @@ namespace MediaBrowser.Controller.Entities
|
|||
}
|
||||
}
|
||||
|
||||
[IgnoreDataMember]
|
||||
public virtual BaseItem DisplayParent
|
||||
{
|
||||
get { return Parent; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// When the item first debuted. For movies this could be premiere date, episodes would be first aired
|
||||
/// </summary>
|
||||
|
@ -548,7 +554,7 @@ namespace MediaBrowser.Controller.Entities
|
|||
return CustomRating;
|
||||
}
|
||||
|
||||
var parent = Parent;
|
||||
var parent = DisplayParent;
|
||||
if (parent != null)
|
||||
{
|
||||
return parent.CustomRatingForComparison;
|
||||
|
|
|
@ -74,7 +74,8 @@ namespace MediaBrowser.Controller.Entities
|
|||
{
|
||||
FileInfo = new DirectoryInfo(path),
|
||||
Path = path,
|
||||
Parent = Parent
|
||||
Parent = Parent,
|
||||
CollectionType = CollectionType
|
||||
};
|
||||
|
||||
// Gather child folder and files
|
||||
|
|
|
@ -736,7 +736,9 @@ namespace MediaBrowser.Controller.Entities
|
|||
/// <returns>IEnumerable{BaseItem}.</returns>
|
||||
protected virtual IEnumerable<BaseItem> GetNonCachedChildren(IDirectoryService directoryService)
|
||||
{
|
||||
return LibraryManager.ResolvePaths<BaseItem>(GetFileSystemChildren(directoryService), directoryService, this);
|
||||
var collectionType = LibraryManager.FindCollectionType(this);
|
||||
|
||||
return LibraryManager.ResolvePaths<BaseItem>(GetFileSystemChildren(directoryService), directoryService, this, collectionType);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -745,7 +747,16 @@ namespace MediaBrowser.Controller.Entities
|
|||
/// <returns>IEnumerable{BaseItem}.</returns>
|
||||
protected IEnumerable<BaseItem> GetCachedChildren()
|
||||
{
|
||||
return ItemRepository.GetChildren(Id).Select(RetrieveChild).Where(i => i != null);
|
||||
var childrenItems = ItemRepository.GetChildrenItems(Id).Select(RetrieveChild).Where(i => i != null);
|
||||
|
||||
//var children = ItemRepository.GetChildren(Id).Select(RetrieveChild).Where(i => i != null).ToList();
|
||||
|
||||
//if (children.Count != childrenItems.Count)
|
||||
//{
|
||||
// var b = this;
|
||||
//}
|
||||
|
||||
return childrenItems;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -770,6 +781,29 @@ namespace MediaBrowser.Controller.Entities
|
|||
return item;
|
||||
}
|
||||
|
||||
private BaseItem RetrieveChild(BaseItem child)
|
||||
{
|
||||
var item = LibraryManager.GetMemoryItemById(child.Id);
|
||||
|
||||
if (item != null)
|
||||
{
|
||||
if (item is IByReferenceItem)
|
||||
{
|
||||
return LibraryManager.GetOrAddByReferenceItem(item);
|
||||
}
|
||||
|
||||
item.Parent = this;
|
||||
}
|
||||
else
|
||||
{
|
||||
child.Parent = this;
|
||||
LibraryManager.RegisterItem(child);
|
||||
item = child;
|
||||
}
|
||||
|
||||
return item;
|
||||
}
|
||||
|
||||
public virtual Task<QueryResult<BaseItem>> GetItems(InternalItemsQuery query)
|
||||
{
|
||||
var user = query.User;
|
||||
|
|
|
@ -11,12 +11,6 @@ namespace MediaBrowser.Controller.Entities
|
|||
{
|
||||
public class MusicVideo : Video, IHasArtist, IHasMusicGenres, IHasProductionLocations, IHasBudget, IHasLookupInfo<MusicVideoInfo>
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets or sets the artist.
|
||||
/// </summary>
|
||||
/// <value>The artist.</value>
|
||||
public string Artist { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the album.
|
||||
/// </summary>
|
||||
|
@ -35,27 +29,12 @@ namespace MediaBrowser.Controller.Entities
|
|||
/// <value>The revenue.</value>
|
||||
public double? Revenue { get; set; }
|
||||
public List<string> ProductionLocations { get; set; }
|
||||
public List<string> Artists { get; set; }
|
||||
|
||||
public MusicVideo()
|
||||
{
|
||||
ProductionLocations = new List<string>();
|
||||
}
|
||||
|
||||
[IgnoreDataMember]
|
||||
public List<string> Artists
|
||||
{
|
||||
get
|
||||
{
|
||||
var list = new List<string>();
|
||||
|
||||
if (!string.IsNullOrEmpty(Artist))
|
||||
{
|
||||
list.Add(Artist);
|
||||
}
|
||||
|
||||
return list;
|
||||
|
||||
}
|
||||
Artists = new List<string>();
|
||||
}
|
||||
|
||||
[IgnoreDataMember]
|
||||
|
@ -63,15 +42,22 @@ namespace MediaBrowser.Controller.Entities
|
|||
{
|
||||
get
|
||||
{
|
||||
var list = new List<string>();
|
||||
return Artists;
|
||||
}
|
||||
}
|
||||
|
||||
if (!string.IsNullOrEmpty(Artist))
|
||||
/// <summary>
|
||||
/// TODO: Remove
|
||||
/// </summary>
|
||||
public string Artist
|
||||
{
|
||||
get { return Artists.FirstOrDefault(); }
|
||||
set
|
||||
{
|
||||
if (!string.IsNullOrEmpty(value) && !Artists.Contains(value, StringComparer.OrdinalIgnoreCase))
|
||||
{
|
||||
list.Add(Artist);
|
||||
Artists.Add(value);
|
||||
}
|
||||
|
||||
return list;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -82,7 +68,7 @@ namespace MediaBrowser.Controller.Entities
|
|||
/// <returns><c>true</c> if the specified name has artist; otherwise, <c>false</c>.</returns>
|
||||
public bool HasArtist(string name)
|
||||
{
|
||||
return string.Equals(Artist, name, StringComparison.OrdinalIgnoreCase);
|
||||
return AllArtists.Contains(name, StringComparer.OrdinalIgnoreCase);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
|
|
@ -104,6 +104,15 @@ namespace MediaBrowser.Controller.Entities.TV
|
|||
}
|
||||
}
|
||||
|
||||
[IgnoreDataMember]
|
||||
public override BaseItem DisplayParent
|
||||
{
|
||||
get
|
||||
{
|
||||
return Season ?? Parent;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the user data key.
|
||||
/// </summary>
|
||||
|
@ -153,7 +162,7 @@ namespace MediaBrowser.Controller.Entities.TV
|
|||
// Episodes directly in series folder
|
||||
if (season == null)
|
||||
{
|
||||
var series = FindParent<Series>();
|
||||
var series = Series;
|
||||
|
||||
if (ParentIndexNumber.HasValue)
|
||||
{
|
||||
|
|
|
@ -44,6 +44,12 @@ namespace MediaBrowser.Controller.Entities.TV
|
|||
}
|
||||
}
|
||||
|
||||
[IgnoreDataMember]
|
||||
public override BaseItem DisplayParent
|
||||
{
|
||||
get { return Series ?? Parent; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// We want to group into our Series
|
||||
/// </summary>
|
||||
|
|
|
@ -17,30 +17,14 @@ namespace MediaBrowser.Controller.Library
|
|||
/// </summary>
|
||||
public interface ILibraryManager
|
||||
{
|
||||
/// <summary>
|
||||
/// Resolves the item.
|
||||
/// </summary>
|
||||
/// <param name="args">The args.</param>
|
||||
/// <returns>BaseItem.</returns>
|
||||
BaseItem ResolveItem(ItemResolveArgs args);
|
||||
|
||||
/// <summary>
|
||||
/// Resolves a path into a BaseItem
|
||||
/// </summary>
|
||||
/// <param name="fileInfo">The file info.</param>
|
||||
/// <param name="directoryService">The directory service.</param>
|
||||
/// <param name="parent">The parent.</param>
|
||||
/// <returns>BaseItem.</returns>
|
||||
/// <exception cref="System.ArgumentNullException"></exception>
|
||||
BaseItem ResolvePath(FileSystemInfo fileInfo, IDirectoryService directoryService, Folder parent = null);
|
||||
|
||||
/// <summary>
|
||||
/// Resolves the path.
|
||||
/// </summary>
|
||||
/// <param name="fileInfo">The file information.</param>
|
||||
/// <param name="parent">The parent.</param>
|
||||
/// <param name="collectionType">Type of the collection.</param>
|
||||
/// <returns>BaseItem.</returns>
|
||||
BaseItem ResolvePath(FileSystemInfo fileInfo, Folder parent = null);
|
||||
BaseItem ResolvePath(FileSystemInfo fileInfo, Folder parent = null, string collectionType = null);
|
||||
|
||||
/// <summary>
|
||||
/// Resolves a set of files into a list of BaseItem
|
||||
|
@ -49,8 +33,9 @@ namespace MediaBrowser.Controller.Library
|
|||
/// <param name="files">The files.</param>
|
||||
/// <param name="directoryService">The directory service.</param>
|
||||
/// <param name="parent">The parent.</param>
|
||||
/// <param name="collectionType">Type of the collection.</param>
|
||||
/// <returns>List{``0}.</returns>
|
||||
List<T> ResolvePaths<T>(IEnumerable<FileSystemInfo> files, IDirectoryService directoryService, Folder parent)
|
||||
List<T> ResolvePaths<T>(IEnumerable<FileSystemInfo> files, IDirectoryService directoryService, Folder parent, string collectionType = null)
|
||||
where T : BaseItem;
|
||||
|
||||
/// <summary>
|
||||
|
@ -151,6 +136,13 @@ namespace MediaBrowser.Controller.Library
|
|||
/// <returns>BaseItem.</returns>
|
||||
BaseItem GetItemById(Guid id);
|
||||
|
||||
/// <summary>
|
||||
/// Gets the memory item by identifier.
|
||||
/// </summary>
|
||||
/// <param name="id">The identifier.</param>
|
||||
/// <returns>BaseItem.</returns>
|
||||
BaseItem GetMemoryItemById(Guid id);
|
||||
|
||||
/// <summary>
|
||||
/// Gets the intros.
|
||||
/// </summary>
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
using MediaBrowser.Controller.Entities;
|
||||
using MediaBrowser.Controller.Providers;
|
||||
using System.Threading;
|
||||
|
||||
namespace MediaBrowser.Controller.Library
|
||||
|
|
|
@ -229,22 +229,6 @@ namespace MediaBrowser.Controller.Library
|
|||
return null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the name of the meta file by.
|
||||
/// </summary>
|
||||
/// <param name="name">The name.</param>
|
||||
/// <returns>FileSystemInfo.</returns>
|
||||
/// <exception cref="System.ArgumentNullException"></exception>
|
||||
public FileSystemInfo GetMetaFileByName(string name)
|
||||
{
|
||||
if (string.IsNullOrEmpty(name))
|
||||
{
|
||||
throw new ArgumentNullException();
|
||||
}
|
||||
|
||||
return GetFileSystemEntryByName(name);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Determines whether [contains meta file by name] [the specified name].
|
||||
/// </summary>
|
||||
|
@ -252,7 +236,12 @@ namespace MediaBrowser.Controller.Library
|
|||
/// <returns><c>true</c> if [contains meta file by name] [the specified name]; otherwise, <c>false</c>.</returns>
|
||||
public bool ContainsMetaFileByName(string name)
|
||||
{
|
||||
return GetMetaFileByName(name) != null;
|
||||
if (string.IsNullOrEmpty(name))
|
||||
{
|
||||
throw new ArgumentNullException();
|
||||
}
|
||||
|
||||
return GetFileSystemEntryByName(name) != null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -265,20 +254,13 @@ namespace MediaBrowser.Controller.Library
|
|||
return GetFileSystemEntryByName(name) != null;
|
||||
}
|
||||
|
||||
private bool _collectionTypeDiscovered;
|
||||
private string _collectionType;
|
||||
|
||||
public string GetCollectionType()
|
||||
{
|
||||
if (!_collectionTypeDiscovered)
|
||||
{
|
||||
_collectionType = Parent == null ? null : _libraryManager.FindCollectionType(Parent);
|
||||
_collectionTypeDiscovered = true;
|
||||
}
|
||||
|
||||
return _collectionType;
|
||||
return CollectionType;
|
||||
}
|
||||
|
||||
public string CollectionType { get; set; }
|
||||
|
||||
#region Equality Overrides
|
||||
|
||||
/// <summary>
|
||||
|
|
|
@ -284,7 +284,7 @@ namespace MediaBrowser.Controller.Library
|
|||
{
|
||||
if (IsSeasonFolder(child.FullName, directoryService, fileSystem))
|
||||
{
|
||||
logger.Debug("{0} is a series because of season folder {1}.", path, child.FullName);
|
||||
//logger.Debug("{0} is a series because of season folder {1}.", path, child.FullName);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
@ -33,7 +33,7 @@ namespace MediaBrowser.Controller.Persistence
|
|||
/// <param name="cancellationToken">The cancellation token.</param>
|
||||
/// <returns>Task.</returns>
|
||||
Task DeleteItem(Guid id, CancellationToken cancellationToken);
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Gets the critic reviews.
|
||||
/// </summary>
|
||||
|
@ -41,6 +41,13 @@ namespace MediaBrowser.Controller.Persistence
|
|||
/// <returns>Task{IEnumerable{ItemReview}}.</returns>
|
||||
IEnumerable<ItemReview> GetCriticReviews(Guid itemId);
|
||||
|
||||
/// <summary>
|
||||
/// Gets the children items.
|
||||
/// </summary>
|
||||
/// <param name="parentId">The parent identifier.</param>
|
||||
/// <returns>IEnumerable<BaseItem>.</returns>
|
||||
IEnumerable<BaseItem> GetChildrenItems(Guid parentId);
|
||||
|
||||
/// <summary>
|
||||
/// Saves the critic reviews.
|
||||
/// </summary>
|
||||
|
@ -101,7 +108,7 @@ namespace MediaBrowser.Controller.Persistence
|
|||
/// <param name="type">The type.</param>
|
||||
/// <returns>IEnumerable{Guid}.</returns>
|
||||
IEnumerable<BaseItem> GetItemsOfType(Type type);
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Saves the children.
|
||||
/// </summary>
|
||||
|
|
|
@ -14,10 +14,6 @@ namespace MediaBrowser.Controller.Providers
|
|||
|
||||
public MetadataRefreshMode MetadataRefreshMode { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// TODO: deprecate. Keeping this for now, for api compatibility
|
||||
/// </summary>
|
||||
[Obsolete]
|
||||
public bool ForceSave { get; set; }
|
||||
|
||||
public MetadataRefreshOptions()
|
||||
|
|
|
@ -246,7 +246,7 @@ namespace MediaBrowser.Controller.Resolvers
|
|||
|
||||
if (config.UseFileCreationTimeForDateAdded)
|
||||
{
|
||||
item.DateModified = fileSystem.GetCreationTimeUtc(info);
|
||||
item.DateCreated = fileSystem.GetCreationTimeUtc(info);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
|
@ -80,6 +80,12 @@ namespace MediaBrowser.Controller.Session
|
|||
/// <value>The last activity date.</value>
|
||||
public DateTime LastActivityDate { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the last playback check in.
|
||||
/// </summary>
|
||||
/// <value>The last playback check in.</value>
|
||||
public DateTime LastPlaybackCheckIn { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the name of the device.
|
||||
/// </summary>
|
||||
|
|
|
@ -1,7 +1,9 @@
|
|||
using MediaBrowser.Common.Extensions;
|
||||
using System.Linq;
|
||||
using MediaBrowser.Common.Extensions;
|
||||
using MediaBrowser.Controller.Configuration;
|
||||
using MediaBrowser.Controller.Drawing;
|
||||
using MediaBrowser.Controller.Entities;
|
||||
using MediaBrowser.Controller.Entities.Movies;
|
||||
using MediaBrowser.Controller.Library;
|
||||
using MediaBrowser.Controller.Localization;
|
||||
using MediaBrowser.Dlna.Didl;
|
||||
|
@ -85,7 +87,9 @@ namespace MediaBrowser.Dlna.ContentDirectory
|
|||
{
|
||||
var id = sparams["ObjectID"];
|
||||
|
||||
var item = GetItemFromObjectId(id, user);
|
||||
var serverItem = GetItemFromObjectId(id, user);
|
||||
|
||||
var item = serverItem.Item;
|
||||
|
||||
var newbookmark = int.Parse(sparams["PosSecond"], _usCulture);
|
||||
|
||||
|
@ -173,49 +177,48 @@ namespace MediaBrowser.Dlna.ContentDirectory
|
|||
//didl.SetAttribute("xmlns:sec", NS_SEC);
|
||||
result.AppendChild(didl);
|
||||
|
||||
var item = GetItemFromObjectId(id, user);
|
||||
var serverItem = GetItemFromObjectId(id, user);
|
||||
var item = serverItem.Item;
|
||||
|
||||
var totalCount = 0;
|
||||
|
||||
if (string.Equals(flag, "BrowseMetadata"))
|
||||
{
|
||||
var folder = item as Folder;
|
||||
|
||||
if (folder == null)
|
||||
if (item.IsFolder || serverItem.StubType.HasValue)
|
||||
{
|
||||
result.DocumentElement.AppendChild(_didlBuilder.GetItemElement(result, item, null, deviceId, filter));
|
||||
var childrenResult = (await GetUserItems(item, serverItem.StubType, user, sortCriteria, start, requested).ConfigureAwait(false));
|
||||
totalCount = childrenResult.TotalRecordCount;
|
||||
|
||||
result.DocumentElement.AppendChild(_didlBuilder.GetFolderElement(result, item, serverItem.StubType, null, totalCount, filter, id));
|
||||
}
|
||||
else
|
||||
{
|
||||
var childrenResult = (await GetUserItems(folder, user, sortCriteria, start, requested).ConfigureAwait(false));
|
||||
totalCount = childrenResult.TotalRecordCount;
|
||||
|
||||
result.DocumentElement.AppendChild(_didlBuilder.GetFolderElement(result, folder, totalCount, filter, id));
|
||||
result.DocumentElement.AppendChild(_didlBuilder.GetItemElement(result, item, null, null, deviceId, filter));
|
||||
}
|
||||
|
||||
provided++;
|
||||
}
|
||||
else
|
||||
{
|
||||
var folder = (Folder)item;
|
||||
|
||||
var childrenResult = (await GetUserItems(folder, user, sortCriteria, start, requested).ConfigureAwait(false));
|
||||
var childrenResult = (await GetUserItems(item, serverItem.StubType, user, sortCriteria, start, requested).ConfigureAwait(false));
|
||||
totalCount = childrenResult.TotalRecordCount;
|
||||
|
||||
provided = childrenResult.Items.Length;
|
||||
|
||||
foreach (var i in childrenResult.Items)
|
||||
{
|
||||
if (i.IsFolder)
|
||||
var displayStubType = GetDisplayStubType(i, serverItem.Item);
|
||||
|
||||
if (i.IsFolder || displayStubType.HasValue)
|
||||
{
|
||||
var f = (Folder)i;
|
||||
var childCount = (await GetUserItems(f, user, sortCriteria, null, 0).ConfigureAwait(false))
|
||||
var childCount = (await GetUserItems(i, displayStubType, user, sortCriteria, null, 0).ConfigureAwait(false))
|
||||
.TotalRecordCount;
|
||||
|
||||
result.DocumentElement.AppendChild(_didlBuilder.GetFolderElement(result, f, childCount, filter));
|
||||
result.DocumentElement.AppendChild(_didlBuilder.GetFolderElement(result, i, displayStubType, item, childCount, filter));
|
||||
}
|
||||
else
|
||||
{
|
||||
result.DocumentElement.AppendChild(_didlBuilder.GetItemElement(result, i, folder, deviceId, filter));
|
||||
result.DocumentElement.AppendChild(_didlBuilder.GetItemElement(result, i, item, serverItem.StubType, deviceId, filter));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -231,6 +234,24 @@ namespace MediaBrowser.Dlna.ContentDirectory
|
|||
};
|
||||
}
|
||||
|
||||
private StubType? GetDisplayStubType(BaseItem item, BaseItem context)
|
||||
{
|
||||
if (context == null || context.IsFolder)
|
||||
{
|
||||
var movie = item as Movie;
|
||||
if (movie != null)
|
||||
{
|
||||
if (movie.LocalTrailerIds.Count > 0 ||
|
||||
movie.SpecialFeatureIds.Count > 0)
|
||||
{
|
||||
return StubType.Folder;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private async Task<IEnumerable<KeyValuePair<string, string>>> HandleSearch(Headers sparams, User user, string deviceId)
|
||||
{
|
||||
var searchCriteria = new SearchCriteria(sparams.GetValueOrDefault("SearchCriteria", ""));
|
||||
|
@ -269,9 +290,11 @@ namespace MediaBrowser.Dlna.ContentDirectory
|
|||
|
||||
result.AppendChild(didl);
|
||||
|
||||
var folder = (Folder)GetItemFromObjectId(sparams["ContainerID"], user);
|
||||
var serverItem = GetItemFromObjectId(sparams["ContainerID"], user);
|
||||
|
||||
var childrenResult = (await GetChildrenSorted(folder, user, searchCriteria, sortCriteria, start, requested).ConfigureAwait(false));
|
||||
var item = serverItem.Item;
|
||||
|
||||
var childrenResult = (await GetChildrenSorted(item, user, searchCriteria, sortCriteria, start, requested).ConfigureAwait(false));
|
||||
|
||||
var totalCount = childrenResult.TotalRecordCount;
|
||||
|
||||
|
@ -281,15 +304,14 @@ namespace MediaBrowser.Dlna.ContentDirectory
|
|||
{
|
||||
if (i.IsFolder)
|
||||
{
|
||||
var f = (Folder)i;
|
||||
var childCount = (await GetChildrenSorted(f, user, searchCriteria, sortCriteria, null, 0).ConfigureAwait(false))
|
||||
var childCount = (await GetChildrenSorted(i, user, searchCriteria, sortCriteria, null, 0).ConfigureAwait(false))
|
||||
.TotalRecordCount;
|
||||
|
||||
result.DocumentElement.AppendChild(_didlBuilder.GetFolderElement(result, f, childCount, filter));
|
||||
result.DocumentElement.AppendChild(_didlBuilder.GetFolderElement(result, i, null, item, childCount, filter));
|
||||
}
|
||||
else
|
||||
{
|
||||
result.DocumentElement.AppendChild(_didlBuilder.GetItemElement(result, i, folder, deviceId, filter));
|
||||
result.DocumentElement.AppendChild(_didlBuilder.GetItemElement(result, i, item, serverItem.StubType, deviceId, filter));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -304,8 +326,10 @@ namespace MediaBrowser.Dlna.ContentDirectory
|
|||
};
|
||||
}
|
||||
|
||||
private async Task<QueryResult<BaseItem>> GetChildrenSorted(Folder folder, User user, SearchCriteria search, SortCriteria sort, int? startIndex, int? limit)
|
||||
private async Task<QueryResult<BaseItem>> GetChildrenSorted(BaseItem item, User user, SearchCriteria search, SortCriteria sort, int? startIndex, int? limit)
|
||||
{
|
||||
var folder = (Folder)item;
|
||||
|
||||
var sortOrders = new List<string>();
|
||||
if (!folder.IsPreSorted)
|
||||
{
|
||||
|
@ -340,7 +364,7 @@ namespace MediaBrowser.Dlna.ContentDirectory
|
|||
//items = items.OfType<MusicAlbum>();
|
||||
isFolder = true;
|
||||
}
|
||||
|
||||
|
||||
return await folder.GetItems(new InternalItemsQuery
|
||||
{
|
||||
Limit = limit,
|
||||
|
@ -356,8 +380,20 @@ namespace MediaBrowser.Dlna.ContentDirectory
|
|||
}).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
private async Task<QueryResult<BaseItem>> GetUserItems(Folder folder, User user, SortCriteria sort, int? startIndex, int? limit)
|
||||
private async Task<QueryResult<BaseItem>> GetUserItems(BaseItem item, StubType? stubType, User user, SortCriteria sort, int? startIndex, int? limit)
|
||||
{
|
||||
if (stubType.HasValue)
|
||||
{
|
||||
var movie = item as Movie;
|
||||
|
||||
if (movie != null)
|
||||
{
|
||||
return await GetMovieItems(movie).ConfigureAwait(false);
|
||||
}
|
||||
}
|
||||
|
||||
var folder = (Folder)item;
|
||||
|
||||
var sortOrders = new List<string>();
|
||||
if (!folder.IsPreSorted)
|
||||
{
|
||||
|
@ -376,6 +412,23 @@ namespace MediaBrowser.Dlna.ContentDirectory
|
|||
}).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
private Task<QueryResult<BaseItem>> GetMovieItems(Movie item)
|
||||
{
|
||||
var list = new List<BaseItem>();
|
||||
|
||||
list.Add(item);
|
||||
|
||||
list.AddRange(item.LocalTrailerIds.Select(i => _libraryManager.GetItemById(i)).Where(i => i != null));
|
||||
list.AddRange(item.SpecialFeatureIds.Select(i => _libraryManager.GetItemById(i)).Where(i => i != null));
|
||||
list.AddRange(item.ThemeVideoIds.Select(i => _libraryManager.GetItemById(i)).Where(i => i != null));
|
||||
|
||||
return Task.FromResult(new QueryResult<BaseItem>
|
||||
{
|
||||
Items = list.ToArray(),
|
||||
TotalRecordCount = list.Count
|
||||
});
|
||||
}
|
||||
|
||||
private bool FilterUnsupportedContent(BaseItem i, User user)
|
||||
{
|
||||
// Unplayable
|
||||
|
@ -399,26 +452,50 @@ namespace MediaBrowser.Dlna.ContentDirectory
|
|||
return true;
|
||||
}
|
||||
|
||||
private BaseItem GetItemFromObjectId(string id, User user)
|
||||
private ServerItem GetItemFromObjectId(string id, User user)
|
||||
{
|
||||
return DidlBuilder.IsIdRoot(id)
|
||||
|
||||
? user.RootFolder
|
||||
? new ServerItem { Item = user.RootFolder }
|
||||
: ParseItemId(id, user);
|
||||
}
|
||||
|
||||
private BaseItem ParseItemId(string id, User user)
|
||||
private ServerItem ParseItemId(string id, User user)
|
||||
{
|
||||
Guid itemId;
|
||||
StubType? stubType = null;
|
||||
|
||||
if (id.StartsWith("folder_", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
stubType = StubType.Folder;
|
||||
id = id.Split(new[] { '_' }, 2)[1];
|
||||
}
|
||||
|
||||
if (Guid.TryParse(id, out itemId))
|
||||
{
|
||||
return _libraryManager.GetItemById(itemId);
|
||||
var item = _libraryManager.GetItemById(itemId);
|
||||
|
||||
return new ServerItem
|
||||
{
|
||||
Item = item,
|
||||
StubType = stubType
|
||||
};
|
||||
}
|
||||
|
||||
Logger.Error("Error parsing item Id: {0}. Returning user root folder.", id);
|
||||
|
||||
return user.RootFolder;
|
||||
return new ServerItem { Item = user.RootFolder };
|
||||
}
|
||||
}
|
||||
|
||||
internal class ServerItem
|
||||
{
|
||||
public BaseItem Item { get; set; }
|
||||
public StubType? StubType { get; set; }
|
||||
}
|
||||
|
||||
public enum StubType
|
||||
{
|
||||
Folder = 0
|
||||
}
|
||||
}
|
||||
|
|
|
@ -9,6 +9,7 @@ using MediaBrowser.Controller.Entities.TV;
|
|||
using MediaBrowser.Controller.Library;
|
||||
using MediaBrowser.Controller.Localization;
|
||||
using MediaBrowser.Controller.Playlists;
|
||||
using MediaBrowser.Dlna.ContentDirectory;
|
||||
using MediaBrowser.Model.Dlna;
|
||||
using MediaBrowser.Model.Drawing;
|
||||
using MediaBrowser.Model.Entities;
|
||||
|
@ -63,25 +64,35 @@ namespace MediaBrowser.Dlna.Didl
|
|||
|
||||
result.AppendChild(didl);
|
||||
|
||||
result.DocumentElement.AppendChild(GetItemElement(result, item, context, deviceId, filter, streamInfo));
|
||||
result.DocumentElement.AppendChild(GetItemElement(result, item, context, null, deviceId, filter, streamInfo));
|
||||
|
||||
return result.DocumentElement.OuterXml;
|
||||
}
|
||||
|
||||
public XmlElement GetItemElement(XmlDocument doc, BaseItem item, BaseItem context, string deviceId, Filter filter, StreamInfo streamInfo = null)
|
||||
public XmlElement GetItemElement(XmlDocument doc, BaseItem item, BaseItem context, StubType? contextStubType, string deviceId, Filter filter, StreamInfo streamInfo = null)
|
||||
{
|
||||
var clientId = GetClientId(item, null);
|
||||
|
||||
var element = doc.CreateElement(string.Empty, "item", NS_DIDL);
|
||||
element.SetAttribute("restricted", "1");
|
||||
element.SetAttribute("id", item.Id.ToString("N"));
|
||||
element.SetAttribute("id", clientId);
|
||||
|
||||
if (item.Parent != null)
|
||||
if (context != null)
|
||||
{
|
||||
element.SetAttribute("parentID", item.Parent.Id.ToString("N"));
|
||||
element.SetAttribute("parentID", GetClientId(context, contextStubType));
|
||||
}
|
||||
else
|
||||
{
|
||||
var parent = item.DisplayParent;
|
||||
if (parent != null)
|
||||
{
|
||||
element.SetAttribute("parentID", GetClientId(parent, null));
|
||||
}
|
||||
}
|
||||
|
||||
//AddBookmarkInfo(item, user, element);
|
||||
|
||||
AddGeneralProperties(item, context, element, filter);
|
||||
AddGeneralProperties(item, null, context, element, filter);
|
||||
|
||||
// refID?
|
||||
// storeAttribute(itemNode, object, ClassProperties.REF_ID, false);
|
||||
|
@ -111,14 +122,14 @@ namespace MediaBrowser.Dlna.Didl
|
|||
{
|
||||
var sources = _user == null ? video.GetMediaSources(true).ToList() : video.GetMediaSources(true, _user).ToList();
|
||||
|
||||
streamInfo = new StreamBuilder().BuildVideoItem(new VideoOptions
|
||||
{
|
||||
ItemId = video.Id.ToString("N"),
|
||||
MediaSources = sources,
|
||||
Profile = _profile,
|
||||
DeviceId = deviceId,
|
||||
MaxBitrate = _profile.MaxStreamingBitrate
|
||||
});
|
||||
streamInfo = new StreamBuilder().BuildVideoItem(new VideoOptions
|
||||
{
|
||||
ItemId = GetClientId(video),
|
||||
MediaSources = sources,
|
||||
Profile = _profile,
|
||||
DeviceId = deviceId,
|
||||
MaxBitrate = _profile.MaxStreamingBitrate
|
||||
});
|
||||
}
|
||||
|
||||
var targetWidth = streamInfo.TargetWidth;
|
||||
|
@ -142,6 +153,7 @@ namespace MediaBrowser.Dlna.Didl
|
|||
streamInfo.TargetPacketLength,
|
||||
streamInfo.TranscodeSeekInfo,
|
||||
streamInfo.IsTargetAnamorphic,
|
||||
streamInfo.IsTargetCabac,
|
||||
streamInfo.TargetRefFrames);
|
||||
|
||||
foreach (var contentFeature in contentFeatureList)
|
||||
|
@ -263,6 +275,7 @@ namespace MediaBrowser.Dlna.Didl
|
|||
streamInfo.TargetPacketLength,
|
||||
streamInfo.TargetTimestamp,
|
||||
streamInfo.IsTargetAnamorphic,
|
||||
streamInfo.IsTargetCabac,
|
||||
streamInfo.TargetRefFrames);
|
||||
|
||||
var filename = url.Substring(0, url.IndexOf('?'));
|
||||
|
@ -311,7 +324,7 @@ namespace MediaBrowser.Dlna.Didl
|
|||
|
||||
return item.Name;
|
||||
}
|
||||
|
||||
|
||||
private void AddAudioResource(XmlElement container, IHasMediaSources audio, string deviceId, Filter filter, StreamInfo streamInfo = null)
|
||||
{
|
||||
var res = container.OwnerDocument.CreateElement(string.Empty, "res", NS_DIDL);
|
||||
|
@ -322,7 +335,7 @@ namespace MediaBrowser.Dlna.Didl
|
|||
|
||||
streamInfo = new StreamBuilder().BuildAudioItem(new AudioOptions
|
||||
{
|
||||
ItemId = audio.Id.ToString("N"),
|
||||
ItemId = GetClientId(audio),
|
||||
MediaSources = sources,
|
||||
Profile = _profile,
|
||||
DeviceId = deviceId
|
||||
|
@ -403,8 +416,8 @@ namespace MediaBrowser.Dlna.Didl
|
|||
|
||||
public static bool IsIdRoot(string id)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(id) ||
|
||||
|
||||
if (string.IsNullOrWhiteSpace(id) ||
|
||||
|
||||
string.Equals(id, "0", StringComparison.OrdinalIgnoreCase)
|
||||
|
||||
// Samsung sometimes uses 1 as root
|
||||
|
@ -416,13 +429,15 @@ namespace MediaBrowser.Dlna.Didl
|
|||
return false;
|
||||
}
|
||||
|
||||
public XmlElement GetFolderElement(XmlDocument doc, BaseItem folder, int childCount, Filter filter, string requestedId = null)
|
||||
public XmlElement GetFolderElement(XmlDocument doc, BaseItem folder, StubType? stubType, BaseItem context, int childCount, Filter filter, string requestedId = null)
|
||||
{
|
||||
var container = doc.CreateElement(string.Empty, "container", NS_DIDL);
|
||||
container.SetAttribute("restricted", "0");
|
||||
container.SetAttribute("searchable", "1");
|
||||
container.SetAttribute("childCount", childCount.ToString(_usCulture));
|
||||
|
||||
var clientId = GetClientId(folder, stubType);
|
||||
|
||||
if (string.Equals(requestedId, "0"))
|
||||
{
|
||||
container.SetAttribute("id", "0");
|
||||
|
@ -430,20 +445,20 @@ namespace MediaBrowser.Dlna.Didl
|
|||
}
|
||||
else
|
||||
{
|
||||
container.SetAttribute("id", folder.Id.ToString("N"));
|
||||
container.SetAttribute("id", clientId);
|
||||
|
||||
var parent = folder.Parent;
|
||||
var parent = context ?? folder.DisplayParent;
|
||||
if (parent == null)
|
||||
{
|
||||
container.SetAttribute("parentID", "0");
|
||||
}
|
||||
else
|
||||
{
|
||||
container.SetAttribute("parentID", parent.Id.ToString("N"));
|
||||
container.SetAttribute("parentID", GetClientId(parent, null));
|
||||
}
|
||||
}
|
||||
|
||||
AddCommonFields(folder, null, container, filter);
|
||||
AddCommonFields(folder, stubType, null, container, filter);
|
||||
|
||||
AddCover(folder, container);
|
||||
|
||||
|
@ -466,10 +481,11 @@ namespace MediaBrowser.Dlna.Didl
|
|||
/// Adds fields used by both items and folders
|
||||
/// </summary>
|
||||
/// <param name="item">The item.</param>
|
||||
/// <param name="itemStubType">Type of the item stub.</param>
|
||||
/// <param name="context">The context.</param>
|
||||
/// <param name="element">The element.</param>
|
||||
/// <param name="filter">The filter.</param>
|
||||
private void AddCommonFields(BaseItem item, BaseItem context, XmlElement element, Filter filter)
|
||||
private void AddCommonFields(BaseItem item, StubType? itemStubType, BaseItem context, XmlElement element, Filter filter)
|
||||
{
|
||||
// Don't filter on dc:title because not all devices will include it in the filter
|
||||
// MediaMonkey for example won't display content without a title
|
||||
|
@ -478,7 +494,7 @@ namespace MediaBrowser.Dlna.Didl
|
|||
AddValue(element, "dc", "title", GetDisplayName(item, context), NS_DC);
|
||||
}
|
||||
|
||||
element.AppendChild(CreateObjectClass(element.OwnerDocument, item));
|
||||
element.AppendChild(CreateObjectClass(element.OwnerDocument, item, itemStubType));
|
||||
|
||||
if (filter.Contains("dc:date"))
|
||||
{
|
||||
|
@ -539,14 +555,14 @@ namespace MediaBrowser.Dlna.Didl
|
|||
AddPeople(item, element);
|
||||
}
|
||||
|
||||
private XmlElement CreateObjectClass(XmlDocument result, BaseItem item)
|
||||
private XmlElement CreateObjectClass(XmlDocument result, BaseItem item, StubType? stubType)
|
||||
{
|
||||
// More types here
|
||||
// http://oss.linn.co.uk/repos/Public/LibUpnpCil/DidlLite/UpnpAv/Test/TestDidlLite.cs
|
||||
|
||||
var objectClass = result.CreateElement("upnp", "class", NS_UPNP);
|
||||
|
||||
if (item.IsFolder)
|
||||
if (item.IsFolder || stubType.HasValue)
|
||||
{
|
||||
string classType = null;
|
||||
|
||||
|
@ -560,7 +576,7 @@ namespace MediaBrowser.Dlna.Didl
|
|||
{
|
||||
classType = "object.container.person.musicArtist";
|
||||
}
|
||||
else if (item is Series || item is Season || item is BoxSet)
|
||||
else if (item is Series || item is Season || item is BoxSet || item is Video)
|
||||
{
|
||||
classType = "object.container.album.videoAlbum";
|
||||
}
|
||||
|
@ -628,9 +644,9 @@ namespace MediaBrowser.Dlna.Didl
|
|||
}
|
||||
}
|
||||
|
||||
private void AddGeneralProperties(BaseItem item, BaseItem context, XmlElement element, Filter filter)
|
||||
private void AddGeneralProperties(BaseItem item, StubType? itemStubType, BaseItem context, XmlElement element, Filter filter)
|
||||
{
|
||||
AddCommonFields(item, context, element, filter);
|
||||
AddCommonFields(item, itemStubType, context, element, filter);
|
||||
|
||||
var audio = item as Audio;
|
||||
|
||||
|
@ -671,10 +687,10 @@ namespace MediaBrowser.Dlna.Didl
|
|||
|
||||
if (musicVideo != null)
|
||||
{
|
||||
if (!string.IsNullOrEmpty(musicVideo.Artist))
|
||||
foreach (var artist in musicVideo.Artists)
|
||||
{
|
||||
AddValue(element, "upnp", "artist", musicVideo.Artist, NS_UPNP);
|
||||
AddAlbumArtist(element, musicVideo.Artist);
|
||||
AddValue(element, "upnp", "artist", artist, NS_UPNP);
|
||||
AddAlbumArtist(element, artist);
|
||||
}
|
||||
|
||||
if (!string.IsNullOrEmpty(musicVideo.Album))
|
||||
|
@ -773,20 +789,26 @@ namespace MediaBrowser.Dlna.Didl
|
|||
}
|
||||
}
|
||||
|
||||
AddImageResElement(item, element, 4096, 4096, playbackPercentage, "jpg", "JPEG_LRG");
|
||||
AddImageResElement(item, element, 4096, 4096, playbackPercentage, "png", "PNG_LRG");
|
||||
AddImageResElement(item, element, 1024, 768, playbackPercentage, "jpg", "JPEG_MED");
|
||||
AddImageResElement(item, element, 640, 480, playbackPercentage, "jpg", "JPEG_SM");
|
||||
var imageLimit = _profile.DidlAlbumArtLimit ?? 100;
|
||||
|
||||
AddImageResElement(item, element, 160, 160, playbackPercentage, "jpg", "JPEG_TN");
|
||||
AddImageResElement(item, element, 160, 160, playbackPercentage, "png", "PNG_TN");
|
||||
|
||||
if (imageLimit > 1)
|
||||
{
|
||||
AddImageResElement(item, element, 4096, 4096, playbackPercentage, "jpg", "JPEG_LRG");
|
||||
AddImageResElement(item, element, 1024, 768, playbackPercentage, "jpg", "JPEG_MED");
|
||||
AddImageResElement(item, element, 640, 480, playbackPercentage, "jpg", "JPEG_SM");
|
||||
AddImageResElement(item, element, 4096, 4096, playbackPercentage, "png", "PNG_LRG");
|
||||
AddImageResElement(item, element, 160, 160, playbackPercentage, "png", "PNG_TN");
|
||||
}
|
||||
}
|
||||
|
||||
private void AddImageResElement(BaseItem item,
|
||||
XmlElement element,
|
||||
int maxWidth,
|
||||
int maxHeight,
|
||||
private void AddImageResElement(BaseItem item,
|
||||
XmlElement element,
|
||||
int maxWidth,
|
||||
int maxHeight,
|
||||
int playbackPercentage,
|
||||
string format,
|
||||
string format,
|
||||
string org_Pn)
|
||||
{
|
||||
var imageInfo = GetImageInfo(item);
|
||||
|
@ -920,6 +942,25 @@ namespace MediaBrowser.Dlna.Didl
|
|||
internal int? Height;
|
||||
}
|
||||
|
||||
public static string GetClientId(BaseItem item, StubType? stubType)
|
||||
{
|
||||
var id = item.Id.ToString("N");
|
||||
|
||||
if (stubType.HasValue)
|
||||
{
|
||||
id = stubType.Value.ToString().ToLower() + "_" + id;
|
||||
}
|
||||
|
||||
return id;
|
||||
}
|
||||
|
||||
public static string GetClientId(IHasMediaSources item)
|
||||
{
|
||||
var id = item.Id.ToString("N");
|
||||
|
||||
return id;
|
||||
}
|
||||
|
||||
private ImageUrlInfo GetImageUrl(ImageDownloadInfo info, int maxWidth, int maxHeight, int playbackPercentage, string format)
|
||||
{
|
||||
var url = string.Format("{0}/Items/{1}/Images/{2}/0/{3}/{4}/{5}/{6}/{7}",
|
||||
|
|
|
@ -3,6 +3,7 @@ using MediaBrowser.Common.Extensions;
|
|||
using MediaBrowser.Common.IO;
|
||||
using MediaBrowser.Controller.Dlna;
|
||||
using MediaBrowser.Controller.Drawing;
|
||||
using MediaBrowser.Controller.Plugins;
|
||||
using MediaBrowser.Dlna.Profiles;
|
||||
using MediaBrowser.Dlna.Server;
|
||||
using MediaBrowser.Model.Dlna;
|
||||
|
@ -37,8 +38,6 @@ namespace MediaBrowser.Dlna
|
|||
_appPaths = appPaths;
|
||||
_logger = logger;
|
||||
_jsonSerializer = jsonSerializer;
|
||||
|
||||
//DumpProfiles();
|
||||
}
|
||||
|
||||
public IEnumerable<DeviceProfile> GetProfiles()
|
||||
|
@ -55,44 +54,6 @@ namespace MediaBrowser.Dlna
|
|||
return list;
|
||||
}
|
||||
|
||||
private void DumpProfiles()
|
||||
{
|
||||
var list = new List<DeviceProfile>
|
||||
{
|
||||
new SamsungSmartTvProfile(),
|
||||
new Xbox360Profile(),
|
||||
new XboxOneProfile(),
|
||||
new SonyPs3Profile(),
|
||||
new SonyBravia2010Profile(),
|
||||
new SonyBravia2011Profile(),
|
||||
new SonyBravia2012Profile(),
|
||||
new SonyBravia2013Profile(),
|
||||
new SonyBlurayPlayer2013Profile(),
|
||||
new SonyBlurayPlayerProfile(),
|
||||
new PanasonicVieraProfile(),
|
||||
new WdtvLiveProfile(),
|
||||
new DenonAvrProfile(),
|
||||
new LinksysDMA2100Profile(),
|
||||
new LgTvProfile(),
|
||||
new Foobar2000Profile(),
|
||||
new MediaMonkeyProfile(),
|
||||
new Windows81Profile(),
|
||||
//new WindowsMediaCenterProfile(),
|
||||
new WindowsPhoneProfile(),
|
||||
new AndroidProfile(true, true, new[]{"baseline", "constrained baseline"}),
|
||||
new DirectTvProfile(),
|
||||
new DishHopperJoeyProfile(),
|
||||
new DefaultProfile()
|
||||
};
|
||||
|
||||
foreach (var item in list)
|
||||
{
|
||||
var path = Path.Combine(_appPaths.ProgramDataPath, _fileSystem.GetValidFilename(item.Name) + ".xml");
|
||||
|
||||
_xmlSerializer.SerializeToFile(item, path);
|
||||
}
|
||||
}
|
||||
|
||||
private bool _extracted;
|
||||
private readonly object _syncLock = new object();
|
||||
private void ExtractProfilesIfNeeded()
|
||||
|
@ -521,4 +482,66 @@ namespace MediaBrowser.Dlna
|
|||
};
|
||||
}
|
||||
}
|
||||
|
||||
class DlnaProfileEntryPoint : IServerEntryPoint
|
||||
{
|
||||
private readonly IApplicationPaths _appPaths;
|
||||
private readonly IXmlSerializer _xmlSerializer;
|
||||
private readonly IFileSystem _fileSystem;
|
||||
|
||||
public DlnaProfileEntryPoint(IApplicationPaths appPaths, IXmlSerializer xmlSerializer, IFileSystem fileSystem)
|
||||
{
|
||||
_appPaths = appPaths;
|
||||
_xmlSerializer = xmlSerializer;
|
||||
_fileSystem = fileSystem;
|
||||
}
|
||||
|
||||
public void Run()
|
||||
{
|
||||
//DumpProfiles();
|
||||
}
|
||||
|
||||
private void DumpProfiles()
|
||||
{
|
||||
var list = new List<DeviceProfile>
|
||||
{
|
||||
new SamsungSmartTvProfile(),
|
||||
new Xbox360Profile(),
|
||||
new XboxOneProfile(),
|
||||
new SonyPs3Profile(),
|
||||
new SonyBravia2010Profile(),
|
||||
new SonyBravia2011Profile(),
|
||||
new SonyBravia2012Profile(),
|
||||
new SonyBravia2013Profile(),
|
||||
new SonyBlurayPlayer2013Profile(),
|
||||
new SonyBlurayPlayerProfile(),
|
||||
new PanasonicVieraProfile(),
|
||||
new WdtvLiveProfile(),
|
||||
new DenonAvrProfile(),
|
||||
new LinksysDMA2100Profile(),
|
||||
new LgTvProfile(),
|
||||
new Foobar2000Profile(),
|
||||
new MediaMonkeyProfile(),
|
||||
new Windows81Profile(),
|
||||
//new WindowsMediaCenterProfile(),
|
||||
new WindowsPhoneProfile(),
|
||||
new AndroidProfile(),
|
||||
new DirectTvProfile(),
|
||||
new DishHopperJoeyProfile(),
|
||||
new DefaultProfile(),
|
||||
new PopcornHourProfile()
|
||||
};
|
||||
|
||||
foreach (var item in list)
|
||||
{
|
||||
var path = Path.Combine(_appPaths.ProgramDataPath, _fileSystem.GetValidFilename(item.Name) + ".xml");
|
||||
|
||||
_xmlSerializer.SerializeToFile(item, path);
|
||||
}
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
|
@ -75,6 +75,7 @@
|
|||
<Compile Include="PlayTo\PlayToController.cs" />
|
||||
<Compile Include="Profiles\DirectTvProfile.cs" />
|
||||
<Compile Include="Profiles\DishHopperJoeyProfile.cs" />
|
||||
<Compile Include="Profiles\PopcornHourProfile.cs" />
|
||||
<Compile Include="Ssdp\DeviceDiscoveryInfo.cs" />
|
||||
<Compile Include="Ssdp\Extensions.cs" />
|
||||
<Compile Include="PlayTo\PlaybackProgressEventArgs.cs" />
|
||||
|
@ -194,6 +195,9 @@
|
|||
<ItemGroup>
|
||||
<EmbeddedResource Include="Profiles\Xml\Dish Hopper-Joey.xml" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<EmbeddedResource Include="Profiles\Xml\Popcorn Hour.xml" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
||||
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
|
||||
Other similar extension points exist, see Microsoft.Common.targets.
|
||||
|
|
|
@ -139,16 +139,21 @@ namespace MediaBrowser.Dlna.PlayTo
|
|||
try
|
||||
{
|
||||
var streamInfo = StreamParams.ParseFromUrl(e.OldMediaInfo.Url, _libraryManager);
|
||||
var progress = GetProgressInfo(e.OldMediaInfo, streamInfo);
|
||||
if (streamInfo.Item != null)
|
||||
{
|
||||
var progress = GetProgressInfo(e.OldMediaInfo, streamInfo);
|
||||
|
||||
var positionTicks = progress.PositionTicks;
|
||||
var positionTicks = progress.PositionTicks;
|
||||
|
||||
ReportPlaybackStopped(e.OldMediaInfo, streamInfo, positionTicks);
|
||||
ReportPlaybackStopped(e.OldMediaInfo, streamInfo, positionTicks);
|
||||
}
|
||||
|
||||
streamInfo = StreamParams.ParseFromUrl(e.NewMediaInfo.Url, _libraryManager);
|
||||
progress = GetProgressInfo(e.NewMediaInfo, streamInfo);
|
||||
if (streamInfo.Item == null) return;
|
||||
|
||||
var newItemProgress = GetProgressInfo(e.NewMediaInfo, streamInfo);
|
||||
|
||||
await _sessionManager.OnPlaybackStart(progress).ConfigureAwait(false);
|
||||
await _sessionManager.OnPlaybackStart(newItemProgress).ConfigureAwait(false);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
|
@ -161,6 +166,9 @@ namespace MediaBrowser.Dlna.PlayTo
|
|||
try
|
||||
{
|
||||
var streamInfo = StreamParams.ParseFromUrl(e.MediaInfo.Url, _libraryManager);
|
||||
|
||||
if (streamInfo.Item == null) return;
|
||||
|
||||
var progress = GetProgressInfo(e.MediaInfo, streamInfo);
|
||||
|
||||
var positionTicks = progress.PositionTicks;
|
||||
|
@ -219,9 +227,14 @@ namespace MediaBrowser.Dlna.PlayTo
|
|||
{
|
||||
try
|
||||
{
|
||||
var info = GetProgressInfo(e.MediaInfo);
|
||||
var info = StreamParams.ParseFromUrl(e.MediaInfo.Url, _libraryManager);
|
||||
|
||||
await _sessionManager.OnPlaybackStart(info).ConfigureAwait(false);
|
||||
if (info.Item != null)
|
||||
{
|
||||
var progress = GetProgressInfo(e.MediaInfo, info);
|
||||
|
||||
await _sessionManager.OnPlaybackStart(progress).ConfigureAwait(false);
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
|
@ -233,9 +246,14 @@ namespace MediaBrowser.Dlna.PlayTo
|
|||
{
|
||||
try
|
||||
{
|
||||
var info = GetProgressInfo(e.MediaInfo);
|
||||
var info = StreamParams.ParseFromUrl(e.MediaInfo.Url, _libraryManager);
|
||||
|
||||
await _sessionManager.OnPlaybackProgress(info).ConfigureAwait(false);
|
||||
if (info.Item != null)
|
||||
{
|
||||
var progress = GetProgressInfo(e.MediaInfo, info);
|
||||
|
||||
await _sessionManager.OnPlaybackProgress(progress).ConfigureAwait(false);
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
|
@ -243,13 +261,6 @@ namespace MediaBrowser.Dlna.PlayTo
|
|||
}
|
||||
}
|
||||
|
||||
private PlaybackStartInfo GetProgressInfo(uBaseObject mediaInfo)
|
||||
{
|
||||
var info = StreamParams.ParseFromUrl(mediaInfo.Url, _libraryManager);
|
||||
|
||||
return GetProgressInfo(mediaInfo, info);
|
||||
}
|
||||
|
||||
private PlaybackStartInfo GetProgressInfo(uBaseObject mediaInfo, StreamParams info)
|
||||
{
|
||||
var ticks = _device.Position.Ticks;
|
||||
|
@ -441,19 +452,9 @@ namespace MediaBrowser.Dlna.PlayTo
|
|||
private void AddItemFromId(Guid id, List<BaseItem> list)
|
||||
{
|
||||
var item = _libraryManager.GetItemById(id);
|
||||
if (item.IsFolder)
|
||||
if (item.MediaType == MediaType.Audio || item.MediaType == MediaType.Video)
|
||||
{
|
||||
foreach (var childId in _itemRepository.GetChildren(item.Id))
|
||||
{
|
||||
AddItemFromId(childId, list);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (item.MediaType == MediaType.Audio || item.MediaType == MediaType.Video)
|
||||
{
|
||||
list.Add(item);
|
||||
}
|
||||
list.Add(item);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -526,6 +527,7 @@ namespace MediaBrowser.Dlna.PlayTo
|
|||
streamInfo.TargetPacketLength,
|
||||
streamInfo.TranscodeSeekInfo,
|
||||
streamInfo.IsTargetAnamorphic,
|
||||
streamInfo.IsTargetCabac,
|
||||
streamInfo.TargetRefFrames);
|
||||
|
||||
return list.FirstOrDefault();
|
||||
|
@ -736,10 +738,10 @@ namespace MediaBrowser.Dlna.PlayTo
|
|||
if (media != null)
|
||||
{
|
||||
var info = StreamParams.ParseFromUrl(media.Url, _libraryManager);
|
||||
var progress = GetProgressInfo(media, info);
|
||||
|
||||
if (info.Item != null)
|
||||
{
|
||||
var progress = GetProgressInfo(media, info);
|
||||
var newPosition = progress.PositionTicks ?? 0;
|
||||
|
||||
var user = _session.UserId.HasValue ? _userManager.GetUserById(_session.UserId.Value) : null;
|
||||
|
@ -762,10 +764,10 @@ namespace MediaBrowser.Dlna.PlayTo
|
|||
if (media != null)
|
||||
{
|
||||
var info = StreamParams.ParseFromUrl(media.Url, _libraryManager);
|
||||
var progress = GetProgressInfo(media, info);
|
||||
|
||||
if (info.Item != null)
|
||||
{
|
||||
var progress = GetProgressInfo(media, info);
|
||||
var newPosition = progress.PositionTicks ?? 0;
|
||||
|
||||
var user = _session.UserId.HasValue ? _userManager.GetUserById(_session.UserId.Value) : null;
|
||||
|
@ -829,7 +831,9 @@ namespace MediaBrowser.Dlna.PlayTo
|
|||
ItemId = GetItemId(url)
|
||||
};
|
||||
|
||||
if (string.IsNullOrWhiteSpace(request.ItemId))
|
||||
Guid parsedId;
|
||||
|
||||
if (string.IsNullOrWhiteSpace(request.ItemId) || !Guid.TryParse(request.ItemId, out parsedId))
|
||||
{
|
||||
return request;
|
||||
}
|
||||
|
@ -882,7 +886,7 @@ namespace MediaBrowser.Dlna.PlayTo
|
|||
|
||||
request.Item = string.IsNullOrWhiteSpace(request.ItemId)
|
||||
? null
|
||||
: libraryManager.GetItemById(new Guid(request.ItemId));
|
||||
: libraryManager.GetItemById(parsedId);
|
||||
|
||||
var hasMediaSources = request.Item as IHasMediaSources;
|
||||
|
||||
|
|
|
@ -202,6 +202,17 @@ namespace MediaBrowser.Dlna.Profiles
|
|||
Method = SubtitleDeliveryMethod.External
|
||||
}
|
||||
};
|
||||
|
||||
ResponseProfiles = new[]
|
||||
{
|
||||
new ResponseProfile
|
||||
{
|
||||
Type = DlnaProfileType.Video,
|
||||
Container = "ts",
|
||||
OrgPn = "MPEG_TS_SD_EU,MPEG_TS_SD_NA,MPEG_TS_SD_KO",
|
||||
MimeType = "video/vnd.dlna.mpeg-tts"
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
178
MediaBrowser.Dlna/Profiles/PopcornHourProfile.cs
Normal file
178
MediaBrowser.Dlna/Profiles/PopcornHourProfile.cs
Normal file
|
@ -0,0 +1,178 @@
|
|||
using MediaBrowser.Model.Dlna;
|
||||
using MediaBrowser.Model.Dlna.Profiles;
|
||||
using System.Xml.Serialization;
|
||||
|
||||
namespace MediaBrowser.Dlna.Profiles
|
||||
{
|
||||
[XmlRoot("Profile")]
|
||||
public class PopcornHourProfile : DefaultProfile
|
||||
{
|
||||
public PopcornHourProfile()
|
||||
{
|
||||
Name = "Popcorn Hour";
|
||||
|
||||
TranscodingProfiles = new[]
|
||||
{
|
||||
new TranscodingProfile
|
||||
{
|
||||
Container = "mp3",
|
||||
AudioCodec = "mp3",
|
||||
Type = DlnaProfileType.Audio
|
||||
},
|
||||
|
||||
new TranscodingProfile
|
||||
{
|
||||
Container = "mp4",
|
||||
Type = DlnaProfileType.Video,
|
||||
AudioCodec = "aac",
|
||||
VideoCodec = "h264",
|
||||
VideoProfile= "baseline"
|
||||
},
|
||||
|
||||
new TranscodingProfile
|
||||
{
|
||||
Container = "jpeg",
|
||||
Type = DlnaProfileType.Photo
|
||||
}
|
||||
};
|
||||
|
||||
DirectPlayProfiles = new[]
|
||||
{
|
||||
new DirectPlayProfile
|
||||
{
|
||||
Container = "mp4,mov",
|
||||
Type = DlnaProfileType.Video,
|
||||
VideoCodec = "h264,mpeg4",
|
||||
AudioCodec = "aac"
|
||||
},
|
||||
|
||||
new DirectPlayProfile
|
||||
{
|
||||
Container = "ts",
|
||||
Type = DlnaProfileType.Video,
|
||||
VideoCodec = "h264",
|
||||
AudioCodec = "aac,ac3,eac3,mp3,mp2,pcm"
|
||||
},
|
||||
|
||||
new DirectPlayProfile
|
||||
{
|
||||
Container = "asf,wmv",
|
||||
Type = DlnaProfileType.Video,
|
||||
VideoCodec = "wmv3,vc1",
|
||||
AudioCodec = "wmav2,wmapro"
|
||||
},
|
||||
|
||||
new DirectPlayProfile
|
||||
{
|
||||
Container = "avi",
|
||||
Type = DlnaProfileType.Video,
|
||||
VideoCodec = "mpeg4,msmpeg4",
|
||||
AudioCodec = "mp3,ac3,eac3,mp2,pcm"
|
||||
},
|
||||
|
||||
new DirectPlayProfile
|
||||
{
|
||||
Container = "mkv",
|
||||
Type = DlnaProfileType.Video,
|
||||
VideoCodec = "h264",
|
||||
AudioCodec = "aac,mp3,ac3,eac3,mp2,pcm"
|
||||
},
|
||||
new DirectPlayProfile
|
||||
{
|
||||
Container = "aac,mp3,flac,ogg,wma,wav",
|
||||
Type = DlnaProfileType.Audio
|
||||
},
|
||||
new DirectPlayProfile
|
||||
{
|
||||
Container = "jpeg,gif,bmp,png",
|
||||
Type = DlnaProfileType.Photo
|
||||
}
|
||||
};
|
||||
|
||||
CodecProfiles = new[]
|
||||
{
|
||||
new CodecProfile
|
||||
{
|
||||
Type = CodecType.Video,
|
||||
Conditions = new []
|
||||
{
|
||||
new ProfileCondition
|
||||
{
|
||||
Condition = ProfileConditionType.LessThanEqual,
|
||||
Property = ProfileConditionValue.Width,
|
||||
Value = "1920"
|
||||
},
|
||||
new ProfileCondition
|
||||
{
|
||||
Condition = ProfileConditionType.LessThanEqual,
|
||||
Property = ProfileConditionValue.Height,
|
||||
Value = "1080"
|
||||
},
|
||||
new ProfileCondition
|
||||
{
|
||||
Condition = ProfileConditionType.NotEquals,
|
||||
Property = ProfileConditionValue.IsAnamorphic,
|
||||
Value = "true",
|
||||
IsRequired = false
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
new CodecProfile
|
||||
{
|
||||
Type = CodecType.VideoAudio,
|
||||
Codec = "aac",
|
||||
Conditions = new []
|
||||
{
|
||||
new ProfileCondition
|
||||
{
|
||||
Condition = ProfileConditionType.LessThanEqual,
|
||||
Property = ProfileConditionValue.AudioChannels,
|
||||
Value = "2",
|
||||
IsRequired = false
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
new CodecProfile
|
||||
{
|
||||
Type = CodecType.Audio,
|
||||
Codec = "aac",
|
||||
Conditions = new []
|
||||
{
|
||||
new ProfileCondition
|
||||
{
|
||||
Condition = ProfileConditionType.LessThanEqual,
|
||||
Property = ProfileConditionValue.AudioChannels,
|
||||
Value = "2",
|
||||
IsRequired = false
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
new CodecProfile
|
||||
{
|
||||
Type = CodecType.Audio,
|
||||
Codec = "mp3",
|
||||
Conditions = new []
|
||||
{
|
||||
new ProfileCondition
|
||||
{
|
||||
Condition = ProfileConditionType.LessThanEqual,
|
||||
Property = ProfileConditionValue.AudioChannels,
|
||||
Value = "2",
|
||||
IsRequired = false
|
||||
},
|
||||
new ProfileCondition
|
||||
{
|
||||
Condition = ProfileConditionType.LessThanEqual,
|
||||
Property = ProfileConditionValue.AudioBitrate,
|
||||
Value = "320000",
|
||||
IsRequired = false
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,7 +1,6 @@
|
|||
using MediaBrowser.Model.Dlna;
|
||||
using System.Xml.Serialization;
|
||||
using MediaBrowser.Model.Dlna.Profiles;
|
||||
using MediaBrowser.Model.MediaInfo;
|
||||
using System.Xml.Serialization;
|
||||
|
||||
namespace MediaBrowser.Dlna.Profiles
|
||||
{
|
||||
|
@ -342,12 +341,6 @@ namespace MediaBrowser.Dlna.Profiles
|
|||
|
||||
SubtitleProfiles = new[]
|
||||
{
|
||||
new SubtitleProfile
|
||||
{
|
||||
Format = "smi",
|
||||
Method = SubtitleDeliveryMethod.External,
|
||||
DidlMode = "CaptionInfoEx"
|
||||
},
|
||||
new SubtitleProfile
|
||||
{
|
||||
Format = "srt",
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
using MediaBrowser.Model.Dlna;
|
||||
using System.Xml.Serialization;
|
||||
using MediaBrowser.Model.Dlna.Profiles;
|
||||
using System.Xml.Serialization;
|
||||
|
||||
namespace MediaBrowser.Dlna.Profiles
|
||||
{
|
||||
|
|
|
@ -47,6 +47,8 @@ namespace MediaBrowser.Dlna.Profiles
|
|||
ProtocolInfo =
|
||||
"http-get:*:audio/mpeg:DLNA.ORG_PN=MP3;DLNA.ORG_OP=01;DLNA.ORG_FLAGS=81500000000000000000000000000000,http-get:*:image/jpeg:DLNA.ORG_PN=JPEG_SM;DLNA.ORG_OP=00;DLNA.ORG_FLAGS=00D00000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=MPEG_PS_PAL;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=81500000000000000000000000000000";
|
||||
|
||||
DidlAlbumArtLimit = 1;
|
||||
|
||||
TranscodingProfiles = new[]
|
||||
{
|
||||
new TranscodingProfile
|
||||
|
|
|
@ -44,6 +44,7 @@ namespace MediaBrowser.Dlna.Profiles
|
|||
Manufacturer = "Microsoft Corporation";
|
||||
ManufacturerUrl = "http://www.microsoft.com/";
|
||||
SonyAggregationFlags = "10";
|
||||
DidlAlbumArtLimit = 1;
|
||||
|
||||
TranscodingProfiles = new[]
|
||||
{
|
||||
|
|
|
@ -44,6 +44,7 @@ namespace MediaBrowser.Dlna.Profiles
|
|||
Manufacturer = "Microsoft Corporation";
|
||||
ManufacturerUrl = "http://www.microsoft.com/";
|
||||
SonyAggregationFlags = "10";
|
||||
DidlAlbumArtLimit = 1;
|
||||
|
||||
TranscodingProfiles = new[]
|
||||
{
|
||||
|
|
|
@ -44,6 +44,7 @@ namespace MediaBrowser.Dlna.Profiles
|
|||
Manufacturer = "Microsoft Corporation";
|
||||
ManufacturerUrl = "http://www.microsoft.com/";
|
||||
SonyAggregationFlags = "10";
|
||||
DidlAlbumArtLimit = 1;
|
||||
|
||||
TranscodingProfiles = new[]
|
||||
{
|
||||
|
|
|
@ -37,6 +37,49 @@ namespace MediaBrowser.Dlna.Profiles
|
|||
|
||||
SonyAggregationFlags = "10";
|
||||
XDlnaDoc = "DMS-1.50";
|
||||
DidlAlbumArtLimit = 1;
|
||||
|
||||
DirectPlayProfiles = new[]
|
||||
{
|
||||
new DirectPlayProfile
|
||||
{
|
||||
Container = "avi",
|
||||
Type = DlnaProfileType.Video,
|
||||
VideoCodec = "mpeg4",
|
||||
AudioCodec = "mp2,mp3"
|
||||
},
|
||||
new DirectPlayProfile
|
||||
{
|
||||
Container = "ts",
|
||||
Type = DlnaProfileType.Video,
|
||||
VideoCodec = "mpeg1video,mpeg2video,h264",
|
||||
AudioCodec = "ac3,mp2,mp3,aac"
|
||||
},
|
||||
new DirectPlayProfile
|
||||
{
|
||||
Container = "mpeg",
|
||||
Type = DlnaProfileType.Video,
|
||||
VideoCodec = "mpeg1video,mpeg2video",
|
||||
AudioCodec = "mp2"
|
||||
},
|
||||
new DirectPlayProfile
|
||||
{
|
||||
Container = "mp4",
|
||||
Type = DlnaProfileType.Video,
|
||||
VideoCodec = "h264,mpeg4",
|
||||
AudioCodec = "aac,ac3"
|
||||
},
|
||||
new DirectPlayProfile
|
||||
{
|
||||
Container = "aac,mp3,wav",
|
||||
Type = DlnaProfileType.Audio
|
||||
},
|
||||
new DirectPlayProfile
|
||||
{
|
||||
Container = "jpeg,png,gif,bmp,tiff",
|
||||
Type = DlnaProfileType.Photo
|
||||
}
|
||||
};
|
||||
|
||||
TranscodingProfiles = new[]
|
||||
{
|
||||
|
@ -185,28 +228,6 @@ namespace MediaBrowser.Dlna.Profiles
|
|||
IsRequired = false
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
new CodecProfile
|
||||
{
|
||||
Type = CodecType.VideoAudio,
|
||||
Codec = "aac",
|
||||
|
||||
Conditions = new []
|
||||
{
|
||||
new ProfileCondition
|
||||
{
|
||||
Condition = ProfileConditionType.LessThanEqual,
|
||||
Property = ProfileConditionValue.AudioChannels,
|
||||
Value = "2"
|
||||
},
|
||||
new ProfileCondition
|
||||
{
|
||||
Condition = ProfileConditionType.NotEquals,
|
||||
Property = ProfileConditionValue.AudioProfile,
|
||||
Value = "he-aac"
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
using MediaBrowser.Model.Dlna;
|
||||
using System.Xml.Serialization;
|
||||
using MediaBrowser.Model.Dlna.Profiles;
|
||||
using System.Xml.Serialization;
|
||||
|
||||
namespace MediaBrowser.Dlna.Profiles
|
||||
{
|
||||
|
@ -10,8 +10,9 @@ namespace MediaBrowser.Dlna.Profiles
|
|||
public XboxOneProfile()
|
||||
{
|
||||
Name = "Xbox One";
|
||||
XDlnaDoc = "DMS-1.50";
|
||||
|
||||
TimelineOffsetSeconds = 40;
|
||||
|
||||
Identification = new DeviceIdentification
|
||||
{
|
||||
ModelName = "Xbox One",
|
||||
|
@ -27,10 +28,16 @@ namespace MediaBrowser.Dlna.Profiles
|
|||
Type = DlnaProfileType.Audio
|
||||
},
|
||||
new TranscodingProfile
|
||||
{
|
||||
Container = "jpeg",
|
||||
VideoCodec = "jpeg",
|
||||
Type = DlnaProfileType.Photo
|
||||
},
|
||||
new TranscodingProfile
|
||||
{
|
||||
Container = "ts",
|
||||
VideoCodec = "h264",
|
||||
AudioCodec = "ac3",
|
||||
AudioCodec = "aac",
|
||||
Type = DlnaProfileType.Video,
|
||||
EstimateContentLength = true
|
||||
}
|
||||
|
@ -114,6 +121,28 @@ namespace MediaBrowser.Dlna.Profiles
|
|||
|
||||
CodecProfiles = new[]
|
||||
{
|
||||
new CodecProfile
|
||||
{
|
||||
Type = CodecType.Video,
|
||||
Conditions = new []
|
||||
{
|
||||
new ProfileCondition
|
||||
{
|
||||
Condition = ProfileConditionType.NotEquals,
|
||||
Property = ProfileConditionValue.IsAnamorphic,
|
||||
Value = "true",
|
||||
IsRequired = false
|
||||
},
|
||||
new ProfileCondition
|
||||
{
|
||||
Condition = ProfileConditionType.LessThanEqual,
|
||||
Property = ProfileConditionValue.VideoBitDepth,
|
||||
Value = "8",
|
||||
IsRequired = false
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
new CodecProfile
|
||||
{
|
||||
Type = CodecType.Video,
|
||||
|
|
|
@ -10,6 +10,7 @@
|
|||
<ModelUrl>http://mediabrowser.tv/</ModelUrl>
|
||||
<IgnoreTranscodeByteRangeRequests>false</IgnoreTranscodeByteRangeRequests>
|
||||
<EnableAlbumArtInDidl>false</EnableAlbumArtInDidl>
|
||||
<DidlAlbumArtLimit xsi:nil="true" />
|
||||
<SupportedMediaTypes>Audio,Photo,Video</SupportedMediaTypes>
|
||||
<AlbumArtPn>JPEG_SM</AlbumArtPn>
|
||||
<MaxAlbumArtWidth>480</MaxAlbumArtWidth>
|
||||
|
@ -25,6 +26,8 @@
|
|||
<TimelineOffsetSeconds>0</TimelineOffsetSeconds>
|
||||
<RequiresPlainVideoItems>false</RequiresPlainVideoItems>
|
||||
<RequiresPlainFolders>false</RequiresPlainFolders>
|
||||
<SupportsDirectRemoteContent>false</SupportsDirectRemoteContent>
|
||||
<SupportsCustomHttpHeaders>false</SupportsCustomHttpHeaders>
|
||||
<XmlRootAttributes />
|
||||
<DirectPlayProfiles>
|
||||
<DirectPlayProfile container="mp4" audioCodec="aac" videoCodec="h264,mpeg4" type="Video" />
|
||||
|
@ -36,33 +39,43 @@
|
|||
</DirectPlayProfiles>
|
||||
<TranscodingProfiles>
|
||||
<TranscodingProfile container="mp3" type="Audio" audioCodec="mp3" estimateContentLength="false" enableMpegtsM2TsMode="false" transcodeSeekInfo="Auto" context="Streaming" />
|
||||
<TranscodingProfile container="ts" type="Video" videoCodec="h264" audioCodec="aac" protocol="hls" estimateContentLength="false" enableMpegtsM2TsMode="false" transcodeSeekInfo="Auto" videoProfile="Baseline" context="Streaming" />
|
||||
<TranscodingProfile container="mp4" type="Video" videoCodec="h264" audioCodec="aac" estimateContentLength="false" enableMpegtsM2TsMode="false" transcodeSeekInfo="Auto" videoProfile="Baseline" context="Static" />
|
||||
<TranscodingProfile container="ts" type="Video" videoCodec="h264" audioCodec="aac" protocol="hls" estimateContentLength="false" enableMpegtsM2TsMode="false" transcodeSeekInfo="Auto" videoProfile="baseline" context="Streaming" />
|
||||
<TranscodingProfile container="mp4" type="Video" videoCodec="h264" audioCodec="aac" estimateContentLength="false" enableMpegtsM2TsMode="false" transcodeSeekInfo="Auto" videoProfile="baseline" context="Static" />
|
||||
</TranscodingProfiles>
|
||||
<ContainerProfiles />
|
||||
<CodecProfiles>
|
||||
<CodecProfile type="Video" codec="h264">
|
||||
<Conditions>
|
||||
<ProfileCondition condition="EqualsAny" property="VideoProfile" value="baseline|constrained baseline" isRequired="false" />
|
||||
<ProfileCondition condition="LessThanEqual" property="Width" value="1920" isRequired="false" />
|
||||
<ProfileCondition condition="LessThanEqual" property="Height" value="1080" isRequired="false" />
|
||||
<ProfileCondition condition="LessThanEqual" property="VideoBitDepth" value="8" isRequired="false" />
|
||||
<ProfileCondition condition="NotEquals" property="IsAnamorphic" value="true" isRequired="false" />
|
||||
<ProfileCondition condition="Equals" property="IsCabac" value="true" isRequired="false" />
|
||||
</Conditions>
|
||||
</CodecProfile>
|
||||
<CodecProfile type="Video">
|
||||
<Conditions>
|
||||
<ProfileCondition condition="LessThanEqual" property="Width" value="1920" isRequired="true" />
|
||||
<ProfileCondition condition="LessThanEqual" property="Height" value="1080" isRequired="true" />
|
||||
<ProfileCondition condition="NotEquals" property="IsAnamorphic" value="true" isRequired="false" />
|
||||
<ProfileCondition condition="LessThanEqual" property="Width" value="1920" isRequired="false" />
|
||||
<ProfileCondition condition="LessThanEqual" property="Height" value="1080" isRequired="false" />
|
||||
<ProfileCondition condition="LessThanEqual" property="VideoBitDepth" value="8" isRequired="false" />
|
||||
<ProfileCondition condition="NotEquals" property="IsAnamorphic" value="true" isRequired="false" />
|
||||
</Conditions>
|
||||
</CodecProfile>
|
||||
<CodecProfile type="VideoAudio" codec="aac">
|
||||
<Conditions>
|
||||
<ProfileCondition condition="LessThanEqual" property="AudioChannels" value="2" isRequired="true" />
|
||||
<ProfileCondition condition="LessThanEqual" property="AudioChannels" value="2" isRequired="false" />
|
||||
</Conditions>
|
||||
</CodecProfile>
|
||||
<CodecProfile type="Audio" codec="aac">
|
||||
<Conditions>
|
||||
<ProfileCondition condition="LessThanEqual" property="AudioChannels" value="2" isRequired="true" />
|
||||
<ProfileCondition condition="LessThanEqual" property="AudioChannels" value="2" isRequired="false" />
|
||||
</Conditions>
|
||||
</CodecProfile>
|
||||
<CodecProfile type="Audio" codec="mp3">
|
||||
<Conditions>
|
||||
<ProfileCondition condition="LessThanEqual" property="AudioChannels" value="2" isRequired="true" />
|
||||
<ProfileCondition condition="LessThanEqual" property="AudioBitrate" value="320000" isRequired="true" />
|
||||
<ProfileCondition condition="LessThanEqual" property="AudioChannels" value="2" isRequired="false" />
|
||||
<ProfileCondition condition="LessThanEqual" property="AudioBitrate" value="320000" isRequired="false" />
|
||||
</Conditions>
|
||||
</CodecProfile>
|
||||
</CodecProfiles>
|
||||
|
|
|
@ -10,6 +10,7 @@
|
|||
<ModelUrl>http://mediabrowser.tv/</ModelUrl>
|
||||
<IgnoreTranscodeByteRangeRequests>false</IgnoreTranscodeByteRangeRequests>
|
||||
<EnableAlbumArtInDidl>false</EnableAlbumArtInDidl>
|
||||
<DidlAlbumArtLimit xsi:nil="true" />
|
||||
<SupportedMediaTypes>Audio,Photo,Video</SupportedMediaTypes>
|
||||
<AlbumArtPn>JPEG_SM</AlbumArtPn>
|
||||
<MaxAlbumArtWidth>480</MaxAlbumArtWidth>
|
||||
|
@ -25,6 +26,8 @@
|
|||
<TimelineOffsetSeconds>0</TimelineOffsetSeconds>
|
||||
<RequiresPlainVideoItems>false</RequiresPlainVideoItems>
|
||||
<RequiresPlainFolders>false</RequiresPlainFolders>
|
||||
<SupportsDirectRemoteContent>false</SupportsDirectRemoteContent>
|
||||
<SupportsCustomHttpHeaders>false</SupportsCustomHttpHeaders>
|
||||
<XmlRootAttributes />
|
||||
<DirectPlayProfiles>
|
||||
<DirectPlayProfile container="mp3,wma" type="Audio" />
|
||||
|
|
|
@ -15,6 +15,7 @@
|
|||
<ModelUrl>http://mediabrowser.tv/</ModelUrl>
|
||||
<IgnoreTranscodeByteRangeRequests>false</IgnoreTranscodeByteRangeRequests>
|
||||
<EnableAlbumArtInDidl>false</EnableAlbumArtInDidl>
|
||||
<DidlAlbumArtLimit xsi:nil="true" />
|
||||
<SupportedMediaTypes>Audio,Photo,Video</SupportedMediaTypes>
|
||||
<AlbumArtPn>JPEG_SM</AlbumArtPn>
|
||||
<MaxAlbumArtWidth>480</MaxAlbumArtWidth>
|
||||
|
@ -30,6 +31,8 @@
|
|||
<TimelineOffsetSeconds>0</TimelineOffsetSeconds>
|
||||
<RequiresPlainVideoItems>false</RequiresPlainVideoItems>
|
||||
<RequiresPlainFolders>false</RequiresPlainFolders>
|
||||
<SupportsDirectRemoteContent>false</SupportsDirectRemoteContent>
|
||||
<SupportsCustomHttpHeaders>false</SupportsCustomHttpHeaders>
|
||||
<XmlRootAttributes />
|
||||
<DirectPlayProfiles>
|
||||
<DirectPlayProfile container="mp3,flac,m4a,wma" type="Audio" />
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
<ModelUrl>http://mediabrowser.tv/</ModelUrl>
|
||||
<IgnoreTranscodeByteRangeRequests>false</IgnoreTranscodeByteRangeRequests>
|
||||
<EnableAlbumArtInDidl>false</EnableAlbumArtInDidl>
|
||||
<DidlAlbumArtLimit xsi:nil="true" />
|
||||
<SupportedMediaTypes>Audio,Photo,Video</SupportedMediaTypes>
|
||||
<AlbumArtPn>JPEG_SM</AlbumArtPn>
|
||||
<MaxAlbumArtWidth>480</MaxAlbumArtWidth>
|
||||
|
@ -31,6 +32,8 @@
|
|||
<TimelineOffsetSeconds>10</TimelineOffsetSeconds>
|
||||
<RequiresPlainVideoItems>true</RequiresPlainVideoItems>
|
||||
<RequiresPlainFolders>true</RequiresPlainFolders>
|
||||
<SupportsDirectRemoteContent>false</SupportsDirectRemoteContent>
|
||||
<SupportsCustomHttpHeaders>false</SupportsCustomHttpHeaders>
|
||||
<XmlRootAttributes />
|
||||
<DirectPlayProfiles>
|
||||
<DirectPlayProfile container="mpeg" audioCodec="mp2" videoCodec="mpeg2video" type="Video" />
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
<ModelUrl>http://mediabrowser.tv/</ModelUrl>
|
||||
<IgnoreTranscodeByteRangeRequests>false</IgnoreTranscodeByteRangeRequests>
|
||||
<EnableAlbumArtInDidl>false</EnableAlbumArtInDidl>
|
||||
<DidlAlbumArtLimit xsi:nil="true" />
|
||||
<SupportedMediaTypes>Audio,Photo,Video</SupportedMediaTypes>
|
||||
<AlbumArtPn>JPEG_SM</AlbumArtPn>
|
||||
<MaxAlbumArtWidth>480</MaxAlbumArtWidth>
|
||||
|
@ -32,6 +33,8 @@
|
|||
<TimelineOffsetSeconds>0</TimelineOffsetSeconds>
|
||||
<RequiresPlainVideoItems>false</RequiresPlainVideoItems>
|
||||
<RequiresPlainFolders>false</RequiresPlainFolders>
|
||||
<SupportsDirectRemoteContent>false</SupportsDirectRemoteContent>
|
||||
<SupportsCustomHttpHeaders>false</SupportsCustomHttpHeaders>
|
||||
<XmlRootAttributes />
|
||||
<DirectPlayProfiles>
|
||||
<DirectPlayProfile container="mp4,mkv,mpeg,ts" audioCodec="mp3,ac3,aac,he-aac,pcm" videoCodec="h264,mpeg2video" type="Video" />
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
<ModelUrl>http://mediabrowser.tv/</ModelUrl>
|
||||
<IgnoreTranscodeByteRangeRequests>false</IgnoreTranscodeByteRangeRequests>
|
||||
<EnableAlbumArtInDidl>false</EnableAlbumArtInDidl>
|
||||
<DidlAlbumArtLimit xsi:nil="true" />
|
||||
<SupportedMediaTypes>Audio,Photo,Video</SupportedMediaTypes>
|
||||
<AlbumArtPn>JPEG_SM</AlbumArtPn>
|
||||
<MaxAlbumArtWidth>480</MaxAlbumArtWidth>
|
||||
|
@ -31,6 +32,8 @@
|
|||
<TimelineOffsetSeconds>10</TimelineOffsetSeconds>
|
||||
<RequiresPlainVideoItems>false</RequiresPlainVideoItems>
|
||||
<RequiresPlainFolders>false</RequiresPlainFolders>
|
||||
<SupportsDirectRemoteContent>false</SupportsDirectRemoteContent>
|
||||
<SupportsCustomHttpHeaders>false</SupportsCustomHttpHeaders>
|
||||
<XmlRootAttributes />
|
||||
<DirectPlayProfiles>
|
||||
<DirectPlayProfile container="ts" audioCodec="aac,ac3,mp3" videoCodec="h264" type="Video" />
|
||||
|
|
|
@ -14,6 +14,7 @@
|
|||
<ModelUrl>http://mediabrowser.tv/</ModelUrl>
|
||||
<IgnoreTranscodeByteRangeRequests>false</IgnoreTranscodeByteRangeRequests>
|
||||
<EnableAlbumArtInDidl>false</EnableAlbumArtInDidl>
|
||||
<DidlAlbumArtLimit xsi:nil="true" />
|
||||
<SupportedMediaTypes>Audio,Photo,Video</SupportedMediaTypes>
|
||||
<AlbumArtPn>JPEG_SM</AlbumArtPn>
|
||||
<MaxAlbumArtWidth>480</MaxAlbumArtWidth>
|
||||
|
@ -29,6 +30,8 @@
|
|||
<TimelineOffsetSeconds>0</TimelineOffsetSeconds>
|
||||
<RequiresPlainVideoItems>false</RequiresPlainVideoItems>
|
||||
<RequiresPlainFolders>false</RequiresPlainFolders>
|
||||
<SupportsDirectRemoteContent>false</SupportsDirectRemoteContent>
|
||||
<SupportsCustomHttpHeaders>false</SupportsCustomHttpHeaders>
|
||||
<XmlRootAttributes />
|
||||
<DirectPlayProfiles>
|
||||
<DirectPlayProfile container="mp3,flac,m4a,wma" type="Audio" />
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
<ModelUrl>http://mediabrowser.tv/</ModelUrl>
|
||||
<IgnoreTranscodeByteRangeRequests>false</IgnoreTranscodeByteRangeRequests>
|
||||
<EnableAlbumArtInDidl>false</EnableAlbumArtInDidl>
|
||||
<DidlAlbumArtLimit xsi:nil="true" />
|
||||
<SupportedMediaTypes>Audio</SupportedMediaTypes>
|
||||
<AlbumArtPn>JPEG_SM</AlbumArtPn>
|
||||
<MaxAlbumArtWidth>480</MaxAlbumArtWidth>
|
||||
|
@ -31,6 +32,8 @@
|
|||
<TimelineOffsetSeconds>0</TimelineOffsetSeconds>
|
||||
<RequiresPlainVideoItems>false</RequiresPlainVideoItems>
|
||||
<RequiresPlainFolders>false</RequiresPlainFolders>
|
||||
<SupportsDirectRemoteContent>false</SupportsDirectRemoteContent>
|
||||
<SupportsCustomHttpHeaders>false</SupportsCustomHttpHeaders>
|
||||
<XmlRootAttributes />
|
||||
<DirectPlayProfiles>
|
||||
<DirectPlayProfile container="mp3" audioCodec="mp2,mp3" type="Audio" />
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
<ModelUrl>http://mediabrowser.tv/</ModelUrl>
|
||||
<IgnoreTranscodeByteRangeRequests>false</IgnoreTranscodeByteRangeRequests>
|
||||
<EnableAlbumArtInDidl>false</EnableAlbumArtInDidl>
|
||||
<DidlAlbumArtLimit xsi:nil="true" />
|
||||
<SupportedMediaTypes>Audio,Photo,Video</SupportedMediaTypes>
|
||||
<AlbumArtPn>JPEG_SM</AlbumArtPn>
|
||||
<MaxAlbumArtWidth>480</MaxAlbumArtWidth>
|
||||
|
@ -32,6 +33,8 @@
|
|||
<TimelineOffsetSeconds>10</TimelineOffsetSeconds>
|
||||
<RequiresPlainVideoItems>false</RequiresPlainVideoItems>
|
||||
<RequiresPlainFolders>false</RequiresPlainFolders>
|
||||
<SupportsDirectRemoteContent>false</SupportsDirectRemoteContent>
|
||||
<SupportsCustomHttpHeaders>false</SupportsCustomHttpHeaders>
|
||||
<XmlRootAttributes>
|
||||
<XmlAttribute name="xmlns:pv" value="http://www.pv.com/pvns/" />
|
||||
</XmlRootAttributes>
|
||||
|
|
74
MediaBrowser.Dlna/Profiles/Xml/Popcorn Hour.xml
Normal file
74
MediaBrowser.Dlna/Profiles/Xml/Popcorn Hour.xml
Normal file
File diff suppressed because one or more lines are too long
|
@ -16,6 +16,7 @@
|
|||
<ModelUrl>http://mediabrowser.tv/</ModelUrl>
|
||||
<IgnoreTranscodeByteRangeRequests>false</IgnoreTranscodeByteRangeRequests>
|
||||
<EnableAlbumArtInDidl>true</EnableAlbumArtInDidl>
|
||||
<DidlAlbumArtLimit xsi:nil="true" />
|
||||
<SupportedMediaTypes>Audio,Photo,Video</SupportedMediaTypes>
|
||||
<AlbumArtPn>JPEG_SM</AlbumArtPn>
|
||||
<MaxAlbumArtWidth>480</MaxAlbumArtWidth>
|
||||
|
@ -31,6 +32,8 @@
|
|||
<TimelineOffsetSeconds>0</TimelineOffsetSeconds>
|
||||
<RequiresPlainVideoItems>false</RequiresPlainVideoItems>
|
||||
<RequiresPlainFolders>false</RequiresPlainFolders>
|
||||
<SupportsDirectRemoteContent>false</SupportsDirectRemoteContent>
|
||||
<SupportsCustomHttpHeaders>false</SupportsCustomHttpHeaders>
|
||||
<XmlRootAttributes>
|
||||
<XmlAttribute name="xmlns:sec" value="http://www.sec.co.kr/" />
|
||||
</XmlRootAttributes>
|
||||
|
@ -109,7 +112,6 @@
|
|||
</ResponseProfile>
|
||||
</ResponseProfiles>
|
||||
<SubtitleProfiles>
|
||||
<SubtitleProfile format="smi" method="External" didlMode="CaptionInfoEx" />
|
||||
<SubtitleProfile format="srt" method="External" didlMode="CaptionInfoEx" />
|
||||
</SubtitleProfiles>
|
||||
</Profile>
|
|
@ -16,6 +16,7 @@
|
|||
<ModelUrl>http://mediabrowser.tv/</ModelUrl>
|
||||
<IgnoreTranscodeByteRangeRequests>false</IgnoreTranscodeByteRangeRequests>
|
||||
<EnableAlbumArtInDidl>false</EnableAlbumArtInDidl>
|
||||
<DidlAlbumArtLimit xsi:nil="true" />
|
||||
<SupportedMediaTypes>Audio,Photo,Video</SupportedMediaTypes>
|
||||
<AlbumArtPn>JPEG_SM</AlbumArtPn>
|
||||
<MaxAlbumArtWidth>480</MaxAlbumArtWidth>
|
||||
|
@ -31,6 +32,8 @@
|
|||
<TimelineOffsetSeconds>0</TimelineOffsetSeconds>
|
||||
<RequiresPlainVideoItems>false</RequiresPlainVideoItems>
|
||||
<RequiresPlainFolders>false</RequiresPlainFolders>
|
||||
<SupportsDirectRemoteContent>false</SupportsDirectRemoteContent>
|
||||
<SupportsCustomHttpHeaders>false</SupportsCustomHttpHeaders>
|
||||
<XmlRootAttributes>
|
||||
<XmlAttribute name="xmlns:av" value="urn:schemas-sony-com:av" />
|
||||
</XmlRootAttributes>
|
||||
|
|
|
@ -18,6 +18,7 @@
|
|||
<ModelUrl>http://mediabrowser.tv/</ModelUrl>
|
||||
<IgnoreTranscodeByteRangeRequests>false</IgnoreTranscodeByteRangeRequests>
|
||||
<EnableAlbumArtInDidl>false</EnableAlbumArtInDidl>
|
||||
<DidlAlbumArtLimit xsi:nil="true" />
|
||||
<SupportedMediaTypes>Audio,Photo,Video</SupportedMediaTypes>
|
||||
<AlbumArtPn>JPEG_SM</AlbumArtPn>
|
||||
<MaxAlbumArtWidth>480</MaxAlbumArtWidth>
|
||||
|
@ -33,6 +34,8 @@
|
|||
<TimelineOffsetSeconds>0</TimelineOffsetSeconds>
|
||||
<RequiresPlainVideoItems>false</RequiresPlainVideoItems>
|
||||
<RequiresPlainFolders>false</RequiresPlainFolders>
|
||||
<SupportsDirectRemoteContent>false</SupportsDirectRemoteContent>
|
||||
<SupportsCustomHttpHeaders>false</SupportsCustomHttpHeaders>
|
||||
<XmlRootAttributes>
|
||||
<XmlAttribute name="xmlns:av" value="urn:schemas-sony-com:av" />
|
||||
</XmlRootAttributes>
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
<ModelUrl>http://www.microsoft.com/</ModelUrl>
|
||||
<IgnoreTranscodeByteRangeRequests>false</IgnoreTranscodeByteRangeRequests>
|
||||
<EnableAlbumArtInDidl>false</EnableAlbumArtInDidl>
|
||||
<DidlAlbumArtLimit>1</DidlAlbumArtLimit>
|
||||
<SupportedMediaTypes>Audio,Photo,Video</SupportedMediaTypes>
|
||||
<AlbumArtPn>JPEG_TN</AlbumArtPn>
|
||||
<MaxAlbumArtWidth>480</MaxAlbumArtWidth>
|
||||
|
@ -33,6 +34,8 @@
|
|||
<TimelineOffsetSeconds>0</TimelineOffsetSeconds>
|
||||
<RequiresPlainVideoItems>false</RequiresPlainVideoItems>
|
||||
<RequiresPlainFolders>false</RequiresPlainFolders>
|
||||
<SupportsDirectRemoteContent>false</SupportsDirectRemoteContent>
|
||||
<SupportsCustomHttpHeaders>false</SupportsCustomHttpHeaders>
|
||||
<XmlRootAttributes>
|
||||
<XmlAttribute name="xmlns:av" value="urn:schemas-sony-com:av" />
|
||||
</XmlRootAttributes>
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
<ModelUrl>http://www.microsoft.com/</ModelUrl>
|
||||
<IgnoreTranscodeByteRangeRequests>false</IgnoreTranscodeByteRangeRequests>
|
||||
<EnableAlbumArtInDidl>false</EnableAlbumArtInDidl>
|
||||
<DidlAlbumArtLimit>1</DidlAlbumArtLimit>
|
||||
<SupportedMediaTypes>Audio,Photo,Video</SupportedMediaTypes>
|
||||
<AlbumArtPn>JPEG_TN</AlbumArtPn>
|
||||
<MaxAlbumArtWidth>480</MaxAlbumArtWidth>
|
||||
|
@ -33,6 +34,8 @@
|
|||
<TimelineOffsetSeconds>0</TimelineOffsetSeconds>
|
||||
<RequiresPlainVideoItems>false</RequiresPlainVideoItems>
|
||||
<RequiresPlainFolders>false</RequiresPlainFolders>
|
||||
<SupportsDirectRemoteContent>false</SupportsDirectRemoteContent>
|
||||
<SupportsCustomHttpHeaders>false</SupportsCustomHttpHeaders>
|
||||
<XmlRootAttributes>
|
||||
<XmlAttribute name="xmlns:av" value="urn:schemas-sony-com:av" />
|
||||
</XmlRootAttributes>
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
<ModelUrl>http://www.microsoft.com/</ModelUrl>
|
||||
<IgnoreTranscodeByteRangeRequests>false</IgnoreTranscodeByteRangeRequests>
|
||||
<EnableAlbumArtInDidl>false</EnableAlbumArtInDidl>
|
||||
<DidlAlbumArtLimit>1</DidlAlbumArtLimit>
|
||||
<SupportedMediaTypes>Audio,Photo,Video</SupportedMediaTypes>
|
||||
<AlbumArtPn>JPEG_TN</AlbumArtPn>
|
||||
<MaxAlbumArtWidth>480</MaxAlbumArtWidth>
|
||||
|
@ -33,6 +34,8 @@
|
|||
<TimelineOffsetSeconds>0</TimelineOffsetSeconds>
|
||||
<RequiresPlainVideoItems>false</RequiresPlainVideoItems>
|
||||
<RequiresPlainFolders>false</RequiresPlainFolders>
|
||||
<SupportsDirectRemoteContent>false</SupportsDirectRemoteContent>
|
||||
<SupportsCustomHttpHeaders>false</SupportsCustomHttpHeaders>
|
||||
<XmlRootAttributes>
|
||||
<XmlAttribute name="xmlns:av" value="urn:schemas-sony-com:av" />
|
||||
</XmlRootAttributes>
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
<ModelUrl>http://www.microsoft.com/</ModelUrl>
|
||||
<IgnoreTranscodeByteRangeRequests>false</IgnoreTranscodeByteRangeRequests>
|
||||
<EnableAlbumArtInDidl>false</EnableAlbumArtInDidl>
|
||||
<DidlAlbumArtLimit>1</DidlAlbumArtLimit>
|
||||
<SupportedMediaTypes>Audio,Photo,Video</SupportedMediaTypes>
|
||||
<AlbumArtPn>JPEG_TN</AlbumArtPn>
|
||||
<MaxAlbumArtWidth>480</MaxAlbumArtWidth>
|
||||
|
@ -33,6 +34,8 @@
|
|||
<TimelineOffsetSeconds>0</TimelineOffsetSeconds>
|
||||
<RequiresPlainVideoItems>false</RequiresPlainVideoItems>
|
||||
<RequiresPlainFolders>false</RequiresPlainFolders>
|
||||
<SupportsDirectRemoteContent>false</SupportsDirectRemoteContent>
|
||||
<SupportsCustomHttpHeaders>false</SupportsCustomHttpHeaders>
|
||||
<XmlRootAttributes>
|
||||
<XmlAttribute name="xmlns:av" value="urn:schemas-sony-com:av" />
|
||||
</XmlRootAttributes>
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
<ModelUrl>http://mediabrowser.tv/</ModelUrl>
|
||||
<IgnoreTranscodeByteRangeRequests>false</IgnoreTranscodeByteRangeRequests>
|
||||
<EnableAlbumArtInDidl>false</EnableAlbumArtInDidl>
|
||||
<DidlAlbumArtLimit>1</DidlAlbumArtLimit>
|
||||
<SupportedMediaTypes>Audio,Photo,Video</SupportedMediaTypes>
|
||||
<AlbumArtPn>JPEG_TN</AlbumArtPn>
|
||||
<MaxAlbumArtWidth>480</MaxAlbumArtWidth>
|
||||
|
@ -33,10 +34,16 @@
|
|||
<TimelineOffsetSeconds>0</TimelineOffsetSeconds>
|
||||
<RequiresPlainVideoItems>false</RequiresPlainVideoItems>
|
||||
<RequiresPlainFolders>false</RequiresPlainFolders>
|
||||
<SupportsDirectRemoteContent>false</SupportsDirectRemoteContent>
|
||||
<SupportsCustomHttpHeaders>false</SupportsCustomHttpHeaders>
|
||||
<XmlRootAttributes />
|
||||
<DirectPlayProfiles>
|
||||
<DirectPlayProfile container="mp3,wma" type="Audio" />
|
||||
<DirectPlayProfile container="avi,mp4" type="Video" />
|
||||
<DirectPlayProfile container="avi" audioCodec="mp2,mp3" videoCodec="mpeg4" type="Video" />
|
||||
<DirectPlayProfile container="ts" audioCodec="ac3,mp2,mp3,aac" videoCodec="mpeg1video,mpeg2video,h264" type="Video" />
|
||||
<DirectPlayProfile container="mpeg" audioCodec="mp2" videoCodec="mpeg1video,mpeg2video" type="Video" />
|
||||
<DirectPlayProfile container="mp4" audioCodec="aac,ac3" videoCodec="h264,mpeg4" type="Video" />
|
||||
<DirectPlayProfile container="aac,mp3,wav" type="Audio" />
|
||||
<DirectPlayProfile container="jpeg,png,gif,bmp,tiff" type="Photo" />
|
||||
</DirectPlayProfiles>
|
||||
<TranscodingProfiles>
|
||||
<TranscodingProfile container="mp3" type="Audio" audioCodec="mp3" estimateContentLength="false" enableMpegtsM2TsMode="false" transcodeSeekInfo="Auto" context="Streaming" />
|
||||
|
@ -77,12 +84,6 @@
|
|||
<ProfileCondition condition="NotEquals" property="AudioProfile" value="he-aac" isRequired="false" />
|
||||
</Conditions>
|
||||
</CodecProfile>
|
||||
<CodecProfile type="VideoAudio" codec="aac">
|
||||
<Conditions>
|
||||
<ProfileCondition condition="LessThanEqual" property="AudioChannels" value="2" isRequired="true" />
|
||||
<ProfileCondition condition="NotEquals" property="AudioProfile" value="he-aac" isRequired="true" />
|
||||
</Conditions>
|
||||
</CodecProfile>
|
||||
</CodecProfiles>
|
||||
<ResponseProfiles>
|
||||
<ResponseProfile container="mp4,mov" audioCodec="aac" type="Video" mimeType="video/mp4">
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
<ModelUrl>http://mediabrowser.tv/</ModelUrl>
|
||||
<IgnoreTranscodeByteRangeRequests>true</IgnoreTranscodeByteRangeRequests>
|
||||
<EnableAlbumArtInDidl>false</EnableAlbumArtInDidl>
|
||||
<DidlAlbumArtLimit xsi:nil="true" />
|
||||
<SupportedMediaTypes>Audio,Photo,Video</SupportedMediaTypes>
|
||||
<AlbumArtPn>JPEG_SM</AlbumArtPn>
|
||||
<MaxAlbumArtWidth>480</MaxAlbumArtWidth>
|
||||
|
@ -32,6 +33,8 @@
|
|||
<TimelineOffsetSeconds>5</TimelineOffsetSeconds>
|
||||
<RequiresPlainVideoItems>false</RequiresPlainVideoItems>
|
||||
<RequiresPlainFolders>false</RequiresPlainFolders>
|
||||
<SupportsDirectRemoteContent>false</SupportsDirectRemoteContent>
|
||||
<SupportsCustomHttpHeaders>false</SupportsCustomHttpHeaders>
|
||||
<XmlRootAttributes />
|
||||
<DirectPlayProfiles>
|
||||
<DirectPlayProfile container="avi" audioCodec="ac3,dca,mp2,mp3,pcm" videoCodec="mpeg1video,mpeg2video,mpeg4,h264,vc1" type="Video" />
|
||||
|
|
|
@ -14,6 +14,7 @@
|
|||
<ModelUrl>http://mediabrowser.tv/</ModelUrl>
|
||||
<IgnoreTranscodeByteRangeRequests>false</IgnoreTranscodeByteRangeRequests>
|
||||
<EnableAlbumArtInDidl>false</EnableAlbumArtInDidl>
|
||||
<DidlAlbumArtLimit xsi:nil="true" />
|
||||
<SupportedMediaTypes>Audio,Photo,Video</SupportedMediaTypes>
|
||||
<AlbumArtPn>JPEG_SM</AlbumArtPn>
|
||||
<MaxAlbumArtWidth>480</MaxAlbumArtWidth>
|
||||
|
@ -29,6 +30,8 @@
|
|||
<TimelineOffsetSeconds>0</TimelineOffsetSeconds>
|
||||
<RequiresPlainVideoItems>false</RequiresPlainVideoItems>
|
||||
<RequiresPlainFolders>false</RequiresPlainFolders>
|
||||
<SupportsDirectRemoteContent>false</SupportsDirectRemoteContent>
|
||||
<SupportsCustomHttpHeaders>false</SupportsCustomHttpHeaders>
|
||||
<XmlRootAttributes />
|
||||
<DirectPlayProfiles>
|
||||
<DirectPlayProfile container="mp4,mov" audioCodec="aac,ac3,eac3,mp3,pcm" videoCodec="h264,mpeg4" type="Video" />
|
||||
|
|
|
@ -10,6 +10,7 @@
|
|||
<ModelUrl>http://mediabrowser.tv/</ModelUrl>
|
||||
<IgnoreTranscodeByteRangeRequests>false</IgnoreTranscodeByteRangeRequests>
|
||||
<EnableAlbumArtInDidl>false</EnableAlbumArtInDidl>
|
||||
<DidlAlbumArtLimit xsi:nil="true" />
|
||||
<SupportedMediaTypes>Audio,Photo,Video</SupportedMediaTypes>
|
||||
<AlbumArtPn>JPEG_SM</AlbumArtPn>
|
||||
<MaxAlbumArtWidth>480</MaxAlbumArtWidth>
|
||||
|
@ -25,6 +26,8 @@
|
|||
<TimelineOffsetSeconds>0</TimelineOffsetSeconds>
|
||||
<RequiresPlainVideoItems>false</RequiresPlainVideoItems>
|
||||
<RequiresPlainFolders>false</RequiresPlainFolders>
|
||||
<SupportsDirectRemoteContent>false</SupportsDirectRemoteContent>
|
||||
<SupportsCustomHttpHeaders>false</SupportsCustomHttpHeaders>
|
||||
<XmlRootAttributes />
|
||||
<DirectPlayProfiles>
|
||||
<DirectPlayProfile container="mp4,mov" audioCodec="aac,mp3" videoCodec="h264" type="Video" />
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
<ModelUrl>http://www.microsoft.com/</ModelUrl>
|
||||
<IgnoreTranscodeByteRangeRequests>false</IgnoreTranscodeByteRangeRequests>
|
||||
<EnableAlbumArtInDidl>false</EnableAlbumArtInDidl>
|
||||
<DidlAlbumArtLimit xsi:nil="true" />
|
||||
<SupportedMediaTypes>Audio,Photo,Video</SupportedMediaTypes>
|
||||
<AlbumArtPn>JPEG_SM</AlbumArtPn>
|
||||
<MaxAlbumArtWidth>480</MaxAlbumArtWidth>
|
||||
|
@ -32,6 +33,8 @@
|
|||
<TimelineOffsetSeconds>40</TimelineOffsetSeconds>
|
||||
<RequiresPlainVideoItems>true</RequiresPlainVideoItems>
|
||||
<RequiresPlainFolders>true</RequiresPlainFolders>
|
||||
<SupportsDirectRemoteContent>false</SupportsDirectRemoteContent>
|
||||
<SupportsCustomHttpHeaders>false</SupportsCustomHttpHeaders>
|
||||
<XmlRootAttributes />
|
||||
<DirectPlayProfiles>
|
||||
<DirectPlayProfile container="avi" audioCodec="ac3,mp3" videoCodec="mpeg4" type="Video" />
|
||||
|
|
File diff suppressed because one or more lines are too long
|
@ -16,6 +16,7 @@
|
|||
<ModelUrl>http://mediabrowser.tv/</ModelUrl>
|
||||
<IgnoreTranscodeByteRangeRequests>false</IgnoreTranscodeByteRangeRequests>
|
||||
<EnableAlbumArtInDidl>false</EnableAlbumArtInDidl>
|
||||
<DidlAlbumArtLimit xsi:nil="true" />
|
||||
<SupportedMediaTypes>Audio</SupportedMediaTypes>
|
||||
<AlbumArtPn>JPEG_SM</AlbumArtPn>
|
||||
<MaxAlbumArtWidth>480</MaxAlbumArtWidth>
|
||||
|
@ -31,6 +32,8 @@
|
|||
<TimelineOffsetSeconds>0</TimelineOffsetSeconds>
|
||||
<RequiresPlainVideoItems>false</RequiresPlainVideoItems>
|
||||
<RequiresPlainFolders>false</RequiresPlainFolders>
|
||||
<SupportsDirectRemoteContent>false</SupportsDirectRemoteContent>
|
||||
<SupportsCustomHttpHeaders>false</SupportsCustomHttpHeaders>
|
||||
<XmlRootAttributes />
|
||||
<DirectPlayProfiles>
|
||||
<DirectPlayProfile container="mp3" audioCodec="mp2,mp3" type="Audio" />
|
||||
|
|
|
@ -172,6 +172,7 @@ namespace MediaBrowser.Dlna.Ssdp
|
|||
values["ST"] = d.Type;
|
||||
values["USN"] = d.USN;
|
||||
|
||||
SendDatagram(header, values, endpoint, null, true);
|
||||
SendDatagram(header, values, endpoint, new IPEndPoint(d.Address, 0), true);
|
||||
//SendDatagram(header, values, endpoint, null, true);
|
||||
|
||||
|
|
|
@ -1,7 +1,8 @@
|
|||
using System.Xml;
|
||||
using MediaBrowser.Controller.Entities;
|
||||
using MediaBrowser.Controller.Entities;
|
||||
using MediaBrowser.Controller.Providers;
|
||||
using MediaBrowser.Model.Logging;
|
||||
using System;
|
||||
using System.Xml;
|
||||
|
||||
namespace MediaBrowser.LocalMetadata.Parsers
|
||||
{
|
||||
|
@ -26,8 +27,17 @@ namespace MediaBrowser.LocalMetadata.Parsers
|
|||
switch (reader.Name)
|
||||
{
|
||||
case "Artist":
|
||||
item.Artist = reader.ReadElementContentAsString();
|
||||
break;
|
||||
{
|
||||
var val = reader.ReadElementContentAsString();
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(val))
|
||||
{
|
||||
var artists = val.Split(new char[] { ';' }, StringSplitOptions.RemoveEmptyEntries);
|
||||
item.Artists.AddRange(artists);
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case "Album":
|
||||
item.Album = reader.ReadElementContentAsString();
|
||||
|
|
|
@ -78,9 +78,9 @@ namespace MediaBrowser.LocalMetadata.Savers
|
|||
|
||||
if (musicVideo != null)
|
||||
{
|
||||
if (!string.IsNullOrEmpty(musicVideo.Artist))
|
||||
if (musicVideo.Artists.Count > 0)
|
||||
{
|
||||
builder.Append("<Artist>" + SecurityElement.Escape(musicVideo.Artist) + "</Artist>");
|
||||
builder.Append("<Artist>" + SecurityElement.Escape(string.Join(";", musicVideo.Artists.ToArray())) + "</Artist>");
|
||||
}
|
||||
if (!string.IsNullOrEmpty(musicVideo.Album))
|
||||
{
|
||||
|
|
|
@ -24,6 +24,12 @@ namespace MediaBrowser.MediaInfo
|
|||
result.IsInterlaced = text.IndexOf("interlac", StringComparison.OrdinalIgnoreCase) != -1;
|
||||
}
|
||||
|
||||
text = GetValue(lib, videoStreamIndex, new[] { "Format_Settings_CABAC", "Format_Settings_CABAC/String" });
|
||||
if (!string.IsNullOrWhiteSpace(text))
|
||||
{
|
||||
result.IsCabac = string.Equals(text, "yes", StringComparison.OrdinalIgnoreCase);
|
||||
}
|
||||
|
||||
int bitDepth;
|
||||
text = GetValue(lib, videoStreamIndex, new[] { "BitDepth", "BitDepth/String" });
|
||||
|
||||
|
@ -51,6 +57,7 @@ namespace MediaBrowser.MediaInfo
|
|||
|
||||
public class MediaInfoResult
|
||||
{
|
||||
public bool? IsCabac { get; set; }
|
||||
public bool? IsInterlaced { get; set; }
|
||||
public int? BitDepth { get; set; }
|
||||
public int? RefFrames { get; set; }
|
||||
|
|
|
@ -413,6 +413,9 @@
|
|||
<Compile Include="..\MediaBrowser.Model\Dto\GameSystemSummary.cs">
|
||||
<Link>Dto\GameSystemSummary.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="..\MediaBrowser.Model\Dto\IHasServerId.cs">
|
||||
<Link>Dto\IHasServerId.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="..\MediaBrowser.Model\Dto\IItemDto.cs">
|
||||
<Link>Dto\IItemDto.cs</Link>
|
||||
</Compile>
|
||||
|
@ -1088,9 +1091,6 @@
|
|||
<Compile Include="..\MediaBrowser.Model\Users\AuthenticationResult.cs">
|
||||
<Link>Users\AuthenticationResult.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="..\MediaBrowser.Model\Weather\WeatherUnits.cs">
|
||||
<Link>Weather\WeatherUnits.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="..\SharedVersion.cs">
|
||||
<Link>Properties\SharedVersion.cs</Link>
|
||||
</Compile>
|
||||
|
|
|
@ -378,6 +378,9 @@
|
|||
<Compile Include="..\MediaBrowser.Model\Dto\GameSystemSummary.cs">
|
||||
<Link>Dto\GameSystemSummary.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="..\MediaBrowser.Model\Dto\IHasServerId.cs">
|
||||
<Link>Dto\IHasServerId.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="..\MediaBrowser.Model\Dto\IItemDto.cs">
|
||||
<Link>Dto\IItemDto.cs</Link>
|
||||
</Compile>
|
||||
|
@ -1047,9 +1050,6 @@
|
|||
<Compile Include="..\MediaBrowser.Model\Users\AuthenticationResult.cs">
|
||||
<Link>Users\AuthenticationResult.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="..\MediaBrowser.Model\Weather\WeatherUnits.cs">
|
||||
<Link>Weather\WeatherUnits.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="..\SharedVersion.cs">
|
||||
<Link>Properties\SharedVersion.cs</Link>
|
||||
</Compile>
|
||||
|
|
|
@ -30,7 +30,9 @@ namespace MediaBrowser.Model.ApiClient
|
|||
/// Occurs when [connect user sign out].
|
||||
/// </summary>
|
||||
event EventHandler<EventArgs> ConnectUserSignOut;
|
||||
|
||||
[Obsolete]
|
||||
event EventHandler<EventArgs> RemoteLoggedOut;
|
||||
|
||||
/// <summary>
|
||||
/// Gets the connect user.
|
||||
/// </summary>
|
||||
|
@ -41,8 +43,8 @@ namespace MediaBrowser.Model.ApiClient
|
|||
/// Gets the API client.
|
||||
/// </summary>
|
||||
/// <param name="item">The item.</param>
|
||||
/// <returns>MediaBrowser.Model.ApiClient.IApiClient.</returns>
|
||||
IApiClient GetApiClient(BaseItemDto item);
|
||||
/// <returns>IApiClient.</returns>
|
||||
IApiClient GetApiClient(IHasServerId item);
|
||||
|
||||
/// <summary>
|
||||
/// Connects the specified cancellation token.
|
||||
|
|
|
@ -4,5 +4,10 @@ namespace MediaBrowser.Model.Configuration
|
|||
public class MetadataConfiguration
|
||||
{
|
||||
public bool UseFileCreationTimeForDateAdded { get; set; }
|
||||
|
||||
public MetadataConfiguration()
|
||||
{
|
||||
UseFileCreationTimeForDateAdded = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -180,6 +180,8 @@ namespace MediaBrowser.Model.Configuration
|
|||
|
||||
public bool SaveMetadataHidden { get; set; }
|
||||
|
||||
public bool PlaylistImagesDeleted { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="ServerConfiguration" /> class.
|
||||
/// </summary>
|
||||
|
|
|
@ -88,6 +88,8 @@ namespace MediaBrowser.Model.Configuration
|
|||
|
||||
public AccessSchedule[] AccessSchedules { get; set; }
|
||||
|
||||
public bool EnableUserPreferenceAccess { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="UserConfiguration" /> class.
|
||||
/// </summary>
|
||||
|
@ -112,6 +114,7 @@ namespace MediaBrowser.Model.Configuration
|
|||
SyncConnectImage = true;
|
||||
IncludeTrailersInSuggestions = true;
|
||||
EnableCinemaMode = true;
|
||||
EnableUserPreferenceAccess = true;
|
||||
|
||||
AccessSchedules = new AccessSchedule[] { };
|
||||
}
|
||||
|
|
|
@ -4,7 +4,7 @@ namespace MediaBrowser.Model.Devices
|
|||
public class LocalFileInfo
|
||||
{
|
||||
public string Name { get; set; }
|
||||
public string FullPath { get; set; }
|
||||
public string Id { get; set; }
|
||||
public string Album { get; set; }
|
||||
public string MimeType { get; set; }
|
||||
}
|
||||
|
|
|
@ -19,6 +19,7 @@ namespace MediaBrowser.Model.Dlna
|
|||
int? packetLength,
|
||||
TransportStreamTimestamp? timestamp,
|
||||
bool? isAnamorphic,
|
||||
bool? isCabac,
|
||||
int? refFrames)
|
||||
{
|
||||
switch (condition.Property)
|
||||
|
@ -31,6 +32,8 @@ namespace MediaBrowser.Model.Dlna
|
|||
return true;
|
||||
case ProfileConditionValue.IsAnamorphic:
|
||||
return IsConditionSatisfied(condition, isAnamorphic);
|
||||
case ProfileConditionValue.IsCabac:
|
||||
return IsConditionSatisfied(condition, isCabac);
|
||||
case ProfileConditionValue.VideoFramerate:
|
||||
return IsConditionSatisfied(condition, videoFramerate);
|
||||
case ProfileConditionValue.VideoLevel:
|
||||
|
|
|
@ -116,6 +116,7 @@ namespace MediaBrowser.Model.Dlna
|
|||
int? packetLength,
|
||||
TranscodeSeekInfo transcodeSeekInfo,
|
||||
bool? isAnamorphic,
|
||||
bool? isCabac,
|
||||
int? refFrames)
|
||||
{
|
||||
// first bit means Time based seek supported, second byte range seek supported (not sure about the order now), so 01 = only byte seek, 10 = time based, 11 = both, 00 = none
|
||||
|
@ -156,6 +157,7 @@ namespace MediaBrowser.Model.Dlna
|
|||
packetLength,
|
||||
timestamp,
|
||||
isAnamorphic,
|
||||
isCabac,
|
||||
refFrames);
|
||||
|
||||
List<string> orgPnValues = new List<string>();
|
||||
|
|
|
@ -35,7 +35,9 @@ namespace MediaBrowser.Model.Dlna
|
|||
public string ModelUrl { get; set; }
|
||||
public string SerialNumber { get; set; }
|
||||
public bool IgnoreTranscodeByteRangeRequests { get; set; }
|
||||
|
||||
public bool EnableAlbumArtInDidl { get; set; }
|
||||
public int? DidlAlbumArtLimit { get; set; }
|
||||
|
||||
public string SupportedMediaTypes { get; set; }
|
||||
|
||||
|
@ -279,6 +281,7 @@ namespace MediaBrowser.Model.Dlna
|
|||
int? packetLength,
|
||||
TransportStreamTimestamp timestamp,
|
||||
bool? isAnamorphic,
|
||||
bool? isCabac,
|
||||
int? refFrames)
|
||||
{
|
||||
container = StringHelper.TrimStart((container ?? string.Empty), '.');
|
||||
|
@ -313,7 +316,7 @@ namespace MediaBrowser.Model.Dlna
|
|||
var anyOff = false;
|
||||
foreach (ProfileCondition c in i.Conditions)
|
||||
{
|
||||
if (!conditionProcessor.IsVideoConditionSatisfied(c, audioBitrate, audioChannels, width, height, bitDepth, videoBitrate, videoProfile, videoLevel, videoFramerate, packetLength, timestamp, isAnamorphic, refFrames))
|
||||
if (!conditionProcessor.IsVideoConditionSatisfied(c, audioBitrate, audioChannels, width, height, bitDepth, videoBitrate, videoProfile, videoLevel, videoFramerate, packetLength, timestamp, isAnamorphic, isCabac, refFrames))
|
||||
{
|
||||
anyOff = true;
|
||||
break;
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
VideoProfile = 11,
|
||||
VideoTimestamp = 12,
|
||||
IsAnamorphic = 13,
|
||||
RefFrames = 14
|
||||
RefFrames = 14,
|
||||
IsCabac = 15
|
||||
}
|
||||
}
|
|
@ -6,8 +6,14 @@ namespace MediaBrowser.Model.Dlna.Profiles
|
|||
[XmlRoot("Profile")]
|
||||
public class AndroidProfile : DefaultProfile
|
||||
{
|
||||
public AndroidProfile(bool supportsHls,
|
||||
bool supportsMpegDash,
|
||||
public AndroidProfile()
|
||||
: this(true, true, new[] { "baseline", "constrained baseline" })
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public AndroidProfile(bool supportsHls,
|
||||
bool supportsMpegDash,
|
||||
string[] supportedH264Profiles)
|
||||
{
|
||||
Name = "Android";
|
||||
|
@ -108,7 +114,8 @@ namespace MediaBrowser.Model.Dlna.Profiles
|
|||
new ProfileCondition(ProfileConditionType.LessThanEqual, ProfileConditionValue.Width, "1920"),
|
||||
new ProfileCondition(ProfileConditionType.LessThanEqual, ProfileConditionValue.Height, "1080"),
|
||||
new ProfileCondition(ProfileConditionType.LessThanEqual, ProfileConditionValue.VideoBitDepth, "8"),
|
||||
new ProfileCondition(ProfileConditionType.NotEquals, ProfileConditionValue.IsAnamorphic, "true")
|
||||
new ProfileCondition(ProfileConditionType.NotEquals, ProfileConditionValue.IsAnamorphic, "true"),
|
||||
new ProfileCondition(ProfileConditionType.Equals, ProfileConditionValue.IsCabac, "true")
|
||||
}
|
||||
},
|
||||
|
||||
|
|
|
@ -419,6 +419,7 @@ namespace MediaBrowser.Model.Dlna
|
|||
string videoProfile = videoStream == null ? null : videoStream.Profile;
|
||||
float? videoFramerate = videoStream == null ? null : videoStream.AverageFrameRate ?? videoStream.AverageFrameRate;
|
||||
bool? isAnamorphic = videoStream == null ? null : videoStream.IsAnamorphic;
|
||||
bool? isCabac = videoStream == null ? null : videoStream.IsCabac;
|
||||
|
||||
int? audioBitrate = audioStream == null ? null : audioStream.BitRate;
|
||||
int? audioChannels = audioStream == null ? null : audioStream.Channels;
|
||||
|
@ -431,7 +432,7 @@ namespace MediaBrowser.Model.Dlna
|
|||
// Check container conditions
|
||||
foreach (ProfileCondition i in conditions)
|
||||
{
|
||||
if (!conditionProcessor.IsVideoConditionSatisfied(i, audioBitrate, audioChannels, width, height, bitDepth, videoBitrate, videoProfile, videoLevel, videoFramerate, packetLength, timestamp, isAnamorphic, refFrames))
|
||||
if (!conditionProcessor.IsVideoConditionSatisfied(i, audioBitrate, audioChannels, width, height, bitDepth, videoBitrate, videoProfile, videoLevel, videoFramerate, packetLength, timestamp, isAnamorphic, isCabac, refFrames))
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
@ -458,7 +459,7 @@ namespace MediaBrowser.Model.Dlna
|
|||
|
||||
foreach (ProfileCondition i in conditions)
|
||||
{
|
||||
if (!conditionProcessor.IsVideoConditionSatisfied(i, audioBitrate, audioChannels, width, height, bitDepth, videoBitrate, videoProfile, videoLevel, videoFramerate, packetLength, timestamp, isAnamorphic, refFrames))
|
||||
if (!conditionProcessor.IsVideoConditionSatisfied(i, audioBitrate, audioChannels, width, height, bitDepth, videoBitrate, videoProfile, videoLevel, videoFramerate, packetLength, timestamp, isAnamorphic, isCabac, refFrames))
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
@ -647,6 +648,7 @@ namespace MediaBrowser.Model.Dlna
|
|||
}
|
||||
case ProfileConditionValue.AudioProfile:
|
||||
case ProfileConditionValue.IsAnamorphic:
|
||||
case ProfileConditionValue.IsCabac:
|
||||
case ProfileConditionValue.Has64BitOffsets:
|
||||
case ProfileConditionValue.PacketLength:
|
||||
case ProfileConditionValue.VideoTimestamp:
|
||||
|
|
|
@ -456,6 +456,19 @@ namespace MediaBrowser.Model.Dlna
|
|||
}
|
||||
}
|
||||
|
||||
public bool? IsTargetCabac
|
||||
{
|
||||
get
|
||||
{
|
||||
if (IsDirectStream)
|
||||
{
|
||||
return TargetVideoStream == null ? null : TargetVideoStream.IsCabac;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
public int? TargetWidth
|
||||
{
|
||||
get
|
||||
|
|
|
@ -16,7 +16,7 @@ namespace MediaBrowser.Model.Dto
|
|||
/// This holds information about a BaseItem in a format that is convenient for the client.
|
||||
/// </summary>
|
||||
[DebuggerDisplay("Name = {Name}, ID = {Id}, Type = {Type}")]
|
||||
public class BaseItemDto : IHasProviderIds, IHasPropertyChangedEvent, IItemDto
|
||||
public class BaseItemDto : IHasProviderIds, IHasPropertyChangedEvent, IItemDto, IHasServerId
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets or sets the name.
|
||||
|
@ -24,6 +24,12 @@ namespace MediaBrowser.Model.Dto
|
|||
/// <value>The name.</value>
|
||||
public string Name { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the server identifier.
|
||||
/// </summary>
|
||||
/// <value>The server identifier.</value>
|
||||
public string ServerId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the id.
|
||||
/// </summary>
|
||||
|
@ -43,7 +49,8 @@ namespace MediaBrowser.Model.Dto
|
|||
public DateTime? DateCreated { get; set; }
|
||||
|
||||
public DateTime? DateLastMediaAdded { get; set; }
|
||||
|
||||
public ExtraType? ExtraType { get; set; }
|
||||
|
||||
public int? AirsBeforeSeasonNumber { get; set; }
|
||||
public int? AirsAfterSeasonNumber { get; set; }
|
||||
public int? AirsBeforeEpisodeNumber { get; set; }
|
||||
|
|
8
MediaBrowser.Model/Dto/IHasServerId.cs
Normal file
8
MediaBrowser.Model/Dto/IHasServerId.cs
Normal file
|
@ -0,0 +1,8 @@
|
|||
|
||||
namespace MediaBrowser.Model.Dto
|
||||
{
|
||||
public interface IHasServerId
|
||||
{
|
||||
string ServerId { get; }
|
||||
}
|
||||
}
|
|
@ -12,7 +12,7 @@ namespace MediaBrowser.Model.Dto
|
|||
/// Class UserDto
|
||||
/// </summary>
|
||||
[DebuggerDisplay("Name = {Name}, ID = {Id}, HasPassword = {HasPassword}")]
|
||||
public class UserDto : IHasPropertyChangedEvent, IItemDto
|
||||
public class UserDto : IHasPropertyChangedEvent, IItemDto, IHasServerId
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets or sets the name.
|
||||
|
@ -20,6 +20,12 @@ namespace MediaBrowser.Model.Dto
|
|||
/// <value>The name.</value>
|
||||
public string Name { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the server identifier.
|
||||
/// </summary>
|
||||
/// <value>The server identifier.</value>
|
||||
public string ServerId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the name of the connect user.
|
||||
/// </summary>
|
||||
|
|
|
@ -175,5 +175,11 @@ namespace MediaBrowser.Model.Entities
|
|||
/// </summary>
|
||||
/// <value><c>true</c> if this instance is anamorphic; otherwise, <c>false</c>.</value>
|
||||
public bool? IsAnamorphic { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a value indicating whether this instance is cabac.
|
||||
/// </summary>
|
||||
/// <value><c>null</c> if [is cabac] contains no value, <c>true</c> if [is cabac]; otherwise, <c>false</c>.</value>
|
||||
public bool? IsCabac { get; set; }
|
||||
}
|
||||
}
|
||||
|
|
|
@ -121,6 +121,7 @@
|
|||
<Compile Include="Dlna\SubtitleDeliveryMethod.cs" />
|
||||
<Compile Include="Dlna\SubtitleStreamInfo.cs" />
|
||||
<Compile Include="Drawing\ImageOrientation.cs" />
|
||||
<Compile Include="Dto\IHasServerId.cs" />
|
||||
<Compile Include="Dto\MediaSourceType.cs" />
|
||||
<Compile Include="Dto\StreamOptions.cs" />
|
||||
<Compile Include="Dto\VideoStreamOptions.cs" />
|
||||
|
@ -402,7 +403,6 @@
|
|||
<Compile Include="Updates\PackageInfo.cs" />
|
||||
<Compile Include="Updates\PackageVersionInfo.cs" />
|
||||
<Compile Include="Users\AuthenticationResult.cs" />
|
||||
<Compile Include="Weather\WeatherUnits.cs" />
|
||||
<None Include="Fody.targets" />
|
||||
<None Include="FodyWeavers.xml" />
|
||||
<None Include="MediaBrowser.Model.snk" />
|
||||
|
|
|
@ -5,26 +5,7 @@ namespace MediaBrowser.Model.Querying
|
|||
/// <summary>
|
||||
/// Represents the result of a query for items
|
||||
/// </summary>
|
||||
public class ItemsResult
|
||||
public class ItemsResult : QueryResult<BaseItemDto>
|
||||
{
|
||||
/// <summary>
|
||||
/// The set of items returned based on sorting, paging, etc
|
||||
/// </summary>
|
||||
/// <value>The items.</value>
|
||||
public BaseItemDto[] Items { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The total number of records available
|
||||
/// </summary>
|
||||
/// <value>The total record count.</value>
|
||||
public int TotalRecordCount { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="ItemsResult"/> class.
|
||||
/// </summary>
|
||||
public ItemsResult()
|
||||
{
|
||||
Items = new BaseItemDto[] { };
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,17 +0,0 @@
|
|||
namespace MediaBrowser.Model.Weather
|
||||
{
|
||||
/// <summary>
|
||||
/// Enum WeatherUnits
|
||||
/// </summary>
|
||||
public enum WeatherUnits
|
||||
{
|
||||
/// <summary>
|
||||
/// The fahrenheit
|
||||
/// </summary>
|
||||
Fahrenheit,
|
||||
/// <summary>
|
||||
/// The celsius
|
||||
/// </summary>
|
||||
Celsius
|
||||
}
|
||||
}
|
|
@ -286,6 +286,7 @@ namespace MediaBrowser.Providers.MediaInfo
|
|||
{
|
||||
var result = new MediaInfoLib().GetVideoInfo(video.Path);
|
||||
|
||||
videoStream.IsCabac = result.IsCabac ?? videoStream.IsCabac;
|
||||
videoStream.IsInterlaced = result.IsInterlaced ?? videoStream.IsInterlaced;
|
||||
videoStream.BitDepth = result.BitDepth ?? videoStream.BitDepth;
|
||||
videoStream.RefFrames = result.RefFrames;
|
||||
|
|
|
@ -18,7 +18,7 @@ namespace MediaBrowser.Providers.Movies
|
|||
{
|
||||
class FanartMovieUpdatesPostScanTask : ILibraryPostScanTask
|
||||
{
|
||||
private const string UpdatesUrl = "http://api.fanart.tv/webservice/newmovies/{0}/{1}/";
|
||||
private const string UpdatesUrl = "http://webservice.fanart.tv/v3/movies/latest?api_key={0}&date={1}";
|
||||
|
||||
/// <summary>
|
||||
/// The _HTTP client
|
||||
|
@ -118,11 +118,26 @@ namespace MediaBrowser.Providers.Movies
|
|||
return new List<string>();
|
||||
}
|
||||
|
||||
var updates = _jsonSerializer.DeserializeFromString<List<FanartUpdatesPostScanTask.FanArtUpdate>>(json);
|
||||
var updates = _jsonSerializer.DeserializeFromString<List<RootObject>>(json);
|
||||
|
||||
var existingDictionary = existingIds.ToDictionary(i => i, StringComparer.OrdinalIgnoreCase);
|
||||
|
||||
return updates.Select(i => i.id).Where(existingDictionary.ContainsKey);
|
||||
return updates.SelectMany(i =>
|
||||
{
|
||||
var list = new List<string>();
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(i.imdb_id))
|
||||
{
|
||||
list.Add(i.imdb_id);
|
||||
}
|
||||
if (!string.IsNullOrWhiteSpace(i.tmdb_id))
|
||||
{
|
||||
list.Add(i.tmdb_id);
|
||||
}
|
||||
|
||||
return list;
|
||||
|
||||
}).Where(existingDictionary.ContainsKey);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -136,7 +151,7 @@ namespace MediaBrowser.Providers.Movies
|
|||
{
|
||||
_logger.Info("Updating movie " + id);
|
||||
|
||||
await FanartMovieImageProvider.Current.DownloadMovieXml(id, cancellationToken).ConfigureAwait(false);
|
||||
await FanartMovieImageProvider.Current.DownloadMovieJson(id, cancellationToken).ConfigureAwait(false);
|
||||
|
||||
numComplete++;
|
||||
double percent = numComplete;
|
||||
|
@ -157,9 +172,10 @@ namespace MediaBrowser.Providers.Movies
|
|||
return (dateTime - new DateTime(1970, 1, 1).ToUniversalTime()).TotalSeconds;
|
||||
}
|
||||
|
||||
public class FanArtUpdate
|
||||
public class RootObject
|
||||
{
|
||||
public string id { get; set; }
|
||||
public string tmdb_id { get; set; }
|
||||
public string imdb_id { get; set; }
|
||||
public string name { get; set; }
|
||||
public string new_images { get; set; }
|
||||
public string total_images { get; set; }
|
||||
|
|
|
@ -1,25 +1,22 @@
|
|||
using MediaBrowser.Common.Configuration;
|
||||
using MediaBrowser.Common.IO;
|
||||
using MediaBrowser.Common.Net;
|
||||
using MediaBrowser.Controller.Channels;
|
||||
using MediaBrowser.Controller.Configuration;
|
||||
using MediaBrowser.Controller.Entities;
|
||||
using MediaBrowser.Controller.Entities.Movies;
|
||||
using MediaBrowser.Controller.Providers;
|
||||
using MediaBrowser.Model.Channels;
|
||||
using MediaBrowser.Model.Dto;
|
||||
using MediaBrowser.Model.Entities;
|
||||
using MediaBrowser.Model.Providers;
|
||||
using MediaBrowser.Model.Serialization;
|
||||
using MediaBrowser.Providers.Music;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using System.Xml;
|
||||
|
||||
namespace MediaBrowser.Providers.Movies
|
||||
{
|
||||
|
@ -29,16 +26,19 @@ namespace MediaBrowser.Providers.Movies
|
|||
private readonly IServerConfigurationManager _config;
|
||||
private readonly IHttpClient _httpClient;
|
||||
private readonly IFileSystem _fileSystem;
|
||||
private readonly IJsonSerializer _json;
|
||||
|
||||
private const string FanArtBaseUrl = "http://api.fanart.tv/webservice/movie/{0}/{1}/xml/all/1/1";
|
||||
private const string FanArtBaseUrl = "http://webservice.fanart.tv/v3/movies/{1}?api_key={0}";
|
||||
// &client_key=52c813aa7b8c8b3bb87f4797532a2f8c
|
||||
|
||||
internal static FanartMovieImageProvider Current;
|
||||
|
||||
public FanartMovieImageProvider(IServerConfigurationManager config, IHttpClient httpClient, IFileSystem fileSystem)
|
||||
public FanartMovieImageProvider(IServerConfigurationManager config, IHttpClient httpClient, IFileSystem fileSystem, IJsonSerializer json)
|
||||
{
|
||||
_config = config;
|
||||
_httpClient = httpClient;
|
||||
_fileSystem = fileSystem;
|
||||
_json = json;
|
||||
|
||||
Current = this;
|
||||
}
|
||||
|
@ -88,13 +88,13 @@ namespace MediaBrowser.Providers.Movies
|
|||
|
||||
if (!string.IsNullOrEmpty(movieId))
|
||||
{
|
||||
await EnsureMovieXml(movieId, cancellationToken).ConfigureAwait(false);
|
||||
await EnsureMovieJson(movieId, cancellationToken).ConfigureAwait(false);
|
||||
|
||||
var xmlPath = GetFanartXmlPath(movieId);
|
||||
var path = GetFanartJsonPath(movieId);
|
||||
|
||||
try
|
||||
{
|
||||
AddImages(list, xmlPath, cancellationToken);
|
||||
AddImages(list, path, cancellationToken);
|
||||
}
|
||||
catch (FileNotFoundException)
|
||||
{
|
||||
|
@ -130,198 +130,63 @@ namespace MediaBrowser.Providers.Movies
|
|||
.ThenByDescending(i => i.CommunityRating ?? 0);
|
||||
}
|
||||
|
||||
private void AddImages(List<RemoteImageInfo> list, string xmlPath, CancellationToken cancellationToken)
|
||||
private void AddImages(List<RemoteImageInfo> list, string path, CancellationToken cancellationToken)
|
||||
{
|
||||
using (var streamReader = new StreamReader(xmlPath, Encoding.UTF8))
|
||||
{
|
||||
// Use XmlReader for best performance
|
||||
using (var reader = XmlReader.Create(streamReader, new XmlReaderSettings
|
||||
{
|
||||
CheckCharacters = false,
|
||||
IgnoreProcessingInstructions = true,
|
||||
IgnoreComments = true,
|
||||
ValidationType = ValidationType.None
|
||||
}))
|
||||
{
|
||||
reader.MoveToContent();
|
||||
var root = _json.DeserializeFromFile<RootObject>(path);
|
||||
|
||||
// Loop through each element
|
||||
while (reader.Read())
|
||||
{
|
||||
cancellationToken.ThrowIfCancellationRequested();
|
||||
|
||||
if (reader.NodeType == XmlNodeType.Element)
|
||||
{
|
||||
switch (reader.Name)
|
||||
{
|
||||
case "movie":
|
||||
{
|
||||
using (var subReader = reader.ReadSubtree())
|
||||
{
|
||||
AddImages(list, subReader, cancellationToken);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
reader.Skip();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
AddImages(list, root, cancellationToken);
|
||||
}
|
||||
|
||||
private void AddImages(List<RemoteImageInfo> list, XmlReader reader, CancellationToken cancellationToken)
|
||||
private void AddImages(List<RemoteImageInfo> list, RootObject obj, CancellationToken cancellationToken)
|
||||
{
|
||||
reader.MoveToContent();
|
||||
|
||||
while (reader.Read())
|
||||
{
|
||||
if (reader.NodeType == XmlNodeType.Element)
|
||||
{
|
||||
switch (reader.Name)
|
||||
{
|
||||
case "hdmoviecleararts":
|
||||
{
|
||||
using (var subReader = reader.ReadSubtree())
|
||||
{
|
||||
PopulateImageCategory(list, subReader, cancellationToken, ImageType.Art, 1000, 562);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case "hdmovielogos":
|
||||
{
|
||||
using (var subReader = reader.ReadSubtree())
|
||||
{
|
||||
PopulateImageCategory(list, subReader, cancellationToken, ImageType.Logo, 800, 310);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case "moviediscs":
|
||||
{
|
||||
using (var subReader = reader.ReadSubtree())
|
||||
{
|
||||
PopulateImageCategory(list, subReader, cancellationToken, ImageType.Disc, 1000, 1000);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case "movieposters":
|
||||
{
|
||||
using (var subReader = reader.ReadSubtree())
|
||||
{
|
||||
PopulateImageCategory(list, subReader, cancellationToken, ImageType.Primary, 1000, 1426);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case "movielogos":
|
||||
{
|
||||
using (var subReader = reader.ReadSubtree())
|
||||
{
|
||||
PopulateImageCategory(list, subReader, cancellationToken, ImageType.Logo, 400, 155);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case "moviearts":
|
||||
{
|
||||
using (var subReader = reader.ReadSubtree())
|
||||
{
|
||||
PopulateImageCategory(list, subReader, cancellationToken, ImageType.Art, 500, 281);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case "moviethumbs":
|
||||
{
|
||||
using (var subReader = reader.ReadSubtree())
|
||||
{
|
||||
PopulateImageCategory(list, subReader, cancellationToken, ImageType.Thumb, 1000, 562);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case "moviebanners":
|
||||
{
|
||||
using (var subReader = reader.ReadSubtree())
|
||||
{
|
||||
PopulateImageCategory(list, subReader, cancellationToken, ImageType.Banner, 1000, 185);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case "moviebackgrounds":
|
||||
{
|
||||
using (var subReader = reader.ReadSubtree())
|
||||
{
|
||||
PopulateImageCategory(list, subReader, cancellationToken, ImageType.Backdrop, 1920, 1080);
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
using (reader.ReadSubtree())
|
||||
{
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
PopulateImages(list, obj.hdmovieclearart, ImageType.Art, 1000, 562);
|
||||
PopulateImages(list, obj.hdmovielogo, ImageType.Logo, 800, 310);
|
||||
PopulateImages(list, obj.moviedisc, ImageType.Disc, 1000, 1000);
|
||||
PopulateImages(list, obj.movieposter, ImageType.Primary, 1000, 1426);
|
||||
PopulateImages(list, obj.movielogo, ImageType.Logo, 400, 155);
|
||||
PopulateImages(list, obj.movieart, ImageType.Art, 500, 281);
|
||||
PopulateImages(list, obj.moviethumb, ImageType.Thumb, 1000, 562);
|
||||
PopulateImages(list, obj.moviebanner, ImageType.Banner, 1000, 185);
|
||||
PopulateImages(list, obj.moviebackground, ImageType.Backdrop, 1920, 1080);
|
||||
}
|
||||
|
||||
private void PopulateImageCategory(List<RemoteImageInfo> list, XmlReader reader, CancellationToken cancellationToken, ImageType type, int width, int height)
|
||||
private void PopulateImages(List<RemoteImageInfo> list, List<Image> images, ImageType type, int width, int height)
|
||||
{
|
||||
reader.MoveToContent();
|
||||
|
||||
while (reader.Read())
|
||||
if (images == null)
|
||||
{
|
||||
cancellationToken.ThrowIfCancellationRequested();
|
||||
|
||||
if (reader.NodeType == XmlNodeType.Element)
|
||||
{
|
||||
switch (reader.Name)
|
||||
{
|
||||
case "hdmovielogo":
|
||||
case "moviedisc":
|
||||
case "hdmovieclearart":
|
||||
case "movieposter":
|
||||
case "movielogo":
|
||||
case "movieart":
|
||||
case "moviethumb":
|
||||
case "moviebanner":
|
||||
case "moviebackground":
|
||||
{
|
||||
var url = reader.GetAttribute("url");
|
||||
|
||||
if (!string.IsNullOrEmpty(url))
|
||||
{
|
||||
var likesString = reader.GetAttribute("likes");
|
||||
int likes;
|
||||
|
||||
var info = new RemoteImageInfo
|
||||
{
|
||||
RatingType = RatingType.Likes,
|
||||
Type = type,
|
||||
Width = width,
|
||||
Height = height,
|
||||
ProviderName = Name,
|
||||
Url = url,
|
||||
Language = reader.GetAttribute("lang")
|
||||
};
|
||||
|
||||
if (!string.IsNullOrEmpty(likesString) && int.TryParse(likesString, NumberStyles.Any, _usCulture, out likes))
|
||||
{
|
||||
info.CommunityRating = likes;
|
||||
}
|
||||
|
||||
list.Add(info);
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
reader.Skip();
|
||||
break;
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
list.AddRange(images.Select(i =>
|
||||
{
|
||||
var url = i.url;
|
||||
|
||||
if (!string.IsNullOrEmpty(url))
|
||||
{
|
||||
var likesString = i.likes;
|
||||
int likes;
|
||||
|
||||
var info = new RemoteImageInfo
|
||||
{
|
||||
RatingType = RatingType.Likes,
|
||||
Type = type,
|
||||
Width = width,
|
||||
Height = height,
|
||||
ProviderName = Name,
|
||||
Url = url,
|
||||
Language = i.lang
|
||||
};
|
||||
|
||||
if (!string.IsNullOrEmpty(likesString) && int.TryParse(likesString, NumberStyles.Any, _usCulture, out likes))
|
||||
{
|
||||
info.CommunityRating = likes;
|
||||
}
|
||||
|
||||
return info;
|
||||
}
|
||||
|
||||
return null;
|
||||
}).Where(i => i != null));
|
||||
}
|
||||
|
||||
public int Order
|
||||
|
@ -347,13 +212,17 @@ namespace MediaBrowser.Providers.Movies
|
|||
}
|
||||
|
||||
var id = item.GetProviderId(MetadataProviders.Tmdb);
|
||||
if (string.IsNullOrEmpty(id))
|
||||
{
|
||||
id = item.GetProviderId(MetadataProviders.Imdb);
|
||||
}
|
||||
|
||||
if (!string.IsNullOrEmpty(id))
|
||||
{
|
||||
// Process images
|
||||
var xmlPath = GetFanartXmlPath(id);
|
||||
var path = GetFanartJsonPath(id);
|
||||
|
||||
var fileInfo = new FileInfo(xmlPath);
|
||||
var fileInfo = new FileInfo(path);
|
||||
|
||||
return !fileInfo.Exists || _fileSystem.GetLastWriteTimeUtc(fileInfo) > date;
|
||||
}
|
||||
|
@ -364,12 +233,12 @@ namespace MediaBrowser.Providers.Movies
|
|||
/// <summary>
|
||||
/// Gets the movie data path.
|
||||
/// </summary>
|
||||
/// <param name="appPaths">The app paths.</param>
|
||||
/// <param name="tmdbId">The TMDB id.</param>
|
||||
/// <param name="appPaths">The application paths.</param>
|
||||
/// <param name="id">The identifier.</param>
|
||||
/// <returns>System.String.</returns>
|
||||
internal static string GetMovieDataPath(IApplicationPaths appPaths, string tmdbId)
|
||||
internal static string GetMovieDataPath(IApplicationPaths appPaths, string id)
|
||||
{
|
||||
var dataPath = Path.Combine(GetMoviesDataPath(appPaths), tmdbId);
|
||||
var dataPath = Path.Combine(GetMoviesDataPath(appPaths), id);
|
||||
|
||||
return dataPath;
|
||||
}
|
||||
|
@ -386,27 +255,27 @@ namespace MediaBrowser.Providers.Movies
|
|||
return dataPath;
|
||||
}
|
||||
|
||||
public string GetFanartXmlPath(string tmdbId)
|
||||
public string GetFanartJsonPath(string id)
|
||||
{
|
||||
var movieDataPath = GetMovieDataPath(_config.ApplicationPaths, tmdbId);
|
||||
return Path.Combine(movieDataPath, "fanart.xml");
|
||||
var movieDataPath = GetMovieDataPath(_config.ApplicationPaths, id);
|
||||
return Path.Combine(movieDataPath, "fanart.json");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Downloads the movie XML.
|
||||
/// Downloads the movie json.
|
||||
/// </summary>
|
||||
/// <param name="tmdbId">The TMDB id.</param>
|
||||
/// <param name="id">The identifier.</param>
|
||||
/// <param name="cancellationToken">The cancellation token.</param>
|
||||
/// <returns>Task.</returns>
|
||||
internal async Task DownloadMovieXml(string tmdbId, CancellationToken cancellationToken)
|
||||
internal async Task DownloadMovieJson(string id, CancellationToken cancellationToken)
|
||||
{
|
||||
cancellationToken.ThrowIfCancellationRequested();
|
||||
|
||||
var url = string.Format(FanArtBaseUrl, FanartArtistProvider.ApiKey, tmdbId);
|
||||
var url = string.Format(FanArtBaseUrl, FanartArtistProvider.ApiKey, id);
|
||||
|
||||
var xmlPath = GetFanartXmlPath(tmdbId);
|
||||
var path = GetFanartJsonPath(id);
|
||||
|
||||
Directory.CreateDirectory(Path.GetDirectoryName(xmlPath));
|
||||
Directory.CreateDirectory(Path.GetDirectoryName(path));
|
||||
|
||||
using (var response = await _httpClient.Get(new HttpRequestOptions
|
||||
{
|
||||
|
@ -416,17 +285,17 @@ namespace MediaBrowser.Providers.Movies
|
|||
|
||||
}).ConfigureAwait(false))
|
||||
{
|
||||
using (var xmlFileStream = _fileSystem.GetFileStream(xmlPath, FileMode.Create, FileAccess.Write, FileShare.Read, true))
|
||||
using (var fileStream = _fileSystem.GetFileStream(path, FileMode.Create, FileAccess.Write, FileShare.Read, true))
|
||||
{
|
||||
await response.CopyToAsync(xmlFileStream).ConfigureAwait(false);
|
||||
await response.CopyToAsync(fileStream).ConfigureAwait(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private readonly Task _cachedTask = Task.FromResult(true);
|
||||
internal Task EnsureMovieXml(string tmdbId, CancellationToken cancellationToken)
|
||||
internal Task EnsureMovieJson(string id, CancellationToken cancellationToken)
|
||||
{
|
||||
var path = GetFanartXmlPath(tmdbId);
|
||||
var path = GetFanartJsonPath(id);
|
||||
|
||||
var fileInfo = _fileSystem.GetFileSystemInfo(path);
|
||||
|
||||
|
@ -438,7 +307,31 @@ namespace MediaBrowser.Providers.Movies
|
|||
}
|
||||
}
|
||||
|
||||
return DownloadMovieXml(tmdbId, cancellationToken);
|
||||
return DownloadMovieJson(id, cancellationToken);
|
||||
}
|
||||
|
||||
public class Image
|
||||
{
|
||||
public string id { get; set; }
|
||||
public string url { get; set; }
|
||||
public string lang { get; set; }
|
||||
public string likes { get; set; }
|
||||
}
|
||||
|
||||
public class RootObject
|
||||
{
|
||||
public string name { get; set; }
|
||||
public string tmdb_id { get; set; }
|
||||
public string imdb_id { get; set; }
|
||||
public List<Image> hdmovielogo { get; set; }
|
||||
public List<Image> moviedisc { get; set; }
|
||||
public List<Image> movielogo { get; set; }
|
||||
public List<Image> movieposter { get; set; }
|
||||
public List<Image> hdmovieclearart { get; set; }
|
||||
public List<Image> movieart { get; set; }
|
||||
public List<Image> moviebackground { get; set; }
|
||||
public List<Image> moviebanner { get; set; }
|
||||
public List<Image> moviethumb { get; set; }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,15 +1,13 @@
|
|||
using MediaBrowser.Common.IO;
|
||||
using MediaBrowser.Controller.Configuration;
|
||||
using MediaBrowser.Controller.Entities;
|
||||
using MediaBrowser.Controller.Entities.Audio;
|
||||
using MediaBrowser.Controller.Library;
|
||||
using MediaBrowser.Controller.Providers;
|
||||
using MediaBrowser.Model.Entities;
|
||||
using MediaBrowser.Model.Logging;
|
||||
using MediaBrowser.Providers.Manager;
|
||||
using System.Collections.Generic;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using System.Linq;
|
||||
|
||||
namespace MediaBrowser.Providers.Music
|
||||
{
|
||||
|
@ -36,9 +34,9 @@ namespace MediaBrowser.Providers.Music
|
|||
target.Album = source.Album;
|
||||
}
|
||||
|
||||
if (replaceData || string.IsNullOrEmpty(target.Artist))
|
||||
if (replaceData || target.Artists.Count == 0)
|
||||
{
|
||||
target.Artist = source.Artist;
|
||||
target.Artists = source.Artists.ToList();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -7,16 +7,15 @@ using MediaBrowser.Controller.Providers;
|
|||
using MediaBrowser.Model.Dto;
|
||||
using MediaBrowser.Model.Entities;
|
||||
using MediaBrowser.Model.Providers;
|
||||
using MediaBrowser.Model.Serialization;
|
||||
using MediaBrowser.Providers.Music;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using System.Xml;
|
||||
|
||||
namespace MediaBrowser.Providers.TV
|
||||
{
|
||||
|
@ -26,12 +25,14 @@ namespace MediaBrowser.Providers.TV
|
|||
private readonly IServerConfigurationManager _config;
|
||||
private readonly IHttpClient _httpClient;
|
||||
private readonly IFileSystem _fileSystem;
|
||||
private readonly IJsonSerializer _json;
|
||||
|
||||
public FanArtSeasonProvider(IServerConfigurationManager config, IHttpClient httpClient, IFileSystem fileSystem)
|
||||
public FanArtSeasonProvider(IServerConfigurationManager config, IHttpClient httpClient, IFileSystem fileSystem, IJsonSerializer json)
|
||||
{
|
||||
_config = config;
|
||||
_httpClient = httpClient;
|
||||
_fileSystem = fileSystem;
|
||||
_json = json;
|
||||
}
|
||||
|
||||
public string Name
|
||||
|
@ -71,14 +72,14 @@ namespace MediaBrowser.Providers.TV
|
|||
|
||||
if (!string.IsNullOrEmpty(id) && season.IndexNumber.HasValue)
|
||||
{
|
||||
await FanartSeriesProvider.Current.EnsureSeriesXml(id, cancellationToken).ConfigureAwait(false);
|
||||
await FanartSeriesProvider.Current.EnsureSeriesJson(id, cancellationToken).ConfigureAwait(false);
|
||||
|
||||
var xmlPath = FanartSeriesProvider.Current.GetFanartXmlPath(id);
|
||||
var path = FanartSeriesProvider.Current.GetFanartJsonPath(id);
|
||||
|
||||
try
|
||||
{
|
||||
int seasonNumber = AdjustForSeriesOffset(series, season.IndexNumber.Value);
|
||||
AddImages(list, seasonNumber, xmlPath, cancellationToken);
|
||||
AddImages(list, seasonNumber, path, cancellationToken);
|
||||
}
|
||||
catch (FileNotFoundException)
|
||||
{
|
||||
|
@ -125,142 +126,67 @@ namespace MediaBrowser.Providers.TV
|
|||
return seasonNumber;
|
||||
}
|
||||
|
||||
private void AddImages(List<RemoteImageInfo> list, int seasonNumber, string xmlPath, CancellationToken cancellationToken)
|
||||
private void AddImages(List<RemoteImageInfo> list, int seasonNumber, string path, CancellationToken cancellationToken)
|
||||
{
|
||||
using (var streamReader = new StreamReader(xmlPath, Encoding.UTF8))
|
||||
{
|
||||
// Use XmlReader for best performance
|
||||
using (var reader = XmlReader.Create(streamReader, new XmlReaderSettings
|
||||
{
|
||||
CheckCharacters = false,
|
||||
IgnoreProcessingInstructions = true,
|
||||
IgnoreComments = true,
|
||||
ValidationType = ValidationType.None
|
||||
}))
|
||||
{
|
||||
reader.MoveToContent();
|
||||
var root = _json.DeserializeFromFile<FanartSeriesProvider.RootObject>(path);
|
||||
|
||||
// Loop through each element
|
||||
while (reader.Read())
|
||||
{
|
||||
cancellationToken.ThrowIfCancellationRequested();
|
||||
|
||||
if (reader.NodeType == XmlNodeType.Element)
|
||||
{
|
||||
switch (reader.Name)
|
||||
{
|
||||
case "series":
|
||||
{
|
||||
using (var subReader = reader.ReadSubtree())
|
||||
{
|
||||
AddImages(list, subReader, seasonNumber, cancellationToken);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
reader.Skip();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
AddImages(list, root, seasonNumber, cancellationToken);
|
||||
}
|
||||
|
||||
private void AddImages(List<RemoteImageInfo> list, XmlReader reader, int seasonNumber, CancellationToken cancellationToken)
|
||||
private void AddImages(List<RemoteImageInfo> list, FanartSeriesProvider.RootObject obj, int seasonNumber, CancellationToken cancellationToken)
|
||||
{
|
||||
reader.MoveToContent();
|
||||
|
||||
while (reader.Read())
|
||||
{
|
||||
if (reader.NodeType == XmlNodeType.Element)
|
||||
{
|
||||
switch (reader.Name)
|
||||
{
|
||||
case "seasonthumbs":
|
||||
{
|
||||
using (var subReader = reader.ReadSubtree())
|
||||
{
|
||||
PopulateImageCategory(list, subReader, cancellationToken, ImageType.Thumb, 500, 281, seasonNumber);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case "showbackgrounds":
|
||||
{
|
||||
using (var subReader = reader.ReadSubtree())
|
||||
{
|
||||
PopulateImageCategory(list, subReader, cancellationToken, ImageType.Backdrop, 1920, 1080, seasonNumber);
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
using (reader.ReadSubtree())
|
||||
{
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
PopulateImages(list, obj.seasonthumb, ImageType.Thumb, 500, 281, seasonNumber);
|
||||
PopulateImages(list, obj.showbackground, ImageType.Backdrop, 1920, 1080, seasonNumber);
|
||||
}
|
||||
|
||||
private void PopulateImageCategory(List<RemoteImageInfo> list, XmlReader reader, CancellationToken cancellationToken, ImageType type, int width, int height, int seasonNumber)
|
||||
private void PopulateImages(List<RemoteImageInfo> list,
|
||||
List<FanartSeriesProvider.Image> images,
|
||||
ImageType type,
|
||||
int width,
|
||||
int height,
|
||||
int seasonNumber)
|
||||
{
|
||||
reader.MoveToContent();
|
||||
|
||||
while (reader.Read())
|
||||
if (images == null)
|
||||
{
|
||||
cancellationToken.ThrowIfCancellationRequested();
|
||||
|
||||
if (reader.NodeType == XmlNodeType.Element)
|
||||
{
|
||||
switch (reader.Name)
|
||||
{
|
||||
case "seasonthumb":
|
||||
case "showbackground":
|
||||
{
|
||||
var url = reader.GetAttribute("url");
|
||||
var season = reader.GetAttribute("season");
|
||||
|
||||
int imageSeasonNumber;
|
||||
|
||||
if (!string.IsNullOrEmpty(url) &&
|
||||
!string.IsNullOrEmpty(season) &&
|
||||
int.TryParse(season, NumberStyles.Any, _usCulture, out imageSeasonNumber) &&
|
||||
seasonNumber == imageSeasonNumber)
|
||||
{
|
||||
var likesString = reader.GetAttribute("likes");
|
||||
int likes;
|
||||
|
||||
var info = new RemoteImageInfo
|
||||
{
|
||||
RatingType = RatingType.Likes,
|
||||
Type = type,
|
||||
Width = width,
|
||||
Height = height,
|
||||
ProviderName = Name,
|
||||
Url = url,
|
||||
Language = reader.GetAttribute("lang")
|
||||
};
|
||||
|
||||
if (!string.IsNullOrEmpty(likesString) && int.TryParse(likesString, NumberStyles.Any, _usCulture, out likes))
|
||||
{
|
||||
info.CommunityRating = likes;
|
||||
}
|
||||
|
||||
list.Add(info);
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
default:
|
||||
reader.Skip();
|
||||
break;
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
list.AddRange(images.Select(i =>
|
||||
{
|
||||
var url = i.url;
|
||||
var season = i.season;
|
||||
|
||||
int imageSeasonNumber;
|
||||
|
||||
if (!string.IsNullOrEmpty(url) &&
|
||||
!string.IsNullOrEmpty(season) &&
|
||||
int.TryParse(season, NumberStyles.Any, _usCulture, out imageSeasonNumber) &&
|
||||
seasonNumber == imageSeasonNumber)
|
||||
{
|
||||
var likesString = i.likes;
|
||||
int likes;
|
||||
|
||||
var info = new RemoteImageInfo
|
||||
{
|
||||
RatingType = RatingType.Likes,
|
||||
Type = type,
|
||||
Width = width,
|
||||
Height = height,
|
||||
ProviderName = Name,
|
||||
Url = url,
|
||||
Language = i.lang
|
||||
};
|
||||
|
||||
if (!string.IsNullOrEmpty(likesString) && int.TryParse(likesString, NumberStyles.Any, _usCulture, out likes))
|
||||
{
|
||||
info.CommunityRating = likes;
|
||||
}
|
||||
|
||||
return info;
|
||||
}
|
||||
|
||||
return null;
|
||||
}).Where(i => i != null));
|
||||
}
|
||||
|
||||
public int Order
|
||||
|
@ -298,9 +224,9 @@ namespace MediaBrowser.Providers.TV
|
|||
if (!String.IsNullOrEmpty(tvdbId))
|
||||
{
|
||||
// Process images
|
||||
var imagesXmlPath = FanartSeriesProvider.Current.GetFanartXmlPath(tvdbId);
|
||||
var imagesFilePath = FanartSeriesProvider.Current.GetFanartJsonPath(tvdbId);
|
||||
|
||||
var fileInfo = new FileInfo(imagesXmlPath);
|
||||
var fileInfo = new FileInfo(imagesFilePath);
|
||||
|
||||
return !fileInfo.Exists || _fileSystem.GetLastWriteTimeUtc(fileInfo) > date;
|
||||
}
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user