#!/bin/bash # This is Kdenlive AppImage → Porteus module build script # Version 2026-08-06 # Copyright 2023-2030, Blaze, Dankov, Russia # All rights reserved. # # Redistribution and use of this script, with or without modification, is # permitted provided that the following conditions are met: # # 1. Redistributions of this script must retain the above copyright # notice, this list of conditions and the following disclaimer. # # THIS SOFTWARE IS PROVIDED BY THE AUTHOR "AS IS" AND ANY EXPRESS OR IMPLIED # WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF # MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO # EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, # PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; # OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, # WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR # OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF # ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # root check if [ "$(whoami)" != "root" ]; then echo -e "\nYou need to be root to run this script.\n" exit 1 fi PRGNAM=${PRGNAM:-kdenlive} BUILD=${BUILD:-1} ARCH=$(uname -m) BOLD=${BOLD:-"\e[1m"} CYAN=${CYAN:-"\e[96m"} GREEN=${GREEN:-"\e[92m"} RED=${RED:-"\e[31m"} RESET=${RESET:-"\e[0m"} CWD=$(pwd) TMPDIR=/tmp/portch PKG=$TMPDIR/package-$PRGNAM PKGINFO=$PKG/var/lib/pkgtools/packages OUTPUT=${OUTPUT:-/tmp} cleanup(){ [ -d "$TMPDIR" ] && rm -rf "$TMPDIR" [ -d "$PKG" ] && rm -rf "$PKG" exit } # ---------- obtain latest version and download URL from KDE CDN ---------- BASE_URL="https://download.kde.org/stable/kdenlive/" echo -e "\nFetching latest release info from KDE..." INDEX=$(wget -q -O- --no-check-certificate "$BASE_URL" 2>/dev/null) if [ -z "$INDEX" ]; then echo -e "${RED}Failed to fetch version list from KDE.${RESET}" exit 1 fi VERSIONS=$(echo "$INDEX" | grep -oP 'href="\K\d+\.\d+(?:\.\d+)?/' | tr -d '/' | sort -V) LATEST=$(echo "$VERSIONS" | tail -1) if [ -z "$LATEST" ]; then echo -e "${RED}No version directories found.${RESET}" exit 1 fi VERSION="$LATEST" echo -e "Latest version: ${GREEN}$VERSION${RESET}" LINUX_INDEX=$(wget -q -O- --no-check-certificate "${BASE_URL}${VERSION}/linux/" 2>/dev/null) if [ -z "$LINUX_INDEX" ]; then echo -e "${RED}Failed to fetch linux directory listing.${RESET}" exit 1 fi APPIMAGE_FILE=$(echo "$LINUX_INDEX" | grep -oP 'href="\K[^"]*\.AppImage' -i | head -1) if [ -z "$APPIMAGE_FILE" ]; then echo -e "${RED}AppImage file not found in ${BASE_URL}${VERSION}/linux/${RESET}" exit 1 fi DOWNLOAD_URL="${BASE_URL}${VERSION}/linux/${APPIMAGE_FILE}" # ---------- check existing installation ---------- INSTALLED_VERSION="" if [ -f /opt/kdenlive/version.txt ]; then INSTALLED_VERSION=$(cat /opt/kdenlive/version.txt) fi if [ "$INSTALLED_VERSION" = "$VERSION" ]; then echo -e "You have the latest ${GREEN}$INSTALLED_VERSION${RESET} version of $PRGNAM" sleep 5 exit else read -p "$(echo -e Would you like to build $PRGNAM ${GREEN}$VERSION${RESET} xzm module? [y/n])" -n 1 -r -s && echo if [[ ! $REPLY =~ ^[Yy]$ ]]; then exit fi fi # ---------- prepare build environment ---------- rm -rf "$PKG" "$TMPDIR" mkdir -p "$TMPDIR" "$PKG/opt/$PRGNAM" "$PKG/usr/bin" "$PKG/usr/share/applications" "$PKG/usr/share/pixmaps" # ---------- download AppImage ---------- echo -e "\nDownloading ${CYAN}${BOLD}${APPIMAGE_FILE}${RESET}" wget -q --show-progress --no-check-certificate -O "$TMPDIR/${APPIMAGE_FILE}" "$DOWNLOAD_URL" # ---------- extract AppImage ---------- cd "$TMPDIR" chmod +x "${APPIMAGE_FILE}" echo -e "\nExtracting AppImage (this may take a moment)..." ./"${APPIMAGE_FILE}" --appimage-extract 2>&1 if [ $? -ne 0 ] || [ ! -d "squashfs-root" ]; then echo -e "${RED}Extraction failed!${RESET}" cleanup fi # ====================== language selection ====================== TRANS_DIR=$(find squashfs-root -type d -name translations -not -path "*/share/locale/*" | head -1) if [ -z "$TRANS_DIR" ]; then echo -e "${RED}Translations directory not found, skipping language cleanup.${RESET}" LANG_CHOICE="en" else mapfile -t LANGUAGES < <(ls "$TRANS_DIR"/qtbase_*.qm 2>/dev/null | \ sed -n 's/.*qtbase_\([a-z]\{2,3\}\(_[A-Z]\{2\}\)\?\)\.qm/\1/p' | sort -u) if [ ${#LANGUAGES[@]} -eq 0 ]; then mapfile -t LANGUAGES < <(ls "$TRANS_DIR"/*.qm 2>/dev/null | \ sed -n 's/.*_\([a-z]\{2,3\}\(_[A-Z]\{2\}\)\?\)\.qm/\1/p' | sort -u) fi if [ ${#LANGUAGES[@]} -eq 0 ]; then echo -e "${RED}No language files found, keeping all.${RESET}" LANG_CHOICE="en" else echo -e "\nAvailable languages for Kdenlive:" PS3="Select language to keep (type number): " select LANG_CHOICE in "${LANGUAGES[@]}"; do if [ -n "$LANG_CHOICE" ]; then echo -e "Keeping all English variants and '$LANG_CHOICE'." break else echo -e "${RED}Invalid choice. Try again.${RESET}" fi done fi fi # ---------- cleanup: docs/licenses ---------- find squashfs-root -type d \( -name licenses -o -name doc -o -name man -o -name info \) -exec rm -rf {} + 2>/dev/null # ---------- locale pruning ---------- for LOCALE_DIR in $(find squashfs-root -type d -path "*/share/locale"); do for DIR in "$LOCALE_DIR"/*; do BASENAME=$(basename "$DIR") if [[ "$BASENAME" == en* ]] || [[ "$BASENAME" == "$LANG_CHOICE"* ]]; then continue fi rm -rf "$DIR" done done # ---------- translation pruning ---------- if [ -n "$TRANS_DIR" ]; then for QMFILE in "$TRANS_DIR"/*.qm; do FILENAME=$(basename "$QMFILE" .qm) if [[ "$FILENAME" =~ _en ]] || [[ "$FILENAME" =~ _${LANG_CHOICE}\. ]] || [[ "$FILENAME" =~ _${LANG_CHOICE}$ ]]; then continue fi rm -f "$QMFILE" done find "$TRANS_DIR" -type l -! -exec test -e {} \; -delete fi find squashfs-root -type d -empty -delete 2>/dev/null # ---------- install extracted contents ---------- rm "${APPIMAGE_FILE}" mv squashfs-root/* "$PKG/opt/$PRGNAM/" 2>/dev/null mv squashfs-root/.DirIcon "$PKG/opt/$PRGNAM/" 2>/dev/null mv squashfs-root/org.kde.kdenlive.desktop "$PKG/opt/$PRGNAM/" 2>/dev/null rmdir squashfs-root echo "$VERSION" > "$PKG/opt/$PRGNAM/version.txt" # ---------- icon handling ---------- ICON_SRC="" for candidate in \ "$PKG/opt/$PRGNAM/usr/share/icons/hicolor/256x256/apps/kdenlive.png" \ "$PKG/opt/$PRGNAM/usr/share/icons/hicolor/128x128/apps/kdenlive.png" \ "$PKG/opt/$PRGNAM/usr/share/icons/hicolor/64x64/apps/kdenlive.png" \ "$PKG/opt/$PRGNAM/usr/share/icons/hicolor/48x48/apps/kdenlive.png" \ "$PKG/opt/$PRGNAM/.DirIcon"; do if [ -f "$candidate" ]; then ICON_SRC="$candidate" break fi done if [ -n "$ICON_SRC" ]; then cp "$ICON_SRC" "$PKG/usr/share/pixmaps/kdenlive.png" chmod 644 "$PKG/usr/share/pixmaps/kdenlive.png" else echo -e "${RED}Warning: Icon not found, module will lack an icon.${RESET}" fi # wrapper script cat > "$PKG/usr/bin/kdenlive" << EOF #!/bin/bash cd /opt/$PRGNAM exec ./AppRun "\$@" EOF chmod 755 "$PKG/usr/bin/kdenlive" # ---------- desktop entry (copy original and fix icon path) ---------- ORIG_DESKTOP="" if [ -f "$PKG/opt/$PRGNAM/org.kde.kdenlive.desktop" ]; then ORIG_DESKTOP="$PKG/opt/$PRGNAM/org.kde.kdenlive.desktop" elif [ -f "$PKG/opt/$PRGNAM/usr/share/applications/org.kde.kdenlive.desktop" ]; then ORIG_DESKTOP="$PKG/opt/$PRGNAM/usr/share/applications/org.kde.kdenlive.desktop" fi if [ -n "$ORIG_DESKTOP" ]; then cp "$ORIG_DESKTOP" "$PKG/usr/share/applications/$PRGNAM.desktop" sed -i 's|^Icon=.*|Icon=/usr/share/pixmaps/kdenlive.png|' "$PKG/usr/share/applications/$PRGNAM.desktop" else cat > "$PKG/usr/share/applications/$PRGNAM.desktop" << EOM [Desktop Entry] Name=Kdenlive GenericName=Video Editor Icon=/usr/share/pixmaps/kdenlive.png Exec=kdenlive %F Terminal=false Type=Application Categories=AudioVideo;Video;Editing; EOM echo -e "Fallback desktop file created." fi # ---------- fake Slackware package info ---------- mkdir -p "$PKGINFO" cat > "$PKGINFO/$PRGNAM-$VERSION-$ARCH" << EOM PACKAGE NAME: $PRGNAM-$VERSION-$ARCH PACKAGE DESCRIPTION: kdenlive: kdenlive (video editor) kdenlive: kdenlive: Kdenlive is a free, open source, cross-platform video editor. kdenlive: kdenlive: https://kdenlive.org/ kdenlive: FILE LIST: EOM cd "$PKG" || exit find . -path ./var -prune -o -print | grep -v "^\./var" >> "$PKGINFO/$PRGNAM-$VERSION-$ARCH" # ---------- create xzm module ---------- dir2xzm "$PKG" "$OUTPUT/$PRGNAM-$VERSION-$ARCH-$BUILD.xzm" # ---------- finish ---------- if [ -f "$OUTPUT/$PRGNAM-$VERSION-$ARCH-$BUILD.xzm" ]; then echo -e "\n${BOLD}Your $PRGNAM module is at: ${GREEN}$OUTPUT/$PRGNAM-$VERSION-${ARCH}-${BUILD}.xzm${RESET}\n${BOLD}Please copy it to your modules folder to survive a reboot.${RESET}\n" else echo -e "\n${RED}${BOLD}Failed. Your $PRGNAM module was not built.${RESET}\n" fi cleanup