def get_drive(self, regex, line):
     """Get the name of the ripping drive used."""
     re_drive = re.compile(fmt_ptn(self.patterns['drive']) + regex)
     result = re_drive.match(line)
     if result:
         return result.group(1).strip()
     raise UnrecognizedException('Could not parse ripping drive')
Beispiel #2
0
def eval_offset(log, offset):
    """Validate the offset used by the ripped drive."""
    if not re.match('-?[0-9]+', offset):
        raise UnrecognizedException('Could not parse drive offset.')

    if not offset.startswith('-') and offset != '0':
        offset = '+' + offset

    if check_for_virtual_drives(log):
        log.add_deduction('Virtual drive')
        log.flagged = True
        return

    drivestr = prep_drive_name(log)
    if not drivestr:
        return

    results = drive_db_query(drivestr)
    if not results:
        # Drive not in database
        if offset == '0':
            log.add_deduction('Zero offset')
        log.unindexed_drive = True
        return

    offsets = {row[0] for row in results}
    if offset not in offsets:
        log.add_deduction('Drive offset',
                          extra_phrase='correct offsets are: {}'.format(
                              ', '.join(offsets)))
Beispiel #3
0
    def check(self, main_log):
        """Checks the EAC logs."""
        logs = combined.split_combined(main_log)
        for log in logs:
            if len(log.concat_contents) < 20:
                raise UnrecognizedException('Cannot parse log file; log file too short')

            log.version = self.check_version(log)
            log.album = log.concat_contents[2]
            log.drive = self.check_drive(log)

            self.index_log(log)
            self.evaluate_settings(log)
            parsers.index_toc(log)
            self.is_there_a_htoa(log)
            self.check_tracks(log)
            parsers.parse_checksum(log, self.patterns['checksum'], 'V1.0 beta 1', 'EAC <1.0')
            if self.markup:
                markup(log, self.patterns, self.translation)

        main_log = combined.defragment(logs)
        validation.validate_track_count(main_log)
        validation.validate_track_settings(main_log)
        self.deduct_and_score(main_log)

        return main_log
Beispiel #4
0
def validate_track_settings(log, xld=False):
    """Also verify that each track contains the required data."""
    if xld:
        if log.range:
            required_settings = ['copy crc']
        else:
            required_settings = ['filename', 'copy crc']
    else:
        required_settings = ['filename', 'peak', 'copy crc']

    for track in log.tracks:
        if track in log.track_errors['Aborted copy']:
            pass
        elif not all(setting in log.tracks[track]
                     for setting in required_settings):
            raise UnrecognizedException(
                'Unable to confirm presence of required track data')

    # Check for Test & Copy and CRC Mismatches
    if not all('test crc' in track for track in log.tracks.values()):
        if log.has_deduction('HTOA extracted') or log.has_deduction(
                'HTOA not ripped twice'):
            # Verify that every track minus HTOA is T&C (Range based is index 0)
            if all('test crc' in track for i, track in log.tracks.items()
                   if i):
                return
        log.add_deduction('Test & Copy')
Beispiel #5
0
    def check(self, log):
        """Checks the XLD logs."""
        if len(log.contents) < 25:
            raise UnrecognizedException('Cannot parse log file; log file too short')

        log.version = self.check_version(log)
        log.album = log.concat_contents[2]
        log.drive = self.check_drive(log)
        self.check_cdr(log)

        self.index_log(log)
        self.evaluate_settings(log)
        parsers.index_toc(log)
        self.check_tracks(log)
        self.is_there_a_htoa(log)
        validation.validate_track_count(log)
        validation.validate_track_settings(log, xld=True)
        parsers.parse_checksum(
            log, self.patterns['checksum'], '20121222', 'XLD pre-142.2'
        )

        self.deduct_and_score(log)
        if self.markup:
            markup(log, self.patterns, self.translation)

        return log
 def verify_version(self, regex, line, ripper):
     """Verify that the version of the log is legitimate."""
     result = regex.search(line)
     if result:
         version, date = result.group(1), result.group(2)
         if (version, date) in VERSIONS[ripper]:
             return version
     raise UnrecognizedException('Unrecognized {} version'.format(ripper))
Beispiel #7
0
def validate_track_count(log):
    """Verify the presence of all tracks and check for a data track."""
    if not log.range:
        # Data tracks have one extra ToC entry, but one less ripped track
        if max(log.tracks.keys()) + 1 == max(log.toc.keys()):
            log.add_deduction('Data track detected')
        elif len(log.tracks) != len(log.toc):
            if not log.ripper == 'XLD' or not log.has_deduction('HTOA extracted'):
                raise UnrecognizedException('Not all tracks are represented in the log')
Beispiel #8
0
def get_track_number(log, index, track_word):
    """Get the track number from the header line of a track block."""
    result = re.search(r'{} ([0-9]+)'.format(fmt_ptn(track_word)),
                       log.contents[index])
    if result:
        return int(result.group(1))
    elif log.range:  # EAC range rip has no track number
        return 0
    else:
        raise UnrecognizedException('A track has an invalid block header')
Beispiel #9
0
def get_ripper(contents):
    """Determine the ripper used in the log."""
    if not contents:  # Is file empty?
        raise UnrecognizedException('Empty log file')

    # Even foreign EAC logs start with this line.
    eac_regex = re.compile(r'Exact Audio Copy V[0-1]\.[0-9]+.*?from.*')
    xld_regex = re.compile(
        r'X Lossless Decoder version ([0-9abc]+) \([0-9\.]+\)')
    if eac_regex.match(contents[0]):
        return 'EAC'
    elif xld_regex.match(contents[0]):
        return 'XLD'
    else:
        # Unfortunately, not all EAC <=0.95 logs are English, so a compiled multi-language ripper
        # regex pattern is necessary.
        re_95 = re.compile('|'.join(list(EAC_RIPLINES.values())))
        if re_95.match(contents[0]):
            return 'EAC95'
        else:
            raise UnrecognizedException('Unrecognized ripper')
Beispiel #10
0
    def evaluate_unmatched_settings(self, log, settings):
        """Override super to account for burst mode not having some settings."""
        burst_no_exist = ['Accurate stream', 'Audio cache', 'C2 pointers']
        if log.has_deduction('Read mode'):
            if any(setting not in settings for setting in burst_no_exist):
                raise UnrecognizedException('Invalid rip settings for a burst/fast mode rip')
            for setting in burst_no_exist:
                del settings[setting]

        if log.has_deduction('Combined offset') and 'Drive offset' in settings:
            del settings['Drive offset']

        super().evaluate_unmatched_settings(log, settings)
Beispiel #11
0
def determine_language(log):
    """Determine the language of the log file, and verify that it is an EAC log file."""
    if log.ripper == 'XLD':
        return 'english'

    useful_contents = [
        re.sub(r'\s+', ' ', l.rstrip()) for l in log.contents if l.strip()
    ]
    for line in useful_contents[:2]:
        for language, line_starter in EAC_RIPLINES.items():
            if re.match(line_starter, line):
                return language

    raise UnrecognizedException('Unrecognized/unsupported language')
Beispiel #12
0
 def check_cdr(self, log):
     """Check the log to see if CD-R is flagged."""
     result = re.search(
         fmt_ptn(self.patterns['disc type']) + r' : (.*)', log.concat_contents[4],
     )
     if result:
         if result.group(1) == 'Pressed CD':
             return
         elif result.group(1) == 'CD-Recordable':
             log.cdr = True
             log.flagged = True
             log.add_deduction('CD-R')
         else:
             raise UnrecognizedException('Unknown disc type')
Beispiel #13
0
 def evaluate_unmatched_settings(self, log, settings):
     """Evaluate all unmatched settings and deduct for them."""
     for key in settings:
         if log.range and key == 'Gap handling':
             log.add_deduction('Could not verify gap handling')
         elif key == 'Gap handling':
             log.add_deduction('Gap handling')
         elif key == 'ID3 tags':
             log.add_deduction('Could not verify presence of ID3 tags')
         elif key == 'Null samples':
             log.add_deduction('Could not verify usage of null samples')
         else:
             raise UnrecognizedException(
                 'One or more required settings could not be found')
    def validate_indices(self, log):
        """Validate the indices of notable lines in the log."""
        if not log.track_indices:
            raise UnrecognizedException('No tracks found')

        # +4 to compensate for range rip lines
        for i in range(max(log.track_indices) + 4, len(log.contents)):
            # Need to check the full_contents and add the extra space for AR summary leading space.
            if re.match(r' ?\w', log.full_contents[i]):
                log.track_indices.append(i - 1)
                log.index_footer = i
                break

        log.index_tracks = min(log.track_indices)
        if not log.index_toc:
            log.index_toc = log.index_tracks
Beispiel #15
0
    def check(self, main_log):
        """Checks the EAC logs."""
        logs = combined.split_combined(main_log)
        for log in logs:
            if len(log.concat_contents) < 12:
                raise UnrecognizedException(
                    'Cannot parse log file; log file too short')

            log.version = 'EAC <=0.95'
            log.album = log.concat_contents[1]
            log.drive = self.check_drive(log)

            self.index_log(log, ninety_five=True)
            self.evaluate_settings(log)
            self.check_tracks(log)
            if self.markup:
                markup(log, self.patterns, self.translation)

        main_log = combined.defragment(logs, eac95=True)
        validation.validate_track_settings(main_log)
        self.deduct_and_score(main_log)

        return main_log