diff --git a/src/fenrir-package/sound/gstreamer.py b/src/fenrir-package/sound/gstreamer.py new file mode 100644 index 00000000..42e1af03 --- /dev/null +++ b/src/fenrir-package/sound/gstreamer.py @@ -0,0 +1,136 @@ +import gi +from gi.repository import GLib + +try: + gi.require_version('Gst', '1.0') + from gi.repository import Gst +except: + _gstreamerAvailable = False +else: + _gstreamerAvailable, args = Gst.init_check(None) + +from . import debug +from .sound_generator import Icon, Tone + +class sound: + """Plays Icons and Tones.""" + + def __init__(self): + self._initialized = False + self._source = None + self._sink = None + + if not _gstreamerAvailable: + msg = 'SOUND ERROR: Gstreamer is not available' + debug.println(debug.LEVEL_INFO, msg, True) + return + + self.init() + + def _onPlayerMessage(self, bus, message): + if message.type == Gst.MessageType.EOS: + self._player.set_state(Gst.State.NULL) + elif message.type == Gst.MessageType.ERROR: + self._player.set_state(Gst.State.NULL) + error, info = message.parse_error() + msg = 'SOUND ERROR: %s' % error + debug.println(debug.LEVEL_INFO, msg, True) + + def _onPipelineMessage(self, bus, message): + if message.type == Gst.MessageType.EOS: + self._pipeline.set_state(Gst.State.NULL) + elif message.type == Gst.MessageType.ERROR: + self._pipeline.set_state(Gst.State.NULL) + error, info = message.parse_error() + msg = 'SOUND ERROR: %s' % error + debug.println(debug.LEVEL_INFO, msg, True) + + def _onTimeout(self, element): + element.set_state(Gst.State.NULL) + return False + + def _playIcon(self, icon, interrupt=True): + """Plays a sound icon, interrupting the current play first unless specified.""" + + if interrupt: + self._player.set_state(Gst.State.NULL) + + self._player.set_property('uri', 'file://%s' % icon.path) + self._player.set_state(Gst.State.PLAYING) + + def _playTone(self, tone, interrupt=True): + """Plays a tone, interrupting the current play first unless specified.""" + + if interrupt: + self._pipeline.set_state(Gst.State.NULL) + + self._source.set_property('volume', tone.volume) + self._source.set_property('freq', tone.frequency) + self._source.set_property('wave', tone.wave) + self._pipeline.set_state(Gst.State.PLAYING) + duration = int(1000 * tone.duration) + GLib.timeout_add(duration, self._onTimeout, self._pipeline) + + def init(self): + """(Re)Initializes the Player.""" + + if self._initialized: + return + + if not _gstreamerAvailable: + return + + self._player = Gst.ElementFactory.make('playbin', 'player') + bus = self._player.get_bus() + bus.add_signal_watch() + bus.connect("message", self._onPlayerMessage) + + self._pipeline = Gst.Pipeline(name='orca-pipeline') + bus = self._pipeline.get_bus() + bus.add_signal_watch() + bus.connect("message", self._onPipelineMessage) + + self._source = Gst.ElementFactory.make('audiotestsrc', 'src') + self._sink = Gst.ElementFactory.make('autoaudiosink', 'output') + self._pipeline.add(self._source) + self._pipeline.add(self._sink) + self._source.link(self._sink) + + self._initialized = True + + def play(self, item, interrupt=True): + """Plays a sound, interrupting the current play first unless specified.""" + + if isinstance(item, Icon): + self._playIcon(item, interrupt) + elif isinstance(item, Tone): + self._playTone(item, interrupt) + else: + msg = 'SOUND ERROR: %s is not an Icon or Tone' % item + debug.println(debug.LEVEL_INFO, msg, True) + + def stop(self, element=None): + """Stops play.""" + + if not _gstreamerAvailable: + return + + if element: + element.set_state(Gst.State.NULL) + return + + self._player.set_state(Gst.State.NULL) + self._pipeline.set_state(Gst.State.NULL) + + def shutdown(self): + """Shuts down the sound utilities.""" + + global _gstreamerAvailable + if not _gstreamerAvailable: + return + + self.stop() + self._initialized = False + _gstreamerAvailable = False + + diff --git a/src/fenrir-package/sound/sox.py b/src/fenrir-package/sound/sox.py index db30591c..2a46e9b0 100644 --- a/src/fenrir-package/sound/sox.py +++ b/src/fenrir-package/sound/sox.py @@ -7,6 +7,8 @@ class sound(): pass def playSoundFile(self, Path): pass + def stop(self): + pass def setCallback(self, callback): pass def shutdown(self):