User Tools

Site Tools


Action disabled: register
programming:python:py-sonic

Table of Contents

Python Subsonic Library

About

py-sonic is a Python library that wraps the Subsonic REST API. This is meant to essentially be a convenience layer when you are writing an app to work against your Subsonic server. You will notice when going through the documentation here that this is a thin layer on top of the REST API. I have plans to make this a bit more “Pythonic” (if I can ever muster up enough time to do it), but though this returns simple language constructs (dict, list, etc.) at this point, it is still very usable.

Downloading

You can download this the package from Github, or just git clone it.

You can also use pip or easy_install:

pip install py-sonic

NOTE: The RPMs are not guaranteed to be the latest versions. Check Github to find out what the latest version is. That said, I will try and keep these up to date.

py-sonic-0.2.2-1.src.rpm
py-sonic-0.2.2-1.noarch.rpm

Donations

By no means should anyone feel they have to donate. However, if you've used this stuff to save some time, prevent head shaped holes in the wall, raise your children or you just think this is awesome and want to contribute to my Surly fund (that stuff isn't cheap, but it's soooooo good), you can click the Paypal donate button below and toss me a couple of dollars. I've heard from others who have donated that they were visited by flying monkeys that spoke Icelandic, and were subsequently showered with fantastic gifts from said monkeys. I don't know if this is true, or if drug use was involved, but it still sounds pretty awesome.

<html> <form action=“https://www.paypal.com/cgi-bin/webscr” method=“post”> <input type=“hidden” name=“cmd” value=“_s-xclick”> <input type=“hidden” name=“hosted_button_id” value=“83ENX2ZV8E694”> <input type=“image” src=“https://www.paypalobjects.com/en_US/i/btn/btn_donateCC_LG.gif” border=“0” name=“submit” alt=“PayPal - The safer, easier way to pay online!”> <img alt=“” border=“0” src=“https://www.paypalobjects.com/en_US/i/scr/pixel.gif” width=“1” height=“1”> </form> </html>

Issues and Feature Requests

Please use the bug tracker built in to Github for all bug reports and feature requests

Code Contributions

I'm always open to code contributions. Please use the “fork” and “pull request” mechanisms on Github for this.

Installing

You can install manually:

tar -xvzf py-sonic-*.tar.gz
cd py-sonic-*
python setup.py install

Or you can install with pip or easy_install:

pip install py-sonic

libsonic.Connection

NOTE: All of the information in this section is also available with pydoc:

pydoc libsonic.connection

This is the only real class (at this point) that you need to use. You will notice that this very much follows the API as documented on the subsonic website. You will notice that the methods for your libsonic.Connection instance all note their relative REST API versions. You can find the API version to Subsonic version on Subsonic's API documentation page.

FIXME I've found that there is a major wart in the upstream API. It appears that any of the calls which can return multiple results will, instead of always returning a list, will return only a dict instead if there is one item. For example, if you call getPlaylists() with only one playlist set up on your server, you would get a structure like the following:

{
    u'playlists': 
        {u'playlist': 
            {u'id': u'62656174732e6d3375',
             u'name': u'beats'
            }
        }
    u'status': u'ok',
    u'version': u'1.5.0',
    u'xmlns': u'http://subsonic.org/restapi'
}

However, if there are multiple playlists, you will get a structure like this:

{
    u'playlists': 
        {u'playlist': 
            [{u'id': u'62656174732e6d3375',
              u'name': u'beats'
             } ,
             {u'id': u'766172696574792e6d3375',
              u'name': u'variety'
             }]
         } ,
    u'status': u'ok',
    u'version': u'1.5.0',
    u'xmlns': u'http://subsonic.org/restapi'
}

As of this writing, you will have to check whether you receive a list or a dict back. I plan on fixing this in a future release so that you always we receive a list when it is possible to have multiple entries, even if there is only one entry.

Enabling HTTPS Connections

A quick note about when you enable HTTPS on your Subsonic server. I recently discovered that when you set SUBSONIC_HTTPS_PORT to a non-zero value (essentially, turning on HTTPS), this will cause Subsonic to 302 redirect all incoming traffic to the now enabled HTTPS port. This should not be a problem, but it seems that the Python urllib2.HTTPRedirectHandler does not handle this correctly, probably because I'm submitting a POST request here. I'm going to look into this further, but the simple workaround is simply: If you set the SUBSONIC_HTTPS_PORT, be sure that your libsonic.Connection arguments are pointing to the HTTPS port (for the example, I assume you set SUBSONIC_HTTPS_PORT=4430):

import libsonic
conn = libsonic.Connection('https://example.com' , 'myuser' , 'mypass' , port=4430)

UPDATE: I found that the urllib2.HTTPRedirectHandler issue is actually a “bug” wherein the POST data is not redirected. It is somewhat questionable practice in terms of security, so who knows if it will be accepted. Since py-sonic sends everything via POST requests, redirection was breaking it by dropping all data. Though I submitted a bug report with patch, I'm going to put a fix into py-sonic that fixes this regardless of whether the upstream Python maintainers fix this.

UPDATE to the UPDATE: I've fixed this in version 0.1.10. This will now handle redirects from Subsonic correctly.

Important Notes About API Version 1.8.0 (and later)

It's important to note that Subsonic API version 1.8.0 added some methods that are not compatible with previous methods. Prior to 1.8.0, the access to your library was only usable within a directory hierarchy context. With 1.8.0, a number of access methods were added to search and get artists, albums, songs, etc. based on, instead of file system structure, the ID3 tags of the music files themselves.

The problem this brings about is that the IDs returned for one type of lookup are not compatible with the other. For example, if you were to use the search2() method to search for, say, an artist. If you then used the resulting artist ID from that search to getArtist(id), you would not get what you expected! Instead, you would get either an error or a different artist altogether.

The crux of this is that if you must make sure you don't mix these methods in what your code. Anything that is introduced in API 1.8.0 (or later) that makes mention of using ID3 tags will not be compatible with things like getMusicDirectory().

__init__(self, baseUrl, username, password, port=4040, serverPath='/rest', appName='py-sonic' , apiVersion=libsonic.API_VERSION)

This is the initialization method for the class. As you can see, the baseUrl, username and password are all required. Set the rest of the options as needed. This will return a libsonic.Connection instance that you will use to perform all interactions with the server.

Name Type Description
baseUrl str The base url for your server. Be sure to use “https” for SSL connections. ex: http://subsonic.example.com
username str The username to use for the connection
password str The password to use for the connection
port int The port number to connect on. The default for unencrypted subsonic connections is 4040
serverPath str The base resource path for the subsonic views. This is useful if you have your subsonic server behind a proxy and the path that you are proxying is differnt from the default of /rest. Ex: serverPath='/path/to/subs' The full url that would be built then would be (assuming defaults and using “example.com” and you are using the “ping” view): http://example.com:4040/path/to/subs/ping.view
appName str The name of your application.
apiVersion str The version of the API you wish your application to support. Subsonic will throw an error if you Subsonic will throw an error if you the server supports. See the Subsonic API docs to find the Subsonic version → API version table. This is useful if you are connecting to an olderversion of Subsonic.

addChatMessage(self, message)

Since API version: 1.2.0

Adds a message to the chat log

Name Type Description
message str The message to add

Returns a dict like the following:

{
    u'status': u'ok',
    u'version': u'1.5.0',
    u'xmlns': u'http://subsonic.org/restapi'
}

changePassword(self, username, password)

Since API version: 1.2.0

Changes the password of an existing Subsonic user. Note that the user performing this must have admin privileges.

Name Type Description
username str The username whose password is being changed
password str The new password of the user

Returns a dict like the following:

{
    u'status': u'ok',
    u'version': u'1.5.0',
    u'xmlns': u'http://subsonic.org/restapi'
}

createPlaylist(self, playlistId=None, name=None, songIds=[])

Since API version: 1.2.0

Creates OR updates a playlist. If updating the list, the playlistId is required. If creating a list, the name is required.

Name Type Description
playlistId str The ID of the playlist to UPDATE
name str The name of the playlist to CREATE
songIds list[str] The list of songIds to populate the list with in either create or update mode. Note that this list will replace the existing list if updating.

Returns a dict like the following:

{
    u'status': u'ok',
    u'version': u'1.5.0',
    u'xmlns': u'http://subsonic.org/restapi'
}

createPodcastChannel(self, url)

Since API version: 1.9.0

Adds a new Podcast channel. Note: The user must be authorized for Podcast administration

Name Type Description
url str The URL of the Podcast to add

Returns a dict like the following:

{
    u'status': u'ok',
    u'version': u'1.5.0',
    u'xmlns': u'http://subsonic.org/restapi'
}

createShare(self, shids=[], description=None, expires=None)

Since API version: 1.6.0

Creates a public URL that can be used by anyone to stream music or video from the Subsonic server. The URL is short and suitable for posting on Facebook, Twitter etc. Note: The user must be authorized to share (see Settings > Users > User is allowed toshare files with anyone).

Name Type Description
shids list[str] A list of IDs of songs, albums or videos
description str A description that will be displayed to people visiting the shared media (optional).
expires float A timestamp pertaining to the time at which this should expire (optional)

This returns a structure like you would get back from getShares() containing just your new share.

createUser(self, username, password, ldapAuthenticated=False, adminRole=False, settingsRole=True, streamRole=True, jukeboxRole=False, downloadRole=False, uploadRole=False, playlistRole=False, coverArtRole=False, commentRole=False, podcastRole=False)

Since API version: 1.1.0

Creates a new subsonic user, using the parameters defined. See the documentation at the Subsonic site for more info on all the roles.

Name Type Description
username str The username of the new user
password str The password for the new user

See the documention on the Subsonic site for more information on all the boolean role args.

Returns a dict like the following:

{
    u'status': u'ok',
    u'version': u'1.5.0',
    u'xmlns': u'http://subsonic.org/restapi'
}

deleteBookmark(self, mid)

Since API version: 1.9.0

Deletes the bookmark for a given file

Name Type Description
mid str The ID of the media file to delete the bookmark from. Other users' bookmarks are not affected

Returns a dict like the following:

{
    u'status': u'ok',
    u'version': u'1.5.0',
    u'xmlns': u'http://subsonic.org/restapi'
}

deletePlaylist(self, pid)

Since API version: 1.2.0

Deletes a saved playlist.

Name Type Description
pid str ID of the playlist to delete, as obtained by getPlaylists()

Returns a dict like the following:

{
    u'status': u'ok',
    u'version': u'1.5.0',
    u'xmlns': u'http://subsonic.org/restapi'
}

deletePodcastChannel(self, pid)

Since API version: 1.9.0

Deletes a Podcast channel. Note: The user must be authorized for Podcast administration

Name Type Description
pid str ID of the Podcast channel to delete

Returns a dict like the following:

{
    u'status': u'ok',
    u'version': u'1.5.0',
    u'xmlns': u'http://subsonic.org/restapi'
}

deletePodcastEpisode(self, pid)

Since API version: 1.9.0

Deletes a Podcast episode. Note: The user must be authorized for Podcast administration

Name Type Description
pid str ID of the Podcast episode to delete

Returns a dict like the following:

{
    u'status': u'ok',
    u'version': u'1.5.0',
    u'xmlns': u'http://subsonic.org/restapi'
}

deleteShare(self, shid)

Since API version: 1.6.0

Deletes an existing share.

Name Type Description
shid str The ID of the share to delete

Returns a dict like the following:

{
    u'status': u'ok',
    u'version': u'1.5.0',
    u'xmlns': u'http://subsonic.org/restapi'
}

deleteUser(self, username)

Since API version: 1.3.0

Deletes an existing Subsonic user. Of course, you must have admin rights for this.

Name Type Description
username str The username of the user to delete

Returns a dict like the following:

{
    u'status': u'ok',
    u'version': u'1.5.0',
    u'xmlns': u'http://subsonic.org/restapi'
}

download(self, sid)

Since API version: 1.0.0

Downloads a given media file.

Name Type Description
sid str The ID of the media file to download.

Returns the file-like object for reading or raises an exception on error.

downloadPodcastEpisode(self , pid)

Since API version: 1.9.0

Tells the server to start downloading a given Podcast episode. Note: The user must be authorized for Podcast administration

Name Type Description
pid str The ID of the Podcast episode to download.

Returns a dict like the following:

{
    u'status': u'ok',
    u'version': u'1.5.0',
    u'xmlns': u'http://subsonic.org/restapi'
}

getAlbum(self , id)

Since API version: 1.8.0

Returns the info and songs for an album. This method uses the ID3 tags for organization.

Name Type Description
id str The ID of the album.

Returns a dict like the following:

           {u'album': {u'artist': u'Massive Attack',
            u'artistId': 0,
            u'coverArt': u'al-0',
            u'created': u'2009-08-28T10:00:44',
            u'duration': 3762,
            u'id': 0,
            u'name': u'100th Window',
            u'song': [{u'album': u'100th Window',
                       u'albumId': 0,
                       u'artist': u'Massive Attack',
                       u'artistId': 0,
                       u'bitRate': 192,
                       u'contentType': u'audio/mpeg',
                       u'coverArt': 2,
                       u'created': u'2009-08-28T10:00:57',
                       u'duration': 341,
                       u'genre': u'Rock',
                       u'id': 14,
                       u'isDir': False,
                       u'isVideo': False,
                       u'parent': 2,
                       u'path': u'Massive Attack/100th Window/01 - Future Proof.mp3',
                       u'size': 8184445,
                       u'suffix': u'mp3',
                       u'title': u'Future Proof',
                       u'track': 1,
                       u'type': u'music',
                       u'year': 2003}],
              u'songCount': 9},
            u'status': u'ok',
            u'version': u'1.8.0',
            u'xmlns': u'http://subsonic.org/restapi'}

getAlbumList(self, ltype, size=10, offset=0)

Since API version: 1.2.0

Returns a list of random, newest, highest rated etc. albums. Similar to the album lists on the home page of the Subsonic web interface.

Name Type Description
ltype str The list type. Must be one of the following: random, newest, highest, frequent, recent
size int The number of albums to return. Max 500
offset int The list offset. Use for paging. Max 5000

Returns a dict like the following:

{
    u'albumList': 
        {u'album': [
            {
                u'artist': u'Hank Williams', 
                u'id': u'3264928374', 
                u'isDir': True,
                u'parent': u'9238479283',
                u'title': u'The Original Singles Collection...Plus'
            } ,
            {
                u'artist': u'Freundeskreis' ,
                u'coverArt': u'9823749823',
                u'id': u'23492834',
                u'isDir': True,
                u'parent': u'9827492374',
                u'title': u'Quadratur des Kreises'
            }
        ]}
    u'status': u'ok',
    u'version': u'1.5.0',
    u'xmlns': u'http://subsonic.org/restapi'
}

getAlbumList2(self, ltype, size=10, offset=0)

Since API version: 1.8.0

Returns a list of random, newest, highest rated etc. albums. This is similar to getAlbumList, but uses ID3 tags for organization.

Name Type Description
ltype str The list type. Must be one of the following: random, newest, highest, frequent, recent
size int The number of albums to return. Max 500
offset int The list offset. Use for paging. Max 5000

Returns a dict like the following:

           {u'albumList2': {u'album': [{u'artist': u'Massive Attack',
                             u'artistId': 0,
                             u'coverArt': u'al-0',
                             u'created': u'2009-08-28T10:00:44',
                             u'duration': 3762,
                             u'id': 0,
                             u'name': u'100th Window',
                             u'songCount': 9},
                            {u'artist': u'Massive Attack',
                             u'artistId': 0,
                             u'coverArt': u'al-5',
                             u'created': u'2003-11-03T22:00:00',
                             u'duration': 2715,
                             u'id': 5,
                             u'name': u'Blue Lines',
                             u'songCount': 9}]},
            u'status': u'ok',
            u'version': u'1.8.0',
            u'xmlns': u'http://subsonic.org/restapi'}

getArtist(self , id)

Since API version: 1.8.0

Name Type Description
id int Get the artist by id

getArtists(self)

Since API version: 1.8.0

Similar to getIndexes(), but this method uses the ID3 tags to determine the artist

Returns a dict like the following:

{u'artists': {u'index': [{u'artist': {u'albumCount': 7,
                                      u'coverArt': u'ar-0',
                                      u'id': 0,
                                      u'name': u'Massive Attack'},
                          u'name': u'M'},
                         {u'artist': {u'albumCount': 2,
                                      u'coverArt': u'ar-1',
                                      u'id': 1,
                                      u'name': u'Tune-Yards'},
                          u'name': u'T'}]},
 u'status': u'ok',
 u'version': u'1.8.0',
 u'xmlns': u'http://subsonic.org/restapi'}

getAvatar(self, username)

Since API version: 1.8.0

Returns the avatar for a user or None if the avatar does not exist

Name Type Description
username str The user to retrieve the avatar for

Returns the file-like object for reading or raises an exception on error

getBookmarks(self)

Since API version: 1.9.0

Returns all bookmarks for this user. A bookmark is a position within a media file

{
  "bookmarks": {
    "bookmark": {
      "changed": "2013-04-28T13:18:55", 
      "comment": "testing a bookmark", 
      "created": "2013-04-28T13:18:55", 
      "entry": {
        "album": "The Anthology", 
        "albumId": 3480, 
        "artist": "A Tribe Called Quest", 
        "artistId": 1512, 
        "bitRate": 128, 
        "contentType": "audio/mpeg", 
        "coverArt": 45794, 
        "created": "2005-07-27T14:27:42", 
        "duration": 292, 
        "id": 45827, 
        "isDir": false, 
        "isVideo": false, 
        "parent": 45794, 
        "path": "A Tribe Called Quest/The Anthology/13 Stressed Out.mp3", 
        "size": 4685211, 
        "suffix": "mp3", 
        "title": "Stressed Out", 
        "track": 13, 
        "type": "music"
      }, 
      "position": 30000, 
      "username": "admin"
    }
  }, 
  "status": "ok", 
  "version": "1.9.0", 
  "xmlns": "http://subsonic.org/restapi"
}

getChatMessages(self, since=1)

Since API version: 1.2.0

Returns the current visible (non-expired) chat messages.

Name Type Description
since int Only return messages newer than this timestamp

NOTE: All times returned are in MILLISECONDS since the Epoch, not seconds!

Returns a dict like the following:

{
    u'chatMessages': 
        [{u'chatMessage': 
            {u'message': u'testing 123',
             u'time': 1303411919872L,
             u'username': u'admin'
            }
        }] ,
    u'status': u'ok',
    u'version': u'1.5.0',
    u'xmlns': u'http://subsonic.org/restapi'
}

getCoverArt(self, aid, size=None)

Since API version: 1.0.0

Returns a cover art image

Name Type Description
aid str ID string for the cover art image to download
size int If specified, scale image to this size

Returns the file-like object for reading or raises an exception on error.

getGenres(self)

Since API version: 1.9.0

Returns all genres

getIndexes(self, musicFolderId=None, ifModifiedSince=0)

Since API version: 1.0.0

Returns an indexed structure of all artists

Name Type Description
musicFolderId int If this is specified, it will only return artists for the given folder ID from the getMusicFolders call
ifModifiedSince int If specified, return a result if the artist collection has changed since the given time

Returns a dict like the following:

{
    u'indexes': 
        {u'index': 
            [{u'name': 'A' ,
              u'artist': 
                [{u'id': u'29834728934',
                   u'name': u'A Perfect Circle'
                 } ,
                 {u'id': u'238472893',
                  u'name': u'A Small Good Thing'
                 } ,
                 ...
                 ...
                 ]
              } ,
              {u'name': 'B' ,
               u'artist': 
                 [{u'id': u'983249823' ,
                 ...
                 ...
                 }]
              }]
        } ,
        u'lastModified': 1303318347000L
}

Since this is a bit ugly and hard to discern, I'm going to lay it out in types table here.

Name Type Keys (if a dict) Description
<base>b dict u'status', u'xmlns', u'version', u'indexes' This is the root object that contains the usual (“status”, “version”, “xmlns”) and also “indexes”
b['indexes'] dict u'index', u'shortcut', u'lastModified' This contains a list of shortcuts, which may or may not be there for you (I won't describe this here). It also contains the “index”, which is where all our real data is
b['indexes']['index'] list N/A This is a list of dictionaries containing the root of the index.
b['indexes']['index'][0] dict u'name', u'artist' The name value here is a string that will be the index name, basically the first letter of this sections artist names (or a # for numbers)
b['indexes']['index'][0]['artist'] list N/A This will be a list of the artist dictionaries within the name section. So, if name is “A”, then this will be a list of all the artists starting with the letter “A”
b['indexes']['index'][0]['artist'][0] dict u'id', u'name' This is the internal ID value for the artist and the actual artist name

I hope that table clarifies things a bit.

getInternetRadioStations(self)

Since API version: 1.9.0

Returns all internet radio stations

Returns a dict like the following:

{
  "internetRadioStations": {
    "internetRadioStation": {
      "homePageUrl": "http://www.di.fm/", 
      "id": 0, 
      "name": "DI hard dance", 
      "streamUrl": "http://listen.di.fm/public3/harddance.pls"
    }
  }, 
  "status": "ok", 
  "version": "1.9.0", 
  "xmlns": "http://subsonic.org/restapi"
}

getLicense(self)

Since API version: 1.0.0

Gets details related to the software license

Returns a dict like the following:

{
    u'license': 
       {u'date': u'2010-05-21T11:14:39',
        u'email': u'email@example.com',
        u'key': u'12345678901234567890123456789012',
        u'valid': True
       } ,
    u'status': u'ok' ,
    u'version': u'1.5.0',
    u'xmlns': u'http://subsonic.org/restapi'
}

getLyrics(self, artist=None, title=None)

Since API version: 1.2.0

Searches for and returns lyrics for a given song

Name Type Description
artist str The artist name
title str The song title

Returns a dict like the following for getLyrics('Bob Dylan' , 'Blowin in the wind'):

{
    u'lyrics': 
        {u'artist': u'Bob Dylan',
         u'content': u"How many roads must a man walk down<snip>",
         u'title': u"Blowin' in the Wind"
        }
    u'status': u'ok',
    u'version': u'1.5.0',
    u'xmlns': u'http://subsonic.org/restapi'
}

getMusicDirectory(self, mid)

Since API version: 1.0.0

Returns a listing of all files in a music directory. Typically used to get a list of albums for an artist or list of songs for an album.

Name Type Description
mid str The string ID value which uniquely identifies the folder. Obtained via calls to getIndexes() or getMusicDirectory().

Returns a dict like the following if I were to call this with id for the artist “A Tribe Called Quest”:

{
    u'directory': 
        {u'child': 
            [{u'artist': u'A Tribe Called Quest',
              u'coverArt': u'223484',
              u'id': u'329084',
              u'isDir': True,
              u'parent': u'234823940',
              u'title': u'Beats, Rhymes And Life'
             } ,
             {u'artist': u'A Tribe Called Quest',
              u'coverArt': u'234823794',
              u'id': u'238472893',
              u'isDir': True,
              u'parent': u'2308472938'
              u'title': u'Midnight Marauders'
             }]
         u'id': u'329847293',
         u'name': u'A Tribe Called Quest'
        },
    u'status': u'ok',
    u'version': u'1.5.0',
    u'xmlns': u'http://subsonic.org/restapi'
}

getMusicFolders(self)

Since API version: 1.0.0

Returns all configured music folders

Returns a dict like the following:

{
    u'musicFolders': 
        {u'musicFolder': 
            [{u'id': 0, u'name': u'folder1'},
             {u'id': 1, u'name': u'folder2'},
             {u'id': 2, u'name': u'folder3'}
            ]
        }
    u'status': u'ok',
    u'version': u'1.5.0',
    u'xmlns': u'http://subsonic.org/restapi'
}

getNowPlaying(self)

Since API version: 1.0.0

Returns what is currently being played by all users

Returns a dict like the following:

{
    u'nowPlaying': 
        {u'entry': 
            [{u'album': u"Jazz 'Round Midnight 12",
              u'artist': u'Astrud Gilberto',
              u'bitRate': 172,
              u'contentType': u'audio/mpeg',
              u'coverArt': u'98349284',
              u'duration': 325,
              u'genre': u'Jazz',
              u'id': u'2424324',
              u'isDir': False,
              u'isVideo': False,
              u'minutesAgo': 0,
              u'parent': u'542352',
              u'path': u"Astrud Gilberto/Jazz 'Round Midnight 12/01 - The Girl From Ipanema.mp3",
              u'playerId': 1,
              u'size': 7004089,
              u'suffix': u'mp3',
              u'title': u'The Girl From Ipanema',
              u'track': 1,
              u'username': u'user1',
              u'year': 1996
             },
             { ...
               ...
             }]
        } ,
    u'status': u'ok',
    u'version': u'1.5.0',
    u'xmlns': u'http://subsonic.org/restapi'
}

getPlaylist(self, pid)

Since API version: 1.0.0

Returns a listing of files in a saved playlist

Name Type Description
id str The ID of the playlist as returned in getPlaylists()

Returns a dict like the following:

{
    u'playlist': 
        {u'entry': 
            [{u'album': u'The Essential Bob Dylan',
              u'artist': u'Bob Dylan',
              u'bitRate': 32,
              u'contentType': u'audio/mpeg',
              u'coverArt': u'2983478293',
              u'duration': 984,
              u'genre': u'Classic Rock',
              u'id': u'982739428',
              u'isDir': False,
              u'isVideo': False,
              u'parent': u'98327428974',
              u'path': u"Bob Dylan/Essential Bob Dylan Disc 1/Bob Dylan - The Essential Bob Dylan - 03 - The Times They Are A-Changin'.mp3",
              u'size': 3921899,
              u'suffix': u'mp3',
              u'title': u"The Times They Are A-Changin'",
              u'track': 3
             } ,
             {u'album': u'Another album',
              ...
              ...
             }] ,
         u'id': u'44796c616e2e6d3375',
         u'name': u'Dylan'}
        } ,
    u'status': u'ok',
    u'version': u'1.5.0',
    u'xmlns': u'http://subsonic.org/restapi'
}

getPlaylists(self)

Since API version: 1.0.0

Returns the ID and name of all saved playlists

Returns a dict like the following:

{
    u'playlists': 
        {u'playlist': 
            [{u'id': u'62656174732e6d3375',
              u'name': u'beats'
             } ,
             {u'id': u'766172696574792e6d3375',
              u'name': u'variety'
             }]
         } ,
    u'status': u'ok',
    u'version': u'1.5.0',
    u'xmlns': u'http://subsonic.org/restapi'
}

getPodcasts(self , incEpisodes=True , pid=None)

Since API version: 1.6.0

Returns all podcast channels the server subscribes to and their episodes.

Name Type Description
incEpisodes bool (since: 1.9.0) Whether to include Podcast episodes in the returned result.
pid str (since: 1.9.0) If specified, only return the Podcast channel with this ID.

Returns a dict like the following:

{
    u'podcasts': 
        {u'channel': 
            {u'description': u"Dr Chris Smith...",
             u'episode': 
                 [{u'album': u'Dr Karl and the Naked Scientist',
                   u'artist': u'BBC Radio 5 live',
                   u'bitRate': 64,
                   u'contentType': u'audio/mpeg',
                   u'coverArt': u'2f6f70742f',
                   u'description': u'Dr Karl answers all your science related questions.',
                   u'duration': 2902,
                   u'genre': u'Podcast',
                   u'id': 0,
                   u'isDir': False,
                   u'isVideo': False,
                   u'parent': u'2f6f70742f7',
                   u'publishDate': u'2011-08-17 22:06:00.0',
                   u'size': 23313059,
                   u'status': u'completed',
                   u'streamId': u'2f6f70742',
                   u'suffix': u'mp3',
                   u'title': u'DrKarl: Peppermints, Chillies & Receptors',
                   u'year': 2011
                  } ,
                  {u'album': u'klsddfjks',
                   ...
                   ...
                  }],
              u'id': 0,
              u'status': u'completed',
              u'title': u'Dr Karl and the Naked Scientist',
              u'url': u'http://downloads.bbc.co.uk/podcasts/fivelive/drkarl/rss.xml'
             }
         },
    u'status': u'ok',
    u'version': u'1.5.0',
    u'xmlns': u'http://subsonic.org/restapi'
}     

See also: http://subsonic.svn.sourceforge.net/viewvc/subsonic/trunk/subsonic-main/src/main/webapp/xsd/podcasts_example_1.xml?view=markup

getRandomSongs(self, size=10, genre=None, fromYear=None, toYear=None, musicFolderId=None)

Since API version: 1.2.0

Returns random songs matching the given criteria

Name Type Description
size int The max number of songs to return. Max 500
genre str Only return songs from this genre
fromYear int Only return songs after or in this year
toYear int Only return songs before or in this year
musicFolderId str Only return songs in the music folder with the given ID. See getMusicFolders()

Returns a dict like the following:

{
    u'randomSongs': 
        {u'song': 
            [{u'album': u'1998 EP - Airbag (How Am I Driving)',
              u'artist': u'Radiohead',
              u'bitRate': 320,
              u'contentType': u'audio/mpeg',
              u'duration': 129,
              u'id': u'9284728934',
              u'isDir': False,
              u'isVideo': False,
              u'parent': u'983249823',
              u'path': u'Radiohead/1998 EP - Airbag (How Am I Driving)/06 - Melatonin.mp3',
              u'size': 5177469,
              u'suffix': u'mp3',
              u'title': u'Melatonin'
             } ,
             {u'album': u'Mezmerize',
              ...
              ...
             }]
        } ,
    u'status': u'ok',
    u'version': u'1.5.0',
    u'xmlns': u'http://subsonic.org/restapi'
}

getShares(self)

Since API version: 1.2.0

Returns information about shared media this user is allowed to manage

Returns a dict like the following:

{
    u'shares': 
        {u'share': 
            [{u'created': u'2011-08-18T10:01:35',
              u'entry': 
                  [{u'artist': u'Alice In Chains',
                    u'coverArt': u'2f66696c65732f6d',
                    u'id': u'2f66696c65732f',
                    u'isDir': True,
                    u'parent': u'2f66696c65732f6d7',
                    u'title': u'Alice In Chains'
                   } ,
                   {u'artist': u'ldksjfklsjf',
                    ...
                    ...
                   }] ,
              u'expires': u'2012-08-18T10:01:35',
              u'id': 0,
              u'url': u'http://someone.subsonic.org/share/BuLbF',
              u'username': u'admin',
              u'visitCount': 0
             }]
        } ,
    u'status': u'ok',
    u'version': u'1.5.0',
    u'xmlns': u'http://subsonic.org/restapi'
}

getSong(self, id)

Since API version: 1.8.0

Returns the info for a song. This method uses the ID3 tags for organization.

Name Type Description
id str The song ID
            {u'song': {u'album': u'W H O K I L L',
               u'albumId': 8,
               u'artist': u'Tune-Yards',
               u'artistId': 1,
               u'bitRate': 320,
               u'contentType': u'audio/mpeg',
               u'coverArt': 106,
               u'created': u'2011-03-22T15:08:00',
               u'discNumber': 1,
               u'duration': 192,
               u'genre': u'Indie Rock',
               u'id': 120,
               u'isDir': False,
               u'isVideo': False,
               u'parent': 106,
               u'path': u'Tune Yards/Who Kill/10 Killa.mp3',
               u'size': 7692656,
               u'suffix': u'mp3',
               u'title': u'Killa',
               u'track': 10,
               u'type': u'music',
               u'year': 2011},
             u'status': u'ok',
             u'version': u'1.8.0',
             u'xmlns': u'http://subsonic.org/restapi'}

getSongsByGenre(self, genre , count=10 , offset=0)

Since API version: 1.9.0

Returns songs in a given genre

Name Type Description
genre str The genre, as returned by getGenres()
count int The maximum number of songs to return. Max is 500. default: 10
offset int The offset if you are paging. default: 0

getStarred(self)

Since API version: 1.8.0

Returns starred songs, albums and artists

Returns a dict like the following:

            {u'starred': {u'album': {u'album': u'Bird-Brains',
                         u'artist': u'Tune-Yards',
                         u'coverArt': 105,
                         u'created': u'2012-01-30T13:16:58',
                         u'id': 105,
                         u'isDir': True,
                         u'parent': 104,
                         u'starred': u'2012-08-26T13:18:34',
                         u'title': u'Bird-Brains'},
              u'song': [{u'album': u'Mezzanine',
                         u'albumId': 4,
                         u'artist': u'Massive Attack',
                         u'artistId': 0,
                         u'bitRate': 256,
                         u'contentType': u'audio/mpeg',
                         u'coverArt': 6,
                         u'created': u'2009-06-15T07:48:28',
                         u'duration': 298,
                         u'genre': u'Dub',
                         u'id': 72,
                         u'isDir': False,
                         u'isVideo': False,
                         u'parent': 6,
                         u'path': u'Massive Attack/Mezzanine/Massive Attack_02_mezzanine.mp3',
                         u'size': 9564160,
                         u'starred': u'2012-08-26T13:19:26',
                         u'suffix': u'mp3',
                         u'title': u'Risingson',
                         u'track': 2,
                         u'type': u'music'},
                        {u'album': u'Mezzanine',
                         u'albumId': 4,
                         u'artist': u'Massive Attack',
                         u'artistId': 0,
                         u'bitRate': 256,
                         u'contentType': u'audio/mpeg',
                         u'coverArt': 6,
                         u'created': u'2009-06-15T07:48:25',
                         u'duration': 380,
                         u'genre': u'Dub',
                         u'id': 71,
                         u'isDir': False,
                         u'isVideo': False,
                         u'parent': 6,
                         u'path': u'Massive Attack/Mezzanine/Massive Attack_01_mezzanine.mp3',
                         u'size': 12179456,
                         u'starred': u'2012-08-26T13:19:03',
                         u'suffix': u'mp3',
                         u'title': u'Angel',
                         u'track': 1,
                         u'type': u'music'}]},
             u'status': u'ok',
             u'version': u'1.8.0',
             u'xmlns': u'http://subsonic.org/restapi'}

getStarred2(self)

Since API version: 1.8.0

Returns starred songs, albums and artists like getStarred(), but this uses ID3 tags for organization.

See the output from getStarred(self)

getUser(self, username)

Since API version: 1.3.0

Get details about a given user, including which auth roles it has. Can be used to enable/disable certain features in the client, such as jukebox control.

Name Type Description
username str The username to retrieve. You can only retrieve your own user unless you have admin privs.

Returns a dict like the following:

{
    u'user': 
        {u'adminRole': False,
         u'commentRole': False,
         u'coverArtRole': False,
         u'downloadRole': True,
         u'jukeboxRole': False,
         u'playlistRole': True,
         u'podcastRole': False,
         u'settingsRole': True,
         u'streamRole': True,
         u'uploadRole': True,
         u'username': u'test'
        }
    u'status': u'ok',
    u'version': u'1.5.0',
    u'xmlns': u'http://subsonic.org/restapi'
}

getVideos(self)

Since API version: 1.8.0

Returns all video files

Returns a dict like the following:

            {u'status': u'ok',
             u'version': u'1.8.0',
             u'videos': {u'video': {u'bitRate': 384,
                        u'contentType': u'video/x-matroska',
                        u'created': u'2012-08-26T13:36:44',
                        u'duration': 1301,
                        u'id': 130,
                        u'isDir': False,
                        u'isVideo': True,
                        u'path': u'South Park - 16x07 - Cartman Finds Love.mkv',
                        u'size': 287309613,
                        u'suffix': u'mkv',
                        u'title': u'South Park - 16x07 - Cartman Finds Love',
                        u'transcodedContentType': u'video/x-flv',
                        u'transcodedSuffix': u'flv'}},
             u'xmlns': u'http://subsonic.org/restapi'}

hls(self , mid , bitrate=None)

Since API version: 1.9.0

Creates an HTTP live streaming playlist for streaming video or audio HLS is a streaming protocol implemented by Apple and works by breaking the overall stream into a sequence of small HTTP-based file downloads. It's supported by iOS and newer versions of Android. This method also supports adaptive bitrate streaming, see the bitRate parameter.

Name Type Description
mid str The ID of the media to stream
bitrate str If specified, the server will attempt to limit the bitrate to this value, in kilobits per second. If this parameter is specified more than once, the server will create a variant playlist, suitable for adaptive bitrate streaming. The playlist will support streaming at all the specified bitrates. The server will automatically choose video dimensions that are suitable for the given bitrates. (since: 1.9.0) you may explicitly request a certain width (480) and height (360) like so: bitRate=1000@480×360

Returns the raw m3u8 file as a string

jukeboxControl(self, action, index=None, sids=[], gain=None , offset=None)

Since API version: 1.2.0

NOTE: Some options were added as of API version 1.7.0

Controls the jukebox, i.e., playback directly on the server's audio hardware. Note: The user must be authorized to control the jukebox

Name Type Description
action str The operation to perform. Must be one of: get, start, stop, skip, add, clear, remove, shuffle, setGain, status (added in API 1.7.0), set (added in API 1.7.0)
index int Used by skip and remove. Zero-based index of the song to skip to or remove.
sids str Used by “add” and “set”. ID of song to add to the jukebox playlist. Use multiple id parameters to add many songs in the same request. Whether you are passing one song or many into this, this parameter MUST be a list
gain float Used by setGain to control the playback volume. A float value between 0.0 and 1.0
offset int (Added in API version: 1.7.0) Used by the “skip” action. Start playing this many seconds into the track.

ping(self)

Since API version: 1.0.0

Returns a boolean True if the server is alive, False otherwise

refreshPodcasts(self)

Since API version: 1.9.0

Tells the server to check for new Podcast episodes. Note: The user must be authorized for Podcast administration

Returns a dict like the following:

{
    u'status': u'ok',
    u'version': u'1.5.0',
    u'xmlns': u'http://subsonic.org/restapi'
}

scrobble(self, sid, submission=True)

Since API version: 1.5.0

“Scrobbles” a given music file on last.fm. Requires that the user has set this up.

Name Type Description
sid str The ID of the file to scrobble
submission bool Whether this is a “submission” or a “now playing” notification
listenTime int The unix timestamp for the listen to scrobble.

Returns a dict like the following:

{
    u'status': u'ok',
    u'version': u'1.5.0',
    u'xmlns': u'http://subsonic.org/restapi'
}

search(self, artist=None, album=None, title=None, any=None, count=20, offset=0, newerThan=None)

Since API version: 1.0.0

DEPRECATED SINCE API 1.4.0! USE search2() INSTEAD!

Returns a listing of files matching the given search criteria. Supports paging with offset

Name Type Description
artist str Search for artist
album str Search for album
title str Search for title of song
any str Search all fields
count int Max number of results to return [default: 20]
offset int Search result offset. For paging [default: 0]
newerThan int Return matches newer than this timestamp

search2(self, query, artistCount=20, artistOffset=0, albumCount=20, albumOffset=0, songCount=20, songOffset=0)

Since API version: 1.4.0

Returns albums, artists and songs matching the given search criteria. Supports paging through the result.

Name Type Description
query str The search query
artistCount int Max number of artists to return [default: 20]
artistOffset int Search offset for artists (for paging) [default: 0]
albumCount int Max number of albums to return [default: 20]
albumOffset int Search offset for albums (for paging) [default: 0]
songCount int Max number of songs to return [default: 20]
songOffset int Search offset for songs (for paging) [default: 0]

Returns a dict like the following:

{
    u'searchResult2': 
        {u'album': 
            [{u'artist': u'A Tribe Called Quest',
              u'coverArt': u'289347',
              u'id': u'32487298',
              u'isDir': True,
              u'parent': u'98374289',
              u'title': u'The Love Movement'
             }] ,
         u'artist': 
             [{u'id': u'2947839',
               u'name': u'A Tribe Called Quest'
              },
              {u'id': u'239847239',
               u'name': u'Tribe'
              }],
         u'song': 
             [{u'album': u'Beats, Rhymes And Life',
               u'artist': u'A Tribe Called Quest',
               u'bitRate': 224,
               u'contentType': u'audio/mpeg',
               u'coverArt': u'329847',
               u'duration': 148,
               u'genre': u'default',
               u'id': u'3928472893',
               u'isDir': False,
               u'isVideo': False,
               u'parent': u'23984728394',
               u'path': u'A Tribe Called Quest/Beats, Rhymes And Life/A Tribe Called Quest - Beats, Rhymes And Life - 03 - Motivators.mp3',
               u'size': 4171913,
               u'suffix': u'mp3',
               u'title': u'Motivators',
               u'track': 3
              }]
        } ,
    u'status': u'ok',
    u'version': u'1.5.0',
    u'xmlns': u'http://subsonic.org/restapi'
}

search3(self, query, artistCount=20, artistOffset=0, albumCount=20, albumOffset=0, songCount=20, songOffset=0)

Since API version: 1.8.0

Works the same way as search2(), but uses ID3 tags for organization

Name Type Description
query str The search query
artistCount int Max number of artists to return [default: 20]
artistOffset int Search offset for artists (for paging) [default: 0]
albumCount int Max number of albums to return [default: 20]
albumOffset int Search offset for albums (for paging) [default: 0]
songCount int Max number of songs to return [default: 20]
songOffset int Search offset for songs (for paging) [default: 0]

Returns a dict like the following:

            {u'searchResult3': {u'album': [{u'artist': u'Tune-Yards',
                                u'artistId': 1,
                                u'coverArt': u'al-7',
                                u'created': u'2012-01-30T12:35:33',
                                u'duration': 3229,
                                u'id': 7,
                                u'name': u'Bird-Brains',
                                u'songCount': 13},
                               {u'artist': u'Tune-Yards',
                                u'artistId': 1,
                                u'coverArt': u'al-8',
                                u'created': u'2011-03-22T15:08:00',
                                u'duration': 2531,
                                u'id': 8,
                                u'name': u'W H O K I L L',
                                u'songCount': 10}],
                    u'artist': {u'albumCount': 2,
                                u'coverArt': u'ar-1',
                                u'id': 1,
                                u'name': u'Tune-Yards'},
                    u'song': [{u'album': u'Bird-Brains',
                               u'albumId': 7,
                               u'artist': u'Tune-Yards',
                               u'artistId': 1,
                               u'bitRate': 160,
                               u'contentType': u'audio/mpeg',
                               u'coverArt': 105,
                               u'created': u'2012-01-30T12:35:33',
                               u'duration': 328,
                               u'genre': u'Lo-Fi',
                               u'id': 107,
                               u'isDir': False,
                               u'isVideo': False,
                               u'parent': 105,
                               u'path': u'Tune Yards/Bird-Brains/10-tune-yards-fiya.mp3',
                               u'size': 6588498,
                               u'suffix': u'mp3',
                               u'title': u'Fiya',
                               u'track': 10,
                               u'type': u'music',
                               u'year': 2009}]},
 
             u'status': u'ok',
             u'version': u'1.5.0',
             u'xmlns': u'http://subsonic.org/restapi'}

setAppName(self, appName)

Sets the appName, as is set in init to the new appName

setBaseUrl(self, url)

Changes the base url to url

setPassword(self, password)

Sets the connection password to password

setPort(self, port)

Sets the connection port to port

setRating(self, id, rating)

Since API version: 1.6.0

Sets the rating for a media file

Name Type Description
id str The id of the item (song/artist/album) to rate
rating int The rating between 1 and 5 (inclusive), or 0 to remove the rating

Returns a dict like the following:

{
    u'status': u'ok',
    u'version': u'1.5.0',
    u'xmlns': u'http://subsonic.org/restapi'
}

setServerPath(self, path)

Sets the path portion of the url to path. See init

setUsername(self, username)

Changes the connection username to username

stream(self, sid, maxBitRate=0 , tformat=None , timeOffset=None , size=None , estimateContentLength=False)

Since API version: 1.0.0

Streams a given music file.

Name Type Description
sid str The ID of the music file to download.
maxBitRate int (since API version: 1.2.0) If specified, the server will attempt to limit the bitrate to this value, in kilobits per second. If set to zero (default), no limit is imposed. Legal values are: 0, 32, 40, 48, 56, 64, 80, 96, 112, 128, 160, 192, 224, 256 and 320.
tformat str (since: 1.6.0) Specifies the target format (e.g. “mp3” or “flv”) in case there are multiple applicable transcodings (since: 1.9.0) You can use the special value “raw” to disable transcoding
timeOffset int (since: 1.6.0) Only applicable to video streaming. Start the stream at the given offset (in seconds) into the video
size str (since: 1.6.0) The requested video size in WxH, for instance 640×480
estimateContentLength bool (since: 1.8.0) If set to True, the HTTP Content-Length header will be set to an estimated value for trancoded media

Returns the file-like object for reading or raises an exception on error

updateShare(self, shid, description=None, expires=None)

Since API version: 1.6.0

Updates the description and/or expiration date for an existing share

Name Type Description
shid str The id of the share to update
description str The new description for the share (optional).
expires float The new timestamp for the expiration time of this share (optional).

Constants

These are the constants defined for the class:

API_VERSION

The version of the Subsonic API that this library currently supports.

ERR_CODE_MAP

A mapping of numbers to libsonic.error.*. This is for internal use to map the error number from the server to the correct error type in this library.

Usage

The basic usage

programming/python/py-sonic.txt · Last modified: 2024/01/01 17:13 by jay