#!/usr/bin/env bash
set -euo pipefail
cd "$(dirname "$0")/.."
TARGET_ARCH="${MACPLAY_ARCH:-$(uname -m)}"
case "$TARGET_ARCH" in x64) TARGET_ARCH=x86_64;; aarch64) TARGET_ARCH=arm64;; esac
REQUIRED_ARCHES=("$TARGET_ARCH")
if [[ "$TARGET_ARCH" == universal ]]; then REQUIRED_ARCHES=(arm64 x86_64); fi
source scripts/prepare-macos-runtime.sh
NODE_BIN="${MACPLAY_NODE_BIN:-$NODE_BIN}"
APP="${MACPLAY_APP_OUTPUT:-$PWD/dist/MacPlay.app}"
RES="$APP/Contents/Resources"
RECEIVER="$RES/runtime/MacPlayReceiver.app"
mkdir -p "$APP/Contents/MacOS" "$RES/runtime" "$RES/engine/node_modules" "$RES/driver" "$RES/gstreamer"
cp build/MacPlay "$APP/Contents/MacOS/MacPlay"
mkdir -p "$RECEIVER/Contents/MacOS" "$RECEIVER/Contents/Resources"
cp "$NODE_BIN" "$RECEIVER/Contents/MacOS/MacPlayReceiver"
rm -f "$RES/runtime/node"
cp assets/icons/mac/macplay.icns "$RECEIVER/Contents/Resources/MacPlay.icns"
cat > "$RECEIVER/Contents/Info.plist" <<'PLIST'
CFBundleIdentifiercom.roylyl.macplay.receiver
CFBundleNameMacPlayCFBundleDisplayNameMacPlay
CFBundleExecutableMacPlayReceiverCFBundlePackageTypeAPPL
CFBundleShortVersionString1.2.1CFBundleVersion35
CFBundleIconFileMacPlayLSMinimumSystemVersion14.0
LSUIElementNSHighResolutionCapable
CFBundleLocalizationsenzh-Hanszh-Hant
NSLocalNetworkUsageDescriptionMacPlay通过本地网络接收iPhone的CarPlay音视频。
NSMicrophoneUsageDescriptionMacPlay使用麦克风进行语音控制和通话。
PLIST
cp -R build/engine/. "$RES/engine/"
for mod in livi-crypto livi-gst-video; do
mkdir -p "$RES/engine/node_modules/$mod/build/Release"
cp "native/$mod/index.js" "native/$mod/package.json" "$RES/engine/node_modules/$mod/"
cp "native/$mod/build/Release/"*.node "$RES/engine/node_modules/$mod/build/Release/"
done
HELPERD_BIN="${MACPLAY_HELPERD_BIN:-native/livi-helperd/target/release/livi-helperd}"
if [[ ! -f "$HELPERD_BIN" && -f "native/livi-helperd/target/x86_64-apple-darwin/release/livi-helperd" ]]; then
HELPERD_BIN="native/livi-helperd/target/x86_64-apple-darwin/release/livi-helperd"
elif [[ ! -f "$HELPERD_BIN" && -f "native/livi-helperd/target/aarch64-apple-darwin/release/livi-helperd" ]]; then
HELPERD_BIN="native/livi-helperd/target/aarch64-apple-darwin/release/livi-helperd"
fi
cp "$HELPERD_BIN" native/macplay-bluetooth/macplay-bluetooth "$RES/driver/"
# Refuse a package whose runtime cannot execute on its advertised architecture.
for required in "${REQUIRED_ARCHES[@]}"; do
for binary in "$APP/Contents/MacOS/MacPlay" "$RECEIVER/Contents/MacOS/MacPlayReceiver" "$RES/driver/"* "$RES/engine/node_modules/"*/build/Release/*.node; do
lipo -verify_arch "$required" "$binary"
done
done
rm -rf "$RES/gstreamer"
mkdir -p "$RES/gstreamer"
cp -R assets/gstreamer/macos-arm64 "$RES/gstreamer/macos-arm64"
ln -sfn macos-arm64 "$RES/gstreamer/macos-x64"
if [[ -n "${MACPLAY_GSTREAMER_EXTRA:-}" ]]; then
cp -R "$MACPLAY_GSTREAMER_EXTRA/lib/." "$RES/gstreamer/macos-arm64/lib/"
fi
if [[ -n "${MACPLAY_APPLEMEDIA_UNIVERSAL:-}" ]]; then
cp "$MACPLAY_APPLEMEDIA_UNIVERSAL" "$RES/gstreamer/macos-arm64/lib/gstreamer-1.0/libgstapplemedia.dylib"
fi
for required in "${REQUIRED_ARCHES[@]}"; do
while IFS= read -r -d '' binary; do
lipo -verify_arch "$required" "$binary"
done < <(find "$RES/gstreamer/macos-arm64" -type f \( -name '*.dylib' -o -name 'gst-*' \) -print0)
done
cp assets/icons/mac/macplay.icns "$RES/MacPlay.icns"
cp -R native/App/Resources/*.lproj "$RES/"
cp -R native/App/Resources/*.lproj "$RECEIVER/Contents/Resources/"
mkdir -p "$RES/icons"
cp assets/icons/carplay/macplay-256.png assets/icons/carplay/macplay-512.png "$RES/icons/"
mkdir -p "$RES/authentication"
cp assets/authentication/identity.pk8 assets/authentication/certificate.p7b assets/authentication/SOURCE.txt "$RES/authentication/"
cp LICENSE NOTICE "$RES/"
cp -R assets/licenses "$RES/ThirdParty-LICENSES"
cp -R assets/gstreamer/LICENSES "$RES/GStreamer-LICENSES"
cat > "$APP/Contents/Info.plist" <<'PLIST'
CFBundleIdentifiercom.roylyl.macplay
CFBundleNameMacPlayCFBundleDisplayNameMacPlay
CFBundleExecutableMacPlayCFBundlePackageTypeAPPL
CFBundleShortVersionString1.2.1CFBundleVersion35
CFBundleIconFileMacPlayLSMinimumSystemVersion14.0
NSHighResolutionCapable
CFBundleLocalizationsenzh-Hanszh-Hant
NSBluetoothAlwaysUsageDescriptionMacPlay通过Mac蓝牙与iPhone建立CarPlay连接。
NSLocalNetworkUsageDescriptionMacPlay通过本地网络接收iPhone的CarPlay音视频。
NSLocationUsageDescriptionmacOS要求定位权限才能读取当前Wi-Fi名称。MacPlay仅用此权限读取网络信息,不保存位置信息。
NSLocationWhenInUseUsageDescriptionmacOS要求定位权限才能读取当前Wi-Fi名称。MacPlay仅用此权限读取网络信息,不保存位置信息。
NSMicrophoneUsageDescriptionMacPlay使用麦克风进行Siri语音控制和通话。
PLIST
ADDON="$RES/engine/node_modules/livi-gst-video/build/Release/gst_video.node"
while IFS= read -r rp; do install_name_tool -delete_rpath "$rp" "$ADDON" 2>/dev/null || true; done < <(otool -l "$ADDON" | awk '/LC_RPATH/{getline;getline;print $2}')
install_name_tool -add_rpath '@loader_path/../../../../../gstreamer/macos-x64/lib' "$ADDON"
install_name_tool -add_rpath '@loader_path/../../../../../gstreamer/macos-arm64/lib' "$ADDON"
for bin in "$RECEIVER/Contents/MacOS/MacPlayReceiver" "$RES/driver/"* "$RES/engine/node_modules/"*/build/Release/*.node; do codesign --force --sign - "$bin"; done
codesign --force --sign - "$RECEIVER"
codesign --force --deep --sign - "$APP"
if [[ "${1:-}" != "--app-only" ]]; then
mkdir -p build/dmg
ln -sfn /Applications build/dmg/Applications
rm -rf build/dmg/MacPlay.app
ditto "$APP" build/dmg/MacPlay.app
hdiutil create -ov -volname MacPlay -srcfolder build/dmg -format UDZO "dist/MacPlay-1.2.1-${TARGET_ARCH}.dmg"
fi