mirror of
https://github.com/jellyfin/jellyfin.git
synced 2025-07-09 03:04:24 -04:00
moved Plugins to separate repo
This commit is contained in:
parent
868a7ce9c8
commit
746c5d2fa7
@ -141,7 +141,7 @@ namespace MediaBrowser.Api
|
|||||||
/// <returns>System.Object.</returns>
|
/// <returns>System.Object.</returns>
|
||||||
public object Get(GetPluginAssembly request)
|
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);
|
return ToStaticFileResult(plugin.AssemblyFilePath);
|
||||||
}
|
}
|
||||||
@ -153,7 +153,7 @@ namespace MediaBrowser.Api
|
|||||||
/// <returns>System.Object.</returns>
|
/// <returns>System.Object.</returns>
|
||||||
public object Get(GetPluginConfiguration request)
|
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;
|
var dateModified = plugin.ConfigurationDateLastModified;
|
||||||
|
|
||||||
@ -169,7 +169,7 @@ namespace MediaBrowser.Api
|
|||||||
/// <returns>System.Object.</returns>
|
/// <returns>System.Object.</returns>
|
||||||
public object Get(GetPluginConfigurationFile request)
|
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);
|
return ToStaticFileResult(plugin.ConfigurationFilePath);
|
||||||
}
|
}
|
||||||
@ -218,7 +218,7 @@ namespace MediaBrowser.Api
|
|||||||
var pathInfo = PathInfo.Parse(Request.PathInfo);
|
var pathInfo = PathInfo.Parse(Request.PathInfo);
|
||||||
var id = new Guid(pathInfo.GetArgumentValue<string>(1));
|
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;
|
var configuration = JsonSerializer.DeserializeFromStream(request.RequestStream, plugin.ConfigurationType) as BasePluginConfiguration;
|
||||||
|
|
||||||
@ -233,7 +233,7 @@ namespace MediaBrowser.Api
|
|||||||
{
|
{
|
||||||
var kernel = (Kernel)Kernel;
|
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);
|
kernel.InstallationManager.UninstallPlugin(plugin);
|
||||||
}
|
}
|
||||||
|
@ -382,15 +382,15 @@ var ApiClient = {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the configuration of a plugin
|
* Gets the configuration of a plugin
|
||||||
* @param {String} uniqueId
|
* @param {String} Id
|
||||||
*/
|
*/
|
||||||
getPluginConfiguration: function (uniqueId) {
|
getPluginConfiguration: function (id) {
|
||||||
|
|
||||||
if (!uniqueId) {
|
if (!id) {
|
||||||
throw new Error("null uniqueId");
|
throw new Error("null Id");
|
||||||
}
|
}
|
||||||
|
|
||||||
var url = ApiClient.getUrl("Plugins/" + uniqueId + "/Configuration");
|
var url = ApiClient.getUrl("Plugins/" + id + "/Configuration");
|
||||||
|
|
||||||
return $.getJSON(url);
|
return $.getJSON(url);
|
||||||
},
|
},
|
||||||
@ -407,15 +407,15 @@ var ApiClient = {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Uninstalls a plugin
|
* Uninstalls a plugin
|
||||||
* @param {String} uniqueId
|
* @param {String} Id
|
||||||
*/
|
*/
|
||||||
uninstallPlugin: function (uniqueId) {
|
uninstallPlugin: function (id) {
|
||||||
|
|
||||||
if (!uniqueId) {
|
if (!id) {
|
||||||
throw new Error("null uniqueId");
|
throw new Error("null Id");
|
||||||
}
|
}
|
||||||
|
|
||||||
var url = ApiClient.getUrl("Plugins/" + uniqueId);
|
var url = ApiClient.getUrl("Plugins/" + id);
|
||||||
|
|
||||||
return $.ajax({
|
return $.ajax({
|
||||||
type: "DELETE",
|
type: "DELETE",
|
||||||
@ -1207,20 +1207,20 @@ var ApiClient = {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Updates a plugin's configuration
|
* Updates a plugin's configuration
|
||||||
* @param {String} uniqueId
|
* @param {String} Id
|
||||||
* @param {Object} configuration
|
* @param {Object} configuration
|
||||||
*/
|
*/
|
||||||
updatePluginConfiguration: function (uniqueId, configuration) {
|
updatePluginConfiguration: function (id, configuration) {
|
||||||
|
|
||||||
if (!uniqueId) {
|
if (!id) {
|
||||||
throw new Error("null uniqueId");
|
throw new Error("null Id");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!configuration) {
|
if (!configuration) {
|
||||||
throw new Error("null 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));
|
return $.post(url, JSON.stringify(configuration));
|
||||||
},
|
},
|
||||||
|
@ -362,7 +362,7 @@ namespace MediaBrowser.ApiInteraction
|
|||||||
throw new ArgumentNullException("plugin");
|
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);
|
return HttpClient.GetStreamAsync(url, Logger, CancellationToken.None);
|
||||||
}
|
}
|
||||||
|
@ -90,7 +90,7 @@ namespace MediaBrowser.Common.Plugins
|
|||||||
/// Gets the unique id.
|
/// Gets the unique id.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <value>The unique id.</value>
|
/// <value>The unique id.</value>
|
||||||
public Guid UniqueId
|
public Guid Id
|
||||||
{
|
{
|
||||||
get
|
get
|
||||||
{
|
{
|
||||||
@ -419,7 +419,7 @@ namespace MediaBrowser.Common.Plugins
|
|||||||
ConfigurationDateLastModified = ConfigurationDateLastModified,
|
ConfigurationDateLastModified = ConfigurationDateLastModified,
|
||||||
Description = Description,
|
Description = Description,
|
||||||
IsCorePlugin = IsCorePlugin,
|
IsCorePlugin = IsCorePlugin,
|
||||||
UniqueId = UniqueId,
|
Id = Id,
|
||||||
EnableAutoUpdate = Configuration.EnableAutoUpdate,
|
EnableAutoUpdate = Configuration.EnableAutoUpdate,
|
||||||
UpdateClass = Configuration.UpdateClass,
|
UpdateClass = Configuration.UpdateClass,
|
||||||
ConfigurationFileName = ConfigurationFileName
|
ConfigurationFileName = ConfigurationFileName
|
||||||
|
@ -35,7 +35,7 @@ namespace MediaBrowser.Common.Plugins
|
|||||||
/// Gets the unique id.
|
/// Gets the unique id.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <value>The unique id.</value>
|
/// <value>The unique id.</value>
|
||||||
Guid UniqueId { get; }
|
Guid Id { get; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets the plugin version
|
/// Gets the plugin version
|
||||||
|
@ -182,8 +182,8 @@ namespace MediaBrowser.Controller
|
|||||||
/// Gets the list of plugin configuration pages
|
/// Gets the list of plugin configuration pages
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <value>The configuration pages.</value>
|
/// <value>The configuration pages.</value>
|
||||||
[ImportMany(typeof(BaseConfigurationPage))]
|
[ImportMany(typeof(IPluginConfigurationPage))]
|
||||||
public IEnumerable<BaseConfigurationPage> PluginConfigurationPages { get; private set; }
|
public IEnumerable<IPluginConfigurationPage> PluginConfigurationPages { get; private set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets the intro providers.
|
/// Gets the intro providers.
|
||||||
|
@ -128,7 +128,7 @@
|
|||||||
<Compile Include="Persistence\IUserRepository.cs" />
|
<Compile Include="Persistence\IUserRepository.cs" />
|
||||||
<Compile Include="Persistence\TypeMapper.cs" />
|
<Compile Include="Persistence\TypeMapper.cs" />
|
||||||
<Compile Include="Playback\IIntroProvider.cs" />
|
<Compile Include="Playback\IIntroProvider.cs" />
|
||||||
<Compile Include="Plugins\BaseConfigurationPage.cs" />
|
<Compile Include="Plugins\IPluginConfigurationPage.cs" />
|
||||||
<Compile Include="Plugins\PluginSecurityManager.cs" />
|
<Compile Include="Plugins\PluginSecurityManager.cs" />
|
||||||
<Compile Include="Providers\FanartBaseProvider.cs" />
|
<Compile Include="Providers\FanartBaseProvider.cs" />
|
||||||
<Compile Include="Providers\BaseImageEnhancer.cs" />
|
<Compile Include="Providers\BaseImageEnhancer.cs" />
|
||||||
|
@ -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
|
|
||||||
}
|
|
||||||
}
|
|
61
MediaBrowser.Controller/Plugins/IPluginConfigurationPage.cs
Normal file
61
MediaBrowser.Controller/Plugins/IPluginConfigurationPage.cs
Normal file
@ -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
|
||||||
|
}
|
||||||
|
}
|
@ -71,7 +71,7 @@ namespace MediaBrowser.Model.Plugins
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
/// <value>The unique id.</value>
|
/// <value>The unique id.</value>
|
||||||
[ProtoMember(9)]
|
[ProtoMember(9)]
|
||||||
public Guid UniqueId { get; set; }
|
public Guid Id { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Whether or not this plug-in should be automatically updated when a
|
/// Whether or not this plug-in should be automatically updated when a
|
||||||
|
@ -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; }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -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>
|
|
@ -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>
|
|
File diff suppressed because it is too large
Load Diff
@ -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.*")]
|
|
@ -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>
|
|
@ -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";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -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"); }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -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.*")]
|
|
@ -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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -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>
|
|
@ -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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,7 +0,0 @@
|
|||||||
<?xml version='1.0' encoding='utf-8'?>
|
|
||||||
<SettingsFile xmlns="uri:settings" CurrentProfile="(Default)">
|
|
||||||
<Profiles>
|
|
||||||
<Profile Name="(Default)" />
|
|
||||||
</Profiles>
|
|
||||||
<Settings />
|
|
||||||
</SettingsFile>
|
|
@ -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>
|
|
@ -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>
|
|
@ -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"); }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -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.*")]
|
|
@ -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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -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>
|
|
@ -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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,7 +0,0 @@
|
|||||||
<?xml version='1.0' encoding='utf-8'?>
|
|
||||||
<SettingsFile xmlns="uri:settings" CurrentProfile="(Default)">
|
|
||||||
<Profiles>
|
|
||||||
<Profile Name="(Default)" />
|
|
||||||
</Profiles>
|
|
||||||
<Settings />
|
|
||||||
</SettingsFile>
|
|
@ -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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -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>
|
|
@ -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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
@ -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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -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; }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -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>
|
|
@ -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; }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -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>
|
|
@ -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>();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -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.*")]
|
|
@ -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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -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."; }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -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();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -11,10 +11,6 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MediaBrowser.ApiInteraction
|
|||||||
EndProject
|
EndProject
|
||||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MediaBrowser.Plugins.DefaultTheme", "MediaBrowser.Plugins.DefaultTheme\MediaBrowser.Plugins.DefaultTheme.csproj", "{6E892999-711D-4E24-8BAC-DACF5BFA783A}"
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MediaBrowser.Plugins.DefaultTheme", "MediaBrowser.Plugins.DefaultTheme\MediaBrowser.Plugins.DefaultTheme.csproj", "{6E892999-711D-4E24-8BAC-DACF5BFA783A}"
|
||||||
EndProject
|
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}"
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MediaBrowser.UI.Uninstall", "MediaBrowser.UI.Uninstall\MediaBrowser.UI.Uninstall.csproj", "{E4BE0659-4084-407B-B8A8-67802331CC9E}"
|
||||||
EndProject
|
EndProject
|
||||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MediaBrowser.IsoMounter", "MediaBrowser.IsoMounter\MediaBrowser.IsoMounter.csproj", "{5356AE30-6A6E-4A64-81E3-F76C50595E64}"
|
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|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.ActiveCfg = Release|Any CPU
|
||||||
{6E892999-711D-4E24-8BAC-DACF5BFA783A}.Release|x86.Build.0 = 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.ActiveCfg = Debug|Any CPU
|
||||||
{E4BE0659-4084-407B-B8A8-67802331CC9E}.Debug|Any CPU.Build.0 = 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
|
{E4BE0659-4084-407B-B8A8-67802331CC9E}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
|
||||||
|
@ -217,7 +217,7 @@ namespace MediaBrowser.UI.Controller
|
|||||||
_logger.Info("Downloading {0} Configuration", pluginInfo.Name);
|
_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
|
// 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())
|
using (var memoryStream = new MemoryStream())
|
||||||
{
|
{
|
||||||
|
@ -5,7 +5,7 @@
|
|||||||
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
||||||
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
|
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
|
||||||
<ProjectGuid>{B5ECE1FB-618E-420B-9A99-8E972D76920A}</ProjectGuid>
|
<ProjectGuid>{B5ECE1FB-618E-420B-9A99-8E972D76920A}</ProjectGuid>
|
||||||
<OutputType>WinExe</OutputType>
|
<OutputType>Library</OutputType>
|
||||||
<AppDesignerFolder>Properties</AppDesignerFolder>
|
<AppDesignerFolder>Properties</AppDesignerFolder>
|
||||||
<RootNamespace>MediaBrowser.UI</RootNamespace>
|
<RootNamespace>MediaBrowser.UI</RootNamespace>
|
||||||
<AssemblyName>MediaBrowser.UI</AssemblyName>
|
<AssemblyName>MediaBrowser.UI</AssemblyName>
|
||||||
@ -57,7 +57,8 @@
|
|||||||
<WarningLevel>4</WarningLevel>
|
<WarningLevel>4</WarningLevel>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<StartupObject>MediaBrowser.UI.App</StartupObject>
|
<StartupObject>
|
||||||
|
</StartupObject>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<ApplicationIcon>Resources\Images\Icon.ico</ApplicationIcon>
|
<ApplicationIcon>Resources\Images\Icon.ico</ApplicationIcon>
|
||||||
|
@ -25,7 +25,7 @@ namespace MediaBrowser.WebDashboard.Api
|
|||||||
/// Class GetDashboardConfigurationPages
|
/// Class GetDashboardConfigurationPages
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[Route("/dashboard/ConfigurationPages", "GET")]
|
[Route("/dashboard/ConfigurationPages", "GET")]
|
||||||
public class GetDashboardConfigurationPages : IReturn<List<BaseConfigurationPage>>
|
public class GetDashboardConfigurationPages : IReturn<List<IPluginConfigurationPage>>
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets or sets the type of the page.
|
/// Gets or sets the type of the page.
|
||||||
@ -38,7 +38,7 @@ namespace MediaBrowser.WebDashboard.Api
|
|||||||
/// Class GetDashboardConfigurationPage
|
/// Class GetDashboardConfigurationPage
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[Route("/dashboard/ConfigurationPage", "GET")]
|
[Route("/dashboard/ConfigurationPage", "GET")]
|
||||||
public class GetDashboardConfigurationPage : IReturn<BaseConfigurationPage>
|
public class GetDashboardConfigurationPage : IReturn<IPluginConfigurationPage>
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets or sets the name.
|
/// Gets or sets the name.
|
||||||
@ -139,9 +139,8 @@ namespace MediaBrowser.WebDashboard.Api
|
|||||||
var kernel = (Kernel)Kernel;
|
var kernel = (Kernel)Kernel;
|
||||||
|
|
||||||
var page = kernel.PluginConfigurationPages.First(p => p.Name.Equals(request.Name, StringComparison.OrdinalIgnoreCase));
|
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>
|
/// <summary>
|
||||||
|
@ -41,7 +41,7 @@
|
|||||||
var options = PluginUpdatesPage.getHtmlOptions(["Off", "On"], (plugin.EnableAutoUpdate ? "On" : "Off"));
|
var options = PluginUpdatesPage.getHtmlOptions(["Off", "On"], (plugin.EnableAutoUpdate ? "On" : "Off"));
|
||||||
|
|
||||||
html += "<td>";
|
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>";
|
html += "</td>";
|
||||||
|
|
||||||
fieldId = "liPluginUpdateFieldb" + fieldIndex;
|
fieldId = "liPluginUpdateFieldb" + fieldIndex;
|
||||||
@ -49,7 +49,7 @@
|
|||||||
options = PluginUpdatesPage.getHtmlOptions(["Release", "Beta", "Dev"], plugin.UpdateClass);
|
options = PluginUpdatesPage.getHtmlOptions(["Release", "Beta", "Dev"], plugin.UpdateClass);
|
||||||
|
|
||||||
html += "<td>";
|
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 += "</td>";
|
||||||
|
|
||||||
html += "</tr>";
|
html += "</tr>";
|
||||||
@ -79,7 +79,7 @@
|
|||||||
|
|
||||||
setAutoUpdate: function (select) {
|
setAutoUpdate: function (select) {
|
||||||
|
|
||||||
var id = $(select).attr('data-uniqueid');
|
var id = $(select).attr('data-id');
|
||||||
|
|
||||||
Dashboard.showLoadingMsg();
|
Dashboard.showLoadingMsg();
|
||||||
|
|
||||||
@ -93,7 +93,7 @@
|
|||||||
|
|
||||||
setUpdateClass: function (select) {
|
setUpdateClass: function (select) {
|
||||||
|
|
||||||
var id = $(select).attr('data-uniqueid');
|
var id = $(select).attr('data-id');
|
||||||
|
|
||||||
Dashboard.showLoadingMsg();
|
Dashboard.showLoadingMsg();
|
||||||
|
|
||||||
|
@ -40,7 +40,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
var configPage = $.grep(pluginConfigurationPages, function (pluginConfigurationPage) {
|
var configPage = $.grep(pluginConfigurationPages, function (pluginConfigurationPage) {
|
||||||
return pluginConfigurationPage.OwnerPluginName == plugin.Name;
|
return pluginConfigurationPage.PluginId == plugin.Id;
|
||||||
})[0];
|
})[0];
|
||||||
|
|
||||||
html += "<li>";
|
html += "<li>";
|
||||||
@ -56,7 +56,7 @@
|
|||||||
html += "</a>";
|
html += "</a>";
|
||||||
|
|
||||||
if (!plugin.IsCorePlugin) {
|
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>";
|
html += "</li>";
|
||||||
@ -70,7 +70,7 @@
|
|||||||
deletePlugin: function (link) {
|
deletePlugin: function (link) {
|
||||||
|
|
||||||
var name = link.getAttribute('data-pluginname');
|
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 + "?";
|
var msg = "Are you sure you wish to uninstall " + name + "?";
|
||||||
|
|
||||||
|
@ -20,8 +20,6 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution
|
|||||||
Performance19.psess = Performance19.psess
|
Performance19.psess = Performance19.psess
|
||||||
EndProjectSection
|
EndProjectSection
|
||||||
EndProject
|
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}"
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MediaBrowser.ApiInteraction.Javascript", "MediaBrowser.ApiInteraction.Javascript\MediaBrowser.ApiInteraction.Javascript.csproj", "{767B536E-D90C-4D74-A14B-8564B16F3499}"
|
||||||
EndProject
|
EndProject
|
||||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MediaBrowser.ApiInteraction", "MediaBrowser.ApiInteraction\MediaBrowser.ApiInteraction.csproj", "{921C0F64-FDA7-4E9F-9E73-0CB0EEDB2422}"
|
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
|
EndProject
|
||||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MediaBrowser.IsoMounter", "MediaBrowser.IsoMounter\MediaBrowser.IsoMounter.csproj", "{5356AE30-6A6E-4A64-81E3-F76C50595E64}"
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MediaBrowser.IsoMounter", "MediaBrowser.IsoMounter\MediaBrowser.IsoMounter.csproj", "{5356AE30-6A6E-4A64-81E3-F76C50595E64}"
|
||||||
EndProject
|
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}"
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MediaBrowser.Installer", "MediaBrowser.Installer\MediaBrowser.Installer.csproj", "{3879F78A-D6F6-45E5-B2A8-D8DCF2DABB74}"
|
||||||
EndProject
|
EndProject
|
||||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MediaBrowser.Server.Sqlite", "MediaBrowser.Server.Sqlite\MediaBrowser.Server.Sqlite.csproj", "{8649ED6B-8504-4D00-BFA5-B8C73CC744DB}"
|
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|x64.ActiveCfg = Release|Any CPU
|
||||||
{5624B7B5-B5A7-41D8-9F10-CC5611109619}.Release|x86.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
|
{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.ActiveCfg = Debug|Any CPU
|
||||||
{767B536E-D90C-4D74-A14B-8564B16F3499}.Debug|Any CPU.Build.0 = 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
|
{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|Win32.ActiveCfg = Release|Any CPU
|
||||||
{5356AE30-6A6E-4A64-81E3-F76C50595E64}.Release|x64.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
|
{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.ActiveCfg = Debug|Any CPU
|
||||||
{3879F78A-D6F6-45E5-B2A8-D8DCF2DABB74}.Debug|Any CPU.Build.0 = 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
|
{3879F78A-D6F6-45E5-B2A8-D8DCF2DABB74}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
|
||||||
|
1
Nuget/MediaBrowser.Server.Core.nupkg.REMOVED.git-id
Normal file
1
Nuget/MediaBrowser.Server.Core.nupkg.REMOVED.git-id
Normal file
@ -0,0 +1 @@
|
|||||||
|
da3d30d634468465d8995ba6cb1c0872959b3e9c
|
Loading…
x
Reference in New Issue
Block a user