Files

3.4 KiB
Raw Permalink Blame History

Second Display

A native macOS app that shows video from a capture device (capture card, camera) in a window and plays audio from a chosen input — a "second monitor".

Requirements

macOS 26+, Xcode (Command Line Tools).

Build and run

make          # builds build/Second Display.app
make run      # build and launch
make check    # lint: typecheck, plists, translations, signature
make install  # copy to ~/Applications
make dmg      # build/second-display-<version>.dmg (universal, not notarized)
make help     # list targets

The app is signed ad-hoc (works on this Mac). For distribution: make SIGN_ID="Developer ID Application: ..." (notarization is still required).

Installation

Build from source and install to ~/Applications:

git clone <repository-url> second-display
cd second-display
make install
open "$HOME/Applications/Second Display.app"

On first launch macOS asks for camera and microphone access — allow both. You can change this later in System Settings → Privacy & Security.

If you received a prebuilt copy (the .dmg), drag the app to Applications. It is not notarized, so macOS blocks it on first launch: allow it once in System Settings → Privacy & Security → "Open Anyway", or run xattr -dr com.apple.quarantine "/Applications/Second Display.app". The same steps are in Read Me First.txt inside the disk image.

Releasing a DMG

make dmg builds a universal (arm64 + x86_64) app and packs it with an Applications shortcut and Read Me First.txt (source: Config/dmg/) in a styled Finder window: large icons and a background with an arrow (Config/dmg/background.png, generated by scripts/make-dmg-background.swift). The layout is written directly into the image by dmgbuild (settings in Config/dmg/settings.py), so no Finder automation is needed. The first make dmg installs it into build/venv (needs python3 and network access). The disk image is not signed with a Developer ID or notarized; the instructions in it explain how recipients allow it. Bump the version in Config/Info.plist before releasing and tag it (git tag -a vX.Y.Z -m vX.Y.Z).

Usage

Menus at the top of the screen: Video (device, format), Audio (source or off), Options (prevent display sleep, start in full screen, always on top, mute ⇧⌘M, scaling), Window (tiling, full screen ⌃⌘F).

Autostart opens the app whenever the chosen USB capture device is plugged in (and makes it the active video source). It installs a per-user LaunchAgent (~/Library/LaunchAgents/com.mmacierzanka.second-display.autostart.plist) matching the device's USB vendor/product ID, so only USB (UVC) devices can be chosen. Choose Off to remove it; the uninstall script removes it too.

Layout

  • Sources/ – the app (AppKit + AVFoundation): App (state, window), Capture (devices, formats), Menu, Power, Preferences, main (entry point)
  • Config/ – Info.plist, entitlements (camera, microphone), dmg/ (instructions shipped in the disk image)
  • Resources/ – icon (AppIcon.icon, Icon Composer), en/pl translations, uninstall.sh
  • scripts/check-strings.sh – translation consistency

Settings and uninstall

Settings: ~/Library/Preferences/com.mmacierzanka.second-display.plist. To remove the app and all its traces: make uninstall or "Second Display.app/Contents/Resources/uninstall.sh".

License

MIT — see LICENSE.