3 Commits
Author SHA1 Message Date
Luke Pulverenti a08bbd0f31 3.2.1 2019-08-12 14:04:56 -04:00
Luke Pulverenti f7a7fced43 update recordings on schedule 2019-05-09 13:14:09 -04:00
Luke Pulverenti 46ea3e4c21 switch to DateTimeOffset 2018-09-07 15:22:39 -04:00
12 changed files with 555 additions and 791 deletions
-199
View File
@@ -1,199 +0,0 @@
# With more recent updates Visual Studio 2017 supports EditorConfig files out of the box
# Visual Studio Code needs an extension: https://github.com/editorconfig/editorconfig-vscode
# For emacs, vim, np++ and other editors, see here: https://github.com/editorconfig
###############################
# Core EditorConfig Options #
###############################
root = true
# All files
[*]
indent_style = space
indent_size = 4
charset = utf-8
trim_trailing_whitespace = true
insert_final_newline = true
end_of_line = lf
max_line_length = 9999
# YAML indentation
[*.{yml,yaml}]
indent_size = 2
# XML indentation
[*.{csproj,xml}]
indent_size = 2
###############################
# .NET Coding Conventions #
###############################
[*.{cs,vb}]
# Organize usings
dotnet_sort_system_directives_first = true
# this. preferences
dotnet_style_qualification_for_field = false:silent
dotnet_style_qualification_for_property = false:silent
dotnet_style_qualification_for_method = false:silent
dotnet_style_qualification_for_event = false:silent
# Language keywords vs BCL types preferences
dotnet_style_predefined_type_for_locals_parameters_members = true:silent
dotnet_style_predefined_type_for_member_access = true:silent
# Parentheses preferences
dotnet_style_parentheses_in_arithmetic_binary_operators = always_for_clarity:silent
dotnet_style_parentheses_in_relational_binary_operators = always_for_clarity:silent
dotnet_style_parentheses_in_other_binary_operators = always_for_clarity:silent
dotnet_style_parentheses_in_other_operators = never_if_unnecessary:silent
# Modifier preferences
dotnet_style_require_accessibility_modifiers = for_non_interface_members:silent
dotnet_style_readonly_field = true:suggestion
# Expression-level preferences
dotnet_style_object_initializer = true:suggestion
dotnet_style_collection_initializer = true:suggestion
dotnet_style_explicit_tuple_names = true:suggestion
dotnet_style_null_propagation = true:suggestion
dotnet_style_coalesce_expression = true:suggestion
dotnet_style_prefer_is_null_check_over_reference_equality_method = true:silent
dotnet_style_prefer_inferred_tuple_names = true:suggestion
dotnet_style_prefer_inferred_anonymous_type_member_names = true:suggestion
dotnet_style_prefer_auto_properties = true:silent
dotnet_style_prefer_conditional_expression_over_assignment = true:silent
dotnet_style_prefer_conditional_expression_over_return = true:silent
###############################
# Naming Conventions #
###############################
# Style Definitions (From Roslyn)
# Non-private static fields are PascalCase
dotnet_naming_rule.non_private_static_fields_should_be_pascal_case.severity = suggestion
dotnet_naming_rule.non_private_static_fields_should_be_pascal_case.symbols = non_private_static_fields
dotnet_naming_rule.non_private_static_fields_should_be_pascal_case.style = non_private_static_field_style
dotnet_naming_symbols.non_private_static_fields.applicable_kinds = field
dotnet_naming_symbols.non_private_static_fields.applicable_accessibilities = public, protected, internal, protected_internal, private_protected
dotnet_naming_symbols.non_private_static_fields.required_modifiers = static
dotnet_naming_style.non_private_static_field_style.capitalization = pascal_case
# Constants are PascalCase
dotnet_naming_rule.constants_should_be_pascal_case.severity = suggestion
dotnet_naming_rule.constants_should_be_pascal_case.symbols = constants
dotnet_naming_rule.constants_should_be_pascal_case.style = constant_style
dotnet_naming_symbols.constants.applicable_kinds = field, local
dotnet_naming_symbols.constants.required_modifiers = const
dotnet_naming_style.constant_style.capitalization = pascal_case
# Static fields are camelCase and start with s_
dotnet_naming_rule.static_fields_should_be_camel_case.severity = suggestion
dotnet_naming_rule.static_fields_should_be_camel_case.symbols = static_fields
dotnet_naming_rule.static_fields_should_be_camel_case.style = static_field_style
dotnet_naming_symbols.static_fields.applicable_kinds = field
dotnet_naming_symbols.static_fields.required_modifiers = static
dotnet_naming_style.static_field_style.capitalization = camel_case
dotnet_naming_style.static_field_style.required_prefix = _
# Instance fields are camelCase and start with _
dotnet_naming_rule.instance_fields_should_be_camel_case.severity = suggestion
dotnet_naming_rule.instance_fields_should_be_camel_case.symbols = instance_fields
dotnet_naming_rule.instance_fields_should_be_camel_case.style = instance_field_style
dotnet_naming_symbols.instance_fields.applicable_kinds = field
dotnet_naming_style.instance_field_style.capitalization = camel_case
dotnet_naming_style.instance_field_style.required_prefix = _
# Locals and parameters are camelCase
dotnet_naming_rule.locals_should_be_camel_case.severity = suggestion
dotnet_naming_rule.locals_should_be_camel_case.symbols = locals_and_parameters
dotnet_naming_rule.locals_should_be_camel_case.style = camel_case_style
dotnet_naming_symbols.locals_and_parameters.applicable_kinds = parameter, local
dotnet_naming_style.camel_case_style.capitalization = camel_case
# Local functions are PascalCase
dotnet_naming_rule.local_functions_should_be_pascal_case.severity = suggestion
dotnet_naming_rule.local_functions_should_be_pascal_case.symbols = local_functions
dotnet_naming_rule.local_functions_should_be_pascal_case.style = local_function_style
dotnet_naming_symbols.local_functions.applicable_kinds = local_function
dotnet_naming_style.local_function_style.capitalization = pascal_case
# By default, name items with PascalCase
dotnet_naming_rule.members_should_be_pascal_case.severity = suggestion
dotnet_naming_rule.members_should_be_pascal_case.symbols = all_members
dotnet_naming_rule.members_should_be_pascal_case.style = pascal_case_style
dotnet_naming_symbols.all_members.applicable_kinds = *
dotnet_naming_style.pascal_case_style.capitalization = pascal_case
###############################
# C# Coding Conventions #
###############################
[*.cs]
# var preferences
csharp_style_var_for_built_in_types = true:silent
csharp_style_var_when_type_is_apparent = true:silent
csharp_style_var_elsewhere = true:silent
# Expression-bodied members
csharp_style_expression_bodied_methods = false:silent
csharp_style_expression_bodied_constructors = false:silent
csharp_style_expression_bodied_operators = false:silent
csharp_style_expression_bodied_properties = true:silent
csharp_style_expression_bodied_indexers = true:silent
csharp_style_expression_bodied_accessors = true:silent
# Pattern matching preferences
csharp_style_pattern_matching_over_is_with_cast_check = true:suggestion
csharp_style_pattern_matching_over_as_with_null_check = true:suggestion
# Null-checking preferences
csharp_style_throw_expression = true:suggestion
csharp_style_conditional_delegate_call = true:suggestion
# Modifier preferences
csharp_preferred_modifier_order = public,private,protected,internal,static,extern,new,virtual,abstract,sealed,override,readonly,unsafe,volatile,async:suggestion
# Expression-level preferences
csharp_prefer_braces = true:silent
csharp_style_deconstructed_variable_declaration = true:suggestion
csharp_prefer_simple_default_expression = true:suggestion
csharp_style_pattern_local_over_anonymous_function = true:suggestion
csharp_style_inlined_variable_declaration = true:suggestion
###############################
# C# Formatting Rules #
###############################
# New line preferences
csharp_new_line_before_open_brace = all
csharp_new_line_before_else = true
csharp_new_line_before_catch = true
csharp_new_line_before_finally = true
csharp_new_line_before_members_in_object_initializers = true
csharp_new_line_before_members_in_anonymous_types = true
csharp_new_line_between_query_expression_clauses = true
# Indentation preferences
csharp_indent_case_contents = true
csharp_indent_switch_labels = true
csharp_indent_labels = flush_left
# Space preferences
csharp_space_after_cast = false
csharp_space_after_keywords_in_control_flow_statements = true
csharp_space_between_method_call_parameter_list_parentheses = false
csharp_space_between_method_declaration_parameter_list_parentheses = false
csharp_space_between_parentheses = false
csharp_space_before_colon_in_inheritance_clause = true
csharp_space_after_colon_in_inheritance_clause = true
csharp_space_around_binary_operators = before_and_after
csharp_space_between_method_declaration_empty_parameter_list_parentheses = false
csharp_space_between_method_call_name_and_opening_parenthesis = false
csharp_space_between_method_call_empty_parameter_list_parentheses = false
# Wrapping preferences
csharp_preserve_single_line_statements = true
csharp_preserve_single_line_blocks = true
-2
View File
@@ -106,5 +106,3 @@ Generated_Code #added for RIA/Silverlight projects
_UpgradeReport_Files/ _UpgradeReport_Files/
Backup*/ Backup*/
UpgradeLog*.XML UpgradeLog*.XML
.vs
-121
View File
@@ -1,121 +0,0 @@
Creative Commons Legal Code
CC0 1.0 Universal
CREATIVE COMMONS CORPORATION IS NOT A LAW FIRM AND DOES NOT PROVIDE
LEGAL SERVICES. DISTRIBUTION OF THIS DOCUMENT DOES NOT CREATE AN
ATTORNEY-CLIENT RELATIONSHIP. CREATIVE COMMONS PROVIDES THIS
INFORMATION ON AN "AS-IS" BASIS. CREATIVE COMMONS MAKES NO WARRANTIES
REGARDING THE USE OF THIS DOCUMENT OR THE INFORMATION OR WORKS
PROVIDED HEREUNDER, AND DISCLAIMS LIABILITY FOR DAMAGES RESULTING FROM
THE USE OF THIS DOCUMENT OR THE INFORMATION OR WORKS PROVIDED
HEREUNDER.
Statement of Purpose
The laws of most jurisdictions throughout the world automatically confer
exclusive Copyright and Related Rights (defined below) upon the creator
and subsequent owner(s) (each and all, an "owner") of an original work of
authorship and/or a database (each, a "Work").
Certain owners wish to permanently relinquish those rights to a Work for
the purpose of contributing to a commons of creative, cultural and
scientific works ("Commons") that the public can reliably and without fear
of later claims of infringement build upon, modify, incorporate in other
works, reuse and redistribute as freely as possible in any form whatsoever
and for any purposes, including without limitation commercial purposes.
These owners may contribute to the Commons to promote the ideal of a free
culture and the further production of creative, cultural and scientific
works, or to gain reputation or greater distribution for their Work in
part through the use and efforts of others.
For these and/or other purposes and motivations, and without any
expectation of additional consideration or compensation, the person
associating CC0 with a Work (the "Affirmer"), to the extent that he or she
is an owner of Copyright and Related Rights in the Work, voluntarily
elects to apply CC0 to the Work and publicly distribute the Work under its
terms, with knowledge of his or her Copyright and Related Rights in the
Work and the meaning and intended legal effect of CC0 on those rights.
1. Copyright and Related Rights. A Work made available under CC0 may be
protected by copyright and related or neighboring rights ("Copyright and
Related Rights"). Copyright and Related Rights include, but are not
limited to, the following:
i. the right to reproduce, adapt, distribute, perform, display,
communicate, and translate a Work;
ii. moral rights retained by the original author(s) and/or performer(s);
iii. publicity and privacy rights pertaining to a person's image or
likeness depicted in a Work;
iv. rights protecting against unfair competition in regards to a Work,
subject to the limitations in paragraph 4(a), below;
v. rights protecting the extraction, dissemination, use and reuse of data
in a Work;
vi. database rights (such as those arising under Directive 96/9/EC of the
European Parliament and of the Council of 11 March 1996 on the legal
protection of databases, and under any national implementation
thereof, including any amended or successor version of such
directive); and
vii. other similar, equivalent or corresponding rights throughout the
world based on applicable law or treaty, and any national
implementations thereof.
2. Waiver. To the greatest extent permitted by, but not in contravention
of, applicable law, Affirmer hereby overtly, fully, permanently,
irrevocably and unconditionally waives, abandons, and surrenders all of
Affirmer's Copyright and Related Rights and associated claims and causes
of action, whether now known or unknown (including existing as well as
future claims and causes of action), in the Work (i) in all territories
worldwide, (ii) for the maximum duration provided by applicable law or
treaty (including future time extensions), (iii) in any current or future
medium and for any number of copies, and (iv) for any purpose whatsoever,
including without limitation commercial, advertising or promotional
purposes (the "Waiver"). Affirmer makes the Waiver for the benefit of each
member of the public at large and to the detriment of Affirmer's heirs and
successors, fully intending that such Waiver shall not be subject to
revocation, rescission, cancellation, termination, or any other legal or
equitable action to disrupt the quiet enjoyment of the Work by the public
as contemplated by Affirmer's express Statement of Purpose.
3. Public License Fallback. Should any part of the Waiver for any reason
be judged legally invalid or ineffective under applicable law, then the
Waiver shall be preserved to the maximum extent permitted taking into
account Affirmer's express Statement of Purpose. In addition, to the
extent the Waiver is so judged Affirmer hereby grants to each affected
person a royalty-free, non transferable, non sublicensable, non exclusive,
irrevocable and unconditional license to exercise Affirmer's Copyright and
Related Rights in the Work (i) in all territories worldwide, (ii) for the
maximum duration provided by applicable law or treaty (including future
time extensions), (iii) in any current or future medium and for any number
of copies, and (iv) for any purpose whatsoever, including without
limitation commercial, advertising or promotional purposes (the
"License"). The License shall be deemed effective as of the date CC0 was
applied by Affirmer to the Work. Should any part of the License for any
reason be judged legally invalid or ineffective under applicable law, such
partial invalidity or ineffectiveness shall not invalidate the remainder
of the License, and in such case Affirmer hereby affirms that he or she
will not (i) exercise any of his or her remaining Copyright and Related
Rights in the Work or (ii) assert any associated claims and causes of
action with respect to the Work, in either case contrary to Affirmer's
express Statement of Purpose.
4. Limitations and Disclaimers.
a. No trademark or patent rights held by Affirmer are waived, abandoned,
surrendered, licensed or otherwise affected by this document.
b. Affirmer offers the Work as-is and makes no representations or
warranties of any kind concerning the Work, express, implied,
statutory or otherwise, including without limitation warranties of
title, merchantability, fitness for a particular purpose, non
infringement, or the absence of latent or other defects, accuracy, or
the present or absence of errors, whether or not discoverable, all to
the greatest extent permissible under applicable law.
c. Affirmer disclaims responsibility for clearing rights of other persons
that may apply to the Work or any use thereof, including without
limitation any person's Copyright and Related Rights in the Work.
Further, Affirmer disclaims responsibility for obtaining any necessary
consents, permissions or other rights required for any use of the
Work.
d. Affirmer understands and acknowledges that Creative Commons is not a
party to this document and has no duty or obligation with respect to
this CC0 or use of the Work.
+3 -8
View File
@@ -1,14 +1,9 @@
Microsoft Visual Studio Solution File, Format Version 12.00 Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 16 # Visual Studio 15
VisualStudioVersion = 16.0.31105.61 VisualStudioVersion = 15.0.26730.3
MinimumVisualStudioVersion = 10.0.40219.1 MinimumVisualStudioVersion = 10.0.40219.1
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MediaBrowser.Plugins.VuPlus", "MediaBrowser.Plugins.VuPlus\MediaBrowser.Plugins.VuPlus.csproj", "{52B1ABDF-09C1-450E-B808-BBA0A9C19848}" Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MediaBrowser.Plugins.VuPlus", "MediaBrowser.Plugins.VuPlus\MediaBrowser.Plugins.VuPlus.csproj", "{52B1ABDF-09C1-450E-B808-BBA0A9C19848}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{A968FB09-8732-407C-8748-6DB383EB5D91}"
ProjectSection(SolutionItems) = preProject
.editorconfig = .editorconfig
EndProjectSection
EndProject EndProject
Global Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution GlobalSection(SolutionConfigurationPlatforms) = preSolution
@@ -1,3 +1,4 @@
using System;
using MediaBrowser.Model.Plugins; using MediaBrowser.Model.Plugins;
namespace MediaBrowser.Plugins.VuPlus.Configuration namespace MediaBrowser.Plugins.VuPlus.Configuration
@@ -12,16 +13,16 @@ namespace MediaBrowser.Plugins.VuPlus.Configuration
public string WebInterfacePort { get; set; } public string WebInterfacePort { get; set; }
public string WebInterfaceUsername { get; set; } public string WebInterfaceUsername { get; set; }
public string WebInterfacePassword { get; set; } public string WebInterfacePassword { get; set; }
public bool UseSecureHTTPS { get; set; } public Boolean UseSecureHTTPS { get; set; }
public bool OnlyOneBouquet { get; set; } public Boolean OnlyOneBouquet { get; set; }
public string TVBouquet { get; set; } public string TVBouquet { get; set; }
public bool ZapToChannel { get; set; } public Boolean ZapToChannel { get; set; }
public bool FetchPiconsFromWebInterface { get; set; } public Boolean FetchPiconsFromWebInterface { get; set; }
public string PiconsPath { get; set; } public string PiconsPath { get; set; }
public string RecordingPath { get; set; } public string RecordingPath { get; set; }
public bool EnableDebugLogging { get; set; } public Boolean EnableDebugLogging { get; set; }
public PluginConfiguration() public PluginConfiguration()
@@ -29,7 +30,7 @@ namespace MediaBrowser.Plugins.VuPlus.Configuration
HostName = "http://localhost"; HostName = "http://localhost";
StreamingPort = "8001"; StreamingPort = "8001";
WebInterfacePort = "8000"; WebInterfacePort = "8000";
WebInterfaceUsername = ""; WebInterfaceUsername= "";
WebInterfacePassword = ""; WebInterfacePassword = "";
UseSecureHTTPS = false; UseSecureHTTPS = false;
OnlyOneBouquet = true; OnlyOneBouquet = true;
@@ -4,14 +4,14 @@
<title>Vu+</title> <title>Vu+</title>
</head> </head>
<body> <body>
<div data-role="page" id="VuPlusConfigurationPage" class="page type-interior pluginConfigurationPage VuPlusConfigurationPage" data-require="emby-button,emby-checkbox,emby-input"> <div data-role="page" class="page type-interior pluginConfigurationPage VuPlusConfigurationPage" data-require="emby-button,emby-checkbox,emby-input">
<div data-role="content"> <div data-role="content">
<div class="content-primary"> <div class="content-primary">
<h1>VuPlus</h1> <h1>VuPlus</h1>
<form id="VuPlusConfigurationForm" class="VuPlusConfigurationForm"> <form class="VuPlusConfigurationForm">
<div class="inputContainer"> <div class="inputContainer">
<input is="emby-input" id="txtHostName" type="text" label="Vu+ hostname or ip address:" /> <input is="emby-input" id="txtHostName" type="text" label="Vu+ hostname or ip address:" />
@@ -122,61 +122,81 @@
<script type="text/javascript"> <script type="text/javascript">
var VuPlusConfigurationPage = { var VuPlusConfigurationPage = {
pluginUniqueId: "9564ac10-af23-39bc-449f-624f23cfa48f", pluginUniqueId: "9564ac10-af23-39bc-449f-624f23cfa48f"
};
loadConfiguration: function () { $('.VuPlusConfigurationPage').on('pageshow', function (event) {
Dashboard.showLoadingMsg();
ApiClient.getPluginConfiguration(VuPlusConfigurationPage.pluginUniqueId).then(function (config) { Dashboard.showLoadingMsg();
document.getElementById('txtHostName').value = config.HostName || "";
document.getElementById('txtStreamingPort').value = config.StreamingPort || "";
document.getElementById('txtWebInterfacePort').value = config.WebInterfacePort || "";
document.getElementById('txtWebInterfaceUsername').value = config.WebInterfaceUsername || "";
document.getElementById('txtWebInterfacePassword').value = config.WebInterfacePassword || "";
document.getElementById('chkUseSecureHTTPS').checked = config.UseSecureHTTPS || false;
document.getElementById('chkOnlyOneBouquet').checked = config.OnlyOneBouquet || false;
document.getElementById('txtTVBouquet').value = config.TVBouquet || "";
document.getElementById('chkZapToChannel').checked = config.ZapToChannel || false;
document.getElementById('chkFetchPiconsFromWebInterface').checked = config.FetchPiconsFromWebInterface || false;
document.getElementById('txtPiconsPath').value = config.PiconsPath || "";
document.getElementById('txtRecordingPath').value = config.RecordingPath || "";
document.getElementById('chkDebugLogging').checked = config.EnableDebugLogging || false;
Dashboard.hideLoadingMsg(); var page = this;
});
},
saveConfiguration: function () { ApiClient.getPluginConfiguration(VuPlusConfigurationPage.pluginUniqueId).then(function (config) {
Dashboard.showLoadingMsg();
ApiClient.getPluginConfiguration(VuPlusConfigurationPage.pluginUniqueId).then(function (config) { $('#txtHostName', page).val(config.HostName || "");
config.HostName = document.getElementById('txtHostName').value; $('#txtStreamingPort', page).val(config.StreamingPort || "");
config.StreamingPort = document.getElementById('txtStreamingPort').value; $('#txtWebInterfacePort', page).val(config.WebInterfacePort || "");
config.WebInterfacePort = document.getElementById('txtWebInterfacePort').value; $('#txtWebInterfaceUsername', page).val(config.WebInterfaceUsername || "");
config.WebInterfaceUsername = document.getElementById('txtWebInterfaceUsername').value; $('#txtWebInterfacePassword', page).val(config.WebInterfacePassword || "");
config.WebInterfacePassword = document.getElementById('txtWebInterfacePassword').value; page.querySelector('#chkUseSecureHTTPS').checked = config.UseSecureHTTPS || false;
config.UseSecureHTTPS = document.getElementById('chkUseSecureHTTPS').checked; page.querySelector('#chkOnlyOneBouquet').checked = config.OnlyOneBouquet || false;
config.OnlyOneBouquet = document.getElementById('chkOnlyOneBouquet').checked; page.querySelector('#txtTVBouquet', page).val(config.TVBouquet || "");
config.TVBouquet = document.getElementById('txtTVBouquet').value; page.querySelector('#chkZapToChannel').checked = config.ZapToChannel || false;
config.ZapToChannel = document.getElementById('chkZapToChannel').checked; page.querySelector('#chkFetchPiconsFromWebInterface').checked = config.FetchPiconsFromWebInterface || false;
config.FetchPiconsFromWebInterface = document.getElementById('chkFetchPiconsFromWebInterface').checked; $('#txtPiconsPath', page).val(config.PiconsPath || "");
config.PiconsPath = document.getElementById('txtPiconsPath').value;
config.RecordingPath = document.getElementById('txtRecordingPath').value;
config.EnableDebugLogging = document.getElementById('chkDebugLogging').checked;
ApiClient.updatePluginConfiguration(VuPlusConfigurationPage.pluginUniqueId, config).then(Dashboard.processPluginConfigurationUpdateResult); $('#txtRecordingPath', page).val(config.RecordingPath || "");
});
}
}
document.getElementById('VuPlusConfigurationPage').addEventListener('pageshow', function () { page.querySelector('#chkDebugLogging').checked = config.EnableDebugLogging || false;
VuPlusConfigurationPage.loadConfiguration();
Dashboard.hideLoadingMsg();
});
}); });
document.getElementById('VuPlusConfigurationForm').addEventListener('submit', function (e) { $('.VuPlusConfigurationForm').on('submit', function (e) {
e.preventDefault();
VuPlusConfigurationPage.saveConfiguration(); Dashboard.showLoadingMsg();
var form = this;
ApiClient.getPluginConfiguration(VuPlusConfigurationPage.pluginUniqueId).then(function (config) {
//reset TV bouquet reference if TV Bouquet changed
//if (config.TVBouquet != $('#txtTVBouquet', form).val()) {
// config.tvBouquetSRef = '';
//}
//reset TV bouquet reference if Only 1 Bouquet not set
//if (form.querySelector('#chkOnlyOneBouquet').checked) {
//}
//else
//{
// config.tvBouquetSRef = '';
//}
config.HostName = $('#txtHostName', form).val();
config.StreamingPort = $('#txtStreamingPort', form).val();
config.WebInterfacePort = $('#txtWebInterfacePort', form).val();
config.WebInterfaceUsername = $('#txtWebInterfaceUsername', form).val();
config.WebInterfacePassword = $('#txtWebInterfacePassword', form).val();
config.UseSecureHTTPS = form.querySelector('#chkUseSecureHTTPS').checked;
config.OnlyOneBouquet = form.querySelector('#chkOnlyOneBouquet').checked;
config.TVBouquet = $('#txtTVBouquet', form).val();
config.ZapToChannel = form.querySelector('#chkZapToChannel').checked;
config.FetchPiconsFromWebInterface = form.querySelector('#chkFetchPiconsFromWebInterface').checked;
config.PiconsPath = $('#txtPiconsPath', form).val();
config.RecordingPath = $('#txtRecordingPath', form).val();
config.EnableDebugLogging = form.querySelector('#chkDebugLogging').checked;
ApiClient.updatePluginConfiguration(VuPlusConfigurationPage.pluginUniqueId, config).then(Dashboard.processPluginConfigurationUpdateResult);
});
// Disable default form submission
return false;
}); });
</script> </script>
</div> </div>
@@ -1,6 +1,6 @@
using System;
using MediaBrowser.Model.LiveTv; using MediaBrowser.Model.LiveTv;
using Microsoft.Extensions.Logging; using System;
using MediaBrowser.Model.Logging;
namespace MediaBrowser.Plugins.VuPlus.Helpers namespace MediaBrowser.Plugins.VuPlus.Helpers
{ {
@@ -8,7 +8,7 @@ namespace MediaBrowser.Plugins.VuPlus.Helpers
{ {
public static ChannelType GetChannelType(string channelType) public static ChannelType GetChannelType(string channelType)
{ {
var type = new ChannelType(); ChannelType type = new ChannelType();
if (channelType == "0x1") if (channelType == "0x1")
{ {
@@ -25,47 +25,16 @@ namespace MediaBrowser.Plugins.VuPlus.Helpers
public static class UtilsHelper public static class UtilsHelper
{ {
public static void DebugInformation(ILogger<LiveTvService> logger, string message) public static void DebugInformation(ILogger logger, string message)
{ {
var config = Plugin.Instance.Configuration; var config = Plugin.Instance.Configuration;
var enableDebugLogging = config.EnableDebugLogging; bool enableDebugLogging = config.EnableDebugLogging;
if (enableDebugLogging) if (enableDebugLogging)
{ {
logger.LogDebug(message); logger.Debug(message);
} }
} }
} }
public static class RecordingHelper
{
}
public static class ApiHelper
{
private static readonly DateTime UnixEpoch =
new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc);
public static long GetCurrentUnixTimestampMillis()
{
return (long)(DateTime.UtcNow - UnixEpoch).TotalMilliseconds;
}
public static DateTime DateTimeFromUnixTimestampMillis(long millis)
{
return UnixEpoch.AddMilliseconds(millis);
}
public static long GetCurrentUnixTimestampSeconds(DateTime date)
{
return (long)(date - UnixEpoch).TotalSeconds;
}
public static DateTime DateTimeFromUnixTimestampSeconds(long seconds)
{
return UnixEpoch.AddSeconds(seconds);
}
}
} }
File diff suppressed because it is too large Load Diff
@@ -1,31 +1,24 @@
<Project Sdk="Microsoft.NET.Sdk"> <Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup> <PropertyGroup>
<TargetFrameworks>net5.0</TargetFrameworks> <TargetFrameworks>netstandard2.0;</TargetFrameworks>
<AssemblyVersion>4.0.0.0</AssemblyVersion> <AssemblyVersion>3.2.1</AssemblyVersion>
<FileVersion>4.0.0.0</FileVersion> <FileVersion>3.2.1</FileVersion>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(TargetFramework)|$(Platform)'=='Release|net5.0|AnyCPU'">
<DebugType>none</DebugType>
<DebugSymbols>false</DebugSymbols>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<None Remove="Configuration\configPage.html" /> <None Remove="Configuration\configPage.html" />
<None Remove="Images\thumb.png" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<EmbeddedResource Include="Configuration\configPage.html" /> <EmbeddedResource Include="Configuration\configPage.html" />
<EmbeddedResource Include="Images\thumb.png" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="Jellyfin.Common" Version="10.7.0" /> <PackageReference Include="mediabrowser.server.core" Version="4.1.0.26" />
<PackageReference Include="Jellyfin.Naming" Version="10.7.0" /> <PackageReference Include="System.Memory" Version="4.5.2" />
<PackageReference Include="Jellyfin.Controller" Version="10.7.0" />
<PackageReference Include="Jellyfin.Model" Version="10.7.0" />
<PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="5.0.1" />
<PackageReference Include="Microsoft.Extensions.Http" Version="5.0.0" />
</ItemGroup> </ItemGroup>
</Project> </Project>
+34 -8
View File
@@ -5,18 +5,18 @@ using MediaBrowser.Common.Plugins;
using MediaBrowser.Model.Plugins; using MediaBrowser.Model.Plugins;
using MediaBrowser.Model.Serialization; using MediaBrowser.Model.Serialization;
using MediaBrowser.Plugins.VuPlus.Configuration; using MediaBrowser.Plugins.VuPlus.Configuration;
using System.IO;
using MediaBrowser.Model.Drawing;
namespace MediaBrowser.Plugins.VuPlus namespace MediaBrowser.Plugins.VuPlus
{ {
/// <summary> /// <summary>
/// Class Plugin /// Class Plugin
/// </summary> /// </summary>
public class Plugin : BasePlugin<PluginConfiguration>, IHasWebPages public class Plugin : BasePlugin<PluginConfiguration>, IHasWebPages, IHasThumbImage
{ {
public Plugin( public Plugin(IApplicationPaths applicationPaths, IXmlSerializer xmlSerializer)
IApplicationPaths applicationPaths, : base(applicationPaths, xmlSerializer)
IXmlSerializer xmlSerializer
) : base(applicationPaths, xmlSerializer)
{ {
Instance = this; Instance = this;
} }
@@ -25,16 +25,28 @@ namespace MediaBrowser.Plugins.VuPlus
/// Gets the name of the plugin /// Gets the name of the plugin
/// </summary> /// </summary>
/// <value>The name.</value> /// <value>The name.</value>
public override string Name => "VuPlus"; public override string Name
{
get { return "VuPlus"; }
}
/// <summary> /// <summary>
/// Gets the description. /// Gets the description.
/// </summary> /// </summary>
/// <value>The description.</value> /// <value>The description.</value>
public override string Description => "Provides live tv using Vu+ / Enigma2 pvr as a back-end."; public override string Description
{
get
{
return "Provides live tv using Vu+ / Enigma2 pvr as a back-end.";
}
}
private Guid _id = new Guid("9564ac10-af23-39bc-449f-624f23cfa48f"); private Guid _id = new Guid("9564ac10-af23-39bc-449f-624f23cfa48f");
public override Guid Id => _id; public override Guid Id
{
get { return _id; }
}
/// <summary> /// <summary>
/// Gets the instance. /// Gets the instance.
@@ -53,5 +65,19 @@ namespace MediaBrowser.Plugins.VuPlus
} }
}; };
} }
public Stream GetThumbImage()
{
var type = GetType();
return type.Assembly.GetManifestResourceStream(type.Namespace + ".Images.thumb.png");
}
public ImageFormat ThumbImageFormat
{
get
{
return ImageFormat.Png;
}
}
} }
} }
@@ -1,52 +1,110 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Globalization; using System.Text;
using System.Linq;
using System.Threading; using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
using MediaBrowser.Common.Extensions;
using MediaBrowser.Controller.Channels; using MediaBrowser.Controller.Channels;
using MediaBrowser.Controller.Entities;
using MediaBrowser.Controller.LiveTv;
using MediaBrowser.Controller.Providers; using MediaBrowser.Controller.Providers;
using MediaBrowser.Model.Channels;
using MediaBrowser.Model.Dto;
using MediaBrowser.Model.Entities; using MediaBrowser.Model.Entities;
using MediaBrowser.Model.LiveTv; using MediaBrowser.Model.Channels;
using MediaBrowser.Model.MediaInfo; using MediaBrowser.Model.MediaInfo;
using MediaBrowser.Controller.LiveTv;
using System.Linq;
using MediaBrowser.Common.Extensions;
using MediaBrowser.Model.Dto;
using System.Globalization;
using MediaBrowser.Controller.Entities;
using MediaBrowser.Model.LiveTv;
namespace MediaBrowser.Plugins.VuPlus namespace MediaBrowser.Plugins.VuPlus
{ {
public class RecordingsChannel : IChannel, IHasCacheKey, ISupportsDelete, ISupportsLatestMedia, ISupportsMediaProbe, IHasFolderAttributes public class RecordingsChannel : IChannel, IHasCacheKey, ISupportsDelete, ISupportsLatestMedia, ISupportsMediaProbe, IHasFolderAttributes, IHasChangeEvent
{ {
public ILiveTvManager _liveTvManager; public ILiveTvManager _liveTvManager;
public event EventHandler ContentChanged;
private Timer _updateTimer;
public void OnContentChanged()
{
if (ContentChanged != null)
{
ContentChanged(this, EventArgs.Empty);
}
}
private void OnUpdateTimerCallback(object state)
{
OnContentChanged();
}
public RecordingsChannel(ILiveTvManager liveTvManager) public RecordingsChannel(ILiveTvManager liveTvManager)
{ {
_liveTvManager = liveTvManager; _liveTvManager = liveTvManager;
var interval = TimeSpan.FromMinutes(15);
_updateTimer = new Timer(OnUpdateTimerCallback, null, interval, interval);
} }
public string Name => "VuPlus Recordings"; public void Dispose()
{
if (_updateTimer != null)
{
_updateTimer.Dispose();
_updateTimer = null;
}
}
public string[] Attributes => new[] { "Recordings" }; public string Name
{
get
{
return "VuPlus Recordings";
}
}
public string Description => "VuPlus Recordings"; public string[] Attributes
{
get
{
return new[] { "Recordings" };
}
}
public string DataVersion => "1"; public string Description
{
get
{
return "VuPlus Recordings";
}
}
public string HomePageUrl => null; public string DataVersion
{
get
{
return "1";
}
}
public ChannelParentalRating ParentalRating => ChannelParentalRating.GeneralAudience; public string HomePageUrl
{
get { return null; }
}
public ChannelParentalRating ParentalRating
{
get { return ChannelParentalRating.GeneralAudience; }
}
public string GetCacheKey(string userId) public string GetCacheKey(string userId)
{ {
var now = DateTime.UtcNow; var now = DateTimeOffset.UtcNow;
var values = new List<string> var values = new List<string>();
{
now.DayOfYear.ToString(CultureInfo.InvariantCulture), values.Add(now.DayOfYear.ToString(CultureInfo.InvariantCulture));
now.Hour.ToString(CultureInfo.InvariantCulture) values.Add(now.Hour.ToString(CultureInfo.InvariantCulture));
};
double minute = now.Minute; double minute = now.Minute;
minute /= 5; minute /= 5;
@@ -64,8 +122,8 @@ namespace MediaBrowser.Plugins.VuPlus
{ {
ContentTypes = new List<ChannelMediaContentType> ContentTypes = new List<ChannelMediaContentType>
{ {
ChannelMediaContentType.Movie, ChannelMediaContentType.Movie,
ChannelMediaContentType.Episode, ChannelMediaContentType.Episode,
ChannelMediaContentType.Clip ChannelMediaContentType.Clip
}, },
MediaTypes = new List<ChannelMediaType> MediaTypes = new List<ChannelMediaType>
@@ -83,7 +141,7 @@ namespace MediaBrowser.Plugins.VuPlus
{ {
return Task.FromResult(new DynamicImageResponse return Task.FromResult(new DynamicImageResponse
{ {
Path = "https://github.com/CompoUK/MediaBrowser.Plugins.VuPlus/blob/master/src/Images/Vu+.png?raw=true", Path = "https://github.com/MediaBrowser/MediaBrowser.Plugins.VuPlus/raw/master/MediaBrowser.Plugins.VuPlus/Images/thumb.png",
Protocol = MediaProtocol.Http, Protocol = MediaProtocol.Http,
HasImage = true HasImage = true
}); });
@@ -123,13 +181,6 @@ namespace MediaBrowser.Plugins.VuPlus
return GetService().DeleteRecordingAsync(id, cancellationToken); return GetService().DeleteRecordingAsync(id, cancellationToken);
} }
public async Task<IEnumerable<ChannelItemInfo>> GetLatestMedia(ChannelLatestMediaSearch request, CancellationToken cancellationToken)
{
var result = await GetChannelItems(new InternalChannelItemQuery(), i => true, cancellationToken).ConfigureAwait(false);
return result.Items.OrderByDescending(i => i.DateCreated ?? DateTime.MinValue);
}
public Task<ChannelItemResult> GetChannelItems(InternalChannelItemQuery query, CancellationToken cancellationToken) public Task<ChannelItemResult> GetChannelItems(InternalChannelItemQuery query, CancellationToken cancellationToken)
{ {
if (string.IsNullOrWhiteSpace(query.FolderId)) if (string.IsNullOrWhiteSpace(query.FolderId))
@@ -380,12 +431,12 @@ namespace MediaBrowser.Plugins.VuPlus
/// <summary> /// <summary>
/// The start date of the recording, in UTC. /// The start date of the recording, in UTC.
/// </summary> /// </summary>
public DateTime StartDate { get; set; } public DateTimeOffset StartDate { get; set; }
/// <summary> /// <summary>
/// The end date of the recording, in UTC. /// The end date of the recording, in UTC.
/// </summary> /// </summary>
public DateTime EndDate { get; set; } public DateTimeOffset EndDate { get; set; }
/// <summary> /// <summary>
/// Gets or sets the program identifier. /// Gets or sets the program identifier.
@@ -432,7 +483,7 @@ namespace MediaBrowser.Plugins.VuPlus
/// Gets or sets the original air date. /// Gets or sets the original air date.
/// </summary> /// </summary>
/// <value>The original air date.</value> /// <value>The original air date.</value>
public DateTime? OriginalAirDate { get; set; } public DateTimeOffset? OriginalAirDate { get; set; }
/// <summary> /// <summary>
/// Gets or sets a value indicating whether this instance is movie. /// Gets or sets a value indicating whether this instance is movie.
@@ -515,7 +566,7 @@ namespace MediaBrowser.Plugins.VuPlus
/// Gets or sets the date last updated. /// Gets or sets the date last updated.
/// </summary> /// </summary>
/// <value>The date last updated.</value> /// <value>The date last updated.</value>
public DateTime DateLastUpdated { get; set; } public DateTimeOffset DateLastUpdated { get; set; }
public MyRecordingInfo() public MyRecordingInfo()
{ {
-44
View File
@@ -1,44 +0,0 @@
---
# The name of the plugin; official plugins always start "jellyfin-plugin-"
name: "jellyfin-plugin-vuplus"
# The GUID of the plugin, found in Plugin.cs
guid: "9564ac10-af23-39bc-449f-624f23cfa48f"
# The version of the plugin, starting at 1. Note that the AssemblyVersion
# and FileVersion flags in the `.csproj` file must have two additional
# fiels, e.g. 1.0.0 to be built correctly.
version: "4.0.0.0" # Please increment with each pull request
# The supported Jellyfin version, usually the earliest binary-compatible
# version. Based on the Jellyfin components from NuGet.
targetAbi: "10.7.0.0" # The earliest binary-compatible version
framework: "net5.0"
# The owner name of the plugin, "jellyfin" for official plugins. Change
# to your own name if you wish to remain a 3rd-party plugin.
owner: "knackebrot"
# A short description of the plugin
overview: "VU+"
# A longer and more detailed description of the plugin; use multiple
# lines as required for readability.
description: >
Live TV plugin for watching Enigma 2 channels and recordings
# The plugin category, in a general sense. These fields are dynamic.
category: "Live TV"
# A list of built artifacts to be bundled into the ZIP for installation.
# Include the main output file, as well as any dependency `.dll`s that
# might be required for the plugin to run.
artifacts:
- "MediaBrowser.Plugins.VuPlus.dll"
# Build information values for the build infrastructure; these should
# not need to be changed usually.
build_type: "dotnet"
dotnet_configuration: "Release"
dotnet_framework: "net5.0"