%PDF- %PDF-
Direktori : /lib/python3/dist-packages/orca/ |
Current File : //lib/python3/dist-packages/orca/sound.py |
# Orca # # Copyright 2016 Orca Team. # # This library is free software; you can redistribute it and/or # modify it under the terms of the GNU Lesser General Public # License as published by the Free Software Foundation; either # version 2.1 of the License, or (at your option) any later version. # # This library is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # Lesser General Public License for more details. # # You should have received a copy of the GNU Lesser General Public # License along with this library; if not, write to the # Free Software Foundation, Inc., Franklin Street, Fifth Floor, # Boston MA 02110-1301 USA. """Utilities for playing sounds.""" __id__ = "$Id:$" __version__ = "$Revision:$" __date__ = "$Date:$" __copyright__ = "Copyright (c) 2016 Orca Team" __license__ = "LGPL" import gi from gi.repository import GLib try: gi.require_version('Gst', '1.0') from gi.repository import Gst except Exception: _gstreamerAvailable = False else: _gstreamerAvailable, args = Gst.init_check(None) from . import debug from .sound_generator import Icon, Tone class Player: """Plays Icons and Tones.""" def __init__(self): self._initialized = False self._source = None self._sink = None self._player = None self._pipeline = None if not _gstreamerAvailable: msg = 'SOUND ERROR: Gstreamer is not available' debug.printMessage(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 = f'SOUND ERROR: {error}' debug.printMessage(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 = f'SOUND ERROR: {error}' debug.printMessage(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', f'file://{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') if self._player is None: msg = 'SOUND ERROR: Gstreamer is available, but player is None' debug.printMessage(debug.LEVEL_INFO, msg, True) return 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') if self._source is None or self._sink is None: return 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: tokens = ["SOUND ERROR:", item, "is not an Icon or Tone"] debug.printTokens(debug.LEVEL_INFO, tokens, True) def stop(self, element=None): """Stops play.""" if not _gstreamerAvailable: return if element: element.set_state(Gst.State.NULL) return if self._player: self._player.set_state(Gst.State.NULL) if self._pipeline: 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 _player = Player() def getPlayer(): return _player