Implemented use of glimagesink
Added looping functions Removed separate quickplayer. Quickplayer is now integrated in normal player
This commit is contained in:
parent
acc3ec8f2b
commit
106a20ad33
2
.gitignore
vendored
Normal file → Executable file
2
.gitignore
vendored
Normal file → Executable file
|
@ -1,3 +1,3 @@
|
|||
build/
|
||||
deb_dist/
|
||||
*.pyc
|
||||
**/*.pyc
|
||||
|
|
0
VERSION.py
Normal file → Executable file
0
VERSION.py
Normal file → Executable file
0
debian/postinst
vendored
Normal file → Executable file
0
debian/postinst
vendored
Normal file → Executable file
6
etc/init.d/mediaserver
Normal file → Executable file
6
etc/init.d/mediaserver
Normal file → Executable file
|
@ -47,8 +47,8 @@ VERBOSE=yes
|
|||
#
|
||||
do_start()
|
||||
{
|
||||
# start background image
|
||||
fbi -a -noverbose -t 1 -T 1 -d /dev/fb0 /usr/share/mediaserver/background-image.png >/dev/null 2> /dev/null &
|
||||
# start background image (No, fbdrawer can be used for that now)
|
||||
# fbi -a -noverbose -t 1 -T 1 -d /dev/fb0 /usr/share/mediaserver/background-image.png >/dev/null 2> /dev/null &
|
||||
|
||||
# Return
|
||||
# 0 if daemon has been started
|
||||
|
@ -71,7 +71,7 @@ do_start()
|
|||
do_stop()
|
||||
{
|
||||
# kill background image (fbi)
|
||||
killall fbi
|
||||
# killall fbi
|
||||
|
||||
# Return
|
||||
# 0 if daemon has been stopped
|
||||
|
|
0
mediacore-mediaserver
Normal file → Executable file
0
mediacore-mediaserver
Normal file → Executable file
0
mediaserver/PKG_CONFIG.py
Normal file → Executable file
0
mediaserver/PKG_CONFIG.py
Normal file → Executable file
0
mediaserver/__init__.py
Normal file → Executable file
0
mediaserver/__init__.py
Normal file → Executable file
|
@ -1,68 +0,0 @@
|
|||
# perform gstreamer imports (python3 style)
|
||||
import gi
|
||||
gi.require_version('Gst','1.0')
|
||||
|
||||
from gi.repository import GObject
|
||||
|
||||
from threading import Thread
|
||||
import time
|
||||
|
||||
# import from this module
|
||||
from basicplayer import BasicPlayer
|
||||
|
||||
class MonitorThread(Thread):
|
||||
def __init__(self,player):
|
||||
self.player = player
|
||||
Thread.__init__(self)
|
||||
self.daemon = True # as in: don't wait on this thread to quit
|
||||
self._running = False
|
||||
|
||||
def stop(self):
|
||||
if self._running:
|
||||
self._running = False
|
||||
#self.join(0.5)
|
||||
|
||||
def run(self):
|
||||
self._running = True
|
||||
while self._running:
|
||||
if self.player.player_state == "PLAYING" and self.player.playtime > 0:
|
||||
position = self.player.position()
|
||||
if (position - self.player.startpos) >= self.player.playtime:
|
||||
self.player._finished()
|
||||
if self._running and time is not None:
|
||||
time.sleep(0.2)
|
||||
pass
|
||||
|
||||
class AudioPlayer(BasicPlayer):
|
||||
|
||||
def __init__(self):
|
||||
BasicPlayer.__init__(self)
|
||||
# setup monitor thread
|
||||
self.monitor = MonitorThread(self)
|
||||
self.monitor.start()
|
||||
self.playtime = -1
|
||||
|
||||
def __del__(self):
|
||||
self.monitor.stop()
|
||||
|
||||
def playfor(self,duration):
|
||||
if duration > 0: # not much point in wasting system resources otherwise
|
||||
self.startpos = self.position()
|
||||
self.playtime = duration
|
||||
# self.monitor.start()
|
||||
BasicPlayer.play(self)
|
||||
elif duration < 0: # same as normal play
|
||||
self.play()
|
||||
|
||||
def play(self):
|
||||
if self.player_state != "PAUSED":
|
||||
self.playtime = -1;
|
||||
BasicPlayer.play(self)
|
||||
|
||||
def stop(self):
|
||||
self.playtime = -1;
|
||||
BasicPlayer.stop(self)
|
||||
#self.monitor.stop()
|
||||
|
||||
GObject.type_register(AudioPlayer)
|
||||
|
11
mediaserver/basicplayer.py
Normal file → Executable file
11
mediaserver/basicplayer.py
Normal file → Executable file
|
@ -101,7 +101,6 @@ class BasicPlayer(GObject.GObject):
|
|||
self.player_state = "LOADING"
|
||||
self.tags.clear()
|
||||
|
||||
|
||||
def stop(self):
|
||||
if self.player_state in ["PLAYING","PAUSED",]:
|
||||
self._running = False
|
||||
|
@ -109,25 +108,27 @@ class BasicPlayer(GObject.GObject):
|
|||
self.player_state = "READY"
|
||||
self.emit('playback-stopped')
|
||||
|
||||
def pause(self):
|
||||
def pause(self,notify=True):
|
||||
# cannot pause/unpause if we're waiting for buffer
|
||||
if self.player_state in ["PLAYING",] and not self.buffering:
|
||||
self.player_state = "PAUSED"
|
||||
self.pipeline.set_state(Gst.State.PAUSED)
|
||||
self.emit('playback-paused')
|
||||
if notify:
|
||||
self.emit('playback-paused')
|
||||
|
||||
def _finished(self):
|
||||
self._running = False
|
||||
self.pipeline.set_state(Gst.State.READY)
|
||||
self.seek(0)
|
||||
self.player_state = "READY"
|
||||
self.player_state = "PAUSED"
|
||||
self.emit('playback-finished')
|
||||
|
||||
|
||||
def prepare_gstreamer(self):
|
||||
# bin containing the recorder stuff
|
||||
|
||||
self.pipeline = Gst.ElementFactory.make("playbin", None)
|
||||
videosink = Gst.ElementFactory.make("eglglessink", None)
|
||||
videosink = Gst.ElementFactory.make("glimagesink", None)
|
||||
alsasink = Gst.ElementFactory.make("alsasink", None)
|
||||
|
||||
# set output device
|
||||
|
|
357
mediaserver/client.py
Executable file
357
mediaserver/client.py
Executable file
|
@ -0,0 +1,357 @@
|
|||
import dbus
|
||||
import dbus.service
|
||||
import dbus.mainloop.glib
|
||||
|
||||
import dbus_smartobject
|
||||
import event
|
||||
|
||||
import __main__
|
||||
import os
|
||||
|
||||
import gi
|
||||
from gi.repository import GLib
|
||||
from gi.repository import GObject
|
||||
|
||||
class MediaClient(dbus_smartobject.DBusSmartObject):
|
||||
def __init__(self,quickfolder=None):
|
||||
|
||||
if not quickfolder is None:
|
||||
self._quickfolder = quickfolder
|
||||
else:
|
||||
self._quickfolder = os.path.dirname(__main__.__file__)
|
||||
|
||||
self.Playing = False
|
||||
self.Paused = False
|
||||
self.Stopped = True
|
||||
self.Buffering = False
|
||||
|
||||
self.status_url = None
|
||||
self.status_position = 0
|
||||
self.status_reloading = False
|
||||
|
||||
# initialize the events
|
||||
self.OnLoading = event.Event()
|
||||
self.OnReady = event.Event()
|
||||
self.OnPlaying = event.Event()
|
||||
self.OnPaused = event.Event()
|
||||
|
||||
self.OnReconnectReady = event.Event()
|
||||
self.OnReconnectPlaying = event.Event()
|
||||
self.OnReconnectPaused = event.Event()
|
||||
|
||||
self.OnStopped = event.Event()
|
||||
self.OnFinished = event.Event()
|
||||
self.OnFinishing = event.Event()
|
||||
|
||||
self.OnLoadFail = event.Event()
|
||||
self.OnRunFail = event.Event()
|
||||
|
||||
self.OnConnect = event.Event()
|
||||
self.OnReconnect = event.Event()
|
||||
self.OnDisconnect = event.Event()
|
||||
|
||||
self.OnBuffering = event.Event()
|
||||
|
||||
# init base object
|
||||
dbus_smartobject.DBusSmartObject.__init__( self,
|
||||
service='nl.miqra.MediaCore.Media',
|
||||
path='/nl/miqra/MediaCore/Media',
|
||||
interface='nl.miqra.MediaCore.Media',
|
||||
systembus=True)
|
||||
|
||||
self.statusticker()
|
||||
|
||||
def init_busobject(self,busobject):
|
||||
# this is what gives us the multi media keys.
|
||||
|
||||
# connect_to_signal registers our callback function.
|
||||
busobject.connect_to_signal('OnLoading', self._onLoading)
|
||||
|
||||
# connect_to_signal registers our callback function.
|
||||
busobject.connect_to_signal('OnReady', self._onReady)
|
||||
|
||||
# connect_to_signal registers our callback function.
|
||||
busobject.connect_to_signal('OnPlaying', self._onPlaying)
|
||||
|
||||
# connect_to_signal registers our callback function.
|
||||
busobject.connect_to_signal('OnPaused', self._onPaused)
|
||||
|
||||
# connect_to_signal registers our callback function.
|
||||
busobject.connect_to_signal('OnStopped', self._onStopped)
|
||||
|
||||
# connect_to_signal registers our callback function.
|
||||
busobject.connect_to_signal('OnFinished', self._onFinished)
|
||||
|
||||
# connect_to_signal registers our callback function.
|
||||
busobject.connect_to_signal('OnFinishing', self._onFinishing)
|
||||
|
||||
# connect_to_signal registers our callback function.
|
||||
busobject.connect_to_signal('OnLoadFail', self._onLoadFail)
|
||||
|
||||
# connect_to_signal registers our callback function.
|
||||
busobject.connect_to_signal('OnRunFail', self._onRunFail)
|
||||
|
||||
# connect_to_signal registers our callback function.
|
||||
busobject.connect_to_signal('OnBuffering', self._onBuffering)
|
||||
|
||||
def on_connection_lost(self):
|
||||
self.OnDisconnect()
|
||||
|
||||
def on_connection_made(self):
|
||||
self.OnConnect()
|
||||
|
||||
def on_connection_regained(self):
|
||||
if self.status_url is not None:
|
||||
self.status_reloading = True
|
||||
self.LoadUrl(self.status_url)
|
||||
|
||||
def statusticker(self):
|
||||
if self.connected():
|
||||
if not self.status_reloading and (self.Playing or self.Paused):
|
||||
self.status_position = self.Position()
|
||||
#print "backed up position: {0}".format(self.status_position)
|
||||
|
||||
GObject.timeout_add(1000, self.statusticker);
|
||||
|
||||
#callback function
|
||||
def _onLoading(self,url):
|
||||
""" gets called when a source has been requested for playback
|
||||
"""
|
||||
self.OnLoading(url)
|
||||
|
||||
def _onBuffering(self,pct):
|
||||
""" gets called when a source has been requested for playback
|
||||
"""
|
||||
if pct < 100:
|
||||
self.Buffering = True
|
||||
else:
|
||||
self.Buffering = False
|
||||
self.OnBuffering(pct)
|
||||
|
||||
def _onReady(self,url,tags):
|
||||
""" gets called when a source is ready for playback
|
||||
"""
|
||||
if not self.status_reloading:
|
||||
self.Playing = False
|
||||
self.Paused = False
|
||||
self.Stopped = True
|
||||
self.status_url = url
|
||||
self.OnReady(url,tags)
|
||||
else:
|
||||
if self.Playing or self.Paused:
|
||||
self.Play()
|
||||
else:
|
||||
self.status_reloading = False
|
||||
self.OnReconnectReady()
|
||||
|
||||
def _onPlaying(self):
|
||||
""" gets called when a playback has started
|
||||
"""
|
||||
if not self.status_reloading:
|
||||
self.Playing = True
|
||||
self.Paused = False
|
||||
self.Stopped = False
|
||||
self.OnPlaying()
|
||||
else:
|
||||
self.Seek(self.status_position)
|
||||
if self.Paused:
|
||||
self.Pause()
|
||||
else:
|
||||
self.status_reloading = False
|
||||
self.OnReconnectPlaying()
|
||||
pass
|
||||
|
||||
def _onPaused(self):
|
||||
""" gets called when a playback is paused
|
||||
"""
|
||||
if not self.status_reloading:
|
||||
self.Playing = False
|
||||
self.Paused = True
|
||||
self.Stopped = False
|
||||
self.OnPaused()
|
||||
else:
|
||||
self.status_reloading = False
|
||||
self.OnReconnectPaused()
|
||||
|
||||
|
||||
def _onStopped(self):
|
||||
""" gets called when playback has stopped
|
||||
"""
|
||||
self.Playing = False
|
||||
self.Paused = False
|
||||
self.Stopped = True
|
||||
self.status_position = 0
|
||||
self.OnStopped()
|
||||
|
||||
def _onFinished(self):
|
||||
""" gets called when playback has completed
|
||||
"""
|
||||
self.Playing = False
|
||||
self.Paused = False
|
||||
self.Stopped = True
|
||||
self.status_position = 0
|
||||
self.OnFinished()
|
||||
|
||||
def _onFinishing(self):
|
||||
self.OnFinishing()
|
||||
|
||||
def _onLoadFail(self,reason):
|
||||
""" gets called when loading a source for playback fails
|
||||
"""
|
||||
self.OnLoadFail(reason)
|
||||
|
||||
def _onRunFail(self,reason):
|
||||
""" gets called when playback fails
|
||||
"""
|
||||
self.OnRunFail(reason)
|
||||
|
||||
def QuickPlay(self, file, duration = None):
|
||||
""" Directly play back a local file
|
||||
"""
|
||||
path = file
|
||||
# check if the file exists, if not, try to find it in the base folder for quickplay or else as a subfolder of the __main__ folder
|
||||
if not os.path.isfile(path):
|
||||
path = os.path.join(self._quickfolder,file)
|
||||
|
||||
if not os.path.isfile(path):
|
||||
path = os.path.join(os.path.dirname(__main__.__file__),file)
|
||||
|
||||
try:
|
||||
if duration is None or duration <= 0:
|
||||
self.call("QuickPlay",file)
|
||||
else:
|
||||
self.call("QuickPlayFor",file,duration)
|
||||
except dbus_smartobject.NoConnectionError as x:
|
||||
print "Could not call QuickPlay function because of no connection"
|
||||
pass
|
||||
|
||||
def QuickPlayUrl(self, url, duration = None):
|
||||
""" Directly play back a URL
|
||||
"""
|
||||
try:
|
||||
if duration is None or duration <= 0:
|
||||
self.call("QuickPlayUrl",url)
|
||||
else:
|
||||
self.call("QuickPlayUrlFor",url,duration)
|
||||
except dbus_smartobject.NoConnectionError as x:
|
||||
print "Could not call QuickPlayUrl function because of no connection"
|
||||
pass
|
||||
|
||||
def QuickLoop(self, file):
|
||||
""" Directly play back a local file
|
||||
"""
|
||||
path = file
|
||||
# check if the file exists, if not, try to find it in the base folder for quickplay or else as a subfolder of the __main__ folder
|
||||
if not os.path.isfile(path):
|
||||
path = os.path.join(self._quickfolder,file)
|
||||
|
||||
if not os.path.isfile(path):
|
||||
path = os.path.join(os.path.dirname(__main__.__file__),file)
|
||||
|
||||
try:
|
||||
self.call("QuickLoop",file)
|
||||
except dbus_smartobject.NoConnectionError as x:
|
||||
print "Could not call QuickPlay function because of no connection"
|
||||
pass
|
||||
|
||||
def QuickLoopUrl(self, url):
|
||||
""" Directly play back a URL
|
||||
"""
|
||||
try:
|
||||
self.call("QuickLoopUrl",url)
|
||||
except dbus_smartobject.NoConnectionError as x:
|
||||
print "Could not call QuickPlayUrl function because of no connection"
|
||||
pass
|
||||
|
||||
def LoadFile(self, file):
|
||||
""" Load a local file for playback
|
||||
"""
|
||||
try:
|
||||
self.call("LoadFile",file)
|
||||
except dbus_smartobject.NoConnectionError as x:
|
||||
print "Could not call LoadFile because of no connection"
|
||||
pass
|
||||
|
||||
def LoadUrl(self, url):
|
||||
""" Load an url for playback
|
||||
"""
|
||||
try:
|
||||
self.call("LoadUrl",url)
|
||||
except dbus_smartobject.NoConnectionError as x:
|
||||
print "Could not call LoadUrl because of no connection"
|
||||
pass
|
||||
|
||||
def PlayFor(self, duration):
|
||||
""" Starts playback for [duration] seconds
|
||||
"""
|
||||
try:
|
||||
self.call("PlayFor",duration)
|
||||
except dbus_smartobject.NoConnectionError as x:
|
||||
print "Could not call PlayFor because of no connection"
|
||||
pass
|
||||
|
||||
def Play(self):
|
||||
""" Starts/resumes playback
|
||||
"""
|
||||
try:
|
||||
self.call("Play")
|
||||
except dbus_smartobject.NoConnectionError as x:
|
||||
print "Could not call Play because of no connection"
|
||||
pass
|
||||
|
||||
def Loop(self):
|
||||
""" Starts/resumes playback
|
||||
"""
|
||||
try:
|
||||
self.call("Loop")
|
||||
except dbus_smartobject.NoConnectionError as x:
|
||||
print "Could not call Loop because of no connection"
|
||||
pass
|
||||
|
||||
def Pause(self):
|
||||
""" Pauses playback
|
||||
"""
|
||||
try:
|
||||
self.call("Pause")
|
||||
except dbus_smartobject.NoConnectionError as x:
|
||||
print "Could not call Pause because of no connection"
|
||||
pass
|
||||
|
||||
def Stop(self):
|
||||
""" Stops playback
|
||||
"""
|
||||
try:
|
||||
self.call("Stop")
|
||||
except dbus_smartobject.NoConnectionError as x:
|
||||
print "Could not call Stop because of no connection"
|
||||
pass
|
||||
|
||||
def Length(self):
|
||||
""" returns length of currently loaded source
|
||||
"""
|
||||
try:
|
||||
return self.call("Length")
|
||||
except dbus_smartobject.NoConnectionError as x:
|
||||
print "Could not call Length because of no connection"
|
||||
return 0
|
||||
|
||||
def Position(self):
|
||||
""" returns current position in the source
|
||||
"""
|
||||
try:
|
||||
return self.call("Position")
|
||||
except dbus_smartobject.NoConnectionError as x:
|
||||
print "Could not call Position because of no connection"
|
||||
return 0
|
||||
|
||||
def Seek(self,position):
|
||||
""" jump to new position in the source
|
||||
"""
|
||||
try:
|
||||
self.call("Seek",position)
|
||||
self.status_position = position
|
||||
|
||||
except dbus_smartobject.NoConnectionError as x:
|
||||
print "Could not call because of no connection"
|
||||
pass
|
||||
|
144
mediaserver/dbus_smartobject.py
Executable file
144
mediaserver/dbus_smartobject.py
Executable file
|
@ -0,0 +1,144 @@
|
|||
import dbus
|
||||
import dbus.service
|
||||
import dbus.mainloop.glib
|
||||
import event
|
||||
|
||||
class NoConnectionError(Exception):
|
||||
pass
|
||||
|
||||
class DBusSmartObject:
|
||||
def __init__(self,service,path,interface,systembus=False):
|
||||
# store service name and object path
|
||||
self._service = service
|
||||
self._object_path = path
|
||||
self._interface = interface
|
||||
|
||||
if systembus == True:
|
||||
self._bus_type = dbus.Bus.TYPE_SYSTEM
|
||||
else:
|
||||
self._bus_type = dbus.Bus.TYPE_SESSION
|
||||
|
||||
# prepare flex object
|
||||
self._bus = None
|
||||
self.busobject = None
|
||||
self._beenconnected = False
|
||||
|
||||
# set up the glib main loop.
|
||||
dbus.mainloop.glib.DBusGMainLoop(set_as_default=True)
|
||||
|
||||
# connect to the dbus object to get information about existing connections
|
||||
self._dbus = dbus.Bus(dbus.Bus.TYPE_SYSTEM)
|
||||
self._dbus_object = self._dbus.get_object('org.freedesktop.DBus', '/org/freedesktop/DBus')
|
||||
|
||||
# this is what gives us the multi media keys.
|
||||
self._dbus_interface='org.freedesktop.DBus'
|
||||
|
||||
# connect_to_signal registers our callback function.
|
||||
self._dbus_object.connect_to_signal('NameOwnerChanged', self._onNameOwnerChanged)
|
||||
|
||||
# start initializing the connection
|
||||
self._initialize_new_connection()
|
||||
|
||||
def close(self):
|
||||
if self._bus is not None:
|
||||
self._bus = None
|
||||
self.busobject = None
|
||||
|
||||
if self._dbus is not None:
|
||||
self._dbus = None
|
||||
|
||||
def init_busobject(self,busobject):
|
||||
''' Override in child class to initialize bus signals on connect and reconnect
|
||||
'''
|
||||
pass
|
||||
|
||||
def on_connection_lost(self):
|
||||
''' Override in child class to handle connection lost
|
||||
'''
|
||||
pass
|
||||
|
||||
def on_connection_made(self):
|
||||
''' Override in child class to handle connection made
|
||||
'''
|
||||
pass
|
||||
|
||||
def on_connection_regained(self):
|
||||
''' Override in child class to handle connection regained
|
||||
'''
|
||||
pass
|
||||
|
||||
def _initialize_new_connection(self):
|
||||
# test if service is available on the selected bus. Skip otherwise
|
||||
if self._dbus_object.NameHasOwner(self._service, dbus_interface=self._dbus_interface):
|
||||
print "Initializing new connection to {0}".format(self._service)
|
||||
|
||||
self._bus = dbus.Bus(self._bus_type)
|
||||
self.busobject = self._bus.get_object(self._service, self._object_path)
|
||||
self.init_busobject(self.busobject)
|
||||
self.on_connection_made()
|
||||
|
||||
if self._beenconnected == True:
|
||||
self.on_connection_regained()
|
||||
else:
|
||||
self._beenconnected = True
|
||||
else:
|
||||
print "Could not create connection to {0}".format(self._service)
|
||||
# bus object is not available - so disconnect the bus
|
||||
|
||||
if self._bus is not None:
|
||||
self._bus = None
|
||||
self.busobject = None
|
||||
|
||||
def _close_existing_connection(self):
|
||||
if self._bus is not None:
|
||||
print "Lost connection to {0}".format(self._service)
|
||||
#self._bus.close()
|
||||
self._bus = None
|
||||
self.busobject = None
|
||||
self.on_connection_lost()
|
||||
|
||||
def _onNameOwnerChanged(self,name,old_adr,new_adr):
|
||||
''' Detects changes in service availablility
|
||||
'''
|
||||
if name == self._service:
|
||||
if old_adr == "": # Service just became available
|
||||
self._initialize_new_connection()
|
||||
elif new_adr == "": # Service just became unavailable
|
||||
self._close_existing_connection()
|
||||
else: # service changed address
|
||||
self._initialize_new_connection()
|
||||
|
||||
def call(self,method, *args, **kwargs):
|
||||
if kwargs.has_key("interface"):
|
||||
interface = kwargs["interface"]
|
||||
else:
|
||||
interface = self._interface
|
||||
|
||||
if self.busobject is not None:
|
||||
#print "Attempting to call {0}".format(method)
|
||||
method = self.busobject.get_dbus_method(method,dbus_interface=interface)
|
||||
|
||||
#print "Got method - calling with arguments: {0}".format(args)
|
||||
return method(*args)
|
||||
else:
|
||||
raise NoConnectionError("Currently no connection to service {0}".format(self._service))
|
||||
|
||||
def trycall(self,method, *args, **kwargs):
|
||||
# see if we have an default return value in case of error
|
||||
if 'default' in kwargs:
|
||||
default = kwargs['default']
|
||||
del kwargs['default']
|
||||
else:
|
||||
default = None
|
||||
try:
|
||||
return self.call(method, *args, **kwargs)
|
||||
except NoConnectionError as x:
|
||||
print "Could not call {0} because there is currently no connection to {1}".format(method,self._service)
|
||||
return default
|
||||
|
||||
def connected(self):
|
||||
if self.busobject is not None:
|
||||
return True
|
||||
else:
|
||||
return False
|
||||
|
0
mediaserver/event.py
Normal file → Executable file
0
mediaserver/event.py
Normal file → Executable file
123
mediaserver/mediaserver.py
Normal file → Executable file
123
mediaserver/mediaserver.py
Normal file → Executable file
|
@ -26,7 +26,7 @@ from dbus.mainloop.glib import DBusGMainLoop
|
|||
DBusGMainLoop(set_as_default=True)
|
||||
|
||||
# imports from module
|
||||
from audioplayer import AudioPlayer
|
||||
from monitoredplayer import MonitoredPlayer
|
||||
from quickplayer import QuickPlayer
|
||||
|
||||
|
||||
|
@ -36,7 +36,7 @@ class MediaService(dbus.service.Object):
|
|||
bus_name = dbus.service.BusName('nl.miqra.MediaCore.Media', bus=dbus.SystemBus())
|
||||
dbus.service.Object.__init__(self, bus_name, '/nl/miqra/MediaCore/Media')
|
||||
|
||||
self.player = AudioPlayer()
|
||||
self.player = MonitoredPlayer()
|
||||
self.quickplayer = QuickPlayer()
|
||||
|
||||
self.player.connect('playback-ready',self.onPlayerReady) # parameters: source_file tag_dict
|
||||
|
@ -51,29 +51,102 @@ class MediaService(dbus.service.Object):
|
|||
self.loadcount = 0;
|
||||
self.loadmax = 1;
|
||||
|
||||
self.quickplay = False
|
||||
self.quickplayduration = 0
|
||||
self.quickplayloop = False
|
||||
|
||||
self.tick()
|
||||
|
||||
# Keepalive timer to help react to Keyboard interrupts
|
||||
def tick(self):
|
||||
GObject.timeout_add(100, self.tick)
|
||||
|
||||
@dbus.service.method(dbus_interface='nl.miqra.MediaCore.Media', in_signature='s', out_signature='')
|
||||
def QuickPlay(self, file,):
|
||||
""" Directly play back a local file
|
||||
"""
|
||||
self.quickplayer.play(file)
|
||||
if self.loadcount < self.loadmax:
|
||||
print "Quickplaying file {0}".format(file)
|
||||
self.quickplay = True
|
||||
self.quickplayduration = 0
|
||||
self.quickplayloop = False
|
||||
self.player.load(file)
|
||||
self.loadcount += 1;
|
||||
else:
|
||||
print "Skipping load of file {0} because maximum simultaneous loads ({1}) was reached. Wait until ready....".format(file,self.loadmax);
|
||||
|
||||
@dbus.service.method(dbus_interface='nl.miqra.MediaCore.Media', in_signature='sd', out_signature='')
|
||||
def QuickPlayFor(self, file, duration):
|
||||
""" Directly play back a local file
|
||||
"""
|
||||
self.quickplayer.playfor(file,duration)
|
||||
if self.loadcount < self.loadmax:
|
||||
print "Quickplaying file {0} for {1} seconds".format(file,duration)
|
||||
self.quickplay = True
|
||||
self.quickplayduration = duration
|
||||
self.quickplayloop = False
|
||||
self.player.load(file)
|
||||
self.loadcount += 1;
|
||||
else:
|
||||
print "Skipping load of file {0} because maximum simultaneous loads ({1}) was reached. Wait until ready....".format(file,self.loadmax);
|
||||
# self.quickplayer.playfor(file,duration)
|
||||
|
||||
@dbus.service.method(dbus_interface='nl.miqra.MediaCore.Media', in_signature='s', out_signature='')
|
||||
def QuickPlayUrl(self, url,):
|
||||
""" Directly play back a url
|
||||
"""
|
||||
self.quickplayer.playurl(url)
|
||||
if self.loadcount < self.loadmax:
|
||||
print "Quickplaying file {0}".format(file)
|
||||
self.quickplay = True
|
||||
self.quickplayduration = 0
|
||||
self.quickplayloop = False
|
||||
self.player.load_uri(file)
|
||||
self.loadcount += 1;
|
||||
else:
|
||||
print "Skipping load of file {0} because maximum simultaneous loads ({1}) was reached. Wait until ready....".format(file,self.loadmax);
|
||||
|
||||
@dbus.service.method(dbus_interface='nl.miqra.MediaCore.Media', in_signature='sd', out_signature='')
|
||||
def QuickPlayUrlFor(self, url, duration):
|
||||
""" Directly play back a url
|
||||
"""
|
||||
self.quickplayer.playurlfor(url,duration)
|
||||
if self.loadcount < self.loadmax:
|
||||
print "Quickplaying file {0} for {1} seconds".format(file,duration)
|
||||
self.quickplay = True
|
||||
self.quickplayduration = duration
|
||||
self.quickplayloop = False
|
||||
self.player.load_uri(file)
|
||||
self.loadcount += 1;
|
||||
else:
|
||||
print "Skipping load of file {0} because maximum simultaneous loads ({1}) was reached. Wait until ready....".format(file,self.loadmax);
|
||||
|
||||
@dbus.service.method(dbus_interface='nl.miqra.MediaCore.Media', in_signature='s', out_signature='')
|
||||
def QuickLoop(self, file,):
|
||||
""" Directly play back a url
|
||||
"""
|
||||
if self.loadcount < self.loadmax:
|
||||
print "Quickplaying file {0}".format(file)
|
||||
self.quickplay = True
|
||||
self.quickplayduration = 0
|
||||
self.quickplayloop = True
|
||||
self.player.load(file)
|
||||
self.loadcount += 1;
|
||||
else:
|
||||
print "Skipping load of file {0} because maximum simultaneous loads ({1}) was reached. Wait until ready....".format(file,self.loadmax);
|
||||
|
||||
@dbus.service.method(dbus_interface='nl.miqra.MediaCore.Media', in_signature='s', out_signature='')
|
||||
def QuickLoopUrl(self, url,):
|
||||
""" Directly play back a url
|
||||
"""
|
||||
if self.loadcount < self.loadmax:
|
||||
print "Quickplaying url {0}".format(uri)
|
||||
self.quickplay = True
|
||||
self.quickplayduration = 0
|
||||
self.quickplayloop = True
|
||||
self.player.load_uri(url)
|
||||
self.loadcount += 1;
|
||||
else:
|
||||
print "Skipping load of file {0} because maximum simultaneous loads ({1}) was reached. Wait until ready....".format(file,self.loadmax);
|
||||
|
||||
|
||||
|
||||
|
||||
@dbus.service.method(dbus_interface='nl.miqra.MediaCore.Media', in_signature='s', out_signature='')
|
||||
|
@ -82,7 +155,7 @@ class MediaService(dbus.service.Object):
|
|||
"""
|
||||
if self.loadcount < self.loadmax:
|
||||
print "Loading file {0}".format(file)
|
||||
print file
|
||||
self.quickplay = False
|
||||
self.player.load(file)
|
||||
self.loadcount += 1;
|
||||
self.OnLoading("file://{0}".format(file))
|
||||
|
@ -95,6 +168,7 @@ class MediaService(dbus.service.Object):
|
|||
"""
|
||||
if self.loadcount < self.loadmax:
|
||||
print "Loading url {0}".format(uri)
|
||||
self.quickplay = False
|
||||
self.player.load_uri(uri)
|
||||
self.loadcount += 1;
|
||||
self.OnLoading(uri)
|
||||
|
@ -116,6 +190,14 @@ class MediaService(dbus.service.Object):
|
|||
print "Starting playback at timestamp {0}".format(pos)
|
||||
self.player.play()
|
||||
|
||||
@dbus.service.method(dbus_interface='nl.miqra.MediaCore.Media', in_signature='', out_signature='')
|
||||
def Loop(self):
|
||||
""" Starts/resumes playback
|
||||
"""
|
||||
pos = self.player.position()
|
||||
print "Starting playback at timestamp {0}".format(pos)
|
||||
self.player.loop()
|
||||
|
||||
@dbus.service.method(dbus_interface='nl.miqra.MediaCore.Media', in_signature='', out_signature='')
|
||||
def Pause(self):
|
||||
""" Pauses playback
|
||||
|
@ -163,8 +245,19 @@ class MediaService(dbus.service.Object):
|
|||
# reset load counter
|
||||
self.loadcount = 0;
|
||||
|
||||
# signal ready
|
||||
self.OnReady(filename,taglist)
|
||||
if self.quickplay:
|
||||
if self.quickplayloop:
|
||||
print("Direct looping")
|
||||
self.player.loop()
|
||||
elif self.quickplayduration > 0:
|
||||
print("Direct playing for {0} s".format(self.quickplayduration))
|
||||
self.player.playfor(self.quickplayduration)
|
||||
else:
|
||||
print("Direct playing")
|
||||
self.player.play()
|
||||
else:
|
||||
# signal ready
|
||||
self.OnReady(filename,taglist)
|
||||
|
||||
def onPlayerPlaying(self,player):
|
||||
self.OnPlaying()
|
||||
|
@ -238,6 +331,12 @@ class MediaService(dbus.service.Object):
|
|||
"""
|
||||
pass
|
||||
|
||||
@dbus.service.signal(dbus_interface='nl.miqra.MediaCore.Media', signature='')
|
||||
def OnFinishing(self):
|
||||
""" gets called when playback is nearly completed
|
||||
"""
|
||||
pass
|
||||
|
||||
@dbus.service.signal(dbus_interface='nl.miqra.MediaCore.Media', signature='s')
|
||||
def OnLoadFail(self,reason):
|
||||
""" gets called when loading a source for playback fails
|
||||
|
@ -262,4 +361,8 @@ def Run():
|
|||
signal.signal(signal.SIGINT, onsigint)
|
||||
|
||||
print "Starting..."
|
||||
loop.run()
|
||||
try:
|
||||
loop.run()
|
||||
except KeyboardInterrupt:
|
||||
print "Quitting"
|
||||
loop.quit()
|
102
mediaserver/monitoredplayer.py
Executable file
102
mediaserver/monitoredplayer.py
Executable file
|
@ -0,0 +1,102 @@
|
|||
# perform gstreamer imports (python3 style)
|
||||
import gi
|
||||
gi.require_version('Gst','1.0')
|
||||
|
||||
from gi.repository import GObject
|
||||
|
||||
from threading import Thread
|
||||
import time
|
||||
|
||||
# import from this module
|
||||
from basicplayer import BasicPlayer
|
||||
|
||||
class MonitorThread:#(Thread):
|
||||
def __init__(self,player):
|
||||
self.player = player
|
||||
#Thread.__init__(self)
|
||||
self.daemon = True # as in: don't wait on this thread to quit
|
||||
self._running = False
|
||||
|
||||
def stop(self):
|
||||
if self._running:
|
||||
self._running = False
|
||||
#self.join(0.5)
|
||||
|
||||
def start(self):
|
||||
self._running = True
|
||||
self.run()
|
||||
|
||||
def run(self):
|
||||
if self.player.player_state == "PLAYING":
|
||||
position = self.player.position()
|
||||
duration = self.player.duration()
|
||||
if position < 0: # handle invalid operation
|
||||
position = duration
|
||||
|
||||
print("\rTime Left: {0}".format(duration - position))
|
||||
|
||||
# handle finishing of limited playtime
|
||||
if self.player.playtime > 0:
|
||||
if (position - self.player.startpos) - self.player.playtime <= 0:
|
||||
#self._player.pause(notify=False)
|
||||
print "Finished limited play"
|
||||
self.player._finished()
|
||||
|
||||
if self._running and time is not None:
|
||||
GObject.timeout_add(20, self.run)
|
||||
|
||||
class MonitoredPlayer(BasicPlayer):
|
||||
def __init__(self):
|
||||
BasicPlayer.__init__(self)
|
||||
# setup monitor thread
|
||||
self.monitor = MonitorThread(self)
|
||||
self.monitor.start()
|
||||
self.playtime = -1
|
||||
self.looping=False
|
||||
|
||||
def __del__(self):
|
||||
self.monitor.stop()
|
||||
|
||||
def playfor(self,duration,loop=False):
|
||||
loop = False
|
||||
if duration > 0: # not much point in wasting system resources otherwise
|
||||
self.startpos = self.position()
|
||||
self.playtime = duration
|
||||
BasicPlayer.play(self)
|
||||
elif duration < 0: # same as normal play
|
||||
self.play()
|
||||
|
||||
def loop(self):
|
||||
self.looping = True
|
||||
if self.player_state != "PAUSED":
|
||||
self.startpos = 0
|
||||
self.playtime = -1;
|
||||
BasicPlayer.play(self)
|
||||
|
||||
|
||||
def play(self):
|
||||
self.looping = False
|
||||
if self.player_state != "PAUSED":
|
||||
self.startpos = 0
|
||||
self.playtime = -1;
|
||||
BasicPlayer.play(self)
|
||||
|
||||
def stop(self):
|
||||
self.playtime = -1;
|
||||
BasicPlayer.stop(self)
|
||||
#self.monitor.stop()
|
||||
|
||||
|
||||
def _finished(self):
|
||||
if self.looping:
|
||||
print("Finished - looping")
|
||||
self.seek(0)
|
||||
if self.player_state in ["READY","PAUSED",]:
|
||||
self.player_state = "PLAYING"
|
||||
self.pipeline.set_state(Gst.State.PLAYING)
|
||||
else:
|
||||
BasicPlayer._finished(self)
|
||||
|
||||
|
||||
GObject.type_register(MonitoredPlayer)
|
||||
|
4
mediaserver/quickplayer.py
Normal file → Executable file
4
mediaserver/quickplayer.py
Normal file → Executable file
|
@ -5,13 +5,13 @@ gi.require_version('Gst','1.0')
|
|||
from gi.repository import GObject
|
||||
|
||||
# import from this module
|
||||
from audioplayer import AudioPlayer
|
||||
from monitoredplayer import MonitoredPlayer
|
||||
|
||||
class QuickPlayer(GObject.GObject):
|
||||
|
||||
def __init__(self):
|
||||
GObject.GObject.__init__(self)
|
||||
self.player = AudioPlayer()
|
||||
self.player = MonitoredPlayer()
|
||||
self._duration = -1;
|
||||
self.player.connect("playback-ready",self.onReady)
|
||||
self.player.connect("playback-error",self.onError)
|
||||
|
|
2
stdeb.cfg
Normal file → Executable file
2
stdeb.cfg
Normal file → Executable file
|
@ -1,6 +1,6 @@
|
|||
|
||||
[DEFAULT]
|
||||
Depends: python-dbus, python-gi, fbi, gir1.2-gstreamer-1.0, gir1.2-gst-plugins-base-1.0, gstreamer1.0-plugins-good, gstreamer1.0-plugins-ugly, gstreamer1.0-plugins-bad, gstreamer1.0-alsa, gstreamer1.0-omx, gstreamer1.0-libav
|
||||
Depends: python-dbus, python-gi, gir1.2-gstreamer-1.0, gir1.2-gst-plugins-base-1.0, gstreamer1.0-plugins-good, gstreamer1.0-plugins-ugly, gstreamer1.0-plugins-bad, gstreamer1.0-alsa, gstreamer1.0-omx, gstreamer1.0-libav
|
||||
XS-Python-Version: >= 2.6
|
||||
Section: sound
|
||||
Package: mediaserver
|
||||
|
|
15
test_basicplayer.py
Normal file → Executable file
15
test_basicplayer.py
Normal file → Executable file
|
@ -3,7 +3,7 @@
|
|||
from mediaserver.audioplayer import AudioPlayer
|
||||
from mediaserver.quickplayer import QuickPlayer
|
||||
from gi.repository import GObject
|
||||
|
||||
import sys
|
||||
|
||||
def onReady(player, file, tags):
|
||||
print "Starting {0} ...\n".format(file)
|
||||
|
@ -29,13 +29,14 @@ def onStop(player):
|
|||
print "Quitting...."
|
||||
loop.quit()
|
||||
|
||||
player = AudioPlayer()
|
||||
player.connect("playback-ready",onReady)
|
||||
player.connect("playback-playing",onPlaying)
|
||||
player.connect("playback-finished",onStop)
|
||||
player.connect("playback-stopped",onStop)
|
||||
player = QuickPlayer()
|
||||
#player.connect("playback-ready",onReady)
|
||||
#player.connect("playback-playing",onPlaying)
|
||||
#player.connect("playback-finished",onStop)
|
||||
#player.connect("playback-stopped",onStop)
|
||||
|
||||
player.load("/opt/mediacore/mediaserver2/snnw_E_138.mp3")
|
||||
#print "Attempting to play {0}".format(sys.argv[1])
|
||||
player.play(sys.argv[1])
|
||||
|
||||
|
||||
|
||||
|
|
90
test_client.py
Executable file
90
test_client.py
Executable file
|
@ -0,0 +1,90 @@
|
|||
#!/usr/bin/python
|
||||
|
||||
from mediaserver.client import MediaClient
|
||||
|
||||
#!/usr/bin/env python
|
||||
import sys, os, glob
|
||||
import signal
|
||||
|
||||
import gi
|
||||
from gi.repository import GLib
|
||||
from gi.repository import GObject
|
||||
|
||||
|
||||
#import Resources
|
||||
|
||||
class TestController:
|
||||
def __init__(self):
|
||||
#initialize loop
|
||||
self.mainloop = GLib.MainLoop() # main loop
|
||||
#initialize sensing
|
||||
self.player = MediaClient()
|
||||
self.player.OnPlaying += self.onPlayerPlaying
|
||||
self.player.OnStopped += self.onPlayerStopped
|
||||
self.player.OnPaused += self.onPlayerPaused
|
||||
self.player.OnFinished += self.onPlayerFinished
|
||||
self.player.OnFinishing += self.onPlayerFinishing
|
||||
self.player.OnLoading += self.onPlayerLoading
|
||||
self.player.OnReady += self.onPlayerReady
|
||||
|
||||
GObject.timeout_add(10, self.tick)
|
||||
|
||||
def tick(self):
|
||||
self.player.QuickLoop("/opt/src/robotvideo/ogen open.mp4")
|
||||
#GObject.timeout_add(3000, self.reboot)
|
||||
pass
|
||||
|
||||
def onStarting(self):
|
||||
pass
|
||||
|
||||
def onStopped(self):
|
||||
pass
|
||||
|
||||
def onPlayerPlaying(self):
|
||||
pass
|
||||
|
||||
def onPlayerStopped(self):
|
||||
pass
|
||||
|
||||
def onPlayerPaused(self):
|
||||
pass
|
||||
|
||||
def onPlayerFinished(self):
|
||||
pass
|
||||
|
||||
def onPlayerFinishing(self):
|
||||
pass
|
||||
|
||||
def onPlayerLoading(self, uri):
|
||||
pass
|
||||
|
||||
def onPlayerReady(self,url,tags):
|
||||
print('Trigger Ready')
|
||||
pass
|
||||
|
||||
def Start(self):
|
||||
print("Starting Mainloop")
|
||||
# initia
|
||||
self.onStarting()
|
||||
try:
|
||||
self.mainloop.run()
|
||||
except KeyboardInterrupt:
|
||||
self.Stop()
|
||||
|
||||
def Stop(self):
|
||||
print("Stopping controller")
|
||||
self.player.Stop()
|
||||
self.mainloop.quit()
|
||||
self.onStopped()
|
||||
|
||||
|
||||
# Sigterm Callback function
|
||||
def signalSIGTERM(self,signum):
|
||||
controller.Stop()
|
||||
|
||||
signal.signal(signal.SIGTERM, signalSIGTERM)
|
||||
|
||||
controller = TestController()
|
||||
controller.Start();
|
||||
|
||||
|
0
usr-share-mediaserver/background-image.png
Normal file → Executable file
0
usr-share-mediaserver/background-image.png
Normal file → Executable file
Before Width: | Height: | Size: 74 KiB After Width: | Height: | Size: 74 KiB |
0
usr-share-mediaserver/background-image.svg
Normal file → Executable file
0
usr-share-mediaserver/background-image.svg
Normal file → Executable file
Before Width: | Height: | Size: 15 KiB After Width: | Height: | Size: 15 KiB |
Loading…
Reference in New Issue
Block a user