<commit_before>import datetime as dt
import logging
import multiprocessing
import threading

from spotify import Link
from spotify.manager import SpotifySessionManager
from spotify.alsahelper import AlsaController

from mopidy import settings
from mopidy.backends import (BaseBackend, BaseCurrentPlaylistController,
    BaseLibraryController, BasePlaybackController,
    BaseStoredPlaylistsController)
from mopidy.models import Artist, Album, Track, Playlist

logger = logging.getLogger('mopidy.backends.libspotify')

ENCODING = 'utf-8'

class LibspotifyBackend(BaseBackend):
    """
    A Spotify backend which uses the official `libspotify library
    <http://developer.spotify.com/en/libspotify/overview/>`_.

    `pyspotify <http://github.com/winjer/pyspotify/>`_ is the Python bindings
    for libspotify. It got no documentation, but multiple examples are
    available. Like libspotify, pyspotify's calls are mostly asynchronous.

    This backend should also work with `openspotify
    <http://github.com/noahwilliamsson/openspotify>`_, but we haven't tested
    that yet.

    **Issues**

    - libspotify is badly packaged. See
      http://getsatisfaction.com/spotify/topics/libspotify_please_fix_the_installation_script.
    """

    def __init__(self, *args, **kwargs):
        super(LibspotifyBackend, self).__init__(*args, **kwargs)
        self.current_playlist = LibspotifyCurrentPlaylistController(
            backend=self)
        self.library = LibspotifyLibraryController(backend=self)
        self.playback = LibspotifyPlaybackController(backend=self)
        self.stored_playlists = LibspotifyStoredPlaylistsController(
            backend=self)
        self.uri_handlers = [u'spotify:', u'http://open.spotify.com/']
        self.spotify = self._connect()

    def _connect(self):
        logger.info(u'Connecting to Spotify')
        spotify = LibspotifySessionManager(
            settings.SPOTIFY_USERNAME, settings.SPOTIFY_PASSWORD,
            core_queue=self.core_queue)
        spotify.start()
        return spotify


class LibspotifyCurrentPlaylistController(BaseCurrentPlaylistController):
    pass


class LibspotifyLibraryController(BaseLibraryController):
    def search(self, type, what):
        if type is u'any':
            query = what
        else:
            query = u'%s:%s' % (type, what)
        my_end, other_end = multiprocessing.Pipe()
        self.backend.spotify.search(query.encode(ENCODING), other_end)
        my_end.poll(None)
        logger.debug(u'In search method, receiving search results')
        playlist = my_end.recv()
        logger.debug(u'In search method, done receiving search results')
        logger.debug(['%s' % t.name for t in playlist.tracks])
        return playlist

    find_exact = search


class LibspotifyPlaybackController(BasePlaybackController):
    def _pause(self):
        # TODO
        return False

    def _play(self, track):
        if self.state == self.PLAYING:
            self.stop()
        if track.uri is None:
            return False
        self.backend.spotify.session.load(
            Link.from_string(track.uri).as_track())
        self.backend.spotify.session.play(1)
        return True

    def _resume(self):
        # TODO
        return False

    def _stop(self):
        self.backend.spotify.session.play(0)
        return True


class LibspotifyStoredPlaylistsController(BaseStoredPlaylistsController):
    pass


class LibspotifyTranslator(object):
    uri_to_id_map = {}
    next_id = 0

    def to_mopidy_id(self, spotify_uri):
        if spotify_uri not in self.uri_to_id_map:
            this_id = self.next_id
            self.next_id += 1
            self.uri_to_id_map[spotify_uri] = this_id
        return self.uri_to_id_map[spotify_uri]

    def to_mopidy_artist(self, spotify_artist):
        if not spotify_artist.is_loaded():
            return Artist(name=u'[loading...]')
        return Artist(
            uri=str(Link.from_artist(spotify_artist)),
            name=spotify_artist.name().decode(ENCODING),
        )

    def to_mopidy_album(self, spotify_album):
        if not spotify_album.is_loaded():
            return Album(name=u'[loading...]')
        # TODO pyspotify got much more data on albums than this
        return Album(name=spotify_album.name().decode(ENCODING))

    def to_mopidy_track(self, spotify_track):
        if not spotify_track.is_loaded():
            return Track(name=u'[loading...]')
        uri = str(Link.from_track(spotify_track, 0))
        return Track(
            uri=uri,
            name=spotify_track.name().decode(ENCODING),
            artists=[self.to_mopidy_artist(a) for a in spotify_track.artists()],
            album=self.to_mopidy_album(spotify_track.album()),
            track_no=spotify_track.index(),
            date=dt.date(spotify_track.album().year(), 1, 1),
            length=spotify_track.duration(),
            bitrate=320,
            id=self.to_mopidy_id(uri),
        )

    def to_mopidy_playlist(self, spotify_playlist):
        if not spotify_playlist.is_loaded():
            return Playlist(name=u'[loading...]')
        return Playlist(
            uri=str(Link.from_playlist(spotify_playlist)),
            name=spotify_playlist.name().decode(ENCODING),
            tracks=[self.to_mopidy_track(t) for t in spotify_playlist],
        )


class LibspotifySessionManager(SpotifySessionManager, threading.Thread):
    def __init__(self, username, password, core_queue):
        SpotifySessionManager.__init__(self, username, password)
        threading.Thread.__init__(self)
        self.core_queue = core_queue
        self.connected = threading.Event()
        self.translate = LibspotifyTranslator()
        self.audio = AlsaController()
        self.playlists = []

    def run(self):
        self.connect()

    def logged_in(self, session, error):
        """Callback used by pyspotify"""
        logger.info('Logged in')
        self.session = session
        try:
            self.playlists = session.playlist_container()
            logger.debug('Got playlist container')
        except Exception, e:
            logger.exception(e)
        self.connected.set()

    def logged_out(self, session):
        """Callback used by pyspotify"""
        logger.info('Logged out')

    def metadata_updated(self, session):
        """Callback used by pyspotify"""
        logger.debug('Metadata updated')
        playlists = []
        for spotify_playlist in session.playlist_container():
            playlists.append(
                self.translate.to_mopidy_playlist(spotify_playlist))
        self.core_queue.put({
            'command': 'set_stored_playlists',<commit_msg>libspotify: Remove unused code<commit_after>import datetime as dt
import logging
import multiprocessing
import threading

from spotify import Link
from spotify.manager import SpotifySessionManager
from spotify.alsahelper import AlsaController

from mopidy import settings
from mopidy.backends import (BaseBackend, BaseCurrentPlaylistController,
    BaseLibraryController, BasePlaybackController,
    BaseStoredPlaylistsController)
from mopidy.models import Artist, Album, Track, Playlist

logger = logging.getLogger('mopidy.backends.libspotify')

ENCODING = 'utf-8'

class LibspotifyBackend(BaseBackend):
    """
    A Spotify backend which uses the official `libspotify library
    <http://developer.spotify.com/en/libspotify/overview/>`_.

    `pyspotify <http://github.com/winjer/pyspotify/>`_ is the Python bindings
    for libspotify. It got no documentation, but multiple examples are
    available. Like libspotify, pyspotify's calls are mostly asynchronous.

    This backend should also work with `openspotify
    <http://github.com/noahwilliamsson/openspotify>`_, but we haven't tested
    that yet.

    **Issues**

    - libspotify is badly packaged. See
      http://getsatisfaction.com/spotify/topics/libspotify_please_fix_the_installation_script.
    """

    def __init__(self, *args, **kwargs):
        super(LibspotifyBackend, self).__init__(*args, **kwargs)
        self.current_playlist = LibspotifyCurrentPlaylistController(
            backend=self)
        self.library = LibspotifyLibraryController(backend=self)
        self.playback = LibspotifyPlaybackController(backend=self)
        self.stored_playlists = LibspotifyStoredPlaylistsController(
            backend=self)
        self.uri_handlers = [u'spotify:', u'http://open.spotify.com/']
        self.spotify = self._connect()

    def _connect(self):
        logger.info(u'Connecting to Spotify')
        spotify = LibspotifySessionManager(
            settings.SPOTIFY_USERNAME, settings.SPOTIFY_PASSWORD,
            core_queue=self.core_queue)
        spotify.start()
        return spotify


class LibspotifyCurrentPlaylistController(BaseCurrentPlaylistController):
    pass


class LibspotifyLibraryController(BaseLibraryController):
    def search(self, type, what):
        if type is u'any':
            query = what
        else:
            query = u'%s:%s' % (type, what)
        my_end, other_end = multiprocessing.Pipe()
        self.backend.spotify.search(query.encode(ENCODING), other_end)
        my_end.poll(None)
        logger.debug(u'In search method, receiving search results')
        playlist = my_end.recv()
        logger.debug(u'In search method, done receiving search results')
        logger.debug(['%s' % t.name for t in playlist.tracks])
        return playlist

    find_exact = search


class LibspotifyPlaybackController(BasePlaybackController):
    def _pause(self):
        # TODO
        return False

    def _play(self, track):
        if self.state == self.PLAYING:
            self.stop()
        if track.uri is None:
            return False
        self.backend.spotify.session.load(
            Link.from_string(track.uri).as_track())
        self.backend.spotify.session.play(1)
        return True

    def _resume(self):
        # TODO
        return False

    def _stop(self):
        self.backend.spotify.session.play(0)
        return True


class LibspotifyStoredPlaylistsController(BaseStoredPlaylistsController):
    pass


class LibspotifyTranslator(object):
    uri_to_id_map = {}
    next_id = 0

    def to_mopidy_id(self, spotify_uri):
        if spotify_uri not in self.uri_to_id_map:
            this_id = self.next_id
            self.next_id += 1
            self.uri_to_id_map[spotify_uri] = this_id
        return self.uri_to_id_map[spotify_uri]

    def to_mopidy_artist(self, spotify_artist):
        if not spotify_artist.is_loaded():
            return Artist(name=u'[loading...]')
        return Artist(
            uri=str(Link.from_artist(spotify_artist)),
            name=spotify_artist.name().decode(ENCODING),
        )

    def to_mopidy_album(self, spotify_album):
        if not spotify_album.is_loaded():
            return Album(name=u'[loading...]')
        # TODO pyspotify got much more data on albums than this
        return Album(name=spotify_album.name().decode(ENCODING))

    def to_mopidy_track(self, spotify_track):
        if not spotify_track.is_loaded():
            return Track(name=u'[loading...]')
        uri = str(Link.from_track(spotify_track, 0))
        return Track(
            uri=uri,
            name=spotify_track.name().decode(ENCODING),
            artists=[self.to_mopidy_artist(a) for a in spotify_track.artists()],
            album=self.to_mopidy_album(spotify_track.album()),
            track_no=spotify_track.index(),
            date=dt.date(spotify_track.album().year(), 1, 1),
            length=spotify_track.duration(),
            bitrate=320,
            id=self.to_mopidy_id(uri),
        )

    def to_mopidy_playlist(self, spotify_playlist):
        if not spotify_playlist.is_loaded():
            return Playlist(name=u'[loading...]')
        return Playlist(
            uri=str(Link.from_playlist(spotify_playlist)),
            name=spotify_playlist.name().decode(ENCODING),
            tracks=[self.to_mopidy_track(t) for t in spotify_playlist],
        )


class LibspotifySessionManager(SpotifySessionManager, threading.Thread):
    def __init__(self, username, password, core_queue):
        SpotifySessionManager.__init__(self, username, password)
        threading.Thread.__init__(self)
        self.core_queue = core_queue
        self.connected = threading.Event()
        self.translate = LibspotifyTranslator()
        self.audio = AlsaController()

    def run(self):
        self.connect()

    def logged_in(self, session, error):
        """Callback used by pyspotify"""
        logger.info('Logged in')
        self.session = session
        self.connected.set()

    def logged_out(self, session):
        """Callback used by pyspotify"""
        logger.info('Logged out')

    def metadata_updated(self, session):
        """Callback used by pyspotify"""
        logger.debug('Metadata updated, refreshing stored playlists')
        playlists = []
        for spotify_playlist in session.playlist_container():
            playlists.append(
                self.translate.to_mopidy_playlist(spotify_playlist))
        self.core_queue.put({
            'command': 'set_stored_playlists',
{'fraction_non_alphanumeric': 0.09755358630614254, 'fraction_numerical': 0.001666287964856472, 'mean_word_length': 2.8139803581744656, 'pattern_counts': {'":': 0, '<': 9, '<?xml version=': 0, '>': 9, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '7194849', 'n_tokens_mistral': 4008, 'n_tokens_neox': 3889, 'n_words': 792}