Config parsing

This commit is contained in:
ABelliqueux 2022-10-08 16:49:45 +02:00
parent e615cc4d7c
commit 14975546ca
7 changed files with 188 additions and 79 deletions

0
__init__.py Normal file
View File

58
app.py
View File

@ -1,7 +1,7 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
#
import sys, os
import sys, os, base64, toml
import http.client
import xml.etree.ElementTree as ET
from flask import Flask, render_template, request, make_response, jsonify
@ -9,21 +9,17 @@ from waitress import serve
app = Flask(__name__)
DEBUG = 0
video_folder = "/home/pi"
media_ext = [ "mp4", "avi", "mkv" ]
# ~ video_folder = "/media/"
## base64 encoded ":secret""
# import base64
# passwd = "foo"
# passswd64 = str(base64.b64encode(passwd.encode('utf-8')), 'utf-8')
auth = "OnNlY3JldA=="
cmd_auth = "OnNlY3JldA=="
hosts = [ "10.42.0.135", "10.42.0.156" ]
# VLC http LUA port
port = 8080
# Clients cmd port
cmd_port = 5000
# Load config defaults, then look for other config files
app.config.from_file("defaults.toml", load=toml.load)
config_locations = ["./", "~/.", "~/.config/"]
for location in config_locations:
# Optional config files, ~ is expanded to $HOME on *nix, %USERPROFILE% on windows
# ~ app.config.from_file("videopi.toml", load=toml.load, silent=True)
if app.config.from_file(os.path.expanduser( location + "videopi.toml"), load=toml.load, silent=True):
print("Found configuration file in " + os.path.expanduser( location ))
# ~ app.config.from_file(os.path.expanduser("~/.config/videopi.toml"), load=toml.load, silent=True)
###
hosts_available, hosts_unavailable = [],[]
@ -64,6 +60,18 @@ cmd = {
}
# Set configuration
DEBUG = app.config['DEFAULT']['DEBUG']
media_folder_remote = app.config['DEFAULT']['media_folder_remote']
media_folder_local = app.config['DEFAULT']['media_folder_local']
media_ext = app.config['DEFAULT']['media_ext']
auth = str(base64.b64encode(str(":" + app.config['DEFAULT']['auth']).encode('utf-8')), 'utf-8')
cmd_auth = str(base64.b64encode(str(":" + app.config['DEFAULT']['cmd_auth']).encode('utf-8')), 'utf-8')
hosts = app.config['DEFAULT']['hosts']
port = app.config['DEFAULT']['port']
cmd_port = app.config['DEFAULT']['cmd_port']
# Network/link utilities
# https://www.metageek.com/training/resources/understanding-rssi/
@ -153,7 +161,7 @@ def sendCommand(host, arg0, arg1, arg2):
elif arg0 == "seek" :
req = req + "&val=" + arg1
elif (arg0 == "enqueue") or (arg0 == "add") :
req = req + "&input=file://" + video_folder + "/" + arg1
req = req + "&input=file://" + media_folder_remote + "/" + arg1
# Send request
conn = http.client.HTTPConnection( host + ":" + str(portl), timeout=3 )
try:
@ -187,14 +195,22 @@ def sendCommand(host, arg0, arg1, arg2):
cur_time = int(xml.find('time').text)
cur_length_fmtd = sec2min(cur_length)
cur_time_fmtd = sec2min(cur_time)
cur_id = int(xml.find('currentplid').text)
cur_pos = xml.find('position').text
cur_loop = xml.find('loop').text
cur_repeat = xml.find('repeat').text
response_dict = {
'host': host,
'file': filename,
'time': cur_time_fmtd,
'leng': cur_length_fmtd,
'pos': xml.find('position').text,
'loop': xml.find('loop').text,
'repeat': xml.find('repeat').text,
'pos': cur_pos,
'loop': cur_loop,
'repeat': cur_repeat,
# ~ 'pos': xml.find('position').text,
# ~ 'loop': xml.find('loop').text,
# ~ 'repeat': xml.find('repeat').text,
'id': cur_id,
}
return response_dict
@ -248,7 +264,7 @@ def scan():
@app.route("/browse")
def browse():
files = listMediaFiles("../");
files = listMediaFiles(media_folder_local);
return files;

12
defaults.toml Normal file
View File

@ -0,0 +1,12 @@
[DEFAULT]
DEBUG = 0
media_folder_local = "~/Videos"
media_folder_remote = "~/Videos"
media_ext = []
auth = ""
cmd_auth = ""
hosts = []
# VLC http LUA port
port = 0
# Clients cmd port
cmd_port = 0

View File

@ -2,7 +2,12 @@
const tl_cont_attr = {id:"tl_cont", ondrop: "drop(event, this)", ondragover:"allowDrop(event)"};
const tl_drag_attr = {id:"tl_drag", draggable:"true", ondragstart:"drag(event, this)"};
// Config
var timeline_color_cursor = "#FF8839";
var timeline_color_bg = "#2EB8E6";
var src_id = "";
var medias_status = {};
function updatePlaylist(){
var new_list = [];
@ -72,7 +77,17 @@ function adjustTl() {
}
};
function addElement(type, attr, meta = [], j = 0){
function addAttr(id, attr, val , child=-1) {
var elem = document.getElementById(id);
if (child>-1){
elem = elem.children[child];
}
var att = document.createAttribute(attr);
att.value = val;
elem.setAttributeNode(att);
};
function addElement(type, attr, meta = 0, j = 0){
var elem = document.createElement(type);
var keys_array = Object.keys(attr);
for (i=0, l=keys_array.length;i<l;i++) {
@ -84,10 +99,12 @@ function addElement(type, attr, meta = [], j = 0){
}
elem.setAttributeNode(att);
}
// Set okaylist id attribute
att = document.createAttribute("media_id");
att.value = meta[0];
elem.setAttributeNode(att);
// Set playlist id attribute
if (meta) {
att = document.createAttribute("media_id");
att.value = meta[0];
elem.setAttributeNode(att);
}
// Get filename
elem.innerText = meta[1];
return elem;
@ -153,9 +170,29 @@ function parseResult(command, infos_array) {
case "/all/status":
// Iterate over array
for (var i = 0, l=infos_array.length; i<l; i++) {
document.getElementById("status_"+infos_array[i].host).innerHTML = "Playing " + infos_array[i].file + " : " + infos_array[i].time + " / " + infos_array[i].leng;
if (infos_array[i].loop == "true") { document.getElementById("loop_ind_" + infos_array[i].host).style.backgroundColor = "#0f0"} else {document.getElementById("loop_ind_" + infos_array[i].host).style.backgroundColor = "#f00"};
if (infos_array[i].repeat == "true") { document.getElementById("repeat_ind_" + infos_array[i].host).style.backgroundColor = "#0f0"} else {document.getElementById("repeat_ind_" + infos_array[i].host).style.backgroundColor = "#f00"};
// Get filename, time/length
document.getElementById("status_"+infos_array[i].host).innerHTML = infos_array[i].file + " <br/> " + infos_array[i].time + " / " + infos_array[i].leng;
medias_status[infos_array[i].id] = infos_array[i].pos;
// Find currently playing element
//~ var pl_length = document.getElementById("timeline").getAttribute("length");
//~ for (j=0,k=pl_length;j<k;j++){
//~ if (document.getElementById("timeline").children[j].children[0].getAttribute('media_id') == infos_array[i].id ) {
//~ addAttr(document.getElementById("timeline").children[j].children[0].id, "pos", infos_array[i].pos);
//~ }
//~ };
//~ document.getElementById("timeline").children[0].children[0].hasAttribute('media_id')
// Toggle loop indicator
if (infos_array[i].loop == "true") {
document.getElementById("loop_ind_" + infos_array[i].host).style.backgroundColor = "#0f0"
} else {
document.getElementById("loop_ind_" + infos_array[i].host).style.backgroundColor = "#f00"
};
// Toggle repeat indicator
if (infos_array[i].repeat == "true") {
document.getElementById("repeat_ind_" + infos_array[i].host).style.backgroundColor = "#0f0"
} else {
document.getElementById("repeat_ind_" + infos_array[i].host).style.backgroundColor = "#f00"
};
};
break;
case "/all/list":
@ -182,12 +219,21 @@ function parseResult(command, infos_array) {
// Timeline
var child_node = addElement("div", tl_drag_attr, item_meta, j);
var len = document.getElementById("timeline").children.length;
addAttr("timeline", "length", len);
if ( len < items_array.length ) {
document.getElementById("timeline").appendChild( addElement("div", tl_cont_attr, [], len) );
document.getElementById("timeline").appendChild( addElement("div", tl_cont_attr, 0, len) );
}
document.getElementById(tl_cont_attr.id + j).replaceChildren(child_node);
adjustTl();
if (item_meta[3] != ""){
document.getElementById(tl_cont_attr.id + j).children[0].style.borderBottom = "4px solid #ff8300";
document.getElementById(tl_cont_attr.id + j).children[0].style.borderBottom = "4px solid " + timeline_color_cursor;
document.getElementById(tl_cont_attr.id + j).children[0].style.fontWeight = "bold";
var pos = medias_status[item_meta[0]] * 100;
//~ pos = pos.toPrecision(2);
var pos1 = pos-1 + "%";
pos = pos + "%";
//console.log( "linear-gradient(90deg," + timeline_color2 + " " + pos1 + ", " + timeline_color1 + " " + pos + ", " + timeline_color2 + " " + pos + ")" );
document.getElementById(tl_cont_attr.id + j).children[0].style.background = "linear-gradient(90deg," + timeline_color_bg + " " + pos1 + ", " + timeline_color_cursor + " " + pos + ", " + timeline_color_bg + " " + pos + ")";
}
}
html_table += "</table>";
@ -198,7 +244,7 @@ function parseResult(command, infos_array) {
var host_up = infos_array[0];
var host_down = infos_array[1];
for ( var i=0, l=host_up.length; i<l; i++){
document.getElementById(host_up[i]).style.display = 'initial';
document.getElementById(host_up[i]).style.display = 'block';
}
for ( var i=0, l=host_down.length; i<l; i++){
document.getElementById(host_down[i]).style.display = 'none';

View File

@ -1,22 +1,36 @@
body {color:#fff;background-color:#666;margin:0;}
div {box-sizing: border-box;}
h2 {margin:0;}
table {background-color: #555;margin:.5em;}
td {padding: .2em .5em;}
table {background-color: #555;margin:.5em;max-width:100%;font-size:.9em}
td {padding: 0;}
th {background-color: #aaa;}
tr:nth-child(2n+1) {background-color: #888;}
* {box-sizing: border-box;}
.btn-group-lg > .btn, .btn-lg {
padding: 10px 16px;
font-size: 18px;
line-height: 1.3333333;
border-radius: 6px;
}
#master_remote {background-color:#222;min-height: 20em;}
#master_remote {
background: linear-gradient(0deg, #222 10%, #444 80%);
min-height: 20em;
}
#master_remote .right_col {background-color:transparent;}
.client_container {border-bottom: #bbb solid 4px;display:none;}
.client_container {
border-bottom: #222 solid 1px;
display:none;
background: linear-gradient(0deg, #999 10%, #666 80%);
}
.client_container .button{}
/*
.timeline {height: 3em;background-color: #0f0;margin: 2em 0;}
*/
#timeline {
background-color:#ddd;
height: 75px;
width:100%
width:100%;
margin-top:1em;
}
[id^="tl_cont"] {
float: left;
@ -32,25 +46,12 @@ tr:nth-child(2n+1) {background-color: #888;}
height:75px;
line-height: 75px;
width:100%;
background-color:#999;
background-color:#1F7B99;
}
[id^="tl_cont"]:nth-child(2n+1) [id^="tl_drag"] {
background-color:#777;
background-color:#255E70;
}
/*
#tl_drag1 {background-color:#486;}
#tl_drag2 {background-color:#a9e;}
#tl_drag3 {background-color:#d53;}
#tl_drag4 {background-color:#ea5;}
#tl_drag5 {background-color:#964;}
#tl_drag6 {background-color:#135;}
#tl_drag7 {background-color:#973;}
#tl_drag8 {background-color:#b26;}
#tl_drag9 {background-color:#fe9;}
#tl_drag10 {background-color:#fe5;}
*/
.right_col {width: 78%;display: inline-block;background-color:#888;}
.client_container:nth-child(2n+1) {background-color:#444;}
.command {margin: 0 !important;}
.buttons {width:75%;margin:auto;text-align: center;padding: 2em;}
@ -59,7 +60,7 @@ tr:nth-child(2n+1) {background-color: #888;}
width:3em;
height: 4em;
display:inline-block;
padding: 6px 12px;
padding: 0;
font-weight: 400;
line-height: 1.42857143;
text-align: center;
@ -72,15 +73,13 @@ tr:nth-child(2n+1) {background-color: #888;}
-moz-user-select: none;
-ms-user-select: none;
user-select: none;
background-image: none;
border: 1px solid transparent;
border-top-color: transparent;
border-right-color: transparent;
border-bottom-color: transparent;
border-left-color: transparent;
border-radius: 4px;
background: linear-gradient(0deg, #b9b9b9 10%, #f9f9f9 80%);
}
.btn_txt {display: block;font-size: small;}
/*Right column*/
.right_col {width: 79.9%;display: inline-block;}
/*Left column*/
.left_col {width: 20%;display: inline-block;float: left;clear: left;}
.left_col button {
@ -89,18 +88,36 @@ tr:nth-child(2n+1) {background-color: #888;}
padding: 0;
line-height: 2em;
}
.left_col button .btn_txt {display:none;position: absolute;left: 5%;color:#fff;font-weight:bold;font-size: medium;}
.left_col button .btn_txt {
display:none;
position: relative;
left: 40%;
top:80%;
color:#fff;
font-weight:bold;
font-size: medium;
background-color: #ff3030;
border: 1px solid #fff;
padding: 0 .5%;
}
.left_col button:hover .btn_txt {display:initial;}
.col_1 {
width: 50%;
width: 40%;
float: left;
padding: 3% 0 0 5%;
}
}
.col_2 {
width: 50%;
width: 60%;
display: inline-block;
clear: right;
}
.indicator {display:inline-block;background-color: #f00;}
.indicator {
display:inline-block;
background-color: #f00;
margin: 0 0 0 5%;
padding: 0.3em;
}
.wl_indicator {
display: inline-block;
background-color: #bbb;
@ -108,9 +125,24 @@ tr:nth-child(2n+1) {background-color: #888;}
margin: 0 1px;
padding: 0;
height: .5em;
width: 1em;
width: 5%;
}
#wl_0 {height:.5em;}
#wl_1 {height:.65em;}
#wl_2 {height:.80em;}
#wl_3 {height:.95em;}
#wl_3 {height:.95em;}
@media screen and (max-width: 800px) {
table {margin:0}
td {padding:0;}
.btn-group-lg > .btn, .btn-lg {
font-size:14px;
}
.left_col {width: 30%;}
.right_col {width: 69.9%;}
.col_2 {
overflow: scroll;
font-size: .9em;
}
}

View File

@ -1,7 +1,9 @@
<!DOCTYPE html>
<head>
<title>RPi Web Server</title>
<!--
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css" integrity="sha384-1q8mTJOASx8j1Au+a5WDVnPi2lkFfwwEAa8hDDdjZlpLegxhjVME1fgjWPGmkzs7" crossorigin="anonymous">
-->
<!--
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap-theme.min.css" integrity="sha384-fLW2N01lMqjakBkx3l/M9EahuwpSfeNvV63J5ezn3uZzapT0u7EYsXMjQV+0En5r" crossorigin="anonymous">
-->
@ -28,6 +30,7 @@
<button value="/all/clear" class="command btn btn-block btn-lg btn-default" role="button">X<span class="btn_txt">Vider<br/>listes</span></button>
<button value="/all/enqueue/tst.mp4" class="command btn btn-block btn-lg btn-default" role="button">&#x3b2;<span class="btn_txt">tst.mp4</span></button>
<button value="/all/enqueue/tst1.mp4" class="command btn btn-block btn-lg btn-default" role="button">&#x3b2;<span class="btn_txt">tst1.mp4</span></button>
<button value="/all/enqueue/sangliers_1080.mp4" class="command btn btn-block btn-lg btn-default" role="button">&#x3b2;<span class="btn_txt">sangli.mp4</span></button>
<button value="/move/0/1" class="command btn btn-block btn-lg btn-default" role="button">&#x3b2;<span class="btn_txt">movePl</span></button>
</p>
</div>
@ -35,13 +38,13 @@
{% for host in hosts %}
<div class="client_container" id="{{ host }}">
<div class="left_col">
<h2>{{ host }}</h2>
<div class="col_1">
<h2>{{ host }}</h2>
<button value="/{{host}}/poweroff" class="command btn btn-block btn-lg btn-default" role="button">&#x23fb;<span class="btn_txt">&Eacute;teindre</span></button>
<button value="/{{host}}/reboot" class="command btn btn-block btn-lg btn-default" role="button">&#x21BA;<span class="btn_txt">Red&eacute;marrer</span></button>
<p id="status_{{ host }}">{{status_message}}</p>
<p id="signal_{{ host }}">
<span style="">Signal:</span>
<span style="">Link:</span>
<span class="wl_indicator" id="wl_0"></span>
<span class="wl_indicator" id="wl_1"></span>
<span class="wl_indicator" id="wl_2"></span>
@ -56,18 +59,6 @@
</div>
<div class="right_col">
<div id="timeline">
<!--
<div id="tl_cont0" ondrop="drop(event, this)" ondragover="allowDrop(event)"><div id="tl_drag1" draggable="true" ondragstart="drag(event, this)">tst.mp4</div></div>
<div id="tl_cont1" ondrop="drop(event, this)" ondragover="allowDrop(event)"><div id="tl_drag2" draggable="true" ondragstart="drag(event, this)">video2.mp4</div></div>
<div id="tl_cont2" ondrop="drop(event, this)" ondragover="allowDrop(event)"><div id="tl_drag3" draggable="true" ondragstart="drag(event, this)">this_video.mp4</div></div>
<div id="tl_cont3" ondrop="drop(event, this)" ondragover="allowDrop(event)"><div id="tl_drag4" draggable="true" ondragstart="drag(event, this)">encore.mp4</div></div>
<div id="tl_cont4" ondrop="drop(event, this)" ondragover="allowDrop(event)"><div id="tl_drag5" draggable="true" ondragstart="drag(event, this)">balah.mp4</div></div>
<div id="tl_cont5" ondrop="drop(event, this)" ondragover="allowDrop(event)"><div id="tl_drag6" draggable="true" ondragstart="drag(event, this)">foo.mp4</div></div>
<div id="tl_cont6" ondrop="drop(event, this)" ondragover="allowDrop(event)"><div id="tl_drag7" draggable="true" ondragstart="drag(event, this)">bar.mp4</div></div>
<div id="tl_cont7" ondrop="drop(event, this)" ondragover="allowDrop(event)"><div id="tl_drag8" draggable="true" ondragstart="drag(event, this)">biche.mp4</div></div>
<div id="tl_cont8" ondrop="drop(event, this)" ondragover="allowDrop(event)"><div id="tl_drag9" draggable="true" ondragstart="drag(event, this)">genou.mp4</div></div>
<div id="tl_cont9" ondrop="drop(event, this)" ondragover="allowDrop(event)"><div id="tl_drag10" draggable="true" ondragstart="drag(event, this)">splaf.mp4</div></div>
-->
<!--
<div id="tl_contX"></div>
-->

12
videopi.toml Normal file
View File

@ -0,0 +1,12 @@
[DEFAULT]
DEBUG = 0
media_folder_local = "../medias"
media_folder_remote = "/home/pi"
media_ext = ["mp4", "avi", "mkv"]
auth = "secret"
cmd_auth = "secret"
hosts = ["10.42.0.135", "10.42.0.156"]
# VLC http LUA port
port = 8080
# Clients cmd port
cmd_port = 5000