aboutsummaryrefslogtreecommitdiff
path: root/MediaBrowser.LocalMetadata
diff options
context:
space:
mode:
authorLuke <luke.pulverenti@gmail.com>2016-12-18 00:44:33 -0500
committerGitHub <noreply@github.com>2016-12-18 00:44:33 -0500
commite7cebb91a73354dc3e0d0b6340c9fbd6511f4406 (patch)
tree6f1c368c766c17b7514fe749c0e92e69cd89194a /MediaBrowser.LocalMetadata
parent025905a3e4d50b9a2e07fbf4ff0a203af6604ced (diff)
parentaaa027f3229073e9a40756c3157d41af2a442922 (diff)
Merge pull request #2350 from MediaBrowser/beta
Beta
Diffstat (limited to 'MediaBrowser.LocalMetadata')
-rw-r--r--MediaBrowser.LocalMetadata/BaseXmlProvider.cs8
-rw-r--r--MediaBrowser.LocalMetadata/Images/CollectionFolderImageProvider.cs4
-rw-r--r--MediaBrowser.LocalMetadata/Images/EpisodeLocalImageProvider.cs4
-rw-r--r--MediaBrowser.LocalMetadata/Images/ImagesByNameImageProvider.cs6
-rw-r--r--MediaBrowser.LocalMetadata/Images/InternalMetadataFolderImageProvider.cs6
-rw-r--r--MediaBrowser.LocalMetadata/Images/LocalImageProvider.cs4
-rw-r--r--MediaBrowser.LocalMetadata/MediaBrowser.LocalMetadata.csproj31
-rw-r--r--MediaBrowser.LocalMetadata/MediaBrowser.LocalMetadata.nuget.targets6
-rw-r--r--MediaBrowser.LocalMetadata/Parsers/BaseItemXmlParser.cs1473
-rw-r--r--MediaBrowser.LocalMetadata/Parsers/BoxSetXmlParser.cs30
-rw-r--r--MediaBrowser.LocalMetadata/Parsers/EpisodeXmlParser.cs9
-rw-r--r--MediaBrowser.LocalMetadata/Parsers/GameSystemXmlParser.cs11
-rw-r--r--MediaBrowser.LocalMetadata/Parsers/GameXmlParser.cs11
-rw-r--r--MediaBrowser.LocalMetadata/Parsers/MovieXmlParser.cs16
-rw-r--r--MediaBrowser.LocalMetadata/Parsers/MusicVideoXmlParser.cs15
-rw-r--r--MediaBrowser.LocalMetadata/Parsers/PlaylistXmlParser.cs83
-rw-r--r--MediaBrowser.LocalMetadata/Parsers/SeriesXmlParser.cs15
-rw-r--r--MediaBrowser.LocalMetadata/Providers/BoxSetXmlProvider.cs11
-rw-r--r--MediaBrowser.LocalMetadata/Providers/EpisodeXmlProvider.cs11
-rw-r--r--MediaBrowser.LocalMetadata/Providers/FolderXmlProvider.cs12
-rw-r--r--MediaBrowser.LocalMetadata/Providers/GameSystemXmlProvider.cs11
-rw-r--r--MediaBrowser.LocalMetadata/Providers/GameXmlProvider.cs11
-rw-r--r--MediaBrowser.LocalMetadata/Providers/MovieXmlProvider.cs11
-rw-r--r--MediaBrowser.LocalMetadata/Providers/MusicVideoXmlProvider.cs11
-rw-r--r--MediaBrowser.LocalMetadata/Providers/PersonXmlProvider.cs32
-rw-r--r--MediaBrowser.LocalMetadata/Providers/PlaylistXmlProvider.cs11
-rw-r--r--MediaBrowser.LocalMetadata/Providers/SeriesXmlProvider.cs11
-rw-r--r--MediaBrowser.LocalMetadata/Providers/VideoXmlProvider.cs11
-rw-r--r--MediaBrowser.LocalMetadata/Savers/BaseXmlSaver.cs752
-rw-r--r--MediaBrowser.LocalMetadata/Savers/BoxSetXmlSaver.cs66
-rw-r--r--MediaBrowser.LocalMetadata/Savers/FolderXmlSaver.cs61
-rw-r--r--MediaBrowser.LocalMetadata/Savers/GameSystemXmlSaver.cs77
-rw-r--r--MediaBrowser.LocalMetadata/Savers/GameXmlSaver.cs92
-rw-r--r--MediaBrowser.LocalMetadata/Savers/PersonXmlSaver.cs133
-rw-r--r--MediaBrowser.LocalMetadata/Savers/PlaylistXmlSaver.cs86
-rw-r--r--MediaBrowser.LocalMetadata/Savers/XmlSaverHelpers.cs647
-rw-r--r--MediaBrowser.LocalMetadata/packages.config5
-rw-r--r--MediaBrowser.LocalMetadata/project.json17
38 files changed, 2631 insertions, 1180 deletions
diff --git a/MediaBrowser.LocalMetadata/BaseXmlProvider.cs b/MediaBrowser.LocalMetadata/BaseXmlProvider.cs
index f23559e4b..50e9de727 100644
--- a/MediaBrowser.LocalMetadata/BaseXmlProvider.cs
+++ b/MediaBrowser.LocalMetadata/BaseXmlProvider.cs
@@ -3,7 +3,9 @@ using MediaBrowser.Controller.Providers;
using System.IO;
using System.Threading;
using System.Threading.Tasks;
-using CommonIO;
+using MediaBrowser.Common.IO;
+using MediaBrowser.Controller.IO;
+using MediaBrowser.Model.IO;
namespace MediaBrowser.LocalMetadata
{
@@ -38,7 +40,7 @@ namespace MediaBrowser.LocalMetadata
{
result.HasMetadata = false;
}
- catch (DirectoryNotFoundException)
+ catch (IOException)
{
result.HasMetadata = false;
}
@@ -94,7 +96,5 @@ namespace MediaBrowser.LocalMetadata
return "Emby Xml";
}
}
-
- internal static readonly SemaphoreSlim XmlParsingResourcePool = new SemaphoreSlim(4, 4);
}
}
diff --git a/MediaBrowser.LocalMetadata/Images/CollectionFolderImageProvider.cs b/MediaBrowser.LocalMetadata/Images/CollectionFolderImageProvider.cs
index 21b3cedae..651273eb0 100644
--- a/MediaBrowser.LocalMetadata/Images/CollectionFolderImageProvider.cs
+++ b/MediaBrowser.LocalMetadata/Images/CollectionFolderImageProvider.cs
@@ -1,7 +1,9 @@
using MediaBrowser.Controller.Entities;
using MediaBrowser.Controller.Providers;
using System.Collections.Generic;
-using CommonIO;
+using MediaBrowser.Common.IO;
+using MediaBrowser.Controller.IO;
+using MediaBrowser.Model.IO;
namespace MediaBrowser.LocalMetadata.Images
{
diff --git a/MediaBrowser.LocalMetadata/Images/EpisodeLocalImageProvider.cs b/MediaBrowser.LocalMetadata/Images/EpisodeLocalImageProvider.cs
index 716d40d8f..e02326838 100644
--- a/MediaBrowser.LocalMetadata/Images/EpisodeLocalImageProvider.cs
+++ b/MediaBrowser.LocalMetadata/Images/EpisodeLocalImageProvider.cs
@@ -6,7 +6,9 @@ using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
-using CommonIO;
+using MediaBrowser.Common.IO;
+using MediaBrowser.Controller.IO;
+using MediaBrowser.Model.IO;
namespace MediaBrowser.LocalMetadata.Images
{
diff --git a/MediaBrowser.LocalMetadata/Images/ImagesByNameImageProvider.cs b/MediaBrowser.LocalMetadata/Images/ImagesByNameImageProvider.cs
index 6034008de..8a6dde6c4 100644
--- a/MediaBrowser.LocalMetadata/Images/ImagesByNameImageProvider.cs
+++ b/MediaBrowser.LocalMetadata/Images/ImagesByNameImageProvider.cs
@@ -1,8 +1,10 @@
using System.Collections.Generic;
using System.IO;
-using CommonIO;
+using MediaBrowser.Common.IO;
+using MediaBrowser.Model.IO;
using MediaBrowser.Controller.Configuration;
using MediaBrowser.Controller.Entities;
+using MediaBrowser.Controller.IO;
using MediaBrowser.Controller.Providers;
namespace MediaBrowser.LocalMetadata.Images
@@ -47,7 +49,7 @@ namespace MediaBrowser.LocalMetadata.Images
{
return new LocalImageProvider(_fileSystem).GetImages(item, path, directoryService);
}
- catch (DirectoryNotFoundException)
+ catch (IOException)
{
return new List<LocalImageInfo>();
}
diff --git a/MediaBrowser.LocalMetadata/Images/InternalMetadataFolderImageProvider.cs b/MediaBrowser.LocalMetadata/Images/InternalMetadataFolderImageProvider.cs
index 1cec4d305..b29182d96 100644
--- a/MediaBrowser.LocalMetadata/Images/InternalMetadataFolderImageProvider.cs
+++ b/MediaBrowser.LocalMetadata/Images/InternalMetadataFolderImageProvider.cs
@@ -4,7 +4,9 @@ using MediaBrowser.Controller.Entities.Audio;
using MediaBrowser.Controller.Providers;
using System.Collections.Generic;
using System.IO;
-using CommonIO;
+using MediaBrowser.Common.IO;
+using MediaBrowser.Controller.IO;
+using MediaBrowser.Model.IO;
namespace MediaBrowser.LocalMetadata.Images
{
@@ -67,7 +69,7 @@ namespace MediaBrowser.LocalMetadata.Images
{
return new LocalImageProvider(_fileSystem).GetImages(item, path, directoryService);
}
- catch (DirectoryNotFoundException)
+ catch (IOException)
{
return new List<LocalImageInfo>();
}
diff --git a/MediaBrowser.LocalMetadata/Images/LocalImageProvider.cs b/MediaBrowser.LocalMetadata/Images/LocalImageProvider.cs
index ef9160b70..2f7059fec 100644
--- a/MediaBrowser.LocalMetadata/Images/LocalImageProvider.cs
+++ b/MediaBrowser.LocalMetadata/Images/LocalImageProvider.cs
@@ -7,7 +7,9 @@ using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
-using CommonIO;
+using MediaBrowser.Common.IO;
+using MediaBrowser.Controller.IO;
+using MediaBrowser.Model.IO;
namespace MediaBrowser.LocalMetadata.Images
{
diff --git a/MediaBrowser.LocalMetadata/MediaBrowser.LocalMetadata.csproj b/MediaBrowser.LocalMetadata/MediaBrowser.LocalMetadata.csproj
index ac127458e..f7b7fa5f2 100644
--- a/MediaBrowser.LocalMetadata/MediaBrowser.LocalMetadata.csproj
+++ b/MediaBrowser.LocalMetadata/MediaBrowser.LocalMetadata.csproj
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
-<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+<Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
@@ -9,9 +9,11 @@
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>MediaBrowser.LocalMetadata</RootNamespace>
<AssemblyName>MediaBrowser.LocalMetadata</AssemblyName>
- <TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
<SolutionDir Condition="$(SolutionDir) == '' Or $(SolutionDir) == '*Undefined*'">..\</SolutionDir>
+ <ProjectTypeGuids>{786C830F-07A1-408B-BD7F-6EE04809D6DB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
+ <TargetFrameworkProfile>Profile7</TargetFrameworkProfile>
+ <TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugSymbols>true</DebugSymbols>
@@ -31,22 +33,6 @@
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<ItemGroup>
- <Reference Include="CommonIO, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL">
- <SpecificVersion>False</SpecificVersion>
- <HintPath>..\packages\CommonIO.1.0.0.9\lib\net45\CommonIO.dll</HintPath>
- </Reference>
- <Reference Include="Patterns.Logging">
- <HintPath>..\packages\Patterns.Logging.1.0.0.2\lib\portable-net45+sl4+wp71+win8+wpa81\Patterns.Logging.dll</HintPath>
- </Reference>
- <Reference Include="System" />
- <Reference Include="System.Core" />
- <Reference Include="System.Xml.Linq" />
- <Reference Include="System.Data.DataSetExtensions" />
- <Reference Include="Microsoft.CSharp" />
- <Reference Include="System.Data" />
- <Reference Include="System.Xml" />
- </ItemGroup>
- <ItemGroup>
<Compile Include="..\SharedVersion.cs">
<Link>Properties\SharedVersion.cs</Link>
</Compile>
@@ -56,6 +42,7 @@
<Compile Include="Images\ImagesByNameImageProvider.cs" />
<Compile Include="Images\InternalMetadataFolderImageProvider.cs" />
<Compile Include="Images\LocalImageProvider.cs" />
+ <Compile Include="Parsers\BaseItemXmlParser.cs" />
<Compile Include="Parsers\BoxSetXmlParser.cs" />
<Compile Include="Parsers\EpisodeXmlParser.cs" />
<Compile Include="Parsers\GameSystemXmlParser.cs" />
@@ -72,17 +59,16 @@
<Compile Include="Providers\GameXmlProvider.cs" />
<Compile Include="Providers\MovieXmlProvider.cs" />
<Compile Include="Providers\MusicVideoXmlProvider.cs" />
- <Compile Include="Providers\PersonXmlProvider.cs" />
<Compile Include="Providers\PlaylistXmlProvider.cs" />
<Compile Include="Providers\SeriesXmlProvider.cs" />
<Compile Include="Providers\VideoXmlProvider.cs" />
+ <Compile Include="Savers\BaseXmlSaver.cs" />
<Compile Include="Savers\BoxSetXmlSaver.cs" />
<Compile Include="Savers\FolderXmlSaver.cs" />
<Compile Include="Savers\GameSystemXmlSaver.cs" />
<Compile Include="Savers\GameXmlSaver.cs" />
<Compile Include="Savers\PersonXmlSaver.cs" />
<Compile Include="Savers\PlaylistXmlSaver.cs" />
- <Compile Include="Savers\XmlSaverHelpers.cs" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\MediaBrowser.Common\MediaBrowser.Common.csproj">
@@ -98,10 +84,7 @@
<Name>MediaBrowser.Model</Name>
</ProjectReference>
</ItemGroup>
- <ItemGroup>
- <None Include="packages.config" />
- </ItemGroup>
- <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
+ <Import Project="$(MSBuildExtensionsPath32)\Microsoft\Portable\$(TargetFrameworkVersion)\Microsoft.Portable.CSharp.targets" />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.
<Target Name="BeforeBuild">
diff --git a/MediaBrowser.LocalMetadata/MediaBrowser.LocalMetadata.nuget.targets b/MediaBrowser.LocalMetadata/MediaBrowser.LocalMetadata.nuget.targets
new file mode 100644
index 000000000..e69ce0e64
--- /dev/null
+++ b/MediaBrowser.LocalMetadata/MediaBrowser.LocalMetadata.nuget.targets
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8" standalone="no"?>
+<Project ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <Target Name="EmitMSBuildWarning" BeforeTargets="Build">
+ <Warning Text="Packages containing MSBuild targets and props files cannot be fully installed in projects targeting multiple frameworks. The MSBuild targets and props files have been ignored." />
+ </Target>
+</Project> \ No newline at end of file
diff --git a/MediaBrowser.LocalMetadata/Parsers/BaseItemXmlParser.cs b/MediaBrowser.LocalMetadata/Parsers/BaseItemXmlParser.cs
new file mode 100644
index 000000000..d66cdf801
--- /dev/null
+++ b/MediaBrowser.LocalMetadata/Parsers/BaseItemXmlParser.cs
@@ -0,0 +1,1473 @@
+using System;
+using System.Collections.Generic;
+using System.Globalization;
+using System.IO;
+using System.Linq;
+using System.Text;
+using System.Threading;
+using System.Xml;
+using MediaBrowser.Controller.Entities;
+using MediaBrowser.Controller.Providers;
+using MediaBrowser.Model.Entities;
+using MediaBrowser.Model.IO;
+using MediaBrowser.Model.Logging;
+using MediaBrowser.Model.Xml;
+
+namespace MediaBrowser.LocalMetadata.Parsers
+{
+ /// <summary>
+ /// Provides a base class for parsing metadata xml
+ /// </summary>
+ /// <typeparam name="T"></typeparam>
+ public class BaseItemXmlParser<T>
+ where T : BaseItem
+ {
+ /// <summary>
+ /// The logger
+ /// </summary>
+ protected ILogger Logger { get; private set; }
+ protected IProviderManager ProviderManager { get; private set; }
+
+ private Dictionary<string, string> _validProviderIds;
+
+ protected IXmlReaderSettingsFactory XmlReaderSettingsFactory { get; private set; }
+ protected IFileSystem FileSystem { get; private set; }
+
+ /// <summary>
+ /// Initializes a new instance of the <see cref="BaseItemXmlParser{T}" /> class.
+ /// </summary>
+ /// <param name="logger">The logger.</param>
+ public BaseItemXmlParser(ILogger logger, IProviderManager providerManager, IXmlReaderSettingsFactory xmlReaderSettingsFactory, IFileSystem fileSystem)
+ {
+ Logger = logger;
+ ProviderManager = providerManager;
+ XmlReaderSettingsFactory = xmlReaderSettingsFactory;
+ FileSystem = fileSystem;
+ }
+
+ /// <summary>
+ /// Fetches metadata for an item from one xml file
+ /// </summary>
+ /// <param name="item">The item.</param>
+ /// <param name="metadataFile">The metadata file.</param>
+ /// <param name="cancellationToken">The cancellation token.</param>
+ /// <exception cref="System.ArgumentNullException"></exception>
+ public void Fetch(MetadataResult<T> item, string metadataFile, CancellationToken cancellationToken)
+ {
+ if (item == null)
+ {
+ throw new ArgumentNullException();
+ }
+
+ if (string.IsNullOrEmpty(metadataFile))
+ {
+ throw new ArgumentNullException();
+ }
+
+ var settings = XmlReaderSettingsFactory.Create(false);
+
+ settings.CheckCharacters = false;
+ settings.IgnoreProcessingInstructions = true;
+ settings.IgnoreComments = true;
+
+ _validProviderIds = _validProviderIds = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);
+
+ var idInfos = ProviderManager.GetExternalIdInfos(item.Item);
+
+ foreach (var info in idInfos)
+ {
+ var id = info.Key + "Id";
+ if (!_validProviderIds.ContainsKey(id))
+ {
+ _validProviderIds.Add(id, info.Key);
+ }
+ }
+
+ //Additional Mappings
+ _validProviderIds.Add("IMDB", "Imdb");
+
+ //Fetch(item, metadataFile, settings, Encoding.GetEncoding("ISO-8859-1"), cancellationToken);
+ Fetch(item, metadataFile, settings, Encoding.UTF8, cancellationToken);
+ }
+
+ /// <summary>
+ /// Fetches the specified item.
+ /// </summary>
+ /// <param name="item">The item.</param>
+ /// <param name="metadataFile">The metadata file.</param>
+ /// <param name="settings">The settings.</param>
+ /// <param name="encoding">The encoding.</param>
+ /// <param name="cancellationToken">The cancellation token.</param>
+ private void Fetch(MetadataResult<T> item, string metadataFile, XmlReaderSettings settings, Encoding encoding, CancellationToken cancellationToken)
+ {
+ item.ResetPeople();
+
+ using (Stream fileStream = FileSystem.OpenRead(metadataFile))
+ {
+ using (var streamReader = new StreamReader(fileStream, encoding))
+ {
+ // Use XmlReader for best performance
+ using (var reader = XmlReader.Create(streamReader, settings))
+ {
+ reader.MoveToContent();
+ reader.Read();
+
+ // Loop through each element
+ while (!reader.EOF && reader.ReadState == ReadState.Interactive)
+ {
+ cancellationToken.ThrowIfCancellationRequested();
+
+ if (reader.NodeType == XmlNodeType.Element)
+ {
+ FetchDataFromXmlNode(reader, item);
+ }
+ else
+ {
+ reader.Read();
+ }
+ }
+ }
+ }
+ }
+ }
+
+ private readonly CultureInfo _usCulture = new CultureInfo("en-US");
+
+ /// <summary>
+ /// Fetches metadata from one Xml Element
+ /// </summary>
+ /// <param name="reader">The reader.</param>
+ /// <param name="itemResult">The item result.</param>
+ protected virtual void FetchDataFromXmlNode(XmlReader reader, MetadataResult<T> itemResult)
+ {
+ var item = itemResult.Item;
+
+ switch (reader.Name)
+ {
+ // DateCreated
+ case "Added":
+ {
+ var val = reader.ReadElementContentAsString();
+
+ if (!string.IsNullOrWhiteSpace(val))
+ {
+ DateTime added;
+ if (DateTime.TryParse(val, out added))
+ {
+ item.DateCreated = added.ToUniversalTime();
+ }
+ else
+ {
+ Logger.Warn("Invalid Added value found: " + val);
+ }
+ }
+ break;
+ }
+
+ case "OriginalTitle":
+ {
+ var val = reader.ReadElementContentAsString();
+
+ if (!string.IsNullOrEmpty(val))
+ {
+ item.OriginalTitle = val;
+ }
+ break;
+ }
+
+ case "LocalTitle":
+ item.Name = reader.ReadElementContentAsString();
+ break;
+
+ case "Type":
+ {
+ var type = reader.ReadElementContentAsString();
+
+ if (!string.IsNullOrWhiteSpace(type) && !type.Equals("none", StringComparison.OrdinalIgnoreCase))
+ {
+ item.DisplayMediaType = type;
+ }
+
+ break;
+ }
+
+ case "CriticRating":
+ {
+ var text = reader.ReadElementContentAsString();
+
+ if (!string.IsNullOrEmpty(text))
+ {
+ float value;
+ if (float.TryParse(text, NumberStyles.Any, _usCulture, out value))
+ {
+ item.CriticRating = value;
+ }
+ }
+
+ break;
+ }
+
+ case "Budget":
+ {
+ var text = reader.ReadElementContentAsString();
+ var hasBudget = item as IHasBudget;
+ if (hasBudget != null)
+ {
+ double value;
+ if (double.TryParse(text, NumberStyles.Any, _usCulture, out value))
+ {
+ hasBudget.Budget = value;
+ }
+ }
+
+ break;
+ }
+
+ case "Revenue":
+ {
+ var text = reader.ReadElementContentAsString();
+ var hasBudget = item as IHasBudget;
+ if (hasBudget != null)
+ {
+ double value;
+ if (double.TryParse(text, NumberStyles.Any, _usCulture, out value))
+ {
+ hasBudget.Revenue = value;
+ }
+ }
+
+ break;
+ }
+
+ case "Metascore":
+ {
+ var text = reader.ReadElementContentAsString();
+ var hasMetascore = item as IHasMetascore;
+ if (hasMetascore != null)
+ {
+ float value;
+ if (float.TryParse(text, NumberStyles.Any, _usCulture, out value))
+ {
+ hasMetascore.Metascore = value;
+ }
+ }
+
+ break;
+ }
+
+ case "AwardSummary":
+ {
+ var text = reader.ReadElementContentAsString();
+ var hasAwards = item as IHasAwards;
+ if (hasAwards != null)
+ {
+ if (!string.IsNullOrWhiteSpace(text))
+ {
+ hasAwards.AwardSummary = text;
+ }
+ }
+
+ break;
+ }
+
+ case "SortTitle":
+ {
+ var val = reader.ReadElementContentAsString();
+
+ if (!string.IsNullOrWhiteSpace(val))
+ {
+ item.ForcedSortName = val;
+ }
+ break;
+ }
+
+ case "Overview":
+ case "Description":
+ {
+ var val = reader.ReadElementContentAsString();
+
+ if (!string.IsNullOrWhiteSpace(val))
+ {
+ item.Overview = val;
+ }
+
+ break;
+ }
+
+ case "ShortOverview":
+ {
+ var val = reader.ReadElementContentAsString();
+
+ if (!string.IsNullOrWhiteSpace(val))
+ {
+ item.ShortOverview = val;
+ }
+
+ break;
+ }
+
+ case "CriticRatingSummary":
+ {
+ var val = reader.ReadElementContentAsString();
+
+ if (!string.IsNullOrWhiteSpace(val))
+ {
+ item.CriticRatingSummary = val;
+ }
+
+ break;
+ }
+
+ case "Language":
+ {
+ var val = reader.ReadElementContentAsString();
+
+ item.PreferredMetadataLanguage = val;
+
+ break;
+ }
+
+ case "CountryCode":
+ {
+ var val = reader.ReadElementContentAsString();
+
+ item.PreferredMetadataCountryCode = val;
+
+ break;
+ }
+
+ case "PlaceOfBirth":
+ {
+ var val = reader.ReadElementContentAsString();
+
+ if (!string.IsNullOrWhiteSpace(val))
+ {
+ var person = item as Person;
+ if (person != null)
+ {
+ person.ProductionLocations = new List<string> { val };
+ }
+ }
+
+ break;
+ }
+
+ case "Website":
+ {
+ var val = reader.ReadElementContentAsString();
+
+ if (!string.IsNullOrWhiteSpace(val))
+ {
+ item.HomePageUrl = val;
+ }
+
+ break;
+ }
+
+ case "LockedFields":
+ {
+ var fields = new List<MetadataFields>();
+
+ var val = reader.ReadElementContentAsString();
+
+ if (!string.IsNullOrWhiteSpace(val))
+ {
+ var list = val.Split('|').Select(i =>
+ {
+ MetadataFields field;
+
+ if (Enum.TryParse<MetadataFields>(i, true, out field))
+ {
+ return (MetadataFields?)field;
+ }
+
+ return null;
+
+ }).Where(i => i.HasValue).Select(i => i.Value);
+
+ fields.AddRange(list);
+ }
+
+ item.LockedFields = fields;
+
+ break;
+ }
+
+ case "TagLines":
+ {
+ if (!reader.IsEmptyElement)
+ {
+ using (var subtree = reader.ReadSubtree())
+ {
+ FetchFromTaglinesNode(subtree, item);
+ }
+ }
+ else
+ {
+ reader.Read();
+ }
+ break;
+ }
+
+ case "Countries":
+ {
+ if (!reader.IsEmptyElement)
+ {
+ using (var subtree = reader.ReadSubtree())
+ {
+ FetchFromCountriesNode(subtree, item);
+ }
+ }
+ else
+ {
+ reader.Read();
+ }
+ break;
+ }
+
+ case "ContentRating":
+ case "MPAARating":
+ {
+ var rating = reader.ReadElementContentAsString();
+
+ if (!string.IsNullOrWhiteSpace(rating))
+ {
+ item.OfficialRating = rating;
+ }
+ break;
+ }
+
+ case "MPAADescription":
+ {
+ var rating = reader.ReadElementContentAsString();
+
+ if (!string.IsNullOrWhiteSpace(rating))
+ {
+ item.OfficialRatingDescription = rating;
+ }
+ break;
+ }
+
+ case "CustomRating":
+ {
+ var val = reader.ReadElementContentAsString();
+
+ if (!string.IsNullOrWhiteSpace(val))
+ {
+ item.CustomRating = val;
+ }
+ break;
+ }
+
+ case "RunningTime":
+ {
+ var text = reader.ReadElementContentAsString();
+
+ if (!string.IsNullOrWhiteSpace(text))
+ {
+ int runtime;
+ if (int.TryParse(text.Split(' ')[0], NumberStyles.Integer, _usCulture, out runtime))
+ {
+ item.RunTimeTicks = TimeSpan.FromMinutes(runtime).Ticks;
+ }
+ }
+ break;
+ }
+
+ case "AspectRatio":
+ {
+ var val = reader.ReadElementContentAsString();
+
+ var hasAspectRatio = item as IHasAspectRatio;
+ if (!string.IsNullOrWhiteSpace(val) && hasAspectRatio != null)
+ {
+ hasAspectRatio.AspectRatio = val;
+ }
+ break;
+ }
+
+ case "LockData":
+ {
+ var val = reader.ReadElementContentAsString();
+
+ if (!string.IsNullOrWhiteSpace(val))
+ {
+ item.IsLocked = string.Equals("true", val, StringComparison.OrdinalIgnoreCase);
+ }
+ break;
+ }
+
+ case "Network":
+ {
+ foreach (var name in SplitNames(reader.ReadElementContentAsString()))
+ {
+ if (string.IsNullOrWhiteSpace(name))
+ {
+ continue;
+ }
+ item.AddStudio(name);
+ }
+ break;
+ }
+
+ case "Director":
+ {
+ foreach (var p in SplitNames(reader.ReadElementContentAsString()).Select(v => new Controller.Entities.PersonInfo { Name = v.Trim(), Type = PersonType.Director }))
+ {
+ if (string.IsNullOrWhiteSpace(p.Name))
+ {
+ continue;
+ }
+ itemResult.AddPerson(p);
+ }
+ break;
+ }
+ case "Writer":
+ {
+ foreach (var p in SplitNames(reader.ReadElementContentAsString()).Select(v => new Controller.Entities.PersonInfo { Name = v.Trim(), Type = PersonType.Writer }))
+ {
+ if (string.IsNullOrWhiteSpace(p.Name))
+ {
+ continue;
+ }
+ itemResult.AddPerson(p);
+ }
+ break;
+ }
+
+ case "Actors":
+ {
+
+ var actors = reader.ReadInnerXml();
+
+ if (actors.Contains("<"))
+ {
+ // This is one of the mis-named "Actors" full nodes created by MB2
+ // Create a reader and pass it to the persons node processor
+ FetchDataFromPersonsNode(XmlReader.Create(new StringReader("<Persons>" + actors + "</Persons>")), itemResult);
+ }
+ else
+ {
+ // Old-style piped string
+ foreach (var p in SplitNames(actors).Select(v => new Controller.Entities.PersonInfo { Name = v.Trim(), Type = PersonType.Actor }))
+ {
+ if (string.IsNullOrWhiteSpace(p.Name))
+ {
+ continue;
+ }
+ itemResult.AddPerson(p);
+ }
+ }
+ break;
+ }
+
+ case "GuestStars":
+ {
+ foreach (var p in SplitNames(reader.ReadElementContentAsString()).Select(v => new Controller.Entities.PersonInfo { Name = v.Trim(), Type = PersonType.GuestStar }))
+ {
+ if (string.IsNullOrWhiteSpace(p.Name))
+ {
+ continue;
+ }
+ itemResult.AddPerson(p);
+ }
+ break;
+ }
+
+ case "Trailer":
+ {
+ var val = reader.ReadElementContentAsString();
+
+ var hasTrailers = item as IHasTrailers;
+ if (hasTrailers != null)
+ {
+ if (!string.IsNullOrWhiteSpace(val))
+ {
+ hasTrailers.AddTrailerUrl(val, false);
+ }
+ }
+ break;
+ }
+
+ case "DisplayOrder":
+ {
+ var val = reader.ReadElementContentAsString();
+
+ var hasDisplayOrder = item as IHasDisplayOrder;
+ if (hasDisplayOrder != null)
+ {
+ if (!string.IsNullOrWhiteSpace(val))
+ {
+ hasDisplayOrder.DisplayOrder = val;
+ }
+ }
+ break;
+ }
+
+ case "Trailers":
+ {
+ if (!reader.IsEmptyElement)
+ {
+ using (var subtree = reader.ReadSubtree())
+ {
+ var hasTrailers = item as IHasTrailers;
+ if (hasTrailers != null)
+ {
+ FetchDataFromTrailersNode(subtree, hasTrailers);
+ }
+ }
+ }
+ else
+ {
+ reader.Read();
+ }
+ break;
+ }
+
+ case "ProductionYear":
+ {
+ var val = reader.ReadElementContentAsString();
+
+ if (!string.IsNullOrWhiteSpace(val))
+ {
+ int productionYear;
+ if (int.TryParse(val, out productionYear) && productionYear > 1850)
+ {
+ item.ProductionYear = productionYear;
+ }
+ }
+
+ break;
+ }
+
+ case "Rating":
+ case "IMDBrating":
+ {
+
+ var rating = reader.ReadElementContentAsString();
+
+ if (!string.IsNullOrWhiteSpace(rating))
+ {
+ float val;
+ // All external meta is saving this as '.' for decimal I believe...but just to be sure
+ if (float.TryParse(rating.Replace(',', '.'), NumberStyles.AllowDecimalPoint, CultureInfo.InvariantCulture, out val))
+ {
+ item.CommunityRating = val;
+ }
+ }
+ break;
+ }
+
+ case "BirthDate":
+ case "PremiereDate":
+ case "FirstAired":
+ {
+ var firstAired = reader.ReadElementContentAsString();
+
+ if (!string.IsNullOrWhiteSpace(firstAired))
+ {
+ DateTime airDate;
+
+ if (DateTime.TryParseExact(firstAired, "yyyy-MM-dd", CultureInfo.InvariantCulture, DateTimeStyles.AssumeLocal, out airDate) && airDate.Year > 1850)
+ {
+ item.PremiereDate = airDate.ToUniversalTime();
+ item.ProductionYear = airDate.Year;
+ }
+ }
+
+ break;
+ }
+
+ case "DeathDate":
+ case "EndDate":
+ {
+ var firstAired = reader.ReadElementContentAsString();
+
+ if (!string.IsNullOrWhiteSpace(firstAired))
+ {
+ DateTime airDate;
+
+ if (DateTime.TryParseExact(firstAired, "yyyy-MM-dd", CultureInfo.InvariantCulture, DateTimeStyles.AssumeLocal, out airDate) && airDate.Year > 1850)
+ {
+ item.EndDate = airDate.ToUniversalTime();
+ }
+ }
+
+ break;
+ }
+
+ case "VoteCount":
+ {
+ var val = reader.ReadElementContentAsString();
+ if (!string.IsNullOrWhiteSpace(val))
+ {
+ int num;
+
+ if (int.TryParse(val, NumberStyles.Integer, _usCulture, out num))
+ {
+ item.VoteCount = num;
+ }
+ }
+ break;
+ }
+ case "CollectionNumber":
+ var tmdbCollection = reader.ReadElementContentAsString();
+ if (!string.IsNullOrWhiteSpace(tmdbCollection))
+ {
+ item.SetProviderId(MetadataProviders.TmdbCollection, tmdbCollection);
+ }
+ break;
+
+ case "Genres":
+ {
+ if (!reader.IsEmptyElement)
+ {
+ using (var subtree = reader.ReadSubtree())
+ {
+ FetchFromGenresNode(subtree, item);
+ }
+ }
+ else
+ {
+ reader.Read();
+ }
+ break;
+ }
+
+ case "Tags":
+ {
+ if (!reader.IsEmptyElement)
+ {
+ using (var subtree = reader.ReadSubtree())
+ {
+ FetchFromTagsNode(subtree, item);
+ }
+ }
+ else
+ {
+ reader.Read();
+ }
+ break;
+ }
+
+ case "PlotKeywords":
+ {
+ if (!reader.IsEmptyElement)
+ {
+ using (var subtree = reader.ReadSubtree())
+ {
+ FetchFromKeywordsNode(subtree, item);
+ }
+ }
+ else
+ {
+ reader.Read();
+ }
+ break;
+ }
+
+ case "Persons":
+ {
+ if (!reader.IsEmptyElement)
+ {
+ using (var subtree = reader.ReadSubtree())
+ {
+ FetchDataFromPersonsNode(subtree, itemResult);
+ }
+ }
+ else
+ {
+ reader.Read();
+ }
+ break;
+ }
+
+ case "Studios":
+ {
+ if (!reader.IsEmptyElement)
+ {
+ using (var subtree = reader.ReadSubtree())
+ {
+ FetchFromStudiosNode(subtree, item);
+ }
+ }
+ else
+ {
+ reader.Read();
+ }
+ break;
+ }
+
+ case "Shares":
+ {
+ if (!reader.IsEmptyElement)
+ {
+ using (var subtree = reader.ReadSubtree())
+ {
+ var hasShares = item as IHasShares;
+ if (hasShares != null)
+ {
+ FetchFromSharesNode(subtree, hasShares);
+ }
+ }
+ }
+ else
+ {
+ reader.Read();
+ }
+ break;
+ }
+
+ case "Format3D":
+ {
+ var val = reader.ReadElementContentAsString();
+
+ var video = item as Video;
+
+ if (video != null)
+ {
+ if (string.Equals("HSBS", val, StringComparison.OrdinalIgnoreCase))
+ {
+ video.Video3DFormat = Video3DFormat.HalfSideBySide;
+ }
+ else if (string.Equals("HTAB", val, StringComparison.OrdinalIgnoreCase))
+ {
+ video.Video3DFormat = Video3DFormat.HalfTopAndBottom;
+ }
+ else if (string.Equals("FTAB", val, StringComparison.OrdinalIgnoreCase))
+ {
+ video.Video3DFormat = Video3DFormat.FullTopAndBottom;
+ }
+ else if (string.Equals("FSBS", val, StringComparison.OrdinalIgnoreCase))
+ {
+ video.Video3DFormat = Video3DFormat.FullSideBySide;
+ }
+ else if (string.Equals("MVC", val, StringComparison.OrdinalIgnoreCase))
+ {
+ video.Video3DFormat = Video3DFormat.MVC;
+ }
+ }
+ break;
+ }
+
+ default:
+ {
+ string readerName = reader.Name;
+ string providerIdValue;
+ if (_validProviderIds.TryGetValue(readerName, out providerIdValue))
+ {
+ var id = reader.ReadElementContentAsString();
+ if (!string.IsNullOrWhiteSpace(id))
+ {
+ item.SetProviderId(providerIdValue, id);
+ }
+ }
+ else
+ {
+ reader.Skip();
+ }
+
+ break;
+
+ }
+ }
+ }
+
+ private void FetchFromSharesNode(XmlReader reader, IHasShares item)
+ {
+ reader.MoveToContent();
+ reader.Read();
+
+ // Loop through each element
+ while (!reader.EOF && reader.ReadState == ReadState.Interactive)
+ {
+ if (reader.NodeType == XmlNodeType.Element)
+ {
+ switch (reader.Name)
+ {
+ case "Share":
+ {
+ if (reader.IsEmptyElement)
+ {
+ reader.Read();
+ continue;
+ }
+ using (var subtree = reader.ReadSubtree())
+ {
+ var share = GetShareFromNode(subtree);
+ if (share != null)
+ {
+ item.Shares.Add(share);
+ }
+ }
+ break;
+ }
+
+ default:
+ reader.Skip();
+ break;
+ }
+ }
+ else
+ {
+ reader.Read();
+ }
+ }
+ }
+
+ private Share GetShareFromNode(XmlReader reader)
+ {
+ var share = new Share();
+
+ reader.MoveToContent();
+ reader.Read();
+
+ // Loop through each element
+ while (!reader.EOF && reader.ReadState == ReadState.Interactive)
+ {
+ if (reader.NodeType == XmlNodeType.Element)
+ {
+ switch (reader.Name)
+ {
+ case "UserId":
+ {
+ share.UserId = reader.ReadElementContentAsString();
+ break;
+ }
+
+ case "CanEdit":
+ {
+ share.CanEdit = string.Equals(reader.ReadElementContentAsString(), true.ToString(), StringComparison.OrdinalIgnoreCase);
+ break;
+ }
+
+ default:
+ reader.Skip();
+ break;
+ }
+ }
+ else
+ {
+ reader.Read();
+ }
+ }
+
+ return share;
+ }
+
+ private void FetchFromCountriesNode(XmlReader reader, T item)
+ {
+ reader.MoveToContent();
+ reader.Read();
+
+ // Loop through each element
+ while (!reader.EOF && reader.ReadState == ReadState.Interactive)
+ {
+ if (reader.NodeType == XmlNodeType.Element)
+ {
+ switch (reader.Name)
+ {
+ case "Country":
+ {
+ var val = reader.ReadElementContentAsString();
+
+ if (!string.IsNullOrWhiteSpace(val))
+ {
+ }
+ break;
+ }
+
+ default:
+ reader.Skip();
+ break;
+ }
+ }
+ else
+ {
+ reader.Read();
+ }
+ }
+ }
+
+ /// <summary>
+ /// Fetches from taglines node.
+ /// </summary>
+ /// <param name="reader">The reader.</param>
+ /// <param name="item">The item.</param>
+ private void FetchFromTaglinesNode(XmlReader reader, T item)
+ {
+ reader.MoveToContent();
+ reader.Read();
+
+ // Loop through each element
+ while (!reader.EOF && reader.ReadState == ReadState.Interactive)
+ {
+ if (reader.NodeType == XmlNodeType.Element)
+ {
+ switch (reader.Name)
+ {
+ case "Tagline":
+ {
+ var val = reader.ReadElementContentAsString();
+
+ if (!string.IsNullOrWhiteSpace(val))
+ {
+ item.Tagline = val;
+ }
+ break;
+ }
+ default:
+ reader.Skip();
+ break;
+ }
+ }
+ else
+ {
+ reader.Read();
+ }
+ }
+ }
+
+ /// <summary>
+ /// Fetches from genres node.
+ /// </summary>
+ /// <param name="reader">The reader.</param>
+ /// <param name="item">The item.</param>
+ private void FetchFromGenresNode(XmlReader reader, T item)
+ {
+ reader.MoveToContent();
+ reader.Read();
+
+ // Loop through each element
+ while (!reader.EOF && reader.ReadState == ReadState.Interactive)
+ {
+ if (reader.NodeType == XmlNodeType.Element)
+ {
+ switch (reader.Name)
+ {
+ case "Genre":
+ {
+ var genre = reader.ReadElementContentAsString();
+
+ if (!string.IsNullOrWhiteSpace(genre))
+ {
+ item.AddGenre(genre);
+ }
+ break;
+ }
+
+ default:
+ reader.Skip();
+ break;
+ }
+ }
+ else
+ {
+ reader.Read();
+ }
+ }
+ }
+
+ private void FetchFromTagsNode(XmlReader reader, BaseItem item)
+ {
+ reader.MoveToContent();
+ reader.Read();
+
+ // Loop through each element
+ while (!reader.EOF && reader.ReadState == ReadState.Interactive)
+ {
+ if (reader.NodeType == XmlNodeType.Element)
+ {
+ switch (reader.Name)
+ {
+ case "Tag":
+ {
+ var tag = reader.ReadElementContentAsString();
+
+ if (!string.IsNullOrWhiteSpace(tag))
+ {
+ item.AddTag(tag);
+ }
+ break;
+ }
+
+ default:
+ reader.Skip();
+ break;
+ }
+ }
+ else
+ {
+ reader.Read();
+ }
+ }
+ }
+
+ private void FetchFromKeywordsNode(XmlReader reader, BaseItem item)
+ {
+ reader.MoveToContent();
+ reader.Read();
+
+ // Loop through each element
+ while (!reader.EOF && reader.ReadState == ReadState.Interactive)
+ {
+ if (reader.NodeType == XmlNodeType.Element)
+ {
+ switch (reader.Name)
+ {
+ case "PlotKeyword":
+ {
+ var tag = reader.ReadElementContentAsString();
+
+ if (!string.IsNullOrWhiteSpace(tag))
+ {
+ item.AddKeyword(tag);
+ }
+ break;
+ }
+
+ default:
+ reader.Skip();
+ break;
+ }
+ }
+ else
+ {
+ reader.Read();
+ }
+ }
+ }
+
+ /// <summary>
+ /// Fetches the data from persons node.
+ /// </summary>
+ /// <param name="reader">The reader.</param>
+ /// <param name="item">The item.</param>
+ private void FetchDataFromPersonsNode(XmlReader reader, MetadataResult<T> item)
+ {
+ reader.MoveToContent();
+ reader.Read();
+
+ // Loop through each element
+ while (!reader.EOF && reader.ReadState == ReadState.Interactive)
+ {
+ if (reader.NodeType == XmlNodeType.Element)
+ {
+ switch (reader.Name)
+ {
+ case "Person":
+ case "Actor":
+ {
+ if (reader.IsEmptyElement)
+ {
+ reader.Read();
+ continue;
+ }
+ using (var subtree = reader.ReadSubtree())
+ {
+ foreach (var person in GetPersonsFromXmlNode(subtree))
+ {
+ if (string.IsNullOrWhiteSpace(person.Name))
+ {
+ continue;
+ }
+ item.AddPerson(person);
+ }
+ }
+ break;
+ }
+
+ default:
+ reader.Skip();
+ break;
+ }
+ }
+ else
+ {
+ reader.Read();
+ }
+ }
+ }
+
+ private void FetchDataFromTrailersNode(XmlReader reader, IHasTrailers item)
+ {
+ reader.MoveToContent();
+ reader.Read();
+
+ // Loop through each element
+ while (!reader.EOF && reader.ReadState == ReadState.Interactive)
+ {
+ if (reader.NodeType == XmlNodeType.Element)
+ {
+ switch (reader.Name)
+ {
+ case "Trailer":
+ {
+ var val = reader.ReadElementContentAsString();
+
+ if (!string.IsNullOrWhiteSpace(val))
+ {
+ item.AddTrailerUrl(val, false);
+ }
+ break;
+ }
+
+ default:
+ reader.Skip();
+ break;
+ }
+ }
+ else
+ {
+ reader.Read();
+ }
+ }
+ }
+
+ /// <summary>
+ /// Fetches from studios node.
+ /// </summary>
+ /// <param name="reader">The reader.</param>
+ /// <param name="item">The item.</param>
+ private void FetchFromStudiosNode(XmlReader reader, T item)
+ {
+ reader.MoveToContent();
+ reader.Read();
+
+ // Loop through each element
+ while (!reader.EOF && reader.ReadState == ReadState.Interactive)
+ {
+ if (reader.NodeType == XmlNodeType.Element)
+ {
+ switch (reader.Name)
+ {
+ case "Studio":
+ {
+ var studio = reader.ReadElementContentAsString();
+
+ if (!string.IsNullOrWhiteSpace(studio))
+ {
+ item.AddStudio(studio);
+ }
+ break;
+ }
+
+ default:
+ reader.Skip();
+ break;
+ }
+ }
+ else
+ {
+ reader.Read();
+ }
+ }
+ }
+
+ /// <summary>
+ /// Gets the persons from XML node.
+ /// </summary>
+ /// <param name="reader">The reader.</param>
+ /// <returns>IEnumerable{PersonInfo}.</returns>
+ private IEnumerable<PersonInfo> GetPersonsFromXmlNode(XmlReader reader)
+ {
+ var name = string.Empty;
+ var type = PersonType.Actor; // If type is not specified assume actor
+ var role = string.Empty;
+ int? sortOrder = null;
+
+ reader.MoveToContent();
+ reader.Read();
+
+ // Loop through each element
+ while (!reader.EOF && reader.ReadState == ReadState.Interactive)
+ {
+ if (reader.NodeType == XmlNodeType.Element)
+ {
+ switch (reader.Name)
+ {
+ case "Name":
+ name = reader.ReadElementContentAsString() ?? string.Empty;
+ break;
+
+ case "Type":
+ {
+ var val = reader.ReadElementContentAsString();
+
+ if (!string.IsNullOrWhiteSpace(val))
+ {
+ type = val;
+ }
+ break;
+ }
+
+ case "Role":
+ {
+ var val = reader.ReadElementContentAsString();
+
+ if (!string.IsNullOrWhiteSpace(val))
+ {
+ role = val;
+ }
+ break;
+ }
+ case "SortOrder":
+ {
+ var val = reader.ReadElementContentAsString();
+
+ if (!string.IsNullOrWhiteSpace(val))
+ {
+ int intVal;
+ if (int.TryParse(val, NumberStyles.Integer, _usCulture, out intVal))
+ {
+ sortOrder = intVal;
+ }
+ }
+ break;
+ }
+
+ default:
+ reader.Skip();
+ break;
+ }
+ }
+ else
+ {
+ reader.Read();
+ }
+ }
+
+ var personInfo = new PersonInfo
+ {
+ Name = name.Trim(),
+ Role = role,
+ Type = type,
+ SortOrder = sortOrder
+ };
+
+ return new[] { personInfo };
+ }
+
+ protected LinkedChild GetLinkedChild(XmlReader reader)
+ {
+ var linkedItem = new LinkedChild
+ {
+ Type = LinkedChildType.Manual
+ };
+
+ reader.MoveToContent();
+ reader.Read();
+
+ // Loop through each element
+ while (!reader.EOF && reader.ReadState == ReadState.Interactive)
+ {
+ if (reader.NodeType == XmlNodeType.Element)
+ {
+ switch (reader.Name)
+ {
+ case "Path":
+ {
+ linkedItem.Path = reader.ReadElementContentAsString();
+ break;
+ }
+
+ default:
+ reader.Skip();
+ break;
+ }
+ }
+ else
+ {
+ reader.Read();
+ }
+ }
+
+ // This is valid
+ if (!string.IsNullOrWhiteSpace(linkedItem.Path))
+ {
+ return linkedItem;
+ }
+
+ return null;
+ }
+
+ protected Share GetShare(XmlReader reader)
+ {
+ var item = new Share();
+
+ reader.MoveToContent();
+ reader.Read();
+
+ // Loop through each element
+ while (!reader.EOF && reader.ReadState == ReadState.Interactive)
+ {
+ if (reader.NodeType == XmlNodeType.Element)
+ {
+ switch (reader.Name)
+ {
+ case "UserId":
+ {
+ item.UserId = reader.ReadElementContentAsString();
+ break;
+ }
+
+ case "CanEdit":
+ {
+ item.CanEdit = string.Equals(reader.ReadElementContentAsString(), "true", StringComparison.OrdinalIgnoreCase);
+ break;
+ }
+ default:
+ {
+ reader.Skip();
+ break;
+ }
+ }
+ }
+ else
+ {
+ reader.Read();
+ }
+ }
+
+ // This is valid
+ if (!string.IsNullOrWhiteSpace(item.UserId))
+ {
+ return item;
+ }
+
+ return null;
+ }
+
+
+ /// <summary>
+ /// Used to split names of comma or pipe delimeted genres and people
+ /// </summary>
+ /// <param name="value">The value.</param>
+ /// <returns>IEnumerable{System.String}.</returns>
+ private IEnumerable<string> SplitNames(string value)
+ {
+ value = value ?? string.Empty;
+
+ // Only split by comma if there is no pipe in the string
+ // We have to be careful to not split names like Matthew, Jr.
+ var separator = value.IndexOf('|') == -1 && value.IndexOf(';') == -1 ? new[] { ',' } : new[] { '|', ';' };
+
+ value = value.Trim().Trim(separator);
+
+ return string.IsNullOrWhiteSpace(value) ? new string[] { } : Split(value, separator, StringSplitOptions.RemoveEmptyEntries);
+ }
+
+ /// <summary>
+ /// Provides an additional overload for string.split
+ /// </summary>
+ /// <param name="val">The val.</param>
+ /// <param name="separators">The separators.</param>
+ /// <param name="options">The options.</param>
+ /// <returns>System.String[][].</returns>
+ private static string[] Split(string val, char[] separators, StringSplitOptions options)
+ {
+ return val.Split(separators, options);
+ }
+
+ }
+}
diff --git a/MediaBrowser.LocalMetadata/Parsers/BoxSetXmlParser.cs b/MediaBrowser.LocalMetadata/Parsers/BoxSetXmlParser.cs
index 9ebb357c6..9dcfa2f76 100644
--- a/MediaBrowser.LocalMetadata/Parsers/BoxSetXmlParser.cs
+++ b/MediaBrowser.LocalMetadata/Parsers/BoxSetXmlParser.cs
@@ -4,16 +4,13 @@ using MediaBrowser.Controller.Providers;
using MediaBrowser.Model.Logging;
using System.Collections.Generic;
using System.Xml;
+using MediaBrowser.Model.IO;
+using MediaBrowser.Model.Xml;
namespace MediaBrowser.LocalMetadata.Parsers
{
public class BoxSetXmlParser : BaseItemXmlParser<BoxSet>
{
- public BoxSetXmlParser(ILogger logger, IProviderManager providerManager)
- : base(logger, providerManager)
- {
- }
-
protected override void FetchDataFromXmlNode(XmlReader reader, MetadataResult<BoxSet> item)
{
switch (reader.Name)
@@ -34,11 +31,13 @@ namespace MediaBrowser.LocalMetadata.Parsers
private void FetchFromCollectionItemsNode(XmlReader reader, MetadataResult<BoxSet> item)
{
- reader.MoveToContent();
-
var list = new List<LinkedChild>();
- while (reader.Read())
+ reader.MoveToContent();
+ reader.Read();
+
+ // Loop through each element
+ while (!reader.EOF && reader.ReadState == ReadState.Interactive)
{
if (reader.NodeType == XmlNodeType.Element)
{
@@ -58,15 +57,24 @@ namespace MediaBrowser.LocalMetadata.Parsers
break;
}
-
default:
- reader.Skip();
- break;
+ {
+ reader.Skip();
+ break;
+ }
}
}
+ else
+ {
+ reader.Read();
+ }
}
item.Item.LinkedChildren = list;
}
+
+ public BoxSetXmlParser(ILogger logger, IProviderManager providerManager, IXmlReaderSettingsFactory xmlReaderSettingsFactory, IFileSystem fileSystem) : base(logger, providerManager, xmlReaderSettingsFactory, fileSystem)
+ {
+ }
}
}
diff --git a/MediaBrowser.LocalMetadata/Parsers/EpisodeXmlParser.cs b/MediaBrowser.LocalMetadata/Parsers/EpisodeXmlParser.cs
index 71f6d3fe9..9adc4e5a9 100644
--- a/MediaBrowser.LocalMetadata/Parsers/EpisodeXmlParser.cs
+++ b/MediaBrowser.LocalMetadata/Parsers/EpisodeXmlParser.cs
@@ -8,7 +8,10 @@ using System.Globalization;
using System.IO;
using System.Threading;
using System.Xml;
-using CommonIO;
+using MediaBrowser.Common.IO;
+using MediaBrowser.Controller.IO;
+using MediaBrowser.Model.IO;
+using MediaBrowser.Model.Xml;
namespace MediaBrowser.LocalMetadata.Parsers
{
@@ -20,8 +23,8 @@ namespace MediaBrowser.LocalMetadata.Parsers
private List<LocalImageInfo> _imagesFound;
private readonly IFileSystem _fileSystem;
- public EpisodeXmlParser(ILogger logger, IFileSystem fileSystem, IProviderManager providerManager)
- : base(logger, providerManager)
+ public EpisodeXmlParser(ILogger logger, IFileSystem fileSystem, IProviderManager providerManager, IXmlReaderSettingsFactory xmlSettings)
+ : base(logger, providerManager, xmlSettings, fileSystem)
{
_fileSystem = fileSystem;
}
diff --git a/MediaBrowser.LocalMetadata/Parsers/GameSystemXmlParser.cs b/MediaBrowser.LocalMetadata/Parsers/GameSystemXmlParser.cs
index 75df53958..8bf09e546 100644
--- a/MediaBrowser.LocalMetadata/Parsers/GameSystemXmlParser.cs
+++ b/MediaBrowser.LocalMetadata/Parsers/GameSystemXmlParser.cs
@@ -5,16 +5,13 @@ using MediaBrowser.Model.Logging;
using System.Threading;
using System.Threading.Tasks;
using System.Xml;
+using MediaBrowser.Model.IO;
+using MediaBrowser.Model.Xml;
namespace MediaBrowser.LocalMetadata.Parsers
{
public class GameSystemXmlParser : BaseItemXmlParser<GameSystem>
{
- public GameSystemXmlParser(ILogger logger, IProviderManager providerManager)
- : base(logger, providerManager)
- {
- }
-
private readonly Task _cachedTask = Task.FromResult(true);
public Task FetchAsync(MetadataResult<GameSystem> item, string metadataFile, CancellationToken cancellationToken)
{
@@ -62,5 +59,9 @@ namespace MediaBrowser.LocalMetadata.Parsers
break;
}
}
+
+ public GameSystemXmlParser(ILogger logger, IProviderManager providerManager, IXmlReaderSettingsFactory xmlReaderSettingsFactory, IFileSystem fileSystem) : base(logger, providerManager, xmlReaderSettingsFactory, fileSystem)
+ {
+ }
}
}
diff --git a/MediaBrowser.LocalMetadata/Parsers/GameXmlParser.cs b/MediaBrowser.LocalMetadata/Parsers/GameXmlParser.cs
index 956b8baef..abce0582c 100644
--- a/MediaBrowser.LocalMetadata/Parsers/GameXmlParser.cs
+++ b/MediaBrowser.LocalMetadata/Parsers/GameXmlParser.cs
@@ -5,7 +5,9 @@ using System.Xml;
using MediaBrowser.Controller.Entities;
using MediaBrowser.Controller.Providers;
using MediaBrowser.Model.Entities;
+using MediaBrowser.Model.IO;
using MediaBrowser.Model.Logging;
+using MediaBrowser.Model.Xml;
namespace MediaBrowser.LocalMetadata.Parsers
{
@@ -16,11 +18,6 @@ namespace MediaBrowser.LocalMetadata.Parsers
{
private readonly CultureInfo _usCulture = new CultureInfo("en-US");
- public GameXmlParser(ILogger logger, IProviderManager providerManager)
- : base(logger, providerManager)
- {
- }
-
private readonly Task _cachedTask = Task.FromResult(true);
public Task FetchAsync(MetadataResult<Game> item, string metadataFile, CancellationToken cancellationToken)
{
@@ -83,5 +80,9 @@ namespace MediaBrowser.LocalMetadata.Parsers
break;
}
}
+
+ public GameXmlParser(ILogger logger, IProviderManager providerManager, IXmlReaderSettingsFactory xmlReaderSettingsFactory, IFileSystem fileSystem) : base(logger, providerManager, xmlReaderSettingsFactory, fileSystem)
+ {
+ }
}
}
diff --git a/MediaBrowser.LocalMetadata/Parsers/MovieXmlParser.cs b/MediaBrowser.LocalMetadata/Parsers/MovieXmlParser.cs
index 6e78d365e..08c895c43 100644
--- a/MediaBrowser.LocalMetadata/Parsers/MovieXmlParser.cs
+++ b/MediaBrowser.LocalMetadata/Parsers/MovieXmlParser.cs
@@ -3,6 +3,8 @@ using MediaBrowser.Controller.Entities.Movies;
using MediaBrowser.Controller.Providers;
using MediaBrowser.Model.Logging;
using System.Xml;
+using MediaBrowser.Model.IO;
+using MediaBrowser.Model.Xml;
namespace MediaBrowser.LocalMetadata.Parsers
{
@@ -12,11 +14,6 @@ namespace MediaBrowser.LocalMetadata.Parsers
public class BaseVideoXmlParser<T> : BaseItemXmlParser<T>
where T : Video
{
- public BaseVideoXmlParser(ILogger logger, IProviderManager providerManager)
- : base(logger, providerManager)
- {
- }
-
/// <summary>
/// Fetches the data from XML node.
/// </summary>
@@ -46,19 +43,22 @@ namespace MediaBrowser.LocalMetadata.Parsers
break;
}
}
+
+ public BaseVideoXmlParser(ILogger logger, IProviderManager providerManager, IXmlReaderSettingsFactory xmlReaderSettingsFactory, IFileSystem fileSystem) : base(logger, providerManager, xmlReaderSettingsFactory, fileSystem)
+ {
+ }
}
public class MovieXmlParser : BaseVideoXmlParser<Movie>
{
- public MovieXmlParser(ILogger logger, IProviderManager providerManager) : base(logger, providerManager)
+ public MovieXmlParser(ILogger logger, IProviderManager providerManager, IXmlReaderSettingsFactory xmlReaderSettingsFactory, IFileSystem fileSystem) : base(logger, providerManager, xmlReaderSettingsFactory, fileSystem)
{
}
}
public class VideoXmlParser : BaseVideoXmlParser<Video>
{
- public VideoXmlParser(ILogger logger, IProviderManager providerManager)
- : base(logger, providerManager)
+ public VideoXmlParser(ILogger logger, IProviderManager providerManager, IXmlReaderSettingsFactory xmlReaderSettingsFactory, IFileSystem fileSystem) : base(logger, providerManager, xmlReaderSettingsFactory, fileSystem)
{
}
}
diff --git a/MediaBrowser.LocalMetadata/Parsers/MusicVideoXmlParser.cs b/MediaBrowser.LocalMetadata/Parsers/MusicVideoXmlParser.cs
index 5f0b447e8..f612d1108 100644
--- a/MediaBrowser.LocalMetadata/Parsers/MusicVideoXmlParser.cs
+++ b/MediaBrowser.LocalMetadata/Parsers/MusicVideoXmlParser.cs
@@ -3,21 +3,14 @@ using MediaBrowser.Controller.Providers;
using MediaBrowser.Model.Logging;
using System;
using System.Xml;
+using MediaBrowser.Model.IO;
+using MediaBrowser.Model.Xml;
namespace MediaBrowser.LocalMetadata.Parsers
{
public class MusicVideoXmlParser : BaseVideoXmlParser<MusicVideo>
{
/// <summary>
- /// Initializes a new instance of the <see cref="BaseItemXmlParser{T}" /> class.
- /// </summary>
- /// <param name="logger">The logger.</param>
- public MusicVideoXmlParser(ILogger logger, IProviderManager providerManager)
- : base(logger, providerManager)
- {
- }
-
- /// <summary>
/// Fetches the data from XML node.
/// </summary>
/// <param name="reader">The reader.</param>
@@ -50,5 +43,9 @@ namespace MediaBrowser.LocalMetadata.Parsers
break;
}
}
+
+ public MusicVideoXmlParser(ILogger logger, IProviderManager providerManager, IXmlReaderSettingsFactory xmlReaderSettingsFactory, IFileSystem fileSystem) : base(logger, providerManager, xmlReaderSettingsFactory, fileSystem)
+ {
+ }
}
}
diff --git a/MediaBrowser.LocalMetadata/Parsers/PlaylistXmlParser.cs b/MediaBrowser.LocalMetadata/Parsers/PlaylistXmlParser.cs
index de46c0a86..695fe2b12 100644
--- a/MediaBrowser.LocalMetadata/Parsers/PlaylistXmlParser.cs
+++ b/MediaBrowser.LocalMetadata/Parsers/PlaylistXmlParser.cs
@@ -6,16 +6,13 @@ using System;
using System.Collections.Generic;
using System.Linq;
using System.Xml;
+using MediaBrowser.Model.IO;
+using MediaBrowser.Model.Xml;
namespace MediaBrowser.LocalMetadata.Parsers
{
public class PlaylistXmlParser : BaseItemXmlParser<Playlist>
{
- public PlaylistXmlParser(ILogger logger, IProviderManager providerManager)
- : base(logger, providerManager)
- {
- }
-
protected override void FetchDataFromXmlNode(XmlReader reader, MetadataResult<Playlist> result)
{
var item = result.Item;
@@ -46,17 +43,31 @@ namespace MediaBrowser.LocalMetadata.Parsers
case "PlaylistItems":
- using (var subReader = reader.ReadSubtree())
+ if (!reader.IsEmptyElement)
+ {
+ using (var subReader = reader.ReadSubtree())
+ {
+ FetchFromCollectionItemsNode(subReader, item);
+ }
+ }
+ else
{
- FetchFromCollectionItemsNode(subReader, item);
+ reader.Read();
}
break;
case "Shares":
- using (var subReader = reader.ReadSubtree())
+ if (!reader.IsEmptyElement)
+ {
+ using (var subReader = reader.ReadSubtree())
+ {
+ FetchFromSharesNode(subReader, item);
+ }
+ }
+ else
{
- FetchFromSharesNode(subReader, item);
+ reader.Read();
}
break;
@@ -68,11 +79,13 @@ namespace MediaBrowser.LocalMetadata.Parsers
private void FetchFromCollectionItemsNode(XmlReader reader, Playlist item)
{
- reader.MoveToContent();
-
var list = new List<LinkedChild>();
- while (reader.Read())
+ reader.MoveToContent();
+ reader.Read();
+
+ // Loop through each element
+ while (!reader.EOF && reader.ReadState == ReadState.Interactive)
{
if (reader.NodeType == XmlNodeType.Element)
{
@@ -80,6 +93,12 @@ namespace MediaBrowser.LocalMetadata.Parsers
{
case "PlaylistItem":
{
+ if (reader.IsEmptyElement)
+ {
+ reader.Read();
+ continue;
+ }
+
using (var subReader = reader.ReadSubtree())
{
var child = GetLinkedChild(subReader);
@@ -92,12 +111,17 @@ namespace MediaBrowser.LocalMetadata.Parsers
break;
}
-
default:
- reader.Skip();
- break;
+ {
+ reader.Skip();
+ break;
+ }
}
}
+ else
+ {
+ reader.Read();
+ }
}
item.LinkedChildren = list;
@@ -105,11 +129,13 @@ namespace MediaBrowser.LocalMetadata.Parsers
private void FetchFromSharesNode(XmlReader reader, Playlist item)
{
- reader.MoveToContent();
-
var list = new List<Share>();
- while (reader.Read())
+ reader.MoveToContent();
+ reader.Read();
+
+ // Loop through each element
+ while (!reader.EOF && reader.ReadState == ReadState.Interactive)
{
if (reader.NodeType == XmlNodeType.Element)
{
@@ -117,6 +143,12 @@ namespace MediaBrowser.LocalMetadata.Parsers
{
case "Share":
{
+ if (reader.IsEmptyElement)
+ {
+ reader.Read();
+ continue;
+ }
+
using (var subReader = reader.ReadSubtree())
{
var child = GetShare(subReader);
@@ -129,15 +161,24 @@ namespace MediaBrowser.LocalMetadata.Parsers
break;
}
-
default:
- reader.Skip();
- break;
+ {
+ reader.Skip();
+ break;
+ }
}
}
+ else
+ {
+ reader.Read();
+ }
}
item.Shares = list;
}
+
+ public PlaylistXmlParser(ILogger logger, IProviderManager providerManager, IXmlReaderSettingsFactory xmlReaderSettingsFactory, IFileSystem fileSystem) : base(logger, providerManager, xmlReaderSettingsFactory, fileSystem)
+ {
+ }
}
}
diff --git a/MediaBrowser.LocalMetadata/Parsers/SeriesXmlParser.cs b/MediaBrowser.LocalMetadata/Parsers/SeriesXmlParser.cs
index 7b7fb4751..2ddd84378 100644
--- a/MediaBrowser.LocalMetadata/Parsers/SeriesXmlParser.cs
+++ b/MediaBrowser.LocalMetadata/Parsers/SeriesXmlParser.cs
@@ -4,7 +4,9 @@ using MediaBrowser.Controller.Entities.TV;
using MediaBrowser.Controller.Library;
using MediaBrowser.Controller.Providers;
using MediaBrowser.Model.Entities;
+using MediaBrowser.Model.IO;
using MediaBrowser.Model.Logging;
+using MediaBrowser.Model.Xml;
namespace MediaBrowser.LocalMetadata.Parsers
{
@@ -14,15 +16,6 @@ namespace MediaBrowser.LocalMetadata.Parsers
public class SeriesXmlParser : BaseItemXmlParser<Series>
{
/// <summary>
- /// Initializes a new instance of the <see cref="BaseItemXmlParser{T}" /> class.
- /// </summary>
- /// <param name="logger">The logger.</param>
- public SeriesXmlParser(ILogger logger, IProviderManager providerManager)
- : base(logger, providerManager)
- {
- }
-
- /// <summary>
/// Fetches the data from XML node.
/// </summary>
/// <param name="reader">The reader.</param>
@@ -116,5 +109,9 @@ namespace MediaBrowser.LocalMetadata.Parsers
break;
}
}
+
+ public SeriesXmlParser(ILogger logger, IProviderManager providerManager, IXmlReaderSettingsFactory xmlReaderSettingsFactory, IFileSystem fileSystem) : base(logger, providerManager, xmlReaderSettingsFactory, fileSystem)
+ {
+ }
}
}
diff --git a/MediaBrowser.LocalMetadata/Providers/BoxSetXmlProvider.cs b/MediaBrowser.LocalMetadata/Providers/BoxSetXmlProvider.cs
index 3acb2b74c..88c51caaa 100644
--- a/MediaBrowser.LocalMetadata/Providers/BoxSetXmlProvider.cs
+++ b/MediaBrowser.LocalMetadata/Providers/BoxSetXmlProvider.cs
@@ -4,7 +4,10 @@ using MediaBrowser.LocalMetadata.Parsers;
using MediaBrowser.Model.Logging;
using System.IO;
using System.Threading;
-using CommonIO;
+using MediaBrowser.Common.IO;
+using MediaBrowser.Controller.IO;
+using MediaBrowser.Model.IO;
+using MediaBrowser.Model.Xml;
namespace MediaBrowser.LocalMetadata.Providers
{
@@ -15,17 +18,19 @@ namespace MediaBrowser.LocalMetadata.Providers
{
private readonly ILogger _logger;
private readonly IProviderManager _providerManager;
+ protected IXmlReaderSettingsFactory XmlReaderSettingsFactory { get; private set; }
- public BoxSetXmlProvider(IFileSystem fileSystem, ILogger logger, IProviderManager providerManager)
+ public BoxSetXmlProvider(IFileSystem fileSystem, ILogger logger, IProviderManager providerManager, IXmlReaderSettingsFactory xmlReaderSettingsFactory)
: base(fileSystem)
{
_logger = logger;
_providerManager = providerManager;
+ XmlReaderSettingsFactory = xmlReaderSettingsFactory;
}
protected override void Fetch(MetadataResult<BoxSet> result, string path, CancellationToken cancellationToken)
{
- new BoxSetXmlParser(_logger, _providerManager).Fetch(result, path, cancellationToken);
+ new BoxSetXmlParser(_logger, _providerManager, XmlReaderSettingsFactory, FileSystem).Fetch(result, path, cancellationToken);
}
protected override FileSystemMetadata GetXmlFile(ItemInfo info, IDirectoryService directoryService)
diff --git a/MediaBrowser.LocalMetadata/Providers/EpisodeXmlProvider.cs b/MediaBrowser.LocalMetadata/Providers/EpisodeXmlProvider.cs
index 493df8c6a..7e0f1707f 100644
--- a/MediaBrowser.LocalMetadata/Providers/EpisodeXmlProvider.cs
+++ b/MediaBrowser.LocalMetadata/Providers/EpisodeXmlProvider.cs
@@ -6,7 +6,10 @@ using MediaBrowser.Model.Logging;
using System.Collections.Generic;
using System.IO;
using System.Threading;
-using CommonIO;
+using MediaBrowser.Common.IO;
+using MediaBrowser.Controller.IO;
+using MediaBrowser.Model.IO;
+using MediaBrowser.Model.Xml;
namespace MediaBrowser.LocalMetadata.Providers
{
@@ -14,12 +17,14 @@ namespace MediaBrowser.LocalMetadata.Providers
{
private readonly ILogger _logger;
private readonly IProviderManager _providerManager;
+ private readonly IXmlReaderSettingsFactory _xmlSettings;
- public EpisodeXmlProvider(IFileSystem fileSystem, ILogger logger, IProviderManager providerManager)
+ public EpisodeXmlProvider(IFileSystem fileSystem, ILogger logger, IProviderManager providerManager, IXmlReaderSettingsFactory xmlSettings)
: base(fileSystem)
{
_logger = logger;
_providerManager = providerManager;
+ _xmlSettings = xmlSettings;
}
protected override void Fetch(MetadataResult<Episode> result, string path, CancellationToken cancellationToken)
@@ -27,7 +32,7 @@ namespace MediaBrowser.LocalMetadata.Providers
var images = new List<LocalImageInfo>();
var chapters = new List<ChapterInfo>();
- new EpisodeXmlParser(_logger, FileSystem, _providerManager).Fetch(result, images, path, cancellationToken);
+ new EpisodeXmlParser(_logger, FileSystem, _providerManager, _xmlSettings).Fetch(result, images, path, cancellationToken);
result.Images = images;
}
diff --git a/MediaBrowser.LocalMetadata/Providers/FolderXmlProvider.cs b/MediaBrowser.LocalMetadata/Providers/FolderXmlProvider.cs
index 7ac41e5cc..45cd8eb93 100644
--- a/MediaBrowser.LocalMetadata/Providers/FolderXmlProvider.cs
+++ b/MediaBrowser.LocalMetadata/Providers/FolderXmlProvider.cs
@@ -1,9 +1,13 @@
using System.IO;
using System.Threading;
-using CommonIO;
+using MediaBrowser.Common.IO;
+using MediaBrowser.Model.IO;
using MediaBrowser.Controller.Entities;
+using MediaBrowser.Controller.IO;
using MediaBrowser.Controller.Providers;
+using MediaBrowser.LocalMetadata.Parsers;
using MediaBrowser.Model.Logging;
+using MediaBrowser.Model.Xml;
namespace MediaBrowser.LocalMetadata.Providers
{
@@ -14,17 +18,19 @@ namespace MediaBrowser.LocalMetadata.Providers
{
private readonly ILogger _logger;
private readonly IProviderManager _providerManager;
+ protected IXmlReaderSettingsFactory XmlReaderSettingsFactory { get; private set; }
- public FolderXmlProvider(IFileSystem fileSystem, ILogger logger, IProviderManager providerManager)
+ public FolderXmlProvider(IFileSystem fileSystem, ILogger logger, IProviderManager providerManager, IXmlReaderSettingsFactory xmlReaderSettingsFactory)
: base(fileSystem)
{
_logger = logger;
_providerManager = providerManager;
+ XmlReaderSettingsFactory = xmlReaderSettingsFactory;
}
protected override void Fetch(MetadataResult<Folder> result, string path, CancellationToken cancellationToken)
{
- new BaseItemXmlParser<Folder>(_logger, _providerManager).Fetch(result, path, cancellationToken);
+ new BaseItemXmlParser<Folder>(_logger, _providerManager, XmlReaderSettingsFactory, FileSystem).Fetch(result, path, cancellationToken);
}
protected override FileSystemMetadata GetXmlFile(ItemInfo info, IDirectoryService directoryService)
diff --git a/MediaBrowser.LocalMetadata/Providers/GameSystemXmlProvider.cs b/MediaBrowser.LocalMetadata/Providers/GameSystemXmlProvider.cs
index 942befb83..8054b1204 100644
--- a/MediaBrowser.LocalMetadata/Providers/GameSystemXmlProvider.cs
+++ b/MediaBrowser.LocalMetadata/Providers/GameSystemXmlProvider.cs
@@ -1,10 +1,13 @@
using System.IO;
using System.Threading;
-using CommonIO;
+using MediaBrowser.Common.IO;
+using MediaBrowser.Model.IO;
using MediaBrowser.Controller.Entities;
+using MediaBrowser.Controller.IO;
using MediaBrowser.Controller.Providers;
using MediaBrowser.LocalMetadata.Parsers;
using MediaBrowser.Model.Logging;
+using MediaBrowser.Model.Xml;
namespace MediaBrowser.LocalMetadata.Providers
{
@@ -12,17 +15,19 @@ namespace MediaBrowser.LocalMetadata.Providers
{
private readonly ILogger _logger;
private readonly IProviderManager _providerManager;
+ private readonly IXmlReaderSettingsFactory _xmlSettings;
- public GameSystemXmlProvider(IFileSystem fileSystem, ILogger logger, IProviderManager providerManager)
+ public GameSystemXmlProvider(IFileSystem fileSystem, ILogger logger, IProviderManager providerManager, IXmlReaderSettingsFactory xmlSettings)
: base(fileSystem)
{
_logger = logger;
_providerManager = providerManager;
+ _xmlSettings = xmlSettings;
}
protected override void Fetch(MetadataResult<GameSystem> result, string path, CancellationToken cancellationToken)
{
- new GameSystemXmlParser(_logger, _providerManager).Fetch(result, path, cancellationToken);
+ new GameSystemXmlParser(_logger, _providerManager, _xmlSettings, FileSystem).Fetch(result, path, cancellationToken);
}
protected override FileSystemMetadata GetXmlFile(ItemInfo info, IDirectoryService directoryService)
diff --git a/MediaBrowser.LocalMetadata/Providers/GameXmlProvider.cs b/MediaBrowser.LocalMetadata/Providers/GameXmlProvider.cs
index c562df7fb..888eff416 100644
--- a/MediaBrowser.LocalMetadata/Providers/GameXmlProvider.cs
+++ b/MediaBrowser.LocalMetadata/Providers/GameXmlProvider.cs
@@ -4,7 +4,10 @@ using MediaBrowser.LocalMetadata.Parsers;
using MediaBrowser.Model.Logging;
using System.IO;
using System.Threading;
-using CommonIO;
+using MediaBrowser.Common.IO;
+using MediaBrowser.Controller.IO;
+using MediaBrowser.Model.IO;
+using MediaBrowser.Model.Xml;
namespace MediaBrowser.LocalMetadata.Providers
{
@@ -12,17 +15,19 @@ namespace MediaBrowser.LocalMetadata.Providers
{
private readonly ILogger _logger;
private readonly IProviderManager _providerManager;
+ private readonly IXmlReaderSettingsFactory _xmlSettings;
- public GameXmlProvider(IFileSystem fileSystem, ILogger logger, IProviderManager providerManager)
+ public GameXmlProvider(IFileSystem fileSystem, ILogger logger, IProviderManager providerManager, IXmlReaderSettingsFactory xmlSettings)
: base(fileSystem)
{
_logger = logger;
_providerManager = providerManager;
+ _xmlSettings = xmlSettings;
}
protected override void Fetch(MetadataResult<Game> result, string path, CancellationToken cancellationToken)
{
- new GameXmlParser(_logger, _providerManager).Fetch(result, path, cancellationToken);
+ new GameXmlParser(_logger, _providerManager, _xmlSettings, FileSystem).Fetch(result, path, cancellationToken);
}
protected override FileSystemMetadata GetXmlFile(ItemInfo info, IDirectoryService directoryService)
diff --git a/MediaBrowser.LocalMetadata/Providers/MovieXmlProvider.cs b/MediaBrowser.LocalMetadata/Providers/MovieXmlProvider.cs
index 333ea2823..0e59db75f 100644
--- a/MediaBrowser.LocalMetadata/Providers/MovieXmlProvider.cs
+++ b/MediaBrowser.LocalMetadata/Providers/MovieXmlProvider.cs
@@ -4,7 +4,10 @@ using MediaBrowser.LocalMetadata.Parsers;
using MediaBrowser.Model.Logging;
using System.IO;
using System.Threading;
-using CommonIO;
+using MediaBrowser.Common.IO;
+using MediaBrowser.Controller.IO;
+using MediaBrowser.Model.IO;
+using MediaBrowser.Model.Xml;
namespace MediaBrowser.LocalMetadata.Providers
{
@@ -12,17 +15,19 @@ namespace MediaBrowser.LocalMetadata.Providers
{
private readonly ILogger _logger;
private readonly IProviderManager _providerManager;
+ protected IXmlReaderSettingsFactory XmlReaderSettingsFactory { get; private set; }
- public MovieXmlProvider(IFileSystem fileSystem, ILogger logger, IProviderManager providerManager)
+ public MovieXmlProvider(IFileSystem fileSystem, ILogger logger, IProviderManager providerManager, IXmlReaderSettingsFactory xmlReaderSettingsFactory)
: base(fileSystem)
{
_logger = logger;
_providerManager = providerManager;
+ XmlReaderSettingsFactory = xmlReaderSettingsFactory;
}
protected override void Fetch(MetadataResult<Movie> result, string path, CancellationToken cancellationToken)
{
- new MovieXmlParser(_logger, _providerManager).Fetch(result, path, cancellationToken);
+ new MovieXmlParser(_logger, _providerManager, XmlReaderSettingsFactory, FileSystem).Fetch(result, path, cancellationToken);
}
protected override FileSystemMetadata GetXmlFile(ItemInfo info, IDirectoryService directoryService)
diff --git a/MediaBrowser.LocalMetadata/Providers/MusicVideoXmlProvider.cs b/MediaBrowser.LocalMetadata/Providers/MusicVideoXmlProvider.cs
index 49d8c09cc..e0bbb119f 100644
--- a/MediaBrowser.LocalMetadata/Providers/MusicVideoXmlProvider.cs
+++ b/MediaBrowser.LocalMetadata/Providers/MusicVideoXmlProvider.cs
@@ -1,9 +1,12 @@
using System.Threading;
-using CommonIO;
+using MediaBrowser.Common.IO;
+using MediaBrowser.Model.IO;
using MediaBrowser.Controller.Entities;
+using MediaBrowser.Controller.IO;
using MediaBrowser.Controller.Providers;
using MediaBrowser.LocalMetadata.Parsers;
using MediaBrowser.Model.Logging;
+using MediaBrowser.Model.Xml;
namespace MediaBrowser.LocalMetadata.Providers
{
@@ -11,17 +14,19 @@ namespace MediaBrowser.LocalMetadata.Providers
{
private readonly ILogger _logger;
private readonly IProviderManager _providerManager;
+ protected IXmlReaderSettingsFactory XmlReaderSettingsFactory { get; private set; }
- public MusicVideoXmlProvider(IFileSystem fileSystem, ILogger logger, IProviderManager providerManager)
+ public MusicVideoXmlProvider(IFileSystem fileSystem, ILogger logger, IProviderManager providerManager, IXmlReaderSettingsFactory xmlReaderSettingsFactory)
: base(fileSystem)
{
_logger = logger;
_providerManager = providerManager;
+ XmlReaderSettingsFactory = xmlReaderSettingsFactory;
}
protected override void Fetch(MetadataResult<MusicVideo> result, string path, CancellationToken cancellationToken)
{
- new MusicVideoXmlParser(_logger, _providerManager).Fetch(result, path, cancellationToken);
+ new MusicVideoXmlParser(_logger, _providerManager, XmlReaderSettingsFactory, FileSystem).Fetch(result, path, cancellationToken);
}
protected override FileSystemMetadata GetXmlFile(ItemInfo info, IDirectoryService directoryService)
diff --git a/MediaBrowser.LocalMetadata/Providers/PersonXmlProvider.cs b/MediaBrowser.LocalMetadata/Providers/PersonXmlProvider.cs
deleted file mode 100644
index 2ccb8968b..000000000
--- a/MediaBrowser.LocalMetadata/Providers/PersonXmlProvider.cs
+++ /dev/null
@@ -1,32 +0,0 @@
-using System.IO;
-using System.Threading;
-using CommonIO;
-using MediaBrowser.Controller.Entities;
-using MediaBrowser.Controller.Providers;
-using MediaBrowser.Model.Logging;
-
-namespace MediaBrowser.LocalMetadata.Providers
-{
- public class PersonXmlProvider : BaseXmlProvider<Person>
- {
- private readonly ILogger _logger;
- private readonly IProviderManager _providerManager;
-
- public PersonXmlProvider(IFileSystem fileSystem, ILogger logger, IProviderManager providerManager)
- : base(fileSystem)
- {
- _logger = logger;
- _providerManager = providerManager;
- }
-
- protected override void Fetch(MetadataResult<Person> result, string path, CancellationToken cancellationToken)
- {
- new BaseItemXmlParser<Person>(_logger, _providerManager).Fetch(result, path, cancellationToken);
- }
-
- protected override FileSystemMetadata GetXmlFile(ItemInfo info, IDirectoryService directoryService)
- {
- return directoryService.GetFile(Path.Combine(info.Path, "person.xml"));
- }
- }
-}
diff --git a/MediaBrowser.LocalMetadata/Providers/PlaylistXmlProvider.cs b/MediaBrowser.LocalMetadata/Providers/PlaylistXmlProvider.cs
index 149a3142d..cd839f9cc 100644
--- a/MediaBrowser.LocalMetadata/Providers/PlaylistXmlProvider.cs
+++ b/MediaBrowser.LocalMetadata/Providers/PlaylistXmlProvider.cs
@@ -4,7 +4,10 @@ using MediaBrowser.LocalMetadata.Parsers;
using MediaBrowser.Model.Logging;
using System.IO;
using System.Threading;
-using CommonIO;
+using MediaBrowser.Common.IO;
+using MediaBrowser.Controller.IO;
+using MediaBrowser.Model.IO;
+using MediaBrowser.Model.Xml;
namespace MediaBrowser.LocalMetadata.Providers
{
@@ -12,17 +15,19 @@ namespace MediaBrowser.LocalMetadata.Providers
{
private readonly ILogger _logger;
private readonly IProviderManager _providerManager;
+ protected IXmlReaderSettingsFactory XmlReaderSettingsFactory { get; private set; }
- public PlaylistXmlProvider(IFileSystem fileSystem, ILogger logger, IProviderManager providerManager)
+ public PlaylistXmlProvider(IFileSystem fileSystem, ILogger logger, IProviderManager providerManager, IXmlReaderSettingsFactory xmlReaderSettingsFactory)
: base(fileSystem)
{
_logger = logger;
_providerManager = providerManager;
+ XmlReaderSettingsFactory = xmlReaderSettingsFactory;
}
protected override void Fetch(MetadataResult<Playlist> result, string path, CancellationToken cancellationToken)
{
- new PlaylistXmlParser(_logger, _providerManager).Fetch(result, path, cancellationToken);
+ new PlaylistXmlParser(_logger, _providerManager, XmlReaderSettingsFactory, FileSystem).Fetch(result, path, cancellationToken);
}
protected override FileSystemMetadata GetXmlFile(ItemInfo info, IDirectoryService directoryService)
diff --git a/MediaBrowser.LocalMetadata/Providers/SeriesXmlProvider.cs b/MediaBrowser.LocalMetadata/Providers/SeriesXmlProvider.cs
index 26d3c7539..ce006ef38 100644
--- a/MediaBrowser.LocalMetadata/Providers/SeriesXmlProvider.cs
+++ b/MediaBrowser.LocalMetadata/Providers/SeriesXmlProvider.cs
@@ -1,10 +1,13 @@
using System.IO;
using System.Threading;
-using CommonIO;
+using MediaBrowser.Common.IO;
+using MediaBrowser.Model.IO;
using MediaBrowser.Controller.Entities.TV;
+using MediaBrowser.Controller.IO;
using MediaBrowser.Controller.Providers;
using MediaBrowser.LocalMetadata.Parsers;
using MediaBrowser.Model.Logging;
+using MediaBrowser.Model.Xml;
namespace MediaBrowser.LocalMetadata.Providers
{
@@ -15,17 +18,19 @@ namespace MediaBrowser.LocalMetadata.Providers
{
private readonly ILogger _logger;
private readonly IProviderManager _providerManager;
+ protected IXmlReaderSettingsFactory XmlReaderSettingsFactory { get; private set; }
- public SeriesXmlProvider(IFileSystem fileSystem, ILogger logger, IProviderManager providerManager)
+ public SeriesXmlProvider(IFileSystem fileSystem, ILogger logger, IProviderManager providerManager, IXmlReaderSettingsFactory xmlReaderSettingsFactory)
: base(fileSystem)
{
_logger = logger;
_providerManager = providerManager;
+ XmlReaderSettingsFactory = xmlReaderSettingsFactory;
}
protected override void Fetch(MetadataResult<Series> result, string path, CancellationToken cancellationToken)
{
- new SeriesXmlParser(_logger, _providerManager).Fetch(result, path, cancellationToken);
+ new SeriesXmlParser(_logger, _providerManager, XmlReaderSettingsFactory, FileSystem).Fetch(result, path, cancellationToken);
}
protected override FileSystemMetadata GetXmlFile(ItemInfo info, IDirectoryService directoryService)
diff --git a/MediaBrowser.LocalMetadata/Providers/VideoXmlProvider.cs b/MediaBrowser.LocalMetadata/Providers/VideoXmlProvider.cs
index 50f3bcda4..4a7149657 100644
--- a/MediaBrowser.LocalMetadata/Providers/VideoXmlProvider.cs
+++ b/MediaBrowser.LocalMetadata/Providers/VideoXmlProvider.cs
@@ -3,7 +3,10 @@ using MediaBrowser.Controller.Providers;
using MediaBrowser.LocalMetadata.Parsers;
using MediaBrowser.Model.Logging;
using System.Threading;
-using CommonIO;
+using MediaBrowser.Common.IO;
+using MediaBrowser.Controller.IO;
+using MediaBrowser.Model.IO;
+using MediaBrowser.Model.Xml;
namespace MediaBrowser.LocalMetadata.Providers
{
@@ -11,17 +14,19 @@ namespace MediaBrowser.LocalMetadata.Providers
{
private readonly ILogger _logger;
private readonly IProviderManager _providerManager;
+ protected IXmlReaderSettingsFactory XmlReaderSettingsFactory { get; private set; }
- public VideoXmlProvider(IFileSystem fileSystem, ILogger logger, IProviderManager providerManager)
+ public VideoXmlProvider(IFileSystem fileSystem, ILogger logger, IProviderManager providerManager, IXmlReaderSettingsFactory xmlReaderSettingsFactory)
: base(fileSystem)
{
_logger = logger;
_providerManager = providerManager;
+ XmlReaderSettingsFactory = xmlReaderSettingsFactory;
}
protected override void Fetch(MetadataResult<Video> result, string path, CancellationToken cancellationToken)
{
- new VideoXmlParser(_logger, _providerManager).Fetch(result, path, cancellationToken);
+ new VideoXmlParser(_logger, _providerManager, XmlReaderSettingsFactory, FileSystem).Fetch(result, path, cancellationToken);
}
protected override FileSystemMetadata GetXmlFile(ItemInfo info, IDirectoryService directoryService)
diff --git a/MediaBrowser.LocalMetadata/Savers/BaseXmlSaver.cs b/MediaBrowser.LocalMetadata/Savers/BaseXmlSaver.cs
new file mode 100644
index 000000000..b52bae2ce
--- /dev/null
+++ b/MediaBrowser.LocalMetadata/Savers/BaseXmlSaver.cs
@@ -0,0 +1,752 @@
+using System;
+using System.Collections.Generic;
+using System.Globalization;
+using System.IO;
+using System.Linq;
+using System.Security;
+using System.Text;
+using System.Threading;
+using System.Xml;
+using MediaBrowser.Common.Extensions;
+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;
+using MediaBrowser.Controller.Persistence;
+using MediaBrowser.Controller.Playlists;
+using MediaBrowser.Model.Configuration;
+using MediaBrowser.Model.Entities;
+using MediaBrowser.Model.Extensions;
+using MediaBrowser.Model.IO;
+using MediaBrowser.Model.Logging;
+using MediaBrowser.Model.Xml;
+
+namespace MediaBrowser.LocalMetadata.Savers
+{
+ public abstract class BaseXmlSaver : IMetadataFileSaver
+ {
+ private static readonly CultureInfo UsCulture = new CultureInfo("en-US");
+
+ private static readonly Dictionary<string, string> CommonTags = new[] {
+
+ "Added",
+ "AspectRatio",
+ "AudioDbAlbumId",
+ "AudioDbArtistId",
+ "AwardSummary",
+ "BirthDate",
+ "Budget",
+
+ // Deprecated. No longer saving in this field.
+ "certification",
+
+ "Chapters",
+ "ContentRating",
+ "Countries",
+ "CustomRating",
+ "CriticRating",
+ "CriticRatingSummary",
+ "DeathDate",
+ "DisplayOrder",
+ "EndDate",
+ "Genres",
+ "Genre",
+ "GamesDbId",
+
+ // Deprecated. No longer saving in this field.
+ "IMDB_ID",
+
+ "IMDB",
+
+ // Deprecated. No longer saving in this field.
+ "IMDbId",
+
+ "Language",
+ "LocalTitle",
+ "OriginalTitle",
+ "LockData",
+ "LockedFields",
+ "Format3D",
+ "Metascore",
+
+ // Deprecated. No longer saving in this field.
+ "MPAARating",
+
+ "MPAADescription",
+
+ "MusicBrainzArtistId",
+ "MusicBrainzAlbumArtistId",
+ "MusicBrainzAlbumId",
+ "MusicBrainzReleaseGroupId",
+
+ // Deprecated. No longer saving in this field.
+ "MusicbrainzId",
+
+ "Overview",
+ "ShortOverview",
+ "Persons",
+ "PlotKeywords",
+ "PremiereDate",
+ "ProductionYear",
+ "Rating",
+ "Revenue",
+ "RottenTomatoesId",
+ "RunningTime",
+
+ // Deprecated. No longer saving in this field.
+ "Runtime",
+
+ "SortTitle",
+ "Studios",
+ "Tags",
+
+ // Deprecated. No longer saving in this field.
+ "TagLine",
+
+ "Taglines",
+ "TMDbCollectionId",
+ "TMDbId",
+
+ // Deprecated. No longer saving in this field.
+ "Trailer",
+
+ "Trailers",
+ "TVcomId",
+ "TvDbId",
+ "Type",
+ "TVRageId",
+ "VoteCount",
+ "Website",
+ "Zap2ItId",
+ "CollectionItems",
+ "PlaylistItems",
+ "Shares"
+
+ }.ToDictionary(i => i, StringComparer.OrdinalIgnoreCase);
+
+ public BaseXmlSaver(IFileSystem fileSystem, IServerConfigurationManager configurationManager, ILibraryManager libraryManager, IUserManager userManager, IUserDataManager userDataManager, ILogger logger, IXmlReaderSettingsFactory xmlReaderSettingsFactory)
+ {
+ FileSystem = fileSystem;
+ ConfigurationManager = configurationManager;
+ LibraryManager = libraryManager;
+ UserManager = userManager;
+ UserDataManager = userDataManager;
+ Logger = logger;
+ XmlReaderSettingsFactory = xmlReaderSettingsFactory;
+ }
+
+ protected IFileSystem FileSystem { get; private set; }
+ protected IServerConfigurationManager ConfigurationManager { get; private set; }
+ protected ILibraryManager LibraryManager { get; private set; }
+ protected IUserManager UserManager { get; private set; }
+ protected IUserDataManager UserDataManager { get; private set; }
+ protected ILogger Logger { get; private set; }
+ protected IXmlReaderSettingsFactory XmlReaderSettingsFactory { get; private set; }
+
+ protected ItemUpdateType MinimumUpdateType
+ {
+ get
+ {
+ return ItemUpdateType.MetadataDownload;
+ }
+ }
+
+ public string Name
+ {
+ get
+ {
+ return XmlProviderUtils.Name;
+ }
+ }
+
+ public string GetSavePath(IHasMetadata item)
+ {
+ return GetLocalSavePath(item);
+ }
+
+ /// <summary>
+ /// Gets the save path.
+ /// </summary>
+ /// <param name="item">The item.</param>
+ /// <returns>System.String.</returns>
+ protected abstract string GetLocalSavePath(IHasMetadata item);
+
+ /// <summary>
+ /// Gets the name of the root element.
+ /// </summary>
+ /// <param name="item">The item.</param>
+ /// <returns>System.String.</returns>
+ protected virtual string GetRootElementName(IHasMetadata item)
+ {
+ return "Item";
+ }
+
+ /// <summary>
+ /// Determines whether [is enabled for] [the specified item].
+ /// </summary>
+ /// <param name="item">The item.</param>
+ /// <param name="updateType">Type of the update.</param>
+ /// <returns><c>true</c> if [is enabled for] [the specified item]; otherwise, <c>false</c>.</returns>
+ public abstract bool IsEnabledFor(IHasMetadata item, ItemUpdateType updateType);
+
+ protected virtual List<string> GetTagsUsed()
+ {
+ return new List<string>();
+ }
+
+ public void Save(IHasMetadata item, CancellationToken cancellationToken)
+ {
+ var path = GetSavePath(item);
+
+ using (var memoryStream = new MemoryStream())
+ {
+ Save(item, memoryStream, path);
+
+ memoryStream.Position = 0;
+
+ cancellationToken.ThrowIfCancellationRequested();
+
+ SaveToFile(memoryStream, path);
+ }
+ }
+
+ private void SaveToFile(Stream stream, string path)
+ {
+ FileSystem.CreateDirectory(Path.GetDirectoryName(path));
+
+ var file = FileSystem.GetFileInfo(path);
+
+ var wasHidden = false;
+
+ // This will fail if the file is hidden
+ if (file.Exists)
+ {
+ if (file.IsHidden)
+ {
+ FileSystem.SetHidden(path, false);
+ wasHidden = true;
+ }
+ if (file.IsReadOnly)
+ {
+ FileSystem.SetReadOnly(path, false);
+ }
+ }
+
+ using (var filestream = FileSystem.GetFileStream(path, FileOpenMode.Create, FileAccessMode.Write, FileShareMode.Read))
+ {
+ stream.CopyTo(filestream);
+ }
+
+ if (wasHidden || ConfigurationManager.Configuration.SaveMetadataHidden)
+ {
+ FileSystem.SetHidden(path, true);
+ }
+ }
+
+ private void Save(IHasMetadata item, Stream stream, string xmlPath)
+ {
+ var settings = new XmlWriterSettings
+ {
+ Indent = true,
+ Encoding = Encoding.UTF8,
+ CloseOutput = false
+ };
+
+ using (XmlWriter writer = XmlWriter.Create(stream, settings))
+ {
+ var root = GetRootElementName(item);
+
+ writer.WriteStartDocument(true);
+
+ writer.WriteStartElement(root);
+
+ var baseItem = item as BaseItem;
+
+ if (baseItem != null)
+ {
+ AddCommonNodes(baseItem, writer, LibraryManager, UserManager, UserDataManager, FileSystem, ConfigurationManager);
+ }
+
+ WriteCustomElements(item, writer);
+
+ var tagsUsed = GetTagsUsed();
+
+ try
+ {
+ AddCustomTags(xmlPath, tagsUsed, writer, Logger, FileSystem);
+ }
+ catch (FileNotFoundException)
+ {
+
+ }
+ catch (IOException)
+ {
+
+ }
+ catch (XmlException ex)
+ {
+ Logger.ErrorException("Error reading existng xml", ex);
+ }
+
+ writer.WriteEndElement();
+
+ writer.WriteEndDocument();
+ }
+ }
+
+ protected abstract void WriteCustomElements(IHasMetadata item, XmlWriter writer);
+
+ public const string DateAddedFormat = "yyyy-MM-dd HH:mm:ss";
+
+ /// <summary>
+ /// Adds the common nodes.
+ /// </summary>
+ /// <returns>Task.</returns>
+ public static void AddCommonNodes(BaseItem item, XmlWriter writer, ILibraryManager libraryManager, IUserManager userManager, IUserDataManager userDataRepo, IFileSystem fileSystem, IServerConfigurationManager config)
+ {
+ var writtenProviderIds = new HashSet<string>(StringComparer.OrdinalIgnoreCase);
+
+ if (!string.IsNullOrEmpty(item.OfficialRating))
+ {
+ writer.WriteElementString("ContentRating", item.OfficialRating);
+ }
+
+ if (!string.IsNullOrEmpty(item.OfficialRatingDescription))
+ {
+ writer.WriteElementString("MPAADescription", item.OfficialRatingDescription);
+ }
+
+ writer.WriteElementString("Added", item.DateCreated.ToLocalTime().ToString("G"));
+
+ writer.WriteElementString("LockData", item.IsLocked.ToString().ToLower());
+
+ if (item.LockedFields.Count > 0)
+ {
+ writer.WriteElementString("LockedFields", string.Join("|", item.LockedFields.Select(i => i.ToString()).ToArray()));
+ }
+
+ if (!string.IsNullOrEmpty(item.DisplayMediaType))
+ {
+ writer.WriteElementString("Type", item.DisplayMediaType);
+ }
+
+ if (item.CriticRating.HasValue)
+ {
+ writer.WriteElementString("CriticRating", item.CriticRating.Value.ToString(UsCulture));
+ }
+
+ if (!string.IsNullOrEmpty(item.CriticRatingSummary))
+ {
+ writer.WriteElementString("CriticRatingSummary", item.CriticRatingSummary);
+ }
+
+ if (!string.IsNullOrEmpty(item.Overview))
+ {
+ writer.WriteElementString("Overview", item.Overview);
+ }
+
+ if (!string.IsNullOrEmpty(item.OriginalTitle))
+ {
+ writer.WriteElementString("OriginalTitle", item.OriginalTitle);
+ }
+ if (!string.IsNullOrEmpty(item.ShortOverview))
+ {
+ writer.WriteElementString("ShortOverview", item.ShortOverview);
+ }
+ if (!string.IsNullOrEmpty(item.CustomRating))
+ {
+ writer.WriteElementString("CustomRating", item.CustomRating);
+ }
+
+ if (!string.IsNullOrEmpty(item.Name) && !(item is Episode))
+ {
+ writer.WriteElementString("LocalTitle", item.Name);
+ }
+
+ if (!string.IsNullOrEmpty(item.ForcedSortName))
+ {
+ writer.WriteElementString("SortTitle", item.ForcedSortName);
+ }
+
+ if (item.PremiereDate.HasValue)
+ {
+ if (item is Person)
+ {
+ writer.WriteElementString("BirthDate", item.PremiereDate.Value.ToLocalTime().ToString("yyyy-MM-dd"));
+ }
+ else if (!(item is Episode))
+ {
+ writer.WriteElementString("PremiereDate", item.PremiereDate.Value.ToLocalTime().ToString("yyyy-MM-dd"));
+ }
+ }
+
+ if (item.EndDate.HasValue)
+ {
+ if (item is Person)
+ {
+ writer.WriteElementString("DeathDate", item.EndDate.Value.ToLocalTime().ToString("yyyy-MM-dd"));
+ }
+ else if (!(item is Episode))
+ {
+ writer.WriteElementString("EndDate", item.EndDate.Value.ToLocalTime().ToString("yyyy-MM-dd"));
+ }
+ }
+
+ var hasTrailers = item as IHasTrailers;
+ if (hasTrailers != null)
+ {
+ if (hasTrailers.RemoteTrailers.Count > 0)
+ {
+ writer.WriteStartElement("Trailers");
+
+ foreach (var trailer in hasTrailers.RemoteTrailers)
+ {
+ writer.WriteElementString("Trailer", trailer.Url);
+ }
+
+ writer.WriteEndElement();
+ }
+ }
+
+ if (item.ProductionLocations.Count > 0)
+ {
+ writer.WriteStartElement("Countries");
+
+ foreach (var name in item.ProductionLocations)
+ {
+ writer.WriteElementString("Country", name);
+ }
+
+ writer.WriteEndElement();
+ }
+
+ var hasDisplayOrder = item as IHasDisplayOrder;
+ if (hasDisplayOrder != null && !string.IsNullOrEmpty(hasDisplayOrder.DisplayOrder))
+ {
+ writer.WriteElementString("DisplayOrder", hasDisplayOrder.DisplayOrder);
+ }
+
+ var hasMetascore = item as IHasMetascore;
+ if (hasMetascore != null && hasMetascore.Metascore.HasValue)
+ {
+ writer.WriteElementString("Metascore", hasMetascore.Metascore.Value.ToString(UsCulture));
+ }
+
+ var hasAwards = item as IHasAwards;
+ if (hasAwards != null && !string.IsNullOrEmpty(hasAwards.AwardSummary))
+ {
+ writer.WriteElementString("AwardSummary", hasAwards.AwardSummary);
+ }
+
+ var hasBudget = item as IHasBudget;
+ if (hasBudget != null)
+ {
+ if (hasBudget.Budget.HasValue)
+ {
+ writer.WriteElementString("Budget", hasBudget.Budget.Value.ToString(UsCulture));
+ }
+
+ if (hasBudget.Revenue.HasValue)
+ {
+ writer.WriteElementString("Revenue", hasBudget.Revenue.Value.ToString(UsCulture));
+ }
+ }
+
+ if (item.CommunityRating.HasValue)
+ {
+ writer.WriteElementString("Rating", item.CommunityRating.Value.ToString(UsCulture));
+ }
+ if (item.VoteCount.HasValue)
+ {
+ writer.WriteElementString("VoteCount", item.VoteCount.Value.ToString(UsCulture));
+ }
+
+ if (item.ProductionYear.HasValue && !(item is Person))
+ {
+ writer.WriteElementString("ProductionYear", item.ProductionYear.Value.ToString(UsCulture));
+ }
+
+ if (!string.IsNullOrEmpty(item.HomePageUrl))
+ {
+ writer.WriteElementString("Website", item.HomePageUrl);
+ }
+
+ var hasAspectRatio = item as IHasAspectRatio;
+ if (hasAspectRatio != null)
+ {
+ if (!string.IsNullOrEmpty(hasAspectRatio.AspectRatio))
+ {
+ writer.WriteElementString("AspectRatio", hasAspectRatio.AspectRatio);
+ }
+ }
+
+ if (!string.IsNullOrEmpty(item.PreferredMetadataLanguage))
+ {
+ writer.WriteElementString("Language", item.PreferredMetadataLanguage);
+ }
+ if (!string.IsNullOrEmpty(item.PreferredMetadataCountryCode))
+ {
+ writer.WriteElementString("CountryCode", item.PreferredMetadataCountryCode);
+ }
+
+ // Use original runtime here, actual file runtime later in MediaInfo
+ var runTimeTicks = item.RunTimeTicks;
+
+ if (runTimeTicks.HasValue)
+ {
+ var timespan = TimeSpan.FromTicks(runTimeTicks.Value);
+
+ writer.WriteElementString("RunningTime", Convert.ToInt32(timespan.TotalMinutes).ToString(UsCulture));
+ }
+
+ if (item.ProviderIds != null)
+ {
+ foreach (var providerKey in item.ProviderIds.Keys)
+ {
+ var providerId = item.ProviderIds[providerKey];
+ if (!string.IsNullOrEmpty(providerId))
+ {
+ writer.WriteElementString(providerKey + "Id", providerId);
+ }
+ }
+ }
+
+ if (!string.IsNullOrWhiteSpace(item.Tagline))
+ {
+ writer.WriteStartElement("Taglines");
+ writer.WriteElementString("Tagline", item.Tagline);
+ writer.WriteEndElement();
+ }
+
+ if (item.Genres.Count > 0)
+ {
+ writer.WriteStartElement("Genres");
+
+ foreach (var genre in item.Genres)
+ {
+ writer.WriteElementString("Genre", genre);
+ }
+
+ writer.WriteEndElement();
+ }
+
+ if (item.Studios.Count > 0)
+ {
+ writer.WriteStartElement("Studios");
+
+ foreach (var studio in item.Studios)
+ {
+ writer.WriteElementString("Studio", studio);
+ }
+
+ writer.WriteEndElement();
+ }
+
+ if (item.Tags.Count > 0)
+ {
+ writer.WriteStartElement("Tags");
+
+ foreach (var tag in item.Tags)
+ {
+ writer.WriteElementString("Tag", tag);
+ }
+
+ writer.WriteEndElement();
+ }
+
+ if (item.Keywords.Count > 0)
+ {
+ writer.WriteStartElement("PlotKeywords");
+
+ foreach (var tag in item.Keywords)
+ {
+ writer.WriteElementString("PlotKeyword", tag);
+ }
+
+ writer.WriteEndElement();
+ }
+
+ var people = libraryManager.GetPeople(item);
+
+ if (people.Count > 0)
+ {
+ writer.WriteStartElement("Persons");
+
+ foreach (var person in people)
+ {
+ writer.WriteStartElement("Person");
+ writer.WriteElementString("Name", person.Name);
+ writer.WriteElementString("Type", person.Type);
+ writer.WriteElementString("Role", person.Role);
+
+ if (person.SortOrder.HasValue)
+ {
+ writer.WriteElementString("SortOrder", person.SortOrder.Value.ToString(UsCulture));
+ }
+
+ writer.WriteEndElement();
+ }
+
+ writer.WriteEndElement();
+ }
+
+ var boxset = item as BoxSet;
+ if (boxset != null)
+ {
+ AddLinkedChildren(boxset, writer, "CollectionItems", "CollectionItem");
+ }
+
+ var playlist = item as Playlist;
+ if (playlist != null)
+ {
+ AddLinkedChildren(playlist, writer, "PlaylistItems", "PlaylistItem");
+ }
+
+ var hasShares = item as IHasShares;
+ if (hasShares != null)
+ {
+ AddShares(hasShares, writer);
+ }
+
+ AddMediaInfo(item, writer);
+ }
+
+ public static void AddShares(IHasShares item, XmlWriter writer)
+ {
+ writer.WriteStartElement("Shares");
+
+ foreach (var share in item.Shares)
+ {
+ writer.WriteStartElement("Share");
+
+ writer.WriteElementString("UserId", share.UserId);
+ writer.WriteElementString("CanEdit", share.CanEdit.ToString().ToLower());
+
+ writer.WriteEndElement();
+ }
+
+ writer.WriteEndElement();
+ }
+
+ /// <summary>
+ /// Appends the media info.
+ /// </summary>
+ /// <typeparam name="T"></typeparam>
+ public static void AddMediaInfo<T>(T item, XmlWriter writer)
+ where T : BaseItem
+ {
+ var video = item as Video;
+
+ if (video != null)
+ {
+ if (video.Video3DFormat.HasValue)
+ {
+ switch (video.Video3DFormat.Value)
+ {
+ case Video3DFormat.FullSideBySide:
+ writer.WriteElementString("Format3D", "FSBS");
+ break;
+ case Video3DFormat.FullTopAndBottom:
+ writer.WriteElementString("Format3D", "FTAB");
+ break;
+ case Video3DFormat.HalfSideBySide:
+ writer.WriteElementString("Format3D", "HSBS");
+ break;
+ case Video3DFormat.HalfTopAndBottom:
+ writer.WriteElementString("Format3D", "HTAB");
+ break;
+ case Video3DFormat.MVC:
+ writer.WriteElementString("Format3D", "MVC");
+ break;
+ }
+ }
+ }
+ }
+
+ public static void AddLinkedChildren(Folder item, XmlWriter writer, string pluralNodeName, string singularNodeName)
+ {
+ var items = item.LinkedChildren
+ .Where(i => i.Type == LinkedChildType.Manual)
+ .ToList();
+
+ if (items.Count == 0)
+ {
+ return;
+ }
+
+ writer.WriteStartElement(pluralNodeName);
+
+ foreach (var link in items)
+ {
+ if (!string.IsNullOrWhiteSpace(link.Path))
+ {
+ writer.WriteStartElement(singularNodeName);
+ writer.WriteElementString("Path", link.Path);
+ writer.WriteEndElement();
+ }
+ }
+
+ writer.WriteEndElement();
+ }
+
+ private static bool IsPersonType(PersonInfo person, string type)
+ {
+ return string.Equals(person.Type, type, StringComparison.OrdinalIgnoreCase) || string.Equals(person.Role, type, StringComparison.OrdinalIgnoreCase);
+ }
+
+ private void AddCustomTags(string path, List<string> xmlTagsUsed, XmlWriter writer, ILogger logger, IFileSystem fileSystem)
+ {
+ var settings = XmlReaderSettingsFactory.Create(false);
+
+ settings.CheckCharacters = false;
+ settings.IgnoreProcessingInstructions = true;
+ settings.IgnoreComments = true;
+
+ using (var fileStream = fileSystem.OpenRead(path))
+ {
+ using (var streamReader = new StreamReader(fileStream, Encoding.UTF8))
+ {
+ // Use XmlReader for best performance
+ using (var reader = XmlReader.Create(streamReader, settings))
+ {
+ try
+ {
+ reader.MoveToContent();
+ }
+ catch (Exception ex)
+ {
+ logger.ErrorException("Error reading existing xml tags from {0}.", ex, path);
+ return;
+ }
+
+ reader.Read();
+
+ // Loop through each element
+ while (!reader.EOF && reader.ReadState == ReadState.Interactive)
+ {
+ if (reader.NodeType == XmlNodeType.Element)
+ {
+ var name = reader.Name;
+
+ if (!CommonTags.ContainsKey(name) && !xmlTagsUsed.Contains(name, StringComparer.OrdinalIgnoreCase))
+ {
+ writer.WriteNode(reader, false);
+ }
+ else
+ {
+ reader.Skip();
+ }
+ }
+ else
+ {
+ reader.Read();
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+}
diff --git a/MediaBrowser.LocalMetadata/Savers/BoxSetXmlSaver.cs b/MediaBrowser.LocalMetadata/Savers/BoxSetXmlSaver.cs
index b307ded97..8167f6002 100644
--- a/MediaBrowser.LocalMetadata/Savers/BoxSetXmlSaver.cs
+++ b/MediaBrowser.LocalMetadata/Savers/BoxSetXmlSaver.cs
@@ -6,38 +6,18 @@ using System.Collections.Generic;
using System.IO;
using System.Text;
using System.Threading;
-using CommonIO;
+using System.Xml;
+using MediaBrowser.Common.IO;
+using MediaBrowser.Controller.IO;
+using MediaBrowser.Model.IO;
+using MediaBrowser.Model.Logging;
+using MediaBrowser.Model.Xml;
namespace MediaBrowser.LocalMetadata.Savers
{
- public class BoxSetXmlSaver : IMetadataFileSaver
+ public class BoxSetXmlSaver : BaseXmlSaver
{
- public string Name
- {
- get
- {
- return XmlProviderUtils.Name;
- }
- }
-
- private readonly IServerConfigurationManager _config;
- private readonly ILibraryManager _libraryManager;
- private readonly IFileSystem _fileSystem;
-
- public BoxSetXmlSaver(IServerConfigurationManager config, ILibraryManager libraryManager, IFileSystem fileSystem)
- {
- _config = config;
- _libraryManager = libraryManager;
- _fileSystem = fileSystem;
- }
-
- /// <summary>
- /// Determines whether [is enabled for] [the specified item].
- /// </summary>
- /// <param name="item">The item.</param>
- /// <param name="updateType">Type of the update.</param>
- /// <returns><c>true</c> if [is enabled for] [the specified item]; otherwise, <c>false</c>.</returns>
- public bool IsEnabledFor(IHasMetadata item, ItemUpdateType updateType)
+ public override bool IsEnabledFor(IHasMetadata item, ItemUpdateType updateType)
{
if (!item.SupportsLocalMetadata)
{
@@ -47,35 +27,17 @@ namespace MediaBrowser.LocalMetadata.Savers
return item is BoxSet && updateType >= ItemUpdateType.MetadataDownload;
}
- /// <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(IHasMetadata item, CancellationToken cancellationToken)
+ protected override void WriteCustomElements(IHasMetadata item, XmlWriter writer)
{
- var builder = new StringBuilder();
-
- builder.Append("<Item>");
-
- XmlSaverHelpers.AddCommonNodes((BoxSet)item, _libraryManager, builder);
-
- builder.Append("</Item>");
-
- var xmlFilePath = GetSavePath(item);
-
- XmlSaverHelpers.Save(builder, xmlFilePath, new List<string>(), _config, _fileSystem);
}
- /// <summary>
- /// Gets the save path.
- /// </summary>
- /// <param name="item">The item.</param>
- /// <returns>System.String.</returns>
- public string GetSavePath(IHasMetadata item)
+ protected override string GetLocalSavePath(IHasMetadata item)
{
return Path.Combine(item.Path, "collection.xml");
}
+
+ public BoxSetXmlSaver(IFileSystem fileSystem, IServerConfigurationManager configurationManager, ILibraryManager libraryManager, IUserManager userManager, IUserDataManager userDataManager, ILogger logger, IXmlReaderSettingsFactory xmlReaderSettingsFactory) : base(fileSystem, configurationManager, libraryManager, userManager, userDataManager, logger, xmlReaderSettingsFactory)
+ {
+ }
}
}
diff --git a/MediaBrowser.LocalMetadata/Savers/FolderXmlSaver.cs b/MediaBrowser.LocalMetadata/Savers/FolderXmlSaver.cs
index 8dad16fc2..b51bd5b91 100644
--- a/MediaBrowser.LocalMetadata/Savers/FolderXmlSaver.cs
+++ b/MediaBrowser.LocalMetadata/Savers/FolderXmlSaver.cs
@@ -9,38 +9,28 @@ using System.Collections.Generic;
using System.IO;
using System.Text;
using System.Threading;
-using CommonIO;
+using System.Xml;
+using MediaBrowser.Common.IO;
+using MediaBrowser.Controller.IO;
+using MediaBrowser.Model.IO;
+using MediaBrowser.Model.Logging;
+using MediaBrowser.Model.Xml;
namespace MediaBrowser.LocalMetadata.Savers
{
- public class FolderXmlSaver : IMetadataFileSaver
+ public class FolderXmlSaver : BaseXmlSaver
{
- public string Name
+ protected override string GetLocalSavePath(IHasMetadata item)
{
- get
- {
- return XmlProviderUtils.Name;
- }
+ return Path.Combine(item.Path, "folder.xml");
}
- private readonly IServerConfigurationManager _config;
- private readonly ILibraryManager _libraryManager;
- private readonly IFileSystem _fileSystem;
-
- public FolderXmlSaver(IServerConfigurationManager config, ILibraryManager libraryManager, IFileSystem fileSystem)
+ protected override string GetRootElementName(IHasMetadata item)
{
- _config = config;
- _libraryManager = libraryManager;
- _fileSystem = fileSystem;
+ return "Item";
}
- /// <summary>
- /// Determines whether [is enabled for] [the specified item].
- /// </summary>
- /// <param name="item">The item.</param>
- /// <param name="updateType">Type of the update.</param>
- /// <returns><c>true</c> if [is enabled for] [the specified item]; otherwise, <c>false</c>.</returns>
- public bool IsEnabledFor(IHasMetadata item, ItemUpdateType updateType)
+ public override bool IsEnabledFor(IHasMetadata item, ItemUpdateType updateType)
{
if (!item.SupportsLocalMetadata)
{
@@ -61,35 +51,12 @@ namespace MediaBrowser.LocalMetadata.Savers
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(IHasMetadata item, CancellationToken cancellationToken)
+ protected override void WriteCustomElements(IHasMetadata item, XmlWriter writer)
{
- var builder = new StringBuilder();
-
- builder.Append("<Item>");
-
- XmlSaverHelpers.AddCommonNodes((Folder)item, _libraryManager, builder);
-
- builder.Append("</Item>");
-
- var xmlFilePath = GetSavePath(item);
-
- XmlSaverHelpers.Save(builder, xmlFilePath, new List<string>(), _config, _fileSystem);
}
- /// <summary>
- /// Gets the save path.
- /// </summary>
- /// <param name="item">The item.</param>
- /// <returns>System.String.</returns>
- public string GetSavePath(IHasMetadata item)
+ public FolderXmlSaver(IFileSystem fileSystem, IServerConfigurationManager configurationManager, ILibraryManager libraryManager, IUserManager userManager, IUserDataManager userDataManager, ILogger logger, IXmlReaderSettingsFactory xmlReaderSettingsFactory) : base(fileSystem, configurationManager, libraryManager, userManager, userDataManager, logger, xmlReaderSettingsFactory)
{
- return Path.Combine(item.Path, "folder.xml");
}
}
}
diff --git a/MediaBrowser.LocalMetadata/Savers/GameSystemXmlSaver.cs b/MediaBrowser.LocalMetadata/Savers/GameSystemXmlSaver.cs
index ddfaedba6..59b69746a 100644
--- a/MediaBrowser.LocalMetadata/Savers/GameSystemXmlSaver.cs
+++ b/MediaBrowser.LocalMetadata/Savers/GameSystemXmlSaver.cs
@@ -3,41 +3,20 @@ using MediaBrowser.Controller.Entities;
using MediaBrowser.Controller.Library;
using System.Collections.Generic;
using System.IO;
-using System.Security;
-using System.Text;
-using System.Threading;
-using CommonIO;
+using System.Xml;
+using MediaBrowser.Model.IO;
+using MediaBrowser.Model.Logging;
+using MediaBrowser.Model.Xml;
namespace MediaBrowser.LocalMetadata.Savers
{
- public class GameSystemXmlSaver : IMetadataFileSaver
+ public class GameSystemXmlSaver : BaseXmlSaver
{
- public string Name
+ public GameSystemXmlSaver(IFileSystem fileSystem, IServerConfigurationManager configurationManager, ILibraryManager libraryManager, IUserManager userManager, IUserDataManager userDataManager, ILogger logger, IXmlReaderSettingsFactory xmlReaderSettingsFactory) : base(fileSystem, configurationManager, libraryManager, userManager, userDataManager, logger, xmlReaderSettingsFactory)
{
- get
- {
- return XmlProviderUtils.Name;
- }
}
- private readonly IServerConfigurationManager _config;
- private readonly ILibraryManager _libraryManager;
- private readonly IFileSystem _fileSystem;
-
- public GameSystemXmlSaver(IServerConfigurationManager config, ILibraryManager libraryManager, IFileSystem fileSystem)
- {
- _config = config;
- _libraryManager = libraryManager;
- _fileSystem = fileSystem;
- }
-
- /// <summary>
- /// Determines whether [is enabled for] [the specified item].
- /// </summary>
- /// <param name="item">The item.</param>
- /// <param name="updateType">Type of the update.</param>
- /// <returns><c>true</c> if [is enabled for] [the specified item]; otherwise, <c>false</c>.</returns>
- public bool IsEnabledFor(IHasMetadata item, ItemUpdateType updateType)
+ public override bool IsEnabledFor(IHasMetadata item, ItemUpdateType updateType)
{
if (!item.SupportsLocalMetadata)
{
@@ -47,42 +26,34 @@ namespace MediaBrowser.LocalMetadata.Savers
return item is GameSystem && updateType >= ItemUpdateType.MetadataDownload;
}
- /// <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(IHasMetadata item, CancellationToken cancellationToken)
+ protected override List<string> GetTagsUsed()
{
- var gameSystem = (GameSystem)item;
+ var list = new List<string>
+ {
+ "GameSystem"
+ };
- var builder = new StringBuilder();
+ return list;
+ }
- builder.Append("<Item>");
+ protected override void WriteCustomElements(IHasMetadata item, XmlWriter writer)
+ {
+ var gameSystem = (GameSystem)item;
if (!string.IsNullOrEmpty(gameSystem.GameSystemName))
{
- builder.Append("<GameSystem>" + SecurityElement.Escape(gameSystem.GameSystemName) + "</GameSystem>");
+ writer.WriteElementString("GameSystem", gameSystem.GameSystemName);
}
-
- XmlSaverHelpers.AddCommonNodes(gameSystem, _libraryManager, builder);
-
- builder.Append("</Item>");
-
- var xmlFilePath = GetSavePath(item);
-
- XmlSaverHelpers.Save(builder, xmlFilePath, new List<string>(), _config, _fileSystem);
}
- /// <summary>
- /// Gets the save path.
- /// </summary>
- /// <param name="item">The item.</param>
- /// <returns>System.String.</returns>
- public string GetSavePath(IHasMetadata item)
+ protected override string GetLocalSavePath(IHasMetadata item)
{
return Path.Combine(item.Path, "gamesystem.xml");
}
+
+ protected override string GetRootElementName(IHasMetadata item)
+ {
+ return "Item";
+ }
}
}
diff --git a/MediaBrowser.LocalMetadata/Savers/GameXmlSaver.cs b/MediaBrowser.LocalMetadata/Savers/GameXmlSaver.cs
index 5592c068c..26c4b4a93 100644
--- a/MediaBrowser.LocalMetadata/Savers/GameXmlSaver.cs
+++ b/MediaBrowser.LocalMetadata/Savers/GameXmlSaver.cs
@@ -4,44 +4,21 @@ using MediaBrowser.Controller.Library;
using System.Collections.Generic;
using System.Globalization;
using System.IO;
-using System.Security;
-using System.Text;
-using System.Threading;
-using CommonIO;
+using System.Xml;
+using MediaBrowser.Model.IO;
+using MediaBrowser.Model.Logging;
+using MediaBrowser.Model.Xml;
namespace MediaBrowser.LocalMetadata.Savers
{
/// <summary>
/// Saves game.xml for games
/// </summary>
- public class GameXmlSaver : IMetadataFileSaver
+ public class GameXmlSaver : BaseXmlSaver
{
- public string Name
- {
- get
- {
- return XmlProviderUtils.Name;
- }
- }
-
- private readonly IServerConfigurationManager _config;
- private readonly ILibraryManager _libraryManager;
- private readonly IFileSystem _fileSystem;
-
- public GameXmlSaver(IServerConfigurationManager config, ILibraryManager libraryManager, IFileSystem fileSystem)
- {
- _config = config;
- _libraryManager = libraryManager;
- _fileSystem = fileSystem;
- }
+ private static readonly CultureInfo UsCulture = new CultureInfo("en-US");
- /// <summary>
- /// Determines whether [is enabled for] [the specified item].
- /// </summary>
- /// <param name="item">The item.</param>
- /// <param name="updateType">Type of the update.</param>
- /// <returns><c>true</c> if [is enabled for] [the specified item]; otherwise, <c>false</c>.</returns>
- public bool IsEnabledFor(IHasMetadata item, ItemUpdateType updateType)
+ public override bool IsEnabledFor(IHasMetadata item, ItemUpdateType updateType)
{
if (!item.SupportsLocalMetadata)
{
@@ -51,52 +28,41 @@ namespace MediaBrowser.LocalMetadata.Savers
return item is Game && updateType >= ItemUpdateType.MetadataDownload;
}
- private static readonly CultureInfo UsCulture = new CultureInfo("en-US");
-
- /// <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(IHasMetadata item, CancellationToken cancellationToken)
+ protected override List<string> GetTagsUsed()
{
- var builder = new StringBuilder();
+ var list = new List<string>
+ {
+ "GameSystem",
+ "Players"
+ };
- builder.Append("<Item>");
+ return list;
+ }
+ protected override void WriteCustomElements(IHasMetadata item, XmlWriter writer)
+ {
var game = (Game)item;
- if (game.PlayersSupported.HasValue)
+ if (!string.IsNullOrEmpty(game.GameSystem))
{
- builder.Append("<Players>" + SecurityElement.Escape(game.PlayersSupported.Value.ToString(UsCulture)) + "</Players>");
+ writer.WriteElementString("GameSystem", game.GameSystem);
}
-
- if (!string.IsNullOrEmpty(game.GameSystem))
+ if (game.PlayersSupported.HasValue)
{
- builder.Append("<GameSystem>" + SecurityElement.Escape(game.GameSystem) + "</GameSystem>");
+ writer.WriteElementString("Players", game.PlayersSupported.Value.ToString(UsCulture));
}
-
- XmlSaverHelpers.AddCommonNodes(game, _libraryManager, builder);
-
- builder.Append("</Item>");
-
- var xmlFilePath = GetSavePath(item);
-
- XmlSaverHelpers.Save(builder, xmlFilePath, new List<string>
- {
- "Players",
- "GameSystem",
- "NesBox",
- "NesBoxRom"
- }, _config, _fileSystem);
}
- public string GetSavePath(IHasMetadata item)
+ protected override string GetLocalSavePath(IHasMetadata item)
{
return GetGameSavePath((Game)item);
}
+ protected override string GetRootElementName(IHasMetadata item)
+ {
+ return "Item";
+ }
+
public static string GetGameSavePath(Game item)
{
if (item.DetectIsInMixedFolder())
@@ -106,5 +72,9 @@ namespace MediaBrowser.LocalMetadata.Savers
return Path.Combine(item.ContainingFolderPath, "game.xml");
}
+
+ public GameXmlSaver(IFileSystem fileSystem, IServerConfigurationManager configurationManager, ILibraryManager libraryManager, IUserManager userManager, IUserDataManager userDataManager, ILogger logger, IXmlReaderSettingsFactory xmlReaderSettingsFactory) : base(fileSystem, configurationManager, libraryManager, userManager, userDataManager, logger, xmlReaderSettingsFactory)
+ {
+ }
}
}
diff --git a/MediaBrowser.LocalMetadata/Savers/PersonXmlSaver.cs b/MediaBrowser.LocalMetadata/Savers/PersonXmlSaver.cs
index 295e64881..8409e483d 100644
--- a/MediaBrowser.LocalMetadata/Savers/PersonXmlSaver.cs
+++ b/MediaBrowser.LocalMetadata/Savers/PersonXmlSaver.cs
@@ -3,92 +3,55 @@ using MediaBrowser.Controller.Entities;
using MediaBrowser.Controller.Library;
using System.Collections.Generic;
using System.IO;
-using System.Security;
-using System.Text;
-using System.Threading;
-using CommonIO;
+using System.Xml;
+using MediaBrowser.Model.IO;
+using MediaBrowser.Model.Logging;
+using MediaBrowser.Model.Xml;
namespace MediaBrowser.LocalMetadata.Savers
{
- /// <summary>
- /// Class PersonXmlSaver
- /// </summary>
- public class PersonXmlSaver : IMetadataFileSaver
- {
- public string Name
- {
- get
- {
- return XmlProviderUtils.Name;
- }
- }
-
- private readonly IServerConfigurationManager _config;
- private readonly ILibraryManager _libraryManager;
- private readonly IFileSystem _fileSystem;
-
- public PersonXmlSaver(IServerConfigurationManager config, ILibraryManager libraryManager, IFileSystem fileSystem)
- {
- _config = config;
- _libraryManager = libraryManager;
- _fileSystem = fileSystem;
- }
-
- /// <summary>
- /// Determines whether [is enabled for] [the specified item].
- /// </summary>
- /// <param name="item">The item.</param>
- /// <param name="updateType">Type of the update.</param>
- /// <returns><c>true</c> if [is enabled for] [the specified item]; otherwise, <c>false</c>.</returns>
- public bool IsEnabledFor(IHasMetadata item, ItemUpdateType updateType)
- {
- if (!item.SupportsLocalMetadata)
- {
- return false;
- }
-
- return item is Person && updateType >= ItemUpdateType.MetadataDownload;
- }
-
- /// <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(IHasMetadata item, CancellationToken cancellationToken)
- {
- var person = (Person)item;
-
- var builder = new StringBuilder();
-
- builder.Append("<Item>");
-
- XmlSaverHelpers.AddCommonNodes(person, _libraryManager, builder);
-
- if (person.ProductionLocations.Count > 0)
- {
- builder.Append("<PlaceOfBirth>" + SecurityElement.Escape(person.ProductionLocations[0]) + "</PlaceOfBirth>");
- }
-
- builder.Append("</Item>");
-
- var xmlFilePath = GetSavePath(item);
-
- XmlSaverHelpers.Save(builder, xmlFilePath, new List<string>
- {
- "PlaceOfBirth"
- }, _config, _fileSystem);
- }
-
- /// <summary>
- /// Gets the save path.
- /// </summary>
- /// <param name="item">The item.</param>
- /// <returns>System.String.</returns>
- public string GetSavePath(IHasMetadata item)
- {
- return Path.Combine(item.Path, "person.xml");
- }
- }
+ ///// <summary>
+ ///// Class PersonXmlSaver
+ ///// </summary>
+ //public class PersonXmlSaver : BaseXmlSaver
+ //{
+ // public override bool IsEnabledFor(IHasMetadata item, ItemUpdateType updateType)
+ // {
+ // if (!item.SupportsLocalMetadata)
+ // {
+ // return false;
+ // }
+
+ // return item is Person && updateType >= ItemUpdateType.MetadataDownload;
+ // }
+
+ // protected override List<string> GetTagsUsed()
+ // {
+ // var list = new List<string>
+ // {
+ // "PlaceOfBirth"
+ // };
+
+ // return list;
+ // }
+
+ // protected override void WriteCustomElements(IHasMetadata item, XmlWriter writer)
+ // {
+ // var person = (Person)item;
+
+ // if (person.ProductionLocations.Count > 0)
+ // {
+ // writer.WriteElementString("PlaceOfBirth", person.ProductionLocations[0]);
+ // }
+ // }
+
+ // protected override string GetLocalSavePath(IHasMetadata item)
+ // {
+ // return Path.Combine(item.Path, "person.xml");
+ // }
+
+ // public PersonXmlSaver(IFileSystem fileSystem, IServerConfigurationManager configurationManager, ILibraryManager libraryManager, IUserManager userManager, IUserDataManager userDataManager, ILogger logger, IXmlReaderSettingsFactory xmlReaderSettingsFactory) : base(fileSystem, configurationManager, libraryManager, userManager, userDataManager, logger, xmlReaderSettingsFactory)
+ // {
+ // }
+ //}
}
diff --git a/MediaBrowser.LocalMetadata/Savers/PlaylistXmlSaver.cs b/MediaBrowser.LocalMetadata/Savers/PlaylistXmlSaver.cs
index 8862f9c03..ef28dde36 100644
--- a/MediaBrowser.LocalMetadata/Savers/PlaylistXmlSaver.cs
+++ b/MediaBrowser.LocalMetadata/Savers/PlaylistXmlSaver.cs
@@ -4,41 +4,16 @@ using MediaBrowser.Controller.Library;
using MediaBrowser.Controller.Playlists;
using System.Collections.Generic;
using System.IO;
-using System.Security;
-using System.Text;
-using System.Threading;
-using CommonIO;
+using System.Xml;
+using MediaBrowser.Model.IO;
+using MediaBrowser.Model.Logging;
+using MediaBrowser.Model.Xml;
namespace MediaBrowser.LocalMetadata.Savers
{
- public class PlaylistXmlSaver : IMetadataFileSaver
+ public class PlaylistXmlSaver : BaseXmlSaver
{
- public string Name
- {
- get
- {
- return XmlProviderUtils.Name;
- }
- }
-
- private readonly IServerConfigurationManager _config;
- private readonly ILibraryManager _libraryManager;
- private readonly IFileSystem _fileSystem;
-
- public PlaylistXmlSaver(IServerConfigurationManager config, ILibraryManager libraryManager, IFileSystem fileSystem)
- {
- _config = config;
- _libraryManager = libraryManager;
- _fileSystem = fileSystem;
- }
-
- /// <summary>
- /// Determines whether [is enabled for] [the specified item].
- /// </summary>
- /// <param name="item">The item.</param>
- /// <param name="updateType">Type of the update.</param>
- /// <returns><c>true</c> if [is enabled for] [the specified item]; otherwise, <c>false</c>.</returns>
- public bool IsEnabledFor(IHasMetadata item, ItemUpdateType updateType)
+ public override bool IsEnabledFor(IHasMetadata item, ItemUpdateType updateType)
{
if (!item.SupportsLocalMetadata)
{
@@ -48,47 +23,34 @@ namespace MediaBrowser.LocalMetadata.Savers
return item is Playlist && updateType >= ItemUpdateType.MetadataImport;
}
- /// <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(IHasMetadata item, CancellationToken cancellationToken)
+ protected override List<string> GetTagsUsed()
{
- var playlist = (Playlist)item;
-
- var builder = new StringBuilder();
-
- builder.Append("<Item>");
-
- if (!string.IsNullOrEmpty(playlist.PlaylistMediaType))
+ var list = new List<string>
{
- builder.Append("<PlaylistMediaType>" + SecurityElement.Escape(playlist.PlaylistMediaType) + "</PlaylistMediaType>");
- }
-
- XmlSaverHelpers.AddCommonNodes(playlist, _libraryManager, builder);
+ "OwnerUserId",
+ "PlaylistMediaType"
+ };
- builder.Append("</Item>");
+ return list;
+ }
- var xmlFilePath = GetSavePath(item);
+ protected override void WriteCustomElements(IHasMetadata item, XmlWriter writer)
+ {
+ var game = (Playlist)item;
- XmlSaverHelpers.Save(builder, xmlFilePath, new List<string>
+ if (!string.IsNullOrEmpty(game.PlaylistMediaType))
{
- "OwnerUserId",
- "PlaylistMediaType"
-
- }, _config, _fileSystem);
+ writer.WriteElementString("PlaylistMediaType", game.PlaylistMediaType);
+ }
}
- /// <summary>
- /// Gets the save path.
- /// </summary>
- /// <param name="item">The item.</param>
- /// <returns>System.String.</returns>
- public string GetSavePath(IHasMetadata item)
+ protected override string GetLocalSavePath(IHasMetadata item)
{
return Path.Combine(item.Path, "playlist.xml");
}
+
+ public PlaylistXmlSaver(IFileSystem fileSystem, IServerConfigurationManager configurationManager, ILibraryManager libraryManager, IUserManager userManager, IUserDataManager userDataManager, ILogger logger, IXmlReaderSettingsFactory xmlReaderSettingsFactory) : base(fileSystem, configurationManager, libraryManager, userManager, userDataManager, logger, xmlReaderSettingsFactory)
+ {
+ }
}
}
diff --git a/MediaBrowser.LocalMetadata/Savers/XmlSaverHelpers.cs b/MediaBrowser.LocalMetadata/Savers/XmlSaverHelpers.cs
deleted file mode 100644
index 314840558..000000000
--- a/MediaBrowser.LocalMetadata/Savers/XmlSaverHelpers.cs
+++ /dev/null
@@ -1,647 +0,0 @@
-using MediaBrowser.Controller.Configuration;
-using MediaBrowser.Controller.Entities;
-using MediaBrowser.Controller.Entities.Movies;
-using MediaBrowser.Controller.Entities.TV;
-using MediaBrowser.Controller.Library;
-using MediaBrowser.Controller.Persistence;
-using MediaBrowser.Controller.Playlists;
-using MediaBrowser.Model.Entities;
-using System;
-using System.Collections.Generic;
-using System.Globalization;
-using System.IO;
-using System.Linq;
-using System.Security;
-using System.Text;
-using System.Xml;
-using CommonIO;
-
-namespace MediaBrowser.LocalMetadata.Savers
-{
- /// <summary>
- /// Class XmlHelpers
- /// </summary>
- public static class XmlSaverHelpers
- {
- private static readonly Dictionary<string, string> CommonTags = new[] {
-
- "Added",
- "AspectRatio",
- "AudioDbAlbumId",
- "AudioDbArtistId",
- "AwardSummary",
- "BirthDate",
- "Budget",
-
- // Deprecated. No longer saving in this field.
- "certification",
-
- "Chapters",
- "ContentRating",
- "Countries",
- "CustomRating",
- "CriticRating",
- "CriticRatingSummary",
- "DeathDate",
- "DisplayOrder",
- "EndDate",
- "Genres",
- "Genre",
- "GamesDbId",
-
- // Deprecated. No longer saving in this field.
- "IMDB_ID",
-
- "IMDB",
-
- // Deprecated. No longer saving in this field.
- "IMDbId",
-
- "Language",
- "LocalTitle",
- "OriginalTitle",
- "LockData",
- "LockedFields",
- "Format3D",
- "Metascore",
-
- // Deprecated. No longer saving in this field.
- "MPAARating",
-
- "MPAADescription",
-
- "MusicBrainzArtistId",
- "MusicBrainzAlbumArtistId",
- "MusicBrainzAlbumId",
- "MusicBrainzReleaseGroupId",
-
- // Deprecated. No longer saving in this field.
- "MusicbrainzId",
-
- "Overview",
- "ShortOverview",
- "Persons",
- "PlotKeywords",
- "PremiereDate",
- "ProductionYear",
- "Rating",
- "Revenue",
- "RottenTomatoesId",
- "RunningTime",
-
- // Deprecated. No longer saving in this field.
- "Runtime",
-
- "SortTitle",
- "Studios",
- "Tags",
-
- // Deprecated. No longer saving in this field.
- "TagLine",
-
- "Taglines",
- "TMDbCollectionId",
- "TMDbId",
-
- // Deprecated. No longer saving in this field.
- "Trailer",
-
- "Trailers",
- "TVcomId",
- "TvDbId",
- "Type",
- "TVRageId",
- "VoteCount",
- "Website",
- "Zap2ItId",
- "CollectionItems",
- "PlaylistItems",
- "Shares"
-
- }.ToDictionary(i => i, StringComparer.OrdinalIgnoreCase);
-
- /// <summary>
- /// The us culture
- /// </summary>
- private static readonly CultureInfo UsCulture = new CultureInfo("en-US");
-
- /// <summary>
- /// Saves the specified XML.
- /// </summary>
- /// <param name="xml">The XML.</param>
- /// <param name="path">The path.</param>
- /// <param name="xmlTagsUsed">The XML tags used.</param>
- public static void Save(StringBuilder xml, string path, List<string> xmlTagsUsed, IServerConfigurationManager config, IFileSystem fileSystem)
- {
- if (fileSystem.FileExists(path))
- {
- var position = xml.ToString().LastIndexOf("</", StringComparison.OrdinalIgnoreCase);
- xml.Insert(position, GetCustomTags(path, xmlTagsUsed));
- }
-
- var xmlDocument = new XmlDocument();
- xmlDocument.LoadXml(xml.ToString());
-
- //Add the new node to the document.
- xmlDocument.InsertBefore(xmlDocument.CreateXmlDeclaration("1.0", "UTF-8", "yes"), xmlDocument.DocumentElement);
-
- fileSystem.CreateDirectory(Path.GetDirectoryName(path));
-
- var wasHidden = false;
-
- var file = new FileInfo(path);
-
- // This will fail if the file is hidden
- if (file.Exists)
- {
- if ((file.Attributes & FileAttributes.Hidden) == FileAttributes.Hidden)
- {
- file.Attributes &= ~FileAttributes.Hidden;
-
- wasHidden = true;
- }
- }
-
- using (var filestream = new FileStream(path, FileMode.Create, FileAccess.Write, FileShare.Read))
- {
- using (var streamWriter = new StreamWriter(filestream, Encoding.UTF8))
- {
- xmlDocument.Save(streamWriter);
- }
- }
-
- if (wasHidden || config.Configuration.SaveMetadataHidden)
- {
- file.Refresh();
-
- // Add back the attribute
- file.Attributes |= FileAttributes.Hidden;
- }
- }
-
- /// <summary>
- /// Gets the custom tags.
- /// </summary>
- /// <param name="path">The path.</param>
- /// <param name="xmlTagsUsed">The XML tags used.</param>
- /// <returns>System.String.</returns>
- private static string GetCustomTags(string path, List<string> xmlTagsUsed)
- {
- var settings = new XmlReaderSettings
- {
- CheckCharacters = false,
- IgnoreProcessingInstructions = true,
- IgnoreComments = true,
- ValidationType = ValidationType.None
- };
-
- var builder = new StringBuilder();
-
- using (var streamReader = new StreamReader(path, Encoding.UTF8))
- {
- // Use XmlReader for best performance
- using (var reader = XmlReader.Create(streamReader, settings))
- {
- reader.MoveToContent();
-
- // Loop through each element
- while (reader.Read())
- {
- if (reader.NodeType == XmlNodeType.Element)
- {
- var name = reader.Name;
-
- if (!CommonTags.ContainsKey(name) && !xmlTagsUsed.Contains(name, StringComparer.OrdinalIgnoreCase))
- {
- builder.AppendLine(reader.ReadOuterXml());
- }
- else
- {
- reader.Skip();
- }
- }
- }
- }
- }
-
- return builder.ToString();
- }
-
- /// <summary>
- /// Adds the common nodes.
- /// </summary>
- /// <param name="item">The item.</param>
- /// <param name="builder">The builder.</param>
- public static void AddCommonNodes(BaseItem item, ILibraryManager libraryManager, StringBuilder builder)
- {
- if (!string.IsNullOrEmpty(item.OfficialRating))
- {
- builder.Append("<ContentRating>" + SecurityElement.Escape(item.OfficialRating) + "</ContentRating>");
- }
-
- if (!string.IsNullOrEmpty(item.OfficialRatingDescription))
- {
- builder.Append("<MPAADescription>" + SecurityElement.Escape(item.OfficialRatingDescription) + "</MPAADescription>");
- }
-
- builder.Append("<Added>" + SecurityElement.Escape(item.DateCreated.ToLocalTime().ToString("G")) + "</Added>");
-
- builder.Append("<LockData>" + item.IsLocked.ToString().ToLower() + "</LockData>");
-
- if (item.LockedFields.Count > 0)
- {
- builder.Append("<LockedFields>" + string.Join("|", item.LockedFields.Select(i => i.ToString()).ToArray()) + "</LockedFields>");
- }
-
- if (!string.IsNullOrEmpty(item.DisplayMediaType))
- {
- builder.Append("<Type>" + SecurityElement.Escape(item.DisplayMediaType) + "</Type>");
- }
-
- if (item.CriticRating.HasValue)
- {
- builder.Append("<CriticRating>" + SecurityElement.Escape(item.CriticRating.Value.ToString(UsCulture)) + "</CriticRating>");
- }
-
- if (!string.IsNullOrEmpty(item.CriticRatingSummary))
- {
- builder.Append("<CriticRatingSummary><![CDATA[" + item.CriticRatingSummary + "]]></CriticRatingSummary>");
- }
-
- if (!string.IsNullOrEmpty(item.Overview))
- {
- builder.Append("<Overview><![CDATA[" + item.Overview + "]]></Overview>");
- }
-
- var hasOriginalTitle = item as IHasOriginalTitle;
- if (hasOriginalTitle != null)
- {
- if (!string.IsNullOrEmpty(hasOriginalTitle.OriginalTitle))
- {
- builder.Append("<OriginalTitle>" + SecurityElement.Escape(hasOriginalTitle.OriginalTitle) + "</OriginalTitle>");
- }
- }
-
- if (!string.IsNullOrEmpty(item.ShortOverview))
- {
- builder.Append("<ShortOverview><![CDATA[" + item.ShortOverview + "]]></ShortOverview>");
- }
-
- if (!string.IsNullOrEmpty(item.CustomRating))
- {
- builder.Append("<CustomRating>" + SecurityElement.Escape(item.CustomRating) + "</CustomRating>");
- }
-
- if (!string.IsNullOrEmpty(item.Name) && !(item is Episode))
- {
- builder.Append("<LocalTitle>" + SecurityElement.Escape(item.Name) + "</LocalTitle>");
- }
-
- if (!string.IsNullOrEmpty(item.ForcedSortName))
- {
- builder.Append("<SortTitle>" + SecurityElement.Escape(item.ForcedSortName) + "</SortTitle>");
- }
-
- if (item.PremiereDate.HasValue)
- {
- if (item is Person)
- {
- builder.Append("<BirthDate>" + SecurityElement.Escape(item.PremiereDate.Value.ToLocalTime().ToString("yyyy-MM-dd")) + "</BirthDate>");
- }
- else if (!(item is Episode))
- {
- builder.Append("<PremiereDate>" + SecurityElement.Escape(item.PremiereDate.Value.ToLocalTime().ToString("yyyy-MM-dd")) + "</PremiereDate>");
- }
- }
-
- if (item.EndDate.HasValue)
- {
- if (item is Person)
- {
- builder.Append("<DeathDate>" + SecurityElement.Escape(item.EndDate.Value.ToString("yyyy-MM-dd")) + "</DeathDate>");
- }
- else if (!(item is Episode))
- {
- builder.Append("<EndDate>" + SecurityElement.Escape(item.EndDate.Value.ToString("yyyy-MM-dd")) + "</EndDate>");
- }
- }
-
- var hasTrailers = item as IHasTrailers;
- if (hasTrailers != null)
- {
- if (hasTrailers.RemoteTrailers.Count > 0)
- {
- builder.Append("<Trailers>");
-
- foreach (var trailer in hasTrailers.RemoteTrailers)
- {
- builder.Append("<Trailer>" + SecurityElement.Escape(trailer.Url) + "</Trailer>");
- }
-
- builder.Append("</Trailers>");
- }
- }
-
- //if (hasProductionLocations.ProductionLocations.Count > 0)
- //{
- // builder.Append("<Countries>");
-
- // foreach (var name in hasProductionLocations.ProductionLocations)
- // {
- // builder.Append("<Country>" + SecurityElement.Escape(name) + "</Country>");
- // }
-
- // builder.Append("</Countries>");
- //}
-
- var hasDisplayOrder = item as IHasDisplayOrder;
- if (hasDisplayOrder != null && !string.IsNullOrEmpty(hasDisplayOrder.DisplayOrder))
- {
- builder.Append("<DisplayOrder>" + SecurityElement.Escape(hasDisplayOrder.DisplayOrder) + "</DisplayOrder>");
- }
-
- var hasMetascore = item as IHasMetascore;
- if (hasMetascore != null && hasMetascore.Metascore.HasValue)
- {
- builder.Append("<Metascore>" + SecurityElement.Escape(hasMetascore.Metascore.Value.ToString(UsCulture)) + "</Metascore>");
- }
-
- var hasAwards = item as IHasAwards;
- if (hasAwards != null && !string.IsNullOrEmpty(hasAwards.AwardSummary))
- {
- builder.Append("<AwardSummary>" + SecurityElement.Escape(hasAwards.AwardSummary) + "</AwardSummary>");
- }
-
- var hasBudget = item as IHasBudget;
- if (hasBudget != null)
- {
- if (hasBudget.Budget.HasValue)
- {
- builder.Append("<Budget>" + SecurityElement.Escape(hasBudget.Budget.Value.ToString(UsCulture)) + "</Budget>");
- }
-
- if (hasBudget.Revenue.HasValue)
- {
- builder.Append("<Revenue>" + SecurityElement.Escape(hasBudget.Revenue.Value.ToString(UsCulture)) + "</Revenue>");
- }
- }
-
- if (item.CommunityRating.HasValue)
- {
- builder.Append("<Rating>" + SecurityElement.Escape(item.CommunityRating.Value.ToString(UsCulture)) + "</Rating>");
- }
- if (item.VoteCount.HasValue)
- {
- builder.Append("<VoteCount>" + SecurityElement.Escape(item.VoteCount.Value.ToString(UsCulture)) + "</VoteCount>");
- }
-
- if (item.ProductionYear.HasValue && !(item is Person))
- {
- builder.Append("<ProductionYear>" + SecurityElement.Escape(item.ProductionYear.Value.ToString(UsCulture)) + "</ProductionYear>");
- }
-
- if (!string.IsNullOrEmpty(item.HomePageUrl))
- {
- builder.Append("<Website>" + SecurityElement.Escape(item.HomePageUrl) + "</Website>");
- }
-
- var hasAspectRatio = item as IHasAspectRatio;
- if (hasAspectRatio != null)
- {
- if (!string.IsNullOrEmpty(hasAspectRatio.AspectRatio))
- {
- builder.Append("<AspectRatio>" + SecurityElement.Escape(hasAspectRatio.AspectRatio) + "</AspectRatio>");
- }
- }
-
- if (!string.IsNullOrEmpty(item.PreferredMetadataLanguage))
- {
- builder.Append("<Language>" + SecurityElement.Escape(item.PreferredMetadataLanguage) + "</Language>");
- }
- if (!string.IsNullOrEmpty(item.PreferredMetadataCountryCode))
- {
- builder.Append("<CountryCode>" + SecurityElement.Escape(item.PreferredMetadataCountryCode) + "</CountryCode>");
- }
-
- // Use original runtime here, actual file runtime later in MediaInfo
- var runTimeTicks = item.RunTimeTicks;
-
- if (runTimeTicks.HasValue)
- {
- var timespan = TimeSpan.FromTicks(runTimeTicks.Value);
-
- builder.Append("<RunningTime>" + Convert.ToInt32(timespan.TotalMinutes).ToString(UsCulture) + "</RunningTime>");
- }
-
- if (item.ProviderIds != null)
- {
- foreach (var providerKey in item.ProviderIds.Keys)
- {
- var providerId = item.ProviderIds[providerKey];
- if (!string.IsNullOrEmpty(providerId))
- {
- builder.Append(string.Format("<{0}>{1}</{0}>", providerKey + "Id", SecurityElement.Escape(providerId)));
- }
- }
- }
-
- if (!string.IsNullOrWhiteSpace(item.Tagline))
- {
- builder.Append("<Taglines>");
- builder.Append("<Tagline>" + SecurityElement.Escape(item.Tagline) + "</Tagline>");
- builder.Append("</Taglines>");
- }
-
- if (item.Genres.Count > 0)
- {
- builder.Append("<Genres>");
-
- foreach (var genre in item.Genres)
- {
- builder.Append("<Genre>" + SecurityElement.Escape(genre) + "</Genre>");
- }
-
- builder.Append("</Genres>");
- }
-
- if (item.Studios.Count > 0)
- {
- builder.Append("<Studios>");
-
- foreach (var studio in item.Studios)
- {
- builder.Append("<Studio>" + SecurityElement.Escape(studio) + "</Studio>");
- }
-
- 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>");
- }
-
- if (item.Keywords.Count > 0)
- {
- builder.Append("<PlotKeywords>");
-
- foreach (var tag in item.Keywords)
- {
- builder.Append("<PlotKeyword>" + SecurityElement.Escape(tag) + "</PlotKeyword>");
- }
-
- builder.Append("</PlotKeywords>");
- }
-
- var people = libraryManager.GetPeople(item);
-
- if (people.Count > 0)
- {
- builder.Append("<Persons>");
-
- foreach (var person in people)
- {
- builder.Append("<Person>");
- builder.Append("<Name>" + SecurityElement.Escape(person.Name) + "</Name>");
- builder.Append("<Type>" + SecurityElement.Escape(person.Type) + "</Type>");
- builder.Append("<Role>" + SecurityElement.Escape(person.Role) + "</Role>");
-
- if (person.SortOrder.HasValue)
- {
- builder.Append("<SortOrder>" + SecurityElement.Escape(person.SortOrder.Value.ToString(UsCulture)) + "</SortOrder>");
- }
-
- builder.Append("</Person>");
- }
-
- builder.Append("</Persons>");
- }
-
- var boxset = item as BoxSet;
- if (boxset != null)
- {
- AddLinkedChildren(boxset, builder, "CollectionItems", "CollectionItem");
- }
-
- var playlist = item as Playlist;
- if (playlist != null)
- {
- AddLinkedChildren(playlist, builder, "PlaylistItems", "PlaylistItem");
- }
-
- var hasShares = item as IHasShares;
- if (hasShares != null)
- {
- AddShares(hasShares, builder);
- }
- }
-
- public static void AddShares(IHasShares item, StringBuilder builder)
- {
- builder.Append("<Shares>");
-
- foreach (var share in item.Shares)
- {
- builder.Append("<Share>");
-
- builder.Append("<UserId>" + SecurityElement.Escape(share.UserId) + "</UserId>");
- builder.Append("<CanEdit>" + SecurityElement.Escape(share.CanEdit.ToString().ToLower()) + "</CanEdit>");
-
- builder.Append("</Share>");
- }
-
- builder.Append("</Shares>");
- }
-
- public static void AddChapters(Video item, StringBuilder builder, IItemRepository repository)
- {
- var chapters = repository.GetChapters(item.Id);
-
- builder.Append("<Chapters>");
-
- foreach (var chapter in chapters)
- {
- builder.Append("<Chapter>");
- builder.Append("<Name>" + SecurityElement.Escape(chapter.Name) + "</Name>");
-
- var time = TimeSpan.FromTicks(chapter.StartPositionTicks);
- var ms = Convert.ToInt64(time.TotalMilliseconds);
-
- builder.Append("<StartPositionMs>" + SecurityElement.Escape(ms.ToString(UsCulture)) + "</StartPositionMs>");
- builder.Append("</Chapter>");
- }
-
- builder.Append("</Chapters>");
- }
-
- /// <summary>
- /// Appends the media info.
- /// </summary>
- /// <typeparam name="T"></typeparam>
- public static void AddMediaInfo<T>(T item, StringBuilder builder, IItemRepository itemRepository)
- where T : BaseItem
- {
- var video = item as Video;
-
- if (video != null)
- {
- //AddChapters(video, builder, itemRepository);
-
- if (video.Video3DFormat.HasValue)
- {
- switch (video.Video3DFormat.Value)
- {
- case Video3DFormat.FullSideBySide:
- builder.Append("<Format3D>FSBS</Format3D>");
- break;
- case Video3DFormat.FullTopAndBottom:
- builder.Append("<Format3D>FTAB</Format3D>");
- break;
- case Video3DFormat.HalfSideBySide:
- builder.Append("<Format3D>HSBS</Format3D>");
- break;
- case Video3DFormat.HalfTopAndBottom:
- builder.Append("<Format3D>HTAB</Format3D>");
- break;
- case Video3DFormat.MVC:
- builder.Append("<Format3D>MVC</Format3D>");
- break;
- }
- }
- }
- }
-
- public static void AddLinkedChildren(Folder item, StringBuilder builder, string pluralNodeName, string singularNodeName)
- {
- var items = item.LinkedChildren
- .Where(i => i.Type == LinkedChildType.Manual)
- .ToList();
-
- if (items.Count == 0)
- {
- return;
- }
-
- builder.Append("<" + pluralNodeName + ">");
- foreach (var link in items)
- {
- builder.Append("<" + singularNodeName + ">");
-
- if (!string.IsNullOrWhiteSpace(link.Path))
- {
- builder.Append("<Path>" + SecurityElement.Escape((link.Path)) + "</Path>");
- }
-
- builder.Append("</" + singularNodeName + ">");
- }
- builder.Append("</" + pluralNodeName + ">");
- }
- }
-}
diff --git a/MediaBrowser.LocalMetadata/packages.config b/MediaBrowser.LocalMetadata/packages.config
deleted file mode 100644
index ccef6d686..000000000
--- a/MediaBrowser.LocalMetadata/packages.config
+++ /dev/null
@@ -1,5 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<packages>
- <package id="CommonIO" version="1.0.0.9" targetFramework="net45" />
- <package id="Patterns.Logging" version="1.0.0.2" targetFramework="net45" />
-</packages> \ No newline at end of file
diff --git a/MediaBrowser.LocalMetadata/project.json b/MediaBrowser.LocalMetadata/project.json
new file mode 100644
index 000000000..fbbe9eaf3
--- /dev/null
+++ b/MediaBrowser.LocalMetadata/project.json
@@ -0,0 +1,17 @@
+{
+ "frameworks":{
+ "netstandard1.6":{
+ "dependencies":{
+ "NETStandard.Library":"1.6.0",
+ }
+ },
+ ".NETPortable,Version=v4.5,Profile=Profile7":{
+ "buildOptions": {
+ "define": [ ]
+ },
+ "frameworkAssemblies":{
+
+ }
+ }
+ }
+} \ No newline at end of file