diff options
| author | LukePulverenti <luke.pulverenti@gmail.com> | 2013-02-22 01:28:57 -0500 |
|---|---|---|
| committer | LukePulverenti <luke.pulverenti@gmail.com> | 2013-02-22 01:28:57 -0500 |
| commit | 746c5d2fa7cd14f648c72a87ce52e5096c1f03f1 (patch) | |
| tree | c2e9dbac2110c8c881ff82af01572b796c931c6f | |
| parent | 868a7ce9c8b50bd64c8b5ae33fec77abfd25ef7c (diff) | |
moved Plugins to separate repo
54 files changed, 104 insertions, 4693 deletions
diff --git a/MediaBrowser.Api/PluginService.cs b/MediaBrowser.Api/PluginService.cs index ad7e37adc..73bafd9fd 100644 --- a/MediaBrowser.Api/PluginService.cs +++ b/MediaBrowser.Api/PluginService.cs @@ -141,7 +141,7 @@ namespace MediaBrowser.Api /// <returns>System.Object.</returns> public object Get(GetPluginAssembly request) { - var plugin = Kernel.Plugins.First(p => p.UniqueId == request.Id); + var plugin = Kernel.Plugins.First(p => p.Id == request.Id); return ToStaticFileResult(plugin.AssemblyFilePath); } @@ -153,7 +153,7 @@ namespace MediaBrowser.Api /// <returns>System.Object.</returns> public object Get(GetPluginConfiguration request) { - var plugin = Kernel.Plugins.First(p => p.UniqueId == request.Id); + var plugin = Kernel.Plugins.First(p => p.Id == request.Id); var dateModified = plugin.ConfigurationDateLastModified; @@ -169,7 +169,7 @@ namespace MediaBrowser.Api /// <returns>System.Object.</returns> public object Get(GetPluginConfigurationFile request) { - var plugin = Kernel.Plugins.First(p => p.UniqueId == request.Id); + var plugin = Kernel.Plugins.First(p => p.Id == request.Id); return ToStaticFileResult(plugin.ConfigurationFilePath); } @@ -218,7 +218,7 @@ namespace MediaBrowser.Api var pathInfo = PathInfo.Parse(Request.PathInfo); var id = new Guid(pathInfo.GetArgumentValue<string>(1)); - var plugin = Kernel.Plugins.First(p => p.UniqueId == id); + var plugin = Kernel.Plugins.First(p => p.Id == id); var configuration = JsonSerializer.DeserializeFromStream(request.RequestStream, plugin.ConfigurationType) as BasePluginConfiguration; @@ -233,7 +233,7 @@ namespace MediaBrowser.Api { var kernel = (Kernel)Kernel; - var plugin = kernel.Plugins.First(p => p.UniqueId == request.Id); + var plugin = kernel.Plugins.First(p => p.Id == request.Id); kernel.InstallationManager.UninstallPlugin(plugin); } diff --git a/MediaBrowser.ApiInteraction.Javascript/ApiClient.js b/MediaBrowser.ApiInteraction.Javascript/ApiClient.js index 0b185a55e..df1c8f2c0 100644 --- a/MediaBrowser.ApiInteraction.Javascript/ApiClient.js +++ b/MediaBrowser.ApiInteraction.Javascript/ApiClient.js @@ -382,15 +382,15 @@ var ApiClient = { /** * Gets the configuration of a plugin - * @param {String} uniqueId + * @param {String} Id */ - getPluginConfiguration: function (uniqueId) { + getPluginConfiguration: function (id) { - if (!uniqueId) { - throw new Error("null uniqueId"); + if (!id) { + throw new Error("null Id"); } - var url = ApiClient.getUrl("Plugins/" + uniqueId + "/Configuration"); + var url = ApiClient.getUrl("Plugins/" + id + "/Configuration"); return $.getJSON(url); }, @@ -407,15 +407,15 @@ var ApiClient = { /** * Uninstalls a plugin - * @param {String} uniqueId + * @param {String} Id */ - uninstallPlugin: function (uniqueId) { + uninstallPlugin: function (id) { - if (!uniqueId) { - throw new Error("null uniqueId"); + if (!id) { + throw new Error("null Id"); } - var url = ApiClient.getUrl("Plugins/" + uniqueId); + var url = ApiClient.getUrl("Plugins/" + id); return $.ajax({ type: "DELETE", @@ -1207,20 +1207,20 @@ var ApiClient = { /** * Updates a plugin's configuration - * @param {String} uniqueId + * @param {String} Id * @param {Object} configuration */ - updatePluginConfiguration: function (uniqueId, configuration) { + updatePluginConfiguration: function (id, configuration) { - if (!uniqueId) { - throw new Error("null uniqueId"); + if (!id) { + throw new Error("null Id"); } if (!configuration) { throw new Error("null configuration"); } - var url = ApiClient.getUrl("Plugins/" + uniqueId + "/Configuration"); + var url = ApiClient.getUrl("Plugins/" + id + "/Configuration"); return $.post(url, JSON.stringify(configuration)); }, diff --git a/MediaBrowser.ApiInteraction/ApiClient.cs b/MediaBrowser.ApiInteraction/ApiClient.cs index cecb6a30b..ef8197e16 100644 --- a/MediaBrowser.ApiInteraction/ApiClient.cs +++ b/MediaBrowser.ApiInteraction/ApiClient.cs @@ -362,7 +362,7 @@ namespace MediaBrowser.ApiInteraction throw new ArgumentNullException("plugin"); } - var url = GetApiUrl("Plugins/" + plugin.UniqueId + "/Assembly"); + var url = GetApiUrl("Plugins/" + plugin.Id + "/Assembly"); return HttpClient.GetStreamAsync(url, Logger, CancellationToken.None); } diff --git a/MediaBrowser.Common/Plugins/BasePlugin.cs b/MediaBrowser.Common/Plugins/BasePlugin.cs index 98b2f8161..d089aa1b3 100644 --- a/MediaBrowser.Common/Plugins/BasePlugin.cs +++ b/MediaBrowser.Common/Plugins/BasePlugin.cs @@ -90,7 +90,7 @@ namespace MediaBrowser.Common.Plugins /// Gets the unique id. /// </summary> /// <value>The unique id.</value> - public Guid UniqueId + public Guid Id { get { @@ -419,7 +419,7 @@ namespace MediaBrowser.Common.Plugins ConfigurationDateLastModified = ConfigurationDateLastModified, Description = Description, IsCorePlugin = IsCorePlugin, - UniqueId = UniqueId, + Id = Id, EnableAutoUpdate = Configuration.EnableAutoUpdate, UpdateClass = Configuration.UpdateClass, ConfigurationFileName = ConfigurationFileName diff --git a/MediaBrowser.Common/Plugins/IPlugin.cs b/MediaBrowser.Common/Plugins/IPlugin.cs index fdd99868a..198678491 100644 --- a/MediaBrowser.Common/Plugins/IPlugin.cs +++ b/MediaBrowser.Common/Plugins/IPlugin.cs @@ -35,7 +35,7 @@ namespace MediaBrowser.Common.Plugins /// Gets the unique id. /// </summary> /// <value>The unique id.</value> - Guid UniqueId { get; } + Guid Id { get; } /// <summary> /// Gets the plugin version diff --git a/MediaBrowser.Controller/Kernel.cs b/MediaBrowser.Controller/Kernel.cs index a8cfb8dd7..952160b2b 100644 --- a/MediaBrowser.Controller/Kernel.cs +++ b/MediaBrowser.Controller/Kernel.cs @@ -182,8 +182,8 @@ namespace MediaBrowser.Controller /// Gets the list of plugin configuration pages /// </summary> /// <value>The configuration pages.</value> - [ImportMany(typeof(BaseConfigurationPage))] - public IEnumerable<BaseConfigurationPage> PluginConfigurationPages { get; private set; } + [ImportMany(typeof(IPluginConfigurationPage))] + public IEnumerable<IPluginConfigurationPage> PluginConfigurationPages { get; private set; } /// <summary> /// Gets the intro providers. diff --git a/MediaBrowser.Controller/MediaBrowser.Controller.csproj b/MediaBrowser.Controller/MediaBrowser.Controller.csproj index 0bf3e6c1f..27d67fd17 100644 --- a/MediaBrowser.Controller/MediaBrowser.Controller.csproj +++ b/MediaBrowser.Controller/MediaBrowser.Controller.csproj @@ -128,7 +128,7 @@ <Compile Include="Persistence\IUserRepository.cs" /> <Compile Include="Persistence\TypeMapper.cs" /> <Compile Include="Playback\IIntroProvider.cs" /> - <Compile Include="Plugins\BaseConfigurationPage.cs" /> + <Compile Include="Plugins\IPluginConfigurationPage.cs" /> <Compile Include="Plugins\PluginSecurityManager.cs" /> <Compile Include="Providers\FanartBaseProvider.cs" /> <Compile Include="Providers\BaseImageEnhancer.cs" /> diff --git a/MediaBrowser.Controller/Plugins/BaseConfigurationPage.cs b/MediaBrowser.Controller/Plugins/BaseConfigurationPage.cs deleted file mode 100644 index dc9405840..000000000 --- a/MediaBrowser.Controller/Plugins/BaseConfigurationPage.cs +++ /dev/null @@ -1,81 +0,0 @@ -using MediaBrowser.Common.Plugins; -using System.IO; - -namespace MediaBrowser.Controller.Plugins -{ - /// <summary> - /// Class BaseConfigurationPage - /// </summary> - public abstract class BaseConfigurationPage - { - /// <summary> - /// Gets the name. - /// </summary> - /// <value>The name.</value> - public abstract string Name { get; } - - /// <summary> - /// Gets the description. - /// </summary> - /// <value>The description.</value> - public virtual string Description - { - get { return string.Empty; } - } - - /// <summary> - /// Gets the type of the configuration page. - /// </summary> - /// <value>The type of the configuration page.</value> - public virtual ConfigurationPageType ConfigurationPageType - { - get { return ConfigurationPageType.PluginConfiguration; } - } - - /// <summary> - /// Gets the HTML stream from manifest resource. - /// </summary> - /// <param name="resource">The resource.</param> - /// <returns>Stream.</returns> - protected Stream GetHtmlStreamFromManifestResource(string resource) - { - return GetType().Assembly.GetManifestResourceStream(resource); - } - - /// <summary> - /// Gets the HTML stream. - /// </summary> - /// <returns>Stream.</returns> - public abstract Stream GetHtmlStream(); - - /// <summary> - /// Gets the name of the plugin. - /// </summary> - /// <value>The name of the plugin.</value> - public virtual string OwnerPluginName - { - get { return GetOwnerPlugin().Name; } - } - - /// <summary> - /// Gets the owner plugin. - /// </summary> - /// <returns>BasePlugin.</returns> - public abstract IPlugin GetOwnerPlugin(); - } - - /// <summary> - /// Enum ConfigurationPageType - /// </summary> - public enum ConfigurationPageType - { - /// <summary> - /// The plugin configuration - /// </summary> - PluginConfiguration, - /// <summary> - /// The none - /// </summary> - None - } -} diff --git a/MediaBrowser.Controller/Plugins/IPluginConfigurationPage.cs b/MediaBrowser.Controller/Plugins/IPluginConfigurationPage.cs new file mode 100644 index 000000000..38fe36857 --- /dev/null +++ b/MediaBrowser.Controller/Plugins/IPluginConfigurationPage.cs @@ -0,0 +1,61 @@ +using System; +using System.IO; + +namespace MediaBrowser.Controller.Plugins +{ + /// <summary> + /// Interface IConfigurationPage + /// </summary> + public interface IPluginConfigurationPage + { + /// <summary> + /// Gets the name. + /// </summary> + /// <value>The name.</value> + string Name { get; } + + /// <summary> + /// Gets the type of the configuration page. + /// </summary> + /// <value>The type of the configuration page.</value> + ConfigurationPageType ConfigurationPageType { get; } + + /// <summary> + /// Gets the plugin id. + /// </summary> + /// <value>The plugin id.</value> + Guid? PluginId { get; } + + /// <summary> + /// Gets the HTML stream. + /// </summary> + /// <returns>Stream.</returns> + Stream GetHtmlStream(); + + /// <summary> + /// Gets the version. Typically taken from Plugin.Version + /// </summary> + /// <value>The version.</value> + string Version { get; } + + /// <summary> + /// For http caching purposes. Typically taken from Plugin.AssemblyDateLastModified + /// </summary> + DateTime DateLastModified { get; } + } + + /// <summary> + /// Enum ConfigurationPageType + /// </summary> + public enum ConfigurationPageType + { + /// <summary> + /// The plugin configuration + /// </summary> + PluginConfiguration, + /// <summary> + /// The none + /// </summary> + None + } +} diff --git a/MediaBrowser.Model/Plugins/PluginInfo.cs b/MediaBrowser.Model/Plugins/PluginInfo.cs index b51834280..0fe6fb6db 100644 --- a/MediaBrowser.Model/Plugins/PluginInfo.cs +++ b/MediaBrowser.Model/Plugins/PluginInfo.cs @@ -71,7 +71,7 @@ namespace MediaBrowser.Model.Plugins /// </summary> /// <value>The unique id.</value> [ProtoMember(9)] - public Guid UniqueId { get; set; } + public Guid Id { get; set; } /// <summary> /// Whether or not this plug-in should be automatically updated when a diff --git a/MediaBrowser.Plugins.Dlna/Configuration/DlnaConfigurationPage.cs b/MediaBrowser.Plugins.Dlna/Configuration/DlnaConfigurationPage.cs deleted file mode 100644 index 44b6004af..000000000 --- a/MediaBrowser.Plugins.Dlna/Configuration/DlnaConfigurationPage.cs +++ /dev/null @@ -1,50 +0,0 @@ -using MediaBrowser.Common.Plugins; -using MediaBrowser.Controller.Plugins; -using System.ComponentModel.Composition; -using System.IO; - -namespace MediaBrowser.Plugins.Dlna.Configuration -{ - /// <summary> - /// Class DlnaConfigurationPage - /// </summary> - [Export(typeof(BaseConfigurationPage))] - class DlnaConfigurationPage : BaseConfigurationPage - { - /// <summary> - /// Gets the name. - /// </summary> - /// <value>The name.</value> - public override string Name - { - get { return "Dlna"; } - } - - /// <summary> - /// Gets the HTML stream. - /// </summary> - /// <returns>Stream.</returns> - public override Stream GetHtmlStream() - { - return GetHtmlStreamFromManifestResource("MediaBrowser.Plugins.Dlna.Configuration.configPage.html"); - } - - /// <summary> - /// Gets the owner plugin. - /// </summary> - /// <returns>BasePlugin.</returns> - public override IPlugin GetOwnerPlugin() - { - return Plugin.Instance; - } - - /// <summary> - /// Gets the type of the configuration page. - /// </summary> - /// <value>The type of the configuration page.</value> - public override ConfigurationPageType ConfigurationPageType - { - get { return ConfigurationPageType.PluginConfiguration; } - } - } -} diff --git a/MediaBrowser.Plugins.Dlna/Configuration/PluginConfiguration.cs b/MediaBrowser.Plugins.Dlna/Configuration/PluginConfiguration.cs deleted file mode 100644 index 47a56c9cf..000000000 --- a/MediaBrowser.Plugins.Dlna/Configuration/PluginConfiguration.cs +++ /dev/null @@ -1,39 +0,0 @@ -using MediaBrowser.Model.Plugins; - -namespace MediaBrowser.Plugins.Dlna.Configuration -{ - /// <summary> - /// Class PluginConfiguration - /// </summary> - public class PluginConfiguration : BasePluginConfiguration - { - /// <summary> - /// Gets or sets the friendly name of the DLNA Server. - /// </summary> - /// <value>The friendly name of the DLNA Server.</value> - public string FriendlyDlnaName { get; set; } - - /// <summary> - /// Gets or sets the Port Number for the DLNA Server. - /// </summary> - /// <value>The Port Number of the DLNA Server.</value> - public short? DlnaPortNumber { get; set; } - - /// <summary> - /// Gets or sets the name of the user to impersonate. - /// </summary> - /// <value>The name of the User.</value> - public string UserName { get; set; } - - /// <summary> - /// Initializes a new instance of the <see cref="PluginConfiguration" /> class. - /// </summary> - public PluginConfiguration() - : base() - { - //this.DlnaPortNumber = 1845; - this.FriendlyDlnaName = "MB3 UPnP"; - this.UserName = string.Empty; - } - } -} diff --git a/MediaBrowser.Plugins.Dlna/Configuration/configPage.html b/MediaBrowser.Plugins.Dlna/Configuration/configPage.html deleted file mode 100644 index 7a147f7c1..000000000 --- a/MediaBrowser.Plugins.Dlna/Configuration/configPage.html +++ /dev/null @@ -1,92 +0,0 @@ -<!DOCTYPE html> -<html> -<head> - <title>dlna</title> -</head> -<body> - <div id="dlnaConfigurationPage" data-role="page" class="page type-interior pluginConfigurationPage"> - - <div data-role="content"> - <div class="content-primary"> - <form id="dlnaConfigurationForm"> - - <ul class="ulForm" data-role="listview"> - <li> - <label for="txtUserName"> - User name: - </label> - <input id="txtUserName" name="txtUserName" /> - </li> - <li> - <label for="txtFriendlyDlnaName"> - Friendly Dlna Server Name: - </label> - <input id="txtFriendlyDlnaName" name="txtFriendlyDlnaName" /> - </li> - <li> - <label for="txtDlnaPortNumber"> - Dlna Server Port: - </label> - <input type="number" id="txtDlnaPortNumber" name="txtDlnaPortNumber" pattern="[0-9]*" min="1" /> - <div class="fieldDescription"> - If specified, the Dlna server will use this port - </div> - </li> - <li> - <button type="submit" data-theme="b">Save</button> - <div class="fieldDescription"> - Saving will restart the dlna server. - </div> - <button type="button" onclick="history.back();">Cancel</button> - </li> - </ul> - - </form> - </div> - </div> - - <script type="text/javascript"> - - var dlnaConfigurationPage = { - pluginUniqueId: "f1855371-7cf5-40d2-bcd8-b780d7f006af" - }; - - $('#dlnaConfigurationPage').on('pageshow', function (event) { - - Dashboard.showLoadingMsg(); - - var page = this; - - ApiClient.getPluginConfiguration(dlnaConfigurationPage.pluginUniqueId).done(function (config) { - - $('#txtUserName', page).val(config.UserName); - $('#txtFriendlyDlnaName', page).val(config.FriendlyDlnaName); - $('#txtDlnaPortNumber', page).val(config.DlnaPortNumber || ""); - - Dashboard.hideLoadingMsg(); - }); - }); - - $('#dlnaConfigurationForm').on('submit', function (e) { - - Dashboard.showLoadingMsg(); - - var form = this; - - ApiClient.getPluginConfiguration(dlnaConfigurationPage.pluginUniqueId).done(function (config) { - - config.UserName = $('#txtUserName', form).val(); - config.FriendlyDlnaName = $('#txtFriendlyDlnaName', form).val(); - var dlnaPortNumber = $('#txtDlnaPortNumber', form).val(); - config.DlnaPortNumber = dlnaPortNumber ? dlnaPortNumber : null; - - ApiClient.updatePluginConfiguration(dlnaConfigurationPage.pluginUniqueId, config).done(Dashboard.processPluginConfigurationUpdateResult); - }); - - // Disable default form submission - return false; - }); - </script> - </div> -</body> -</html> diff --git a/MediaBrowser.Plugins.Dlna/MediaBrowser.Plugins.Dlna.csproj b/MediaBrowser.Plugins.Dlna/MediaBrowser.Plugins.Dlna.csproj deleted file mode 100644 index e5f3e7e18..000000000 --- a/MediaBrowser.Plugins.Dlna/MediaBrowser.Plugins.Dlna.csproj +++ /dev/null @@ -1,91 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<Project ToolsVersion="4.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> - <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform> - <ProjectGuid>{A2CF4266-2110-419E-8620-E2FEEFCA0F48}</ProjectGuid> - <OutputType>Library</OutputType> - <AppDesignerFolder>Properties</AppDesignerFolder> - <RootNamespace>MediaBrowser.Plugins.Dlna</RootNamespace> - <AssemblyName>MediaBrowser.Plugins.Dlna</AssemblyName> - <TargetFrameworkVersion>v4.5</TargetFrameworkVersion> - <FileAlignment>512</FileAlignment> - </PropertyGroup> - <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' "> - <DebugSymbols>true</DebugSymbols> - <DebugType>full</DebugType> - <Optimize>false</Optimize> - <OutputPath>bin\Debug\</OutputPath> - <DefineConstants>DEBUG;TRACE</DefineConstants> - <ErrorReport>prompt</ErrorReport> - <WarningLevel>4</WarningLevel> - <CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet> - </PropertyGroup> - <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' "> - <DebugType>pdbonly</DebugType> - <Optimize>true</Optimize> - <OutputPath>bin\Release\</OutputPath> - <DefineConstants>TRACE</DefineConstants> - <ErrorReport>prompt</ErrorReport> - <WarningLevel>4</WarningLevel> - </PropertyGroup> - <PropertyGroup> - <RunPostBuildEvent>Always</RunPostBuildEvent> - </PropertyGroup> - <ItemGroup> - <Reference Include="Platinum.Managed"> - <HintPath>..\ThirdParty\UPnP\Libs\Platinum.Managed.dll</HintPath> - </Reference> - <Reference Include="System" /> - <Reference Include="System.ComponentModel.Composition" /> - <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="Configuration\DlnaConfigurationPage.cs" /> - <Compile Include="Configuration\PluginConfiguration.cs" /> - <Compile Include="Plugin.cs" /> - <Compile Include="Properties\AssemblyInfo.cs" /> - </ItemGroup> - <ItemGroup> - <ProjectReference Include="..\MediaBrowser.Common\MediaBrowser.Common.csproj"> - <Project>{9142eefa-7570-41e1-bfcc-468bb571af2f}</Project> - <Name>MediaBrowser.Common</Name> - </ProjectReference> - <ProjectReference Include="..\MediaBrowser.Controller\MediaBrowser.Controller.csproj"> - <Project>{17e1f4e6-8abd-4fe5-9ecf-43d4b6087ba2}</Project> - <Name>MediaBrowser.Controller</Name> - </ProjectReference> - <ProjectReference Include="..\MediaBrowser.Model\MediaBrowser.Model.csproj"> - <Project>{7eeeb4bb-f3e8-48fc-b4c5-70f0fff8329b}</Project> - <Name>MediaBrowser.Model</Name> - </ProjectReference> - </ItemGroup> - <ItemGroup> - <EmbeddedResource Include="..\ThirdParty\UPnP\Libs\Platinum.Managed.dll"> - <Link>Assemblies\Platinum.Managed.dll</Link> - </EmbeddedResource> - </ItemGroup> - <ItemGroup> - <Content Include="..\ThirdParty\UPnP\Libs\log4net.dll"> - <Link>Assemblies\log4net.dll</Link> - </Content> - <EmbeddedResource Include="Configuration\configPage.html" /> - </ItemGroup> - <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" /> - <PropertyGroup> - <PostBuildEvent>xcopy "$(TargetPath)" "$(SolutionDir)\ProgramData-Server\Plugins\" /y</PostBuildEvent> - </PropertyGroup> - <!-- 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"> - </Target> - <Target Name="AfterBuild"> - </Target> - --> -</Project>
\ No newline at end of file diff --git a/MediaBrowser.Plugins.Dlna/Plugin.cs b/MediaBrowser.Plugins.Dlna/Plugin.cs deleted file mode 100644 index 9cca31d34..000000000 --- a/MediaBrowser.Plugins.Dlna/Plugin.cs +++ /dev/null @@ -1,1027 +0,0 @@ -using System; -using System.Collections.Generic; -using System.ComponentModel.Composition; -using System.IO; -using System.Linq; -using System.Reflection; -using MediaBrowser.Common.Extensions; -using MediaBrowser.Common.Net; -using MediaBrowser.Common.Plugins; -using MediaBrowser.Controller.Entities; -using MediaBrowser.Controller.Entities.Audio; -using MediaBrowser.Controller.Entities.TV; -using MediaBrowser.Model.Entities; -using MediaBrowser.Plugins.Dlna.Configuration; - -namespace MediaBrowser.Plugins.Dlna -{ - /// <summary> - /// Class Plugin - /// </summary> - [Export(typeof(IPlugin))] - public class Plugin : BasePlugin<PluginConfiguration> - { - //these are Neptune values, they probably belong in the managed wrapper somewhere, but they aren't - //techincally theres 50 to 100 of these values, but these 3 seem to be the most useful - private const int NEP_Failure = -1; - private const int NEP_NotImplemented = -2012; - private const int NEP_Success = 0; - - private Platinum.UPnP _Upnp; - private Platinum.MediaConnect _PlatinumServer; - private User _CurrentUser; - - - /// <summary> - /// Gets the name. - /// </summary> - /// <value>The name.</value> - public override string Name - { - get { return "DLNA Server"; } - } - - /// <summary> - /// Gets the description. - /// </summary> - /// <value>The description.</value> - public override string Description - { - get { return "DLNA Server"; } - } - - /// <summary> - /// Gets the instance. - /// </summary> - /// <value>The instance.</value> - public static Plugin Instance { get; private set; } - - /// <summary> - /// Initializes a new instance of the <see cref="Plugin" /> class. - /// </summary> - public Plugin() - : base() - { - Instance = this; - } - - /// <summary> - /// Initializes the on server. - /// </summary> - /// <param name="isFirstRun">if set to <c>true</c> [is first run].</param> - protected override void InitializeOnServer(bool isFirstRun) - { - base.InitializeOnServer(isFirstRun); - - Kernel.ReloadCompleted += Kernel_ReloadCompleted; - AppDomain.CurrentDomain.AssemblyResolve += CurrentDomain_AssemblyResolve; - - } - - /// <summary> - /// Handles the AssemblyResolve event of the CurrentDomain control. - /// </summary> - /// <param name="sender">The source of the event.</param> - /// <param name="args">The <see cref="ResolveEventArgs" /> instance containing the event data.</param> - /// <returns>Assembly.</returns> - Assembly CurrentDomain_AssemblyResolve(object sender, ResolveEventArgs args) - { - var askedAssembly = new AssemblyName(args.Name); - - var resourcePath = "MediaBrowser.Plugins.Dlna.Assemblies." + askedAssembly.Name + ".dll"; - - using (var stream = GetType().Assembly.GetManifestResourceStream(resourcePath)) - { - if (stream != null) - { - Logger.Info("Loading assembly from resource {0}", resourcePath); - - using (var memoryStream = new MemoryStream()) - { - stream.CopyTo(memoryStream); - - memoryStream.Position = 0; - - return Assembly.Load(memoryStream.ToArray()); - } - } - } - - return null; - } - - /// <summary> - /// Disposes the on server. - /// </summary> - /// <param name="dispose">if set to <c>true</c> [dispose].</param> - protected override void DisposeOnServer(bool dispose) - { - if (dispose) - { - Kernel.ReloadCompleted -= Kernel_ReloadCompleted; - AppDomain.CurrentDomain.AssemblyResolve -= CurrentDomain_AssemblyResolve; - DisposeDlnaServer(); - } - - base.DisposeOnServer(dispose); - } - - /// <summary> - /// Handles the ReloadCompleted event of the Kernel control. - /// </summary> - /// <param name="sender">The source of the event.</param> - /// <param name="e">The <see cref="EventArgs" /> instance containing the event data.</param> - void Kernel_ReloadCompleted(object sender, EventArgs e) - { - InitializeDlnaServer(); - } - - /// <summary> - /// Initializes the dlna server. - /// </summary> - private void InitializeDlnaServer() - { - this.SetupUPnPServer(); - } - - /// <summary> - /// Disposes the dlna server. - /// </summary> - private void DisposeDlnaServer() - { - this.CleanupUPnPServer(); - } - - private void SetupUPnPServer() - { - - this._Upnp = new Platinum.UPnP(); - // Will need a config setting to set the friendly name of the upnp server - //this._PlatinumServer = new Platinum.MediaConnect("MB3 UPnP", "MB3UPnP", 1901); - if (this.Configuration.DlnaPortNumber.HasValue) - this._PlatinumServer = new Platinum.MediaConnect(this.Configuration.FriendlyDlnaName, "MB3UPnP", this.Configuration.DlnaPortNumber.Value); - else - this._PlatinumServer = new Platinum.MediaConnect(this.Configuration.FriendlyDlnaName); - - this._PlatinumServer.BrowseMetadata += new Platinum.MediaConnect.BrowseMetadataDelegate(server_BrowseMetadata); - this._PlatinumServer.BrowseDirectChildren += new Platinum.MediaConnect.BrowseDirectChildrenDelegate(server_BrowseDirectChildren); - this._PlatinumServer.ProcessFileRequest += new Platinum.MediaConnect.ProcessFileRequestDelegate(server_ProcessFileRequest); - this._PlatinumServer.SearchContainer += new Platinum.MediaConnect.SearchContainerDelegate(server_SearchContainer); - - this._Upnp.AddDeviceHost(this._PlatinumServer); - this._Upnp.Start(); - } - - private void CleanupUPnPServer() - { - if (this._Upnp != null && this._Upnp.Running) - this._Upnp.Stop(); - - if (this._PlatinumServer != null) - { - this._PlatinumServer.BrowseMetadata -= new Platinum.MediaConnect.BrowseMetadataDelegate(server_BrowseMetadata); - this._PlatinumServer.BrowseDirectChildren -= new Platinum.MediaConnect.BrowseDirectChildrenDelegate(server_BrowseDirectChildren); - this._PlatinumServer.ProcessFileRequest -= new Platinum.MediaConnect.ProcessFileRequestDelegate(server_ProcessFileRequest); - this._PlatinumServer.SearchContainer -= new Platinum.MediaConnect.SearchContainerDelegate(server_SearchContainer); - - this._PlatinumServer.Dispose(); - this._PlatinumServer = null; - } - - if (this._Upnp != null) - { - this._Upnp.Dispose(); - this._Upnp = null; - } - } - - private int server_BrowseMetadata(Platinum.Action action, string object_id, string filter, int starting_index, int requested_count, string sort_criteria, Platinum.HttpRequestContext context) - { - Logger.Info("BrowseMetadata Entered - Parameters: action:{0} object_id:{1} filter:{2} starting_index:{3} requested_count:{4} sort_criteria:{5} context:{6}", - action.ToLogString(), object_id, filter, starting_index, requested_count, sort_criteria, context.ToLogString()); - - //nothing much seems to call BrowseMetadata so far - //but perhaps that is because we aren't handing out the correct info for the client to call this... I don't know - - //PS3 calls it - //Parameters: action:Action Name:Browse Description:Platinum.ActionDescription Arguments: object_id:0 - //filter:@id,upnp:class,res,res@protocolInfo,res@av:authenticationUri,res@size,dc:title,upnp:albumArtURI,res@dlna:ifoFileURI,res@protection,res@bitrate,res@duration,res@sampleFrequency,res@bitsPerSample,res@nrAudioChannels,res@resolution,res@colorDepth,dc:date,av:dateTime,upnp:artist,upnp:album,upnp:genre,dc:contributer,upnp:storageFree,upnp:storageUsed,upnp:originalTrackNumber,dc:publisher,dc:language,dc:region,dc:description,upnp:toc,@childCount,upnp:albumArtURI@dlna:profileID,res@dlna:cleartextSize - //starting_index:0 requested_count:1 sort_criteria: context:HttpRequestContext LocalAddress:HttpRequestContext.SocketAddress IP:192.168.1.56 Port:1845 RemoteAddress:HttpRequestContext.SocketAddress IP:192.168.1.40 Port:49277 Request:http://192.168.1.56:1845/ContentDirectory/7c6b1b90-872b-2cda-3c5c-21a0e430ce5e/control.xml Signature:PS3 - - - - if (object_id == "0") - { - var root = new Platinum.MediaContainer(); - root.Title = "Root"; - root.ObjectID = "0"; - root.ParentID = "-1"; - root.Class = new Platinum.ObjectClass("object.container.storageFolder", ""); - - var didl = Platinum.Didl.header + root.ToDidl(filter) + Platinum.Didl.footer; - action.SetArgumentValue("Result", didl); - action.SetArgumentValue("NumberReturned", "1"); - action.SetArgumentValue("TotalMatches", "1"); - - // update ID may be wrong here, it should be the one of the container? - action.SetArgumentValue("UpdateId", "1"); - - return NEP_Success; - } - else - { - return NEP_Failure; - } - } - private int server_BrowseDirectChildren(Platinum.Action action, String object_id, String filter, Int32 starting_index, Int32 requested_count, String sort_criteria, Platinum.HttpRequestContext context) - { - Logger.Info("BrowseDirectChildren Entered - Parameters: action:{0} object_id:{1} filter:{2} starting_index:{3} requested_count:{4} sort_criteria:{5} context:{6}", - action.ToLogString(), object_id, filter, starting_index, requested_count, sort_criteria, context.ToLogString()); - - //WMP doesn't care how many results we return and what type they are - //Xbox360 Music App is unknown, it calls SearchContainer and stops, not sure what will happen once we return it results - //XBox360 Video App has fairly specific filter string and it need it - if you serve it music (mp3), it'll put music in the video list, so we have to do our own filtering - - //XBox360 Video App - // action: "Browse" - // object_id: "15" - // filter: "dc:title,res,res@protection,res@duration,res@bitrate,upnp:genre,upnp:actor,res@microsoft:codec" - // starting_index: 0 - // requested_count: 100 - // sort_criteria: "+upnp:class,+dc:title" - // - //the wierd thing about the filter is that there isn't much in it that says "only give me video"... except... - //if we look at the doc available here: http://msdn.microsoft.com/en-us/library/windows/hardware/gg487545.aspx which describes the way WMP does its DLNA serving (not clienting) - //doc is also a search cached google docs here: https://docs.google.com/viewer?a=v&q=cache:tnrdpTFCc84J:download.microsoft.com/download/0/0/b/00bba048-35e6-4e5b-a3dc-36da83cbb0d1/NetCompat_WMP11.docx+&hl=en&gl=au&pid=bl&srcid=ADGEESiBSKE1ZJeWmgYVOkKmRJuYaSL3_50KL1o6Ugp28JL1Ytq-2QbEeu6xFD8rbWcX35ZG4d7qPQnzqURGR5vig79S2Arj5umQNPnLeJo1k5_iWYbqPejeMHwwAv0ATmq2ynoZCBNL&sig=AHIEtbQ2qZJ8xMXLZYBWHHerezzXShKoVg - //it describes object 15 as beeing Root/Video/Folders which can contain object.storageFolder - //so perhaps thats what is saying 'only give me video' - //I'm just not sure if those folders listed with object IDs are all well known across clients or if these ones are WMP specific - //if they are device specific but also significant, then that might explain why Plex goes to the trouble of having configurable client device profiles for its DLNA server - - var didl = Platinum.Didl.header; - - IEnumerable<BaseItem> children = null; - - // I need to ask someone on the MB team if there's a better way to do this, it seems like it - //could get pretty expensive to get ALL children all the time - //if it's our only option perhaps we should cache results locally or something similar - children = this.CurrentUser.RootFolder.GetRecursiveChildren(this.CurrentUser); - //children = children.Filter(Extensions.FilterType.Music | Extensions.FilterType.Video).Page(starting_index, requested_count); - - int itemCount = 0; - - if (children != null) - { - foreach (var child in children) - { - - using (var item = BaseItemToMediaItem(child, context)) - { - if (item != null) - { - string test; - test = item.ToDidl(filter); - didl += item.ToDidl(filter); - itemCount++; - } - } - } - - didl += Platinum.Didl.footer; - - action.SetArgumentValue("Result", didl); - action.SetArgumentValue("NumberReturned", itemCount.ToString()); - action.SetArgumentValue("TotalMatches", itemCount.ToString()); - - // update ID may be wrong here, it should be the one of the container? - action.SetArgumentValue("UpdateId", "1"); - - return NEP_Success; - } - return NEP_Failure; - } - private int server_ProcessFileRequest(Platinum.HttpRequestContext context, Platinum.HttpResponse response) - { - Logger.Info("ProcessFileRequest Entered - Parameters: context:{0} response:{1}", - context.ToLogString(), response); - - Uri uri = context.Request.URI; - var id = uri.AbsolutePath.TrimStart('/'); - Guid itemID; - if (Guid.TryParseExact(id, "D", out itemID)) - { - var item = this.CurrentUser.RootFolder.FindItemById(itemID, this.CurrentUser); - - if (item != null) - { - //this is how the Xbox 360 Video app asks for artwork, it tacks this query string onto its request - //?albumArt=true - if (uri.Query == "?albumArt=true") - { - if (!string.IsNullOrWhiteSpace(item.PrimaryImagePath)) - //let see if we can serve artwork like this to the Xbox 360 Video App - Platinum.MediaServer.SetResponseFilePath(context, response, Kernel.HttpServerUrlPrefix.Replace("+", context.LocalAddress.ip) + "/api/image?id=" + item.Id.ToString() + "&type=primary"); - //Platinum.MediaServer.SetResponseFilePath(context, response, item.PrimaryImagePath); - } - else - Platinum.MediaServer.SetResponseFilePath(context, response, item.Path); - //this does not work for WMP - //Platinum.MediaServer.SetResponseFilePath(context, response, Kernel.HttpServerUrlPrefix.Replace("+", context.LocalAddress.ip) + "/api/video.ts?id=" + item.Id.ToString()); - - return NEP_Success; - } - } - return NEP_Failure; - } - private int server_SearchContainer(Platinum.Action action, string object_id, string searchCriteria, string filter, int starting_index, int requested_count, string sort_criteria, Platinum.HttpRequestContext context) - { - Logger.Info("SearchContainer Entered - Parameters: action:{0} object_id:{1} searchCriteria:{7} filter:{2} starting_index:{3} requested_count:{4} sort_criteria:{5} context:{6}", - action.ToLogString(), object_id, filter, starting_index, requested_count, sort_criteria, context.ToLogString(), searchCriteria); - - //Doesn't call search at all: - // XBox360 Video App - - //Calls search but does not require it to be implemented: - // WMP, probably uses it just for its "images" section - - //Calls search Seems to require it: - // XBox360 Music App - - //WMP - // action: "Search" - // object_id: "0" - // searchCriteria: "upnp:class derivedfrom \"object.item.imageItem\" and @refID exists false" - // filter: "*" - // starting_index: 0 - // requested_count: 200 - // sort_criteria: "-dc:date" - - //XBox360 Music App - // action: "Search" - // object_id: "7" - // searchCriteria: "(upnp:class = \"object.container.album.musicAlbum\")" - // filter: "dc:title,upnp:artist" - // starting_index: 0 - // requested_count: 1000 - // sort_criteria: "+dc:title" - // - //XBox360 Music App seems to work souly using SearchContainer and ProcessFileRequest - //I think the current resource Uri's aren't going to work because it seems to require an extension like .mp3 to work, but this requires further testing - //When hitting the Album tab of the app it's searching criteria is object.container.album.musicAlbum - //this means it wants albums put into containers, I thought Platinum might do this for us, but it doesn't - - - var didl = Platinum.Didl.header; - - IEnumerable<BaseItem> children = null; - - // I need to ask someone on the MB team if there's a better way to do this, it seems like it - //could get pretty expensive to get ALL children all the time - //if it's our only option perhaps we should cache results locally or something similar - children = this.CurrentUser.RootFolder.GetRecursiveChildren(this.CurrentUser); - //children = children.Filter(Extensions.FilterType.Music | Extensions.FilterType.Video).Page(starting_index, requested_count); - - //var test = GetFilterFromCriteria(searchCriteria); - children = children.Where(GetBaseItemMatchFromCriteria(searchCriteria)); - - - int itemCount = 0; - - if (children != null) - { - Platinum.MediaItem item = null; - foreach (var child in children) - { - item = BaseItemToMediaItem(child, context); - - if (item != null) - { - item.ParentID = string.Empty; - - didl += item.ToDidl(filter); - itemCount++; - } - } - - didl += Platinum.Didl.footer; - - action.SetArgumentValue("Result", didl); - action.SetArgumentValue("NumberReturned", itemCount.ToString()); - action.SetArgumentValue("TotalMatches", itemCount.ToString()); - - // update ID may be wrong here, it should be the one of the container? - action.SetArgumentValue("UpdateId", "1"); - - return NEP_Success; - } - return NEP_Failure; - } - - private Platinum.MediaItem BaseItemToMediaItem(BaseItem child, Platinum.HttpRequestContext context) - { - Platinum.MediaItem result = null; - Platinum.MediaResource resource = null; - - if (child.IsFolder) - { - //DLNA is a fairly flat system, there doesn't appear to be much room in the system for folders so far - //I haven't tested too many DLNA clients yet tho - result = null; - //item = new Platinum.MediaItem(); - //item.Class = new Platinum.ObjectClass("object.container.storageFolder", ""); - } - else if (child is Episode) - { - result = MediaItemHelper.GetMediaItem((Episode)child); - resource = MediaItemHelper.GetMediaResource((Episode)child); - } - else if (child is Video) - { - result = MediaItemHelper.GetMediaItem((Video)child); - resource = MediaItemHelper.GetMediaResource((Video)child); - } - else if (child is Audio) - { - result = MediaItemHelper.GetMediaItem((Audio)child); - resource = MediaItemHelper.GetMediaResource((Audio)child); - } - - if (result != null) - { - //have a go at finding the mime type - var mimeType = string.Empty; - if (child.Path != null && Path.HasExtension(child.Path)) - mimeType = MimeTypes.GetMimeType(child.Path); - - resource.ProtoInfo = Platinum.ProtocolInfo.GetProtocolInfoFromMimeType(mimeType, true, context); - - // get list of ips and make sure the ip the request came from is used for the first resource returned - // this ensures that clients which look only at the first resource will be able to reach the item - IEnumerable<String> ips = GetUPnPIPAddresses(context); //.Distinct(); - - // iterate through all ips and create a resource for each - // I think we need extensions (".mp3" type extensions) on these for Xbox360 Video and Music apps to work - - - //resource.URI = new Uri(Kernel.HttpServerUrlPrefix + "/api/video.ts?id=" + child.Id.ToString("D")).ToString(); - //result.AddResource(resource); - - foreach (String ip in ips) - { - //doesn't work for WMP - //resource.URI = new Uri(Kernel.HttpServerUrlPrefix.Replace("+", ip) + "/api/video.ts?id=" + child.Id.ToString()).ToString(); - resource.URI = new Uri("http://" + ip + ":" + context.LocalAddress.port + "/" + child.Id.ToString("D")).ToString(); - - result.AddResource(resource); - } - MediaItemHelper.AddAlbumArtInfoToMediaItem(result, child, Kernel.HttpServerUrlPrefix, ips); - } - - return result; - } - - private void AddResourcesToMediaItem(Platinum.MediaItem item, BaseItem child, Platinum.HttpRequestContext context) - { - Platinum.MediaResource resource = null; - - if (child is Video) - { - var videoChild = (Video)child; - resource = new Platinum.MediaResource(); - - if (videoChild.DefaultVideoStream != null) - { - //Bitrate is Bytes per second - if (videoChild.DefaultVideoStream.BitRate.HasValue) - resource.Bitrate = (uint)videoChild.DefaultVideoStream.BitRate; - - //not sure if we know Colour Depth - //resource.ColorDepth - if (videoChild.DefaultVideoStream.Channels.HasValue) - resource.NbAudioChannels = (uint)videoChild.DefaultVideoStream.Channels.Value; - - //resource.Protection - //resource.ProtoInfo - - //we must know resolution, I'm just not sure how to get it - //resource.Resolution - - //I'm not sure what this actually means, is it Sample Rate - if (videoChild.DefaultVideoStream.SampleRate.HasValue) - resource.SampleFrequency = (uint)videoChild.DefaultVideoStream.SampleRate.Value; - //file size? - //resource.Size - - } - } - else if (child is Audio) - { - - } - - // get list of ips and make sure the ip the request came from is used for the first resource returned - // this ensures that clients which look only at the first resource will be able to reach the item - List<String> ips = GetUPnPIPAddresses(context); - - // iterate through all ips and create a resource for each - // I think we need extensions (".mp3" type extensions) on these for Xbox360 Video and Music apps to work - - foreach (String ip in ips) - { - resource.URI = new Uri("http://" + ip + ":" + context.LocalAddress.port + "/" + child.Id.ToString("D")).ToString(); - item.AddResource(resource); - } - } - - /// <summary> - /// Gets a list of valid IP Addresses that the UPnP server is using - /// </summary> - /// <param name="context"></param> - /// <returns></returns> - private List<String> GetUPnPIPAddresses(Platinum.HttpRequestContext context) - { - // get list of ips and make sure the ip the request came from is used for the first resource returned - // this ensures that clients which look only at the first resource will be able to reach the item - List<String> result = Platinum.UPnP.GetIpAddresses(true); //if this call is expensive we could cache the results - String localIP = context.LocalAddress.ip; - if (localIP != "0.0.0.0") - { - result.Remove(localIP); - result.Insert(0, localIP); - } - return result; - } - - /// <summary> - /// Gets the MB User with a user name that matches the user name configured in the plugin config - /// </summary> - /// <returns>MediaBrowser.Controller.Entities.User</returns> - private User CurrentUser - { - get - { - if (this._CurrentUser == null) - { - //this looks like a lot of processing but it really isn't - //its mostly gaurding against no users or no matching user existing - var serverKernel = Controller.Kernel.Instance; - if (serverKernel.Users.Any()) - { - if (string.IsNullOrWhiteSpace(this.Configuration.UserName)) - this._CurrentUser = serverKernel.Users.First(); - else - { - this._CurrentUser = serverKernel.Users.FirstOrDefault(i => string.Equals(i.Name, this.Configuration.UserName, StringComparison.OrdinalIgnoreCase)); - if (this._CurrentUser == null) - { - //log and return first user - this._CurrentUser = serverKernel.Users.First(); - Logger.Error("Configured user: \"{0}\" not found. Using first user found: \"{1}\" instead", this.Configuration.UserName, this._CurrentUser.Name); - } - } - } - else - { - Logger.Fatal("No users in the system"); - this._CurrentUser = null; - } - } - return this._CurrentUser; - } - } - - #region "A Search Idea" - //this is just an idea of how we might do some search - //it's a bit lackluster in places and might be overkill in others - //all in all it might not be a good idea, but I thought I'd see how it felt - - private Func<BaseItem, bool> GetBaseItemMatchFromCriteria(string searchCriteria) - { - //WMP Search when clicking Music: - //"upnp:class derivedfrom \"object.item.audioItem\" and @refID exists false" - //WMP Search when clicking Videos: - //"upnp:class derivedfrom \"object.item.videoItem\" and @refID exists false" - //WMP Search when clicking Pictures: - //"upnp:class derivedfrom \"object.item.imageItem\" and @refID exists false" - //WMP Search when clicking Recorded TV: - //"upnp:class derivedfrom \"object.item.videoItem\" and @refID exists false" - - //we really need a syntax tree parser here - //but the requests never seem to get more complex than "'Condition One' And 'Condition Two'" - //something like Rosylin would be fun but it'd be serious overkill - //the syntax seems to be very clear and there are only a handful of valid constructs - //so this very basic parsing will provide some support for now - - Queue<string> criteriaQueue = new Queue<string>(searchCriteria.Split(' ')); - - Func<BaseItem, bool> result = null; - var currentMainOperatorIsAnd = false; - - //loop through in order and process - do not parallelise, order is important - while (criteriaQueue.Any()) - { - Func<BaseItem, bool> currentFilter = null; - - var metadataElement = criteriaQueue.Dequeue(); - var criteriaOperator = criteriaQueue.Dequeue(); - var value = criteriaQueue.Dequeue(); - if (value.StartsWith("\"") || value.StartsWith("\\\"")) - while (!value.EndsWith("\"")) - { - value += criteriaQueue.Dequeue(); - } - value = value.Trim(); - - - if (string.Equals(metadataElement, "upnp:class", StringComparison.OrdinalIgnoreCase)) - currentFilter = GetUpnpClassFilter(criteriaOperator, value); - else if (string.Equals(metadataElement, "@refID", StringComparison.OrdinalIgnoreCase)) - { - //not entirely sure what refID is for - //Platinum has ReferenceID which I assume is the same thing, but we're not using it yet - - } - else - { - //fail?? - } - - - if (currentFilter != null) - { - if (result == null) - result = currentFilter; - else - if (currentMainOperatorIsAnd) - result = (i) => result(i) && currentFilter(i); - else - result = (i) => result(i) || currentFilter(i); - } - if (criteriaQueue.Any()) - { - var op = criteriaQueue.Dequeue(); - if (string.Equals(op, "and", StringComparison.OrdinalIgnoreCase)) - currentMainOperatorIsAnd = true; - else - currentMainOperatorIsAnd = false; - } - } - return result; - } - - private Func<BaseItem, bool> GetUpnpClassFilter(string criteriaOperator, string value) - { - //"upnp:class derivedfrom \"object.item.videoItem\" " - //"(upnp:class = \"object.container.album.musicAlbum\")" - - //only two options are valid for criteria - // =, derivedfrom - - //there are only a few values we care about - //object.item.videoItem - //object.item.audioItem - //object.container.storageFolder - - if (string.Equals(criteriaOperator, "=", StringComparison.OrdinalIgnoreCase)) - { - if (value.Contains("object.item.videoItem")) - return (i) => (i is Video); - else if (value.Contains("object.item.audioItem")) - return (i) => (i is Audio); - else if (value.Contains("object.container.storageFolder")) - return (i) => (i is Folder); - else - //something has gone wrong, don't filter anything - return (i) => true; - } - else if (string.Equals(criteriaOperator, "derivedfrom", StringComparison.OrdinalIgnoreCase)) - { - if (value.Contains("object.item.videoItem")) - return (i) => (i is Video); - else if (value.Contains("object.item.audioItem")) - return (i) => (i is Audio); - else if (value.Contains("object.container.storageFolder")) - return (i) => (i is Folder); - else - //something has gone wrong, don't filter anything - return (i) => true; - } - else - { - //something has gone wrong, don't filter anything - return (i) => true; - } - } - #endregion - - public override void UpdateConfiguration(Model.Plugins.BasePluginConfiguration configuration) - { - base.UpdateConfiguration(configuration); - var config = (PluginConfiguration)configuration; - - this.CleanupUPnPServer(); - this._CurrentUser = null; - this.SetupUPnPServer(); - } - } - - internal static class MediaItemHelper - { - internal static Platinum.MediaResource GetMediaResource(Video item) - { - var result = GetMediaResource((BaseItem)item); - - if (item.DefaultVideoStream != null) - { - //Bitrate is Bytes per second - if (item.DefaultVideoStream.BitRate.HasValue) - result.Bitrate = (uint)item.DefaultVideoStream.BitRate; - - //not sure if we know Colour Depth - //resource.ColorDepth - if (item.DefaultVideoStream.Channels.HasValue) - result.NbAudioChannels = (uint)item.DefaultVideoStream.Channels.Value; - - //resource.Protection - //resource.ProtoInfo - - //we must know resolution, I'm just not sure how to get it - //resource.Resolution - - //I'm not sure what this actually means, is it Sample Rate - if (item.DefaultVideoStream.SampleRate.HasValue) - result.SampleFrequency = (uint)item.DefaultVideoStream.SampleRate.Value; - //file size? - //resource.Size - - ////to do subtitles for clients that can deal with external subtitles (like srt) - ////we will have to do something like this - //IEnumerable<String> ips = GetUPnPIPAddresses(context); - //foreach (var st in videoChild.MediaStreams) - //{ - // if (st.Type == MediaStreamType.Subtitle) - // { - // Platinum.MediaResource subtitleResource = new Platinum.MediaResource(); - // subtitleResource.ProtoInfo = Platinum.ProtocolInfo.GetProtocolInfo(st.Path, with_dlna_extension: false); - // foreach (String ip in ips) - // { - // //we'll need to figure out which of these options works for whick players - // //either serve them ourselves - // resource.URI = new Uri("http://" + ip + ":" + context.LocalAddress.port + "/" + child.Id.ToString("D")).ToString(); - // //or get the web api to serve them directly - // resource.URI = new Uri(Kernel.HttpServerUrlPrefix.Replace("+", ip) + "/api/video?id=" + child.Id.ToString() + "&type=Subtitle").ToString(); - // result.AddResource(resource); - // } - // } - //} - } - return result; - } - internal static Platinum.MediaItem GetMediaItem(Video item) - { - var result = GetMediaItem((BaseItem)item); - result.Title = GetTitle(item); - return result; - } - - internal static Platinum.MediaResource GetMediaResource(Episode item) - { - //there's nothing specific about an episode that requires extra Resources - return GetMediaResource((Video)item); - } - internal static Platinum.MediaItem GetMediaItem(Episode item) - { - var result = GetMediaItem((Video)item); - - if (item.IndexNumber.HasValue) - result.Recorded.EpisodeNumber = (uint)item.IndexNumber.Value; - if (item.Series != null && item.Series.Name != null) - result.Recorded.SeriesTitle = item.Series.Name; - result.Recorded.ProgramTitle = item.Name == null ? string.Empty : item.Name; - - return result; - } - - internal static Platinum.MediaResource GetMediaResource(Audio item) - { - //there's nothing specific about an audio item that requires extra Resources - return GetMediaResource((BaseItem)item); - } - internal static Platinum.MediaItem GetMediaItem(Audio item) - { - var result = GetMediaItem((BaseItem)item); - result.Title = GetTitle(item); - result.People.AddArtist(new Platinum.PersonRole(item.Artist)); - result.People.Contributor = item.AlbumArtist; - result.Affiliation.Album = item.Album; - return result; - } - - internal static Platinum.MediaResource GetMediaResource(BaseItem item) - { - var result = new Platinum.MediaResource(); - //duration is in seconds - if (item.RunTimeTicks.HasValue) - result.Duration = (uint)TimeSpan.FromTicks(item.RunTimeTicks.Value).TotalSeconds; - - return result; - } - internal static Platinum.MediaItem GetMediaItem(BaseItem item) - { - var result = new Platinum.MediaItem(); - - result.ObjectID = item.Id.ToString(); - - //if (child.Parent != null) - // result.ParentID = child.Parent.Id.ToString(); - result.Class = item.GetPlatinumClassObject(); - - result.Description.Date = item.PremiereDate.HasValue ? item.PremiereDate.Value.ToString() : string.Empty; - result.Description.Language = item.Language == null ? string.Empty : item.Language; - result.Description.DescriptionText = "this is DescriptionText"; - result.Description.LongDescriptionText = item.Overview == null ? string.Empty : item.Overview; - result.Description.Rating = item.CommunityRating.ToString(); - - if (item.Genres != null) - { - foreach (var genre in item.Genres) - { - result.Affiliation.AddGenre(genre); - } - } - if (item.People != null) - { - foreach (var person in item.People) - { - if (string.Equals(person.Type, PersonType.Actor, StringComparison.OrdinalIgnoreCase)) - result.People.AddActor(new Platinum.PersonRole(person.Name, person.Role == null ? string.Empty : person.Role)); - else if (string.Equals(person.Type, PersonType.MusicArtist, StringComparison.OrdinalIgnoreCase)) - { - result.People.AddArtist(new Platinum.PersonRole(person.Name, "MusicArtist")); - result.People.AddArtist(new Platinum.PersonRole(person.Name, "Performer")); - } - else if (string.Equals(person.Type, PersonType.Composer, StringComparison.OrdinalIgnoreCase)) - result.People.AddAuthors(new Platinum.PersonRole(person.Name, "Composer")); - else if (string.Equals(person.Type, PersonType.Writer, StringComparison.OrdinalIgnoreCase)) - result.People.AddAuthors(new Platinum.PersonRole(person.Name, "Writer")); - else if (string.Equals(person.Type, PersonType.Director, StringComparison.OrdinalIgnoreCase)) - { - result.People.AddAuthors(new Platinum.PersonRole(person.Name, "Director")); - result.People.Director = result.People.Director + " " + person.Name; - } - else - result.People.AddArtist(new Platinum.PersonRole(person.Name, person.Type == null ? string.Empty : person.Type)); - } - } - return result; - } - - internal static void AddAlbumArtInfoToMediaItem(Platinum.MediaItem item, BaseItem child, string httpServerUrlPrefix, IEnumerable<String> ips) - { - foreach (var ip in ips) - { - AddAlbumArtInfoToMediaItem(item, child, httpServerUrlPrefix, ip); - } - } - private static void AddAlbumArtInfoToMediaItem(Platinum.MediaItem item, BaseItem child, string httpServerUrlPrefix, string ip) - { - //making the artwork a direct hit to the MediaBrowser server instead of via the DLNA plugin works for WMP - item.Extra.AddAlbumArtInfo(new Platinum.AlbumArtInfo(httpServerUrlPrefix.Replace("+", ip) + "/api/image?id=" + child.Id.ToString() + "&type=primary")); - } - - - /// <summary> - /// Gets the title. - /// </summary> - /// <param name="video">The video.</param> - /// <returns>System.String.</returns> - private static string GetTitle(Video video) - { - //we have to be extremely careful with all string handling - //if we set a null reference to a Platinum string it will not marshall to native correctly and things got very bad very quickly - var title = video.Name == null ? string.Empty : video.Name; - - var episode = video as Episode; - - if (episode != null) - { - if (episode.Season != null) - { - title = string.Format("{0}-{1}", episode.Season.Name, title); - } - if (episode.Series != null) - { - title = string.Format("{0}-{1}", episode.Series.Name, title); - } - } - - return title; - } - - /// <summary> - /// Gets the title. - /// </summary> - /// <param name="audio">The audio.</param> - /// <returns>System.String.</returns> - private static string GetTitle(Audio audio) - { - return audio.Name == null ? string.Empty : audio.Name; - } - - } - - internal static class Extensions - { - [Flags()] - internal enum FilterType - { - Folder = 1, - Music = 2, - Video = 4 - } - internal static IEnumerable<BaseItem> Filter(this IEnumerable<BaseItem> en, FilterType filter) - { - return en.Where(i => ( - (((filter & FilterType.Folder) == FilterType.Folder) && (i is Folder)) || - (((filter & FilterType.Music) == FilterType.Music) && (i is Audio)) || - (((filter & FilterType.Video) == FilterType.Video) && (i is Video))) - ); - } - - internal static IEnumerable<BaseItem> Page(this IEnumerable<BaseItem> en, int starting_index, int requested_count) - { - return en.Skip(starting_index).Take(requested_count); - } - - - internal static Platinum.ObjectClass GetPlatinumClassObject(this BaseItem item) - { - if (item is Video) - return new Platinum.ObjectClass("object.item.videoItem", ""); - else if (item is Audio) - return new Platinum.ObjectClass("object.item.audioItem.musicTrack", ""); - else if (item is Folder) - return new Platinum.ObjectClass("object.container.storageFolder", ""); - else - return null; - } - internal static Platinum.ObjectClass GetPlatinumClassObject(this Folder item) - { - return new Platinum.ObjectClass("object.container.storageFolder", ""); - } - internal static Platinum.ObjectClass GetPlatinumClassObject(this Audio item) - { - return new Platinum.ObjectClass("object.item.audioItem.musicTrack", ""); - } - internal static Platinum.ObjectClass GetPlatinumClassObject(this Video item) - { - return new Platinum.ObjectClass("object.item.videoItem", ""); - } - } - internal static class LoggingExtensions - { - //provide some json-esque string that can be used for Verbose logging purposed - internal static string ToLogString(this Platinum.Action item) - { - return string.Format(" {{ Name:\"{0}\", Description:\"{1}\", Arguments:{2} }} ", - item.Name, item.Description.ToLogString(), item.Arguments.ToLogString()); - - } - internal static string ToLogString(this IEnumerable<Platinum.ActionArgumentDescription> items) - { - var result = "["; - foreach (var arg in items) - { - result += (" " + arg.ToLogString()); - } - result += " ]"; - return result; - } - internal static string ToLogString(this Platinum.ActionArgumentDescription item) - { - return string.Format(" {{ Name:\"{0}\", Direction:{1}, HasReturnValue:{2}, RelatedStateVariable:{3} }} ", - item.Name, item.Direction, item.HasReturnValue, item.RelatedStateVariable.ToLogString()); - - } - internal static string ToLogString(this Platinum.StateVariable item) - { - return string.Format(" {{ Name:\"{0}\", DataType:{1}, DataTypeString:\"{2}\", Value:{3}, ValueString:\"{4}\" }} ", - item.Name, item.DataType, item.DataTypeString, item.Value, item.ValueString); - } - internal static string ToLogString(this Platinum.ActionDescription item) - { - return string.Format(" {{ Name:\"{0}\", Arguments:{1} }} ", - item.Name, item.Arguments.ToLogString()); - } - internal static string ToLogString(this Platinum.HttpRequestContext item) - { - return string.Format(" {{ LocalAddress:{0}, RemoteAddress:{1}, Request:\"{2}\", Signature:{3} }}", - item.LocalAddress.ToLogString(), item.RemoteAddress.ToLogString(), item.Request.URI.ToString(), item.Signature); - } - internal static string ToLogString(this Platinum.HttpRequestContext.SocketAddress item) - { - return string.Format("{{ IP:{0}, Port:{1} }}", - item.ip, item.port); - } - } -} diff --git a/MediaBrowser.Plugins.Dlna/Properties/AssemblyInfo.cs b/MediaBrowser.Plugins.Dlna/Properties/AssemblyInfo.cs deleted file mode 100644 index eab7fd5f1..000000000 --- a/MediaBrowser.Plugins.Dlna/Properties/AssemblyInfo.cs +++ /dev/null @@ -1,35 +0,0 @@ -using System.Reflection; -using System.Runtime.CompilerServices; -using System.Runtime.InteropServices; - -// General Information about an assembly is controlled through the following -// set of attributes. Change these attribute values to modify the information -// associated with an assembly. -[assembly: AssemblyTitle("MediaBrowser.Plugins.Dlna")] -[assembly: AssemblyDescription("")] -[assembly: AssemblyConfiguration("")] -[assembly: AssemblyCompany("")] -[assembly: AssemblyProduct("MediaBrowser.Plugins.Dlna")] -[assembly: AssemblyCopyright("Copyright © 2013")] -[assembly: AssemblyTrademark("")] -[assembly: AssemblyCulture("")] - -// Setting ComVisible to false makes the types in this assembly not visible -// to COM components. If you need to access a type in this assembly from -// COM, set the ComVisible attribute to true on that type. -[assembly: ComVisible(false)] - -// The following GUID is for the ID of the typelib if this project is exposed to COM -[assembly: Guid("f1855371-7cf5-40d2-bcd8-b780d7f006af")] - -// Version information for an assembly consists of the following four values: -// -// Major Version -// Minor Version -// Build Number -// Revision -// -// You can specify all the values or you can default the Build and Revision Numbers -// by using the '*' as shown below: -// [assembly: AssemblyVersion("1.0.*")] -[assembly: AssemblyVersion("1.0.*")] diff --git a/MediaBrowser.Plugins.MpcHc/MediaBrowser.Plugins.MpcHc.csproj b/MediaBrowser.Plugins.MpcHc/MediaBrowser.Plugins.MpcHc.csproj deleted file mode 100644 index f95b73b65..000000000 --- a/MediaBrowser.Plugins.MpcHc/MediaBrowser.Plugins.MpcHc.csproj +++ /dev/null @@ -1,109 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<Project ToolsVersion="4.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> - <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform> - <ProjectGuid>{2E94BC08-A7A2-42DD-9893-EAA3DACD1CF9}</ProjectGuid> - <OutputType>library</OutputType> - <AppDesignerFolder>Properties</AppDesignerFolder> - <RootNamespace>MediaBrowser.Plugins.MpcHc</RootNamespace> - <AssemblyName>MediaBrowser.Plugins.MpcHc</AssemblyName> - <TargetFrameworkVersion>v4.5</TargetFrameworkVersion> - <FileAlignment>512</FileAlignment> - <ProjectTypeGuids>{60dc8134-eba5-43b8-bcc9-bb4bc16c2548};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids> - <WarningLevel>4</WarningLevel> - <SolutionDir Condition="$(SolutionDir) == '' Or $(SolutionDir) == '*Undefined*'">..\</SolutionDir> - <RestorePackages>true</RestorePackages> - </PropertyGroup> - <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' "> - <DebugSymbols>true</DebugSymbols> - <DebugType>full</DebugType> - <Optimize>false</Optimize> - <OutputPath>bin\Debug\</OutputPath> - <DefineConstants>DEBUG;TRACE</DefineConstants> - <ErrorReport>prompt</ErrorReport> - <WarningLevel>4</WarningLevel> - </PropertyGroup> - <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' "> - <DebugType>pdbonly</DebugType> - <Optimize>true</Optimize> - <OutputPath>bin\Release\</OutputPath> - <DefineConstants>TRACE</DefineConstants> - <ErrorReport>prompt</ErrorReport> - <WarningLevel>4</WarningLevel> - </PropertyGroup> - <PropertyGroup> - <RunPostBuildEvent>Always</RunPostBuildEvent> - </PropertyGroup> - <ItemGroup> - <Reference Include="System" /> - <Reference Include="System.ComponentModel.Composition" /> - <Reference Include="System.Data" /> - <Reference Include="System.Net.Http" /> - <Reference Include="System.Xml" /> - <Reference Include="Microsoft.CSharp" /> - <Reference Include="System.Core" /> - <Reference Include="System.Xml.Linq" /> - <Reference Include="System.Data.DataSetExtensions" /> - <Reference Include="System.Xaml"> - <RequiredTargetFramework>4.0</RequiredTargetFramework> - </Reference> - <Reference Include="WindowsBase" /> - <Reference Include="PresentationCore" /> - <Reference Include="PresentationFramework" /> - </ItemGroup> - <ItemGroup> - <Compile Include="MpcHcMediaPlayer.cs" /> - <Compile Include="Plugin.cs" /> - <Compile Include="Properties\AssemblyInfo.cs"> - <SubType>Code</SubType> - </Compile> - <Compile Include="Properties\Resources.Designer.cs"> - <AutoGen>True</AutoGen> - <DesignTime>True</DesignTime> - <DependentUpon>Resources.resx</DependentUpon> - </Compile> - <Compile Include="Properties\Settings.Designer.cs"> - <AutoGen>True</AutoGen> - <DependentUpon>Settings.settings</DependentUpon> - <DesignTimeSharedInput>True</DesignTimeSharedInput> - </Compile> - <EmbeddedResource Include="Properties\Resources.resx"> - <Generator>ResXFileCodeGenerator</Generator> - <LastGenOutput>Resources.Designer.cs</LastGenOutput> - </EmbeddedResource> - <None Include="app.config" /> - <None Include="Properties\Settings.settings"> - <Generator>SettingsSingleFileGenerator</Generator> - <LastGenOutput>Settings.Designer.cs</LastGenOutput> - </None> - <AppDesigner Include="Properties\" /> - </ItemGroup> - <ItemGroup> - <ProjectReference Include="..\MediaBrowser.Common\MediaBrowser.Common.csproj"> - <Project>{9142eefa-7570-41e1-bfcc-468bb571af2f}</Project> - <Name>MediaBrowser.Common</Name> - </ProjectReference> - <ProjectReference Include="..\MediaBrowser.Model\MediaBrowser.Model.csproj"> - <Project>{7eeeb4bb-f3e8-48fc-b4c5-70f0fff8329b}</Project> - <Name>MediaBrowser.Model</Name> - </ProjectReference> - <ProjectReference Include="..\MediaBrowser.UI\MediaBrowser.UI.csproj"> - <Project>{b5ece1fb-618e-420b-9a99-8e972d76920a}</Project> - <Name>MediaBrowser.UI</Name> - </ProjectReference> - </ItemGroup> - <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" /> - <PropertyGroup> - <PostBuildEvent>xcopy "$(TargetPath)" "$(SolutionDir)\ProgramData-Server\Plugins\" /y</PostBuildEvent> - </PropertyGroup> - <Import Project="$(SolutionDir)\.nuget\nuget.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"> - </Target> - <Target Name="AfterBuild"> - </Target> - --> -</Project>
\ No newline at end of file diff --git a/MediaBrowser.Plugins.MpcHc/MpcHcMediaPlayer.cs b/MediaBrowser.Plugins.MpcHc/MpcHcMediaPlayer.cs deleted file mode 100644 index e2d5398e4..000000000 --- a/MediaBrowser.Plugins.MpcHc/MpcHcMediaPlayer.cs +++ /dev/null @@ -1,580 +0,0 @@ -using MediaBrowser.Model.Dto; -using MediaBrowser.Model.Entities; -using MediaBrowser.Model.Logging; -using MediaBrowser.UI.Configuration; -using MediaBrowser.UI.Controller; -using MediaBrowser.UI.Playback; -using MediaBrowser.UI.Playback.ExternalPlayer; -using System; -using System.Collections.Generic; -using System.ComponentModel.Composition; -using System.IO; -using System.Linq; -using System.Net.Http; -using System.Threading; -using System.Threading.Tasks; - -namespace MediaBrowser.Plugins.MpcHc -{ - /// <summary> - /// Class GenericExternalPlayer - /// </summary> - [Export(typeof(BaseMediaPlayer))] - public class MpcHcMediaPlayer : BaseExternalPlayer - { - /// <summary> - /// The state sync lock - /// </summary> - private object stateSyncLock = new object(); - - /// <summary> - /// The MPC HTTP interface resource pool - /// </summary> - private SemaphoreSlim MpcHttpInterfaceResourcePool = new SemaphoreSlim(1, 1); - - [ImportingConstructor] - public MpcHcMediaPlayer([Import("logger")] ILogger logger) - : base(logger) - { - } - - /// <summary> - /// Gets or sets the HTTP interface cancellation token. - /// </summary> - /// <value>The HTTP interface cancellation token.</value> - private CancellationTokenSource HttpInterfaceCancellationTokenSource { get; set; } - - /// <summary> - /// Gets or sets a value indicating whether this instance has started playing. - /// </summary> - /// <value><c>true</c> if this instance has started playing; otherwise, <c>false</c>.</value> - private bool HasStartedPlaying { get; set; } - - /// <summary> - /// Gets or sets the status update timer. - /// </summary> - /// <value>The status update timer.</value> - private Timer StatusUpdateTimer { get; set; } - - /// <summary> - /// Gets a value indicating whether this instance can monitor progress. - /// </summary> - /// <value><c>true</c> if this instance can monitor progress; otherwise, <c>false</c>.</value> - protected override bool CanMonitorProgress - { - get - { - return true; - } - } - - /// <summary> - /// The _current position ticks - /// </summary> - private long? _currentPositionTicks; - - /// <summary> - /// Gets the current position ticks. - /// </summary> - /// <value>The current position ticks.</value> - public override long? CurrentPositionTicks - { - get - { - return _currentPositionTicks; - } - } - - /// <summary> - /// The _current playlist index - /// </summary> - private int _currentPlaylistIndex; - - /// <summary> - /// Gets the index of the current playlist. - /// </summary> - /// <value>The index of the current playlist.</value> - public override int CurrentPlaylistIndex - { - get - { - return _currentPlaylistIndex; - } - } - - /// <summary> - /// Gets the name. - /// </summary> - /// <value>The name.</value> - public override string Name - { - get { return "MpcHc"; } - } - - /// <summary> - /// Gets a value indicating whether this instance can close automatically. - /// </summary> - /// <value><c>true</c> if this instance can close automatically; otherwise, <c>false</c>.</value> - protected override bool CanCloseAutomatically - { - get - { - return true; - } - } - - /// <summary> - /// Determines whether this instance can play the specified item. - /// </summary> - /// <param name="item">The item.</param> - /// <returns><c>true</c> if this instance can play the specified item; otherwise, <c>false</c>.</returns> - public override bool CanPlay(BaseItemDto item) - { - return item.IsVideo || item.IsAudio; - } - - /// <summary> - /// Gets the command arguments. - /// </summary> - /// <param name="items">The items.</param> - /// <param name="options">The options.</param> - /// <param name="playerConfiguration">The player configuration.</param> - /// <returns>System.String.</returns> - protected override string GetCommandArguments(List<BaseItemDto> items, PlayOptions options, PlayerConfiguration playerConfiguration) - { - var formatString = "{0} /play /fullscreen /close"; - - var firstItem = items[0]; - - var startTicks = Math.Max(options.StartPositionTicks, 0); - - if (startTicks > 0 && firstItem.IsVideo && firstItem.VideoType.HasValue && firstItem.VideoType.Value == VideoType.Dvd) - { - formatString += " /dvdpos 1#" + TimeSpan.FromTicks(startTicks).ToString("hh\\:mm\\:ss"); - } - else - { - formatString += " /start " + TimeSpan.FromTicks(startTicks).TotalMilliseconds; - } - - - return GetCommandArguments(items, formatString); - } - - /// <summary> - /// Gets the path for command line. - /// </summary> - /// <param name="item">The item.</param> - /// <returns>System.String.</returns> - protected override string GetPathForCommandLine(BaseItemDto item) - { - var path = base.GetPathForCommandLine(item); - - if (item.IsVideo && item.VideoType.HasValue) - { - if (item.VideoType.Value == VideoType.Dvd) - { - // Point directly to the video_ts path - // Otherwise mpc will play any other media files that might exist in the dvd top folder (e.g. video backdrops). - var videoTsPath = Path.Combine(path, "video_ts"); - - if (Directory.Exists(videoTsPath)) - { - path = videoTsPath; - } - } - if (item.VideoType.Value == VideoType.BluRay) - { - // Point directly to the bdmv path - var bdmvPath = Path.Combine(path, "bdmv"); - - if (Directory.Exists(bdmvPath)) - { - path = bdmvPath; - } - } - } - - return FormatPath(path); - } - - /// <summary> - /// Formats the path. - /// </summary> - /// <param name="path">The path.</param> - /// <returns>System.String.</returns> - private string FormatPath(string path) - { - if (path.EndsWith(":\\", StringComparison.OrdinalIgnoreCase)) - { - path = path.TrimEnd('\\'); - } - - return path; - } - - /// <summary> - /// Called when [external player launched]. - /// </summary> - protected override void OnExternalPlayerLaunched() - { - base.OnExternalPlayerLaunched(); - - ReloadStatusUpdateTimer(); - } - - /// <summary> - /// Reloads the status update timer. - /// </summary> - private void ReloadStatusUpdateTimer() - { - DisposeStatusTimer(); - - HttpInterfaceCancellationTokenSource = new CancellationTokenSource(); - - StatusUpdateTimer = new Timer(OnStatusUpdateTimerStopped, null, TimeSpan.FromSeconds(1), TimeSpan.FromSeconds(1)); - } - - /// <summary> - /// Called when [status update timer stopped]. - /// </summary> - /// <param name="state">The state.</param> - private async void OnStatusUpdateTimerStopped(object state) - { - try - { - var token = HttpInterfaceCancellationTokenSource.Token; - - using (var stream = await UIKernel.Instance.HttpManager.Get(StatusUrl, MpcHttpInterfaceResourcePool, token).ConfigureAwait(false)) - { - token.ThrowIfCancellationRequested(); - - using (var reader = new StreamReader(stream)) - { - token.ThrowIfCancellationRequested(); - - var result = await reader.ReadToEndAsync().ConfigureAwait(false); - - token.ThrowIfCancellationRequested(); - - ProcessStatusResult(result); - } - } - } - catch (HttpRequestException ex) - { - Logger.ErrorException("Error connecting to MpcHc status interface", ex); - } - catch (OperationCanceledException) - { - // Manually cancelled by us - Logger.Info("Status request cancelled"); - } - } - - /// <summary> - /// Processes the status result. - /// </summary> - /// <param name="result">The result.</param> - private async void ProcessStatusResult(string result) - { - // Sample result - // OnStatus('test.avi', 'Playing', 5292, '00:00:05', 1203090, '00:20:03', 0, 100, 'C:\test.avi') - // 5292 = position in ms - // 00:00:05 = position - // 1203090 = duration in ms - // 00:20:03 = duration - - var quoteChar = result.IndexOf(", \"", StringComparison.OrdinalIgnoreCase) == -1 ? '\'' : '\"'; - - // Strip off the leading "OnStatus(" and the trailing ")" - result = result.Substring(result.IndexOf(quoteChar)); - result = result.Substring(0, result.LastIndexOf(quoteChar)); - - // Strip off the filename at the beginning - result = result.Substring(result.IndexOf(string.Format("{0}, {0}", quoteChar), StringComparison.OrdinalIgnoreCase) + 3); - - // Find the last index of ", '" so that we can extract and then strip off the file path at the end. - var lastIndexOfSeparator = result.LastIndexOf(", " + quoteChar, StringComparison.OrdinalIgnoreCase); - - // Get the current playing file path - var currentPlayingFile = result.Substring(lastIndexOfSeparator + 2).Trim(quoteChar); - - // Strip off the current playing file path - result = result.Substring(0, lastIndexOfSeparator); - - var values = result.Split(',').Select(v => v.Trim().Trim(quoteChar)).ToList(); - - var currentPositionTicks = TimeSpan.FromMilliseconds(double.Parse(values[1])).Ticks; - //var currentDurationTicks = TimeSpan.FromMilliseconds(double.Parse(values[3])).Ticks; - - var playstate = values[0]; - - var playlistIndex = GetPlaylistIndex(currentPlayingFile); - - if (playstate.Equals("stopped", StringComparison.OrdinalIgnoreCase)) - { - if (HasStartedPlaying) - { - await ClosePlayer().ConfigureAwait(false); - } - } - else - { - lock (stateSyncLock) - { - if (_currentPlaylistIndex != playlistIndex) - { - OnMediaChanged(_currentPlaylistIndex, _currentPositionTicks, playlistIndex); - } - - _currentPositionTicks = currentPositionTicks; - _currentPlaylistIndex = playlistIndex; - } - - if (playstate.Equals("playing", StringComparison.OrdinalIgnoreCase)) - { - HasStartedPlaying = true; - PlayState = PlayState.Playing; - } - else if (playstate.Equals("paused", StringComparison.OrdinalIgnoreCase)) - { - HasStartedPlaying = true; - PlayState = PlayState.Paused; - } - } - } - - /// <summary> - /// Gets the index of the playlist. - /// </summary> - /// <param name="nowPlayingPath">The now playing path.</param> - /// <returns>System.Int32.</returns> - private int GetPlaylistIndex(string nowPlayingPath) - { - for (var i = 0; i < Playlist.Count; i++) - { - var item = Playlist[i]; - - var pathArg = GetPathForCommandLine(item); - - if (pathArg.Equals(nowPlayingPath, StringComparison.OrdinalIgnoreCase)) - { - return i; - } - - if (item.VideoType.HasValue) - { - if (item.VideoType.Value == VideoType.BluRay || item.VideoType.Value == VideoType.Dvd || item.VideoType.Value == VideoType.HdDvd) - { - if (nowPlayingPath.StartsWith(pathArg, StringComparison.OrdinalIgnoreCase)) - { - return i; - } - } - } - } - return -1; - } - - /// <summary> - /// Called when [player stopped internal]. - /// </summary> - protected override void OnPlayerStoppedInternal() - { - HttpInterfaceCancellationTokenSource.Cancel(); - - DisposeStatusTimer(); - _currentPositionTicks = null; - _currentPlaylistIndex = 0; - HasStartedPlaying = false; - HttpInterfaceCancellationTokenSource = null; - - base.OnPlayerStoppedInternal(); - } - - /// <summary> - /// Disposes the status timer. - /// </summary> - private void DisposeStatusTimer() - { - if (StatusUpdateTimer != null) - { - StatusUpdateTimer.Dispose(); - } - } - - /// <summary> - /// Releases unmanaged and - optionally - managed resources. - /// </summary> - /// <param name="dispose"><c>true</c> to release both managed and unmanaged resources; <c>false</c> to release only unmanaged resources.</param> - protected override void Dispose(bool dispose) - { - if (dispose) - { - DisposeStatusTimer(); - - MpcHttpInterfaceResourcePool.Dispose(); - } - - base.Dispose(dispose); - } - - /// <summary> - /// Seeks the internal. - /// </summary> - /// <param name="positionTicks">The position ticks.</param> - /// <returns>Task.</returns> - protected override Task SeekInternal(long positionTicks) - { - var additionalParams = new Dictionary<string, string>(); - - var time = TimeSpan.FromTicks(positionTicks); - - var timeString = time.Hours + ":" + time.Minutes + ":" + time.Seconds; - - additionalParams.Add("position", timeString); - - return SendCommandToPlayer("-1", additionalParams); - } - - /// <summary> - /// Pauses the internal. - /// </summary> - /// <returns>Task.</returns> - protected override Task PauseInternal() - { - return SendCommandToPlayer("888", new Dictionary<string, string>()); - } - - /// <summary> - /// Uns the pause internal. - /// </summary> - /// <returns>Task.</returns> - protected override Task UnPauseInternal() - { - return SendCommandToPlayer("887", new Dictionary<string, string>()); - } - - /// <summary> - /// Stops the internal. - /// </summary> - /// <returns>Task.</returns> - protected override Task StopInternal() - { - return SendCommandToPlayer("890", new Dictionary<string, string>()); - } - - /// <summary> - /// Closes the player. - /// </summary> - /// <returns>Task.</returns> - protected Task ClosePlayer() - { - return SendCommandToPlayer("816", new Dictionary<string, string>()); - } - - /// <summary> - /// Sends a command to MPC using the HTTP interface - /// http://www.autohotkey.net/~specter333/MPC/HTTP%20Commands.txt - /// </summary> - /// <param name="commandNumber">The command number.</param> - /// <param name="additionalParams">The additional params.</param> - /// <returns>Task.</returns> - /// <exception cref="System.ArgumentNullException">commandNumber</exception> - private async Task SendCommandToPlayer(string commandNumber, Dictionary<string, string> additionalParams) - { - if (string.IsNullOrEmpty(commandNumber)) - { - throw new ArgumentNullException("commandNumber"); - } - - if (additionalParams == null) - { - throw new ArgumentNullException("additionalParams"); - } - - var url = CommandUrl + "?wm_command=" + commandNumber; - - url = additionalParams.Keys.Aggregate(url, (current, name) => current + ("&" + name + "=" + additionalParams[name])); - - Logger.Info("Sending command to MPC: " + url); - - try - { - using (var stream = await UIKernel.Instance.HttpManager.Get(url, MpcHttpInterfaceResourcePool, HttpInterfaceCancellationTokenSource.Token).ConfigureAwait(false)) - { - } - } - catch (HttpRequestException ex) - { - Logger.ErrorException("Error connecting to MpcHc command interface", ex); - } - catch (OperationCanceledException) - { - // Manually cancelled by us - Logger.Info("Command request cancelled"); - } - } - - /// <summary> - /// Gets a value indicating whether this instance can pause. - /// </summary> - /// <value><c>true</c> if this instance can pause; otherwise, <c>false</c>.</value> - public override bool CanPause - { - get - { - return true; - } - } - - /// <summary> - /// Gets the server name that the http interface will be running on - /// </summary> - /// <value>The HTTP server.</value> - private string HttpServer - { - get - { - return "localhost"; - } - } - - /// <summary> - /// Gets the port that the web interface will be running on - /// </summary> - /// <value>The HTTP port.</value> - private string HttpPort - { - get - { - return "13579"; - } - } - - /// <summary> - /// Gets the url of that will be called to for status - /// </summary> - /// <value>The status URL.</value> - private string StatusUrl - { - get - { - return "http://" + HttpServer + ":" + HttpPort + "/status.html"; - } - } - - /// <summary> - /// Gets the url of that will be called to send commands - /// </summary> - /// <value>The command URL.</value> - private string CommandUrl - { - get - { - return "http://" + HttpServer + ":" + HttpPort + "/command.html"; - } - } - } -} diff --git a/MediaBrowser.Plugins.MpcHc/Plugin.cs b/MediaBrowser.Plugins.MpcHc/Plugin.cs deleted file mode 100644 index ca8acc94e..000000000 --- a/MediaBrowser.Plugins.MpcHc/Plugin.cs +++ /dev/null @@ -1,32 +0,0 @@ -using MediaBrowser.Common.Plugins; -using MediaBrowser.Model.Plugins; -using System; -using System.ComponentModel.Composition; - -namespace MediaBrowser.Plugins.MpcHc -{ - /// <summary> - /// Class Plugin - /// </summary> - [Export(typeof(IPlugin))] - public class Plugin : BaseUiPlugin<BasePluginConfiguration> - { - /// <summary> - /// Gets the name of the plugin - /// </summary> - /// <value>The name.</value> - public override string Name - { - get { return "MPC-HC Integration"; } - } - - /// <summary> - /// Gets the minimum required UI version. - /// </summary> - /// <value>The minimum required UI version.</value> - public override Version MinimumRequiredUIVersion - { - get { return new Version("2.9.4782.23738"); } - } - } -} diff --git a/MediaBrowser.Plugins.MpcHc/Properties/AssemblyInfo.cs b/MediaBrowser.Plugins.MpcHc/Properties/AssemblyInfo.cs deleted file mode 100644 index 10442b136..000000000 --- a/MediaBrowser.Plugins.MpcHc/Properties/AssemblyInfo.cs +++ /dev/null @@ -1,53 +0,0 @@ -using System.Reflection; -using System.Runtime.InteropServices; -using System.Windows; - -// General Information about an assembly is controlled through the following -// set of attributes. Change these attribute values to modify the information -// associated with an assembly. -[assembly: AssemblyTitle("MediaBrowser.Plugins.MpcHc")] -[assembly: AssemblyDescription("")] -[assembly: AssemblyConfiguration("")] -[assembly: AssemblyCompany("")] -[assembly: AssemblyProduct("MediaBrowser.Plugins.MpcHc")] -[assembly: AssemblyCopyright("Copyright © 2013")] -[assembly: AssemblyTrademark("")] -[assembly: AssemblyCulture("")] - -// Setting ComVisible to false makes the types in this assembly not visible -// to COM components. If you need to access a type in this assembly from -// COM, set the ComVisible attribute to true on that type. -[assembly: ComVisible(false)] - -//In order to begin building localizable applications, set -//<UICulture>CultureYouAreCodingWith</UICulture> in your .csproj file -//inside a <PropertyGroup>. For example, if you are using US english -//in your source files, set the <UICulture> to en-US. Then uncomment -//the NeutralResourceLanguage attribute below. Update the "en-US" in -//the line below to match the UICulture setting in the project file. - -//[assembly: NeutralResourcesLanguage("en-US", UltimateResourceFallbackLocation.Satellite)] - - -[assembly:ThemeInfo( - ResourceDictionaryLocation.None, //where theme specific resource dictionaries are located - //(used if a resource is not found in the page, - // or application resource dictionaries) - ResourceDictionaryLocation.SourceAssembly //where the generic resource dictionary is located - //(used if a resource is not found in the page, - // app, or any theme specific resource dictionaries) -)] - -[assembly: Guid("F6D17656-25FE-4564-9246-B4584F797348")] - -// Version information for an assembly consists of the following four values: -// -// Major Version -// Minor Version -// Build Number -// Revision -// -// You can specify all the values or you can default the Build and Revision Numbers -// by using the '*' as shown below: -// [assembly: AssemblyVersion("1.0.*")] -[assembly: AssemblyVersion("1.0.*")] diff --git a/MediaBrowser.Plugins.MpcHc/Properties/Resources.Designer.cs b/MediaBrowser.Plugins.MpcHc/Properties/Resources.Designer.cs deleted file mode 100644 index 14f2a3ba2..000000000 --- a/MediaBrowser.Plugins.MpcHc/Properties/Resources.Designer.cs +++ /dev/null @@ -1,62 +0,0 @@ -//------------------------------------------------------------------------------ -// <auto-generated> -// This code was generated by a tool. -// Runtime Version:4.0.30319.18010 -// -// Changes to this file may cause incorrect behavior and will be lost if -// the code is regenerated. -// </auto-generated> -//------------------------------------------------------------------------------ - -namespace MediaBrowser.Plugins.MpcHc.Properties { - - - /// <summary> - /// A strongly-typed resource class, for looking up localized strings, etc. - /// </summary> - // This class was auto-generated by the StronglyTypedResourceBuilder - // class via a tool like ResGen or Visual Studio. - // To add or remove a member, edit your .ResX file then rerun ResGen - // with the /str option, or rebuild your VS project. - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")] - [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] - [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] - internal class Resources { - - private static global::System.Resources.ResourceManager resourceMan; - - private static global::System.Globalization.CultureInfo resourceCulture; - - [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] - internal Resources() { - } - - /// <summary> - /// Returns the cached ResourceManager instance used by this class. - /// </summary> - [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] - internal static global::System.Resources.ResourceManager ResourceManager { - get { - if ((resourceMan == null)) { - global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("MediaBrowser.Plugins.MpcHc.Properties.Resources", typeof(Resources).Assembly); - resourceMan = temp; - } - return resourceMan; - } - } - - /// <summary> - /// Overrides the current thread's CurrentUICulture property for all - /// resource lookups using this strongly typed resource class. - /// </summary> - [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] - internal static global::System.Globalization.CultureInfo Culture { - get { - return resourceCulture; - } - set { - resourceCulture = value; - } - } - } -} diff --git a/MediaBrowser.Plugins.MpcHc/Properties/Resources.resx b/MediaBrowser.Plugins.MpcHc/Properties/Resources.resx deleted file mode 100644 index af7dbebba..000000000 --- a/MediaBrowser.Plugins.MpcHc/Properties/Resources.resx +++ /dev/null @@ -1,117 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<root> - <!-- - Microsoft ResX Schema - - Version 2.0 - - The primary goals of this format is to allow a simple XML format - that is mostly human readable. The generation and parsing of the - various data types are done through the TypeConverter classes - associated with the data types. - - Example: - - ... ado.net/XML headers & schema ... - <resheader name="resmimetype">text/microsoft-resx</resheader> - <resheader name="version">2.0</resheader> - <resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader> - <resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader> - <data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data> - <data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data> - <data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64"> - <value>[base64 mime encoded serialized .NET Framework object]</value> - </data> - <data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64"> - <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value> - <comment>This is a comment</comment> - </data> - - There are any number of "resheader" rows that contain simple - name/value pairs. - - Each data row contains a name, and value. The row also contains a - type or mimetype. Type corresponds to a .NET class that support - text/value conversion through the TypeConverter architecture. - Classes that don't support this are serialized and stored with the - mimetype set. - - The mimetype is used for serialized objects, and tells the - ResXResourceReader how to depersist the object. This is currently not - extensible. For a given mimetype the value must be set accordingly: - - Note - application/x-microsoft.net.object.binary.base64 is the format - that the ResXResourceWriter will generate, however the reader can - read any of the formats listed below. - - mimetype: application/x-microsoft.net.object.binary.base64 - value : The object must be serialized with - : System.Serialization.Formatters.Binary.BinaryFormatter - : and then encoded with base64 encoding. - - mimetype: application/x-microsoft.net.object.soap.base64 - value : The object must be serialized with - : System.Runtime.Serialization.Formatters.Soap.SoapFormatter - : and then encoded with base64 encoding. - - mimetype: application/x-microsoft.net.object.bytearray.base64 - value : The object must be serialized into a byte array - : using a System.ComponentModel.TypeConverter - : and then encoded with base64 encoding. - --> - <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata"> - <xsd:element name="root" msdata:IsDataSet="true"> - <xsd:complexType> - <xsd:choice maxOccurs="unbounded"> - <xsd:element name="metadata"> - <xsd:complexType> - <xsd:sequence> - <xsd:element name="value" type="xsd:string" minOccurs="0" /> - </xsd:sequence> - <xsd:attribute name="name" type="xsd:string" /> - <xsd:attribute name="type" type="xsd:string" /> - <xsd:attribute name="mimetype" type="xsd:string" /> - </xsd:complexType> - </xsd:element> - <xsd:element name="assembly"> - <xsd:complexType> - <xsd:attribute name="alias" type="xsd:string" /> - <xsd:attribute name="name" type="xsd:string" /> - </xsd:complexType> - </xsd:element> - <xsd:element name="data"> - <xsd:complexType> - <xsd:sequence> - <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" /> - <xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" /> - </xsd:sequence> - <xsd:attribute name="name" type="xsd:string" msdata:Ordinal="1" /> - <xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" /> - <xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" /> - </xsd:complexType> - </xsd:element> - <xsd:element name="resheader"> - <xsd:complexType> - <xsd:sequence> - <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" /> - </xsd:sequence> - <xsd:attribute name="name" type="xsd:string" use="required" /> - </xsd:complexType> - </xsd:element> - </xsd:choice> - </xsd:complexType> - </xsd:element> - </xsd:schema> - <resheader name="resmimetype"> - <value>text/microsoft-resx</value> - </resheader> - <resheader name="version"> - <value>2.0</value> - </resheader> - <resheader name="reader"> - <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value> - </resheader> - <resheader name="writer"> - <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value> - </resheader> -</root>
\ No newline at end of file diff --git a/MediaBrowser.Plugins.MpcHc/Properties/Settings.Designer.cs b/MediaBrowser.Plugins.MpcHc/Properties/Settings.Designer.cs deleted file mode 100644 index f64175f33..000000000 --- a/MediaBrowser.Plugins.MpcHc/Properties/Settings.Designer.cs +++ /dev/null @@ -1,30 +0,0 @@ -//------------------------------------------------------------------------------ -// <auto-generated> -// This code was generated by a tool. -// Runtime Version:4.0.30319.18010 -// -// Changes to this file may cause incorrect behavior and will be lost if -// the code is regenerated. -// </auto-generated> -//------------------------------------------------------------------------------ - -namespace MediaBrowser.Plugins.MpcHc.Properties -{ - - - [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "11.0.0.0")] - internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase - { - - private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings()))); - - public static Settings Default - { - get - { - return defaultInstance; - } - } - } -} diff --git a/MediaBrowser.Plugins.MpcHc/Properties/Settings.settings b/MediaBrowser.Plugins.MpcHc/Properties/Settings.settings deleted file mode 100644 index 033d7a5e9..000000000 --- a/MediaBrowser.Plugins.MpcHc/Properties/Settings.settings +++ /dev/null @@ -1,7 +0,0 @@ -<?xml version='1.0' encoding='utf-8'?> -<SettingsFile xmlns="uri:settings" CurrentProfile="(Default)"> - <Profiles> - <Profile Name="(Default)" /> - </Profiles> - <Settings /> -</SettingsFile>
\ No newline at end of file diff --git a/MediaBrowser.Plugins.MpcHc/app.config b/MediaBrowser.Plugins.MpcHc/app.config deleted file mode 100644 index 29abde1f6..000000000 --- a/MediaBrowser.Plugins.MpcHc/app.config +++ /dev/null @@ -1,11 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<configuration> - <runtime> - <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1"> - <dependentAssembly> - <assemblyIdentity name="NLog" publicKeyToken="5120e14c03d0593c" culture="neutral" /> - <bindingRedirect oldVersion="0.0.0.0-2.0.0.0" newVersion="2.0.0.0" /> - </dependentAssembly> - </assemblyBinding> - </runtime> -</configuration>
\ No newline at end of file diff --git a/MediaBrowser.Plugins.Tmt5/MediaBrowser.Plugins.Tmt5.csproj b/MediaBrowser.Plugins.Tmt5/MediaBrowser.Plugins.Tmt5.csproj deleted file mode 100644 index 113c63f0f..000000000 --- a/MediaBrowser.Plugins.Tmt5/MediaBrowser.Plugins.Tmt5.csproj +++ /dev/null @@ -1,108 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<Project ToolsVersion="4.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> - <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform> - <ProjectGuid>{BE9BAA85-9EF2-4308-92E4-0D2B6E33C487}</ProjectGuid> - <OutputType>library</OutputType> - <AppDesignerFolder>Properties</AppDesignerFolder> - <RootNamespace>MediaBrowser.Plugins.Tmt5</RootNamespace> - <AssemblyName>MediaBrowser.Plugins.Tmt5</AssemblyName> - <TargetFrameworkVersion>v4.5</TargetFrameworkVersion> - <FileAlignment>512</FileAlignment> - <ProjectTypeGuids>{60dc8134-eba5-43b8-bcc9-bb4bc16c2548};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids> - <WarningLevel>4</WarningLevel> - <SolutionDir Condition="$(SolutionDir) == '' Or $(SolutionDir) == '*Undefined*'">..\</SolutionDir> - <RestorePackages>true</RestorePackages> - </PropertyGroup> - <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' "> - <DebugSymbols>true</DebugSymbols> - <DebugType>full</DebugType> - <Optimize>false</Optimize> - <OutputPath>bin\Debug\</OutputPath> - <DefineConstants>DEBUG;TRACE</DefineConstants> - <ErrorReport>prompt</ErrorReport> - <WarningLevel>4</WarningLevel> - </PropertyGroup> - <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' "> - <DebugType>pdbonly</DebugType> - <Optimize>true</Optimize> - <OutputPath>bin\Release\</OutputPath> - <DefineConstants>TRACE</DefineConstants> - <ErrorReport>prompt</ErrorReport> - <WarningLevel>4</WarningLevel> - </PropertyGroup> - <PropertyGroup> - <RunPostBuildEvent>Always</RunPostBuildEvent> - </PropertyGroup> - <ItemGroup> - <Reference Include="System" /> - <Reference Include="System.ComponentModel.Composition" /> - <Reference Include="System.Data" /> - <Reference Include="System.Xml" /> - <Reference Include="Microsoft.CSharp" /> - <Reference Include="System.Core" /> - <Reference Include="System.Xml.Linq" /> - <Reference Include="System.Data.DataSetExtensions" /> - <Reference Include="System.Xaml"> - <RequiredTargetFramework>4.0</RequiredTargetFramework> - </Reference> - <Reference Include="WindowsBase" /> - <Reference Include="PresentationCore" /> - <Reference Include="PresentationFramework" /> - </ItemGroup> - <ItemGroup> - <Compile Include="Tmt5MediaPlayer.cs" /> - <Compile Include="Plugin.cs" /> - <Compile Include="Properties\AssemblyInfo.cs"> - <SubType>Code</SubType> - </Compile> - <Compile Include="Properties\Resources.Designer.cs"> - <AutoGen>True</AutoGen> - <DesignTime>True</DesignTime> - <DependentUpon>Resources.resx</DependentUpon> - </Compile> - <Compile Include="Properties\Settings.Designer.cs"> - <AutoGen>True</AutoGen> - <DependentUpon>Settings.settings</DependentUpon> - <DesignTimeSharedInput>True</DesignTimeSharedInput> - </Compile> - <EmbeddedResource Include="Properties\Resources.resx"> - <Generator>ResXFileCodeGenerator</Generator> - <LastGenOutput>Resources.Designer.cs</LastGenOutput> - </EmbeddedResource> - <None Include="app.config" /> - <None Include="Properties\Settings.settings"> - <Generator>SettingsSingleFileGenerator</Generator> - <LastGenOutput>Settings.Designer.cs</LastGenOutput> - </None> - <AppDesigner Include="Properties\" /> - </ItemGroup> - <ItemGroup> - <ProjectReference Include="..\MediaBrowser.Common\MediaBrowser.Common.csproj"> - <Project>{9142eefa-7570-41e1-bfcc-468bb571af2f}</Project> - <Name>MediaBrowser.Common</Name> - </ProjectReference> - <ProjectReference Include="..\MediaBrowser.Model\MediaBrowser.Model.csproj"> - <Project>{7eeeb4bb-f3e8-48fc-b4c5-70f0fff8329b}</Project> - <Name>MediaBrowser.Model</Name> - </ProjectReference> - <ProjectReference Include="..\MediaBrowser.UI\MediaBrowser.UI.csproj"> - <Project>{b5ece1fb-618e-420b-9a99-8e972d76920a}</Project> - <Name>MediaBrowser.UI</Name> - </ProjectReference> - </ItemGroup> - <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" /> - <PropertyGroup> - <PostBuildEvent>xcopy "$(TargetPath)" "$(SolutionDir)\ProgramData-Server\Plugins\" /y</PostBuildEvent> - </PropertyGroup> - <Import Project="$(SolutionDir)\.nuget\nuget.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"> - </Target> - <Target Name="AfterBuild"> - </Target> - --> -</Project>
\ No newline at end of file diff --git a/MediaBrowser.Plugins.Tmt5/Plugin.cs b/MediaBrowser.Plugins.Tmt5/Plugin.cs deleted file mode 100644 index 7b5fb9267..000000000 --- a/MediaBrowser.Plugins.Tmt5/Plugin.cs +++ /dev/null @@ -1,32 +0,0 @@ -using MediaBrowser.Common.Plugins; -using MediaBrowser.Model.Plugins; -using System; -using System.ComponentModel.Composition; - -namespace MediaBrowser.Plugins.Tmt5 -{ - /// <summary> - /// Class Plugin - /// </summary> - [Export(typeof(IPlugin))] - public class Plugin : BaseUiPlugin<BasePluginConfiguration> - { - /// <summary> - /// Gets the name of the plugin - /// </summary> - /// <value>The name.</value> - public override string Name - { - get { return "TMT5 Integration"; } - } - - /// <summary> - /// Gets the minimum required UI version. - /// </summary> - /// <value>The minimum required UI version.</value> - public override Version MinimumRequiredUIVersion - { - get { return new Version("2.9.4782.23738"); } - } - } -} diff --git a/MediaBrowser.Plugins.Tmt5/Properties/AssemblyInfo.cs b/MediaBrowser.Plugins.Tmt5/Properties/AssemblyInfo.cs deleted file mode 100644 index eadd74785..000000000 --- a/MediaBrowser.Plugins.Tmt5/Properties/AssemblyInfo.cs +++ /dev/null @@ -1,53 +0,0 @@ -using System.Reflection; -using System.Runtime.InteropServices; -using System.Windows; - -// General Information about an assembly is controlled through the following -// set of attributes. Change these attribute values to modify the information -// associated with an assembly. -[assembly: AssemblyTitle("MediaBrowser.Plugins.Tmt5")] -[assembly: AssemblyDescription("")] -[assembly: AssemblyConfiguration("")] -[assembly: AssemblyCompany("")] -[assembly: AssemblyProduct("MediaBrowser.Plugins.Tmt5")] -[assembly: AssemblyCopyright("Copyright © 2013")] -[assembly: AssemblyTrademark("")] -[assembly: AssemblyCulture("")] - -// Setting ComVisible to false makes the types in this assembly not visible -// to COM components. If you need to access a type in this assembly from -// COM, set the ComVisible attribute to true on that type. -[assembly: ComVisible(false)] - -//In order to begin building localizable applications, set -//<UICulture>CultureYouAreCodingWith</UICulture> in your .csproj file -//inside a <PropertyGroup>. For example, if you are using US english -//in your source files, set the <UICulture> to en-US. Then uncomment -//the NeutralResourceLanguage attribute below. Update the "en-US" in -//the line below to match the UICulture setting in the project file. - -//[assembly: NeutralResourcesLanguage("en-US", UltimateResourceFallbackLocation.Satellite)] - - -[assembly:ThemeInfo( - ResourceDictionaryLocation.None, //where theme specific resource dictionaries are located - //(used if a resource is not found in the page, - // or application resource dictionaries) - ResourceDictionaryLocation.SourceAssembly //where the generic resource dictionary is located - //(used if a resource is not found in the page, - // app, or any theme specific resource dictionaries) -)] - -[assembly: Guid("3921C21B-B8C0-46C2-92DE-CC0E1FE0C434")] - -// Version information for an assembly consists of the following four values: -// -// Major Version -// Minor Version -// Build Number -// Revision -// -// You can specify all the values or you can default the Build and Revision Numbers -// by using the '*' as shown below: -// [assembly: AssemblyVersion("1.0.*")] -[assembly: AssemblyVersion("1.0.*")] diff --git a/MediaBrowser.Plugins.Tmt5/Properties/Resources.Designer.cs b/MediaBrowser.Plugins.Tmt5/Properties/Resources.Designer.cs deleted file mode 100644 index 3656ce547..000000000 --- a/MediaBrowser.Plugins.Tmt5/Properties/Resources.Designer.cs +++ /dev/null @@ -1,62 +0,0 @@ -//------------------------------------------------------------------------------ -// <auto-generated> -// This code was generated by a tool. -// Runtime Version:4.0.30319.18010 -// -// Changes to this file may cause incorrect behavior and will be lost if -// the code is regenerated. -// </auto-generated> -//------------------------------------------------------------------------------ - -namespace MediaBrowser.Plugins.Tmt5.Properties { - - - /// <summary> - /// A strongly-typed resource class, for looking up localized strings, etc. - /// </summary> - // This class was auto-generated by the StronglyTypedResourceBuilder - // class via a tool like ResGen or Visual Studio. - // To add or remove a member, edit your .ResX file then rerun ResGen - // with the /str option, or rebuild your VS project. - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")] - [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] - [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] - internal class Resources { - - private static global::System.Resources.ResourceManager resourceMan; - - private static global::System.Globalization.CultureInfo resourceCulture; - - [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] - internal Resources() { - } - - /// <summary> - /// Returns the cached ResourceManager instance used by this class. - /// </summary> - [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] - internal static global::System.Resources.ResourceManager ResourceManager { - get { - if ((resourceMan == null)) { - global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("MediaBrowser.Plugins.Tmt5.Properties.Resources", typeof(Resources).Assembly); - resourceMan = temp; - } - return resourceMan; - } - } - - /// <summary> - /// Overrides the current thread's CurrentUICulture property for all - /// resource lookups using this strongly typed resource class. - /// </summary> - [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] - internal static global::System.Globalization.CultureInfo Culture { - get { - return resourceCulture; - } - set { - resourceCulture = value; - } - } - } -} diff --git a/MediaBrowser.Plugins.Tmt5/Properties/Resources.resx b/MediaBrowser.Plugins.Tmt5/Properties/Resources.resx deleted file mode 100644 index af7dbebba..000000000 --- a/MediaBrowser.Plugins.Tmt5/Properties/Resources.resx +++ /dev/null @@ -1,117 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<root> - <!-- - Microsoft ResX Schema - - Version 2.0 - - The primary goals of this format is to allow a simple XML format - that is mostly human readable. The generation and parsing of the - various data types are done through the TypeConverter classes - associated with the data types. - - Example: - - ... ado.net/XML headers & schema ... - <resheader name="resmimetype">text/microsoft-resx</resheader> - <resheader name="version">2.0</resheader> - <resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader> - <resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader> - <data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data> - <data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data> - <data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64"> - <value>[base64 mime encoded serialized .NET Framework object]</value> - </data> - <data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64"> - <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value> - <comment>This is a comment</comment> - </data> - - There are any number of "resheader" rows that contain simple - name/value pairs. - - Each data row contains a name, and value. The row also contains a - type or mimetype. Type corresponds to a .NET class that support - text/value conversion through the TypeConverter architecture. - Classes that don't support this are serialized and stored with the - mimetype set. - - The mimetype is used for serialized objects, and tells the - ResXResourceReader how to depersist the object. This is currently not - extensible. For a given mimetype the value must be set accordingly: - - Note - application/x-microsoft.net.object.binary.base64 is the format - that the ResXResourceWriter will generate, however the reader can - read any of the formats listed below. - - mimetype: application/x-microsoft.net.object.binary.base64 - value : The object must be serialized with - : System.Serialization.Formatters.Binary.BinaryFormatter - : and then encoded with base64 encoding. - - mimetype: application/x-microsoft.net.object.soap.base64 - value : The object must be serialized with - : System.Runtime.Serialization.Formatters.Soap.SoapFormatter - : and then encoded with base64 encoding. - - mimetype: application/x-microsoft.net.object.bytearray.base64 - value : The object must be serialized into a byte array - : using a System.ComponentModel.TypeConverter - : and then encoded with base64 encoding. - --> - <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata"> - <xsd:element name="root" msdata:IsDataSet="true"> - <xsd:complexType> - <xsd:choice maxOccurs="unbounded"> - <xsd:element name="metadata"> - <xsd:complexType> - <xsd:sequence> - <xsd:element name="value" type="xsd:string" minOccurs="0" /> - </xsd:sequence> - <xsd:attribute name="name" type="xsd:string" /> - <xsd:attribute name="type" type="xsd:string" /> - <xsd:attribute name="mimetype" type="xsd:string" /> - </xsd:complexType> - </xsd:element> - <xsd:element name="assembly"> - <xsd:complexType> - <xsd:attribute name="alias" type="xsd:string" /> - <xsd:attribute name="name" type="xsd:string" /> - </xsd:complexType> - </xsd:element> - <xsd:element name="data"> - <xsd:complexType> - <xsd:sequence> - <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" /> - <xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" /> - </xsd:sequence> - <xsd:attribute name="name" type="xsd:string" msdata:Ordinal="1" /> - <xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" /> - <xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" /> - </xsd:complexType> - </xsd:element> - <xsd:element name="resheader"> - <xsd:complexType> - <xsd:sequence> - <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" /> - </xsd:sequence> - <xsd:attribute name="name" type="xsd:string" use="required" /> - </xsd:complexType> - </xsd:element> - </xsd:choice> - </xsd:complexType> - </xsd:element> - </xsd:schema> - <resheader name="resmimetype"> - <value>text/microsoft-resx</value> - </resheader> - <resheader name="version"> - <value>2.0</value> - </resheader> - <resheader name="reader"> - <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value> - </resheader> - <resheader name="writer"> - <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value> - </resheader> -</root>
\ No newline at end of file diff --git a/MediaBrowser.Plugins.Tmt5/Properties/Settings.Designer.cs b/MediaBrowser.Plugins.Tmt5/Properties/Settings.Designer.cs deleted file mode 100644 index ac7a3dcab..000000000 --- a/MediaBrowser.Plugins.Tmt5/Properties/Settings.Designer.cs +++ /dev/null @@ -1,30 +0,0 @@ -//------------------------------------------------------------------------------ -// <auto-generated> -// This code was generated by a tool. -// Runtime Version:4.0.30319.18010 -// -// Changes to this file may cause incorrect behavior and will be lost if -// the code is regenerated. -// </auto-generated> -//------------------------------------------------------------------------------ - -namespace MediaBrowser.Plugins.Tmt5.Properties -{ - - - [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "11.0.0.0")] - internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase - { - - private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings()))); - - public static Settings Default - { - get - { - return defaultInstance; - } - } - } -} diff --git a/MediaBrowser.Plugins.Tmt5/Properties/Settings.settings b/MediaBrowser.Plugins.Tmt5/Properties/Settings.settings deleted file mode 100644 index 033d7a5e9..000000000 --- a/MediaBrowser.Plugins.Tmt5/Properties/Settings.settings +++ /dev/null @@ -1,7 +0,0 @@ -<?xml version='1.0' encoding='utf-8'?> -<SettingsFile xmlns="uri:settings" CurrentProfile="(Default)"> - <Profiles> - <Profile Name="(Default)" /> - </Profiles> - <Settings /> -</SettingsFile>
\ No newline at end of file diff --git a/MediaBrowser.Plugins.Tmt5/Tmt5MediaPlayer.cs b/MediaBrowser.Plugins.Tmt5/Tmt5MediaPlayer.cs deleted file mode 100644 index 2643eaa44..000000000 --- a/MediaBrowser.Plugins.Tmt5/Tmt5MediaPlayer.cs +++ /dev/null @@ -1,405 +0,0 @@ -using MediaBrowser.Common.IO; -using MediaBrowser.Model.Dto; -using MediaBrowser.Model.Logging; -using MediaBrowser.UI.Configuration; -using MediaBrowser.UI.Playback; -using MediaBrowser.UI.Playback.ExternalPlayer; -using System; -using System.Collections.Generic; -using System.Collections.Specialized; -using System.ComponentModel.Composition; -using System.Diagnostics; -using System.Globalization; -using System.IO; -using System.Threading.Tasks; - -namespace MediaBrowser.Plugins.Tmt5 -{ - /// <summary> - /// Class GenericExternalPlayer - /// </summary> - [Export(typeof(BaseMediaPlayer))] - public class Tmt5MediaPlayer : BaseExternalPlayer - { - [ImportingConstructor] - public Tmt5MediaPlayer([Import("logger")] ILogger logger) - : base(logger) - { - } - - /// <summary> - /// Gets the name. - /// </summary> - /// <value>The name.</value> - public override string Name - { - get { return "TMT5"; } - } - - /// <summary> - /// Gets a value indicating whether this instance can pause. - /// </summary> - /// <value><c>true</c> if this instance can pause; otherwise, <c>false</c>.</value> - public override bool CanPause - { - get - { - return true; - } - } - - /// <summary> - /// Gets a value indicating whether this instance can close automatically. - /// </summary> - /// <value><c>true</c> if this instance can close automatically; otherwise, <c>false</c>.</value> - protected override bool CanCloseAutomatically - { - get - { - return true; - } - } - - /// <summary> - /// Gets the play state directory. - /// </summary> - /// <value>The play state directory.</value> - private string PlayStateDirectory - { - get - { - return Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), "ArcSoft"); - } - } - - - /// <summary> - /// The _current position ticks - /// </summary> - private long? _currentPositionTicks; - - /// <summary> - /// Gets the current position ticks. - /// </summary> - /// <value>The current position ticks.</value> - public override long? CurrentPositionTicks - { - get - { - return _currentPositionTicks; - } - } - - /// <summary> - /// The _current playlist index - /// </summary> - private int _currentPlaylistIndex; - - /// <summary> - /// Gets the index of the current playlist. - /// </summary> - /// <value>The index of the current playlist.</value> - public override int CurrentPlaylistIndex - { - get - { - return _currentPlaylistIndex; - } - } - - /// <summary> - /// Gets or sets the status file watcher. - /// </summary> - /// <value>The status file watcher.</value> - private FileSystemWatcher StatusFileWatcher { get; set; } - - /// <summary> - /// Gets or sets a value indicating whether this instance has started playing. - /// </summary> - /// <value><c>true</c> if this instance has started playing; otherwise, <c>false</c>.</value> - private bool HasStartedPlaying { get; set; } - - /// <summary> - /// Gets or sets a value indicating whether this instance has stopped playing. - /// </summary> - /// <value><c>true</c> if this instance has stopped playing; otherwise, <c>false</c>.</value> - private bool HasStoppedPlaying { get; set; } - - /// <summary> - /// Determines whether this instance can play the specified item. - /// </summary> - /// <param name="item">The item.</param> - /// <returns><c>true</c> if this instance can play the specified item; otherwise, <c>false</c>.</returns> - public override bool CanPlay(BaseItemDto item) - { - return item.IsVideo || item.IsAudio; - } - - /// <summary> - /// Called when [player stopped internal]. - /// </summary> - protected override void OnPlayerStoppedInternal() - { - DisposeFileSystemWatcher(); - HasStartedPlaying = false; - HasStoppedPlaying = false; - _currentPlaylistIndex = 0; - _currentPositionTicks = 0; - - base.OnPlayerStoppedInternal(); - } - - /// <summary> - /// Gets the command arguments. - /// </summary> - /// <param name="items">The items.</param> - /// <param name="options">The options.</param> - /// <param name="playerConfiguration">The player configuration.</param> - /// <returns>System.String.</returns> - protected override string GetCommandArguments(List<BaseItemDto> items, PlayOptions options, PlayerConfiguration playerConfiguration) - { - return "\"" + items[0].Path + "\""; - } - - /// <summary> - /// Called when [external player launched]. - /// </summary> - protected override void OnExternalPlayerLaunched() - { - base.OnExternalPlayerLaunched(); - - // If the playstate directory exists, start watching it - if (Directory.Exists(PlayStateDirectory)) - { - ReloadFileSystemWatcher(); - } - } - - /// <summary> - /// Pauses the internal. - /// </summary> - /// <returns>Task.</returns> - protected override Task PauseInternal() - { - return SendCommandToMMC("-pause"); - } - - /// <summary> - /// Uns the pause internal. - /// </summary> - /// <returns>Task.</returns> - protected override Task UnPauseInternal() - { - return SendCommandToMMC("-play"); - } - - /// <summary> - /// Stops the internal. - /// </summary> - /// <returns>Task.</returns> - protected override Task StopInternal() - { - return SendCommandToMMC("-stop"); - } - - /// <summary> - /// Closes the player. - /// </summary> - /// <returns>Task.</returns> - protected Task ClosePlayer() - { - return SendCommandToMMC("-close"); - } - - /// <summary> - /// Seeks the internal. - /// </summary> - /// <param name="positionTicks">The position ticks.</param> - /// <returns>Task.</returns> - /// <exception cref="System.InvalidOperationException">No media to seek to</exception> - protected override Task SeekInternal(long positionTicks) - { - if (CurrentMedia == null) - { - throw new InvalidOperationException("No media to seek to"); - } - - if (CurrentMedia.Chapters == null) - { - throw new InvalidOperationException("TMT5 cannot seek without chapter information"); - } - - var chapterIndex = 0; - - for (var i = 0; i < CurrentMedia.Chapters.Count; i++) - { - if (CurrentMedia.Chapters[i].StartPositionTicks < positionTicks) - { - chapterIndex = i; - } - } - - return JumpToChapter(chapterIndex); - } - - /// <summary> - /// Jumps to chapter. - /// </summary> - /// <param name="chapter">The chapter.</param> - /// <returns>Task.</returns> - protected Task JumpToChapter(int chapter) - { - return SendCommandToMMC(" -chapter " + chapter); - } - - /// <summary> - /// Sends an arbitrary command to the TMT MMC console - /// </summary> - /// <param name="command">The command.</param> - /// <returns>Task.</returns> - protected Task SendCommandToMMC(string command) - { - return Task.Run(() => - { - var directory = Path.GetDirectoryName(CurrentPlayerConfiguration.Command); - - var processInfo = new ProcessStartInfo - { - FileName = Path.Combine(directory, "MMCEDT5.exe"), - Arguments = command, - CreateNoWindow = true - }; - - Logger.Debug("{0} {1}", processInfo.FileName, processInfo.Arguments); - - using (var process = Process.Start(processInfo)) - { - process.WaitForExit(2000); - } - }); - } - - /// <summary> - /// Reloads the file system watcher. - /// </summary> - private void ReloadFileSystemWatcher() - { - DisposeFileSystemWatcher(); - - Logger.Info("Watching TMT folder: " + PlayStateDirectory); - - StatusFileWatcher = new FileSystemWatcher(PlayStateDirectory, "*.set") - { - IncludeSubdirectories = true - }; - - // Need to include subdirectories since there are subfolders undearneath this with the TMT version #. - StatusFileWatcher.Changed += StatusFileWatcher_Changed; - StatusFileWatcher.EnableRaisingEvents = true; - } - - private static readonly CultureInfo UsCulture = new CultureInfo("en-US"); - - /// <summary> - /// Handles the Changed event of the StatusFileWatcher control. - /// </summary> - /// <param name="sender">The source of the event.</param> - /// <param name="e">The <see cref="FileSystemEventArgs" /> instance containing the event data.</param> - async void StatusFileWatcher_Changed(object sender, FileSystemEventArgs e) - { - Logger.Debug("TMT File Watcher reports change type {1} at {0}", e.FullPath, e.ChangeType); - - NameValueCollection values; - - try - { - values = FileSystem.ParseIniFile(e.FullPath); - } - catch (IOException) - { - // This can happen if the file is being written to at the exact moment we're trying to access it - // Unfortunately we kind of have to just eat it - return; - } - - var tmtPlayState = values["State"]; - - if (tmtPlayState.Equals("play", StringComparison.OrdinalIgnoreCase)) - { - PlayState = PlayState.Playing; - - // Playback just started - HasStartedPlaying = true; - - if (CurrentPlayOptions.StartPositionTicks > 0) - { - SeekInternal(CurrentPlayOptions.StartPositionTicks); - } - } - else if (tmtPlayState.Equals("pause", StringComparison.OrdinalIgnoreCase)) - { - PlayState = PlayState.Paused; - } - - // If playback has previously started... - // First notify the Progress event handler - // Then check if playback has stopped - if (HasStartedPlaying) - { - TimeSpan currentPosition; - - //TimeSpan.TryParse(values["TotalTime"], out currentDuration); - - if (TimeSpan.TryParse(values["CurTime"], UsCulture, out currentPosition)) - { - _currentPositionTicks = currentPosition.Ticks; - } - - _currentPlaylistIndex = 0; - - // Playback has stopped - if (tmtPlayState.Equals("stop", StringComparison.OrdinalIgnoreCase)) - { - Logger.Info("Playstate changed to stopped"); - - if (!HasStoppedPlaying) - { - HasStoppedPlaying = true; - - DisposeFileSystemWatcher(); - - await ClosePlayer().ConfigureAwait(false); - } - } - } - } - - /// <summary> - /// Disposes the file system watcher. - /// </summary> - private void DisposeFileSystemWatcher() - { - if (StatusFileWatcher != null) - { - StatusFileWatcher.EnableRaisingEvents = false; - StatusFileWatcher.Changed -= StatusFileWatcher_Changed; - StatusFileWatcher.Dispose(); - StatusFileWatcher = null; - } - } - - /// <summary> - /// Releases unmanaged and - optionally - managed resources. - /// </summary> - /// <param name="dispose"><c>true</c> to release both managed and unmanaged resources; <c>false</c> to release only unmanaged resources.</param> - protected override void Dispose(bool dispose) - { - if (dispose) - { - DisposeFileSystemWatcher(); - } - - base.Dispose(dispose); - } - } -} diff --git a/MediaBrowser.Plugins.Tmt5/app.config b/MediaBrowser.Plugins.Tmt5/app.config deleted file mode 100644 index 29abde1f6..000000000 --- a/MediaBrowser.Plugins.Tmt5/app.config +++ /dev/null @@ -1,11 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<configuration> - <runtime> - <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1"> - <dependentAssembly> - <assemblyIdentity name="NLog" publicKeyToken="5120e14c03d0593c" culture="neutral" /> - <bindingRedirect oldVersion="0.0.0.0-2.0.0.0" newVersion="2.0.0.0" /> - </dependentAssembly> - </assemblyBinding> - </runtime> -</configuration>
\ No newline at end of file diff --git a/MediaBrowser.Plugins.Trailers/AppleTrailerListingDownloader.cs b/MediaBrowser.Plugins.Trailers/AppleTrailerListingDownloader.cs deleted file mode 100644 index 76d7569b9..000000000 --- a/MediaBrowser.Plugins.Trailers/AppleTrailerListingDownloader.cs +++ /dev/null @@ -1,314 +0,0 @@ -using MediaBrowser.Common.Extensions; -using MediaBrowser.Controller; -using MediaBrowser.Controller.Entities; -using MediaBrowser.Controller.Extensions; -using MediaBrowser.Model.Entities; -using System; -using System.Collections.Generic; -using System.Globalization; -using System.Threading; -using System.Threading.Tasks; -using System.Xml; - -namespace MediaBrowser.Plugins.Trailers -{ - /// <summary> - /// Fetches Apple's list of current movie trailers - /// </summary> - public static class AppleTrailerListingDownloader - { - /// <summary> - /// The trailer feed URL - /// </summary> - private const string TrailerFeedUrl = "http://trailers.apple.com/trailers/home/xml/current_720p.xml"; - - /// <summary> - /// Downloads a list of trailer info's from the apple url - /// </summary> - /// <returns>Task{List{TrailerInfo}}.</returns> - public static async Task<List<TrailerInfo>> GetTrailerList(CancellationToken cancellationToken) - { - var stream = await Kernel.Instance.HttpManager.Get(TrailerFeedUrl, Kernel.Instance.ResourcePools.AppleTrailerVideos, cancellationToken).ConfigureAwait(false); - - var list = new List<TrailerInfo>(); - - using (var reader = XmlReader.Create(stream, new XmlReaderSettings { Async = true })) - { - await reader.MoveToContentAsync().ConfigureAwait(false); - - while (await reader.ReadAsync().ConfigureAwait(false)) - { - cancellationToken.ThrowIfCancellationRequested(); - - if (reader.NodeType == XmlNodeType.Element) - { - switch (reader.Name) - { - case "movieinfo": - var trailer = FetchTrailerInfo(reader.ReadSubtree()); - list.Add(trailer); - break; - } - } - } - } - - return list; - } - - /// <summary> - /// Fetches trailer info from an xml node - /// </summary> - /// <param name="reader">The reader.</param> - /// <returns>TrailerInfo.</returns> - private static TrailerInfo FetchTrailerInfo(XmlReader reader) - { - var trailerInfo = new TrailerInfo { }; - - reader.MoveToContent(); - - while (reader.Read()) - { - if (reader.NodeType == XmlNodeType.Element) - { - switch (reader.Name) - { - case "info": - FetchInfo(reader.ReadSubtree(), trailerInfo); - break; - case "cast": - FetchCast(reader.ReadSubtree(), trailerInfo); - break; - case "genre": - FetchGenres(reader.ReadSubtree(), trailerInfo); - break; - case "poster": - FetchPosterUrl(reader.ReadSubtree(), trailerInfo); - break; - case "preview": - FetchTrailerUrl(reader.ReadSubtree(), trailerInfo); - break; - default: - reader.Skip(); - break; - } - } - } - - return trailerInfo; - } - - private static readonly CultureInfo USCulture = new CultureInfo("en-US"); - - /// <summary> - /// Fetches from the info node - /// </summary> - /// <param name="reader">The reader.</param> - /// <param name="info">The info.</param> - private static void FetchInfo(XmlReader reader, TrailerInfo info) - { - reader.MoveToContent(); - reader.Read(); - - while (reader.NodeType == XmlNodeType.Element) - { - switch (reader.Name) - { - case "title": - info.Video.Name = reader.ReadStringSafe(); - break; - case "runtime": - { - var runtime = reader.ReadStringSafe(); - - if (!string.IsNullOrWhiteSpace(runtime)) - { - if (runtime.StartsWith(":", StringComparison.OrdinalIgnoreCase)) - { - runtime = "0" + runtime; - } - - TimeSpan runtimeTimeSpan; - - if (TimeSpan.TryParse(runtime, USCulture, out runtimeTimeSpan)) - { - info.Video.RunTimeTicks = runtimeTimeSpan.Ticks; - } - } - break; - } - case "rating": - info.Video.OfficialRating = reader.ReadStringSafe(); - break; - case "studio": - { - var studio = reader.ReadStringSafe(); - if (!string.IsNullOrWhiteSpace(studio)) - { - info.Video.AddStudio(studio); - } - break; - } - case "postdate": - { - DateTime date; - - if (DateTime.TryParse(reader.ReadStringSafe(), USCulture, DateTimeStyles.None, out date)) - { - info.PostDate = date; - } - break; - } - case "releasedate": - { - var val = reader.ReadStringSafe(); - - if (!string.IsNullOrWhiteSpace(val)) - { - DateTime date; - - if (DateTime.TryParse(val, USCulture, DateTimeStyles.None, out date)) - { - info.Video.PremiereDate = date; - info.Video.ProductionYear = date.Year; - } - } - - break; - } - case "director": - { - var directors = reader.ReadStringSafe() ?? string.Empty; - - foreach (var director in directors.Split(',', StringSplitOptions.RemoveEmptyEntries)) - { - var name = director.Trim(); - - if (!string.IsNullOrWhiteSpace(name)) - { - info.Video.AddPerson(new PersonInfo { Name = name, Type = PersonType.Director }); - } - } - break; - } - case "description": - info.Video.Overview = reader.ReadStringSafe(); - break; - default: - reader.Skip(); - break; - } - } - } - - /// <summary> - /// Fetches from the genre node - /// </summary> - /// <param name="reader">The reader.</param> - /// <param name="info">The info.</param> - private static void FetchGenres(XmlReader reader, TrailerInfo info) - { - reader.MoveToContent(); - reader.Read(); - - while (reader.IsStartElement()) - { - if (reader.NodeType == XmlNodeType.Element) - { - switch (reader.Name) - { - case "name": - info.Video.AddGenre(reader.ReadStringSafe()); - break; - default: - reader.Skip(); - break; - } - } - } - - } - - /// <summary> - /// Fetches from the cast node - /// </summary> - /// <param name="reader">The reader.</param> - /// <param name="info">The info.</param> - private static void FetchCast(XmlReader reader, TrailerInfo info) - { - reader.MoveToContent(); - reader.Read(); - - while (reader.IsStartElement()) - { - if (reader.NodeType == XmlNodeType.Element) - { - switch (reader.Name) - { - case "name": - info.Video.AddPerson(new PersonInfo { Name = reader.ReadStringSafe(), Type = PersonType.Actor }); - break; - default: - reader.Skip(); - break; - } - } - } - - } - - /// <summary> - /// Fetches from the preview node - /// </summary> - /// <param name="reader">The reader.</param> - /// <param name="info">The info.</param> - private static void FetchTrailerUrl(XmlReader reader, TrailerInfo info) - { - reader.MoveToContent(); - reader.Read(); - - while (reader.NodeType == XmlNodeType.Element) - { - switch (reader.Name) - { - case "large": - info.TrailerUrl = reader.ReadStringSafe(); - break; - default: - reader.Skip(); - break; - } - } - - } - - /// <summary> - /// Fetches from the poster node - /// </summary> - /// <param name="reader">The reader.</param> - /// <param name="info">The info.</param> - private static void FetchPosterUrl(XmlReader reader, TrailerInfo info) - { - reader.MoveToContent(); - reader.Read(); - - while (reader.NodeType == XmlNodeType.Element) - { - switch (reader.Name) - { - case "location": - info.ImageUrl = reader.ReadStringSafe(); - break; - case "xlarge": - info.HdImageUrl = reader.ReadStringSafe(); - break; - default: - reader.Skip(); - break; - } - } - - } - - } -} diff --git a/MediaBrowser.Plugins.Trailers/Configuration/PluginConfiguration.cs b/MediaBrowser.Plugins.Trailers/Configuration/PluginConfiguration.cs deleted file mode 100644 index d54f01797..000000000 --- a/MediaBrowser.Plugins.Trailers/Configuration/PluginConfiguration.cs +++ /dev/null @@ -1,46 +0,0 @@ -using MediaBrowser.Model.Plugins; - -namespace MediaBrowser.Plugins.Trailers.Configuration -{ - /// <summary> - /// Class PluginConfiguration - /// </summary> - public class PluginConfiguration : BasePluginConfiguration - { - /// <summary> - /// Gets or sets the name of the folder. - /// </summary> - /// <value>The name of the folder.</value> - public string FolderName { get; set; } - - /// <summary> - /// Trailers older than this will not be downloaded and deleted if already downloaded. - /// </summary> - /// <value>The max trailer age.</value> - public int? MaxTrailerAge { get; set; } - - /// <summary> - /// Gets the path to where trailers should be downloaded. - /// If not supplied then programdata/cache/trailers will be used. - /// </summary> - /// <value>The download path.</value> - public string DownloadPath { get; set; } - - /// <summary> - /// Gets or sets a value indicating whether [delete old trailers]. - /// </summary> - /// <value><c>true</c> if [delete old trailers]; otherwise, <c>false</c>.</value> - public bool DeleteOldTrailers { get; set; } - - /// <summary> - /// Initializes a new instance of the <see cref="PluginConfiguration" /> class. - /// </summary> - public PluginConfiguration() - : base() - { - FolderName = "Trailers"; - - MaxTrailerAge = 60; - } - } -} diff --git a/MediaBrowser.Plugins.Trailers/Configuration/TrailerConfigurationPage.cs b/MediaBrowser.Plugins.Trailers/Configuration/TrailerConfigurationPage.cs deleted file mode 100644 index 93ce49dc2..000000000 --- a/MediaBrowser.Plugins.Trailers/Configuration/TrailerConfigurationPage.cs +++ /dev/null @@ -1,50 +0,0 @@ -using MediaBrowser.Common.Plugins; -using MediaBrowser.Controller.Plugins; -using System.ComponentModel.Composition; -using System.IO; - -namespace MediaBrowser.Plugins.Trailers.Configuration -{ - /// <summary> - /// Class TrailerConfigurationPage - /// </summary> - [Export(typeof(BaseConfigurationPage))] - class TrailerConfigurationPage : BaseConfigurationPage - { - /// <summary> - /// Gets the name. - /// </summary> - /// <value>The name.</value> - public override string Name - { - get { return "Trailers"; } - } - - /// <summary> - /// Gets the HTML stream. - /// </summary> - /// <returns>Stream.</returns> - public override Stream GetHtmlStream() - { - return GetHtmlStreamFromManifestResource("MediaBrowser.Plugins.Trailers.Configuration.configPage.html"); - } - - /// <summary> - /// Gets the owner plugin. - /// </summary> - /// <returns>BasePlugin.</returns> - public override IPlugin GetOwnerPlugin() - { - return Plugin.Instance; - } - - /// <summary> - /// Gets the type of the configuration page. - /// </summary> - /// <value>The type of the configuration page.</value> - public override ConfigurationPageType ConfigurationPageType - { - get { return ConfigurationPageType.PluginConfiguration; } - } - } -} diff --git a/MediaBrowser.Plugins.Trailers/Configuration/configPage.html b/MediaBrowser.Plugins.Trailers/Configuration/configPage.html deleted file mode 100644 index 9467f3f98..000000000 --- a/MediaBrowser.Plugins.Trailers/Configuration/configPage.html +++ /dev/null @@ -1,119 +0,0 @@ -<!DOCTYPE html> -<html> -<head> - <title>Trailers</title> -</head> -<body> - <div id="trailersConfigurationPage" data-role="page" class="page type-interior pluginConfigurationPage"> - - <div data-role="content"> - <div class="content-primary"> - <form id="trailersConfigurationForm"> - - <ul class="ulForm" data-role="listview"> - <li> - <label for="txtFolderName"> - Trailer collection name: - </label> - <input id="txtFolderName" name="txtFolderName" /> - </li> - <li> - <label for="txtMaxTrailerAge"> - Max trailer age (days): - </label> - <input type="number" id="txtMaxTrailerAge" name="txtMaxTrailerAge" pattern="[0-9]*" min="1" /> - <div class="fieldDescription"> - If specified, trailers older than this will not be downloaded - </div> - </li> - <li> - <input type="checkbox" id="chkDeleteOldTrailers" name="chkDeleteOldTrailers" /> - <label for="chkDeleteOldTrailers">Delete trailers older than the max age</label> - </li> - <li> - <label for="txtDownloadPath"> - Download path: - </label> - <div style="display: inline-block; width:92%;"> - <input id="txtDownloadPath" name="txtDownloadPath" data-inline="true" /> - </div> - <button type="button" data-icon="folder-close" data-iconpos="notext" data-inline="true" onclick="TrailersConfigurationPage.selectDirectory();">Select Directory</button> - <div class="fieldDescription"> - By default, trailers are downloaded to an internal data directory. Using a different location may make it easier to share over your network. - </div> - </li> - <li> - <button type="submit" data-theme="b">Save</button> - <button type="button" onclick="history.back();">Cancel</button> - </li> - </ul> - - </form> - </div> - </div> - - <script type="text/javascript"> - - var TrailersConfigurationPage = { - pluginUniqueId: "986a7283-205a-4436-862d-23135c067f8a", - - selectDirectory: function () { - - Dashboard.selectDirectory({ - callback: function (path) { - - if (path) { - $('#txtDownloadPath', $.mobile.activePage).val(path); - } - $('#popupDirectoryPicker', $.mobile.activePage).popup("close"); - }, - - header: "Select Trailer Path" - }); - - } - }; - - $('#trailersConfigurationPage').on('pageshow', function (event) { - - Dashboard.showLoadingMsg(); - - var page = this; - - ApiClient.getPluginConfiguration(TrailersConfigurationPage.pluginUniqueId).done(function (config) { - - $('#txtDownloadPath', page).val(config.DownloadPath); - $('#txtFolderName', page).val(config.FolderName); - $('#txtMaxTrailerAge', page).val(config.MaxTrailerAge || ""); - $('#chkDeleteOldTrailers', page).checked(config.DeleteOldTrailers).checkboxradio("refresh"); - - Dashboard.hideLoadingMsg(); - }); - }); - - $('#trailersConfigurationForm').on('submit', function (e) { - - Dashboard.showLoadingMsg(); - - var form = this; - - ApiClient.getPluginConfiguration(TrailersConfigurationPage.pluginUniqueId).done(function (config) { - - config.DownloadPath = $('#txtDownloadPath', form).val(); - config.FolderName = $('#txtFolderName', form).val(); - var maxTrailerAge = $('#txtMaxTrailerAge', form).val(); - - config.MaxTrailerAge = maxTrailerAge ? maxTrailerAge : null; - - config.DeleteOldTrailers = $('#chkDeleteOldTrailers', form).checked(); - - ApiClient.updatePluginConfiguration(TrailersConfigurationPage.pluginUniqueId, config).done(Dashboard.processPluginConfigurationUpdateResult); - }); - - // Disable default form submission - return false; - }); - </script> - </div> -</body> -</html> diff --git a/MediaBrowser.Plugins.Trailers/Entities/TrailerCollectionFolder.cs b/MediaBrowser.Plugins.Trailers/Entities/TrailerCollectionFolder.cs deleted file mode 100644 index 95ba07967..000000000 --- a/MediaBrowser.Plugins.Trailers/Entities/TrailerCollectionFolder.cs +++ /dev/null @@ -1,33 +0,0 @@ -using MediaBrowser.Controller.Entities; -using System.ComponentModel.Composition; - -namespace MediaBrowser.Plugins.Trailers.Entities -{ - /// <summary> - /// Class TrailerCollectionFolder - /// </summary> - [Export(typeof(BasePluginFolder))] - class TrailerCollectionFolder : BasePluginFolder - { - /// <summary> - /// Gets the name. - /// </summary> - /// <value>The name.</value> - public override string Name - { - get - { - return Plugin.Instance.Configuration.FolderName; - } - } - - /// <summary> - /// Gets the path. - /// </summary> - /// <value>The path.</value> - public override string Path - { - get { return Plugin.Instance.DownloadPath; } - } - } -} diff --git a/MediaBrowser.Plugins.Trailers/MediaBrowser.Plugins.Trailers.csproj b/MediaBrowser.Plugins.Trailers/MediaBrowser.Plugins.Trailers.csproj deleted file mode 100644 index 6cf2aef78..000000000 --- a/MediaBrowser.Plugins.Trailers/MediaBrowser.Plugins.Trailers.csproj +++ /dev/null @@ -1,88 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<Project ToolsVersion="4.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> - <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform> - <ProjectGuid>{2F4C01E2-7C9F-4F08-922E-27AC4A1D53FF}</ProjectGuid> - <OutputType>Library</OutputType> - <AppDesignerFolder>Properties</AppDesignerFolder> - <RootNamespace>MediaBrowser.Plugins.Trailers</RootNamespace> - <AssemblyName>MediaBrowser.Plugins.Trailers</AssemblyName> - <TargetFrameworkVersion>v4.5</TargetFrameworkVersion> - <FileAlignment>512</FileAlignment> - <SolutionDir Condition="$(SolutionDir) == '' Or $(SolutionDir) == '*Undefined*'">..\</SolutionDir> - <RestorePackages>true</RestorePackages> - </PropertyGroup> - <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' "> - <DebugSymbols>true</DebugSymbols> - <DebugType>full</DebugType> - <Optimize>false</Optimize> - <OutputPath>bin\Debug\</OutputPath> - <DefineConstants>DEBUG;TRACE</DefineConstants> - <ErrorReport>prompt</ErrorReport> - <WarningLevel>4</WarningLevel> - </PropertyGroup> - <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' "> - <DebugType>pdbonly</DebugType> - <Optimize>true</Optimize> - <OutputPath>bin\Release\</OutputPath> - <DefineConstants>TRACE</DefineConstants> - <ErrorReport>prompt</ErrorReport> - <WarningLevel>4</WarningLevel> - </PropertyGroup> - <PropertyGroup> - <RunPostBuildEvent>Always</RunPostBuildEvent> - </PropertyGroup> - <ItemGroup> - <Reference Include="System" /> - <Reference Include="System.ComponentModel.Composition" /> - <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="AppleTrailerListingDownloader.cs" /> - <Compile Include="Configuration\PluginConfiguration.cs" /> - <Compile Include="Configuration\TrailerConfigurationPage.cs" /> - <Compile Include="Providers\TrailerFromJsonProvider.cs" /> - <Compile Include="Resolvers\TrailerResolver.cs" /> - <Compile Include="ScheduledTasks\CurrentTrailerDownloadTask.cs" /> - <Compile Include="Plugin.cs" /> - <Compile Include="Properties\AssemblyInfo.cs" /> - <Compile Include="Entities\TrailerCollectionFolder.cs" /> - <Compile Include="TrailerInfo.cs" /> - </ItemGroup> - <ItemGroup> - <ProjectReference Include="..\MediaBrowser.Common\MediaBrowser.Common.csproj"> - <Project>{9142eefa-7570-41e1-bfcc-468bb571af2f}</Project> - <Name>MediaBrowser.Common</Name> - </ProjectReference> - <ProjectReference Include="..\MediaBrowser.Controller\MediaBrowser.Controller.csproj"> - <Project>{17e1f4e6-8abd-4fe5-9ecf-43d4b6087ba2}</Project> - <Name>MediaBrowser.Controller</Name> - </ProjectReference> - <ProjectReference Include="..\MediaBrowser.Model\MediaBrowser.Model.csproj"> - <Project>{7eeeb4bb-f3e8-48fc-b4c5-70f0fff8329b}</Project> - <Name>MediaBrowser.Model</Name> - </ProjectReference> - </ItemGroup> - <ItemGroup> - <EmbeddedResource Include="Configuration\configPage.html" /> - </ItemGroup> - <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" /> - <PropertyGroup> - <PostBuildEvent>xcopy "$(TargetPath)" "$(SolutionDir)\ProgramData-Server\Plugins\" /y</PostBuildEvent> - </PropertyGroup> - <Import Project="$(SolutionDir)\.nuget\nuget.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"> - </Target> - <Target Name="AfterBuild"> - </Target> - --> -</Project>
\ No newline at end of file diff --git a/MediaBrowser.Plugins.Trailers/Plugin.cs b/MediaBrowser.Plugins.Trailers/Plugin.cs deleted file mode 100644 index 2fc2773d3..000000000 --- a/MediaBrowser.Plugins.Trailers/Plugin.cs +++ /dev/null @@ -1,119 +0,0 @@ -using MediaBrowser.Common.Plugins; -using MediaBrowser.Controller.ScheduledTasks; -using MediaBrowser.Model.Plugins; -using MediaBrowser.Plugins.Trailers.Configuration; -using MediaBrowser.Plugins.Trailers.ScheduledTasks; -using System; -using System.ComponentModel.Composition; -using System.IO; - -namespace MediaBrowser.Plugins.Trailers -{ - /// <summary> - /// Class Plugin - /// </summary> - [Export(typeof(IPlugin))] - public class Plugin : BasePlugin<PluginConfiguration> - { - /// <summary> - /// Gets the name of the plugin - /// </summary> - /// <value>The name.</value> - public override string Name - { - get { return "Trailers"; } - } - - /// <summary> - /// Gets the description. - /// </summary> - /// <value>The description.</value> - public override string Description - { - get - { - return "Movie trailers for your collection."; - } - } - - /// <summary> - /// Gets the instance. - /// </summary> - /// <value>The instance.</value> - public static Plugin Instance { get; private set; } - - /// <summary> - /// Initializes a new instance of the <see cref="Plugin" /> class. - /// </summary> - public Plugin() - : base() - { - Instance = this; - } - - /// <summary> - /// The _download path - /// </summary> - private string _downloadPath; - /// <summary> - /// Gets the path to the trailer download directory - /// </summary> - /// <value>The download path.</value> - public string DownloadPath - { - get - { - if (_downloadPath == null) - { - // Use - _downloadPath = Configuration.DownloadPath; - - if (string.IsNullOrWhiteSpace(_downloadPath)) - { - _downloadPath = Path.Combine(Controller.Kernel.Instance.ApplicationPaths.DataPath, Name); - } - - if (!Directory.Exists(_downloadPath)) - { - Directory.CreateDirectory(_downloadPath); - } - } - return _downloadPath; - } - } - - /// <summary> - /// Starts the plugin on the server - /// </summary> - /// <param name="isFirstRun">if set to <c>true</c> [is first run].</param> - protected override void InitializeOnServer(bool isFirstRun) - { - base.InitializeOnServer(isFirstRun); - - if (isFirstRun) - { - Kernel.TaskManager.QueueScheduledTask<CurrentTrailerDownloadTask>(); - } - } - - /// <summary> - /// Completely overwrites the current configuration with a new copy - /// Returns true or false indicating success or failure - /// </summary> - /// <param name="configuration">The configuration.</param> - public override void UpdateConfiguration(BasePluginConfiguration configuration) - { - var config = (PluginConfiguration) configuration; - - var pathChanged = !string.Equals(Configuration.DownloadPath, config.DownloadPath, StringComparison.OrdinalIgnoreCase); - - base.UpdateConfiguration(configuration); - - if (pathChanged) - { - _downloadPath = null; - Kernel.TaskManager.QueueScheduledTask<RefreshMediaLibraryTask>(); - } - } - } -} diff --git a/MediaBrowser.Plugins.Trailers/Properties/AssemblyInfo.cs b/MediaBrowser.Plugins.Trailers/Properties/AssemblyInfo.cs deleted file mode 100644 index 32dd174d5..000000000 --- a/MediaBrowser.Plugins.Trailers/Properties/AssemblyInfo.cs +++ /dev/null @@ -1,34 +0,0 @@ -using System.Reflection; -using System.Runtime.InteropServices; - -// General Information about an assembly is controlled through the following -// set of attributes. Change these attribute values to modify the information -// associated with an assembly. -[assembly: AssemblyTitle("MediaBrowser.Plugins.Trailers")] -[assembly: AssemblyDescription("")] -[assembly: AssemblyConfiguration("")] -[assembly: AssemblyCompany("")] -[assembly: AssemblyProduct("MediaBrowser.Plugins.Trailers")] -[assembly: AssemblyCopyright("Copyright © 2012")] -[assembly: AssemblyTrademark("")] -[assembly: AssemblyCulture("")] - -// Setting ComVisible to false makes the types in this assembly not visible -// to COM components. If you need to access a type in this assembly from -// COM, set the ComVisible attribute to true on that type. -[assembly: ComVisible(false)] - -// The following GUID is for the ID of the typelib if this project is exposed to COM -[assembly: Guid("986a7283-205a-4436-862d-23135c067f8a")] - -// Version information for an assembly consists of the following four values: -// -// Major Version -// Minor Version -// Build Number -// Revision -// -// You can specify all the values or you can default the Build and Revision Numbers -// by using the '*' as shown below: -// [assembly: AssemblyVersion("1.0.*")] -[assembly: AssemblyVersion("1.0.*")] diff --git a/MediaBrowser.Plugins.Trailers/Providers/TrailerFromJsonProvider.cs b/MediaBrowser.Plugins.Trailers/Providers/TrailerFromJsonProvider.cs deleted file mode 100644 index 3f126dcdd..000000000 --- a/MediaBrowser.Plugins.Trailers/Providers/TrailerFromJsonProvider.cs +++ /dev/null @@ -1,143 +0,0 @@ -using MediaBrowser.Common.Serialization; -using MediaBrowser.Controller.Entities; -using MediaBrowser.Controller.Providers; -using MediaBrowser.Plugins.Trailers.Entities; -using System; -using System.ComponentModel.Composition; -using System.IO; -using System.Threading; -using System.Threading.Tasks; - -namespace MediaBrowser.Plugins.Trailers.Providers -{ - /// <summary> - /// Class TrailerFromJsonProvider - /// </summary> - [Export(typeof(BaseMetadataProvider))] - class TrailerFromJsonProvider : BaseMetadataProvider - { - /// <summary> - /// Supportses the specified item. - /// </summary> - /// <param name="item">The item.</param> - /// <returns><c>true</c> if XXXX, <c>false</c> otherwise</returns> - public override bool Supports(BaseItem item) - { - var trailer = item as Trailer; - - return trailer != null && trailer.Parent is TrailerCollectionFolder; - } - - /// <summary> - /// Override this to return the date that should be compared to the last refresh date - /// to determine if this provider should be re-fetched. - /// </summary> - /// <param name="item">The item.</param> - /// <returns>DateTime.</returns> - protected override DateTime CompareDate(BaseItem item) - { - var entry = item.ResolveArgs.GetMetaFileByPath(Path.Combine(item.MetaLocation, "trailer.json")); - return entry != null ? entry.Value.LastWriteTimeUtc : DateTime.MinValue; - } - - /// <summary> - /// Fetches metadata and returns true or false indicating if any work that requires persistence was done - /// </summary> - /// <param name="item">The item.</param> - /// <param name="force">if set to <c>true</c> [force].</param> - /// <returns>Task{System.Boolean}.</returns> - protected override Task<bool> FetchAsyncInternal(BaseItem item, bool force, CancellationToken cancellationToken) - { - return Task.Run(() => Fetch((Trailer)item)); - } - - /// <summary> - /// Fetches the specified item. - /// </summary> - /// <param name="item">The item.</param> - /// <returns><c>true</c> if XXXX, <c>false</c> otherwise</returns> - private bool Fetch(Trailer item) - { - var metadataFile = item.ResolveArgs.GetMetaFileByPath(Path.Combine(item.MetaLocation, "trailer.json")); - - if (metadataFile.HasValue) - { - var tempTrailer = JsonSerializer.DeserializeFromFile<Trailer>(metadataFile.Value.Path); - - ImportMetdata(tempTrailer, item); - - SetLastRefreshed(item, DateTime.UtcNow); - return true; - } - return false; - } - - /// <summary> - /// Gets the priority. - /// </summary> - /// <value>The priority.</value> - public override MetadataProviderPriority Priority - { - get { return MetadataProviderPriority.First; } - } - - /// <summary> - /// Imports the metdata. - /// </summary> - /// <param name="source">The source.</param> - /// <param name="target">The target.</param> - private void ImportMetdata(Trailer source, Trailer target) - { - if (!string.IsNullOrWhiteSpace(source.Name)) - { - target.Name = source.Name; - } - - if (source.RunTimeTicks.HasValue) - { - target.RunTimeTicks = source.RunTimeTicks; - } - - if (source.Genres != null) - { - foreach (var entry in source.Genres) - { - target.AddGenre(entry); - } - } - - if (!string.IsNullOrWhiteSpace(source.OfficialRating)) - { - target.OfficialRating = source.OfficialRating; - } - - if (!string.IsNullOrWhiteSpace(source.Overview)) - { - target.Overview = source.Overview; - } - - if (source.People != null) - { - target.AddPeople(source.People); - } - - if (source.PremiereDate.HasValue) - { - target.PremiereDate = source.PremiereDate; - } - - if (source.ProductionYear.HasValue) - { - target.ProductionYear = source.ProductionYear; - } - - if (source.Studios != null) - { - foreach (var entry in source.Studios) - { - target.AddStudio(entry); - } - } - } - } -} diff --git a/MediaBrowser.Plugins.Trailers/Resolvers/TrailerResolver.cs b/MediaBrowser.Plugins.Trailers/Resolvers/TrailerResolver.cs deleted file mode 100644 index b1e4968df..000000000 --- a/MediaBrowser.Plugins.Trailers/Resolvers/TrailerResolver.cs +++ /dev/null @@ -1,51 +0,0 @@ -using MediaBrowser.Controller.Entities; -using MediaBrowser.Controller.Library; -using MediaBrowser.Controller.Resolvers; -using System; -using System.ComponentModel.Composition; -using System.Linq; - -namespace MediaBrowser.Plugins.Trailers.Resolvers -{ - /// <summary> - /// Class TrailerResolver - /// </summary> - [Export(typeof(IBaseItemResolver))] - public class TrailerResolver : BaseVideoResolver<Trailer> - { - /// <summary> - /// Resolves the specified args. - /// </summary> - /// <param name="args">The args.</param> - /// <returns>Trailer.</returns> - protected override Trailer Resolve(ItemResolveArgs args) - { - // Must be a directory and under the trailer download folder - if (args.IsDirectory && args.Path.StartsWith(Plugin.Instance.DownloadPath, StringComparison.OrdinalIgnoreCase)) - { - // The trailer must be a video file - return FindTrailer(args); - } - - return null; - } - - /// <summary> - /// Finds a movie based on a child file system entries - /// </summary> - /// <param name="args">The args.</param> - /// <returns>Trailer.</returns> - private Trailer FindTrailer(ItemResolveArgs args) - { - // Loop through each child file/folder and see if we find a video - return args.FileSystemChildren - .Where(c => !c.IsDirectory) - .Select(child => base.Resolve(new ItemResolveArgs - { - FileInfo = child, - Path = child.Path - })) - .FirstOrDefault(i => i != null); - } - } -} diff --git a/MediaBrowser.Plugins.Trailers/ScheduledTasks/CurrentTrailerDownloadTask.cs b/MediaBrowser.Plugins.Trailers/ScheduledTasks/CurrentTrailerDownloadTask.cs deleted file mode 100644 index 47206fca0..000000000 --- a/MediaBrowser.Plugins.Trailers/ScheduledTasks/CurrentTrailerDownloadTask.cs +++ /dev/null @@ -1,311 +0,0 @@ -using MediaBrowser.Common.IO; -using MediaBrowser.Common.ScheduledTasks; -using MediaBrowser.Common.Serialization; -using MediaBrowser.Controller; -using MediaBrowser.Controller.Entities; -using MediaBrowser.Model.Net; -using MediaBrowser.Model.Tasks; -using MediaBrowser.Plugins.Trailers.Entities; -using System; -using System.Collections.Generic; -using System.ComponentModel.Composition; -using System.IO; -using System.Linq; -using System.Threading; -using System.Threading.Tasks; - -namespace MediaBrowser.Plugins.Trailers.ScheduledTasks -{ - /// <summary> - /// Downloads trailers from the web at scheduled times - /// </summary> - [Export(typeof(IScheduledTask))] - public class CurrentTrailerDownloadTask : BaseScheduledTask<Kernel> - { - /// <summary> - /// Creates the triggers that define when the task will run - /// </summary> - /// <returns>IEnumerable{BaseTaskTrigger}.</returns> - protected override IEnumerable<BaseTaskTrigger> GetDefaultTriggers() - { - var trigger = new DailyTrigger { TimeOfDay = TimeSpan.FromHours(2) }; //2am - - return new[] { trigger }; - } - - /// <summary> - /// Returns the task to be executed - /// </summary> - /// <param name="cancellationToken">The cancellation token.</param> - /// <param name="progress">The progress.</param> - /// <returns>Task.</returns> - protected override async Task ExecuteInternal(CancellationToken cancellationToken, IProgress<double> progress) - { - // Get the list of trailers - var trailers = await AppleTrailerListingDownloader.GetTrailerList(cancellationToken).ConfigureAwait(false); - - progress.Report(1); - - var trailersToDownload = trailers.Where(t => !IsOldTrailer(t.Video)).ToList(); - - cancellationToken.ThrowIfCancellationRequested(); - - var numComplete = 0; - - // Fetch them all in parallel - var tasks = trailersToDownload.Select(t => Task.Run(async () => - { - cancellationToken.ThrowIfCancellationRequested(); - - try - { - await DownloadTrailer(t, cancellationToken).ConfigureAwait(false); - } - catch (Exception ex) - { - Logger.ErrorException("Error downloading {0}", ex, t.TrailerUrl); - } - - // Update progress - lock (progress) - { - numComplete++; - double percent = numComplete; - percent /= trailersToDownload.Count; - - // Leave 1% for DeleteOldTrailers - progress.Report((99 * percent) + 1); - } - })); - - cancellationToken.ThrowIfCancellationRequested(); - - await Task.WhenAll(tasks).ConfigureAwait(false); - - cancellationToken.ThrowIfCancellationRequested(); - - if (Plugin.Instance.Configuration.DeleteOldTrailers) - { - // Enforce MaxTrailerAge - DeleteOldTrailers(); - } - - progress.Report(100); - } - - /// <summary> - /// Downloads a single trailer into the trailers directory - /// </summary> - /// <param name="trailer">The trailer.</param> - /// <param name="cancellationToken">The cancellation token.</param> - /// <returns>Task.</returns> - private async Task DownloadTrailer(TrailerInfo trailer, CancellationToken cancellationToken) - { - // Construct the trailer foldername - var folderName = FileSystem.GetValidFilename(trailer.Video.Name); - - if (trailer.Video.ProductionYear.HasValue) - { - folderName += string.Format(" ({0})", trailer.Video.ProductionYear); - } - - var folderPath = Path.Combine(Plugin.Instance.DownloadPath, folderName); - - // Figure out which image we're going to download - var imageUrl = trailer.HdImageUrl ?? trailer.ImageUrl; - - // Construct the video filename (to match the folder name) - var videoFileName = Path.ChangeExtension(folderName, Path.GetExtension(trailer.TrailerUrl)); - - // Construct the image filename (folder + original extension) - var imageFileName = Path.ChangeExtension("folder", Path.GetExtension(imageUrl)); - - // Construct full paths - var videoFilePath = Path.Combine(folderPath, videoFileName); - var imageFilePath = Path.Combine(folderPath, imageFileName); - - // Create tasks to download each of them, if we don't already have them - Task<string> videoTask = null; - Task<MemoryStream> imageTask = null; - - var tasks = new List<Task>(); - - if (!File.Exists(videoFilePath)) - { - Logger.Info("Downloading trailer: " + trailer.TrailerUrl); - - // Fetch the video to a temp file because it's too big to put into a MemoryStream - videoTask = Kernel.HttpManager.FetchToTempFile(trailer.TrailerUrl, Kernel.ResourcePools.AppleTrailerVideos, cancellationToken, new Progress<double> { }, "QuickTime/7.6.2"); - tasks.Add(videoTask); - } - - if (!string.IsNullOrWhiteSpace(imageUrl) && !File.Exists(imageFilePath)) - { - // Fetch the image to a memory stream - Logger.Info("Downloading trailer image: " + imageUrl); - imageTask = Kernel.HttpManager.FetchToMemoryStream(imageUrl, Kernel.ResourcePools.AppleTrailerImages, cancellationToken); - tasks.Add(imageTask); - } - - try - { - // Wait for both downloads to finish - await Task.WhenAll(tasks).ConfigureAwait(false); - } - catch (HttpException ex) - { - Logger.ErrorException("Error downloading trailer file or image", ex); - } - - var videoFailed = false; - var directoryEnsured = false; - - // Proces the video file task result - if (videoTask != null) - { - if (videoTask.Status == TaskStatus.RanToCompletion) - { - EnsureDirectory(folderPath); - - directoryEnsured = true; - - // Move the temp file to the final destination - try - { - File.Move(videoTask.Result, videoFilePath); - } - catch (IOException ex) - { - Logger.ErrorException("Error moving temp file", ex); - File.Delete(videoTask.Result); - videoFailed = true; - } - } - else - { - Logger.Info("Trailer download failed: " + trailer.TrailerUrl); - - // Don't bother with the image if the video download failed - videoFailed = true; - } - } - - // Process the image file task result - if (imageTask != null && !videoFailed && imageTask.Status == TaskStatus.RanToCompletion) - { - if (!directoryEnsured) - { - EnsureDirectory(folderPath); - } - - try - { - // Save the image to the file system - using (var fs = new FileStream(imageFilePath, FileMode.Create, FileAccess.Write, FileShare.Read, StreamDefaults.DefaultFileStreamBufferSize, FileOptions.Asynchronous)) - { - using (var sourceStream = imageTask.Result) - { - await sourceStream.CopyToAsync(fs).ConfigureAwait(false); - } - } - } - catch (IOException ex) - { - Logger.ErrorException("Error saving image to file system", ex); - } - } - - // Save metadata only if the video was downloaded - if (!videoFailed && videoTask != null) - { - JsonSerializer.SerializeToFile(trailer.Video, Path.Combine(folderPath, "trailer.json")); - } - } - - /// <summary> - /// Determines whether [is old trailer] [the specified trailer]. - /// </summary> - /// <param name="trailer">The trailer.</param> - /// <returns><c>true</c> if [is old trailer] [the specified trailer]; otherwise, <c>false</c>.</returns> - private bool IsOldTrailer(Trailer trailer) - { - if (!Plugin.Instance.Configuration.MaxTrailerAge.HasValue) - { - return false; - } - - if (!trailer.PremiereDate.HasValue) - { - return false; - } - - var now = DateTime.UtcNow; - - // Not old if it still hasn't premiered. - if (now < trailer.PremiereDate.Value) - { - return false; - } - - return (DateTime.UtcNow - trailer.PremiereDate.Value).TotalDays > - Plugin.Instance.Configuration.MaxTrailerAge.Value; - } - - /// <summary> - /// Deletes trailers that are older than the supplied date - /// </summary> - private void DeleteOldTrailers() - { - var collectionFolder = (Folder)Kernel.RootFolder.Children.First(c => c.GetType().Name.Equals(typeof(TrailerCollectionFolder).Name)); - - foreach (var trailer in collectionFolder.RecursiveChildren.OfType<Trailer>().Where(IsOldTrailer)) - { - Logger.Info("Deleting old trailer: " + trailer.Name); - - Directory.Delete(Path.GetDirectoryName(trailer.Path), true); - } - } - - /// <summary> - /// Ensures the directory. - /// </summary> - /// <param name="path">The path.</param> - private void EnsureDirectory(string path) - { - if (!Directory.Exists(path)) - { - Directory.CreateDirectory(path); - } - } - - /// <summary> - /// Gets the name of the task - /// </summary> - /// <value>The name.</value> - public override string Name - { - get { return "Find current trailers"; } - } - - /// <summary> - /// Gets the category. - /// </summary> - /// <value>The category.</value> - public override string Category - { - get - { - return "Trailers"; - } - } - - /// <summary> - /// Gets the description. - /// </summary> - /// <value>The description.</value> - public override string Description - { - get { return "Searches the web for upcoming movie trailers, and downloads them based on your Trailer plugin settings."; } - } - } -} diff --git a/MediaBrowser.Plugins.Trailers/TrailerInfo.cs b/MediaBrowser.Plugins.Trailers/TrailerInfo.cs deleted file mode 100644 index e3c661b67..000000000 --- a/MediaBrowser.Plugins.Trailers/TrailerInfo.cs +++ /dev/null @@ -1,45 +0,0 @@ -using MediaBrowser.Controller.Entities; -using System; - -namespace MediaBrowser.Plugins.Trailers -{ - /// <summary> - /// This is a stub class used to hold information about a trailer - /// </summary> - public class TrailerInfo - { - /// <summary> - /// Gets or sets the video. - /// </summary> - /// <value>The video.</value> - public Trailer Video { get; set; } - /// <summary> - /// Gets or sets the image URL. - /// </summary> - /// <value>The image URL.</value> - public string ImageUrl { get; set; } - /// <summary> - /// Gets or sets the hd image URL. - /// </summary> - /// <value>The hd image URL.</value> - public string HdImageUrl { get; set; } - /// <summary> - /// Gets or sets the trailer URL. - /// </summary> - /// <value>The trailer URL.</value> - public string TrailerUrl { get; set; } - /// <summary> - /// Gets or sets the post date. - /// </summary> - /// <value>The post date.</value> - public DateTime PostDate { get; set; } - - /// <summary> - /// Initializes a new instance of the <see cref="TrailerInfo" /> class. - /// </summary> - public TrailerInfo() - { - Video = new Trailer(); - } - } -} diff --git a/MediaBrowser.UI.sln b/MediaBrowser.UI.sln index dc58dc089..8b79d2c6b 100644 --- a/MediaBrowser.UI.sln +++ b/MediaBrowser.UI.sln @@ -11,10 +11,6 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MediaBrowser.ApiInteraction EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MediaBrowser.Plugins.DefaultTheme", "MediaBrowser.Plugins.DefaultTheme\MediaBrowser.Plugins.DefaultTheme.csproj", "{6E892999-711D-4E24-8BAC-DACF5BFA783A}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MediaBrowser.Plugins.MpcHc", "MediaBrowser.Plugins.MpcHc\MediaBrowser.Plugins.MpcHc.csproj", "{2E94BC08-A7A2-42DD-9893-EAA3DACD1CF9}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MediaBrowser.Plugins.Tmt5", "MediaBrowser.Plugins.Tmt5\MediaBrowser.Plugins.Tmt5.csproj", "{BE9BAA85-9EF2-4308-92E4-0D2B6E33C487}" -EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MediaBrowser.UI.Uninstall", "MediaBrowser.UI.Uninstall\MediaBrowser.UI.Uninstall.csproj", "{E4BE0659-4084-407B-B8A8-67802331CC9E}" EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MediaBrowser.IsoMounter", "MediaBrowser.IsoMounter\MediaBrowser.IsoMounter.csproj", "{5356AE30-6A6E-4A64-81E3-F76C50595E64}" @@ -95,26 +91,6 @@ Global {6E892999-711D-4E24-8BAC-DACF5BFA783A}.Release|Mixed Platforms.Build.0 = Release|Any CPU {6E892999-711D-4E24-8BAC-DACF5BFA783A}.Release|x86.ActiveCfg = Release|Any CPU {6E892999-711D-4E24-8BAC-DACF5BFA783A}.Release|x86.Build.0 = Release|Any CPU - {2E94BC08-A7A2-42DD-9893-EAA3DACD1CF9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {2E94BC08-A7A2-42DD-9893-EAA3DACD1CF9}.Debug|Any CPU.Build.0 = Debug|Any CPU - {2E94BC08-A7A2-42DD-9893-EAA3DACD1CF9}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU - {2E94BC08-A7A2-42DD-9893-EAA3DACD1CF9}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU - {2E94BC08-A7A2-42DD-9893-EAA3DACD1CF9}.Debug|x86.ActiveCfg = Debug|Any CPU - {2E94BC08-A7A2-42DD-9893-EAA3DACD1CF9}.Release|Any CPU.ActiveCfg = Release|Any CPU - {2E94BC08-A7A2-42DD-9893-EAA3DACD1CF9}.Release|Any CPU.Build.0 = Release|Any CPU - {2E94BC08-A7A2-42DD-9893-EAA3DACD1CF9}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU - {2E94BC08-A7A2-42DD-9893-EAA3DACD1CF9}.Release|Mixed Platforms.Build.0 = Release|Any CPU - {2E94BC08-A7A2-42DD-9893-EAA3DACD1CF9}.Release|x86.ActiveCfg = Release|Any CPU - {BE9BAA85-9EF2-4308-92E4-0D2B6E33C487}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {BE9BAA85-9EF2-4308-92E4-0D2B6E33C487}.Debug|Any CPU.Build.0 = Debug|Any CPU - {BE9BAA85-9EF2-4308-92E4-0D2B6E33C487}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU - {BE9BAA85-9EF2-4308-92E4-0D2B6E33C487}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU - {BE9BAA85-9EF2-4308-92E4-0D2B6E33C487}.Debug|x86.ActiveCfg = Debug|Any CPU - {BE9BAA85-9EF2-4308-92E4-0D2B6E33C487}.Release|Any CPU.ActiveCfg = Release|Any CPU - {BE9BAA85-9EF2-4308-92E4-0D2B6E33C487}.Release|Any CPU.Build.0 = Release|Any CPU - {BE9BAA85-9EF2-4308-92E4-0D2B6E33C487}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU - {BE9BAA85-9EF2-4308-92E4-0D2B6E33C487}.Release|Mixed Platforms.Build.0 = Release|Any CPU - {BE9BAA85-9EF2-4308-92E4-0D2B6E33C487}.Release|x86.ActiveCfg = Release|Any CPU {E4BE0659-4084-407B-B8A8-67802331CC9E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {E4BE0659-4084-407B-B8A8-67802331CC9E}.Debug|Any CPU.Build.0 = Debug|Any CPU {E4BE0659-4084-407B-B8A8-67802331CC9E}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU diff --git a/MediaBrowser.UI/Controller/PluginUpdater.cs b/MediaBrowser.UI/Controller/PluginUpdater.cs index c5673f2d4..e56b6f54f 100644 --- a/MediaBrowser.UI/Controller/PluginUpdater.cs +++ b/MediaBrowser.UI/Controller/PluginUpdater.cs @@ -217,7 +217,7 @@ namespace MediaBrowser.UI.Controller _logger.Info("Downloading {0} Configuration", pluginInfo.Name); // First download to a MemoryStream. This way if the download is cut off, we won't be left with a partial file - using (var stream = await UIKernel.Instance.ApiClient.GetPluginConfigurationFileAsync(pluginInfo.UniqueId).ConfigureAwait(false)) + using (var stream = await UIKernel.Instance.ApiClient.GetPluginConfigurationFileAsync(pluginInfo.Id).ConfigureAwait(false)) { using (var memoryStream = new MemoryStream()) { diff --git a/MediaBrowser.UI/MediaBrowser.UI.csproj b/MediaBrowser.UI/MediaBrowser.UI.csproj index f25707afa..798bf461a 100644 --- a/MediaBrowser.UI/MediaBrowser.UI.csproj +++ b/MediaBrowser.UI/MediaBrowser.UI.csproj @@ -5,7 +5,7 @@ <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration> <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform> <ProjectGuid>{B5ECE1FB-618E-420B-9A99-8E972D76920A}</ProjectGuid> - <OutputType>WinExe</OutputType> + <OutputType>Library</OutputType> <AppDesignerFolder>Properties</AppDesignerFolder> <RootNamespace>MediaBrowser.UI</RootNamespace> <AssemblyName>MediaBrowser.UI</AssemblyName> @@ -57,7 +57,8 @@ <WarningLevel>4</WarningLevel> </PropertyGroup> <PropertyGroup> - <StartupObject>MediaBrowser.UI.App</StartupObject> + <StartupObject> + </StartupObject> </PropertyGroup> <PropertyGroup> <ApplicationIcon>Resources\Images\Icon.ico</ApplicationIcon> diff --git a/MediaBrowser.WebDashboard/Api/DashboardService.cs b/MediaBrowser.WebDashboard/Api/DashboardService.cs index 41bde3c7f..7bf5bbab7 100644 --- a/MediaBrowser.WebDashboard/Api/DashboardService.cs +++ b/MediaBrowser.WebDashboard/Api/DashboardService.cs @@ -25,7 +25,7 @@ namespace MediaBrowser.WebDashboard.Api /// Class GetDashboardConfigurationPages /// </summary> [Route("/dashboard/ConfigurationPages", "GET")] - public class GetDashboardConfigurationPages : IReturn<List<BaseConfigurationPage>> + public class GetDashboardConfigurationPages : IReturn<List<IPluginConfigurationPage>> { /// <summary> /// Gets or sets the type of the page. @@ -38,7 +38,7 @@ namespace MediaBrowser.WebDashboard.Api /// Class GetDashboardConfigurationPage /// </summary> [Route("/dashboard/ConfigurationPage", "GET")] - public class GetDashboardConfigurationPage : IReturn<BaseConfigurationPage> + public class GetDashboardConfigurationPage : IReturn<IPluginConfigurationPage> { /// <summary> /// Gets or sets the name. @@ -139,9 +139,8 @@ namespace MediaBrowser.WebDashboard.Api var kernel = (Kernel)Kernel; var page = kernel.PluginConfigurationPages.First(p => p.Name.Equals(request.Name, StringComparison.OrdinalIgnoreCase)); - var plugin = page.GetOwnerPlugin(); - return ToStaticResult(plugin.Version.ToString().GetMD5(), plugin.AssemblyDateLastModified, null, MimeTypes.GetMimeType("page.html"), () => ModifyHtml(page.GetHtmlStream())); + return ToStaticResult(page.Version.GetMD5(), page.DateLastModified, null, MimeTypes.GetMimeType("page.html"), () => ModifyHtml(page.GetHtmlStream())); } /// <summary> diff --git a/MediaBrowser.WebDashboard/Html/scripts/PluginUpdatesPage.js b/MediaBrowser.WebDashboard/Html/scripts/PluginUpdatesPage.js index 4edb08602..a89169c53 100644 --- a/MediaBrowser.WebDashboard/Html/scripts/PluginUpdatesPage.js +++ b/MediaBrowser.WebDashboard/Html/scripts/PluginUpdatesPage.js @@ -41,7 +41,7 @@ var options = PluginUpdatesPage.getHtmlOptions(["Off", "On"], (plugin.EnableAutoUpdate ? "On" : "Off")); html += "<td>"; - html += "<select data-uniqueid='" + plugin.UniqueId + "' onchange='PluginUpdatesPage.setAutoUpdate(this);' data-role='slider' id='" + fieldId + "' name='" + fieldId + "'>" + options + "</select>"; + html += "<select data-id='" + plugin.Id + "' onchange='PluginUpdatesPage.setAutoUpdate(this);' data-role='slider' id='" + fieldId + "' name='" + fieldId + "'>" + options + "</select>"; html += "</td>"; fieldId = "liPluginUpdateFieldb" + fieldIndex; @@ -49,7 +49,7 @@ options = PluginUpdatesPage.getHtmlOptions(["Release", "Beta", "Dev"], plugin.UpdateClass); html += "<td>"; - html += "<select data-uniqueid='" + plugin.UniqueId + "' onchange='PluginUpdatesPage.setUpdateClass(this);' data-inline='true' id='" + fieldId + "' name='" + fieldId + "'>" + options + "</select>"; + html += "<select data-id='" + plugin.Id + "' onchange='PluginUpdatesPage.setUpdateClass(this);' data-inline='true' id='" + fieldId + "' name='" + fieldId + "'>" + options + "</select>"; html += "</td>"; html += "</tr>"; @@ -79,7 +79,7 @@ setAutoUpdate: function (select) { - var id = $(select).attr('data-uniqueid'); + var id = $(select).attr('data-id'); Dashboard.showLoadingMsg(); @@ -93,7 +93,7 @@ setUpdateClass: function (select) { - var id = $(select).attr('data-uniqueid'); + var id = $(select).attr('data-id'); Dashboard.showLoadingMsg(); diff --git a/MediaBrowser.WebDashboard/Html/scripts/PluginsPage.js b/MediaBrowser.WebDashboard/Html/scripts/PluginsPage.js index f7e05e4ba..e9098427d 100644 --- a/MediaBrowser.WebDashboard/Html/scripts/PluginsPage.js +++ b/MediaBrowser.WebDashboard/Html/scripts/PluginsPage.js @@ -40,7 +40,7 @@ } var configPage = $.grep(pluginConfigurationPages, function (pluginConfigurationPage) { - return pluginConfigurationPage.OwnerPluginName == plugin.Name; + return pluginConfigurationPage.PluginId == plugin.Id; })[0]; html += "<li>"; @@ -56,7 +56,7 @@ html += "</a>"; if (!plugin.IsCorePlugin) { - html += "<a data-uniqueid='" + plugin.UniqueId + "' data-pluginname='" + plugin.Name + "' onclick='PluginsPage.deletePlugin(this);' href='#'>Delete</a>"; + html += "<a data-id='" + plugin.Id + "' data-pluginname='" + plugin.Name + "' onclick='PluginsPage.deletePlugin(this);' href='#'>Delete</a>"; } html += "</li>"; @@ -70,7 +70,7 @@ deletePlugin: function (link) { var name = link.getAttribute('data-pluginname'); - var uniqueid = link.getAttribute('data-uniqueid'); + var uniqueid = link.getAttribute('data-id'); var msg = "Are you sure you wish to uninstall " + name + "?"; diff --git a/MediaBrowser.sln b/MediaBrowser.sln index 27b0f81b5..902792c2e 100644 --- a/MediaBrowser.sln +++ b/MediaBrowser.sln @@ -20,8 +20,6 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Performance19.psess = Performance19.psess EndProjectSection EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MediaBrowser.Plugins.Trailers", "MediaBrowser.Plugins.Trailers\MediaBrowser.Plugins.Trailers.csproj", "{2F4C01E2-7C9F-4F08-922E-27AC4A1D53FF}" -EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MediaBrowser.ApiInteraction.Javascript", "MediaBrowser.ApiInteraction.Javascript\MediaBrowser.ApiInteraction.Javascript.csproj", "{767B536E-D90C-4D74-A14B-8564B16F3499}" EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MediaBrowser.ApiInteraction", "MediaBrowser.ApiInteraction\MediaBrowser.ApiInteraction.csproj", "{921C0F64-FDA7-4E9F-9E73-0CB0EEDB2422}" @@ -41,8 +39,6 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "BDInfo", "BDInfo\BDInfo.csp EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MediaBrowser.IsoMounter", "MediaBrowser.IsoMounter\MediaBrowser.IsoMounter.csproj", "{5356AE30-6A6E-4A64-81E3-F76C50595E64}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MediaBrowser.Plugins.Dlna", "MediaBrowser.Plugins.Dlna\MediaBrowser.Plugins.Dlna.csproj", "{A2CF4266-2110-419E-8620-E2FEEFCA0F48}" -EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MediaBrowser.Installer", "MediaBrowser.Installer\MediaBrowser.Installer.csproj", "{3879F78A-D6F6-45E5-B2A8-D8DCF2DABB74}" EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MediaBrowser.Server.Sqlite", "MediaBrowser.Server.Sqlite\MediaBrowser.Server.Sqlite.csproj", "{8649ED6B-8504-4D00-BFA5-B8C73CC744DB}" @@ -163,21 +159,6 @@ Global {5624B7B5-B5A7-41D8-9F10-CC5611109619}.Release|x64.ActiveCfg = Release|Any CPU {5624B7B5-B5A7-41D8-9F10-CC5611109619}.Release|x86.ActiveCfg = Release|Any CPU {5624B7B5-B5A7-41D8-9F10-CC5611109619}.Release|x86.Build.0 = Release|Any CPU - {2F4C01E2-7C9F-4F08-922E-27AC4A1D53FF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {2F4C01E2-7C9F-4F08-922E-27AC4A1D53FF}.Debug|Any CPU.Build.0 = Debug|Any CPU - {2F4C01E2-7C9F-4F08-922E-27AC4A1D53FF}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU - {2F4C01E2-7C9F-4F08-922E-27AC4A1D53FF}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU - {2F4C01E2-7C9F-4F08-922E-27AC4A1D53FF}.Debug|Win32.ActiveCfg = Debug|Any CPU - {2F4C01E2-7C9F-4F08-922E-27AC4A1D53FF}.Debug|x64.ActiveCfg = Debug|Any CPU - {2F4C01E2-7C9F-4F08-922E-27AC4A1D53FF}.Debug|x86.ActiveCfg = Debug|Any CPU - {2F4C01E2-7C9F-4F08-922E-27AC4A1D53FF}.Debug|x86.Build.0 = Debug|Any CPU - {2F4C01E2-7C9F-4F08-922E-27AC4A1D53FF}.Release|Any CPU.ActiveCfg = Release|Any CPU - {2F4C01E2-7C9F-4F08-922E-27AC4A1D53FF}.Release|Any CPU.Build.0 = Release|Any CPU - {2F4C01E2-7C9F-4F08-922E-27AC4A1D53FF}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU - {2F4C01E2-7C9F-4F08-922E-27AC4A1D53FF}.Release|Mixed Platforms.Build.0 = Release|Any CPU - {2F4C01E2-7C9F-4F08-922E-27AC4A1D53FF}.Release|Win32.ActiveCfg = Release|Any CPU - {2F4C01E2-7C9F-4F08-922E-27AC4A1D53FF}.Release|x64.ActiveCfg = Release|Any CPU - {2F4C01E2-7C9F-4F08-922E-27AC4A1D53FF}.Release|x86.ActiveCfg = Release|Any CPU {767B536E-D90C-4D74-A14B-8564B16F3499}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {767B536E-D90C-4D74-A14B-8564B16F3499}.Debug|Any CPU.Build.0 = Debug|Any CPU {767B536E-D90C-4D74-A14B-8564B16F3499}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU @@ -267,20 +248,6 @@ Global {5356AE30-6A6E-4A64-81E3-F76C50595E64}.Release|Win32.ActiveCfg = Release|Any CPU {5356AE30-6A6E-4A64-81E3-F76C50595E64}.Release|x64.ActiveCfg = Release|Any CPU {5356AE30-6A6E-4A64-81E3-F76C50595E64}.Release|x86.ActiveCfg = Release|Any CPU - {A2CF4266-2110-419E-8620-E2FEEFCA0F48}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {A2CF4266-2110-419E-8620-E2FEEFCA0F48}.Debug|Any CPU.Build.0 = Debug|Any CPU - {A2CF4266-2110-419E-8620-E2FEEFCA0F48}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU - {A2CF4266-2110-419E-8620-E2FEEFCA0F48}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU - {A2CF4266-2110-419E-8620-E2FEEFCA0F48}.Debug|Win32.ActiveCfg = Debug|Any CPU - {A2CF4266-2110-419E-8620-E2FEEFCA0F48}.Debug|x64.ActiveCfg = Debug|Any CPU - {A2CF4266-2110-419E-8620-E2FEEFCA0F48}.Debug|x86.ActiveCfg = Debug|Any CPU - {A2CF4266-2110-419E-8620-E2FEEFCA0F48}.Release|Any CPU.ActiveCfg = Release|Any CPU - {A2CF4266-2110-419E-8620-E2FEEFCA0F48}.Release|Any CPU.Build.0 = Release|Any CPU - {A2CF4266-2110-419E-8620-E2FEEFCA0F48}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU - {A2CF4266-2110-419E-8620-E2FEEFCA0F48}.Release|Mixed Platforms.Build.0 = Release|Any CPU - {A2CF4266-2110-419E-8620-E2FEEFCA0F48}.Release|Win32.ActiveCfg = Release|Any CPU - {A2CF4266-2110-419E-8620-E2FEEFCA0F48}.Release|x64.ActiveCfg = Release|Any CPU - {A2CF4266-2110-419E-8620-E2FEEFCA0F48}.Release|x86.ActiveCfg = Release|Any CPU {3879F78A-D6F6-45E5-B2A8-D8DCF2DABB74}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {3879F78A-D6F6-45E5-B2A8-D8DCF2DABB74}.Debug|Any CPU.Build.0 = Debug|Any CPU {3879F78A-D6F6-45E5-B2A8-D8DCF2DABB74}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU diff --git a/Nuget/MediaBrowser.Server.Core.nupkg.REMOVED.git-id b/Nuget/MediaBrowser.Server.Core.nupkg.REMOVED.git-id new file mode 100644 index 000000000..a2490601e --- /dev/null +++ b/Nuget/MediaBrowser.Server.Core.nupkg.REMOVED.git-id @@ -0,0 +1 @@ +da3d30d634468465d8995ba6cb1c0872959b3e9c
\ No newline at end of file |
