Пример #1
0
                except (audiotools.InvalidFilenameFormat,
                        audiotools.OutputFileIsInput,
                        audiotools.DuplicateOutputFile), err:
                    msg.error(unicode(err))
                    sys.exit(1)

        #queue conversion jobs to ProgressQueue
        for (audiofile,
             output_class,
             output_filename,
             output_quality,
             output_metadata) in conversion_jobs:
            #try to create subdirectories in advance
            #so to bail out early if there's an error creating one
            try:
                audiotools.make_dirs(str(output_filename))
            except OSError:
                msg.error(_.ERR_ENCODING_ERROR % (output_filename,))
                sys.exit(1)

            queue.execute(
                function=convert,
                progress_text=unicode(output_filename),
                completion_output=
                (_.LAB_ENCODE %
                 {"source": audiotools.Filename(audiofile.filename),
                  "destination": output_filename}),
                source_audiofile=audiofile,
                destination_filename=str(output_filename),
                destination_class=output_class,
                compression=output_quality,
Пример #2
0
def rip_disk(self):
    """Most of this is just copied from cdda2track, a part of python-audio-tools"""
    try:
        cddareader = CDDAReader(app.config['ripper']['cdrom'], True)
        track_offsets = cddareader.track_offsets
        track_lengths = cddareader.track_lengths
    except (IOError, ValueError, OSError) as err:
        self.update_state(state='FAILURE', meta={'error': str(err)})
        raise Ignore()

    if "offset" in app.config['ripper']:
        read_offset = app.config['ripper']['offset']
    else:
        read_offset = 0
    if "speed" in app.config['ripper']:
        cddareader.set_speed(app.config['ripper']['speed'])

    pre_gap_length = cddareader.track_offsets[1]
    if pre_gap_length > 0:
        with audiotools.BufferedPCMReader(audiotools.PCMReaderWindow(cddareader,
                                                                     read_offset,
                                                                     pre_gap_length,
                                                                     forward_close=False)) as r:
            preserve_pre_gap = set(r.read(pre_gap_length)) != {0}
            if preserve_pre_gap:
                track_offsets[0] = 0
                track_lengths[0] = pre_gap_length
    else:
        preserve_pre_gap = False

    self.update_state(state='PROGRESS', meta={'current': None,
                                              'total': None,
                                              'album': None,
                                              'artist': None,
                                              'metadata': [],
                                              'status': 'Reading metadata'})
    metadata_choices = audiotools.cddareader_metadata_lookup(cddareader)

    if preserve_pre_gap:
        # prepend "track 0" track to start of list for each choice
        for choice in metadata_choices:
            track_0 = merge_metadatas(choice)
            track_0.track_number = 0
            choice.insert(0, track_0)

    album = metadata_choices[0][0].album_name
    artist = metadata_choices[0][0].artist_name
    self.update_state(state='PROGRESS', meta={'current': None,
                                              'total': len(track_offsets),
                                              'album': album,
                                              'artist': artist,
                                              'metadata': jsonify_metadata(metadata_choices[0]),
                                              'status': 'Got metadata, preparing to rip'})

    tracks_to_rip = list(sorted(track_offsets.keys()))
    try:
        output_tracks = list(
            process_output_options(
                metadata_choices=[
                    [c for i, c in
                     enumerate(choices, 0 if preserve_pre_gap else 1)
                     if i in tracks_to_rip]
                    for choices in metadata_choices],
                input_filenames=[
                    audiotools.Filename("track{:02d}.cdda.wav".format(i))
                    for i in tracks_to_rip],
                output_directory=app.config['ripper']['output_directory'],
                format_string=None,
                output_class=audiotools.wav.WaveAudio,
                quality='',
                msg=msg,
                use_default=True))
    except audiotools.UnsupportedTracknameField as err:
        self.update_state(state='FAILURE', meta={'error': str(err)})
        raise Ignore()

    encoded = []
    rip_log = {}
    accuraterip_log_v1 = {}
    accuraterip_log_v2 = {}
    replay_gain = audiotools.ReplayGainCalculator(cddareader.sample_rate)

    for (track_number,
         index,
         (output_class,
          output_filename,
          output_quality,
          output_metadata)) in zip(tracks_to_rip,
                                   range(1, len(tracks_to_rip) + 1),
                                   output_tracks):
        self.update_state(state='PROGRESS', meta={'current': track_number,
                                                  'total': len(tracks_to_rip),
                                                  'album': album,
                                                  'artist': artist,
                                                  'metadata': jsonify_metadata(metadata_choices[0]),
                                                  'status': 'Preparing to rip'})
        cddareader.reset_log()
        track_offset = (track_offsets[track_number] +
                        read_offset -
                        PREVIOUS_TRACK_FRAMES)
        track_length = track_lengths[track_number]

        # seek to indicated starting offset
        if track_offset > 0:
            seeked_offset = cddareader.seek(track_offset)
        else:
            seeked_offset = cddareader.seek(0)

        # make leading directories, if necessary
        try:
            audiotools.make_dirs(str(output_filename))
        except OSError as err:
            self.update_state(state='FAILURE', meta={'error': str(err)})
            raise Ignore()

        # setup individual progress bar per track
        state = {'current': track_number,
                 'total': len(tracks_to_rip),
                 'album': album,
                 'artist': artist,
                 'metadata': jsonify_metadata(metadata_choices[0]),
                 'status': 'Ripping...'}
        progress = CeleryProgressDisplay(msg, state, self)

        # perform extraction over an AccurateRip window
        track_data = audiotools.PCMReaderWindow(
            cddareader,
            track_offset - seeked_offset,
            PREVIOUS_TRACK_FRAMES + track_length + NEXT_TRACK_FRAMES)

        # with AccurateRip calculated during extraction
        accuraterip = AccurateRipReader(
            track_data,
            track_length,
            track_number == min(track_offsets.keys()),
            track_number == max(track_offsets.keys()))

        try:
            # encode output file itself
            track = output_class.from_pcm(
                str(output_filename),
                replay_gain.to_pcm(
                    audiotools.PCMReaderProgress(
                        audiotools.PCMReaderWindow(
                            accuraterip,
                            PREVIOUS_TRACK_FRAMES,
                            track_length,
                            forward_close=False),
                        track_length,
                        progress.update)),
                output_quality,
                total_pcm_frames=track_length)
            encoded.append(track)

            # since the inner PCMReaderWindow only outputs part
            # of the accuraterip reader, we need to ensure
            # anything left over in accuraterip gets processed also
            audiotools.transfer_data(accuraterip.read, lambda f: None)
        except audiotools.EncodingError as err:
            self.update_state(state='FAILURE', meta={'error': str(err)})
            raise Ignore()

        track.set_metadata(output_metadata)

        rip_log[track_number] = cddareader.log()
        accuraterip_log_v1[track_number] = accuraterip.checksums_v1()
        accuraterip_log_v2[track_number] = accuraterip.checksums_v2()

    self.update_state(state='SUCCESS', meta={'total': len(tracks_to_rip),
                                             'album': album,
                                             'artist': artist,
                                             'metadata': jsonify_metadata(metadata_choices[0]),
                                             'status': 'Fully ripped'})

    return {'status': 'done', 'tracks': len(tracks_to_rip)}