aboutsummaryrefslogtreecommitdiff
path: root/MediaBrowser.Providers
diff options
context:
space:
mode:
Diffstat (limited to 'MediaBrowser.Providers')
-rw-r--r--MediaBrowser.Providers/BoxSets/BoxSetMetadataService.cs6
-rw-r--r--MediaBrowser.Providers/FolderImages/DefaultImageProvider.cs153
-rw-r--r--MediaBrowser.Providers/Manager/ItemImageProvider.cs38
-rw-r--r--MediaBrowser.Providers/Manager/MetadataService.cs7
-rw-r--r--MediaBrowser.Providers/Manager/ProviderManager.cs7
-rw-r--r--MediaBrowser.Providers/MediaBrowser.Providers.csproj9
-rw-r--r--MediaBrowser.Providers/MediaInfo/FFProbeAudioInfo.cs350
-rw-r--r--MediaBrowser.Providers/MediaInfo/FFProbeHelpers.cs118
-rw-r--r--MediaBrowser.Providers/MediaInfo/FFProbeVideoInfo.cs326
-rw-r--r--MediaBrowser.Providers/MediaInfo/VideoImageProvider.cs6
-rw-r--r--MediaBrowser.Providers/MediaInfo/whitelist.txt1
-rw-r--r--MediaBrowser.Providers/Movies/FanArtMovieUpdatesPostScanTask.cs2
-rw-r--r--MediaBrowser.Providers/Movies/MovieMetadataService.cs4
-rw-r--r--MediaBrowser.Providers/Music/ArtistMetadataService.cs2
-rw-r--r--MediaBrowser.Providers/TV/SeriesMetadataService.cs4
-rw-r--r--MediaBrowser.Providers/TV/TvdbSeriesProvider.cs32
16 files changed, 213 insertions, 852 deletions
diff --git a/MediaBrowser.Providers/BoxSets/BoxSetMetadataService.cs b/MediaBrowser.Providers/BoxSets/BoxSetMetadataService.cs
index 3ac3cccb3d..92327c9bc3 100644
--- a/MediaBrowser.Providers/BoxSets/BoxSetMetadataService.cs
+++ b/MediaBrowser.Providers/BoxSets/BoxSetMetadataService.cs
@@ -3,7 +3,6 @@ using MediaBrowser.Controller.Configuration;
using MediaBrowser.Controller.Entities;
using MediaBrowser.Controller.Entities.Movies;
using MediaBrowser.Controller.Library;
-using MediaBrowser.Controller.Localization;
using MediaBrowser.Controller.Providers;
using MediaBrowser.Model.Entities;
using MediaBrowser.Model.Logging;
@@ -16,11 +15,8 @@ namespace MediaBrowser.Providers.BoxSets
{
public class BoxSetMetadataService : MetadataService<BoxSet, BoxSetInfo>
{
- private readonly ILocalizationManager _iLocalizationManager;
-
- public BoxSetMetadataService(IServerConfigurationManager serverConfigurationManager, ILogger logger, IProviderManager providerManager, IProviderRepository providerRepo, IFileSystem fileSystem, IUserDataManager userDataManager, ILocalizationManager iLocalizationManager) : base(serverConfigurationManager, logger, providerManager, providerRepo, fileSystem, userDataManager)
+ public BoxSetMetadataService(IServerConfigurationManager serverConfigurationManager, ILogger logger, IProviderManager providerManager, IProviderRepository providerRepo, IFileSystem fileSystem, IUserDataManager userDataManager) : base(serverConfigurationManager, logger, providerManager, providerRepo, fileSystem, userDataManager)
{
- _iLocalizationManager = iLocalizationManager;
}
/// <summary>
diff --git a/MediaBrowser.Providers/FolderImages/DefaultImageProvider.cs b/MediaBrowser.Providers/FolderImages/DefaultImageProvider.cs
deleted file mode 100644
index 3550ee6885..0000000000
--- a/MediaBrowser.Providers/FolderImages/DefaultImageProvider.cs
+++ /dev/null
@@ -1,153 +0,0 @@
-using MediaBrowser.Common.Net;
-using MediaBrowser.Controller.Entities;
-using MediaBrowser.Controller.Providers;
-using MediaBrowser.Model.Entities;
-using MediaBrowser.Model.Providers;
-using MediaBrowser.Providers.Genres;
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Threading;
-using System.Threading.Tasks;
-
-namespace MediaBrowser.Providers.FolderImages
-{
- public class DefaultImageProvider : IRemoteImageProvider, IHasItemChangeMonitor, IHasOrder
- {
- private readonly IHttpClient _httpClient;
-
- public DefaultImageProvider(IHttpClient httpClient)
- {
- _httpClient = httpClient;
- }
-
- public IEnumerable<ImageType> GetSupportedImages(IHasImages item)
- {
- return new List<ImageType>
- {
- ImageType.Primary,
- ImageType.Thumb
- };
- }
-
- public Task<IEnumerable<RemoteImageInfo>> GetImages(IHasImages item, CancellationToken cancellationToken)
- {
- var view = item as UserView;
-
- if (view != null)
- {
- return GetImages(view.ViewType, view.ParentId != Guid.Empty, cancellationToken);
- }
-
- var folder = (ICollectionFolder)item;
- return GetImages(folder.CollectionType, false, cancellationToken);
- }
-
- private Task<IEnumerable<RemoteImageInfo>> GetImages(string viewType, bool isSubView, CancellationToken cancellationToken)
- {
- var url = GetImageUrl(viewType, isSubView);
- var list = new List<RemoteImageInfo>();
-
- if (!string.IsNullOrWhiteSpace(url))
- {
- list.AddRange(new List<RemoteImageInfo>
- {
- new RemoteImageInfo
- {
- ProviderName = Name,
- Url = url,
- Type = ImageType.Primary
- },
-
- new RemoteImageInfo
- {
- ProviderName = Name,
- Url = url,
- Type = ImageType.Thumb
- }
- });
- }
-
- return Task.FromResult<IEnumerable<RemoteImageInfo>>(list);
- }
-
- private string GetImageUrl(string viewType, bool isSubView)
- {
- const string urlPrefix = "https://raw.githubusercontent.com/MediaBrowser/MediaBrowser.Resources/master/images/folders/";
-
- if (string.Equals(viewType, CollectionType.Books, StringComparison.OrdinalIgnoreCase))
- {
- return null;
- }
- if (string.Equals(viewType, CollectionType.Games, StringComparison.OrdinalIgnoreCase))
- {
- return null;
- }
- if (string.Equals(viewType, CollectionType.Music, StringComparison.OrdinalIgnoreCase))
- {
- return null;
- }
- if (string.Equals(viewType, CollectionType.Photos, StringComparison.OrdinalIgnoreCase))
- {
- return null;
- }
- if (string.Equals(viewType, CollectionType.TvShows, StringComparison.OrdinalIgnoreCase))
- {
- return null;
- }
- if (string.Equals(viewType, CollectionType.Channels, StringComparison.OrdinalIgnoreCase))
- {
- return null;
- }
- if (string.Equals(viewType, CollectionType.LiveTv, StringComparison.OrdinalIgnoreCase))
- {
- return null;
- }
- if (string.Equals(viewType, CollectionType.Movies, StringComparison.OrdinalIgnoreCase))
- {
- return null;
- }
-
- if (isSubView)
- {
- return null;
- }
-
- return urlPrefix + "generic.png";
- }
-
- public string Name
- {
- get { return "Default Image Provider"; }
- }
-
- public bool Supports(IHasImages item)
- {
- return item is ICollectionFolder || item is UserView;
- }
-
- public Task<HttpResponseInfo> GetImageResponse(string url, CancellationToken cancellationToken)
- {
- return _httpClient.GetResponse(new HttpRequestOptions
- {
- CancellationToken = cancellationToken,
- Url = url,
- ResourcePool = GenreImageProvider.ImageDownloadResourcePool
- });
- }
-
- public bool HasChanged(IHasMetadata item, MetadataStatus status, IDirectoryService directoryService)
- {
- return GetSupportedImages(item).Any(i => !item.HasImage(i));
- }
-
- public int Order
- {
- get
- {
- // Run after the dynamic image provider
- return 1;
- }
- }
- }
-}
diff --git a/MediaBrowser.Providers/Manager/ItemImageProvider.cs b/MediaBrowser.Providers/Manager/ItemImageProvider.cs
index 533e843ea8..fc47b0259a 100644
--- a/MediaBrowser.Providers/Manager/ItemImageProvider.cs
+++ b/MediaBrowser.Providers/Manager/ItemImageProvider.cs
@@ -36,16 +36,15 @@ namespace MediaBrowser.Providers.Manager
public bool ValidateImages(IHasImages item, IEnumerable<IImageProvider> providers, IDirectoryService directoryService)
{
- var hasChanges = item.ValidateImages(directoryService);
+ var hasChanges = false;
- foreach (var provider in providers.OfType<ILocalImageFileProvider>())
- {
- var images = provider.GetImages(item, directoryService);
+ var images = providers.OfType<ILocalImageFileProvider>()
+ .SelectMany(i => i.GetImages(item, directoryService))
+ .ToList();
- if (MergeImages(item, images))
- {
- hasChanges = true;
- }
+ if (MergeImages(item, images))
+ {
+ hasChanges = true;
}
return hasChanges;
@@ -377,8 +376,7 @@ namespace MediaBrowser.Providers.Manager
item.SetImagePath(type, image.FileInfo);
changed = true;
}
- else if (!string.Equals(currentImage.Path, image.FileInfo.FullName,
- StringComparison.OrdinalIgnoreCase))
+ else if (!string.Equals(currentImage.Path, image.FileInfo.FullName, StringComparison.OrdinalIgnoreCase))
{
item.SetImagePath(type, image.FileInfo);
changed = true;
@@ -386,7 +384,15 @@ namespace MediaBrowser.Providers.Manager
else
{
currentImage.DateModified = _fileSystem.GetLastWriteTimeUtc(image.FileInfo);
- currentImage.Length = ((FileInfo) image.FileInfo).Length;
+ }
+ }
+ else
+ {
+ var existing = item.GetImageInfo(type, 0);
+ if (existing != null && !File.Exists(existing.Path))
+ {
+ item.RemoveImage(existing);
+ changed = true;
}
}
}
@@ -412,16 +418,16 @@ namespace MediaBrowser.Providers.Manager
{
var changed = false;
- var backdrops = images.Where(i => i.Type == type).ToList();
- if (backdrops.Count > 0)
+ var newImages = images.Where(i => i.Type == type).ToList();
+ if (newImages.Count > 0)
{
- var foundImages = images.Where(i => i.Type == type)
+ var newImageFileInfos = images.Where(i => i.Type == type)
.Select(i => i.FileInfo)
.ToList();
- if (foundImages.Count > 0)
+ if (newImageFileInfos.Count > 0)
{
- if (item.AddImages(type, foundImages))
+ if (item.AddImages(type, newImageFileInfos))
{
changed = true;
}
diff --git a/MediaBrowser.Providers/Manager/MetadataService.cs b/MediaBrowser.Providers/Manager/MetadataService.cs
index 62def8b8bb..334e148506 100644
--- a/MediaBrowser.Providers/Manager/MetadataService.cs
+++ b/MediaBrowser.Providers/Manager/MetadataService.cs
@@ -141,7 +141,6 @@ namespace MediaBrowser.Providers.Manager
updateType = updateType | result.UpdateType;
refreshResult.AddStatus(result.Status, result.ErrorMessage);
refreshResult.SetDateLastMetadataRefresh(DateTime.UtcNow);
- refreshResult.AddMetadataProvidersRefreshed(result.Providers);
MergeIdentities(itemOfType, id);
}
@@ -159,7 +158,6 @@ namespace MediaBrowser.Providers.Manager
updateType = updateType | result.UpdateType;
refreshResult.AddStatus(result.Status, result.ErrorMessage);
refreshResult.SetDateLastImagesRefresh(DateTime.UtcNow);
- refreshResult.AddImageProvidersRefreshed(result.Providers);
}
}
@@ -484,6 +482,11 @@ namespace MediaBrowser.Providers.Manager
protected virtual bool IsFullLocalMetadata(TItemType item)
{
+ if (string.IsNullOrWhiteSpace(item.Name))
+ {
+ return false;
+ }
+
return true;
}
diff --git a/MediaBrowser.Providers/Manager/ProviderManager.cs b/MediaBrowser.Providers/Manager/ProviderManager.cs
index c9ae47ad0b..01a89bf26d 100644
--- a/MediaBrowser.Providers/Manager/ProviderManager.cs
+++ b/MediaBrowser.Providers/Manager/ProviderManager.cs
@@ -148,6 +148,13 @@ namespace MediaBrowser.Providers.Manager
return new ImageSaver(ConfigurationManager, _libraryMonitor, _fileSystem, _logger).SaveImage(item, source, mimeType, type, imageIndex, internalCacheKey, cancellationToken);
}
+ public Task SaveImage(IHasImages item, string source, string mimeType, ImageType type, int? imageIndex, string internalCacheKey, CancellationToken cancellationToken)
+ {
+ var fileStream = _fileSystem.GetFileStream(source, FileMode.Open, FileAccess.Read, FileShare.ReadWrite, true);
+
+ return new ImageSaver(ConfigurationManager, _libraryMonitor, _fileSystem, _logger).SaveImage(item, fileStream, mimeType, type, imageIndex, internalCacheKey, cancellationToken);
+ }
+
public async Task<IEnumerable<RemoteImageInfo>> GetAvailableRemoteImages(IHasImages item, RemoteImageQuery query, CancellationToken cancellationToken)
{
var providers = GetRemoteImageProviders(item, query.IncludeDisabledProviders);
diff --git a/MediaBrowser.Providers/MediaBrowser.Providers.csproj b/MediaBrowser.Providers/MediaBrowser.Providers.csproj
index 3b5103f209..444567afaf 100644
--- a/MediaBrowser.Providers/MediaBrowser.Providers.csproj
+++ b/MediaBrowser.Providers/MediaBrowser.Providers.csproj
@@ -83,7 +83,6 @@
<Compile Include="BoxSets\MovieDbBoxSetProvider.cs" />
<Compile Include="Channels\ChannelMetadataService.cs" />
<Compile Include="Chapters\ChapterManager.cs" />
- <Compile Include="FolderImages\DefaultImageProvider.cs" />
<Compile Include="Folders\FolderMetadataService.cs" />
<Compile Include="Channels\AudioChannelItemMetadataService.cs" />
<Compile Include="Folders\UserViewMetadataService.cs" />
@@ -102,7 +101,6 @@
<Compile Include="Manager\MetadataService.cs" />
<Compile Include="Manager\SeriesOrderManager.cs" />
<Compile Include="MediaInfo\FFProbeAudioInfo.cs" />
- <Compile Include="MediaInfo\FFProbeHelpers.cs" />
<Compile Include="MediaInfo\FFProbeProvider.cs" />
<Compile Include="MediaInfo\FFProbeVideoInfo.cs" />
<Compile Include="MediaInfo\SubtitleDownloader.cs" />
@@ -198,10 +196,6 @@
<Project>{17E1F4E6-8ABD-4FE5-9ECF-43D4B6087BA2}</Project>
<Name>MediaBrowser.Controller</Name>
</ProjectReference>
- <ProjectReference Include="..\MediaBrowser.MediaInfo\MediaBrowser.MediaInfo.csproj">
- <Project>{6e4145e4-c6d4-4e4d-94f2-87188db6e239}</Project>
- <Name>MediaBrowser.MediaInfo</Name>
- </ProjectReference>
<ProjectReference Include="..\MediaBrowser.Model\MediaBrowser.Model.csproj">
<Project>{7EEEB4BB-F3E8-48FC-B4C5-70F0FFF8329B}</Project>
<Name>MediaBrowser.Model</Name>
@@ -214,9 +208,6 @@
<ItemGroup>
<None Include="packages.config" />
</ItemGroup>
- <ItemGroup>
- <EmbeddedResource Include="MediaInfo\whitelist.txt" />
- </ItemGroup>
<ItemGroup />
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
diff --git a/MediaBrowser.Providers/MediaInfo/FFProbeAudioInfo.cs b/MediaBrowser.Providers/MediaInfo/FFProbeAudioInfo.cs
index ea191dd08f..d78f1b48e6 100644
--- a/MediaBrowser.Providers/MediaInfo/FFProbeAudioInfo.cs
+++ b/MediaBrowser.Providers/MediaInfo/FFProbeAudioInfo.cs
@@ -1,15 +1,13 @@
using MediaBrowser.Common.Configuration;
-using MediaBrowser.Model.Extensions;
using MediaBrowser.Controller.Entities;
using MediaBrowser.Controller.Entities.Audio;
using MediaBrowser.Controller.Library;
using MediaBrowser.Controller.MediaEncoding;
using MediaBrowser.Controller.Persistence;
+using MediaBrowser.Model.Dlna;
using MediaBrowser.Model.Entities;
using MediaBrowser.Model.MediaInfo;
using MediaBrowser.Model.Serialization;
-using System;
-using System.Collections.Generic;
using System.Globalization;
using System.IO;
using System.Linq;
@@ -49,18 +47,14 @@ namespace MediaBrowser.Providers.MediaInfo
cancellationToken.ThrowIfCancellationRequested();
- FFProbeHelpers.NormalizeFFProbeResult(result);
-
- cancellationToken.ThrowIfCancellationRequested();
-
await Fetch(item, cancellationToken, result).ConfigureAwait(false);
return ItemUpdateType.MetadataImport;
}
- private const string SchemaVersion = "1";
+ private const string SchemaVersion = "2";
- private async Task<InternalMediaInfoResult> GetMediaInfo(BaseItem item, CancellationToken cancellationToken)
+ private async Task<Model.MediaInfo.MediaInfo> GetMediaInfo(BaseItem item, CancellationToken cancellationToken)
{
cancellationToken.ThrowIfCancellationRequested();
@@ -71,7 +65,7 @@ namespace MediaBrowser.Providers.MediaInfo
try
{
- return _json.DeserializeFromFile<InternalMediaInfoResult>(cachePath);
+ return _json.DeserializeFromFile<Model.MediaInfo.MediaInfo>(cachePath);
}
catch (FileNotFoundException)
{
@@ -81,9 +75,13 @@ namespace MediaBrowser.Providers.MediaInfo
{
}
- var inputPath = new[] { item.Path };
+ var result = await _mediaEncoder.GetMediaInfo(new MediaInfoRequest
+ {
+ InputPath = item.Path,
+ MediaType = DlnaProfileType.Audio,
+ Protocol = MediaProtocol.File
- var result = await _mediaEncoder.GetMediaInfo(inputPath, MediaProtocol.File, false, cancellationToken).ConfigureAwait(false);
+ }, cancellationToken).ConfigureAwait(false);
Directory.CreateDirectory(Path.GetDirectoryName(cachePath));
_json.SerializeToFile(result, cachePath);
@@ -96,61 +94,23 @@ namespace MediaBrowser.Providers.MediaInfo
/// </summary>
/// <param name="audio">The audio.</param>
/// <param name="cancellationToken">The cancellation token.</param>
- /// <param name="data">The data.</param>
+ /// <param name="mediaInfo">The media information.</param>
/// <returns>Task.</returns>
- protected Task Fetch(Audio audio, CancellationToken cancellationToken, InternalMediaInfoResult data)
+ protected Task Fetch(Audio audio, CancellationToken cancellationToken, Model.MediaInfo.MediaInfo mediaInfo)
{
- var mediaInfo = MediaEncoderHelpers.GetMediaInfo(data);
var mediaStreams = mediaInfo.MediaStreams;
- audio.FormatName = mediaInfo.Format;
- audio.TotalBitrate = mediaInfo.TotalBitrate;
+ audio.FormatName = mediaInfo.Container;
+ audio.TotalBitrate = mediaInfo.Bitrate;
audio.HasEmbeddedImage = mediaStreams.Any(i => i.Type == MediaStreamType.EmbeddedImage);
- if (data.streams != null)
- {
- // Get the first audio stream
- var stream = data.streams.FirstOrDefault(s => string.Equals(s.codec_type, "audio", StringComparison.OrdinalIgnoreCase));
-
- if (stream != null)
- {
- // Get duration from stream properties
- var duration = stream.duration;
-
- // If it's not there go into format properties
- if (string.IsNullOrEmpty(duration))
- {
- duration = data.format.duration;
- }
-
- // If we got something, parse it
- if (!string.IsNullOrEmpty(duration))
- {
- audio.RunTimeTicks = TimeSpan.FromSeconds(double.Parse(duration, _usCulture)).Ticks;
- }
- }
- }
-
- if (data.format != null)
- {
- var extension = (Path.GetExtension(audio.Path) ?? string.Empty).TrimStart('.');
-
- audio.Container = extension;
+ audio.RunTimeTicks = mediaInfo.RunTimeTicks;
+ audio.Size = mediaInfo.Size;
- if (!string.IsNullOrEmpty(data.format.size))
- {
- audio.Size = long.Parse(data.format.size, _usCulture);
- }
- else
- {
- audio.Size = null;
- }
+ var extension = (Path.GetExtension(audio.Path) ?? string.Empty).TrimStart('.');
+ audio.Container = extension;
- if (data.format.tags != null)
- {
- FetchDataFromTags(audio, data.format.tags);
- }
- }
+ FetchDataFromTags(audio, mediaInfo);
return _itemRepo.SaveMediaStreams(audio.Id, mediaStreams, cancellationToken);
}
@@ -159,92 +119,37 @@ namespace MediaBrowser.Providers.MediaInfo
/// Fetches data from the tags dictionary
/// </summary>
/// <param name="audio">The audio.</param>
- /// <param name="tags">The tags.</param>
- private void FetchDataFromTags(Audio audio, Dictionary<string, string> tags)
+ /// <param name="data">The data.</param>
+ private void FetchDataFromTags(Audio audio, Model.MediaInfo.MediaInfo data)
{
- var title = FFProbeHelpers.GetDictionaryValue(tags, "title");
-
// Only set Name if title was found in the dictionary
- if (!string.IsNullOrEmpty(title))
+ if (!string.IsNullOrEmpty(data.Title))
{
- audio.Name = title;
+ audio.Name = data.Title;
}
if (!audio.LockedFields.Contains(MetadataFields.Cast))
{
audio.People.Clear();
- var composer = FFProbeHelpers.GetDictionaryValue(tags, "composer");
-
- if (!string.IsNullOrWhiteSpace(composer))
+ foreach (var person in data.People)
{
- foreach (var person in Split(composer, false))
+ audio.AddPerson(new PersonInfo
{
- audio.AddPerson(new PersonInfo { Name = person, Type = PersonType.Composer });
- }
+ Name = person.Name,
+ Type = person.Type,
+ Role = person.Role
+ });
}
}
- audio.Album = FFProbeHelpers.GetDictionaryValue(tags, "album");
-
- var artists = FFProbeHelpers.GetDictionaryValue(tags, "artists");
-
- if (!string.IsNullOrWhiteSpace(artists))
- {
- audio.Artists = artists.Split(new[] { '/' }, StringSplitOptions.RemoveEmptyEntries)
- .Distinct(StringComparer.OrdinalIgnoreCase)
- .ToList();
- }
- else
- {
- var artist = FFProbeHelpers.GetDictionaryValue(tags, "artist");
- if (string.IsNullOrWhiteSpace(artist))
- {
- audio.Artists.Clear();
- }
- else
- {
- audio.Artists = SplitArtists(artist)
- .Distinct(StringComparer.OrdinalIgnoreCase)
- .ToList();
- }
- }
-
- var albumArtist = FFProbeHelpers.GetDictionaryValue(tags, "albumartist");
- if (string.IsNullOrWhiteSpace(albumArtist))
- {
- albumArtist = FFProbeHelpers.GetDictionaryValue(tags, "album artist");
- }
- if (string.IsNullOrWhiteSpace(albumArtist))
- {
- albumArtist = FFProbeHelpers.GetDictionaryValue(tags, "album_artist");
- }
-
- if (string.IsNullOrWhiteSpace(albumArtist))
- {
- audio.AlbumArtists = new List<string>();
- }
- else
- {
- audio.AlbumArtists = SplitArtists(albumArtist)
- .Distinct(StringComparer.OrdinalIgnoreCase)
- .ToList();
-
- }
-
- // Track number
- audio.IndexNumber = GetDictionaryDiscValue(tags, "track");
-
- // Disc number
- audio.ParentIndexNumber = GetDictionaryDiscValue(tags, "disc");
-
- audio.ProductionYear = FFProbeHelpers.GetDictionaryNumericValue(tags, "date");
-
- // Several different forms of retaildate
- audio.PremiereDate = FFProbeHelpers.GetDictionaryDateTime(tags, "retaildate") ??
- FFProbeHelpers.GetDictionaryDateTime(tags, "retail date") ??
- FFProbeHelpers.GetDictionaryDateTime(tags, "retail_date") ??
- FFProbeHelpers.GetDictionaryDateTime(tags, "date");
+ audio.Album = data.Album;
+ audio.Artists = data.Artists;
+ audio.AlbumArtists = data.AlbumArtists;
+ audio.IndexNumber = data.IndexNumber;
+ audio.ParentIndexNumber = data.ParentIndexNumber;
+ audio.ProductionYear = data.ProductionYear;
+ audio.PremiereDate = data.PremiereDate;
// If we don't have a ProductionYear try and get it from PremiereDate
if (audio.PremiereDate.HasValue && !audio.ProductionYear.HasValue)
@@ -254,192 +159,29 @@ namespace MediaBrowser.Providers.MediaInfo
if (!audio.LockedFields.Contains(MetadataFields.Genres))
{
- FetchGenres(audio, tags);
- }
-
- if (!audio.LockedFields.Contains(MetadataFields.Studios))
- {
- audio.Studios.Clear();
-
- // There's several values in tags may or may not be present
- FetchStudios(audio, tags, "organization");
- FetchStudios(audio, tags, "ensemble");
- FetchStudios(audio, tags, "publisher");
- }
-
- // These support mulitple values, but for now we only store the first.
- audio.SetProviderId(MetadataProviders.MusicBrainzAlbumArtist, GetMultipleMusicBrainzId(FFProbeHelpers.GetDictionaryValue(tags, "MusicBrainz Album Artist Id")));
- audio.SetProviderId(MetadataProviders.MusicBrainzArtist, GetMultipleMusicBrainzId(FFProbeHelpers.GetDictionaryValue(tags, "MusicBrainz Artist Id")));
-
- audio.SetProviderId(MetadataProviders.MusicBrainzAlbum, GetMultipleMusicBrainzId(FFProbeHelpers.GetDictionaryValue(tags, "MusicBrainz Album Id")));
- audio.SetProviderId(MetadataProviders.MusicBrainzReleaseGroup, GetMultipleMusicBrainzId(FFProbeHelpers.GetDictionaryValue(tags, "MusicBrainz Release Group Id")));
- audio.SetProviderId(MetadataProviders.MusicBrainzTrack, GetMultipleMusicBrainzId(FFProbeHelpers.GetDictionaryValue(tags, "MusicBrainz Release Track Id")));
- }
-
- private string GetMultipleMusicBrainzId(string value)
- {
- if (string.IsNullOrWhiteSpace(value))
- {
- return null;
- }
-
- return value.Split(new[] { '/' }, StringSplitOptions.RemoveEmptyEntries)
- .Select(i => i.Trim())
- .FirstOrDefault(i => !string.IsNullOrWhiteSpace(i));
- }
-
- private readonly char[] _nameDelimiters = { '/', '|', ';', '\\' };
-
- /// <summary>
- /// Splits the specified val.
- /// </summary>
- /// <param name="val">The val.</param>
- /// <param name="allowCommaDelimiter">if set to <c>true</c> [allow comma delimiter].</param>
- /// <returns>System.String[][].</returns>
- private IEnumerable<string> Split(string val, bool allowCommaDelimiter)
- {
- // Only use the comma as a delimeter if there are no slashes or pipes.
- // We want to be careful not to split names that have commas in them
- var delimeter = !allowCommaDelimiter || _nameDelimiters.Any(i => val.IndexOf(i) != -1) ?
- _nameDelimiters :
- new[] { ',' };
-
- return val.Split(delimeter, StringSplitOptions.RemoveEmptyEntries)
- .Where(i => !string.IsNullOrWhiteSpace(i))
- .Select(i => i.Trim());
- }
-
- private const string ArtistReplaceValue = " | ";
-
- private IEnumerable<string> SplitArtists(string val)
- {
- val = val.Replace(" featuring ", ArtistReplaceValue, StringComparison.OrdinalIgnoreCase)
- .Replace(" feat. ", ArtistReplaceValue, StringComparison.OrdinalIgnoreCase);
-
- var artistsFound = new List<string>();
-
- foreach (var whitelistArtist in GetSplitWhitelist())
- {
- var originalVal = val;
- val = val.Replace(whitelistArtist, "|", StringComparison.OrdinalIgnoreCase);
-
- if (!string.Equals(originalVal, val, StringComparison.OrdinalIgnoreCase))
- {
- artistsFound.Add(whitelistArtist);
- }
- }
-
- // Only use the comma as a delimeter if there are no slashes or pipes.
- // We want to be careful not to split names that have commas in them
- var delimeter = _nameDelimiters;
-
- var artists = val.Split(delimeter, StringSplitOptions.RemoveEmptyEntries)
- .Where(i => !string.IsNullOrWhiteSpace(i))
- .Select(i => i.Trim());
-
- artistsFound.AddRange(artists);
- return artistsFound;
- }
-
-
- private List<string> _splitWhiteList = null;
-
- private IEnumerable<string> GetSplitWhitelist()
- {
- if (_splitWhiteList == null)
- {
- var file = GetType().Namespace + ".whitelist.txt";
-
- using (var stream = GetType().Assembly.GetManifestResourceStream(file))
- {
- using (var reader = new StreamReader(stream))
- {
- var list = new List<string>();
-
- while (!reader.EndOfStream)
- {
- var val = reader.ReadLine();
-
- if (!string.IsNullOrWhiteSpace(val))
- {
- list.Add(val);
- }
- }
-
- _splitWhiteList = list;
- }
- }
- }
-
- return _splitWhiteList;
- }
-
- /// <summary>
- /// Gets the studios from the tags collection
- /// </summary>
- /// <param name="audio">The audio.</param>
- /// <param name="tags">The tags.</param>
- /// <param name="tagName">Name of the tag.</param>
- private void FetchStudios(Audio audio, Dictionary<string, string> tags, string tagName)
- {
- var val = FFProbeHelpers.GetDictionaryValue(tags, tagName);
-
- if (!string.IsNullOrEmpty(val))
- {
- // Sometimes the artist name is listed here, account for that
- var studios = Split(val, true).Where(i => !audio.HasAnyArtist(i));
-
- foreach (var studio in studios)
- {
- audio.AddStudio(studio);
- }
- }
- }
-
- /// <summary>
- /// Gets the genres from the tags collection
- /// </summary>
- /// <param name="audio">The audio.</param>
- /// <param name="tags">The tags.</param>
- private void FetchGenres(Audio audio, Dictionary<string, string> tags)
- {
- var val = FFProbeHelpers.GetDictionaryValue(tags, "genre");
-
- if (!string.IsNullOrEmpty(val))
- {
audio.Genres.Clear();
- foreach (var genre in Split(val, true))
+ foreach (var genre in data.Genres)
{
audio.AddGenre(genre);
}
}
- }
-
- /// <summary>
- /// Gets the disc number, which is sometimes can be in the form of '1', or '1/3'
- /// </summary>
- /// <param name="tags">The tags.</param>
- /// <param name="tagName">Name of the tag.</param>
- /// <returns>System.Nullable{System.Int32}.</returns>
- private int? GetDictionaryDiscValue(Dictionary<string, string> tags, string tagName)
- {
- var disc = FFProbeHelpers.GetDictionaryValue(tags, tagName);
- if (!string.IsNullOrEmpty(disc))
+ if (!audio.LockedFields.Contains(MetadataFields.Studios))
{
- disc = disc.Split('/')[0];
-
- int num;
+ audio.Studios.Clear();
- if (int.TryParse(disc, out num))
+ foreach (var studio in data.Studios)
{
- return num;
+ audio.AddStudio(studio);
}
}
- return null;
+ audio.SetProviderId(MetadataProviders.MusicBrainzAlbumArtist, data.GetProviderId(MetadataProviders.MusicBrainzAlbumArtist));
+ audio.SetProviderId(MetadataProviders.MusicBrainzArtist, data.GetProviderId(MetadataProviders.MusicBrainzArtist));
+ audio.SetProviderId(MetadataProviders.MusicBrainzAlbum, data.GetProviderId(MetadataProviders.MusicBrainzAlbum));
+ audio.SetProviderId(MetadataProviders.MusicBrainzReleaseGroup, data.GetProviderId(MetadataProviders.MusicBrainzReleaseGroup));
+ audio.SetProviderId(MetadataProviders.MusicBrainzTrack, data.GetProviderId(MetadataProviders.MusicBrainzTrack));
}
-
}
}
diff --git a/MediaBrowser.Providers/MediaInfo/FFProbeHelpers.cs b/MediaBrowser.Providers/MediaInfo/FFProbeHelpers.cs
deleted file mode 100644
index 2044979e4e..0000000000
--- a/MediaBrowser.Providers/MediaInfo/FFProbeHelpers.cs
+++ /dev/null
@@ -1,118 +0,0 @@
-using MediaBrowser.Controller.MediaEncoding;
-using System;
-using System.Collections.Generic;
-
-namespace MediaBrowser.Providers.MediaInfo
-{
- public static class FFProbeHelpers
- {
- /// <summary>
- /// Normalizes the FF probe result.
- /// </summary>
- /// <param name="result">The result.</param>
- public static void NormalizeFFProbeResult(InternalMediaInfoResult result)
- {
- if (result == null)
- {
- throw new ArgumentNullException("result");
- }
-
- if (result.format != null && result.format.tags != null)
- {
- result.format.tags = ConvertDictionaryToCaseInSensitive(result.format.tags);
- }
-
- if (result.streams != null)
- {
- // Convert all dictionaries to case insensitive
- foreach (var stream in result.streams)
- {
- if (stream.tags != null)
- {
- stream.tags = ConvertDictionaryToCaseInSensitive(stream.tags);
- }
-
- if (stream.disposition != null)
- {
- stream.disposition = ConvertDictionaryToCaseInSensitive(stream.disposition);
- }
- }
- }
- }
-
- /// <summary>
- /// Gets a string from an FFProbeResult tags dictionary
- /// </summary>
- /// <param name="tags">The tags.</param>
- /// <param name="key">The key.</param>
- /// <returns>System.String.</returns>
- public static string GetDictionaryValue(Dictionary<string, string> tags, string key)
- {
- if (tags == null)
- {
- return null;
- }
-
- string val;
-
- tags.TryGetValue(key, out val);
- return val;
- }
-
- /// <summary>
- /// Gets an int from an FFProbeResult tags dictionary
- /// </summary>
- /// <param name="tags">The tags.</param>
- /// <param name="key">The key.</param>
- /// <returns>System.Nullable{System.Int32}.</returns>
- public static int? GetDictionaryNumericValue(Dictionary<string, string> tags, string key)
- {
- var val = GetDictionaryValue(tags, key);
-
- if (!string.IsNullOrEmpty(val))
- {
- int i;
-
- if (int.TryParse(val, out i))
- {
- return i;
- }
- }
-
- return null;
- }
-
- /// <summary>
- /// Gets a DateTime from an FFProbeResult tags dictionary
- /// </summary>
- /// <param name="tags">The tags.</param>
- /// <param name="key">The key.</param>
- /// <returns>System.Nullable{DateTime}.</returns>
- public static DateTime? GetDictionaryDateTime(Dictionary<string, string> tags, string key)
- {
- var val = GetDictionaryValue(tags, key);
-
- if (!string.IsNullOrEmpty(val))
- {
- DateTime i;
-
- if (DateTime.TryParse(val, out i))
- {
- return i.ToUniversalTime();
- }
- }
-
- return null;
- }
-
- /// <summary>
- /// Converts a dictionary to case insensitive
- /// </summary>
- /// <param name="dict">The dict.</param>
- /// <returns>Dictionary{System.StringSystem.String}.</returns>
- private static Dictionary<string, string> ConvertDictionaryToCaseInSensitive(Dictionary<string, string> dict)
- {
- return new Dictionary<string, string>(dict, StringComparer.OrdinalIgnoreCase);
- }
- }
-}
diff --git a/MediaBrowser.Providers/MediaInfo/FFProbeVideoInfo.cs b/MediaBrowser.Providers/MediaInfo/FFProbeVideoInfo.cs
index ca11f858af..b53e313168 100644
--- a/MediaBrowser.Providers/MediaInfo/FFProbeVideoInfo.cs
+++ b/MediaBrowser.Providers/MediaInfo/FFProbeVideoInfo.cs
@@ -1,5 +1,6 @@
using DvdLib.Ifo;
using MediaBrowser.Common.Configuration;
+using MediaBrowser.Model.Dlna;
using MediaBrowser.Model.Extensions;
using MediaBrowser.Common.IO;
using MediaBrowser.Controller.Chapters;
@@ -13,7 +14,6 @@ using MediaBrowser.Controller.MediaEncoding;
using MediaBrowser.Controller.Persistence;
using MediaBrowser.Controller.Providers;
using MediaBrowser.Controller.Subtitles;
-using MediaBrowser.MediaInfo;
using MediaBrowser.Model.Configuration;
using MediaBrowser.Model.Entities;
using MediaBrowser.Model.IO;
@@ -116,10 +116,6 @@ namespace MediaBrowser.Providers.MediaInfo
cancellationToken.ThrowIfCancellationRequested();
- FFProbeHelpers.NormalizeFFProbeResult(result);
-
- cancellationToken.ThrowIfCancellationRequested();
-
await Fetch(item, cancellationToken, result, isoMount, blurayDiscInfo, options).ConfigureAwait(false);
}
@@ -134,9 +130,9 @@ namespace MediaBrowser.Providers.MediaInfo
return ItemUpdateType.MetadataImport;
}
- private const string SchemaVersion = "1";
+ private const string SchemaVersion = "4";
- private async Task<InternalMediaInfoResult> GetMediaInfo(Video item,
+ private async Task<Model.MediaInfo.MediaInfo> GetMediaInfo(Video item,
IIsoMount isoMount,
CancellationToken cancellationToken)
{
@@ -149,7 +145,7 @@ namespace MediaBrowser.Providers.MediaInfo
try
{
- return _json.DeserializeFromFile<InternalMediaInfoResult>(cachePath);
+ return _json.DeserializeFromFile<Model.MediaInfo.MediaInfo>(cachePath);
}
catch (FileNotFoundException)
{
@@ -163,9 +159,18 @@ namespace MediaBrowser.Providers.MediaInfo
? MediaProtocol.Http
: MediaProtocol.File;
- var inputPath = MediaEncoderHelpers.GetInputArgument(item.Path, protocol, isoMount, item.PlayableStreamFileNames);
+ var result = await _mediaEncoder.GetMediaInfo(new MediaInfoRequest
+ {
+ PlayableStreamFileNames = item.PlayableStreamFileNames,
+ MountedIso = isoMount,
+ ExtractChapters = true,
+ VideoType = item.VideoType,
+ MediaType = DlnaProfileType.Video,
+ InputPath = item.Path,
+ Protocol = protocol,
+ ExtractKeyFrameInterval = true
- var result = await _mediaEncoder.GetMediaInfo(inputPath, protocol, false, cancellationToken).ConfigureAwait(false);
+ }, cancellationToken).ConfigureAwait(false);
Directory.CreateDirectory(Path.GetDirectoryName(cachePath));
_json.SerializeToFile(result, cachePath);
@@ -175,52 +180,37 @@ namespace MediaBrowser.Providers.MediaInfo
protected async Task Fetch(Video video,
CancellationToken cancellationToken,
- InternalMediaInfoResult data,
+ Model.MediaInfo.MediaInfo mediaInfo,
IIsoMount isoMount,
BlurayDiscInfo blurayInfo,
MetadataRefreshOptions options)
{
- var mediaInfo = MediaEncoderHelpers.GetMediaInfo(data);
var mediaStreams = mediaInfo.MediaStreams;
- video.TotalBitrate = mediaInfo.TotalBitrate;
- video.FormatName = (mediaInfo.Format ?? string.Empty)
+ video.TotalBitrate = mediaInfo.Bitrate;
+ video.FormatName = (mediaInfo.Container ?? string.Empty)
.Replace("matroska", "mkv", StringComparison.OrdinalIgnoreCase);
- if (data.format != null)
- {
- // For dvd's this may not always be accurate, so don't set the runtime if the item already has one
- var needToSetRuntime = video.VideoType != VideoType.Dvd || video.RunTimeTicks == null || video.RunTimeTicks.Value == 0;
-
- if (needToSetRuntime && !string.IsNullOrEmpty(data.format.duration))
- {
- video.RunTimeTicks = TimeSpan.FromSeconds(double.Parse(data.format.duration, _usCulture)).Ticks;
- }
+ // For dvd's this may not always be accurate, so don't set the runtime if the item already has one
+ var needToSetRuntime = video.VideoType != VideoType.Dvd || video.RunTimeTicks == null || video.RunTimeTicks.Value == 0;
- if (video.VideoType == VideoType.VideoFile)
- {
- var extension = (Path.GetExtension(video.Path) ?? string.Empty).TrimStart('.');
+ if (needToSetRuntime)
+ {
+ video.RunTimeTicks = mediaInfo.RunTimeTicks;
+ }
- video.Container = extension;
- }
- else
- {
- video.Container = null;
- }
+ if (video.VideoType == VideoType.VideoFile)
+ {
+ var extension = (Path.GetExtension(video.Path) ?? string.Empty).TrimStart('.');
- if (!string.IsNullOrEmpty(data.format.size))
- {
- video.Size = long.Parse(data.format.size, _usCulture);
- }
- else
- {
- video.Size = null;
- }
+ video.Container = extension;
+ }
+ else
+ {
+ video.Container = null;
}
- var mediaChapters = (data.Chapters ?? new MediaChapter[] { }).ToList();
- var chapters = mediaChapters.Select(GetChapterInfo).ToList();
-
+ var chapters = mediaInfo.Chapters ?? new List<ChapterInfo>();
if (video.VideoType == VideoType.BluRay || (video.IsoType.HasValue && video.IsoType.Value == IsoType.BluRay))
{
FetchBdInfo(video, chapters, mediaStreams, blurayInfo);
@@ -228,7 +218,7 @@ namespace MediaBrowser.Providers.MediaInfo
await AddExternalSubtitles(video, mediaStreams, options, cancellationToken).ConfigureAwait(false);
- FetchWtvInfo(video, data);
+ FetchEmbeddedInfo(video, mediaInfo, options);
video.IsHD = mediaStreams.Any(i => i.Type == MediaStreamType.Video && i.Width.HasValue && i.Width.Value >= 1270);
@@ -238,9 +228,7 @@ namespace MediaBrowser.Providers.MediaInfo
video.DefaultVideoStreamIndex = videoStream == null ? (int?)null : videoStream.Index;
video.HasSubtitles = mediaStreams.Any(i => i.Type == MediaStreamType.Subtitle);
-
- ExtractTimestamp(video);
- UpdateFromMediaInfo(video, videoStream);
+ video.Timestamp = mediaInfo.Timestamp;
await _itemRepo.SaveMediaStreams(video.Id, mediaStreams, cancellationToken).ConfigureAwait(false);
@@ -283,29 +271,6 @@ namespace MediaBrowser.Providers.MediaInfo
}
}
- private void UpdateFromMediaInfo(Video video, MediaStream videoStream)
- {
- if (video.VideoType == VideoType.VideoFile && video.LocationType != LocationType.Remote && video.LocationType != LocationType.Virtual)
- {
- if (videoStream != null)
- {
- try
- {
- 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;
- }
- catch (Exception ex)
- {
- _logger.ErrorException("Error running MediaInfo on {0}", ex, video.Path);
- }
- }
- }
- }
-
private void NormalizeChapterNames(List<ChapterInfo> chapters)
{
var index = 1;
@@ -325,32 +290,6 @@ namespace MediaBrowser.Providers.MediaInfo
}
}
- private ChapterInfo GetChapterInfo(MediaChapter chapter)
- {
- var info = new ChapterInfo();
-
- if (chapter.tags != null)
- {
- string name;
- if (chapter.tags.TryGetValue("title", out name))
- {
- info.Name = name;
- }
- }
-
- // Limit accuracy to milliseconds to match xml saving
- var secondsString = chapter.start_time;
- double seconds;
-
- if (double.TryParse(secondsString, NumberStyles.Any, CultureInfo.InvariantCulture, out seconds))
- {
- var ms = Math.Round(TimeSpan.FromSeconds(seconds).TotalMilliseconds);
- info.StartPositionTicks = TimeSpan.FromMilliseconds(ms).Ticks;
- }
-
- return info;
- }
-
private void FetchBdInfo(BaseItem item, List<ChapterInfo> chapters, List<MediaStream> mediaStreams, BlurayDiscInfo blurayInfo)
{
var video = (Video)item;
@@ -419,129 +358,102 @@ namespace MediaBrowser.Providers.MediaInfo
return _blurayExaminer.GetDiscInfo(path);
}
- public const int MaxSubtitleDescriptionExtractionLength = 100; // When extracting subtitles, the maximum length to consider (to avoid invalid filenames)
-
- private void FetchWtvInfo(Video video, InternalMediaInfoResult data)
+ private void FetchEmbeddedInfo(Video video, Model.MediaInfo.MediaInfo data, MetadataRefreshOptions options)
{
- if (data.format == null || data.format.tags == null)
+ var isFullRefresh = options.MetadataRefreshMode == MetadataRefreshMode.FullRefresh;
+
+ if (!video.LockedFields.Contains(MetadataFields.OfficialRating))
{
- return;
+ if (!string.IsNullOrWhiteSpace(data.OfficialRating) || isFullRefresh)
+ {
+ video.OfficialRating = data.OfficialRating;
+ }
}
- if (!video.LockedFields.Contains(MetadataFields.Genres))
+ if (!video.LockedFields.Contains(MetadataFields.Cast))
{
- var genres = FFProbeHelpers.GetDictionaryValue(data.format.tags, "WM/Genre");
-
- if (!string.IsNullOrWhiteSpace(genres))
+ if (video.People.Count == 0 || isFullRefresh)
{
- //genres = FFProbeHelpers.GetDictionaryValue(data.format.tags, "genre");
+ video.People.Clear();
+
+ foreach (var person in data.People)
+ {
+ video.AddPerson(new PersonInfo
+ {
+ Name = person.Name,
+ Type = person.Type,
+ Role = person.Role
+ });
+ }
}
+ }
- if (!string.IsNullOrWhiteSpace(genres))
+ if (!video.LockedFields.Contains(MetadataFields.Genres))
+ {
+ if (video.Genres.Count == 0 || isFullRefresh)
{
- video.Genres = genres.Split(new[] { ';', '/', ',' }, StringSplitOptions.RemoveEmptyEntries)
- .Where(i => !string.IsNullOrWhiteSpace(i))
- .Select(i => i.Trim())
- .ToList();
+ video.Genres.Clear();
+
+ foreach (var genre in data.Genres)
+ {
+ video.AddGenre(genre);
+ }
}
}
- if (!video.LockedFields.Contains(MetadataFields.OfficialRating))
+ if (!video.LockedFields.Contains(MetadataFields.Studios))
{
- var officialRating = FFProbeHelpers.GetDictionaryValue(data.format.tags, "WM/ParentalRating");
-
- if (!string.IsNullOrWhiteSpace(officialRating))
+ if (video.Studios.Count == 0 || isFullRefresh)
{
- video.OfficialRating = officialRating;
+ video.Studios.Clear();
+
+ foreach (var studio in data.Studios)
+ {
+ video.AddStudio(studio);
+ }
}
}
- if (!video.LockedFields.Contains(MetadataFields.Cast))
+ if (data.ProductionYear.HasValue)
{
- var people = FFProbeHelpers.GetDictionaryValue(data.format.tags, "WM/MediaCredits");
-
- if (!string.IsNullOrEmpty(people))
+ if (!video.ProductionYear.HasValue || isFullRefresh)
{
- video.People = people.Split(new[] { ';', '/' }, StringSplitOptions.RemoveEmptyEntries)
- .Where(i => !string.IsNullOrWhiteSpace(i))
- .Select(i => new PersonInfo { Name = i.Trim(), Type = PersonType.Actor })
- .ToList();
+ video.ProductionYear = data.ProductionYear;
}
}
-
- var year = FFProbeHelpers.GetDictionaryValue(data.format.tags, "WM/OriginalReleaseTime");
- if (!string.IsNullOrWhiteSpace(year))
+ if (data.PremiereDate.HasValue)
{
- int val;
-
- if (int.TryParse(year, NumberStyles.Integer, _usCulture, out val))
+ if (!video.PremiereDate.HasValue || isFullRefresh)
{
- video.ProductionYear = val;
+ video.PremiereDate = data.PremiereDate;
}
}
-
- var premiereDateString = FFProbeHelpers.GetDictionaryValue(data.format.tags, "WM/MediaOriginalBroadcastDateTime");
- if (!string.IsNullOrWhiteSpace(premiereDateString))
+ if (data.IndexNumber.HasValue)
{
- DateTime val;
-
- // Credit to MCEBuddy: https://mcebuddy2x.codeplex.com/
- // DateTime is reported along with timezone info (typically Z i.e. UTC hence assume None)
- if (DateTime.TryParse(year, null, DateTimeStyles.None, out val))
+ if (!video.IndexNumber.HasValue || isFullRefresh)
{
- video.PremiereDate = val.ToUniversalTime();
+ video.IndexNumber = data.IndexNumber;
}
}
-
- var description = FFProbeHelpers.GetDictionaryValue(data.format.tags, "WM/SubTitleDescription");
-
- var episode = video as Episode;
- if (episode != null)
+ if (data.ParentIndexNumber.HasValue)
{
- var subTitle = FFProbeHelpers.GetDictionaryValue(data.format.tags, "WM/SubTitle");
-
- // For below code, credit to MCEBuddy: https://mcebuddy2x.codeplex.com/
-
- // Sometimes for TV Shows the Subtitle field is empty and the subtitle description contains the subtitle, extract if possible. See ticket https://mcebuddy2x.codeplex.com/workitem/1910
- // The format is -> EPISODE/TOTAL_EPISODES_IN_SEASON. SUBTITLE: DESCRIPTION
- // OR -> COMMENT. SUBTITLE: DESCRIPTION
- // e.g. -> 4/13. The Doctor's Wife: Science fiction drama. When he follows a Time Lord distress signal, the Doctor puts Amy, Rory and his beloved TARDIS in grave danger. Also in HD. [AD,S]
- // e.g. -> CBeebies Bedtime Hour. The Mystery: Animated adventures of two friends who live on an island in the middle of the big city. Some of Abney and Teal's favourite objects are missing. [S]
- if (String.IsNullOrWhiteSpace(subTitle) && !String.IsNullOrWhiteSpace(description) && description.Substring(0, Math.Min(description.Length, MaxSubtitleDescriptionExtractionLength)).Contains(":")) // Check within the Subtitle size limit, otherwise from description it can get too long creating an invalid filename
+ if (!video.ParentIndexNumber.HasValue || isFullRefresh)
{
- string[] parts = description.Split(':');
- if (parts.Length > 0)
- {
- string subtitle = parts[0];
- try
- {
- if (subtitle.Contains("/")) // It contains a episode number and season number
- {
- string[] numbers = subtitle.Split(' ');
- episode.IndexNumber = int.Parse(numbers[0].Replace(".", "").Split('/')[0]);
- int totalEpisodesInSeason = int.Parse(numbers[0].Replace(".", "").Split('/')[1]);
-
- description = String.Join(" ", numbers, 1, numbers.Length - 1).Trim(); // Skip the first, concatenate the rest, clean up spaces and save it
- }
- else
- throw new Exception(); // Switch to default parsing
- }
- catch // Default parsing
- {
- if (subtitle.Contains(".")) // skip the comment, keep the subtitle
- description = String.Join(".", subtitle.Split('.'), 1, subtitle.Split('.').Length - 1).Trim(); // skip the first
- else
- description = subtitle.Trim(); // Clean up whitespaces and save it
- }
- }
+ video.ParentIndexNumber = data.ParentIndexNumber;
}
}
+ // If we don't have a ProductionYear try and get it from PremiereDate
+ if (video.PremiereDate.HasValue && !video.ProductionYear.HasValue)
+ {
+ video.ProductionYear = video.PremiereDate.Value.ToLocalTime().Year;
+ }
+
if (!video.LockedFields.Contains(MetadataFields.Overview))
{
- if (!string.IsNullOrWhiteSpace(description))
+ if (string.IsNullOrWhiteSpace(video.Overview) || isFullRefresh)
{
- video.Overview = description;
+ video.Overview = data.Overview;
}
}
}
@@ -709,56 +621,6 @@ namespace MediaBrowser.Providers.MediaInfo
}
}
- private void ExtractTimestamp(Video video)
- {
- if (video.VideoType == VideoType.VideoFile)
- {
- if (string.Equals(video.Container, "mpeg2ts", StringComparison.OrdinalIgnoreCase) ||
- string.Equals(video.Container, "m2ts", StringComparison.OrdinalIgnoreCase) ||
- string.Equals(video.Container, "ts", StringComparison.OrdinalIgnoreCase))
- {
- try
- {
- video.Timestamp = GetMpegTimestamp(video.Path);
-
- _logger.Debug("Video has {0} timestamp", video.Timestamp);
- }
- catch (Exception ex)
- {
- _logger.ErrorException("Error extracting timestamp info from {0}", ex, video.Path);
- video.Timestamp = null;
- }
- }
- }
- }
-
- private TransportStreamTimestamp GetMpegTimestamp(string path)
- {
- var packetBuffer = new byte['Å'];
-
- using (var fs = _fileSystem.GetFileStream(path, FileMode.Open, FileAccess.Read, FileShare.Read))
- {
- fs.Read(packetBuffer, 0, packetBuffer.Length);
- }
-
- if (packetBuffer[0] == 71)
- {
- return TransportStreamTimestamp.None;
- }
-
- if ((packetBuffer[4] == 71) && (packetBuffer['Ä'] == 71))
- {
- if ((packetBuffer[0] == 0) && (packetBuffer[1] == 0) && (packetBuffer[2] == 0) && (packetBuffer[3] == 0))
- {
- return TransportStreamTimestamp.Zero;
- }
-
- return TransportStreamTimestamp.Valid;
- }
-
- return TransportStreamTimestamp.None;
- }
-
private void FetchFromDvdLib(Video item, IIsoMount mount)
{
var path = mount == null ? item.Path : mount.MountedPath;
diff --git a/MediaBrowser.Providers/MediaInfo/VideoImageProvider.cs b/MediaBrowser.Providers/MediaInfo/VideoImageProvider.cs
index 7c32432251..bcea66662e 100644
--- a/MediaBrowser.Providers/MediaInfo/VideoImageProvider.cs
+++ b/MediaBrowser.Providers/MediaInfo/VideoImageProvider.cs
@@ -6,6 +6,7 @@ using MediaBrowser.Controller.Providers;
using MediaBrowser.Model.Drawing;
using MediaBrowser.Model.Entities;
using MediaBrowser.Model.IO;
+using MediaBrowser.Model.Logging;
using MediaBrowser.Model.MediaInfo;
using System;
using System.Collections.Generic;
@@ -20,13 +21,15 @@ namespace MediaBrowser.Providers.MediaInfo
private readonly IMediaEncoder _mediaEncoder;
private readonly IServerConfigurationManager _config;
private readonly ILibraryManager _libraryManager;
+ private readonly ILogger _logger;
- public VideoImageProvider(IIsoManager isoManager, IMediaEncoder mediaEncoder, IServerConfigurationManager config, ILibraryManager libraryManager)
+ public VideoImageProvider(IIsoManager isoManager, IMediaEncoder mediaEncoder, IServerConfigurationManager config, ILibraryManager libraryManager, ILogger logger)
{
_isoManager = isoManager;
_mediaEncoder = mediaEncoder;
_config = config;
_libraryManager = libraryManager;
+ _logger = logger;
}
/// <summary>
@@ -74,6 +77,7 @@ namespace MediaBrowser.Providers.MediaInfo
// Can't extract if we didn't find a video stream in the file
if (!video.DefaultVideoStreamIndex.HasValue)
{
+ _logger.Debug("Skipping image extraction due to missing DefaultVideoStreamIndex for {0}.", video.Path ?? string.Empty);
return Task.FromResult(new DynamicImageResponse { HasImage = false });
}
diff --git a/MediaBrowser.Providers/MediaInfo/whitelist.txt b/MediaBrowser.Providers/MediaInfo/whitelist.txt
deleted file mode 100644
index 1fd3665512..0000000000
--- a/MediaBrowser.Providers/MediaInfo/whitelist.txt
+++ /dev/null
@@ -1 +0,0 @@
-AC/DC \ No newline at end of file
diff --git a/MediaBrowser.Providers/Movies/FanArtMovieUpdatesPostScanTask.cs b/MediaBrowser.Providers/Movies/FanArtMovieUpdatesPostScanTask.cs
index 6e57ddb01c..f133f74db4 100644
--- a/MediaBrowser.Providers/Movies/FanArtMovieUpdatesPostScanTask.cs
+++ b/MediaBrowser.Providers/Movies/FanArtMovieUpdatesPostScanTask.cs
@@ -6,6 +6,7 @@ using MediaBrowser.Model.Configuration;
using MediaBrowser.Model.Logging;
using MediaBrowser.Model.Serialization;
using MediaBrowser.Providers.Music;
+using MediaBrowser.Providers.TV;
using System;
using System.Collections.Generic;
using System.Globalization;
@@ -14,7 +15,6 @@ using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
-using MediaBrowser.Providers.TV;
namespace MediaBrowser.Providers.Movies
{
diff --git a/MediaBrowser.Providers/Movies/MovieMetadataService.cs b/MediaBrowser.Providers/Movies/MovieMetadataService.cs
index 172ae6814c..f886deb007 100644
--- a/MediaBrowser.Providers/Movies/MovieMetadataService.cs
+++ b/MediaBrowser.Providers/Movies/MovieMetadataService.cs
@@ -36,10 +36,6 @@ namespace MediaBrowser.Providers.Movies
protected override bool IsFullLocalMetadata(Movie item)
{
- if (string.IsNullOrWhiteSpace(item.Name))
- {
- return false;
- }
if (string.IsNullOrWhiteSpace(item.Overview))
{
return false;
diff --git a/MediaBrowser.Providers/Music/ArtistMetadataService.cs b/MediaBrowser.Providers/Music/ArtistMetadataService.cs
index 2497cc1ec7..7905293717 100644
--- a/MediaBrowser.Providers/Music/ArtistMetadataService.cs
+++ b/MediaBrowser.Providers/Music/ArtistMetadataService.cs
@@ -54,7 +54,7 @@ namespace MediaBrowser.Providers.Music
var currentList = item.Genres.ToList();
item.Genres = taggedItems.SelectMany(i => i.Genres)
- .Distinct(StringComparer.OrdinalIgnoreCase)
+ .DistinctNames()
.ToList();
if (currentList.Count != item.Genres.Count || !currentList.OrderBy(i => i).SequenceEqual(item.Genres.OrderBy(i => i), StringComparer.OrdinalIgnoreCase))
diff --git a/MediaBrowser.Providers/TV/SeriesMetadataService.cs b/MediaBrowser.Providers/TV/SeriesMetadataService.cs
index a5959f0b75..b0cd7382a1 100644
--- a/MediaBrowser.Providers/TV/SeriesMetadataService.cs
+++ b/MediaBrowser.Providers/TV/SeriesMetadataService.cs
@@ -77,10 +77,6 @@ namespace MediaBrowser.Providers.TV
protected override bool IsFullLocalMetadata(Series item)
{
- if (string.IsNullOrWhiteSpace(item.Name))
- {
- return false;
- }
if (string.IsNullOrWhiteSpace(item.Overview))
{
return false;
diff --git a/MediaBrowser.Providers/TV/TvdbSeriesProvider.cs b/MediaBrowser.Providers/TV/TvdbSeriesProvider.cs
index c644da0b82..a31cc1e0c1 100644
--- a/MediaBrowser.Providers/TV/TvdbSeriesProvider.cs
+++ b/MediaBrowser.Providers/TV/TvdbSeriesProvider.cs
@@ -10,6 +10,7 @@ using MediaBrowser.Model.Configuration;
using MediaBrowser.Model.Entities;
using MediaBrowser.Model.IO;
using MediaBrowser.Model.Logging;
+using MediaBrowser.Model.Net;
using MediaBrowser.Model.Providers;
using System;
using System.Collections.Generic;
@@ -191,6 +192,27 @@ namespace MediaBrowser.Providers.TV
/// <returns>Task.</returns>
internal async Task DownloadSeriesZip(string seriesId, string seriesDataPath, long? lastTvDbUpdateTime, string preferredMetadataLanguage, CancellationToken cancellationToken)
{
+ try
+ {
+ await DownloadSeriesZip(seriesId, seriesDataPath, lastTvDbUpdateTime, preferredMetadataLanguage, preferredMetadataLanguage, cancellationToken).ConfigureAwait(false);
+ return;
+ }
+ catch (HttpException ex)
+ {
+ if (!ex.StatusCode.HasValue || ex.StatusCode.Value != HttpStatusCode.NotFound)
+ {
+ throw;
+ }
+ }
+
+ if (!string.Equals(preferredMetadataLanguage, "en", StringComparison.OrdinalIgnoreCase))
+ {
+ await DownloadSeriesZip(seriesId, seriesDataPath, lastTvDbUpdateTime, "en", preferredMetadataLanguage, cancellationToken).ConfigureAwait(false);
+ }
+ }
+
+ private async Task DownloadSeriesZip(string seriesId, string seriesDataPath, long? lastTvDbUpdateTime, string preferredMetadataLanguage, string saveAsMetadataLanguage, CancellationToken cancellationToken)
+ {
var url = string.Format(SeriesGetZip, TVUtils.TvdbApiKey, seriesId, preferredMetadataLanguage);
using (var zipStream = await _httpClient.Get(new HttpRequestOptions
@@ -221,7 +243,15 @@ namespace MediaBrowser.Providers.TV
await SanitizeXmlFile(file).ConfigureAwait(false);
}
- await ExtractEpisodes(seriesDataPath, Path.Combine(seriesDataPath, preferredMetadataLanguage + ".xml"), lastTvDbUpdateTime).ConfigureAwait(false);
+ var downloadLangaugeXmlFile = Path.Combine(seriesDataPath, preferredMetadataLanguage + ".xml");
+ var saveAsLanguageXmlFile = Path.Combine(seriesDataPath, saveAsMetadataLanguage + ".xml");
+
+ if (!string.Equals(downloadLangaugeXmlFile, saveAsLanguageXmlFile, StringComparison.OrdinalIgnoreCase))
+ {
+ File.Copy(downloadLangaugeXmlFile, saveAsLanguageXmlFile, true);
+ }
+
+ await ExtractEpisodes(seriesDataPath, downloadLangaugeXmlFile, lastTvDbUpdateTime).ConfigureAwait(false);
}
public TvdbOptions GetTvDbOptions()