def test_unicode_in_uri(self): if sys.platform == 'win32': result = path.uri_to_path('file:///C://%C3%A6%C3%B8%C3%A5') self.assertEqual(result, 'C:/æøå'.encode('utf-8')) else: result = path.uri_to_path('file:///tmp/%C3%A6%C3%B8%C3%A5') self.assertEqual(result, '/tmp/æøå'.encode('utf-8'))
def test_simple_uri(self): if sys.platform == "win32": result = uri_to_path("file:///C://WINDOWS/clock.avi") self.assertEqual(result, u"C:/WINDOWS/clock.avi") else: result = uri_to_path("file:///etc/fstab") self.assertEqual(result, u"/etc/fstab")
def test_unicode_in_uri(self): if sys.platform == 'win32': result = uri_to_path( 'file:///C://%C3%A6%C3%B8%C3%A5') self.assertEqual(result, u'C:/æøå') else: result = uri_to_path(u'file:///tmp/%C3%A6%C3%B8%C3%A5') self.assertEqual(result, u'/tmp/æøå')
def test_simple_uri(self): if sys.platform == 'win32': result = uri_to_path('file:///C://WINDOWS/clock.avi') self.assertEqual(result, u'C:/WINDOWS/clock.avi') else: result = uri_to_path('file:///etc/fstab') self.assertEqual(result, u'/etc/fstab')
def test_space_in_uri(self): if sys.platform == 'win32': result = path.uri_to_path('file:///C://test%20this') self.assertEqual(result, 'C:/test this'.encode('utf-8')) else: result = path.uri_to_path('file:///tmp/test%20this') self.assertEqual(result, '/tmp/test this'.encode('utf-8'))
def test_space_in_uri(self): if sys.platform == 'win32': result = uri_to_path('file:///C://test%20this') self.assertEqual(result, u'C:/test this') else: result = uri_to_path(u'file:///tmp/test%20this') self.assertEqual(result, u'/tmp/test this')
def test_latin1_in_uri(self): if sys.platform == 'win32': result = path.uri_to_path('file:///C://%E6%F8%E5') self.assertEqual(result, 'C:/æøå'.encode('latin-1')) else: result = path.uri_to_path('file:///tmp/%E6%F8%E5') self.assertEqual(result, '/tmp/æøå'.encode('latin-1'))
def test_simple_uri(self): if sys.platform == 'win32': result = path.uri_to_path('file:///C://WINDOWS/clock.avi') self.assertEqual(result, 'C:/WINDOWS/clock.avi'.encode('utf-8')) else: result = path.uri_to_path('file:///etc/fstab') self.assertEqual(result, '/etc/fstab'.encode('utf-8'))
def test_unicode_in_uri(self): if sys.platform == "win32": result = uri_to_path("file:///C://%C3%A6%C3%B8%C3%A5") self.assertEqual(result, u"C:/æøå") else: result = uri_to_path(u"file:///tmp/%C3%A6%C3%B8%C3%A5") self.assertEqual(result, u"/tmp/æøå")
def test_space_in_uri(self): if sys.platform == "win32": result = uri_to_path("file:///C://test%20this") self.assertEqual(result, u"C:/test this") else: result = uri_to_path(u"file:///tmp/test%20this") self.assertEqual(result, u"/tmp/test this")
def _save_m3u(self, playlist): file_path = path.uri_to_path(playlist.uri) path.check_file_path_is_inside_base_dir(file_path, self._path) with open(file_path, 'w') as file_handle: for track in playlist.tracks: if track.uri.startswith('file://'): uri = path.uri_to_path(track.uri) else: uri = track.uri file_handle.write(uri + '\n')
def translate(self, track): base_path = self.media_dir.encode("utf-8") result = dict(translator.track_to_mpd_format(track)) result["file"] = uri_to_path(result["file"])[len(base_path) + 1 :] result["key"] = os.path.basename(result["file"]) result["mtime"] = mtime("") return translator.order_mpd_track_info(result.items())
def change_track(self, track): media_dir = self.backend.config['local']['media_dir'] # TODO: check that type is correct. file_path = path.uri_to_path(track.uri).split(b':', 1)[1] file_path = os.path.join(media_dir, file_path) track = track.copy(uri=path.path_to_uri(file_path)) return super(LocalPlaybackProvider, self).change_track(track)
def translate(self, track): base_path = self.media_dir.encode('utf-8') result = dict(translator.track_to_mpd_format(track)) result['file'] = uri_to_path(result['file'])[len(base_path) + 1:] result['key'] = os.path.basename(result['file']) result['mtime'] = mtime('') return translator.order_mpd_track_info(result.items())
def translate(self, track): folder = settings.LOCAL_MUSIC_PATH result = dict(translator.track_to_mpd_format(track)) result['file'] = uri_to_path(result['file']) result['file'] = result['file'][len(folder)+1:] result['key'] = os.path.basename(result['file']) result['mtime'] = mtime('') return translator.order_mpd_track_info(result.items())
def _rename_m3u(self, playlist): src_file_path = path.uri_to_path(playlist.uri) path.check_file_path_is_inside_base_dir(src_file_path, self._path) dst_file_path = self._get_m3u_path(playlist.name) path.check_file_path_is_inside_base_dir(dst_file_path, self._path) shutil.move(src_file_path, dst_file_path) return playlist.copy(uri=path.path_to_uri(dst_file_path))
def tracks_to_directory_tree(tracks): directories = ({}, []) for track in tracks: path = b"" current = directories absolute_track_dir_path = os.path.dirname(uri_to_path(track.uri)) relative_track_dir_path = re.sub("^" + re.escape(settings.LOCAL_MUSIC_PATH), b"", absolute_track_dir_path) for part in split_path(relative_track_dir_path): path = os.path.join(path, part) if path not in current[0]: current[0][path] = ({}, []) current = current[0][path] current[1].append(track) return directories
def process_application(self, bus, message): if message.src != self.fakesink: return if message.structure.get_name() != 'handoff': return uri = unicode(self.uribin.get_property('uri')) self.data['uri'] = uri self.data['mtime'] = os.path.getmtime(path.uri_to_path(uri)) self.data[gst.TAG_DURATION] = self.get_duration() try: self.data_callback(self.data) self.next_uri() except KeyboardInterrupt: self.stop()
def tracks_to_directory_tree(tracks): directories = ({}, []) for track in tracks: path = u'' current = directories local_folder = settings.LOCAL_MUSIC_PATH track_path = uri_to_path(track.uri) track_path = re.sub('^' + re.escape(local_folder), '', track_path) track_dir = os.path.dirname(track_path) for part in split_path(track_dir): path = os.path.join(path, part) if path not in current[0]: current[0][path] = ({}, []) current = current[0][path] current[1].append(track) return directories
def tracks_to_directory_tree(tracks, media_dir): directories = ({}, []) for track in tracks: path = b'' current = directories absolute_track_dir_path = os.path.dirname(uri_to_path(track.uri)) relative_track_dir_path = re.sub( '^' + re.escape(media_dir), b'', absolute_track_dir_path) for part in split_path(relative_track_dir_path): path = os.path.join(path, part) if path not in current[0]: current[0][path] = ({}, []) current = current[0][path] current[1].append(track) return directories
def scan(self, uri): logger.debug('Scanning %s for images', uri) data = self.scanner.scan(uri) images = [] # Use image 'image' tag if available, or smaller, lower quality 'preview-image' otherwise for image in data['tags'].get('image', []) or data['tags'].get('preview-image', []): try: images.append(self.get_or_create_image_file(None, image.data)) except Exception as e: logger.warn('Cannot extract images for %s: %s', uri, e) dirname = os.path.dirname(uri_to_path(uri)) for pattern in self.patterns: for path in glob.glob(os.path.join(dirname, pattern)): try: images.append(self.get_or_create_image(path)) except Exception as e: logger.warn('Cannot read album art from %s: %s', path, e) return images
def scan(self, uri): if not self._scanner: self._scanner = Scanner() data = self._scanner.scan(uri) logger.debug('Scanning for images: %r', data) images = [] for image in data['tags'].get('image', []): try: images.append(self._get_or_create_image(None, image.data)) except Exception as e: logger.warn('Cannot extract image from %s: %s', uri, e) dirname = os.path.dirname(uri_to_path(uri)) for pattern in self._patterns: for path in glob.glob(os.path.join(dirname, pattern)): try: images.append(self._get_or_create_image(path)) except Exception as e: logger.warn('Cannot read album art from %s: %s', path, e) return images
def _add_to_tag_cache(result, dirs, files, media_dir): base_path = media_dir.encode('utf-8') for path, (entry_dirs, entry_files) in dirs.items(): try: text_path = path.decode('utf-8') except UnicodeDecodeError: text_path = urllib.quote(path).decode('utf-8') name = os.path.split(text_path)[1] result.append(('directory', text_path)) result.append(('mtime', get_mtime(os.path.join(base_path, path)))) result.append(('begin', name)) _add_to_tag_cache(result, entry_dirs, entry_files, media_dir) result.append(('end', name)) result.append(('songList begin',)) for track in files: track_result = dict(track_to_mpd_format(track)) # XXX Don't save comments to the tag cache as they may span multiple # lines. We'll start saving track comments when we move from tag_cache # to a JSON file. See #579 for details. if 'Comment' in track_result: del track_result['Comment'] path = uri_to_path(track_result['file']) try: text_path = path.decode('utf-8') except UnicodeDecodeError: text_path = urllib.quote(path).decode('utf-8') relative_path = os.path.relpath(path, base_path) relative_uri = urllib.quote(relative_path) # TODO: use track.last_modified track_result['file'] = relative_uri track_result['mtime'] = get_mtime(path) track_result['key'] = os.path.basename(text_path) track_result = order_mpd_track_info(track_result.items()) result.extend(track_result) result.append(('songList end',))
def _add_to_tag_cache(result, folders, files): music_folder = settings.LOCAL_MUSIC_PATH regexp = '^' + re.escape(music_folder).rstrip('/') + '/?' for path, entry in folders.items(): name = os.path.split(path)[1] mtime = get_mtime(os.path.join(music_folder, path)) result.append(('directory', path)) result.append(('mtime', mtime)) result.append(('begin', name)) _add_to_tag_cache(result, *entry) result.append(('end', name)) result.append(('songList begin',)) for track in files: track_result = dict(track_to_mpd_format(track)) path = uri_to_path(track_result['file']) track_result['mtime'] = get_mtime(path) track_result['file'] = re.sub(regexp, '', path) track_result['key'] = os.path.basename(track_result['file']) track_result = order_mpd_track_info(track_result.items()) result.extend(track_result) result.append(('songList end',))
def _add_to_tag_cache(result, folders, files): base_path = settings.LOCAL_MUSIC_PATH.encode("utf-8") for path, entry in folders.items(): try: text_path = path.decode("utf-8") except UnicodeDecodeError: text_path = urllib.quote(path).decode("utf-8") name = os.path.split(text_path)[1] result.append(("directory", text_path)) result.append(("mtime", get_mtime(os.path.join(base_path, path)))) result.append(("begin", name)) _add_to_tag_cache(result, *entry) result.append(("end", name)) result.append(("songList begin",)) for track in files: track_result = dict(track_to_mpd_format(track)) path = uri_to_path(track_result["file"]) try: text_path = path.decode("utf-8") except UnicodeDecodeError: text_path = urllib.quote(path).decode("utf-8") relative_path = os.path.relpath(path, base_path) relative_uri = urllib.quote(relative_path) track_result["file"] = relative_uri track_result["mtime"] = get_mtime(path) track_result["key"] = os.path.basename(text_path) track_result = order_mpd_track_info(track_result.items()) result.extend(track_result) result.append(("songList end",))
def _add_to_tag_cache(result, folders, files): base_path = settings.LOCAL_MUSIC_PATH.encode('utf-8') for path, entry in folders.items(): try: text_path = path.decode('utf-8') except UnicodeDecodeError: text_path = urllib.quote(path).decode('utf-8') name = os.path.split(text_path)[1] result.append(('directory', text_path)) result.append(('mtime', get_mtime(os.path.join(base_path, path)))) result.append(('begin', name)) _add_to_tag_cache(result, *entry) result.append(('end', name)) result.append(('songList begin',)) for track in files: track_result = dict(track_to_mpd_format(track)) path = uri_to_path(track_result['file']) try: text_path = path.decode('utf-8') except UnicodeDecodeError: text_path = urllib.quote(path).decode('utf-8') relative_path = os.path.relpath(path, base_path) relative_uri = urllib.quote(relative_path) track_result['file'] = relative_uri track_result['mtime'] = get_mtime(path) track_result['key'] = os.path.basename(text_path) track_result = order_mpd_track_info(track_result.items()) result.extend(track_result) result.append(('songList end',))
def playlist_uri_to_path(uri, playlists_dir): if not uri.startswith('m3u:'): raise ValueError('Invalid URI %s' % uri) file_path = uri_to_path(uri) return os.path.join(playlists_dir, file_path)
def main(): args = parse_args() # TODO: support config files and overrides (shared from main?) config_files = [b'/etc/mopidy/mopidy.conf', b'$XDG_CONFIG_DIR/mopidy/mopidy.conf'] config_overrides = [] # TODO: decide if we want to avoid this boilerplate some how. # Initial config without extensions to bootstrap logging. logging_config, _ = config_lib.load(config_files, [], config_overrides) log.setup_root_logger() log.setup_console_logging(logging_config, args.verbosity_level) extensions = ext.load_extensions() config, errors = config_lib.load( config_files, extensions, config_overrides) log.setup_log_levels(config) if not config['local']['media_dir']: logging.warning('Config value local/media_dir is not set.') return if not config['local']['scan_timeout']: logging.warning('Config value local/scan_timeout is not set.') return # TODO: missing config error checking and other default setup code. updaters = {} for e in extensions: for updater_class in e.get_library_updaters(): if updater_class and 'local' in updater_class.uri_schemes: updaters[e.ext_name] = updater_class if not updaters: logging.error('No usable library updaters found.') return elif len(updaters) > 1: logging.error('More than one library updater found. ' 'Provided by: %s', ', '.join(updaters.keys())) return local_updater = updaters.values()[0](config) # TODO: switch to actor? media_dir = config['local']['media_dir'] uris_library = set() uris_update = set() uris_remove = set() logging.info('Checking tracks from library.') for track in local_updater.load(): try: stat = os.stat(path.uri_to_path(track.uri)) if int(stat.st_mtime) > track.last_modified: uris_update.add(track.uri) uris_library.add(track.uri) except OSError: uris_remove.add(track.uri) logging.info('Removing %d moved or deleted tracks.', len(uris_remove)) for uri in uris_remove: local_updater.remove(uri) logging.info('Checking %s for new or modified tracks.', media_dir) for uri in path.find_uris(config['local']['media_dir']): if uri not in uris_library: uris_update.add(uri) logging.info('Found %d new or modified tracks.', len(uris_update)) def store(data): track = translator(data) local_updater.add(track) logging.debug('Added %s', track.uri) def debug(uri, error, debug): logging.warning('Failed %s: %s', uri, error) logging.debug('Debug info for %s: %s', uri, debug) scan_timeout = config['local']['scan_timeout'] logging.info('Scanning new and modified tracks.') # TODO: just pass the library in instead? scanner = Scanner(uris_update, store, debug, scan_timeout) try: scanner.start() except KeyboardInterrupt: scanner.stop() raise logging.info('Done scanning; commiting changes.') local_updater.commit()
def _query_mtime(self, uri): if not uri.startswith('file:'): return None return os.path.getmtime(path.uri_to_path(uri))
def test_latin1_in_uri(self): result = path.uri_to_path("file:///tmp/%E6%F8%E5") self.assertEqual(result, "/tmp/æøå".encode("latin-1"))
def test_unicode_in_uri(self): result = path.uri_to_path("file:///tmp/%C3%A6%C3%B8%C3%A5") self.assertEqual(result, "/tmp/æøå".encode("utf-8"))
def test_space_in_uri(self): result = path.uri_to_path("file:///tmp/test%20this") self.assertEqual(result, "/tmp/test this".encode("utf-8"))
def local_track_uri_to_path(uri, media_dir): if not uri.startswith('local:track:'): raise ValueError('Invalid URI.') file_path = uri_to_path(uri).split(b':', 1)[1] return os.path.join(media_dir, file_path)
def _delete_m3u(self, uri): file_path = path.uri_to_path(uri) path.check_file_path_is_inside_base_dir(file_path, self._path) if os.path.exists(file_path): os.remove(file_path)