dart_rip_log 0.1.0 copy "dart_rip_log: ^0.1.0" to clipboard
dart_rip_log: ^0.1.0 copied to clipboard

Parses CD rip log files from EAC, XLD, and other rippers into structured, JSON-serialisable quality data (AccurateRip, CRCs, peaks, errors).

dart_rip_log #

CI pub package License: Apache 2.0

A pure Dart library that parses CD rip log files from the major CD-ripping tools (EAC, XLD) into structured, JSON-serialisable quality data. Extracts AccurateRip verification status, CRC-32 checksums, peak levels, track quality, and per-track error statistics.

Zero runtime dependencies beyond the Dart SDK.

Features #

  • Auto-detects the log format from the log content.
  • EAC (Exact Audio Copy) — full parser, including:
    • Header: tool version, extraction date, drive, read mode, read offset, overread, gap handling, media type.
    • Per track: filename, peak level, track quality, test/copy CRCs, Copy OK.
    • AccurateRip: verified (with confidence, v1 CRC and optional v2 signature), mismatch, notInDatabase.
    • Full error-statistics block (read / skip / edge jitter / atom jitter / drift / dropped bytes / duplicated bytes / inconsistency).
    • Footer: summary line and log checksum.
    • Range-rip logs (single-track whole-disc extractions).
  • XLD (X Lossless Decoder) — full parser, including per-track AR v1/v2 signatures and the Statistics block.
  • CUERipper, whipper, dBpoweramp — format detection and scaffolded parsers (tool version captured; full per-track parsing pending real-world sample logs).
  • Tolerant of malformed input: truncated files, garbled lines, CRLF/LF/mixed line endings, and missing fields return a best-effort RipLog rather than throwing.
  • toJson() on every model for easy serialisation.
  • Command-line tool (bin/riplog.dart) for quick inspection.

Installing #

Add to your pubspec.yaml:

dependencies:
  dart_rip_log: ^0.0.1

Then:

dart pub get

Quick start #

import 'dart:io';
import 'package:dart_rip_log/dart_rip_log.dart';

Future<void> main(List<String> args) async {
  final log = await parseRipLogFile(args.first);

  print('Format:  ${log.logFormat.name}');
  print('Tool:    ${log.toolVersion}');
  print('Tracks:  ${log.tracks.length}');
  print('Verified: ${isFullyVerified(log)}');

  for (final track in tracksWithArMismatch(log)) {
    print('  ! Track ${track.trackNumber} did not verify against AccurateRip');
  }
}

Parsing from a string #

final log = parseRipLog(logContent);
if (log.logFormat == RipLogFormat.unknown) {
  // Format could not be identified — handle gracefully.
}

Convenience helpers #

  • isFullyVerified(log)true when every track has AccurateRip status verified.

  • tracksWithErrors(log) — tracks whose TrackErrors.hasErrors is true.

  • tracksWithArMismatch(log) — tracks whose AccurateRip check failed.

  • toJson(log) — JSON-compatible Map<String, dynamic>.

  • RipLog.fromJson(map) — inverse of toJson. All models support round-trip serialisation.

  • compareRipLogs(a, b) — structured per-field diff between two logs, useful for verifying re-rips:

    final diff = compareRipLogs(oldLog, newLog);
    for (final e in diff.trackDifferences) {
      print('${e.path}: ${e.left} → ${e.right}');
    }
    

Command-line tool #

Install globally:

dart pub global activate dart_rip_log

Then:

riplog --format json my_rip.log          # pretty-printed JSON (default)
riplog --format text my_rip.log          # human-readable
riplog --format ndjson *.log             # one JSON per line (jq-friendly)
riplog --summary my_rip.log              # one line per track
riplog -q *.log                          # tab-separated one line per file
riplog -r ~/music/rips/                  # walk directory for *.log
riplog --filter problems log.log         # only mismatch / errored tracks
riplog --fail-on mismatch -q *.log       # exit 1 only on AR mismatch
riplog --color always log.log | less -R  # keep colour through pagers
cat my_rip.log | riplog -q -             # read from stdin
riplog --help                            # full usage

Exit-code policy is controlled by --fail-on:

Policy Exits 1 when…
any default — any AR mismatch or track error counts
mismatch any AR mismatch
errors any track error counts
never never (always exits 0 on successful parse)

2 is always returned for bad arguments or I/O errors. With multiple files the JSON output is an array (one entry per file); ndjson emits one object per line; text / --summary each file is prefixed with # <path>. Colour output respects NO_COLOR and stdout.hasTerminal by default.

Data model #

Class Purpose
RipLog Top-level result — header fields + tracks.
RipLogTrack Per-track quality data (unified across formats).
TrackErrors Per-track error counters.
DriveInfo Optical drive name, read offset, adapter.
LogSource Lineage metadata: byte size, line count, parser, timestamp.
RipLogFormat (enum) eac, xld, cueRipper, whipper, dbPoweramp, unknown.
AccurateRipStatus (enum) verified, mismatch, notInDatabase, notChecked.
RipLogQuality (enum) allVerified, partiallyVerified, mismatches, errors, unknown.

RipLog.quality returns a single-value summary of the whole log. Precedence (most severe first): errors > mismatches > partiallyVerified > allVerified > unknown.

Error tolerance #

The library never throws on malformed content. It may still throw at the file-I/O layer — for example, parseRipLogFile will throw a FileSystemException when given a non-UTF-8 binary file. On truncated, garbled, or partially-unknown input the parser returns a RipLog with whatever it could extract; any parsing warnings are collected in RipLog.errors.

JSON shape #

Calling toJson(log) (or log.toJson()) returns a stable, JSON-compatible Map<String, dynamic>. The shape is pinned by golden tests in test/fixtures/*.expected.json — any intentional change requires regenerating the goldens. Top-level keys:

logFormat, toolVersion, extractionDate, drive, readMode, readOffset,
overread, gapHandling, mediaType, tracks[], accurateRipSummary,
integrityHash, errors[]

Each track includes: trackNumber, filename, peakLevel, trackQuality, copyCrc, testCrc, accurateRipStatus, accurateRipCrcV1, accurateRipCrcV2, accurateRipConfidence, copyOk, errors{}, logFormat. Numeric peak/quality values are fractions in [0.0, 1.0]. Dates are ISO-8601 strings. Optional fields are omitted when null.

Running the tests #

dart test                         # full suite (unit + CLI integration)
dart test --exclude-tags cli      # fast: skip shell-out tests

The test suite covers header/track/footer parsing, AccurateRip variants, per-track error statistics, line-ending tolerance, Unicode filenames (Latin accents, CJK, emoji), a 500-track performance smoke, CLI behaviour, and JSON-shape golden tests.

Contributing #

Issues and pull requests welcome on GitHub. Additional real-world log samples from CUERipper, whipper, and dBpoweramp would be especially valuable for finishing those parsers.

Licence #

Apache-2.0. See LICENSE.

0
likes
160
points
36
downloads

Documentation

API reference

Publisher

unverified uploader

Weekly Downloads

Parses CD rip log files from EAC, XLD, and other rippers into structured, JSON-serialisable quality data (AccurateRip, CRCs, peaks, errors).

Repository (GitHub)
View/report issues

Topics

#cd #audio #parser #ripping #accuraterip

License

Apache-2.0 (license)

More

Packages that depend on dart_rip_log