def getArtist(self, **kwargs): rest = SubsonicREST(kwargs) success, response = rest.check_login() if not success: return response artistId = kwargs.get('id') if artistId: artist = request.env['oomusic.artist'].browse([int(artistId)]) if not artist.exists(): return rest.make_error(code='70', message='Artist not found') else: return rest.make_error( code='10', message='Required int parameter "id" is not present') root = etree.Element('subsonic-response', status='ok', version=rest.version_server) xml_artist = rest.make_ArtistID3(artist) root.append(xml_artist) for album in artist.album_ids: xml_album = rest.make_AlbumID3(album) xml_artist.append(xml_album) return rest.make_response(root)
def getSimilarSongs2(self, **kwargs): rest = SubsonicREST(kwargs) success, response = rest.check_login() if not success: return response songId = kwargs.get('id') if songId: track = request.env['oomusic.track'].browse([int(songId)]) if not track.exists(): return rest.make_error(code='70', message='Song not found') else: return rest.make_error( code='10', message='Required int parameter "id" is not present') count = int(kwargs.get('count', 50)) tag_name = kwargs.get('tag_name', 'similarSongs2') root = etree.Element('subsonic-response', status='ok', version=rest.version_server) xml_song_info = rest.make_SimilarSongs2(track, count=count, tag_name=tag_name) root.append(xml_song_info) return rest.make_response(root)
def getCoverArt(self, **kwargs): rest = SubsonicREST(kwargs) success, response = rest.check_login() if not success: return response folderId = kwargs.get('id') if folderId: try: if 'al-' in folderId: folder = request.env['oomusic.album'].browse( [int(folderId.split('-')[-1])]) else: folder = request.env['oomusic.folder'].browse( [int(folderId.split('-')[-1])]) if not folder.exists(): return rest.make_error(code='70', message='Folder not found') except: folder = request.env['oomusic.folder'] else: return rest.make_error( code='10', message='Required int parameter "id" is not present') image = folder.image_medium or 'R0lGODlhAQABAAD/ACwAAAAAAQABAAACADs=' image_stream = StringIO.StringIO(image.decode('base64')) image_ext = '.' + (imghdr.what(image_stream) or 'png') return http.send_file(image_stream, filename=folderId + image_ext)
def getArtists(self, **kwargs): rest = SubsonicREST(kwargs) success, response = rest.check_login() if not success: return response root = etree.Element('subsonic-response', status='ok', version=rest.version_server) xml_artists = rest.make_ArtistsID3() root.append(xml_artists) musicFolderId = kwargs.get('musicFolderId') if musicFolderId: artists = request.env['oomusic.track'].search([ ('folder_id', 'child_of', int(musicFolderId)) ]).mapped('artist_id') else: artists = request.env['oomusic.artist'].search([]) # Build indexes indexes_dict = rest.build_dict_indexes_artists(artists) # List of artists for k, v in sorted(indexes_dict.iteritems()): xml_index = rest.make_IndexID3(k) xml_artists.append(xml_index) for artist in v: xml_artist = rest.make_ArtistID3(artist) xml_index.append(xml_artist) return rest.make_response(root)
def deletePlaylist(self, **kwargs): rest = SubsonicREST(kwargs) success, response = rest.check_login() if not success: return response PlaylistObj = request.env['oomusic.playlist'] playlistId = kwargs.get('id') if playlistId: playlist = PlaylistObj.browse([int(playlistId)]) if not playlist.exists(): return rest.make_error(code='70', message='Playlist not found') else: return rest.make_error( code='10', message='Required int parameter "id" is not present') playlist.unlink() root = etree.Element('subsonic-response', status='ok', version=rest.version_server) return rest.make_response(root)
def unstar(self, **kwargs): rest = SubsonicREST(kwargs) success, response = rest.check_login() if not success: return response trackId = kwargs.get('id') if trackId: track = request.env['oomusic.track'].browse([int(trackId)]) if track.exists(): track.write({'star': '0'}) else: folder = request.env['oomusic.folder'].browse([int(trackId)]) if folder.exists(): folder.write({'star': '1'}) albumId = kwargs.get('albumId') if albumId: album = request.env['oomusic.album'].browse([int(albumId)]) if album.exists(): album.write({'star': '0'}) artistId = kwargs.get('artistId') if artistId: artist = request.env['oomusic.artist'].browse([int(artistId)]) if artist.exists(): artist.write({'star': '0'}) root = etree.Element('subsonic-response', status='ok', version=rest.version_server) return rest.make_response(root)
def getMusicDirectory(self, **kwargs): rest = SubsonicREST(kwargs) success, response = rest.check_login() if not success: return response folderId = kwargs.get('id') if folderId: folder = request.env['oomusic.folder'].browse([int(folderId)]) if not folder.exists(): return rest.make_error(code='70', message='Folder not found') else: return rest.make_error( code='10', message='Required int parameter "id" is not present') root = etree.Element('subsonic-response', status='ok', version=rest.version_server) xml_directory = rest.make_Directory(folder) root.append(xml_directory) # List of folders for child in folder.child_ids: xml_data = rest.make_Child_folder(child) xml_directory.append(xml_data) # List of tracks for track in folder.track_ids: xml_data = rest.make_Child_track(track) xml_directory.append(xml_data) return rest.make_response(root)
def getPlaylist(self, **kwargs): rest = SubsonicREST(kwargs) success, response = rest.check_login() if not success: return response playlistId = kwargs.get('id') if playlistId: playlist = request.env['oomusic.playlist'].browse( [int(playlistId)]) if not playlist.exists(): return rest.make_error(code='70', message='Playlist not found') else: return rest.make_error( code='10', message='Required int parameter "id" is not present') root = etree.Element('subsonic-response', status='ok', version=rest.version_server) xml_playlist = rest.make_Playlist(playlist) root.append(xml_playlist) for playlist_line in playlist.playlist_line_ids: xml_playlist_line = rest.make_Child_track(playlist_line.track_id, tag_name='entry') xml_playlist.append(xml_playlist_line) return rest.make_response(root)
def getArtistInfo2(self, **kwargs): rest = SubsonicREST(kwargs) success, response = rest.check_login() if not success: return response artistId = kwargs.get('id') if artistId: artist = request.env['oomusic.artist'].browse([int(artistId)]) if not artist.exists(): return rest.make_error(code='70', message='Artist not found') else: return rest.make_error( code='10', message='Required int parameter "id" is not present') count = int(kwargs.get('count', 20)) if kwargs.get('includeNotPresent'): includeNotPresent = True if kwargs.get( 'includeNotPresent') == 'true' else False else: includeNotPresent = False root = etree.Element('subsonic-response', status='ok', version=rest.version_server) xml_artist_info = rest.make_ArtistInfo2( artist, count=count, includeNotPresent=includeNotPresent) root.append(xml_artist_info) return rest.make_response(root)
def getAlbum(self, **kwargs): rest = SubsonicREST(kwargs) success, response = rest.check_login() if not success: return response albumId = kwargs.get('id') if albumId: album = request.env['oomusic.album'].browse([int(albumId)]) if not album.exists(): return rest.make_error(code='70', message='Album not found') else: return rest.make_error( code='10', message='Required int parameter "id" is not present') root = etree.Element('subsonic-response', status='ok', version=rest.version_server) xml_album = rest.make_AlbumID3(album) root.append(xml_album) for track in album.track_ids: xml_song = rest.make_Child_track(track, tag_name='song') xml_album.append(xml_song) return rest.make_response(root)
def jukeboxControl(self, **kwargs): rest = SubsonicREST(kwargs) success, response = rest.check_login() if not success: return response return rest.make_error(code='30', message='Feature not supported by server.')
def getVideoInfo(self, **kwargs): # TODO: support video infos rest = SubsonicREST(kwargs) success, response = rest.check_login() if not success: return response return request.make_error(code='30', message='Videos are not supported yet')
def scrobble(self, **kwargs): rest = SubsonicREST(kwargs) success, response = rest.check_login() if not success: return response # TODO support lastfm scrobble return rest.make_error(code='30', message='Feature not supported by server.')
def addChatMessage(self, **kwargs): rest = SubsonicREST(kwargs) success, response = rest.check_login() if not success: return response root = etree.Element('subsonic-response', status='ok', version=rest.version_server) return rest.make_response(root)
def getChatMessages(self, **kwargs): rest = SubsonicREST(kwargs) success, response = rest.check_login() if not success: return response root = etree.Element('subsonic-response', status='ok', version=rest.version_server) xml_messages = rest.make_ChatMessages() root.append(xml_messages) return rest.make_response(root)
def actionUsers(self, **kwargs): rest = SubsonicREST(kwargs) success, response = rest.check_login() if not success: return response # Do not support these actions on purpose, for security reason root = etree.Element('subsonic-response', status='ok', version=rest.version_server) return rest.make_response(root)
def getInternetRadioStations(self, **kwargs): rest = SubsonicREST(kwargs) success, response = rest.check_login() if not success: return response root = etree.Element('subsonic-response', status='ok', version=rest.version_server) xml_radios = rest.make_InternetRadioStations() root.append(xml_radios) return rest.make_response(root)
def getNewestPodcasts(self, **kwargs): rest = SubsonicREST(kwargs) success, response = rest.check_login() if not success: return response root = etree.Element('subsonic-response', status='ok', version=rest.version_server) xml_podcasts = rest.make_Podcasts(tag_name='newestPodcasts') root.append(xml_podcasts) return rest.make_response(root)
def stream(self, **kwargs): rest = SubsonicREST(kwargs) success, response = rest.check_login() if not success: return response trackId = kwargs.get('id') if trackId: track = request.env['oomusic.track'].browse([int(trackId)]) if not track.exists(): return rest.make_error(code='70', message='Song not found') else: return rest.make_error( code='10', message='Required int parameter "id" is not present') maxBitRate = int(kwargs.get('maxBitRate', 0)) output_format = kwargs.get('format', 'mp3') estimateContentLength = kwargs.get('estimateContentLength', False) # Only for video # timeOffset = kwargs.get('timeOffset') # size = kwargs.get('size') # converted = kwargs.get('size', False) fn_ext = os.path.splitext(track.path)[1] # As specified in Subsonic API: if maxBitRate is set to zero, no limit is imposed. We also # avoid any upsampling. if fn_ext[1:] == output_format and (not maxBitRate or maxBitRate >= track.bitrate): return http.send_file(track.path) Transcoder = request.env['oomusic.transcoder'].search( [('input_formats.name', '=', fn_ext[1:]), ('output_format.name', '=', output_format)], limit=1, ) if Transcoder: generator = Transcoder.transcode(int(trackId), bitrate=maxBitRate).stdout mimetype = Transcoder.output_format.mimetype else: _logger.warning('Could not find converter from "%s" to "%s"', fn_ext[1:], output_format) return http.send_file(track.path) data = wrap_file(request.httprequest.environ, generator, buffer_size=Transcoder.buffer_size * 1024) return Response(data, mimetype=mimetype, direct_passthrough=True)
def getNowPlaying(self, **kwargs): rest = SubsonicREST(kwargs) success, response = rest.check_login() if not success: return response root = etree.Element('subsonic-response', status='ok', version=rest.version_server) xml_song_list = rest.make_listSongs('nowPlaying') root.append(xml_song_list) # TODO support NowPlayingEntry return rest.make_response(root)
def getLicense(self, **kwargs): rest = SubsonicREST(kwargs) success, response = rest.check_login() if not success: return response root = etree.Element('subsonic-response', status='ok', version=rest.version_server) etree.SubElement(root, 'license', valid='true', email='*****@*****.**', licenseExpires='2099-12-31T23:59:59') return rest.make_response(root)
def getShares(self, **kwargs): rest = SubsonicREST(kwargs) success, response = rest.check_login() if not success: return response root = etree.Element('subsonic-response', status='ok', version=rest.version_server) xml_shares = rest.make_Shares() root.append(xml_shares) # TODO support shares return rest.make_response(root)
def getIndexes(self, **kwargs): rest = SubsonicREST(kwargs) success, response = rest.check_login() if not success: return response ifModifiedSince = kwargs.get('ifModifiedSince') if ifModifiedSince: try: ifModifiedSince = int(ifModifiedSince) / 1000 except: return rest.make_error(code='0', message='Invalid timestamp') musicFolderId = kwargs.get('musicFolderId') if musicFolderId is None: folder = request.env['oomusic.folder'].search( [('root', '=', True)], limit=1) else: folder = request.env['oomusic.folder'].browse([int(musicFolderId)]) if not folder.exists(): return rest.make_error(code='70', message='Folder not found') root = etree.Element('subsonic-response', status='ok', version=rest.version_server) xml_indexes = rest.make_Indexes(folder) root.append(xml_indexes) if ifModifiedSince is not None and folder.last_modification < ifModifiedSince: return rest.make_response(root) # Build indexes indexes_dict = rest.build_dict_indexes_folder(folder) # List of folders for k, v in sorted(indexes_dict.iteritems()): xml_index = rest.make_Index(k) xml_indexes.append(xml_index) for child in v: xml_data = rest.make_Artist(child) xml_index.append(xml_data) # List of tracks for track in folder.track_ids: xml_data = rest.make_Child_track(track) xml_indexes.append(xml_data) return rest.make_response(root)
def getLyrics(self, **kwargs): rest = SubsonicREST(kwargs) success, response = rest.check_login() if not success: return response artist = kwargs.get('artist') title = kwargs.get('title') root = etree.Element('subsonic-response', status='ok', version=rest.version_server) xml_lyrics = rest.make_Lyrics(artist, title) root.append(xml_lyrics) return rest.make_response(root)
def download(self, **kwargs): rest = SubsonicREST(kwargs) success, response = rest.check_login() if not success: return response trackId = kwargs.get('id') if trackId: track = request.env['oomusic.track'].browse([int(trackId)]) if not track.exists(): return rest.make_error(code='70', message='Song not found') else: return rest.make_error( code='10', message='Required int parameter "id" is not present') return http.send_file(track.path, as_attachment=True)
def createPlaylist(self, **kwargs): rest = SubsonicREST(kwargs) success, response = rest.check_login() if not success: return response PlaylistObj = request.env['oomusic.playlist'] mode = 'create' playlistId = kwargs.get('id') if playlistId: playlist = PlaylistObj.browse([int(playlistId)]) if playlist.exists(): mode = 'update' name = kwargs.get('name') if mode == 'mode' and not name: return rest.make_error( code='10', message='Required str parameter "name" is not present') songId = kwargs.get('songId') if songId: track = request.env['oomusic.track'].browse([int(songId)]) if not track.exists(): return rest.make_error(code='70', message='Song not found') if mode == 'create': playlist = PlaylistObj.create({'name': name}) if playlist: playlist._add_tracks(track) root = etree.Element('subsonic-response', status='ok', version=rest.version_server) if API_VERSION_LIST[rest.version_client] >= API_VERSION_LIST['1.14.0']: xml_playlist = rest.make_Playlist(playlist) root.append(xml_playlist) for playlist_line in playlist.playlist_line_ids: xml_playlist_line = rest.make_Child_track( playlist_line.track_id, tag_name='entry') xml_playlist.append(xml_playlist_line) return rest.make_response(root)
def getRandomSongs(self, **kwargs): rest = SubsonicREST(kwargs) success, response = rest.check_login() if not success: return response TrackObj = request.env['oomusic.track'] fromYear = kwargs.get('fromYear') toYear = kwargs.get('toYear') genre = kwargs.get('genre') folderId = kwargs.get('musicFolderId') if folderId: folder = request.env['oomusic.folder'].browse([int(folderId)]) if not folder.exists(): return rest.make_error(code='70', message='Folder not found') size = min(int(kwargs.get('size', 10)), 500) # Build domain domain = [('id', 'child_of', int(folderId))] if folderId else [] if fromYear: domain += [('year', '>=', fromYear)] if toYear: domain += [('year', '<=', toYear)] if genre: domain += [('genre_id.name', 'ilike', genre)] track_ids = TrackObj.search(domain).ids if track_ids: track_ids = random.sample(track_ids, min(size, len(track_ids))) tracks = TrackObj.browse(track_ids) root = etree.Element('subsonic-response', status='ok', version=rest.version_server) xml_song_list = rest.make_listSongs('randomSongs') root.append(xml_song_list) for track in tracks: xml_song = rest.make_Child_track(track, tag_name='song') xml_song_list.append(xml_song) return rest.make_response(root)
def getPlaylists(self, **kwargs): rest = SubsonicREST(kwargs) success, response = rest.check_login() if not success: return response root = etree.Element('subsonic-response', status='ok', version=rest.version_server) xml_playlists = rest.make_Playlists() root.append(xml_playlists) for playlist in request.env['oomusic.playlist'].search([]): xml_playlist = rest.make_Playlist(playlist) xml_playlists.append(xml_playlist) return rest.make_response(root)
def getUsers(self, **kwargs): rest = SubsonicREST(kwargs) success, response = rest.check_login() if not success: return response root = etree.Element('subsonic-response', status='ok', version=rest.version_server) xml_users = rest.make_Users() root.append(xml_users) users = request.env['res.users'].search([]) for user in users: xml_user = rest.make_User(user) xml_users.append(xml_user) return rest.make_response(root)
def getMusicFolders(self, **kwargs): rest = SubsonicREST(kwargs) success, response = rest.check_login() if not success: return response root = etree.Element('subsonic-response', status='ok', version=rest.version_server) xml_music_folders = rest.make_MusicFolders() root.append(xml_music_folders) for folder in request.env['oomusic.folder'].search([('root', '=', True) ]): xml_music_folder = rest.make_MusicFolder(folder) xml_music_folders.append(xml_music_folder) return rest.make_response(root)