All notable changes to futureburn will land here. Format roughly follows Keep a Changelog, versioning is SemVer — though while we're pre-1.0 the rules are loose: minor version = a milestone from the README roadmap, patch version = everything else.
Folds the non-driver value of DAEMON Tools (adware now) into futureburn, which already owned the optical layer. The guiding rule — avoid the kernel driver, ship the documented-API cousin — means the virtual-SCSI driver DAEMON Tools sells is deliberately skipped; everything here is plain user-mode work:
rip <drive> <out.iso>— grab a finalized data disc (CD/DVD/BD) to an ISO via SPTI READ (10). Unreadable sectors are retried, then zero-filled and counted so a rip completes on a scratched disc. Verified end-to-end: ripped the burned Dalmatians BD-R back to a 2,460,288-sector ISO that re-mounts clean.convert <image> <out.iso>— BIN/CUE, MDF/MDS, and NRG → ISO. NRG's data extent is read from its NERO/NER5 footer; MDF/NRG sector layout (cooked 2048 vs raw 2352 Mode 1/2) is detected from the CD-ROM sync mark and the 2048-byte payload extracted. Round-trip verified byte-identical for all three formats.mount <image>/unmount <image | X:>— mount via Windows' nativeAttachVirtualDisk(the Tier-A cousin — no driver). ISO/IMG/VHD mount directly; BIN/CUE/MDF/NRG auto-convert to a temp ISO first. futureburn keeps a small mount ledger sounmount <letter>works (Windows exposes no clean letter→image reverse lookup) and cleans up temp ISOs on unmount.erase <drive> [--full]— blank a rewritable: BLANK for CD-RW/DVD-RW, FORMAT UNIT for DVD+RW/DVD-RAM/BD-RE. Built and wired, but not yet verified on hardware (no rewritable disc on the bench — the test drive only had write-once BD-R). Confirm on a CD-RW/BD-RE before trusting it.- New Core:
DiscRipper,ImageConverter,DiscEraser,DiskImageMounter, plus SPTIRead10/ReadCapacity10/Blank/FormatUnit.
Fifth main-window tile surfacing rip / convert / mount / unmount / erase, with a
drive picker, live progress + log, and background-threaded operations. Tile
subtitles now wrap instead of clipping. Tiles carry AutomationProperties.Name
(accessibility + drives the screenshot harness).
scripts/capture-screenshots.ps1 launches the GUI, invokes each tile via UI
Automation, and captures every window to docs/screenshots/*.png with
PrintWindow (per-monitor-DPI-aware, so scaled displays capture at full res).
First real Blu-ray milestone, developed and verified end-to-end on a Pioneer BDR-206 with blank BD-R media:
- BD-R / BD-RE image burning.
SptiDataBurnernow recognises the Blu-ray profiles (0x0041BD-R SRM,0x0042BD-R RRM,0x0043BD-RE) and burns them through the DVD-R Sequential path (RESERVE TRACK → WRITE 12 → CLOSE), with BD's 1× = 4390 KB/s speed unit and a tolerant MODE SELECT (BD-R records sequentially by profile; the CD/DVD Write Parameters page is skipped if the drive refuses it).burn-isoandburn-folderboth get BD for free. - BD-R finalization fix. BD-R SRM finalizes with CLOSE TRACK/SESSION function 6 ("finalize disc"), not function 2 — function 2 is a no-op on BD-R and leaves the disc
Incompleteforever. Verified on the BDR-206: fn 2 → still Incomplete after 5 min; fn 6 → Finalized in ~2 s.finalize <drive>now auto-picks the right function from the loaded profile (with an optional numeric override for probing). bd-author <input> <out.iso>— author a playable Blu-ray (BD-Video) from any video file. BD-legal streams (H.264 ≤L4.1 at a legal frame size, AC-3/DTS/LPCM/TrueHD audio) are muxed with no re-encode; anything else is conformed with ffmpeg (re-encode to H.264 High@4.1 with padding to a legal frame size, transcode non-BD audio to AC-3). Text subtitles are rendered to PGS and chapters are carried over. Output is a UDF 2.50 Blu-ray ISO;--burn <drive>chains straight into the BD-R burn. Muxing/BDMV/UDF work is delegated to tsMuxeR (located, not bundled — Apache-licensed but a portable download);bd-author-infochecks the toolchain.- New
MkvBdPipeline,TsMuxerLocator,TsMuxerRunner.
FfprobeRunner.TryIntthrew on 64-bit chapter IDs. MKV chapters carry a 64-bitChapterUIDthat ffprobe reports asid;JsonElement.GetInt32()threwFormatExceptionon any value pastInt32, killing every probe of such a file — which also affecteddvdv-author. Now usesTryGetInt32and falls back gracefully.
- Ported
.gitlab-ci.ymlto.github/workflows/release.yml. On each push tomainawindows-latestjob builds the solution, runs the xUnit suite, and publishes the two self-contained single-file x86.exes (CLI + GUI) as the assets of a rollinglatestpre-release. GitHub-hosted standard runners are free with unlimited minutes on public repos, so this can stand in for the self-hosted buildforever runners. The GitLab SMBdeploystep has no cloud equivalent (runners can't reach the LAN share) — the binaries live on the GitHub Release instead.
Housekeeping pass, no behaviour changes:
- Mascot icon. The cool-CD character (
src/Futureburn.Gui/app.ico) is now the program/taskbar icon, wired in via<ApplicationIcon>. The source art's white background was flood-filled to transparency from the edges — so the character's own whites (sneakers, disc highlights) survive while the background drops out — then squared and rendered into a 16–256 px multi-resolution.ico. docs/folder. New how-it-works documentation: architecture, burn engines, audio CDs, data discs, video discs, LightScribe, the CD-Text/gapless situation, and a full CLI reference.docs/README.mdis the index.- README cleanup. The bloated 27-bullet "What works today" list is now a concise grouped feature list. CD-Text and
--gaplessmoved to a new "Coming later" section (they need an SAO-capable drive — seedocs/cd-text-and-gapless.md). Fixed stale text claiming three GUI tiles are placeholders (all four are live) and corrected the outdated repository-layout tree. - Refreshed screenshots. All four window screenshots updated to v0.0.54 (mascot icon now visible in the title bars), plus a new Burn Label (LightScribe) screenshot in the README.
- CI/CD on the project's own GitLab. Added
.gitlab-ci.ymlforbuildforever.cloud— Windows-runner pipeline that builds, runs the xUnit suite, publishes self-contained single-file x86 CLI and GUI.exes per push to main, and drops them on thereleasesSMB share at/mnt/releases/futureburn/<ref>/via the dedicatedgitlab-ciSMB user (creds via masked CI variables, mounted withNew-PSDrive -Credential). Bypassed aPublishSingleFile+ WPF + x86 landmine —SetWindowLongWndProcDllNotFoundException— withIncludeAllContentForSelfExtract=true. Newscripts/install_dotnet8_windows_runner.pyautomates the runner-side machine-wide .NET SDK install via Proxmoxqm guest exec.originis wired to fan-push to both GitHub and buildforever from one command.
The DAO/SAO cue-sheet builder (SptiCueSheet) had three format bugs that made a drive reject SEND CUE SHEET with sense 0x5/0x26/0x00 (INVALID FIELD IN PARAMETER LIST) — so --gapless and CD-Text never actually worked:
- It BCD-encoded track numbers and MSF times. The SEND CUE SHEET parameter list is plain binary — the v0.0.41 "BCD fix" was backwards. (cdrecord and libburn both emit binary; confirmed against MMC-5 §6.26.)
- It emitted A0/A1/A2 pointer descriptors. A cue sheet has none — the drive derives first/last track and the lead-out from the descriptor stream. The sheet is now: one lead-in entry, two per track, one lead-out entry.
- DATA FORM on the lead-in and lead-out entries was
0x00; it must be0x01(audio pause).
The cue sheet now matches what cdrecord/libburn emit, byte for byte (worked example covered by a test). New cuesheet-probe <drive> diagnostic sends cue sheets to a drive and reports acceptance — SEND CUE SHEET writes nothing, so it's free to run against a blank disc.
With the corrected cue sheet, the test-bench GE20LU10 (FE06) still rejects SEND CUE SHEET — and rejects all seven structurally-different cue sheets cuesheet-probe tries, down to a single-track minimal one. This drive doesn't do DAO/SAO cue-sheet recording. CD-Text rides in the SAO lead-in, so it can't be burned on this drive; it needs an SAO-capable writer. The cue-sheet fix is spec-correct (MMC-5 + cdrecord + libburn) but consequently can't be hardware-validated here. No CD-R was consumed — SEND CUE SHEET writes nothing.
Multi-track audio CD-Rs played everywhere they were tested, but READ DISC INFORMATION reported them as Incomplete/appendable, never Finalized. Root cause: the Write Parameters mode page (0x05) set the Multi-session field to 11b — "next session allowed, leave the disc appendable" — under a code comment that wrongly claimed 11b meant "final session." It's the inverse; finalizing a CD-R needs 11b's opposite, 00b. There is no separate CD "close disc" command — the Multi-session bits are what decide whether CLOSE SESSION finalizes or leaves the disc appendable. Fixed to 00b, verified against the MMC-5 Write Parameters page and libburn's mmc_compose_mode_page_5.
Hardware validation pending the next audio-CD burn — but it's a one-byte inverted-flag fix, cross-checked against libburn's source.
v0.0.50's separate Drives tile overlapped almost entirely with CD Info, which already enumerates every drive and inspects the loaded disc. So they're merged: CD Info now also shows a one-line suggested action per drive (blank → ready to burn, finalized → ready to rip, has-data → ...) — the one genuinely new bit Drives had. The standalone Drives window is gone and the main-window tile grid is back to a clean 2×2.
A new Drives tile on the main window opens a dashboard listing every optical drive, the disc currently in it, its state (blank / finalized / has-data / erasable, read straight from the drive over SCSI), and a suggested next action. CD Info does the deep single-disc inspection; this is the quick all-drives overview. The main-window tile grid grew from 2×2 to 3×2 to fit it.
cd-lookup now falls back to MusicBrainz's fuzzy TOC search when the exact disc-ID lookup misses. A burned disc almost never reproduces a pressed CD's TOC exactly, so the exact-ID lookup failed on most home-burned and many older discs; the discid/-?toc= endpoint matches releases whose track layout is close and identifies far more of them. Results are labelled as fuzzy matches and capped at the first few pressings (a fuzzy search can return dozens).
Verified against the live MusicBrainz API: a 12-track TOC fuzzy-matched Nirvana's Nevermind, response parsed cleanly.
Bitmap subtitle tracks (VobSub, PGS) are now carried into the DVD instead of being detected-and-skipped. ffmpeg re-encodes them straight to the DVD subpicture format in the transcode (-c:s dvdsub) — bitmap→bitmap, which ffmpeg allows; text→bitmap it doesn't, so text subtitles still go via spumux. The dvdauthor <subpicture> declarations are ordered bitmap-then-text to match the muxed stream order, and the 32-subpicture DVD limit is shared across both kinds.
Verified end-to-end: a DVD rip's VobSub track → dvdv-author → a validate-folder-confirmed DVD-Video whose VOB carries the dvd_subtitle stream.
dvdv-author --menu (and a "DVD menu" checkbox on the GUI's Burn Blu-ray / DVD tile) authors a navigable menu instead of auto-playing the disc:
- A root menu — "Play Movie", plus "Scene Selection" when the disc has chapters.
- A scene-selection menu — one button per chapter (up to 12) plus a Back button.
DvdMenuBuilderrenders the menu art with System.Drawing: the full-colour background, and the transparent highlight/select overlays (identical shapes, ≤3 colours, anti-aliasing off — honouring the DVD 4-colour subpicture rule, the thing most likely to fail on a first attempt).- Menu backgrounds become short MPEG-2 stills via ffmpeg;
spumux -m dvdmuxes the button-highlight subpictures;DvdauthorRunner.BuildMenuXmlemits the VMGM root menu + VTSM scene menu with the navigation commands (jump titleset 1 title 1,jump title 1 chapter N,call vmgm menu, ...). - Auto-chapters — when
--menuis used on a rip with no chapters, ~8 evenly-spaced chapter marks are generated so the scene menu is actually useful.
- 6 new
DvdMenuTests. 183 tests pass. Verified end-to-end: a 3-chapter MKV →dvdv-author --menu→ avalidate-folder-confirmed DVD-Video whose root and scene menu VOBs both carry the button-highlight subpicture stream.
Menu authoring is verified to produce a well-formed disc; on-TV menu navigation hasn't had a dedicated set-top-player run yet.
Every common file dialog in the WPF GUI (Add files, Choose ISO/folder/video, Choose image, Save M3U8) hung hard after the first one opened in a session — the second OpenFileDialog / OpenFolderDialog / SaveFileDialog shown on the WPF UI thread froze inside the native dialog (CommonItemDialog.RunDialog → native, never returning; Windows reported AppHangB1). A captured stack of the frozen UI thread confirmed the freeze sat in the native common-item-dialog modal loop.
- New
FileDialogshelper runs every common dialog on its own fresh STA thread, so each one is "the first" on a clean thread; the UI thread just awaits and keeps pumping. All seven dialog call sites across the three windows now route through it.
- README screenshots refreshed — the four-tile main window, plus a new shot of the Burn Blu-ray / DVD window with its MKV→DVD "Choose video" workflow.
The CD-Text, gapless, and MKV→DVD work was all CLI-only. Now it's clickable.
MkvDvdPipeline— the MKV→DVD orchestration (probe → transcode → spumux → dvdauthor) was extracted out of the CLI intoFutureburn.Core.Authoring, with log + 0..1 progress callbacks, so the CLI and GUI drive the same code.dvdv-authoris now a thin wrapper over it.- Burn Blu-ray / DVD tile → "Choose video..." — pick an MKV/MP4/AVI and the window transcodes + authors a real DVD-Video, builds the UDF image, and is ready to burn. The tile's "drop your movie" promise is finally true.
- Burn Audio CD tile → Gapless + CD-Text — a checkbox row with Gapless (DAO) and CD-Text, plus album/artist fields. Ticking CD-Text enables the fields and implies gapless. Track titles come from the playlist.
- 15 new tests for the extracted pipeline helpers (subtitle classification, aspect guessing, ffmpeg progress parsing). 177 tests pass.
First end-to-end hardware run of the MKV→DVD pipeline (Wallace & Gromit's The Wrong Trousers MKV → a finalized DVD-R) surfaced two real bugs:
FsImageBuildercapped image size at CD capacity. IMAPI2FS defaults its image-size limit to a CD, so building a UDF image larger than ~700 MB failed with "...larger than the current configured limit" — every DVD-Video or large data DVD would have hit this. Now setsFreeMediaBlockspast Blu-ray capacity; the burn step enforces the actual disc's real capacity.SptiDataBurnerreported a false failure on DVD finalization. It trustedCLOSE SESSION's return code, but the GE20LU10 keeps returning sense0x5/0x72/0x03(session fixation error — incomplete track) while it finalizes the lead-out asynchronously, which can take minutes. The burn was reported FAILED on a disc that had in fact finalized seconds later. Now pollsREAD DISC INFORMATIONuntil the disc reports Finalized — the same proven pattern the audio burner uses.
The MKV→DVD pipeline is now hardware-proven: a 30-minute 1080p MKV transcoded, subtitle-muxed, authored, imaged, and burned to a DVD-R that reads back as a well-formed, finalized DVD-Video. 162 tests pass.
dvdv-author graduated from "transcode one title" into a real pipeline: feed it an MKV (or MP4, AVI, ...) and it carries the structure through to a hardware-playable DVD-Video — chapters, every audio track, and subtitles — optionally burning the disc in the same command.
- Chapters —
FfprobeRunnernow runs-show_chaptersand parses chapter markers; they're authored as real DVD chapter stops (next/previous-chapter works on the remote). - Multiple audio tracks — the transcode maps every audio stream (up to the DVD limit of 8) to AC-3; each is declared in the dvdauthor XML with its language so players show language labels.
- Subtitles — text subtitle tracks are extracted to SRT and muxed into the program stream as DVD subpicture streams via
spumux(newSpumuxRunner). Bitmap subtitles (VobSub/PGS) are detected and skipped for now. - One-command burn —
dvdv-author <in> <out> --burn <drive>authors then builds a UDF image and burns it. The whole MKV-to-disc path in one step. DvdauthorRunnergained aDvdTitleSpec+BuildXmlthat emit chapter lists, per-stream<audio>/<subpicture>language declarations;IsoLanguagemaps ISO 639-2 (eng) to the two-letter codes (en) DVD-Video wants.
DvdauthorLocatornever found DVDStyler's bundleddvdauthor.exe: the CLI builds as x86, so under WOW64SpecialFolder.ProgramFilesresolves to "Program Files (x86)" and the 64-bitC:\Program Files\DVDStyler\was never checked. Now also consults%ProgramW6432%.
- 30 new tests: ffprobe chapter/stream parsing, dvdauthor chapter-time formatting + XML generation, spumux XML, ISO language mapping. 162 tests pass. Pipeline validated end-to-end on a synthesized MKV (3 chapters, 2 audio, 1 subtitle) →
validate-folderconfirms a well-formed DVD-Video with all streams present.
Authoring is verified against real tools and a real MKV. The --burn step reuses the already-proven data-burn path but hasn't had a dedicated DVD-R hardware run. Bitmap subtitles and DVD menus aren't supported yet.
Encode artist + album + per-track titles into the disc lead-in so car stereos and standalone players show "Whatever You Want" instead of "Track 16".
Futureburn.Core/Spti/SptiCdText.cs— the CD-Text pack encoder. Builds the 18-byte packs (4-byte header + 12-byte text + CRC-16), splits the per-track text streams into 12-byte payloads with correct track-number and character-position fields, and emits the mandatory three0x8Fsize-info packs. CRC-16 is the CCITT variant (poly 0x1021, init 0x0000, complemented, big-endian) verified against a cataloged known-answer. Also does the 18→24-byte 6-bit subchannel expansion and builds the full lead-in image (packs cycled to fill every 96-byte lead-in sector) — both matching libburn'sburn_write_leadin_cdtext().SptiCueSheet.BuildAudioCdgained acdTextflag — when set, the A0/A1/A2 lead-in pointer entries carry DATA FORM0x41(the0x40bit tells the drive CD-Text is coming).SptiDevice—ReadAtipLeadInStartLba()(READ TOC/PMA/ATIP format 0100b → the negative lead-in start LBA) andWriteCdTextLeadIn()(WRITE 10 of 96-byte blocks to negative lead-in LBAs).SptiAudioCdBurner.ExecuteBurn— a CD-Text lead-in write phase, inserted after SEND CUE SHEET and before the audio, using the libburn-style cooked-SAO approach (no DataBlockType switching; the audio phase is byte-for-byte unchanged).- CLI:
burn ... --engine spti --cdtext --album NAME --artist NAME(auto-enables--gapless; track titles come from the playlist's#EXTINFlines). Newcdtext-dump <playlist>command prints the encoded packs offline — no drive, no disc — for verification before a real burn.
- 23 new tests (
SptiCdTextTests+ 2 inSptiCueSheetTests): CRC known-answer, the byte-level worked example,0x8Fpack-count correctness, 6-bit expansion against libburn's worked example, lead-in image cycling, decode round-trip. 133 tests pass.
The pack encoder is fully verifiable offline and well-tested. The lead-in transport — negative-LBA 96-byte WRITEs — has not yet been validated on real hardware; CD-Text-in-SAO support is drive-dependent. Burn-ready, not burn-proven. Use cdtext-dump and a reference tool to sanity-check the packs first.
DVD-Video discs that play in standalone hardware DVD players (PS4 etc.) require fully spec-compliant IFO files with TT_SRPT, VTS_PGCI, VTS_C_ADT, and VTS_VOBU_ADMAP — the last of which requires scanning the VOB for NAV packets to find every VOBU boundary. That's its own multi-session subsystem. Pragmatic answer for "make discs that work today": detect and shell out to dvdauthor, the canonical open-source DVD-Video authoring tool.
Futureburn.Core/Tools/DvdauthorLocator.cs— finds dvdauthor on PATH, Chocolatey, Scoop, common manual install paths.Futureburn.Core/Tools/DvdauthorRunner.cs— invokes dvdauthor with a small XML control file describing one title (jumppad on, vmgm jump-to-title-1 trigger so the disc auto-plays on insert).- CLI
dvdauthorcommand — reports presence/version (parallel toffmpeg). dvdv-authoris now bifurcated:- dvdauthor mode (default when dvdauthor is detected): ffmpeg → MPEG-PS → dvdauthor → real IFOs → hardware-playable disc.
- Skeleton mode (fallback): only fires when dvdauthor isn't installed, or you pass
--skeleton-only. Same as v0.0.21's behavior — software-player-only. - The chosen mode is announced in the output up front so you know what kind of disc you're getting.
- dvdauthor is GPL — same licensing posture as ffmpeg. We don't bundle it; users install via
choco install dvdauthor,scoop install dvdauthor, or the Sourceforge binary.
Futureburn.Core/Authoring/DvdIfoBuilder.cswrites minimal-but-recognizable VIDEO_TS.IFO and VTS_##_0.IFO skeletons (2048 bytes each: "DVDVIDEO-VMG" / "DVDVIDEO-VTS" signatures, spec version 1.0, volume / title-set count, provider id; the rest of the navigation tables are zero).dvdv-author <input-video> <output-folder>CLI command. Runs ffmpeg-target ntsc-dvd(or pal-dvd with--pal) to transcode to MPEG-2 + AC-3 in DVD-PS, places the result asVIDEO_TS/VTS_01_1.VOBcapped at the per-VOB 1 GB DVD-Video limit, writes IFO/BUP pairs for both VMG and VTS_01_0, creates the spec-required emptyAUDIO_TS/folder.
- Same Wallace & Gromit short used for the VCD test (~24 min, 1080p H.264) → 695 MB MPEG-2/AC-3 DVD payload in 34 sec via ffmpeg.
validate-folderrecognizes the result as well-formed DvdVideo (after a related fix below).
DiscFolderValidatorwas misclassifying pure DVD-Video discs asDvdAudioVideoHybridwhenever the spec-required emptyAUDIO_TS\folder was present. Now distinguishes "AUDIO_TS exists with files" (real DVD-Audio content) from "AUDIO_TS exists empty" (DVD-Video spec compliance). The DvdVideo branch's findings now affirm "AUDIO_TS\ folder present (empty is normal for pure DVD-Video)" so users don't worry it should have content.
- 6 new
DvdIfoBuilderTests, 1 newDiscFolderValidatorTestsfor the empty-AUDIO_TS case. Total 108 tests.
The IFO files we write are SKELETONS — signature + version + a couple of fields, otherwise zero. A real DVD-Video IFO has nested tables (TT_SRPT, VTS_PTT_SRPT, VTS_PGCI, VTS_C_ADT, VTS_VOBU_ADMAP) that tell standalone DVD players how to navigate the disc. Building the VOBU address map alone requires scanning the VOB for NAV packets. That level of authoring is its own multi-session subsystem (or just call dvdauthor externally — the open-source GPL DVD-Video authoring tool that does this properly).
What our skeletons get you: a folder structure that plays in VLC, MPC-HC, and most software DVD readers (they accept the VOBs directly). What they don't get you: standalone DVD player playback. For that, author with DVDStyler/DVDFlick/dvdauthor and burn-folder the result.
- Drag-reorder in the track list. Custom WPF DragDrop with our own
"FuturreburnTrack"data format (so it doesn't conflict with the Window-level Drop that accepts files / folders / playlists). DragOver shows Move; Drop computes the target row and reorders the ObservableCollection. - Rename: F2 on a selected row, double-click, or the new "Rename" toolbar button — opens a small reusable
TextInputDialogseeded with the current title. MadeTrackItem.Titlemutable to support live updates. - Audio preview: ▶ Play / ■ Stop toolbar buttons, NAudio
MediaFoundationReader+WaveOutEvent. Auto-resets on PlaybackStopped. Disposes on window close.
Futureburn.Core/Authoring/VcdInfoBuilder.csandVcdEntriesBuilder.cswrite the binary 2048-byteINFO.VCDandENTRIES.VCDfiles per the VCD 2.0 White Book layout. ToBcd + LbaToMsfBcd helpers handle the CD-time conversions.vcd-author <input-video> <output-folder>CLI command. Locates ffmpeg, runs-target ntsc-vcd(orpal-vcdwith--pal) to transcode the input to MPEG-1 video + MP2 audio in MPEG-PS, places the result atMPEGAV/AVSEQ01.DAT, and writes theVCD/INFO.VCD+VCD/ENTRIES.VCDcompanions. Result can beburn-folder'd.
- Synthetic 5-second 320×240 test video → ffmpeg → 846.54 KB AVSEQ01.DAT (MPEG-1 + MP2 muxed). INFO.VCD + ENTRIES.VCD both 2048 bytes.
validate-folderrecognizes the result as a well-formed VideoCd structure.
- 12 new
VcdBuilderTests(signature/length checks, profile/version, album-label padding + truncation, BE16 volume fields, PAL flag, BCD encoder, LBA→MSF). Total 101 tests.
- CD-Text writing was on the same request batch but is a separate ~300+ line subsystem (binary subchannel R-W generation + SCSI WRITE 12 in raw mode). Holding for its own dedicated turn.
- Strict-spec VCD multi-track CD writing (file system on track 1, video on tracks 2+) — what older standalone VCD players require. Our SPTI data path writes single-track. The validator surfaces this caveat as a finding when it identifies a VCD folder.
- ffmpeg / ffprobe runtime integration.
Futureburn.Core/Ffmpeg/{FfmpegRunner,FfprobeRunner}.cs:FfmpegRunnershells out to ffmpeg.exe with arbitrary args, streams stderr line-by-line via callback. Foundation for transcoding pipelines (DVD-Video / VCD / DVD-Audio authoring will all sit on top of this).FfprobeRunnerrunsffprobe -print_format json -show_format -show_streamsand parses the JSON into typedFormatInfo+StreamInforecords. Handles audio + video streams, embedded tags, optional fields.probe <file>CLI command now augments the basic NAudio readout with container/codec/bitrate/tags from ffprobe when it's installed. Silently skipped when ffmpeg isn't there.
FfmpegLocatorextended for winget installs. Now finds ffmpeg under%LOCALAPPDATA%\Microsoft\WinGet\Packages\Gyan.FFmpeg*\ffmpeg-*\bin\ffmpeg.exe(the path Gyan.FFmpeg uses) and theMicrosoft\WindowsApps\shim location. Validated against a freshwinget install Gyan.FFmpeginstall.- Burn Audio CD GUI tile — major UX upgrade:
- Drag-and-drop any combination of audio files, folders, or
.m3u/.m3u8playlists onto the window. Files added directly. Folders scanned for supported audio. Playlists parsed with our existingPlaylistParser. - Add folder... button (uses .NET 8's
OpenFolderDialog). - Load M3U... button + corresponding Save M3U8... button. The Save button writes an extended M3U8 with
#EXTINFdurations + titles you can hand back tofutureburn burn. - Fits-on-disc indicator: shows whether the current track total fits a 74-min CD-R, needs an 80-min CD-R, or exceeds standard capacity (with overage in minutes).
- Estimated burn time at the currently-selected speed, recomputed live when you change the Speed dropdown. Adds ~30 sec for finalization overhead.
- Drag-and-drop any combination of audio files, folders, or
- 3 new
FfprobeParseTestscovering AAC/M4A audio streams, MKV with H.264 video + AC-3 audio, and missing-optional-fields handling. Total 83 tests.
None of the actual authoring (transcoding + IFO/BUP/VOB / INFO.VCD generation) lands in this commit — those are still long-arc projects. What does land are foundational pieces that all three authoring paths will use:
Futureburn.Core/Tools/FfmpegLocator.cs+ffmpegCLI command. Locates ffmpeg on PATH, ProgramFiles, ProgramFilesX86, %LOCALAPPDATA%\Programs, C:\ffmpeg, Chocolatey, Scoop. Reports the version line. Documents which package managers can install it. We don't bundle ffmpeg (LGPL/GPL licensing concerns for our MIT distribution).Futureburn.Core/Fs/DiscFolderValidator.cs+validate-folderCLI command. Recognizes the well-known disc-folder structures (VIDEO_TS, AUDIO_TS, VCD, SVCD, BDMV) AND validates the structural details — VIDEO_TS.IFO + .BUP pairing, AOB presence, AVSEQ*.DAT presence, etc. Reports findings + issues. Catches "almost a DVD-Video disc but missing VIDEO_TS.BUP" before a disc gets wasted.cd-infonow uses the same validator for its disc-type label, so CLI + GUI agree on what a disc is. VCD and SVCD are now explicitly recognized (was just "Data CD/DVD" before).
- ffmpeg detection: correctly reports "not found" + install instructions on the user's machine (no ffmpeg installed yet).
- DVD-Video validation: synthetic folder with VIDEO_TS.IFO + VTS_01_1.VOB but no .BUP correctly flagged.
- VCD validation: synthetic folder with INFO.VCD + ENTRIES.VCD + AVSEQ01.DAT recognized as well-formed VideoCd, with the Mode-2-sectors caveat surfaced as a note.
- 12 new
DiscFolderValidatorTestscovering each disc type + a few malformed cases. Total 80 tests.
User asked specifically about VCD. Same answer as DVD-Video and DVD-Audio: needs authoring (MPEG-1 video + MPEG-1 Layer II audio + MPEG-PS muxing + binary INFO.VCD/ENTRIES.VCD/etc.). One additional VCD-specific quirk: spec-compliant VCDs use CD-ROM XA Mode 2 Form 2 sectors for video tracks (2324 user bytes), while our SPTI data path writes Mode 1 (2048 bytes). In practice most modern players accept Mode-1-burned VCDs; older standalone VCD players may not. The validator surfaces this as a note.
- BIN/CUE data-mode burning. New
Futureburn.Core/Image/{CueSheet,CueSheetParser,BinCueImageStream}.cs:CueSheetParseris a minimal text-mode .cue parser. Single-FILE sheets only. SupportsMODE1/2048,MODE1/2352, andAUDIOtrack types; silently ignoresPERFORMER/TITLE/REMetc.BinCueImageStreamexposes a.bin's user-data portion as a 2048-byte-per-sector stream — forMODE1/2352it strips the 12-byte sync + 4-byte header and 288-byte ECC per sector and emits just the 2048-byte payload, so downstream code is identical to ISO burning.SptiDataBurner.Plan()now detects.cueextensions and resolves to the referenced.bin. Audio BIN/CUE is rejected with a clear message (on the roadmap).burn-isoCLI command accepts.cuefiles transparently — no separate command needed.
- MusicBrainz disc lookup. New
Futureburn.Core/Net/MusicBrainz.cscomputes the canonical MB disc ID from a TOC (SHA-1 over the standard hex-string format, with the URL-safe base64 substitutions+ → .,/ → _,= → -) and queries the public MB API at/ws/2/discid/{id}. Parses the JSON response into typed releases + tracks, handles multi-artistjoinphrasefields. CLI:cd-lookup <drive>. - 17 new unit tests across
CueSheetParserTests(8) andMusicBrainzTests(9) — total 68 tests.
- Live MusicBrainz lookup on the audio CD currently in F:\ correctly identified it as OutKast — Aquemini (16 tracks, 1998), with full per-track titles. Algorithm matches the documented MB spec exactly.
This commit was driven by a request that included DVD-Video and DVD-Audio authoring. Those are full subsystems on their own:
- DVD-Video from MKV = MPEG-2 video transcoding + AC-3 / LPCM audio transcoding + IFO/BUP/VOB authoring + UDF burn. Realistically requires ffmpeg integration. Months, not weeks.
- DVD-Audio from album = LPCM AOB authoring + ATS_##_#.IFO authoring. Smaller than DVD-Video but still substantial; obscure tooling.
- NRG / MDS / CDI / CCD image formats — each is a proprietary container with its own header format. Doable but lower priority than BIN/CUE which we just added.
For DVD-Video and DVD-Audio burning today: author the VIDEO_TS / AUDIO_TS folder structure with an external tool, then burn-folder it — the IMAPI UDF generator handles the file system and the disc plays itself in standalone players.
- Folder → ISO image builder. New
Futureburn.Core/Fs/FsImageBuilder.cswraps Windows'IMAPI2FS.MsftFileSystemImageCOM via dynamic dispatch (same pattern as our IMAPI v2 work — no NuGet wrappers). Builds ISO 9660 + Joliet + UDF in any combination, configurable volume label, sequential-byte output to either aStreamor a file path. - CLI:
mkiso <folder> <output.iso>builds the image to disk. Flags:--label NAME,--fs all|iso|joliet|udf. - CLI:
burn-folder <folder> <drive>does mkiso + burn-iso in one step (writes to a temp ISO, burns it, cleans up). Flags:--label,--fs,--speed,--dry-run,--yes,--keep-iso. - GUI: BurnImageWindow gains a Choose folder... button. Builds the ISO in the background (Task.Run + Dispatcher progress updates), displays the source folder + temp ISO path together, cleans up the temp file when the window closes.
- Built a 348.63 MB / 178,496-sector ISO from the 5-track whale-album folder. Mounted it via Windows (
Mount-DiskImage); all 6 files (5 WAVs + playlist.m3u8) readable with correct sizes. ISO 9660 magic "CD001" present at byte 0x8001.
- Initial implementation had wrong
FsiFileSystemsenum values (guessed 0x02/0x04/0x08; spec says 0x01/0x02/0x04). IMAPI2FS rejected the bogus combo with "value specified for parameter 'newVal' is not valid." Fixed and noted with a// must match IMAPI2FS's FsiFileSystemscomment so we don't drift again.
- ISO image burning to blank CD-R or DVD-R via raw SCSI (no IMAPI involved). New
Futureburn.Core/Spti/SptiDataBurner.csplus CLI commandburn-iso <iso> <drive>with--dry-run,--speed Nx,--yesflags. Detects disc type from the loaded profile and picks CD-data or DVD-data MODE SELECT settings appropriately. WRITE 12 in 32-sector (64 KB) chunks with the same retry-on-Win32-121 logic the audio burner uses. SptiDevice.ConfigureForDataCd()/ConfigureForDataDvd()— Mode Page 0x05 setup for data writes (Mode 1, 2048 bytes per sector, BUFE on, TAO for CD / SAO for DVD).- Burn Blu-ray / DVD GUI tile is real.
BurnImageWindow.xamllets you choose an ISO, pick a drive + speed, and burn. Same background-thread + Dispatcher pattern asBurnAudioCdWindow. Shows which standard disc capacities the chosen image fits on (CD-R / DVD-R / DVD-R DL / BD-R). - README's "What's coming" list reorganized to clarify the realistic next steps: folder → ISO builder, then MKV → DVD-Video transcoding (the latter being a separate large subsystem). Blu-ray burning waits for hardware.
- ISO burning assumes the image is pre-authored. We don't build the file system from a folder yet — that's a separate (smaller) future task using either IMAPI's
MsftFileSystemImageor our own UDF/ISO 9660 writer. Building DVD-Video discs from raw video files is a much bigger task involving MPEG-2 encoding and IFO/BUP/VOB authoring; that's the long-arc goal for the Burn Blu-ray / DVD tile.
- CD Info GUI tile now reads real disc info via SPTI. When you select a drive with a disc loaded, the details pane shows: disc finalization status, last session state, session count, disc type, layout (audio CD / data / mixed), and a full track listing with per-track type and duration. Same data the CLI's
cd-infocommand surfaces, just clickable. - Failures degrade gracefully — if SCSI pass-through is unavailable for any reason, you still see the IMAPI-based info above it.
SptiDevice.ReadDiscInformation()— SCSI MMC READ DISC INFORMATION (opcode 0x51). Returns Disc Status (Empty/Incomplete/Finalized/Other), State of Last Session (Empty/Incomplete/Reserved/Complete), session count, disc type, and erasable flag. This is the authoritative answer to "is this disc finalized?" — finalized + complete = will play in any standalone CD player.cd-infonow reports the disc-info fields above before the TOC, with a friendly "will play in standalone players" / "NOT fully finalized" annotation.
- Initial bit parsing of READ DISC INFORMATION byte 2 was wrong — had Disc Status in bits 7-6, but per MMC-6 it's in bits 1-0 (and State of Last Session is in bits 3-2). Caught when a known-finalized 19-track audio CD reported "Empty" with "Reserved" session state. Fixed to match the spec.
- The user's previously-burned puck disc (CDBurnerXP from the same playlist) reports Disc Status: Finalized, Last Session: Complete — definitive proof the disc is structurally fine. Any playback failure (VLC's longstanding Windows CD-DA bugs being the prime suspect) is a player-side issue.
SptiDevice.ReadToc()+cd-info <drive>CLI command. SCSI READ TOC/PMA/ATIP via SPTI. Returns first/last track numbers, lead-out LBA, plus per-track type (audio vs data, with pre-emphasis flag), start LBA, length, and duration. Works on any CD with a readable TOC — audio CDs, mixed-mode, finalized CD-Rs.
- Read the puck disc (a finalized 19-track audio CD that CDBurnerXP burned from the user's same playlist earlier). Result: 19 audio tracks, lead-out at LBA 281,457, total 01:02:32. Matches our Plan() output for the same playlist track-for-track. End-to-end proof that our pipeline computes the right disc layout.
- IMAPI v1 burn engine.
Futureburn.Core/Imapi/AudioCdBurnerV1.csandImapiV1Interop.cs. Typed[ComImport]declarations forIDiscMaster,IDiscRecorder,IEnumDiscRecorders,IRedbookDiscMaster. Used as a fallback for drives where IMAPI v2's TAO path returns a SCSI mode-page error on blank CD-Rs (LG GE20LU10 firmware FE06 is the known case). Selected viafutureburn burn ... --engine v1. - CLI:
imapi-v1-info— non-destructive diagnostic that opens v1, enumerates recorders, and reports Redbook capabilities. Validated on the LG drive: v1 sees the drive correctly while v2 chokes. - SPTI scaffold.
Futureburn.Core/Spti/{SptiNative,MmcOpcodes,SptiDevice,SptiBurnEngine}.cs. P/Invoke forIOCTL_SCSI_PASS_THROUGH_DIRECT, MMC opcode constants, drive-opener that talks raw SCSI.SptiBurnEngineis a stub for now — full audio CD burn via raw SCSI is the work that comes if v1 also fails on someone's hardware. - CLI:
spti-info <drive>— runs a SCSI INQUIRY via SPTI. Validated end-to-end on the LG drive: returns vendor/product/firmware identical to IMAPI's view, proving the SPTI pipeline works.
BurnPlantime displays were usingmm\\:ssformat which capped at 59:59 — burned playlists over an hour showed mangled minutes ("14:00" for a 74-min disc). Now useshh\\:mm\\:ss.- Wrong field referenced when computing v1 plan total time (was reading disc capacity instead of track sum).
- IMAPI v1 interfaces are vtable-only IUnknown. PowerShell can't talk to them at all. Typed
[ComImport]is the only way in. - The LG GE20LU10 FE06 returns "mode page not present" from
IDiscFormat2TrackAtOnce::PrepareMediafor blank CD-R, even withAcquireExclusiveAccess(force=true)andDisableMcn. Bare PowerShell IMAPI hits the same error — it's not our code. - ImgBurn talks to the same drive successfully because it uses SPTI directly (not IMAPI). That's why we have the SPTI scaffold ready.
- IMAPI 2 IIDs do NOT all share the
7F64second segment that IDiscMaster2 uses. Look up actual GUIDs fromHKLM:\SOFTWARE\Classes\Interface\rather than guessing.
Futureburn.Core/Imapi/AudioCdBurner.cs— two-phase burn pipeline.Plan()validates the request and returns aBurnPlan;ExecuteBurn()actually writes. UsesMsftDiscFormat2TrackAtOncevia dynamic COM. No typed[ComImport]interfaces required — every TAO property we touch (NumberOfExistingTracks,TotalSectorsOnMedia,FreeSectorsOnMedia,SupportedWriteSpeeds) lives onIDiscFormat2TrackAtOncedirectly.Futureburn.Core/Imapi/ManagedIStream.cs— adapts a .NETStreamto a COMIStreamso we can pass it toAddAudioTrack. Marked[ComVisible(true)]because the assembly default is false.Futureburn.Core/Audio/CdPaddedAudioStream.cs— wraps a CD-format WAV file as raw PCM bytes padded to 2352-byte CD sectors (IMAPI's hard requirement).- CLI:
burn <playlist> <drive>with--dry-run,--speed Nx,--force,--yes/-y,--keep-tempflags. - Smart pre-check: if
MsftDiscFormat2Datacan't read the loaded CD-R/CD-RW's capacity, we abort with a friendly "this disc isn't fresh" message instead of lettingPrepareMediafail later with a cryptic SCSI mode page error. - Tracks already in CD format (44.1k / 16-bit / stereo WAV) are passed through directly — no pointless re-decode of huge WAV files.
- IMAPI track minimum-length enforcement (4 seconds = 300 sectors) to refuse tracks too short for CD-DA.
IDiscFormat2TrackAtOnce.PrepareMedia()must be called beforeNumberOfExistingTracks, sector counts, andSupportedWriteSpeedsare readable. PrepareMedia reserves the drive but writes nothing — releasing the COM object withoutReleaseMediaaborts the session cleanly (noAddAudioTrackwas issued, so nothing was committed to the disc).- For our test CD-R (already had data), both
MsftDiscFormat2DataandMsftDiscFormat2TrackAtOncerefused to read it — exactly the expected symptom of a write-once disc that's already been used. The pre-check now catches this politely.
- Builds clean. CLI prints the right
usagetext forburn. - Dry-run with the test playlist successfully reaches Plan() and surfaces the "disc isn't fresh" pre-check error when given a non-blank CD-R.
- Real-hardware test with a fresh blank CD-R. Will update the changelog and README once we've completed an actual burn end-to-end.
- NAudio (2.3.0) added to
Futureburn.Core. First — and so far only — third-party audio dependency. Justified because writing MP3/AAC/FLAC decoders from scratch is a separate career. Futureburn.Core/Audio/CdFormat.cs— Red Book audio constants (44.1 kHz, 16-bit, stereo, 2352-byte sectors, 75 sectors/sec) plus duration/sector math helpers.Futureburn.Core/Audio/AudioDecoder.cs—Probe()returns format/duration without decoding;DecodeToCdWav()decodes any supported file and writes a CD-format WAV. Inputs that are already CD-format skip the resampler entirely. WAV uses NAudio's lightweightWaveFileReader; MP3 / M4A / AAC / WMA / FLAC go through Windows Media Foundation viaMediaFoundationReader.Futureburn.Core/Audio/Playlist.cs— M3U / M3U8 parser. Handles both simple (paths only) and extended (#EXTM3U+#EXTINF:<seconds>,<title>) flavors. Relative paths resolved against the playlist's directory.- CLI:
probe <file>,decode <in> <out.wav>,playlist <file.m3u>. The probe command tells you whether resampling will be needed.
- Decoded
C:\Windows\Media\Alarm01.wav(22050 Hz / stereo / 16-bit) → CD-format WAV (44100 Hz / stereo / 16-bit). Round-tripped probe confirmsIsCdFormat: yes — no resampling needed. - Extended M3U with a missing-file entry parses correctly, marks the missing track with
?, and reports the total duration.
- Still nothing! But we can now produce the exact bytes a CD wants. v0.0.6 carries those bytes to a disc.
- The four-tile shell.
MainWindowis now a 2×2 grid of big tile buttons (Burn Audio CD / Burn Video DVD / CD Info / Settings) with a menu bar (File → Exit, Help → About) and a status bar. Each tile has a quippy subtitle. CdInfoWindow— the CD Info tile opens a real sub-program: a drive list on the left, a live details pane on the right (capabilities, loaded media, capacity, write speeds), plus a Refresh button. Same data the CLI'sdrivesanddisccommands show, just interactive.PlaceholderWindow— parameterized "this ships in v0.X" dialog reused by the other three tiles.- About dialog with the GitHub URL, because every passion project deserves an About box.
- Code-behind, not MVVM. We'll graduate to MVVM if/when bindings get hairy enough to earn the ceremony.
- No third-party packages. WPF defaults all the way down.
- Still nothing. But you can now click on Burn Audio CD and read a polite refusal in window form.
Futureburn.Core/Imapi/Mmc.cs— lookup tables for MMC profile codes (CD-R, DVD+R DL, BD-RE, HD DVD-RAM, ...) and feature pages, plus the IMAPI media physical type enum. Unknown codes are still surfaced as raw hex with an "Unknown" label so weird drives (Xbox 360, exotic Blu-ray formats) stay visible.Futureburn.Core/Imapi/OpticalDrive.cs— extracted into its own file, now carriesSupportedProfiles,CurrentProfiles,SupportedFeaturePages,CurrentFeaturePages,CanLoadMedia, plusWritableProfiles/ReadOnlyProfiles/PrimaryMountconveniences.Futureburn.Core/Imapi/LoadedDisc.cs— record describing what's in the drive: media type, sectors total/free, next writable address, current + supported write speeds, blank flag. Has aHasFormatDetailsflag for when MsftDiscFormat2Data can't read the disc (audio CDs, finalized media, ROM).Futureburn.Core/Imapi/DiscInspector.cs— uses MsftDiscFormat2Data to read media info. Fails gracefully on non-data discs.DriveEnumerator.Find(identifier)— look up a drive by mount point ("F", "F:", "F:\") or by unique id.- CLI:
drives -v/drives --verbosedumps every supported profile and feature page (raw codes shown for unknown ones). - CLI:
disc <drive>inspects the loaded media in a drive.
- The IDispatch on
MsftDiscFormat2Datadoesn't expose the inheritedIDiscFormat2base members (CurrentMediaType, MediaPhysicallyBlank, etc.) when we go through C#dynamic. To stay hand-rolled (no[ComImport]interface declarations), we derive media type from the drive's CurrentProfile and infer "blank" fromFreeSectors == TotalSectors. If we ever need authoritative state, the next step is to declare a typed IDiscFormat2 and cast.
- Still nothing. But we now know exactly which of your drives can write CD-R, DVD-R DL, or whatever exotic format you've got plugged in.
Futureburn.Core/Imapi/DriveEnumerator.cs— hand-rolled IMAPI2 access viaType.GetTypeFromProgID+dynamic. No COM interface declarations, no NuGet wrappers. Returns a list ofOpticalDriverecords (vendor, product, firmware revision, mount points, unique id).futureburn drivesCLI command. Lists every optical drive Windows can see.futureburn help/--help/-hfor usage.
- All three projects now target
net8.0-windows(wasnet8.0for Core/Cli, alreadynet8.0-windowsfor Gui). We're Win11-only, so this kills CA1416 warnings on Windows-specific APIs without scattering[SupportedOSPlatform]everywhere. - Hoisted
TargetFramework,Nullable,ImplicitUsingsintoDirectory.Build.props. The csprojs are now mercifully short. - Deleted the
Class1.csplaceholder that came withdotnet new classlib.
- Still nothing. But we know who's capable of burning now, which is progress.
- Empty .NET 8 solution with three projects:
Futureburn.Core(class library),Futureburn.Cli(console app),Futureburn.Gui(WPF app). - Both
CliandGuireferenceCore. - Centralized version + metadata in
Directory.Build.propsso bumping a version means editing one line. - Repo, README, .gitignore, and this changelog.
- Nothing yet. We are pre-burn. Like pre-Cambrian, but with less life.