Esempio n. 1
0
    def test_can_decode_utf8_strings_with_french_content(self, mock):
        mock.return_value = 'UTF-8'

        result = encoding.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)
Esempio n. 2
0
    def __init__(self, config, core):
        super(MpdFrontend, self).__init__()

        self.hostname = network.format_hostname(config['mpd']['hostname'])
        self.port = config['mpd']['port']
        self.uri_map = uri_mapper.MpdUriMapper(core)

        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,
                               'uri_map': self.uri_map,
                           },
                           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)
Esempio n. 3
0
    def __init__(self, config, core):
        super(HttpFrontend, self).__init__()

        self.hostname = network.format_hostname(
            config['mopidy_bamp']['hostname'])
        self.port = config['mopidy_bamp']['port']
        tornado_hostname = config['mopidy_bamp']['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['mopidy_bamp']['zeroconf']
        self.zeroconf_http = None
        self.zeroconf_mopidy_http = None
Esempio n. 4
0
    def __init__(self, config, core):
        super(MpdFrontend, self).__init__()

        self.hostname = network.format_hostname(config['mpd']['hostname'])
        self.port = config['mpd']['port']
        self.uri_map = uri_mapper.MpdUriMapper(core)

        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,
                    'uri_map': self.uri_map,
                },
                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)
Esempio n. 5
0
    def test_can_decode_utf8_strings_with_french_content(self, mock):
        mock.return_value = 'UTF-8'

        result = encoding.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)
Esempio n. 6
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)
Esempio n. 7
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)
Esempio n. 8
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 = encoding.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))
Esempio n. 9
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)
Esempio n. 10
0
def _process(pipeline, timeout_ms):
    bus = pipeline.get_bus()
    tags = {}
    mime = None
    have_audio = False
    missing_message = None

    types = (
        Gst.MessageType.ELEMENT
        | Gst.MessageType.APPLICATION
        | Gst.MessageType.ERROR
        | Gst.MessageType.EOS
        | Gst.MessageType.ASYNC_DONE
        | Gst.MessageType.TAG
    )

    timeout = timeout_ms
    previous = int(time.time() * 1000)
    while timeout > 0:
        message = bus.timed_pop_filtered(timeout * Gst.MSECOND, types)

        if message is None:
            break
        elif message.type == Gst.MessageType.ELEMENT:
            if GstPbutils.is_missing_plugin_message(message):
                missing_message = message
        elif message.type == Gst.MessageType.APPLICATION:
            if message.get_structure().get_name() == "have-type":
                mime = message.get_structure().get_value("caps").get_name()
                if mime and (mime.startswith("text/") or mime == "application/xml"):
                    return tags, mime, have_audio
            elif message.get_structure().get_name() == "have-audio":
                have_audio = True
        elif message.type == Gst.MessageType.ERROR:
            error = encoding.locale_decode(message.parse_error()[0])
            if missing_message and not mime:
                caps = missing_message.get_structure().get_value("detail")
                mime = caps.get_structure(0).get_name()
                return tags, mime, have_audio
            raise exceptions.ScannerError(error)
        elif message.type == Gst.MessageType.EOS:
            return tags, mime, have_audio
        elif message.type == Gst.MessageType.ASYNC_DONE:
            if message.src == pipeline:
                return tags, mime, have_audio
        elif message.type == Gst.MessageType.TAG:
            taglist = message.parse_tag()
            # Note that this will only keep the last tag.
            tags.update(tags_lib.convert_taglist(taglist))

        now = int(time.time() * 1000)
        timeout -= now - previous
        previous = now

    raise exceptions.ScannerError("Timeout after %dms" % timeout_ms)
Esempio n. 11
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''
Esempio n. 12
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''
Esempio n. 13
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 = encoding.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))
Esempio n. 14
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))
Esempio n. 15
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
Esempio n. 16
0
    def on_message(self, message):
        if not message:
            return

        try:
            response = self.jsonrpc.handle_json(tornado.escape.native_str(message))

            if response and self.write_message(response):
                logger.debug('Sonate sent WebSocket message to %s: %r', self.request.remote_ip, response)
        except Exception as e:
            error_msg = encoding.locale_decode(e)
            logger.error('Sonate WebSocket request error: %s', error_msg)
Esempio n. 17
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
Esempio n. 18
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)
Esempio n. 19
0
def _process(pipeline, timeout_ms):
    bus = pipeline.get_bus()
    tags = {}
    mime = None
    have_audio = False
    missing_message = None

    types = (Gst.MessageType.ELEMENT | Gst.MessageType.APPLICATION
             | Gst.MessageType.ERROR | Gst.MessageType.EOS
             | Gst.MessageType.ASYNC_DONE | Gst.MessageType.TAG)

    timeout = timeout_ms
    previous = int(time.time() * 1000)
    while timeout > 0:
        message = bus.timed_pop_filtered(timeout * Gst.MSECOND, types)

        if message is None:
            break
        elif message.type == Gst.MessageType.ELEMENT:
            if GstPbutils.is_missing_plugin_message(message):
                missing_message = message
        elif message.type == Gst.MessageType.APPLICATION:
            if message.get_structure().get_name() == 'have-type':
                mime = message.get_structure().get_value('caps').get_name()
                if mime and (mime.startswith('text/')
                             or mime == 'application/xml'):
                    return tags, mime, have_audio
            elif message.get_structure().get_name() == 'have-audio':
                have_audio = True
        elif message.type == Gst.MessageType.ERROR:
            error = encoding.locale_decode(message.parse_error()[0])
            if missing_message and not mime:
                caps = missing_message.get_structure().get_value('detail')
                mime = caps.get_structure(0).get_name()
                return tags, mime, have_audio
            raise exceptions.ScannerError(error)
        elif message.type == Gst.MessageType.EOS:
            return tags, mime, have_audio
        elif message.type == Gst.MessageType.ASYNC_DONE:
            if message.src == pipeline:
                return tags, mime, have_audio
        elif message.type == Gst.MessageType.TAG:
            taglist = message.parse_tag()
            # Note that this will only keep the last tag.
            tags.update(tags_lib.convert_taglist(taglist))

        now = int(time.time() * 1000)
        timeout -= now - previous
        previous = now

    raise exceptions.ScannerError('Timeout after %dms' % timeout_ms)
Esempio n. 20
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)
Esempio n. 21
0
File: json.py Progetto: vrs01/mopidy
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 {}
Esempio n. 22
0
def create_initial_config_file(args, extensions_data):
    """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_data)
        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))
Esempio n. 23
0
def create_initial_config_file(args, extensions_data):
    """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_data)
        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))
Esempio n. 24
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()
Esempio n. 25
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()
Esempio n. 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 {}
Esempio n. 27
0
    def _setup_server(self, config, core):
        try:
            network.Server(self.hostname,
                           self.port,
                           protocol=session.MpdSession,
                           protocol_kwargs={
                               'config': config,
                               'core': core,
                               'uri_map': self.uri_map,
                           },
                           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)
Esempio n. 28
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)
            self.close()
Esempio n. 29
0
    def _setup_server(self, config, core):
        try:
            network.Server(
                self.hostname, self.port,
                protocol=session.MpdSession,
                protocol_kwargs={
                    'config': config,
                    'core': core,
                    'uri_map': self.uri_map,
                },
                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)
Esempio n. 30
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
Esempio n. 31
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()
Esempio n. 32
0
def load(path):
    """
    Deserialize data from file.

    :param path: full path to import file
    :type path: bytes
    :return: deserialized data
    :rtype: dict
    """
    # Todo: raise an exception in case of error?
    if not os.path.isfile(path):
        logger.info('File does not exist: %s', path)
        return {}
    try:
        with gzip.open(path, 'rb') as fp:
            return json.load(fp, object_hook=models.model_json_decoder)
    except (IOError, ValueError) as error:
        logger.warning(
            'Loading JSON failed: %s',
            encoding.locale_decode(error))
        return {}
Esempio n. 33
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()
Esempio n. 34
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
Esempio n. 35
0
    def test_does_not_use_locale_to_decode_ascii_bytestrings(self, mock):
        mock.return_value = 'UTF-8'

        encoding.locale_decode(b'abc')

        self.assertFalse(mock.called)
Esempio n. 36
0
def _process(pipeline, timeout_ms):
    bus = pipeline.get_bus()
    tags = {}
    mime = None
    have_audio = False
    missing_message = None
    duration = None

    types = (Gst.MessageType.ELEMENT | Gst.MessageType.APPLICATION
             | Gst.MessageType.ERROR | Gst.MessageType.EOS
             | Gst.MessageType.ASYNC_DONE | Gst.MessageType.DURATION_CHANGED
             | Gst.MessageType.TAG)

    timeout = timeout_ms
    start = int(time.time() * 1000)
    while timeout > 0:
        msg = bus.timed_pop_filtered(timeout * Gst.MSECOND, types)
        if msg is None:
            break

        if logger.isEnabledFor(log.TRACE_LOG_LEVEL) and msg.get_structure():
            debug_text = msg.get_structure().to_string()
            if len(debug_text) > 77:
                debug_text = debug_text[:77] + '...'
            _trace('element %s: %s', msg.src.get_name(), debug_text)

        if msg.type == Gst.MessageType.ELEMENT:
            if GstPbutils.is_missing_plugin_message(msg):
                missing_message = msg
        elif msg.type == Gst.MessageType.APPLICATION:
            if msg.get_structure().get_name() == 'have-type':
                mime = msg.get_structure().get_value('caps').get_name()
                if mime and (mime.startswith('text/')
                             or mime == 'application/xml'):
                    return tags, mime, have_audio, duration
            elif msg.get_structure().get_name() == 'have-audio':
                have_audio = True
        elif msg.type == Gst.MessageType.ERROR:
            error = encoding.locale_decode(msg.parse_error()[0])
            if missing_message and not mime:
                caps = missing_message.get_structure().get_value('detail')
                mime = caps.get_structure(0).get_name()
                return tags, mime, have_audio, duration
            raise exceptions.ScannerError(error)
        elif msg.type == Gst.MessageType.EOS:
            return tags, mime, have_audio, duration
        elif msg.type == Gst.MessageType.ASYNC_DONE:
            success, duration = _query_duration(pipeline)
            if tags and success:
                return tags, mime, have_audio, duration

            # Don't try workaround for non-seekable sources such as mmssrc:
            if not _query_seekable(pipeline):
                return tags, mime, have_audio, duration

            # Workaround for upstream bug which causes tags/duration to arrive
            # after pre-roll. We get around this by starting to play the track
            # and then waiting for a duration change.
            # https://bugzilla.gnome.org/show_bug.cgi?id=763553
            logger.debug('Using workaround for duration missing before play.')
            result = pipeline.set_state(Gst.State.PLAYING)
            if result == Gst.StateChangeReturn.FAILURE:
                return tags, mime, have_audio, duration

        elif msg.type == Gst.MessageType.DURATION_CHANGED and tags:
            # VBR formats sometimes seem to not have a duration by the time we
            # go back to paused. So just try to get it right away.
            success, duration = _query_duration(pipeline)
            pipeline.set_state(Gst.State.PAUSED)
            if success:
                return tags, mime, have_audio, duration
        elif msg.type == Gst.MessageType.TAG:
            taglist = msg.parse_tag()
            # Note that this will only keep the last tag.
            tags.update(tags_lib.convert_taglist(taglist))

        timeout = timeout_ms - (int(time.time() * 1000) - start)

    raise exceptions.ScannerError('Timeout after %dms' % timeout_ms)
Esempio n. 37
0
def _process(pipeline, timeout_ms):
    bus = pipeline.get_bus()
    tags = {}
    mime = None
    have_audio = False
    missing_message = None
    duration = None

    types = (
        Gst.MessageType.ELEMENT |
        Gst.MessageType.APPLICATION |
        Gst.MessageType.ERROR |
        Gst.MessageType.EOS |
        Gst.MessageType.ASYNC_DONE |
        Gst.MessageType.DURATION_CHANGED |
        Gst.MessageType.TAG
    )

    timeout = timeout_ms
    start = int(time.time() * 1000)
    while timeout > 0:
        message = bus.timed_pop_filtered(timeout * Gst.MSECOND, types)

        if message is None:
            break
        elif message.type == Gst.MessageType.ELEMENT:
            if GstPbutils.is_missing_plugin_message(message):
                missing_message = message
        elif message.type == Gst.MessageType.APPLICATION:
            if message.get_structure().get_name() == 'have-type':
                mime = message.get_structure().get_value('caps').get_name()
                if mime and (
                        mime.startswith('text/') or mime == 'application/xml'):
                    return tags, mime, have_audio, duration
            elif message.get_structure().get_name() == 'have-audio':
                have_audio = True
        elif message.type == Gst.MessageType.ERROR:
            error = encoding.locale_decode(message.parse_error()[0])
            if missing_message and not mime:
                caps = missing_message.get_structure().get_value('detail')
                mime = caps.get_structure(0).get_name()
                return tags, mime, have_audio, duration
            raise exceptions.ScannerError(error)
        elif message.type == Gst.MessageType.EOS:
            return tags, mime, have_audio, duration
        elif message.type == Gst.MessageType.ASYNC_DONE:
            success, duration = _query_duration(pipeline)
            if tags and success:
                return tags, mime, have_audio, duration

            # Workaround for upstream bug which causes tags/duration to arrive
            # after pre-roll. We get around this by starting to play the track
            # and then waiting for a duration change.
            # https://bugzilla.gnome.org/show_bug.cgi?id=763553
            result = pipeline.set_state(Gst.State.PLAYING)
            if result == Gst.StateChangeReturn.FAILURE:
                return tags, mime, have_audio, duration

        elif message.type == Gst.MessageType.DURATION_CHANGED:
            # duration will be read after ASYNC_DONE received; for now
            # just give it a non-None value to flag that we have a duration:
            duration = 0
        elif message.type == Gst.MessageType.TAG:
            taglist = message.parse_tag()
            # Note that this will only keep the last tag.
            tags.update(tags_lib.convert_taglist(taglist))

        timeout = timeout_ms - (int(time.time() * 1000) - start)

        # workaround for https://bugzilla.gnome.org/show_bug.cgi?id=763553:
        # if we got what we want then stop playing (and wait for ASYNC_DONE)
        if tags and duration is not None:
            pipeline.set_state(Gst.State.PAUSED)

    raise exceptions.ScannerError('Timeout after %dms' % timeout_ms)
Esempio n. 38
0
    def test_replaces_unknown_bytes_instead_of_crashing(self, mock):
        mock.return_value = 'US-ASCII'

        result = encoding.locale_decode(b'abc\xc3def')

        assert result == 'abc\ufffddef'
Esempio n. 39
0
    def test_does_not_use_locale_to_decode_ascii_bytestrings(self, mock):
        mock.return_value = 'UTF-8'

        encoding.locale_decode(b'abc')

        self.assertFalse(mock.called)
Esempio n. 40
0
def _process(pipeline, timeout_ms):
    bus = pipeline.get_bus()
    tags = {}
    mime = None
    have_audio = False
    missing_message = None
    duration = None

    types = (
        Gst.MessageType.ELEMENT |
        Gst.MessageType.APPLICATION |
        Gst.MessageType.ERROR |
        Gst.MessageType.EOS |
        Gst.MessageType.ASYNC_DONE |
        Gst.MessageType.DURATION_CHANGED |
        Gst.MessageType.TAG
    )

    timeout = timeout_ms
    start = int(time.time() * 1000)
    while timeout > 0:
        msg = bus.timed_pop_filtered(timeout * Gst.MSECOND, types)
        if msg is None:
            break

        if logger.isEnabledFor(log.TRACE_LOG_LEVEL) and msg.get_structure():
            debug_text = msg.get_structure().to_string()
            if len(debug_text) > 77:
                debug_text = debug_text[:77] + '...'
            _trace('element %s: %s', msg.src.get_name(), debug_text)

        if msg.type == Gst.MessageType.ELEMENT:
            if GstPbutils.is_missing_plugin_message(msg):
                missing_message = msg
        elif msg.type == Gst.MessageType.APPLICATION:
            if msg.get_structure().get_name() == 'have-type':
                mime = msg.get_structure().get_value('caps').get_name()
                if mime and (
                        mime.startswith('text/') or mime == 'application/xml'):
                    return tags, mime, have_audio, duration
            elif msg.get_structure().get_name() == 'have-audio':
                have_audio = True
        elif msg.type == Gst.MessageType.ERROR:
            error = encoding.locale_decode(msg.parse_error()[0])
            if missing_message and not mime:
                caps = missing_message.get_structure().get_value('detail')
                mime = caps.get_structure(0).get_name()
                return tags, mime, have_audio, duration
            raise exceptions.ScannerError(error)
        elif msg.type == Gst.MessageType.EOS:
            return tags, mime, have_audio, duration
        elif msg.type == Gst.MessageType.ASYNC_DONE:
            success, duration = _query_duration(pipeline)
            if tags and success:
                return tags, mime, have_audio, duration

            # Don't try workaround for non-seekable sources such as mmssrc:
            if not _query_seekable(pipeline):
                return tags, mime, have_audio, duration

            # Workaround for upstream bug which causes tags/duration to arrive
            # after pre-roll. We get around this by starting to play the track
            # and then waiting for a duration change.
            # https://bugzilla.gnome.org/show_bug.cgi?id=763553
            logger.debug('Using workaround for duration missing before play.')
            result = pipeline.set_state(Gst.State.PLAYING)
            if result == Gst.StateChangeReturn.FAILURE:
                return tags, mime, have_audio, duration

        elif msg.type == Gst.MessageType.DURATION_CHANGED and tags:
            # VBR formats sometimes seem to not have a duration by the time we
            # go back to paused. So just try to get it right away.
            success, duration = _query_duration(pipeline)
            pipeline.set_state(Gst.State.PAUSED)
            if success:
                return tags, mime, have_audio, duration
        elif msg.type == Gst.MessageType.TAG:
            taglist = msg.parse_tag()
            # Note that this will only keep the last tag.
            tags.update(tags_lib.convert_taglist(taglist))

        timeout = timeout_ms - (int(time.time() * 1000) - start)

    raise exceptions.ScannerError('Timeout after %dms' % timeout_ms)
Esempio n. 41
0
    def test_replaces_unknown_bytes_instead_of_crashing(self, mock):
        mock.return_value = 'US-ASCII'

        result = encoding.locale_decode(b'abc\xc3def')

        assert result == 'abc\ufffddef'
Esempio n. 42
0
def _process(pipeline, timeout_ms):
    bus = pipeline.get_bus()
    tags = {}
    mime = None
    have_audio = False
    missing_message = None
    duration = None

    types = (Gst.MessageType.ELEMENT | Gst.MessageType.APPLICATION
             | Gst.MessageType.ERROR | Gst.MessageType.EOS
             | Gst.MessageType.ASYNC_DONE | Gst.MessageType.DURATION_CHANGED
             | Gst.MessageType.TAG)

    timeout = timeout_ms
    start = int(time.time() * 1000)
    while timeout > 0:
        message = bus.timed_pop_filtered(timeout * Gst.MSECOND, types)

        if message is None:
            break
        elif message.type == Gst.MessageType.ELEMENT:
            if GstPbutils.is_missing_plugin_message(message):
                missing_message = message
        elif message.type == Gst.MessageType.APPLICATION:
            if message.get_structure().get_name() == 'have-type':
                mime = message.get_structure().get_value('caps').get_name()
                if mime and (mime.startswith('text/')
                             or mime == 'application/xml'):
                    return tags, mime, have_audio, duration
            elif message.get_structure().get_name() == 'have-audio':
                have_audio = True
        elif message.type == Gst.MessageType.ERROR:
            error = encoding.locale_decode(message.parse_error()[0])
            if missing_message and not mime:
                caps = missing_message.get_structure().get_value('detail')
                mime = caps.get_structure(0).get_name()
                return tags, mime, have_audio, duration
            raise exceptions.ScannerError(error)
        elif message.type == Gst.MessageType.EOS:
            return tags, mime, have_audio, duration
        elif message.type == Gst.MessageType.ASYNC_DONE:
            success, duration = _query_duration(pipeline)
            if tags and success:
                return tags, mime, have_audio, duration

            # Workaround for upstream bug which causes tags/duration to arrive
            # after pre-roll. We get around this by starting to play the track
            # and then waiting for a duration change.
            # https://bugzilla.gnome.org/show_bug.cgi?id=763553
            result = pipeline.set_state(Gst.State.PLAYING)
            if result == Gst.StateChangeReturn.FAILURE:
                return tags, mime, have_audio, duration

        elif message.type == Gst.MessageType.DURATION_CHANGED:
            # duration will be read after ASYNC_DONE received; for now
            # just give it a non-None value to flag that we have a duration:
            duration = 0
        elif message.type == Gst.MessageType.TAG:
            taglist = message.parse_tag()
            # Note that this will only keep the last tag.
            tags.update(tags_lib.convert_taglist(taglist))

        timeout = timeout_ms - (int(time.time() * 1000) - start)

        # workaround for https://bugzilla.gnome.org/show_bug.cgi?id=763553:
        # if we got what we want then stop playing (and wait for ASYNC_DONE)
        if tags and duration is not None:
            pipeline.set_state(Gst.State.PAUSED)

    raise exceptions.ScannerError('Timeout after %dms' % timeout_ms)
Esempio n. 43
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.
    - m3u8 files are utf-8
    """
    # TODO: uris as bytes
    file_encoding = 'utf-8' if file_path.endswith(b'.m3u8') else 'latin1'

    tracks = []
    try:
        with codecs.open(file_path, 'rb', file_encoding, 'replace') as m3u:
            contents = m3u.readlines()
    except IOError as error:
        logger.warning('Couldn\'t open m3u: %s', encoding.locale_decode(error))
        return tracks

    if not contents:
        return tracks

    # Strip newlines left by codecs
    contents = [line.strip() for line in contents]

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

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

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

        track = Track()
    return tracks
Esempio n. 44
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.
    - m3u8 files are utf-8
    """
    # TODO: uris as bytes
    file_encoding = 'utf-8' if file_path.endswith(b'.m3u8') else 'latin1'

    tracks = []
    try:
        with codecs.open(file_path, 'rb', file_encoding, 'replace') as m3u:
            contents = m3u.readlines()
    except IOError as error:
        logger.warning('Couldn\'t open m3u: %s', encoding.locale_decode(error))
        return tracks

    if not contents:
        return tracks

    # Strip newlines left by codecs
    contents = [line.strip() for line in contents]

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

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

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

        track = Track()
    return tracks