Esempio n. 1
0
 def generate_clip(self, song: Song, start: int, end: int) -> Path:
     """Create one clip from an existing MP3 file."""
     assert song.filepath is not None
     album: Optional[str] = song.album
     if album is None:
         album = song.filepath.parent.name
     assert album is not None
     album = Song.clean(album)
     dest_dir = self.options.clip_destination_dir(album)
     filename = song.filename
     if filename is None or filename == '':
         filename = song.filepath.name
     assert filename is not None
     assert filename != ''
     if not dest_dir.exists():
         dest_dir.mkdir(parents=True)
     dest_path = dest_dir / filename
     metadata = Metadata(artist=Song.clean(song.artist),
                         title=Song.clean(song.title),
                         album=album)
     with self.mp3.create(dest_path, metadata=metadata) as output:
         src = self.mp3.use(song).clip(start, end)
         src = src.normalize(0)
         output.append(src)
         output.generate()
     return dest_path
Esempio n. 2
0
    def _sort_level(self, parent: str, column: str, reverse: bool) -> None:
        """
        Sort specified directory level and then any children of that
        level.
        """
        # create tuple of the value of selected column + its ID for
        # each item at this level of the tree
        has_children = False
        pairs: List[Tuple[str, str]] = []
        for ref_id in self.tree.get_children(parent):
            value = Song.clean(self.tree.set(ref_id, column)).lower()
            pairs.append((
                value,
                ref_id,
            ))
            children = self.tree.get_children(ref_id)
            if children:
                self._sort_level(ref_id, column, reverse)
                has_children = True

        if has_children and column != 'filename':
            return

        pairs.sort(reverse=reverse)

        # rearrange items into sorted positions
        for index, (_, ref_id) in enumerate(pairs):
            self.tree.move(ref_id, parent, index)
Esempio n. 3
0
 def generate_clip(self, song: Song, start: int, end: int) -> Path:
     """Create one clip from an existing MP3 file."""
     album: Optional[str] = song.album
     if album is None:
         album = song.fullpath.parent.name
     assert album is not None
     album = Song.clean(album)
     dest_dir = self.options.clip_destination_dir(album)
     filename = song.filename
     assert filename is not None
     assert filename != ''
     if not dest_dir.exists():
         dest_dir.mkdir(parents=True)
     dest_path = dest_dir / filename
     metadata = song.as_dict(exclude={'filename', 'ref_id'})
     metadata['album'] = album
     if start > int(song.duration):
         raise ValueError(
             f'{start} is beyond the duration of song "{song.title}"')
     with self.mp3.create(dest_path,
                          metadata=Metadata(**metadata)) as output:
         src = self.mp3.use(song).clip(start, end)
         output.append(src)
         output.generate()
     return dest_path
Esempio n. 4
0
 def _generate(self, destination: MP3FileWriter,
               progress: Progress) -> None:
     """generate output file, combining all input files"""
     output: Optional[AudioSegment] = None
     num_files = float(len(destination._files))
     for index, mp3file in enumerate(destination._files, 1):
         progress.pct = 50.0 * index / num_files
         progress.text = f'Adding {mp3file.filename.name}'
         if progress.abort:
             return
         seg = AudioSegment.from_mp3(str(mp3file.filename))
         if mp3file.start is not None:
             if mp3file.end is not None:
                 seg = seg[mp3file.start:mp3file.end]
             else:
                 seg = seg[mp3file.start:]
         elif mp3file.end is not None:
             seg = seg[:mp3file.end]
         if mp3file.headroom is not None:
             seg = seg.normalize(mp3file.headroom)
         if output is None:
             output = seg
         else:
             output += seg
     tags = None
     if destination._metadata is not None:
         tags = {
             "artist": Song.clean(destination._metadata.artist),
             "title": Song.clean(destination._metadata.title)
         }
         if destination._metadata.album:
             tags["album"] = Song.clean(destination._metadata.album)
     assert output is not None
     progress.text = f'Encoding MP3 file "{destination.filename.name}"'
     progress.pct = 50.0
     if progress.abort:
         return
     dest_dir = destination.filename.parent
     if not dest_dir.exists():
         dest_dir.mkdir(parents=True)
     output.export(str(destination.filename),
                   format="mp3",
                   bitrate=destination.bitrate,
                   tags=tags)
     progress.pct = 100.0
Esempio n. 5
0
 def generate(self, songs: List[Song]) -> List[Path]:
     """
     Generate all clips for all selected Songs
     Returns list of filenames of new clips
     """
     total_songs = len(songs)
     clips: List[Path] = []
     start = int(Duration(self.options.clip_start))
     end = start + 1000 * self.options.clip_duration
     for index, song in enumerate(songs):
         self.progress.text = '{} ({:d}/{:d})'.format(
             Song.clean(song.title), index, total_songs)
         self.progress.pct = 100.0 * float(index) / float(total_songs)
         #pylint: disable=broad-except
         try:
             clips.append(self.generate_clip(song, start, end))
         except InvalidMP3Exception as err:
             traceback.print_exc()
             print(r'Error generating clip: {0} - {1}'.format(
                 Song.clean(song.title), str(err)))
     self.progress.pct = 100.0
     self.progress.text = 'Finished generating clips'
     return clips