Browse Source

a bit cleanup and live-mode

master
Stefan Naumann 5 years ago
parent
commit
11834b9934
  1. 1
      .gitignore
  2. 2
      cfg/config.json
  3. 6
      setup.sh
  4. 341
      src/piplayer.py
  5. 221
      src/ui.py

1
.gitignore

@ -0,0 +1 @@
*.pyc

2
cfg/config.json

@ -1 +1 @@
{"WindowX": 3, "WindowY": 47, "WindowWidth": 641, "WindowHeight": 449}
{"WindowX": 1, "WindowY": 460, "WindowWidth": 641, "WindowHeight": 449}

6
setup.sh

@ -64,7 +64,13 @@ prepare)
rm -rf $pyFLTKFolder
rm $pyFLTKFile
fi
bash setup.sh livestreamer
;;
# install only the livestreamer python-skript
livestreamer)
sudo pip install livestreamer
;;
# create documentation from the python doxygen comments
doc)
mkdir doc
doxygen Doxyfile

341
src/piplayer.py

@ -7,135 +7,80 @@ import time
import genericThread
import config
import fileio
playState = True;
durationState = 0;
positionState = 0;
import ui
omx = genericThread.genericThread ( 1, "OMX", 1);
state = genericThread.genericThread ( 2, "State", 2);
stateRun = True;
live=False;
def startOMX ( argv ):
global stateRun
argv=argv[0];
argv.insert ( 0, "omxplayer" )
argv.append ( "--win");
(x,y,x2,y2) = sizeCalc();
argv.append( str(x)+","+str(y)+","+str(x2)+","+str(y2) )
argv.append ( "-o");
argv.append("local");
argv.append("--aspect-mode");
argv.append("letterbox");
subprocess.run ( argv );
stateRun = False;
def callDBus ( param ):
try:
param.insert ( 0, config.dbusconfig );
param.insert ( 0, "bash" );
out = subprocess.check_output ( param )
return out;
except subprocess.CalledProcessError:
return b"";
def playCb(ptr):
callDBus ( ["pause"] );
getState( None );
global playState
global playBtn
if ( playState == True ):
playBtn.label ("@||");
else :
playBtn.label("@>");
def resizeCb ():
(x,y,x2,y2) = sizeCalc()
status = callDBus ( ["status"] );
times = 0;
while (status=="" and times < 5) :
status = callDBus ( ["status"] );
time.sleep ( 0.5 );
times = times + 1;
stream = argv.pop();
if ( times < 5 ):
callDBus (["setvideopos", str(x), str(y), str(x2), str(y2)]);
i = 0;
output = "local"
while ( i < len(argv) ):
if ( argv[i] =="-o"):
if ( argv[i+1] == "local" or argv[i+1] == "hdmi" ):
output=argv[i+1];
else:
output="local"
i = i + 1
(x,y,x2,y2) = ui.sizeCalc();
argv = [ "omxplayer", "--win", str(x)+","+str(y)+","+str(x2)+","+str(y2), "-o", output, "--aspect-mode", "letterbox", stream ];
subprocess.run ( argv );
stateRun = False;
def sizeCalc ( ):
global window
x = window.x();
y = window.y();
w = window.w();
h = window.h();
def startOMXLive ( argv ):
global stateRun
quality=argv[1];
argv=argv[0];
#x=x+2;
#y=y+2;
x2 = x + w;
y2 = y + h - 75;
stream = argv.pop();
return (x,y,x2,y2);
def DecodeState ( param ):
global playState;
global durationState;
global positionState;
i=0
while (i < len(param)) :
m = re.search ( "Duration: ([0-9]+)", param[i] );
if ( m is None ):
m = re.search ( "Position: ([0-9]+)", param[i] );
if ( m is None ):
m = re.search ( "Paused: (true|false)", param[i] );
if ( m is None ) :
pass;
else :
playState = ( m.group(1) == "false");
i = 0;
output = "local"
while ( i < len(argv) ):
if ( argv[i] =="-o"):
if ( argv[i+1] == "local" or argv[i+1] == "hdmi" ):
output=argv[i+1];
else:
positionState = int ( m.group(1) );
else:
durationState = int ( m.group(1) );
i=i+1
def timeOut ( time ) :
time = int(time / 1000000); # mikrosec -> sec
hours = int(time / 3600);
minutes = int((time / 60)) - hours*60;
sec = time - minutes*60 - hours*360;
return ( str(hours).zfill(2) + ":" + str(minutes).zfill(2) + ":" +str(sec).zfill(2) );
def setPosition ( pos ):
callDBus ( ["setposition", str(pos)] );
getState ( None );
def getState ( ptr ) :
status = callDBus ( ["status"] );
status = status.decode("utf-8").split("\n")
DecodeState ( status );
output="local"
i = i + 1
(x,y,x2,y2) = ui.sizeCalc();
argv = [ "livestreamer", stream, quality, "-np",
"omxplayer --win "+str(x)+","+str(y)+","+str(x2)+","+str(y2)+" -o "+output+" --aspect-mode letterbox --live" ];
print (argv);
subprocess.run ( argv );
stateRun = False;
statusLabel.value ( timeOut ( positionState ) + " / " + timeOut ( durationState ) );
if ( durationState == 0):
statusProgress.value(0);
else :
statusProgress.value( positionState / durationState );
stateRun = True;
def thread_state ( args ) :
global stateRun;
while ( stateRun == True ):
getState( None );
time.sleep (1);
global stateRun
global live
beginTime = int(time.time());
if ( live == False ):
while ( stateRun == True ):
ui.getState( None );
time.sleep (1);
else :
while ( stateRun == True ):
ui.statusLabel.value ( "Uptime: " + ui.timeOut ( (int(time.time()) - beginTime)*1000000 ))
time.sleep(1);
def killAll ( ptr ):
global stateRun;
global cfg
global window
def killAll ( cfg ):
global stateRun
stateRun = False;
callDBus ( ["stop"] );
cfg["WindowX"] = window.x();
cfg["WindowY"] = window.y();
cfg["WindowWidth"] = window.w();
cfg["WindowHeight"] = window.h();
ui.callDBus ( ["stop"] );
cfg["WindowX"] = ui.window.x();
cfg["WindowY"] = ui.window.y();
cfg["WindowWidth"] = ui.window.w();
cfg["WindowHeight"] = ui.window.h();
fileio.saveConfig ( config.configfile, cfg );
@ -145,125 +90,59 @@ def killAll ( ptr ):
def FLTK_run () :
global stateRun
global window
global statusProgress
x = window.x();
y = window.y();
w = window.w();
h = window.h();
while (stateRun == True and window.shown()):
x = ui.window.x();
y = ui.window.y();
w = ui.window.w();
h = ui.window.h();
while (stateRun == True and ui.window.shown()):
Fl.check();
if ( x != window.x() or y != window.y() or
w != window.w() or h != window.h() ):
resizeWindow ();
if (Fl.event_button1() and Fl.event_inside ( statusProgress.x(), statusProgress.y(), statusProgress.x() + statusProgress.w(), statusProgress.y() + statusProgress.h() ) ):
seekCb ();
if ( x != ui.window.x() or y != ui.window.y() or
w != ui.window.w() or h != ui.window.h() ):
ui.resizeWindow ();
if (Fl.event_button1() and
Fl.event_inside ( ui.statusProgress.x(),
ui.statusProgress.y(),
ui.statusProgress.x() + ui.statusProgress.w(),
ui.statusProgress.y() + ui.statusProgress.h() ) ):
ui.seekCb ();
time.sleep(0.1); # I don't want to burn that much cpu-time
def resizeWindow ( ):
global window;
global playBtn
global stateBtn
global killBtn
global statusLabel
global statusProgress
global volUp
global volDown
h = window.h()
w = window.w()
statusLabel.resize ( w-230, h-50, statusLabel.w(), statusLabel.h() );
playBtn.position ( 20, h-60 );
stateBtn.position ( 60, h-60);
killBtn.position ( 100, h-60 );
volUp.position ( w - 40, h-50 );
volDown.position ( w - 60, h-50 );
statusProgress.position ( 160, h-50 );
statusProgress.size ( w - 410, 20 );
playBtn.redraw();
stateBtn.redraw();
killBtn.redraw();
#statusLabel.redraw();
statusProgress.redraw();
window.redraw();
resizeCb ();
def seekCb ():
global statusProgress;
x = Fl.event_x();
x = x - statusProgress.x();
dim = x / statusProgress.w();
positionState = durationState * dim;
setPosition ( positionState );
def volUpCb ( ptr ):
callDBus ( ["volumeup"] );
def volDownCb ( ptr ):
callDBus ( ["volumedown"] );
if ( len ( sys.argv ) <= 1 ):
print ("Usage: " + sys.argv[0] + "[omxplayer-arguments] FILENAME");
sys.exit(0);
omx.setFn ( startOMX, [sys.argv[1:]] );
state.setFn ( thread_state, [] );
cfg = fileio.getConfig ( config.configfile );
window = Fl_Window( cfg.get("WindowX", 100) , cfg.get("WindowY", 100), cfg.get("WindowWidth", 640), cfg.get("WindowHeight", 480))
window.label(sys.argv[0])
window.size_range ( 320, 240, 0, 0);
# start omx-player
omx.start();
playBtn = Fl_Button(20, 420, 40, 40)
playBtn.labeltype(FL_SYMBOL_LABEL)
playBtn.label("@||")
playBtn.callback(playCb)
playBtn.box ( FL_THIN_UP_BOX );
stateBtn = Fl_Button ( 60, 420, 40, 40 );
stateBtn.label("?")
stateBtn.callback(getState)
stateBtn.box ( FL_THIN_UP_BOX );
killBtn = Fl_Button ( 100, 420, 40, 40 );
killBtn.label ("x");
killBtn.callback ( killAll );
killBtn.box ( FL_THIN_UP_BOX );
statusLabel = Fl_Output ( 410, 430, 150, 20 );
statusLabel.label ("");
statusLabel.box ( FL_FLAT_BOX );
statusProgress = Fl_Progress ( 160, 430, 230, 20 );
statusProgress.box( FL_FLAT_BOX );
statusProgress.minimum(0);
statusProgress.maximum(1);
statusProgress.color ( 0xffffffff );
statusProgress.selection_color( 0x272828ff );
volUp = Fl_Button ( 600, 430, 20,20 );
volUp.label ( "+" );
volUp.box ( FL_THIN_UP_BOX );
volUp.callback ( volUpCb );
volDown = Fl_Button ( 580, 430, 20,20 );
volDown.label ( "-" );
volDown.box ( FL_THIN_UP_BOX );
volDown.callback ( volDownCb );
resizeWindow();
window.end()
window.show(len(sys.argv), sys.argv)
state.start();
FLTK_run ();
killAll( None )
def main () :
global live
if ( len ( sys.argv ) <= 1 ):
print ("Usage: " + sys.argv[0] + " [parameters] FILENAME\n\
Options:\n\
* --live - indicate that a livestream is played (i.e. Twitch), will be played using livestreamer");
sys.exit(0);
i = 0
quality = "best"
live = False;
omx.setFn ( startOMX, [sys.argv[1:]] );
while ( i < len (sys.argv) ):
if (sys.argv[i] == "--live"):
live = True
if (sys.argv[i] == "--quality" or sys.argv[i] =="-q"):
quality=sys.argv[1+i];
i = i + 1;
print (quality)
if ( live == True ):
omx.setFn ( startOMXLive, [sys.argv[1:], quality] );
state.setFn ( thread_state, [] );
cfg = fileio.getConfig ( config.configfile );
ui.init( cfg );
# start omx-player
omx.start();
state.start();
FLTK_run ();
killAll( cfg )
if __name__ == "__main__" :
main()

221
src/ui.py

@ -0,0 +1,221 @@
import subprocess
import sys
import config
## TODO find a better way to get killAll-fn
import piplayer
import re
from fltk import *
playState = True;
durationState = 0;
positionState = 0;
dbusaddr = "org.mpris.MediaPlayer2.omxplayer"
def setDBusAddr ( addr ) :
global dbusaddr
dbusaddr = addr
def callDBus ( param ):
try:
param.insert ( 0, config.dbusconfig );
param.insert ( 0, "bash" );
out = subprocess.check_output ( param )
return out;
except subprocess.CalledProcessError:
return b"";
def playCb(ptr):
callDBus ( ["pause"] );
getState( None );
global playState
global playBtn
if ( playState == True ):
playBtn.label ("@||");
else :
playBtn.label("@>");
def sizeCalc ( ):
global window
x = window.x();
y = window.y();
w = window.w();
h = window.h();
#x=x+2;
#y=y+2;
x2 = x + w;
y2 = y + h - 75;
return (x,y,x2,y2);
def DecodeState ( param ):
global playState;
global durationState;
global positionState;
i=0
while (i < len(param)) :
m = re.search ( "Duration: ([0-9]+)", param[i] );
if ( m is None ):
m = re.search ( "Position: ([0-9]+)", param[i] );
if ( m is None ):
m = re.search ( "Paused: (true|false)", param[i] );
if ( m is None ) :
pass;
else :
playState = ( m.group(1) == "false");
else:
positionState = int ( m.group(1) );
else:
durationState = int ( m.group(1) );
i=i+1
def timeOut ( time ) :
time = int(time / 1000000); # mikrosec -> sec
hours = int(time / 3600);
minutes = int((time / 60)) - hours*60;
sec = time - minutes*60 - hours*360;
return ( str(hours).zfill(2) + ":" + str(minutes).zfill(2) + ":" +str(sec).zfill(2) );
def setPosition ( pos ):
callDBus ( ["setposition", str(pos)] );
getState ( None );
def getState ( ptr ) :
status = callDBus ( ["status"] );
status = status.decode("utf-8").split("\n")
DecodeState ( status );
statusLabel.value ( timeOut ( positionState ) + " / " + timeOut ( durationState ) );
if ( durationState == 0):
statusProgress.value(0);
else :
statusProgress.value( positionState / durationState );
def resizeWindow ( ):
global window;
global playBtn
global stateBtn
global killBtn
global statusLabel
global statusProgress
global volUp
global volDown
h = window.h()
w = window.w()
statusLabel.resize ( w-230, h-50, statusLabel.w(), statusLabel.h() );
playBtn.position ( 20, h-60 );
stateBtn.position ( 60, h-60);
killBtn.position ( 100, h-60 );
volUp.position ( w - 40, h-50 );
volDown.position ( w - 60, h-50 );
statusProgress.position ( 160, h-50 );
statusProgress.size ( w - 410, 20 );
playBtn.redraw();
stateBtn.redraw();
killBtn.redraw();
#statusLabel.redraw();
statusProgress.redraw();
window.redraw();
resizeOMX ();
def resizeOMX ():
(x,y,x2,y2) = sizeCalc()
status = callDBus ( ["status"] );
times = 0;
while (status=="" and times < 5) :
status = callDBus ( ["status"] );
time.sleep ( 0.5 );
times = times + 1;
if ( times < 5 ):
callDBus (["setvideopos", str(x), str(y), str(x2), str(y2)]);
def seekCb ():
global statusProgress;
x = Fl.event_x();
x = x - statusProgress.x();
dim = x / statusProgress.w();
positionState = durationState * dim;
setPosition ( positionState );
def volUpCb ( ptr ):
callDBus ( ["volumeup"] );
def volDownCb ( ptr ):
callDBus ( ["volumedown"] );
window=""
playBtn=""
stateBtn=""
killBtn=""
statusLabel=""
statusProgress=""
volUp=""
volDown=""
def init ( cfg ):
global window
global playBtn
global stateBtn
global killBtn
global statusLabel
global statusProgress
global volUp
global volDown
global stateBtn
window = Fl_Window( cfg.get("WindowX", 100) , cfg.get("WindowY", 100), cfg.get("WindowWidth", 640), cfg.get("WindowHeight", 480))
window.label(sys.argv[0])
window.size_range ( 320, 240, 0, 0);
playBtn = Fl_Button(20, 420, 40, 40)
playBtn.labeltype(FL_SYMBOL_LABEL)
playBtn.label("@||")
playBtn.callback(playCb)
playBtn.box ( FL_THIN_UP_BOX );
stateBtn = Fl_Button ( 60, 420, 40, 40 );
stateBtn.label("?")
stateBtn.callback(getState)
stateBtn.box ( FL_THIN_UP_BOX );
killBtn = Fl_Button ( 100, 420, 40, 40 );
killBtn.label ("x");
## TODO
killBtn.callback ( piplayer.killAll );
killBtn.box ( FL_THIN_UP_BOX );
statusLabel = Fl_Output ( 410, 430, 150, 20 );
statusLabel.label ("");
statusLabel.box ( FL_FLAT_BOX );
statusProgress = Fl_Progress ( 160, 430, 230, 20 );
statusProgress.box( FL_FLAT_BOX );
statusProgress.minimum(0);
statusProgress.maximum(1);
statusProgress.color ( 0xffffffff );
statusProgress.selection_color( 0x272828ff );
volUp = Fl_Button ( 600, 430, 20,20 );
volUp.label ( "+" );
volUp.box ( FL_THIN_UP_BOX );
volUp.callback ( volUpCb );
volDown = Fl_Button ( 580, 430, 20,20 );
volDown.label ( "-" );
volDown.box ( FL_THIN_UP_BOX );
volDown.callback ( volDownCb );
resizeWindow();
window.end()
window.show(1, [sys.argv[0]])