Skip to content

Instantly share code, notes, and snippets.

@adamcik
Created August 11, 2014 22:24
Show Gist options
  • Save adamcik/42d20e2ec66d02697fee to your computer and use it in GitHub Desktop.
Save adamcik/42d20e2ec66d02697fee to your computer and use it in GitHub Desktop.
New mopidy.audio.player classes
class Player(object):
"""Main class responsible for gluing together our audio components.
This class should:
- Create the playbin element and set it up according to the config
- Connect the handlers event and message routers to the playbin
- Add an additional signal handlers for source-setup hooked up to proxy
setup and the appsrc.
- Add an additional signal handler for about-to-finish hooked up to
playback's callback.
"""
# TODO: we could also pass a pre constructed element to this class?
playback = None
handler = None
outputs = None
appsrc = None
mixer = None
def __init__(self, config, mixer):
pass
def teardown(self):
"""Perform any cleanup needed and forward the teardown message."""
pass
class Playback(object):
"""Main class for accessing playback state."""
#: Callback which will be called when the end of the current track is about
#: to be reached. If the callee has a next track to play it _must_ call
#: `set_uri(new_uri)` before returning.
about_to_finish_callback = None
def __init__(self, element):
pass
def prepare_change(self):
"""Signal that we plan to change the URI.
This is not part of the ``set_uri(uri)`` call as this will often be
called for us when performing gapless playback.
"""
pass
def set_uri(self, uri):
"""Set the next URI to be played.
This method does not ensure the pipeline is in the correct state for
changing the URI.
"""
pass
def get_position(self):
"""Return the current position in milliseconds."""
pass
def set_position(self, position_ms):
"""Set the new position in milliseconds.
Note that seeks are asynchronous, so the seek will not have happened
when we return from this call.
"""
pass
def get_duration(self):
"""Get the duration of the currently playing URI in milliseconds."""
pass
def get_state(self):
"""Returns the current state of playback.
Result will be: STOPPED, PAUSED, BUFFERING or PLAYING
"""
pass
def get_target_state(self):
"""Returns the state we should really be in.
This will differ from the current state while buffering, or when
waiting for an asynchronous state change to finish.
Result will be: STOPPED, PAUSED, or PLAYING
"""
pass
def set_state(self, state):
"""Initiate a state a change.
Most state changes are asynchronous, so the actual state change will
often occur after this method has returned.
"""
pass
def on_state_change(self, new_state):
"""Hook for handler to tell us about state changes.
new_state will be: STOPPED, PAUSED, BUFFERING or PLAYING
"""
pass
class Handler(object):
"""Perform the message and event routing.
Currently this only has access to the public APIs of playback and the
events and messages handled reflect this. Things not handled by this
class include mixer notifies, source-setup and about-to-finish.
"""
def __init__(self, playback):
pass
def handle_message(self, msg, pipeline):
"""Route a message from the bus to the correct handler.
The player is responsible for making sure we get called, and the extra
pipeline may be used for filtering to only top level messages.
"""
pass
def handle_event(self, event):
"""Route an event from our output pad to the correct handler.
The player is responsible for making sure we get called.
"""
pass
def on_playbin_state_changed(self, old_state, new_state, pending_state):
"""Triggered for all GStreamer state changes and intermediate states.
Note that switching to NULL flushes the message bus, so we never
receive that message.
"""
pass
def on_buffering(self, percent):
"""Triggered when the buffer level changes."""
pass
def on_end_of_stream(self):
"""Triggered when we are all out of data to play."""
pass
def on_error(self, error, debug):
"""Triggered on GStremer errors."""
pass
def on_warning(self, error, debug):
"""Triggered on GStremer warnings."""
pass
def on_async_done(self):
"""Triggered when ever an async state change completes."""
pass
def on_missing_plugin(self, details, instal_string):
"""Triggered when ever we fail due to missing plugins."""
pass
def on_new_segment(self, update, rate, format_, start, stop, position):
"""Triggered when ever the stream is synced to a new position."""
pass
def on_stream_changed(self, uri):
"""Triggered when the output pad starts playing data from a new uri.
This will normally happen a while after we have changed tracks
internally when gapless is working as intended.
"""
pass
class Outputs(object):
# TODO: missing a way to add this to the playbin and hook it up to our
# the queue we will be using as audio-sink in the playbin.
def add_output(self, sink):
"""Add a new GStreamer sink to output audio to."""
pass
def get_outputs(self):
"""Get the {name: state} for all ouputs."""
pass
def toogle_output(self, name):
"""Toggle the named outputs state."""
pass
def remove_output(self, name):
"""Remove a named output."""
pass
class Appsrc(object):
"""Helper class for dealing with appsrc based playback."""
def reset(self):
"""Reset the helper.
Should be called whenever the source changes and we are not setting up
a new appsrc.
"""
pass
def prepare(self, caps, need_data, enough_data, seek_data):
"""Store info we will need when the appsrc element gets installed.
The provided callbacks will be hooked up to the source allowing appsrc
users to know when more data is needed, when the queue is full and
when a seek request comes in.
"""
# TODO: add queue settings
pass
def configure(self, source):
"""Configure the supplied source for use.
Player is responsible for calling this on source-setup for appsrcs.
"""
pass
def push(self, buffer_):
"""Push a new buffer, return value indicates if buffer was consumed.
When you are out of data to push simply push a None buffer.
"""
pass
class Mixer(object):
# TODO: we could perhaps use our listeners to pass state back and forth
# between this mixer and the real software mixer?
def __init__(self, element, mixer):
pass
def setup(self, mixer_ref):
"""Inject the mixer_ref pointing to us into the mixer."""
pass
def teardown(self):
"""Cleanup after ourselves."""
pass
def get_volume(self):
"""Get the current volume [0,100] on a linear scale."""
pass
def set_volume(self, volume):
"""Set the volume [0,100] on a linear scale."""
pass
def get_mute(self):
"""Get the mute state."""
pass
def set_mute(self, mute):
"""Set the mute state."""
pass
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment