Ejemplo n.º 1
0
    def update_playlist(self, filename, base_dir):
        """Find M3U playlists in the specified directory."""
        changes = 0
        deletions = 0

        with tempfile.NamedTemporaryFile(mode='w+b', delete=False) as tempfp:
            new_playlist = tempfp.name
            with open(filename, mode='rb') as fp:
                for line in fp:
                    original_path = line.rstrip(b'\r\n')

                    # Ensure that path from playlist is absolute
                    is_relative = not os.path.isabs(line)
                    if is_relative:
                        lookup = os.path.join(base_dir, original_path)
                    else:
                        lookup = original_path

                    try:
                        new_path = self.changes[beets.util.normpath(lookup)]
                    except KeyError:
                        if self.config['forward_slash']:
                            line = path_as_posix(line)
                        tempfp.write(line)
                    else:
                        if new_path is None:
                            # Item has been deleted
                            deletions += 1
                            continue

                        changes += 1
                        if is_relative:
                            new_path = os.path.relpath(new_path, base_dir)
                        line = line.replace(original_path, new_path)
                        if self.config['forward_slash']:
                            line = path_as_posix(line)
                        tempfp.write(line)

        if changes or deletions:
            self._log.info(
                'Updated playlist {0} ({1} changes, {2} deletions)'.format(
                    filename, changes, deletions))
            beets.util.copy(new_playlist, filename, replace=True)
        beets.util.remove(new_playlist)
Ejemplo n.º 2
0
    def update_playlists(self, lib):
        self._log.info("Updating {0} smart playlists...",
                       len(self._matched_playlists))

        playlist_dir = self.config['playlist_dir'].as_filename()
        playlist_dir = bytestring_path(playlist_dir)
        relative_to = self.config['relative_to'].get()
        if relative_to:
            relative_to = normpath(relative_to)

        # Maps playlist filenames to lists of track filenames.
        m3us = {}

        for playlist in self._matched_playlists:
            name, (query, q_sort), (album_query, a_q_sort) = playlist
            self._log.debug("Creating playlist {0}", name)
            items = []

            if query:
                items.extend(lib.items(query, q_sort))
            if album_query:
                for album in lib.albums(album_query, a_q_sort):
                    items.extend(album.items())

            # As we allow tags in the m3u names, we'll need to iterate through
            # the items and generate the correct m3u file names.
            for item in items:
                m3u_name = item.evaluate_template(name, True)
                m3u_name = sanitize_path(m3u_name, lib.replacements)
                if m3u_name not in m3us:
                    m3us[m3u_name] = []
                item_path = item.path
                if relative_to:
                    item_path = os.path.relpath(item.path, relative_to)
                if item_path not in m3us[m3u_name]:
                    m3us[m3u_name].append(item_path)

        prefix = bytestring_path(self.config['prefix'].as_str())
        # Write all of the accumulated track lists to files.
        for m3u in m3us:
            m3u_path = normpath(
                os.path.join(playlist_dir, bytestring_path(m3u)))
            mkdirall(m3u_path)
            with open(syspath(m3u_path), 'wb') as f:
                for path in m3us[m3u]:
                    if self.config['forward_slash'].get():
                        path = path_as_posix(path)
                    if self.config['urlencode']:
                        path = bytestring_path(pathname2url(path))
                    f.write(prefix + path + b'\n')

        self._log.info("{0} playlists updated", len(self._matched_playlists))
Ejemplo n.º 3
0
    def write_ratings_file(self, lib):
        """ Android Poweramp supports importing ratings from playlist files
            This function writes a playlist file containing all songs with
            metadata tag #EXT-X-RATING:<n>, where n is 1-5.
        """

        if not self.config["ratings_file"]:
            return
        # FIXME: Unsanitized rating file location
        rating_file = os.path.expanduser(
            bytestring_path(self.config["ratings_file"].get()))
        rating_dir = os.path.dirname(rating_file)
        if not os.path.exists(rating_dir):
            os.makedirs(rating_dir)

        # If the file has %s use a timestamp
        if "%s" in str(rating_file):
            old_files = glob.glob(rating_file % b"*")
            if len(old_files):
                # Remove up to one file to avoid surprises
                os.remove(old_files[0])
            rating_file = rating_file % bytearray(str(int(time.time())),
                                                  "utf-8")

        ratings = {}
        for item in lib.items(""):
            # Grab rating
            userrating = None
            if 'userrating' in item:
                userrating = item.userrating
            elif 'externalrating' in item:
                userrating = item.externalrating

            # Add to dict
            if userrating is not None:
                item_path = os.path.relpath(item.path, rating_dir)
                ratings[item_path] = userrating

        # Write ratings to rating file
        with open(rating_file, 'wb') as f:
            for fn, rating in ratings.items():
                if self.config['forward_slash'].get():
                    fn = path_as_posix(fn)
                f.write(b"#EXT-X-RATING:" + bytes("%d" %
                                                  (rating // 2), 'utf-8') +
                        b"\n" + fn + b"\n")

        self._log.info(u"Wrote ratings to {0}", rating_file)
Ejemplo n.º 4
0
 def test_forward_slash(self):
     p = br'C:\a\b\c'
     a = br'C:/a/b/c'
     self.assertEqual(util.path_as_posix(p), a)