Beispiel #1
0
    def check_dirs_and_files(self):
        if not os.path.isdir(self.config["local"]["media_dir"]):
            logger.warning("Local media dir %s does not exist." % self.config["local"]["media_dir"])

        try:
            path.get_or_create_dir(self.config["local"]["data_dir"])
        except EnvironmentError as error:
            logger.warning("Could not create local data dir: %s", encoding.locale_decode(error))

        # TODO: replace with data dir?
        try:
            path.get_or_create_dir(self.config["local"]["playlists_dir"])
        except EnvironmentError as error:
            logger.warning("Could not create local playlists dir: %s", encoding.locale_decode(error))
Beispiel #2
0
def _process(pipeline, timeout_ms):
    clock = pipeline.get_clock()
    bus = pipeline.get_bus()
    timeout = timeout_ms * gst.MSECOND
    tags, mime, have_audio, missing_description = {}, None, False, None

    types = (
        gst.MESSAGE_ELEMENT
        | gst.MESSAGE_APPLICATION
        | gst.MESSAGE_ERROR
        | gst.MESSAGE_EOS
        | gst.MESSAGE_ASYNC_DONE
        | gst.MESSAGE_TAG
    )

    start = clock.get_time()
    while timeout > 0:
        message = bus.timed_pop_filtered(timeout, types)

        if message is None:
            break
        elif message.type == gst.MESSAGE_ELEMENT:
            if gst.pbutils.is_missing_plugin_message(message):
                missing_description = encoding.locale_decode(_missing_plugin_desc(message))
        elif message.type == gst.MESSAGE_APPLICATION:
            if message.structure.get_name() == "have-type":
                mime = message.structure["caps"].get_name()
                if mime.startswith("text/") or mime == "application/xml":
                    return tags, mime, have_audio
            elif message.structure.get_name() == "have-audio":
                have_audio = True
        elif message.type == gst.MESSAGE_ERROR:
            error = encoding.locale_decode(message.parse_error()[0])
            if missing_description:
                error = "%s (%s)" % (missing_description, error)
            raise exceptions.ScannerError(error)
        elif message.type == gst.MESSAGE_EOS:
            return tags, mime, have_audio
        elif message.type == gst.MESSAGE_ASYNC_DONE:
            if message.src == pipeline:
                return tags, mime, have_audio
        elif message.type == gst.MESSAGE_TAG:
            taglist = message.parse_tag()
            # Note that this will only keep the last tag.
            tags.update(utils.convert_taglist(taglist))

        timeout -= clock.get_time() - start

    raise exceptions.ScannerError("Timeout after %dms" % timeout_ms)
Beispiel #3
0
    def test_can_decode_utf8_strings_with_french_content(self, mock):
        mock.return_value = 'UTF-8'

        result = locale_decode(
            b'[Errno 98] Adresse d\xc3\xa9j\xc3\xa0 utilis\xc3\xa9e')

        self.assertEqual('[Errno 98] Adresse d\xe9j\xe0 utilis\xe9e', result)
Beispiel #4
0
    def _collect(self):
        """Polls for messages to collect data."""
        start = time.time()
        timeout_s = self._timeout_ms / float(1000)
        tags = {}

        while time.time() - start < timeout_s:
            if not self._bus.have_pending():
                continue
            message = self._bus.pop()

            if message.type == gst.MESSAGE_ERROR:
                raise exceptions.ScannerError(
                    encoding.locale_decode(message.parse_error()[0]))
            elif message.type == gst.MESSAGE_EOS:
                return tags
            elif message.type == gst.MESSAGE_ASYNC_DONE:
                if message.src == self._pipe:
                    return tags
            elif message.type == gst.MESSAGE_TAG:
                # Taglists are not really dicts, hence the lack of .items() and
                # explicit .keys. We only keep the last tag for each key, as we
                # assume this is the best, some formats will produce multiple
                # taglists. Lastly we force everything to lists for conformity.
                taglist = message.parse_tag()
                for key in taglist.keys():
                    value = taglist[key]
                    if not isinstance(value, list):
                        value = [value]
                    tags[key] = value

        raise exceptions.ScannerError('Timeout after %dms' % self._timeout_ms)
Beispiel #5
0
    def check_dirs_and_files(self):
        if not os.path.isdir(self.config['local']['media_dir']):
            logger.warning('Local media dir %s does not exist.' %
                           self.config['local']['media_dir'])

        try:
            path.get_or_create_dir(self.config['local']['playlists_dir'])
        except EnvironmentError as error:
            logger.warning('Could not create local playlists dir: %s',
                           encoding.locale_decode(error))

        try:
            path.get_or_create_file(self.config['local']['tag_cache_file'])
        except EnvironmentError as error:
            logger.warning('Could not create empty tag cache file: %s',
                           encoding.locale_decode(error))
Beispiel #6
0
    def __init__(self, config, core):
        super(MpdFrontend, self).__init__()

        hostname = network.format_hostname(config['mpd']['hostname'])
        self.hostname = hostname
        self.port = config['mpd']['port']
        self.zeroconf_name = config['mpd']['zeroconf']
        self.zeroconf_service = None

        try:
            network.Server(
                self.hostname, self.port,
                protocol=session.MpdSession,
                protocol_kwargs={
                    'config': config,
                    'core': core,
                },
                max_connections=config['mpd']['max_connections'],
                timeout=config['mpd']['connection_timeout'])
        except IOError as error:
            logger.error(
                'MPD server startup failed: %s',
                encoding.locale_decode(error))
            sys.exit(1)

        logger.info('MPD server running at [%s]:%s', self.hostname, self.port)
Beispiel #7
0
    def test_can_decode_an_ioerror_with_french_content(self, mock):
        mock.return_value = 'UTF-8'

        error = IOError(98, b'Adresse d\xc3\xa9j\xc3\xa0 utilis\xc3\xa9e')
        result = locale_decode(error)

        self.assertEquals('[Errno 98] Adresse d\xe9j\xe0 utilis\xe9e', result)
Beispiel #8
0
    def test_can_decode_utf8_strings_with_french_content(self, mock):
        mock.return_value = 'UTF-8'

        result = locale_decode(
            b'[Errno 98] Adresse d\xc3\xa9j\xc3\xa0 utilis\xc3\xa9e')

        self.assertEqual('[Errno 98] Adresse d\xe9j\xe0 utilis\xe9e', result)
Beispiel #9
0
    def _collect(self):
        """Polls for messages to collect data."""
        start = time.time()
        timeout_s = self._timeout_ms / float(1000)
        tags = {}

        while time.time() - start < timeout_s:
            if not self._bus.have_pending():
                continue
            message = self._bus.pop()

            if message.type == gst.MESSAGE_ERROR:
                raise exceptions.ScannerError(
                    encoding.locale_decode(message.parse_error()[0]))
            elif message.type == gst.MESSAGE_EOS:
                return tags
            elif message.type == gst.MESSAGE_ASYNC_DONE:
                if message.src == self._pipe:
                    return tags
            elif message.type == gst.MESSAGE_TAG:
                # Taglists are not really dicts, hence the lack of .items() and
                # explicit .keys. We only keep the last tag for each key, as we
                # assume this is the best, some formats will produce multiple
                # taglists. Lastly we force everything to lists for conformity.
                taglist = message.parse_tag()
                for key in taglist.keys():
                    value = taglist[key]
                    if not isinstance(value, list):
                        value = [value]
                    tags[key] = value

        raise exceptions.ScannerError('Timeout after %dms' % self._timeout_ms)
Beispiel #10
0
    def __init__(self, config, core):
        super(MpdFrontend, self).__init__()

        self.hostname = network.format_hostname(config['mpd']['hostname'])
        self.port = config['mpd']['port']

        self.zeroconf_name = config['mpd']['zeroconf']
        self.zeroconf_service = None

        try:
            network.Server(
                self.hostname, self.port,
                protocol=session.MpdSession,
                protocol_kwargs={
                    'config': config,
                    'core': core,
                },
                max_connections=config['mpd']['max_connections'],
                timeout=config['mpd']['connection_timeout'])
        except IOError as error:
            raise exceptions.FrontendError(
                'MPD server startup failed: %s' %
                encoding.locale_decode(error))

        logger.info('MPD server running at [%s]:%s', self.hostname, self.port)
Beispiel #11
0
    def check_dirs_and_files(self):
        if not os.path.isdir(self.config['local']['media_dir']):
            logger.warning('Local media dir %s does not exist.' %
                           self.config['local']['media_dir'])

        try:
            path.get_or_create_dir(self.config['local']['data_dir'])
        except EnvironmentError as error:
            logger.warning('Could not create local data dir: %s',
                           encoding.locale_decode(error))

        # TODO: replace with data dir?
        try:
            path.get_or_create_dir(self.config['local']['playlists_dir'])
        except EnvironmentError as error:
            logger.warning('Could not create local playlists dir: %s',
                           encoding.locale_decode(error))
Beispiel #12
0
    def check_dirs_and_files(self):
        if not os.path.isdir(self.config['local']['media_dir']):
            logger.warning('Local media dir %s does not exist.' %
                           self.config['local']['media_dir'])

        try:
            path.get_or_create_dir(self.config['local']['playlists_dir'])
        except EnvironmentError as error:
            logger.warning(
                'Could not create local playlists dir: %s',
                encoding.locale_decode(error))

        try:
            path.get_or_create_file(self.config['local']['tag_cache_file'])
        except EnvironmentError as error:
            logger.warning(
                'Could not create empty tag cache file: %s',
                encoding.locale_decode(error))
Beispiel #13
0
def _process(pipeline, timeout_ms):
    clock = pipeline.get_clock()
    bus = pipeline.get_bus()
    timeout = timeout_ms * gst.MSECOND
    tags, mime, have_audio, missing_description = {}, None, False, None

    types = (gst.MESSAGE_ELEMENT | gst.MESSAGE_APPLICATION | gst.MESSAGE_ERROR
             | gst.MESSAGE_EOS | gst.MESSAGE_ASYNC_DONE | gst.MESSAGE_TAG)

    start = clock.get_time()
    while timeout > 0:
        message = bus.timed_pop_filtered(timeout, types)

        if message is None:
            break
        elif message.type == gst.MESSAGE_ELEMENT:
            if gst.pbutils.is_missing_plugin_message(message):
                missing_description = encoding.locale_decode(
                    _missing_plugin_desc(message))
        elif message.type == gst.MESSAGE_APPLICATION:
            if message.structure.get_name() == 'have-type':
                mime = message.structure['caps'].get_name()
                if mime.startswith('text/') or mime == 'application/xml':
                    return tags, mime, have_audio
            elif message.structure.get_name() == 'have-audio':
                have_audio = True
        elif message.type == gst.MESSAGE_ERROR:
            error = encoding.locale_decode(message.parse_error()[0])
            if missing_description:
                error = '%s (%s)' % (missing_description, error)
            raise exceptions.ScannerError(error)
        elif message.type == gst.MESSAGE_EOS:
            return tags, mime, have_audio
        elif message.type == gst.MESSAGE_ASYNC_DONE:
            if message.src == pipeline:
                return tags, mime, have_audio
        elif message.type == gst.MESSAGE_TAG:
            taglist = message.parse_tag()
            # Note that this will only keep the last tag.
            tags.update(utils.convert_taglist(taglist))

        timeout -= clock.get_time() - start

    raise exceptions.ScannerError('Timeout after %dms' % timeout_ms)
Beispiel #14
0
def _send_broadcast(client, msg):
    # We could check for client.ws_connection, but we don't really
    # care why the broadcast failed, we just want the rest of them
    # to succeed, so catch everything.
    try:
        client.write_message(msg)
    except Exception as e:
        error_msg = encoding.locale_decode(e)
        logger.debug('Broadcast of WebSocket message to %s failed: %s',
                     client.request.remote_ip, error_msg)
Beispiel #15
0
def check_dirs_and_files(config):
    if not os.path.isdir(config['local']['media_dir']):
        logger.warning('Local media dir %s does not exist.' %
                       config['local']['media_dir'])

    try:
        path.get_or_create_dir(config['local']['data_dir'])
    except EnvironmentError as error:
        logger.warning('Could not create local data dir: %s',
                       encoding.locale_decode(error))
Beispiel #16
0
    def test_can_decode_an_ioerror_with_french_content(self, mock):
        mock.return_value = 'UTF-8'

        error = IOError(98, b'Adresse d\xc3\xa9j\xc3\xa0 utilis\xc3\xa9e')
        result = locale_decode(error)
        expected = '[Errno 98] Adresse d\xe9j\xe0 utilis\xe9e'

        self.assertEqual(
            expected, result, '%r decoded to %r does not match expected %r' %
            (error, result, expected))
Beispiel #17
0
    def __init__(self, frontend, serial_port, serial_bps):
        super(SerialMonoboxController, self).__init__()
        try:
            self.s = serial.Serial(serial_port, serial_bps, timeout=0.5)
        except Exception as error:
            raise exceptions.FrontendError('SMC serial connection failed: %s' %
                    encoding.locale_decode(error))

        self.frontend = frontend
        self.buffer = ''
Beispiel #18
0
def _send_broadcast(client, msg):
    # We could check for client.ws_connection, but we don't really
    # care why the broadcast failed, we just want the rest of them
    # to succeed, so catch everything.
    try:
        client.write_message(msg)
    except Exception as e:
        error_msg = encoding.locale_decode(e)
        logger.debug('Broadcast of WebSocket message to %s failed: %s',
                     client.request.remote_ip, error_msg)
Beispiel #19
0
 def send(self, data):
     """Send data to client, return any unsent data."""
     try:
         sent = self.sock.send(data)
         return data[sent:]
     except socket.error as e:
         if e.errno in (errno.EWOULDBLOCK, errno.EINTR):
             return data
         self.stop(
             'Unexpected client error: %s' % encoding.locale_decode(e))
         return b''
Beispiel #20
0
def check_dirs_and_files(config):
    if not os.path.isdir(config['local']['media_dir']):
        logger.warning(
            'Local media dir %s does not exist.' %
            config['local']['media_dir'])

    try:
        path.get_or_create_dir(config['local']['data_dir'])
    except EnvironmentError as error:
        logger.warning(
            'Could not create local data dir: %s',
            encoding.locale_decode(error))

    # TODO: replace with data dir?
    try:
        path.get_or_create_dir(config['local']['playlists_dir'])
    except EnvironmentError as error:
        logger.warning(
            'Could not create local playlists dir: %s',
            encoding.locale_decode(error))
Beispiel #21
0
    def test_can_decode_an_ioerror_with_french_content(self, mock):
        mock.return_value = 'UTF-8'

        error = IOError(98, b'Adresse d\xc3\xa9j\xc3\xa0 utilis\xc3\xa9e')
        result = locale_decode(error)
        expected = '[Errno 98] Adresse d\xe9j\xe0 utilis\xe9e'

        self.assertEqual(
            expected, result,
            '%r decoded to %r does not match expected %r' % (
                error, result, expected))
Beispiel #22
0
def try_ipv6_socket():
    """Determine if system really supports IPv6"""
    if not socket.has_ipv6:
        return False
    try:
        socket.socket(socket.AF_INET6).close()
        return True
    except IOError as error:
        logger.debug(
            'Platform supports IPv6, but socket creation failed, '
            'disabling: %s', encoding.locale_decode(error))
    return False
Beispiel #23
0
def try_ipv6_socket():
    """Determine if system really supports IPv6"""
    if not socket.has_ipv6:
        return False
    try:
        socket.socket(socket.AF_INET6).close()
        return True
    except IOError as error:
        logger.debug(
            "Platform supports IPv6, but socket creation failed, " "disabling: %s", encoding.locale_decode(error)
        )
    return False
Beispiel #24
0
    def __init__(self, config, audio):
        super(M3UBackend, self).__init__()

        self._config = config

        try:
            path.get_or_create_dir(config['m3u']['playlists_dir'])
        except EnvironmentError as error:
            logger.warning('Could not create M3U playlists dir: %s',
                           encoding.locale_decode(error))

        self.playlists = M3UPlaylistsProvider(backend=self)
        self.library = M3ULibraryProvider(backend=self)
Beispiel #25
0
    def __init__(self, config, audio):
        super(M3UBackend, self).__init__()

        self._config = config

        try:
            path.get_or_create_dir(config['m3u']['playlists_dir'])
        except EnvironmentError as error:
            logger.warning(
                'Could not create M3U playlists dir: %s',
                encoding.locale_decode(error))

        self.playlists = M3UPlaylistsProvider(backend=self)
        self.library = M3ULibraryProvider(backend=self)
Beispiel #26
0
def load_library(json_file):
    if not os.path.isfile(json_file):
        logger.info(
            'No local library metadata cache found at %s. Please run '
            '`mopidy local scan` to index your local music library. '
            'If you do not have a local music collection, you can disable the '
            'local backend to hide this message.', json_file)
        return {}
    try:
        with gzip.open(json_file, 'rb') as fp:
            return json.load(fp, object_hook=models.model_json_decoder)
    except (IOError, ValueError) as error:
        logger.warning('Loading JSON local library failed: %s',
                       encoding.locale_decode(error))
        return {}
Beispiel #27
0
def create_file_structures_and_config(args, extensions):
    path.get_or_create_dir(b'$XDG_DATA_DIR/mopidy')
    path.get_or_create_dir(b'$XDG_CONFIG_DIR/mopidy')

    # Initialize whatever the last config file is with defaults
    config_file = args.config_files[-1]
    if os.path.exists(path.expand_path(config_file)):
        return

    try:
        default = config_lib.format_initial(extensions)
        path.get_or_create_file(config_file, mkdir=False, content=default)
        logger.info('Initialized %s with default config', config_file)
    except IOError as error:
        logger.warning('Unable to initialize %s with default config: %s',
                       config_file, encoding.locale_decode(error))
Beispiel #28
0
def _find_worker(relative, follow, done, work, results, errors):
    """Worker thread for collecting stat() results.

    :param str relative: directory to make results relative to
    :param bool follow: if symlinks should be followed
    :param threading.Event done: event indicating that all work has been done
    :param queue.Queue work: queue of paths to process
    :param dict results: shared dictionary for storing all the stat() results
    :param dict errors: shared dictionary for storing any per path errors
    """
    while not done.is_set():
        try:
            entry, parents = work.get(block=False)
        except queue.Empty:
            continue

        if relative:
            path = os.path.relpath(entry, relative)
        else:
            path = entry

        try:
            if follow:
                st = os.stat(entry)
            else:
                st = os.lstat(entry)

            if (st.st_dev, st.st_ino) in parents:
                errors[path] = exceptions.FindError('Sym/hardlink loop found.')
                continue

            parents = parents + [(st.st_dev, st.st_ino)]
            if stat.S_ISDIR(st.st_mode):
                for e in os.listdir(entry):
                    work.put((os.path.join(entry, e), parents))
            elif stat.S_ISREG(st.st_mode):
                results[path] = st
            elif stat.S_ISLNK(st.st_mode):
                errors[path] = exceptions.FindError('Not following symlinks.')
            else:
                errors[path] = exceptions.FindError('Not a file or directory.')

        except OSError as e:
            errors[path] = exceptions.FindError(
                encoding.locale_decode(e.strerror), e.errno)
        finally:
            work.task_done()
Beispiel #29
0
def _find_worker(relative, follow, done, work, results, errors):
    """Worker thread for collecting stat() results.

    :param str relative: directory to make results relative to
    :param bool follow: if symlinks should be followed
    :param threading.Event done: event indicating that all work has been done
    :param queue.Queue work: queue of paths to process
    :param dict results: shared dictionary for storing all the stat() results
    :param dict errors: shared dictionary for storing any per path errors
    """
    while not done.is_set():
        try:
            entry, parents = work.get(block=False)
        except queue.Empty:
            continue

        if relative:
            path = os.path.relpath(entry, relative)
        else:
            path = entry

        try:
            if follow:
                st = os.stat(entry)
            else:
                st = os.lstat(entry)

            if (st.st_dev, st.st_ino) in parents:
                errors[path] = exceptions.FindError('Sym/hardlink loop found.')
                continue

            parents = parents + [(st.st_dev, st.st_ino)]
            if stat.S_ISDIR(st.st_mode):
                for e in os.listdir(entry):
                    work.put((os.path.join(entry, e), parents))
            elif stat.S_ISREG(st.st_mode):
                results[path] = st
            elif stat.S_ISLNK(st.st_mode):
                errors[path] = exceptions.FindError('Not following symlinks.')
            else:
                errors[path] = exceptions.FindError('Not a file or directory.')

        except OSError as e:
            errors[path] = exceptions.FindError(
                encoding.locale_decode(e.strerror), e.errno)
        finally:
            work.task_done()
Beispiel #30
0
    def __init__(self, core):
        super(MpdFrontend, self).__init__()
        hostname = network.format_hostname(settings.MPD_SERVER_HOSTNAME)
        port = settings.MPD_SERVER_PORT

        try:
            network.Server(
                hostname, port,
                protocol=session.MpdSession, protocol_kwargs={'core': core},
                max_connections=settings.MPD_SERVER_MAX_CONNECTIONS)
        except IOError as error:
            logger.error(
                'MPD server startup failed: %s',
                encoding.locale_decode(error))
            sys.exit(1)

        logger.info('MPD server running at [%s]:%s', hostname, port)
Beispiel #31
0
    def __init__(self, core):
        super(MpdFrontend, self).__init__()
        hostname = network.format_hostname(settings.MPD_SERVER_HOSTNAME)
        port = settings.MPD_SERVER_PORT

        try:
            network.Server(hostname,
                           port,
                           protocol=session.MpdSession,
                           protocol_kwargs={'core': core},
                           max_connections=settings.MPD_SERVER_MAX_CONNECTIONS)
        except IOError as error:
            logger.error('MPD server startup failed: %s',
                         encoding.locale_decode(error))
            sys.exit(1)

        logger.info('MPD server running at [%s]:%s', hostname, port)
Beispiel #32
0
def create_file_structures_and_config(args, extensions):
    path.get_or_create_dir(b'$XDG_DATA_DIR/mopidy')
    path.get_or_create_dir(b'$XDG_CONFIG_DIR/mopidy')

    # Initialize whatever the last config file is with defaults
    config_file = args.config_files[-1]
    if os.path.exists(path.expand_path(config_file)):
        return

    try:
        default = config_lib.format_initial(extensions)
        path.get_or_create_file(config_file, mkdir=False, content=default)
        logger.info('Initialized %s with default config', config_file)
    except IOError as error:
        logger.warning(
            'Unable to initialize %s with default config: %s',
            config_file, encoding.locale_decode(error))
Beispiel #33
0
def load_library(json_file):
    if not os.path.isfile(json_file):
        logger.info(
            'No local library metadata cache found at %s. Please run '
            '`mopidy local scan` to index your local music library. '
            'If you do not have a local music collection, you can disable the '
            'local backend to hide this message.',
            json_file)
        return {}
    try:
        with gzip.open(json_file, 'rb') as fp:
            return json.load(fp, object_hook=models.model_json_decoder)
    except (IOError, ValueError) as error:
        logger.warning(
            'Loading JSON local library failed: %s',
            encoding.locale_decode(error))
        return {}
Beispiel #34
0
def parse_m3u(file_path, media_dir):
    r"""
    Convert M3U file list of uris

    Example M3U data::

        # This is a comment
        Alternative\Band - Song.mp3
        Classical\Other Band - New Song.mp3
        Stuff.mp3
        D:\More Music\Foo.mp3
        http://www.example.com:8000/Listen.pls
        http://www.example.com/~user/Mine.mp3

    - Relative paths of songs should be with respect to location of M3U.
    - Paths are normaly platform specific.
    - Lines starting with # should be ignored.
    - m3u files are latin-1.
    - This function does not bother with Extended M3U directives.
    """
    # TODO: uris as bytes
    uris = []
    try:
        with open(file_path) as m3u:
            contents = m3u.readlines()
    except IOError as error:
        logger.warning('Couldn\'t open m3u: %s', locale_decode(error))
        return uris

    for line in contents:
        line = line.strip().decode('latin1')

        if line.startswith('#'):
            continue

        if urlparse.urlsplit(line).scheme:
            uris.append(line)
        elif os.path.normpath(line) == os.path.abspath(line):
            path = path_to_uri(line)
            uris.append(path)
        else:
            path = path_to_uri(os.path.join(media_dir, line))
            uris.append(path)

    return uris
Beispiel #35
0
def parse_m3u(file_path, music_folder):
    r"""
    Convert M3U file list of uris

    Example M3U data::

        # This is a comment
        Alternative\Band - Song.mp3
        Classical\Other Band - New Song.mp3
        Stuff.mp3
        D:\More Music\Foo.mp3
        http://www.example.com:8000/Listen.pls
        http://www.example.com/~user/Mine.mp3

    - Relative paths of songs should be with respect to location of M3U.
    - Paths are normaly platform specific.
    - Lines starting with # should be ignored.
    - m3u files are latin-1.
    - This function does not bother with Extended M3U directives.
    """

    uris = []
    try:
        with open(file_path) as m3u:
            contents = m3u.readlines()
    except IOError as error:
        logger.error("Couldn't open m3u: %s", locale_decode(error))
        return uris

    for line in contents:
        line = line.strip().decode("latin1")

        if line.startswith("#"):
            continue

        # FIXME what about other URI types?
        if line.startswith("file://"):
            uris.append(line)
        else:
            path = path_to_uri(music_folder, line)
            uris.append(path)

    return uris
Beispiel #36
0
def parse_m3u(file_path, music_folder):
    r"""
    Convert M3U file list of uris

    Example M3U data::

        # This is a comment
        Alternative\Band - Song.mp3
        Classical\Other Band - New Song.mp3
        Stuff.mp3
        D:\More Music\Foo.mp3
        http://www.example.com:8000/Listen.pls
        http://www.example.com/~user/Mine.mp3

    - Relative paths of songs should be with respect to location of M3U.
    - Paths are normaly platform specific.
    - Lines starting with # should be ignored.
    - m3u files are latin-1.
    - This function does not bother with Extended M3U directives.
    """

    uris = []
    try:
        with open(file_path) as m3u:
            contents = m3u.readlines()
    except IOError as error:
        logger.error('Couldn\'t open m3u: %s', locale_decode(error))
        return uris

    for line in contents:
        line = line.strip().decode('latin1')

        if line.startswith('#'):
            continue

        # FIXME what about other URI types?
        if line.startswith('file://'):
            uris.append(line)
        else:
            path = path_to_uri(music_folder, line)
            uris.append(path)

    return uris
Beispiel #37
0
    def __init__(self, config, core):
        super(HttpFrontend, self).__init__()

        self.hostname = network.format_hostname(config["http"]["hostname"])
        self.port = config["http"]["port"]
        tornado_hostname = config["http"]["hostname"]
        if tornado_hostname == "::":
            tornado_hostname = None

        try:
            logger.debug("Starting HTTP server")
            sockets = tornado.netutil.bind_sockets(self.port, tornado_hostname)
            self.server = HttpServer(config=config, core=core, sockets=sockets, apps=self.apps, statics=self.statics)
        except IOError as error:
            raise exceptions.FrontendError("HTTP server startup failed: %s" % encoding.locale_decode(error))

        self.zeroconf_name = config["http"]["zeroconf"]
        self.zeroconf_http = None
        self.zeroconf_mopidy_http = None
Beispiel #38
0
    def __init__(self, core):
        super(MpdFrontend, self).__init__()
        hostname = network.format_hostname(settings.MPD_SERVER_HOSTNAME)
        port = settings.MPD_SERVER_PORT

        # NOTE kwargs dict keys must be bytestrings to work on Python < 2.6.5
        # See https://github.com/mopidy/mopidy/issues/302 for details.
        try:
            network.Server(
                hostname, port,
                protocol=session.MpdSession, protocol_kwargs={b'core': core},
                max_connections=settings.MPD_SERVER_MAX_CONNECTIONS,
                timeout=settings.MPD_SERVER_CONNECTION_TIMEOUT)
        except IOError as error:
            logger.error(
                'MPD server startup failed: %s',
                encoding.locale_decode(error))
            sys.exit(1)

        logger.info('MPD server running at [%s]:%s', hostname, port)
Beispiel #39
0
    def __init__(self, core):
        super(MpdFrontend, self).__init__()
        hostname = network.format_hostname(settings.MPD_SERVER_HOSTNAME)
        port = settings.MPD_SERVER_PORT

        # NOTE kwargs dict keys must be bytestrings to work on Python < 2.6.5
        # See https://github.com/mopidy/mopidy/issues/302 for details.
        try:
            network.Server(hostname,
                           port,
                           protocol=session.MpdSession,
                           protocol_kwargs={b'core': core},
                           max_connections=settings.MPD_SERVER_MAX_CONNECTIONS,
                           timeout=settings.MPD_SERVER_CONNECTION_TIMEOUT)
        except IOError as error:
            logger.error('MPD server startup failed: %s',
                         encoding.locale_decode(error))
            sys.exit(1)

        logger.info('MPD server running at [%s]:%s', hostname, port)
Beispiel #40
0
    def on_message(self, message):
        if not message:
            return

        logger.debug('Received WebSocket message from %s: %r',
                     self.request.remote_ip, message)

        try:
            response = self.jsonrpc.handle_json(
                tornado.escape.native_str(message))
            if response and self.write_message(response):
                logger.debug('Sent WebSocket message to %s: %r',
                             self.request.remote_ip, response)
        except Exception as e:
            error_msg = encoding.locale_decode(e)
            logger.error('WebSocket request error: %s', error_msg)
            if self.ws_connection:
                # Tornado 3.2+ checks if self.ws_connection is None before
                # using it, but not older versions.
                self.close()
Beispiel #41
0
    def __init__(self, config, core):
        super(MpdFrontend, self).__init__()

        self.hostname = network.format_hostname(config["mpd"]["hostname"])
        self.port = config["mpd"]["port"]

        self.zeroconf_name = config["mpd"]["zeroconf"]
        self.zeroconf_service = None

        try:
            network.Server(
                self.hostname,
                self.port,
                protocol=session.MpdSession,
                protocol_kwargs={"config": config, "core": core},
                max_connections=config["mpd"]["max_connections"],
                timeout=config["mpd"]["connection_timeout"],
            )
        except IOError as error:
            raise exceptions.FrontendError("MPD server startup failed: %s" % encoding.locale_decode(error))

        logger.info("MPD server running at [%s]:%s", self.hostname, self.port)
Beispiel #42
0
    def on_message(self, message):
        if not message:
            return

        logger.debug(
            'Received WebSocket message from %s: %r',
            self.request.remote_ip, message)

        try:
            response = self.jsonrpc.handle_json(
                tornado.escape.native_str(message))
            if response and self.write_message(response):
                logger.debug(
                    'Sent WebSocket message to %s: %r',
                    self.request.remote_ip, response)
        except Exception as e:
            error_msg = encoding.locale_decode(e)
            logger.error('WebSocket request error: %s', error_msg)
            if self.ws_connection:
                # Tornado 3.2+ checks if self.ws_connection is None before
                # using it, but not older versions.
                self.close()
Beispiel #43
0
    def __init__(self, config, core):
        super(MpdFrontend, self).__init__()
        hostname = network.format_hostname(config['mpd']['hostname'])
        port = config['mpd']['port']

        try:
            network.Server(
                hostname, port,
                protocol=session.MpdSession,
                protocol_kwargs={
                    'config': config,
                    'core': core,
                },
                max_connections=config['mpd']['max_connections'],
                timeout=config['mpd']['connection_timeout'])
        except IOError as error:
            logger.error(
                'MPD server startup failed: %s',
                encoding.locale_decode(error))
            sys.exit(1)

        logger.info('MPD server running at [%s]:%s', hostname, port)
Beispiel #44
0
def parse_mpd_tag_cache(tag_cache, music_dir=''):
    """
    Converts a MPD tag_cache into a lists of tracks, artists and albums.
    """
    tracks = set()

    try:
        with open(tag_cache) as library:
            contents = library.read()
    except IOError as error:
        logger.warning('Could not open tag cache: %s', locale_decode(error))
        return tracks

    current = {}
    state = None

    # TODO: uris as bytes
    for line in contents.split(b'\n'):
        if line == b'songList begin':
            state = 'songs'
            continue
        elif line == b'songList end':
            state = None
            continue
        elif not state:
            continue

        key, value = line.split(b': ', 1)

        if key == b'key':
            _convert_mpd_data(current, tracks)
            current.clear()

        current[key.lower()] = value.decode('utf-8')

    _convert_mpd_data(current, tracks)

    return tracks
Beispiel #45
0
    def __init__(self, config, core):
        super(HttpFrontend, self).__init__()

        self.hostname = network.format_hostname(config['http']['hostname'])
        self.port = config['http']['port']
        tornado_hostname = config['http']['hostname']
        if tornado_hostname == '::':
            tornado_hostname = None

        try:
            logger.debug('Starting HTTP server')
            sockets = tornado.netutil.bind_sockets(self.port, tornado_hostname)
            self.server = HttpServer(
                config=config, core=core, sockets=sockets,
                apps=self.apps, statics=self.statics)
        except IOError as error:
            raise exceptions.FrontendError(
                'HTTP server startup failed: %s' %
                encoding.locale_decode(error))

        self.zeroconf_name = config['http']['zeroconf']
        self.zeroconf_http = None
        self.zeroconf_mopidy_http = None
Beispiel #46
0
    def __init__(self, config, core):
        super(MpdFrontend, self).__init__()
        hostname = network.format_hostname(config['mpd']['hostname'])
        port = config['mpd']['port']

        # NOTE kwargs dict keys must be bytestrings to work on Python < 2.6.5
        # See https://github.com/mopidy/mopidy/issues/302 for details.
        try:
            network.Server(hostname,
                           port,
                           protocol=session.MpdSession,
                           protocol_kwargs={
                               b'config': config,
                               b'core': core,
                           },
                           max_connections=config['mpd']['max_connections'],
                           timeout=config['mpd']['connection_timeout'])
        except IOError as error:
            logger.error('MPD server startup failed: %s',
                         encoding.locale_decode(error))
            sys.exit(1)

        logger.info('MPD server running at [%s]:%s', hostname, port)
Beispiel #47
0
    def __init__(self, config, core):
        super(HttpFrontend, self).__init__()

        self.hostname = network.format_hostname(config['http']['hostname'])
        self.port = config['http']['port']
        tornado_hostname = config['http']['hostname']
        if tornado_hostname == '::':
            tornado_hostname = None

        try:
            logger.debug('Starting HTTP server')
            sockets = tornado.netutil.bind_sockets(self.port, tornado_hostname)
            self.server = HttpServer(
                config=config, core=core, sockets=sockets,
                apps=self.apps, statics=self.statics)
        except IOError as error:
            raise exceptions.FrontendError(
                'HTTP server startup failed: %s' %
                encoding.locale_decode(error))

        self.zeroconf_name = config['http']['zeroconf']
        self.zeroconf_http = None
        self.zeroconf_mopidy_http = None
Beispiel #48
0
def parse_mpd_tag_cache(tag_cache, music_dir=""):
    """
    Converts a MPD tag_cache into a lists of tracks, artists and albums.
    """
    tracks = set()

    try:
        with open(tag_cache) as library:
            contents = library.read()
    except IOError as error:
        logger.error("Could not open tag cache: %s", locale_decode(error))
        return tracks

    current = {}
    state = None

    for line in contents.split(b"\n"):
        if line == b"songList begin":
            state = "songs"
            continue
        elif line == b"songList end":
            state = None
            continue
        elif not state:
            continue

        key, value = line.split(b": ", 1)

        if key == b"key":
            _convert_mpd_data(current, tracks, music_dir)
            current.clear()

        current[key.lower()] = value.decode("utf-8")

    _convert_mpd_data(current, tracks, music_dir)

    return tracks
Beispiel #49
0
    def __init__(self, config, core):
        super(MpdFrontend, self).__init__()
        hostname = network.format_hostname(config['mpd']['hostname'])
        port = config['mpd']['port']

        # NOTE kwargs dict keys must be bytestrings to work on Python < 2.6.5
        # See https://github.com/mopidy/mopidy/issues/302 for details.
        try:
            network.Server(
                hostname, port,
                protocol=session.MpdSession,
                protocol_kwargs={
                    b'config': config,
                    b'core': core,
                },
                max_connections=config['mpd']['max_connections'],
                timeout=config['mpd']['connection_timeout'])
        except IOError as error:
            logger.error(
                'MPD server startup failed: %s',
                encoding.locale_decode(error))
            sys.exit(1)

        logger.info('MPD server running at [%s]:%s', hostname, port)
Beispiel #50
0
    def test_does_not_use_locale_to_decode_ascii_bytestrings(self, mock):
        mock.return_value = 'UTF-8'

        locale_decode('abc')

        self.assertFalse(mock.called)
Beispiel #51
0
def parse_m3u(file_path, media_dir=None):
    r"""
    Convert M3U file list to list of tracks

    Example M3U data::

        # This is a comment
        Alternative\Band - Song.mp3
        Classical\Other Band - New Song.mp3
        Stuff.mp3
        D:\More Music\Foo.mp3
        http://www.example.com:8000/Listen.pls
        http://www.example.com/~user/Mine.mp3

    Example extended M3U data::

        #EXTM3U
        #EXTINF:123, Sample artist - Sample title
        Sample.mp3
        #EXTINF:321,Example Artist - Example title
        Greatest Hits\Example.ogg
        #EXTINF:-1,Radio XMP
        http://mp3stream.example.com:8000/

    - Relative paths of songs should be with respect to location of M3U.
    - Paths are normally platform specific.
    - Lines starting with # are ignored, except for extended M3U directives.
    - Track.name and Track.length are set from extended M3U directives.
    - m3u files are latin-1.
    """
    # TODO: uris as bytes
    tracks = []
    try:
        with open(file_path) as m3u:
            contents = m3u.readlines()
    except IOError as error:
        logger.warning('Couldn\'t open m3u: %s', locale_decode(error))
        return tracks

    if not contents:
        return tracks

    extended = contents[0].decode('latin1').startswith('#EXTM3U')

    track = Track()
    for line in contents:
        line = line.strip().decode('latin1')

        if line.startswith('#'):
            if extended and line.startswith('#EXTINF'):
                track = m3u_extinf_to_track(line)
            continue

        if urlparse.urlsplit(line).scheme:
            tracks.append(track.copy(uri=line))
        elif os.path.normpath(line) == os.path.abspath(line):
            path = path_to_uri(line)
            tracks.append(track.copy(uri=path))
        elif media_dir is not None:
            path = path_to_uri(os.path.join(media_dir, line))
            tracks.append(track.copy(uri=path))

        track = Track()
    return tracks
Beispiel #52
0
    def test_does_not_use_locale_to_decode_ascii_bytestrings(self, mock):
        mock.return_value = 'UTF-8'

        locale_decode('abc')

        self.assertFalse(mock.called)