added artist/slbum xml savers

pull/702/head
Luke Pulverenti 11 years ago
parent 41f84fc6b2
commit 10caa7ff83

@ -1142,6 +1142,19 @@ namespace MediaBrowser.Controller.Entities
}
}
public void AddTag(string name)
{
if (string.IsNullOrWhiteSpace(name))
{
throw new ArgumentNullException("name");
}
if (!Tags.Contains(name, StringComparer.OrdinalIgnoreCase))
{
Tags.Add(name);
}
}
/// <summary>
/// Adds a tagline to the item
/// </summary>

@ -65,6 +65,7 @@ namespace MediaBrowser.Controller.Providers
item.Studios.Clear();
item.Genres.Clear();
item.People.Clear();
item.Tags.Clear();
// Use european encoding as it will accept more characters
using (var streamReader = new StreamReader(metadataFile, Encoding.GetEncoding("ISO-8859-1")))
@ -397,6 +398,7 @@ namespace MediaBrowser.Controller.Providers
break;
}
case "PremiereDate":
case "FirstAired":
{
var firstAired = reader.ReadElementContentAsString();
@ -453,6 +455,10 @@ namespace MediaBrowser.Controller.Providers
FetchFromGenresNode(reader.ReadSubtree(), item);
break;
case "Tags":
FetchFromTagsNode(reader.ReadSubtree(), item);
break;
case "Persons":
FetchDataFromPersonsNode(reader.ReadSubtree(), item);
break;
@ -539,6 +545,35 @@ namespace MediaBrowser.Controller.Providers
}
}
private void FetchFromTagsNode(XmlReader reader, T item)
{
reader.MoveToContent();
while (reader.Read())
{
if (reader.NodeType == XmlNodeType.Element)
{
switch (reader.Name)
{
case "Tag":
{
var tag = reader.ReadElementContentAsString();
if (!string.IsNullOrWhiteSpace(tag))
{
item.AddTagline(tag);
}
break;
}
default:
reader.Skip();
break;
}
}
}
}
/// <summary>
/// Fetches the data from persons node.
/// </summary>

@ -15,7 +15,8 @@ namespace MediaBrowser.Providers
/// </summary>
public class FolderProviderFromXml : BaseMetadataProvider
{
public FolderProviderFromXml(ILogManager logManager, IServerConfigurationManager configurationManager) : base(logManager, configurationManager)
public FolderProviderFromXml(ILogManager logManager, IServerConfigurationManager configurationManager)
: base(logManager, configurationManager)
{
}

@ -64,6 +64,7 @@
<Compile Include="Movies\OpenMovieDatabaseProvider.cs" />
<Compile Include="Movies\PersonProviderFromXml.cs" />
<Compile Include="Movies\TmdbPersonProvider.cs" />
<Compile Include="Music\ArtistProviderFromXml.cs" />
<Compile Include="Music\ArtistsPostScanTask.cs" />
<Compile Include="Music\FanArtAlbumProvider.cs" />
<Compile Include="Music\FanArtArtistByNameProvider.cs" />
@ -74,14 +75,15 @@
<Compile Include="Music\LastfmArtistProvider.cs" />
<Compile Include="Music\LastfmBaseProvider.cs" />
<Compile Include="Music\LastfmHelper.cs" />
<Compile Include="Music\MusicArtistProviderFromJson.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="Savers\AlbumXmlSaver.cs" />
<Compile Include="Savers\ArtistXmlSaver.cs" />
<Compile Include="Savers\EpisodeXmlSaver.cs" />
<Compile Include="Savers\FolderXmlSaver.cs" />
<Compile Include="Savers\MovieXmlSaver.cs" />
<Compile Include="Savers\PersonXmlSaver.cs" />
<Compile Include="Savers\SeriesXmlSaver.cs" />
<Compile Include="Savers\XmlHelpers.cs" />
<Compile Include="Savers\XmlSaverHelpers.cs" />
<Compile Include="TV\EpisodeImageFromMediaLocationProvider.cs" />
<Compile Include="TV\EpisodeIndexNumberProvider.cs" />
<Compile Include="TV\EpisodeProviderFromXml.cs" />

@ -1,11 +1,9 @@
using MediaBrowser.Common.Net;
using MediaBrowser.Controller.Configuration;
using MediaBrowser.Controller.Library;
using MediaBrowser.Controller.Providers;
using MediaBrowser.Controller.Providers.Music;
using MediaBrowser.Model.Logging;
using MediaBrowser.Model.Net;
using MediaBrowser.Model.Serialization;
using MediaBrowser.Providers.Music;
using System;
using System.Collections.Generic;
using System.Globalization;
@ -14,7 +12,6 @@ using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using MediaBrowser.Providers.Music;
namespace MediaBrowser.Providers.Movies
{

@ -0,0 +1,107 @@
using MediaBrowser.Controller.Configuration;
using MediaBrowser.Controller.Entities;
using MediaBrowser.Controller.Entities.Audio;
using MediaBrowser.Controller.Providers;
using MediaBrowser.Model.Entities;
using MediaBrowser.Model.Logging;
using System;
using System.IO;
using System.Threading;
using System.Threading.Tasks;
namespace MediaBrowser.Providers.Music
{
class ArtistProviderFromXml : BaseMetadataProvider
{
public ArtistProviderFromXml(ILogManager logManager, IServerConfigurationManager configurationManager)
: base(logManager, configurationManager)
{
}
/// <summary>
/// Supportses the specified item.
/// </summary>
/// <param name="item">The item.</param>
/// <returns><c>true</c> if XXXX, <c>false</c> otherwise</returns>
public override bool Supports(BaseItem item)
{
return (item is Artist || item is MusicArtist) && item.LocationType == LocationType.FileSystem;
}
/// <summary>
/// Gets the priority.
/// </summary>
/// <value>The priority.</value>
public override MetadataProviderPriority Priority
{
get { return MetadataProviderPriority.First; }
}
/// <summary>
/// Override this to return the date that should be compared to the last refresh date
/// to determine if this provider should be re-fetched.
/// </summary>
/// <param name="item">The item.</param>
/// <returns>DateTime.</returns>
protected override DateTime CompareDate(BaseItem item)
{
var entry = item.MetaLocation != null ? item.ResolveArgs.GetMetaFileByPath(Path.Combine(item.MetaLocation, "artist.xml")) : null;
return entry != null ? entry.LastWriteTimeUtc : DateTime.MinValue;
}
/// <summary>
/// Fetches metadata and returns true or false indicating if any work that requires persistence was done
/// </summary>
/// <param name="item">The item.</param>
/// <param name="force">if set to <c>true</c> [force].</param>
/// <param name="cancellationToken">The cancellation token.</param>
/// <returns>Task{System.Boolean}.</returns>
public override Task<bool> FetchAsync(BaseItem item, bool force, CancellationToken cancellationToken)
{
return Fetch(item, cancellationToken);
}
/// <summary>
/// Fetches the specified item.
/// </summary>
/// <param name="item">The item.</param>
/// <param name="cancellationToken">The cancellation token.</param>
/// <returns><c>true</c> if XXXX, <c>false</c> otherwise</returns>
private async Task<bool> Fetch(BaseItem item, CancellationToken cancellationToken)
{
cancellationToken.ThrowIfCancellationRequested();
var metadataFile = item.ResolveArgs.GetMetaFileByPath(Path.Combine(item.MetaLocation, "artist.xml"));
if (metadataFile != null)
{
var path = metadataFile.FullName;
await XmlParsingResourcePool.WaitAsync(cancellationToken).ConfigureAwait(false);
try
{
var artist = item as Artist;
if (artist != null)
{
new BaseItemXmlParser<Artist>(Logger).Fetch(artist, path, cancellationToken);
}
else
{
new BaseItemXmlParser<MusicArtist>(Logger).Fetch((MusicArtist)item, path, cancellationToken);
}
}
finally
{
XmlParsingResourcePool.Release();
}
SetLastRefreshed(item, DateTime.UtcNow);
return true;
}
return false;
}
}
}

@ -7,12 +7,11 @@ using MediaBrowser.Controller.Providers;
using MediaBrowser.Model.Entities;
using MediaBrowser.Model.Logging;
using MediaBrowser.Model.Serialization;
using MoreLinq;
using System;
using System.IO;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using MoreLinq;
namespace MediaBrowser.Providers.Music
{
@ -20,18 +19,9 @@ namespace MediaBrowser.Providers.Music
{
private static readonly Task<string> BlankId = Task.FromResult("");
private readonly IProviderManager _providerManager;
/// <summary>
/// The name of the local json meta file for this item type
/// </summary>
protected string LocalMetaFileName { get; set; }
public LastfmAlbumProvider(IJsonSerializer jsonSerializer, IHttpClient httpClient, ILogManager logManager, IServerConfigurationManager configurationManager, IProviderManager providerManager)
public LastfmAlbumProvider(IJsonSerializer jsonSerializer, IHttpClient httpClient, ILogManager logManager, IServerConfigurationManager configurationManager)
: base(jsonSerializer, httpClient, logManager, configurationManager)
{
_providerManager = providerManager;
LocalMetaFileName = LastfmHelper.LocalAlbumMetaFileName;
}
protected override Task<string> FindId(BaseItem item, CancellationToken cancellationToken)
@ -40,6 +30,11 @@ namespace MediaBrowser.Providers.Music
return BlankId;
}
private bool HasAltMeta(BaseItem item)
{
return item.LocationType == LocationType.FileSystem && item.ResolveArgs.ContainsMetaFileByName("album.xml");
}
/// <summary>
/// Needses the refresh internal.
/// </summary>
@ -48,6 +43,11 @@ namespace MediaBrowser.Providers.Music
/// <returns><c>true</c> if XXXX, <c>false</c> otherwise</returns>
protected override bool NeedsRefreshInternal(BaseItem item, BaseProviderInfo providerInfo)
{
if (HasAltMeta(item))
{
return false;
}
// If song metadata has changed and we don't have an mbid, refresh
if (string.IsNullOrEmpty(item.GetProviderId(MetadataProviders.Musicbrainz)) &&
GetComparisonData(item as MusicAlbum) != providerInfo.FileStamp)
@ -65,17 +65,6 @@ namespace MediaBrowser.Providers.Music
if (result != null && result.album != null)
{
LastfmHelper.ProcessAlbumData(item, result.album);
//And save locally if indicated
if (ConfigurationManager.Configuration.SaveLocalMeta)
{
var ms = new MemoryStream();
JsonSerializer.SerializeToStream(result.album, ms);
cancellationToken.ThrowIfCancellationRequested();
await _providerManager.SaveToLibraryFilesystem(item, Path.Combine(item.MetaLocation, LocalMetaFileName), ms, cancellationToken).ConfigureAwait(false);
}
}
BaseProviderInfo data;

@ -3,7 +3,6 @@ using MediaBrowser.Controller.Configuration;
using MediaBrowser.Controller.Entities;
using MediaBrowser.Controller.Entities.Audio;
using MediaBrowser.Controller.Library;
using MediaBrowser.Controller.Providers;
using MediaBrowser.Model.Entities;
using MediaBrowser.Model.Logging;
using MediaBrowser.Model.Serialization;
@ -26,10 +25,9 @@ namespace MediaBrowser.Providers.Music
/// <param name="httpClient">The HTTP client.</param>
/// <param name="logManager">The log manager.</param>
/// <param name="configurationManager">The configuration manager.</param>
/// <param name="providerManager">The provider manager.</param>
/// <param name="libraryManager">The library manager.</param>
public LastfmArtistByNameProvider(IJsonSerializer jsonSerializer, IHttpClient httpClient, ILogManager logManager, IServerConfigurationManager configurationManager, IProviderManager providerManager, ILibraryManager libraryManager)
: base(jsonSerializer, httpClient, logManager, configurationManager, providerManager, libraryManager)
public LastfmArtistByNameProvider(IJsonSerializer jsonSerializer, IHttpClient httpClient, ILogManager logManager, IServerConfigurationManager configurationManager, ILibraryManager libraryManager)
: base(jsonSerializer, httpClient, logManager, configurationManager, libraryManager)
{
}

@ -4,7 +4,6 @@ using MediaBrowser.Controller.Entities;
using MediaBrowser.Controller.Entities.Audio;
using MediaBrowser.Controller.Library;
using MediaBrowser.Controller.Providers;
using MediaBrowser.Controller.Providers.Music;
using MediaBrowser.Model.Entities;
using MediaBrowser.Model.Logging;
using MediaBrowser.Model.Net;
@ -26,37 +25,40 @@ namespace MediaBrowser.Providers.Music
/// </summary>
public class LastfmArtistProvider : LastfmBaseProvider
{
/// <summary>
/// The _provider manager
/// </summary>
private readonly IProviderManager _providerManager;
/// <summary>
/// The _library manager
/// </summary>
protected readonly ILibraryManager LibraryManager;
/// <summary>
/// The name of the local json meta file for this item type
/// </summary>
protected string LocalMetaFileName { get; set; }
/// <summary>
/// Initializes a new instance of the <see cref="LastfmArtistProvider"/> class.
/// Initializes a new instance of the <see cref="LastfmArtistProvider" /> class.
/// </summary>
/// <param name="jsonSerializer">The json serializer.</param>
/// <param name="httpClient">The HTTP client.</param>
/// <param name="logManager">The log manager.</param>
/// <param name="configurationManager">The configuration manager.</param>
/// <param name="providerManager">The provider manager.</param>
/// <param name="libraryManager">The library manager.</param>
public LastfmArtistProvider(IJsonSerializer jsonSerializer, IHttpClient httpClient, ILogManager logManager, IServerConfigurationManager configurationManager, IProviderManager providerManager, ILibraryManager libraryManager)
public LastfmArtistProvider(IJsonSerializer jsonSerializer, IHttpClient httpClient, ILogManager logManager, IServerConfigurationManager configurationManager, ILibraryManager libraryManager)
: base(jsonSerializer, httpClient, logManager, configurationManager)
{
_providerManager = providerManager;
LibraryManager = libraryManager;
LocalMetaFileName = LastfmHelper.LocalArtistMetaFileName;
}
protected override bool NeedsRefreshInternal(BaseItem item, BaseProviderInfo providerInfo)
{
if (HasAltMeta(item))
{
return false;
}
return base.NeedsRefreshInternal(item, providerInfo);
}
private bool HasAltMeta(BaseItem item)
{
return item.LocationType == LocationType.FileSystem && item.ResolveArgs.ContainsMetaFileByName("artist.xml");
}
/// <summary>
/// Finds the id.
/// </summary>
@ -259,21 +261,6 @@ namespace MediaBrowser.Providers.Music
if (result != null && result.artist != null)
{
LastfmHelper.ProcessArtistData(item, result.artist);
//And save locally if indicated
if (SaveLocalMeta)
{
var ms = new MemoryStream();
JsonSerializer.SerializeToStream(result.artist, ms);
if (cancellationToken.IsCancellationRequested)
{
ms.Dispose();
cancellationToken.ThrowIfCancellationRequested();
}
await _providerManager.SaveToLibraryFilesystem(item, Path.Combine(item.MetaLocation, LocalMetaFileName), ms, cancellationToken).ConfigureAwait(false);
}
}
}

@ -1,6 +1,5 @@
using MediaBrowser.Controller.Entities;
using MediaBrowser.Controller.Entities.Audio;
using MediaBrowser.Controller.Providers.Music;
using MediaBrowser.Model.Entities;
using System;
using System.Linq;
@ -9,9 +8,6 @@ namespace MediaBrowser.Providers.Music
{
public static class LastfmHelper
{
public static string LocalArtistMetaFileName = "lastfmartist.json";
public static string LocalAlbumMetaFileName = "lastfmalbum.json";
public static void ProcessArtistData(BaseItem artist, LastfmArtist data)
{
var yearFormed = 0;

@ -1,101 +0,0 @@
using MediaBrowser.Controller.Configuration;
using MediaBrowser.Controller.Entities;
using MediaBrowser.Controller.Entities.Audio;
using MediaBrowser.Model.Entities;
using MediaBrowser.Model.Logging;
using MediaBrowser.Model.Serialization;
using System;
using System.IO;
using System.Threading;
using System.Threading.Tasks;
using MediaBrowser.Providers.Music;
namespace MediaBrowser.Controller.Providers.Music
{
public class MusicArtistProviderFromJson : BaseMetadataProvider
{
/// <summary>
/// Gets the json serializer.
/// </summary>
/// <value>The json serializer.</value>
protected IJsonSerializer JsonSerializer { get; private set; }
public MusicArtistProviderFromJson(IJsonSerializer jsonSerializer, ILogManager logManager, IServerConfigurationManager configurationManager)
: base(logManager, configurationManager)
{
if (jsonSerializer == null)
{
throw new ArgumentNullException("jsonSerializer");
}
JsonSerializer = jsonSerializer;
}
public override Task<bool> FetchAsync(BaseItem item, bool force, CancellationToken cancellationToken)
{
cancellationToken.ThrowIfCancellationRequested();
var entry = item.ResolveArgs.GetMetaFileByPath(Path.Combine(item.MetaLocation, LastfmHelper.LocalArtistMetaFileName));
if (entry != null)
{
// read in our saved meta and pass to processing function
var data = JsonSerializer.DeserializeFromFile<LastfmArtist>(entry.FullName);
cancellationToken.ThrowIfCancellationRequested();
LastfmHelper.ProcessArtistData(item, data);
item.SetProviderId(MetadataProviders.Musicbrainz, data.mbid);
SetLastRefreshed(item, DateTime.UtcNow);
return TrueTaskResult;
}
return FalseTaskResult;
}
public override MetadataProviderPriority Priority
{
get
{
return MetadataProviderPriority.First;
}
}
public override bool Supports(BaseItem item)
{
return false;
}
public override bool RequiresInternet
{
get
{
return false;
}
}
protected override bool NeedsRefreshInternal(BaseItem item, BaseProviderInfo providerInfo)
{
if (!item.ResolveArgs.ContainsMetaFileByName(LastfmHelper.LocalArtistMetaFileName))
{
return false; // nothing to read
}
// Need to re-override to jump over intermediate implementation
return CompareDate(item) > providerInfo.LastRefreshed;
}
/// <summary>
/// Override this to return the date that should be compared to the last refresh date
/// to determine if this provider should be re-fetched.
/// </summary>
/// <param name="item">The item.</param>
/// <returns>DateTime.</returns>
protected override DateTime CompareDate(BaseItem item)
{
var entry = item.ResolveArgs.GetMetaFileByPath(Path.Combine(item.MetaLocation, LastfmHelper.LocalArtistMetaFileName));
return entry != null ? entry.LastWriteTimeUtc : DateTime.MinValue;
}
}
}

@ -0,0 +1,77 @@
using MediaBrowser.Controller.Configuration;
using MediaBrowser.Controller.Entities;
using MediaBrowser.Controller.Entities.Audio;
using MediaBrowser.Controller.Library;
using MediaBrowser.Model.Entities;
using MediaBrowser.Providers.Movies;
using System;
using System.IO;
using System.Text;
using System.Threading;
namespace MediaBrowser.Providers.Savers
{
class AlbumXmlSaver : IMetadataSaver
{
private readonly IServerConfigurationManager _config;
public AlbumXmlSaver(IServerConfigurationManager config)
{
_config = config;
}
/// <summary>
/// Supportses the specified item.
/// </summary>
/// <param name="item">The item.</param>
/// <returns><c>true</c> if XXXX, <c>false</c> otherwise</returns>
public bool Supports(BaseItem item)
{
if (item.LocationType != LocationType.FileSystem)
{
return false;
}
if (item is MusicAlbum)
{
return _config.Configuration.SaveLocalMeta;
}
return false;
}
/// <summary>
/// Saves the specified item.
/// </summary>
/// <param name="item">The item.</param>
/// <param name="cancellationToken">The cancellation token.</param>
/// <returns>Task.</returns>
public void Save(BaseItem item, CancellationToken cancellationToken)
{
var builder = new StringBuilder();
builder.Append("<Item>");
XmlSaverHelpers.AddCommonNodes(item, builder);
builder.Append("</Item>");
var xmlFilePath = GetSavePath(item);
XmlSaverHelpers.Save(builder, xmlFilePath);
// Set last refreshed so that the provider doesn't trigger after the file save
PersonProviderFromXml.Current.SetLastRefreshed(item, DateTime.UtcNow);
}
/// <summary>
/// Gets the save path.
/// </summary>
/// <param name="item">The item.</param>
/// <returns>System.String.</returns>
public string GetSavePath(BaseItem item)
{
return Path.Combine(item.Path, "album.xml");
}
}
}

@ -0,0 +1,77 @@
using MediaBrowser.Controller.Configuration;
using MediaBrowser.Controller.Entities;
using MediaBrowser.Controller.Entities.Audio;
using MediaBrowser.Controller.Library;
using MediaBrowser.Model.Entities;
using MediaBrowser.Providers.Movies;
using System;
using System.IO;
using System.Text;
using System.Threading;
namespace MediaBrowser.Providers.Savers
{
class ArtistXmlSaver : IMetadataSaver
{
private readonly IServerConfigurationManager _config;
public ArtistXmlSaver(IServerConfigurationManager config)
{
_config = config;
}
/// <summary>
/// Supportses the specified item.
/// </summary>
/// <param name="item">The item.</param>
/// <returns><c>true</c> if XXXX, <c>false</c> otherwise</returns>
public bool Supports(BaseItem item)
{
if (item.LocationType != LocationType.FileSystem)
{
return false;
}
if (item is MusicArtist)
{
return _config.Configuration.SaveLocalMeta;
}
return item is Artist;
}
/// <summary>
/// Saves the specified item.
/// </summary>
/// <param name="item">The item.</param>
/// <param name="cancellationToken">The cancellation token.</param>
/// <returns>Task.</returns>
public void Save(BaseItem item, CancellationToken cancellationToken)
{
var builder = new StringBuilder();
builder.Append("<Item>");
XmlSaverHelpers.AddCommonNodes(item, builder);
builder.Append("</Item>");
var xmlFilePath = GetSavePath(item);
XmlSaverHelpers.Save(builder, xmlFilePath);
// Set last refreshed so that the provider doesn't trigger after the file save
PersonProviderFromXml.Current.SetLastRefreshed(item, DateTime.UtcNow);
}
/// <summary>
/// Gets the save path.
/// </summary>
/// <param name="item">The item.</param>
/// <returns>System.String.</returns>
public string GetSavePath(BaseItem item)
{
return Path.Combine(item.Path, "artist.xml");
}
}
}

@ -65,14 +65,14 @@ namespace MediaBrowser.Providers.Savers
builder.Append("<FirstAired>" + SecurityElement.Escape(episode.PremiereDate.Value.ToString("yyyy-MM-dd")) + "</FirstAired>");
}
XmlHelpers.AddCommonNodes(item, builder);
XmlHelpers.AppendMediaInfo(episode, builder);
XmlSaverHelpers.AddCommonNodes(item, builder);
XmlSaverHelpers.AppendMediaInfo(episode, builder);
builder.Append("</Item>");
var xmlFilePath = GetSavePath(item);
XmlHelpers.Save(builder, xmlFilePath);
XmlSaverHelpers.Save(builder, xmlFilePath);
// Set last refreshed so that the provider doesn't trigger after the file save
EpisodeProviderFromXml.Current.SetLastRefreshed(item, DateTime.UtcNow);

@ -1,4 +1,6 @@
using MediaBrowser.Controller.Entities;
using MediaBrowser.Controller.Configuration;
using MediaBrowser.Controller.Entities;
using MediaBrowser.Controller.Entities.Audio;
using MediaBrowser.Controller.Entities.Movies;
using MediaBrowser.Controller.Entities.TV;
using MediaBrowser.Controller.Library;
@ -11,6 +13,13 @@ namespace MediaBrowser.Providers.Savers
{
public class FolderXmlSaver : IMetadataSaver
{
private readonly IServerConfigurationManager _config;
public FolderXmlSaver(IServerConfigurationManager config)
{
_config = config;
}
/// <summary>
/// Supportses the specified item.
/// </summary>
@ -18,12 +27,12 @@ namespace MediaBrowser.Providers.Savers
/// <returns><c>true</c> if XXXX, <c>false</c> otherwise</returns>
public bool Supports(BaseItem item)
{
if (item.LocationType != LocationType.FileSystem)
if (!_config.Configuration.SaveLocalMeta || item.LocationType != LocationType.FileSystem)
{
return false;
}
return item is Folder && !(item is Series) && !(item is BoxSet);
return item is Folder && !(item is Series) && !(item is BoxSet) && !(item is MusicArtist) && !(item is MusicAlbum);
}
/// <summary>
@ -38,13 +47,13 @@ namespace MediaBrowser.Providers.Savers
builder.Append("<Item>");
XmlHelpers.AddCommonNodes(item, builder);
XmlSaverHelpers.AddCommonNodes(item, builder);
builder.Append("</Item>");
var xmlFilePath = GetSavePath(item);
XmlHelpers.Save(builder, xmlFilePath);
XmlSaverHelpers.Save(builder, xmlFilePath);
}
/// <summary>

@ -1,4 +1,4 @@
using System.Text;
using MediaBrowser.Controller.Configuration;
using MediaBrowser.Controller.Entities;
using MediaBrowser.Controller.Entities.Movies;
using MediaBrowser.Controller.Library;
@ -6,6 +6,7 @@ using MediaBrowser.Model.Entities;
using MediaBrowser.Providers.Movies;
using System;
using System.IO;
using System.Text;
using System.Threading;
namespace MediaBrowser.Providers.Savers
@ -15,6 +16,13 @@ namespace MediaBrowser.Providers.Savers
/// </summary>
public class MovieXmlSaver : IMetadataSaver
{
private readonly IServerConfigurationManager _config;
public MovieXmlSaver(IServerConfigurationManager config)
{
_config = config;
}
/// <summary>
/// Supportses the specified item.
/// </summary>
@ -22,7 +30,7 @@ namespace MediaBrowser.Providers.Savers
/// <returns><c>true</c> if XXXX, <c>false</c> otherwise</returns>
public bool Supports(BaseItem item)
{
if (item.LocationType != LocationType.FileSystem)
if (!_config.Configuration.SaveLocalMeta || item.LocationType != LocationType.FileSystem)
{
return false;
}
@ -50,13 +58,13 @@ namespace MediaBrowser.Providers.Savers
builder.Append("<Title>");
XmlHelpers.AddCommonNodes(item, builder);
XmlSaverHelpers.AddCommonNodes(item, builder);
builder.Append("</Title>");
var xmlFilePath = GetSavePath(item);
XmlHelpers.Save(builder, xmlFilePath);
XmlSaverHelpers.Save(builder, xmlFilePath);
// Set last refreshed so that the provider doesn't trigger after the file save
MovieProviderFromXml.Current.SetLastRefreshed(item, DateTime.UtcNow);

@ -41,13 +41,13 @@ namespace MediaBrowser.Providers.Savers
builder.Append("<Item>");
XmlHelpers.AddCommonNodes(item, builder);
XmlSaverHelpers.AddCommonNodes(item, builder);
builder.Append("</Item>");
var xmlFilePath = GetSavePath(item);
XmlHelpers.Save(builder, xmlFilePath);
XmlSaverHelpers.Save(builder, xmlFilePath);
// Set last refreshed so that the provider doesn't trigger after the file save
PersonProviderFromXml.Current.SetLastRefreshed(item, DateTime.UtcNow);

@ -1,4 +1,5 @@
using System;
using MediaBrowser.Controller.Configuration;
using MediaBrowser.Controller.Entities;
using MediaBrowser.Controller.Entities.TV;
using MediaBrowser.Controller.Library;
@ -13,6 +14,13 @@ namespace MediaBrowser.Providers.Savers
{
public class SeriesXmlSaver : IMetadataSaver
{
private readonly IServerConfigurationManager _config;
public SeriesXmlSaver(IServerConfigurationManager config)
{
_config = config;
}
/// <summary>
/// Supportses the specified item.
/// </summary>
@ -20,7 +28,7 @@ namespace MediaBrowser.Providers.Savers
/// <returns><c>true</c> if XXXX, <c>false</c> otherwise</returns>
public bool Supports(BaseItem item)
{
if (item.LocationType != LocationType.FileSystem)
if (!_config.Configuration.SaveLocalMeta || item.LocationType != LocationType.FileSystem)
{
return false;
}
@ -78,13 +86,13 @@ namespace MediaBrowser.Providers.Savers
builder.Append("<Airs_DayOfWeek>" + SecurityElement.Escape(series.AirDays[0].ToString()) + "</Airs_DayOfWeek>");
}
XmlHelpers.AddCommonNodes(item, builder);
XmlSaverHelpers.AddCommonNodes(item, builder);
builder.Append("</Series>");
var xmlFilePath = GetSavePath(item);
XmlHelpers.Save(builder, xmlFilePath);
XmlSaverHelpers.Save(builder, xmlFilePath);
// Set last refreshed so that the provider doesn't trigger after the file save
SeriesProviderFromXml.Current.SetLastRefreshed(item, DateTime.UtcNow);

@ -4,7 +4,6 @@ using MediaBrowser.Model.Entities;
using System;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Security;
using System.Text;
using System.Xml;
@ -14,7 +13,7 @@ namespace MediaBrowser.Providers.Savers
/// <summary>
/// Class XmlHelpers
/// </summary>
public static class XmlHelpers
public static class XmlSaverHelpers
{
/// <summary>
/// The us culture
@ -34,6 +33,13 @@ namespace MediaBrowser.Providers.Savers
//Add the new node to the document.
xmlDocument.InsertBefore(xmlDocument.CreateXmlDeclaration("1.0", "UTF-8", "yes"), xmlDocument.DocumentElement);
var parentPath = Path.GetDirectoryName(path);
if (!Directory.Exists(parentPath))
{
Directory.CreateDirectory(parentPath);
}
using (var streamWriter = new StreamWriter(path, false, Encoding.UTF8))
{
xmlDocument.Save(streamWriter);
@ -94,6 +100,11 @@ namespace MediaBrowser.Providers.Savers
{
builder.Append("<SortTitle>" + SecurityElement.Escape(item.ForcedSortName) + "</SortTitle>");
}
if (item.PremiereDate.HasValue)
{
builder.Append("<PremiereDate>" + SecurityElement.Escape(item.PremiereDate.Value.ToString("yyyy-MM-dd")) + "</PremiereDate>");
}
if (item.Budget.HasValue)
{
@ -182,6 +193,13 @@ namespace MediaBrowser.Providers.Savers
builder.Append("<RottenTomatoesId>" + SecurityElement.Escape(rt) + "</RottenTomatoesId>");
}
var mbz = item.GetProviderId(MetadataProviders.Musicbrainz);
if (!string.IsNullOrEmpty(mbz))
{
builder.Append("<MusicbrainzId>" + SecurityElement.Escape(mbz) + "</MusicbrainzId>");
}
var tmdbCollection = item.GetProviderId(MetadataProviders.TmdbCollection);
if (!string.IsNullOrEmpty(tmdbCollection))
@ -213,6 +231,18 @@ namespace MediaBrowser.Providers.Savers
builder.Append("</Studios>");
}
if (item.Tags.Count > 0)
{
builder.Append("<Tags>");
foreach (var tag in item.Tags)
{
builder.Append("<Tag>" + SecurityElement.Escape(tag) + "</Tag>");
}
builder.Append("</Tags>");
}
builder.Append("<Added>" + SecurityElement.Escape(item.DateCreated.ToString(UsCulture)) + "</Added>");
}

@ -83,40 +83,38 @@ namespace MediaBrowser.Server.Implementations.Providers
libraryManager.ItemUpdated += libraryManager_ItemUpdated;
}
private readonly ConcurrentDictionary<string, SemaphoreSlim> _fileLocks = new ConcurrentDictionary<string, SemaphoreSlim>();
/// <summary>
/// Handles the ItemUpdated event of the libraryManager control.
/// </summary>
/// <param name="sender">The source of the event.</param>
/// <param name="e">The <see cref="ItemChangeEventArgs"/> instance containing the event data.</param>
void libraryManager_ItemUpdated(object sender, ItemChangeEventArgs e)
async void libraryManager_ItemUpdated(object sender, ItemChangeEventArgs e)
{
var item = e.Item;
if (ConfigurationManager.Configuration.SaveLocalMeta)
foreach (var saver in _savers.Where(i => i.Supports(item)))
{
if (item.LocationType != LocationType.FileSystem)
{
return;
}
var path = saver.GetSavePath(item);
foreach (var saver in _savers.Where(i => i.Supports(item)))
{
var path = saver.GetSavePath(item);
var semaphore = _fileLocks.GetOrAdd(path, key => new SemaphoreSlim(1, 1));
_directoryWatchers.TemporarilyIgnore(path);
await semaphore.WaitAsync().ConfigureAwait(false);
try
{
saver.Save(item, CancellationToken.None);
}
catch (Exception ex)
{
_logger.ErrorException("Error in metadata saver", ex);
}
finally
{
_directoryWatchers.RemoveTempIgnore(path);
}
try
{
_directoryWatchers.TemporarilyIgnore(path);
saver.Save(item, CancellationToken.None);
}
catch (Exception ex)
{
_logger.ErrorException("Error in metadata saver", ex);
}
finally
{
_directoryWatchers.RemoveTempIgnore(path);
semaphore.Release();
}
}
}

Loading…
Cancel
Save