Merge pull request #2238 from MediaBrowser/dev

Dev
This commit is contained in:
Luke 2016-10-16 13:12:31 -04:00 committed by GitHub
commit fa0795b65b
19 changed files with 144 additions and 29 deletions

View File

@ -1735,6 +1735,13 @@ namespace MediaBrowser.Api.Playback
{ {
request.Tag = val; request.Tag = val;
} }
else if (i == 29)
{
if (videoRequest != null)
{
videoRequest.EnableSplittingOnNonKeyFrames = string.Equals("true", val, StringComparison.OrdinalIgnoreCase);
}
}
} }
} }
@ -2354,6 +2361,7 @@ namespace MediaBrowser.Api.Playback
{ {
state.VideoRequest.CopyTimestamps = transcodingProfile.CopyTimestamps; state.VideoRequest.CopyTimestamps = transcodingProfile.CopyTimestamps;
state.VideoRequest.EnableSubtitlesInManifest = transcodingProfile.EnableSubtitlesInManifest; state.VideoRequest.EnableSubtitlesInManifest = transcodingProfile.EnableSubtitlesInManifest;
state.VideoRequest.EnableSplittingOnNonKeyFrames = transcodingProfile.EnableSplittingOnNonKeyFrames;
} }
} }
} }

View File

@ -886,13 +886,11 @@ namespace MediaBrowser.Api.Playback.Hls
var mapArgs = state.IsOutputVideo ? GetMapArgs(state) : string.Empty; var mapArgs = state.IsOutputVideo ? GetMapArgs(state) : string.Empty;
var enableGenericSegmenter = false; if (state.VideoRequest.EnableSplittingOnNonKeyFrames)
if (enableGenericSegmenter)
{ {
var outputTsArg = Path.Combine(Path.GetDirectoryName(outputPath), Path.GetFileNameWithoutExtension(outputPath)) + "%d" + GetSegmentFileExtension(state); var outputTsArg = Path.Combine(Path.GetDirectoryName(outputPath), Path.GetFileNameWithoutExtension(outputPath)) + "%d" + GetSegmentFileExtension(state);
return string.Format("{0} {10} {1} -map_metadata -1 -threads {2} {3} {4} {5} -f segment -max_delay 5000000 -avoid_negative_ts disabled -start_at_zero -segment_time {6} -segment_format mpegts -segment_list_type m3u8 -segment_start_number {7} -segment_list \"{8}\" -y \"{9}\"", return string.Format("{0} {10} {1} -map_metadata -1 -threads {2} {3} {4} {5} -f segment -max_delay 5000000 -avoid_negative_ts disabled -start_at_zero -segment_time {6} -break_non_keyframes 1 -segment_format mpegts -segment_list_type m3u8 -segment_start_number {7} -segment_list \"{8}\" -y \"{9}\"",
inputModifier, inputModifier,
GetInputArgument(state), GetInputArgument(state),
threads, threads,
@ -908,7 +906,11 @@ namespace MediaBrowser.Api.Playback.Hls
} }
// TODO: check libavformat version for 57 50.100 and use -hls_flags split_by_time // TODO: check libavformat version for 57 50.100 and use -hls_flags split_by_time
return string.Format("{0}{11} {1} -map_metadata -1 -threads {2} {3} {4}{5} {6} -max_delay 5000000 -avoid_negative_ts disabled -start_at_zero -hls_time {7} -start_number {8} -hls_list_size {9} -y \"{10}\"", var supportsSplitByTime = false;
var splitByTime = supportsSplitByTime && state.VideoRequest.EnableSplittingOnNonKeyFrames;
var splitByTimeArg = splitByTime ? " -hls_flags split_by_time" : "";
return string.Format("{0}{12} {1} -map_metadata -1 -threads {2} {3} {4}{5} {6} -max_delay 5000000 -avoid_negative_ts disabled -start_at_zero -hls_time {7}{8} -start_number {9} -hls_list_size {10} -y \"{11}\"",
inputModifier, inputModifier,
GetInputArgument(state), GetInputArgument(state),
threads, threads,
@ -917,6 +919,7 @@ namespace MediaBrowser.Api.Playback.Hls
timestampOffsetParam, timestampOffsetParam,
GetAudioArguments(state), GetAudioArguments(state),
state.SegmentLength.ToString(UsCulture), state.SegmentLength.ToString(UsCulture),
splitByTimeArg,
startNumberParam, startNumberParam,
state.HlsListSize.ToString(UsCulture), state.HlsListSize.ToString(UsCulture),
outputPath, outputPath,

View File

@ -194,6 +194,7 @@ namespace MediaBrowser.Api.Playback
public bool CopyTimestamps { get; set; } public bool CopyTimestamps { get; set; }
public bool EnableSubtitlesInManifest { get; set; } public bool EnableSubtitlesInManifest { get; set; }
public bool EnableSplittingOnNonKeyFrames { get; set; }
public VideoStreamRequest() public VideoStreamRequest()
{ {

View File

@ -1188,7 +1188,7 @@ namespace MediaBrowser.Controller.Entities
var itemsChanged = !item.LocalTrailerIds.SequenceEqual(newItemIds); var itemsChanged = !item.LocalTrailerIds.SequenceEqual(newItemIds);
var tasks = newItems.Select(i => i.RefreshMetadata(options, cancellationToken)); var tasks = newItems.Select(i => RefreshMetadataForOwnedItem(i, true, options, cancellationToken));
await Task.WhenAll(tasks).ConfigureAwait(false); await Task.WhenAll(tasks).ConfigureAwait(false);
@ -1197,7 +1197,7 @@ namespace MediaBrowser.Controller.Entities
return itemsChanged; return itemsChanged;
} }
private static async Task<bool> RefreshThemeVideos(BaseItem item, MetadataRefreshOptions options, IEnumerable<FileSystemMetadata> fileSystemChildren, CancellationToken cancellationToken) private async Task<bool> RefreshThemeVideos(BaseItem item, MetadataRefreshOptions options, IEnumerable<FileSystemMetadata> fileSystemChildren, CancellationToken cancellationToken)
{ {
var newThemeVideos = LoadThemeVideos(fileSystemChildren, options.DirectoryService).ToList(); var newThemeVideos = LoadThemeVideos(fileSystemChildren, options.DirectoryService).ToList();
@ -1215,7 +1215,7 @@ namespace MediaBrowser.Controller.Entities
subOptions.ForceSave = true; subOptions.ForceSave = true;
} }
return i.RefreshMetadata(subOptions, cancellationToken); return RefreshMetadataForOwnedItem(i, true, subOptions, cancellationToken);
}); });
await Task.WhenAll(tasks).ConfigureAwait(false); await Task.WhenAll(tasks).ConfigureAwait(false);
@ -1228,7 +1228,7 @@ namespace MediaBrowser.Controller.Entities
/// <summary> /// <summary>
/// Refreshes the theme songs. /// Refreshes the theme songs.
/// </summary> /// </summary>
private static async Task<bool> RefreshThemeSongs(BaseItem item, MetadataRefreshOptions options, List<FileSystemMetadata> fileSystemChildren, CancellationToken cancellationToken) private async Task<bool> RefreshThemeSongs(BaseItem item, MetadataRefreshOptions options, List<FileSystemMetadata> fileSystemChildren, CancellationToken cancellationToken)
{ {
var newThemeSongs = LoadThemeSongs(fileSystemChildren, options.DirectoryService).ToList(); var newThemeSongs = LoadThemeSongs(fileSystemChildren, options.DirectoryService).ToList();
var newThemeSongIds = newThemeSongs.Select(i => i.Id).ToList(); var newThemeSongIds = newThemeSongs.Select(i => i.Id).ToList();
@ -1245,7 +1245,7 @@ namespace MediaBrowser.Controller.Entities
subOptions.ForceSave = true; subOptions.ForceSave = true;
} }
return i.RefreshMetadata(subOptions, cancellationToken); return RefreshMetadataForOwnedItem(i, true, subOptions, cancellationToken);
}); });
await Task.WhenAll(tasks).ConfigureAwait(false); await Task.WhenAll(tasks).ConfigureAwait(false);
@ -2203,14 +2203,85 @@ namespace MediaBrowser.Controller.Entities
return Task.FromResult(true); return Task.FromResult(true);
} }
protected Task RefreshMetadataForOwnedVideo(MetadataRefreshOptions options, string path, CancellationToken cancellationToken) protected Task RefreshMetadataForOwnedItem(BaseItem ownedItem, bool copyTitleMetadata, MetadataRefreshOptions options, CancellationToken cancellationToken)
{ {
var newOptions = new MetadataRefreshOptions(options.DirectoryService) var newOptions = new MetadataRefreshOptions(options);
newOptions.SearchResult = null;
var item = this;
if (copyTitleMetadata)
{ {
ImageRefreshMode = options.ImageRefreshMode, // Take some data from the main item, for querying purposes
MetadataRefreshMode = options.MetadataRefreshMode, if (!item.Genres.SequenceEqual(ownedItem.Genres, StringComparer.Ordinal))
ReplaceAllMetadata = options.ReplaceAllMetadata {
}; newOptions.ForceSave = true;
ownedItem.Genres = item.Genres.ToList();
}
if (!item.Studios.SequenceEqual(ownedItem.Studios, StringComparer.Ordinal))
{
newOptions.ForceSave = true;
ownedItem.Studios = item.Studios.ToList();
}
if (!item.ProductionLocations.SequenceEqual(ownedItem.ProductionLocations, StringComparer.Ordinal))
{
newOptions.ForceSave = true;
ownedItem.ProductionLocations = item.ProductionLocations.ToList();
}
if (!item.Keywords.SequenceEqual(ownedItem.Keywords, StringComparer.Ordinal))
{
newOptions.ForceSave = true;
ownedItem.Keywords = item.Keywords.ToList();
}
if (item.CommunityRating != ownedItem.CommunityRating)
{
ownedItem.CommunityRating = item.CommunityRating;
newOptions.ForceSave = true;
}
if (item.CriticRating != ownedItem.CriticRating)
{
ownedItem.CriticRating = item.CriticRating;
newOptions.ForceSave = true;
}
if (!string.Equals(item.Overview, ownedItem.Overview, StringComparison.Ordinal))
{
ownedItem.Overview = item.Overview;
newOptions.ForceSave = true;
}
if (!string.Equals(item.ShortOverview, ownedItem.ShortOverview, StringComparison.Ordinal))
{
ownedItem.ShortOverview = item.ShortOverview;
newOptions.ForceSave = true;
}
if (!string.Equals(item.OfficialRating, ownedItem.OfficialRating, StringComparison.Ordinal))
{
ownedItem.OfficialRating = item.OfficialRating;
newOptions.ForceSave = true;
}
if (!string.Equals(item.CustomRating, ownedItem.CustomRating, StringComparison.Ordinal))
{
ownedItem.CustomRating = item.CustomRating;
newOptions.ForceSave = true;
}
if (!string.Equals(item.CriticRatingSummary, ownedItem.CriticRatingSummary, StringComparison.Ordinal))
{
ownedItem.CriticRatingSummary = item.CriticRatingSummary;
newOptions.ForceSave = true;
}
if (!string.Equals(item.OfficialRatingDescription, ownedItem.OfficialRatingDescription, StringComparison.Ordinal))
{
ownedItem.OfficialRatingDescription = item.OfficialRatingDescription;
newOptions.ForceSave = true;
}
}
return ownedItem.RefreshMetadata(newOptions, cancellationToken);
}
protected Task RefreshMetadataForOwnedVideo(MetadataRefreshOptions options, bool copyTitleMetadata, string path, CancellationToken cancellationToken)
{
var newOptions = new MetadataRefreshOptions(options);
newOptions.SearchResult = null;
var id = LibraryManager.GetNewItemId(path, typeof(Video)); var id = LibraryManager.GetNewItemId(path, typeof(Video));
@ -2229,7 +2300,7 @@ namespace MediaBrowser.Controller.Entities
return Task.FromResult(true); return Task.FromResult(true);
} }
return video.RefreshMetadata(newOptions, cancellationToken); return RefreshMetadataForOwnedItem(video, copyTitleMetadata, newOptions, cancellationToken);
} }
public string GetEtag(User user) public string GetEtag(User user)

View File

@ -103,7 +103,7 @@ namespace MediaBrowser.Controller.Entities.Movies
var itemsChanged = !SpecialFeatureIds.SequenceEqual(newItemIds); var itemsChanged = !SpecialFeatureIds.SequenceEqual(newItemIds);
var tasks = newItems.Select(i => i.RefreshMetadata(options, cancellationToken)); var tasks = newItems.Select(i => RefreshMetadataForOwnedItem(i, false, options, cancellationToken));
await Task.WhenAll(tasks).ConfigureAwait(false); await Task.WhenAll(tasks).ConfigureAwait(false);

View File

@ -427,7 +427,7 @@ namespace MediaBrowser.Controller.Entities
if (IsStacked) if (IsStacked)
{ {
var tasks = AdditionalParts var tasks = AdditionalParts
.Select(i => RefreshMetadataForOwnedVideo(options, i, cancellationToken)); .Select(i => RefreshMetadataForOwnedVideo(options, true, i, cancellationToken));
await Task.WhenAll(tasks).ConfigureAwait(false); await Task.WhenAll(tasks).ConfigureAwait(false);
} }
@ -442,7 +442,7 @@ namespace MediaBrowser.Controller.Entities
RefreshLinkedAlternateVersions(); RefreshLinkedAlternateVersions();
var tasks = LocalAlternateVersions var tasks = LocalAlternateVersions
.Select(i => RefreshMetadataForOwnedVideo(options, i, cancellationToken)); .Select(i => RefreshMetadataForOwnedVideo(options, false, i, cancellationToken));
await Task.WhenAll(tasks).ConfigureAwait(false); await Task.WhenAll(tasks).ConfigureAwait(false);
} }

View File

@ -113,7 +113,11 @@ namespace MediaBrowser.Controller.LiveTv
public override bool CanDelete() public override bool CanDelete()
{ {
return Status == RecordingStatus.Completed || Status == RecordingStatus.New; if (string.Equals(ServiceName, "Emby", StringComparison.OrdinalIgnoreCase))
{
return Status == RecordingStatus.Completed;
}
return true;
} }
public override bool IsAuthorizedToDelete(User user) public override bool IsAuthorizedToDelete(User user)

View File

@ -130,7 +130,11 @@ namespace MediaBrowser.Controller.LiveTv
public override bool CanDelete() public override bool CanDelete()
{ {
return Status == RecordingStatus.Completed || Status == RecordingStatus.New; if (string.Equals(ServiceName, "Emby", StringComparison.OrdinalIgnoreCase))
{
return Status == RecordingStatus.Completed;
}
return true;
} }
public override bool IsAuthorizedToDelete(User user) public override bool IsAuthorizedToDelete(User user)

View File

@ -154,6 +154,8 @@ namespace MediaBrowser.MediaEncoding.Encoder
} }
}; };
_logger.Info("Running {0} {1}", path, arguments);
using (process) using (process)
{ {
process.Start(); process.Start();

View File

@ -610,6 +610,11 @@ namespace MediaBrowser.MediaEncoding.Encoder
{ {
if (video.Protocol != MediaProtocol.File) if (video.Protocol != MediaProtocol.File)
{ {
// If it's mpeg based, assume true
if ((videoStream.Codec ?? string.Empty).IndexOf("mpeg", StringComparison.OrdinalIgnoreCase) != -1)
{
return true;
}
return false; return false;
} }

View File

@ -478,6 +478,7 @@ namespace MediaBrowser.Model.Dlna
playlistItem.VideoCodec = transcodingProfile.VideoCodec; playlistItem.VideoCodec = transcodingProfile.VideoCodec;
playlistItem.CopyTimestamps = transcodingProfile.CopyTimestamps; playlistItem.CopyTimestamps = transcodingProfile.CopyTimestamps;
playlistItem.EnableSubtitlesInManifest = transcodingProfile.EnableSubtitlesInManifest; playlistItem.EnableSubtitlesInManifest = transcodingProfile.EnableSubtitlesInManifest;
playlistItem.EnableSplittingOnNonKeyFrames = transcodingProfile.EnableSplittingOnNonKeyFrames;
if (!string.IsNullOrEmpty(transcodingProfile.MaxAudioChannels)) if (!string.IsNullOrEmpty(transcodingProfile.MaxAudioChannels))
{ {

View File

@ -37,6 +37,7 @@ namespace MediaBrowser.Model.Dlna
public bool CopyTimestamps { get; set; } public bool CopyTimestamps { get; set; }
public bool EnableSubtitlesInManifest { get; set; } public bool EnableSubtitlesInManifest { get; set; }
public bool EnableSplittingOnNonKeyFrames { get; set; }
public string[] AudioCodecs { get; set; } public string[] AudioCodecs { get; set; }
public int? AudioStreamIndex { get; set; } public int? AudioStreamIndex { get; set; }
@ -264,6 +265,7 @@ namespace MediaBrowser.Model.Dlna
list.Add(new NameValuePair("EnableSubtitlesInManifest", item.EnableSubtitlesInManifest.ToString().ToLower())); list.Add(new NameValuePair("EnableSubtitlesInManifest", item.EnableSubtitlesInManifest.ToString().ToLower()));
list.Add(new NameValuePair("Tag", item.MediaSource.ETag ?? string.Empty)); list.Add(new NameValuePair("Tag", item.MediaSource.ETag ?? string.Empty));
list.Add(new NameValuePair("EnableSplittingOnNonKeyFrames", item.EnableSplittingOnNonKeyFrames.ToString().ToLower()));
return list; return list;
} }

View File

@ -38,6 +38,9 @@ namespace MediaBrowser.Model.Dlna
[XmlAttribute("enableSubtitlesInManifest")] [XmlAttribute("enableSubtitlesInManifest")]
public bool EnableSubtitlesInManifest { get; set; } public bool EnableSubtitlesInManifest { get; set; }
[XmlAttribute("enableSplittingOnNonKeyFrames")]
public bool EnableSplittingOnNonKeyFrames { get; set; }
[XmlAttribute("maxAudioChannels")] [XmlAttribute("maxAudioChannels")]
public string MaxAudioChannels { get; set; } public string MaxAudioChannels { get; set; }

View File

@ -66,10 +66,12 @@ namespace MediaBrowser.Server.Implementations.Intros
var candidates = new List<ItemWithTrailer>(); var candidates = new List<ItemWithTrailer>();
var trailerTypes = new List<TrailerType>(); var trailerTypes = new List<TrailerType>();
var sourceTypes = new List<SourceType>();
if (config.EnableIntrosFromMoviesInLibrary) if (config.EnableIntrosFromMoviesInLibrary)
{ {
trailerTypes.Add(TrailerType.LocalTrailer); trailerTypes.Add(TrailerType.LocalTrailer);
sourceTypes.Add(SourceType.Library);
} }
if (IsSupporter) if (IsSupporter)
@ -77,18 +79,22 @@ namespace MediaBrowser.Server.Implementations.Intros
if (config.EnableIntrosFromUpcomingTrailers) if (config.EnableIntrosFromUpcomingTrailers)
{ {
trailerTypes.Add(TrailerType.ComingSoonToTheaters); trailerTypes.Add(TrailerType.ComingSoonToTheaters);
sourceTypes.Clear();
} }
if (config.EnableIntrosFromUpcomingDvdMovies) if (config.EnableIntrosFromUpcomingDvdMovies)
{ {
trailerTypes.Add(TrailerType.ComingSoonToDvd); trailerTypes.Add(TrailerType.ComingSoonToDvd);
sourceTypes.Clear();
} }
if (config.EnableIntrosFromUpcomingStreamingMovies) if (config.EnableIntrosFromUpcomingStreamingMovies)
{ {
trailerTypes.Add(TrailerType.ComingSoonToStreaming); trailerTypes.Add(TrailerType.ComingSoonToStreaming);
sourceTypes.Clear();
} }
if (config.EnableIntrosFromSimilarMovies) if (config.EnableIntrosFromSimilarMovies)
{ {
trailerTypes.Add(TrailerType.Archive); trailerTypes.Add(TrailerType.Archive);
sourceTypes.Clear();
} }
} }
@ -102,7 +108,8 @@ namespace MediaBrowser.Server.Implementations.Intros
IsPlayed = config.EnableIntrosForWatchedContent ? (bool?)null : false, IsPlayed = config.EnableIntrosForWatchedContent ? (bool?)null : false,
MaxParentalRating = config.EnableIntrosParentalControl ? ratingLevel : null, MaxParentalRating = config.EnableIntrosParentalControl ? ratingLevel : null,
BlockUnratedItems = config.EnableIntrosParentalControl ? new[] { UnratedItem.Trailer } : new UnratedItem[] { }, BlockUnratedItems = config.EnableIntrosParentalControl ? new[] { UnratedItem.Trailer } : new UnratedItem[] { },
Limit = config.TrailerLimit Limit = config.TrailerLimit,
SourceTypes = sourceTypes.ToArray()
}); });
candidates.AddRange(trailerResult.Select(i => new ItemWithTrailer candidates.AddRange(trailerResult.Select(i => new ItemWithTrailer

View File

@ -764,7 +764,7 @@ namespace MediaBrowser.Server.Implementations.LiveTv.EmbyTV
defaults.RecordNewOnly = !program.IsRepeat; defaults.RecordNewOnly = !program.IsRepeat;
} }
defaults.SkipEpisodesInLibrary = true; defaults.SkipEpisodesInLibrary = defaults.RecordNewOnly;
defaults.KeepUntil = KeepUntil.UntilDeleted; defaults.KeepUntil = KeepUntil.UntilDeleted;
return Task.FromResult(defaults); return Task.FromResult(defaults);

View File

@ -114,6 +114,10 @@ namespace MediaBrowser.Server.Implementations.LiveTv.TunerHosts
{ {
protocol = MediaProtocol.Rtsp; protocol = MediaProtocol.Rtsp;
} }
else if (path.StartsWith("udp", StringComparison.OrdinalIgnoreCase))
{
protocol = MediaProtocol.Udp;
}
var mediaSource = new MediaSourceInfo var mediaSource = new MediaSourceInfo
{ {

View File

@ -2,7 +2,7 @@
<package xmlns="http://schemas.microsoft.com/packaging/2011/08/nuspec.xsd"> <package xmlns="http://schemas.microsoft.com/packaging/2011/08/nuspec.xsd">
<metadata> <metadata>
<id>MediaBrowser.Common.Internal</id> <id>MediaBrowser.Common.Internal</id>
<version>3.0.662</version> <version>3.0.663</version>
<title>MediaBrowser.Common.Internal</title> <title>MediaBrowser.Common.Internal</title>
<authors>Luke</authors> <authors>Luke</authors>
<owners>ebr,Luke,scottisafool</owners> <owners>ebr,Luke,scottisafool</owners>
@ -12,7 +12,7 @@
<description>Contains common components shared by Emby Theater and Emby Server. Not intended for plugin developer consumption.</description> <description>Contains common components shared by Emby Theater and Emby Server. Not intended for plugin developer consumption.</description>
<copyright>Copyright © Emby 2013</copyright> <copyright>Copyright © Emby 2013</copyright>
<dependencies> <dependencies>
<dependency id="MediaBrowser.Common" version="3.0.662" /> <dependency id="MediaBrowser.Common" version="3.0.663" />
<dependency id="NLog" version="4.3.8" /> <dependency id="NLog" version="4.3.8" />
<dependency id="SimpleInjector" version="3.2.2" /> <dependency id="SimpleInjector" version="3.2.2" />
</dependencies> </dependencies>

View File

@ -2,7 +2,7 @@
<package xmlns="http://schemas.microsoft.com/packaging/2011/08/nuspec.xsd"> <package xmlns="http://schemas.microsoft.com/packaging/2011/08/nuspec.xsd">
<metadata> <metadata>
<id>MediaBrowser.Common</id> <id>MediaBrowser.Common</id>
<version>3.0.662</version> <version>3.0.663</version>
<title>MediaBrowser.Common</title> <title>MediaBrowser.Common</title>
<authors>Emby Team</authors> <authors>Emby Team</authors>
<owners>ebr,Luke,scottisafool</owners> <owners>ebr,Luke,scottisafool</owners>

View File

@ -2,7 +2,7 @@
<package xmlns="http://schemas.microsoft.com/packaging/2010/07/nuspec.xsd"> <package xmlns="http://schemas.microsoft.com/packaging/2010/07/nuspec.xsd">
<metadata> <metadata>
<id>MediaBrowser.Server.Core</id> <id>MediaBrowser.Server.Core</id>
<version>3.0.662</version> <version>3.0.663</version>
<title>Media Browser.Server.Core</title> <title>Media Browser.Server.Core</title>
<authors>Emby Team</authors> <authors>Emby Team</authors>
<owners>ebr,Luke,scottisafool</owners> <owners>ebr,Luke,scottisafool</owners>
@ -12,7 +12,7 @@
<description>Contains core components required to build plugins for Emby Server.</description> <description>Contains core components required to build plugins for Emby Server.</description>
<copyright>Copyright © Emby 2013</copyright> <copyright>Copyright © Emby 2013</copyright>
<dependencies> <dependencies>
<dependency id="MediaBrowser.Common" version="3.0.662" /> <dependency id="MediaBrowser.Common" version="3.0.663" />
<dependency id="Interfaces.IO" version="1.0.0.5" /> <dependency id="Interfaces.IO" version="1.0.0.5" />
</dependencies> </dependencies>
</metadata> </metadata>