Exemple #1
0
    def update(self, create=None):
        if not os.path.isdir(self.directory) and not self.ask_create(create):
            print_(u'Skipping creation of {0}'.format(
                displayable_path(self.directory)))
            return

        converter = self.converter()
        for (item, action) in self.items_action():
            dest = self.destination(item)
            path = self.get_path(item)
            if action == self.MOVE:
                print_(u'>{0} -> {1}'.format(displayable_path(path),
                                             displayable_path(dest)))
                util.mkdirall(dest)
                util.move(path, dest)
                util.prune_dirs(os.path.dirname(path), root=self.directory)
                self.set_path(item, dest)
                item.store()
                item.write(path=dest)
            elif action == self.WRITE:
                print_(u'*{0}'.format(displayable_path(path)))
                item.write(path=path)
            elif action == self.ADD:
                print_(u'+{0}'.format(displayable_path(dest)))
                converter.submit(item)
            elif action == self.REMOVE:
                print_(u'-{0}'.format(displayable_path(path)))
                self.remove_item(item)
                item.store()

        for item, dest in converter.as_completed():
            self.set_path(item, dest)
            item.store()
        converter.shutdown()
Exemple #2
0
def _write_m3u(m3u_path, items_paths):
    """Append relative paths to items into m3u file.
    """
    mkdirall(m3u_path)
    with open(syspath(m3u_path), 'ab') as f:
        for path in items_paths:
            f.write(path + b'\n')
Exemple #3
0
def convert_item(lib, dest_dir):
    while True:
        item = yield

        dest = os.path.join(dest_dir, lib.destination(item, fragment=True))
        dest = os.path.splitext(dest)[0] + '.mp3'

        if os.path.exists(dest):
            log.info(u'Skipping {0} (target file exists)'.format(
                util.displayable_path(item.path)))
            continue

        # Ensure that only one thread tries to create directories at a
        # time. (The existence check is not atomic with the directory
        # creation inside this function.)
        with _fs_lock:
            util.mkdirall(dest)

        maxbr = config['convert']['max_bitrate'].get(int)
        if item.format == 'MP3' and item.bitrate < 1000 * maxbr:
            log.info(u'Copying {0}'.format(util.displayable_path(item.path)))
            util.copy(item.path, dest)
        else:
            encode(item.path, dest)

        item.path = dest
        item.write()

        if config['convert']['embed']:
            album = lib.get_album(item)
            if album:
                artpath = album.artpath
                if artpath:
                    _embed(artpath, [item])
 def create_symlink(self, item):
     dest = self.destination(item)
     util.mkdirall(dest)
     link = (
         os.path.relpath(item.path, os.path.dirname(dest))
         if self.relativelinks == self.LINK_RELATIVE else item.path)
     util.link(link, dest)
Exemple #5
0
def convert_item(lib, dest_dir):
    while True:
        item = yield

        dest = os.path.join(dest_dir, lib.destination(item, fragment=True))
        dest = os.path.splitext(dest)[0] + '.mp3'

        if os.path.exists(dest):
            log.info(u'Skipping {0} (target file exists)'.format(
                util.displayable_path(item.path)
            ))
            continue

        # Ensure that only one thread tries to create directories at a
        # time. (The existence check is not atomic with the directory
        # creation inside this function.)
        with _fs_lock:
            util.mkdirall(dest)

        maxbr = config['convert']['max_bitrate'].get(int)
        if item.format == 'MP3' and item.bitrate < 1000 * maxbr:
            log.info(u'Copying {0}'.format(util.displayable_path(item.path)))
            util.copy(item.path, dest)
        else:
            encode(item.path, dest)

        item.path = dest
        item.write()

        if config['convert']['embed']:
            album = lib.get_album(item)
            if album:
                artpath = album.artpath
                if artpath:
                    _embed(artpath, [item])
Exemple #6
0
    def copy_album_art(self, album, dest_dir, path_formats, pretend=False):
        """Copies the associated cover art of the album. Album must have at
        least one track.
        """
        if not album or not album.artpath:
            return

        album_item = album.items().get()
        # Album shouldn't be empty.
        if not album_item:
            return

        # Get the destination of the first item (track) of the album, we use
        # this function to format the path accordingly to path_formats.
        dest = album_item.destination(basedir=dest_dir, path_formats=path_formats)

        # Remove item from the path.
        dest = os.path.join(*util.components(dest)[:-1])

        dest = album.art_destination(album.artpath, item_dir=dest)
        if album.artpath == dest:
            return

        if not pretend:
            util.mkdirall(dest)

        if os.path.exists(util.syspath(dest)):
            self._log.info("Skipping {0} (target file exists)", util.displayable_path(album.artpath))
            return

        if pretend:
            self._log.info("cp {0} {1}", util.displayable_path(album.artpath), util.displayable_path(dest))
        else:
            self._log.info("Copying cover art to {0}", util.displayable_path(dest))
            util.copy(album.artpath, dest)
    def update(self, create=None):
        if not os.path.isdir(self.directory) and not self.ask_create(create):
            print_(u'Skipping creation of {0}'
                   .format(displayable_path(self.directory)))
            return

        converter = self.converter()
        for (item, action) in self.items_action():
            dest = self.destination(item)
            path = self.get_path(item)
            if action == self.MOVE:
                print_(u'>{0} -> {1}'.format(displayable_path(path),
                                             displayable_path(dest)))
                util.mkdirall(dest)
                util.move(path, dest)
                util.prune_dirs(os.path.dirname(path), root=self.directory)
                self.set_path(item, dest)
                item.store()
                item.write(path=dest)
            elif action == self.WRITE:
                print_(u'*{0}'.format(displayable_path(path)))
                item.write(path=path)
            elif action == self.ADD:
                print_(u'+{0}'.format(displayable_path(dest)))
                converter.submit(item)
            elif action == self.REMOVE:
                print_(u'-{0}'.format(displayable_path(path)))
                self.remove_item(item)
                item.store()

        for item, dest in converter.as_completed():
            self.set_path(item, dest)
            item.store()
        converter.shutdown()
Exemple #8
0
def _save_playlist(m3u_path, items):
    """Saves a list of Items as a playlist at m3u_path
    """
    mkdirall(m3u_path)
    with open(syspath(m3u_path), 'w') as f:
        for item in items:
            f.write(item.path + b'\n')
Exemple #9
0
def convert_item(dest_dir, keep_new, path_formats, command, ext):
    while True:
        item = yield
        dest = item.destination(basedir=dest_dir, path_formats=path_formats)

        # When keeping the new file in the library, we first move the
        # current (pristine) file to the destination. We'll then copy it
        # back to its old path or transcode it to a new path.
        if keep_new:
            original = dest
            converted = replace_ext(item.path, ext)
        else:
            original = item.path
            dest = replace_ext(dest, ext)
            converted = dest

        # Ensure that only one thread tries to create directories at a
        # time. (The existence check is not atomic with the directory
        # creation inside this function.)
        with _fs_lock:
            util.mkdirall(dest)

        if os.path.exists(util.syspath(dest)):
            log.info(u'Skipping {0} (target file exists)'.format(
                util.displayable_path(item.path)
            ))
            continue

        if keep_new:
            log.info(u'Moving to {0}'.
                     format(util.displayable_path(original)))
            util.move(item.path, original)

        if not should_transcode(item):
            # No transcoding necessary.
            log.info(u'Copying {0}'.format(util.displayable_path(item.path)))
            util.copy(original, converted)
        else:
            try:
                encode(command, original, converted)
            except subprocess.CalledProcessError:
                continue

        # Write tags from the database to the converted file.
        item.write(path=converted)

        if keep_new:
            # If we're keeping the transcoded file, read it again (after
            # writing) to get new bitrate, duration, etc.
            item.path = converted
            item.read()
            item.store()  # Store new path and audio data.

        if config['convert']['embed']:
            album = item.get_album()
            if album and album.artpath:
                embed_item(item, album.artpath, itempath=converted)

        plugins.send('after_convert', item=item, dest=dest, keepnew=keep_new)
Exemple #10
0
def convert_item(dest_dir, keep_new, path_formats):
    while True:
        item = yield
        dest = _destination(dest_dir, item, keep_new, path_formats)

        if os.path.exists(util.syspath(dest)):
            log.info(u'Skipping {0} (target file exists)'.format(
                util.displayable_path(item.path)
            ))
            continue

        # Ensure that only one thread tries to create directories at a
        # time. (The existence check is not atomic with the directory
        # creation inside this function.)
        with _fs_lock:
            util.mkdirall(dest)

        # When keeping the new file in the library, we first move the
        # current (pristine) file to the destination. We'll then copy it
        # back to its old path or transcode it to a new path.
        if keep_new:
            log.info(u'Moving to {0}'.
                     format(util.displayable_path(dest)))
            util.move(item.path, dest)

        if not should_transcode(item):
            # No transcoding necessary.
            log.info(u'Copying {0}'.format(util.displayable_path(item.path)))
            if keep_new:
                util.copy(dest, item.path)
            else:
                util.copy(item.path, dest)

        else:
            if keep_new:
                _, ext = get_format()
                item.path = os.path.splitext(item.path)[0] + ext
                encode(dest, item.path)
            else:
                encode(item.path, dest)

        # Write tags from the database to the converted file.
        if not keep_new:
            item.path = dest
        item.write()

        # If we're keeping the transcoded file, read it again (after
        # writing) to get new bitrate, duration, etc.
        if keep_new:
            item.read()
            item.store()  # Store new path and audio data.

        if config['convert']['embed']:
            album = item.get_album()
            if album:
                artpath = album.artpath
                if artpath:
                    _embed(artpath, [item])
Exemple #11
0
    def copy_album_art(self, album, dest_dir, path_formats, pretend=False):
        """Copies or converts the associated cover art of the album. Album must
        have at least one track.
        """
        if not album or not album.artpath:
            return

        album_item = album.items().get()
        # Album shouldn't be empty.
        if not album_item:
            return

        # Get the destination of the first item (track) of the album, we use
        # this function to format the path accordingly to path_formats.
        dest = album_item.destination(basedir=dest_dir, path_formats=path_formats)

        # Remove item from the path.
        dest = os.path.join(*util.components(dest)[:-1])

        dest = album.art_destination(album.artpath, item_dir=dest)
        if album.artpath == dest:
            return

        if not pretend:
            util.mkdirall(dest)

        if os.path.exists(util.syspath(dest)):
            self._log.info(u"Skipping {0} (target file exists)", util.displayable_path(album.artpath))
            return

        # Decide whether we need to resize the cover-art image.
        resize = False
        maxwidth = None
        if self.config["album_art_maxwidth"]:
            maxwidth = self.config["album_art_maxwidth"].get(int)
            size = ArtResizer.shared.get_size(album.artpath)
            self._log.debug("image size: {}", size)
            if size:
                resize = size[0] > maxwidth
            else:
                self._log.warning(u"Could not get size of image (please see " u"documentation for dependencies).")

        # Either copy or resize (while copying) the image.
        if resize:
            self._log.info(
                u"Resizing cover art from {0} to {1}", util.displayable_path(album.artpath), util.displayable_path(dest)
            )
            if not pretend:
                ArtResizer.shared.resize(maxwidth, album.artpath, dest)
        else:
            if pretend:
                self._log.info(u"cp {0} {1}", util.displayable_path(album.artpath), util.displayable_path(dest))
            else:
                self._log.info(
                    u"Copying cover art to {0}", util.displayable_path(album.artpath), util.displayable_path(dest)
                )
                util.copy(album.artpath, dest)
Exemple #12
0
def convert_item(dest_dir, keep_new, path_formats):
    while True:
        item = yield
        dest = _destination(dest_dir, item, keep_new, path_formats)

        if os.path.exists(util.syspath(dest)):
            log.info(u'Skipping {0} (target file exists)'.format(
                util.displayable_path(item.path)))
            continue

        # Ensure that only one thread tries to create directories at a
        # time. (The existence check is not atomic with the directory
        # creation inside this function.)
        with _fs_lock:
            util.mkdirall(dest)

        # When keeping the new file in the library, we first move the
        # current (pristine) file to the destination. We'll then copy it
        # back to its old path or transcode it to a new path.
        if keep_new:
            log.info(u'Moving to {0}'.format(util.displayable_path(dest)))
            util.move(item.path, dest)

        if not should_transcode(item):
            # No transcoding necessary.
            log.info(u'Copying {0}'.format(util.displayable_path(item.path)))
            if keep_new:
                util.copy(dest, item.path)
            else:
                util.copy(item.path, dest)

        else:
            if keep_new:
                _, ext = get_format()
                item.path = os.path.splitext(item.path)[0] + ext
                encode(dest, item.path)
            else:
                encode(item.path, dest)

        # Write tags from the database to the converted file.
        if not keep_new:
            item.path = dest
        item.write()

        # If we're keeping the transcoded file, read it again (after
        # writing) to get new bitrate, duration, etc.
        if keep_new:
            item.read()
            item.store()  # Store new path and audio data.

        if config['convert']['embed']:
            album = item.get_album()
            if album:
                artpath = album.artpath
                if artpath:
                    _embed(artpath, [item])
Exemple #13
0
        def _convert(item):
            dest = self.destination(item)
            with fs_lock:
                util.mkdirall(dest)

            if self.should_transcode(item):
                convert.encode(self.convert_cmd, item.path, dest)
            else:
                log.debug(u'copying {0}'.format(displayable_path(dest)))
                util.copy(item.path, dest, replace=True)
            return item, dest
Exemple #14
0
 def setUp(self):
     # Make library and item.
     self.lib = beets.library.Library(':memory:')
     self.libdir = os.path.abspath(os.path.join(_common.RSRC, 'testlibdir'))
     self.lib.directory = self.libdir
     self.i = item()
     self.i.path = self.lib.destination(self.i)
     # Make a music file.
     util.mkdirall(self.i.path)
     touch(self.i.path)
     # Make an album with the item.
     self.ai = self.lib.add_album((self.i, ))
Exemple #15
0
 def setUp(self):
     # Make library and item.
     self.lib = beets.library.Library(':memory:')
     self.libdir = os.path.abspath(os.path.join(_common.RSRC, 'testlibdir'))
     self.lib.directory = self.libdir
     self.i = item()
     self.i.path = self.lib.destination(self.i)
     # Make a music file.
     util.mkdirall(self.i.path)
     touch(self.i.path)
     # Make an album with the item.
     self.ai = self.lib.add_album((self.i,))
Exemple #16
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))
        def _convert(item):
            dest = self.destination(item)
            with fs_lock:
                util.mkdirall(dest)

            if self.should_transcode(item):
                self._encode(self.convert_cmd, item.path, dest)
                if self._embed:
                    embed_art(item, dest)
            else:
                log.debug(u'copying {0}'.format(displayable_path(dest)))
                util.copy(item.path, dest, replace=True)
            return item, dest
Exemple #18
0
 def setUp(self):
     # Make library and item.
     self.lib = beets.library.Library(':memory:')
     self.lib.path_formats = \
         {'default': join('$albumartist', '$album', '$title')}
     self.libdir = os.path.join(_common.RSRC, 'testlibdir')
     self.lib.directory = self.libdir
     self.i = item()
     # Make a file for the item.
     self.i.path = self.lib.destination(self.i)
     util.mkdirall(self.i.path)
     touch(self.i.path)
     # Make an album.
     self.ai = self.lib.add_album((self.i, ))
Exemple #19
0
    def move(self,
             item,
             copy=False,
             in_album=False,
             basedir=None,
             with_album=True):
        """Move the item to its designated location within the library
        directory (provided by destination()). Subdirectories are
        created as needed. If the operation succeeds, the item's path
        field is updated to reflect the new location.
        
        If copy is True, moving the file is copied rather than moved.
        
        If in_album is True, then the track is treated as part of an
        album even if it does not yet have an album_id associated with
        it. (This allows items to be moved before they are added to the
        database, a performance optimization.)

        basedir overrides the library base directory for the
        destination.

        If the item is in an album, the album is given an opportunity to
        move its art. (This can be disabled by passing
        with_album=False.)
        
        The item is stored to the database if it is in the database, so
        any dirty fields prior to the move() call will be written as a
        side effect. You probably want to call save() to commit the DB
        transaction.
        """
        dest = self.destination(item, in_album=in_album, basedir=basedir)

        # Create necessary ancestry for the move.
        util.mkdirall(dest)

        # Perform the move and store the change.
        old_path = item.path
        item.move(dest, copy)
        if item.id is not None:
            self.store(item)

        # If this item is in an album, move its art.
        if with_album:
            album = self.get_album(item)
            if album:
                album.move_art(copy)

        # Prune vacated directory.
        if not copy:
            util.prune_dirs(os.path.dirname(old_path), self.directory)
Exemple #20
0
    def setUp(self):
        super(RemoveTest, self).setUp()

        # Make library and item.
        self.lib = beets.library.Library(':memory:')
        self.libdir = os.path.join(self.temp_dir, b'testlibdir')
        self.lib.directory = self.libdir
        self.i = item(self.lib)
        self.i.path = self.i.destination()
        # Make a music file.
        util.mkdirall(self.i.path)
        touch(self.i.path)
        # Make an album with the item.
        self.ai = self.lib.add_album((self.i, ))
Exemple #21
0
 def setUp(self):
     # Make library and item.
     self.lib = beets.library.Library(':memory:')
     self.lib.path_formats = \
         {'default': join('$albumartist', '$album', '$title')}
     self.libdir = os.path.join(_common.RSRC, 'testlibdir')
     self.lib.directory = self.libdir
     self.i = item()
     # Make a file for the item.
     self.i.path = self.lib.destination(self.i)
     util.mkdirall(self.i.path)
     touch(self.i.path)
     # Make an album.
     self.ai = self.lib.add_album((self.i,))
Exemple #22
0
    def setUp(self):
        super(RemoveTest, self).setUp()

        # Make library and item.
        self.lib = beets.library.Library(':memory:')
        self.libdir = os.path.join(self.temp_dir, 'testlibdir')
        self.lib.directory = self.libdir
        self.i = item(self.lib)
        self.i.path = self.i.destination()
        # Make a music file.
        util.mkdirall(self.i.path)
        touch(self.i.path)
        # Make an album with the item.
        self.ai = self.lib.add_album((self.i,))
    def update(self, create=None):
        if (not os.path.isdir(syspath(self.directory))
                and not self.ask_create(create)):
            print_(u'Skipping creation of {0}'
                   .format(displayable_path(self.directory)))
            return

        converter = self.converter()
        for (item, actions) in self.items_actions():
            dest = self.destination(item)
            path = self.get_path(item)
            for action in actions:
                if action == self.MOVE:
                    print_(u'>{0} -> {1}'.format(displayable_path(path),
                                                 displayable_path(dest)))
                    util.mkdirall(dest)
                    util.move(path, dest)
                    util.prune_dirs(os.path.dirname(path), root=self.directory)
                    self.set_path(item, dest)
                    item.store()
                    path = dest
                elif action == self.WRITE:
                    print_(u'*{0}'.format(displayable_path(path)))
                    item.write(path=path)
                elif action == self.SYNC_ART:
                    print_(u'~{0}'.format(displayable_path(path)))
                    self.sync_art(item, path)
                elif action == self.ADD:
                    print_(u'+{0}'.format(displayable_path(dest)))
                    converter.submit(item)
                elif action == self.REMOVE:
                    print_(u'-{0}'.format(displayable_path(path)))
                    self.remove_item(item)
                    item.store()

        for item, dest in converter.as_completed():
            self.set_path(item, dest)
            item.store()
        converter.shutdown()

        for (album, actions) in self.albums_actions():
            for action in actions:
                dest_dir = self.album_destination(album)
                if action == self.COPY_ART:
                    path = album.artpath
                    dest = album.art_destination(path, dest_dir)
                    util.copy(path, dest, replace=True)
                    print_(u'$~{0}'.format(displayable_path(dest)))
                    print_(u'$!{0}'.format(displayable_path(path)))
Exemple #24
0
        def _convert(item):
            dest = self.destination(item)
            with fs_lock:
                util.mkdirall(dest)

            if self.should_transcode(item):
                self._encode(self.convert_cmd, item.path, dest)
                # Don't rely on the converter to write correct/complete tags.
                item.write(path=dest)
            else:
                self._log.debug(u'copying {0}'.format(displayable_path(dest)))
                util.copy(item.path, dest, replace=True)
            if self._embed:
                self.sync_art(item, dest)
            return item, dest
Exemple #25
0
 def setUp(self):
     # Make library and item.
     self.lib = beets.library.Library(':memory:')
     self.libdir = os.path.abspath(os.path.join(_common.RSRC, 'testlibdir'))
     self.lib.directory = self.libdir
     self.i = item()
     self.i.path = self.lib.destination(self.i)
     # Make a music file.
     util.mkdirall(self.i.path)
     touch(self.i.path)
     # Make an album.
     self.ai = self.lib.add_album((self.i,))
     # Make an art file too.
     self.art = self.lib.get_album(self.i).art_destination('something.jpg')
     touch(self.art)
     self.ai.artpath = self.art
Exemple #26
0
 def setUp(self):
     # Make library and item.
     self.lib = beets.library.Library(':memory:')
     self.libdir = os.path.abspath(os.path.join(_common.RSRC, 'testlibdir'))
     self.lib.directory = self.libdir
     self.i = item()
     self.i.path = self.lib.destination(self.i)
     # Make a music file.
     util.mkdirall(self.i.path)
     touch(self.i.path)
     # Make an album.
     self.ai = self.lib.add_album((self.i, ))
     # Make an art file too.
     self.art = self.lib.get_album(self.i).art_destination('something.jpg')
     touch(self.art)
     self.ai.artpath = self.art
Exemple #27
0
    def update_playlists(self, lib):
        self._log.info(u"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(u"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)

        # 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]:
                    f.write(path + b'\n')

        self._log.info(u"{0} playlists updated", len(self._matched_playlists))
Exemple #28
0
    def move(self, item, copy=False, in_album=False, basedir=None,
             with_album=True):
        """Move the item to its designated location within the library
        directory (provided by destination()). Subdirectories are
        created as needed. If the operation succeeds, the item's path
        field is updated to reflect the new location.
        
        If copy is True, moving the file is copied rather than moved.
        
        If in_album is True, then the track is treated as part of an
        album even if it does not yet have an album_id associated with
        it. (This allows items to be moved before they are added to the
        database, a performance optimization.)

        basedir overrides the library base directory for the
        destination.

        If the item is in an album, the album is given an opportunity to
        move its art. (This can be disabled by passing
        with_album=False.)
        
        The item is stored to the database if it is in the database, so
        any dirty fields prior to the move() call will be written as a
        side effect. You probably want to call save() to commit the DB
        transaction.
        """
        dest = self.destination(item, in_album=in_album, basedir=basedir)
        
        # Create necessary ancestry for the move.
        util.mkdirall(dest)
        
        # Perform the move and store the change.
        old_path = item.path
        item.move(dest, copy)
        if item.id is not None:
            self.store(item)

        # If this item is in an album, move its art.
        if with_album:
            album = self.get_album(item)
            if album:
                album.move_art(copy)

        # Prune vacated directory.
        if not copy:
            util.prune_dirs(os.path.dirname(old_path), self.directory)
Exemple #29
0
    def setUp(self):
        super(AlbumFileTest, self).setUp()

        # Make library and item.
        self.lib = beets.library.Library(':memory:')
        self.lib.path_formats = \
            [('default', join('$albumartist', '$album', '$title'))]
        self.libdir = os.path.join(self.temp_dir, b'testlibdir')
        self.lib.directory = self.libdir
        self.i = item(self.lib)
        # Make a file for the item.
        self.i.path = self.i.destination()
        util.mkdirall(self.i.path)
        touch(self.i.path)
        # Make an album.
        self.ai = self.lib.add_album((self.i, ))
        # Alternate destination dir.
        self.otherdir = os.path.join(self.temp_dir, b'testotherdir')
Exemple #30
0
    def setUp(self):
        super(AlbumFileTest, self).setUp()

        # Make library and item.
        self.lib = beets.library.Library(':memory:')
        self.lib.path_formats = \
            [('default', join('$albumartist', '$album', '$title'))]
        self.libdir = os.path.join(self.temp_dir, 'testlibdir')
        self.lib.directory = self.libdir
        self.i = item(self.lib)
        # Make a file for the item.
        self.i.path = self.i.destination()
        util.mkdirall(self.i.path)
        touch(self.i.path)
        # Make an album.
        self.ai = self.lib.add_album((self.i,))
        # Alternate destination dir.
        self.otherdir = os.path.join(self.temp_dir, 'testotherdir')
Exemple #31
0
    def update_playlists(self, lib):
        self._log.info(u"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)

        for playlist in self._matched_playlists:
            name, (query, q_sort), (album_query, a_q_sort) = playlist
            self._log.debug(u"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())

            m3us = {}
            # 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)
            # Now iterate through the m3us that we need to generate
            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]:
                        f.write(path + b'\n')

        self._log.info(u"{0} playlists updated", len(self._matched_playlists))
Exemple #32
0
    def move(self, copy=False, basedir=None, with_album=True, pretend=False):
        """Move the item to its designated location within the library
        directory (provided by destination()). Subdirectories are
        created as needed. If the operation succeeds, the item's path
        field is updated to reflect the new location.

        If copy is True, moving the file is copied rather than moved.

        basedir overrides the library base directory for the
        destination.

        If the item is in an album, the album is given an opportunity to
        move its art. (This can be disabled by passing
        with_album=False.)

        The item is stored to the database if it is in the database, so
        any dirty fields prior to the move() call will be written as a
        side effect. You probably want to call save() to commit the DB
        transaction.
        """
        self._check_db()
        dest = self.destination(basedir=basedir)
        if pretend:
            return dest

        # Create necessary ancestry for the move.
        util.mkdirall(dest)

        # Perform the move and store the change.
        old_path = self.path
        self.move_file(dest, copy)
        self.store()

        # If this item is in an album, move its art.
        if with_album:
            album = self.get_album()
            if album:
                album.move_art(copy)
                album.store()

        # Prune vacated directory.
        if not copy:
            util.prune_dirs(os.path.dirname(old_path), self._db.directory)
Exemple #33
0
    def setUp(self):
        super(ArtFileTest, self).setUp()

        # Make library and item.
        self.lib = beets.library.Library(':memory:')
        self.libdir = os.path.abspath(os.path.join(self.temp_dir, 'testlibdir'))
        self.lib.directory = self.libdir
        self.i = item()
        self.i.path = self.lib.destination(self.i)
        # Make a music file.
        util.mkdirall(self.i.path)
        touch(self.i.path)
        # Make an album.
        self.ai = self.lib.add_album((self.i,))
        # Make an art file too.
        self.art = self.lib.get_album(self.i).art_destination('something.jpg')
        touch(self.art)
        self.ai.artpath = self.art
        # Alternate destination dir.
        self.otherdir = os.path.join(self.temp_dir, 'testotherdir')
Exemple #34
0
def copy_album_art(album, dest_dir, path_formats, pretend=False):
    """Copies the associated cover art of the album. Album must have at least
    one track.
    """
    if not album or not album.artpath:
        return

    album_item = album.items().get()
    # Album shouldn't be empty.
    if not album_item:
        return

    # Get the destination of the first item (track) of the album, we use this
    # function to format the path accordingly to path_formats.
    dest = album_item.destination(basedir=dest_dir, path_formats=path_formats)

    # Remove item from the path.
    dest = os.path.join(*util.components(dest)[:-1])

    dest = album.art_destination(album.artpath, item_dir=dest)
    if album.artpath == dest:
        return

    if not pretend:
        util.mkdirall(dest)

    if os.path.exists(util.syspath(dest)):
        log.info(u'Skipping {0} (target file exists)'.format(
            util.displayable_path(album.artpath)
        ))
        return

    if pretend:
        log.info(u'cp {0} {1}'.format(
            util.displayable_path(album.artpath),
            util.displayable_path(dest),
        ))
    else:
        log.info(u'Copying cover art to {0}'.format(
                 util.displayable_path(dest)))
        util.copy(album.artpath, dest)
Exemple #35
0
    def move(self, library, copy=False, in_album=False, basedir=None):
        """Move the item to its designated location within the library
        directory (provided by destination()). Subdirectories are
        created as needed. If the operation succeeds, the item's path
        field is updated to reflect the new location.
        
        If copy is True, moving the file is copied rather than moved.
        
        If in_album is True, then the track is treated as part of an
        album even if it does not yet have an album_id associated with
        it. (This allows items to be moved before they are added to the
        database, a performance optimization.)

        basedir overrides the library base directory for the
        destination.

        Passes on appropriate exceptions if directories cannot be
        created or moving/copying fails.
        
        Note that one should almost certainly call store() and
        library.save() after this method in order to keep on-disk data
        consistent.
        """
        dest = library.destination(self, in_album=in_album, basedir=basedir)
        
        # Create necessary ancestry for the move.
        util.mkdirall(dest)
        
        if not samefile(self.path, dest):
            if copy:
                util.copy(self.path, dest)
            else:
                util.move(self.path, dest)
            
        # Either copying or moving succeeded, so update the stored path.
        old_path = self.path
        self.path = dest

        # Prune vacated directory.
        if not copy:
            util.prune_dirs(os.path.dirname(old_path), library.directory)
Exemple #36
0
    def setUp(self):
        super(ArtFileTest, self).setUp()

        # Make library and item.
        self.lib = beets.library.Library(':memory:')
        self.libdir = os.path.join(self.temp_dir, b'testlibdir')
        self.lib.directory = self.libdir
        self.i = item(self.lib)
        self.i.path = self.i.destination()
        # Make a music file.
        util.mkdirall(self.i.path)
        touch(self.i.path)
        # Make an album.
        self.ai = self.lib.add_album((self.i, ))
        # Make an art file too.
        self.art = self.lib.get_album(self.i).art_destination('something.jpg')
        touch(self.art)
        self.ai.artpath = self.art
        self.ai.store()
        # Alternate destination dir.
        self.otherdir = os.path.join(self.temp_dir, b'testotherdir')
Exemple #37
0
    def update_playlists(self, lib):
        self._log.info("Updating smart playlists...")
        playlists = self.config['playlists'].get(list)
        playlist_dir = self.config['playlist_dir'].as_filename()
        relative_to = self.config['relative_to'].get()
        if relative_to:
            relative_to = normpath(relative_to)

        for playlist in playlists:
            self._log.debug(u"Creating playlist {0[name]}", playlist)
            items = []
            if 'album_query' in playlist:
                items.extend(_items_for_query(lib, playlist['album_query'],
                                              True))
            if 'query' in playlist:
                items.extend(_items_for_query(lib, playlist['query'], False))

            m3us = {}
            # 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(playlist['name'], True)
                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)
            # Now iterate through the m3us that we need to generate
            for m3u in m3us:
                m3u_path = normpath(os.path.join(playlist_dir, m3u))
                mkdirall(m3u_path)
                with open(syspath(m3u_path), 'w') as f:
                    for path in m3us[m3u]:
                        f.write(path + b'\n')
        self._log.info("{0} playlists updated", len(playlists))
Exemple #38
0
    def update_playlists(self, lib):
        self._log.info("Updating smart playlists...")
        playlists = self.config['playlists'].get(list)
        playlist_dir = self.config['playlist_dir'].as_filename()
        relative_to = self.config['relative_to'].get()
        if relative_to:
            relative_to = normpath(relative_to)

        for playlist in playlists:
            self._log.debug(u"Creating playlist {0[name]}", playlist)
            items = []
            if 'album_query' in playlist:
                items.extend(
                    _items_for_query(lib, playlist['album_query'], True))
            if 'query' in playlist:
                items.extend(_items_for_query(lib, playlist['query'], False))

            m3us = {}
            # 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(playlist['name'], True)
                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)
            # Now iterate through the m3us that we need to generate
            for m3u in m3us:
                m3u_path = normpath(os.path.join(playlist_dir, m3u))
                mkdirall(m3u_path)
                with open(syspath(m3u_path), 'w') as f:
                    for path in m3us[m3u]:
                        f.write(path + '\n')
        self._log.info("{0} playlists updated", len(playlists))
Exemple #39
0
    def move(self, library, copy=False, in_album=False):
        """Move the item to its designated location within the library
        directory (provided by destination()). Subdirectories are
        created as needed. If the operation succeeds, the item's path
        field is updated to reflect the new location.
        
        If copy is True, moving the file is copied rather than moved.
        
        If in_album is True, then the track is treated as part of an
        album even if it does not yet have an album_id associated with
        it. (This allows items to be moved before they are added to the
        database, a performance optimization.)

        Passes on appropriate exceptions if directories cannot be created
        or moving/copying fails.
        
        Note that one should almost certainly call store() and
        library.save() after this method in order to keep on-disk data
        consistent.
        """
        dest = library.destination(self, in_album=in_album)
        
        # Create necessary ancestry for the move.
        util.mkdirall(dest)
        
        if not shutil._samefile(syspath(self.path), syspath(dest)):
            if copy:
                # copyfile rather than copy will not copy permissions
                # bits, thus possibly making the copy writable even when
                # the original is read-only.
                shutil.copyfile(syspath(self.path), syspath(dest))
            else:
                shutil.move(syspath(self.path), syspath(dest))
            
        # Either copying or moving succeeded, so update the stored path.
        self.path = dest
Exemple #40
0
    def move(self, library, copy=False, in_album=False):
        """Move the item to its designated location within the library
        directory (provided by destination()). Subdirectories are
        created as needed. If the operation succeeds, the item's path
        field is updated to reflect the new location.
        
        If copy is True, moving the file is copied rather than moved.
        
        If in_album is True, then the track is treated as part of an
        album even if it does not yet have an album_id associated with
        it. (This allows items to be moved before they are added to the
        database, a performance optimization.)

        Passes on appropriate exceptions if directories cannot be created
        or moving/copying fails.
        
        Note that one should almost certainly call store() and
        library.save() after this method in order to keep on-disk data
        consistent.
        """
        dest = library.destination(self, in_album=in_album)

        # Create necessary ancestry for the move.
        util.mkdirall(dest)

        if not shutil._samefile(syspath(self.path), syspath(dest)):
            if copy:
                # copyfile rather than copy will not copy permissions
                # bits, thus possibly making the copy writable even when
                # the original is read-only.
                shutil.copyfile(syspath(self.path), syspath(dest))
            else:
                shutil.move(syspath(self.path), syspath(dest))

        # Either copying or moving succeeded, so update the stored path.
        self.path = dest
 def _convert(item):
     dest = self.destination(item)
     util.mkdirall(dest)
     util.copy(item.path, dest, replace=True)
     return item, dest
Exemple #42
0
def convert_item(dest_dir, keep_new, path_formats, format, pretend=False):
    command, ext = get_format(format)
    item, original, converted = None, None, None
    while True:
        item = yield (item, original, converted)
        dest = item.destination(basedir=dest_dir, path_formats=path_formats)

        # When keeping the new file in the library, we first move the
        # current (pristine) file to the destination. We'll then copy it
        # back to its old path or transcode it to a new path.
        if keep_new:
            original = dest
            converted = item.path
            if should_transcode(item, format):
                converted = replace_ext(converted, ext)
        else:
            original = item.path
            if should_transcode(item, format):
                dest = replace_ext(dest, ext)
            converted = dest

        # Ensure that only one thread tries to create directories at a
        # time. (The existence check is not atomic with the directory
        # creation inside this function.)
        if not pretend:
            with _fs_lock:
                util.mkdirall(dest)

        if os.path.exists(util.syspath(dest)):
            log.info(u'Skipping {0} (target file exists)'.format(
                util.displayable_path(item.path)
            ))
            continue

        if keep_new:
            if pretend:
                log.info(u'mv {0} {1}'.format(
                    util.displayable_path(item.path),
                    util.displayable_path(original),
                ))
            else:
                log.info(u'Moving to {0}'.format(
                    util.displayable_path(original))
                )
                util.move(item.path, original)

        if should_transcode(item, format):
            try:
                encode(command, original, converted, pretend)
            except subprocess.CalledProcessError:
                continue
        else:
            if pretend:
                log.info(u'cp {0} {1}'.format(
                    util.displayable_path(original),
                    util.displayable_path(converted),
                ))
            else:
                # No transcoding necessary.
                log.info(u'Copying {0}'.format(
                    util.displayable_path(item.path))
                )
                util.copy(original, converted)

        if pretend:
            continue

        # Write tags from the database to the converted file.
        item.try_write(path=converted)

        if keep_new:
            # If we're keeping the transcoded file, read it again (after
            # writing) to get new bitrate, duration, etc.
            item.path = converted
            item.read()
            item.store()  # Store new path and audio data.

        if config['convert']['embed']:
            album = item.get_album()
            if album and album.artpath:
                embed_item(item, album.artpath, itempath=converted)

        if keep_new:
            plugins.send('after_convert', item=item,
                         dest=dest, keepnew=True)
        else:
            plugins.send('after_convert', item=item,
                         dest=converted, keepnew=False)
 def create_symlink(self, item):
     dest = self.destination(item)
     util.mkdirall(dest)
     os.symlink(item.path, dest)
Exemple #44
0
    def convert_item(self, dest_dir, keep_new, path_formats, fmt, pretend=False):
        command, ext = get_format(fmt)
        item, original, converted = None, None, None
        while True:
            item = yield (item, original, converted)
            dest = item.destination(basedir=dest_dir, path_formats=path_formats)

            # When keeping the new file in the library, we first move the
            # current (pristine) file to the destination. We'll then copy it
            # back to its old path or transcode it to a new path.
            if keep_new:
                original = dest
                converted = item.path
                if should_transcode(item, fmt):
                    converted = replace_ext(converted, ext)
            else:
                original = item.path
                if should_transcode(item, fmt):
                    dest = replace_ext(dest, ext)
                converted = dest

            # Ensure that only one thread tries to create directories at a
            # time. (The existence check is not atomic with the directory
            # creation inside this function.)
            if not pretend:
                with _fs_lock:
                    util.mkdirall(dest)

            if os.path.exists(util.syspath(dest)):
                self._log.info("Skipping {0} (target file exists)", util.displayable_path(item.path))
                continue

            if keep_new:
                if pretend:
                    self._log.info("mv {0} {1}", util.displayable_path(item.path), util.displayable_path(original))
                else:
                    self._log.info("Moving to {0}", util.displayable_path(original))
                    util.move(item.path, original)

            if should_transcode(item, fmt):
                try:
                    self.encode(command, original, converted, pretend)
                except subprocess.CalledProcessError:
                    continue
            else:
                if pretend:
                    self._log.info("cp {0} {1}", util.displayable_path(original), util.displayable_path(converted))
                else:
                    # No transcoding necessary.
                    self._log.info("Copying {0}", util.displayable_path(item.path))
                    util.copy(original, converted)

            if pretend:
                continue

            # Write tags from the database to the converted file.
            item.try_write(path=converted)

            if keep_new:
                # If we're keeping the transcoded file, read it again (after
                # writing) to get new bitrate, duration, etc.
                item.path = converted
                item.read()
                item.store()  # Store new path and audio data.

            if self.config["embed"]:
                album = item.get_album()
                if album and album.artpath:
                    self._log.debug("embedding album art from {}", util.displayable_path(album.artpath))
                    art.embed_item(self._log, item, album.artpath, itempath=converted)

            if keep_new:
                plugins.send("after_convert", item=item, dest=dest, keepnew=True)
            else:
                plugins.send("after_convert", item=item, dest=converted, keepnew=False)
Exemple #45
0
 def create_symlink(self, item):
     dest = self.destination(item)
     util.mkdirall(dest)
     os.symlink(item.path, dest)
Exemple #46
0
 def test_child_does_not_exist(self):
     path = os.path.join(self.temp_dir, 'foo', 'bar', 'baz', 'qux.mp3')
     util.mkdirall(path)
     self.assertTrue(not os.path.exists(
         os.path.join(self.temp_dir, 'foo', 'bar', 'baz', 'qux.mp3')
     ))
Exemple #47
0
    def convert_item(self, dest_dir, keep_new, path_formats, fmt,
                     pretend=False, link=False, hardlink=False):
        """A pipeline thread that converts `Item` objects from a
        library.
        """
        command, ext = get_format(fmt)
        item, original, converted = None, None, None
        while True:
            item = yield (item, original, converted)
            dest = item.destination(basedir=dest_dir,
                                    path_formats=path_formats)

            # When keeping the new file in the library, we first move the
            # current (pristine) file to the destination. We'll then copy it
            # back to its old path or transcode it to a new path.
            if keep_new:
                original = dest
                converted = item.path
                if should_transcode(item, fmt):
                    converted = replace_ext(converted, ext)
            else:
                original = item.path
                if should_transcode(item, fmt):
                    dest = replace_ext(dest, ext)
                converted = dest

            # Ensure that only one thread tries to create directories at a
            # time. (The existence check is not atomic with the directory
            # creation inside this function.)
            if not pretend:
                with _fs_lock:
                    util.mkdirall(dest)

            if os.path.exists(util.syspath(dest)):
                self._log.info(u'Skipping {0} (target file exists)',
                               util.displayable_path(item.path))
                continue

            if keep_new:
                if pretend:
                    self._log.info(u'mv {0} {1}',
                                   util.displayable_path(item.path),
                                   util.displayable_path(original))
                else:
                    self._log.info(u'Moving to {0}',
                                   util.displayable_path(original))
                    util.move(item.path, original)

            if should_transcode(item, fmt):
                linked = False
                try:
                    self.encode(command, original, converted, pretend)
                except subprocess.CalledProcessError:
                    continue
            else:
                linked = link or hardlink
                if pretend:
                    msg = 'ln' if hardlink else ('ln -s' if link else 'cp')

                    self._log.info(u'{2} {0} {1}',
                                   util.displayable_path(original),
                                   util.displayable_path(converted),
                                   msg)
                else:
                    # No transcoding necessary.
                    msg = 'Hardlinking' if hardlink \
                        else ('Linking' if link else 'Copying')

                    self._log.info(u'{1} {0}',
                                   util.displayable_path(item.path),
                                   msg)

                    if hardlink:
                        util.hardlink(original, converted)
                    elif link:
                        util.link(original, converted)
                    else:
                        util.copy(original, converted)

            if pretend:
                continue

            id3v23 = self.config['id3v23'].as_choice([True, False, 'inherit'])
            if id3v23 == 'inherit':
                id3v23 = None

            # Write tags from the database to the converted file.
            item.try_write(path=converted, id3v23=id3v23)

            if keep_new:
                # If we're keeping the transcoded file, read it again (after
                # writing) to get new bitrate, duration, etc.
                item.path = converted
                item.read()
                item.store()  # Store new path and audio data.

            if self.config['embed'] and not linked:
                album = item._cached_album
                if album and album.artpath:
                    self._log.debug(u'embedding album art from {}',
                                    util.displayable_path(album.artpath))
                    art.embed_item(self._log, item, album.artpath,
                                   itempath=converted, id3v23=id3v23)

            if keep_new:
                plugins.send('after_convert', item=item,
                             dest=dest, keepnew=True)
            else:
                plugins.send('after_convert', item=item,
                             dest=converted, keepnew=False)
Exemple #48
0
    def copy_album_art(self, album, dest_dir, path_formats, pretend=False,
                       link=False, hardlink=False):
        """Copies or converts the associated cover art of the album. Album must
        have at least one track.
        """
        if not album or not album.artpath:
            return

        album_item = album.items().get()
        # Album shouldn't be empty.
        if not album_item:
            return

        # Get the destination of the first item (track) of the album, we use
        # this function to format the path accordingly to path_formats.
        dest = album_item.destination(basedir=dest_dir,
                                      path_formats=path_formats)

        # Remove item from the path.
        dest = os.path.join(*util.components(dest)[:-1])

        dest = album.art_destination(album.artpath, item_dir=dest)
        if album.artpath == dest:
            return

        if not pretend:
            util.mkdirall(dest)

        if os.path.exists(util.syspath(dest)):
            self._log.info(u'Skipping {0} (target file exists)',
                           util.displayable_path(album.artpath))
            return

        # Decide whether we need to resize the cover-art image.
        resize = False
        maxwidth = None
        if self.config['album_art_maxwidth']:
            maxwidth = self.config['album_art_maxwidth'].get(int)
            size = ArtResizer.shared.get_size(album.artpath)
            self._log.debug('image size: {}', size)
            if size:
                resize = size[0] > maxwidth
            else:
                self._log.warning(u'Could not get size of image (please see '
                                  u'documentation for dependencies).')

        # Either copy or resize (while copying) the image.
        if resize:
            self._log.info(u'Resizing cover art from {0} to {1}',
                           util.displayable_path(album.artpath),
                           util.displayable_path(dest))
            if not pretend:
                ArtResizer.shared.resize(maxwidth, album.artpath, dest)
        else:
            if pretend:
                msg = 'ln' if hardlink else ('ln -s' if link else 'cp')

                self._log.info(u'{2} {0} {1}',
                               util.displayable_path(album.artpath),
                               util.displayable_path(dest),
                               msg)
            else:
                msg = 'Hardlinking' if hardlink \
                    else ('Linking' if link else 'Copying')

                self._log.info(u'{2} cover art from {0} to {1}',
                               util.displayable_path(album.artpath),
                               util.displayable_path(dest),
                               msg)
                if hardlink:
                    util.hardlink(album.artpath, dest)
                elif link:
                    util.link(album.artpath, dest)
                else:
                    util.copy(album.artpath, dest)
Exemple #49
0
def convert_item(dest_dir, keep_new, path_formats):
    while True:
        item = yield
        dest = _destination(dest_dir, item, keep_new, path_formats)

        if os.path.exists(util.syspath(dest)):
            log.info(u'Skipping {0} (target file exists)'.format(
                util.displayable_path(item.path)))
            continue

        # Ensure that only one thread tries to create directories at a
        # time. (The existence check is not atomic with the directory
        # creation inside this function.)
        with _fs_lock:
            util.mkdirall(dest)

        # When keeping the new file in the library, we first move the
        # current (pristine) file to the destination. We'll then copy it
        # back to its old path or transcode it to a new path.
        if keep_new:
            log.info(u'Moving to {0}'.format(util.displayable_path(dest)))
            util.move(item.path, dest)
            original = dest
            _, ext = get_format()
            converted = os.path.splitext(item.path)[0] + ext
        else:
            original = item.path
            converted = dest

        if not should_transcode(item):
            # No transcoding necessary.
            log.info(u'Copying {0}'.format(util.displayable_path(item.path)))
            util.copy(original, converted)
        else:
            try:
                encode(original, converted)
            except subprocess.CalledProcessError:
                continue

        # Write tags from the database to the converted file.
        item.write(path=converted)

        if keep_new:
            # If we're keeping the transcoded file, read it again (after
            # writing) to get new bitrate, duration, etc.
            item.path = converted
            item.read()
            item.store()  # Store new path and audio data.

        if config['convert']['embed']:
            album = item.get_album()
            if album:
                artpath = album.artpath
                if artpath:
                    try:
                        _embed(artpath, [converted])
                    except IOError as exc:
                        log.warn(
                            u'could not embed cover art in {0}: {1}'.format(
                                util.displayable_path(item.path), exc))

        plugins.send('after_convert', item=item, dest=dest, keepnew=keep_new)
Exemple #50
0
 def _convert(item):
     dest = self.destination(item)
     util.mkdirall(dest)
     util.copy(item.path, dest, replace=True)
     return item, dest
Exemple #51
0
 def test_parent_exists(self):
     path = os.path.join(self.temp_dir, 'foo', 'bar', 'baz', 'qux.mp3')
     util.mkdirall(path)
     self.assertTrue(os.path.isdir(
         os.path.join(self.temp_dir, 'foo', 'bar', 'baz')
     ))
Exemple #52
0
 def test_child_does_not_exist(self):
     path = os.path.join(self.temp_dir, b'foo', b'bar', b'baz', b'qux.mp3')
     util.mkdirall(path)
     self.assertTrue(not os.path.exists(
         os.path.join(self.temp_dir, b'foo', b'bar', b'baz', b'qux.mp3')))
Exemple #53
0
 def test_parent_exists(self):
     path = os.path.join(self.temp_dir, b'foo', b'bar', b'baz', b'qux.mp3')
     util.mkdirall(path)
     self.assertTrue(
         os.path.isdir(os.path.join(self.temp_dir, b'foo', b'bar', b'baz')))