max / audiofiles
7 files changed,
+331 insertions,
-0 deletions
| @@ -29,3 +29,4 @@ recursive fonts.085/ | |||
| 29 | 29 | .vscode/ | |
| 30 | 30 | *.swp | |
| 31 | 31 | *.swo | |
| 32 | + | dist/*.exe |
| @@ -0,0 +1,9 @@ | |||
| 1 | + | [Desktop Entry] | |
| 2 | + | Type=Application | |
| 3 | + | Name=AudioFiles | |
| 4 | + | Comment=Sample manager with content-addressed storage | |
| 5 | + | Exec=audiofiles-app | |
| 6 | + | Icon=audiofiles | |
| 7 | + | Categories=Audio;AudioVideo; | |
| 8 | + | MimeType=audio/wav;audio/x-wav;audio/flac;audio/x-flac;audio/mpeg;audio/ogg;audio/aiff;audio/x-aiff; | |
| 9 | + | Terminal=false |
| @@ -0,0 +1,60 @@ | |||
| 1 | + | #!/usr/bin/env bash | |
| 2 | + | set -euo pipefail | |
| 3 | + | ||
| 4 | + | SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)" | |
| 5 | + | PROJECT_DIR="$(cd "$SCRIPT_DIR/.." && pwd)" | |
| 6 | + | DIST_DIR="$SCRIPT_DIR" | |
| 7 | + | TOOLS_DIR="$DIST_DIR/tools" | |
| 8 | + | ARCH=$(uname -m) | |
| 9 | + | ||
| 10 | + | # Read version from Cargo.toml | |
| 11 | + | VERSION=$(grep '^version' "$PROJECT_DIR/crates/audiofiles-app/Cargo.toml" | head -1 | sed 's/.*"\(.*\)".*/\1/') | |
| 12 | + | echo "Building AudioFiles v${VERSION} AppImage (${ARCH})" | |
| 13 | + | ||
| 14 | + | # Step 1: Build release binary | |
| 15 | + | echo "==> Building release binary..." | |
| 16 | + | cd "$PROJECT_DIR" | |
| 17 | + | cargo build --release -p audiofiles-app | |
| 18 | + | ||
| 19 | + | # Step 2: Create AppDir | |
| 20 | + | echo "==> Assembling AppDir..." | |
| 21 | + | APPDIR="$DIST_DIR/AppDir" | |
| 22 | + | rm -rf "$APPDIR" | |
| 23 | + | mkdir -p "$APPDIR/usr/bin" | |
| 24 | + | ||
| 25 | + | cp "$PROJECT_DIR/target/release/audiofiles-app" "$APPDIR/usr/bin/audiofiles-app" | |
| 26 | + | cp "$DIST_DIR/audiofiles.desktop" "$APPDIR/audiofiles.desktop" | |
| 27 | + | cp "$DIST_DIR/audiofiles.png" "$APPDIR/audiofiles.png" | |
| 28 | + | ||
| 29 | + | # AppRun wrapper | |
| 30 | + | cat > "$APPDIR/AppRun" << 'APPRUN' | |
| 31 | + | #!/usr/bin/env bash | |
| 32 | + | SELF="$(readlink -f "$0")" | |
| 33 | + | HERE="${SELF%/*}" | |
| 34 | + | exec "${HERE}/usr/bin/audiofiles-app" "$@" | |
| 35 | + | APPRUN | |
| 36 | + | chmod +x "$APPDIR/AppRun" | |
| 37 | + | ||
| 38 | + | # Step 3: Get appimagetool | |
| 39 | + | mkdir -p "$TOOLS_DIR" | |
| 40 | + | APPIMAGETOOL="$TOOLS_DIR/appimagetool-${ARCH}.AppImage" | |
| 41 | + | if [ ! -x "$APPIMAGETOOL" ]; then | |
| 42 | + | echo "==> Downloading appimagetool..." | |
| 43 | + | curl -fSL "https://github.com/AppImage/appimagetool/releases/download/continuous/appimagetool-${ARCH}.AppImage" \ | |
| 44 | + | -o "$APPIMAGETOOL" | |
| 45 | + | chmod +x "$APPIMAGETOOL" | |
| 46 | + | fi | |
| 47 | + | ||
| 48 | + | # Step 4: Build AppImage | |
| 49 | + | echo "==> Creating AppImage..." | |
| 50 | + | APPIMAGE_NAME="AudioFiles-${VERSION}-${ARCH}.AppImage" | |
| 51 | + | APPIMAGE_PATH="$DIST_DIR/$APPIMAGE_NAME" | |
| 52 | + | rm -f "$APPIMAGE_PATH" | |
| 53 | + | ||
| 54 | + | ARCH="$ARCH" "$APPIMAGETOOL" "$APPDIR" "$APPIMAGE_PATH" | |
| 55 | + | ||
| 56 | + | # Cleanup | |
| 57 | + | rm -rf "$APPDIR" | |
| 58 | + | ||
| 59 | + | echo "" | |
| 60 | + | echo "Done: $APPIMAGE_PATH" |
| @@ -0,0 +1,75 @@ | |||
| 1 | + | #!/usr/bin/env bash | |
| 2 | + | set -euo pipefail | |
| 3 | + | ||
| 4 | + | SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)" | |
| 5 | + | PROJECT_DIR="$(cd "$SCRIPT_DIR/.." && pwd)" | |
| 6 | + | DIST_DIR="$SCRIPT_DIR" | |
| 7 | + | ARCH=$(dpkg --print-architecture 2>/dev/null || echo "amd64") | |
| 8 | + | ||
| 9 | + | # Read version from Cargo.toml | |
| 10 | + | VERSION=$(grep '^version' "$PROJECT_DIR/crates/audiofiles-app/Cargo.toml" | head -1 | sed 's/.*"\(.*\)".*/\1/') | |
| 11 | + | echo "Building AudioFiles v${VERSION} .deb (${ARCH})" | |
| 12 | + | ||
| 13 | + | # Step 1: Build release binary | |
| 14 | + | echo "==> Building release binary..." | |
| 15 | + | cd "$PROJECT_DIR" | |
| 16 | + | cargo build --release -p audiofiles-app | |
| 17 | + | ||
| 18 | + | # Step 2: Assemble deb tree | |
| 19 | + | echo "==> Assembling package..." | |
| 20 | + | PKG_DIR="$DIST_DIR/.deb-staging/audiofiles_${VERSION}_${ARCH}" | |
| 21 | + | rm -rf "$DIST_DIR/.deb-staging" | |
| 22 | + | mkdir -p "$PKG_DIR/DEBIAN" | |
| 23 | + | mkdir -p "$PKG_DIR/usr/bin" | |
| 24 | + | mkdir -p "$PKG_DIR/usr/share/applications" | |
| 25 | + | mkdir -p "$PKG_DIR/usr/share/icons/hicolor/256x256/apps" | |
| 26 | + | ||
| 27 | + | cp "$PROJECT_DIR/target/release/audiofiles-app" "$PKG_DIR/usr/bin/audiofiles-app" | |
| 28 | + | cp "$DIST_DIR/audiofiles.desktop" "$PKG_DIR/usr/share/applications/audiofiles.desktop" | |
| 29 | + | cp "$DIST_DIR/audiofiles.png" "$PKG_DIR/usr/share/icons/hicolor/256x256/apps/audiofiles.png" | |
| 30 | + | ||
| 31 | + | # Compute installed size in KB | |
| 32 | + | INSTALLED_SIZE=$(du -sk "$PKG_DIR" | cut -f1) | |
| 33 | + | ||
| 34 | + | # Runtime deps: | |
| 35 | + | # libasound2 - ALSA (cpal audio playback) | |
| 36 | + | # libgl1 - OpenGL (eframe glow backend) | |
| 37 | + | # libxcb1 - X11 connection (egui/winit) | |
| 38 | + | # libxkbcommon0 - Keyboard input | |
| 39 | + | # libssl3 - TLS (reqwest native-tls) -- libssl3 for Ubuntu 22.04+ | |
| 40 | + | # libgtk-3-0 - File dialogs (rfd/nfd) | |
| 41 | + | cat > "$PKG_DIR/DEBIAN/control" << CONTROL | |
| 42 | + | Package: audiofiles | |
| 43 | + | Version: ${VERSION} | |
| 44 | + | Section: sound | |
| 45 | + | Priority: optional | |
| 46 | + | Architecture: ${ARCH} | |
| 47 | + | Depends: libasound2, libgl1, libxcb1, libxkbcommon0, libssl3, libgtk-3-0 | |
| 48 | + | Installed-Size: ${INSTALLED_SIZE} | |
| 49 | + | Maintainer: Maxwell Morgan Johnson <max@makenot.work> | |
| 50 | + | Homepage: https://makenot.work | |
| 51 | + | Description: Sample manager with content-addressed storage | |
| 52 | + | AudioFiles is a desktop sample manager with content-addressed storage, | |
| 53 | + | virtual filesystem, and cloud sync. Supports WAV, FLAC, MP3, OGG, and | |
| 54 | + | AIFF formats. | |
| 55 | + | CONTROL | |
| 56 | + | ||
| 57 | + | # Step 3: Set permissions | |
| 58 | + | chmod 755 "$PKG_DIR/usr/bin/audiofiles-app" | |
| 59 | + | chmod 644 "$PKG_DIR/usr/share/applications/audiofiles.desktop" | |
| 60 | + | chmod 644 "$PKG_DIR/usr/share/icons/hicolor/256x256/apps/audiofiles.png" | |
| 61 | + | ||
| 62 | + | # Step 4: Build .deb | |
| 63 | + | echo "==> Building .deb..." | |
| 64 | + | DEB_NAME="audiofiles_${VERSION}_${ARCH}.deb" | |
| 65 | + | DEB_PATH="$DIST_DIR/$DEB_NAME" | |
| 66 | + | rm -f "$DEB_PATH" | |
| 67 | + | ||
| 68 | + | dpkg-deb --build --root-owner-group "$PKG_DIR" "$DEB_PATH" | |
| 69 | + | ||
| 70 | + | # Cleanup | |
| 71 | + | rm -rf "$DIST_DIR/.deb-staging" | |
| 72 | + | ||
| 73 | + | echo "" | |
| 74 | + | echo "Done: $DEB_PATH" | |
| 75 | + | echo "Install with: sudo dpkg -i $DEB_NAME" |
| @@ -0,0 +1,142 @@ | |||
| 1 | + | #!/usr/bin/env bash | |
| 2 | + | set -euo pipefail | |
| 3 | + | ||
| 4 | + | SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)" | |
| 5 | + | PROJECT_DIR="$(cd "$SCRIPT_DIR/.." && pwd)" | |
| 6 | + | DIST_DIR="$SCRIPT_DIR" | |
| 7 | + | ||
| 8 | + | # Parse flags | |
| 9 | + | SKIP_NOTARIZE=false | |
| 10 | + | for arg in "$@"; do | |
| 11 | + | case "$arg" in | |
| 12 | + | --skip-notarize) SKIP_NOTARIZE=true ;; | |
| 13 | + | *) echo "Unknown flag: $arg"; echo "Usage: $0 [--skip-notarize]"; exit 1 ;; | |
| 14 | + | esac | |
| 15 | + | done | |
| 16 | + | ||
| 17 | + | # Read version from Cargo.toml | |
| 18 | + | VERSION=$(grep '^version' "$PROJECT_DIR/crates/audiofiles-app/Cargo.toml" | head -1 | sed 's/.*"\(.*\)".*/\1/') | |
| 19 | + | echo "Building AudioFiles v${VERSION}" | |
| 20 | + | ||
| 21 | + | ARCH=$(uname -m) | |
| 22 | + | APP_BUNDLE="$DIST_DIR/AudioFiles.app" | |
| 23 | + | DMG_NAME="AudioFiles_${VERSION}_${ARCH}.dmg" | |
| 24 | + | DMG_PATH="$DIST_DIR/$DMG_NAME" | |
| 25 | + | SIGNING_IDENTITY="Developer ID Application: MAXWELL MORGAN JOHNSON (93C54W92UP)" | |
| 26 | + | NOTARY_PROFILE="notarytool-profile" | |
| 27 | + | ||
| 28 | + | # Step 1: Build release binary | |
| 29 | + | echo "==> Building release binary..." | |
| 30 | + | cd "$PROJECT_DIR" | |
| 31 | + | cargo build --release -p audiofiles-app | |
| 32 | + | ||
| 33 | + | # Step 2: Assemble app bundle | |
| 34 | + | echo "==> Assembling app bundle..." | |
| 35 | + | rm -rf "$APP_BUNDLE" | |
| 36 | + | mkdir -p "$APP_BUNDLE/Contents/MacOS" | |
| 37 | + | mkdir -p "$APP_BUNDLE/Contents/Resources" | |
| 38 | + | ||
| 39 | + | cp "$PROJECT_DIR/target/release/audiofiles-app" "$APP_BUNDLE/Contents/MacOS/audiofiles-app" | |
| 40 | + | cp "$PROJECT_DIR/crates/audiofiles-app/AppIcon.icns" "$APP_BUNDLE/Contents/Resources/AppIcon.icns" | |
| 41 | + | ||
| 42 | + | # Patch Info.plist with current version | |
| 43 | + | sed -e "s|<string>0\.[0-9]*\.[0-9]*</string><!-- CFBundleVersion -->|<string>${VERSION}</string><!-- CFBundleVersion -->|" \ | |
| 44 | + | "$DIST_DIR/Info.plist.template" > "$APP_BUNDLE/Contents/Info.plist" 2>/dev/null || true | |
| 45 | + | ||
| 46 | + | # If template doesn't exist, write Info.plist directly with current version | |
| 47 | + | if [ ! -f "$APP_BUNDLE/Contents/Info.plist" ] || [ ! -s "$APP_BUNDLE/Contents/Info.plist" ]; then | |
| 48 | + | cat > "$APP_BUNDLE/Contents/Info.plist" << PLIST | |
| 49 | + | <?xml version="1.0" encoding="UTF-8"?> | |
| 50 | + | <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> | |
| 51 | + | <plist version="1.0"> | |
| 52 | + | <dict> | |
| 53 | + | <key>CFBundleName</key> | |
| 54 | + | <string>AudioFiles</string> | |
| 55 | + | <key>CFBundleIdentifier</key> | |
| 56 | + | <string>com.audiofiles.app</string> | |
| 57 | + | <key>CFBundleVersion</key> | |
| 58 | + | <string>${VERSION}</string> | |
| 59 | + | <key>CFBundleShortVersionString</key> | |
| 60 | + | <string>${VERSION}</string> | |
| 61 | + | <key>CFBundleExecutable</key> | |
| 62 | + | <string>audiofiles-app</string> | |
| 63 | + | <key>CFBundleIconFile</key> | |
| 64 | + | <string>AppIcon</string> | |
| 65 | + | <key>CFBundlePackageType</key> | |
| 66 | + | <string>APPL</string> | |
| 67 | + | <key>NSHighResolutionCapable</key> | |
| 68 | + | <true/> | |
| 69 | + | <key>CFBundleDocumentTypes</key> | |
| 70 | + | <array> | |
| 71 | + | <dict> | |
| 72 | + | <key>CFBundleTypeName</key> | |
| 73 | + | <string>Audio File</string> | |
| 74 | + | <key>CFBundleTypeRole</key> | |
| 75 | + | <string>Viewer</string> | |
| 76 | + | <key>LSHandlerRank</key> | |
| 77 | + | <string>Alternate</string> | |
| 78 | + | <key>CFBundleTypeExtensions</key> | |
| 79 | + | <array> | |
| 80 | + | <string>wav</string> | |
| 81 | + | <string>flac</string> | |
| 82 | + | <string>mp3</string> | |
| 83 | + | <string>ogg</string> | |
| 84 | + | <string>aiff</string> | |
| 85 | + | <string>aif</string> | |
| 86 | + | </array> | |
| 87 | + | </dict> | |
| 88 | + | </array> | |
| 89 | + | </dict> | |
| 90 | + | </plist> | |
| 91 | + | PLIST | |
| 92 | + | fi | |
| 93 | + | ||
| 94 | + | # Step 3: Code sign the app bundle | |
| 95 | + | echo "==> Signing app bundle..." | |
| 96 | + | codesign --deep --force --options runtime \ | |
| 97 | + | --sign "$SIGNING_IDENTITY" \ | |
| 98 | + | "$APP_BUNDLE" | |
| 99 | + | ||
| 100 | + | echo "==> Verifying signature..." | |
| 101 | + | codesign --verify --deep --strict "$APP_BUNDLE" | |
| 102 | + | ||
| 103 | + | # Step 4: Create DMG | |
| 104 | + | echo "==> Creating DMG..." | |
| 105 | + | rm -f "$DMG_PATH" | |
| 106 | + | ||
| 107 | + | DMG_STAGING="$DIST_DIR/.dmg-staging" | |
| 108 | + | rm -rf "$DMG_STAGING" | |
| 109 | + | mkdir -p "$DMG_STAGING" | |
| 110 | + | cp -R "$APP_BUNDLE" "$DMG_STAGING/" | |
| 111 | + | ln -s /Applications "$DMG_STAGING/Applications" | |
| 112 | + | ||
| 113 | + | hdiutil create -volname "AudioFiles" \ | |
| 114 | + | -srcfolder "$DMG_STAGING" \ | |
| 115 | + | -ov -format UDZO \ | |
| 116 | + | "$DMG_PATH" | |
| 117 | + | ||
| 118 | + | rm -rf "$DMG_STAGING" | |
| 119 | + | ||
| 120 | + | # Step 5: Sign the DMG | |
| 121 | + | echo "==> Signing DMG..." | |
| 122 | + | codesign --force --sign "$SIGNING_IDENTITY" "$DMG_PATH" | |
| 123 | + | ||
| 124 | + | if [ "$SKIP_NOTARIZE" = true ]; then | |
| 125 | + | echo "==> Skipping notarization (--skip-notarize)" | |
| 126 | + | echo "" | |
| 127 | + | echo "Done: $DMG_PATH" | |
| 128 | + | exit 0 | |
| 129 | + | fi | |
| 130 | + | ||
| 131 | + | # Step 6: Notarize | |
| 132 | + | echo "==> Notarizing DMG..." | |
| 133 | + | xcrun notarytool submit "$DMG_PATH" \ | |
| 134 | + | --keychain-profile "$NOTARY_PROFILE" \ | |
| 135 | + | --wait | |
| 136 | + | ||
| 137 | + | # Step 7: Staple | |
| 138 | + | echo "==> Stapling notarization ticket..." | |
| 139 | + | xcrun stapler staple "$DMG_PATH" | |
| 140 | + | ||
| 141 | + | echo "" | |
| 142 | + | echo "Done: $DMG_PATH" |
| @@ -0,0 +1,44 @@ | |||
| 1 | + | #!/usr/bin/env bash | |
| 2 | + | set -euo pipefail | |
| 3 | + | ||
| 4 | + | SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)" | |
| 5 | + | PROJECT_DIR="$(cd "$SCRIPT_DIR/.." && pwd)" | |
| 6 | + | DIST_DIR="$SCRIPT_DIR" | |
| 7 | + | TARGET="x86_64-pc-windows-msvc" | |
| 8 | + | ||
| 9 | + | # Read version from Cargo.toml | |
| 10 | + | VERSION=$(grep '^version' "$PROJECT_DIR/crates/audiofiles-app/Cargo.toml" | head -1 | sed 's/.*"\(.*\)".*/\1/') | |
| 11 | + | echo "Building AudioFiles v${VERSION} Windows (${TARGET})" | |
| 12 | + | ||
| 13 | + | # Prerequisites check | |
| 14 | + | if ! command -v cargo-xwin &>/dev/null; then | |
| 15 | + | echo "Error: cargo-xwin not found. Install with: cargo install cargo-xwin" | |
| 16 | + | exit 1 | |
| 17 | + | fi | |
| 18 | + | ||
| 19 | + | if ! rustup target list --installed | grep -q "$TARGET"; then | |
| 20 | + | echo "Error: Rust target $TARGET not installed. Add with: rustup target add $TARGET" | |
| 21 | + | exit 1 | |
| 22 | + | fi | |
| 23 | + | ||
| 24 | + | # Step 1: Build release binary | |
| 25 | + | echo "==> Building release binary..." | |
| 26 | + | cd "$PROJECT_DIR" | |
| 27 | + | cargo xwin build --release -p audiofiles-app --target "$TARGET" | |
| 28 | + | ||
| 29 | + | # Step 2: Copy artifact | |
| 30 | + | echo "==> Copying artifact..." | |
| 31 | + | EXE_NAME="audiofiles-app.exe" | |
| 32 | + | SRC="$PROJECT_DIR/target/$TARGET/release/$EXE_NAME" | |
| 33 | + | ||
| 34 | + | if [ ! -f "$SRC" ]; then | |
| 35 | + | echo "Error: Build artifact not found at $SRC" | |
| 36 | + | exit 1 | |
| 37 | + | fi | |
| 38 | + | ||
| 39 | + | DEST="$DIST_DIR/AudioFiles_${VERSION}_x86_64.exe" | |
| 40 | + | cp "$SRC" "$DEST" | |
| 41 | + | ||
| 42 | + | echo "" | |
| 43 | + | echo "Done: $DEST" | |
| 44 | + | echo "Size: $(du -h "$DEST" | cut -f1)" |