Ejemplo n.º 1
0
    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)
Ejemplo n.º 2
0
    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)
Ejemplo n.º 3
0
    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.')
Ejemplo n.º 4
0
    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')
Ejemplo n.º 5
0
    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)
Ejemplo n.º 6
0
    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.')
Ejemplo n.º 7
0
    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)
Ejemplo n.º 8
0
    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)
Ejemplo n.º 9
0
    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)
Ejemplo n.º 10
0
    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)
Ejemplo n.º 11
0
    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)
Ejemplo n.º 12
0
    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)
Ejemplo n.º 13
0
    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)
Ejemplo n.º 14
0
    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)
Ejemplo n.º 15
0
    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)
Ejemplo n.º 16
0
    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)
Ejemplo n.º 17
0
    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)
Ejemplo n.º 18
0
    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)
Ejemplo n.º 19
0
    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)
Ejemplo n.º 20
0
    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)
Ejemplo n.º 21
0
    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)
Ejemplo n.º 22
0
    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)
Ejemplo n.º 23
0
    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)
Ejemplo n.º 24
0
    def getAvatar(self, **kwargs):
        rest = SubsonicREST(kwargs)
        success, response = rest.check_login()
        if not success:
            return response

        username = kwargs.get('username')
        if not username:
            return rest.make_error(
                code='10',
                message='Required str parameter "username" is not present')

        user = request.env['res.users'].search([('login', '=', username)])

        image = user.partner_id.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=str(user.id) + image_ext)
Ejemplo n.º 25
0
    def getGenres(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_genres = rest.make_Genres()
        root.append(xml_genres)

        # For some mysterious reason, in this particular route, the xml declaration should be made
        # with double quotes instead of simple quotes.
        response =\
            '<?xml version="1.0" encoding="UTF-8"?>\n'\
            + etree.tostring(root, encoding='UTF-8', pretty_print=True)
        return request.make_response(response)
Ejemplo n.º 26
0
    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)
Ejemplo n.º 27
0
    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)
Ejemplo n.º 28
0
    def getStarred2(self, **kwargs):
        rest = SubsonicREST(kwargs)
        success, response = rest.check_login()
        if not success:
            return response

        ArtistObj = request.env['oomusic.artist']
        AlbumObj = request.env['oomusic.album']
        TrackObj = request.env['oomusic.track']

        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')
        domain = [('id', 'child_of', int(folderId))] if folderId else []

        root = etree.Element('subsonic-response',
                             status='ok',
                             version=rest.version_server)
        xml_starred_list = rest.make_listSongs('starred2')
        root.append(xml_starred_list)

        artists = ArtistObj.search(domain + [('star', '=', '1')])
        albums = AlbumObj.search(domain + [('star', '=', '1')])
        tracks = TrackObj.search(domain + [('star', '=', '1')])

        for artist in artists:
            xml_artist = rest.make_ArtistID3(artist)
            xml_starred_list.append(xml_artist)

        for album in albums:
            xml_album = rest.make_AlbumID3(album)
            xml_starred_list.append(xml_album)

        for track in tracks:
            xml_song = rest.make_Child_track(track, tag_name='song')
            xml_starred_list.append(xml_song)

        return rest.make_response(root)
Ejemplo n.º 29
0
    def getSongsByGenre(self, **kwargs):
        rest = SubsonicREST(kwargs)
        success, response = rest.check_login()
        if not success:
            return response

        TrackObj = request.env['oomusic.track']

        genre = kwargs.get('genre')
        if not genre:
            return rest.make_error(
                code='10',
                message='Required str parameter "genre" is not present')

        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)
        offset = int(kwargs.get('offset', 0))

        # Build domain
        domain = [('id', 'child_of', int(folderId))] if folderId else []
        domain += [('genre_id.name', '=', genre)]

        root = etree.Element('subsonic-response',
                             status='ok',
                             version=rest.version_server)
        xml_song_list = rest.make_listSongs('songsByGenre')
        root.append(xml_song_list)

        tracks = TrackObj.search(domain)

        if tracks:
            min_val = min(offset, len(tracks))
            max_val = min_val + size
            for track in tracks[min_val:max_val]:
                xml_song = rest.make_Child_track(track, tag_name='song')
                xml_song_list.append(xml_song)

        return rest.make_response(root)
Ejemplo n.º 30
0
    def getStarred(self, **kwargs):
        rest = SubsonicREST(kwargs)
        success, response = rest.check_login()
        if not success:
            return response

        FolderObj = request.env['oomusic.folder']
        TrackObj = request.env['oomusic.track']

        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')
        domain = [('id', 'child_of', int(folderId))] if folderId else []

        root = etree.Element('subsonic-response',
                             status='ok',
                             version=rest.version_server)
        xml_starred_list = rest.make_listSongs('starred')
        root.append(xml_starred_list)

        folders = FolderObj.search(domain + [('star', '=', '1')])
        tracks = TrackObj.search(domain + [('star', '=', '1')])

        for folder in folders.sorted(lambda r: len(r.track_ids)):
            if not folder.track_ids:
                xml_folder = rest.make_Artist(folder)
            else:
                xml_folder = rest.make_Child_folder(folder, tag_name='album')
            xml_starred_list.append(xml_folder)

        for track in tracks:
            xml_song = rest.make_Child_track(track, tag_name='song')
            xml_starred_list.append(xml_song)

        return rest.make_response(root)