Skip to content

Commit

Permalink
Merge a7e56f9 into add79d9
Browse files Browse the repository at this point in the history
  • Loading branch information
txomon committed Oct 26, 2013
2 parents add79d9 + a7e56f9 commit e042b81
Show file tree
Hide file tree
Showing 7 changed files with 439 additions and 6 deletions.
22 changes: 22 additions & 0 deletions mopidy/audio/actor.py
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@ def __init__(self, config):
self._mixer_scale = None
self._software_mixing = False
self._volume_set = None
self._metadata = None

self._appsrc = None
self._appsrc_caps = None
Expand Down Expand Up @@ -283,6 +284,8 @@ def _on_message(self, bus, message):
logger.warning(
'%s Debug message: %s',
str(error).decode('utf-8'), debug.decode('utf-8') or 'None')
elif message.type == gst.MESSAGE_TAG:
self._on_tag_update(dict(message.parse_tag()))

def _on_playbin_state_changed(self, old_state, new_state, pending_state):
if new_state == gst.STATE_READY and pending_state == gst.STATE_NULL:
Expand Down Expand Up @@ -317,6 +320,22 @@ def _on_end_of_stream(self):
logger.debug('Triggering reached_end_of_stream event')
AudioListener.send('reached_end_of_stream')

def _on_tag_update(self, tags):
trigger = False
for key, value in tags.iteritems():
if key in self._metadata:
if not self._metadata[key] == value:
self._metadata[key] = value
trigger = True
else:
self._metadata[key] = value
trigger = True

if trigger:
logger.debug("Tiggering event: stream_metadata_changed")
AudioListener.send('stream_metadata_changed',
metadata=self._metadata)

def set_uri(self, uri):
"""
Set URI of audio to be played.
Expand All @@ -326,6 +345,7 @@ def set_uri(self, uri):
:param uri: the URI to play
:type uri: string
"""
self._metadata = dict()
self._playbin.set_property('uri', uri)

def set_appsrc(
Expand All @@ -346,6 +366,8 @@ def set_appsrc(
to continue playback
:type seek_data: callable which takes time position in ms
"""
self._metadata = dict()

if isinstance(caps, unicode):
caps = caps.encode('utf-8')
self._appsrc_caps = gst.Caps(caps)
Expand Down
11 changes: 11 additions & 0 deletions mopidy/audio/listener.py
Original file line number Diff line number Diff line change
Expand Up @@ -59,3 +59,14 @@ def state_changed(self, old_state, new_state):
:type new_state: string from :class:`mopidy.core.PlaybackState` field
"""
pass

def stream_metadata_changed(self, metadata):
"""
Called after the stream sends some tag information.
*MAY* be implmeneted by actor.
:param metadata: the actual metadata
:type metadata: dict
"""
pass
158 changes: 158 additions & 0 deletions mopidy/backends/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,11 @@ class Backend(object):
#: the backend doesn't provide playlists.
playlists = None

#: The tracklist provider. An instance of
#: :class:`~mopidy.backends.base.BaseTracklistProvider`, or class:`None` if
#: the backend doesn't provide additional tracklist control logic.
tracklist = None

#: List of URI schemes this backend can handle.
uri_schemes = []

Expand All @@ -41,6 +46,9 @@ def has_playback(self):
def has_playlists(self):
return self.playlists is not None

def has_tracklist(self):
return self.tracklist is not None


class BaseLibraryProvider(object):
"""
Expand Down Expand Up @@ -279,3 +287,153 @@ def save(self, playlist):
*MUST be implemented by subclass.*
"""
raise NotImplementedError


class BaseTracklistProvider(object):
"""
:param backend: backend the controller is a part of
:type backend: :class:`mopidy.backends.base.Backend`
"""

pykka_traversable = True

def __init__(self, backend):
self.backend = backend

def next_track(self, tracklist, tl_track):
"""
Get the next track to be played if the user used next button. The
Provider should be careful with all the tracklist states. See
:meth:`mopidy.core.TracklistController.next_track` code to know which
parameters to take care of.
:param tracklist: The instance of core's TracklistController
:type tracklist: :class:`mopidy.core.TracklistController`
:param tl_track: The track to have the next song's of
:type tl_track: :class:`mopidy.models.TlTrack`
:rtype: It should be a :class:`mopidy.models.TlTrack`, None if the
intention is to tell there is no way to go onwards. For example under
a continuous non-seekable stream. Or finally, any other datatype than
:class:`mopidy.models.TlTrack` or None, which will denote that normal
actions should be following.
"""
return str()

def previous_track(self, tracklist, tl_track):
"""
Get the track to be played if the user used previous button. The
Provider should be careful with all the tracklist states. See
:meth:`mopidy.core.TracklistController.previous_track` code to know
which parameters to take care of.
:param tracklist: The instance of core's TracklistController
:type tracklist: :class:`mopidy.core.TracklistController`
:param tl_track: The track to have the previous song's of
:type tl_track: :class:`mopidy.models.TlTrack`
:rtype: It should be a :class:`mopidy.models.TlTrack`, None if the
intention is to tell there is no way to go backwards. For example under
a continuous non-seekable stream. Or finally, any other datatype than
:class:`mopidy.models.TlTrack` or None, which will denote that normal
actions should be following.
"""
return str()

def eot_track(self, tracklist, tl_track):
"""
Get the track to be played if the previous track ended naturally. The
Provider should be careful with all the tracklist states. See
:meth:`mopidy.core.TracklistController.eot_track` code to know
which parameters to take care of.
:param tracklist: The instance of core's TracklistController
:type tracklist: :class:`mopidy.core.TracklistController`
:param tl_track: The track to have the next song's of
:type tl_track: :class:`mopidy.models.TlTrack`
:rtype: It should be a :class:`mopidy.models.TlTrack`, None if the
intention is to tell there is no way to go onwards for example when the
tracklist is finished. Or finally, any other datatype than
:class:`mopidy.models.TlTrack` or None, which will denote that normal
actions should be following.
"""
return str()

def add(self, tracklist, tracks=None, at_position=None, uri=None):
"""
When adding a new song, the Provider may decide to add or replace
:meth:`mopidy.core.TracklistController.add`.
:param tracklist: The instance of core's TracklistController
:type tracklist: :class:`mopidy.core.TracklistController`
:param tracks: tracks to add
:type tracks: list of :class:`mopidy.models.Track`
:param at_position: position in tracklist to add track
:type at_position: int or :class:`None`
:param uri: URI for tracks to add
:type uri: string
:rtype: It should be a list of :class:`mopidy.models.TlTrack`, pointing
out which where actually the added songs. Anything else will be
considered as that the Controller should be running standard behaviour
"""
return None

def move(self, tracklist, start, end, to_position):
"""
When moving songs from one position to another, this method can be
used to add or replace the logic into
:meth:`mopidy.core.TracklistController.move`.
:param tracklist: The instance of core's TracklistController
:type tracklist: :class:`mopidy.core.TracklistController`
:param start: Where to move tracks from tracklist position start
:type start: int
:param end: Where to move tracks from tracklist position end
:type end: int
:rtype: In order to add some login before, the Provider must return
False, to replace the logic, the Provider must return True.
"""
return False

def remove(self, tracklist, tl_tracks):
"""
When revmoving a song list, more logic can be added before or replacing
completelly the standard one in
:meth:`mopidy.core.TracklistController.remove`
:param tracklist: The instance of core's TracklistController
:type tracklist: :class:`mopidy.core.TracklistController`
:param tl_tracks: The tracks we are trying to remove from the tracklist
:type tl_tracks: list of :class:`mopidy.models.TlTrack`
:rtype: It should be a list of :class:`mopidy.models.TlTrack`, pointing
out which where actually the removed songs. Anything else will be
considered as that the Controller should be running standard behaviour
"""
return None

def shuffle(self, tracklist, start, end):
"""
When suffling a slice of the tracklist, more logic can be added before
or replacing completelly the standard one in
:meth:`mopidy.core.TracklistController.shuffle`
:param tracklist: The instance of core's TracklistController
:type tracklist: :class:`mopidy.core.TracklistController`
:param start: Where to shuffle tracklist from
:type start: int
:param end: Where to shuffle tracklist to
:type end: int
:rtype: In order to add some login before, the Provider must return
False, to replace the logic, the Provider must return True.
"""
return False

def mark_played(self, tracklist, tl_track):
return None

def mark_playing(self, tracklist, tl_track):
return None

def mark_unplayable(self, tracklist, tl_track):
return None

def mark_metadata(self, tracklist, tl_track, metadata):
return None
33 changes: 33 additions & 0 deletions mopidy/backends/dummy.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ def __init__(self, config, audio):
self.library = DummyLibraryProvider(backend=self)
self.playback = DummyPlaybackProvider(audio=audio, backend=self)
self.playlists = DummyPlaylistsProvider(backend=self)
self.tracklist = DummyTracklistProvider(backend=self)

self.uri_schemes = ['dummy']

Expand Down Expand Up @@ -113,3 +114,35 @@ def save(self, playlist):
self._playlists.append(playlist)

return playlist


class DummyTracklistProvider(base.BaseTracklistProvider):
def next_track(self, tracklist, tl_track):
return str()

def previous_track(self, tracklist, tl_track):
return str()

def eot_track(self, tracklist, tl_track):
return str()

def add(self, tracklist, tracks=None, at_position=None, uri=None):
return False

def move(self, tracklist, start, end, to_position):
return False

def remove(self, tracklist, criteria=None, **kwargs):
return False

def shuffle(self, tracklist, start, end):
return False

def mark_played(self, tracklist, tl_track):
return None

def mark_playing(self, tracklist, tl_track):
return None

def mark_unplayable(self, tracklist, tl_track):
return None

0 comments on commit e042b81

Please sign in to comment.