Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

added playlistadd command

  • Loading branch information...
commit d62848b0cd556330075afac614da0a2a1a1e48bd 1 parent ab0d047
@wendlers authored
View
24 doc/PyScMPDArchitecture.txt
@@ -94,27 +94,3 @@ Resource (root)
|
+- Directory (soundcloud user)
-
-Persistent Playlists
---------------------
-
-The current playlist is persisted automatically whenever the daemon receives the TERM signal.
-
-It is also possible to save the current playlist under a user defined name. However it is not
-guarntied, that sound-cloud queries deliver the same resultis between two calls for the same
-resource.
-
-E.g. if you added some favorite group "A" which contains more then the maximum amount of users
-the SoundCloud API is returning a more or less random set of users for that groups.
-If now one addes some tracks lets say from user "U" to a playlist, and then comes back the other
-day (starting the daemon freshly), it is very likely, that this time user "U" and its tracks are not
-returned by the API query. Since MPD clients like ncmpcpp try to add songs from a user defined
-playlist to the current playlist by using "addid" or "add" command, and supplying the path,
-the daemon fails to find that track again from the query.
-
-The workaround for this is, to put all tracks retrived from a playlist to a track cache. Since
-a track from a playlist contains all information needed to show it or play it, including its
-former path, every time the "addid" or "add" command is called, the daemon first looks if it
-findes the requested path in the cache. If so, the cached information is used instead of
-querying it from SoundCloud.
-
View
55 doc/PyScMPDImplementation.txt
@@ -59,8 +59,8 @@ playlistid No Displays a list of songs in the play
playlistinfo Yes (no ranges) Displays a list of all songs in the playlist.
playlistsearch No Searches case-sensitively for partial matches in the
current playlist.
-plchanges No Displays changed songs currently in the playlist.
-plchangesposid No As above but only returns positions and ids.
+plchanges Yes Displays changed songs currently in the playlist.
+plchangesposid Yes As above but only returns positions and ids.
prio No Set the priority of the specified songs.
prioid No Same as above but ueses ids.
shuffle No Shuffle the current playlist.
@@ -68,9 +68,9 @@ swap No Swap two songs.
swapid No As above but ueses ids.
listplaylist Yes Lists the songs in the playlist.
listplaylistinfo Yes Lists the songs with metadata in the playlist.
-listplaylists No Prints a list of the playlist directory.
+listplaylists Yes Prints a list of the playlist directory.
load Yes Loads the playlist into the current queue.
-playlistadd No Adds track to a playlist.
+playlistadd Yes Adds track to a playlist.
playlistclear Yes Clears a playlist.
playlistdelete Yes Delete track from playlist.
playlistmove Yes Move songe in playlist.
@@ -109,3 +109,50 @@ channels No Obtain a list of all channels.
readmessages No Reads messages for this client.
sendmessage No Send a message to the specified channel.
+
+Song ID
+-------
+
+Each resource (song or directory) needs to have an ID which is stabel over time. This ID is passed
+to the MPD clients. In general every resource on SoundCloud has a stable ID too. Thus, this ID
+is used to be serverd to clients. However, "pyscmpd" inserts some artifical resources like "favorites",
+"groups" etc. To distinguish this categories from SoundCloud songs, ID_OFFSET (= 100000000) is added
+to each ID retrieved from SoundCloud.
+
+
+moveId Workaround
+-----------------
+
+MPD defines two commands for changing the position of a song in the current playlist.
+
+* move: takes the from and to position for a song within the playlist
+* moveId: takes the song ID and to tho position within the playlist
+
+For some reason, "ncmpcpp" calls "moveId" but does not provide a song ID as first parameter
+but a playlist position. To overcome this problem, it is checked if the provided song ID is
+smaller than ID_OFFEST (= 100000000), and if so, "move" is called instead of "moveId".
+
+
+Persistent Playlists
+--------------------
+
+The current playlist is persisted automatically whenever the daemon receives the TERM signal.
+
+It is also possible to save the current playlist under a user defined name. However it is not
+guarntied, that sound-cloud queries deliver the same resultis between two calls for the same
+resource.
+
+E.g. if you added some favorite group "A" which contains more then the maximum amount of users
+the SoundCloud API is returning a more or less random set of users for that groups.
+If now one addes some tracks lets say from user "U" to a playlist, and then comes back the other
+day (starting the daemon freshly), it is very likely, that this time user "U" and its tracks are not
+returned by the API query. Since MPD clients like ncmpcpp try to add songs from a user defined
+playlist to the current playlist by using "addid" or "add" command, and supplying the path,
+the daemon fails to find that track again from the query.
+
+The workaround for this is, to put all tracks retrived from a playlist to a track cache. Since
+a track from a playlist contains all information needed to show it or play it, including its
+former path, every time the "addid" or "add" command is called, the daemon first looks if it
+findes the requested path in the cache. If so, the cached information is used instead of
+querying it from SoundCloud.
+
View
3  extlib/python-mpd-server/mpdserver/command_skel.py
@@ -218,6 +218,9 @@ class PlaylistDelete(Command):
class Rename(Command):
formatArg=[('playlistName',str), ('playlistNameNew',str)]
+class PlaylistAdd(Command):
+ formatArg=[('playlistName', str), ('song',str)]
+
class Decoders(CommandItems):
def items(self):
return [('plugin','gstreamer'),
View
1  extlib/python-mpd-server/mpdserver/mpdserver.py
@@ -151,6 +151,7 @@ class MpdRequestHandler(SocketServer.StreamRequestHandler):
'playlistclear' :{'class':None,'users':[],'group':'read','mpdVersion':"0.12",'neededBy':None},
'playlistmove' :{'class':None,'users':[],'group':'read','mpdVersion':"0.12",'neededBy':None},
'playlistdelete' :{'class':None,'users':[],'group':'read','mpdVersion':"0.12",'neededBy':None},
+ 'playlistadd' :{'class':None,'users':[],'group':'read','mpdVersion':"0.12",'neededBy':None},
'load' :{'class':None,'users':[],'group':'write','mpdVersion':"0.12",'neededBy':None},
'save' :{'class':None,'users':[],'group':'write','mpdVersion':"0.12",'neededBy':None},
'search' :{'class':None,'users':[],'group':'read','mpdVersion':"0.12",'neededBy':None},
View
30 src/pyscmpd/scmpd.py
@@ -70,6 +70,7 @@ def __init__(self, favoriteUsers, favoriteGroups, favoriteFavorites, serverPort
self.requestHandler.RegisterCommand(PlaylistClear)
self.requestHandler.RegisterCommand(PlaylistMove)
self.requestHandler.RegisterCommand(PlaylistDelete)
+ self.requestHandler.RegisterCommand(PlaylistAdd)
self.requestHandler.Playlist = MpdPlaylist
@@ -396,7 +397,36 @@ class PlaylistDelete(mpdserver.PlaylistDelete):
def handle_args(self, playlistName, songPos):
ScMpdServerDaemon.player.playlistDelete(playlistName, songPos)
+
+class PlaylistAdd(mpdserver.PlaylistAdd):
+
+ def handle_args(self, playlistName, song):
+ logging.info("Adding song [%s] to playlist [%s]" % (song, playlistName))
+
+ # see if we could retrive track from cache
+ if ScMpdServerDaemon.player.trackCache.has_key(song):
+ logging.debug("Cache hit for: %s" % song)
+ t = ScMpdServerDaemon.player.trackCache[song]
+ else:
+ t = ScMpdServerDaemon.scroot.getChildByPath(song)
+
+ if t == None:
+ logging.error("Track [%s] not found" % song)
+ return
+
+ # get playlist
+ p = ScMpdServerDaemon.player.retrivePlaylist(playlistName, False)
+
+ if p == None:
+ logging.info("Playlist [%s] not found, creating new one" % playlistName)
+ p = []
+
+ # add song to playlist
+ p.append(t)
+ # save playlist
+ ScMpdServerDaemon.player.storePlaylist(playlistName, p)
+
class Save(mpdserver.Save):
def handle_args(self, playlistName):
Please sign in to comment.
Something went wrong with that request. Please try again.