Example #1
0
 def test_versions_can_be_strictly_ordered(self):
     self.assert_(SV('0.1.0a0') < SV('0.1.0a1'))
     self.assert_(SV('0.1.0a1') < SV('0.1.0a2'))
     self.assert_(SV('0.1.0a2') < SV('0.1.0a3'))
     self.assert_(SV('0.1.0a3') < SV('0.1.0'))
     self.assert_(SV('0.1.0') < SV('0.2.0'))
     self.assert_(SV('0.1.0') < SV('1.0.0'))
     self.assert_(SV('0.2.0') < SV('0.3.0'))
     self.assert_(SV('0.3.0') < SV(get_version()))
     self.assert_(SV(get_version()) < SV('0.3.2'))
Example #2
0
File: log.py Project: Amli/mopidy
def setup_logging(verbosity_level, save_debug_log):
    setup_root_logger()
    setup_console_logging(verbosity_level)
    if save_debug_log:
        setup_debug_logging_to_file()
    logger = logging.getLogger('mopidy.utils.log')
    logger.info(u'Starting Mopidy %s on %s %s',
        get_version(), get_platform(), get_python())
Example #3
0
def setup_logging(verbosity_level, save_debug_log):
    setup_root_logger()
    setup_console_logging(verbosity_level)
    if save_debug_log:
        setup_debug_logging_to_file()
    logger = logging.getLogger('mopidy.utils.log')
    logger.info(u'Starting Mopidy %s on %s %s',
        get_version(), get_platform(), get_python())
Example #4
0
File: core.py Project: bok/mopidy
 def parse_options(self):
     parser = optparse.OptionParser(version='Mopidy %s' % get_version())
     parser.add_option('-q', '--quiet',
         action='store_const', const=0, dest='verbosity_level',
         help='less output (warning level)')
     parser.add_option('-v', '--verbose',
         action='store_const', const=2, dest='verbosity_level',
         help='more output (debug level)')
     parser.add_option('--save-debug-log',
         action='store_true', dest='save_debug_log',
         help='save debug log to "./mopidy.log"')
     parser.add_option('--list-settings',
         action='callback', callback=list_settings_optparse_callback,
         help='list current settings')
     return parser.parse_args()[0]
Example #5
0
File: core.py Project: Amli/mopidy
def parse_options():
    parser = optparse.OptionParser(version=u'Mopidy %s' % get_version())
    parser.add_option('--help-gst',
        action='store_true', dest='help_gst',
        help='show GStreamer help options')
    parser.add_option('-i', '--interactive',
        action='store_true', dest='interactive',
        help='ask interactively for required settings which is missing')
    parser.add_option('-q', '--quiet',
        action='store_const', const=0, dest='verbosity_level',
        help='less output (warning level)')
    parser.add_option('-v', '--verbose',
        action='store_const', const=2, dest='verbosity_level',
        help='more output (debug level)')
    parser.add_option('--save-debug-log',
        action='store_true', dest='save_debug_log',
        help='save debug log to "./mopidy.log"')
    parser.add_option('--list-settings',
        action='callback', callback=list_settings_optparse_callback,
        help='list current settings')
    return parser.parse_args(args=mopidy_args)[0]
Example #6
0
def parse_options():
    parser = optparse.OptionParser(version=u'Mopidy %s' % get_version())
    parser.add_option('--help-gst',
        action='store_true', dest='help_gst',
        help='show GStreamer help options')
    parser.add_option('-i', '--interactive',
        action='store_true', dest='interactive',
        help='ask interactively for required settings which are missing')
    parser.add_option('-q', '--quiet',
        action='store_const', const=0, dest='verbosity_level',
        help='less output (warning level)')
    parser.add_option('-v', '--verbose',
        action='count', default=1, dest='verbosity_level',
        help='more output (debug level)')
    parser.add_option('--save-debug-log',
        action='store_true', dest='save_debug_log',
        help='save debug log to "./mopidy.log"')
    parser.add_option('--list-settings',
        action='callback', callback=list_settings_optparse_callback,
        help='list current settings')
    return parser.parse_args(args=mopidy_args)[0]
Example #7
0
File: conf.py Project: Amli/mopidy
# The encoding of source files.
#source_encoding = 'utf-8'

# The master toctree document.
master_doc = 'index'

# General information about the project.
project = u'Mopidy'
copyright = u'2010-2011, Stein Magnus Jodal and contributors'

# The version info for the project you're documenting, acts as replacement for
# |version| and |release|, also used in various other places throughout the
# built documents.
#
# The full version, including alpha/beta/rc tags.
release = mopidy.get_version()
# The short X.Y version.
version = '.'.join(release.split('.')[:2])


# The language for content autogenerated by Sphinx. Refer to documentation
# for a list of supported languages.
#language = None

# There are two options for replacing |today|: either, you set today to some
# non-false value, then it is used:
#today = ''
# Else, today_fmt is used as the format for a strftime call.
#today_fmt = '%B %d, %Y'

# List of documents that shouldn't be included in the build.
Example #8
0
File: setup.py Project: bok/mopidy
        if dirname.startswith('.'):
            del dirnames[i]
    if '__init__.py' in filenames:
        packages.append('.'.join(fullsplit(dirpath)))
    elif filenames:
        data_files.append([dirpath,
            [os.path.join(dirpath, f) for f in filenames]])

if os.geteuid() == 0:
    # Only try to install this file if we are root
    data_files.append(
        ('/usr/local/share/applications', ['data/mopidy.desktop']))

setup(
    name='Mopidy',
    version=get_version(),
    author='Stein Magnus Jodal',
    author_email='*****@*****.**',
    packages=packages,
    package_data={'mopidy': ['backends/spotify/spotify_appkey.key']},
    cmdclass=cmdclasses,
    data_files=data_files,
    scripts=['bin/mopidy', 'bin/mopidy-scan'],
    url='http://www.mopidy.com/',
    license='Apache License, Version 2.0',
    description='MPD server with Spotify support',
    long_description=open('README.rst').read(),
    classifiers=[
        'Development Status :: 4 - Beta',
        'Environment :: No Input/Output (Daemon)',
        'Intended Audience :: End Users/Desktop',
Example #9
0
# The encoding of source files.
#source_encoding = 'utf-8'

# The master toctree document.
master_doc = 'index'

# General information about the project.
project = u'Mopidy'
copyright = u'2010-2011, Stein Magnus Jodal and contributors'

# The version info for the project you're documenting, acts as replacement for
# |version| and |release|, also used in various other places throughout the
# built documents.
#
# The full version, including alpha/beta/rc tags.
release = mopidy.get_version()
# The short X.Y version.
version = '.'.join(release.split('.')[:2])

# The language for content autogenerated by Sphinx. Refer to documentation
# for a list of supported languages.
#language = None

# There are two options for replacing |today|: either, you set today to some
# non-false value, then it is used:
#today = ''
# Else, today_fmt is used as the format for a strftime call.
#today_fmt = '%B %d, %Y'

# List of documents that shouldn't be included in the build.
#unused_docs = []
Example #10
0
project_dir = 'mopidy'

for dirpath, dirnames, filenames in os.walk(project_dir):
    # Ignore dirnames that start with '.'
    for i, dirname in enumerate(dirnames):
        if dirname.startswith('.'):
            del dirnames[i]
    if '__init__.py' in filenames:
        packages.append('.'.join(fullsplit(dirpath)))
    elif filenames:
        data_files.append(
            [dirpath, [os.path.join(dirpath, f) for f in filenames]])

setup(
    name='Mopidy',
    version=get_version(),
    author='Stein Magnus Jodal',
    author_email='*****@*****.**',
    packages=packages,
    package_data={'mopidy': ['backends/spotify/spotify_appkey.key']},
    cmdclass=cmdclasses,
    data_files=data_files,
    scripts=['bin/mopidy', 'bin/mopidy-scan'],
    url='http://www.mopidy.com/',
    license='Apache License, Version 2.0',
    description='MPD server with Spotify support',
    long_description=open('README.rst').read(),
    classifiers=[
        'Development Status :: 4 - Beta',
        'Environment :: No Input/Output (Daemon)',
        'Intended Audience :: End Users/Desktop',
Example #11
0
class SpotifySessionManager(BaseThread, PyspotifySessionManager):
    cache_location = settings.SPOTIFY_CACHE_PATH or CACHE_PATH
    settings_location = settings.SPOTIFY_CACHE_PATH or CACHE_PATH
    appkey_file = os.path.join(os.path.dirname(__file__), 'spotify_appkey.key')
    user_agent = 'Mopidy %s' % get_version()

    def __init__(self, username, password):
        PyspotifySessionManager.__init__(self, username, password)
        BaseThread.__init__(self)
        self.name = 'SpotifyThread'

        self.gstreamer = None
        self.backend = None

        self.connected = threading.Event()
        self.session = None

        self.container_manager = None
        self.playlist_manager = None

    def run_inside_try(self):
        self.setup()
        self.connect()

    def setup(self):
        gstreamer_refs = ActorRegistry.get_by_class(GStreamer)
        assert len(gstreamer_refs) == 1, \
            'Expected exactly one running gstreamer.'
        self.gstreamer = gstreamer_refs[0].proxy()

        backend_refs = ActorRegistry.get_by_class(Backend)
        assert len(backend_refs) == 1, 'Expected exactly one running backend.'
        self.backend = backend_refs[0].proxy()

    def logged_in(self, session, error):
        """Callback used by pyspotify"""
        if error:
            logger.error(u'Spotify login error: %s', error)
            return

        logger.info(u'Connected to Spotify')
        self.session = session

        logger.debug(u'Preferred Spotify bitrate is %s kbps',
                     settings.SPOTIFY_BITRATE)
        self.session.set_preferred_bitrate(BITRATES[settings.SPOTIFY_BITRATE])

        self.container_manager = SpotifyContainerManager(self)
        self.playlist_manager = SpotifyPlaylistManager(self)

        self.container_manager.watch(self.session.playlist_container())

        self.connected.set()

    def logged_out(self, session):
        """Callback used by pyspotify"""
        logger.info(u'Disconnected from Spotify')

    def metadata_updated(self, session):
        """Callback used by pyspotify"""
        logger.debug(u'Callback called: Metadata updated')

    def connection_error(self, session, error):
        """Callback used by pyspotify"""
        if error is None:
            logger.info(u'Spotify connection OK')
        else:
            logger.error(u'Spotify connection error: %s', error)
            self.backend.playback.pause()

    def message_to_user(self, session, message):
        """Callback used by pyspotify"""
        logger.debug(u'User message: %s', message.strip())

    def notify_main_thread(self, session):
        """Callback used by pyspotify"""
        logger.debug(u'notify_main_thread() called')

    def music_delivery(self, session, frames, frame_size, num_frames,
                       sample_type, sample_rate, channels):
        """Callback used by pyspotify"""
        # pylint: disable = R0913
        # Too many arguments (8/5)
        assert sample_type == 0, u'Expects 16-bit signed integer samples'
        capabilites = """
            audio/x-raw-int,
            endianness=(int)1234,
            channels=(int)%(channels)d,
            width=(int)16,
            depth=(int)16,
            signed=(boolean)true,
            rate=(int)%(sample_rate)d
        """ % {
            'sample_rate': sample_rate,
            'channels': channels,
        }
        self.gstreamer.emit_data(capabilites, bytes(frames))
        return num_frames

    def play_token_lost(self, session):
        """Callback used by pyspotify"""
        logger.debug(u'Play token lost')
        self.backend.playback.pause()

    def log_message(self, session, data):
        """Callback used by pyspotify"""
        logger.debug(u'System message: %s' % data.strip())

    def end_of_track(self, session):
        """Callback used by pyspotify"""
        logger.debug(u'End of data stream reached')
        self.gstreamer.emit_end_of_stream()

    def refresh_stored_playlists(self):
        """Refresh the stored playlists in the backend with fresh meta data
        from Spotify"""
        playlists = map(SpotifyTranslator.to_mopidy_playlist,
                        self.session.playlist_container())
        playlists = filter(None, playlists)
        self.backend.stored_playlists.playlists = playlists
        logger.debug(u'Refreshed %d stored playlist(s)', len(playlists))

    def search(self, query, queue):
        """Search method used by Mopidy backend"""
        def callback(results, userdata=None):
            # TODO Include results from results.albums(), etc. too
            # TODO Consider launching a second search if results.total_tracks()
            # is larger than len(results.tracks())
            playlist = Playlist(tracks=[
                SpotifyTranslator.to_mopidy_track(t) for t in results.tracks()
            ])
            queue.put(playlist)

        self.connected.wait()
        self.session.search(query,
                            callback,
                            track_count=100,
                            album_count=0,
                            artist_count=0)

    def logout(self):
        """Log out from spotify"""
        logger.debug(u'Logging out from Spotify')
        if self.session:
            self.session.logout()
Example #12
0
#source_encoding = 'utf-8'

# The master toctree document.
master_doc = 'index'

# General information about the project.
project = u'Mopidy'
copyright = u'2010-2012, Stein Magnus Jodal and contributors'

# The version info for the project you're documenting, acts as replacement for
# |version| and |release|, also used in various other places throughout the
# built documents.
#
# The full version, including alpha/beta/rc tags.
from mopidy import get_version
release = get_version()
# The short X.Y version.
version = '.'.join(release.split('.')[:2])

# The language for content autogenerated by Sphinx. Refer to documentation
# for a list of supported languages.
#language = None

# There are two options for replacing |today|: either, you set today to some
# non-false value, then it is used:
#today = ''
# Else, today_fmt is used as the format for a strftime call.
#today_fmt = '%B %d, %Y'

# List of documents that shouldn't be included in the build.
#unused_docs = []
Example #13
0
File: conf.py Project: Dvad/mopidy
#source_encoding = 'utf-8'

# The master toctree document.
master_doc = 'index'

# General information about the project.
project = u'Mopidy'
copyright = u'2010-2012, Stein Magnus Jodal and contributors'

# The version info for the project you're documenting, acts as replacement for
# |version| and |release|, also used in various other places throughout the
# built documents.
#
# The full version, including alpha/beta/rc tags.
from mopidy import get_version
release = get_version()
# The short X.Y version.
version = '.'.join(release.split('.')[:2])


# The language for content autogenerated by Sphinx. Refer to documentation
# for a list of supported languages.
#language = None

# There are two options for replacing |today|: either, you set today to some
# non-false value, then it is used:
#today = ''
# Else, today_fmt is used as the format for a strftime call.
#today_fmt = '%B %d, %Y'

# List of documents that shouldn't be included in the build.
Example #14
0
 def test_current_version_is_parsable_as_a_strict_version_number(self):
     SV(get_version())
Example #15
0
class SpotifySessionManager(BaseThread, PyspotifySessionManager):
    cache_location = settings.SPOTIFY_CACHE_PATH
    settings_location = cache_location
    appkey_file = os.path.join(os.path.dirname(__file__), 'spotify_appkey.key')
    user_agent = 'Mopidy %s' % get_version()

    def __init__(self, username, password):
        PyspotifySessionManager.__init__(self, username, password)
        BaseThread.__init__(self)
        self.name = 'SpotifyThread'

        self.audio = None
        self.backend = None

        self.connected = threading.Event()
        self.session = None

        self.container_manager = None
        self.playlist_manager = None

        self._initial_data_receive_completed = False

    def run_inside_try(self):
        self.setup()
        self.connect()

    def setup(self):
        audio_refs = ActorRegistry.get_by_class(audio.Audio)
        assert len(audio_refs) == 1, \
            'Expected exactly one running Audio instance.'
        self.audio = audio_refs[0].proxy()

        backend_refs = ActorRegistry.get_by_class(Backend)
        assert len(backend_refs) == 1, 'Expected exactly one running backend.'
        self.backend = backend_refs[0].proxy()

    def logged_in(self, session, error):
        """Callback used by pyspotify"""
        if error:
            logger.error(u'Spotify login error: %s', error)
            return

        logger.info(u'Connected to Spotify')
        self.session = session

        logger.debug(u'Preferred Spotify bitrate is %s kbps',
                     settings.SPOTIFY_BITRATE)
        self.session.set_preferred_bitrate(BITRATES[settings.SPOTIFY_BITRATE])

        self.container_manager = SpotifyContainerManager(self)
        self.playlist_manager = SpotifyPlaylistManager(self)

        self.container_manager.watch(self.session.playlist_container())

        self.connected.set()

    def logged_out(self, session):
        """Callback used by pyspotify"""
        logger.info(u'Disconnected from Spotify')

    def metadata_updated(self, session):
        """Callback used by pyspotify"""
        logger.debug(u'Callback called: Metadata updated')

    def connection_error(self, session, error):
        """Callback used by pyspotify"""
        if error is None:
            logger.info(u'Spotify connection OK')
        else:
            logger.error(u'Spotify connection error: %s', error)
            self.backend.playback.pause()

    def message_to_user(self, session, message):
        """Callback used by pyspotify"""
        logger.debug(u'User message: %s', message.strip())

    def music_delivery(self, session, frames, frame_size, num_frames,
                       sample_type, sample_rate, channels):
        """Callback used by pyspotify"""
        # pylint: disable = R0913
        # Too many arguments (8/5)
        assert sample_type == 0, u'Expects 16-bit signed integer samples'
        capabilites = """
            audio/x-raw-int,
            endianness=(int)1234,
            channels=(int)%(channels)d,
            width=(int)16,
            depth=(int)16,
            signed=(boolean)true,
            rate=(int)%(sample_rate)d
        """ % {
            'sample_rate': sample_rate,
            'channels': channels,
        }
        self.audio.emit_data(capabilites, bytes(frames))
        return num_frames

    def play_token_lost(self, session):
        """Callback used by pyspotify"""
        logger.debug(u'Play token lost')
        self.backend.playback.pause()

    def log_message(self, session, data):
        """Callback used by pyspotify"""
        logger.debug(u'System message: %s' % data.strip())
        if 'offline-mgr' in data and 'files unlocked' in data:
            # XXX This is a very very fragile and ugly hack, but we get no
            # proper event when libspotify is done with initial data loading.
            # We delay the expensive refresh of Mopidy's stored playlists until
            # this message arrives. This way, we avoid doing the refresh once
            # for every playlist or other change. This reduces the time from
            # startup until the Spotify backend is ready from 35s to 12s in one
            # test with clean Spotify cache. In cases with an outdated cache
            # the time improvements should be a lot better.
            self._initial_data_receive_completed = True
            self.refresh_stored_playlists()

    def end_of_track(self, session):
        """Callback used by pyspotify"""
        logger.debug(u'End of data stream reached')
        self.audio.emit_end_of_stream()

    def refresh_stored_playlists(self):
        """Refresh the stored playlists in the backend with fresh meta data
        from Spotify"""
        if not self._initial_data_receive_completed:
            logger.debug(u'Still getting data; skipped refresh of playlists')
            return
        playlists = map(SpotifyTranslator.to_mopidy_playlist,
                        self.session.playlist_container())
        playlists = filter(None, playlists)
        self.backend.stored_playlists.playlists = playlists
        logger.info(u'Loaded %d Spotify playlist(s)', len(playlists))

    def search(self, query, queue):
        """Search method used by Mopidy backend"""
        def callback(results, userdata=None):
            # TODO Include results from results.albums(), etc. too
            # TODO Consider launching a second search if results.total_tracks()
            # is larger than len(results.tracks())
            playlist = Playlist(tracks=[
                SpotifyTranslator.to_mopidy_track(t) for t in results.tracks()
            ])
            queue.put(playlist)

        self.connected.wait()
        self.session.search(query,
                            callback,
                            track_count=100,
                            album_count=0,
                            artist_count=0)

    def logout(self):
        """Log out from spotify"""
        logger.debug(u'Logging out from Spotify')
        if self.session:
            self.session.logout()