diff --git a/mediacore-mediaserver b/mediacore-mediaserver
index 188a82e..2b047f6 100755
--- a/mediacore-mediaserver
+++ b/mediacore-mediaserver
@@ -1,4 +1,4 @@
-#!/usr/bin/python
+#!/usr/bin/python3
import mediaserver.mediaserver
mediaserver.mediaserver.Run()
\ No newline at end of file
diff --git a/mediaserver/PKG_CONFIG.py b/mediaserver/PKG_CONFIG.py
deleted file mode 100755
index 188b90e..0000000
--- a/mediaserver/PKG_CONFIG.py
+++ /dev/null
@@ -1,51 +0,0 @@
-# shared package configuration settings for applications in KHMedia
-##### Common #####
-
-# folder to store user specific configuration
-user_cfg_folder = "~/.khmedia"
-
-# khmedia config file
-config_file = "khmedia_config.xml"
-
-# khmedia example config resource
-example_config_resource = "khmedia_config.example.xml"
-
-# location of the khsystem_need_config file
-khsystem_need_config = "~/.khsystem_config_needed"
-
-##### Player #####
-
-#default folders to look for song files (last in line is the fallback folder that will be created if none are existing)
-default_song_folders = ["/usr/share/khmedia/songs","/usr/local/share/khmedia/songs","~/Songs"]
-
-#default folders to look for background music files (last in line is the fallback folder that will be created if none are existing)
-default_music_folders = ["/usr/share/khmedia/music","/usr/local/share/khmedia/music","~/Music"]
-
-# files that are considered playable music files
-music_extensions = [".mp3",".wav",".ogg",".m4b",".m4a"]
-
-# default volume for song playback (Linear 0.0 <= value <= 1.0 )
-default_song_volume = 0.5
-
-# default volume for music playback (Linear 0.0 <= value <= 1.0 )
-default_music_volume = 0.12
-
-##### Recorder #####
-
-#default folder to store recordings
-# You can use the following replacements
-# {XDG_DESKTOP_DIR}
-# {XDG_DOWNLOAD_DIR}
-# {XDG_TEMPLATES_DIR}
-# {XDG_PUBLICSHARE_DIR}
-# {XDG_DOCUMENTS_DIR}
-# {XDG_MUSIC_DIR}
-# {XDG_PICTURES_DIR}
-# {XDG_VIDEOS_DIR}
-
-# lowercase text between brackets is replaced by the corresponding text in the
-# currently loaded translation table
-# e.g. {something} can be replaced by "Something" or "Iets" if that is defined in the
-# translation tabled
-default_recordings_folder = "{XDG_DESKTOP_DIR}/{dir_recordings}"
-
diff --git a/mediaserver/__init__.py b/mediaserver/__init__.py
index aee403e..64cd19c 100755
--- a/mediaserver/__init__.py
+++ b/mediaserver/__init__.py
@@ -9,7 +9,7 @@ from gi.repository import Gst
GObject.threads_init()
Gst.init(None)
-"""
-from mediaserver.basicplayer import BasicPlayer
-player = BasicPlayer()
-"""
\ No newline at end of file
+from . resources import Resources
+
+# set Resources to use resources from this package
+Resources.SetPackage(__name__)
diff --git a/mediaserver/basicplayer.py b/mediaserver/basicplayer.py
index cd48c77..a549284 100755
--- a/mediaserver/basicplayer.py
+++ b/mediaserver/basicplayer.py
@@ -7,9 +7,11 @@ import sys, os
# perform gstreamer imports (python3 style)
import gi
gi.require_version('Gst','1.0')
+gi.require_version('GstGL', '1.0')
+gi.require_version('GstVideo', '1.0')
from gi.repository import GObject
-from gi.repository import Gst
+from gi.repository import Gst, GstGL, GstVideo
class BasicPlayer(GObject.GObject):
@@ -51,9 +53,9 @@ class BasicPlayer(GObject.GObject):
def __init__(self):
GObject.GObject.__init__(self)
# setup gstreamer
- self.pipeline_state = Gst.State.NULL;
+ self.pipeline_state = Gst.State.NULL
+ self.window_handle = 0
self.prepare_gstreamer()
-
self.buffering = False
def __del__(self):
@@ -63,17 +65,16 @@ class BasicPlayer(GObject.GObject):
if property.name == 'volume':
return self.pipeline.get_property('volume')
else:
- raise AttributeError, 'unknown property %s' % property.name
+ raise AttributeError("unknown property '{0}'".format(property.name_))
def do_set_property(self, property, value):
if property.name == 'volume':
volume = clamp(value,0.0,1.0)
self.pipeline.set_property('volume', volume)
- #print "Set volume to {0}, got {1}".format(volume,self.pipeline.get_property('volume'))
+ #print("Set volume to {0}, got {1}".format(volume,self.pipeline.get_property('volume')))
self.emit('volume-changed',volume)
else:
- raise AttributeError, 'unknown property %s' % property.name
-
+ raise AttributeError("unknown property '{0}'".format(property.name_))
def play(self):
# start playback ;)
if self.player_state in ["READY","PAUSED",]:
@@ -83,20 +84,20 @@ class BasicPlayer(GObject.GObject):
def load(self,file):
self.source = "file://" + file
- #print "Attempting to load: '{0}'".format(file)
- self.pipeline.set_state(Gst.State.NULL);
+ #print( "Attempting to load: '{0}'".format(file))
+ self.pipeline.set_state(Gst.State.NULL)
self.pipeline.set_property("uri", self.source)
- self.pipeline.set_state(Gst.State.PAUSED);
+ self.pipeline.set_state(Gst.State.PAUSED)
self.player_state = "LOADING"
self.tags.clear()
def load_uri(self,uri):
self.source = uri
- #print "Attempting to load: '{0}'".format(file)
- self.pipeline.set_state(Gst.State.NULL);
+ #print("Attempting to load: '{0}'".format(file))
+ self.pipeline.set_state(Gst.State.NULL)
self.pipeline.set_property("uri", self.source)
- self.pipeline.set_state(Gst.State.PAUSED);
+ self.pipeline.set_state(Gst.State.PAUSED)
self.player_state = "LOADING"
self.tags.clear()
@@ -104,8 +105,7 @@ class BasicPlayer(GObject.GObject):
def stop(self):
if self.player_state in ["PLAYING","PAUSED",]:
self._running = False
- self.pipeline.set_state(Gst.State.READY)
- self.player_state = "READY"
+ self.unload()
self.emit('playback-stopped')
def pause(self,notify=True):
@@ -116,42 +116,49 @@ class BasicPlayer(GObject.GObject):
if notify:
self.emit('playback-paused')
- def _finished(self):
+ def finished(self):
self._running = False
- self.pipeline.set_state(Gst.State.READY)
- self.seek(0)
- self.player_state = "PAUSED"
+ self.unload()
self.emit('playback-finished')
+ def unload(self):
+ self.stop_gstreamer()
+ self.prepare_gstreamer()
+
def prepare_gstreamer(self):
# bin containing the recorder stuff
self.pipeline = Gst.ElementFactory.make("playbin", None)
- videosink = Gst.ElementFactory.make("glimagesink", None)
- alsasink = Gst.ElementFactory.make("alsasink", None)
+ self.videosink = Gst.ElementFactory.make("glimagesink", None)
+ self.videosink.set_window_handle(self.window_handle)
+ self.alsasink = Gst.ElementFactory.make("alsasink", None)
# set output device
#devicename = self.config["Devices.Output"].getStr('name')
#if common.check_alsadev(devicename):
# alsasink.set_property('device', devicename)
- self.pipeline.set_property("video-sink", videosink)
- self.pipeline.set_property("audio-sink", alsasink)
+ self.pipeline.set_property("video-sink", self.videosink)
+ self.pipeline.set_property("audio-sink", self.alsasink)
# connect the bus listener to the message function
self.bus = self.pipeline.get_bus()
self.bus.add_signal_watch()
- self.bus.connect("message", self.on_message)
+ self.busconnection = self.bus.connect("message", self.on_message)
- self.player_state = "NONE"
+ self.player_state = "NULL"
+
+ def link_to_window(self,window_handle):
+ self.window_handle = window_handle
+ self.videosink.set_window_handle(window_handle)
def stop_gstreamer(self):
try:
self.pipeline.get_bus().disconnect(self.busconnection)
self.pipeline.get_bus().remove_signal_watch()
self.pipeline.set_state(Gst.State.NULL)
- except GObject.GError, e:
+ except GObject.GError as e:
self.set_sensitive(True)
def seek(self,seconds):
@@ -162,21 +169,21 @@ class BasicPlayer(GObject.GObject):
if result is not None and result[0]:
return float(result[1]) / Gst.SECOND
else:
- return -1;
+ return -1
def position(self):
result = self.pipeline.query_position(Gst.Format.TIME)
if result is not None and result[0]:
return float(result[1]) / Gst.SECOND
else:
- return -1;
+ return -1
def on_message(self, bus, message):
t = message.type
# detect end of stream, and
if t == Gst.MessageType.EOS:
- self._finished()
+ self.finished()
elif t == Gst.MessageType.ERROR:
self.pipeline.set_state(Gst.State.NULL)
err, debug = message.parse_error()
@@ -185,23 +192,23 @@ class BasicPlayer(GObject.GObject):
self._running = False
self.emit('playback-finished')
self.emit('playback-error', self.player_state, err, debug)
- self.player_state = "NONE"
+ self.player_state = "NULL"
elif t == Gst.MessageType.TAG:
- tags = message.parse_tag();
+ tags = message.parse_tag()
for i in range(0,tags.n_tags()):
key = tags.nth_tag_name(i)
val = tags.get_value_index(key,0)
- self.tags[key] = val;
+ self.tags[key] = val
elif t == Gst.MessageType.ASYNC_DONE:
if message.src == self.pipeline:
pass
elif t == Gst.MessageType.STREAM_STATUS:
(status,owner) = message.parse_stream_status()
-# print "Stream status: {0} (by {1})\n".format(status,owner)
+# print("Stream status: {0} (by {1})\n".format(status,owner))
pass
elif t == Gst.MessageType.BUFFERING:
pct = message.parse_buffering()
- print "Buffering: {0}%".format(pct)
+ print("Buffering: {0}%".format(pct))
self.emit('playback-buffering',pct)
if pct != 100:
if self.pipeline_state == Gst.State.PLAYING:
@@ -212,13 +219,13 @@ class BasicPlayer(GObject.GObject):
self.pipeline.set_state(Gst.State.PLAYING)
self.buffering = False
elif t == Gst.MessageType.DURATION_CHANGED:
-# print "Stream duration changed: {0}\n".format(float(self.pipeline.query_duration(Gst.Format.TIME)[1])/Gst.SECOND)
+# print("Stream duration changed: {0}\n".format(float(self.pipeline.query_duration(Gst.Format.TIME)[1])/Gst.SECOND))
pass
elif t == Gst.MessageType.STATE_CHANGED:
if message.src == self.pipeline:
(old,new,pending) = message.parse_state_changed()
self.pipeline_state = new
-# print "State changed from '{0}' to '{1}' pending '{2}'\n".format(old,new,pending)
+# print("State changed from '{0}' to '{1}' pending '{2}'\n".format(old,new,pending))
if old == Gst.State.READY and new == Gst.State.PAUSED and self.player_state == "LOADING":
self.pipeline.set_state(Gst.State.PAUSED)
self.player_state = "READY"
diff --git a/mediaserver/images/background-base.png b/mediaserver/images/background-base.png
new file mode 100644
index 0000000..7ef6a9b
Binary files /dev/null and b/mediaserver/images/background-base.png differ
diff --git a/mediaserver/images/background-base.svg b/mediaserver/images/background-base.svg
new file mode 100644
index 0000000..cccc1f1
--- /dev/null
+++ b/mediaserver/images/background-base.svg
@@ -0,0 +1,297 @@
+
+
diff --git a/mediaserver/images/background-image.png b/mediaserver/images/background-image.png
new file mode 100644
index 0000000..cf32351
Binary files /dev/null and b/mediaserver/images/background-image.png differ
diff --git a/mediaserver/images/background-image.svg b/mediaserver/images/background-image.svg
new file mode 100644
index 0000000..14d2a5f
--- /dev/null
+++ b/mediaserver/images/background-image.svg
@@ -0,0 +1,296 @@
+
+
diff --git a/mediaserver/mediaserver.py b/mediaserver/mediaserver.py
index e24c760..9d07596 100755
--- a/mediaserver/mediaserver.py
+++ b/mediaserver/mediaserver.py
@@ -1,6 +1,6 @@
# License for this source file
#
-# Copyright (c) 2014 Miqra Engineering
+# Copyright (c) 2021 Miqra Engineering
#
import sys, os
@@ -9,12 +9,22 @@ import signal
from optparse import OptionParser
from collections import OrderedDict
+from .resources import Resources
+
# perform gstreamer imports (python3 style)
import gi
-gi.require_version('Gst','1.0')
+gi.require_version('Gst', '1.0')
+gi.require_version('Gtk', '3.0')
+gi.require_version('GstGL', '1.0')
+gi.require_version('GstVideo', '1.0')
+gi.require_version('GdkPixbuf', '2.0')
from gi.repository import GObject
-from gi.repository import Gst
+from gi.repository import Gst, GstGL, GstVideo
+from gi.repository import GdkPixbuf
+from gi.repository import GLib, Gio, Gtk, Gdk
+from gi.repository import GdkX11
+
Gst.init(None)
# perform dbus imports
@@ -26,15 +36,19 @@ from dbus.mainloop.glib import DBusGMainLoop
DBusGMainLoop(set_as_default=True)
# imports from module
-from monitoredplayer import MonitoredPlayer
+from . monitoredplayer import MonitoredPlayer
class MediaService(dbus.service.Object):
def __init__(self):
+
bus_name = dbus.service.BusName('nl.miqra.MediaCore.Media', bus=dbus.SystemBus())
dbus.service.Object.__init__(self, bus_name, '/nl/miqra/MediaCore/Media')
+ self.window = Gtk.Window(title="MediaServer")
+ self.windowInit()
+
self.player = MonitoredPlayer()
self.player.connect('playback-ready',self.onPlayerReady) # parameters: source_file tag_dict
@@ -46,46 +60,110 @@ class MediaService(dbus.service.Object):
self.player.connect('volume-changed',self.onPlayerVolumeChanged) # parameters: volume
self.player.connect('playback-buffering',self.onPlayerBuffering) # parameters: volume
- self.loadcount = 0;
- self.loadmax = 1;
+ self.window.connect('show',self.onWindowShow)
+
+ self.loadcount = 0
+ self.loadmax = 1
self.quickplay = False
self.quickplayduration = 0
self.quickplayloop = False
+ self.window.show()
self.tick()
# Keepalive timer to help react to Keyboard interrupts
def tick(self):
GObject.timeout_add(100, self.tick)
+ def windowInit(self):
+ self.window.set_name("mainwindow")
+ self.imagebox = Gtk.Box()
+ self.imagebox.set_name("imbox")
+ self.imagebox.set_hexpand(True)
+ self.imagebox.set_vexpand(True)
+ self.imagebox.set_halign(Gtk.Align.CENTER)
+ self.imagebox.set_valign(Gtk.Align.CENTER)
+
+ css = b"""
+ #mainwindow
+ {
+ background-color: #000;
+ }
+ """
+ css_provider = Gtk.CssProvider()
+ css_provider.load_from_data(css)
+ context = Gtk.StyleContext()
+ screen = Gdk.Screen.get_default()
+ context.add_provider_for_screen(screen, css_provider, Gtk.STYLE_PROVIDER_PRIORITY_APPLICATION)
+
+ self.window.add(self.imagebox)
+
+ self.window.fullscreen()
+ pass
+
+ def loadImage(self,image):
+ # remove any existing children
+ for child in self.imagebox.get_children():
+ self.imagebox.remove(child)
+
+ self.imagebox.add(image)
+ self.imagebox.show_all()
+
+ def loadImageFile(self,imfile):
+ print("Loading image {0}".format(imfile))
+
+ image = Gtk.Image()
+ image.set_from_file(imfile)
+ self.loadImage(image)
+
+ def loadImageData(self,data):
+ print("Loading image from data")
+ loader = GdkPixbuf.PixbufLoader.new()
+ loader.write(data)
+ pixbuf = loader.get_pixbuf()
+ loader.close()
+ image = Gtk.Image()
+ image.set_from_pixbuf(pixbuf)
+ self.loadImage(image)
+
+ def onWindowShow(self,w):
+ xid = self.window.get_window().get_xid()
+ print("Retrieved XID for window: {0}".format(xid))
+ self.player.link_to_window(xid)
+ self.loadBaseImage()
+
+ def loadBaseImage(self):
+ self.loadImageFile(Resources.filename("images/background-base.svg"))
+
+
@dbus.service.method(dbus_interface='nl.miqra.MediaCore.Media', in_signature='s', out_signature='')
def QuickPlay(self, file,):
""" Directly play back a local file
"""
if self.loadcount < self.loadmax:
- print "Quickplaying file {0}".format(file)
+ print("Quickplaying file {0}".format(file))
self.quickplay = True
self.quickplayduration = 0
self.quickplayloop = False
self.player.load(file)
- self.loadcount += 1;
+ self.loadcount += 1
else:
- print "Skipping load of file {0} because maximum simultaneous loads ({1}) was reached. Wait until ready....".format(file,self.loadmax);
+ 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
"""
if self.loadcount < self.loadmax:
- print "Quickplaying file {0} for {1} seconds".format(file,duration)
+ 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;
+ self.loadcount += 1
else:
- print "Skipping load of file {0} because maximum simultaneous loads ({1}) was reached. Wait until ready....".format(file,self.loadmax);
+ 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='')
@@ -93,56 +171,56 @@ class MediaService(dbus.service.Object):
""" Directly play back a url
"""
if self.loadcount < self.loadmax:
- print "Quickplaying file {0}".format(file)
+ print("Quickplaying file {0}".format(file))
self.quickplay = True
self.quickplayduration = 0
self.quickplayloop = False
self.player.load_uri(file)
- self.loadcount += 1;
+ self.loadcount += 1
else:
- print "Skipping load of file {0} because maximum simultaneous loads ({1}) was reached. Wait until ready....".format(file,self.loadmax);
+ 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
"""
if self.loadcount < self.loadmax:
- print "Quickplaying file {0} for {1} seconds".format(file,duration)
+ 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;
+ self.loadcount += 1
else:
- print "Skipping load of file {0} because maximum simultaneous loads ({1}) was reached. Wait until ready....".format(file,self.loadmax);
+ 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)
+ print("Quickplaying file {0}".format(file))
self.quickplay = True
self.quickplayduration = 0
self.quickplayloop = True
self.player.load(file)
- self.loadcount += 1;
+ self.loadcount += 1
else:
- print "Skipping load of file {0} because maximum simultaneous loads ({1}) was reached. Wait until ready....".format(file,self.loadmax);
+ 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)
+ print("Quickplaying url {0}".format(uri))
self.quickplay = True
self.quickplayduration = 0
self.quickplayloop = True
self.player.load_uri(url)
- self.loadcount += 1;
+ self.loadcount += 1
else:
- print "Skipping load of file {0} because maximum simultaneous loads ({1}) was reached. Wait until ready....".format(file,self.loadmax);
+ print("Skipping load of file {0} because maximum simultaneous loads ({1}) was reached. Wait until ready....".format(file,self.loadmax))
@@ -152,32 +230,32 @@ class MediaService(dbus.service.Object):
""" Load a local file for playback
"""
if self.loadcount < self.loadmax:
- print "Loading file {0}".format(file)
+ print("Loading file {0}".format(file))
self.quickplay = False
self.player.load(file)
- self.loadcount += 1;
+ self.loadcount += 1
self.OnLoading("file://{0}".format(file))
else:
- print "Skipping load of file {0} because maximum simultaneous loads ({1}) was reached. Wait until ready....".format(file,self.loadmax);
+ 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 LoadUrl(self, uri):
""" Load an url for playback
"""
if self.loadcount < self.loadmax:
- print "Loading url {0}".format(uri)
+ print("Loading url {0}".format(uri))
self.quickplay = False
self.player.load_uri(uri)
self.loadcount += 1;
self.OnLoading(uri)
else:
- print "Skipping load of url {0} because maximum simultaneous loads ({1}) was reached. Wait until ready....".format(uri,self.loadmax);
+ print("Skipping load of url {0} because maximum simultaneous loads ({1}) was reached. Wait until ready....".format(uri,self.loadmax))
@dbus.service.method(dbus_interface='nl.miqra.MediaCore.Media', in_signature='d', out_signature='')
def PlayFor(self, duration):
""" Starts playback for [duration] seconds
"""
- print "Starting playback for {0} seconds".format(duration)
+ print("Starting playback for {0} seconds".format(duration))
self.player.playfor(duration)
@dbus.service.method(dbus_interface='nl.miqra.MediaCore.Media', in_signature='', out_signature='')
@@ -185,7 +263,7 @@ class MediaService(dbus.service.Object):
""" Starts/resumes playback
"""
pos = self.player.position()
- print "Starting playback at timestamp {0}".format(pos)
+ print("Starting playback at timestamp {0}".format(pos))
self.player.play()
@dbus.service.method(dbus_interface='nl.miqra.MediaCore.Media', in_signature='', out_signature='')
@@ -193,21 +271,21 @@ class MediaService(dbus.service.Object):
""" Starts/resumes playback
"""
pos = self.player.position()
- print "Starting playback at timestamp {0}".format(pos)
+ 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
"""
- print "Pausing"
+ print("Pausing")
self.player.pause()
@dbus.service.method(dbus_interface='nl.miqra.MediaCore.Media', in_signature='', out_signature='')
def Stop(self):
""" Stops playback
"""
- print "Stopping"
+ print("Stopping")
self.player.stop()
@dbus.service.method(dbus_interface='nl.miqra.MediaCore.Media', in_signature='', out_signature='d')
@@ -230,18 +308,26 @@ class MediaService(dbus.service.Object):
### Callback functions
def onPlayerReady(self,player,filename,tags):
- print "Loaded {0}".format(filename)
- print "Tags:"
+ print("Loaded {0}".format(filename))
+ print("Tags:")
taglist = {}
for tag in tags:
try:
taglist[tag] = str(tags[tag])
- print " {0}: {1}".format(tag,taglist[tag])
+ print(" {0}: {1}".format(tag,taglist[tag]))
except Exception as x:
- print "Error converting value for '{0}':\n {1}".format(tag,x)
+ print("Error converting value for '{0}':\n {1}".format(tag,x))
+
+ # extract cover art from tags
+ if "image" in tags:
+ buffer = tags["image"].get_buffer() # Gst.Buffer
+ (result, mapinfo) = buffer.map(Gst.MapFlags.READ)
+ if result:
+ self.loadImageData(mapinfo.data)
+
# reset load counter
- self.loadcount = 0;
+ self.loadcount = 0
if self.quickplay:
if self.quickplayloop:
@@ -261,21 +347,23 @@ class MediaService(dbus.service.Object):
self.OnPlaying()
def onPlayerStopped(self,player):
+ self.loadBaseImage()
self.OnStopped()
def onPlayerPaused(self,player):
self.OnPaused()
def onPlayerFinished(self,player):
+ self.loadBaseImage()
self.OnFinished()
def onPlayerError(self,player,state,error,debug):
- print "Player state: {0}".format(state)
+ print("Player state: {0}".format(state))
if state == "LOADING":
- print "Failure during LOAD: {0}".format(error)
+ print("Failure during LOAD: {0}".format(error))
self.OnLoadFail(error)
else:
- print "Failure during RUN: {0}".format(error)
+ print("Failure during RUN: {0}".format(error))
self.OnRunFail(error)
def onPlayerVolumeChanged(self,player,volume):
@@ -348,19 +436,27 @@ class MediaService(dbus.service.Object):
pass
def Run():
+
+ print("Initializing")
+
+ # quick bugfix - set XDG runtime dir if it has not been set
+ if not 'XDG_RUNTIME_DIR' in os.environ:
+ os.environ['XDG_RUNTIME_DIR'] = "/run/user/{0}".format(os.getuid())
+
mediaservice = MediaService()
loop = GObject.MainLoop()
loopcontext = loop.get_context()
+
def onsigint(signal,frame):
- print "Quitting"
+ print("Quitting")
loop.quit()
signal.signal(signal.SIGINT, onsigint)
- print "Starting..."
+ print("Starting..." )
try:
loop.run()
except KeyboardInterrupt:
- print "Quitting"
- loop.quit()
\ No newline at end of file
+ print("Quitting")
+ loop.quit()
diff --git a/mediaserver/monitoredplayer.py b/mediaserver/monitoredplayer.py
index 0b47806..bcf648b 100755
--- a/mediaserver/monitoredplayer.py
+++ b/mediaserver/monitoredplayer.py
@@ -8,9 +8,9 @@ from threading import Thread
import time
# import from this module
-from basicplayer import BasicPlayer
+from . basicplayer import BasicPlayer
-class MonitorThread:#(Thread):
+class Monitor:
def __init__(self,player):
self.player = player
#Thread.__init__(self)
@@ -34,8 +34,8 @@ class MonitorThread:#(Thread):
if self.player.playtime > 0:
if (position - self.player.startpos) > self.player.playtime:
#self._player.pause(notify=False)
- print "Finished limited play"
- self.player._finished()
+ print("Finished limited play")
+ self.player.finished()
if self._running and time is not None:
GObject.timeout_add(100, self.run)
@@ -44,7 +44,7 @@ class MonitoredPlayer(BasicPlayer):
def __init__(self):
BasicPlayer.__init__(self)
# setup monitor thread
- self.monitor = MonitorThread(self)
+ self.monitor = Monitor(self)
self.monitor.start()
self.playtime = -1
self.looping=False
@@ -82,7 +82,7 @@ class MonitoredPlayer(BasicPlayer):
#self.monitor.stop()
- def _finished(self):
+ def finished(self):
if self.looping:
print("Finished - looping")
self.seek(0)
@@ -90,7 +90,7 @@ class MonitoredPlayer(BasicPlayer):
self.player_state = "PLAYING"
self.pipeline.set_state(Gst.State.PLAYING)
else:
- BasicPlayer._finished(self)
+ BasicPlayer.finished(self)
GObject.type_register(MonitoredPlayer)
diff --git a/mediaserver/resources.py b/mediaserver/resources.py
new file mode 100644
index 0000000..0eb022b
--- /dev/null
+++ b/mediaserver/resources.py
@@ -0,0 +1,59 @@
+# License for this source file
+#
+# Copyright (c) 2014 Miqra Engineering
+#
+# Permission is hereby granted, free of charge, to any person obtaining a copy
+# of this software and associated documentation files (the "Software"), to deal
+# in the Software without restriction, including without limitation the rights
+# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+# copies of the Software, and to permit persons to whom the Software is
+# furnished to do so, subject to the following conditions:
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+# THE SOFTWARE
+
+import os,sys
+import pkg_resources
+
+class Resources(object): # needs to be explicitly subclassed from object to get the __new__ method to work
+
+ PACKAGE = __name__
+
+
+ @classmethod
+ def SetPackage(cls, package):
+ """
+ Set the package from which to load localization data
+ """
+ cls.PACKAGE = package
+ pass
+
+
+ @classmethod
+ def string_from(cls,path):
+ return pkg_resources.resource_string(cls.PACKAGE, path)
+
+ @classmethod
+ def filename(cls,path):
+ return pkg_resources.resource_filename(cls.PACKAGE, path)
+
+ @classmethod
+ def stream_from(cls,path):
+ return pkg_resources.resource_stream(cls.PACKAGE, path)
+
+ @classmethod
+ def isdir(cls,path):
+ return pkg_resources.resource_isdir(cls.PACKAGE,path)
+
+ @classmethod
+ def exists(cls,path):
+ return pkg_resources.resource_exists(cls.PACKAGE,path)
+
+ @classmethod
+ def listdir(cls,path):
+ return pkg_resources.resource_listdir(cls.PACKAGE,path)
diff --git a/test_client.py b/test_client.py
index d6d17a5..6c4ae64 100755
--- a/test_client.py
+++ b/test_client.py
@@ -30,7 +30,7 @@ class TestController:
GObject.timeout_add(10, self.tick)
def tick(self):
- self.player.QuickLoop("/opt/src/robotvideo/ogen open.mp4")
+ self.player.QuickPlay(sys.argv[1])
#GObject.timeout_add(3000, self.reboot)
pass
@@ -85,6 +85,6 @@ def signalSIGTERM(self,signum):
signal.signal(signal.SIGTERM, signalSIGTERM)
controller = TestController()
-controller.Start();
+controller.Start()