dart_cue 0.0.5
dart_cue: ^0.0.5 copied to clipboard
A pure Dart CUE sheet parser and serialiser for album, track, and index metadata with lossless round-trip support and no runtime dependencies.
dart_cue #
A pure Dart CUE sheet parser and serialiser. Reads album, track and index metadata into a well-typed model, writes it back losslessly, and tolerates the quirks of real-world CUE files produced by EAC, cdrdao, XLD and friends.
No runtime dependencies. Works on the Dart VM, AOT binaries, Flutter (mobile, desktop, web) and plain Dart web.
On the web,
parseCueFileis not available (there is no filesystem) — fetch the file bytes yourself and callparseCueBytes.
Features #
- Parse from a
String, raw bytes, or a file path. - Serialise a
CueSheetback to CUE text (toCueString) with frame-accurate round-trip. - Full coverage of standard commands:
CATALOG,CDTEXTFILE,PERFORMER,SONGWRITER,TITLE,FILE,TRACK,INDEX,PREGAP,POSTGAP,ISRC,FLAGS,REM(album- and track-scoped). - File types:
WAVE,MP3,AIFF,AIFC,BINARY,MOTOROLA. - Track types:
AUDIO,CDG,MODE1/2048,MODE1/2352,MODE2/2336,MODE2/2352,CDI/2336,CDI/2352,DATA. - Flags:
DCP,4CH,PRE,SCMS,DATA. - MSF (
mm:ss:ff, 75 fps) timestamps with rounding-safeparseMsf/formatMsf. - Automatic
endTimeanddurationderivation per track. - Encoding detection: UTF-8, UTF-16 LE and UTF-16 BE byte-order marks are handled; falls back to Latin-1 for legacy Windows rippers.
- Permissive parsing — malformed timestamps, unknown tokens and misplaced
commands never throw; valid data is preserved. Opt in to
parseCueSheetWithDiagnosticsfor a line-numbered warning list. - Unmodifiable collections on parsed sheets — safe to share across isolates and cache layers without defensive copies.
- Structural
==/hashCode/toStringonCueSheet,CueFileandCueTrack— parsed sheets can be compared, put inSets, or keyed inMaps by their content. - ReplayGain helpers:
replayGainAlbumGain/replayGainAlbumPeakonCueSheetandreplayGainTrackGain/replayGainTrackPeakonCueTrackparse the standardREM REPLAYGAIN_*fields todouble.
Install #
dependencies:
dart_cue: ^0.0.5
Usage #
Parse a file #
import 'package:dart_cue/dart_cue.dart';
Future<void> main() async {
final sheet = await parseCueFile('album.cue');
if (sheet == null) return;
print('${sheet.performer} — ${sheet.title}');
for (final file in sheet.files) {
for (final track in file.tracks) {
print(' ${track.trackNumber}. ${track.title} '
'(${track.duration})');
}
}
}
Parse a string or bytes #
final sheet = parseCueSheet(cueText);
final sheet2 = parseCueBytes(Uint8List.fromList(utf8.encode(cueText)));
Surface diagnostics #
final result = parseCueSheetWithDiagnostics(cueText);
for (final issue in result.issues) {
print(issue); // WARNING: line 3: unknown TRACK type "WEIRD" (defaulting to AUDIO)
}
// result.sheet is still populated — the parser stays permissive.
Round-trip #
final sheet = parseCueSheet(input)!;
final output = toCueString(sheet); // re-parseable, lossless
MSF timestamps #
final d = parseMsf('04:12:37'); // Duration
final s = formatMsf(Duration(minutes: 1, seconds: 5)); // '01:05:00'
Data model at a glance #
CueSheet
├── performer, title, songwriter, catalog, cdTextFile
├── remComments: Map<String, String> // album-level REM
└── files: List<CueFile>
├── filename, fileType
└── tracks: List<CueTrack>
├── trackNumber, trackType
├── title, performer, songwriter, isrc
├── pregap, postgap, flags
├── indices: Map<int, Duration>
├── remComments: Map<String, String> // track-level REM
└── startTime, endTime, duration // derived
CLI #
The package ships a cueinfo executable. Install it globally:
$ dart pub global activate dart_cue
$ cueinfo --help
Or run it from a cloned repo with dart run bin/cueinfo.dart ….
Subcommands #
cueinfo info <file.cue> [--format text|json] # default
cueinfo validate <file.cue> # exit 0 = clean, 1 = issues
cueinfo reformat <file.cue> # canonical CUE to stdout
cueinfo tracks <file.cue> # one line per track
Examples:
$ cueinfo info album.cue --format text
Title : Great Album
Performer : The Artist
...
$ cueinfo validate album.cue
album.cue: OK
$ cueinfo validate broken.cue
broken.cue: TRACK 01: missing INDEX 01
broken.cue: CATALOG "123" is not 13 digits
$ cueinfo reformat messy.cue > clean.cue # normalise formatting
$ cueinfo tracks album.cue
01 03:42:15 The Artist — First Song
02 04:03:30 The Artist — Second Song
validate checks: missing INDEX 01, non-monotonic track numbers,
out-of-range track numbers, empty filenames, missing tracks, and malformed
CATALOG / ISRC values. Exits non-zero on any issue, so it's suitable for
CI pipelines.
Testing #
$ dart test
The suite includes malformed-input fuzzing, immutability contracts, a public
API surface check, and end-to-end fixtures under test/fixtures/ modelled on
EAC, cdrdao, per-track WAV and hidden-pregap layouts.
Author #
Paul Snow
Licence #
Apache License 2.0. See LICENSE.