mirror of
https://github.com/jellyfin/jellyfin.git
synced 2024-11-15 09:59:06 -07:00
update media source methods
This commit is contained in:
parent
3fe1c25c3e
commit
db315c4e32
@ -193,7 +193,7 @@ namespace Emby.Dlna.Didl
|
||||
{
|
||||
if (streamInfo == null)
|
||||
{
|
||||
var sources = _mediaSourceManager.GetStaticMediaSources(video, true, _user).ToList();
|
||||
var sources = _mediaSourceManager.GetStaticMediaSources(video, true, _user);
|
||||
|
||||
streamInfo = new StreamBuilder(_mediaEncoder, GetStreamBuilderLogger(options)).BuildVideoItem(new VideoOptions
|
||||
{
|
||||
@ -508,7 +508,7 @@ namespace Emby.Dlna.Didl
|
||||
|
||||
if (streamInfo == null)
|
||||
{
|
||||
var sources = _mediaSourceManager.GetStaticMediaSources(audio, true, _user).ToList();
|
||||
var sources = _mediaSourceManager.GetStaticMediaSources(audio, true, _user);
|
||||
|
||||
streamInfo = new StreamBuilder(_mediaEncoder, GetStreamBuilderLogger(options)).BuildAudioItem(new AudioOptions
|
||||
{
|
||||
|
@ -503,7 +503,7 @@ namespace Emby.Dlna.PlayTo
|
||||
|
||||
var hasMediaSources = item as IHasMediaSources;
|
||||
var mediaSources = hasMediaSources != null
|
||||
? (_mediaSourceManager.GetStaticMediaSources(hasMediaSources, true, user)).ToList()
|
||||
? (_mediaSourceManager.GetStaticMediaSources(hasMediaSources, true, user))
|
||||
: new List<MediaSourceInfo>();
|
||||
|
||||
var playlistItem = GetPlaylistItem(item, mediaSources, profile, _session.DeviceId, mediaSourceId, audioStreamIndex, subtitleStreamIndex);
|
||||
|
@ -113,7 +113,7 @@ namespace Emby.Server.Implementations.Data
|
||||
{
|
||||
get
|
||||
{
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@ -1972,20 +1972,7 @@ namespace Emby.Server.Implementations.Data
|
||||
/// <returns>Task{IEnumerable{ItemReview}}.</returns>
|
||||
public IEnumerable<ItemReview> GetCriticReviews(Guid itemId)
|
||||
{
|
||||
try
|
||||
{
|
||||
var path = Path.Combine(_criticReviewsPath, itemId + ".json");
|
||||
|
||||
return _jsonSerializer.DeserializeFromFile<List<ItemReview>>(path);
|
||||
}
|
||||
catch (FileNotFoundException)
|
||||
{
|
||||
return new List<ItemReview>();
|
||||
}
|
||||
catch (IOException)
|
||||
{
|
||||
return new List<ItemReview>();
|
||||
}
|
||||
return new List<ItemReview>();
|
||||
}
|
||||
|
||||
private readonly Task _cachedTask = Task.FromResult(true);
|
||||
@ -1997,12 +1984,6 @@ namespace Emby.Server.Implementations.Data
|
||||
/// <returns>Task.</returns>
|
||||
public Task SaveCriticReviews(Guid itemId, IEnumerable<ItemReview> criticReviews)
|
||||
{
|
||||
_fileSystem.CreateDirectory(_criticReviewsPath);
|
||||
|
||||
var path = Path.Combine(_criticReviewsPath, itemId + ".json");
|
||||
|
||||
_jsonSerializer.SerializeToFile(criticReviews.ToList(), path);
|
||||
|
||||
return _cachedTask;
|
||||
}
|
||||
|
||||
@ -5610,7 +5591,7 @@ namespace Emby.Server.Implementations.Data
|
||||
return item;
|
||||
}
|
||||
|
||||
public IEnumerable<MediaStream> GetMediaStreams(MediaStreamQuery query)
|
||||
public List<MediaStream> GetMediaStreams(MediaStreamQuery query)
|
||||
{
|
||||
CheckDisposed();
|
||||
|
||||
|
@ -95,7 +95,7 @@ namespace Emby.Server.Implementations.Data
|
||||
{
|
||||
get
|
||||
{
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -359,11 +359,11 @@ namespace Emby.Server.Implementations.Dto
|
||||
{
|
||||
if (user == null)
|
||||
{
|
||||
dto.MediaSources = _mediaSourceManager().GetStaticMediaSources(hasMediaSources, true).ToList();
|
||||
dto.MediaSources = _mediaSourceManager().GetStaticMediaSources(hasMediaSources, true);
|
||||
}
|
||||
else
|
||||
{
|
||||
dto.MediaSources = _mediaSourceManager().GetStaticMediaSources(hasMediaSources, true, user).ToList();
|
||||
dto.MediaSources = _mediaSourceManager().GetStaticMediaSources(hasMediaSources, true, user);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -413,6 +413,9 @@
|
||||
<ItemGroup>
|
||||
<EmbeddedResource Include="Localization\Ratings\es.txt" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<EmbeddedResource Include="Localization\Ratings\ro.txt" />
|
||||
</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.
|
||||
|
@ -49,10 +49,9 @@ namespace Emby.Server.Implementations.Library
|
||||
_providers = providers.ToArray();
|
||||
}
|
||||
|
||||
public IEnumerable<MediaStream> GetMediaStreams(MediaStreamQuery query)
|
||||
public List<MediaStream> GetMediaStreams(MediaStreamQuery query)
|
||||
{
|
||||
var list = _itemRepo.GetMediaStreams(query)
|
||||
.ToList();
|
||||
var list = _itemRepo.GetMediaStreams(query);
|
||||
|
||||
foreach (var stream in list)
|
||||
{
|
||||
@ -77,7 +76,7 @@ namespace Emby.Server.Implementations.Library
|
||||
return false;
|
||||
}
|
||||
|
||||
public IEnumerable<MediaStream> GetMediaStreams(string mediaSourceId)
|
||||
public List<MediaStream> GetMediaStreams(string mediaSourceId)
|
||||
{
|
||||
var list = GetMediaStreams(new MediaStreamQuery
|
||||
{
|
||||
@ -87,7 +86,7 @@ namespace Emby.Server.Implementations.Library
|
||||
return GetMediaStreamsForItem(list);
|
||||
}
|
||||
|
||||
public IEnumerable<MediaStream> GetMediaStreams(Guid itemId)
|
||||
public List<MediaStream> GetMediaStreams(Guid itemId)
|
||||
{
|
||||
var list = GetMediaStreams(new MediaStreamQuery
|
||||
{
|
||||
@ -97,7 +96,7 @@ namespace Emby.Server.Implementations.Library
|
||||
return GetMediaStreamsForItem(list);
|
||||
}
|
||||
|
||||
private IEnumerable<MediaStream> GetMediaStreamsForItem(IEnumerable<MediaStream> streams)
|
||||
private List<MediaStream> GetMediaStreamsForItem(IEnumerable<MediaStream> streams)
|
||||
{
|
||||
var list = streams.ToList();
|
||||
|
||||
@ -253,7 +252,7 @@ namespace Emby.Server.Implementations.Library
|
||||
return sources.FirstOrDefault(i => string.Equals(i.Id, mediaSourceId, StringComparison.OrdinalIgnoreCase));
|
||||
}
|
||||
|
||||
public IEnumerable<MediaSourceInfo> GetStaticMediaSources(IHasMediaSources item, bool enablePathSubstitution, User user = null)
|
||||
public List<MediaSourceInfo> GetStaticMediaSources(IHasMediaSources item, bool enablePathSubstitution, User user = null)
|
||||
{
|
||||
if (item == null)
|
||||
{
|
||||
@ -265,7 +264,7 @@ namespace Emby.Server.Implementations.Library
|
||||
return item.GetMediaSources(enablePathSubstitution);
|
||||
}
|
||||
|
||||
var sources = item.GetMediaSources(enablePathSubstitution).ToList();
|
||||
var sources = item.GetMediaSources(enablePathSubstitution);
|
||||
|
||||
if (user != null)
|
||||
{
|
||||
|
@ -1957,7 +1957,7 @@ namespace Emby.Server.Implementations.LiveTv
|
||||
|
||||
if (dto.MediaSources == null)
|
||||
{
|
||||
dto.MediaSources = recording.GetMediaSources(true).ToList();
|
||||
dto.MediaSources = recording.GetMediaSources(true);
|
||||
}
|
||||
|
||||
if (dto.MediaStreams == null)
|
||||
@ -2365,7 +2365,7 @@ namespace Emby.Server.Implementations.LiveTv
|
||||
|
||||
if (addMediaSources)
|
||||
{
|
||||
dto.MediaSources = channel.GetMediaSources(true).ToList();
|
||||
dto.MediaSources = channel.GetMediaSources(true);
|
||||
}
|
||||
|
||||
if (addCurrentProgram)
|
||||
|
@ -78,8 +78,7 @@ namespace Emby.Server.Implementations.LiveTv
|
||||
{
|
||||
var hasMediaSources = (IHasMediaSources)item;
|
||||
|
||||
sources = _mediaSourceManager.GetStaticMediaSources(hasMediaSources, false)
|
||||
.ToList();
|
||||
sources = _mediaSourceManager.GetStaticMediaSources(hasMediaSources, false);
|
||||
|
||||
forceRequireOpening = true;
|
||||
}
|
||||
|
@ -1,4 +1,5 @@
|
||||
ES-A,1
|
||||
ES-APTA,1
|
||||
ES-7,3
|
||||
ES-12,6
|
||||
ES-16,8
|
||||
|
1
Emby.Server.Implementations/Localization/Ratings/ro.txt
Normal file
1
Emby.Server.Implementations/Localization/Ratings/ro.txt
Normal file
@ -0,0 +1 @@
|
||||
RO-AG,1
|
@ -29,9 +29,9 @@ namespace Emby.Server.Implementations.MediaEncoder
|
||||
private readonly IChapterManager _chapterManager;
|
||||
private readonly ILibraryManager _libraryManager;
|
||||
|
||||
public EncodingManager(IFileSystem fileSystem,
|
||||
ILogger logger,
|
||||
IMediaEncoder encoder,
|
||||
public EncodingManager(IFileSystem fileSystem,
|
||||
ILogger logger,
|
||||
IMediaEncoder encoder,
|
||||
IChapterManager chapterManager, ILibraryManager libraryManager)
|
||||
{
|
||||
_fileSystem = fileSystem;
|
||||
@ -121,12 +121,16 @@ namespace Emby.Server.Implementations.MediaEncoder
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
List<string> playableStreamFileNames = null;
|
||||
if (video.VideoType == VideoType.BluRay || video.VideoType == VideoType.Dvd)
|
||||
{
|
||||
if (video.PlayableStreamFileNames.Count != 1)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
if (playableStreamFileNames == null)
|
||||
{
|
||||
playableStreamFileNames = new List<string>();
|
||||
}
|
||||
|
||||
try
|
||||
@ -136,7 +140,7 @@ namespace Emby.Server.Implementations.MediaEncoder
|
||||
|
||||
var protocol = MediaProtocol.File;
|
||||
|
||||
var inputPath = MediaEncoderHelpers.GetInputArgument(_fileSystem, video.Path, protocol, null, video.PlayableStreamFileNames);
|
||||
var inputPath = MediaEncoderHelpers.GetInputArgument(_fileSystem, video.Path, protocol, null, playableStreamFileNames);
|
||||
|
||||
_fileSystem.CreateDirectory(_fileSystem.GetDirectoryName(path));
|
||||
|
||||
@ -151,7 +155,7 @@ namespace Emby.Server.Implementations.MediaEncoder
|
||||
}
|
||||
catch
|
||||
{
|
||||
|
||||
|
||||
}
|
||||
|
||||
chapter.ImagePath = path;
|
||||
|
@ -9,6 +9,7 @@ using System.Globalization;
|
||||
using System.Linq;
|
||||
using System.Threading;
|
||||
using MediaBrowser.Common.Extensions;
|
||||
using MediaBrowser.Controller.Persistence;
|
||||
using MediaBrowser.Model.Serialization;
|
||||
|
||||
namespace MediaBrowser.Controller.Entities.Audio
|
||||
@ -193,6 +194,23 @@ namespace MediaBrowser.Controller.Entities.Audio
|
||||
return base.GetBlockUnratedType();
|
||||
}
|
||||
|
||||
public List<MediaStream> GetMediaStreams()
|
||||
{
|
||||
return MediaSourceManager.GetMediaStreams(new MediaStreamQuery
|
||||
{
|
||||
ItemId = Id
|
||||
});
|
||||
}
|
||||
|
||||
public List<MediaStream> GetMediaStreams(MediaStreamType type)
|
||||
{
|
||||
return MediaSourceManager.GetMediaStreams(new MediaStreamQuery
|
||||
{
|
||||
ItemId = Id,
|
||||
Type = type
|
||||
});
|
||||
}
|
||||
|
||||
public SongInfo GetLookupInfo()
|
||||
{
|
||||
var info = GetItemLookupInfo<SongInfo>();
|
||||
@ -204,7 +222,7 @@ namespace MediaBrowser.Controller.Entities.Audio
|
||||
return info;
|
||||
}
|
||||
|
||||
public virtual IEnumerable<MediaSourceInfo> GetMediaSources(bool enablePathSubstitution)
|
||||
public virtual List<MediaSourceInfo> GetMediaSources(bool enablePathSubstitution)
|
||||
{
|
||||
if (SourceType == SourceType.Channel)
|
||||
{
|
||||
@ -248,7 +266,7 @@ namespace MediaBrowser.Controller.Entities.Audio
|
||||
{
|
||||
Id = i.Id.ToString("N"),
|
||||
Protocol = locationType == LocationType.Remote ? MediaProtocol.Http : MediaProtocol.File,
|
||||
MediaStreams = MediaSourceManager.GetMediaStreams(i.Id).ToList(),
|
||||
MediaStreams = MediaSourceManager.GetMediaStreams(i.Id),
|
||||
Name = i.Name,
|
||||
Path = enablePathSubstituion ? GetMappedPath(i, i.Path, locationType) : i.Path,
|
||||
RunTimeTicks = i.RunTimeTicks,
|
||||
|
@ -1,9 +0,0 @@
|
||||
using System;
|
||||
|
||||
namespace MediaBrowser.Controller.Entities
|
||||
{
|
||||
public interface IHasId
|
||||
{
|
||||
Guid Id { get; }
|
||||
}
|
||||
}
|
@ -10,7 +10,7 @@ using MediaBrowser.Model.IO;
|
||||
|
||||
namespace MediaBrowser.Controller.Entities
|
||||
{
|
||||
public interface IHasImages : IHasProviderIds, IHasId
|
||||
public interface IHasImages : IHasProviderIds, IHasUserData
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets the name.
|
||||
|
@ -1,5 +1,6 @@
|
||||
using MediaBrowser.Model.Dto;
|
||||
using System.Collections.Generic;
|
||||
using MediaBrowser.Model.Entities;
|
||||
|
||||
namespace MediaBrowser.Controller.Entities
|
||||
{
|
||||
@ -10,6 +11,7 @@ namespace MediaBrowser.Controller.Entities
|
||||
/// </summary>
|
||||
/// <param name="enablePathSubstitution">if set to <c>true</c> [enable path substitution].</param>
|
||||
/// <returns>Task{IEnumerable{MediaSourceInfo}}.</returns>
|
||||
IEnumerable<MediaSourceInfo> GetMediaSources(bool enablePathSubstitution);
|
||||
List<MediaSourceInfo> GetMediaSources(bool enablePathSubstitution);
|
||||
List<MediaStream> GetMediaStreams();
|
||||
}
|
||||
}
|
||||
|
@ -65,5 +65,6 @@ namespace MediaBrowser.Controller.Entities
|
||||
int InheritedParentalRatingValue { get; set; }
|
||||
List<string> GetInheritedTags();
|
||||
List<string> InheritedTags { get; set; }
|
||||
long? RunTimeTicks { get; set; }
|
||||
}
|
||||
}
|
||||
|
@ -1,4 +1,5 @@
|
||||
using System.Collections.Generic;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Threading.Tasks;
|
||||
using MediaBrowser.Model.Dto;
|
||||
using MediaBrowser.Model.Querying;
|
||||
@ -8,7 +9,7 @@ namespace MediaBrowser.Controller.Entities
|
||||
/// <summary>
|
||||
/// Interface IHasUserData
|
||||
/// </summary>
|
||||
public interface IHasUserData : IHasId
|
||||
public interface IHasUserData
|
||||
{
|
||||
List<string> GetUserDataKeys();
|
||||
|
||||
@ -20,5 +21,7 @@ namespace MediaBrowser.Controller.Entities
|
||||
bool EnableRememberingTrackSelections { get; }
|
||||
|
||||
bool SupportsPlayedStatus { get; }
|
||||
|
||||
Guid Id { get; }
|
||||
}
|
||||
}
|
||||
|
@ -148,11 +148,6 @@ namespace MediaBrowser.Controller.Entities
|
||||
/// <value>The video3 D format.</value>
|
||||
public Video3DFormat? Video3DFormat { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// If the video is a folder-rip, this will hold the file list for the largest playlist
|
||||
/// </summary>
|
||||
public List<string> PlayableStreamFileNames { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the playable stream files.
|
||||
/// </summary>
|
||||
@ -162,6 +157,11 @@ namespace MediaBrowser.Controller.Entities
|
||||
return GetPlayableStreamFiles(Path);
|
||||
}
|
||||
|
||||
public List<string> GetPlayableStreamFileNames()
|
||||
{
|
||||
return GetPlayableStreamFiles().Select(System.IO.Path.GetFileName).ToList(); ;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the aspect ratio.
|
||||
/// </summary>
|
||||
@ -170,7 +170,6 @@ namespace MediaBrowser.Controller.Entities
|
||||
|
||||
public Video()
|
||||
{
|
||||
PlayableStreamFileNames = new List<string>();
|
||||
AdditionalParts = new List<string>();
|
||||
LocalAlternateVersions = new List<string>();
|
||||
SubtitleFiles = new List<string>();
|
||||
@ -395,11 +394,45 @@ namespace MediaBrowser.Controller.Entities
|
||||
{
|
||||
var allFiles = FileSystem.GetFilePaths(rootPath, true).ToList();
|
||||
|
||||
return PlayableStreamFileNames.Select(name => allFiles.FirstOrDefault(f => string.Equals(System.IO.Path.GetFileName(f), name, StringComparison.OrdinalIgnoreCase)))
|
||||
var videoType = VideoType;
|
||||
|
||||
if (videoType == VideoType.Iso && IsoType == Model.Entities.IsoType.BluRay)
|
||||
{
|
||||
videoType = VideoType.BluRay;
|
||||
}
|
||||
else if (videoType == VideoType.Iso && IsoType == Model.Entities.IsoType.Dvd)
|
||||
{
|
||||
videoType = VideoType.Dvd;
|
||||
}
|
||||
|
||||
return QueryPlayableStreamFiles(rootPath, videoType).Select(name => allFiles.FirstOrDefault(f => string.Equals(System.IO.Path.GetFileName(f), name, StringComparison.OrdinalIgnoreCase)))
|
||||
.Where(f => !string.IsNullOrEmpty(f))
|
||||
.ToList();
|
||||
}
|
||||
|
||||
public static List<string> QueryPlayableStreamFiles(string rootPath, VideoType videoType)
|
||||
{
|
||||
if (videoType == VideoType.Dvd)
|
||||
{
|
||||
return FileSystem.GetFiles(rootPath, new[] { ".vob" }, false, true)
|
||||
.OrderByDescending(i => i.Length)
|
||||
.ThenBy(i => i.FullName)
|
||||
.Take(1)
|
||||
.Select(i => i.FullName)
|
||||
.ToList();
|
||||
}
|
||||
if (videoType == VideoType.BluRay)
|
||||
{
|
||||
return FileSystem.GetFiles(rootPath, new[] { ".m2ts" }, false, true)
|
||||
.OrderByDescending(i => i.Length)
|
||||
.ThenBy(i => i.FullName)
|
||||
.Take(1)
|
||||
.Select(i => i.FullName)
|
||||
.ToList();
|
||||
}
|
||||
return new List<string>();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets a value indicating whether [is3 D].
|
||||
/// </summary>
|
||||
@ -505,17 +538,12 @@ namespace MediaBrowser.Controller.Entities
|
||||
return base.GetDeletePaths();
|
||||
}
|
||||
|
||||
public IEnumerable<MediaStream> GetMediaStreams()
|
||||
public List<MediaStream> GetMediaStreams()
|
||||
{
|
||||
var mediaSource = GetMediaSources(false)
|
||||
.FirstOrDefault();
|
||||
|
||||
if (mediaSource == null)
|
||||
return MediaSourceManager.GetMediaStreams(new MediaStreamQuery
|
||||
{
|
||||
return new List<MediaStream>();
|
||||
}
|
||||
|
||||
return mediaSource.MediaStreams;
|
||||
ItemId = Id
|
||||
});
|
||||
}
|
||||
|
||||
public virtual MediaStream GetDefaultVideoStream()
|
||||
@ -563,7 +591,7 @@ namespace MediaBrowser.Controller.Entities
|
||||
return list;
|
||||
}
|
||||
|
||||
public virtual IEnumerable<MediaSourceInfo> GetMediaSources(bool enablePathSubstitution)
|
||||
public virtual List<MediaSourceInfo> GetMediaSources(bool enablePathSubstitution)
|
||||
{
|
||||
if (SourceType == SourceType.Channel)
|
||||
{
|
||||
@ -610,8 +638,7 @@ namespace MediaBrowser.Controller.Entities
|
||||
throw new ArgumentNullException("media");
|
||||
}
|
||||
|
||||
var mediaStreams = MediaSourceManager.GetMediaStreams(media.Id)
|
||||
.ToList();
|
||||
var mediaStreams = MediaSourceManager.GetMediaStreams(media.Id);
|
||||
|
||||
var locationType = media.LocationType;
|
||||
|
||||
@ -630,7 +657,6 @@ namespace MediaBrowser.Controller.Entities
|
||||
Size = media.Size,
|
||||
Timestamp = media.Timestamp,
|
||||
Type = type,
|
||||
PlayableStreamFileNames = media.PlayableStreamFileNames.ToList(),
|
||||
SupportsDirectStream = media.VideoType == VideoType.VideoFile,
|
||||
IsRemote = media.IsShortcut
|
||||
};
|
||||
|
@ -24,19 +24,19 @@ namespace MediaBrowser.Controller.Library
|
||||
/// </summary>
|
||||
/// <param name="itemId">The item identifier.</param>
|
||||
/// <returns>IEnumerable<MediaStream>.</returns>
|
||||
IEnumerable<MediaStream> GetMediaStreams(Guid itemId);
|
||||
List<MediaStream> GetMediaStreams(Guid itemId);
|
||||
/// <summary>
|
||||
/// Gets the media streams.
|
||||
/// </summary>
|
||||
/// <param name="mediaSourceId">The media source identifier.</param>
|
||||
/// <returns>IEnumerable<MediaStream>.</returns>
|
||||
IEnumerable<MediaStream> GetMediaStreams(string mediaSourceId);
|
||||
List<MediaStream> GetMediaStreams(string mediaSourceId);
|
||||
/// <summary>
|
||||
/// Gets the media streams.
|
||||
/// </summary>
|
||||
/// <param name="query">The query.</param>
|
||||
/// <returns>IEnumerable<MediaStream>.</returns>
|
||||
IEnumerable<MediaStream> GetMediaStreams(MediaStreamQuery query);
|
||||
List<MediaStream> GetMediaStreams(MediaStreamQuery query);
|
||||
|
||||
/// <summary>
|
||||
/// Gets the playack media sources.
|
||||
@ -56,7 +56,7 @@ namespace MediaBrowser.Controller.Library
|
||||
/// <param name="enablePathSubstitution">if set to <c>true</c> [enable path substitution].</param>
|
||||
/// <param name="user">The user.</param>
|
||||
/// <returns>IEnumerable<MediaSourceInfo>.</returns>
|
||||
IEnumerable<MediaSourceInfo> GetStaticMediaSources(IHasMediaSources item, bool enablePathSubstitution, User user = null);
|
||||
List<MediaSourceInfo> GetStaticMediaSources(IHasMediaSources item, bool enablePathSubstitution, User user = null);
|
||||
|
||||
/// <summary>
|
||||
/// Gets the static media source.
|
||||
|
@ -151,9 +151,9 @@ namespace MediaBrowser.Controller.LiveTv
|
||||
return user.Policy.EnableLiveTvManagement;
|
||||
}
|
||||
|
||||
public override IEnumerable<MediaSourceInfo> GetMediaSources(bool enablePathSubstitution)
|
||||
public override List<MediaSourceInfo> GetMediaSources(bool enablePathSubstitution)
|
||||
{
|
||||
var list = base.GetMediaSources(enablePathSubstitution).ToList();
|
||||
var list = base.GetMediaSources(enablePathSubstitution);
|
||||
|
||||
foreach (var mediaSource in list)
|
||||
{
|
||||
|
@ -122,7 +122,7 @@ namespace MediaBrowser.Controller.LiveTv
|
||||
return new List<BaseItem>();
|
||||
}
|
||||
|
||||
public IEnumerable<MediaSourceInfo> GetMediaSources(bool enablePathSubstitution)
|
||||
public List<MediaSourceInfo> GetMediaSources(bool enablePathSubstitution)
|
||||
{
|
||||
var list = new List<MediaSourceInfo>();
|
||||
|
||||
@ -144,6 +144,11 @@ namespace MediaBrowser.Controller.LiveTv
|
||||
return list;
|
||||
}
|
||||
|
||||
public List<MediaStream> GetMediaStreams()
|
||||
{
|
||||
return new List<MediaStream>();
|
||||
}
|
||||
|
||||
protected override string GetInternalMetadataPath(string basePath)
|
||||
{
|
||||
return System.IO.Path.Combine(basePath, "livetv", Id.ToString("N"), "metadata");
|
||||
|
@ -150,9 +150,9 @@ namespace MediaBrowser.Controller.LiveTv
|
||||
return user.Policy.EnableLiveTvManagement;
|
||||
}
|
||||
|
||||
public override IEnumerable<MediaSourceInfo> GetMediaSources(bool enablePathSubstitution)
|
||||
public override List<MediaSourceInfo> GetMediaSources(bool enablePathSubstitution)
|
||||
{
|
||||
var list = base.GetMediaSources(enablePathSubstitution).ToList();
|
||||
var list = base.GetMediaSources(enablePathSubstitution);
|
||||
|
||||
foreach (var mediaSource in list)
|
||||
{
|
||||
|
@ -99,7 +99,6 @@
|
||||
<Compile Include="Entities\GameSystem.cs" />
|
||||
<Compile Include="Entities\IHasAspectRatio.cs" />
|
||||
<Compile Include="Entities\IHasDisplayOrder.cs" />
|
||||
<Compile Include="Entities\IHasId.cs" />
|
||||
<Compile Include="Entities\IHasImages.cs" />
|
||||
<Compile Include="Entities\IHasMediaSources.cs" />
|
||||
<Compile Include="Entities\IHasProgramAttributes.cs" />
|
||||
|
@ -4,6 +4,7 @@ using System.Globalization;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Threading;
|
||||
using MediaBrowser.Controller.Entities;
|
||||
using MediaBrowser.Model.Configuration;
|
||||
using MediaBrowser.Model.Dlna;
|
||||
using MediaBrowser.Model.Dto;
|
||||
@ -1671,14 +1672,33 @@ namespace MediaBrowser.Controller.MediaEncoding
|
||||
state.RunTimeTicks = mediaSource.RunTimeTicks;
|
||||
state.RemoteHttpHeaders = mediaSource.RequiredHttpHeaders;
|
||||
|
||||
state.IsoType = mediaSource.IsoType;
|
||||
|
||||
if (mediaSource.VideoType.HasValue)
|
||||
{
|
||||
state.VideoType = mediaSource.VideoType.Value;
|
||||
|
||||
if (mediaSource.VideoType.Value == VideoType.BluRay || mediaSource.VideoType.Value == VideoType.Dvd)
|
||||
{
|
||||
state.PlayableStreamFileNames = Video.QueryPlayableStreamFiles(state.MediaPath, mediaSource.VideoType.Value);
|
||||
}
|
||||
else if (mediaSource.VideoType.Value == VideoType.Iso && state.IsoType == IsoType.BluRay)
|
||||
{
|
||||
state.PlayableStreamFileNames = Video.QueryPlayableStreamFiles(state.MediaPath, VideoType.BluRay);
|
||||
}
|
||||
else if (mediaSource.VideoType.Value == VideoType.Iso && state.IsoType == IsoType.Dvd)
|
||||
{
|
||||
state.PlayableStreamFileNames = Video.QueryPlayableStreamFiles(state.MediaPath, VideoType.Dvd);
|
||||
}
|
||||
else
|
||||
{
|
||||
state.PlayableStreamFileNames = new List<string>();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
state.PlayableStreamFileNames = new List<string>();
|
||||
}
|
||||
|
||||
state.IsoType = mediaSource.IsoType;
|
||||
|
||||
state.PlayableStreamFileNames = mediaSource.PlayableStreamFileNames.ToList();
|
||||
|
||||
if (mediaSource.Timestamp.HasValue)
|
||||
{
|
||||
|
@ -89,7 +89,7 @@ namespace MediaBrowser.Controller.Persistence
|
||||
/// </summary>
|
||||
/// <param name="query">The query.</param>
|
||||
/// <returns>IEnumerable{MediaStream}.</returns>
|
||||
IEnumerable<MediaStream> GetMediaStreams(MediaStreamQuery query);
|
||||
List<MediaStream> GetMediaStreams(MediaStreamQuery query);
|
||||
|
||||
/// <summary>
|
||||
/// Saves the media streams.
|
||||
|
@ -53,7 +53,6 @@ namespace MediaBrowser.Model.Dto
|
||||
public Video3DFormat? Video3DFormat { get; set; }
|
||||
|
||||
public List<MediaStream> MediaStreams { get; set; }
|
||||
public List<string> PlayableStreamFileNames { get; set; }
|
||||
|
||||
public List<string> Formats { get; set; }
|
||||
|
||||
@ -73,7 +72,6 @@ namespace MediaBrowser.Model.Dto
|
||||
Formats = new List<string>();
|
||||
MediaStreams = new List<MediaStream>();
|
||||
RequiredHttpHeaders = new Dictionary<string, string>();
|
||||
PlayableStreamFileNames = new List<string>();
|
||||
SupportsTranscoding = true;
|
||||
SupportsDirectStream = true;
|
||||
SupportsDirectPlay = true;
|
||||
|
@ -41,9 +41,7 @@ namespace MediaBrowser.Providers.MediaInfo
|
||||
var audio = (Audio)item;
|
||||
|
||||
var imageStreams =
|
||||
audio.GetMediaSources(false)
|
||||
.Take(1)
|
||||
.SelectMany(i => i.MediaStreams)
|
||||
audio.GetMediaStreams(MediaStreamType.EmbeddedImage)
|
||||
.Where(i => i.Type == MediaStreamType.EmbeddedImage)
|
||||
.ToList();
|
||||
|
||||
|
@ -80,35 +80,45 @@ namespace MediaBrowser.Providers.MediaInfo
|
||||
|
||||
try
|
||||
{
|
||||
if (item.VideoType == VideoType.BluRay || (item.IsoType.HasValue && item.IsoType == IsoType.BluRay))
|
||||
{
|
||||
var inputPath = isoMount != null ? isoMount.MountedPath : item.Path;
|
||||
List<string> streamFileNames = null;
|
||||
|
||||
blurayDiscInfo = GetBDInfo(inputPath);
|
||||
if (item.VideoType == VideoType.Iso)
|
||||
{
|
||||
item.IsoType = DetermineIsoType(isoMount);
|
||||
}
|
||||
|
||||
OnPreFetch(item, isoMount, blurayDiscInfo);
|
||||
|
||||
// If we didn't find any satisfying the min length, just take them all
|
||||
if (item.VideoType == VideoType.Dvd || (item.IsoType.HasValue && item.IsoType == IsoType.Dvd))
|
||||
{
|
||||
if (item.PlayableStreamFileNames.Count == 0)
|
||||
streamFileNames = FetchFromDvdLib(item, isoMount);
|
||||
|
||||
if (streamFileNames.Count == 0)
|
||||
{
|
||||
_logger.Error("No playable vobs found in dvd structure, skipping ffprobe.");
|
||||
return ItemUpdateType.MetadataImport;
|
||||
}
|
||||
}
|
||||
|
||||
if (item.VideoType == VideoType.BluRay || (item.IsoType.HasValue && item.IsoType == IsoType.BluRay))
|
||||
else if (item.VideoType == VideoType.BluRay || (item.IsoType.HasValue && item.IsoType == IsoType.BluRay))
|
||||
{
|
||||
if (item.PlayableStreamFileNames.Count == 0)
|
||||
var inputPath = isoMount != null ? isoMount.MountedPath : item.Path;
|
||||
|
||||
blurayDiscInfo = GetBDInfo(inputPath);
|
||||
|
||||
streamFileNames = blurayDiscInfo.Files;
|
||||
|
||||
if (streamFileNames.Count == 0)
|
||||
{
|
||||
_logger.Error("No playable vobs found in bluray structure, skipping ffprobe.");
|
||||
return ItemUpdateType.MetadataImport;
|
||||
}
|
||||
}
|
||||
|
||||
var result = await GetMediaInfo(item, isoMount, cancellationToken).ConfigureAwait(false);
|
||||
if (streamFileNames == null)
|
||||
{
|
||||
streamFileNames = new List<string>();
|
||||
}
|
||||
|
||||
var result = await GetMediaInfo(item, isoMount, streamFileNames, cancellationToken).ConfigureAwait(false);
|
||||
|
||||
cancellationToken.ThrowIfCancellationRequested();
|
||||
|
||||
@ -126,10 +136,9 @@ namespace MediaBrowser.Providers.MediaInfo
|
||||
return ItemUpdateType.MetadataImport;
|
||||
}
|
||||
|
||||
private const string SchemaVersion = "6";
|
||||
|
||||
private async Task<Model.MediaInfo.MediaInfo> GetMediaInfo(Video item,
|
||||
private Task<Model.MediaInfo.MediaInfo> GetMediaInfo(Video item,
|
||||
IIsoMount isoMount,
|
||||
List<string> streamFileNames,
|
||||
CancellationToken cancellationToken)
|
||||
{
|
||||
cancellationToken.ThrowIfCancellationRequested();
|
||||
@ -138,9 +147,9 @@ namespace MediaBrowser.Providers.MediaInfo
|
||||
? MediaProtocol.Http
|
||||
: MediaProtocol.File;
|
||||
|
||||
var result = await _mediaEncoder.GetMediaInfo(new MediaInfoRequest
|
||||
return _mediaEncoder.GetMediaInfo(new MediaInfoRequest
|
||||
{
|
||||
PlayableStreamFileNames = item.PlayableStreamFileNames,
|
||||
PlayableStreamFileNames = streamFileNames,
|
||||
MountedIso = isoMount,
|
||||
ExtractChapters = true,
|
||||
VideoType = item.VideoType,
|
||||
@ -148,12 +157,7 @@ namespace MediaBrowser.Providers.MediaInfo
|
||||
InputPath = item.Path,
|
||||
Protocol = protocol
|
||||
|
||||
}, cancellationToken).ConfigureAwait(false);
|
||||
|
||||
//Directory.CreateDirectory(_fileSystem.GetDirectoryName(cachePath));
|
||||
//_json.SerializeToFile(result, cachePath);
|
||||
|
||||
return result;
|
||||
}, cancellationToken);
|
||||
}
|
||||
|
||||
protected async Task Fetch(Video video,
|
||||
@ -266,7 +270,7 @@ namespace MediaBrowser.Providers.MediaInfo
|
||||
{
|
||||
var video = (Video)item;
|
||||
|
||||
video.PlayableStreamFileNames = blurayInfo.Files.ToList();
|
||||
//video.PlayableStreamFileNames = blurayInfo.Files.ToList();
|
||||
|
||||
// Use BD Info if it has multiple m2ts. Otherwise, treat it like a video file and rely more on ffprobe output
|
||||
if (blurayInfo.Files.Count > 1)
|
||||
@ -559,31 +563,7 @@ namespace MediaBrowser.Providers.MediaInfo
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Called when [pre fetch].
|
||||
/// </summary>
|
||||
/// <param name="item">The item.</param>
|
||||
/// <param name="mount">The mount.</param>
|
||||
/// <param name="blurayDiscInfo">The bluray disc information.</param>
|
||||
private void OnPreFetch(Video item, IIsoMount mount, BlurayDiscInfo blurayDiscInfo)
|
||||
{
|
||||
if (item.VideoType == VideoType.Iso)
|
||||
{
|
||||
item.IsoType = DetermineIsoType(mount);
|
||||
}
|
||||
|
||||
if (item.VideoType == VideoType.Dvd || (item.IsoType.HasValue && item.IsoType == IsoType.Dvd))
|
||||
{
|
||||
FetchFromDvdLib(item, mount);
|
||||
}
|
||||
|
||||
if (blurayDiscInfo != null)
|
||||
{
|
||||
item.PlayableStreamFileNames = blurayDiscInfo.Files.ToList();
|
||||
}
|
||||
}
|
||||
|
||||
private void FetchFromDvdLib(Video item, IIsoMount mount)
|
||||
private List<string> FetchFromDvdLib(Video item, IIsoMount mount)
|
||||
{
|
||||
var path = mount == null ? item.Path : mount.MountedPath;
|
||||
var dvd = new Dvd(path, _fileSystem);
|
||||
@ -598,7 +578,7 @@ namespace MediaBrowser.Providers.MediaInfo
|
||||
item.RunTimeTicks = GetRuntime(primaryTitle);
|
||||
}
|
||||
|
||||
item.PlayableStreamFileNames = GetPrimaryPlaylistVobFiles(item, mount, titleNumber)
|
||||
return GetPrimaryPlaylistVobFiles(item, mount, titleNumber)
|
||||
.Select(Path.GetFileName)
|
||||
.ToList();
|
||||
}
|
||||
|
@ -18,44 +18,17 @@ namespace MediaBrowser.Providers.MediaInfo
|
||||
{
|
||||
public class VideoImageProvider : IDynamicImageProvider, IHasItemChangeMonitor, IHasOrder
|
||||
{
|
||||
private readonly IIsoManager _isoManager;
|
||||
private readonly IMediaEncoder _mediaEncoder;
|
||||
private readonly IServerConfigurationManager _config;
|
||||
private readonly ILibraryManager _libraryManager;
|
||||
private readonly ILogger _logger;
|
||||
private readonly IFileSystem _fileSystem;
|
||||
|
||||
public VideoImageProvider(IIsoManager isoManager, IMediaEncoder mediaEncoder, IServerConfigurationManager config, ILibraryManager libraryManager, ILogger logger, IFileSystem fileSystem)
|
||||
public VideoImageProvider(IMediaEncoder mediaEncoder, ILogger logger, IFileSystem fileSystem)
|
||||
{
|
||||
_isoManager = isoManager;
|
||||
_mediaEncoder = mediaEncoder;
|
||||
_config = config;
|
||||
_libraryManager = libraryManager;
|
||||
_logger = logger;
|
||||
_fileSystem = fileSystem;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The null mount task result
|
||||
/// </summary>
|
||||
protected readonly Task<IIsoMount> NullMountTaskResult = Task.FromResult<IIsoMount>(null);
|
||||
|
||||
/// <summary>
|
||||
/// Mounts the iso if needed.
|
||||
/// </summary>
|
||||
/// <param name="item">The item.</param>
|
||||
/// <param name="cancellationToken">The cancellation token.</param>
|
||||
/// <returns>Task{IIsoMount}.</returns>
|
||||
protected Task<IIsoMount> MountIsoIfNeeded(Video item, CancellationToken cancellationToken)
|
||||
{
|
||||
if (item.VideoType == VideoType.Iso)
|
||||
{
|
||||
return _isoManager.Mount(item.Path, cancellationToken);
|
||||
}
|
||||
|
||||
return NullMountTaskResult;
|
||||
}
|
||||
|
||||
public IEnumerable<ImageType> GetSupportedImages(IHasImages item)
|
||||
{
|
||||
return new List<ImageType> { ImageType.Primary };
|
||||
@ -71,8 +44,8 @@ namespace MediaBrowser.Providers.MediaInfo
|
||||
return Task.FromResult(new DynamicImageResponse { HasImage = false });
|
||||
}
|
||||
|
||||
// Can't extract from iso's if we weren't unable to determine iso type
|
||||
if (video.VideoType == VideoType.Iso && !video.IsoType.HasValue)
|
||||
// No support for this
|
||||
if (video.VideoType == VideoType.Iso)
|
||||
{
|
||||
return Task.FromResult(new DynamicImageResponse { HasImage = false });
|
||||
}
|
||||
@ -89,81 +62,66 @@ namespace MediaBrowser.Providers.MediaInfo
|
||||
|
||||
public async Task<DynamicImageResponse> GetVideoImage(Video item, CancellationToken cancellationToken)
|
||||
{
|
||||
var isoMount = await MountIsoIfNeeded(item, cancellationToken).ConfigureAwait(false);
|
||||
var protocol = item.LocationType == LocationType.Remote
|
||||
? MediaProtocol.Http
|
||||
: MediaProtocol.File;
|
||||
|
||||
try
|
||||
var inputPath = MediaEncoderHelpers.GetInputArgument(_fileSystem, item.Path, protocol, null, item.GetPlayableStreamFileNames());
|
||||
|
||||
var mediaStreams =
|
||||
item.GetMediaStreams();
|
||||
|
||||
var imageStreams =
|
||||
mediaStreams
|
||||
.Where(i => i.Type == MediaStreamType.EmbeddedImage)
|
||||
.ToList();
|
||||
|
||||
var imageStream = imageStreams.FirstOrDefault(i => (i.Comment ?? string.Empty).IndexOf("front", StringComparison.OrdinalIgnoreCase) != -1) ??
|
||||
imageStreams.FirstOrDefault(i => (i.Comment ?? string.Empty).IndexOf("cover", StringComparison.OrdinalIgnoreCase) != -1) ??
|
||||
imageStreams.FirstOrDefault();
|
||||
|
||||
string extractedImagePath;
|
||||
|
||||
if (imageStream != null)
|
||||
{
|
||||
var protocol = item.LocationType == LocationType.Remote
|
||||
? MediaProtocol.Http
|
||||
: MediaProtocol.File;
|
||||
|
||||
var inputPath = MediaEncoderHelpers.GetInputArgument(_fileSystem, item.Path, protocol, isoMount, item.PlayableStreamFileNames);
|
||||
|
||||
var mediaStreams =
|
||||
item.GetMediaSources(false)
|
||||
.Take(1)
|
||||
.SelectMany(i => i.MediaStreams)
|
||||
.ToList();
|
||||
|
||||
var imageStreams =
|
||||
mediaStreams
|
||||
.Where(i => i.Type == MediaStreamType.EmbeddedImage)
|
||||
.ToList();
|
||||
|
||||
var imageStream = imageStreams.FirstOrDefault(i => (i.Comment ?? string.Empty).IndexOf("front", StringComparison.OrdinalIgnoreCase) != -1) ??
|
||||
imageStreams.FirstOrDefault(i => (i.Comment ?? string.Empty).IndexOf("cover", StringComparison.OrdinalIgnoreCase) != -1) ??
|
||||
imageStreams.FirstOrDefault();
|
||||
|
||||
string extractedImagePath;
|
||||
|
||||
if (imageStream != null)
|
||||
// Instead of using the raw stream index, we need to use nth video/embedded image stream
|
||||
var videoIndex = -1;
|
||||
foreach (var mediaStream in mediaStreams)
|
||||
{
|
||||
// Instead of using the raw stream index, we need to use nth video/embedded image stream
|
||||
var videoIndex = -1;
|
||||
foreach (var mediaStream in mediaStreams)
|
||||
if (mediaStream.Type == MediaStreamType.Video ||
|
||||
mediaStream.Type == MediaStreamType.EmbeddedImage)
|
||||
{
|
||||
if (mediaStream.Type == MediaStreamType.Video ||
|
||||
mediaStream.Type == MediaStreamType.EmbeddedImage)
|
||||
{
|
||||
videoIndex++;
|
||||
}
|
||||
if (mediaStream == imageStream)
|
||||
{
|
||||
break;
|
||||
}
|
||||
videoIndex++;
|
||||
}
|
||||
if (mediaStream == imageStream)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
extractedImagePath = await _mediaEncoder.ExtractVideoImage(inputPath, item.Container, protocol, imageStream, videoIndex, cancellationToken).ConfigureAwait(false);
|
||||
}
|
||||
else
|
||||
{
|
||||
// If we know the duration, grab it from 10% into the video. Otherwise just 10 seconds in.
|
||||
// Always use 10 seconds for dvd because our duration could be out of whack
|
||||
var imageOffset = item.VideoType != VideoType.Dvd && item.RunTimeTicks.HasValue &&
|
||||
item.RunTimeTicks.Value > 0
|
||||
? TimeSpan.FromTicks(Convert.ToInt64(item.RunTimeTicks.Value * .1))
|
||||
: TimeSpan.FromSeconds(10);
|
||||
|
||||
var videoStream = mediaStreams.FirstOrDefault(i => i.Type == MediaStreamType.Video);
|
||||
|
||||
extractedImagePath = await _mediaEncoder.ExtractVideoImage(inputPath, item.Container, protocol, videoStream, item.Video3DFormat, imageOffset, cancellationToken).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
return new DynamicImageResponse
|
||||
{
|
||||
Format = ImageFormat.Jpg,
|
||||
HasImage = true,
|
||||
Path = extractedImagePath,
|
||||
Protocol = MediaProtocol.File
|
||||
};
|
||||
extractedImagePath = await _mediaEncoder.ExtractVideoImage(inputPath, item.Container, protocol, imageStream, videoIndex, cancellationToken).ConfigureAwait(false);
|
||||
}
|
||||
finally
|
||||
else
|
||||
{
|
||||
if (isoMount != null)
|
||||
{
|
||||
isoMount.Dispose();
|
||||
}
|
||||
// If we know the duration, grab it from 10% into the video. Otherwise just 10 seconds in.
|
||||
// Always use 10 seconds for dvd because our duration could be out of whack
|
||||
var imageOffset = item.VideoType != VideoType.Dvd && item.RunTimeTicks.HasValue &&
|
||||
item.RunTimeTicks.Value > 0
|
||||
? TimeSpan.FromTicks(Convert.ToInt64(item.RunTimeTicks.Value * .1))
|
||||
: TimeSpan.FromSeconds(10);
|
||||
|
||||
var videoStream = mediaStreams.FirstOrDefault(i => i.Type == MediaStreamType.Video);
|
||||
|
||||
extractedImagePath = await _mediaEncoder.ExtractVideoImage(inputPath, item.Container, protocol, videoStream, item.Video3DFormat, imageOffset, cancellationToken).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
return new DynamicImageResponse
|
||||
{
|
||||
Format = ImageFormat.Jpg,
|
||||
HasImage = true,
|
||||
Path = extractedImagePath,
|
||||
Protocol = MediaProtocol.File
|
||||
};
|
||||
}
|
||||
|
||||
public string Name
|
||||
|
@ -300,9 +300,9 @@ namespace MediaBrowser.XbmcMetadata.Savers
|
||||
writer.WriteStartElement("fileinfo");
|
||||
writer.WriteStartElement("streamdetails");
|
||||
|
||||
var mediaSource = item.GetMediaSources(false).First();
|
||||
var mediaStreams = item.GetMediaStreams();
|
||||
|
||||
foreach (var stream in mediaSource.MediaStreams)
|
||||
foreach (var stream in mediaStreams)
|
||||
{
|
||||
writer.WriteStartElement(stream.Type.ToString().ToLower());
|
||||
|
||||
@ -378,9 +378,10 @@ namespace MediaBrowser.XbmcMetadata.Savers
|
||||
|
||||
if (stream.Type == MediaStreamType.Video)
|
||||
{
|
||||
if (mediaSource.RunTimeTicks.HasValue)
|
||||
var runtimeTicks = ((IHasMetadata) item).RunTimeTicks;
|
||||
if (runtimeTicks.HasValue)
|
||||
{
|
||||
var timespan = TimeSpan.FromTicks(mediaSource.RunTimeTicks.Value);
|
||||
var timespan = TimeSpan.FromTicks(runtimeTicks.Value);
|
||||
|
||||
writer.WriteElementString("duration", Convert.ToInt32(timespan.TotalMinutes).ToString(UsCulture));
|
||||
writer.WriteElementString("durationinseconds", Convert.ToInt32(timespan.TotalSeconds).ToString(UsCulture));
|
||||
|
Loading…
Reference in New Issue
Block a user