mirror of
https://github.com/storytold/filmcraft.git
synced 2026-10-24 10:10:05 -06:00
#659: macOS app may use the microphone for voice-over
Problem: the macOS bundle had no NSMicrophoneUsageDescription and empty hardened-runtime entitlements, so macOS never asked for microphone access and voice-over recording got no input. Fix: declare NSMicrophoneUsageDescription in Info.plist.in and grant com.apple.security.device.audio-input in entitlements.plist; an xtask test guards both. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5.5
parent
98ba9acbce
commit
379b9b5dec
@@ -42,6 +42,10 @@
|
||||
<true/>
|
||||
<key>NSRequiresAquaSystemAppearance</key>
|
||||
<false/>
|
||||
<!-- Voice-over recording (timeline track header ▸ Voice-over Record) reads the microphone.
|
||||
Without this string macOS never asks and the app gets no input. -->
|
||||
<key>NSMicrophoneUsageDescription</key>
|
||||
<string>FilmCraft uses the microphone to record voice-over onto the timeline.</string>
|
||||
<key>NSHumanReadableCopyright</key>
|
||||
<string>Copyright © the FilmCraft authors. MIT OR Apache-2.0.</string>
|
||||
|
||||
|
||||
@@ -1,9 +1,13 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<!-- Hardened-runtime entitlements for Filmcraft. Deliberately empty: the app is pure Rust,
|
||||
<!-- Hardened-runtime entitlements for Filmcraft. Deliberately minimal: the app is pure Rust,
|
||||
loads no unsigned code, needs no JIT, and is not sandboxed (it opens files by path, from the
|
||||
command line and drag-and-drop). Add exceptions here only with a reason in a comment. -->
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<!-- Voice-over recording reads the microphone; the hardened runtime blocks audio input without
|
||||
this (Info.plist.in carries the matching NSMicrophoneUsageDescription). -->
|
||||
<key>com.apple.security.device.audio-input</key>
|
||||
<true/>
|
||||
</dict>
|
||||
</plist>
|
||||
|
||||
@@ -504,3 +504,24 @@ fn main() -> ExitCode {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use std::path::Path;
|
||||
|
||||
fn macos_packaging(file: &str) -> String {
|
||||
let path = Path::new(env!("CARGO_MANIFEST_DIR")).join("../packaging/macos").join(file);
|
||||
std::fs::read_to_string(&path).unwrap_or_else(|e| panic!("{}: {e}", path.display()))
|
||||
}
|
||||
|
||||
/// Voice-over recording needs both halves on macOS: the usage string (else the permission
|
||||
/// prompt never appears) and the hardened-runtime audio-input entitlement (else the input is
|
||||
/// blocked). Regression test for #659.
|
||||
#[test]
|
||||
fn macos_bundle_may_use_the_microphone() {
|
||||
let plist = macos_packaging("Info.plist.in");
|
||||
assert!(plist.contains("<key>NSMicrophoneUsageDescription</key>"));
|
||||
let entitlements = macos_packaging("entitlements.plist");
|
||||
assert!(entitlements.contains("<key>com.apple.security.device.audio-input</key>\n <true/>"));
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user