Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a08bbd0f31 | ||
|
|
f7a7fced43 | ||
|
|
46ea3e4c21 |
-199
@@ -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
|
|
||||||
@@ -106,5 +106,3 @@ Generated_Code #added for RIA/Silverlight projects
|
|||||||
_UpgradeReport_Files/
|
_UpgradeReport_Files/
|
||||||
Backup*/
|
Backup*/
|
||||||
UpgradeLog*.XML
|
UpgradeLog*.XML
|
||||||
|
|
||||||
.vs
|
|
||||||
Vendored
-41
@@ -1,41 +0,0 @@
|
|||||||
{
|
|
||||||
"version": "2.0.0",
|
|
||||||
"tasks": [
|
|
||||||
{
|
|
||||||
"label": "build",
|
|
||||||
"command": "dotnet",
|
|
||||||
"type": "process",
|
|
||||||
"args": [
|
|
||||||
"build",
|
|
||||||
"${workspaceFolder}/Jellyfin.Plugin.Enigma2/Jellyfin.Plugin.Enigma2.csproj",
|
|
||||||
"/property:GenerateFullPaths=true",
|
|
||||||
"/consoleloggerparameters:NoSummary"
|
|
||||||
],
|
|
||||||
"problemMatcher": "$msCompile"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"label": "publish",
|
|
||||||
"command": "dotnet",
|
|
||||||
"type": "process",
|
|
||||||
"args": [
|
|
||||||
"publish",
|
|
||||||
"${workspaceFolder}/Jellyfin.Plugin.Enigma2/Jellyfin.Plugin.Enigma2.csproj",
|
|
||||||
"/property:GenerateFullPaths=true",
|
|
||||||
"/consoleloggerparameters:NoSummary"
|
|
||||||
],
|
|
||||||
"problemMatcher": "$msCompile"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"label": "watch",
|
|
||||||
"command": "dotnet",
|
|
||||||
"type": "process",
|
|
||||||
"args": [
|
|
||||||
"watch",
|
|
||||||
"run",
|
|
||||||
"--project",
|
|
||||||
"${workspaceFolder}/Jellyfin.Plugin.Enigma2/Jellyfin.Plugin.Enigma2.csproj"
|
|
||||||
],
|
|
||||||
"problemMatcher": "$msCompile"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
@@ -1,228 +0,0 @@
|
|||||||
<!DOCTYPE html>
|
|
||||||
<html>
|
|
||||||
<head>
|
|
||||||
<title>Enigma2</title>
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
<div data-role="page" id="Enigma2ConfigurationPage" class="page type-interior pluginConfigurationPage Enigma2ConfigurationPage" data-require="emby-button,emby-checkbox,emby-input">
|
|
||||||
|
|
||||||
<div data-role="content">
|
|
||||||
<div class="content-primary">
|
|
||||||
|
|
||||||
<h1>Enigma2</h1>
|
|
||||||
|
|
||||||
<form id="Enigma2ConfigurationForm" class="Enigma2ConfigurationForm">
|
|
||||||
|
|
||||||
<div class="inputContainer">
|
|
||||||
<input is="emby-input" id="txtHostName" type="text" label="Enigma2 hostname or ip address:" />
|
|
||||||
<div class="fieldDescription">
|
|
||||||
The host name (address) or ip address of your receiver
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="inputContainer">
|
|
||||||
<input is="emby-input" id="txtStreamingPort" type="text" label="Enigma2 streaming port:" />
|
|
||||||
<div class="fieldDescription">
|
|
||||||
The Streaming port of your receiver eg. 8001
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="inputContainer">
|
|
||||||
<input is="emby-input" id="txtWebInterfacePort" type="text" label="Enigma2 Web Interface port:" />
|
|
||||||
<div class="fieldDescription">
|
|
||||||
The web interface port of your receiver eg. 8000
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="inputContainer">
|
|
||||||
<input is="emby-input" id="txtWebInterfaceUsername" type="text" label="Enigma2 Web Interface username:" />
|
|
||||||
<div class="fieldDescription">
|
|
||||||
The web interface username of your receiver (optional)
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="inputContainer">
|
|
||||||
<input is="emby-input" id="txtWebInterfacePassword" type="password" label="Enigma2 Web Interface password:" />
|
|
||||||
<div class="fieldDescription">
|
|
||||||
The web interface password of your receiver (optional)
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="checkboxContainer checkboxContainer-withDescription">
|
|
||||||
<label>
|
|
||||||
<input is="emby-checkbox" type="checkbox" id="chkUseLoginForStreams" />
|
|
||||||
<span>Use login for streaming</span>
|
|
||||||
</label>
|
|
||||||
<div class="fieldDescription checkboxFieldDescription">
|
|
||||||
Use web interface login for streaming
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="checkboxContainer checkboxContainer-withDescription">
|
|
||||||
<label>
|
|
||||||
<input is="emby-checkbox" type="checkbox" id="chkUseSecureHTTPS" />
|
|
||||||
<span>Use secure HTTP (HTTPS)</span>
|
|
||||||
</label>
|
|
||||||
<div class="fieldDescription checkboxFieldDescription">
|
|
||||||
Use HTTPS to connect to your receiver
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="checkboxContainer checkboxContainer-withDescription">
|
|
||||||
<label>
|
|
||||||
<input is="emby-checkbox" type="checkbox" id="chkUseSecureHTTPSForStreams" />
|
|
||||||
<span>Use secure HTTP (HTTPS) for streams</span>
|
|
||||||
</label>
|
|
||||||
<div class="fieldDescription checkboxFieldDescription">
|
|
||||||
Use HTTPS to connect to streaming port
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="checkboxContainer checkboxContainer-withDescription">
|
|
||||||
<label>
|
|
||||||
<input is="emby-checkbox" type="checkbox" id="chkOnlyOneBouquet" />
|
|
||||||
<span>Fetch Only one TV bouquet</span>
|
|
||||||
</label>
|
|
||||||
<div class="fieldDescription checkboxFieldDescription">
|
|
||||||
Limit channels to only those contained within the specified TV Bouquet below (optional)
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
|
|
||||||
<div class="inputContainer">
|
|
||||||
<input is="emby-input" id="txtTVBouquet" type="text" label="Enigma2 TVBouquet:" />
|
|
||||||
<div class="fieldDescription">
|
|
||||||
The TV Bouquet to load channels for (optional)
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="checkboxContainer checkboxContainer-withDescription">
|
|
||||||
<label>
|
|
||||||
<input is="emby-checkbox" type="checkbox" id="chkZapToChannel" />
|
|
||||||
<span>Zap before Channel switch (single tuner)</span>
|
|
||||||
</label>
|
|
||||||
<div class="fieldDescription checkboxFieldDescription">
|
|
||||||
Set if only one tuner within receiver
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="checkboxContainer checkboxContainer-withDescription">
|
|
||||||
<label>
|
|
||||||
<input is="emby-checkbox" type="checkbox" id="chkFetchPiconsFromWebInterface" />
|
|
||||||
<span>Fetch picons from webinterface</span>
|
|
||||||
</label>
|
|
||||||
<div class="fieldDescription checkboxFieldDescription">
|
|
||||||
Set if you want to retrieve Picons from the web interface of the receiver
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
|
|
||||||
<div class="inputContainer">
|
|
||||||
<input is="emby-input" id="txtPiconsPath" type="text" label="Picons Path:" />
|
|
||||||
<div class="fieldDescription">
|
|
||||||
The local location of your Picons eg. C:\Picons\ (optional)
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="inputContainer">
|
|
||||||
<input is="emby-input" id="txtRecordingPath" type="text" label="Recording Path:" />
|
|
||||||
<div class="fieldDescription">
|
|
||||||
The location to store your recordings on your receiver eg. /hdd/movie/ (optional)
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="checkboxContainer checkboxContainer-withDescription">
|
|
||||||
<label>
|
|
||||||
<input is="emby-checkbox" type="checkbox" id="chkTranscodedStream" />
|
|
||||||
<span>Request Transcoded Stream</span>
|
|
||||||
</label>
|
|
||||||
<div class="fieldDescription checkboxFieldDescription">
|
|
||||||
Request Transcoded Stream (h264, 720p, 1Mpbs and mp4 as default)
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="inputContainer">
|
|
||||||
<input is="emby-input" id="txtTranscodingPort" type="text" label="Enigma2 transcoding port:" />
|
|
||||||
<div class="fieldDescription">
|
|
||||||
The Transcoding port of your receiver eg. 8002
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<label class="checkboxContainer">
|
|
||||||
<input is="emby-checkbox" type="checkbox" id="chkDebugLogging" />
|
|
||||||
<span>Enable Enigma2 debug logging</span>
|
|
||||||
</label>
|
|
||||||
|
|
||||||
<div>
|
|
||||||
<button is="emby-button" type="submit" class="raised button-submit block"><span>Save</span></button>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
</form>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
|
|
||||||
<script type="text/javascript">
|
|
||||||
var Enigma2ConfigurationPage = {
|
|
||||||
pluginUniqueId: "193f29f9-ea6c-4595-a6f6-55e79d7c590a",
|
|
||||||
|
|
||||||
loadConfiguration: function () {
|
|
||||||
Dashboard.showLoadingMsg();
|
|
||||||
|
|
||||||
ApiClient.getPluginConfiguration(Enigma2ConfigurationPage.pluginUniqueId).then(function (config) {
|
|
||||||
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('chkUseLoginForStreams').checked = config.UseLoginForStreams || false;
|
|
||||||
document.getElementById('chkUseSecureHTTPS').checked = config.UseSecureHTTPS || false;
|
|
||||||
document.getElementById('chkUseSecureHTTPSForStreams').checked = config.UseSecureHTTPSForStreams || 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('chkTranscodedStream').checked = config.TranscodedStream || false;
|
|
||||||
document.getElementById('txtTranscodingPort').value = config.TranscodingPort || "";
|
|
||||||
document.getElementById('chkDebugLogging').checked = config.EnableDebugLogging || false;
|
|
||||||
|
|
||||||
Dashboard.hideLoadingMsg();
|
|
||||||
});
|
|
||||||
},
|
|
||||||
|
|
||||||
saveConfiguration: function () {
|
|
||||||
Dashboard.showLoadingMsg();
|
|
||||||
|
|
||||||
ApiClient.getPluginConfiguration(Enigma2ConfigurationPage.pluginUniqueId).then(function (config) {
|
|
||||||
config.HostName = document.getElementById('txtHostName').value;
|
|
||||||
config.StreamingPort = document.getElementById('txtStreamingPort').value;
|
|
||||||
config.WebInterfacePort = document.getElementById('txtWebInterfacePort').value;
|
|
||||||
config.WebInterfaceUsername = document.getElementById('txtWebInterfaceUsername').value;
|
|
||||||
config.WebInterfacePassword = document.getElementById('txtWebInterfacePassword').value;
|
|
||||||
config.UseLoginForStreams = document.getElementById('chkUseLoginForStreams').checked;
|
|
||||||
config.UseSecureHTTPS = document.getElementById('chkUseSecureHTTPS').checked;
|
|
||||||
config.UseSecureHTTPSForStreams = document.getElementById('chkUseSecureHTTPSForStreams').checked;
|
|
||||||
config.OnlyOneBouquet = document.getElementById('chkOnlyOneBouquet').checked;
|
|
||||||
config.TVBouquet = document.getElementById('txtTVBouquet').value;
|
|
||||||
config.ZapToChannel = document.getElementById('chkZapToChannel').checked;
|
|
||||||
config.FetchPiconsFromWebInterface = document.getElementById('chkFetchPiconsFromWebInterface').checked;
|
|
||||||
config.PiconsPath = document.getElementById('txtPiconsPath').value;
|
|
||||||
config.RecordingPath = document.getElementById('txtRecordingPath').value;
|
|
||||||
config.TranscodedStream = document.getElementById('chkTranscodedStream').checked;
|
|
||||||
config.TranscodingPort = document.getElementById('txtTranscodingPort').value;
|
|
||||||
config.EnableDebugLogging = document.getElementById('chkDebugLogging').checked;
|
|
||||||
|
|
||||||
ApiClient.updatePluginConfiguration(Enigma2ConfigurationPage.pluginUniqueId, config).then(Dashboard.processPluginConfigurationUpdateResult);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
document.getElementById('Enigma2ConfigurationPage').addEventListener('pageshow', function () {
|
|
||||||
Enigma2ConfigurationPage.loadConfiguration();
|
|
||||||
});
|
|
||||||
|
|
||||||
document.getElementById('Enigma2ConfigurationForm').addEventListener('submit', function (e) {
|
|
||||||
e.preventDefault();
|
|
||||||
Enigma2ConfigurationPage.saveConfiguration();
|
|
||||||
});
|
|
||||||
</script>
|
|
||||||
</div>
|
|
||||||
</body>
|
|
||||||
</html>
|
|
||||||
@@ -1,71 +0,0 @@
|
|||||||
using System;
|
|
||||||
using MediaBrowser.Model.LiveTv;
|
|
||||||
using Microsoft.Extensions.Logging;
|
|
||||||
|
|
||||||
namespace Jellyfin.Plugin.Enigma2.Helpers
|
|
||||||
{
|
|
||||||
public static class ChannelHelper
|
|
||||||
{
|
|
||||||
public static ChannelType GetChannelType(string channelType)
|
|
||||||
{
|
|
||||||
var type = new ChannelType();
|
|
||||||
|
|
||||||
if (channelType == "0x1")
|
|
||||||
{
|
|
||||||
type = ChannelType.TV;
|
|
||||||
}
|
|
||||||
else if (channelType == "0xa")
|
|
||||||
{
|
|
||||||
type = ChannelType.Radio;
|
|
||||||
}
|
|
||||||
|
|
||||||
return type;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static class UtilsHelper
|
|
||||||
{
|
|
||||||
public static void DebugInformation(ILogger<LiveTvService> logger, string message)
|
|
||||||
{
|
|
||||||
var config = Plugin.Instance.Configuration;
|
|
||||||
var enableDebugLogging = config.EnableDebugLogging;
|
|
||||||
|
|
||||||
if (enableDebugLogging)
|
|
||||||
{
|
|
||||||
logger.LogDebug(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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,35 +0,0 @@
|
|||||||
<Project Sdk="Microsoft.NET.Sdk">
|
|
||||||
|
|
||||||
<PropertyGroup>
|
|
||||||
<TargetFrameworks>net8.0</TargetFrameworks>
|
|
||||||
<AssemblyVersion>6.0.0.0</AssemblyVersion>
|
|
||||||
<FileVersion>6.0.0.0</FileVersion>
|
|
||||||
</PropertyGroup>
|
|
||||||
|
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(TargetFramework)|$(Platform)'=='Release|net6.0|AnyCPU'">
|
|
||||||
<DebugType>none</DebugType>
|
|
||||||
<DebugSymbols>false</DebugSymbols>
|
|
||||||
</PropertyGroup>
|
|
||||||
|
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(TargetFramework)|$(Platform)'=='Release|net8.0|AnyCPU'">
|
|
||||||
<DebugType>none</DebugType>
|
|
||||||
</PropertyGroup>
|
|
||||||
|
|
||||||
<ItemGroup>
|
|
||||||
<None Remove="Configuration\configPage.html" />
|
|
||||||
</ItemGroup>
|
|
||||||
|
|
||||||
<ItemGroup>
|
|
||||||
<EmbeddedResource Include="Configuration\configPage.html" />
|
|
||||||
</ItemGroup>
|
|
||||||
|
|
||||||
<ItemGroup>
|
|
||||||
<PackageReference Include="Jellyfin.Common" Version="10.9.0" />
|
|
||||||
<PackageReference Include="Jellyfin.Naming" Version="10.9.0" />
|
|
||||||
<PackageReference Include="Jellyfin.Controller" Version="10.9.0" />
|
|
||||||
<PackageReference Include="Jellyfin.Model" Version="10.9.0" />
|
|
||||||
<PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="8.0.0" />
|
|
||||||
<PackageReference Include="Microsoft.Extensions.Http" Version="8.0.0" />
|
|
||||||
</ItemGroup>
|
|
||||||
|
|
||||||
</Project>
|
|
||||||
@@ -1,57 +0,0 @@
|
|||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using MediaBrowser.Common.Configuration;
|
|
||||||
using MediaBrowser.Common.Plugins;
|
|
||||||
using MediaBrowser.Model.Plugins;
|
|
||||||
using MediaBrowser.Model.Serialization;
|
|
||||||
using Jellyfin.Plugin.Enigma2.Configuration;
|
|
||||||
|
|
||||||
namespace Jellyfin.Plugin.Enigma2
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// Class Plugin
|
|
||||||
/// </summary>
|
|
||||||
public class Plugin : BasePlugin<PluginConfiguration>, IHasWebPages
|
|
||||||
{
|
|
||||||
public Plugin(
|
|
||||||
IApplicationPaths applicationPaths,
|
|
||||||
IXmlSerializer xmlSerializer
|
|
||||||
) : base(applicationPaths, xmlSerializer)
|
|
||||||
{
|
|
||||||
Instance = this;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets the name of the plugin
|
|
||||||
/// </summary>
|
|
||||||
/// <value>The name.</value>
|
|
||||||
public override string Name => "Enigma2";
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets the description.
|
|
||||||
/// </summary>
|
|
||||||
/// <value>The description.</value>
|
|
||||||
public override string Description => "Provides live TV using Enigma2 PVR as a back-end.";
|
|
||||||
|
|
||||||
private Guid _id = new Guid("193f29f9-ea6c-4595-a6f6-55e79d7c590a");
|
|
||||||
public override Guid Id => _id;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets the instance.
|
|
||||||
/// </summary>
|
|
||||||
/// <value>The instance.</value>
|
|
||||||
public static Plugin Instance { get; private set; }
|
|
||||||
|
|
||||||
public IEnumerable<PluginPageInfo> GetPages()
|
|
||||||
{
|
|
||||||
return new[]
|
|
||||||
{
|
|
||||||
new PluginPageInfo
|
|
||||||
{
|
|
||||||
Name = "enigma2",
|
|
||||||
EmbeddedResourcePath = "Jellyfin.Plugin.Enigma2.Configuration.configPage.html"
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,20 +0,0 @@
|
|||||||
using MediaBrowser.Controller.Channels;
|
|
||||||
using MediaBrowser.Controller.LiveTv;
|
|
||||||
using MediaBrowser.Controller.Plugins;
|
|
||||||
using MediaBrowser.Controller;
|
|
||||||
using Microsoft.Extensions.DependencyInjection;
|
|
||||||
using System.Net.Http;
|
|
||||||
using Jellyfin.Plugin.Enigma2.Helpers;
|
|
||||||
|
|
||||||
namespace Jellyfin.Plugin.Enigma2
|
|
||||||
{
|
|
||||||
public class ServiceRegistrator : IPluginServiceRegistrator
|
|
||||||
{
|
|
||||||
/// <inheritdoc />
|
|
||||||
public void RegisterServices(IServiceCollection serviceCollection, IServerApplicationHost applicationHost)
|
|
||||||
{
|
|
||||||
serviceCollection.AddSingleton<ILiveTvService, LiveTvService>();
|
|
||||||
serviceCollection.AddSingleton<IChannel, RecordingsChannel>();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -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.
|
|
||||||
@@ -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 17
|
# Visual Studio 15
|
||||||
VisualStudioVersion = 17.2.32616.157
|
VisualStudioVersion = 15.0.26730.3
|
||||||
MinimumVisualStudioVersion = 10.0.40219.1
|
MinimumVisualStudioVersion = 10.0.40219.1
|
||||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Jellyfin.Plugin.Enigma2", "Jellyfin.Plugin.Enigma2\Jellyfin.Plugin.Enigma2.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
|
||||||
+10
-19
@@ -1,6 +1,7 @@
|
|||||||
|
using System;
|
||||||
using MediaBrowser.Model.Plugins;
|
using MediaBrowser.Model.Plugins;
|
||||||
|
|
||||||
namespace Jellyfin.Plugin.Enigma2.Configuration
|
namespace MediaBrowser.Plugins.VuPlus.Configuration
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Class PluginConfiguration
|
/// Class PluginConfiguration
|
||||||
@@ -12,34 +13,26 @@ namespace Jellyfin.Plugin.Enigma2.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 UseLoginForStreams { get; set; }
|
public Boolean UseSecureHTTPS { get; set; }
|
||||||
public bool UseSecureHTTPS { get; set; }
|
public Boolean OnlyOneBouquet { get; set; }
|
||||||
public bool UseSecureHTTPSForStreams { get; set; }
|
|
||||||
public bool 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 TranscodedStream { get; set; }
|
public Boolean EnableDebugLogging { get; set; }
|
||||||
|
|
||||||
public string TranscodingPort { get; set; }
|
|
||||||
|
|
||||||
public bool EnableDebugLogging { get; set; }
|
|
||||||
|
|
||||||
|
|
||||||
public PluginConfiguration()
|
public PluginConfiguration()
|
||||||
{
|
{
|
||||||
HostName = "localhost";
|
HostName = "http://localhost";
|
||||||
StreamingPort = "8001";
|
StreamingPort = "8001";
|
||||||
WebInterfacePort = "8000";
|
WebInterfacePort = "8000";
|
||||||
WebInterfaceUsername = "";
|
WebInterfaceUsername= "";
|
||||||
WebInterfacePassword = "";
|
WebInterfacePassword = "";
|
||||||
UseLoginForStreams = false;
|
|
||||||
UseSecureHTTPS = false;
|
UseSecureHTTPS = false;
|
||||||
UseSecureHTTPSForStreams = false;
|
|
||||||
OnlyOneBouquet = true;
|
OnlyOneBouquet = true;
|
||||||
TVBouquet = "Favourites (TV)";
|
TVBouquet = "Favourites (TV)";
|
||||||
ZapToChannel = false;
|
ZapToChannel = false;
|
||||||
@@ -48,10 +41,8 @@ namespace Jellyfin.Plugin.Enigma2.Configuration
|
|||||||
|
|
||||||
RecordingPath = "";
|
RecordingPath = "";
|
||||||
|
|
||||||
TranscodedStream = false;
|
|
||||||
TranscodingPort = "8002";
|
|
||||||
|
|
||||||
EnableDebugLogging = false;
|
EnableDebugLogging = false;
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,204 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<title>Vu+</title>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div data-role="page" class="page type-interior pluginConfigurationPage VuPlusConfigurationPage" data-require="emby-button,emby-checkbox,emby-input">
|
||||||
|
|
||||||
|
<div data-role="content">
|
||||||
|
<div class="content-primary">
|
||||||
|
|
||||||
|
<h1>VuPlus</h1>
|
||||||
|
|
||||||
|
<form class="VuPlusConfigurationForm">
|
||||||
|
|
||||||
|
<div class="inputContainer">
|
||||||
|
<input is="emby-input" id="txtHostName" type="text" label="Vu+ hostname or ip address:" />
|
||||||
|
<div class="fieldDescription">
|
||||||
|
The host name (address) or ip address of your receiver
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="inputContainer">
|
||||||
|
<input is="emby-input" id="txtStreamingPort" type="text" label="Vu+ streaming port:" />
|
||||||
|
<div class="fieldDescription">
|
||||||
|
The Streaming port of your receiver eg. 8001
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="inputContainer">
|
||||||
|
<input is="emby-input" id="txtWebInterfacePort" type="text" label="Vu+ Web Interface port:" />
|
||||||
|
<div class="fieldDescription">
|
||||||
|
The web Interface port of your receiver eg. 8000
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="inputContainer">
|
||||||
|
<input is="emby-input" id="txtWebInterfaceUsername" type="text" label="Vu+ Web Interface username:" />
|
||||||
|
<div class="fieldDescription">
|
||||||
|
The web Interface username of your receiver (optional)
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="inputContainer">
|
||||||
|
<input is="emby-input" id="txtWebInterfacePassword" type="text" label="Vu+ Web Interface password:" />
|
||||||
|
<div class="fieldDescription">
|
||||||
|
The web Interface password of your receiver (optional)
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="checkboxContainer checkboxContainer-withDescription">
|
||||||
|
<label>
|
||||||
|
<input is="emby-checkbox" type="checkbox" id="chkUseSecureHTTPS" />
|
||||||
|
<span>Use secure HTTP (HTTPS)</span>
|
||||||
|
</label>
|
||||||
|
<div class="fieldDescription checkboxFieldDescription">
|
||||||
|
Use HTTPS to connect to your receiver
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="checkboxContainer checkboxContainer-withDescription">
|
||||||
|
<label>
|
||||||
|
<input is="emby-checkbox" type="checkbox" id="chkOnlyOneBouquet" />
|
||||||
|
<span>Fetch Only one TV bouquet</span>
|
||||||
|
</label>
|
||||||
|
<div class="fieldDescription checkboxFieldDescription">
|
||||||
|
Limit channels to only those contained within the specified TV Bouquet below (optional)
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
<div class="inputContainer">
|
||||||
|
<input is="emby-input" id="txtTVBouquet" type="text" label="Vu+ TVBouquet:" />
|
||||||
|
<div class="fieldDescription">
|
||||||
|
The TV Bouquet to load channels for (optional)
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="checkboxContainer checkboxContainer-withDescription">
|
||||||
|
<label>
|
||||||
|
<input is="emby-checkbox" type="checkbox" id="chkZapToChannel" />
|
||||||
|
<span>Zap before Channel switch (single tuner)</span>
|
||||||
|
</label>
|
||||||
|
<div class="fieldDescription checkboxFieldDescription">
|
||||||
|
Set if only one tuner within receiver
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="checkboxContainer checkboxContainer-withDescription">
|
||||||
|
<label>
|
||||||
|
<input is="emby-checkbox" type="checkbox" id="chkFetchPiconsFromWebInterface" />
|
||||||
|
<span>Fetch picons from webinterface</span>
|
||||||
|
</label>
|
||||||
|
<div class="fieldDescription checkboxFieldDescription">
|
||||||
|
Set if you want to retrieve Picons from the web interface of the receiver
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
<div class="inputContainer">
|
||||||
|
<input is="emby-input" id="txtPiconsPath" type="text" label="Picons Path:" />
|
||||||
|
<div class="fieldDescription">
|
||||||
|
The local location of your Picons eg. C:\Picons\ (optional)
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="inputContainer">
|
||||||
|
<input is="emby-input" id="txtRecordingPath" type="text" label="Recording Path:" />
|
||||||
|
<div class="fieldDescription">
|
||||||
|
The location to store your recordings on your receiver eg. /hdd/movie/ (optional)
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<label class="checkboxContainer">
|
||||||
|
<input is="emby-checkbox" type="checkbox" id="chkDebugLogging" />
|
||||||
|
<span>Enable VuPlus debug logging</span>
|
||||||
|
</label>
|
||||||
|
|
||||||
|
<div>
|
||||||
|
<button is="emby-button" type="submit" class="raised button-submit block"><span>Save</span></button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
<script type="text/javascript">
|
||||||
|
|
||||||
|
var VuPlusConfigurationPage = {
|
||||||
|
pluginUniqueId: "9564ac10-af23-39bc-449f-624f23cfa48f"
|
||||||
|
};
|
||||||
|
|
||||||
|
$('.VuPlusConfigurationPage').on('pageshow', function (event) {
|
||||||
|
|
||||||
|
Dashboard.showLoadingMsg();
|
||||||
|
|
||||||
|
var page = this;
|
||||||
|
|
||||||
|
ApiClient.getPluginConfiguration(VuPlusConfigurationPage.pluginUniqueId).then(function (config) {
|
||||||
|
|
||||||
|
$('#txtHostName', page).val(config.HostName || "");
|
||||||
|
$('#txtStreamingPort', page).val(config.StreamingPort || "");
|
||||||
|
$('#txtWebInterfacePort', page).val(config.WebInterfacePort || "");
|
||||||
|
$('#txtWebInterfaceUsername', page).val(config.WebInterfaceUsername || "");
|
||||||
|
$('#txtWebInterfacePassword', page).val(config.WebInterfacePassword || "");
|
||||||
|
page.querySelector('#chkUseSecureHTTPS').checked = config.UseSecureHTTPS || false;
|
||||||
|
page.querySelector('#chkOnlyOneBouquet').checked = config.OnlyOneBouquet || false;
|
||||||
|
page.querySelector('#txtTVBouquet', page).val(config.TVBouquet || "");
|
||||||
|
page.querySelector('#chkZapToChannel').checked = config.ZapToChannel || false;
|
||||||
|
page.querySelector('#chkFetchPiconsFromWebInterface').checked = config.FetchPiconsFromWebInterface || false;
|
||||||
|
$('#txtPiconsPath', page).val(config.PiconsPath || "");
|
||||||
|
|
||||||
|
$('#txtRecordingPath', page).val(config.RecordingPath || "");
|
||||||
|
|
||||||
|
page.querySelector('#chkDebugLogging').checked = config.EnableDebugLogging || false;
|
||||||
|
|
||||||
|
Dashboard.hideLoadingMsg();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
$('.VuPlusConfigurationForm').on('submit', function (e) {
|
||||||
|
|
||||||
|
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>
|
||||||
|
</div>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
@@ -0,0 +1,40 @@
|
|||||||
|
using MediaBrowser.Model.LiveTv;
|
||||||
|
using System;
|
||||||
|
using MediaBrowser.Model.Logging;
|
||||||
|
|
||||||
|
namespace MediaBrowser.Plugins.VuPlus.Helpers
|
||||||
|
{
|
||||||
|
public static class ChannelHelper
|
||||||
|
{
|
||||||
|
public static ChannelType GetChannelType(string channelType)
|
||||||
|
{
|
||||||
|
ChannelType type = new ChannelType();
|
||||||
|
|
||||||
|
if (channelType == "0x1")
|
||||||
|
{
|
||||||
|
type = ChannelType.TV;
|
||||||
|
}
|
||||||
|
else if (channelType == "0xa")
|
||||||
|
{
|
||||||
|
type = ChannelType.Radio;
|
||||||
|
}
|
||||||
|
|
||||||
|
return type;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class UtilsHelper
|
||||||
|
{
|
||||||
|
public static void DebugInformation(ILogger logger, string message)
|
||||||
|
{
|
||||||
|
var config = Plugin.Instance.Configuration;
|
||||||
|
bool enableDebugLogging = config.EnableDebugLogging;
|
||||||
|
|
||||||
|
if (enableDebugLogging)
|
||||||
|
{
|
||||||
|
logger.Debug(message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Before Width: | Height: | Size: 20 KiB After Width: | Height: | Size: 20 KiB |
+422
-369
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,24 @@
|
|||||||
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
|
<PropertyGroup>
|
||||||
|
<TargetFrameworks>netstandard2.0;</TargetFrameworks>
|
||||||
|
<AssemblyVersion>3.2.1</AssemblyVersion>
|
||||||
|
<FileVersion>3.2.1</FileVersion>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<None Remove="Configuration\configPage.html" />
|
||||||
|
<None Remove="Images\thumb.png" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<EmbeddedResource Include="Configuration\configPage.html" />
|
||||||
|
<EmbeddedResource Include="Images\thumb.png" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<PackageReference Include="mediabrowser.server.core" Version="4.1.0.26" />
|
||||||
|
<PackageReference Include="System.Memory" Version="4.5.2" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
</Project>
|
||||||
@@ -0,0 +1,83 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using MediaBrowser.Common.Configuration;
|
||||||
|
using MediaBrowser.Common.Plugins;
|
||||||
|
using MediaBrowser.Model.Plugins;
|
||||||
|
using MediaBrowser.Model.Serialization;
|
||||||
|
using MediaBrowser.Plugins.VuPlus.Configuration;
|
||||||
|
using System.IO;
|
||||||
|
using MediaBrowser.Model.Drawing;
|
||||||
|
|
||||||
|
namespace MediaBrowser.Plugins.VuPlus
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Class Plugin
|
||||||
|
/// </summary>
|
||||||
|
public class Plugin : BasePlugin<PluginConfiguration>, IHasWebPages, IHasThumbImage
|
||||||
|
{
|
||||||
|
public Plugin(IApplicationPaths applicationPaths, IXmlSerializer xmlSerializer)
|
||||||
|
: base(applicationPaths, xmlSerializer)
|
||||||
|
{
|
||||||
|
Instance = this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the name of the plugin
|
||||||
|
/// </summary>
|
||||||
|
/// <value>The name.</value>
|
||||||
|
public override string Name
|
||||||
|
{
|
||||||
|
get { return "VuPlus"; }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the description.
|
||||||
|
/// </summary>
|
||||||
|
/// <value>The description.</value>
|
||||||
|
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");
|
||||||
|
public override Guid Id
|
||||||
|
{
|
||||||
|
get { return _id; }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the instance.
|
||||||
|
/// </summary>
|
||||||
|
/// <value>The instance.</value>
|
||||||
|
public static Plugin Instance { get; private set; }
|
||||||
|
|
||||||
|
public IEnumerable<PluginPageInfo> GetPages()
|
||||||
|
{
|
||||||
|
return new[]
|
||||||
|
{
|
||||||
|
new PluginPageInfo
|
||||||
|
{
|
||||||
|
Name = "vuplus",
|
||||||
|
EmbeddedResourcePath = "MediaBrowser.Plugins.VuPlus.Configuration.configPage.html"
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
public Stream GetThumbImage()
|
||||||
|
{
|
||||||
|
var type = GetType();
|
||||||
|
return type.Assembly.GetManifestResourceStream(type.Namespace + ".Images.thumb.png");
|
||||||
|
}
|
||||||
|
|
||||||
|
public ImageFormat ThumbImageFormat
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return ImageFormat.Png;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
+111
-58
@@ -1,53 +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.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 Microsoft.Extensions.Logging;
|
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 Jellyfin.Plugin.Enigma2
|
namespace MediaBrowser.Plugins.VuPlus
|
||||||
{
|
{
|
||||||
public class RecordingsChannel : IChannel, IHasCacheKey, ISupportsDelete, ISupportsLatestMedia, ISupportsMediaProbe, IHasFolderAttributes
|
public class RecordingsChannel : IChannel, IHasCacheKey, ISupportsDelete, ISupportsLatestMedia, ISupportsMediaProbe, IHasFolderAttributes, IHasChangeEvent
|
||||||
{
|
{
|
||||||
private readonly ILogger<LiveTvService> _logger;
|
public ILiveTvManager _liveTvManager;
|
||||||
|
|
||||||
public RecordingsChannel(ILoggerFactory loggerFactory)
|
public event EventHandler ContentChanged;
|
||||||
|
private Timer _updateTimer;
|
||||||
|
|
||||||
|
public void OnContentChanged()
|
||||||
{
|
{
|
||||||
_logger = loggerFactory.CreateLogger<LiveTvService>();
|
if (ContentChanged != null)
|
||||||
_logger.LogDebug("[Enigma2] RecordingsChannel()");
|
{
|
||||||
|
ContentChanged(this, EventArgs.Empty);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public string Name => "Enigma2 Recordings";
|
private void OnUpdateTimerCallback(object state)
|
||||||
|
{
|
||||||
|
OnContentChanged();
|
||||||
|
}
|
||||||
|
|
||||||
public string[] Attributes => new[] { "Recordings" };
|
public RecordingsChannel(ILiveTvManager liveTvManager)
|
||||||
|
{
|
||||||
|
_liveTvManager = liveTvManager;
|
||||||
|
|
||||||
public string Description => "Enigma2 Recordings";
|
var interval = TimeSpan.FromMinutes(15);
|
||||||
|
_updateTimer = new Timer(OnUpdateTimerCallback, null, interval, interval);
|
||||||
|
}
|
||||||
|
|
||||||
public string DataVersion => "1";
|
public void Dispose()
|
||||||
|
{
|
||||||
|
if (_updateTimer != null)
|
||||||
|
{
|
||||||
|
_updateTimer.Dispose();
|
||||||
|
_updateTimer = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public string HomePageUrl => null;
|
public string Name
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return "VuPlus Recordings";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public ChannelParentalRating ParentalRating => ChannelParentalRating.GeneralAudience;
|
public string[] Attributes
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return new[] { "Recordings" };
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public string Description
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return "VuPlus Recordings";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public string DataVersion
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return "1";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
@@ -65,8 +122,8 @@ namespace Jellyfin.Plugin.Enigma2
|
|||||||
{
|
{
|
||||||
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>
|
||||||
@@ -84,7 +141,7 @@ namespace Jellyfin.Plugin.Enigma2
|
|||||||
{
|
{
|
||||||
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
|
||||||
});
|
});
|
||||||
@@ -111,7 +168,7 @@ namespace Jellyfin.Plugin.Enigma2
|
|||||||
|
|
||||||
private LiveTvService GetService()
|
private LiveTvService GetService()
|
||||||
{
|
{
|
||||||
return LiveTvService.Instance;
|
return _liveTvManager.Services.OfType<LiveTvService>().First();
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool CanDelete(BaseItem item)
|
public bool CanDelete(BaseItem item)
|
||||||
@@ -124,13 +181,6 @@ namespace Jellyfin.Plugin.Enigma2
|
|||||||
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))
|
||||||
@@ -182,10 +232,14 @@ namespace Jellyfin.Plugin.Enigma2
|
|||||||
var service = GetService();
|
var service = GetService();
|
||||||
var allRecordings = await service.GetAllRecordingsAsync(cancellationToken).ConfigureAwait(false);
|
var allRecordings = await service.GetAllRecordingsAsync(cancellationToken).ConfigureAwait(false);
|
||||||
|
|
||||||
return new ChannelItemResult()
|
var result = new ChannelItemResult()
|
||||||
{
|
{
|
||||||
Items = allRecordings.Where(filter).Select(ConvertToChannelItem).ToList()
|
Items = new List<ChannelItemInfo>()
|
||||||
};
|
};
|
||||||
|
|
||||||
|
result.Items.AddRange(allRecordings.Where(filter).Select(ConvertToChannelItem));
|
||||||
|
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
private ChannelItemInfo ConvertToChannelItem(MyRecordingInfo item)
|
private ChannelItemInfo ConvertToChannelItem(MyRecordingInfo item)
|
||||||
@@ -204,7 +258,7 @@ namespace Jellyfin.Plugin.Enigma2
|
|||||||
//HomePageUrl = item.HomePageUrl
|
//HomePageUrl = item.HomePageUrl
|
||||||
Id = item.Id,
|
Id = item.Id,
|
||||||
//IndexNumber = item.IndexNumber,
|
//IndexNumber = item.IndexNumber,
|
||||||
MediaType = item.ChannelType == ChannelType.TV ? ChannelMediaType.Video : ChannelMediaType.Audio,
|
MediaType = item.ChannelType == Model.LiveTv.ChannelType.TV ? ChannelMediaType.Video : ChannelMediaType.Audio,
|
||||||
MediaSources = new List<MediaSourceInfo>
|
MediaSources = new List<MediaSourceInfo>
|
||||||
{
|
{
|
||||||
new MediaSourceInfo
|
new MediaSourceInfo
|
||||||
@@ -222,7 +276,7 @@ namespace Jellyfin.Plugin.Enigma2
|
|||||||
DateModified = item.DateLastUpdated,
|
DateModified = item.DateLastUpdated,
|
||||||
Overview = item.Overview,
|
Overview = item.Overview,
|
||||||
//People = item.People
|
//People = item.People
|
||||||
IsLiveStream = item.Status == RecordingStatus.InProgress,
|
IsLiveStream = item.Status == Model.LiveTv.RecordingStatus.InProgress,
|
||||||
Etag = item.Status.ToString()
|
Etag = item.Status.ToString()
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -234,14 +288,16 @@ namespace Jellyfin.Plugin.Enigma2
|
|||||||
var service = GetService();
|
var service = GetService();
|
||||||
|
|
||||||
var allRecordings = await service.GetAllRecordingsAsync(cancellationToken).ConfigureAwait(false);
|
var allRecordings = await service.GetAllRecordingsAsync(cancellationToken).ConfigureAwait(false);
|
||||||
|
var result = new ChannelItemResult()
|
||||||
|
{
|
||||||
|
Items = new List<ChannelItemInfo>()
|
||||||
|
};
|
||||||
|
|
||||||
var series = allRecordings
|
var series = allRecordings
|
||||||
.Where(i => i.IsSeries)
|
.Where(i => i.IsSeries)
|
||||||
.ToLookup(i => i.Name, StringComparer.OrdinalIgnoreCase);
|
.ToLookup(i => i.Name, StringComparer.OrdinalIgnoreCase);
|
||||||
|
|
||||||
var items = new List<ChannelItemInfo>();
|
result.Items.AddRange(series.OrderBy(i => i.Key).Select(i => new ChannelItemInfo
|
||||||
|
|
||||||
items.AddRange(series.OrderBy(i => i.Key).Select(i => new ChannelItemInfo
|
|
||||||
{
|
{
|
||||||
Name = i.Key,
|
Name = i.Key,
|
||||||
FolderType = ChannelFolderType.Container,
|
FolderType = ChannelFolderType.Container,
|
||||||
@@ -254,7 +310,7 @@ namespace Jellyfin.Plugin.Enigma2
|
|||||||
|
|
||||||
if (kids != null)
|
if (kids != null)
|
||||||
{
|
{
|
||||||
items.Add(new ChannelItemInfo
|
result.Items.Add(new ChannelItemInfo
|
||||||
{
|
{
|
||||||
Name = "Kids",
|
Name = "Kids",
|
||||||
FolderType = ChannelFolderType.Container,
|
FolderType = ChannelFolderType.Container,
|
||||||
@@ -267,7 +323,7 @@ namespace Jellyfin.Plugin.Enigma2
|
|||||||
var movies = allRecordings.FirstOrDefault(i => i.IsMovie);
|
var movies = allRecordings.FirstOrDefault(i => i.IsMovie);
|
||||||
if (movies != null)
|
if (movies != null)
|
||||||
{
|
{
|
||||||
items.Add(new ChannelItemInfo
|
result.Items.Add(new ChannelItemInfo
|
||||||
{
|
{
|
||||||
Name = "Movies",
|
Name = "Movies",
|
||||||
FolderType = ChannelFolderType.Container,
|
FolderType = ChannelFolderType.Container,
|
||||||
@@ -280,7 +336,7 @@ namespace Jellyfin.Plugin.Enigma2
|
|||||||
var news = allRecordings.FirstOrDefault(i => i.IsNews);
|
var news = allRecordings.FirstOrDefault(i => i.IsNews);
|
||||||
if (news != null)
|
if (news != null)
|
||||||
{
|
{
|
||||||
items.Add(new ChannelItemInfo
|
result.Items.Add(new ChannelItemInfo
|
||||||
{
|
{
|
||||||
Name = "News",
|
Name = "News",
|
||||||
FolderType = ChannelFolderType.Container,
|
FolderType = ChannelFolderType.Container,
|
||||||
@@ -293,7 +349,7 @@ namespace Jellyfin.Plugin.Enigma2
|
|||||||
var sports = allRecordings.FirstOrDefault(i => i.IsSports);
|
var sports = allRecordings.FirstOrDefault(i => i.IsSports);
|
||||||
if (sports != null)
|
if (sports != null)
|
||||||
{
|
{
|
||||||
items.Add(new ChannelItemInfo
|
result.Items.Add(new ChannelItemInfo
|
||||||
{
|
{
|
||||||
Name = "Sports",
|
Name = "Sports",
|
||||||
FolderType = ChannelFolderType.Container,
|
FolderType = ChannelFolderType.Container,
|
||||||
@@ -306,7 +362,7 @@ namespace Jellyfin.Plugin.Enigma2
|
|||||||
var other = allRecordings.FirstOrDefault(i => !i.IsSports && !i.IsNews && !i.IsMovie && !i.IsKids && !i.IsSeries);
|
var other = allRecordings.FirstOrDefault(i => !i.IsSports && !i.IsNews && !i.IsMovie && !i.IsKids && !i.IsSeries);
|
||||||
if (other != null)
|
if (other != null)
|
||||||
{
|
{
|
||||||
items.Add(new ChannelItemInfo
|
result.Items.Add(new ChannelItemInfo
|
||||||
{
|
{
|
||||||
Name = "Others",
|
Name = "Others",
|
||||||
FolderType = ChannelFolderType.Container,
|
FolderType = ChannelFolderType.Container,
|
||||||
@@ -316,10 +372,7 @@ namespace Jellyfin.Plugin.Enigma2
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
return new ChannelItemResult()
|
return result;
|
||||||
{
|
|
||||||
Items = items
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
public class MyRecordingInfo
|
public class MyRecordingInfo
|
||||||
@@ -378,12 +431,12 @@ namespace Jellyfin.Plugin.Enigma2
|
|||||||
/// <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.
|
||||||
@@ -430,7 +483,7 @@ namespace Jellyfin.Plugin.Enigma2
|
|||||||
/// 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.
|
||||||
@@ -513,7 +566,7 @@ namespace Jellyfin.Plugin.Enigma2
|
|||||||
/// 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
@@ -1,44 +0,0 @@
|
|||||||
---
|
|
||||||
# The name of the plugin; official plugins always start "jellyfin-plugin-"
|
|
||||||
name: "jellyfin-plugin-enigma2"
|
|
||||||
|
|
||||||
# The GUID of the plugin, found in Plugin.cs
|
|
||||||
guid: "193f29f9-ea6c-4595-a6f6-55e79d7c590a"
|
|
||||||
|
|
||||||
# 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: "5.0.1.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.8.0.0" # The earliest binary-compatible version
|
|
||||||
|
|
||||||
framework: "net6.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: "Enigma2"
|
|
||||||
|
|
||||||
# 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:
|
|
||||||
- "Jellyfin.Plugin.Enigma2.dll"
|
|
||||||
|
|
||||||
# Build information values for the build infrastructure; these should
|
|
||||||
# not need to be changed usually.
|
|
||||||
build_type: "dotnet"
|
|
||||||
dotnet_configuration: "Release"
|
|
||||||
dotnet_framework: "net6.0"
|
|
||||||
Reference in New Issue
Block a user