Skip to content

Fix M3U generation to exclude raw .bin tracks when .cue files are present#3100

Merged
gantoine merged 3 commits intomasterfrom
copilot/fix-multifile-download-m3u
Mar 9, 2026
Merged

Fix M3U generation to exclude raw .bin tracks when .cue files are present#3100
gantoine merged 3 commits intomasterfrom
copilot/fix-multifile-download-m3u

Conversation

Copy link
Copy Markdown
Contributor

Copilot AI commented Mar 9, 2026

When downloading a multi-file ROM containing .bin/.cue pairs, the auto-generated .m3u listed all files indiscriminately — including raw binary tracks — producing an invalid playlist that emulators misinterpret as multi-disc or fail to load.

Changes

  • Both download paths (DEV_MODE in-memory ZIP and nginx mod_zip proxy): before building the M3U content, filter to only .cue files when any are present; fall back to all files otherwise.

Before:

Dracula Unleashed (USA) (Disc 1) (Track 1).bin
Dracula Unleashed (USA) (Disc 1) (Track 2).bin
Dracula Unleashed (USA) (Disc 1).cue
Dracula Unleashed (USA) (Disc 2) (Track 1).bin
Dracula Unleashed (USA) (Disc 2) (Track 2).bin
Dracula Unleashed (USA) (Disc 2).cue

After:

Dracula Unleashed (USA) (Disc 1).cue
Dracula Unleashed (USA) (Disc 2).cue

This also correctly handles multi-disc bin/cue games, where the M3U should enumerate disc .cue descriptors — not individual tracks.

Original prompt

This section details on the original issue you should resolve

<issue_title>[Bug] Multifile Download generates invalid .m3u for bin/cue games (includes both files)</issue_title>
<issue_description>RomM version
Version 4.6.1

Describe the bug
When downloading a game that consists of multiple files (specifically a .bin and .cue pair) using the download feature, RomM automatically generates an .m3u playlist that indiscriminately includes every file in the directory.

For a standard bin/cue game, this results in an .m3u file containing both game.bin and game.cue. This is incorrect behavior for emulators, which will often interpret this as a multi-disc game or fail to load the tracks correctly because the .bin is being loaded independently of its .cue descriptor. The generated .m3u should only include the .cue entries.

This issue is different from #2706, which requests a toggle per-platform to turn .m3u creation on/off. This issue represents a scenario where an .m3u file is desired for a supported bin/cue game, but an invalid .m3u file is created instead.

To Reproduce
Steps to reproduce the behavior:

  1. Identify a game in the library that consists of a .bin and .cue file (and does not already have an existing .m3u).
  2. Click on the Download button for that game.
  3. Open the downloaded Zip file and inspect the generated .m3u file.
  4. See error: The .m3u file lists both the .bin and the .cue file as separate entries.

Example of the incorrect .m3u output:

Dracula Unleashed (USA) (Disc 1) (Track 1).bin
Dracula Unleashed (USA) (Disc 1) (Track 2).bin
Dracula Unleashed (USA) (Disc 1).cue
Dracula Unleashed (USA) (Disc 2) (Track 1).bin
Dracula Unleashed (USA) (Disc 2) (Track 2).bin
Dracula Unleashed (USA) (Disc 2).cue

Expected behavior
The .m3u generation logic should be smart enough to exclude binary files (like .bin) if a descriptor file (like .cue) is present in the same package.

Ideally:

  1. If an .m3u is generated, it should only list the .cue file(s), not the .bin file. This would also satisfy the use case for multi-disc bin/cue games.

Example of correct/expected output (if .m3u is generated):

Dracula Unleashed (USA) (Disc 1).cue
Dracula Unleashed (USA) (Disc 2).cue

Screenshots
See examples

Server (please complete the following information):

  • OS: TrueNAS (via Docker Compose)
  • Version 25.10.1

Client (please complete the following information):

  • Device: Windows Desktop Client
  • OS: Windows 11 Pro
  • Browser Chrome
  • Version 144.0.7559.133

Additional context
This would also improve the behavior of the RomM Playnite Plugin when using the 'Use M3U File' feature when it comes to bin/cue games.
</issue_description>

Comments on the Issue (you are @copilot in this section)


✨ Let Copilot coding agent set things up for you — coding agent works faster and does higher quality work when set up for your repo.

Copilot AI changed the title [WIP] Fix multifile download to generate correct .m3u for bin/cue games Fix M3U generation to exclude raw .bin tracks when .cue files are present Mar 9, 2026
@gantoine gantoine marked this pull request as ready for review March 9, 2026 22:08
@greptile-apps
Copy link
Copy Markdown

greptile-apps bot commented Mar 9, 2026

Greptile Summary

This PR fixes an invalid .m3u playlist generated during multi-file ROM downloads by filtering M3U entries to only .cue descriptor files when they are present, falling back to all files otherwise. The fix is applied once, shared across both the DEV_MODE in-memory ZIP path and the nginx mod_zip proxy path.

Key changes:

  • Adds a single cue_files / m3u_files computation (lines 910–911) before the DEV_MODE branch, eliminating any duplication and keeping both paths in sync.
  • Both M3U construction blocks now reference m3u_files instead of the raw files list.
  • The fallback (m3u_files = files when no .cue files exist) preserves the original behaviour for non-bin/cue ROMs.

Observations:

  • The fix is straightforward and correctly scoped — file_extension is a @cached_property that returns the extension without the leading dot (e.g., "cue"), so the comparison f.file_extension.lower() == "cue" is reliable.
  • No test coverage was added for the new filtering logic; the download endpoint has no existing tests, making this a gap worth addressing (see inline comment).
  • Other disc-image descriptor formats (.gdi for Dreamcast, .ccd for CloneCD, .mds for Alcohol 120%) still produce the same raw-track pollution in the M3U if co-existing track files are present.

Confidence Score: 4/5

  • This PR is safe to merge — the change is minimal, correctly scoped, and the fallback preserves existing behaviour for non-bin/cue ROMs.
  • The logic is simple and correct: filter to .cue files when present, fall back to all files otherwise. The shared computation before both download paths removes any risk of the two paths diverging. The only concern is the complete absence of test coverage for the new behaviour, which means regressions won't be caught automatically.
  • No files require special attention beyond the noted lack of test coverage in backend/endpoints/roms/__init__.py.

Important Files Changed

Filename Overview
backend/endpoints/roms/init.py Adds a shared m3u_files filter before both download paths that restricts M3U entries to .cue files when any are present, falling back to all files otherwise. Logic is correct and duplication-free; no test coverage added for the new behaviour.

Flowchart

%%{init: {'theme': 'neutral'}}%%
flowchart TD
    A[GET /roms/:id/content] --> B[Resolve files list\noptionally filtered by file_ids]
    B --> C{Any .cue files\nin files list?}
    C -- Yes --> D[m3u_files = cue_files only]
    C -- No --> E[m3u_files = all files]
    D & E --> F{DEV_MODE?}
    F -- Yes / single file --> G[Return FileResponse directly]
    F -- Yes / multi-file --> H[Build in-memory ZIP]
    H --> I{rom.has_m3u_file?}
    I -- No --> J[Generate .m3u from m3u_files\nwrite into ZIP]
    I -- Yes --> K[Skip M3U generation]
    J & K --> L[Return ZIP Response]
    F -- No / single file --> M[Return FileRedirectResponse]
    F -- No / multi-file --> N[Build nginx mod_zip content_lines]
    N --> O{rom.has_m3u_file?}
    O -- No --> P[Generate .m3u from m3u_files\nappend to content_lines]
    O -- Yes --> Q[Skip M3U generation]
    P & Q --> R[Return ZipResponse via nginx]
Loading

Last reviewed commit: 8a76391

@github-actions
Copy link
Copy Markdown
Contributor

github-actions bot commented Mar 9, 2026

Test Results (postgresql)

945 tests   944 ✅  2m 8s ⏱️
  1 suites    1 💤
  1 files      0 ❌

Results for commit 8a76391.

♻️ This comment has been updated with latest results.

@github-actions
Copy link
Copy Markdown
Contributor

github-actions bot commented Mar 9, 2026

Test Results (mariadb)

945 tests   944 ✅  2m 8s ⏱️
  1 suites    1 💤
  1 files      0 ❌

Results for commit 8a76391.

♻️ This comment has been updated with latest results.

@github-actions
Copy link
Copy Markdown
Contributor

github-actions bot commented Mar 9, 2026

☂️ Python Coverage

current status: ✅

Overall Coverage

Lines Covered Coverage Threshold Status
13815 9264 67% 0% 🟢

New Files

No new covered files...

Modified Files

File Coverage Status
backend/endpoints/roms/_init_.py 61% 🟢
TOTAL 61% 🟢

updated for commit: 8a76391 by action🐍

@gantoine gantoine merged commit da09f6c into master Mar 9, 2026
12 checks passed
@gantoine gantoine deleted the copilot/fix-multifile-download-m3u branch March 9, 2026 22:44
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Bug] Multifile Download generates invalid .m3u for bin/cue games (includes both files)

2 participants