Merge remote-tracking branch 'upstream/master' into docker

pull/702/head
HurricaneHernandez 10 years ago
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,44 +652,25 @@ 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 (operationCanceledException != null)
if (webException != null)
{
// Cleanup
DeleteTempFile(tempFile);
return GetCancellationException(options.Url, options.CancellationToken, operationCanceledException);
return GetException(webException, options);
}
_logger.ErrorException("Error getting response from " + options.Url, ex);
// Cleanup
DeleteTempFile(tempFile);
var httpRequestException = ex as HttpRequestException;
var operationCanceledException = ex as OperationCanceledException
?? ex.InnerException as OperationCanceledException;
if (httpRequestException != null)
if (operationCanceledException != null)
{
return new HttpException(ex.Message, ex);
return GetCancellationException(options.Url, options.CancellationToken, operationCanceledException);
}
var webException = ex as WebException;
if (webException != null)
{
throw GetException(webException, options);
}
_logger.ErrorException("Error getting response from " + options.Url, ex);
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,43 +29,35 @@ 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>();
Artists = new List<string>();
}
[IgnoreDataMember]
public List<string> Artists
public List<string> AllArtists
{
get
{
var list = new List<string>();
if (!string.IsNullOrEmpty(Artist))
{
list.Add(Artist);
}
return list;
return Artists;
}
}
[IgnoreDataMember]
public List<string> AllArtists
/// <summary>
/// TODO: Remove
/// </summary>
public string Artist
{
get
get { return Artists.FirstOrDefault(); }
set
{
var list = new List<string>();
if (!string.IsNullOrEmpty(Artist))
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

@ -230,29 +230,18 @@ namespace MediaBrowser.Controller.Library
}
/// <summary>
/// Gets the name of the meta file by.
/// Determines whether [contains meta file by name] [the specified name].
/// </summary>
/// <param name="name">The name.</param>
/// <returns>FileSystemInfo.</returns>
/// <exception cref="System.ArgumentNullException"></exception>
public FileSystemInfo GetMetaFileByName(string name)
/// <returns><c>true</c> if [contains meta file by name] [the specified name]; otherwise, <c>false</c>.</returns>
public bool ContainsMetaFileByName(string name)
{
if (string.IsNullOrEmpty(name))
{
throw new ArgumentNullException();
}
return GetFileSystemEntryByName(name);
}
/// <summary>
/// Determines whether [contains meta file by name] [the specified name].
/// </summary>
/// <param name="name">The name.</param>
/// <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;
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&lt;BaseItem&gt;.</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 item = serverItem.Item;
var childrenResult = (await GetChildrenSorted(folder, user, searchCriteria, sortCriteria, start, requested).ConfigureAwait(false));
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", GetClientId(context, contextStubType));
}
else
{
element.SetAttribute("parentID", item.Parent.Id.ToString("N"));
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);
if (info.Item != null)
{
var progress = GetProgressInfo(e.MediaInfo, info);
await _sessionManager.OnPlaybackStart(info).ConfigureAwait(false);
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);
if (info.Item != null)
{
var progress = GetProgressInfo(e.MediaInfo, info);
await _sessionManager.OnPlaybackProgress(info).ConfigureAwait(false);
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)
{
foreach (var childId in _itemRepository.GetChildren(item.Id))
{
AddItemFromId(childId, list);
}
}
else
if (item.MediaType == MediaType.Audio || item.MediaType == MediaType.Video)
{
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"
}
};
}
}
}

@ -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">
<CodecProfile type="Video" codec="h264">
<Conditions>
<ProfileCondition condition="LessThanEqual" property="Width" value="1920" isRequired="true" />
<ProfileCondition condition="LessThanEqual" property="Height" value="1080" isRequired="true" />
<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="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>

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; }

@ -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();
// Loop through each element
while (reader.Read())
{
cancellationToken.ThrowIfCancellationRequested();
var root = _json.DeserializeFromFile<RootObject>(path);
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();
if (images == null)
{
return;
}
while (reader.Read())
list.AddRange(images.Select(i =>
{
cancellationToken.ThrowIfCancellationRequested();
var url = i.url;
if (reader.NodeType == XmlNodeType.Element)
if (!string.IsNullOrEmpty(url))
{
switch (reader.Name)
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))
{
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;
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();
if (images == null)
{
return;
}
while (reader.Read())
list.AddRange(images.Select(i =>
{
cancellationToken.ThrowIfCancellationRequested();
var url = i.url;
var season = i.season;
if (reader.NodeType == XmlNodeType.Element)
int imageSeasonNumber;
if (!string.IsNullOrEmpty(url) &&
!string.IsNullOrEmpty(season) &&
int.TryParse(season, NumberStyles.Any, _usCulture, out imageSeasonNumber) &&
seasonNumber == imageSeasonNumber)
{
switch (reader.Name)
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))
{
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;
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…
Cancel
Save