├── .github └── workflows │ ├── github_artifact.yml │ └── main.yml ├── .gitignore ├── .travis.yml ├── LICENSE ├── Makefile ├── README.md ├── heybrochecklog ├── __init__.py ├── __main__.py ├── analyze.py ├── logfile.py ├── markup │ ├── __init__.py │ └── matches.py ├── resources │ ├── __init__.py │ ├── drives.db │ ├── eac │ │ ├── bulgarian.json │ │ ├── chinese (simplified).json │ │ ├── czech.json │ │ ├── dutch.json │ │ ├── english.json │ │ ├── french.json │ │ ├── german.json │ │ ├── italian.json │ │ ├── polish.json │ │ ├── russian.json │ │ ├── serbian.json │ │ ├── slovak.json │ │ ├── spanish.json │ │ ├── swedish.json │ │ └── uzbek.json │ ├── eac95 │ │ ├── chinese (simplified).json │ │ ├── chinese (traditional).json │ │ ├── croatian.json │ │ ├── czech.json │ │ ├── danish.json │ │ ├── dutch.json │ │ ├── english.json │ │ ├── french.json │ │ ├── german.json │ │ ├── hungarian.json │ │ ├── italian.json │ │ ├── japanese.json │ │ ├── korean.json │ │ ├── norwegian.json │ │ ├── portuguese-br.json │ │ ├── portuguese.json │ │ ├── russian.json │ │ ├── serbian.json │ │ ├── slovak.json │ │ ├── spanish.json │ │ ├── swedish.json │ │ ├── taiwan.json │ │ ├── ukrainian.json │ │ └── uzbek.json │ └── xld.json ├── score │ ├── __init__.py │ ├── eac.py │ ├── eac95.py │ ├── integrity.py │ ├── logchecker.py │ ├── modules │ │ ├── __init__.py │ │ ├── combined.py │ │ ├── drives.py │ │ ├── parsers.py │ │ └── validation.py │ ├── xld.py │ └── xld_integrity.py ├── shared.py └── translate.py ├── poetry.lock ├── pyproject.toml ├── scripts ├── accuraterip_offsets.py ├── eac95_builder │ ├── __init__.py │ ├── constants.py │ ├── generators.py │ └── to_json.py ├── eac_builder │ ├── constants.py │ ├── generators.py │ └── to_json.py └── generate_marked_up_test_log.py ├── setup.cfg ├── setup.py └── tests ├── eac95_test.py ├── eac_test.py ├── logs ├── EAC │ ├── 1.3-good.log │ ├── abort.log │ ├── bad-htoa.log │ ├── bad-russian-099.log │ ├── badcombo.log │ ├── burst.log │ ├── data-track.log │ ├── eac-99-good.log │ ├── fast.log │ ├── hella-aborted.log │ ├── htoa-not-ripped-twice.log │ ├── inconsistent-accuraterip.log │ ├── mac-roman-charset.log │ ├── markup │ │ ├── 1.3-good.log.markup │ │ ├── abort.log.markup │ │ ├── bad-htoa.log.markup │ │ ├── bad-russian-099.log.markup │ │ ├── badcombo.log.markup │ │ ├── burst.log.markup │ │ ├── data-track.log.markup │ │ ├── eac-99-good.log.markup │ │ ├── fast.log.markup │ │ ├── hella-aborted.log.markup │ │ ├── htoa-not-ripped-twice.log.markup │ │ ├── inconsistent-accuraterip.log.markup │ │ ├── mac-roman-charset.log.markup │ │ ├── negative-offset.log.markup │ │ ├── perf-hunid.log.markup │ │ ├── range-rip.log.markup │ │ ├── russian-range-rip-ar-issue.log.markup │ │ ├── russian1.log.markup │ │ ├── russian2.log.markup │ │ ├── russian3.log.markup │ │ ├── russian4.log.markup │ │ ├── shitty.log.markup │ │ ├── spanish-log-extra-colons.log.markup │ │ └── swedish-timing-problems.log.markup │ ├── negative-offset.log │ ├── perf-hunid.log │ ├── range-rip.log │ ├── russian-range-rip-ar-issue.log │ ├── russian1.log │ ├── russian2.log │ ├── russian3.log │ ├── russian4.log │ ├── shitty.log │ ├── spanish-log-extra-colons.log │ └── swedish-timing-problems.log ├── EAC95 │ ├── also-bad.log │ ├── bad-settings.log │ ├── burst.log │ ├── had-decoding-issues.log │ ├── markup │ │ ├── also-bad.log.markup │ │ ├── bad-settings.log.markup │ │ ├── burst.log.markup │ │ ├── had-decoding-issues.log.markup │ │ └── read-mode.log.markup │ └── read-mode.log ├── XLD │ ├── 100-percent-new.log │ ├── bad-chardet-no-checksum.log │ ├── cdparanoia.log │ ├── cdr-multi-filename.log │ ├── crc-mismatch.log │ ├── htoa.log │ ├── markup │ │ ├── 100-percent-new.log.markup │ │ ├── bad-chardet-no-checksum.log.markup │ │ ├── cdparanoia.log.markup │ │ ├── cdr-multi-filename.log.markup │ │ ├── crc-mismatch.log.markup │ │ ├── htoa.log.markup │ │ ├── range-vbox.log.markup │ │ ├── ripping-error.log.markup │ │ └── xld-cdp.log.markup │ ├── range-vbox.log │ ├── ripping-error.log │ └── xld-cdp.log ├── spanish-099.log ├── translations │ ├── bad-russian-099.log │ ├── french-big-calm.log │ ├── russian-range-rip-ar-issue.log │ ├── spanish-log-extra-colons.log │ ├── swedish-timing-problems.log │ └── translated │ │ └── french-big-calm.log.translated └── unrecognized │ ├── eac-edited-at-top-extra-spaces.log │ ├── eac-edited-wrongly-split-combined.log │ ├── eac-failed-to-properly-forge-a.log │ ├── eac-unrecognized-not-all-tracks.log │ └── eac-wrong-date.log ├── translate_test.py ├── unrecognized_test.py └── xld_test.py /.github/workflows/github_artifact.yml: -------------------------------------------------------------------------------- 1 | name: CD 2 | 3 | on: 4 | push: 5 | tags: 6 | - '*' 7 | 8 | jobs: 9 | build: 10 | runs-on: ubuntu-latest 11 | 12 | steps: 13 | - uses: actions/checkout@v3 14 | 15 | - name: Setup Python 16 | uses: actions/setup-python@v4 17 | with: 18 | python-version: 3.10.11 19 | 20 | - name: Install poetry 21 | run: python -m pip install poetry 22 | 23 | - name: Install dependencies 24 | run: poetry install 25 | 26 | - name: Update dependencies according to the manifest 27 | run: poetry update 28 | 29 | - name: Build project 30 | run: poetry build 31 | 32 | - name: Create release to github according to tag 33 | uses: svenstaro/upload-release-action@v2 34 | with: 35 | repo_token: ${{ secrets.GITHUB_TOKEN }} 36 | file: dist/heybrochecklog* 37 | tag: ${{ github.ref }} 38 | overwrite: true 39 | file_glob: true -------------------------------------------------------------------------------- /.github/workflows/main.yml: -------------------------------------------------------------------------------- 1 | name: CI 2 | 3 | on: 4 | push: 5 | branches: [ master ] 6 | pull_request: 7 | branches: [ master ] 8 | 9 | jobs: 10 | build: 11 | runs-on: ubuntu-latest 12 | 13 | steps: 14 | - uses: actions/checkout@v2 15 | 16 | - name: Setup python 17 | uses: actions/setup-python@v4 18 | with: 19 | python-version: '3.10.11' 20 | 21 | - name: Install poetry 22 | run: python -m pip install poetry 23 | 24 | - name: Run poetry install 25 | run: poetry install 26 | 27 | - name: Run tests 28 | run: poetry run pytest 29 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | __pycache__ 2 | 3 | .* 4 | !.gitignore 5 | !.flake8 6 | !.travis.yml 7 | 8 | translation-files 9 | build/ 10 | dist/ 11 | *.egg-info 12 | *.spec -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: python 2 | python: 3 | - "3.5" 4 | - "3.6" 5 | - "3.7" 6 | - "3.8" 7 | cache: pip 8 | install: 9 | - pip install poetry 10 | - poetry install 11 | script: 12 | - make tests 13 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | lint: 2 | isort -rc heybrochecklog/ tests/ 3 | # black heybrochecklog/ tests/ 4 | 5 | tests: 6 | # black --check heybrochecklog/ tests/ 7 | python3 -m pytest 8 | 9 | clean: 10 | rm -rf build/ dist/ *.egg-info 11 | find . -type d -name "__pycache__" -exec rm -r "{}" \; 12 | 13 | .PHONY: lint tests clean 14 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # hey-bro-check-log 2 | 3 | [![Come on Join us!](https://img.shields.io/badge/Discord-Come%20on%20Join%20us!-7289da)](https://discord.gg/mC4Yp6J) 4 | ![Github Actions Badge](https://github.com/doujinmusic/hbcl/actions/workflows/main.yml/badge.svg) 5 | 6 | This version of hey-bro-check-log is maintained by doujin café discord community. 7 | 8 | A python tool which analyzes and verifies good ripping practices and potential inaccuracies 9 | in CD ripping logs. 10 | 11 | ## Support 12 | 13 | - Supports checking EAC and XLD logs. 14 | - Matches deductions on Redacted (minus stupid aggregate ones) 15 | - Supports combined EAC logs 16 | - Detects other irregularities and special occurrences in the rip 17 | - Data tracks 18 | - Irregular AR results 19 | - Hidden tracks and extraction 20 | - Foreign language support (temperamental, as it's based on the most recent translation files). 21 | 22 | ## Running CLI 23 | 24 | ``` 25 | usage: heybrochecklog [-h] [-t] [-m] [-s] [-ei] log [log ...] 26 | 27 | Tool to analyze, translate, and score a CD Rip Log. 28 | 29 | positional arguments: 30 | log log file to check. 31 | 32 | optional arguments: 33 | -h, --help show this help message and exit 34 | -t, --translate translate a foreign log to English 35 | -m, --markup print the marked up version of the log after analyzing 36 | -s, --score-only Only print the score of the log. 37 | -ei, --experimental-integrity 38 | Enable Log Integrity Checking (Experimental, EAC & XLD only) 39 | 40 | ``` 41 | 42 | ## Acknowledgements 43 | 44 | - [Original hey-bro-check-log by ligh7s](https://github.com/ligh7s/hey-bro-check-log) 45 | - [EAC checksum check implementation on eac_logsigner by puddly](https://github.com/puddly/eac_logsigner/blob/master/eac.py) 46 | - [XLD checksum check implementation](https://github.com/OPSnet/xld_logchecker.py/blob/master/xld_logchecker.py) 47 | -------------------------------------------------------------------------------- /heybrochecklog/__init__.py: -------------------------------------------------------------------------------- 1 | class UnrecognizedException(Exception): 2 | pass 3 | 4 | 5 | import argparse # noqa: E402 6 | from pathlib import Path # noqa: E402 7 | 8 | from heybrochecklog.score import score_log # noqa: E402 9 | from heybrochecklog.translate import translate_log # noqa: E402 10 | 11 | 12 | def parse_args(): 13 | """Parse arguments.""" 14 | description = 'Tool to analyze, translate, and score a CD Rip Log.' 15 | 16 | parser = argparse.ArgumentParser(description=description) 17 | parser.add_argument('log', help='log file to check.', nargs='+') 18 | parser.add_argument( 19 | '-t', 20 | '--translate', 21 | help='translate a foreign log to English', 22 | action='store_true', 23 | ) 24 | parser.add_argument( 25 | '-m', 26 | '--markup', 27 | help='print the marked up version of the log after analyzing', 28 | action='store_true', 29 | ) 30 | parser.add_argument( 31 | '-s', 32 | '--score-only', 33 | help='Only print the score of the log.', 34 | action='store_true', 35 | ) 36 | parser.add_argument( 37 | '-ei', 38 | '--experimental-integrity', 39 | help='Enable Log Integrity Checking (Experimental, EAC & XLD only)', 40 | action='store_true' 41 | ) 42 | 43 | return parser.parse_args() 44 | 45 | 46 | def runner(): 47 | """Main function to handle command line usage of the heybrochecklog package.""" 48 | args = parse_args() 49 | for log_path in args.log: 50 | log_file = Path(log_path) 51 | if not log_file.is_file(): 52 | print('{} does not exist.'.format(log_path)) 53 | elif args.translate: 54 | translate_(args, log_file, log_path) 55 | elif args.log: 56 | score_(args, log_file, log_path) 57 | 58 | 59 | def score_(args, log_file, log_path): 60 | log = score_log(log_file, args.markup, args.experimental_integrity) 61 | if args.score_only: 62 | if not log['unrecognized']: 63 | print(log['score']) 64 | else: 65 | print('Log is unrecognized: {}'.format(log['unrecognized'])) 66 | else: 67 | try: 68 | print(format_score(log_path, log, args.markup)) 69 | except UnicodeEncodeError as error: 70 | print('Cannot encode logpath: {}'.format(error)) 71 | 72 | 73 | def translate_(args, log_file, log_path): 74 | log = translate_log(log_file) 75 | try: 76 | print(format_translation(log_path, log)) 77 | except UnicodeEncodeError as error: 78 | print('Cannot encode logpath: {}'.format(error)) 79 | 80 | 81 | def format_score(logpath, log, markup): 82 | """Turn a log file JSON into a pretty string.""" 83 | output = [] 84 | output.append('\nLog: ' + logpath) 85 | if log['unrecognized']: 86 | output.append('\nLog is unrecognized: {}'.format(log['unrecognized'])) 87 | else: 88 | if log['flagged']: 89 | output.append('\nLog is flagged: {}'.format(log['flagged'])) 90 | output.append('\nDisc name: {}'.format(log['name'])) 91 | output.append('\nScore: {}'.format(log['score'])) 92 | 93 | if log['deductions']: 94 | output.append('\nDeductions:') 95 | for deduction in log['deductions']: 96 | output.append(' >> {}'.format(deduction[0])) 97 | 98 | if markup: 99 | output.append('\n\nStylized Log:\n\n{}'.format(log['contents'])) 100 | 101 | return '\n'.join(output) 102 | 103 | 104 | def format_translation(logpath, log): 105 | """Turn a translated log JSON into a pretty string.""" 106 | output = [] 107 | output.append('\nLog: ' + logpath) 108 | 109 | if log['unrecognized']: 110 | output.append('\nFailed to recognize log. {}'.format(log['unrecognized'])) 111 | elif log['language'] == 'english': 112 | output.append('\nLog is already in English!') 113 | else: 114 | output.append('\nOriginal language: {}'.format(log['language']).title()) 115 | output.append('\n---------------------------------------------------') 116 | output.append('\n' + log['log']) 117 | 118 | return '\n'.join(output) 119 | -------------------------------------------------------------------------------- /heybrochecklog/__main__.py: -------------------------------------------------------------------------------- 1 | from heybrochecklog import runner 2 | 3 | if __name__ == '__main__': 4 | runner() 5 | -------------------------------------------------------------------------------- /heybrochecklog/analyze.py: -------------------------------------------------------------------------------- 1 | """ 2 | This module analyzes the log file and determines generic stuff like 3 | it's ripper and language, etc. 4 | """ 5 | 6 | import re 7 | 8 | from heybrochecklog import UnrecognizedException 9 | from heybrochecklog.resources import EAC_RIPLINES 10 | 11 | 12 | def analyze_log(log): 13 | """Analyze a log file and determine some generic background information.""" 14 | log.ripper = get_ripper(log.contents) 15 | log.language = determine_language(log) 16 | 17 | 18 | def get_ripper(contents): 19 | """Determine the ripper used in the log.""" 20 | if not contents: # Is file empty? 21 | raise UnrecognizedException('Empty log file') 22 | 23 | # Even foreign EAC logs start with this line. 24 | eac_regex = re.compile(r'Exact Audio Copy V[0-1]\.[0-9]+.*?from.*') 25 | xld_regex = re.compile(r'X Lossless Decoder version ([0-9abc]+) \([0-9\.]+\)') 26 | if eac_regex.match(contents[0]): 27 | return 'EAC' 28 | elif xld_regex.match(contents[0]): 29 | return 'XLD' 30 | else: 31 | # Unfortunately, not all EAC <=0.95 logs are English, so a compiled 32 | # multi-language ripper regex pattern is necessary. 33 | re_95 = re.compile('|'.join(list(EAC_RIPLINES.values()))) 34 | if re_95.match(contents[0]): 35 | return 'EAC95' 36 | else: 37 | raise UnrecognizedException('Unrecognized ripper') 38 | 39 | 40 | def determine_language(log): 41 | """Determine the language of the log file, and verify that it is an EAC log file.""" 42 | if log.ripper == 'XLD': 43 | return 'english' 44 | 45 | useful_contents = [ 46 | re.sub(r'\s+', ' ', l.rstrip()) for l in log.contents if l.strip() 47 | ] 48 | for line in useful_contents[:2]: 49 | for language, line_starter in EAC_RIPLINES.items(): 50 | if re.match(line_starter, line): 51 | return language 52 | 53 | raise UnrecognizedException('Unrecognized/unsupported language') 54 | -------------------------------------------------------------------------------- /heybrochecklog/logfile.py: -------------------------------------------------------------------------------- 1 | """This module contains the LogFile class, an encapsulation of log variables.""" 2 | 3 | import re 4 | 5 | from heybrochecklog.resources import DEDUCTIONS 6 | 7 | 8 | class LogFile: 9 | """A log file class containing variables, score, deductions, etc.""" 10 | 11 | def __init__(self, contents, ripper=None): 12 | 13 | self.full_contents = contents 14 | self.contents = format_full_contents(contents) 15 | self.concat_contents = [line for line in self.contents if line.strip()] 16 | self.score = 100 17 | self.ripper = ripper 18 | self.language = None 19 | self.drive = None 20 | self.version = None 21 | self.album = None 22 | self.unrecognized = None 23 | 24 | # Some other log settings 25 | self.range = False 26 | self.cdr = False 27 | self.unindexed_drive = False 28 | self.htoa = False 29 | self.htoa_index = False 30 | self.htoa_ripped = False 31 | 32 | # Important parts of the log 33 | self.checksum = False 34 | self.all_tracks = None 35 | self.deductions = {} 36 | self.crc_mismatch = [] 37 | self.track_errors = { 38 | "Aborted copy": [], 39 | "Timing problem": [], 40 | "Suspicious position": [], 41 | "Missing samples": [], 42 | "Read error": [], 43 | "Damaged sector count": [], 44 | } 45 | 46 | # Lists of data for the log 47 | self.toc = {} 48 | self.accuraterip = [] 49 | self.track_indices = [] 50 | self.tracks = {} 51 | 52 | # Indexes of log locations 53 | self.index_settings = None 54 | self.index_toc = None 55 | self.index_tracks = None 56 | self.index_footer = None 57 | 58 | # Flagged = auto report log 59 | self.flagged = False 60 | 61 | def to_dict(self): 62 | """Return a dict of the log analysis.""" 63 | if self.unrecognized: 64 | return { 65 | 'unrecognized': self.unrecognized, 66 | 'flagged': self.flagged, 67 | 'contents': ''.join(self.full_contents), 68 | } 69 | 70 | deductions = [deduction for deduction in self.deductions.values()] 71 | 72 | return { 73 | 'deductions': deductions, 74 | 'flagged': self.flagged, 75 | 'name': self.album, 76 | 'ripper': self.ripper, 77 | 'score': self.score, 78 | 'version': self.version, 79 | 'unrecognized': False, 80 | 'contents': ''.join(self.full_contents), 81 | } 82 | 83 | def add_deduction( 84 | self, deduction, multiplier=1, track=None, extra_phrase=None, cap_10=False 85 | ): 86 | """Add a deduction to the log file.""" 87 | name, score = self._get_deduction_from_dict(deduction) 88 | if score: 89 | score = score * multiplier if not cap_10 else score * min(10, multiplier) 90 | 91 | if track: 92 | name = 'Track {}: {}'.format(track, name) 93 | if multiplier > 1: 94 | name += ' ({} occurrences)'.format(multiplier) 95 | if score: 96 | name += ' (-{} points)'.format(score) 97 | if extra_phrase: 98 | name += ' ({})'.format(extra_phrase) 99 | 100 | self.deductions[deduction] = [name, score] 101 | 102 | def _get_deduction_from_dict(self, deduction): 103 | """Get the deduction's name and score from the deductions dict.""" 104 | if deduction not in DEDUCTIONS: 105 | return (deduction, None) 106 | 107 | deduction_entry = DEDUCTIONS[deduction] 108 | # Some deductions are different per-ripper and are represented 109 | # with an extra embedded dictionary. 110 | if isinstance(deduction_entry, dict): 111 | if self.ripper in deduction_entry: 112 | deduction_entry = deduction_entry[self.ripper] 113 | else: 114 | deduction_entry = deduction_entry['Default'] 115 | 116 | return (deduction_entry[0], deduction_entry[1]) 117 | 118 | def remove_deduction(self, deduction): 119 | """Remove a deduction from the log file.""" 120 | if deduction in self.deductions: 121 | del self.deductions[deduction] 122 | 123 | def has_deduction(self, deduction): 124 | """Learn whether or not the log file has a deduction.""" 125 | return deduction in self.deductions 126 | 127 | def has_deductions(self, *deductions): 128 | """Return whether or not log has every deduction in deductions.""" 129 | return all(de in self.deductions for de in deductions) 130 | 131 | 132 | def format_full_contents(full_contents): 133 | """ 134 | Format raw contents by stripping spaces, blank lines, and filtering 135 | out unicode crap. 136 | """ 137 | contents = [re.sub(r'\s+', ' ', l.rstrip()) for l in full_contents] 138 | contents = [re.sub(':', ':', l) for l in contents] 139 | contents = [re.sub(',', ', ', l) for l in contents] 140 | 141 | return contents 142 | -------------------------------------------------------------------------------- /heybrochecklog/markup/matches.py: -------------------------------------------------------------------------------- 1 | """This module contains the generation functions for dicts of to-match lines 2 | when marking up log files. 3 | """ 4 | 5 | import html 6 | import re 7 | 8 | from heybrochecklog.shared import format_pattern as fmt_ptn 9 | 10 | 11 | def eac_track_matches(translation): 12 | """Generate the list of to-match lines from translations.""" 13 | source_one = { 14 | 'log4': ['1269', '1270', '1217', '1299', '1227', '1218'], 15 | 'good': ['1220', '1281'], 16 | 'crc': ['1271', '1272'], 17 | } 18 | source_two = { 19 | 'log3': ['1221'], 20 | 'badish': ['1330', '1283', '1210', '1211'], 21 | 'bad': ['1212', '1213', '1214', '1215', '1216', '1228'], 22 | } 23 | return { 24 | **generate_match_type(translation, source_one), 25 | **generate_match_type(translation, source_two, append='.*'), 26 | } 27 | 28 | 29 | def xld_track_matches(): 30 | """Return a dictionary containing the XLD matches.""" 31 | return { 32 | 'full_line': [ 33 | ['log4', 'Statistics'], 34 | ['good', '->Accurately ripped'], 35 | ['badish', '->Track not present in AccurateRip database'], 36 | ['bad', '->Rip may not be accurate'], 37 | ['bad', 'List of damaged sector positions +:'], 38 | ['badish', r'\(\d+\) \d{2}:\d{2}:\d{2}'], 39 | ['log3', r'\/.+\.(?:[Ff][Ll][Aa][Cc]|[Ww][Aa][Vv]|[Mm][Pp]3|[Aa][Aa][Cc])'], 40 | ], 41 | 'crc': [r'CRC32 hash \(test run\)', 'CRC32 hash'], 42 | 'statistics': { 43 | 'bad': [ 44 | 'Read error', 45 | r'Skipped \(treated as error\)', 46 | 'Inconsistency in error sectors', 47 | 'Damaged sector count', 48 | ], 49 | 'badish': [ 50 | r'Jitter error \(maybe fixed\)', 51 | 'Retry sector count', 52 | r'Edge jitter error \(maybe fixed\)', 53 | r'Atom jitter error \(maybe fixed\)', 54 | r'Drift error \(maybe fixed\)', 55 | r'Dropped bytes error \(maybe fixed\)', 56 | r'Duplicated bytes error \(maybe fixed\)', 57 | ], 58 | }, 59 | } 60 | 61 | 62 | def eac_footer_matches(translation): 63 | """Matches for the EAC footer block.""" 64 | source = { 65 | 'good': ['1336', '1222', '1225'], 66 | 'badish': ['1333', '1334', '1344', '1335'], 67 | 'bad': ['1284', '1224'], 68 | 'log4 log5': ['1275'], 69 | } 70 | matches = generate_match_type(translation, source) 71 | 72 | # AccurateRip stuff 73 | source = {'good': ['1340'], 'badish': ['1339', '1341'], 'bad': ['1342', '1343']} 74 | matches = generate_match_type(translation, source, matches=matches, prepend='.+') 75 | 76 | if '1290' in translation: 77 | ar_prepend = r'{} +\d+ +'.format(translation['1290']) 78 | source = {'good': ['1277'], 'badish': ['1279'], 'bad': ['1276', '1278']} 79 | matches = generate_match_type( 80 | translation, source, matches=matches, prepend=ar_prepend, append='.+' 81 | ) 82 | 83 | # Checksum stuff 84 | if '1325' in translation: 85 | matches['good'].append('==== {} [0-9A-F]+ ===='.format(translation['1325'])) 86 | 87 | # EAC HAS A TYPO FOR "NO ERRORS OCCURED" WTF 88 | if translation['1222'] == 'No errors occurred': 89 | matches['good'].append('No errors occured') 90 | 91 | return matches 92 | 93 | 94 | def xld_footer_matches(): 95 | """Matches for the XLD footer block.""" 96 | return { 97 | 'good': ['No errors occurred', 'End of status report'], 98 | 'badish': ['Some inconsistencies found'], 99 | } 100 | 101 | 102 | def xld_ar_summary(): 103 | """Matches for the XLD AccurateRip Summary block.""" 104 | return { 105 | 'good': [ 106 | r'Track \d+ : OK.+', 107 | html.escape('->All tracks accurately ripped.*'), 108 | ], 109 | 'badish': [ 110 | r'Track \d+ : NG.+', 111 | 'Disc not found in AccurateRip DB', 112 | r'->\d+ tracks? accurately ripped, \d+ tracks? not', 113 | ], 114 | 'log4 log5': ['AccurateRip Summary'], 115 | } 116 | 117 | 118 | def generate_match_type(translation, source, matches=None, prepend='', append=''): 119 | """Function to generate the match types.""" 120 | matches = {} if not matches else matches 121 | for match_type in source.keys(): 122 | if match_type not in matches: 123 | matches[match_type] = [] 124 | for line_id in source[match_type]: 125 | if line_id in translation: 126 | match = prepend + re_paren(translation[line_id]) + append 127 | matches[match_type].append(html.escape(match)) 128 | 129 | return matches 130 | 131 | 132 | def re_paren(line): 133 | """Regex the comma. Quality docstring.""" 134 | line = re.sub(r'\(', r'\(', fmt_ptn(line)) 135 | return re.sub(r'\)', r'\)', line) 136 | -------------------------------------------------------------------------------- /heybrochecklog/resources/drives.db: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/doujincafe/hbcl/48d2f27746e212d023e72f270f67a06125830451/heybrochecklog/resources/drives.db -------------------------------------------------------------------------------- /heybrochecklog/resources/eac95/chinese (simplified).json: -------------------------------------------------------------------------------- 1 | { 2 | "patterns": { 3 | "drive": ["ʹÓÃÇý¶¯Æ÷ £º"], 4 | "settings": { 5 | "Read mode": null, 6 | "C2 pointers": null, 7 | "Accurate stream": null, 8 | "Audio cache": null, 9 | "Drive offset": ["¶ÁÈ¡Æ«ÒÆÐ£Õý£º"] 10 | }, 11 | "full line settings": { 12 | "Fill missing offset samples with silence": ["Óþ²ÒôÌî³äץȡÖжªÊ§Æ«ÒƵIJÉÑù"], 13 | "Deleting silent blocks": ["È¥³ýÊ×β¾²Òô¿é"] 14 | }, 15 | "bad settings": { 16 | "Normalization": ["±ê×¼»¯ÖÁ"], 17 | "Compression offset": ["ʹÓÃѹËõÆ«ÒÆ£º"], 18 | "Combined offset": ["×éºÏ¶ÁÐ´Æ«ÒÆÐ£Õý£º"] 19 | }, 20 | "proper settings": { 21 | "Fill missing offset samples with silence": ["ÊÇ"], 22 | "Deleting silent blocks": ["·ñ"] 23 | }, 24 | "range": ["·¶Î§×´Ì¬¼°´íÎó"], 25 | "track": ["Òô¹ì"], 26 | "track settings": { 27 | "filename": ["ÎļþÃû"], 28 | "pregap": ["ǰ¼ä϶³¤¶È"], 29 | "peak": ["·åÖµµçƽ"], 30 | "test crc": ["²âÊÔ CRC"], 31 | "copy crc": ["(?:¸´ÖÆ CRC|CRC)"] 32 | }, 33 | "track errors": { 34 | "Aborted copy": ["¸´ÖƱ»ÖÐÖ¹"], 35 | "Timing problem": ["¼ÆÊ±ÎÊÌâ"], 36 | "Missing samples": ["ȱʧ²ÉÑù"], 37 | "Suspicious position": ["¿ÉÒÉλÖÃ"] 38 | }, 39 | "footer": ["״̬±¨¸æ½áβ"] 40 | }, 41 | "translation": { 42 | "1": ["¼òÌåÖÐÎÄ"], 43 | "2": ["Simplified Chinese"], 44 | "5": ["´íÎóÐÅÏ¢"], 45 | "6": ["¾¯¸æ"], 46 | "7": ["³É¹¦"], 47 | "10": ["È·¶¨"], 48 | "11": ["È¡Ïû"], 49 | "12": ["Ó¦ÓÃ"], 50 | "15": ["ÊÇ"], 51 | "16": ["·ñ"], 52 | "31": ["ÎļþÃû½«±»ºöÂÔ"], 53 | "50": ["ÊýÖµÔ½½ç£¡"], 54 | "51": ["ÎÞЧ×Ö·û£¡"], 55 | "52": ["ÎÞЧÎļþÃû£¡"], 56 | "4270": ["µÍ"], 57 | "4271": ["ÖÐ"], 58 | "4272": ["¸ß"], 59 | "1200": ["״̬¼°´íÎóÐÅÏ¢"], 60 | "2501": ["Òô¹ì״̬¼°´íÎó"], 61 | "1203": ["¿ÉÄܵĴíÎó"], 62 | "1204": ["´´½¨ÈÕÖ¾"], 63 | "1210": ["·¶Î§×´Ì¬¼°´íÎó"], 64 | "1211": ["ÒÑÑ¡Ôñ·¶Î§"], 65 | "1212": ["¼ÆÊ±ÎÊÌâ"], 66 | "1213": ["¿ÉÒÉλÖÃ"], 67 | "1214": ["ȱʧ²ÉÑù"], 68 | "1215": ["¹ý¶à²ÉÑù"], 69 | "1216": ["ÎļþдÈë´íÎó"], 70 | "1217": ["·åÖµµçƽ"], 71 | "1218": ["·¶Î§ÖÊÁ¿"], 72 | "1219": ["CRC"], 73 | "1220": ["¸´ÖƳɹ¦"], 74 | "1221": ["¸´ÖƽáÊø"], 75 | "1227": ["Òô¹ìÖÊÁ¿"], 76 | "1228": ["¸´ÖƱ»ÖÐÖ¹"], 77 | "1269": ["ÎļþÃû"], 78 | "1270": ["ǰ¼ä϶³¤¶È"], 79 | "1271": ["²âÊÔ CRC"], 80 | "1272": ["¸´ÖÆ CRC"], 81 | "1273": ["ÕýÔÚѹËõ"], 82 | "1222": ["ûÓдíÎó·¢Éú"], 83 | "1223": ["ÖØÐ¼ì²é·¶Î§"], 84 | "1224": ["³öÏÖ´íÎó"], 85 | "1225": ["״̬±¨¸æ½áβ"], 86 | "1226": ["Òô¹ì"], 87 | "1230": ["Ë÷Òý"], 88 | "1229": ["ÖØÐ¼ì²éÒô¹ì"], 89 | "1274": ["EAC ץȡÈÕÖ¾Îļþ´Ó"], 90 | "1240": ["Ò»ÔÂ"], 91 | "1241": ["¶þÔÂ"], 92 | "1242": ["ÈýÔÂ"], 93 | "1243": ["ËÄÔÂ"], 94 | "1244": ["ÎåÔÂ"], 95 | "1245": ["ÁùÔÂ"], 96 | "1246": ["ÆßÔÂ"], 97 | "1247": ["°ËÔÂ"], 98 | "1248": ["¾ÅÔÂ"], 99 | "1249": ["Ê®ÔÂ"], 100 | "1250": ["ʮһÔÂ"], 101 | "1251": ["Ê®¶þÔÂ"], 102 | "1232": ["EAC ץȡ CD ÅäÖÃÎļþ"], 103 | "1233": ["ʹÓÃÇý¶¯Æ÷ £º"], 104 | "1234": ["¶Áȡģʽ £º"], 105 | "1235": ["±©·¢"], 106 | "1236": ["¿ìËÙ"], 107 | "1237": ["²»Ê¹Óà C2,²»Ê¹Óþ«È·Á÷£¬²»½ûÓûº´æµÄ°²È«Ä£Ê½"], 108 | "1238": ["²»Ê¹Óà C2, ʹÓþ«È·Á÷£¬²»½ûÓûº´æµÄ°²È«Ä£Ê½"], 109 | "1239": ["²»Ê¹Óà C2, ²»Ê¹Óþ«È·Á÷£¬½ûÓûº´æµÄ°²È«Ä£Ê½"], 110 | "1252": ["ʹÓà C2,ʹÓþ«È·Á÷£¬²»½ûÓûº´æµÄ°²È«Ä£Ê½"], 111 | "1253": ["ʹÓà C2, ʹÓþ«È·Á÷£¬½ûÓûº´æµÄ°²È«Ä£Ê½"], 112 | "1254": ["²»Ê¹Óà C2£¬Ê¹Óþ«È·Á÷, ½ûÓûº´æµÄ°²È«Ä£Ê½"], 113 | "1255": ["×éºÏ¶ÁÐ´Æ«ÒÆÐ£Õý£º"], 114 | "1256": ["¶ÁÈ¡Æ«ÒÆÐ£Õý£º"], 115 | "1257": ["¶ÁÈ¡ Lead-In ºÍ Lead-Out"], 116 | "1258": ["ËùÓÃÊä³öģʽ£º"], 117 | "1259": ["¸½¼ÓÃüÁîÐвÎÊý£º"], 118 | "1260": ["ÄÚ²¿ WAV º¯Êý"], 119 | "1261": ["44.100 Hz; 16 Bit; Á¢ÌåÉù"], 120 | "1262": ["ʹÓÃѹËõÆ«ÒÆ£º"], 121 | "1263": ["ÆäËûÑ¡Ïî £º"], 122 | "1264": ["Óþ²ÒôÌî³äץȡÖжªÊ§Æ«ÒƵIJÉÑù"], 123 | "1265": ["È¥³ýÊ×β¾²Òô¿é"], 124 | "1266": ["±ê×¼»¯ÖÁ"], 125 | "1267": ["Win NT ¼° 2000 ±¾µØ Win32 ½Ó¿Ú"], 126 | "1268": ["ÒѰ²×°Íⲿ ASPI ½Ó¿Ú"], 127 | "81700": ["L3Enc MP3 ¼æÈݱàÂëÆ÷"], 128 | "81701": ["Fraunhofer MP3Enc MP3 ±àÂëÆ÷"], 129 | "81702": ["Xing X3Enc MP3 ±àÂëÆ÷"], 130 | "81703": ["Xing ToMPG MP3 ±àÂëÆ÷"], 131 | "81704": ["LAME MP3 ±àÂëÆ÷"], 132 | "81705": ["GOGO MP3 ±àÂëÆ÷"], 133 | "81706": ["MPC ±àÂëÆ÷"], 134 | "81707": ["Ogg Vorbis ±àÂëÆ÷"], 135 | "81708": ["Microsoft WMA9 ±àÂëÆ÷"], 136 | "81709": ["FAAC AAC ±àÂëÆ÷"], 137 | "81710": ["Homeboy AAC ±àÂëÆ÷"], 138 | "81711": ["Quartex AAC ±àÂëÆ÷"], 139 | "81712": ["PsyTEL AAC ±àÂëÆ÷"], 140 | "81713": ["MBSoft AAC ±àÂëÆ÷"], 141 | "81714": ["Yamaha VQF ±àÂëÆ÷"], 142 | "81715": ["Real Audio ±àÂëÆ÷"], 143 | "81716": ["Monkey's Audio ÎÞËð±àÂëÆ÷"], 144 | "81717": ["Shorten ÎÞËð±àÂëÆ÷"], 145 | "81718": ["RKAU ÎÞËð±àÂëÆ÷"], 146 | "81719": ["LPAC ÎÞËð±àÂëÆ÷"], 147 | "81720": ["Óû§¶¨ÒåµÄ±àÂëÆ÷"] 148 | } 149 | } -------------------------------------------------------------------------------- /heybrochecklog/resources/eac95/chinese (traditional).json: -------------------------------------------------------------------------------- 1 | { 2 | "patterns": { 3 | "drive": ["¨Ï¥Î¥úºÐ¾÷ ¡G"], 4 | "settings": { 5 | "Read mode": null, 6 | "C2 pointers": null, 7 | "Accurate stream": null, 8 | "Audio cache": null, 9 | "Drive offset": ["Ū¨ú¿ù»~­×¥¿¡G"] 10 | }, 11 | "full line settings": { 12 | "Fill missing offset samples with silence": ["¥ÎÀR­µ¶ñ¥R§ì¨ú¤¤¥á¥¢°¾²¾ªº¨ú¼Ë"], 13 | "Deleting silent blocks": ["¥h°£­º§ÀÀR­µ°Ï¶ô"] 14 | }, 15 | "bad settings": { 16 | "Normalization": ["¼Ð·Ç¤Æ¦Ü"], 17 | "Compression offset": ["¨Ï¥ÎÀ£ÁY°¾²¾¡G"], 18 | "Combined offset": ["²Õ¦XŪ¼g¿ù»~­×¥¿¡G"] 19 | }, 20 | "proper settings": { 21 | "Fill missing offset samples with silence": ["¬O"], 22 | "Deleting silent blocks": ["§_"] 23 | }, 24 | "range": ["½d³òª¬ºA¤Î¿ù»~"], 25 | "track": ["­µ­y"], 26 | "track settings": { 27 | "filename": ["ÀɮצWºÙ"], 28 | "pregap": ["«e¶¡»Øªø«×"], 29 | "peak": ["®p­È¹q¥­"], 30 | "test crc": ["´ú¸Õ CRC"], 31 | "copy crc": ["(?:½Æ»s CRC|CRC)"] 32 | }, 33 | "track errors": { 34 | "Aborted copy": ["½Æ»s³Q¤¤¤î"], 35 | "Timing problem": ["­p®É°ÝÃD"], 36 | "Missing samples": ["¯Ê¥¢¨ú¼Ë"], 37 | "Suspicious position": ["¥iºÃ¦ì¸m"] 38 | }, 39 | "footer": ["ª¬ºA³ø§iµ²§À"] 40 | }, 41 | "translation": { 42 | "1": ["ÁcÅ餤¤å"], 43 | "2": ["Traditional Chinese ÁcÅ餤¤å"], 44 | "5": ["¿ù»~¸ê°T"], 45 | "6": ["ĵ§i"], 46 | "7": ["§¹¦¨"], 47 | "10": ["½T©w"], 48 | "11": ["¨ú®ø"], 49 | "12": ["À³¥Î"], 50 | "15": ["¬O"], 51 | "16": ["§_"], 52 | "31": ["ÀɮצWºÙ±N³Q©¿²¤"], 53 | "50": ["¼Æ­È¶V¬É¡I"], 54 | "51": ["µL®Ä¦r²Å¡I"], 55 | "52": ["µL®ÄÀɮצWºÙ¡I"], 56 | "4270": ["§C"], 57 | "4271": ["¤¤"], 58 | "4272": ["°ª"], 59 | "1200": ["ª¬ºA¤Î¿ù»~¸ê°T"], 60 | "2501": ["­µ­yª¬ºA¤Î¿ù»~"], 61 | "1203": ["¥i¯àªº¿ù»~"], 62 | "1204": ["·s¼W¤é»x"], 63 | "1210": ["½d³òª¬ºA¤Î¿ù»~"], 64 | "1211": ["¤w¿ï¾Ü½d³ò"], 65 | "1212": ["­p®É°ÝÃD"], 66 | "1213": ["¥iºÃ¦ì¸m"], 67 | "1214": ["¯Ê¥¢¨ú¼Ë"], 68 | "1215": ["¹L¦h¨ú¼Ë"], 69 | "1216": ["ÀÉ®×¼g¤J¿ù»~"], 70 | "1217": ["®p­È¹q¥­"], 71 | "1218": ["½d³ò½è¶q"], 72 | "1219": ["CRC"], 73 | "1220": ["½Æ»s§¹¦¨"], 74 | "1221": ["½Æ»sµ²§ô"], 75 | "1227": ["­µ­y½è¶q"], 76 | "1228": ["½Æ»s³Q¤¤¤î"], 77 | "1269": ["ÀɮצWºÙ"], 78 | "1270": ["«e¶¡»Øªø«×"], 79 | "1271": ["´ú¸Õ CRC"], 80 | "1272": ["½Æ»s CRC"], 81 | "1273": ["¥¿¦bÀ£ÁY"], 82 | "1222": ["¨S¦³¿ù»~µo¥Í"], 83 | "1223": ["­«·sÀˬd½d³ò"], 84 | "1224": ["¥X²{¿ù»~"], 85 | "1225": ["ª¬ºA³ø§iµ²§À"], 86 | "1226": ["­µ­y"], 87 | "1230": ["¯Á¤Þ"], 88 | "1229": ["­«·sÀˬd­µ­y"], 89 | "1274": ["EAC §ì¨ú¤é»xÀÉ®×±q"], 90 | "1240": ["¤@¤ë"], 91 | "1241": ["¤G¤ë"], 92 | "1242": ["¤T¤ë"], 93 | "1243": ["¥|¤ë"], 94 | "1244": ["¤­¤ë"], 95 | "1245": ["¤»¤ë"], 96 | "1246": ["¤C¤ë"], 97 | "1247": ["¤K¤ët"], 98 | "1248": ["¤E¤ë"], 99 | "1249": ["¤Q¤ë"], 100 | "1250": ["¤Q¤@¤ë"], 101 | "1251": ["¤Q¤G¤ë"], 102 | "1232": ["EAC §ì¨ú CD °t¸mÀÉ®×"], 103 | "1233": ["¨Ï¥Î¥úºÐ¾÷ ¡G"], 104 | "1234": ["Ū¨ú¼Ò¦¡ ¡G"], 105 | "1235": ["¼Éµo"], 106 | "1236": ["§Ö³t"], 107 | "1237": ["¤£¨Ï¥Î C2,¤£¨Ï¥Îºë½T¬y¡A¤£°±¤î½w¦sªº¦w¥þ¼Ò¦¡"], 108 | "1238": ["¤£¨Ï¥Î C2, ¨Ï¥Îºë½T¬y¡A¤£°±¤î½w¦sªº¦w¥þ¼Ò¦¡"], 109 | "1239": ["¤£¨Ï¥Î C2, ¤£¨Ï¥Îºë½T¬y¡A°±¤î½w¦sªº¦w¥þ¼Ò¦¡"], 110 | "1252": ["¨Ï¥Î C2,¨Ï¥Îºë½T¬y¡A¤£°±¤î½w¦sªº¦w¥þ¼Ò¦¡"], 111 | "1253": ["¨Ï¥Î C2, ¨Ï¥Îºë½T¬y¡A°±¤î½w¦sªº¦w¥þ¼Ò¦¡"], 112 | "1254": ["¤£¨Ï¥Î C2¡A¨Ï¥Îºë½T¬y, °±¤î½w¦sªº¦w¥þ¼Ò¦¡"], 113 | "1255": ["²Õ¦XŪ¼g¿ù»~­×¥¿¡G"], 114 | "1256": ["Ū¨ú¿ù»~­×¥¿¡G"], 115 | "1257": ["Ū¨ú Lead-In ©M Lead-Out"], 116 | "1258": ["©Ò¥Î¿é¥X¼Ò¦¡¡G"], 117 | "1259": ["ªþ¥[©R¥O¦æ°Ñ¼Æ¡G"], 118 | "1260": ["¤º³¡ WAV ¨ç¼Æ"], 119 | "1261": ["44.100 Hz;16 Bit;¥ßÅéÁn"], 120 | "1262": ["¨Ï¥ÎÀ£ÁY°¾²¾¡G"], 121 | "1263": ["¨ä¥L¿ï¶µ ¡G"], 122 | "1264": ["¥ÎÀR­µ¶ñ¥R§ì¨ú¤¤¥á¥¢°¾²¾ªº¨ú¼Ë"], 123 | "1265": ["¥h°£­º§ÀÀR­µ°Ï¶ô"], 124 | "1266": ["¼Ð·Ç¤Æ¦Ü"], 125 | "1267": ["Win NT ¤Î 2000 ¥»¦a Win32 ¤¶­±"], 126 | "1268": ["¤w¦w¸Ë¥~³¡ ASPI ¤¶­±"], 127 | "81700": ["L3Enc MP3 Encoder & Compatible"], 128 | "81701": ["Fraunhofer MP3Enc MP3 Encoder"], 129 | "81702": ["Xing X3Enc MP3 Encoder"], 130 | "81703": ["Xing ToMPG MP3 Encoder"], 131 | "81704": ["LAME MP3 Encoder"], 132 | "81705": ["GOGO MP3 Encoder"], 133 | "81706": ["MPC Encoder"], 134 | "81707": ["Ogg Vorbis Encoder"], 135 | "81708": ["Microsoft WMA9 Encoder"], 136 | "81709": ["FAAC AAC Encoder"], 137 | "81710": ["Homeboy AAC Encoder"], 138 | "81711": ["Quartex AAC Encoder"], 139 | "81712": ["PsyTEL AAC Encoder"], 140 | "81713": ["MBSoft AAC Encoder"], 141 | "81714": ["Yamaha VQF Encoder"], 142 | "81715": ["Real Audio Encoder"], 143 | "81716": ["Monkey's Audio Lossless Encoder"], 144 | "81717": ["Shorten Lossless Encoder"], 145 | "81718": ["RKAU Lossless Encoder"], 146 | "81719": ["LPAC Lossless Encoder"], 147 | "81720": ["User Defined Encoder"] 148 | } 149 | } -------------------------------------------------------------------------------- /heybrochecklog/resources/eac95/czech.json: -------------------------------------------------------------------------------- 1 | { 2 | "patterns": { 3 | "drive": ["Mechaniku"], 4 | "settings": { 5 | "Read mode": ["Žádný"], 6 | "C2 pointers": ["bezpeèný C2"], 7 | "Accurate stream": [", pøesný tok"], 8 | "Audio cache": [", zakázaná pamì"], 9 | "Drive offset": ["Ètecí offset korekce"] 10 | }, 11 | "full line settings": { 12 | "Fill missing offset samples with silence": ["Vyplnit chybìjící offset samples tichem"], 13 | "Deleting silent blocks": ["Vymazat ticho na zaèátku i konci"] 14 | }, 15 | "bad settings": { 16 | "Normalization": ["Normalizovat na"], 17 | "Compression offset": ["Použitá offset komprimace"], 18 | "Combined offset": ["Kombinovaná ètecí/zapisovací offset korekce"] 19 | }, 20 | "proper settings": { 21 | "Fill missing offset samples with silence": ["Ano"], 22 | "Deleting silent blocks": ["Ne"] 23 | }, 24 | "range": ["Stav a zprávy o chybách"], 25 | "track": ["Stopa"], 26 | "track settings": { 27 | "filename": ["Název souboru"], 28 | "pregap": ["Ticho pøed stopou"], 29 | "peak": ["Vrcholová úroveò"], 30 | "test crc": ["Test CRC"], 31 | "copy crc": ["(?:Kopírování CRC|CRC)"] 32 | }, 33 | "track errors": { 34 | "Aborted copy": ["Kopírování zrušeno"], 35 | "Timing problem": ["Problém s èasem"], 36 | "Missing samples": ["Missing samples"], 37 | "Suspicious position": ["Podezøelé pozice"] 38 | }, 39 | "footer": ["Konec zprávy"] 40 | }, 41 | "translation": { 42 | "1": ["Èeský"], 43 | "2": ["Czech"], 44 | "5": ["Zpráva o chybì"], 45 | "6": ["Varování"], 46 | "7": ["Úspìšnì"], 47 | "10": ["OK"], 48 | "11": ["Storno"], 49 | "12": ["Použít"], 50 | "15": ["Ano"], 51 | "16": ["Ne"], 52 | "31": ["Název souboru bude ignorovaný"], 53 | "50": ["Hodnota mimo rozsah!"], 54 | "51": ["Neplatný znak!"], 55 | "52": ["Neplatný název souboru!"], 56 | "4270": ["Nízká"], 57 | "4271": ["Støední"], 58 | "4272": ["Vysoká"], 59 | "1200": ["Stav a zprávy o chybách"], 60 | "2501": ["Stav a zprávy o chybách"], 61 | "1203": ["Možné chyby"], 62 | "1204": ["Vytvoøit Log"], 63 | "1210": ["Stav a zprávy o chybách"], 64 | "1211": ["Výbìr"], 65 | "1212": ["Problém s èasem"], 66 | "1213": ["Podezøelé pozice"], 67 | "1214": ["Missing samples"], 68 | "1215": ["Pøíliš mnoho samples"], 69 | "1216": ["Chyba zápisu souboru"], 70 | "1217": ["Vrcholová úroveò"], 71 | "1218": ["Oblast kvality"], 72 | "1219": ["CRC"], 73 | "1220": ["Kopírování OK"], 74 | "1221": ["Kopírování dokonèeno"], 75 | "1227": ["Kvalita stopy"], 76 | "1228": ["Kopírování zrušeno"], 77 | "1269": ["Název souboru"], 78 | "1270": ["Ticho pøed stopou"], 79 | "1271": ["Test CRC"], 80 | "1272": ["Kopírování CRC"], 81 | "1273": ["Komprimace"], 82 | "1222": ["Nevyskytla se žádná chyba"], 83 | "1223": ["Kontrola výbìru"], 84 | "1224": ["Vyskytnuvší se chyby"], 85 | "1225": ["Konec zprávy"], 86 | "1226": ["Stopa"], 87 | "1230": ["Index"], 88 | "1229": ["Kontrola stop"], 89 | "1274": ["Log soubor extrakce EAC z"], 90 | "1240": ["Ledna"], 91 | "1241": ["Února"], 92 | "1242": ["Bøezna"], 93 | "1243": ["Dubna"], 94 | "1244": ["Kvìtna"], 95 | "1245": ["Èervna"], 96 | "1246": ["Èervence"], 97 | "1247": ["Srpna"], 98 | "1248": ["Záøí"], 99 | "1249": ["Øíjna"], 100 | "1250": ["Listopadu"], 101 | "1251": ["Prosince"], 102 | "1232": ["Log soubor extrakce EAC pro CD"], 103 | "1233": ["Mechaniku :"], 104 | "1234": ["Ètecí režim :"], 105 | "1235": ["Burst"], 106 | "1236": ["Rychlý"], 107 | "1237": ["Žádný bezpeèný C2, Žádný pøesný tok, Žádná zakázaná pamì"], 108 | "1238": ["Žádný bezpeèný C2, pøesný tok, Žádná zakázaná pamì"], 109 | "1239": ["Žádný bezpeèný C2, Žádný pøesný tok, zakázaná pamì"], 110 | "1252": ["Bezpeèný C2, pøesný tok, Žádná zakázaná pamì"], 111 | "1253": ["Bezpeèný C2, pøesný tok, zakázaná pamì"], 112 | "1254": ["Žádný bezpeèný C2, pøesný tok, zakázaná pamì"], 113 | "1255": ["Kombinovaná ètecí/zapisovací offset korekce :"], 114 | "1256": ["Ètecí offset korekce :"], 115 | "1257": ["Naèítání v Lead-In a Lead-Out"], 116 | "1258": ["Použitý výstupní formát :"], 117 | "1259": ["Rozšíøené volby pro pøíkazovou øádku :"], 118 | "1260": ["Normální WAV"], 119 | "1261": ["44.100 Hz; 16 Bit; Stereo"], 120 | "1262": ["Použitá offset komprimace :"], 121 | "1263": ["Další volby :"], 122 | "1264": ["Vyplnit chybìjící offset samples tichem"], 123 | "1265": ["Vymazat ticho na zaèátku i konci"], 124 | "1266": ["Normalizovat na"], 125 | "1267": ["Pùvodní rozhraní Win32 pro Win NT & 2000"], 126 | "1268": ["Nainstalované externí ASPI rozhraní"], 127 | "81700": ["L3Enc MP3 kodér & kompatibilní"], 128 | "81701": ["Fraunhofer MP3Enc MP3 kodér"], 129 | "81702": ["Xing X3Enc MP3 kodér"], 130 | "81703": ["Xing ToMPG MP3 kodér"], 131 | "81704": ["LAME MP3 kodér"], 132 | "81705": ["GOGO MP3 kodér"], 133 | "81706": ["MPC kodér"], 134 | "81707": ["Ogg Vorbis kodér"], 135 | "81708": ["Microsoft WMA9 kodér"], 136 | "81709": ["FAAC AAC kodér"], 137 | "81710": ["Homeboy AAC kodér"], 138 | "81711": ["Quartex AAC kodér"], 139 | "81712": ["PsyTEL AAC kodér"], 140 | "81713": ["MBSoft AAC kodér"], 141 | "81714": ["Yamaha VQF kodér"], 142 | "81715": ["Real Audio kodér"], 143 | "81716": ["Monkey's Audio Lossless kodér"], 144 | "81717": ["Shorten Lossless kodér"], 145 | "81718": ["RKAU Lossless kodér"], 146 | "81719": ["LPAC bezeztrátový kodér"], 147 | "81720": ["Uživatelsky definovaný kodér"] 148 | } 149 | } -------------------------------------------------------------------------------- /heybrochecklog/resources/eac95/english.json: -------------------------------------------------------------------------------- 1 | { 2 | "patterns": { 3 | "drive": ["Used [Dd]rive"], 4 | "settings": { 5 | "Read mode": ["Secure"], 6 | "C2 pointers": ["with NO C2"], 7 | "Accurate stream": [", accurate stream"], 8 | "Audio cache": [", disable cache"], 9 | "Drive offset": ["Read offset correction"] 10 | }, 11 | "full line settings": { 12 | "Fill missing offset samples with silence": ["Fill up missing offset samples with silence"], 13 | "Deleting silent blocks": ["Delete leading and trailing silent blocks"] 14 | }, 15 | "bad settings": { 16 | "Normalization": ["Normalize to"], 17 | "Compression offset": ["Use compression offset"], 18 | "Combined offset": ["Combined read/write offset correction"] 19 | }, 20 | "proper settings": { 21 | "Fill missing offset samples with silence": ["Yes"], 22 | "Deleting silent blocks": ["No"] 23 | }, 24 | "range": ["Range status and errors"], 25 | "track": ["Track"], 26 | "track settings": { 27 | "filename": ["Filename"], 28 | "pregap": ["Pre-gap length"], 29 | "peak": ["Peak level"], 30 | "test crc": ["Test CRC"], 31 | "copy crc": ["(?:Copy CRC|CRC)"] 32 | }, 33 | "track errors": { 34 | "Aborted copy": ["Copy aborted"], 35 | "Timing problem": ["Timing problem"], 36 | "Missing samples": ["Missing samples"], 37 | "Suspicious position": ["Suspicious position"] 38 | }, 39 | "footer": ["End of status report"] 40 | }, 41 | "translation": { 42 | "1": ["English"], 43 | "2": ["English"], 44 | "5": ["Error Message"], 45 | "6": ["Warning"], 46 | "7": ["Success"], 47 | "10": ["OK"], 48 | "11": ["Cancel"], 49 | "12": ["Apply"], 50 | "15": ["Yes"], 51 | "16": ["No"], 52 | "31": ["Filename will be ignored"], 53 | "50": ["Value out of range !"], 54 | "51": ["Invalid characters !"], 55 | "52": ["Invalid filename !"], 56 | "4270": ["Low"], 57 | "4271": ["Medium"], 58 | "4272": ["High"], 59 | "1200": ["Status and Error Messages"], 60 | "2501": ["Track status and errors"], 61 | "1203": ["Possible Errors"], 62 | "1204": ["Create Log"], 63 | "1210": ["Range status and errors"], 64 | "1211": ["Selected range"], 65 | "1212": ["Timing problem"], 66 | "1213": ["Suspicious position"], 67 | "1214": ["Missing samples"], 68 | "1215": ["Too many samples"], 69 | "1216": ["File write error"], 70 | "1217": ["Peak level"], 71 | "1218": ["Range quality"], 72 | "1219": ["CRC"], 73 | "1220": ["Copy OK"], 74 | "1221": ["Copy finished"], 75 | "1227": ["Track quality"], 76 | "1228": ["Copy aborted"], 77 | "1269": ["Filename"], 78 | "1270": ["Pre-gap length"], 79 | "1271": ["Test CRC"], 80 | "1272": ["Copy CRC"], 81 | "1273": ["Compressing"], 82 | "1222": ["No errors occured"], 83 | "1223": ["Review Range"], 84 | "1224": ["There were errors"], 85 | "1225": ["End of status report"], 86 | "1226": ["Track"], 87 | "1230": ["Index"], 88 | "1229": ["Review Tracks"], 89 | "1274": ["EAC extraction logfile from"], 90 | "1240": ["January"], 91 | "1241": ["February"], 92 | "1242": ["March"], 93 | "1243": ["April"], 94 | "1244": ["May"], 95 | "1245": ["June"], 96 | "1246": ["July"], 97 | "1247": ["August"], 98 | "1248": ["September"], 99 | "1249": ["October"], 100 | "1250": ["November"], 101 | "1251": ["December"], 102 | "1232": ["EAC extraction logfile for CD"], 103 | "1233": ["Used drive :"], 104 | "1234": ["Read mode :"], 105 | "1235": ["Burst"], 106 | "1236": ["Fast"], 107 | "1237": ["Secure with NO C2, NO accurate stream, NO disable cache"], 108 | "1238": ["Secure with NO C2, accurate stream, NO disable cache"], 109 | "1239": ["Secure with NO C2, NO accurate stream, disable cache"], 110 | "1252": ["Secure with C2, accurate stream, NO disable cache"], 111 | "1253": ["Secure with C2, accurate stream, disable cache"], 112 | "1254": ["Secure with NO C2, accurate stream, disable cache"], 113 | "1255": ["Combined read/write offset correction :"], 114 | "1256": ["Read offset correction :"], 115 | "1257": ["Overread into Lead-In and Lead-Out"], 116 | "1258": ["Used output format :"], 117 | "1259": ["Additional command line options :"], 118 | "1260": ["Internal WAV Routines"], 119 | "1261": ["44.100 Hz; 16 Bit; Stereo"], 120 | "1262": ["Use compression offset :"], 121 | "1263": ["Other options :"], 122 | "1264": ["Fill up missing offset samples with silence"], 123 | "1265": ["Delete leading and trailing silent blocks"], 124 | "1266": ["Normalize to"], 125 | "1267": ["Native Win32 interface for Win NT & 2000"], 126 | "1268": ["Installed external ASPI interface"], 127 | "81700": ["L3Enc MP3 Encoder & Compatible"], 128 | "81701": ["Fraunhofer MP3Enc MP3 Encoder"], 129 | "81702": ["Xing X3Enc MP3 Encoder"], 130 | "81703": ["Xing ToMPG MP3 Encoder"], 131 | "81704": ["LAME MP3 Encoder"], 132 | "81705": ["GOGO MP3 Encoder"], 133 | "81706": ["MPC Encoder"], 134 | "81707": ["Ogg Vorbis Encoder"], 135 | "81708": ["Microsoft WMA9 Encoder"], 136 | "81709": ["FAAC AAC Encoder"], 137 | "81710": ["Homeboy AAC Encoder"], 138 | "81711": ["Quartex AAC Encoder"], 139 | "81712": ["PsyTEL AAC Encoder"], 140 | "81713": ["MBSoft AAC Encoder"], 141 | "81714": ["Yamaha VQF Encoder"], 142 | "81715": ["Real Audio Encoder"], 143 | "81716": ["Monkey's Audio Lossless Encoder"], 144 | "81717": ["Shorten Lossless Encoder"], 145 | "81718": ["RKAU Lossless Encoder"], 146 | "81719": ["LPAC Lossless Encoder"], 147 | "81720": ["User Defined Encoder"] 148 | } 149 | } 150 | -------------------------------------------------------------------------------- /heybrochecklog/resources/eac95/japanese.json: -------------------------------------------------------------------------------- 1 | { 2 | "patterns": { 3 | "drive": ["Žg—pƒhƒ‰ƒCƒu"], 4 | "settings": { 5 | "Read mode": null, 6 | "C2 pointers": null, 7 | "Accurate stream": null, 8 | "Audio cache": null, 9 | "Drive offset": ["“ǂݍž‚݃IƒtƒZƒbƒg’ù³’l"] 10 | }, 11 | "full line settings": { 12 | "Fill missing offset samples with silence": ["Áޏ‚µ‚½ƒIƒtƒZƒbƒgƒTƒ“ƒvƒ‹‚𖳉¹‚É’u‚«Š·‚¦‚é"], 13 | "Deleting silent blocks": ["‹È‚̐擪‚Æ––”ö‚Ì–³‰¹•”‚ðíœ‚·‚é"] 14 | }, 15 | "bad settings": { 16 | "Normalization": ["ƒm[ƒ}ƒ‰ƒCƒY"], 17 | "Compression offset": ["Žg—pƒGƒ“ƒR[ƒhƒIƒtƒZƒbƒg’l"], 18 | "Combined offset": ["“ǂݍž‚݁E‘‚«ž‚݃IƒtƒZƒbƒg’ù³’l"] 19 | }, 20 | "proper settings": { 21 | "Fill missing offset samples with silence": ["Yes"], 22 | "Deleting silent blocks": ["No"] 23 | }, 24 | "range": ["“WŠJ”͈̓Xƒe[ƒ^ƒX‚ƃGƒ‰["], 25 | "track": ["ƒgƒ‰ƒbƒN"], 26 | "track settings": { 27 | "filename": ["ƒtƒ@ƒCƒ‹–¼"], 28 | "pregap": ["ƒvƒŠƒMƒƒƒbƒv’·"], 29 | "peak": ["ƒs[ƒNƒŒƒxƒ‹"], 30 | "test crc": ["ƒeƒXƒg CRC"], 31 | "copy crc": ["(?:ƒRƒs[ CRC|CRC)"] 32 | }, 33 | "track errors": { 34 | "Aborted copy": ["ƒRƒs[’†Ž~"], 35 | "Timing problem": ["ƒ^ƒCƒ~ƒ“ƒOƒvƒƒuƒŒƒ€"], 36 | "Missing samples": ["ÁޏƒTƒ“ƒvƒ‹"], 37 | "Suspicious position": ["‹^‚킵‚¢ˆÊ’u"] 38 | }, 39 | "footer": ["ƒXƒe[ƒ^ƒX‚Ì•ñI—¹"] 40 | }, 41 | "translation": { 42 | "1": ["“ú–{Œê"], 43 | "2": ["Japanese"], 44 | "5": ["ƒGƒ‰[ƒƒbƒZ[ƒW"], 45 | "6": ["Œx"], 46 | "7": ["¬Œ÷"], 47 | "10": ["OK"], 48 | "11": ["ƒLƒƒƒ“ƒZƒ‹"], 49 | "12": ["“K—p"], 50 | "15": ["Yes"], 51 | "16": ["No"], 52 | "31": ["Žw’肳‚ꂽƒtƒ@ƒCƒ‹–¼‚Í–³Ž‹‚³‚ê‚Ü‚·"], 53 | "50": ["”͈͊O‚Å‚· !"], 54 | "51": ["–³Œø‚È•¶Žš‚Å‚· !"], 55 | "52": ["–³Œø‚ȃtƒ@ƒCƒ‹–¼‚Å‚· !"], 56 | "4270": ["’á"], 57 | "4271": ["’†"], 58 | "4272": ["‚"], 59 | "1200": ["ƒXƒe[ƒ^ƒX‚ƃGƒ‰[ ƒƒbƒZ[ƒW"], 60 | "2501": ["ƒgƒ‰ƒbƒNƒXƒe[ƒ^ƒX‚ƃGƒ‰["], 61 | "1203": ["l‚¦‚ç‚ê‚éƒGƒ‰["], 62 | "1204": ["ƒƒOì¬"], 63 | "1210": ["“WŠJ”͈̓Xƒe[ƒ^ƒX‚ƃGƒ‰["], 64 | "1211": ["‘I‘ð‚³‚ê‚½”͈Í"], 65 | "1212": ["ƒ^ƒCƒ~ƒ“ƒOƒvƒƒuƒŒƒ€"], 66 | "1213": ["‹^‚킵‚¢ˆÊ’u"], 67 | "1214": ["ÁޏƒTƒ“ƒvƒ‹"], 68 | "1215": ["‰ßèƒTƒ“ƒvƒ‹"], 69 | "1216": ["ƒtƒ@ƒCƒ‹‘‚«ž‚݃Gƒ‰["], 70 | "1217": ["ƒs[ƒNƒŒƒxƒ‹"], 71 | "1218": ["‘I‘ð”͈͕iŽ¿"], 72 | "1219": ["CRC"], 73 | "1220": ["ƒRƒs[ OK"], 74 | "1221": ["ƒRƒs[Š®—¹"], 75 | "1227": ["ƒgƒ‰ƒbƒN•iŽ¿"], 76 | "1228": ["ƒRƒs[’†Ž~"], 77 | "1269": ["ƒtƒ@ƒCƒ‹–¼"], 78 | "1270": ["ƒvƒŠƒMƒƒƒbƒv’·"], 79 | "1271": ["ƒeƒXƒg CRC"], 80 | "1272": ["ƒRƒs[ CRC"], 81 | "1273": ["ƒGƒ“ƒR[ƒh’†"], 82 | "1222": ["ƒGƒ‰[‚ÍŒŸo‚³‚ê‚Ü‚¹‚ñ‚Å‚µ‚½"], 83 | "1223": ["‘I‘ð”͈͍Dz¸"], 84 | "1224": ["ƒGƒ‰[‚ª‚ ‚è‚Ü‚µ‚½"], 85 | "1225": ["ƒXƒe[ƒ^ƒX‚Ì•ñI—¹"], 86 | "1226": ["ƒgƒ‰ƒbƒN"], 87 | "1230": ["ƒCƒ“ƒfƒbƒNƒX"], 88 | "1229": ["ƒgƒ‰ƒbƒNÄ’²¸"], 89 | "1274": ["EAC “WŠJ ƒƒOƒtƒ@ƒCƒ‹ “ú•tF"], 90 | "1240": ["1ŒŽ"], 91 | "1241": ["2ŒŽ"], 92 | "1242": ["3ŒŽ"], 93 | "1243": ["4ŒŽ"], 94 | "1244": ["5ŒŽ"], 95 | "1245": ["6ŒŽ"], 96 | "1246": ["7ŒŽ"], 97 | "1247": ["8ŒŽ"], 98 | "1248": ["9ŒŽ"], 99 | "1249": ["10ŒŽ"], 100 | "1250": ["11ŒŽ"], 101 | "1251": ["12ŒŽ"], 102 | "1232": ["EAC “WŠJó‹µ ƒƒOƒtƒ@ƒCƒ‹ for CD"], 103 | "1233": ["Žg—pƒhƒ‰ƒCƒu :"], 104 | "1234": ["“ǂݍž‚݃‚[ƒh :"], 105 | "1235": ["ƒo[ƒXƒg"], 106 | "1236": ["ƒtƒ@ƒXƒg"], 107 | "1237": ["ƒZƒLƒ…ƒAiC2 : NO / ³Šm‚ȃf[ƒ^“]‘——Í : NO / ƒLƒƒƒbƒVƒ…–³Œø : NOj"], 108 | "1238": ["ƒZƒLƒ…ƒAiC2 : NO / ³Šm‚ȃf[ƒ^“]‘——Í : YES / ƒLƒƒƒbƒVƒ…–³Œø : NOj"], 109 | "1239": ["ƒZƒLƒ…ƒAiC2 : NO / ³Šm‚ȃf[ƒ^“]‘——Í : NO / ƒLƒƒƒbƒVƒ…–³Œø : YESj"], 110 | "1252": ["ƒZƒLƒ…ƒAiC2 : YES / ³Šm‚ȃf[ƒ^“]‘——Í : YES / ƒLƒƒƒbƒVƒ…–³Œø : NOj"], 111 | "1253": ["ƒZƒLƒ…ƒAiC2 : YES / ³Šm‚ȃf[ƒ^“]‘——Í : YES / ƒLƒƒƒbƒVƒ…–³Œø : YESj"], 112 | "1254": ["ƒZƒLƒ…ƒAiC2 : NO / ³Šm‚ȃf[ƒ^“]‘——Í : YES / ƒLƒƒƒbƒVƒ…–³Œø : YESj"], 113 | "1255": ["“ǂݍž‚݁E‘‚«ž‚݃IƒtƒZƒbƒg’ù³’l :"], 114 | "1256": ["“ǂݍž‚݃IƒtƒZƒbƒg’ù³’l :"], 115 | "1257": ["ƒŠ[ƒhƒCƒ“‚ÆƒŠ[ƒhƒAƒEƒg‚ðƒI[ƒo[ƒŠ[ƒh‚·‚é"], 116 | "1258": ["Žg—po—̓tƒH[ƒ}ƒbƒg :"], 117 | "1259": ["’ljÁƒRƒ}ƒ“ƒhƒ‰ƒCƒ“ƒIƒvƒVƒ‡ƒ“ :"], 118 | "1260": ["“à•” WAV ƒ‹[ƒ`ƒ“"], 119 | "1261": ["44.100 Hz; 16 Bit; ƒXƒeƒŒƒI"], 120 | "1262": ["Žg—pƒGƒ“ƒR[ƒhƒIƒtƒZƒbƒg’l :"], 121 | "1263": ["‚»‚Ì‘¼‚̃IƒvƒVƒ‡ƒ“ :"], 122 | "1264": ["Áޏ‚µ‚½ƒIƒtƒZƒbƒgƒTƒ“ƒvƒ‹‚𖳉¹‚É’u‚«Š·‚¦‚é"], 123 | "1265": ["‹È‚̐擪‚Æ––”ö‚Ì–³‰¹•”‚ðíœ‚·‚é"], 124 | "1266": ["ƒm[ƒ}ƒ‰ƒCƒY :"], 125 | "1267": ["•W€ Win32 ‚Ì Win NT & 2000 —p"], 126 | "1268": ["ƒCƒ“ƒXƒg[ƒ‹Ï‚ÝŠO•” ASPI ƒCƒ“ƒ^[ƒtƒFƒCƒX"], 127 | "81700": ["L3Enc MP3 Encoder & Compatible"], 128 | "81701": ["Fraunhofer MP3Enc MP3 Encoder"], 129 | "81702": ["Xing X3Enc MP3 Encoder"], 130 | "81703": ["Xing ToMPG MP3 Encoder"], 131 | "81704": ["LAME MP3 Encoder"], 132 | "81705": ["GOGO MP3 Encoder"], 133 | "81706": ["MPC Encoder"], 134 | "81707": ["Ogg Vorbis Encoder"], 135 | "81708": ["Microsoft WMA9 Encoder"], 136 | "81709": ["FAAC AAC Encoder"], 137 | "81710": ["Homeboy AAC Encoder"], 138 | "81711": ["Quartex AAC Encoder"], 139 | "81712": ["PsyTEL AAC Encoder"], 140 | "81713": ["MBSoft AAC Encoder"], 141 | "81714": ["Yamaha VQF Encoder"], 142 | "81715": ["Real Audio Encoder"], 143 | "81716": ["Monkey's Audio Lossless Encoder"], 144 | "81717": ["Shorten Lossless Encoder"], 145 | "81718": ["RKAU Lossless Encoder"], 146 | "81719": ["LPAC Lossless Encoder"], 147 | "81720": ["ƒ†[ƒU[’è‹` ƒGƒ“ƒR[ƒ_["] 148 | } 149 | } -------------------------------------------------------------------------------- /heybrochecklog/resources/eac95/korean.json: -------------------------------------------------------------------------------- 1 | { 2 | "patterns": { 3 | "drive": ["»ç¿ëµÈ µå¶óÀ̺ê"], 4 | "settings": { 5 | "Read mode": ["¾ÈÀü"], 6 | "C2 pointers": ["(C2 °¡´É"], 7 | "Accurate stream": [", Á¤¹ÐÇÑ Àü¼Û °¡´É"], 8 | "Audio cache": [", ij½¬ ¹«È¿ °¡´É)"], 9 | "Drive offset": ["Àб⠿ÀÇÁ¼Â ±³Á¤"] 10 | }, 11 | "full line settings": { 12 | "Fill missing offset samples with silence": ["¼Õ½ÇµÈ ¿ÀÇÁ¼Â »ùÇÃÀ» ¹«À½À¸·Î ´ëÄ¡"], 13 | "Deleting silent blocks": ["óÀ½°ú ³¡ ºÎºÐÀÇ ¹«À½ ºí¶ô »èÁ¦"] 14 | }, 15 | "bad settings": { 16 | "Normalization": ["À½·®Æò±ÕÈ­ to"], 17 | "Compression offset": ["»ç¿ë ¾ÐÃà ¿ÀÇÁ¼Â"], 18 | "Combined offset": ["°áÇÕµÈ Àбâ/¾²±â ¿ÀÇÁ¼Â ±³Á¤"] 19 | }, 20 | "proper settings": { 21 | "Fill missing offset samples with silence": ["¿¹"], 22 | "Deleting silent blocks": ["¾Æ´Ï¿À"] 23 | }, 24 | "range": ["»óÅÂ¿Í ¿À·ù ¹üÀ§"], 25 | "track": ["Æ®·¢"], 26 | "track settings": { 27 | "filename": ["ÆÄÀÏ À̸§"], 28 | "pregap": ["ÀÌÀü °ø°£ ±æÀÌ"], 29 | "peak": ["ÇÇÅ© ·¹º§"], 30 | "test crc": ["°Ë»ç CRC"], 31 | "copy crc": ["(?:º¹»ç CRC|CRC)"] 32 | }, 33 | "track errors": { 34 | "Aborted copy": ["º¹»ç ÁߴܵÊ"], 35 | "Timing problem": ["ŸÀÌ¹Ö ¹®Á¦"], 36 | "Missing samples": ["ÀÒÀº »ùÇÃ"], 37 | "Suspicious position": ["¹Ì½ÉÀûÀº À§Ä¡"] 38 | }, 39 | "footer": ["»óÅ º¸°í¼­ÀÇ ³¡"] 40 | }, 41 | "translation": { 42 | "1": ["Çѱ¹¾î"], 43 | "2": ["Korean"], 44 | "5": ["¿À·ù ¸Þ½ÃÁö"], 45 | "6": ["°æ°í"], 46 | "7": ["¼º°ø"], 47 | "10": ["OK"], 48 | "11": ["Ãë¼Ò"], 49 | "12": ["Àû¿ë"], 50 | "15": ["¿¹"], 51 | "16": ["¾Æ´Ï¿À"], 52 | "31": ["ÆÄÀÏ À̸§Àº ¹«½ÃµÊ"], 53 | "50": ["Çã¿ë ¹üÀ§ ³ÑÀ½ !"], 54 | "51": ["À߸øµÈ ¹®ÀÚ !"], 55 | "52": ["À߸øµÈ ÆÄÀÏ À̸§ !"], 56 | "4270": ["³·À½"], 57 | "4271": ["º¸Åë"], 58 | "4272": ["³ôÀ½"], 59 | "1200": ["»óÅÂ¿Í ¿À·ù ¸Þ½ÃÁö"], 60 | "2501": ["Æ®·¢ »óÅÂ¿Í ¿À·ù"], 61 | "1203": ["¹ß»ý °¡´ÉÇÑ ¿À·ù"], 62 | "1204": ["·Î±× »ý¼º"], 63 | "1210": ["»óÅÂ¿Í ¿À·ù ¹üÀ§"], 64 | "1211": ["¼±ÅÃµÈ ¹üÀ§"], 65 | "1212": ["ŸÀÌ¹Ö ¹®Á¦"], 66 | "1213": ["¹Ì½ÉÀûÀº À§Ä¡"], 67 | "1214": ["ÀÒÀº »ùÇÃ"], 68 | "1215": ["³Ê¹« ¸¹Àº »ùÇÃ"], 69 | "1216": ["ÆÄÀÏ ¾²±â ¿À·ù"], 70 | "1217": ["ÇÇÅ© ·¹º§"], 71 | "1218": ["¼±Åà ¹üÀ§ ǰÁú"], 72 | "1219": ["CRC"], 73 | "1220": ["º¹»ç OK"], 74 | "1221": ["º¹»ç ³¡³²"], 75 | "1227": ["Æ®·¢ ǰÁú"], 76 | "1228": ["º¹»ç ÁߴܵÊ"], 77 | "1269": ["ÆÄÀÏ À̸§"], 78 | "1270": ["ÀÌÀü °ø°£ ±æÀÌ"], 79 | "1271": ["°Ë»ç CRC"], 80 | "1272": ["º¹»ç CRC"], 81 | "1273": ["¾ÐÃà Áß"], 82 | "1222": ["¿À·ù ¹ß»ý ¾ø¾úÀ½"], 83 | "1223": ["¼±Åà ¹üÀ§ Àç°Ë»ç"], 84 | "1224": ["¿À·ù°¡ ÀÖ¾úÀ½"], 85 | "1225": ["»óÅ º¸°í¼­ÀÇ ³¡"], 86 | "1226": ["Æ®·¢"], 87 | "1230": ["»öÀÎ"], 88 | "1229": ["Æ®·¢ Àç°Ë»ç"], 89 | "1274": ["EAC ÃßÃâ ·Î±× ÆÄÀÏ from"], 90 | "1240": ["1¿ù"], 91 | "1241": ["2¿ù"], 92 | "1242": ["3¿ù"], 93 | "1243": ["4¿ù"], 94 | "1244": ["5¿ù"], 95 | "1245": ["6¿ù"], 96 | "1246": ["7¿ù"], 97 | "1247": ["8¿ù"], 98 | "1248": ["9¿ù"], 99 | "1249": ["10¿ù"], 100 | "1250": ["11¿ù"], 101 | "1251": ["12¿ù"], 102 | "1232": ["EAC ÃßÃâ ·Î±× ÆÄÀÏ for CD"], 103 | "1233": ["»ç¿ëµÈ µå¶óÀ̺ê :"], 104 | "1234": ["Àб⠹æ½Ä :"], 105 | "1235": ["¹ö½ºÆ®"], 106 | "1236": ["ºü¸¥"], 107 | "1237": ["¾ÈÀü (C2 ºÒ°¡´É, Á¤¹ÐÇÑ Àü¼Û ºÒ°¡´É, ij½¬ ¹«È¿ ºÒ°¡´É)"], 108 | "1238": ["¾ÈÀü (C2 ºÒ°¡´É, Á¤¹ÐÇÑ Àü¼Û °¡´É, ij½¬ ¹«È¿ ºÒ°¡´É)"], 109 | "1239": ["¾ÈÀü (C2 ºÒ°¡´É, Á¤¹ÐÇÑ Àü¼Û ºÒ°¡, ij½¬ ¹«È¿ °¡´É)"], 110 | "1252": ["¾ÈÀü (C2 °¡´É, Á¤¹ÐÇÑ Àü¼Û °¡´É, ij½¬ ¹«È¿ ºÒ°¡´É)"], 111 | "1253": ["¾ÈÀü (C2 °¡´É, Á¤¹ÐÇÑ Àü¼Û °¡´É, ij½¬ ¹«È¿ °¡´É)"], 112 | "1254": ["¾ÈÀü (C2 °¡´É, Á¤¹ÐÇÑ Àü¼Û °¡´É, ij½¬ ¹«È¿ °¡´É)"], 113 | "1255": ["°áÇÕµÈ Àбâ/¾²±â ¿ÀÇÁ¼Â ±³Á¤ :"], 114 | "1256": ["Àб⠿ÀÇÁ¼Â ±³Á¤ :"], 115 | "1257": ["¸®µå-Àΰú ¸®µå-¾Æ¿ôÀ¸·Î ¿À¹ö¸®µå"], 116 | "1258": ["»ç¿ëµÈ Ãâ·Â Çü½Ä :"], 117 | "1259": ["Ãß°¡ ¸í·ÉÁÙ ¼³Á¤ :"], 118 | "1260": ["³»ºÎ WAV ·çƾ"], 119 | "1261": ["44.100 Hz; 16 ºñÆ®; ½ºÅ×·¹¿À"], 120 | "1262": ["»ç¿ë ¾ÐÃà ¿ÀÇÁ¼Â :"], 121 | "1263": ["±× ¹ÛÀÇ ¼³Á¤ :"], 122 | "1264": ["¼Õ½ÇµÈ ¿ÀÇÁ¼Â »ùÇÃÀ» ¹«À½À¸·Î ´ëÄ¡"], 123 | "1265": ["óÀ½°ú ³¡ ºÎºÐÀÇ ¹«À½ ºí¶ô »èÁ¦"], 124 | "1266": ["À½·®Æò±ÕÈ­ to"], 125 | "1267": ["À©µµ¿ìÁî NT & 2000À» À§ÇÑ Ç¥ÁØ Win32 ÀÎÅÍÆäÀ̽º"], 126 | "1268": ["¿ÜºÎ ASPI ÀÎÅÍÆäÀ̽º°¡ ¼³Ä¡µÊ"], 127 | "81700": ["L3Enc MP3 ÀÎÄÚ´õ & ȣȯ ÀÎÄÚ´õ"], 128 | "81701": ["Fraunhofer MP3Enc MP3 ÀÎÄÚ´õ"], 129 | "81702": ["Xing X3Enc MP3 ÀÎÄÚ´õ"], 130 | "81703": ["Xing ToMPG MP3 ÀÎÄÚ´õ"], 131 | "81704": ["LAME MP3 ÀÎÄÚ´õ"], 132 | "81705": ["GOGO MP3 ÀÎÄÚ´õ"], 133 | "81706": ["MPC ÀÎÄÚ´õ"], 134 | "81707": ["Ogg Vorbis ÀÎÄÚ´õ"], 135 | "81708": ["¸¶ÀÌÅ©·Î¼ÒÇÁÆ® WMA9 ÀÎÄÚ´õ"], 136 | "81709": ["FAAC AAC ÀÎÄÚ´õ"], 137 | "81710": ["Homeboy AAC ÀÎÄÚ´õ"], 138 | "81711": ["Quartex AAC ÀÎÄÚ´õ"], 139 | "81712": ["PsyTEL AAC ÀÎÄÚ´õ"], 140 | "81713": ["MBSoft AAC ÀÎÄÚ´õ"], 141 | "81714": ["Yamaha VQF ÀÎÄÚ´õ"], 142 | "81715": ["Real Audio ÀÎÄÚ´õ"], 143 | "81716": ["Monkey's Audio ¹«¼Õ½Ç ÀÎÄÚ´õ"], 144 | "81717": ["Shorten ¹«¼Õ½Ç ÀÎÄÚ´õ"], 145 | "81718": ["RKAU ¹«¼Õ½Ç ÀÎÄÚ´õ"], 146 | "81719": ["LPAC ¹«¼Õ½Ç ÀÎÄÚ´õ"], 147 | "81720": ["»ç¿ëÀÚ Á¤ÀÇ ÀÎÄÚ´õ"] 148 | } 149 | } -------------------------------------------------------------------------------- /heybrochecklog/resources/eac95/swedish.json: -------------------------------------------------------------------------------- 1 | { 2 | "patterns": { 3 | "drive": ["Använd enhet"], 4 | "settings": { 5 | "Read mode": ["Säker"], 6 | "C2 pointers": ["med INGEN C2"], 7 | "Accurate stream": [", accurate stream"], 8 | "Audio cache": [", bortkopplad cache"], 9 | "Drive offset": ["Läs-offset-korrigering"] 10 | }, 11 | "full line settings": { 12 | "Fill missing offset samples with silence": ["Fyll upp saknade offset-samplingar med tystnad"], 13 | "Deleting silent blocks": ["Radera inledande och eftersläpande tysta block"] 14 | }, 15 | "bad settings": { 16 | "Normalization": ["Normalisera till"], 17 | "Compression offset": ["Använd komprimerings-offset"], 18 | "Combined offset": ["Kombinerad läs/skriv offset-korrigering"] 19 | }, 20 | "proper settings": { 21 | "Fill missing offset samples with silence": ["Ja"], 22 | "Deleting silent blocks": ["Nej"] 23 | }, 24 | "range": ["Områdets status och fel"], 25 | "track": ["Spår"], 26 | "track settings": { 27 | "filename": ["Filnamn"], 28 | "pregap": ["För-gap längd"], 29 | "peak": ["Peak-nivå"], 30 | "test crc": ["Testar CRC"], 31 | "copy crc": ["(?:Kopiera CRC|CRC)"] 32 | }, 33 | "track errors": { 34 | "Aborted copy": ["Kopia avbruten"], 35 | "Timing problem": ["Timing-problem"], 36 | "Missing samples": ["Saknade samplingar"], 37 | "Suspicious position": ["Misstänkt position"] 38 | }, 39 | "footer": ["Slut på status rapport"] 40 | }, 41 | "translation": { 42 | "1": ["Svenska"], 43 | "2": ["Swedish"], 44 | "5": ["Felmeddelande"], 45 | "6": ["Varning"], 46 | "7": ["Framgångsrik"], 47 | "10": ["OK"], 48 | "11": ["Avbryt"], 49 | "12": ["Verkställ"], 50 | "15": ["Ja"], 51 | "16": ["Nej"], 52 | "31": ["Filnamnet kommer att ignoreras"], 53 | "50": ["Värdet är utom valt område !"], 54 | "51": ["Felaktiga tecken !"], 55 | "52": ["Felaktigt filnamn !"], 56 | "4270": ["Låg"], 57 | "4271": ["Medium"], 58 | "4272": ["Hög"], 59 | "1200": ["Status och Fel Meddelanden"], 60 | "2501": ["Spårstatus och fel"], 61 | "1203": ["Möjliga fel"], 62 | "1204": ["Skapa Logg"], 63 | "1210": ["Områdets status och fel"], 64 | "1211": ["Utvalt område"], 65 | "1212": ["Timing-problem"], 66 | "1213": ["Misstänkt position"], 67 | "1214": ["Saknade samplingar"], 68 | "1215": ["För många samplingar"], 69 | "1216": ["Fil-skrivfel"], 70 | "1217": ["Peak-nivå"], 71 | "1218": ["Områdets kvalité"], 72 | "1219": ["CRC"], 73 | "1220": ["Kopia OK"], 74 | "1221": ["Kopia färdig"], 75 | "1227": ["Spårkvalité"], 76 | "1228": ["Kopia avbruten"], 77 | "1269": ["Filnamn"], 78 | "1270": ["För-gap längd"], 79 | "1271": ["Testar CRC"], 80 | "1272": ["Kopiera CRC"], 81 | "1273": ["Komprimerar"], 82 | "1222": ["Inga fel uppstod"], 83 | "1223": ["Granska Område"], 84 | "1224": ["Det fanns fel"], 85 | "1225": ["Slut på status rapport"], 86 | "1226": ["Spår"], 87 | "1230": ["Index"], 88 | "1229": ["Granska Spår"], 89 | "1274": ["EAC extraheringsloggfil från"], 90 | "1240": ["Januari"], 91 | "1241": ["Februari"], 92 | "1242": ["Mars"], 93 | "1243": ["April"], 94 | "1244": ["Maj"], 95 | "1245": ["Juni"], 96 | "1246": ["Juli"], 97 | "1247": ["Augusti"], 98 | "1248": ["September"], 99 | "1249": ["Oktober"], 100 | "1250": ["November"], 101 | "1251": ["December"], 102 | "1232": ["EAC extraheringsloggfil för CD"], 103 | "1233": ["Använd enhet :"], 104 | "1234": ["Läsmetod :"], 105 | "1235": ["Burst"], 106 | "1236": ["Snabb"], 107 | "1237": ["Säker med INGEN C2, INGEN accurate stream, INGEN bortkopplad cache"], 108 | "1238": ["Säker med INGEN C2, accurate stream, INGEN bortkopplad cache"], 109 | "1239": ["Säker med INGEN C2, INGEN accurate stream, bortkopplad cache"], 110 | "1252": ["Säker med C2, accurate stream, INGEN bortkopplad cache"], 111 | "1253": ["Säker med C2, accurate stream, bortkopplad cache"], 112 | "1254": ["Säker med INGEN C2, accurate stream, bortkopplad cache"], 113 | "1255": ["Kombinerad läs/skriv offset-korrigering :"], 114 | "1256": ["Läs-offset-korrigering :"], 115 | "1257": ["Läs in i Lead-In och Lead-Out"], 116 | "1258": ["Använt output format :"], 117 | "1259": ["Ytterligare kommandoradsinställningar :"], 118 | "1260": ["Interna WAV Rutiner"], 119 | "1261": ["44.100 Hz; 16 Bit; Stereo"], 120 | "1262": ["Använd komprimerings-offset :"], 121 | "1263": ["Andra inställningar :"], 122 | "1264": ["Fyll upp saknade offset-samplingar med tystnad"], 123 | "1265": ["Radera inledande och eftersläpande tysta block"], 124 | "1266": ["Normalisera till"], 125 | "1267": ["Native Win32 gränssnitt för Win NT & 2000"], 126 | "1268": ["Installerat externt ASPI gränssnitt"], 127 | "81700": ["L3Enc MP3 Kodare & Kompatibla"], 128 | "81701": ["Fraunhofer MP3Enc MP3 Kodare"], 129 | "81702": ["Xing X3Enc MP3 Kodare"], 130 | "81703": ["Xing ToMPG MP3 Kodare"], 131 | "81704": ["LAME MP3 Kodare"], 132 | "81705": ["GOGO MP3 Kodare"], 133 | "81706": ["MPC Kodare"], 134 | "81707": ["Ogg Vorbis Kodare"], 135 | "81708": ["Microsoft WMA9 Kodare"], 136 | "81709": ["FAAC AAC Kodare"], 137 | "81710": ["Homeboy AAC Kodare"], 138 | "81711": ["Quartex AAC Kodare"], 139 | "81712": ["PsyTEL AAC Kodare"], 140 | "81713": ["MBSoft AAC Kodare"], 141 | "81714": ["Yamaha VQF Kodare"], 142 | "81715": ["Real Audio Kodare"], 143 | "81716": ["Monkey's Audio Förlustfri Kodare"], 144 | "81717": ["Shorten Förlustfri Kodare"], 145 | "81718": ["RKAU Förlustfri Kodare"], 146 | "81719": ["LPAC Förlustfri Kodare"], 147 | "81720": ["Användardefinierad Kodare"] 148 | } 149 | } -------------------------------------------------------------------------------- /heybrochecklog/resources/eac95/taiwan.json: -------------------------------------------------------------------------------- 1 | { 2 | "patterns": { 3 | "drive": ["¨Ï¥Î¥úºÐ¾÷ ¡G"], 4 | "settings": { 5 | "Read mode": null, 6 | "C2 pointers": null, 7 | "Accurate stream": null, 8 | "Audio cache": null, 9 | "Drive offset": ["Ū¨ú°¾²¾¡]offset¡^®Õ¥¿¡G"] 10 | }, 11 | "full line settings": { 12 | "Fill missing offset samples with silence": ["¥ÎÀR­µ¶ñ¥R§ì¨ú¤¤¿ò¥¢°¾²¾¡]offset¡^ªº¨ú¼Ë"], 13 | "Deleting silent blocks": ["¥h°£­º§ÀÀR­µ¶ô"] 14 | }, 15 | "bad settings": { 16 | "Normalization": ["¼Ð·Ç¤Æ¦Ü"], 17 | "Compression offset": ["¨Ï¥ÎÀ£ÁY°¾²¾¡]offset¡^¡G"], 18 | "Combined offset": ["µ²¦XŪ¼g°¾²¾¡]offset¡^®Õ¥¿¡G"] 19 | }, 20 | "proper settings": { 21 | "Fill missing offset samples with silence": ["¬O"], 22 | "Deleting silent blocks": ["§_"] 23 | }, 24 | "range": ["½d³òª¬ºA¤Î¿ù»~"], 25 | "track": ["­µ­y"], 26 | "track settings": { 27 | "filename": ["ÀɮצWºÙ"], 28 | "pregap": ["«e¶¡»Øªø«×"], 29 | "peak": ["®p­È¹q¥­"], 30 | "test crc": ["´ú¸Õ CRC"], 31 | "copy crc": ["(?:½Æ»s CRC|CRC)"] 32 | }, 33 | "track errors": { 34 | "Aborted copy": ["½Æ»s³Q¤¤¤î"], 35 | "Timing problem": ["­p®É°ÝÃD"], 36 | "Missing samples": ["¿ò¥¢¨ú¼Ë"], 37 | "Suspicious position": ["¥iºÃ¦ì¸m"] 38 | }, 39 | "footer": ["ª¬ºA³ø§iµ²§À"] 40 | }, 41 | "translation": { 42 | "1": ["¥¿Å餤¤å"], 43 | "2": ["Taiwan"], 44 | "5": ["¿ù»~°T®§"], 45 | "6": ["ĵ§i"], 46 | "7": ["¦¨¥\\\\"], 47 | "10": ["½T©w"], 48 | "11": ["¨ú®ø"], 49 | "12": ["®M¥Î"], 50 | "15": ["¬O"], 51 | "16": ["§_"], 52 | "31": ["ÀɮצWºÙ±N³Q©¿²¤"], 53 | "50": ["¼Æ­È¶W¹L½d³ò¡I"], 54 | "51": ["µL®Ä¦r¤¸¡I"], 55 | "52": ["µL®ÄÀɮצWºÙ¡I"], 56 | "4270": ["§C"], 57 | "4271": ["¤¤"], 58 | "4272": ["°ª"], 59 | "1200": ["ª¬ºA¤Î¿ù»~°T®§"], 60 | "2501": ["­µ­yª¬ºA¤Î¿ù»~"], 61 | "1203": ["¥i¯àªº¿ù»~"], 62 | "1204": ["«Ø¥ß¤é»x"], 63 | "1210": ["½d³òª¬ºA¤Î¿ù»~"], 64 | "1211": ["¤w¿ï¾Ü½d³ò"], 65 | "1212": ["­p®É°ÝÃD"], 66 | "1213": ["¥iºÃ¦ì¸m"], 67 | "1214": ["¿ò¥¢¨ú¼Ë"], 68 | "1215": ["¹L¦h¨ú¼Ë"], 69 | "1216": ["ÀÉ®×¼g¤J¿ù»~"], 70 | "1217": ["®p­È¹q¥­"], 71 | "1218": ["½d³ò½è¶q"], 72 | "1219": ["CRC"], 73 | "1220": ["½Æ»s¦¨¥\\\\"], 74 | "1221": ["½Æ»sµ²§ô"], 75 | "1227": ["­µ­y«~½è"], 76 | "1228": ["½Æ»s³Q¤¤¤î"], 77 | "1269": ["ÀɮצWºÙ"], 78 | "1270": ["«e¶¡»Øªø«×"], 79 | "1271": ["´ú¸Õ CRC"], 80 | "1272": ["½Æ»s CRC"], 81 | "1273": ["¥¿¦bÀ£ÁY"], 82 | "1222": ["¨S¦³¿ù»~µo¥Í"], 83 | "1223": ["­«·sÀˬd½d³ò"], 84 | "1224": ["¥X²{¿ù»~"], 85 | "1225": ["ª¬ºA³ø§iµ²§À"], 86 | "1226": ["­µ­y"], 87 | "1230": ["¯Á¤Þ"], 88 | "1229": ["­«·sÀˬd­µ­y"], 89 | "1274": ["EAC §ì¨ú¤é»xÀÉ®×±q"], 90 | "1240": ["¤@¤ë"], 91 | "1241": ["¤G¤ë"], 92 | "1242": ["¤T¤ë"], 93 | "1243": ["¥|¤ë"], 94 | "1244": ["¤­¤ë"], 95 | "1245": ["¤»¤ë"], 96 | "1246": ["¤C¤ë"], 97 | "1247": ["¤K¤ët"], 98 | "1248": ["¤E¤ë"], 99 | "1249": ["¤Q¤ë"], 100 | "1250": ["¤Q¤@¤ë"], 101 | "1251": ["¤Q¤G¤ë"], 102 | "1232": ["EAC §ì¨ú CD ³]¸mÀÉ®×"], 103 | "1233": ["¨Ï¥Î¥úºÐ¾÷ ¡G"], 104 | "1234": ["Ū¨ú¼Ò¦¡ ¡G"], 105 | "1235": ["¼É¤O"], 106 | "1236": ["§Ö³t"], 107 | "1237": ["¤£¨Ï¥Î C2,¤£¨Ï¥Îºë½T¬y¡]Accurate Stream¡^¡A¤£Ãö³¬¼È¦s°Ïªº¦w¥þ¼Ò¦¡"], 108 | "1238": ["¤£¨Ï¥Î C2, ¨Ï¥Îºë½T¬y¡]Accurate Stream¡^¡A¤£Ãö³¬¼È¦s°Ïªº¦w¥þ¼Ò¦¡"], 109 | "1239": ["¤£¨Ï¥Î C2, ¤£¨Ï¥Îºë½T¬y¡]Accurate Stream¡^¡AÃö³¬¼È¦s°Ïªº¦w¥þ¼Ò¦¡"], 110 | "1252": ["¨Ï¥Î C2,¨Ï¥Îºë½T¬y¡]Accurate Stream¡^¡A¤£Ãö³¬¼È¦s°Ïªº¦w¥þ¼Ò¦¡"], 111 | "1253": ["¨Ï¥Î C2, ¨Ï¥Îºë½T¬y¡]Accurate Stream¡^¡AÃö³¬¼È¦s°Ïªº¦w¥þ¼Ò¦¡"], 112 | "1254": ["¤£¨Ï¥Î C2¡A¨Ï¥Îºë½T¬y¡]Accurate Stream¡^, Ãö³¬¼È¦s°Ïªº¦w¥þ¼Ò¦¡"], 113 | "1255": ["µ²¦XŪ¼g°¾²¾¡]offset¡^®Õ¥¿¡G"], 114 | "1256": ["Ū¨ú°¾²¾¡]offset¡^®Õ¥¿¡G"], 115 | "1257": ["Ū¨ú Lead-In ©M Lead-Out"], 116 | "1258": ["©Ò¥Î¿é¥X¼Ò¦¡¡G"], 117 | "1259": ["ªþ¥[©R¥O¦C¡]commandline¡^°Ñ¼Æ¡G"], 118 | "1260": ["¤º³¡ WAV ¨ç¼Æ"], 119 | "1261": ["44.100 Hz;16 Bit;¥ßÅéÁn"], 120 | "1262": ["¨Ï¥ÎÀ£ÁY°¾²¾¡]offset¡^¡G"], 121 | "1263": ["¨ä¥L¿ï¶µ ¡G"], 122 | "1264": ["¥ÎÀR­µ¶ñ¥R§ì¨ú¤¤¿ò¥¢°¾²¾¡]offset¡^ªº¨ú¼Ë"], 123 | "1265": ["¥h°£­º§ÀÀR­µ¶ô"], 124 | "1266": ["¼Ð·Ç¤Æ¦Ü"], 125 | "1267": ["Win NT ¤Î 2000 ¥»¦a Win32 ÅX°Êµ{¦¡"], 126 | "1268": ["¤w¦w¸Ë¥~³¡ ASPI ÅX°Êµ{¦¡"], 127 | "81700": ["L3Enc MP3 ¬Û®e½s½X¾¹"], 128 | "81701": ["Fraunhofer MP3Enc MP3 ½s½X¾¹"], 129 | "81702": ["Xing X3Enc MP3 ½s½X¾¹"], 130 | "81703": ["Xing ToMPG MP3 ½s½X¾¹"], 131 | "81704": ["LAME MP3 ½s½X¾¹"], 132 | "81705": ["GOGO MP3 ½s½X¾¹"], 133 | "81706": ["MPC ½s½X¾¹"], 134 | "81707": ["Ogg Vorbis ½s½X¾¹"], 135 | "81708": ["Microsoft WMA9 ½s½X¾¹"], 136 | "81709": ["FAAC AAC ½s½X¾¹"], 137 | "81710": ["Homeboy AAC ½s½X¾¹"], 138 | "81711": ["Quartex AAC ½s½X¾¹"], 139 | "81712": ["PsyTEL AAC ½s½X¾¹"], 140 | "81713": ["MBSoft AAC ½s½X¾¹"], 141 | "81714": ["Yamaha VQF ½s½X¾¹"], 142 | "81715": ["Real Audio ½s½X¾¹"], 143 | "81716": ["Monkey's Audio «D¯}Ãa©Ê½s½X¾¹"], 144 | "81717": ["Shorten «D¯}Ãa©Ê½s½X¾¹"], 145 | "81718": ["RKAU «D¯}Ãa©Ê½s½X¾¹"], 146 | "81719": ["LPAC «D¯}Ãa©Ê½s½X¾¹"], 147 | "81720": ["¨Ï¥ÎªÌ©w¸qªº½s½X¾¹"] 148 | } 149 | } -------------------------------------------------------------------------------- /heybrochecklog/resources/xld.json: -------------------------------------------------------------------------------- 1 | { 2 | "drive": ["Used [Dd]rive"], 3 | "settings": { 4 | "Read mode": ["(?:Ripper|Use cdparanoia) mode"], 5 | "Audio cache": ["Disable audio cache"], 6 | "C2 pointers": ["Make use of C2 pointers"], 7 | "Drive offset": ["Read offset correction"], 8 | "Gap handling": ["Gap status"] 9 | }, 10 | "proper settings": { 11 | "Read mode": ["XLD Secure Ripper"], 12 | "Audio cache": ["OK for the drive with(?: a)? cache less than [0-9]+Ki?B"], 13 | "C2 pointers": ["NO"], 14 | "Gap handling": ["Analyzed, Appended(?: \\(except HTOA\\))?"] 15 | }, 16 | "disc type": ["Media type"], 17 | "toc": ["TOC of the extracted CD"], 18 | "track": ["Track"], 19 | "All Tracks": ["All Tracks"], 20 | "track settings": { 21 | "gain": ["Track gain"], 22 | "filename": ["Filename"], 23 | "pregap": ["Pre-gap length"], 24 | "peak": ["Peak"], 25 | "test crc": ["CRC32 hash \\(test run\\)"], 26 | "copy crc": ["CRC32 hash"] 27 | }, 28 | "track errors": { 29 | "Read error": ["Read error"], 30 | "Damaged sector count": ["Damaged sector count"] 31 | }, 32 | "accuraterip": { 33 | "match": [ 34 | "->Accurately ripped!? \\((?:(AR)?[v12,+]+ )?confidence ([0-9\\/+]+)\\)", 35 | "->Accurately ripped!? (with different offset \\(v\\d, confidence \\d\\/\\d, offset -?\\d+\\))", 36 | "->Accurately ripped!? (with different offset\\s)?\\((?:(AR)?[v12,+]+ )?confidence ([0-9\\/+]+)(, offset -?\\d+)?\\)" 37 | ], 38 | "no match": ["->Track not present in AccurateRip database"] 39 | }, 40 | "footer": ["End of status report"], 41 | "checksum": ["-----BEGIN XLD SIGNATURE-----"] 42 | } 43 | -------------------------------------------------------------------------------- /heybrochecklog/score/__init__.py: -------------------------------------------------------------------------------- 1 | """This module handles the log scoring functionality of the heybrochecklog package.""" 2 | 3 | import html 4 | 5 | from heybrochecklog import UnrecognizedException 6 | from heybrochecklog.analyze import analyze_log 7 | from heybrochecklog.logfile import LogFile 8 | from heybrochecklog.score import eac, eac95, xld 9 | from heybrochecklog.shared import get_log_contents, open_json 10 | 11 | 12 | def score_log(log_file, markup=False, integrity=False): 13 | try: 14 | contents = get_log_contents(log_file) 15 | log = LogFile(contents) 16 | log = score_wrapper(log, markup, integrity) 17 | except UnicodeDecodeError: 18 | log = LogFile('') 19 | log.unrecognized = 'Could not decode log file.' 20 | return log.to_dict() 21 | 22 | 23 | def score_log_from_contents(contents): 24 | """Score a log file given its contents, instead of opening it from a file.""" 25 | log = LogFile(contents.split('\n')) 26 | try: 27 | log = score_wrapper(log) 28 | except UnicodeDecodeError: 29 | log.unrecognized = 'Could not decode log file.' 30 | return log.to_dict() 31 | 32 | 33 | def score_wrapper(log, markup=False, integrity=False): 34 | """Determine the type of log file and passes the log to the appropriate logchecker.""" 35 | 36 | try: 37 | analyze_log(log) 38 | except UnrecognizedException as exception: 39 | log.unrecognized = str(exception) 40 | log.full_contents = [html.escape(line) for line in log.full_contents] 41 | return log 42 | 43 | if log.ripper == 'EAC': 44 | info_json = open_json('eac', '{}.json'.format(log.language)) 45 | logchecker = eac.EACChecker( 46 | info_json['patterns'], info_json['translation'], markup 47 | ) 48 | elif log.ripper == 'XLD': 49 | patterns = open_json('xld.json') 50 | logchecker = xld.XLDChecker(patterns, markup=markup) 51 | elif log.ripper == 'EAC95': 52 | info_json = open_json('eac95', '{}.json'.format(log.language)) 53 | logchecker = eac95.EAC95Checker( 54 | info_json['patterns'], info_json['translation'], markup 55 | ) 56 | 57 | try: 58 | log = logchecker.check(log, integrity) 59 | except UnrecognizedException as exception: 60 | log.unrecognized = str(exception) 61 | log.full_contents = [html.escape(line) for line in log.full_contents] 62 | 63 | return log 64 | -------------------------------------------------------------------------------- /heybrochecklog/score/integrity.py: -------------------------------------------------------------------------------- 1 | # Log Integrity Checker 2 | # Glorified modification to make use of latest pprp and python 3.9 :) 3 | # Source from https://github.com/puddly/eac_logsigner/blob/master/eac.py 4 | 5 | import pprp 6 | 7 | 8 | def eac_checksum(text): 9 | # Ignore newlines 10 | text = text.replace('\r', '').replace('\n', '') 11 | 12 | # Fuzzing reveals BOMs are also ignored 13 | text = text.replace('\ufeff', '').replace('\ufffe', '') 14 | 15 | # Setup Rijndael-256 with a 256-bit blocksize 16 | cipher = pprp.crypto.rijndael( 17 | # Probably SHA256('super secret password') but it doesn't actually matter 18 | key=bytes.fromhex('9378716cf13e4265ae55338e940b376184da389e50647726b35f6f341ee3efd9'), 19 | block_size=256 // 8 20 | ) 21 | 22 | # Encode the text as UTF-16-LE 23 | plaintext = text.encode('utf-16-le') 24 | 25 | # The IV is all zeroes so we don't have to handle it 26 | signature = b'\x00' * 32 27 | 28 | # Process it block-by-block 29 | for i in range(0, len(plaintext), 32): 30 | # Zero-pad the last block, if necessary 31 | plaintext_block = plaintext[i:i + 32].ljust(32, b'\x00') 32 | 33 | # CBC mode (XOR the previous ciphertext block into the plaintext) 34 | cbc_plaintext = bytes((ord_or_int(a)) ^ (ord_or_int(b)) for a, b in zip(signature, plaintext_block)) 35 | 36 | # New signature is the ciphertext. 37 | signature = cipher.encrypt(cbc_plaintext) 38 | 39 | raw_signature = bytes(signature, "utf-16-le").hex().upper() 40 | signature = "" 41 | 42 | for i in range(0, len(raw_signature), 4): 43 | signature += raw_signature[i:i + 2] 44 | 45 | # Textual signature is just the hex representation 46 | return signature 47 | 48 | 49 | def ord_or_int(data): 50 | if type(data) is int: 51 | return data 52 | 53 | return ord(data) 54 | 55 | 56 | def extract_info(text): 57 | if '\r\n\r\n==== Log checksum' not in text: 58 | signature = None 59 | else: 60 | text, signature_parts = text.split('\r\n\r\n==== Log checksum', 1) 61 | signature = signature_parts.split()[0].strip() 62 | 63 | return text, signature 64 | 65 | 66 | def eac_verify(text): 67 | # Strip off BOM 68 | if text.startswith('\ufeff'): 69 | text = text[1:] 70 | 71 | # Null bytes screw it up 72 | if '\x00' in text: 73 | text = text[:text.index('\x00')] 74 | 75 | unsigned_text, old_signature = extract_info(text) 76 | return old_signature, eac_checksum(unsigned_text) 77 | 78 | 79 | def check_integrity(text): 80 | text = text.replace('\n', '\r\n') # dunno 81 | old_signature, actual_signature = eac_verify(text) 82 | 83 | if old_signature is None: 84 | return "LOG_CHECKSUM_NOT_PRESENT" 85 | 86 | if old_signature == actual_signature: 87 | return "LOG_OK" 88 | 89 | return "LOG_NOT_OK" 90 | -------------------------------------------------------------------------------- /heybrochecklog/score/modules/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/doujincafe/hbcl/48d2f27746e212d023e72f270f67a06125830451/heybrochecklog/score/modules/__init__.py -------------------------------------------------------------------------------- /heybrochecklog/score/modules/combined.py: -------------------------------------------------------------------------------- 1 | """This module contains the functions which deal with combined logs.""" 2 | 3 | import re 4 | 5 | from heybrochecklog.logfile import LogFile 6 | 7 | 8 | def split_combined(log): 9 | """Split a combined log into an array of logs. If there is a single 10 | log, return a list with one log inside it. Not relevant for XLD. 11 | """ 12 | logs = [] 13 | 14 | # Create a list of indices for combined log markers. By default # includes indices 0 and len() 15 | log_indices = ( 16 | [0] 17 | + [ 18 | i + 2 19 | for i, line in enumerate(log.full_contents) 20 | if re.match(r'-{60}', line) 21 | ] 22 | + [len(log.full_contents)] 23 | ) 24 | 25 | # Split the log files. Create new log object for each log. 26 | for i, line in enumerate(log_indices): 27 | new_log = LogFile( 28 | log.full_contents[line : (log_indices[i + 1])], ripper=log.ripper 29 | ) 30 | logs.append(new_log) 31 | 32 | # Return the array of logs if the end index of section is 33 | # equivalent to the length of the original log. 34 | if log_indices[i + 1] == max(log_indices): 35 | break 36 | 37 | return logs 38 | 39 | 40 | def defragment(logs, eac95=False): 41 | """Re-combine split combined logs.""" 42 | if len(logs) == 1 and not logs[0].htoa: 43 | return logs[0] 44 | 45 | full_contents = [] 46 | for log in logs: 47 | full_contents += log.full_contents 48 | logs[0].full_contents = full_contents 49 | 50 | # Make sure HTOA CRC's match if they exist. 51 | if not eac95: 52 | htoa_logs = [log for log in logs if log.htoa] 53 | if htoa_logs: 54 | analyze_htoa(logs, htoa_logs) 55 | 56 | # Iterate through each log and patch the original log's data where new data exists. 57 | # logs[0] is used as the base log and returned at the end. 58 | for log in logs[1:]: 59 | # Make sure the albums have the same name. 60 | if log.album != logs[0].album: 61 | return logs[0] 62 | 63 | sub_settings(logs, log) 64 | sub_double_copy(logs, log) 65 | if not log.range: 66 | sub_track_errors(logs, log) 67 | 68 | # Remove HTOA detection if it was extracted. 69 | if not eac95: 70 | patch_htoa(logs, htoa_logs) 71 | 72 | if len(logs) > 1: 73 | logs[0].add_deduction('Combined log') 74 | 75 | return logs[0] 76 | 77 | 78 | def sub_settings(logs, log): 79 | """Check settings of newer rip; add new deductions and pop fixed deductions.""" 80 | # Remove the deductions from the first log if they aren't present in the final log, 81 | # but verify the number of tracks is consistent between the two. 82 | for deduction in logs[0].deductions.copy(): 83 | if not log.has_deduction(deduction) and len(log.tracks) == len(logs[0].tracks): 84 | logs[0].remove_deduction(deduction) 85 | # Add additional deductions from the newer log to the older log. 86 | for deduction in log.deductions.copy(): 87 | if not logs[0].has_deduction(deduction): 88 | logs[0].add_deduction(deduction) 89 | 90 | 91 | def sub_double_copy(logs, log): 92 | """Check two copy only rips and score as T&C Rip.""" 93 | if logs[0].has_deduction('Test & Copy') and len(logs[0].tracks) == len(log.tracks): 94 | for new_track, original_track in zip( 95 | log.tracks.values(), logs[0].tracks.values() 96 | ): 97 | if 'copy crc' in new_track and 'copy crc' in original_track: 98 | if new_track['copy crc'] != original_track['copy crc']: 99 | break 100 | else: 101 | logs[0].remove_deduction('Test & Copy') 102 | 103 | 104 | def sub_track_errors(logs, log): 105 | """Substitute newer ripped track data for older ripped track data.""" 106 | for track in log.tracks: 107 | # Don't substitute track errors for aborted copies. 108 | if 'copy crc' in log.tracks[track]: 109 | logs[0].tracks[track] = log.tracks[track] 110 | replace_accumulated_errors(track, logs, log) 111 | replace_crc_mismatches(track, logs, log) 112 | 113 | 114 | def replace_accumulated_errors(track, logs, log): 115 | """Replace accumulated track errors.""" 116 | for error in logs[0].track_errors: 117 | if track in log.track_errors[error]: 118 | continue 119 | for i, original_track in enumerate(logs[0].track_errors[error]): 120 | if track == original_track: 121 | logs[0].track_errors[error].pop(i) 122 | 123 | 124 | def replace_crc_mismatches(track, logs, log): 125 | """Replace CRC mismatch errors.""" 126 | if track not in log.crc_mismatch: 127 | for i, original_track in enumerate(logs[0].crc_mismatch): 128 | if track == original_track: 129 | logs[0].crc_mismatch.pop(i) 130 | 131 | 132 | def analyze_htoa(logs, htoa_logs): 133 | """Analyze potential HTOA rips to and add deductions for CRCs and T&C.""" 134 | # Remove htoa logs from logs list 135 | logs = [log for log in logs if log not in htoa_logs] 136 | 137 | if len(htoa_logs) >= 2: 138 | matches = [ 139 | log 140 | for log in htoa_logs[1:] 141 | if log.tracks[0]['copy crc'] == htoa_logs[0].tracks[0]['copy crc'] 142 | ] 143 | if not matches: 144 | htoa_logs[0].add_deduction('CRC mismatch on HTOA extraction') 145 | elif len(htoa_logs) == 1: 146 | htoa_logs[0].add_deduction('HTOA not ripped twice') 147 | 148 | htoa_logs[0].remove_deduction('Test & Copy') 149 | logs.append(htoa_logs[0]) 150 | 151 | 152 | def patch_htoa(logs, htoa_logs): 153 | """Adjust the HTOA deductions based on the defragmented log.""" 154 | htoa_ripped = any(log for log in htoa_logs if log.htoa_ripped) 155 | 156 | if htoa_ripped and logs[0].has_deduction('HTOA detected'): 157 | logs[0].remove_deduction('HTOA detected not extracted') 158 | 159 | if logs[0].has_deductions('Improper HTOA extraction', 'HTOA extracted'): 160 | logs[0].remove_deduction('HTOA extracted') 161 | -------------------------------------------------------------------------------- /heybrochecklog/score/modules/drives.py: -------------------------------------------------------------------------------- 1 | """This module contains the functions which deal with drives and offsets.""" 2 | 3 | import os 4 | import re 5 | import sqlite3 6 | 7 | from heybrochecklog import UnrecognizedException 8 | from heybrochecklog.shared import get_path 9 | 10 | 11 | def eval_offset(log, offset): 12 | """Validate the offset used by the ripped drive.""" 13 | if not re.match('-?[0-9]+', offset): 14 | raise UnrecognizedException('Could not parse drive offset.') 15 | 16 | if not offset.startswith('-') and offset != '0': 17 | offset = '+' + offset 18 | 19 | if check_for_virtual_drives(log): 20 | log.add_deduction('Virtual drive') 21 | log.flagged = True 22 | return 23 | 24 | drivestr = prep_drive_name(log) 25 | if not drivestr: 26 | return 27 | 28 | results = drive_db_query(drivestr) 29 | if not results: 30 | # Drive not in database 31 | if offset == '0': 32 | log.add_deduction('Zero offset') 33 | log.unindexed_drive = True 34 | return 35 | 36 | offsets = {row[0] for row in results} 37 | if offset not in offsets: 38 | log.add_deduction( 39 | 'Drive offset', 40 | extra_phrase='correct offsets are: {}'.format(', '.join(offsets)), 41 | ) 42 | 43 | 44 | def check_for_virtual_drives(log): 45 | """Check for usage of virtual drives; they aren't good and should be reported.""" 46 | fake_drives = [ 47 | 'Generic DVD-ROM SCSI CdRom Device' 48 | # TODO: Compile a more comprehensive list. 49 | ] 50 | if log.drive in fake_drives: 51 | return True 52 | return False 53 | 54 | 55 | def prep_drive_name(log): 56 | """Prepare the drive name for a DB query.""" 57 | drive = sub_drive_names(log.drive) 58 | drive_words = re.split(r'[^A-Za-z0-9]+', drive) 59 | drivestr = '%" AND Name LIKE "%'.join(drive_words) 60 | 61 | return drivestr 62 | 63 | 64 | def sub_drive_names(drive): 65 | """Perform regex substitution actions on the drive name for better query results.""" 66 | # Replace generic companies with real companies? 67 | drive = re.sub(r'JLMS', 'Lite-ON', drive) 68 | drive = re.sub(r'HL-DT-ST', 'LG Electronics', drive) 69 | drive = re.sub(r'Matshita', 'MATSHITA', drive) 70 | drive = re.sub(r'TSSTcorp(BD|CD|DVD)', r'TSSTcorp \1', drive) 71 | drive = re.sub(r'(\s+-\s|\s+)', ' ', drive) 72 | return drive 73 | 74 | 75 | def drive_db_query(drivestr): 76 | """Query the SQLite3 DB for the drive offset.""" 77 | db_path = os.path.join(get_path(), 'resources', 'drives.db') 78 | conn = sqlite3.connect(db_path) 79 | 80 | cursor = conn.cursor() 81 | cursor.execute('SELECT Offset FROM Drives WHERE Name LIKE "%' + drivestr + '%"') 82 | results = cursor.fetchall() 83 | 84 | conn.close() 85 | 86 | return results 87 | -------------------------------------------------------------------------------- /heybrochecklog/score/modules/parsers.py: -------------------------------------------------------------------------------- 1 | """This module contains functions which parse lines for data.""" 2 | 3 | import re 4 | 5 | from heybrochecklog import UnrecognizedException 6 | from heybrochecklog.resources import VERSIONS 7 | from heybrochecklog.shared import format_pattern as fmt_ptn 8 | 9 | 10 | def index_toc(log): 11 | """Index the ToC data of the log.""" 12 | re_toc = re.compile(r' ([0-9]+) \| [0-9:\.]+ \| [0-9:\.]+ \| ([0-9]+) \| ([0-9]+)') 13 | for line in log.contents[log.index_toc : log.index_tracks]: 14 | result = re_toc.search(line) 15 | if result: 16 | log.toc[int(result.group(1))] = [int(result.group(2)), int(result.group(3))] 17 | 18 | 19 | def get_track_number(log, index, track_word): 20 | """Get the track number from the header line of a track block.""" 21 | result = re.search(r'{} ([0-9]+)'.format(fmt_ptn(track_word)), log.contents[index]) 22 | if result: 23 | return int(result.group(1)) 24 | elif log.range: # EAC range rip has no track number 25 | return 0 26 | else: 27 | raise UnrecognizedException('A track has an invalid block header') 28 | 29 | 30 | def parse_settings(track_data, track_settings, line): 31 | """Loop through and parse the settings used in the rip.""" 32 | for setting, reg in track_settings.items(): 33 | result = reg.match(line) 34 | if result: 35 | track_data[setting] = result.group(1) 36 | 37 | 38 | def parse_accuraterip(log, ar_patterns, line): 39 | """Parse line for an AccurateRip result.""" 40 | for status, re_accurip in ar_patterns: 41 | result = re.search(fmt_ptn(re_accurip), line) 42 | if result and isinstance(result.lastindex, int) and result.lastindex >= 1: 43 | log.accuraterip.append([status, result.group(result.lastindex)]) 44 | elif result and result.lastindex is None: 45 | log.accuraterip.append([status, None]) 46 | 47 | 48 | def parse_range_accuraterip(log, ar_rr_patterns): 49 | """Parse range rip footer for AccurateRip results.""" 50 | for line in log.contents[log.index_footer :]: 51 | parse_accuraterip(log, ar_rr_patterns, line) 52 | 53 | 54 | def parse_errors_eac(log, err_patterns, track_num, line): 55 | """Parse line of an EAC log for a ripping error.""" 56 | for error, re_err in err_patterns: 57 | if track_num not in log.track_errors[error] and re.match( 58 | r' ' + fmt_ptn(re_err), line 59 | ): 60 | log.track_errors[error].append(track_num) 61 | 62 | 63 | def parse_errors_xld(log, err_patterns, track_num, line): 64 | """Parse line of a XLD log for a ripping error.""" 65 | for error, re_err in err_patterns: 66 | if track_num not in log.track_errors[error]: 67 | result = re.search(r' ' + fmt_ptn(re_err) + r' : ([0-9]+)', line) 68 | if result and result.group(1) != "0": 69 | log.track_errors[error].append([track_num, int(result.group(1))]) 70 | 71 | 72 | def parse_checksum(log, regex, imp_version, deduc_line): 73 | """Parse line(s) for presence of a checksum.""" 74 | re_checksum = re.compile(fmt_ptn(regex)) 75 | for line in log.contents[log.index_footer :]: 76 | if re_checksum.match(line): 77 | log.checksum = True 78 | break 79 | else: # If checksum not found 80 | # Compare version numbers to see if Log is older than checksums. 81 | for version in VERSIONS[log.ripper]: 82 | if version[0] == log.version: 83 | log_version = version 84 | if version[0] == imp_version: 85 | imp_version = version 86 | if VERSIONS[log.ripper].index(log_version) <= VERSIONS[log.ripper].index( 87 | imp_version 88 | ): 89 | log.add_deduction('Checksum') 90 | else: 91 | log.add_deduction(deduc_line + ' (no checksum)') 92 | -------------------------------------------------------------------------------- /heybrochecklog/score/modules/validation.py: -------------------------------------------------------------------------------- 1 | """This module contains validation functions for log checking.""" 2 | 3 | from heybrochecklog import UnrecognizedException 4 | 5 | 6 | def analyze_accuraterip(log): 7 | """Analyze the AccurateRip results in the log.""" 8 | if log.accuraterip: 9 | for ar_result in log.accuraterip: 10 | if ( 11 | ar_result[0] != log.accuraterip[0][0] 12 | and (ar_result[1] is not None and log.accuraterip[0][1] is not None) 13 | and (int(ar_result[1]) >= 5 or int(log.accuraterip[0][1]) >= 5) 14 | ): 15 | log.add_deduction('AccurateRip discrepancies') 16 | break 17 | elif any('copy crc' in data for tnum, data in log.tracks.items()): 18 | log.add_deduction('AccurateRip') 19 | 20 | 21 | def check_crc_mismatch(log, track_num, track_data): 22 | """Check a track block for a CRC mismatch.""" 23 | if all(data in track_data for data in ['test crc', 'copy crc']): 24 | if track_data['test crc'] != track_data['copy crc']: 25 | log.crc_mismatch.append(track_num) 26 | 27 | 28 | def validate_track_count(log): 29 | """Verify the presence of all tracks and check for a data track.""" 30 | if not log.range: 31 | # Data tracks have one extra ToC entry, but one less ripped track 32 | if max(log.tracks.keys()) + 1 == max(log.toc.keys()): 33 | log.add_deduction('Data track detected') 34 | elif len(log.tracks) != len(log.toc): 35 | if not log.ripper == 'XLD' or not log.has_deduction('HTOA extracted'): 36 | raise UnrecognizedException('Not all tracks are represented in the log') 37 | 38 | 39 | def validate_track_settings(log, xld=False): 40 | """Also verify that each track contains the required data.""" 41 | if xld: 42 | if log.range: 43 | required_settings = ['copy crc'] 44 | else: 45 | required_settings = ['filename', 'copy crc'] 46 | else: 47 | required_settings = ['filename', 'peak', 'copy crc'] 48 | 49 | for track in log.tracks: 50 | if track in log.track_errors['Aborted copy']: 51 | pass 52 | elif not all(setting in log.tracks[track] for setting in required_settings): 53 | raise UnrecognizedException( 54 | 'Unable to confirm presence of required track data' 55 | ) 56 | 57 | # Check for Test & Copy and CRC Mismatches 58 | if not all('test crc' in track for track in log.tracks.values()): 59 | if log.has_deduction('HTOA extracted') or log.has_deduction( 60 | 'HTOA not ripped twice' 61 | ): 62 | # Verify that every track minus HTOA is T&C (Range based is index 0) 63 | if all('test crc' in track for i, track in log.tracks.items() if i): 64 | return 65 | log.add_deduction('Test & Copy') 66 | -------------------------------------------------------------------------------- /heybrochecklog/shared.py: -------------------------------------------------------------------------------- 1 | """This module contains shared functions between the various top-level modules.""" 2 | 3 | import codecs 4 | import json 5 | import os 6 | 7 | import cchardet 8 | import chardet 9 | 10 | 11 | def get_log_contents(log_file): 12 | """Open a log file and return its contents.""" 13 | encoding = get_log_encoding(log_file) 14 | with log_file.open(encoding=encoding) as log: 15 | contents = log.readlines() 16 | 17 | return contents 18 | 19 | 20 | def detect_chardet(log_data): 21 | cchardet_detection = cchardet.detect(log_data) 22 | chardet_detection = chardet.detect(log_data) 23 | 24 | """In cases chardet spews out Windows-1252 as encoding, switch over to cchardet.""" 25 | if chardet_detection['encoding'] == "Windows-1252": 26 | return cchardet_detection 27 | 28 | """When chardet has higher confidence than cchardet, then we will use chardet.""" 29 | if (chardet_detection['confidence'] or 0) > (cchardet_detection['confidence'] or 0): 30 | return chardet_detection 31 | 32 | return cchardet_detection 33 | 34 | 35 | def get_log_encoding(log_file): 36 | """Get the encoding of the log file with the chardet library.""" 37 | raw = log_file.read_bytes() 38 | if raw.startswith(codecs.BOM_UTF8): 39 | return 'utf-8-sig' 40 | else: 41 | result = detect_chardet(raw) 42 | return result['encoding'] if (result['confidence'] or 0) > 0.7 else 'utf-8-sig' 43 | 44 | 45 | def format_pattern(pattern, append=None): 46 | if append: 47 | pattern = [p + append for p in pattern] 48 | return '|'.join(pattern) 49 | 50 | 51 | def format_pattern_for_setting_evaluation(pattern): 52 | return '(?:{})'.format('|'.join(pattern)) 53 | 54 | 55 | def open_json(*paths): 56 | """Open the language JSON patterns file and return it.""" 57 | basepath = get_path() 58 | with open(os.path.join(basepath, 'resources', *paths)) as jsonfile: 59 | language_data = json.load(jsonfile) 60 | 61 | return language_data 62 | 63 | 64 | def get_path(): 65 | """Get the filepath for the heybrochecklog package directory.""" 66 | return os.path.abspath(os.path.dirname(__file__)) 67 | -------------------------------------------------------------------------------- /heybrochecklog/translate.py: -------------------------------------------------------------------------------- 1 | """ 2 | This module handles the log translation functionality of 3 | the heybrochecklog package 4 | .""" 5 | 6 | import html 7 | import re 8 | from collections import OrderedDict 9 | 10 | from heybrochecklog import UnrecognizedException 11 | from heybrochecklog.analyze import analyze_log 12 | from heybrochecklog.logfile import LogFile 13 | from heybrochecklog.shared import get_log_contents, open_json 14 | 15 | 16 | def translate_log(log_file): 17 | """Initialize and capture all logs.""" 18 | try: 19 | contents = get_log_contents(log_file) 20 | log = LogFile(contents) 21 | return translate_wrapper(log) 22 | except UnicodeDecodeError: 23 | return {'unrecognized': 'Could not decode log'} 24 | 25 | 26 | def translate_log_from_contents(contents): 27 | """Translate a log file given its contents.""" 28 | log = LogFile(contents.split('\n')) 29 | try: 30 | return translate_wrapper(log) 31 | except UnicodeDecodeError: 32 | return {'unrecognized': 'Could not decode log'} 33 | 34 | 35 | def translate_wrapper(log): 36 | """Translate log given log file.""" 37 | try: 38 | analyze_log(log) 39 | except UnrecognizedException as exception: 40 | return { 41 | 'unrecognized': str(exception), 42 | 'log': ''.join([html.escape(line) for line in log.full_contents]), 43 | } 44 | 45 | if log.language == 'english': 46 | return { 47 | 'unrecognized': False, 48 | 'language': 'english', 49 | 'log': ''.join([html.escape(line) for line in log.full_contents]), 50 | } 51 | 52 | return sub_english(log) 53 | 54 | 55 | def sub_english(log): 56 | """Translate the log file and return a dict of info and log.""" 57 | english = open_json('eac', 'english.json')['translation'] 58 | foreign = open_json('eac', '{}.json'.format(log.language))['translation'] 59 | 60 | # Sort foreign lines from longest to shortest 61 | foreign = OrderedDict( 62 | sorted(foreign.items(), key=lambda t: len(t[1][0]), reverse=True) 63 | ) 64 | 65 | # Compile all the regex now instead of repeating. 66 | for key, value in foreign.items(): 67 | for i, v in enumerate(value): 68 | value[i] = re.escape(v) 69 | foreign[key] = re.compile('|'.join(value), flags=re.IGNORECASE) 70 | 71 | # Iterate through each line and find/replace each string. 72 | new_log = [] 73 | for line in log.full_contents: 74 | if not line: # No use wasting time here. 75 | new_log.append('') 76 | else: 77 | for key, regex in foreign.items(): 78 | if regex.search(line): 79 | for value in english[key]: 80 | line = regex.sub(value, line) 81 | new_log.append(line) 82 | 83 | re_space_settings(new_log) 84 | new_log = ''.join(new_log) 85 | 86 | return { 87 | 'unrecognized': False, 88 | 'language': log.language, 89 | 'log': html.escape(new_log), 90 | } 91 | 92 | 93 | def re_space_settings(log): 94 | """Fix the spacing in the rip settings block.""" 95 | spacings = [ 96 | 24, 97 | 44, 98 | 32, 99 | ] # Number of characters before colons in each block of settings. 100 | end_of_blocks = [ 101 | 'Make use of C2 pointers', 102 | 'Gap handling', 103 | ] # Last setting in blocks. 104 | index = 0 105 | 106 | for i, line in enumerate(log): 107 | if re.match('Used drive', line): 108 | continue # Ignore that line 109 | 110 | result = re.search(r'^([A-Z][A-Za-z0-9- ]+[a-z]) +:(.*)$', line) 111 | if result: 112 | word = result.group(1) 113 | spaces = spacings[index] - len(word) 114 | log[i] = word + ' ' * spaces + ':' + result.group(2) + '\n' 115 | 116 | if word in end_of_blocks: 117 | index += 1 118 | 119 | if re.match('TOC', line): # No need to continue after settings are done. 120 | return 121 | -------------------------------------------------------------------------------- /pyproject.toml: -------------------------------------------------------------------------------- 1 | [tool.poetry] 2 | name = "heybrochecklog" 3 | version = "1.4.6" 4 | description = "A python tool for evaluating and working with EAC/XLD rip logs." 5 | authors = ["lights "] 6 | license = "Apache-2.0" 7 | readme = "README.md" 8 | repository = "https://github.com/ligh7s/hey-bro-check-log" 9 | keywords = ["logchecker", "eac", "xld"] 10 | include = [ 11 | "heybrochecklog/resources/*", 12 | "heybrochecklog/resources/eac/*", 13 | "heybrochecklog/resources/eac95/*", 14 | ] 15 | 16 | [tool.poetry.scripts] 17 | heybrochecklog = 'heybrochecklog.__main__:runner' 18 | 19 | [tool.poetry.dependencies] 20 | python = "^3.10" 21 | faust-cchardet = "^2.1.19" 22 | chardet = "^5.1.0" 23 | pprp = "^0.2.7" 24 | 25 | [tool.poetry.dev-dependencies] 26 | pytest = "^7.2.0" 27 | 28 | [tool.black] 29 | line-length = 88 30 | target-version = ['py310'] 31 | skip-string-normalization = true 32 | 33 | [build-system] 34 | requires = ["poetry>=0.12"] 35 | build-backend = "poetry.masonry.api" 36 | -------------------------------------------------------------------------------- /scripts/accuraterip_offsets.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | """This script scrapes the AccurateRip offsets page and fills the drive offsests 4 | database with information. 5 | """ 6 | 7 | import os 8 | import re 9 | import sqlite3 10 | import sys 11 | 12 | import requests 13 | 14 | 15 | def main(): 16 | """Call the rest of the functions--create db, scrape the text and send text to 17 | regex function. 18 | """ 19 | create_db() 20 | text_ = scrape() 21 | process_scrape(text_) 22 | 23 | 24 | def scrape(): 25 | """Scrapes the AR page.""" 26 | url = 'http://www.accuraterip.com/driveoffsets.htm' 27 | response = requests.get(url) 28 | return response.text 29 | 30 | 31 | def process_scrape(text_): 32 | """Process the scrape and send offset values to add to database function.""" 33 | regex = re.compile(r'\s+' 34 | r'(.*)\s+' 35 | r'' 36 | r'(.*)') 37 | for match in regex.finditer(text_): 38 | if 'Purged' not in match.group(2): 39 | add_to_db(match.group(1), match.group(2)) 40 | 41 | 42 | def add_to_db(name, offset): 43 | """Adds an offset to the database.""" 44 | query('INSERT INTO Drives (Name, Offset) VALUES (?, ?)', (name, offset)) 45 | print('Added drive: {} (Offset: {}).'.format(name, offset)) 46 | 47 | 48 | def create_db(): 49 | """Create the database.""" 50 | query(""" 51 | CREATE TABLE Drives ( 52 | DriveID INTEGER NOT NULL PRIMARY KEY, 53 | Name TEXT NOT NULL, 54 | Offset TEXT NOT NULL 55 | ) 56 | """) 57 | 58 | 59 | def query(string, args=None): 60 | """Send a query to the DB.""" 61 | path = os.path.join(sys.path[0], 'drives.db') 62 | conn = sqlite3.connect(path) 63 | cursor = conn.cursor() 64 | 65 | if args: 66 | cursor.execute(string, args) 67 | else: 68 | cursor.execute(string) 69 | 70 | conn.commit() 71 | conn.close() 72 | 73 | 74 | if __name__ == '__main__': 75 | main() 76 | -------------------------------------------------------------------------------- /scripts/eac95_builder/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/doujincafe/hbcl/48d2f27746e212d023e72f270f67a06125830451/scripts/eac95_builder/__init__.py -------------------------------------------------------------------------------- /scripts/eac95_builder/constants.py: -------------------------------------------------------------------------------- 1 | """The constants used in translation.""" 2 | 3 | LINENUMBERS = [ 4 | 1, 2, 5, 6, 7, 10, 11, 12, 15, 16, 31, 50, 51, 52, 1200, 1203, 1204, 1210, 5 | 1211, 1212, 1213, 1214, 1215, 1216, 1217, 1218, 1219, 1220, 1221, 1222, 6 | 1223, 1224, 1225, 1226, 1227, 1228, 1229, 1230, 1232, 1233, 1234, 1235, 7 | 1236, 1237, 1238, 1239, 1240, 1241, 1242, 1243, 1244, 1245, 1246, 1247, 8 | 1248, 1249, 1250, 1251, 1252, 1253, 1254, 1255, 1256, 1257, 1258, 1259, 9 | 1260, 1261, 1262, 1263, 1264, 1265, 1266, 1267, 1268, 1269, 1270, 1271, 10 | 1272, 1273, 1274, 2501, 4270, 4271, 4272, 81700, 81701, 81702, 81703, 11 | 81704, 81705, 81706, 81707, 81708, 81709, 81710, 81711, 81712, 81713, 12 | 81714, 81715, 81716, 81717, 81718, 81719, 81720 13 | ] 14 | 15 | SAMPLEPATTERN = { 16 | 'drive': None, 17 | 'settings': { 18 | 'Read mode': None, 19 | 'C2 pointers': None, 20 | 'Accurate stream': None, 21 | 'Audio cache': None, 22 | 'Drive offset': 1256 23 | }, 24 | 'full line settings': { 25 | 'Fill missing offset samples with silence': 1264, 26 | 'Deleting silent blocks': 1265 27 | }, 28 | 'bad settings': { 29 | 'Normalization': 1266, 30 | 'Compression offset': 1262, 31 | 'Combined offset': 1255 32 | }, 33 | 'proper settings': { 34 | 'Fill missing offset samples with silence': 15, 35 | 'Deleting silent blocks': 16 36 | }, 37 | 'range': 1210, 38 | 'track': 1226, 39 | 'track settings': { 40 | 'filename': 1269, 41 | 'pregap': 1270, 42 | 'peak': 1217, 43 | 'test crc': 1271, 44 | 'copy crc': None 45 | }, 46 | 'track errors': { 47 | 'Aborted copy': 1228, 48 | 'Timing problem': 1212, 49 | 'Missing samples': 1214, 50 | 'Suspicious position': 1213 51 | }, 52 | 'footer': 1225, 53 | } 54 | -------------------------------------------------------------------------------- /scripts/eac95_builder/generators.py: -------------------------------------------------------------------------------- 1 | """ 2 | This module contains the functions which generate the lines that get placed 3 | in the JSON. 4 | """ 5 | 6 | import re # eeeeeeeeeeeeeeeeeeeee 7 | 8 | 9 | def substitute_translations(patterns, translation): 10 | """Substitute the translated strings in for their string IDs.""" 11 | for key, value in patterns.items(): 12 | if isinstance(value, int): 13 | patterns[key] = remove_colon(translation[value]) 14 | elif isinstance(value, dict): 15 | for sub_key, sub_value in patterns[key].items(): 16 | if isinstance(sub_value, int): 17 | patterns[key][sub_key] = remove_colon(translation[sub_value]) 18 | 19 | 20 | def remove_colon(string): 21 | """Remove the trailing colon from some lines.""" 22 | string = string.strip() 23 | string = re.sub(r'\s*(?::|:)\s*', '', string) 24 | return string 25 | 26 | 27 | def regex_the_drive(translation): 28 | """Regex out `Used drive` string from the translation json.""" 29 | drive_string = translation[1233] 30 | used_drive = remove_colon(drive_string) 31 | used_drive = re.sub('drive', '[Dd]rive', used_drive) 32 | return used_drive 33 | 34 | 35 | def ninety_five_settings(patterns, translation): 36 | """Populate patterns dict with EAC95 settings.""" 37 | # This is going to be messy, with no guarantee of success. 38 | perf_line = translation[1254] # The line with optimal settings. 39 | 40 | # Remove `Secure` from string. 41 | secure, perf_line = perf_line.split(' ', 1) 42 | 43 | # Split the rest of the line by commas. 44 | rest_of_line = [',' + stri for stri in perf_line.split(',')] 45 | rest_of_line[0] = rest_of_line[0].lstrip(',') 46 | 47 | if len(rest_of_line) != 3: # We're looking for two commas here. 48 | print('Error: ({}) Failed to split EAC95 line. Please fill out manually.' 49 | .format(translation[1])) 50 | return 51 | 52 | # Assign the split variables to the patterns dict. 53 | patterns['settings']['Read mode'] = secure 54 | patterns['settings']['C2 pointers'] = rest_of_line[0] 55 | patterns['settings']['Accurate stream'] = rest_of_line[1] 56 | patterns['settings']['Audio cache'] = rest_of_line[2] 57 | 58 | 59 | def copy_crc_substitution(patterns, translation): 60 | """Generate the HTOA line, Copy CRC line.""" 61 | copycrc = translation[1272] 62 | crc = translation[1219] 63 | patterns['track settings']['copy crc'] = '(?:{}|{})'.format(copycrc, crc) 64 | 65 | 66 | def regex_out_paren(line): 67 | """Regex the comma. Quality docstring.""" 68 | return re.sub(r'\(', r'\(', line) 69 | -------------------------------------------------------------------------------- /scripts/eac95_builder/to_json.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | """ 4 | This script takes one or more EAC language files and converts it 5 | into a JSON for the log checker. The resultant .json is named after 6 | the first argument. 7 | """ 8 | 9 | import codecs 10 | import json 11 | import os 12 | import re 13 | import sys 14 | from copy import deepcopy 15 | from pathlib import Path 16 | 17 | import chardet 18 | 19 | import constants 20 | import generators 21 | 22 | 23 | def main(): 24 | """The main function for the module; handles calling the other functions.""" 25 | language_info = [] 26 | filenames = sys.argv[1:] 27 | file_contents = read_files(filenames) 28 | for file_content in file_contents: 29 | info = {} 30 | info['patterns'] = deepcopy(constants.SAMPLEPATTERN) 31 | info['translation'] = {} 32 | for number, line in regex_the_line(file_content): 33 | info['translation'][number] = line 34 | compile_patterns(info) 35 | language_info.append(info) 36 | language_info = defragment(language_info) 37 | dump_json(language_info) 38 | 39 | 40 | def read_files(paths): 41 | """Reads the file and returns a list of the file's contents.""" 42 | file_contents = list() 43 | for path in paths: 44 | file_ = Path(path) 45 | if not file_.is_file(): 46 | print(path, 'does not exist! Exiting.') 47 | exit() 48 | 49 | raw = file_.read_bytes() 50 | encoding = chardet.detect(raw)['encoding'] 51 | if encoding not in ['UTF-16' or 'iso-8859-1']: 52 | encoding = 'iso-8859-1' 53 | 54 | try: 55 | with open(path, 'r', encoding=encoding) as source_file: 56 | file_content = source_file.readlines() 57 | except UnicodeDecodeError: 58 | print('Error decoding', path) 59 | exit() 60 | 61 | file_contents.append(file_content) 62 | 63 | return file_contents 64 | 65 | 66 | def regex_the_line(file_contents): 67 | """Extracts the line number and text from the language file, 68 | and returns a (#, line) tuple.""" 69 | for line in file_contents: 70 | result = re.search(r'(\d+)\s=>?\s"(.*)"', line) 71 | if result: 72 | number, text = int(result.group(1)), result.group(2).strip() 73 | if number in constants.LINENUMBERS: 74 | yield (number, text) 75 | 76 | 77 | def defragment(language_info): 78 | real_info = language_info.pop(0) 79 | for key, val in real_info['patterns'].items(): 80 | if isinstance(val, dict): 81 | for subkey, subval in val.items(): 82 | if isinstance(subval, str): 83 | real_info['patterns'][key][subkey] = [subval] 84 | elif isinstance(val, str): 85 | real_info['patterns'][key] = [val] 86 | for num, line in real_info['translation'].items(): 87 | real_info['translation'][num] = [line] 88 | 89 | for info in language_info: 90 | real_info['patterns'] = defrag_patterns(real_info['patterns'], info['patterns']) 91 | for num, line in info['translation'].items(): 92 | if line not in real_info['translation'][num]: 93 | real_info['translation'][num].append(line) 94 | 95 | return real_info 96 | 97 | 98 | def defrag_patterns(real_patterns, new_patterns): 99 | for key, val in new_patterns.items(): 100 | if isinstance(val, str): 101 | if val not in real_patterns[key]: 102 | real_patterns[key].append(val) 103 | elif isinstance(val, dict): 104 | for subkey, subval in val.items(): 105 | if subval not in real_patterns[key][subkey]: 106 | real_patterns[key][subkey].append(subval) 107 | 108 | return real_patterns 109 | 110 | 111 | def dump_json(language_info): 112 | """Dump the language file to a JSON.""" 113 | input_filename = os.path.basename(sys.argv[1]) 114 | export_filename = re.sub(r'\..+', '', input_filename).lower() 115 | file_path = os.path.dirname(os.path.realpath(__file__)) 116 | export_filepath = os.path.join(file_path, '{}.json'.format(export_filename)) 117 | if os.path.exists(export_filepath): 118 | print('{} already exists, JSON dump canceled.'.format(export_filepath)) 119 | else: 120 | json_dump = json.dumps(language_info, ensure_ascii=False, indent=4) 121 | json_dump = re.sub(r'\[\s+(".+")\s+\]', r'[\1]', json_dump, flags=re.MULTILINE) 122 | with codecs.open(export_filepath, 'w', encoding='utf-8') as jsonfile: 123 | jsonfile.write(json_dump) 124 | 125 | 126 | def compile_patterns(language_info): 127 | """Compile the patterns dict for the language.""" 128 | translation = language_info['translation'] 129 | generators.substitute_translations(language_info['patterns'], translation) 130 | language_info['patterns']['drive'] = generators.regex_the_drive(translation) 131 | generators.ninety_five_settings(language_info['patterns'], translation) 132 | generators.copy_crc_substitution(language_info['patterns'], translation) 133 | 134 | 135 | if __name__ == '__main__': 136 | main() 137 | -------------------------------------------------------------------------------- /scripts/eac_builder/constants.py: -------------------------------------------------------------------------------- 1 | """The constants used in translation.""" 2 | 3 | LINENUMBERS = [ 4 | 1, 5 | 2, 6 | 5, 7 | 6, 8 | 7, 9 | 8, 10 | 10, 11 | 11, 12 | 12, 13 | 15, 14 | 16, 15 | 31, 16 | 50, 17 | 51, 18 | 52, 19 | 1200, 20 | 1203, 21 | 1204, 22 | 1210, 23 | 1211, 24 | 1212, 25 | 1213, 26 | 1214, 27 | 1215, 28 | 1216, 29 | 1217, 30 | 1218, 31 | 1219, 32 | 1220, 33 | 1221, 34 | 1222, 35 | 1223, 36 | 1224, 37 | 1225, 38 | 1226, 39 | 1227, 40 | 1228, 41 | 1229, 42 | 1230, 43 | 1232, 44 | 1233, 45 | 1234, 46 | 1235, 47 | 1236, 48 | 1237, 49 | 1238, 50 | 1239, 51 | 1240, 52 | 1241, 53 | 1242, 54 | 1243, 55 | 1244, 56 | 1245, 57 | 1246, 58 | 1247, 59 | 1248, 60 | 1249, 61 | 1250, 62 | 1251, 63 | 1252, 64 | 1253, 65 | 1254, 66 | 1255, 67 | 1256, 68 | 1257, 69 | 1258, 70 | 1259, 71 | 1260, 72 | 1261, 73 | 1262, 74 | 1263, 75 | 1264, 76 | 1265, 77 | 1266, 78 | 1267, 79 | 1268, 80 | 1269, 81 | 1270, 82 | 1271, 83 | 1272, 84 | 1273, 85 | 1274, 86 | 1275, 87 | 1276, 88 | 1277, 89 | 1278, 90 | 1279, 91 | 1280, 92 | 1281, 93 | 1282, 94 | 1283, 95 | 1284, 96 | 1285, 97 | 1286, 98 | 1287, 99 | 1288, 100 | 1289, 101 | 1290, 102 | 1291, 103 | 1292, 104 | 1293, 105 | 1294, 106 | 1295, 107 | 1296, 108 | 1297, 109 | 1298, 110 | 1299, 111 | 1305, 112 | 1306, 113 | 1307, 114 | 1308, 115 | 1309, 116 | 1310, 117 | 1320, 118 | 1321, 119 | 1322, 120 | 1323, 121 | 1324, 122 | 1325, 123 | 1328, 124 | 1329, 125 | 1330, 126 | 1331, 127 | 1332, 128 | 1333, 129 | 1334, 130 | 1335, 131 | 1336, 132 | 1337, 133 | 1338, 134 | 1339, 135 | 1340, 136 | 1341, 137 | 1342, 138 | 1343, 139 | 1344, 140 | 2501, 141 | 4270, 142 | 4271, 143 | 4272, 144 | 81700, 145 | 81701, 146 | 81702, 147 | 81703, 148 | 81704, 149 | 81705, 150 | 81706, 151 | 81707, 152 | 81708, 153 | 81709, 154 | 81710, 155 | 81711, 156 | 81712, 157 | 81713, 158 | 81714, 159 | 81715, 160 | 81716, 161 | 81717, 162 | 81718, 163 | 81719, 164 | 81720, 165 | ] 166 | 167 | SAMPLEPATTERN = { 168 | 'drive': None, 169 | 'settings': { 170 | 'Read mode': 1234, 171 | 'Accurate stream': 1297, 172 | 'Audio cache': 1298, 173 | 'C2 pointers': 1296, 174 | 'Drive offset': 1256, 175 | 'Fill missing offset samples with silence': 1264, 176 | 'Deleting silent blocks': 1265, 177 | 'Null samples': 1338, 178 | 'Gap handling': 1320, 179 | 'ID3 tags': 1309, 180 | }, 181 | 'bad settings': { 182 | 'Normalization': 1266, 183 | 'Compression offset': 1262, 184 | 'Combined offset': 1255, 185 | }, 186 | 'proper settings': { 187 | 'Read mode': 1295, 188 | 'Accurate stream': 15, 189 | 'Audio cache': 15, 190 | 'C2 pointers': 16, 191 | 'Fill missing offset samples with silence': 15, 192 | 'Deleting silent blocks': 16, 193 | 'Null samples': 15, 194 | 'Gap handling': 1322, 195 | 'ID3 tags': 16, 196 | }, 197 | 'toc': 1289, 198 | 'range': 1210, 199 | 'htoa': None, 200 | 'track': 1226, 201 | 'track settings': { 202 | 'filename': 1269, 203 | 'pregap': 1270, 204 | 'peak': 1217, 205 | 'test crc': 1271, 206 | 'copy crc': None, 207 | }, 208 | 'track errors': { 209 | 'Aborted copy': 1228, 210 | 'Timing problem': 1212, 211 | 'Missing samples': 1214, 212 | 'Suspicious position': 1213, 213 | }, 214 | 'accuraterip': { 215 | 'match': 1281, 216 | 'no match': 1330, 217 | 'bad match': 1282, 218 | 'no result': 1283, 219 | 'not ripped': 1280, 220 | }, 221 | 'range accuraterip': {'match': None, 'no match': None, 'no result': None}, 222 | 'footer': 1225, 223 | 'checksum': None, 224 | } 225 | -------------------------------------------------------------------------------- /scripts/eac_builder/generators.py: -------------------------------------------------------------------------------- 1 | """This module contains the functions which generate the lines that get placed in the JSON.""" 2 | 3 | import re # eeeeeeeeeeeeeeeeeeeee 4 | 5 | 6 | def substitute_translations(patterns, translation): 7 | """Substitute the translated strings in for their string IDs.""" 8 | for key, value in patterns.items(): 9 | if isinstance(value, int): 10 | patterns[key] = remove_colon(translation[value]) 11 | elif isinstance(value, dict): 12 | for sub_key, sub_value in patterns[key].items(): 13 | if isinstance(sub_value, int): 14 | patterns[key][sub_key] = remove_colon(translation[sub_value]) 15 | 16 | 17 | def remove_colon(string): 18 | """Remove the trailing colon from some lines.""" 19 | string = string.strip() 20 | string = re.sub(r'\s*(?::|:)\s*', '', string) 21 | return string 22 | 23 | 24 | def regex_the_drive(translation): 25 | """Regex out `Used drive` string from the translation json.""" 26 | drive_string = translation[1233] 27 | used_drive = remove_colon(drive_string) 28 | used_drive = re.sub('drive', '[Dd]rive', used_drive) 29 | return used_drive 30 | 31 | 32 | def htoa_crc_checksum_substitution(patterns, translation): 33 | """Generate the HTOA line, Copy CRC line.""" 34 | sel_range = translation[1211] 35 | sectors = translation[1287] 36 | copycrc = translation[1272] 37 | crc = translation[1219] 38 | checksum = translation[1325] if 1325 in translation else 'Log checksum' 39 | 40 | patterns['htoa'] = r'{} \({} 0-([0-9]+)\)'.format(sel_range, sectors) 41 | patterns['track settings']['copy crc'] = '(?:{}|{})'.format(copycrc, crc) 42 | patterns['checksum'] = '==== ' + checksum + ' [A-Z0-9]{64} ====' 43 | 44 | 45 | def accuraterip(patterns, translation): 46 | """Append the numbers regex to the AccurateRip lines.""" 47 | # Escape parentheses. 48 | for key, value in patterns['accuraterip'].items(): 49 | patterns['accuraterip'][key] = regex_out_paren(value) 50 | 51 | # Append confidence regex to AR 52 | confidence_regex = r' ([0-9]+)\) \[[A-Z0-9]{8}\]' 53 | patterns['accuraterip']['match'] += confidence_regex 54 | patterns['accuraterip']['no match'] += ' \\' + translation[1332] + confidence_regex 55 | patterns['accuraterip']['bad match'] += confidence_regex 56 | 57 | 58 | def range_accuraterip(patterns, translation): 59 | """Generate the lines for range rip AccurateRip.""" 60 | confidence_regex = r'([0-9]+)\) \[[A-Z0-9]{8}]' 61 | track = regex_out_paren(translation[1226]) 62 | accurate = regex_out_paren(translation[1277]) 63 | not_accurate = regex_out_paren(translation[1278]) 64 | not_present = regex_out_paren(translation[1279]) 65 | 66 | patterns['range accuraterip']['match'] = '{} [0-9]+ {} {}'.format(track, accurate, 67 | confidence_regex) 68 | patterns['range accuraterip']['no match'] = '{} [0-9]+ {} {}'.format(track, not_accurate, 69 | confidence_regex) 70 | patterns['range accuraterip']['no result'] = '{} [0-9]+ {}'.format(track, not_present) 71 | 72 | 73 | def regex_out_paren(line): 74 | """Regex the comma. Quality docstring.""" 75 | return re.sub(r'\(', r'\(', line) 76 | -------------------------------------------------------------------------------- /scripts/eac_builder/to_json.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | """ 4 | This script takes one or more EAC language files and converts it 5 | into a JSON for the log checker. The resultant .json is named after 6 | the first argument. 7 | """ 8 | 9 | import codecs 10 | import json 11 | import os 12 | import re 13 | import sys 14 | from pathlib import Path 15 | 16 | import chardet 17 | 18 | import constants 19 | import generators 20 | 21 | 22 | def main(): 23 | """The main function for the module; handles calling the other functions.""" 24 | language_info = [] 25 | filenames = sys.argv[1:] 26 | file_contents = read_files(filenames) 27 | for file_content in file_contents: 28 | info = {} 29 | info['patterns'] = constants.SAMPLEPATTERN 30 | info['translation'] = {} 31 | for number, line in regex_the_line(file_content): 32 | info['translation'][number] = line 33 | compile_patterns(info) 34 | language_info.append(info) 35 | language_info = defragment(language_info) 36 | dump_json(language_info) 37 | 38 | 39 | def read_files(paths): 40 | """Reads the file and returns a list of the file's contents.""" 41 | file_contents = list() 42 | for path in paths: 43 | file_ = Path(path) 44 | if not file_.is_file(): 45 | print(path, 'does not exist! Exiting.') 46 | exit() 47 | 48 | raw = file_.read_bytes() 49 | encoding = chardet.detect(raw)['encoding'] 50 | if encoding not in ['UTF-16' or 'iso-8859-1']: 51 | encoding = 'iso-8859-1' 52 | 53 | try: 54 | with open(path, 'r', encoding=encoding) as source_file: 55 | file_content = source_file.readlines() 56 | except UnicodeDecodeError: 57 | print('Error decoding', path) 58 | exit() 59 | 60 | file_contents.append(file_content) 61 | 62 | return file_contents 63 | 64 | 65 | def regex_the_line(file_contents): 66 | """Extracts the line number and text from the language file, 67 | and returns a (#, line) tuple.""" 68 | for line in file_contents: 69 | result = re.search(r'(\d+)\s=>?\s"(.*)"', line) 70 | if result: 71 | number, text = int(result.group(1)), result.group(2).strip() 72 | if number in constants.LINENUMBERS: 73 | yield (number, text) 74 | 75 | 76 | def defragment(language_info): 77 | real_info = language_info[0] 78 | for key, val in real_info['patterns'].items(): 79 | if isinstance(val, dict): 80 | for subkey, subval in val.items(): 81 | if isinstance(subval, str): 82 | real_info['patterns'][key][subkey] = [subval] 83 | elif isinstance(val, str): 84 | real_info['patterns'][key] = [val] 85 | for num, line in real_info['translation'].items(): 86 | real_info['translation'][num] = [line] 87 | 88 | if len(language_info) > 1: 89 | for info in language_info[1:]: 90 | real_info['patterns'] = defrag_patterns(real_info['patterns'], info['patterns']) 91 | for num, line in info['translation'].items(): 92 | if line not in real_info['translation'][num]: 93 | real_info['translation'][num].append(line) 94 | 95 | return real_info 96 | 97 | 98 | def defrag_patterns(real_patterns, new_patterns): 99 | for key, val in new_patterns.items(): 100 | if isinstance(val, str): 101 | if val not in real_patterns[key]: 102 | real_patterns[key].append(val) 103 | elif isinstance(val, dict): 104 | for subkey, subval in val.items(): 105 | if subval not in real_patterns[key][subkey]: 106 | real_patterns[key][subkey].append(subval) 107 | 108 | return real_patterns 109 | 110 | 111 | def dump_json(language_info): 112 | """Dump the language file to a JSON.""" 113 | input_filename = os.path.basename(sys.argv[1]) 114 | export_filename = re.sub(r'\..+', '', input_filename).lower() 115 | file_path = os.path.dirname(os.path.realpath(__file__)) 116 | export_filepath = os.path.join(file_path, '{}.json'.format(export_filename)) 117 | if os.path.exists(export_filepath): 118 | print('{} already exists, JSON dump canceled.'.format(export_filepath)) 119 | else: 120 | json_dump = json.dumps(language_info, ensure_ascii=False, indent=4) 121 | json_dump = re.sub(r'\[\s+(".+")\s+\]', r'[\1]', json_dump, flags=re.MULTILINE) 122 | with codecs.open(export_filepath, 'w', encoding='utf-8') as jsonfile: 123 | jsonfile.write(json_dump) 124 | 125 | 126 | def compile_patterns(language_info): 127 | """Compile the patterns dict for the language.""" 128 | translation = language_info['translation'] 129 | generators.substitute_translations(language_info['patterns'], translation) 130 | language_info['patterns']['drive'] = generators.regex_the_drive(translation) 131 | generators.htoa_crc_checksum_substitution(language_info['patterns'], translation) 132 | generators.accuraterip(language_info['patterns'], translation) 133 | generators.range_accuraterip(language_info['patterns'], translation) 134 | 135 | 136 | if __name__ == '__main__': 137 | main() 138 | -------------------------------------------------------------------------------- /scripts/generate_marked_up_test_log.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | import sys 4 | from os import path 5 | from pathlib import Path 6 | 7 | from heybrochecklog.score import score_log 8 | 9 | for log_path in sys.argv[1:]: 10 | log_file = Path(log_path) 11 | if not log_file.is_file(): 12 | print('{} does not exist.'.format(log_path)) 13 | continue 14 | 15 | log = score_log(log_file, markup=True) 16 | dir_, file_name = path.split(log_path) 17 | output_path = path.join(dir_, 'markup', file_name + '.markup') 18 | 19 | with open(output_path, 'w') as output_file: 20 | output_file.write(log['contents']) 21 | 22 | print('Wrote marked up log to {}.'.format(output_path)) 23 | -------------------------------------------------------------------------------- /setup.cfg: -------------------------------------------------------------------------------- 1 | [flake8] 2 | max-line-length: 88 3 | exclude = resources 4 | ignore = E203 W503 5 | 6 | [isort] 7 | not_skip = __init__.py 8 | line_length = 79 9 | include_trailing_comma = true 10 | wrap_length = 1 11 | multi_line_output = 3 12 | -------------------------------------------------------------------------------- /setup.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | # DO NOT EDIT THIS FILE! 4 | # This file has been autogenerated by dephell <3 5 | # https://github.com/dephell/dephell 6 | 7 | # dephell made a fucking duplicate .rst README... 8 | 9 | try: 10 | from setuptools import setup 11 | except ImportError: 12 | from distutils.core import setup 13 | 14 | import os.path 15 | 16 | readme = '' 17 | here = os.path.abspath(os.path.dirname(__file__)) 18 | readme_path = os.path.join(here, 'README.md') 19 | if os.path.exists(readme_path): 20 | with open(readme_path, 'rb') as stream: 21 | readme = stream.read().decode('utf8') 22 | 23 | setup( 24 | long_description=readme, 25 | long_description_content_type='text/markdown', 26 | name='heybrochecklog', 27 | version='1.3.3', 28 | description='A python tool for evaluating and working with EAC/XLD rip logs.', 29 | python_requires='==3.*,>=3.5.0', 30 | project_urls={"repository": "https://github.com/ligh7s/hey-bro-check-log"}, 31 | author='lights', 32 | author_email='lights@tutanota.de', 33 | license='Apache-2.0', 34 | keywords='logchecker eac xld', 35 | entry_points={ 36 | "console_scripts": ["heybrochecklog = heybrochecklog.__main__:runner"] 37 | }, 38 | packages=[ 39 | 'heybrochecklog', 'heybrochecklog.markup', 'heybrochecklog.resources', 40 | 'heybrochecklog.score', 'heybrochecklog.score.modules', 41 | 'scripts.eac95_builder' 42 | ], 43 | package_dir={"": "."}, 44 | package_data={ 45 | "heybrochecklog.resources": [ 46 | "*.db", "*.json", "eac/*.json", "eac95/*.json" 47 | ] 48 | }, 49 | install_requires=['cchardet>=2.1.7'], 50 | extras_require={"dev": ["pytest==5.*,>=5.3.5"]}, 51 | ) 52 | -------------------------------------------------------------------------------- /tests/eac95_test.py: -------------------------------------------------------------------------------- 1 | import os 2 | from pathlib import Path 3 | 4 | import pytest 5 | from heybrochecklog.score import score_log 6 | 7 | """Lazy person not going to do full unit testing.""" 8 | 9 | LOGS = [ 10 | ( 11 | 'had-decoding-issues.log', 12 | { 13 | 'EAC 0.95 log or older (-30 points)', 14 | 'EAC <1.0 (no checksum)', 15 | 'Gaps were not analyzed and appended (-10 points)', 16 | }, 17 | ), 18 | ( 19 | 'also-bad.log', 20 | { 21 | 'Combined read/write offset cannot be verified (-5 points)', 22 | 'Test & Copy was not used (-20 points)', 23 | 'EAC 0.95 log or older (-30 points)', 24 | 'EAC <1.0 (no checksum)', 25 | 'Gaps were not analyzed and appended (-10 points)', 26 | }, 27 | ), 28 | ( 29 | 'bad-settings.log', 30 | { 31 | 'Combined read/write offset cannot be verified (-5 points)', 32 | 'C2 pointers were used (-20 points)', 33 | 'EAC 0.95 log or older (-30 points)', 34 | 'EAC <1.0 (no checksum)', 35 | 'Gaps were not analyzed and appended (-10 points)', 36 | }, 37 | ), 38 | ( 39 | 'read-mode.log', 40 | { 41 | 'Audio cache not defeated (-10 points)', 42 | 'EAC 0.95 log or older (-30 points)', 43 | 'EAC <1.0 (no checksum)', 44 | 'Gaps were not analyzed and appended (-10 points)', 45 | }, 46 | ), 47 | ( 48 | 'burst.log', 49 | { 50 | 'The drive could not be found in the database; however, an offset of 0 is rarely correct (-5 points)', # noqa E501 51 | 'Read mode was not secure (-20 points)', 52 | 'C2 pointers were used (-20 points)', 53 | 'Accurate stream was not used (-20 points)', 54 | 'Audio cache not defeated (-10 points)', 55 | 'Test & Copy was not used (-20 points)', 56 | 'EAC 0.95 log or older (-30 points)', 57 | 'EAC <1.0 (no checksum)', 58 | 'Gaps were not analyzed and appended (-10 points)', 59 | }, 60 | ), 61 | ] 62 | 63 | 64 | @pytest.mark.parametrize('filename, deductions', LOGS) 65 | def test_scoring(filename, deductions): 66 | log_path = os.path.join(os.path.dirname(__file__), 'logs', 'EAC95', filename) 67 | log_file = Path(log_path) 68 | log = score_log(log_file) 69 | assert deductions == {d[0] for d in log['deductions']} 70 | 71 | 72 | @pytest.mark.parametrize('filename', [log_tuple[0] for log_tuple in LOGS]) 73 | def test_markup(filename): 74 | log_path = os.path.join(os.path.dirname(__file__), 'logs', 'EAC95', filename) 75 | log_file = Path(log_path) 76 | log = score_log(log_file, markup=True) 77 | 78 | markup_path = os.path.join( 79 | os.path.dirname(__file__), 80 | 'logs', 81 | 'EAC95', 82 | 'markup', 83 | '{}.markup'.format(filename), 84 | ) 85 | with open(markup_path, 'r') as markup_file: 86 | markup_contents = markup_file.read() 87 | 88 | assert log['contents'] == markup_contents 89 | -------------------------------------------------------------------------------- /tests/eac_test.py: -------------------------------------------------------------------------------- 1 | import os 2 | from pathlib import Path 3 | 4 | import pytest 5 | from heybrochecklog.score import score_log 6 | 7 | LOGS = [ 8 | ( 9 | 'mac-roman-charset.log', 10 | { 11 | 'Audio cache not defeated (-10 points)', 12 | 'Null samples were not used in CRC calculations (-1 points)', 13 | 'Gaps were not analyzed and appended (-10 points)', 14 | 'Could not verify presence of ID3 tags', 15 | 'No checksum (-15 points)' 16 | } 17 | ), 18 | ('perf-hunid.log', set()), 19 | ('1.3-good.log', set()), 20 | ('abort.log', {'Combined log'}), 21 | ( 22 | 'badcombo.log', 23 | {'Gaps were not analyzed and appended (-10 points)', 'Combined log'}, 24 | ), 25 | ('eac-99-good.log', {'EAC <1.0 (no checksum)'}), 26 | ( 27 | 'hella-aborted.log', 28 | { 29 | 'Audio cache not defeated (-10 points)', 30 | 'Gaps were not analyzed and appended (-10 points)', 31 | 'Could not verify usage of null samples', 32 | 'EAC <1.0 (no checksum)', 33 | 'Could not verify presence of ID3 tags', 34 | 'Combined log', 35 | 'Test & Copy was not used (-20 points)', 36 | }, 37 | ), 38 | ( 39 | 'bad-htoa.log', 40 | { 41 | 'Could not verify presence of ID3 tags', 42 | 'HTOA was improperly extracted (-10 points)', 43 | 'HTOA was not ripped twice (-10 points)', 44 | 'Combined log', 45 | }, 46 | ), 47 | ( 48 | 'range-rip.log', 49 | {'Could not verify gap handling', 'Range rip detected (-20 points)'}, 50 | ), 51 | ( 52 | 'htoa-not-ripped-twice.log', 53 | {'HTOA extracted', 'HTOA was not ripped twice (-10 points)'}, 54 | ), 55 | ( 56 | 'shitty.log', 57 | { 58 | 'Suspicious position (3 occurrences) (-60 points)', 59 | 'CRC mismatch (3 occurrences) (-90 points)', 60 | }, 61 | ), 62 | ( 63 | 'inconsistent-accuraterip.log', 64 | {'AccurateRip discrepancies; rip may contain silent errors'}, 65 | ), 66 | ('negative-offset.log', {'EAC <1.0 (no checksum)'}), 67 | ('data-track.log', {'EAC <1.0 (no checksum)', 'Data track detected'}), 68 | ('burst.log', {'Read mode was not secure (-20 points)', 'EAC <1.0 (no checksum)'}), 69 | ( 70 | 'swedish-timing-problems.log', 71 | { 72 | 'Read mode was not secure (-20 points)', 73 | 'No checksum (-15 points)', 74 | 'Timing problem (-20 points)', 75 | 'CRC mismatch (3 occurrences) (-90 points)', 76 | }, 77 | ), 78 | ( 79 | 'bad-russian-099.log', 80 | { 81 | 'Audio cache not defeated (-10 points)', 82 | 'Combined read/write offset cannot be verified (-5 points)', 83 | 'Null samples were not used in CRC calculations (-1 points)', 84 | 'AccurateRip was not enabled (-5 points)', 85 | 'EAC <1.0 (no checksum)', 86 | 'Test & Copy was not used (-20 points)', 87 | }, 88 | ), 89 | ( 90 | 'fast.log', 91 | { 92 | 'Read mode was not secure (-20 points)', 93 | 'Could not verify gap handling', 94 | 'Could not verify presence of ID3 tags', 95 | 'Range rip detected (-20 points)', 96 | 'AccurateRip was not enabled (-5 points)', 97 | 'No checksum (-15 points)', 98 | 'Test & Copy was not used (-20 points)', 99 | }, 100 | ), 101 | ( 102 | 'spanish-log-extra-colons.log', 103 | { 104 | 'Audio cache not defeated (-10 points)', 105 | 'Gaps were not analyzed and appended (-10 points)', 106 | 'No checksum (-15 points)', 107 | 'Test & Copy was not used (-20 points)', 108 | }, 109 | ), 110 | ( 111 | 'russian-range-rip-ar-issue.log', 112 | { 113 | 'Could not verify gap handling', 114 | 'Range rip detected (-20 points)', 115 | 'EAC <1.0 (no checksum)', 116 | 'Test & Copy was not used (-20 points)', 117 | }, 118 | ), 119 | ( 120 | 'russian1.log', 121 | { 122 | 'Could not verify gap handling', 123 | 'Range rip detected (-20 points)' 124 | } 125 | ), 126 | ( 127 | 'russian2.log', 128 | { 129 | 'Could not verify gap handling', 130 | 'Range rip detected (-20 points)', 131 | 'AccurateRip was not enabled (-5 points)' 132 | } 133 | ), 134 | ( 135 | 'russian3.log', 136 | { 137 | 'Could not verify gap handling', 138 | 'Range rip detected (-20 points)' 139 | } 140 | ), 141 | ( 142 | 'russian4.log', 143 | { 144 | 'Could not verify gap handling', 145 | 'Range rip detected (-20 points)' 146 | } 147 | ) 148 | ] 149 | 150 | 151 | @pytest.mark.parametrize('filename, deductions', LOGS) 152 | def test_scoring(filename, deductions): 153 | log_path = os.path.join(os.path.dirname(__file__), 'logs', 'EAC', filename) 154 | log_file = Path(log_path) 155 | log = score_log(log_file) 156 | assert deductions == {d[0] for d in log['deductions']} 157 | 158 | 159 | @pytest.mark.parametrize('filename', [log_tuple[0] for log_tuple in LOGS]) 160 | def test_markup(filename): 161 | log_path = os.path.join(os.path.dirname(__file__), 'logs', 'EAC', filename) 162 | log_file = Path(log_path) 163 | log = score_log(log_file, markup=True) 164 | 165 | markup_path = os.path.join( 166 | os.path.dirname(__file__), 'logs', 'EAC', 'markup', '{}.markup'.format(filename) 167 | ) 168 | with open(markup_path, 'r') as markup_file: 169 | markup_contents = markup_file.read() 170 | 171 | assert log['contents'] == markup_contents 172 | -------------------------------------------------------------------------------- /tests/logs/EAC/1.3-good.log: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/doujincafe/hbcl/48d2f27746e212d023e72f270f67a06125830451/tests/logs/EAC/1.3-good.log -------------------------------------------------------------------------------- /tests/logs/EAC/bad-russian-099.log: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/doujincafe/hbcl/48d2f27746e212d023e72f270f67a06125830451/tests/logs/EAC/bad-russian-099.log -------------------------------------------------------------------------------- /tests/logs/EAC/eac-99-good.log: -------------------------------------------------------------------------------- 1 | Exact Audio Copy V0.99 prebeta 5 from 4. May 2009 2 | 3 | EAC extraction logfile from 15. May 2009, 22:21 4 | 5 | Above & Beyond / Far From In Love 6 | 7 | Used drive : Optiarc DVD RW AD-7191A Adapter: 1 ID: 1 8 | 9 | Read mode : Secure 10 | Utilize accurate stream : Yes 11 | Defeat audio cache : Yes 12 | Make use of C2 pointers : No 13 | 14 | Read offset correction : 6 15 | Overread into Lead-In and Lead-Out : No 16 | Fill up missing offset samples with silence : Yes 17 | Delete leading and trailing silent blocks : No 18 | Null samples used in CRC calculations : Yes 19 | Used interface : Installed external ASPI interface 20 | Gap handling : Appended to previous track 21 | 22 | Used output format : User Defined Encoder 23 | Selected bitrate : 128 kBit/s 24 | Quality : High 25 | Add ID3 tag : No 26 | Command line compressor : C:\Program Files\Exact Audio Copy\Flac\flac.exe 27 | Additional command line options : -8 -V -T "ARTIST=%a" -T "TITLE=%t" -T "ALBUM=%g" -T "DATE=%y" -T "TRACKNUMBER=%n" -T "GENRE=%m" -T "COMMENT=ripped by Leontiou" %s 28 | 29 | 30 | TOC of the extracted CD 31 | 32 | Track | Start | Length | Start sector | End sector 33 | --------------------------------------------------------- 34 | 1 | 0:00.00 | 7:20.28 | 0 | 33027 35 | 2 | 7:20.28 | 8:14.72 | 33028 | 70149 36 | 3 | 15:35.25 | 10:02.07 | 70150 | 115306 37 | 4 | 25:37.32 | 6:49.34 | 115307 | 146015 38 | 5 | 32:26.66 | 5:27.49 | 146016 | 170589 39 | 40 | 41 | Track 1 42 | 43 | Filename G:\Music\01. Far From In Love [original mix].wav 44 | 45 | Pre-gap length 0:00:02.00 46 | 47 | Peak level 99.9 % 48 | Track quality 100.0 % 49 | Test CRC 0DDFDEF3 50 | Copy CRC 0DDFDEF3 51 | Track not present in AccurateRip database 52 | Copy OK 53 | 54 | Track 2 55 | 56 | Filename G:\Music\02. Far From In Love [san francisco mix].wav 57 | 58 | Pre-gap length 0:00:02.00 59 | 60 | Peak level 98.8 % 61 | Track quality 100.0 % 62 | Test CRC EE2A86D2 63 | Copy CRC EE2A86D2 64 | Track not present in AccurateRip database 65 | Copy OK 66 | 67 | Track 3 68 | 69 | Filename G:\Music\03. Far From In Love [shane54 on spec remix].wav 70 | 71 | Pre-gap length 0:00:02.00 72 | 73 | Peak level 99.7 % 74 | Track quality 100.0 % 75 | Test CRC 9493C6AF 76 | Copy CRC 9493C6AF 77 | Track not present in AccurateRip database 78 | Copy OK 79 | 80 | Track 4 81 | 82 | Filename G:\Music\04. Far From In Love [airbase remix].wav 83 | 84 | Pre-gap length 0:00:02.00 85 | 86 | Peak level 99.7 % 87 | Track quality 99.9 % 88 | Test CRC D6E0F8AE 89 | Copy CRC D6E0F8AE 90 | Track not present in AccurateRip database 91 | Copy OK 92 | 93 | Track 5 94 | 95 | Filename G:\Music\05. Far From In Love [complexz remix].wav 96 | 97 | Pre-gap length 0:00:02.00 98 | 99 | Peak level 99.7 % 100 | Track quality 100.0 % 101 | Test CRC 5B05B9F5 102 | Copy CRC 5B05B9F5 103 | Track not present in AccurateRip database 104 | Copy OK 105 | 106 | 107 | None of the tracks are present in the AccurateRip database 108 | 109 | No errors occurred 110 | 111 | End of status report 112 | -------------------------------------------------------------------------------- /tests/logs/EAC/fast.log: -------------------------------------------------------------------------------- 1 | Exact Audio Copy V1.0 beta 3 from 29. August 2011 2 | 3 | EAC extraction logfile from 31. August 2014, 9:42 4 | 5 | Genesis / Abacab [19313-2 800044-2] 6 | 7 | Used drive : HL-DT-STBD-RE WH14NS40 Adapter: 3 ID: 0 8 | 9 | Read mode : Fast 10 | 11 | Read offset correction : 6 12 | Overread into Lead-In and Lead-Out : No 13 | Fill up missing offset samples with silence : Yes 14 | Delete leading and trailing silent blocks : No 15 | Null samples used in CRC calculations : Yes 16 | Used interface : Native Win32 interface for Win NT & 2000 17 | 18 | Used output format : Internal WAV Routines 19 | Sample format : 44.100 Hz; 16 Bit; Stereo 20 | 21 | 22 | TOC of the extracted CD 23 | 24 | Track | Start | Length | Start sector | End sector 25 | --------------------------------------------------------- 26 | 1 | 0:00.37 | 6:58.70 | 37 | 31456 27 | 2 | 6:59.32 | 4:39.23 | 31457 | 52404 28 | 3 | 11:38.55 | 5:59.62 | 52405 | 79391 29 | 4 | 17:38.42 | 4:31.25 | 79392 | 99741 30 | 5 | 22:09.67 | 7:29.43 | 99742 | 133459 31 | 6 | 29:39.35 | 3:24.52 | 133460 | 148811 32 | 7 | 33:04.12 | 4:25.13 | 148812 | 168699 33 | 8 | 37:29.25 | 4:52.52 | 168700 | 190651 34 | 9 | 42:22.02 | 4:21.63 | 190652 | 210289 35 | 36 | 37 | Range status and errors 38 | 39 | Selected range 40 | 41 | Filename C:\EAC\Genesis - Abacab [19313-2 800044-2]\Genesis - Abacab [19313-2 800044-2].wav 42 | 43 | Peak level 100.0 % 44 | Extraction speed 5.5 X 45 | Copy CRC A4C47653 46 | Copy OK 47 | 48 | No errors occurred 49 | 50 | AccurateRip summary 51 | Track 1 cannot be verified as accurate (confidence 23) [68C1C10C], AccurateRip returned [42B8A10C] (AR v2) 52 | Track 2 cannot be verified as accurate (confidence 22) [C0181E28], AccurateRip returned [9A24A648] (AR v2) 53 | Track 3 cannot be verified as accurate (confidence 22) [5C0A99E8], AccurateRip returned [AFAF005C] (AR v2) 54 | Track 4 cannot be verified as accurate (confidence 21) [6C1A7CE6], AccurateRip returned [F1085052] (AR v2) 55 | Track 5 cannot be verified as accurate (confidence 20) [C6FB5E67], AccurateRip returned [ED9EB427] (AR v2) 56 | Track 6 cannot be verified as accurate (confidence 20) [1200A9FB], AccurateRip returned [022E57DB] (AR v2) 57 | Track 7 cannot be verified as accurate (confidence 19) [55E9D57F], AccurateRip returned [79DAD723] (AR v2) 58 | Track 8 cannot be verified as accurate (confidence 19) [3E2AF80F], AccurateRip returned [450721D5] (AR v2) 59 | Track 9 cannot be verified as accurate (confidence 21) [369B26AF], AccurateRip returned [8515378B] (AR v2) 60 | No tracks could be verified as accurate 61 | You may have a different pressing from the one(s) in the database 62 | 63 | End of status report 64 | -------------------------------------------------------------------------------- /tests/logs/EAC/htoa-not-ripped-twice.log: -------------------------------------------------------------------------------- 1 | Exact Audio Copy V1.3 from 2. September 2016 2 | 3 | EAC extraction logfile from 9. April 2017, 15:43 4 | 5 | Arcade Fire / Reflektor 6 | 7 | Used Drive : ASUS DRW-24B1ST a Adapter: 1 ID: 0 8 | 9 | Read mode : Secure 10 | Utilize accurate stream : Yes 11 | Defeat audio cache : Yes 12 | Make use of C2 pointers : No 13 | 14 | Read offset correction : 6 15 | Overread into Lead-In and Lead-Out : No 16 | Fill up missing offset samples with silence : Yes 17 | Delete leading and trailing silent blocks : No 18 | Null samples used in CRC calculations : Yes 19 | Used interface : Native Win32 interface for Win NT & 2000 20 | 21 | Used output format : User Defined Encoder 22 | Selected bitrate : 1024 kBit/s 23 | Quality : High 24 | Add ID3 tag : No 25 | Command line compressor : C:\Program Files (x86)\Exact Audio Copy\Flac\flac.exe 26 | Additional command line options : -8 -V -T "ARTIST=%artist%" -T "TITLE=%title%" -T "ALBUM=%albumtitle%" -T 27 | "DATE=%year%" -T "TRACKNUMBER=%tracknr%" -T "GENRE=%genre%" -T "PERFORMER=%albuminterpret%" -T "COMPOSER=%composer%" %haslyrics%--tag-from-file=LYRICS="%lyricsfile%"%haslyrics% -T "ALBUMARTIST=%albumartist%" -T "DISCNUMBER=%cdnumber%" -T "TOTALDISCS=%totalcds%" -T "TOTALTRACKS=%numtracks%" -T "COMMENT=%comment%" %source% -o %dest% 28 | 29 | 30 | TOC of the extracted CD 31 | 32 | Track | Start | Length | Start sector | End sector 33 | --------------------------------------------------------- 34 | 1 | 10:02.00 | 7:33.71 | 45150 | 79195 35 | 2 | 17:35.71 | 5:43.59 | 79196 | 104979 36 | 3 | 23:19.55 | 2:42.15 | 104980 | 117144 37 | 4 | 26:01.70 | 6:30.61 | 117145 | 146455 38 | 5 | 32:32.56 | 4:22.27 | 146456 | 166132 39 | 6 | 36:55.08 | 3:59.05 | 166133 | 184062 40 | 7 | 40:54.13 | 5:28.39 | 184063 | 208701 41 | 42 | 43 | Range status and errors 44 | 45 | Selected range (Sectors 0-45149) 46 | 47 | Filename C:\Users\thomas\Desktop\Arcade Fire - Reflektor (MRG485B) [FLAC]\Vol. 1\00 - Untitled.wav 48 | 49 | Peak level 14.9 % 50 | Extraction speed 1.7 X 51 | Range quality 99.9 % 52 | Copy CRC 255229CD 53 | Copy OK 54 | 55 | No errors occurred 56 | 57 | 58 | AccurateRip summary 59 | 60 | 61 | 62 | No tracks could be verified as accurate 63 | 64 | End of status report 65 | 66 | ==== Log checksum F679AD2B4CC812E305ADBE5E015246D3FEB36D44FD57F1E143FDE317AD070555 ==== 67 | -------------------------------------------------------------------------------- /tests/logs/EAC/inconsistent-accuraterip.log: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/doujincafe/hbcl/48d2f27746e212d023e72f270f67a06125830451/tests/logs/EAC/inconsistent-accuraterip.log -------------------------------------------------------------------------------- /tests/logs/EAC/mac-roman-charset.log: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/doujincafe/hbcl/48d2f27746e212d023e72f270f67a06125830451/tests/logs/EAC/mac-roman-charset.log -------------------------------------------------------------------------------- /tests/logs/EAC/markup/fast.log.markup: -------------------------------------------------------------------------------- 1 | Exact Audio Copy V1.0 beta 3 from 29. August 2011 2 | 3 | EAC extraction logfile from 31. August 2014, 9:42 4 | 5 | Genesis / Abacab [19313-2 800044-2] 6 | 7 | Used drive : HL-DT-STBD-RE WH14NS40 Adapter: 3 ID: 0 (not found in database) 8 | 9 | Read mode : Fast 10 | 11 | Read offset correction : 6 12 | Overread into Lead-In and Lead-Out : No 13 | Fill up missing offset samples with silence : Yes 14 | Delete leading and trailing silent blocks : No 15 | Null samples used in CRC calculations : Yes 16 | Used interface : Native Win32 interface for Win NT & 2000 17 | 18 | Used output format : Internal WAV Routines 19 | Sample format : 44.100 Hz; 16 Bit; Stereo 20 | 21 | 22 | TOC of the extracted CD 23 | 24 | Track | Start | Length | Start sector | End sector 25 | --------------------------------------------------------- 26 | 1 | 0:00.37 | 6:58.70 | 37 | 31456 27 | 2 | 6:59.32 | 4:39.23 | 31457 | 52404 28 | 3 | 11:38.55 | 5:59.62 | 52405 | 79391 29 | 4 | 17:38.42 | 4:31.25 | 79392 | 99741 30 | 5 | 22:09.67 | 7:29.43 | 99742 | 133459 31 | 6 | 29:39.35 | 3:24.52 | 133460 | 148811 32 | 7 | 33:04.12 | 4:25.13 | 148812 | 168699 33 | 8 | 37:29.25 | 4:52.52 | 168700 | 190651 34 | 9 | 42:22.02 | 4:21.63 | 190652 | 210289 35 | 36 | 37 | Range status and errors 38 | 39 | Selected range 40 | 41 | Filename C:\EAC\Genesis - Abacab [19313-2 800044-2]\Genesis - Abacab [19313-2 800044-2].wav 42 | 43 | Peak level 100.0 % 44 | Extraction speed 5.5 X 45 | Copy CRC A4C47653 46 | Copy OK 47 | 48 | No errors occurred 49 | 50 | AccurateRip summary 51 | Track 1 cannot be verified as accurate (confidence 23) [68C1C10C], AccurateRip returned [42B8A10C] (AR v2) 52 | Track 2 cannot be verified as accurate (confidence 22) [C0181E28], AccurateRip returned [9A24A648] (AR v2) 53 | Track 3 cannot be verified as accurate (confidence 22) [5C0A99E8], AccurateRip returned [AFAF005C] (AR v2) 54 | Track 4 cannot be verified as accurate (confidence 21) [6C1A7CE6], AccurateRip returned [F1085052] (AR v2) 55 | Track 5 cannot be verified as accurate (confidence 20) [C6FB5E67], AccurateRip returned [ED9EB427] (AR v2) 56 | Track 6 cannot be verified as accurate (confidence 20) [1200A9FB], AccurateRip returned [022E57DB] (AR v2) 57 | Track 7 cannot be verified as accurate (confidence 19) [55E9D57F], AccurateRip returned [79DAD723] (AR v2) 58 | Track 8 cannot be verified as accurate (confidence 19) [3E2AF80F], AccurateRip returned [450721D5] (AR v2) 59 | Track 9 cannot be verified as accurate (confidence 21) [369B26AF], AccurateRip returned [8515378B] (AR v2) 60 | No tracks could be verified as accurate 61 | You may have a different pressing from the one(s) in the database 62 | 63 | End of status report 64 | -------------------------------------------------------------------------------- /tests/logs/EAC/markup/htoa-not-ripped-twice.log.markup: -------------------------------------------------------------------------------- 1 | Exact Audio Copy V1.3 from 2. September 2016 2 | 3 | EAC extraction logfile from 9. April 2017, 15:43 4 | 5 | Arcade Fire / Reflektor 6 | 7 | Used Drive : ASUS DRW-24B1ST a Adapter: 1 ID: 0 8 | 9 | Read mode : Secure 10 | Utilize accurate stream : Yes 11 | Defeat audio cache : Yes 12 | Make use of C2 pointers : No 13 | 14 | Read offset correction : 6 15 | Overread into Lead-In and Lead-Out : No 16 | Fill up missing offset samples with silence : Yes 17 | Delete leading and trailing silent blocks : No 18 | Null samples used in CRC calculations : Yes 19 | Used interface : Native Win32 interface for Win NT & 2000 20 | 21 | Used output format : User Defined Encoder 22 | Selected bitrate : 1024 kBit/s 23 | Quality : High 24 | Add ID3 tag : No 25 | Command line compressor : C:\Program Files (x86)\Exact Audio Copy\Flac\flac.exe 26 | Additional command line options : -8 -V -T "ARTIST=%artist%" -T "TITLE=%title%" -T "ALBUM=%albumtitle%" -T 27 | "DATE=%year%" -T "TRACKNUMBER=%tracknr%" -T "GENRE=%genre%" -T "PERFORMER=%albuminterpret%" -T "COMPOSER=%composer%" %haslyrics%--tag-from-file=LYRICS="%lyricsfile%"%haslyrics% -T "ALBUMARTIST=%albumartist%" -T "DISCNUMBER=%cdnumber%" -T "TOTALDISCS=%totalcds%" -T "TOTALTRACKS=%numtracks%" -T "COMMENT=%comment%" %source% -o %dest% 28 | 29 | 30 | TOC of the extracted CD 31 | 32 | Track | Start | Length | Start sector | End sector 33 | --------------------------------------------------------- 34 | 1 | 10:02.00 | 7:33.71 | 45150 | 79195 35 | 2 | 17:35.71 | 5:43.59 | 79196 | 104979 36 | 3 | 23:19.55 | 2:42.15 | 104980 | 117144 37 | 4 | 26:01.70 | 6:30.61 | 117145 | 146455 38 | 5 | 32:32.56 | 4:22.27 | 146456 | 166132 39 | 6 | 36:55.08 | 3:59.05 | 166133 | 184062 40 | 7 | 40:54.13 | 5:28.39 | 184063 | 208701 41 | 42 | 43 | Range status and errors 44 | 45 | Selected range (Sectors 0-45149) 46 | 47 | Filename C:\Users\thomas\Desktop\Arcade Fire - Reflektor (MRG485B) [FLAC]\Vol. 1\00 - Untitled.wav 48 | 49 | Peak level 14.9 % 50 | Extraction speed 1.7 X 51 | Range quality 99.9 % 52 | Copy CRC 255229CD 53 | Copy OK 54 | 55 | No errors occurred 56 | 57 | 58 | AccurateRip summary 59 | 60 | 61 | 62 | No tracks could be verified as accurate 63 | 64 | End of status report 65 | 66 | ==== Log checksum F679AD2B4CC812E305ADBE5E015246D3FEB36D44FD57F1E143FDE317AD070555 ==== 67 | -------------------------------------------------------------------------------- /tests/logs/EAC/markup/russian4.log.markup: -------------------------------------------------------------------------------- 1 | Exact Audio Copy V1.0 beta 3 from 29. August 2011 2 | 3 | Отчёт EAC об извлечении, выполненном 21. января 2012, 17:51 4 | 5 | Asia (2) / Aura 6 | 7 | Дисковод: TSSTcorpCDDVDW TS-L633J Adapter: 0 ID: 1 8 | 9 | Режим чтения : Достоверность 10 | Использование точного потока : Да 11 | Отключение кэша аудио : Да 12 | Использование указателей C2 : Нет 13 | 14 | Коррекция смещения при чтении : 6 15 | Способность читать области Lead-in и Lead-out : Нет 16 | Заполнение пропущенных сэмплов тишиной : Да 17 | Удаление блоков с тишиной в начале и конце : Нет 18 | При вычислениях CRC использовались нулевые сэмплы : Да 19 | Интерфейс : Установленный внешний ASPI-интерфейс 20 | 21 | Выходной формат : Пользовательский кодировщик 22 | Выбранный битрейт : 128 kBit/s 23 | Качество : Высокий 24 | Добавление ID3-тега : Нет 25 | Утилита сжатия : C:\Program Files\Exact Audio Copy\FLAC\FLAC.EXE 26 | Дополнительные параметры : -6 -V -T "ARTIST=%artist%" -T "TITLE=%title%" -T "ALBUM=%albumtitle%" -T "DATE=%year%" -T "TRACKNUMBER=%tracknr%" -T "GENRE=%genre%" -T "COMMENT=%comment%" -T "BAND=%albuminterpret%" -T "ALBUMARTIST=%albuminterpret%" -T "COMPOSER=%composer%" %haslyrics%--tag-from-file=LYRICS="%lyricsfile%"%haslyrics% -T "DISCNUMBER=%cdnumber%" -T "TOTALDISCS=%totalcds%" -T "TOTALTRACKS=%numtracks%" %hascover%--picture="%coverfile%"%hascover% %source% -o %dest% 27 | 28 | 29 | TOC извлечённого CD 30 | 31 | Трек | Старт | Длительность | Начальный сектор | Конечный сектор 32 | --------------------------------------------------------------------- 33 | 1 | 0:00.00 | 14:00.38 | 0 | 63037 34 | 35 | 36 | Характеристики диапазона извлечения и сообщения об ошибках 37 | 38 | Выбранный диапазон 39 | 40 | Имя файла C:\ASIA AURA\CD2\Asia (2) - Aura.wav 41 | 42 | Пиковый уровень 78.0 % 43 | Скорость извлечения 2.1 X 44 | Качество диапазона 100.0 % 45 | CRC теста EF1BBBE7 46 | CRC копии EF1BBBE7 47 | Копирование... OK 48 | 49 | Ошибок не произошло 50 | 51 | 52 | AccurateRip: сводка 53 | 54 | Трек 1 : извлечено точно (доверие 3) [970DAEC4] (AR v2) 55 | 56 | Все треки извлечены точно 57 | 58 | Конец отчёта 59 | 60 | ---- CUETools DB Plugin V2.1.3 61 | 62 | [CTDB TOCID: GPTQXaktW53iiPsU5kxCzjIyT00-] disk not present in database, Submit result: GPTQXaktW53iiPsU5kxCzjIyT00- has been uploaded 63 | 64 | 65 | ==== Контрольная сумма отчёта 7E505BB4BA325A35D5D1A55C2BCF98BAD5B8AF0CB8EE7EC8B9875A757668A60A ==== 66 | -------------------------------------------------------------------------------- /tests/logs/EAC/perf-hunid.log: -------------------------------------------------------------------------------- 1 | Exact Audio Copy V1.1 from 23. June 2015 2 | 3 | EAC extraction logfile from 15. March 2018, 19:05 4 | 5 | Alice / CHOICE 6 | 7 | Used drive : ASUS SBC-06D2X-U Adapter: 1 ID: 2 8 | 9 | Read mode : Secure 10 | Utilize accurate stream : Yes 11 | Defeat audio cache : Yes 12 | Make use of C2 pointers : No 13 | 14 | Read offset correction : 667 15 | Overread into Lead-In and Lead-Out : No 16 | Fill up missing offset samples with silence : Yes 17 | Delete leading and trailing silent blocks : No 18 | Null samples used in CRC calculations : Yes 19 | Used interface : Native Win32 interface for Win NT & 2000 20 | Gap handling : Appended to previous track 21 | 22 | Used output format : User Defined Encoder 23 | Selected bitrate : 1024 kBit/s 24 | Quality : High 25 | Add ID3 tag : No 26 | Command line compressor : C:\Program Files (x86)\Exact Audio Copy\Flac\flac.exe 27 | Additional command line options : -8 -V -T "ARTIST=%artist%" -T "TITLE=%title%" -T "ALBUM=%albumtitle%" -T "DATE=%year%" -T "TRACKNUMBER=%tracknr%" -T "GENRE=%genre%" -T "PERFORMER=%albuminterpret%" -T "COMPOSER=%composer%" %haslyrics%--tag-from-file=LYRICS="%lyricsfile%"%haslyrics% -T "ALBUMARTIST=%albumartist%" -T "DISCNUMBER=%cdnumber%" -T "TOTALDISCS=%totalcds%" -T "TOTALTRACKS=%numtracks%" -T "COMMENT=%comment%" %source% -o %dest% 28 | 29 | 30 | TOC of the extracted CD 31 | 32 | Track | Start | Length | Start sector | End sector 33 | --------------------------------------------------------- 34 | 1 | 0:00.00 | 5:16.35 | 0 | 23734 35 | 2 | 5:16.35 | 2:57.14 | 23735 | 37023 36 | 3 | 8:13.49 | 4:26.71 | 37024 | 57044 37 | 38 | 39 | Track 1 40 | 41 | Filename C:\EAC rips\01. CHOICE.wav 42 | 43 | Pre-gap length 0:00:02.00 44 | 45 | Peak level 100.0 % 46 | Extraction speed 2.8 X 47 | Track quality 100.0 % 48 | Test CRC 9B6CDC62 49 | Copy CRC 9B6CDC62 50 | Track not present in AccurateRip database 51 | Copy OK 52 | 53 | Track 2 54 | 55 | Filename C:\EAC rips\02. Can't Wait.wav 56 | 57 | Pre-gap length 0:00:02.00 58 | 59 | Peak level 100.0 % 60 | Extraction speed 2.9 X 61 | Track quality 100.0 % 62 | Test CRC 0CAB6AA7 63 | Copy CRC 0CAB6AA7 64 | Track not present in AccurateRip database 65 | Copy OK 66 | 67 | Track 3 68 | 69 | Filename C:\EAC rips\03. Clock.wav 70 | 71 | Pre-gap length 0:00:02.00 72 | 73 | Peak level 100.0 % 74 | Extraction speed 2.9 X 75 | Track quality 99.9 % 76 | Test CRC 1896E620 77 | Copy CRC 1896E620 78 | Track not present in AccurateRip database 79 | Copy OK 80 | 81 | 82 | None of the tracks are present in the AccurateRip database 83 | 84 | No errors occurred 85 | 86 | End of status report 87 | 88 | ---- CUETools DB Plugin V2.1.6 89 | 90 | [CTDB TOCID: cljPK5E11RHTwep_jXNr7GNVxhA-] disk not present in database 91 | Submit result: cljPK5E11RHTwep_jXNr7GNVxhA- has been uploaded 92 | 93 | 94 | ==== Log checksum 1AD3B8CE83AC8573CB7354EFF39310F97C325EBE47EAD7E226C3FB1E2960551E ==== -------------------------------------------------------------------------------- /tests/logs/EAC/range-rip.log: -------------------------------------------------------------------------------- 1 | Exact Audio Copy V1.0 beta 3 from 29. August 2011 2 | 3 | EAC extraction logfile from 15. February 2013, 19:20 4 | 5 | ABBA / Waterloo 6 | 7 | Used drive : Optiarc BD RW BD-5300S Adapter: 3 ID: 0 8 | 9 | Read mode : Secure 10 | Utilize accurate stream : Yes 11 | Defeat audio cache : Yes 12 | Make use of C2 pointers : No 13 | 14 | Read offset correction : 6 15 | Overread into Lead-In and Lead-Out : No 16 | Fill up missing offset samples with silence : Yes 17 | Delete leading and trailing silent blocks : No 18 | Null samples used in CRC calculations : Yes 19 | Used interface : Installed external ASPI interface 20 | 21 | Used output format : User Defined Encoder 22 | Selected bitrate : 1024 kBit/s 23 | Quality : High 24 | Add ID3 tag : No 25 | Command line compressor : C:\Program Files (x86)\Exact Audio Copy\Flac\flac.exe 26 | Additional command line options : -8 -V -T "Date=%year%" -T "Genre=%genre%" -T "COMMENT=ripped by 27 | bvstudio®" %source% 28 | 29 | 30 | TOC of the extracted CD 31 | 32 | Track | Start | Length | Start sector | End sector 33 | --------------------------------------------------------- 34 | 1 | 0:00.33 | 2:44.25 | 33 | 12357 35 | 2 | 2:44.58 | 3:36.62 | 12358 | 28619 36 | 3 | 6:21.45 | 3:11.25 | 28620 | 42969 37 | 4 | 9:32.70 | 3:09.13 | 42970 | 57157 38 | 5 | 12:42.08 | 3:13.12 | 57158 | 71644 39 | 6 | 15:55.20 | 3:12.50 | 71645 | 86094 40 | 7 | 19:07.70 | 2:55.38 | 86095 | 99257 41 | 8 | 22:03.33 | 2:55.37 | 99258 | 112419 42 | 9 | 24:58.70 | 3:48.13 | 112420 | 129532 43 | 10 | 28:47.08 | 3:41.00 | 129533 | 146107 44 | 11 | 32:28.08 | 3:10.25 | 146108 | 160382 45 | 46 | 47 | Range status and errors 48 | 49 | Selected range 50 | 51 | Filename F:\ABBA®\1974 - Waterloo (1990 - Polydor - 843 643-2)\ABBA - Waterloo.wav 52 | 53 | Peak level 97.7 % 54 | Extraction speed 2.8 X 55 | Range quality 99.9 % 56 | Test CRC 4199FFCA 57 | Copy CRC 4199FFCA 58 | Copy OK 59 | 60 | No errors occurred 61 | 62 | 63 | AccurateRip summary 64 | 65 | Track 1 accurately ripped (confidence 7) [63DA46C4] (AR v2) 66 | Track 2 accurately ripped (confidence 7) [4334B581] (AR v2) 67 | Track 3 accurately ripped (confidence 7) [BC9D2EB3] (AR v2) 68 | Track 4 accurately ripped (confidence 7) [CA198833] (AR v2) 69 | Track 5 accurately ripped (confidence 7) [EB74FD25] (AR v2) 70 | Track 6 accurately ripped (confidence 7) [042E1875] (AR v2) 71 | Track 7 accurately ripped (confidence 7) [1B18C99B] (AR v2) 72 | Track 8 accurately ripped (confidence 7) [704684FF] (AR v2) 73 | Track 9 accurately ripped (confidence 7) [7FBE3435] (AR v2) 74 | Track 10 accurately ripped (confidence 7) [6D20FD41] (AR v2) 75 | Track 11 accurately ripped (confidence 7) [0B021200] (AR v2) 76 | 77 | All tracks accurately ripped 78 | 79 | End of status report 80 | 81 | ---- CUETools DB Plugin V2.1.4 82 | 83 | [CTDB TOCID: KhAHhDj3XzY_7wr53p8OrhbqZD0-] found 84 | Submit result: already submitted 85 | Track | CTDB Status 86 | 1 | (3/3) Accurately ripped 87 | 2 | (3/3) Accurately ripped 88 | 3 | (3/3) Accurately ripped 89 | 4 | (3/3) Accurately ripped 90 | 5 | (3/3) Accurately ripped 91 | 6 | (3/3) Accurately ripped 92 | 7 | (3/3) Accurately ripped 93 | 8 | (3/3) Accurately ripped 94 | 9 | (3/3) Accurately ripped 95 | 10 | (3/3) Accurately ripped 96 | 11 | (3/3) Accurately ripped 97 | 98 | 99 | ==== Log checksum 56FE14AFBBBB6D7A1267A708835A821133E15CC20911599A7B0AEF54B9C55DFD ==== 100 | -------------------------------------------------------------------------------- /tests/logs/EAC/russian-range-rip-ar-issue.log: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/doujincafe/hbcl/48d2f27746e212d023e72f270f67a06125830451/tests/logs/EAC/russian-range-rip-ar-issue.log -------------------------------------------------------------------------------- /tests/logs/EAC/russian1.log: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/doujincafe/hbcl/48d2f27746e212d023e72f270f67a06125830451/tests/logs/EAC/russian1.log -------------------------------------------------------------------------------- /tests/logs/EAC/russian2.log: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/doujincafe/hbcl/48d2f27746e212d023e72f270f67a06125830451/tests/logs/EAC/russian2.log -------------------------------------------------------------------------------- /tests/logs/EAC/russian3.log: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/doujincafe/hbcl/48d2f27746e212d023e72f270f67a06125830451/tests/logs/EAC/russian3.log -------------------------------------------------------------------------------- /tests/logs/EAC/russian4.log: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/doujincafe/hbcl/48d2f27746e212d023e72f270f67a06125830451/tests/logs/EAC/russian4.log -------------------------------------------------------------------------------- /tests/logs/EAC/spanish-log-extra-colons.log: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/doujincafe/hbcl/48d2f27746e212d023e72f270f67a06125830451/tests/logs/EAC/spanish-log-extra-colons.log -------------------------------------------------------------------------------- /tests/logs/EAC95/also-bad.log: -------------------------------------------------------------------------------- 1 | EAC extraction logfile from 29. January 2007, 20:27 for CD 2 | Luomo / Vocalcity 3 | 4 | Used drive : PIONEER DVD-RW DVR-106D Adapter: 1 ID: 0 5 | Read mode : Secure with NO C2, accurate stream, disable cache 6 | Combined read/write offset correction : 0 7 | Overread into Lead-In and Lead-Out : No 8 | 9 | Used output format : C:\Program Files\Exact Audio Copy\lame.exe (User Defined Encoder) 10 | 128 kBit/s 11 | Additional command line options : -V 0 --vbr-new --add-id3v2 --pad-id3v2 --ta "%a" --tt "%t" --tl "%g" --ty "%y" --tn "%n" %s %d 12 | 13 | Other options : 14 | Fill up missing offset samples with silence : Yes 15 | Delete leading and trailing silent blocks : No 16 | Installed external ASPI interface 17 | 18 | 19 | Track 1 20 | Filename D:\Music\Luomo\Luomo - Vocalcity\01 Market.wav 21 | 22 | Pre-gap length 0:00:02.00 23 | 24 | Peak level 99.5 % 25 | Track quality 100.0 % 26 | Copy CRC 965600D8 27 | Copy OK 28 | 29 | Track 2 30 | Filename D:\Music\Luomo\Luomo - Vocalcity\02 Class.wav 31 | 32 | Peak level 98.4 % 33 | Track quality 100.0 % 34 | Copy CRC 6CE86AF5 35 | Copy OK 36 | 37 | Track 3 38 | Filename D:\Music\Luomo\Luomo - Vocalcity\03 Synkro.wav 39 | 40 | Peak level 100.0 % 41 | Track quality 100.0 % 42 | Copy CRC 623A57EC 43 | Copy OK 44 | 45 | Track 4 46 | Filename D:\Music\Luomo\Luomo - Vocalcity\04 The Right Wing.wav 47 | 48 | Peak level 100.0 % 49 | Track quality 100.0 % 50 | Copy CRC D9B80369 51 | Copy OK 52 | 53 | Track 5 54 | Filename D:\Music\Luomo\Luomo - Vocalcity\05 Tessio.wav 55 | 56 | Peak level 100.0 % 57 | Track quality 99.9 % 58 | Copy CRC F2151670 59 | Copy OK 60 | 61 | Track 6 62 | Filename D:\Music\Luomo\Luomo - Vocalcity\06 She-center.wav 63 | 64 | Peak level 99.8 % 65 | Track quality 100.0 % 66 | Copy CRC 822774DA 67 | Copy OK 68 | 69 | No errors occured 70 | 71 | 72 | End of status report 73 | -------------------------------------------------------------------------------- /tests/logs/EAC95/bad-settings.log: -------------------------------------------------------------------------------- 1 | EAC extraction logfile from 6. September 2006, 16:00 for CD 2 | The Rolling Stones / Exile On Main Street 3 | 4 | Used drive : PLEXTOR CD-R PX-W5224A Adapter: 1 ID: 0 5 | Read mode : Secure with C2, accurate stream, disable cache 6 | Combined read/write offset correction : 0 7 | Overread into Lead-In and Lead-Out : No 8 | 9 | Used output format : C:\Program Files\Lame\lame.exe (User Defined Encoder) 10 | 320 kBit/s 11 | Additional command line options : -V 0 --vbr-new --add-id3v2 --pad-id3v2 --ta "%a" --tt "%t" --tl "%g" --ty "%y" --tn "%n" %s %d 12 | 13 | Other options : 14 | Fill up missing offset samples with silence : Yes 15 | Delete leading and trailing silent blocks : No 16 | Native Win32 interface for Win NT & 2000 17 | 18 | 19 | Track 1 20 | Filename D:\music files\eac own cd\01 - Rocks Off.wav 21 | 22 | Pre-gap length 0:00:02.00 23 | 24 | Peak level 86.9 % 25 | Track quality 99.9 % 26 | Test CRC C33FBDE2 27 | Copy CRC C33FBDE2 28 | Copy OK 29 | 30 | Track 2 31 | Filename D:\music files\eac own cd\02 - Rip This Joint.wav 32 | 33 | Peak level 91.5 % 34 | Track quality 100.0 % 35 | Test CRC EFA16E3D 36 | Copy CRC EFA16E3D 37 | Copy OK 38 | 39 | Track 3 40 | Filename D:\music files\eac own cd\03 - Shake Your Hips.wav 41 | 42 | Peak level 69.6 % 43 | Track quality 100.0 % 44 | Test CRC 0656F5A9 45 | Copy CRC 0656F5A9 46 | Copy OK 47 | 48 | Track 4 49 | Filename D:\music files\eac own cd\04 - Casino Boogie.wav 50 | 51 | Peak level 99.2 % 52 | Track quality 100.0 % 53 | Test CRC 9B9404C6 54 | Copy CRC 9B9404C6 55 | Copy OK 56 | 57 | Track 5 58 | Filename D:\music files\eac own cd\05 - Tumbling Dice.wav 59 | 60 | Peak level 91.1 % 61 | Track quality 100.0 % 62 | Test CRC 12CDD644 63 | Copy CRC 12CDD644 64 | Copy OK 65 | 66 | Track 6 67 | Filename D:\music files\eac own cd\06 - Sweet Virginia.wav 68 | 69 | Peak level 92.9 % 70 | Track quality 100.0 % 71 | Test CRC EC0AE46B 72 | Copy CRC EC0AE46B 73 | Copy OK 74 | 75 | Track 7 76 | Filename D:\music files\eac own cd\07 - Torn And Frayed.wav 77 | 78 | Pre-gap length 0:00:00.43 79 | 80 | Peak level 100.0 % 81 | Track quality 100.0 % 82 | Test CRC 0712DC72 83 | Copy CRC 0712DC72 84 | Copy OK 85 | 86 | Track 8 87 | Filename D:\music files\eac own cd\08 - Sweet Black Angel.wav 88 | 89 | Pre-gap length 0:00:00.15 90 | 91 | Peak level 78.7 % 92 | Track quality 100.0 % 93 | Test CRC 4CCE79FE 94 | Copy CRC 4CCE79FE 95 | Copy OK 96 | 97 | Track 9 98 | Filename D:\music files\eac own cd\09 - Loving Cup.wav 99 | 100 | Pre-gap length 0:00:00.25 101 | 102 | Peak level 100.0 % 103 | Track quality 100.0 % 104 | Test CRC 6687351D 105 | Copy CRC 6687351D 106 | Copy OK 107 | 108 | Track 10 109 | Filename D:\music files\eac own cd\10 - Happy.wav 110 | 111 | Peak level 100.0 % 112 | Track quality 100.0 % 113 | Test CRC 1C238B32 114 | Copy CRC 1C238B32 115 | Copy OK 116 | 117 | Track 11 118 | Filename D:\music files\eac own cd\11 - Turd On The Run.wav 119 | 120 | Peak level 81.1 % 121 | Track quality 99.8 % 122 | Test CRC 69D65474 123 | Copy CRC 69D65474 124 | Copy OK 125 | 126 | Track 12 127 | Filename D:\music files\eac own cd\12 - Ventilator Blues.wav 128 | 129 | Peak level 89.8 % 130 | Track quality 100.0 % 131 | Test CRC A78C9318 132 | Copy CRC A78C9318 133 | Copy OK 134 | 135 | Track 13 136 | Filename D:\music files\eac own cd\13 - Just Wanna See His Face.wav 137 | 138 | Peak level 68.1 % 139 | Track quality 100.0 % 140 | Test CRC EE119853 141 | Copy CRC EE119853 142 | Copy OK 143 | 144 | Track 14 145 | Filename D:\music files\eac own cd\14 - Let It Loose.wav 146 | 147 | Peak level 100.0 % 148 | Track quality 99.9 % 149 | Test CRC BAA80513 150 | Copy CRC BAA80513 151 | Copy OK 152 | 153 | Track 15 154 | Filename D:\music files\eac own cd\15 - All Down The Line.wav 155 | 156 | Peak level 94.4 % 157 | Track quality 100.0 % 158 | Test CRC D3EDE177 159 | Copy CRC D3EDE177 160 | Copy OK 161 | 162 | Track 16 163 | Filename D:\music files\eac own cd\16 - Stop Breaking Down.wav 164 | 165 | Peak level 100.0 % 166 | Track quality 100.0 % 167 | Test CRC BE0BAA8A 168 | Copy CRC BE0BAA8A 169 | Copy OK 170 | 171 | Track 17 172 | Filename D:\music files\eac own cd\17 - Shine A Light.wav 173 | 174 | Peak level 77.9 % 175 | Track quality 100.0 % 176 | Test CRC C698F4EA 177 | Copy CRC C698F4EA 178 | Copy OK 179 | 180 | Track 18 181 | Filename D:\music files\eac own cd\18 - Soul Survivor.wav 182 | 183 | Peak level 100.0 % 184 | Track quality 100.0 % 185 | Test CRC 96CCE6EA 186 | Copy CRC 96CCE6EA 187 | Copy OK 188 | 189 | No errors occured 190 | 191 | 192 | End of status report 193 | -------------------------------------------------------------------------------- /tests/logs/EAC95/burst.log: -------------------------------------------------------------------------------- 1 | EAC extraction logfile from 19. January 2008, 14:21 for CD 2 | Dead Can Dance / Spleen and Ideal 3 | 4 | Used drive : HL-DT-STDVDRAM GSA-H44L Adapter: 2 ID: 0 5 | Read mode : Burst 6 | Read offset correction : 0 7 | Overread into Lead-In and Lead-Out : No 8 | 9 | Used output format : C:\Program Files\Exact Audio Copy\lame.exe (User Defined Encoder) 10 | 320 kBit/s 11 | Additional command line options : -V 0 --vbr-new --add-id3v2 --ignore-tag-errors --ta "%a" --tt "%t" --tg "%m" --tl "%g" --ty "%y" --tn "%n" %s %d 12 | 13 | Other options : 14 | Fill up missing offset samples with silence : Yes 15 | Delete leading and trailing silent blocks : No 16 | Installed external ASPI interface 17 | 18 | 19 | Track 1 20 | Filename C:\EAC Rips\01 - Dead Can Dance - De Profundis (Out of the Depths of Sorrow).wav 21 | 22 | Pre-gap length 0:00:02.42 23 | 24 | Peak level 97.7 % 25 | Copy CRC 3020F329 26 | Copy OK 27 | 28 | Track 2 29 | Filename C:\EAC Rips\02 - Dead Can Dance - Ascension.wav 30 | 31 | Pre-gap length 0:00:02.76 32 | 33 | Peak level 68.8 % 34 | Copy CRC 0EDCDE6F 35 | Copy OK 36 | 37 | Track 3 38 | Filename C:\EAC Rips\03 - Dead Can Dance - Circumradiant Dawn.wav 39 | 40 | Pre-gap length 0:00:01.29 41 | 42 | Peak level 52.5 % 43 | Copy CRC 91FE3362 44 | Copy OK 45 | 46 | Track 4 47 | Filename C:\EAC Rips\04 - Dead Can Dance - The Cardinal Sin.wav 48 | 49 | Pre-gap length 0:00:00.80 50 | 51 | Peak level 88.2 % 52 | Copy CRC 1FCEA6F2 53 | Copy OK 54 | 55 | Track 5 56 | Filename C:\EAC Rips\05 - Dead Can Dance - Mesmerism.wav 57 | 58 | Pre-gap length 0:00:00.52 59 | 60 | Peak level 94.1 % 61 | Copy CRC 03CBB5FF 62 | Copy OK 63 | 64 | Track 6 65 | Filename C:\EAC Rips\06 - Dead Can Dance - Enigma of the Absolute.wav 66 | 67 | Pre-gap length 0:00:02.66 68 | 69 | Peak level 97.6 % 70 | Copy CRC 547EB52F 71 | Copy OK 72 | 73 | Track 7 74 | Filename C:\EAC Rips\07 - Dead Can Dance - Advent.wav 75 | 76 | Pre-gap length 0:00:00.02 77 | 78 | Peak level 91.6 % 79 | Copy CRC AE2F16AD 80 | Copy OK 81 | 82 | Track 8 83 | Filename C:\EAC Rips\08 - Dead Can Dance - Avatar.wav 84 | 85 | Pre-gap length 0:00:03.82 86 | 87 | Peak level 81.1 % 88 | Copy CRC AFB0AD01 89 | Copy OK 90 | 91 | Track 9 92 | Filename C:\EAC Rips\09 - Dead Can Dance - Indoctrination (A Design for Living).wav 93 | 94 | Pre-gap length 0:00:01.29 95 | 96 | Peak level 87.1 % 97 | Copy CRC 0204D7DC 98 | Copy OK 99 | 100 | No errors occured 101 | 102 | 103 | End of status report 104 | -------------------------------------------------------------------------------- /tests/logs/EAC95/had-decoding-issues.log: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/doujincafe/hbcl/48d2f27746e212d023e72f270f67a06125830451/tests/logs/EAC95/had-decoding-issues.log -------------------------------------------------------------------------------- /tests/logs/EAC95/markup/also-bad.log.markup: -------------------------------------------------------------------------------- 1 | EAC extraction logfile from 29. January 2007, 20:27 for CD 2 | Luomo / Vocalcity 3 | 4 | Used drive : PIONEER DVD-RW DVR-106D Adapter: 1 ID: 0 5 | Read mode : Secure with NO C2, accurate stream, disable cache 6 | Combined read/write offset correction : 0 7 | Overread into Lead-In and Lead-Out : No 8 | 9 | Used output format : C:\Program Files\Exact Audio Copy\lame.exe (User Defined Encoder) 10 | 128 kBit/s 11 | Additional command line options : -V 0 --vbr-new --add-id3v2 --pad-id3v2 --ta "%a" --tt "%t" --tl "%g" --ty "%y" --tn "%n" %s %d 12 | 13 | Other options : 14 | Fill up missing offset samples with silence : Yes 15 | Delete leading and trailing silent blocks : No 16 | Installed external ASPI interface 17 | 18 | 19 | an class="log4 log5">Track 1 20 | Filename D:\Music\Luomo\Luomo - Vocalcity\01 Market.wav 21 | 22 | Pre-gap length 0:00:02.00 23 | 24 | Peak level 99.5 % 25 | Track quality 100.0 % 26 | Copy CRC 965600D8 27 | Copy OK 28 | 29 | Track 2 30 | Filename D:\Music\Luomo\Luomo - Vocalcity\02 Class.wav 31 | 32 | Peak level 98.4 % 33 | Track quality 100.0 % 34 | Copy CRC 6CE86AF5 35 | Copy OK 36 | 37 | Track 3 38 | Filename D:\Music\Luomo\Luomo - Vocalcity\03 Synkro.wav 39 | 40 | Peak level 100.0 % 41 | Track quality 100.0 % 42 | Copy CRC 623A57EC 43 | Copy OK 44 | 45 | Track 4 46 | Filename D:\Music\Luomo\Luomo - Vocalcity\04 The Right Wing.wav 47 | 48 | Peak level 100.0 % 49 | Track quality 100.0 % 50 | Copy CRC D9B80369 51 | Copy OK 52 | 53 | Track 5 54 | Filename D:\Music\Luomo\Luomo - Vocalcity\05 Tessio.wav 55 | 56 | Peak level 100.0 % 57 | Track quality 99.9 % 58 | Copy CRC F2151670 59 | Copy OK 60 | 61 | Track 6 62 | Filename D:\Music\Luomo\Luomo - Vocalcity\06 She-center.wav 63 | 64 | Peak level 99.8 % 65 | Track quality 100.0 % 66 | Copy CRC 822774DA 67 | Copy OK 68 | 69 | No errors occured 70 | 71 | 72 | End of status report 73 | -------------------------------------------------------------------------------- /tests/logs/EAC95/markup/burst.log.markup: -------------------------------------------------------------------------------- 1 | EAC extraction logfile from 19. January 2008, 14:21 for CD 2 | Dead Can Dance / Spleen and Ideal 3 | 4 | Used drive : HL-DT-STDVDRAM GSA-H44L Adapter: 2 ID: 0 (not found in database) 5 | Read mode : Burst 6 | Read offset correction : 0 7 | Overread into Lead-In and Lead-Out : No 8 | 9 | Used output format : C:\Program Files\Exact Audio Copy\lame.exe (User Defined Encoder) 10 | 320 kBit/s 11 | Additional command line options : -V 0 --vbr-new --add-id3v2 --ignore-tag-errors --ta "%a" --tt "%t" --tg "%m" --tl "%g" --ty "%y" --tn "%n" %s %d 12 | 13 | Other options : 14 | Fill up missing offset samples with silence : Yes 15 | Delete leading and trailing silent blocks : No 16 | Installed external ASPI interface 17 | 18 | 19 | an class="log4 log5">Track 1 20 | Filename C:\EAC Rips\01 - Dead Can Dance - De Profundis (Out of the Depths of Sorrow).wav 21 | 22 | Pre-gap length 0:00:02.42 23 | 24 | Peak level 97.7 % 25 | Copy CRC 3020F329 26 | Copy OK 27 | 28 | Track 2 29 | Filename C:\EAC Rips\02 - Dead Can Dance - Ascension.wav 30 | 31 | Pre-gap length 0:00:02.76 32 | 33 | Peak level 68.8 % 34 | Copy CRC 0EDCDE6F 35 | Copy OK 36 | 37 | Track 3 38 | Filename C:\EAC Rips\03 - Dead Can Dance - Circumradiant Dawn.wav 39 | 40 | Pre-gap length 0:00:01.29 41 | 42 | Peak level 52.5 % 43 | Copy CRC 91FE3362 44 | Copy OK 45 | 46 | Track 4 47 | Filename C:\EAC Rips\04 - Dead Can Dance - The Cardinal Sin.wav 48 | 49 | Pre-gap length 0:00:00.80 50 | 51 | Peak level 88.2 % 52 | Copy CRC 1FCEA6F2 53 | Copy OK 54 | 55 | Track 5 56 | Filename C:\EAC Rips\05 - Dead Can Dance - Mesmerism.wav 57 | 58 | Pre-gap length 0:00:00.52 59 | 60 | Peak level 94.1 % 61 | Copy CRC 03CBB5FF 62 | Copy OK 63 | 64 | Track 6 65 | Filename C:\EAC Rips\06 - Dead Can Dance - Enigma of the Absolute.wav 66 | 67 | Pre-gap length 0:00:02.66 68 | 69 | Peak level 97.6 % 70 | Copy CRC 547EB52F 71 | Copy OK 72 | 73 | Track 7 74 | Filename C:\EAC Rips\07 - Dead Can Dance - Advent.wav 75 | 76 | Pre-gap length 0:00:00.02 77 | 78 | Peak level 91.6 % 79 | Copy CRC AE2F16AD 80 | Copy OK 81 | 82 | Track 8 83 | Filename C:\EAC Rips\08 - Dead Can Dance - Avatar.wav 84 | 85 | Pre-gap length 0:00:03.82 86 | 87 | Peak level 81.1 % 88 | Copy CRC AFB0AD01 89 | Copy OK 90 | 91 | Track 9 92 | Filename C:\EAC Rips\09 - Dead Can Dance - Indoctrination (A Design for Living).wav 93 | 94 | Pre-gap length 0:00:01.29 95 | 96 | Peak level 87.1 % 97 | Copy CRC 0204D7DC 98 | Copy OK 99 | 100 | No errors occured 101 | 102 | 103 | End of status report 104 | -------------------------------------------------------------------------------- /tests/logs/EAC95/read-mode.log: -------------------------------------------------------------------------------- 1 | EAC extraction logfile from 29. September 2006, 23:18 for CD 2 | Four Tet / Rounds 3 | 4 | Used drive : TEAC CD-W524E Adapter: 1 ID: 1 5 | Read mode : Secure with NO C2, accurate stream, NO disable cache 6 | Read offset correction : 685 7 | Overread into Lead-In and Lead-Out : No 8 | 9 | Used output format : G:\Program Files\Lame\Lame 3.97\lame.exe (User Defined Encoder) 10 | 192 kBit/s 11 | Additional command line options : -V 0 --vbr-new --add-id3v2 --pad-id3v2 --ta "%a" --tt "%t" --tl "%g" --ty "%y" --tn "%n" %s %d 12 | 13 | Other options : 14 | Fill up missing offset samples with silence : Yes 15 | Delete leading and trailing silent blocks : No 16 | Native Win32 interface for Win NT & 2000 17 | 18 | 19 | Track 1 20 | Filename F:\Audio\Four Tet\Four Tet - [2003.05.05] Rounds\01 - Hands.wav 21 | 22 | Peak level 100.0 % 23 | Track quality 100.0 % 24 | Test CRC 0759E4F7 25 | Copy CRC 0759E4F7 26 | Copy OK 27 | 28 | Track 2 29 | Filename F:\Audio\Four Tet\Four Tet - [2003.05.05] Rounds\02 - She Moves She.wav 30 | 31 | Peak level 100.0 % 32 | Track quality 100.0 % 33 | Test CRC F799C261 34 | Copy CRC F799C261 35 | Copy OK 36 | 37 | Track 3 38 | Filename F:\Audio\Four Tet\Four Tet - [2003.05.05] Rounds\03 - First Thing.wav 39 | 40 | Peak level 36.9 % 41 | Track quality 100.0 % 42 | Test CRC DD981688 43 | Copy CRC DD981688 44 | Copy OK 45 | 46 | Track 4 47 | Filename F:\Audio\Four Tet\Four Tet - [2003.05.05] Rounds\04 - My Angel Rocks Back And Forth.wav 48 | 49 | Peak level 100.0 % 50 | Track quality 100.0 % 51 | Test CRC 0589EFDD 52 | Copy CRC 0589EFDD 53 | Copy OK 54 | 55 | Track 5 56 | Filename F:\Audio\Four Tet\Four Tet - [2003.05.05] Rounds\05 - Spirit Fingers.wav 57 | 58 | Peak level 100.0 % 59 | Track quality 100.0 % 60 | Test CRC 19CBEFDB 61 | Copy CRC 19CBEFDB 62 | Copy OK 63 | 64 | Track 6 65 | Filename F:\Audio\Four Tet\Four Tet - [2003.05.05] Rounds\06 - Unspoken.wav 66 | 67 | Peak level 100.0 % 68 | Track quality 100.0 % 69 | Test CRC 503DB496 70 | Copy CRC 503DB496 71 | Copy OK 72 | 73 | Track 7 74 | Filename F:\Audio\Four Tet\Four Tet - [2003.05.05] Rounds\07 - Chia.wav 75 | 76 | Peak level 99.5 % 77 | Track quality 100.0 % 78 | Test CRC B7EB0820 79 | Copy CRC B7EB0820 80 | Copy OK 81 | 82 | Track 8 83 | Filename F:\Audio\Four Tet\Four Tet - [2003.05.05] Rounds\08 - As Serious As Your Life.wav 84 | 85 | Peak level 100.0 % 86 | Track quality 100.0 % 87 | Test CRC 475B8166 88 | Copy CRC 475B8166 89 | Copy OK 90 | 91 | Track 9 92 | Filename F:\Audio\Four Tet\Four Tet - [2003.05.05] Rounds\09 - And They All Look Broken Hearted.wav 93 | 94 | Peak level 89.1 % 95 | Track quality 100.0 % 96 | Test CRC 8FD7D3E1 97 | Copy CRC 8FD7D3E1 98 | Copy OK 99 | 100 | Track 10 101 | Filename F:\Audio\Four Tet\Four Tet - [2003.05.05] Rounds\10 - Slow Jam.wav 102 | 103 | Peak level 100.0 % 104 | Track quality 100.0 % 105 | Test CRC D1C15DB9 106 | Copy CRC D1C15DB9 107 | Copy OK 108 | 109 | No errors occured 110 | 111 | 112 | End of status report 113 | -------------------------------------------------------------------------------- /tests/logs/XLD/htoa.log: -------------------------------------------------------------------------------- 1 | X Lossless Decoder version 20170729 (150.3) 2 | 3 | XLD extraction logfile from 2017-08-28 03:03:05 +0100 4 | 5 | Quinoline Yellow / Uchel001 6 | 7 | Used drive : TSSTcorp CDDVDW SE-S084C (revision TS01) 8 | Media type : CD-Recordable 9 | 10 | Ripper mode : XLD Secure Ripper 11 | Disable audio cache : OK for the drive with a cache less than 1375KiB 12 | Make use of C2 pointers : NO 13 | Read offset correction : 6 14 | Max retry count : 20 15 | Gap status : Analyzed, Appended 16 | 17 | TOC of the extracted CD 18 | Track | Start | Length | Start sector | End sector 19 | --------------------------------------------------------- 20 | 1 | 01:01:17 | 03:48:58 | 4592 | 21749 21 | 2 | 04:50:00 | 04:27:22 | 21750 | 41796 22 | 3 | 09:17:22 | 04:10:59 | 41797 | 60605 23 | 4 | 13:28:06 | 01:52:71 | 60606 | 69076 24 | 5 | 15:21:02 | 03:49:53 | 69077 | 86304 25 | 26 | AccurateRip Summary (DiscID: 000455df-00138492-40044105) 27 | Track 01 : OK (v1, confidence 1/2) 28 | ->All tracks accurately ripped. 29 | 30 | All Tracks 31 | Statistics 32 | Read error : 0 33 | Jitter error (maybe fixed) : 0 34 | Retry sector count : 0 35 | Damaged sector count : 0 36 | 37 | Track 01 38 | Filename : /XLD Rips/Quinoline Yellow - Uchel001 (2005) {uchel001, CDr, Mini} [WAV]/00 - Untitled.wav 39 | Pre-gap length : 01:03:17 40 | 41 | Track gain : -5.47 dB 42 | Peak : 1.000000 43 | CRC32 hash (test run) : 7AEE75EC 44 | CRC32 hash : 7AEE75EC 45 | CRC32 hash (skip zero) : FA6488BC 46 | AccurateRip v1 signature : 7F906C67 47 | AccurateRip v2 signature : DCC30E8E 48 | ->Accurately ripped (v1, confidence 1/2) 49 | Statistics 50 | Read error : 0 51 | Jitter error (maybe fixed) : 0 52 | Retry sector count : 0 53 | Damaged sector count : 0 54 | 55 | No errors occurred 56 | 57 | End of status report 58 | 59 | -----BEGIN XLD SIGNATURE----- 60 | 1wzdA1lWBzTfsDeL6AHIRV5sF.wWMjtFSNR_NAn172OFxMJTyc7P7ns0oSToGxA1bTXZcOJruRXqkid.PtKaEjoHVfhsjla64FKsDV0 61 | -----END XLD SIGNATURE----- 62 | -------------------------------------------------------------------------------- /tests/logs/XLD/markup/htoa.log.markup: -------------------------------------------------------------------------------- 1 | X Lossless Decoder version 20170729 (150.3) 2 | 3 | XLD extraction logfile from 2017-08-28 03:03:05 +0100 4 | 5 | Quinoline Yellow / Uchel001 6 | 7 | Used drive : TSSTcorp CDDVDW SE-S084C (revision TS01) (not found in database) 8 | Media type : CD-Recordable 9 | 10 | Ripper mode : XLD Secure Ripper 11 | Disable audio cache : OK for the drive with a cache less than 1375KiB 12 | Make use of C2 pointers : NO 13 | Read offset correction : 6 14 | Max retry count : 20 15 | Gap status : Analyzed, Appended 16 | 17 | TOC of the extracted CD 18 | Track | Start | Length | Start sector | End sector 19 | --------------------------------------------------------- 20 | 1 | 01:01:17 | 03:48:58 | 4592 | 21749 21 | 2 | 04:50:00 | 04:27:22 | 21750 | 41796 22 | 3 | 09:17:22 | 04:10:59 | 41797 | 60605 23 | 4 | 13:28:06 | 01:52:71 | 60606 | 69076 24 | 5 | 15:21:02 | 03:49:53 | 69077 | 86304 25 | 26 | AccurateRip Summary (DiscID: 000455df-00138492-40044105) 27 | Track 01 : OK (v1, confidence 1/2) 28 | ->All tracks accurately ripped. 29 | 30 | All Tracks 31 | Statistics 32 | Read error : 0 33 | Jitter error (maybe fixed) : 0 34 | Retry sector count : 0 35 | Damaged sector count : 0 36 | 37 | Track 01 38 | Filename : /XLD Rips/Quinoline Yellow - Uchel001 (2005) {uchel001, CDr, Mini} [WAV]/00 - Untitled.wav 39 | Pre-gap length : 01:03:17 40 | 41 | Track gain : -5.47 dB 42 | Peak : 1.000000 43 | CRC32 hash (test run) : 7AEE75EC 44 | CRC32 hash : 7AEE75EC 45 | CRC32 hash (skip zero) : FA6488BC 46 | AccurateRip v1 signature : 7F906C67 47 | AccurateRip v2 signature : DCC30E8E 48 | ->Accurately ripped (v1, confidence 1/2) 49 | Statistics 50 | Read error : 0 51 | Jitter error (maybe fixed) : 0 52 | Retry sector count : 0 53 | Damaged sector count : 0 54 | 55 | No errors occurred 56 | 57 | End of status report 58 | 59 | -----BEGIN XLD SIGNATURE----- 60 | 1wzdA1lWBzTfsDeL6AHIRV5sF.wWMjtFSNR_NAn172OFxMJTyc7P7ns0oSToGxA1bTXZcOJruRXqkid.PtKaEjoHVfhsjla64FKsDV0 61 | -----END XLD SIGNATURE----- -------------------------------------------------------------------------------- /tests/logs/XLD/range-vbox.log: -------------------------------------------------------------------------------- 1 | X Lossless Decoder version 20170729 (150.3) 2 | 3 | XLD extraction logfile from 2017-08-01 14:56:16 -0300 4 | 5 | KARA / ジャンピン 6 | 7 | Used drive : VBOX CD-ROM (revision 1.0) 8 | Media type : Pressed CD 9 | 10 | Ripper mode : XLD Secure Ripper 11 | Disable audio cache : OK for the drive with a cache less than 1375KiB 12 | Make use of C2 pointers : NO 13 | Read offset correction : 6 14 | Max retry count : 20 15 | Gap status : Analyzed, Appended 16 | 17 | TOC of the extracted CD 18 | Track | Start | Length | Start sector | End sector 19 | --------------------------------------------------------- 20 | 1 | 00:00:00 | 03:00:27 | 0 | 13526 21 | 2 | 03:00:27 | 03:32:48 | 13527 | 29474 22 | 3 | 06:33:00 | 02:59:05 | 29475 | 42904 23 | 24 | AccurateRip Summary (DiscID: 00014f93-0004617c-1e023c03) 25 | Track 01 : OK (v1+v2, confidence 11/11) 26 | Track 02 : OK (v1+v2, confidence 9/9) 27 | Track 03 : OK (v1+v2, confidence 9/9) 28 | ->All tracks accurately ripped. 29 | 30 | All Tracks 31 | Filename : /Users/dubious/xld rips/01. ジャンピン.flac 32 | Album gain : -11.92 dB 33 | Peak : 1.000000 34 | CRC32 hash (test run) : F55D3134 35 | CRC32 hash : F55D3134 36 | CRC32 hash (skip zero) : 2154552F 37 | Statistics 38 | Read error : 0 39 | Jitter error (maybe fixed) : 0 40 | Retry sector count : 0 41 | Damaged sector count : 0 42 | 43 | Track 01 44 | Pre-gap length : 00:02:00 45 | 46 | Track gain : -11.95 dB 47 | Peak : 1.000000 48 | CRC32 hash (test run) : 0248840B 49 | CRC32 hash : 0248840B 50 | CRC32 hash (skip zero) : 8DAB64A0 51 | AccurateRip v1 signature : AB11CF3F 52 | AccurateRip v2 signature : 0021EFA8 53 | ->Accurately ripped (v1+v2, confidence 5+6/11) 54 | Statistics 55 | Read error : 0 56 | Jitter error (maybe fixed) : 0 57 | Retry sector count : 0 58 | Damaged sector count : 0 59 | 60 | Track 02 61 | 62 | Track gain : -12.51 dB 63 | Peak : 1.000000 64 | CRC32 hash (test run) : DB57CD66 65 | CRC32 hash : DB57CD66 66 | CRC32 hash (skip zero) : 15D163C0 67 | AccurateRip v1 signature : D627D9F5 68 | AccurateRip v2 signature : 689E1528 69 | ->Accurately ripped (v1+v2, confidence 3+6/9) 70 | Statistics 71 | Read error : 0 72 | Jitter error (maybe fixed) : 0 73 | Retry sector count : 0 74 | Damaged sector count : 0 75 | 76 | Track 03 77 | 78 | Track gain : -9.38 dB 79 | Peak : 1.000000 80 | CRC32 hash (test run) : 07AB8339 81 | CRC32 hash : 07AB8339 82 | CRC32 hash (skip zero) : 73FCDD4A 83 | AccurateRip v1 signature : A61A5EA8 84 | AccurateRip v2 signature : 7081171C 85 | ->Accurately ripped (v1+v2, confidence 4+5/9) 86 | Statistics 87 | Read error : 0 88 | Jitter error (maybe fixed) : 0 89 | Retry sector count : 0 90 | Damaged sector count : 0 91 | 92 | No errors occurred 93 | 94 | End of status report 95 | 96 | -----BEGIN XLD SIGNATURE----- 97 | 9NvFdxRPNWm8G8dJyzLLbEkLcpVqzExZwC1NJ6OKyjUQNpvIZZ24MD3aoglPsjyU28tRYNsxO11FjHIvl3E1vavNwxiVZ1gT_RhqPDq 98 | -----END XLD SIGNATURE----- 99 | -------------------------------------------------------------------------------- /tests/logs/spanish-099.log: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/doujincafe/hbcl/48d2f27746e212d023e72f270f67a06125830451/tests/logs/spanish-099.log -------------------------------------------------------------------------------- /tests/logs/translations/bad-russian-099.log: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/doujincafe/hbcl/48d2f27746e212d023e72f270f67a06125830451/tests/logs/translations/bad-russian-099.log -------------------------------------------------------------------------------- /tests/logs/translations/french-big-calm.log: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/doujincafe/hbcl/48d2f27746e212d023e72f270f67a06125830451/tests/logs/translations/french-big-calm.log -------------------------------------------------------------------------------- /tests/logs/translations/russian-range-rip-ar-issue.log: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/doujincafe/hbcl/48d2f27746e212d023e72f270f67a06125830451/tests/logs/translations/russian-range-rip-ar-issue.log -------------------------------------------------------------------------------- /tests/logs/translations/spanish-log-extra-colons.log: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/doujincafe/hbcl/48d2f27746e212d023e72f270f67a06125830451/tests/logs/translations/spanish-log-extra-colons.log -------------------------------------------------------------------------------- /tests/logs/translations/translated/french-big-calm.log.translated: -------------------------------------------------------------------------------- 1 | EAC extraction logfile from 3. February 2005, 17:30 pour CD 2 | Morcheeba / Big Calm 3 | 4 | Used drive : PLEXTOR DVD-ROM PX-130A Adapter: 0 ID: 0 5 | Read mode Secure with NO C2, accurate stream, disable cache 6 | Combined read/write offset correction 0 7 | Overread into Lead-In and Lead-Out: No 8 | 9 | Used output format Internal WAV Routines 10 | 44.100 Hz; 16 Bit; Stereo 11 | 12 | Other options : 13 | Fill up missing offset samples with silence : Yes 14 | Delete leading and trailing silent blocks : No 15 | Native Win32 interface for Win NT & 2000 16 | 17 | 18 | Track 1 19 | Filename D:\ftp\Musique\Morcheeba\Morcheeba - Big Calm - 1998\01_The sea_Morcheeba.wav 20 | 21 | Peak level 100.0 % 22 | Track quality 100.0 % 23 | Copy CRC 02531EFA 24 | Copy OK 25 | 26 | Track 2 27 | Filename D:\ftp\Musique\Morcheeba\Morcheeba - Big Calm - 1998\02_Shoulder holster_Morcheeba.wav 28 | 29 | Peak level 100.0 % 30 | Track quality 100.0 % 31 | Copy CRC 69160C64 32 | Copy OK 33 | 34 | Track 3 35 | Filename D:\ftp\Musique\Morcheeba\Morcheeba - Big Calm - 1998\03_Part of the process_Morcheeba.wav 36 | 37 | Peak level 100.0 % 38 | Track quality 100.0 % 39 | Copy CRC BF909584 40 | Copy OK 41 | 42 | Track 4 43 | Filename D:\ftp\Musique\Morcheeba\Morcheeba - Big Calm - 1998\04_Blindfold_Morcheeba.wav 44 | 45 | Peak level 100.0 % 46 | Track quality 100.0 % 47 | Copy CRC 3F8A120E 48 | Copy OK 49 | 50 | Track 5 51 | Filename D:\ftp\Musique\Morcheeba\Morcheeba - Big Calm - 1998\05_Let me see_Morcheeba.wav 52 | 53 | Peak level 100.0 % 54 | Track quality 100.0 % 55 | Copy CRC 4B83A5FB 56 | Copy OK 57 | 58 | Track 6 59 | Filename D:\ftp\Musique\Morcheeba\Morcheeba - Big Calm - 1998\06_Bullet proof_Morcheeba.wav 60 | 61 | Peak level 100.0 % 62 | Track quality 100.0 % 63 | Copy CRC 0A470DC1 64 | Copy OK 65 | 66 | Track 7 67 | Filename D:\ftp\Musique\Morcheeba\Morcheeba - Big Calm - 1998\07_Over and over_Morcheeba.wav 68 | 69 | Peak level 100.0 % 70 | Track quality 100.0 % 71 | Copy CRC A112E32C 72 | Copy OK 73 | 74 | Track 8 75 | Filename D:\ftp\Musique\Morcheeba\Morcheeba - Big Calm - 1998\08_Friction_Morcheeba.wav 76 | 77 | Peak level 100.0 % 78 | Track quality 100.0 % 79 | Copy CRC 9B8B3C9E 80 | Copy OK 81 | 82 | Track 9 83 | Filename D:\ftp\Musique\Morcheeba\Morcheeba - Big Calm - 1998\09_Diggin' a watery grave_Morcheeba.wav 84 | 85 | Peak level 100.0 % 86 | Track quality 100.0 % 87 | Copy CRC 27A498D0 88 | Copy OK 89 | 90 | Track 10 91 | Filename D:\ftp\Musique\Morcheeba\Morcheeba - Big Calm - 1998\10_Fear and love_Morcheeba.wav 92 | 93 | Peak level 100.0 % 94 | Track quality 100.0 % 95 | Copy CRC 9F8D3A5A 96 | Copy OK 97 | 98 | Track 11 99 | Filename D:\ftp\Musique\Morcheeba\Morcheeba - Big Calm - 1998\11_Big calm_Morcheeba.wav 100 | 101 | Peak level 100.0 % 102 | Track quality 100.0 % 103 | Copy CRC E22A31C4 104 | Copy OK 105 | 106 | No errors occurred 107 | 108 | 109 | End of status report 110 | -------------------------------------------------------------------------------- /tests/logs/unrecognized/eac-edited-at-top-extra-spaces.log: -------------------------------------------------------------------------------- 1 | 2 | 3 | Exact Audio Copy V0.99 prebeta 5 from 4. May 2009 4 | 5 | EAC extraction logfile from 18. July 2010, 3:47 6 | 7 | !!! / Strange Weather, Isn't It? 8 | 9 | Used drive : HL-DT-STDVDRAM GSA-U10N Adapter: 1 ID: 0 10 | 11 | Read mode : Secure 12 | Utilize accurate stream : Yes 13 | Defeat audio cache : Yes 14 | Make use of C2 pointers : No 15 | 16 | Read offset correction : 667 17 | Overread into Lead-In and Lead-Out : No 18 | Fill up missing offset samples with silence : Yes 19 | Delete leading and trailing silent blocks : No 20 | Null samples used in CRC calculations : Yes 21 | Used interface : Native Win32 interface for Win NT & 2000 22 | Gap handling : Appended to previous track 23 | 24 | Used output format : User Defined Encoder 25 | Selected bitrate : 192 kBit/s 26 | Quality : High 27 | Add ID3 tag : No 28 | Command line compressor : C:\Program Files\Exact Audio Copy\Flac\flac.exe 29 | Additional command line options : -V -8 -T "artist=%a" -T "title=%t" -T "album=%g" -T "date=%y" -T "tracknumber=%n" -T "genre=%m" %s 30 | 31 | 32 | TOC of the extracted CD 33 | 34 | Track | Start | Length | Start sector | End sector 35 | --------------------------------------------------------- 36 | 1 | 0:00.00 | 4:55.13 | 0 | 22137 37 | 2 | 4:55.13 | 5:39.06 | 22138 | 47568 38 | 3 | 10:34.19 | 3:49.72 | 47569 | 64815 39 | 4 | 14:24.16 | 5:06.33 | 64816 | 87798 40 | 5 | 19:30.49 | 4:25.11 | 87799 | 107684 41 | 6 | 23:55.60 | 2:48.10 | 107685 | 120294 42 | 7 | 26:43.70 | 3:20.73 | 120295 | 135367 43 | 8 | 30:04.68 | 5:45.07 | 135368 | 161249 44 | 9 | 35:50.00 | 4:58.67 | 161250 | 183666 45 | 10 | 40:48.67 | 3:06.70 | 183667 | 197686 46 | 47 | 48 | Track 1 49 | 50 | Filename C:\Users\elleven\Desktop\!!! - Strange Weather, Isn't It () [FLAC]\01 - AM,FM.wav 51 | 52 | Pre-gap length 0:00:02.00 53 | 54 | Peak level 100.0 % 55 | Track quality 99.9 % 56 | Test CRC 2C5C8621 57 | Copy CRC 2C5C8621 58 | Track not present in AccurateRip database 59 | Copy OK 60 | 61 | Track 2 62 | 63 | Filename C:\Users\elleven\Desktop\!!! - Strange Weather, Isn't It () [FLAC]\02 - The Most Certain Sure.wav 64 | 65 | Pre-gap length 0:00:02.25 66 | 67 | Peak level 100.0 % 68 | Track quality 100.0 % 69 | Test CRC 78BA3F79 70 | Copy CRC 78BA3F79 71 | Track not present in AccurateRip database 72 | Copy OK 73 | 74 | Track 3 75 | 76 | Filename C:\Users\elleven\Desktop\!!! - Strange Weather, Isn't It () [FLAC]\03 - Wannagain Wannagain.wav 77 | 78 | Peak level 100.0 % 79 | Track quality 100.0 % 80 | Test CRC EEDD73B4 81 | Copy CRC EEDD73B4 82 | Track not present in AccurateRip database 83 | Copy OK 84 | 85 | Track 4 86 | 87 | Filename C:\Users\elleven\Desktop\!!! - Strange Weather, Isn't It () [FLAC]\04 - Jamie, My Intentions Are Bass.wav 88 | 89 | Pre-gap length 0:00:00.92 90 | 91 | Peak level 100.0 % 92 | Track quality 100.0 % 93 | Test CRC CBAC60E6 94 | Copy CRC CBAC60E6 95 | Track not present in AccurateRip database 96 | Copy OK 97 | 98 | Track 5 99 | 100 | Filename C:\Users\elleven\Desktop\!!! - Strange Weather, Isn't It () [FLAC]\05 - Steady As The Sidewalk Cracks.wav 101 | 102 | Peak level 100.0 % 103 | Track quality 100.0 % 104 | Test CRC 9199CEAD 105 | Copy CRC 9199CEAD 106 | Track not present in AccurateRip database 107 | Copy OK 108 | 109 | Track 6 110 | 111 | Filename C:\Users\elleven\Desktop\!!! - Strange Weather, Isn't It () [FLAC]\06 - Hollow.wav 112 | 113 | Peak level 100.0 % 114 | Track quality 100.0 % 115 | Test CRC B985034C 116 | Copy CRC B985034C 117 | Track not present in AccurateRip database 118 | Copy OK 119 | 120 | Track 7 121 | 122 | Filename C:\Users\elleven\Desktop\!!! - Strange Weather, Isn't It () [FLAC]\07 - Jump Back.wav 123 | 124 | Peak level 100.0 % 125 | Track quality 99.8 % 126 | Test CRC 449F14E8 127 | Copy CRC 449F14E8 128 | Track not present in AccurateRip database 129 | Copy OK 130 | 131 | Track 8 132 | 133 | Filename C:\Users\elleven\Desktop\!!! - Strange Weather, Isn't It () [FLAC]\08 - Even Judas Gave Jesus A Kiss.wav 134 | 135 | Pre-gap length 0:00:00.46 136 | 137 | Peak level 100.0 % 138 | Track quality 99.6 % 139 | Test CRC 4D67E03D 140 | Copy CRC 4D67E03D 141 | Track not present in AccurateRip database 142 | Copy OK 143 | 144 | Track 9 145 | 146 | Filename C:\Users\elleven\Desktop\!!! - Strange Weather, Isn't It () [FLAC]\09 - The Hammer.wav 147 | 148 | Pre-gap length 0:00:00.38 149 | 150 | Peak level 100.0 % 151 | Track quality 99.9 % 152 | Test CRC E81E4969 153 | Copy CRC E81E4969 154 | Track not present in AccurateRip database 155 | Copy OK 156 | 157 | Track 10 158 | 159 | Filename C:\Users\elleven\Desktop\!!! - Strange Weather, Isn't It () [FLAC]\10 - Made Of Money.wav 160 | 161 | Pre-gap length 0:00:06.92 162 | 163 | Peak level 100.0 % 164 | Track quality 100.0 % 165 | Test CRC 9726E3C1 166 | Copy CRC 9726E3C1 167 | Track not present in AccurateRip database 168 | Copy OK 169 | 170 | 171 | None of the tracks are present in the AccurateRip database 172 | 173 | No errors occurred 174 | 175 | End of status report 176 | -------------------------------------------------------------------------------- /tests/logs/unrecognized/eac-unrecognized-not-all-tracks.log: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/doujincafe/hbcl/48d2f27746e212d023e72f270f67a06125830451/tests/logs/unrecognized/eac-unrecognized-not-all-tracks.log -------------------------------------------------------------------------------- /tests/logs/unrecognized/eac-wrong-date.log: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/doujincafe/hbcl/48d2f27746e212d023e72f270f67a06125830451/tests/logs/unrecognized/eac-wrong-date.log -------------------------------------------------------------------------------- /tests/translate_test.py: -------------------------------------------------------------------------------- 1 | import os 2 | from pathlib import Path 3 | 4 | import pytest 5 | from heybrochecklog.translate import translate_log 6 | 7 | LOGS = [ 8 | ('french-big-calm.log'), 9 | ] 10 | 11 | 12 | @pytest.mark.parametrize('filename', LOGS) 13 | def test_translation(filename): 14 | log_path = os.path.join(os.path.dirname(__file__), 'logs', 'translations', filename) 15 | log_file = Path(log_path) 16 | log = translate_log(log_file) 17 | 18 | translated_path = os.path.join( 19 | os.path.dirname(__file__), 20 | 'logs', 21 | 'translations', 22 | 'translated', 23 | '{}.translated'.format(filename), 24 | ) 25 | with open(translated_path, 'r') as translated_file: 26 | translated_contents = translated_file.read() 27 | 28 | assert log['log'] == translated_contents 29 | -------------------------------------------------------------------------------- /tests/unrecognized_test.py: -------------------------------------------------------------------------------- 1 | import os 2 | from pathlib import Path 3 | 4 | import pytest 5 | from heybrochecklog.score import score_log 6 | 7 | LOGS = [ 8 | ('eac-edited-at-top-extra-spaces.log', 'Unrecognized ripper'), 9 | ('eac-edited-wrongly-split-combined.log', 'Unrecognized ripper'), 10 | ('eac-failed-to-properly-forge-a.log', 'Unrecognized/unsupported language'), 11 | ( 12 | 'eac-unrecognized-not-all-tracks.log', 13 | 'Not all tracks are represented in the log', 14 | ), 15 | ('eac-wrong-date.log', 'Unrecognized EAC version'), 16 | ] 17 | 18 | 19 | @pytest.mark.parametrize('filename, unrecognized_reason', LOGS) 20 | def test_scoring(filename, unrecognized_reason): 21 | log_path = os.path.join(os.path.dirname(__file__), 'logs', 'unrecognized', filename) 22 | log_file = Path(log_path) 23 | log = score_log(log_file) 24 | assert log['unrecognized'] == unrecognized_reason 25 | -------------------------------------------------------------------------------- /tests/xld_test.py: -------------------------------------------------------------------------------- 1 | import os 2 | from pathlib import Path 3 | 4 | import pytest 5 | from heybrochecklog.score import score_log 6 | 7 | """Lazy person not going to do full unit testing.""" 8 | 9 | LOGS = [ 10 | ( 11 | 'cdparanoia.log', 12 | { 13 | 'Ripper mode was not XLD Secure Ripper (-100 points)', 14 | 'C2 pointers were used (-20 points)', 15 | 'Gaps were not analyzed and appended (-10 points)', 16 | 'XLD pre-142.2 (no checksum)', 17 | 'Track gain was not turned on (-1 points)', 18 | }, 19 | ), 20 | ('crc-mismatch.log', {'CRC mismatch (-30 points)'}), 21 | ('htoa.log', {'CD-R detected; not a pressed CD', 'HTOA extracted'}), 22 | ( 23 | 'ripping-error.log', 24 | { 25 | 'Track 16: Damaged sector (724 occurrences) (-10 points)', 26 | 'CRC mismatch (-30 points)', 27 | }, 28 | ), 29 | ('range-vbox.log', {'Range rip detected (-20 points)'}), 30 | ('bad-chardet-no-checksum.log', {'No checksum (-15 points)'}), 31 | ('cdr-multi-filename.log', {'CD-R detected; not a pressed CD'}), 32 | ( 33 | 'xld-cdp.log', 34 | { 35 | 'Ripper mode was not XLD Secure Ripper (-100 points)', 36 | 'XLD pre-142.2 (no checksum)', 37 | }, 38 | ), 39 | ('100-percent-new.log', { 'Data track detected' }) 40 | ] 41 | 42 | 43 | @pytest.mark.parametrize('filename, deductions', LOGS) 44 | def test_scoring(filename, deductions): 45 | log_path = os.path.join(os.path.dirname(__file__), 'logs', 'XLD', filename) 46 | log_file = Path(log_path) 47 | log = score_log(log_file) 48 | assert deductions == {d[0] for d in log['deductions']} 49 | 50 | 51 | @pytest.mark.parametrize('filename', [log_tuple[0] for log_tuple in LOGS]) 52 | def test_markup(filename): 53 | log_path = os.path.join(os.path.dirname(__file__), 'logs', 'XLD', filename) 54 | log_file = Path(log_path) 55 | log = score_log(log_file, markup=True) 56 | 57 | markup_path = os.path.join( 58 | os.path.dirname(__file__), 'logs', 'XLD', 'markup', '{}.markup'.format(filename) 59 | ) 60 | with open(markup_path, 'r') as markup_file: 61 | markup_contents = markup_file.read() 62 | 63 | assert log['contents'] == markup_contents 64 | --------------------------------------------------------------------------------