Skip to content

[FIX] macOS GUI silently reports "Process Complete" even when CCExtractor is missing or extraction fails#2297

Merged
cfsmp3 merged 3 commits into
CCExtractor:masterfrom
kaihere14:fix/mac-gui-error-handling
Jul 26, 2026
Merged

[FIX] macOS GUI silently reports "Process Complete" even when CCExtractor is missing or extraction fails#2297
cfsmp3 merged 3 commits into
CCExtractor:masterfrom
kaihere14:fix/mac-gui-error-handling

Conversation

@kaihere14

Copy link
Copy Markdown
Contributor

Summary

The macOS GUI (Platypus droplet, mac/gui/src/CCExtractor.app, added in #1138) called /usr/local/bin/ccextractor $1 and then unconditionally displayed "Process Complete," regardless of whether the binary existed, the run succeeded, or the file had no captions at all. $1 was also unquoted, breaking on file paths containing spaces.

Changes

  • Added shebang and defined a CCEXTRACTOR variable for clarity.
  • Added a check for the existence/executability of the CCExtractor CLI at the expected path, with a user-friendly error dialog if it's missing.
  • Added a check for missing input (no file dropped onto the app), with a clear error dialog instead of silently proceeding.
  • Quoted $1 throughout so file paths with spaces no longer break the script.
  • Replaced the unconditional success dialog with exit-status handling based on src/lib_ccx/ccx_common_common.h:
    • 0 → "Process Complete. Check the source file's folder for the subtitles."
    • 10 (EXIT_NO_CAPTIONS) → "No captions were found in this file, so no subtitle file was created."
    • any other code → "CCExtractor failed (exit code $status). Run it from the Terminal to see the detailed error output."
  • Script now exits with the same status code it received from CCExtractor, so failures propagate correctly instead of being masked.

In raising this pull request, I confirm the following (please check boxes):

Reason for this PR:

  • This PR adds new functionality.
  • This PR fixes a bug that I have personally experienced or that a real user has reported and for which a sample exists.
  • This PR is porting code from C to Rust.

Sanity check:

  • I have read and understood the contributors guide.
  • I have checked that another pull request for this purpose does not exist.
  • If the PR adds new functionality, I've added it to the changelog. If it's just a bug fix, I have NOT added it to the changelog.
  • I am NOT adding new C code unless it's to fix an existing, reproducible bug.

Repro instructions

Before the fix, the GUI showed "Process Complete" in all three of the following cases, with no indication anything had gone wrong. After the fix, each case shows the correct, distinct message and the script exits with the matching status code:

  1. Success case — a video file with captions is dropped onto the app; CCExtractor runs, exits 0, and the app correctly reports "Process Complete." (video attached)
Screen.Recording.2026-07-24.at.4.20.53.AM.mp4
  1. No captions case — a video file with no captions is dropped onto the app; CCExtractor exits 10 (EXIT_NO_CAPTIONS); the app now reports "No captions were found in this file, so no subtitle file was created" instead of falsely reporting success. (video attached)
Screen.Recording.2026-07-24.at.4.20.39.AM.mp4
  1. Failure case — reproduced by pointing CCEXTRACTOR at a bad/missing path (or by triggering a genuine extraction failure); the app now reports "CCExtractor failed (exit code $status)..." instead of "Process Complete." (video attached)
Screen.Recording.2026-07-24.at.4.19.08.AM.mp4

Closes #2296

…ctor scripts

- Added shebang and defined CCEXTRACTOR variable for clarity.
- Implemented checks for the existence of the CCExtractor tool and for input file presence, providing user-friendly error messages.
- Improved exit status handling with specific messages for different outcomes of the CCExtractor execution.
- Ensured consistent user feedback for process completion and error scenarios.

@cfsmp3 cfsmp3 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Three things before this can go in.

  1. Handle all dropped files, not just $1 (it's possible to drop more than one).
  2. Fall back to PATH for the binary location. /usr/local/bin/ccextractor is Intel-Homebrew's prefix. On Apple Silicon, Homebrew installs to /opt/homebrew/bin
  3. The shipped artifacts still contain the old script. End users don't run mac/gui/src/scripts. They install through InstallCCExtractorMacGUI.app, which unpacks a bundled DMG. Both DMGs in the repo still embed CCExtractor.app with the old droplet script.

…g and user feedback

- Updated the CCEXTRACTOR variable assignment to dynamically locate the ccextractor tool.
- Enhanced input file checks to allow multiple files and provide clearer user messages.
- Improved exit status handling with detailed feedback for each processed file, including success, no captions found, and failures.
- Ensured consistent user notifications for process completion and errors.
@kaihere14

Copy link
Copy Markdown
Contributor Author

@cfsmp3 Thanks for the review, all three points are addressed:

  1. Handle all dropped files: the script now loops over "$@" instead of only reading $1, runs ccextractor on each file, and shows one consolidated dialog summarizing the whole batch (successes, no-captions-found, and failures separately).

  2. PATH fallback: it now resolves the binary with command -v ccextractor first (respects the user's actual PATH), and only falls back to explicitly checking /usr/local/bin and /opt/homebrew/bin if that fails, so both Intel and Apple Silicon Homebrew prefixes are covered.

  3. Shipped artifacts: both mac/gui/src/CCExtractor.dmg and mac/gui/InstallCCExtractorMacGUI.app/Contents/Resources/CCExtractor.dmg embedded a CCExtractor.app with the old droplet script. Regenerated both from the fixed app so the install flow (not just building from source) picks up the fix.

Incidental finding while regenerating those: the old installer DMG (InstallCCExtractorMacGUI.app's bundled CCExtractor.dmg) was actually unmountable on current macOS. hdiutil attach failed with "no mountable file systems". It's a legacy raw, unpartitioned HFS+ image, a format that no longer reliably mounts. The regenerated DMGs use a standard GUID-partitioned HFS+ image and mount/verify cleanly, so this fixes a second latent bug along the way.

Screenshots covering all five states (binary not found, no input file, success, extraction failure, and multiple dropped files with a mixed result):

Screenshot 2026-07-26 at 11 46 48 PM Screenshot 2026-07-26 at 11 47 01 PM Screenshot 2026-07-26 at 11 49 28 PM Screenshot 2026-07-26 at 11 50 22 PM Screenshot 2026-07-26 at 11 55 51 PM

@cfsmp3

cfsmp3 commented Jul 26, 2026

Copy link
Copy Markdown
Contributor

@kaihere14

this revision introduces a new bug.

Filenames go into the AppleScript dialog unescaped. Double quotes are legal in macOS filenames, and one breaks out of the string literal. With a file named my"movie bad.ts, the generated script is:

display dialog "Finished processing 1 file(s).
Failed:
my"movie bad.ts (exit code 4)
Run from the Terminal to see detailed error output." buttons {"OK"} ...

That's a syntax error, so osascript fails and the user gets no dialog at all after processing — which is the same class of silent failure this PR set out to fix. It's also an execution vector, since AppleScript has do shell script; low severity for a local droplet, but worth closing. Only the failure and no-captions paths are affected — the all-success path uses a fixed string.

Something like this is enough:

 escape_as() { printf '%s' "$1" | sed 's/\\/\\\\/g; s/"/\\"/g'; }
 display "$(escape_as "$message")"
...

I think that's all needed

- Added an escape function to properly format messages for display in macOS dialogs.
- Updated dialog display logic to use escaped strings, improving the clarity of user notifications.
@kaihere14

Copy link
Copy Markdown
Contributor Author

@cfsmp3

Good catch, thanks. Fixed. Root cause was exactly as you described: the message was interpolated into the AppleScript string literal unescaped, so a stray " in a filename terminated the string early and made osascript choke, producing the same silent-failure symptom this PR was meant to fix.

Fix: added an escape_as() helper that backslash-escapes \ and " before the message goes into the dialog string, applied inside display() so every call site is covered, not just the failure/no-captions paths:

function escape_as() {
  printf '%s' "$1" | sed 's/\\/\\\\/g; s/"/\\"/g'
}

function display() {
  local escaped
  escaped="$(escape_as "$1")"
  osascript <<EOT
    ...
      display dialog "$escaped" buttons {"OK"} ...
    ...
EOT
}

Since none of this is build-generated, I also had to sync the fix into the checked-in binary copies that actually ship: CCExtractor.app/Contents/Resources/script, and repackaged both CCExtractor.dmg copies (mac/gui/src/ and the one embedded in InstallCCExtractorMacGUI.app) from the updated app bundle. Otherwise the source fix alone wouldn't reach users.

Tested by dropping a file literally named te"st.png onto the app. Dialog now renders correctly instead of erroring out silently. Screenshot below:

Screenshot 2026-07-27 at 12 56 15 AM

@cfsmp3
cfsmp3 merged commit ba4a839 into CCExtractor:master Jul 26, 2026
10 checks passed
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] macOS GUI always reports "Process Complete", even when CCExtractor is missing or extraction fails

2 participants