Created
August 11, 2014 22:24
-
-
Save adamcik/42d20e2ec66d02697fee to your computer and use it in GitHub Desktop.
New mopidy.audio.player classes
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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