31 커밋 9d0c484aa0 ... 8aa01958ff

작성자 SHA1 메시지 날짜
  bryan 8aa01958ff 1.34.1 release 1 개월 전
  bryan dc0eaed0f6 Use internal package name 1 개월 전
  bryan f227050f6c Fix rpm --query lookup for --reinstall 1 개월 전
  bryan d3c049818a Make install_mesa_freeworld fedora-specific 1 개월 전
  bryan 17512a2c00 Improve recommends for freeworld packages on fedora 1 개월 전
  bryan 444ebbfa25 Improve recommends for freeworld packages on fedora 1 개월 전
  bryan 8de1608a77 Also remove /usr/lib/jriver 1 개월 전
  bryan 361dcb8ce3 Return successfully 1 개월 전
  bryan 8af309488d Re-enable dnf reinstalls 1 개월 전
  bryan d5aecc6902 Disable CoW recursively in ~/.jriver 1 개월 전
  bryan 82b31361d4 Only disable CoW for ~/.jriver 1 개월 전
  bryan 96d6044c85 Make temp repos more prolific 1 개월 전
  bryan 71c21bf084 Simplify legacy checks 1 개월 전
  bryan 8388a3ab26 Streamline version check 1 개월 전
  bryan 9b978e43b7 Clobber repo file 1 개월 전
  bryan 4b166fd025 use a single suite 1 개월 전
  bryan de2032d389 Add temp debug 1 개월 전
  bryan f21e162177 Selectively remove repo files for --uninstall 1 개월 전
  bryan 768e00dff3 Ask to backup and reset library on --uninstall 1 개월 전
  bryan 5e890900f2 Ask to backup and reset library on --uninstall 1 개월 전
  bryan 18a3ae02fa Narrow --uninstall output 1 개월 전
  bryan c729f1fb9b Allow --uninstall to be used seamlessly before other operations 1 개월 전
  bryan cc7c1d4c5f Also uninstall installJRMC output 1 개월 전
  bryan 36548581d3 Return on successful license restore 1 개월 전
  bryan 605dc78cf8 Cleanup documentation 1 개월 전
  bryan 8b464fffc7 Add README.bbcode 1 개월 전
  bryan eb9c9fbf9d Rollup for new minor version, may be buggy 1 개월 전
  bryan afb9ff6ed5 Make createrepo noisier 1 개월 전
  bryan dfac619e9d Append dev to version name 2 달 전
  bryan 005fe17298 Pass --mcrepo to createrepo service 2 달 전
  bryan 190a6e7b10 Move UID check after parse 2 달 전
4개의 변경된 파일389개의 추가작업 그리고 184개의 파일을 삭제
  1. 0 1
      .gitignore
  2. 136 0
      README.bbcode
  3. 24 15
      README.md
  4. 229 168
      installJRMC

+ 0 - 1
.gitignore

@@ -1,6 +1,5 @@
 .old/
 .old/
 .vscode/
 .vscode/
-README.bbcode
 installJRMC.zip
 installJRMC.zip
 README.shdoc.md
 README.shdoc.md
 output/
 output/

+ 136 - 0
README.bbcode

@@ -0,0 +1,136 @@
+[size=20pt]installJRMC[/size]
+
+This program will install [url=https://www.jriver.com/]JRiver Media Center[/url] and associated services on most Linux distributions.
+
+You can find the latest version of installJRMC, changelog, and documentation in [url=https://git.bryanroessler.com/bryan/installJRMC]my repository[/url].
+
+[size=18pt]tl;dr One-line MC install[/size] 
+[code]curl https://git.bryanroessler.com/bryan/installJRMC/raw/master/installJRMC|bash[/code]
+
+[size=18pt]Instructions[/size]
+
+Download and unzip installJRMC from the attachment below or grab the latest stable version directly:
+[code]curl -O https://git.bryanroessler.com/bryan/installJRMC/raw/master/installJRMC && 
+chmod +x ./installJRMC && 
+./installJRMC [--option [ARGUMENT]]
+[/code]
+
+[tt]installJRMC[/tt] defaults to [tt]--install=repo[/tt] on distros with MC repositories and [tt]--install=local[/tt] on all others.
+Specifying [tt]--build[/tt], [tt]--createrepo[/tt], [tt]--service[/tt], or [tt]--uninstall[/tt] disables the default install method.
+
+[size=18pt]Options[/size]
+
+[code]
+$ installJRMC --help
+--install, -i repo|local
+    repo: Install MC from repository, future updates will be handled by the system package manager
+    local: Build and install MC package from official source package
+--build[=suse|fedora|centos]
+    Build RPM from source DEB but do not install
+    Optionally, specify a target distro for cross-building (ex. --build=suse, note the '=')
+--compat
+    Build/install MC without minimum dependency version requirements
+--mcversion VERSION
+    Specify the MC version, ex. "33", "34.0.31", or "34.0.31-1" (default: latest)
+--arch ARCH
+    Specify the target MC architecture, ex. "amd64", "arm64", etc (default: host architecture)
+--mcrepo REPO
+    Specify the MC repository, ex. "bullseye", "bookworm", "noble", etc (default: host or official)
+--outputdir PATH
+    Generate reusable installJRMC output in this PATH (default: ./output)
+--restorefile RESTOREFILE
+    Restore file location for automatic license registration
+--betapass PASSWORD
+    Enter beta team password for access to beta builds
+--service, -s SERVICE
+    See SERVICES section below for the list of services to deploy
+  --service-type user|system
+      Starts services at boot (system) or user login (user) (default: per-service, see SERVICES)
+--container, -c CONTAINER (TODO: Under construction)
+    See CONTAINERS section below for a list of containers to deploy
+--createrepo[=suse|fedora|centos]
+    Build rpm, copy to webroot, and run createrepo.
+    Optionally, specify a target distro for non-native repo (ex. --createrepo=fedora, note the '=')
+  --createrepo-webroot PATH
+      The webroot directory to install the repo (default: /var/www/jriver/)
+  --createrepo-user USER
+      The web server user if different from the current user
+--no-update
+    Disable the installJRMC update check
+--yes, -y, --auto
+    Always assumes yes for questions
+--version, -v
+    Print installJRMC version and exit
+--debug, -d
+    Print debug output
+--help, -h
+    Print help dialog and exit
+--uninstall, -u
+    Uninstall JRiver MC, service files, and firewall rules (does not remove library or media files)
+[/code]
+
+[size=18pt]Services[/size]
+
+[code]jriver-mediaserver (user)
+    Enable and start a mediaserver systemd service (requires an existing X server)
+jriver-mediacenter (user)
+    Enable and start a mediacenter systemd service (requires an existing X server)
+jriver-x11vnc (user)
+    Enable and start x11vnc for the local desktop (requires an existing X server, does NOT support Wayland)
+  --vncpass and --display are also valid options (see below)
+jriver-xvnc (system)
+    Enable and start a new Xvnc session running JRiver Media Center
+  --vncpass PASSWORD
+    Set vnc password for x11vnc/Xvnc access. If no password is set, the script will either use existing password stored in ~/.vnc/jrmc_passwd or else no password
+  --display DISPLAY
+    Manually specify display to use for x11vnc/Xvnc (ex. ':1')
+jriver-createrepo (system)
+    Install hourly service to build latest MC RPM and run createrepo
+[/code]
+
+Services use a sane default [tt]--service-type[/tt] listed next to the service name in the Services description. 
+User services can be manipulated as an unprivileged user, for example: [tt]systemctl --user stop jriver-mediacenter[/tt] and begin at user login.
+System services are manipulable as root, for example: [tt]sudo systemctl stop jriver-servicename@username.service[/tt] and begin at system boot.
+Note that it is possible to run all services of a particular user at boot using [tt][url=https://www.freedesktop.org/software/systemd/man/loginctl.html]sudo loginctl enable-linger username[/url][/tt].
+
+Multiple services (but not [tt]--service-types[/tt]) can be installed at one time using multiple [tt]--service[/tt] blocks:
+[code]installJRMC --install repo --service jriver-x11vnc --service jriver-mediacenter[/code]
+
+[size=14pt][tt]jriver-x11vnc[/tt] versus [tt]jriver-xvnc[/tt][/size]
+
+[url=http://www.karlrunge.com/x11vnc/]jriver-x11vnc[/url] shares your existing X display via VNC and can be combined with additional services to start Media Center or Media Server. Conversely, [url=https://tigervnc.org/doc/Xvnc.html]jriver-xvnc[/url] creates a new Xvnc display and starts a JRiver Media Center service in the foreground of the new VNC display.
+
+[size=18pt]Containers[/size]
+
+[b]Coming soon![/b]
+
+[size=18pt]Firewall[/size]
+
+installJRMC automatically creates port forwarding firewall rules for remote access to Media Network (52100-52200/tcp, 1900/udp DLNA) and Xvnc/x11vnc (if selected), using firewall-cmd or ufw.
+
+[size=18pt]Examples[/size]
+
+[code]installJRMC[/code]
+Install the latest version of MC from the best available repository.
+[code]installJRMC --mcversion 33 --debug[/code]
+Install the latest version of MC33 from the best available repository with debugging output.
+[code]installJRMC --install local --compat[/code]
+Install a more widely-compatible version of the latest MC version.
+[code]installJRMC --install repo --service jriver-mediacenter --service-type user[/code]
+Install MC from the repository and start/enable jriver-mediacenter.service as a user service.
+[code]installJRMC --install local --compat --restorefile /path/to/license.mjr --mcversion 34.0.31[/code]
+Build and install an MC 34.0.31 comptability RPM locally and activate it using the /path/to/license.mjr
+[code]installJRMC --createrepo --createrepo-webroot /srv/jriver/repo --createrepo-user www-user[/code]
+Build an RPM locally for the current distro, move it to the webroot, and run createrepo as www-user.
+[code]installJRMC --service jriver-createrepo --createrepo-webroot /srv/jriver/repo --createrepo-user www-user[/code]
+Install the jriver-createrepo timer and service to build the RPM, move it to the webroot, and run createrepo as www-user hourly.
+[code]installJRMC --install repo --service jriver-x11vnc --service jriver-mediacenter --vncpass "letmein"[/code]
+Install services to share the existing local desktop via VNC and automatically run MC on startup.
+[code]installJRMC --install repo --service jriver-xvnc --display ":2"[/code]
+Install an Xvnc server on display ':2' that starts MC.
+[code]installJRMC --uninstall[/code]
+Uninstall MC, services, and firewall rules. This will [b]not[/b] remove your media, media library/database, or library backups.
+
+[size=18pt]Additional Info[/size]
+
+Did you find installJRMC useful? [url=https://paypal.me/bryanroessler]Buy me a coffee![/url]

+ 24 - 15
README.md

@@ -1,6 +1,6 @@
 # installJRMC
 # installJRMC
 
 
-This self-contained program will install [JRiver Media Center](https://www.jriver.com/) and associated services on most Linux distributions.
+This program will install [JRiver Media Center](https://www.jriver.com/) and associated services on most Linux distributions.
 
 
 You can find the latest version of installJRMC, changelog, and documentation in [my repository](https://git.bryanroessler.com/bryan/installJRMC).
 You can find the latest version of installJRMC, changelog, and documentation in [my repository](https://git.bryanroessler.com/bryan/installJRMC).
 
 
@@ -8,11 +8,10 @@ You can find the latest version of installJRMC, changelog, and documentation in
 
 
 `installJRMC [--option [ARGUMENT]]`
 `installJRMC [--option [ARGUMENT]]`
 
 
-Running `installJRMC` without any options implies `--install repo` (on SUSE: `--install local`) and will install the latest version of Media Center from the official JRiver repository (Ubuntu/Debian) or my [unofficial repository](https://repos.bryanroessler.com/jriver/) (Fedora/CentOS) using the system package manager. If `--service` or `--container` is passed then the default install method (`--install repo` or `--install local`) must be specified (to allow services and containers to be installed independent of MC).
+`installJRMC` defaults to `--install=repo` on distros with MC repositories and `--install=local` on all others.
+Specifying `--build`, `--createrepo`, `--service`, or `--uninstall` disables the default install method.
 
 
-Recent versions of installJRMC will automatically self-update to the latest installJRMC release.
-
-## tl;dr
+### tl;dr
 
 
 `curl https://git.bryanroessler.com/bryan/installJRMC/raw/master/installJRMC|bash`
 `curl https://git.bryanroessler.com/bryan/installJRMC/raw/master/installJRMC|bash`
 
 
@@ -29,7 +28,7 @@ $ installJRMC --help
 --compat
 --compat
     Build/install MC without minimum dependency version requirements
     Build/install MC without minimum dependency version requirements
 --mcversion VERSION
 --mcversion VERSION
-    Build or install a specific MC version, ex. "34.0.20" or "33" (default: latest)
+    Build or install a specific MC version, ex. "34.0.31" or "33" (default: latest)
 --mcrepo REPO
 --mcrepo REPO
     Specify the MC repository, ex. "bullseye", "bookworm", "noble", etc (default: latest official)
     Specify the MC repository, ex. "bullseye", "bookworm", "noble", etc (default: latest official)
 --arch ARCH
 --arch ARCH
@@ -58,7 +57,7 @@ $ installJRMC --help
 --yes, -y, --auto
 --yes, -y, --auto
     Always assume yes for questions
     Always assume yes for questions
 --version, -v
 --version, -v
-    Print this script version and exit
+    Print installJRMC version and exit
 --debug, -d
 --debug, -d
     Print debug output
     Print debug output
 --help, -h
 --help, -h
@@ -85,14 +84,13 @@ jriver-xvnc [--service-type=system]
     Manually specify display to use for x11vnc/Xvnc (ex. ':1')
     Manually specify display to use for x11vnc/Xvnc (ex. ':1')
 jriver-createrepo [--service-type=system]
 jriver-createrepo [--service-type=system]
     Install hourly service to build latest MC RPM and run createrepo
     Install hourly service to build latest MC RPM and run createrepo
-    By default installs as root service to handle www permissions more gracefully
 ```
 ```
 
 
 #### `--service-type=`
 #### `--service-type=`
 
 
-By default, MC services use a sane `--service-type` listed next to the service name in the [`--service=`](#--service) section. User services begin at user login and are managed by the unprivileged user, for example: `systemctl --user stop jriver-mediacenter`. System services begin at boot and are managed by root, for example: `sudo systemctl stop jriver-servicename@username.service`. It is possible to run all services of a particular user at boot using [`sudo loginctl enable-linger username`](https://www.freedesktop.org/software/systemd/man/loginctl.html).
+Services use a sane default `--service-type` listed next to the service name in the [`--service=`](#--service) section. User services begin at user login and are managed by the unprivileged user, for example: `systemctl --user stop jriver-mediacenter`. System services begin at boot and are managed by root, for example: `sudo systemctl stop jriver-servicename@username.service`. It is possible to run all services of a particular user at boot using [`sudo loginctl enable-linger username`](https://www.freedesktop.org/software/systemd/man/loginctl.html).
 
 
-Multiple services (but not `--service-types`) can be installed at one time using multiple `--service` blocks: `installJRMC --install repo --service jriver-x11vnc --service jriver-mediacenter`
+Multiple services (but not `--service-types`) can be installed at one time using multiple `--service` blocks: `installJRMC --install=repo --service=jriver-x11vnc --service=jriver-mediacenter`
 
 
 #### `jriver-x11vnc` versus `jriver-xvnc`
 #### `jriver-x11vnc` versus `jriver-xvnc`
 
 
@@ -108,15 +106,26 @@ Multiple services (but not `--service-types`) can be installed at one time using
 
 
 **Note:** `ufw` is not installed by default on Debian but will be installed by `installJRMC`. To prevent SSH lock-out, Debian users that have not already enabled `ufw` will need to `sudo ufw enable` after running `installJRMC` and inspecting their configuration.
 **Note:** `ufw` is not installed by default on Debian but will be installed by `installJRMC`. To prevent SSH lock-out, Debian users that have not already enabled `ufw` will need to `sudo ufw enable` after running `installJRMC` and inspecting their configuration.
 
 
+## Nicities
+
+Depending on the distribution, `installJRMC` also performs the following tasks during MC installation:
+
+* Automatically updates `installJRMC` to the latest release
+* Activates external third-party repositories for improved media playback (hardware decoding, etc.)
+* Adds temporary legacy repositories to provide deprecated libraries
+* Links non-standard SSL certs
+* Disables BTRFS CoW for MC database directories
+* Activates MC if a valid license file is found in common locations
+
 ## Examples
 ## Examples
 
 
 * `installJRMC`
 * `installJRMC`
 
 
     Install the latest version of MC from the best available repository.
     Install the latest version of MC from the best available repository.
 
 
-* `installJRMC --mcversion 32 --debug`
+* `installJRMC --mcversion 33 --debug`
 
 
-    Install the latest version of MC32 from the best available repository with debugging output.
+    Install the latest version of MC33 from the best available repository with debugging output.
 
 
 * `installJRMC --install local --compat`
 * `installJRMC --install local --compat`
 
 
@@ -126,9 +135,9 @@ Multiple services (but not `--service-types`) can be installed at one time using
 
 
     Install MC from the repository and start/enable `jriver-mediacenter.service` as a user service.
     Install MC from the repository and start/enable `jriver-mediacenter.service` as a user service.
 
 
-* `installJRMC --install local --compat --restorefile /path/to/license.mjr --mcversion 34.0.20`
+* `installJRMC --install local --compat --restorefile /path/to/license.mjr --mcversion 34.0.31`
 
 
-    Build and install an MC 34.0.20 compatibility RPM locally and activate it using the `/path/to/license.mjr`
+    Build and install an MC 34.0.31 compatibility RPM locally and activate it using the `/path/to/license.mjr`
 
 
 * `installJRMC --createrepo --createrepo-webroot /srv/jriver/repo --createrepo-user www-user`
 * `installJRMC --createrepo --createrepo-webroot /srv/jriver/repo --createrepo-user www-user`
 
 
@@ -154,4 +163,4 @@ Multiple services (but not `--service-types`) can be installed at one time using
 
 
 Did you find `installJRMC` useful? [Buy me a coffee!](https://paypal.me/bryanroessler)
 Did you find `installJRMC` useful? [Buy me a coffee!](https://paypal.me/bryanroessler)
 
 
-Did you find a bug? Let me know on [Interact!](https://yabb.jriver.com/interact/index.php/topic,134152.0.html)
+Did you find a bug? [Let me know on Interact!](https://yabb.jriver.com/interact/index.php/topic,141168.0.html)

+ 229 - 168
installJRMC

@@ -1,5 +1,4 @@
 #!/usr/bin/env bash
 #!/usr/bin/env bash
-# shellcheck disable=SC2317
 # @file installJRMC
 # @file installJRMC
 # @brief Installs JRiver Media Center and associated services
 # @brief Installs JRiver Media Center and associated services
 # @description See installJRMC --help or print_help() below for usage
 # @description See installJRMC --help or print_help() below for usage
@@ -17,10 +16,13 @@
 # NOTES
 # NOTES
 # * Be careful with tabs in heredocs
 # * Be careful with tabs in heredocs
 # * Avoid execute() for stdout
 # * Avoid execute() for stdout
+#
+# We use indirection to match service names to their functions
+# shellcheck disable=SC2317
 shopt -s extglob
 shopt -s extglob
 
 
-declare -g SCRIPT_VERSION="1.6.5"
-declare -g MC_VERSION="34.0.20" # do find all replace
+declare -g SCRIPT_VERSION="1.34.1"
+declare -g MC_VERSION="34.0.31" # do find all replace
 declare -g MC_REPO="bookworm" # should match the MC_VERSION
 declare -g MC_REPO="bookworm" # should match the MC_VERSION
 declare -g BOARD_ID="89.0" # MC34
 declare -g BOARD_ID="89.0" # MC34
 declare -gi UPDATE_SWITCH=1 # set to 0 to disable automatic self-update
 declare -gi UPDATE_SWITCH=1 # set to 0 to disable automatic self-update
@@ -33,28 +35,32 @@ print_help() {
   debug "${FUNCNAME[0]}()"
   debug "${FUNCNAME[0]}()"
 
 
   cat <<-EOF
   cat <<-EOF
+		SEE:
+		  README.md for more information
+
 		USAGE:
 		USAGE:
 		  installJRMC [[OPTION] [VALUE]]...
 		  installJRMC [[OPTION] [VALUE]]...
 
 
-		  If no options (excluding -d or --debug) are provided installJRMC defaults to '--install repo'.
+		  installJRMC defaults to --install=repo on platforms with a JRiver repository and --install=local on all others.
+		  Specifying --build, --createrepo, --service, or --uninstall disables the default install method.
 
 
 		OPTIONS
 		OPTIONS
 		  --install, -i repo|local
 		  --install, -i repo|local
 		    repo: Install MC from repository, updates are handled by the system package manager
 		    repo: Install MC from repository, updates are handled by the system package manager
-		    local: Build and install MC package locally from official source release
+		    local: Build and install MC locally from official source package
 		  --build[=suse|fedora|centos]
 		  --build[=suse|fedora|centos]
 		    Build RPM from source DEB but do not install
 		    Build RPM from source DEB but do not install
 		    Optionally, specify a target distro for cross-building (ex. --build=suse, note the '=')
 		    Optionally, specify a target distro for cross-building (ex. --build=suse, note the '=')
 		  --compat
 		  --compat
 		    Build/install MC locally without minimum dependency version requirements
 		    Build/install MC locally without minimum dependency version requirements
 		  --mcversion VERSION
 		  --mcversion VERSION
-		    Specify the MC version, ex. "$MC_VERSION" or "${MC_VERSION%%.*}"
+		    Specify the MC version, ex. "$MC_VERSION" or "${MC_VERSION%%.*}" (default: latest release)
 		  --arch VERSION
 		  --arch VERSION
 		    Specify the target MC architecture, ex. "amd64", "arm64", etc (default: host)
 		    Specify the target MC architecture, ex. "amd64", "arm64", etc (default: host)
 		  --mcrepo REPO
 		  --mcrepo REPO
 		    Specify the MC repository, ex. "bullseye", "bookworm", "noble", etc (default: auto)
 		    Specify the MC repository, ex. "bullseye", "bookworm", "noble", etc (default: auto)
 		  --outputdir PATH
 		  --outputdir PATH
-		    Generate rpmbuild output in this directory (default: ./output)
+		    Generate reusable installJRMC output in this PATH (default: ./output)
 		  --restorefile MJR_FILE
 		  --restorefile MJR_FILE
 		    Restore file location for automatic license registration
 		    Restore file location for automatic license registration
 		  --betapass PASSWORD
 		  --betapass PASSWORD
@@ -80,7 +86,7 @@ print_help() {
 		  --yes, -y, --auto
 		  --yes, -y, --auto
 		    Assume yes response to questions
 		    Assume yes response to questions
 		  --version, -v
 		  --version, -v
-		    Print this script version and exit
+		    Print installJRMC version and exit
 		  --debug, -d
 		  --debug, -d
 		    Print debug output
 		    Print debug output
 		  --help, -h
 		  --help, -h
@@ -99,16 +105,12 @@ print_help() {
 		    Enable and start a new Xvnc session running JRiver Media Center
 		    Enable and start a new Xvnc session running JRiver Media Center
 		    --vncpass PASSWORD
 		    --vncpass PASSWORD
 		      Set the vnc password for x11vnc/Xvnc access. If no password is set, installJRMC
 		      Set the vnc password for x11vnc/Xvnc access. If no password is set, installJRMC
-		      will either use existing password stored in \$HOME/.vnc/jrmc_passwd or use no password
+		      will either use existing password stored in \$HOME/.vnc/jrmc_passwd or else no password
 		    --display DISPLAY
 		    --display DISPLAY
 		      Display to use for x11vnc/Xvnc (default: The current display (x11vnc) or the
 		      Display to use for x11vnc/Xvnc (default: The current display (x11vnc) or the
 		      current display incremented by 1 (Xvnc))
 		      current display incremented by 1 (Xvnc))
 		  jriver-createrepo (system)
 		  jriver-createrepo (system)
 		    Install hourly service to build latest MC RPM and run createrepo
 		    Install hourly service to build latest MC RPM and run createrepo
-
-		CONTAINERS (TODO: Under construction)
-		  mediacenter-xvnc
-		  createrepo
 	EOF
 	EOF
 }
 }
 
 
@@ -134,8 +136,7 @@ parse_input() {
     eval set -- "$input"
     eval set -- "$input"
     while true; do
     while true; do
       case $1 in
       case $1 in
-        --install|-i)
-          shift
+        --install|-i) shift;
           case $1 in
           case $1 in
             local|rpm|deb) BUILD_SWITCH=1 LOCAL_INSTALL_SWITCH=1 ;;
             local|rpm|deb) BUILD_SWITCH=1 LOCAL_INSTALL_SWITCH=1 ;;
             repo|remote) REPO_INSTALL_SWITCH=1 ;;
             repo|remote) REPO_INSTALL_SWITCH=1 ;;
@@ -151,11 +152,11 @@ parse_input() {
           if [[ $1 =~ ^([0-9]+)(\.[0-9]+\.[0-9]+)?(-([0-9]+))?$ ]]; then
           if [[ $1 =~ ^([0-9]+)(\.[0-9]+\.[0-9]+)?(-([0-9]+))?$ ]]; then
             # Major version is required
             # Major version is required
             USER_MC_MVERSION="${BASH_REMATCH[1]}"
             USER_MC_MVERSION="${BASH_REMATCH[1]}"
-            # If we get the full version, use it
-            [[ -n ${BASH_REMATCH[2]} ]] && USER_MC_VERSION="${BASH_REMATCH[1]}${BASH_REMATCH[2]}"
             # Set default release to 1 if not provided
             # Set default release to 1 if not provided
             USER_MC_RELEASE="${BASH_REMATCH[4]:-1}"
             USER_MC_RELEASE="${BASH_REMATCH[4]:-1}"
-            
+            # If we get the full version, use it
+            [[ -n ${BASH_REMATCH[2]} ]] && USER_MC_VERSION="${BASH_REMATCH[1]}${BASH_REMATCH[2]}"
+
             # Set major version defaults
             # Set major version defaults
             case "$USER_MC_MVERSION" in
             case "$USER_MC_MVERSION" in
               34) MC_VERSION="${USER_MC_VERSION:-$MC_VERSION}" MC_REPO="bookworm" BOARD_ID="89.0" ;;
               34) MC_VERSION="${USER_MC_VERSION:-$MC_VERSION}" MC_REPO="bookworm" BOARD_ID="89.0" ;;
@@ -181,7 +182,7 @@ parse_input() {
           ;;
           ;;
         --arch) shift; USER_ARCH="$1" ;;
         --arch) shift; USER_ARCH="$1" ;;
         --mcrepo) shift; USER_MC_REPO="$1" ;;
         --mcrepo) shift; USER_MC_REPO="$1" ;;
-        --restorefile) shift; MJR_FILE="$1" ;;
+        --restorefile) shift; MJR_FILE="$1"; [[ -f $MJR_FILE ]] || err "Specified license $MJR_FILE missing." ;;
         --betapass) shift; BETAPASS="$1" ;;
         --betapass) shift; BETAPASS="$1" ;;
         --service-type) shift; SERVICE_TYPE="$1" ;;
         --service-type) shift; SERVICE_TYPE="$1" ;;
         --service|-s|--services) shift; SERVICES+=("$1") ;;
         --service|-s|--services) shift; SERVICES+=("$1") ;;
@@ -207,12 +208,11 @@ parse_input() {
     err "Incorrect option provided, see installJRMC --help"; exit 1
     err "Incorrect option provided, see installJRMC --help"; exit 1
   fi
   fi
 
 
-  # Fallback to default install method in some scenarios
-  if ! ((UNINSTALL_SWITCH + BUILD_SWITCH + CREATEREPO_SWITCH + 
-    LOCAL_INSTALL_SWITCH + CONTAINER_INSTALL_SWITCH + SNAP_INSTALL_SWITCH +
-    APPIMAGE_INSTALL_SWITCH)) &&
-    [[ ${#SERVICES[@]} -eq 0 && ${#CONTAINERS[@]} -eq 0 ]]; then
-    debug "Automatically using --install=repo"
+  # Set some default conditions
+  if ! ((UNINSTALL_SWITCH || BUILD_SWITCH || CREATEREPO_SWITCH || LOCAL_INSTALL_SWITCH
+  || CONTAINER_INSTALL_SWITCH || SNAP_INSTALL_SWITCH || APPIMAGE_INSTALL_SWITCH)) &&
+  [[ ${#SERVICES[@]} -eq 0 && ${#CONTAINERS[@]} -eq 0 ]]; then
+    debug "Defaulting to --install=repo"
     REPO_INSTALL_SWITCH=1
     REPO_INSTALL_SWITCH=1
   fi
   fi
 
 
@@ -220,16 +220,12 @@ parse_input() {
     echo "Warning: not all repositories have beta channels"
     echo "Warning: not all repositories have beta channels"
     echo "If the MC package is unavailable, try using --mcrepo to select another repository"
     echo "If the MC package is unavailable, try using --mcrepo to select another repository"
   fi
   fi
-
-  # if [[ -n $CONTAINER_INSTALL_SWITCH ]] && ((LOCAL_INSTALL_SWITCH || REPO_INSTALL_SWITCH)); then
-  #   err "Some --install methods are incompatible"
-  # fi
 }
 }
 
 
 # @description Perform OS detection and generate OS-specific functions
 # @description Perform OS detection and generate OS-specific functions
 # @see parse_input
 # @see parse_input
 init() {
 init() {
-  debug "${FUNCNAME[0]}()"
+  debug "${FUNCNAME[0]}()" "$@"
   declare -g USER
   declare -g USER
   declare -g SCRIPT_PATH; SCRIPT_PATH=$(readlink -f "${BASH_SOURCE[0]}")
   declare -g SCRIPT_PATH; SCRIPT_PATH=$(readlink -f "${BASH_SOURCE[0]}")
   declare -g SCRIPT_DIR; SCRIPT_DIR=$(readlink -f "$(dirname "${BASH_SOURCE[0]}")")
   declare -g SCRIPT_DIR; SCRIPT_DIR=$(readlink -f "$(dirname "${BASH_SOURCE[0]}")")
@@ -241,20 +237,18 @@ init() {
   declare -ga PKG_INSTALL PKG_REMOVE PKG_UPDATE PKG_QUERY
   declare -ga PKG_INSTALL PKG_REMOVE PKG_UPDATE PKG_QUERY
   declare -ga SERVICES CONTAINERS
   declare -ga SERVICES CONTAINERS
 
 
+  parse_input "$@"
+
   # Try to save users from themselves
   # Try to save users from themselves
-  if ((EUID == 0)); then
+  if [[ $EUID -eq 0 ]]; then
     err "Running as root but attempting to continue"
     err "Running as root but attempting to continue"
-    ask_ok "Continue as root user?" || exit 1
-  fi
-
-  if [[ -n $SUDO_USER ]]; then
+    ask_ok "Continue as root user (not recommended)?" || exit 1
+  elif [[ -n $SUDO_USER ]]; then
     err "Sudo detected, installJRMC should not be run with sudo but attempting to continue"
     err "Sudo detected, installJRMC should not be run with sudo but attempting to continue"
     ask_ok "Continue as user $SUDO_USER (unsupported and may result in permission issues)?" || exit 1
     ask_ok "Continue as user $SUDO_USER (unsupported and may result in permission issues)?" || exit 1
     USER="${SUDO_USER:-$USER}"
     USER="${SUDO_USER:-$USER}"
   fi
   fi
 
 
-  parse_input "$@"
-
   # Run the self-updater if enabled
   # Run the self-updater if enabled
   ((UPDATE_SWITCH)) && update "$@"
   ((UPDATE_SWITCH)) && update "$@"
 
 
@@ -293,7 +287,7 @@ init() {
     raspbian) ID="debian" ;;
     raspbian) ID="debian" ;;
     manjaro|arch) ID="arch"
     manjaro|arch) ID="arch"
       if ((REPO_INSTALL_SWITCH)); then
       if ((REPO_INSTALL_SWITCH)); then
-        debug "Automatically using --install=local for SUSE"
+        debug "Automatically using --install=local for Arch"
         REPO_INSTALL_SWITCH=0
         REPO_INSTALL_SWITCH=0
         BUILD_SWITCH=1
         BUILD_SWITCH=1
         LOCAL_INSTALL_SWITCH=1
         LOCAL_INSTALL_SWITCH=1
@@ -384,7 +378,7 @@ init() {
   fi
   fi
   MC_REPO="${USER_MC_REPO:-$MC_REPO}" # allow user override
   MC_REPO="${USER_MC_REPO:-$MC_REPO}" # allow user override
 
 
-  echo "MC target: $MC_REPO $MC_ARCH -> $BUILD_TARGET $ARCH"
+  echo "MC source -> target: $MC_REPO $MC_ARCH -> $BUILD_TARGET $ARCH"
 
 
   # Retrieves the latest MC version number if we need it
   # Retrieves the latest MC version number if we need it
   if ((BUILD_SWITCH || LOCAL_INSTALL_SWITCH || CREATEREPO_SWITCH)); then
   if ((BUILD_SWITCH || LOCAL_INSTALL_SWITCH || CREATEREPO_SWITCH)); then
@@ -433,7 +427,7 @@ get_latest_mc_version() {
     err "Warning! Using hardcoded version number"
     err "Warning! Using hardcoded version number"
   fi
   fi
     
     
-  echo "Determined MC version $MC_VERSION from the $MC_REPO repo (via $mc_version_source)"
+  echo "Selected MC version $MC_VERSION from the $MC_REPO repo (via $mc_version_source)"
 }
 }
 
 
 # @description Installs a package using the system package manager
 # @description Installs a package using the system package manager
@@ -449,6 +443,7 @@ install_package() {
   local input pkg _pkg
   local input pkg _pkg
   local -i no_install_check=0 allow_downgrades=0 silent=0 refresh=0 no_gpg_check=0 reinstall=0
   local -i no_install_check=0 allow_downgrades=0 silent=0 refresh=0 no_gpg_check=0 reinstall=0
   local long_opts="no-install-check,allow-downgrades,no-gpg-check,refresh,reinstall,silent"
   local long_opts="no-install-check,allow-downgrades,no-gpg-check,refresh,reinstall,silent"
+  local -a pkg_install=("${PKG_INSTALL[@]}")
 
 
   input=$(getopt -o +s -l "$long_opts" -- "$@") || { err "Incorrect options provided"; exit 1; }
   input=$(getopt -o +s -l "$long_opts" -- "$@") || { err "Incorrect options provided"; exit 1; }
   eval set -- "$input"
   eval set -- "$input"
@@ -482,27 +477,20 @@ install_package() {
 
 
   # Filter out already installed packages to create pkg_array
   # Filter out already installed packages to create pkg_array
   for pkg in "$@"; do
   for pkg in "$@"; do
+    # Use alias if present, otherwise just pkg itself
+    pkg_names=("$pkg")
     if [[ -v pkg_aliases[$pkg] ]]; then
     if [[ -v pkg_aliases[$pkg] ]]; then
       debug "Aliasing $pkg to ${pkg_aliases[$pkg]}"
       debug "Aliasing $pkg to ${pkg_aliases[$pkg]}"
-      IFS=' ' read -ra pkgs <<< "${pkg_aliases[$pkg]}"
-      for _pkg in "${pkgs[@]}"; do
-        if ((no_install_check)) ||
-        ! { command -v "$_pkg" &>/dev/null ||
-        "${PKG_QUERY[@]}" "$_pkg" &>/dev/null; }; then
-          pkg_array+=("$_pkg")
-        else
-          debug "$_pkg is already installed, skipping installation"
-        fi
-      done
-    else
-      if ((no_install_check)) ||
-      ! { command -v "$pkg" &>/dev/null ||
-      "${PKG_QUERY[@]}" "$pkg" &>/dev/null; }; then
-        pkg_array+=("$pkg")
+      IFS=' ' read -ra pkg_names <<< "${pkg_aliases[$pkg]}"
+    fi
+    for p in "${pkg_names[@]}"; do
+      if (( no_install_check )) ||
+      ! { command -v "$p" &>/dev/null || "${PKG_QUERY[@]}" "$p" &>/dev/null; }; then
+        pkg_array+=("$p")
       else
       else
-        debug "$pkg is already installed, skipping installation"
+        debug "$p is already installed, skipping installation"
       fi
       fi
-    fi
+    done
   done
   done
 
 
   # Generate installation flags based on the distribution
   # Generate installation flags based on the distribution
@@ -514,17 +502,18 @@ install_package() {
       ((allow_downgrades)) && install_flags+=(--allowerasing)
       ((allow_downgrades)) && install_flags+=(--allowerasing)
       ((no_gpg_check)) && install_flags+=(--nogpgcheck)
       ((no_gpg_check)) && install_flags+=(--nogpgcheck)
       ((refresh)) && install_flags+=(--refresh)
       ((refresh)) && install_flags+=(--refresh)
-      # if ((reinstall)) && [[ ${#pkg_array[@]} -eq 1 ]] && "${PKG_QUERY[@]}" "${pkg_array[0]}" &>/dev/null; then
-      #   PKG_INSTALL=("${PKG_INSTALL[@]/install/reinstall}")
-      # fi
+      # Only add reinstall flag for mediacenter package
+      if ((reinstall)) && [[ ${#pkg_array[@]} -eq 1 ]] && "${PKG_QUERY[@]}" "mediacenter$MC_MVERSION" &>/dev/null; then
+        pkg_install=("${pkg_install[@]/install/reinstall}")
+      fi
       ;;
       ;;
     suse)
     suse)
       ((no_gpg_check)) && install_flags+=(--allow-unsigned-rpm) ;;
       ((no_gpg_check)) && install_flags+=(--allow-unsigned-rpm) ;;
   esac
   esac
 
 
-  # Install packages if any need installation
+  # Install packages
   if [[ ${#pkg_array[@]} -gt 0 ]]; then
   if [[ ${#pkg_array[@]} -gt 0 ]]; then
-    if ! execute "${PKG_INSTALL[@]}" "${install_flags[@]}" "${pkg_array[@]}"; then     
+    if ! execute "${pkg_install[@]}" "${install_flags[@]}" "${pkg_array[@]}"; then     
       ((silent)) || err "Failed to install ${pkg_array[*]}"
       ((silent)) || err "Failed to install ${pkg_array[*]}"
       return 1
       return 1
     fi
     fi
@@ -568,10 +557,8 @@ install_external_repos() {
         install_package --no-install-check \
         install_package --no-install-check \
           "https://download1.rpmfusion.org/free/fedora/rpmfusion-free-release-$VERSION_ID.noarch.rpm"
           "https://download1.rpmfusion.org/free/fedora/rpmfusion-free-release-$VERSION_ID.noarch.rpm"
       fi
       fi
-      # Install mesa-va-drivers-freeworld separately from the RPM using dnf swap
-      install_mesa_freeworld
       ;;
       ;;
-    suse) : # TODO may be needed if X11_XOrg is unavailable in default repos
+    suse) : # TODO may be needed if X11_XOrg is made unavailable in default repos
       # if ! zypper repos | grep -q "X11_XOrg"; then
       # if ! zypper repos | grep -q "X11_XOrg"; then
       #   echo "Installing the X11 repository"
       #   echo "Installing the X11 repository"
       #   execute sudo zypper  --non-interactive --quiet addrepo \
       #   execute sudo zypper  --non-interactive --quiet addrepo \
@@ -582,22 +569,26 @@ install_external_repos() {
   esac
   esac
 }
 }
 
 
-# @description Installs mesa-va-drivers-freeworld
+# @description Installs mesa-va-drivers-freeworld on Fedora
 install_mesa_freeworld() {
 install_mesa_freeworld() {
   debug "${FUNCNAME[0]}()"
   debug "${FUNCNAME[0]}()"
   local pkg freeworld_pkg
   local pkg freeworld_pkg
-  for pkg in mesa-va-drivers mesa-vdpau-drivers mesa-vulkan-drivers; do
-    freeworld_pkg="${pkg}-freeworld"
-    if ! "${PKG_QUERY[@]}" "$freeworld_pkg" &>/dev/null; then
-      if "${PKG_QUERY[@]}" "$pkg" &>/dev/null; then
-        if ! execute sudo dnf swap -y "$pkg" "$freeworld_pkg"; then
-          err "Package swap failed for $pkg!"
+  case $ID in
+    fedora)
+      for pkg in mesa-va-drivers mesa-vdpau-drivers mesa-vulkan-drivers; do
+        freeworld_pkg="${pkg}-freeworld"
+        if ! "${PKG_QUERY[@]}" "$freeworld_pkg" &>/dev/null; then
+          if "${PKG_QUERY[@]}" "$pkg" &>/dev/null; then
+            if ! execute sudo dnf swap -y "$pkg" "$freeworld_pkg"; then
+              err "Package swap failed for $pkg!"
+            fi
+          else
+            "${PKG_INSTALL[@]}" "$freeworld_pkg"
+          fi
         fi
         fi
-      else
-        "${PKG_INSTALL[@]}" "$freeworld_pkg"
-      fi
-    fi
-  done
+      done
+      ;;
+  esac
 }
 }
 
 
 # @description Installs JRiver Media Center from a remote repository
 # @description Installs JRiver Media Center from a remote repository
@@ -627,7 +618,7 @@ install_mc_repo() {
           repo_file="/etc/apt/sources.list.d/jriver.sources"
           repo_file="/etc/apt/sources.list.d/jriver.sources"
         fi
         fi
 
 
-        # Remove old repo
+        # Remove deprecated repo files
         old_repo_files=(
         old_repo_files=(
           "/etc/apt/sources.list.d/jriver.list"
           "/etc/apt/sources.list.d/jriver.list"
           "/etc/apt/sources.list.d/jriver-beta.list"
           "/etc/apt/sources.list.d/jriver-beta.list"
@@ -642,9 +633,9 @@ install_mc_repo() {
 					Types: deb
 					Types: deb
 					URIs: https://dist.jriver.com/$channel/mediacenter/
 					URIs: https://dist.jriver.com/$channel/mediacenter/
 					Signed-By: $keyfile
 					Signed-By: $keyfile
-					Suites: $MC_REPO trixie bookworm bullseye oracular noble jammy focal
+					Suites: $MC_REPO
 					Components: main
 					Components: main
-					Architectures: amd64 i386 armhf arm64
+					Architectures: amd64 armhf arm64
 				EOF
 				EOF
       else
       else
         if [[ $channel == "beta" ]]; then
         if [[ $channel == "beta" ]]; then
@@ -653,7 +644,7 @@ install_mc_repo() {
         else
         else
           repo_file="/etc/apt/sources.list.d/jriver.list"
           repo_file="/etc/apt/sources.list.d/jriver.list"
         fi
         fi
-        repo_text="deb [signed-by=$keyfile arch=amd64,i386,armhf,arm64] https://dist.jriver.com/$channel/mediacenter/ $MC_REPO main"
+        repo_text="deb [signed-by=$keyfile arch=amd64,armhf,arm64] https://dist.jriver.com/$channel/mediacenter/ $MC_REPO main"
       fi
       fi
       echo "Installing JRiver Media Center GPG key"
       echo "Installing JRiver Media Center GPG key"
       download "https://dist.jriver.com/mediacenter@jriver.com.gpg.key" "-" | 
       download "https://dist.jriver.com/mediacenter@jriver.com.gpg.key" "-" | 
@@ -666,12 +657,24 @@ install_mc_repo() {
       ;;
       ;;
   esac
   esac
 
 
+  if [[ -f $repo_file ]]; then
+    ask_ok "Replace existing $repo_file repository file" && execute sudo rm -f "$repo_file" 
+  fi
+
   echo "Adding MC repository file: $repo_file"
   echo "Adding MC repository file: $repo_file"
-  debug "repo_text: $repo_text"
+  debug "$repo_text"
   sudo tee "$repo_file" &>/dev/null <<< "$repo_text"
   sudo tee "$repo_file" &>/dev/null <<< "$repo_text"
 
 
+  # Add older repository for libwebkit2gtk-4.0-37, etc, on newer Debian/Ubuntu
+  if add_temp_repo; then
+    trap 'execute sudo rm -f "$TEMP_REPO_FILE"' EXIT
+  else
+    err "Failed to add temporary repository"
+    return 1
+  fi
   "${PKG_UPDATE[@]}" || { err "Package update failed!"; return 1; }
   "${PKG_UPDATE[@]}" || { err "Package update failed!"; return 1; }
 
 
+  echo "Installing $MC_PKG package"
   if ! install_package \
   if ! install_package \
     --no-install-check \
     --no-install-check \
     --allow-downgrades \
     --allow-downgrades \
@@ -681,6 +684,11 @@ install_mc_repo() {
     err "Package install failed!"
     err "Package install failed!"
     return 1
     return 1
   fi
   fi
+
+  # Unset the trap and remove temporary legacy repository
+  trap - EXIT
+  [[ -f $TEMP_REPO_FILE ]] && execute sudo rm -f "$TEMP_REPO_FILE"
+  return 0
 }
 }
 
 
 # @description Acquires the source DEB package from JRiver
 # @description Acquires the source DEB package from JRiver
@@ -815,7 +823,9 @@ build_rpm() {
       requires=("${requires[@]/python/python3}")
       requires=("${requires[@]/python/python3}")
       requires=("${requires[@]/libwebkit2gtk-4.0*/webkit2gtk4.0}")
       requires=("${requires[@]/libwebkit2gtk-4.0*/webkit2gtk4.0}")
       requires=("${requires[@]/libwebkit2gtk-4.1*/webkit2gtk4.1}")
       requires=("${requires[@]/libwebkit2gtk-4.1*/webkit2gtk4.1}")
-      recommends+=(mesa-va-drivers-freeworld)
+      recommends+=("mesa-va-drivers-freeworld|mesa-va-drivers")
+      recommends+=("mesa-vulkan-drivers-freeworld|mesa-vulkan-drivers")
+      recommends+=("mesa-vdpau-driver-freeworld|mesa-vdpau-driver")
       ;;
       ;;
     suse)
     suse)
       requires=("${requires[@]/python*/python313}")
       requires=("${requires[@]/python*/python313}")
@@ -912,7 +922,7 @@ build_rpm() {
 	EOF
 	EOF
 
 
   # Run rpmbuild
   # Run rpmbuild
-  echo "Building MC $MC_VERSION RPM, this may take some time"
+  echo "Building $MC_RPM, this may take some time"
   rpmbuild_cmd=(
   rpmbuild_cmd=(
     rpmbuild 
     rpmbuild 
       --define="_topdir $OUTPUT_DIR" 
       --define="_topdir $OUTPUT_DIR" 
@@ -925,15 +935,20 @@ build_rpm() {
     echo "Build successful. The RPM file is located at: $MC_RPM"
     echo "Build successful. The RPM file is located at: $MC_RPM"
   else
   else
     err "Build failed"
     err "Build failed"
-    # After failire, remove the source DEB and reaquire it on next run
-    [[ -f $MC_DEB ]] && echo "Removing source DEB" && execute sudo rm -f "$MC_DEB"
-    exit 1
+    # After failure, remove the source DEB and reaquire it on next run
+    if [[ -f $MC_DEB ]]; then
+      echo "Removing source DEB"
+      if ! execute rm -f "$MC_DEB"; then
+        execute sudo rm -f "$MC_DEB"
+      fi
+    fi
+    return 1
   fi
   fi
 }
 }
 
 
 # @description Installs Media Center via DEB package w/ optional compatability fixes
 # @description Installs Media Center via DEB package w/ optional compatability fixes
 install_mc_deb() {
 install_mc_deb() {
-  debug "${FUNCNAME[0]}()"  
+  debug "${FUNCNAME[0]}()" "$@"
 
 
   if ((COMPAT_SWITCH)); then
   if ((COMPAT_SWITCH)); then
     local extract_dir; extract_dir="$(mktemp -d)"
     local extract_dir; extract_dir="$(mktemp -d)"
@@ -959,44 +974,14 @@ install_mc_deb() {
     execute rm -rf "$extract_dir"
     execute rm -rf "$extract_dir"
   fi
   fi
 
 
-  # Helper function to add repository
-  add_temp_repo() {
-    local repo_name="$1"
-    local repo_uri="$2"
-    local repo_suite="$3"
-    local repo_key="$4"
-    declare -g TEMP_REPO_FILE="/etc/apt/sources.list.d/${repo_name}.sources"
-
-    echo "Creating temporary repository file $TEMP_REPO_FILE for $repo_suite"
-    sudo bash -c "cat <<-EOF > $TEMP_REPO_FILE
-			Types: deb
-			URIs: $repo_uri
-			Suites: $repo_suite
-			Components: main
-			Architectures: $MC_ARCH
-			Signed-By: $repo_key
-		EOF"
-    "${PKG_UPDATE[@]}" || { err "Package update failed!"; return 1; }
-  }
-
   # Add older repository for libwebkit2gtk-4.0-37, etc, on newer Debian/Ubuntu
   # Add older repository for libwebkit2gtk-4.0-37, etc, on newer Debian/Ubuntu
-  local -i remove_temp_repo=0
-  if [[ "$ID" == "ubuntu" ]]; then
-    local major_version="${VERSION_ID%%.*}"
-    local minor_version="${VERSION_ID##*.}"
-    if [[ $major_version -gt 24 || ($major_version == 24 && minor_version -ge 4) ]]; then
-      echo "Temporarily adding jammy repository for libwebkit2gtk-4.0-37, etc."
-      remove_temp_repo=1
-      add_temp_repo "jammy" "https://archive.ubuntu.com/ubuntu" "jammy" "/usr/share/keyrings/ubuntu-archive-keyring.gpg"
-    fi
-  elif [[ "$ID" == "debian" ]]; then
-    local major_version="${VERSION_ID%%.*}"
-    if [[ $major_version -ge 13 || -z $major_version ]]; then
-      echo "Temporarily adding bookworm repository for libwebkit2gtk-4.0-37, etc."
-      remove_temp_repo=1
-      add_temp_repo "bookworm" "https://deb.debian.org/debian" "bookworm" "/usr/share/keyrings/debian-archive-keyring.gpg"
-    fi
+  if add_temp_repo; then
+    trap 'execute sudo rm -f "$TEMP_REPO_FILE"' EXIT
+  else
+    err "Failed to add temporary repository"
+    return 1
   fi
   fi
+  "${PKG_UPDATE[@]}" || { err "Package update failed!"; return 1; }
 
 
   # Copy the DEB to a temporary file so _apt can read it
   # Copy the DEB to a temporary file so _apt can read it
   debug "Creating temporary deb file owned by _apt"
   debug "Creating temporary deb file owned by _apt"
@@ -1013,16 +998,17 @@ install_mc_deb() {
     --reinstall \
     --reinstall \
     "$temp_deb"; then
     "$temp_deb"; then
     err "Local MC DEB installation failed"
     err "Local MC DEB installation failed"
-    ((remove_temp_repo)) && { echo "Removing temporary repo"; execute sudo rm -f "$TEMP_REPO_FILE"; }
     if ask_ok "Remove source DEB and retry"; then
     if ask_ok "Remove source DEB and retry"; then
       execute sudo rm -f "$MC_DEB" "$temp_deb"
       execute sudo rm -f "$MC_DEB" "$temp_deb"
       exec "$SCRIPT_PATH" "$@" "--no-update"
       exec "$SCRIPT_PATH" "$@" "--no-update"
     fi
     fi
   fi
   fi
 
 
-  # Cleanup temporary repository and temporary DEB file
-  ((remove_temp_repo)) && { echo "Removing temporary repo"; execute sudo rm -f "$TEMP_REPO_FILE"; }
+  # Unset the trap and remove temporary legacy repository
+  trap - EXIT
+  [[ -f $TEMP_REPO_FILE ]] && execute sudo rm -f "$TEMP_REPO_FILE"
   execute sudo rm -f "$temp_deb"
   execute sudo rm -f "$temp_deb"
+  return 0
 }
 }
 
 
 # @description Installs MC via RPM package
 # @description Installs MC via RPM package
@@ -1111,7 +1097,6 @@ install_mc_arch() {
 # @description Copy the RPM to createrepo-webroot and run createrepo as the createrepo-user
 # @description Copy the RPM to createrepo-webroot and run createrepo as the createrepo-user
 run_createrepo() {
 run_createrepo() {
   debug "${FUNCNAME[0]}()"
   debug "${FUNCNAME[0]}()"
-  local -a cr_cmd
 
 
   install_package createrepo_c
   install_package createrepo_c
 
 
@@ -1136,15 +1121,10 @@ run_createrepo() {
   fi
   fi
 
 
   # Run createrepo
   # Run createrepo
-  cr_cmd=(sudo -u "$CREATEREPO_USER" createrepo -q "$CREATEREPO_WEBROOT")
-  [[ -d $CREATEREPO_WEBROOT/repodata ]] && cr_cmd+=(--update)
-  
-  if ! execute "${cr_cmd[@]}"; then
-    cr_cmd=(sudo createrepo -q "$CREATEREPO_WEBROOT")
-    [[ -d $CREATEREPO_WEBROOT/repodata ]] && cr_cmd+=(--update)
-    
-    if ! (execute "${cr_cmd[@]}" ||
-    execute sudo chown -R "$CREATEREPO_USER:$CREATEREPO_USER" "$CREATEREPO_WEBROOT"); then
+  local -a cr_opts=(-q "$CREATEREPO_WEBROOT")
+  # [[ -d "$CREATEREPO_WEBROOT/repodata" ]] && cr_opts+=(--update) # TODO temporarily disabled for legacy createrepo
+  if ! execute sudo -u "$CREATEREPO_USER" createrepo "${cr_opts[@]}"; then
+    if ! (execute sudo createrepo "${cr_opts[@]}" && execute sudo chown -R "$CREATEREPO_USER:$CREATEREPO_USER" "$CREATEREPO_WEBROOT"); then
       err "createrepo failed"
       err "createrepo failed"
       return 1
       return 1
     fi
     fi
@@ -1207,7 +1187,12 @@ restore_license() {
 
 
     for f in "$MJR_FILE" "$newest"; do
     for f in "$MJR_FILE" "$newest"; do
       if [[ -f $f ]]; then
       if [[ -f $f ]]; then
-        execute "mediacenter$MC_MVERSION" "/RestoreFromFile" "$f"
+        if execute "mediacenter$MC_MVERSION" "/RestoreFromFile" "$f"; then
+          echo "Restored license from $f"
+          return 0
+        else
+          err "Failed to restore license from $f"
+        fi
       fi
       fi
     done
     done
   fi
   fi
@@ -1534,7 +1519,7 @@ service_jriver-createrepo() {
 		[Service]
 		[Service]
 		$USER_STRING
 		$USER_STRING
 		ExecStart=$SCRIPT_DIR/installJRMC --outputdir=$OUTPUT_DIR --createrepo=$CREATEREPO_TARGET \
 		ExecStart=$SCRIPT_DIR/installJRMC --outputdir=$OUTPUT_DIR --createrepo=$CREATEREPO_TARGET \
-      --createrepo-webroot=$CREATEREPO_WEBROOT --createrepo-user=$CREATEREPO_USER --yes --no-update
+      --createrepo-webroot=$CREATEREPO_WEBROOT --createrepo-user=$CREATEREPO_USER --mcrepo=$MC_REPO --yes --no-update
 
 
 		[Install]
 		[Install]
 		WantedBy=multi-user.target
 		WantedBy=multi-user.target
@@ -1559,17 +1544,15 @@ service_jriver-createrepo() {
 # @description Detects if MC is installed on btrfs and disables CoW
 # @description Detects if MC is installed on btrfs and disables CoW
 disable_btrfs_cow() {
 disable_btrfs_cow() {
   debug "${FUNCNAME[0]}()"
   debug "${FUNCNAME[0]}()"
-  local dir 
   local mc_user_path="$HOME/.jriver"
   local mc_user_path="$HOME/.jriver"
+  [[ -d "$mc_user_path" ]] || execute mkdir -p "$mc_user_path"
 
 
-  for dir in "$MC_ROOT" "$mc_user_path"; do
-    [[ -d $mc_user_path ]] || execute mkdir -p "$mc_user_path"
-    if [[ $(stat -f -c %T "$dir") == "btrfs" ]] &&
-    ! lsattr -d "$dir" | cut -f1 -d" " | grep -q C &&
-    execute sudo chattr +C "$dir"; then
-      echo "Disabled btrfs CoW for $dir directory"
+  # Disable btrfs CoW
+  if [[ $(stat -f -c %T "$mc_user_path") == "btrfs" ]]; then
+    if execute chattr -R +C "$mc_user_path"; then
+      echo "Disabled btrfs CoW for $mc_user_path"
     fi
     fi
-  done
+  fi
 }
 }
 
 
 # @description Completely uninstalls MC, services, and firewall rules
 # @description Completely uninstalls MC, services, and firewall rules
@@ -1577,6 +1560,11 @@ uninstall() {
   debug "${FUNCNAME[0]}()"
   debug "${FUNCNAME[0]}()"
   local service type unit f
   local service type unit f
 
 
+  if ! ask_ok "Do you really want to uninstall JRiver Media Center?"; then
+    echo "Uninstall cancelled"
+    return 1
+  fi
+
   echo "Stopping and removing all Media Center services"
   echo "Stopping and removing all Media Center services"
   for service in $(compgen -A "function" "service"); do
   for service in $(compgen -A "function" "service"); do
     service="${service##service_}"
     service="${service##service_}"
@@ -1595,13 +1583,15 @@ uninstall() {
     done
     done
   done
   done
 
 
-  echo "Removing MC repositories"
-  execute sudo rm -rf \
-    "/etc/yum.repos.d/jriver.repo" \
-    /etc/apt/sources.list.d/{jriver,mediacenter}*.{list,sources} # also remove legacy repo files
+  # Remove the repository files
+  for file in "/etc/yum.repos.d/jriver.repo" /etc/apt/sources.list.d/{jriver,mediacenter}*.{list,sources}; do
+    if [[ -e $file ]]; then
+      echo "Removing repository file: $file"
+      execute sudo rm -f "$file"
+    fi
+  done
 
 
-  [[ $ID == "suse" ]] &&
-    execute sudo zypper --non-interactive removerepo jriver
+  [[ $ID == "suse" ]] && execute sudo zypper --non-interactive removerepo jriver
 
 
   echo "Removing firewall rules"
   echo "Removing firewall rules"
   for service in jriver-mediacenter jriver-xvnc jriver-x11vnc; do
   for service in jriver-mediacenter jriver-xvnc jriver-x11vnc; do
@@ -1616,18 +1606,21 @@ uninstall() {
     fi
     fi
   done
   done
 
 
-  echo "Uninstalling JRiver Media Center package"
+  echo "Uninstalling the JRiver Media Center package"
   if "${PKG_REMOVE[@]}" "${MC_PKG%%=*}"; then # remove version specifier
   if "${PKG_REMOVE[@]}" "${MC_PKG%%=*}"; then # remove version specifier
-    echo "JRiver Media Center has been completely uninstalled"
+    echo "Successfully uninstalled the ${MC_PKG%%=*} package"
   elif [[ $? -eq 100 ]]; then
   elif [[ $? -eq 100 ]]; then
     err "JRiver Media Center package '${MC_PKG%%=*}' is not present and was not uninstalled"
     err "JRiver Media Center package '${MC_PKG%%=*}' is not present and was not uninstalled"
   else
   else
     err "Could not remove Media Center package"
     err "Could not remove Media Center package"
   fi
   fi
 
 
-  echo "Uninstalling JRiver Media Center GPG key"
+  # Remove the JRiver GPG keyfile
   local keyfile="/usr/share/keyrings/jriver-com-archive-keyring.gpg"
   local keyfile="/usr/share/keyrings/jriver-com-archive-keyring.gpg"
-  [[ -f $keyfile ]] && execute sudo rm -f "$keyfile"
+  if [[ -f $keyfile ]]; then
+    echo "Removing the JRiver Media Center GPG key"
+    execute sudo rm -f "$keyfile"
+  fi
 
 
   if [[ -f $SCRIPT_DIR/.uninstall ]]; then
   if [[ -f $SCRIPT_DIR/.uninstall ]]; then
     echo "Removing files from .uninstall log"
     echo "Removing files from .uninstall log"
@@ -1637,9 +1630,28 @@ uninstall() {
     mv "$SCRIPT_DIR/.uninstall" "$SCRIPT_DIR/.uninstall.bk"
     mv "$SCRIPT_DIR/.uninstall" "$SCRIPT_DIR/.uninstall.bk"
   fi
   fi
 
 
-  echo "To remove installJRMC output: rm -rf $OUTPUT_DIR"
-  echo "To remove your MC library: rm -rf $HOME/.jriver"
-  return 0
+  if [[ -d $OUTPUT_DIR ]]; then
+    if ask_ok "Remove installJRMC output directory $OUTPUT_DIR?"; then
+      execute sudo rm -rf "$OUTPUT_DIR"
+    fi
+  fi
+
+  if [[ -d $MC_ROOT ]]; then
+    if ask_ok "Remove MC installation directory $MC_ROOT?"; then
+      execute sudo rm -rf "$MC_ROOT"
+    fi
+  fi
+
+  if [[ -d $HOME/.jriver ]]; then
+    if ask_ok "Backup and reset your MC library?"; then
+      execute mv "$HOME/.jriver" "$HOME/.jriver.bk"
+      echo "Your MC library has been backed up to $HOME/.jriver.bk and reset"
+      echo "To restore your MC library backup: mv $HOME/.jriver.bk $HOME/.jriver"
+      return
+    fi
+    echo "To backup and reset your MC library: mv $HOME/.jriver $HOME/.jriver.bk"
+    echo "To remove your MC library: rm -rf $HOME/.jriver"
+  fi
 }
 }
 
 
 # @description Checks for installJRMC update and re-executes, if necessary
 # @description Checks for installJRMC update and re-executes, if necessary
@@ -1728,9 +1740,10 @@ update() {
 
 
 # @description installJRMC main function
 # @description installJRMC main function
 main() {
 main() {
-  debug "${FUNCNAME[0]}()" "$@"
+  debug "${FUNCNAME[0]}()" "$@" # prints function name and arguments
 
 
   echo "Starting installJRMC $SCRIPT_VERSION"
   echo "Starting installJRMC $SCRIPT_VERSION"
+
   if ((DEBUG)); then
   if ((DEBUG)); then
     echo "Debugging on"
     echo "Debugging on"
   else
   else
@@ -1740,13 +1753,13 @@ main() {
   # Parse input, set default/host variables, and MC version
   # Parse input, set default/host variables, and MC version
   init "$@"
   init "$@"
 
 
-  if ((UNINSTALL_SWITCH)); then
-    if ask_ok "Do you really want to uninstall JRiver Media Center?"; then
-      uninstall
-    else
-      echo "Uninstall canceled"
-    fi
-    exit
+  ((UNINSTALL_SWITCH)) && uninstall
+
+  # Exit now if only --uninstall is passed
+  if ! (( BUILD_SWITCH || CREATEREPO_SWITCH || REPO_INSTALL_SWITCH || LOCAL_INSTALL_SWITCH ||
+  CONTAINER_INSTALL_SWITCH || SNAP_INSTALL_SWITCH || APPIMAGE_INSTALL_SWITCH )) &&
+  [[ ${#SERVICES[@]} -eq 0 && ${#CONTAINERS[@]} -eq 0 ]]; then
+    exit 0
   fi
   fi
 
 
   install_external_repos
   install_external_repos
@@ -1755,6 +1768,7 @@ main() {
     echo "Installing JRiver Media Center from remote repository"
     echo "Installing JRiver Media Center from remote repository"
     if install_mc_repo; then
     if install_mc_repo; then
       echo "JRiver Media Center installed successfully from remote repository"
       echo "JRiver Media Center installed successfully from remote repository"
+      install_mesa_freeworld
       link_ssl_certs
       link_ssl_certs
       restore_license
       restore_license
       open_firewall "jriver-mediacenter" "52100-52200/tcp" "1900/udp"
       open_firewall "jriver-mediacenter" "52100-52200/tcp" "1900/udp"
@@ -1776,12 +1790,14 @@ main() {
   fi
   fi
 
 
   if ((LOCAL_INSTALL_SWITCH)); then
   if ((LOCAL_INSTALL_SWITCH)); then
+    echo "Installing JRiver Media Center from local package"
     if PKG_INSTALL_LOCAL "$@"; then
     if PKG_INSTALL_LOCAL "$@"; then
       echo "JRiver Media Center installed successfully from local package"
       echo "JRiver Media Center installed successfully from local package"
     else
     else
       err "JRiver Media Center local package installation failed"
       err "JRiver Media Center local package installation failed"
       return 1
       return 1
     fi
     fi
+    install_mesa_freeworld
     link_ssl_certs
     link_ssl_certs
     restore_license
     restore_license
     open_firewall "jriver-mediacenter" "52100-52200/tcp" "1900/udp"
     open_firewall "jriver-mediacenter" "52100-52200/tcp" "1900/udp"
@@ -1877,6 +1893,51 @@ create_mc_apt_container() {
     sudo buildah run "$CNT" -- sh -c "$cmd" || { err "$cmd failed"; return 1; }
     sudo buildah run "$CNT" -- sh -c "$cmd" || { err "$cmd failed"; return 1; }
   done
   done
 }
 }
+add_temp_repo() {
+  debug "${FUNCNAME[0]}()"
+  local repo_name repo_uri repo_suite repo_key
+
+  if [[ "$ID" == "ubuntu" ]]; then
+    local major_version="${VERSION_ID%%.*}"
+    local minor_version="${VERSION_ID##*.}"
+    minor_version="${minor_version#0}"  # strip leading zero
+    if [[ $major_version -gt 24 || ( $major_version -eq 24 && minor_version -ge 4 ) ]]; then
+      echo "Temporarily adding jammy repository for libwebkit2gtk-4.0-37, etc."
+      repo_name="ubuntu-jammy-temp"
+      repo_uri="https://archive.ubuntu.com/ubuntu"
+      repo_suite="jammy"
+      repo_key="/usr/share/keyrings/ubuntu-archive-keyring.gpg"
+    else
+      return 0
+    fi
+  elif [[ "$ID" == "debian" ]]; then
+    local major_version="${VERSION_ID%%.*}"
+    if [[ $major_version -ge 13 ]]; then
+      echo "Temporarily adding bookworm repository for libwebkit2gtk-4.0-37, etc."
+      repo_name="debian-bookworm-temp"
+      repo_uri="https://deb.debian.org/debian"
+      repo_suite="bookworm"
+      repo_key="/usr/share/keyrings/debian-archive-keyring.gpg"
+    else
+      return 0
+    fi
+  else
+    # For other distributions, do nothing.
+    return 0
+  fi
+
+  declare -g TEMP_REPO_FILE="/etc/apt/sources.list.d/${repo_name}.sources"
+
+  echo "Creating temporary repository file $TEMP_REPO_FILE for $repo_suite"
+  sudo bash -c "cat <<-EOF > $TEMP_REPO_FILE
+		Types: deb
+		URIs: $repo_uri
+		Suites: $repo_suite
+		Components: main
+		Architectures: $MC_ARCH
+		Signed-By: $repo_key
+	EOF"
+}
 
 
 # Roughly turn debugging on for pre-init
 # Roughly turn debugging on for pre-init
 # Reset and reparse in parse_input() with getopt
 # Reset and reparse in parse_input() with getopt