installJRMC 47 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486
  1. #!/usr/bin/env bash
  2. shopt -s extglob
  3. #######################################
  4. # This script will download, build, and install JRiver Media Center with optional systemd services
  5. # on Fedora, CentOS, Debian, and Ubuntu
  6. #
  7. # Run installJRMC --help to see available options
  8. #
  9. # To-dos:
  10. # 1. Raspberry Pi OS support
  11. # 2. Interactive installation (ncurses?)
  12. #
  13. # installJRMC can be run directly or sourced as a function (by sourcing this file)
  14. # Arguments:
  15. # see _printHelpAndExit() and/or check getopt's in _parseInput() for available options
  16. # Returns:
  17. # 0 if critical functions complete successfully
  18. #######################################
  19. installJRMC() {
  20. _scriptversion="0.9.1"
  21. _boardurl="https://yabb.jriver.com/interact/index.php/board,67.0.html"
  22. _outputdir="$_basedir/output"
  23. _createrepo_webroot="/srv/jriver"
  24. _exec_user="$(whoami)"
  25. _available_services=("jriver-createrepo" "jriver-x11vnc" "jriver-mediaserver" "jriver-mediacenter" "jriver-xvnc-mediacenter")
  26. #_available_containers=("mediacenter-xvnc" "createrepo")
  27. _printHelpAndExit() {
  28. debug "Running: ${FUNCNAME[0]}"
  29. cat <<-'EOF'
  30. USAGE:
  31. installJRMC [[OPTION] [VALUE]]...
  32. OPTIONS
  33. --install-repo
  34. Install JRiver Media Center from repository using package manager (Default)
  35. DEB-based OSes: Official package repository
  36. RPM-based OSes: BryanC unofficial repository
  37. --install-rpm
  38. (RPM-based OSes only) Build RPM from source DEB and install it
  39. --rpmbuild
  40. Build RPM from source DEB
  41. --outputdir PATH
  42. Generate rpmbuild output in this directory (Default: $PWD/outputdir)
  43. --mcversion VERSION
  44. Build or install a specific version (Default: install the latest version)
  45. --restorefile RESTOREFILE
  46. Restore file location for registration (Default: skip registration)
  47. --betapass PASSWORD
  48. Enter beta team password for access to beta builds
  49. --service-user USER
  50. Install systemd services and containers for USER
  51. --service, -s SERVICE
  52. See SERVICES section below for a list of possible services to install
  53. --container, -c CONTAINER (TODO: Under construction)
  54. See CONTAINERS section below for a list of possible services to install
  55. --createrepo
  56. Build rpm, copy to webroot, and run createrepo
  57. --createrepo-webroot PATH
  58. The webroot directory to install the repo (Default: /srv/jriver/)
  59. --createrepo-user USER
  60. The web server user (Default: current user)
  61. --version, -v
  62. Print this script version and exit
  63. --debug, -d
  64. Print debug output
  65. --help, -h
  66. Print help dialog and exit
  67. --uninstall, -u
  68. Uninstall JRiver MC, cleanup service files, and remove firewall rules (does not remove library files)
  69. SERVICES
  70. jriver-mediaserver
  71. Enable and start a mediaserver systemd service (requires an existing X server)
  72. jriver-mediacenter
  73. Enable and start a mediacenter systemd service (requires an existing X server)
  74. jriver-x11vnc
  75. Enable and start x11vnc for the local desktop (requires an existing X server)
  76. Usually combined with jriver-mediaserver or jriver-mediacenter services
  77. --vncpass and --display are also valid options (see below)
  78. jriver-xvnc-mediacenter
  79. Enable and start a new Xvnc session running JRiver Media Center
  80. --vncpass PASSWORD
  81. Set vnc password for x11vnc/Xvnc access. If no password is set, the script
  82. will either use existing password stored in ~/.vnc/jrmc_passwd or use no password
  83. --display DISPLAY
  84. Display to start x11vnc/Xvnc (Default: The current display (x11vnc) or the
  85. current display incremented by 1 (Xvnc))
  86. jriver-createrepo
  87. Install hourly service to build latest MC RPM and run createrepo
  88. CONTAINERS (TODO: Under construction)
  89. mediacenter-xvnc
  90. createrepo
  91. EOF
  92. # Exit using passed exit code
  93. [[ -z $1 ]] && exit 0 || exit "$1"
  94. }
  95. _parseInput() {
  96. debug "Running: ${FUNCNAME[0]}"
  97. # set default behavior
  98. if [[ $# -eq 0 ]] || [[ $# -eq 1 && "$1" == "--debug" ]]; then
  99. _repoinstall="true"
  100. fi
  101. if _input=$(getopt -o +vdhus:c: -l install-repo,install-rpm,rpmbuild,outputdir:,mcversion:,restorefile:,betapass:,service-user:,service:,version,debug,help,uninstall,createrepo,createrepo-webroot:,createrepo-user:,vncpass:,display:,container: -- "$@"); then
  102. eval set -- "$_input"
  103. while true; do
  104. case "$1" in
  105. --install-repo)
  106. _repoinstall="true"
  107. ;;
  108. --install-rpm)
  109. _rpmbuild="true"
  110. _rpminstall="true"
  111. ;;
  112. --rpmbuild)
  113. _rpmbuild="true"
  114. ;;
  115. --outputdir)
  116. shift && _outputdir="$1"
  117. ;;
  118. --mcversion)
  119. shift && _mcversion="$1"
  120. ;;
  121. --restorefile)
  122. shift && _restorefile="$1"
  123. ;;
  124. --betapass)
  125. shift && _betapass="$1"
  126. ;;
  127. --service-user)
  128. shift && _service_user="$1"
  129. ;;
  130. --service|-s)
  131. shift && _services+=("$1")
  132. ;;
  133. --container|-c)
  134. shift && _containers+=("$1")
  135. ;;
  136. --version|-v)
  137. echo "Version: $_scriptversion"
  138. exit 0
  139. ;;
  140. --debug|-d)
  141. echo "Debugging on"
  142. _debug="true"
  143. ;;
  144. --help|-h)
  145. _printHelpAndExit 0
  146. ;;
  147. --uninstall|-u)
  148. _uninstall="true"
  149. ;;
  150. --createrepo)
  151. _createrepo="true"
  152. _rpmbuild="true"
  153. ;;
  154. --createrepo-webroot)
  155. shift && _createrepo_webroot="$1"
  156. ;;
  157. --createrepo-user)
  158. shift && _createrepo_user="$1"
  159. ;;
  160. --vncpass)
  161. shift && _vncpass="$1"
  162. ;;
  163. --display)
  164. shift && _display="$1"
  165. ;;
  166. --)
  167. shift
  168. break
  169. ;;
  170. esac
  171. shift
  172. done
  173. else
  174. err "Incorrect options provided"
  175. _printHelpAndExit 1
  176. fi
  177. }
  178. err() { echo "Error: $*" >&2; }
  179. debug() { [[ -n $_debug ]] && echo "Debug: $*"; }
  180. #######################################
  181. # Prepend this to any command that you wish to execute with sudo
  182. # Requires:
  183. # _exec_user
  184. #######################################
  185. _ifSudo() {
  186. if [[ "$_exec_user" != "root" ]]; then
  187. sudo "$@"
  188. else
  189. "$@"
  190. fi
  191. }
  192. #######################################
  193. # Sources /etc/os-release so we know which OS we're running on
  194. # Used in: _buildCommands()
  195. #######################################
  196. _getOS() {
  197. debug "Running: ${FUNCNAME[0]}"
  198. if [[ -e "/etc/os-release" ]]; then
  199. source "/etc/os-release"
  200. else
  201. err "No /etc/os-release found"
  202. err "Your OS is unsupported"
  203. _printHelpAndExit 1
  204. fi
  205. [[ -n $_debug ]] && echo "Platform: $ID $VERSION_ID"
  206. }
  207. #######################################
  208. # Creates some OS-specific functions to query, install, and remove packages and edit
  209. # firewalls, run bash, remove and copy files, etc.
  210. # Requires:
  211. # ID
  212. # _createrepo_user
  213. # _createrepo_webroot
  214. # Globals:
  215. # _bash_cmd
  216. # _rm_cmd
  217. # _cp_cmd
  218. # _mkdir_cmd
  219. # _ln_cmd
  220. # _createrepo_cmd
  221. # _pkg_install
  222. # _pkg_reinstall
  223. # _pkg_install_nogpg
  224. # _pkg_remove
  225. # _pkg_update
  226. # _pkg_query
  227. # _firewall_cmd
  228. # _systemctl_reload
  229. # _systemctl_enable
  230. # _systemctl_disable
  231. #######################################
  232. _buildCommands() {
  233. # Detect OS
  234. _getOS
  235. debug "Running: ${FUNCNAME[0]}"
  236. # Agnostic commands
  237. _bash_cmd(){ _ifSudo bash -c "$@"; }
  238. _rm_cmd(){ _ifSudo rm -rf "$@"; }
  239. _cp_cmd(){ _ifSudo cp -n "$@"; }
  240. _mkdir_cmd(){ _ifSudo mkdir -p "$@"; }
  241. _ln_cmd(){ _ifSudo ln -s "$@"; }
  242. _systemctl_reload(){ _ifSudo systemctl daemon-reload; }
  243. _systemctl_start(){
  244. echo "Starting $*"
  245. if ! _ifSudo systemctl start "$@"; then
  246. err "Could not start $*"
  247. err "Check service status using \"sudo systemctl status $*\""
  248. return 1
  249. fi
  250. }
  251. _systemctl_enable(){ _ifSudo systemctl enable "$@"; }
  252. _systemctl_disable(){ _ifSudo systemctl disable --now "$@"; }
  253. # OS-specific commands
  254. if [[ "$ID" =~ ^(fedora|centos)$ ]]; then
  255. _pkg_install(){ _ifSudo dnf install -y "$@"; }
  256. _pkg_reinstall(){ _ifSudo dnf reinstall -y "$@"; }
  257. _pkg_install_nogpg(){ _ifSudo dnf install --nogpgcheck -y "$@"; }
  258. _pkg_remove(){ _ifSudo dnf remove -y "$@"; }
  259. _pkg_update(){ _ifSudo dnf makecache; }
  260. _pkg_query(){ _ifSudo rpm -q "$@"; }
  261. _firewall_cmd(){ _ifSudo firewall-cmd "$@"; }
  262. elif [[ "$ID" =~ ^(ubuntu|debian)$ ]]; then
  263. _pkg_install(){ _ifSudo apt-get install -y -q0 "$@"; }
  264. _pkg_reinstall(){ _ifSudo apt-get reinstall -y -q0 "$@"; }
  265. _pkg_install_nogpg(){ _ifSudo apt-get install -y -q0 "$@"; }
  266. _pkg_remove(){ _ifSudo apt-get remove -y -q0 "$@"; }
  267. _pkg_update(){ _ifSudo apt-get update -y -q0; }
  268. _pkg_query(){ _ifSudo dpkg -s "$@"; }
  269. _firewall_cmd(){ _ifSudo ufw "$@"; }
  270. fi
  271. # Some additional commands specifically for createrepo (primarily to handle user rights)
  272. # Could also go in runCreaterepo() but let's leave it here for now
  273. if [[ $_createrepo_user != "root" ]]; then
  274. if [[ -d "$_createrepo_webroot/repodata" ]]; then
  275. _createrepo_cmd(){ sudo -u "$_createrepo_user" createrepo -q --update "$@"; }
  276. else
  277. _createrepo_cmd(){ sudo -u "$_createrepo_user" createrepo -q "$@"; }
  278. fi
  279. _cr_mkdir_cmd(){ sudo -u "$_createrepo_user" mkdir -p "$@"; }
  280. _cr_cp_cmd(){ sudo -u "$_createrepo_user" cp -n "$@"; }
  281. else
  282. if [[ -d "$_createrepo_webroot/repodata" ]]; then
  283. _createrepo_cmd(){ createrepo -q --update "$@"; }
  284. else
  285. _createrepo_cmd(){ createrepo -q "$@"; }
  286. fi
  287. fi
  288. }
  289. #######################################
  290. # Sets default user variables
  291. # Requires:
  292. # _exec_user
  293. # Globals
  294. # _service_user
  295. # _createrepo_user
  296. #######################################
  297. _setUser() {
  298. [[ -z $_service_user ]] && _service_user="$_exec_user"
  299. [[ -z $_createrepo_user ]] && _createrepo_user="$_exec_user"
  300. }
  301. #######################################
  302. # Installs a package using the system package manager
  303. # Arguments:
  304. # One or more package names
  305. # Options:
  306. # --noquery, -n: Do not query the package state (useful if installing a local RPM)
  307. # Returns:
  308. # Will exit 1 if failed
  309. #######################################
  310. _installPackage() {
  311. debug "Running: ${FUNCNAME[0]}" "$@"
  312. if _input=$(getopt -o +n -l noquery -- "$@"); then
  313. eval set -- "$_input"
  314. while true; do
  315. case "$1" in
  316. --noquery|-n)
  317. local _noquery="true"
  318. ;;
  319. --)
  320. shift
  321. break
  322. ;;
  323. esac
  324. shift
  325. done
  326. else
  327. err "Incorrect options provided"
  328. _printHelpAndExit 1
  329. fi
  330. # We will add packages to this array if their command is not available
  331. local -a _pkg_array
  332. local -a _url_pkg_array
  333. # parse arguments (packages)
  334. for _pkg in "$@"; do
  335. # Clean up package name and handle OS-specific tweaks
  336. _packageQuirks "$_pkg"
  337. # Insert the package name to test if already installed
  338. if [[ "$_pkg" != "" ]]; then
  339. if [[ -n $_noquery ]] || ! _pkg_query "$_pkg" > /dev/null 2>&1; then
  340. if [[ -n $_url_pkg ]]; then
  341. _url_pkg_array+=("$_url_pkg")
  342. else
  343. _pkg_array+=("$_pkg")
  344. fi
  345. fi
  346. fi
  347. done
  348. # Install from package name (with gpg check)
  349. if [[ ${#_pkg_array[@]} -ge 1 ]]; then
  350. echo "Installing:" "${_pkg_array[@]}"
  351. if [[ -n $_debug ]]; then
  352. if ! _pkg_install "${_pkg_array[@]}"; then
  353. err "Failed to install package. Attempting to continue..."
  354. return 1
  355. fi
  356. elif ! _pkg_install "${_pkg_array[@]}" > /dev/null 2>&1; then
  357. err "Failed to install package. Attempting to continue..."
  358. return 1
  359. fi
  360. fi
  361. # Install from package url (without gpg check)
  362. if [[ ${#_url_pkg_array[@]} -ge 1 ]]; then
  363. echo "Installing:" "${_url_pkg_array[@]}"
  364. if [[ -n $_debug ]]; then
  365. if ! _pkg_install_nogpg "${_url_pkg_array[@]}"; then
  366. err "Failed to install package. Attempting to continue..."
  367. return 1
  368. fi
  369. elif ! _pkg_install_nogpg "${_url_pkg_array[@]}" > /dev/null 2>&1; then
  370. err "Failed to install package. Attempting to continue..."
  371. return 1
  372. fi
  373. fi
  374. }
  375. #######################################
  376. # Handles OS-specific package name tweaks and source urls
  377. # Arguments:
  378. # A package name
  379. # Globals:
  380. # _pkg
  381. # _url_pkg
  382. #######################################
  383. _packageQuirks() {
  384. debug "Running: ${FUNCNAME[0]}" "$@"
  385. unset _url_pkg
  386. if [[ "$1" == "xorg-x11-utils" && "$ID" =~ ^(ubuntu|debian)$ ]]; then
  387. _pkg="x11-utils"
  388. elif [[ "$1" == "rpm-build" && "$ID" =~ ^(ubuntu|debian)$ ]]; then
  389. _pkg="rpm"
  390. elif [[ "$1" == "createrepo_c" && "$ID" =~ ^(ubuntu|debian)$ ]]; then
  391. _pkg="createrepo"
  392. elif [[ "$1" == "rpmfusion-free-release" ]]; then
  393. if [[ "$ID" == "fedora" ]]; then
  394. # As of MC26 and Fedora 32 I don't believe that the rpmfusion repo is necessary
  395. #_url_pkg="https://download1.rpmfusion.org/free/$ID/rpmfusion-free-release-$VERSION_ID.noarch.rpm"
  396. #_pkg="$1"
  397. _pkg=""
  398. elif [[ "$ID" == "centos" ]]; then
  399. _url_pkg="https://download1.rpmfusion.org/free/el/rpmfusion-free-release-$VERSION_ID.noarch.rpm"
  400. _pkg="$1"
  401. else
  402. _pkg=""
  403. fi
  404. elif [[ "$1" == "epel-release" && "$ID" != "centos" ]]; then
  405. _pkg=""
  406. elif [[ "$1" == "tigervnc-server" && "$ID" =~ ^(ubuntu|debian)$ ]]; then
  407. _pkg="tigervnc-standalone-server"
  408. else
  409. _pkg="$1"
  410. fi
  411. }
  412. #######################################
  413. # Get our MC working version from input argument or scraping Interact
  414. # Requires:
  415. # _boardurl
  416. # _installPackage
  417. # Globals:
  418. # _mcversion (i.e. "26.0.12")
  419. # _mversion (i.e. "26")
  420. #######################################
  421. _setVersion() {
  422. debug "Running: ${FUNCNAME[0]}"
  423. if [[ -z "$_mcversion" ]]; then
  424. _installPackage wget
  425. # Get latest version from Interact
  426. echo "Scraping latest MC version number from Interact..."
  427. if ! _mcversion=$(wget -qO- "$_boardurl" | grep -o "[0-9][0-9]\.[0-9]\.[0-9]\+" | head -n 1); then
  428. err "MC version could not be scraped. Please specify a version manually using --mcversion or check your --boardurl"
  429. _printHelpAndExit 1
  430. fi
  431. fi
  432. echo "Using version: $_mcversion"
  433. # Extract major version number
  434. _mversion="${_mcversion%%.*}"
  435. # Saving this substituion in case it's needed in the future
  436. #_variation="${_mcversion##*.}"
  437. }
  438. #######################################
  439. # Check if an argument exists in an array
  440. # Arguments:
  441. # The first argument is the string to match to the following arguments
  442. # Example:
  443. # _inArray "zebra" "${animals_arr[@]}"
  444. # Returns:
  445. # 0 if a match is found, 1 if not
  446. #######################################
  447. _inArray() {
  448. local _match="$1"
  449. shift
  450. local _item
  451. for _item in "$@"; do
  452. [[ "$_item" == "$_match" ]] && return 0
  453. done
  454. return 1
  455. }
  456. #######################################
  457. # Clean up nonsensical user input
  458. # Notes:
  459. # I try to keep this function as short as possible and provide better input options and
  460. # sensible defaults than workarounds
  461. # Test:
  462. # _installJRMC should run sucessfully even without running _sanityChecks()
  463. #######################################
  464. _sanityChecks() {
  465. debug "Running: ${FUNCNAME[0]}"
  466. # Check for bad service name
  467. _checkServices() {
  468. debug "Running: ${FUNCNAME[0]}"
  469. for _service in "${_services[@]}"; do
  470. if ! _inArray "$_service" "${_available_services[@]}"; then
  471. echo "Incorrect service type provided"
  472. _printHelpAndExit 1
  473. fi
  474. done
  475. }
  476. _checkMCInstalled() {
  477. debug "Running: ${FUNCNAME[0]}"
  478. for _service in "${_services[@]}"; do
  479. if [[ "$_service" =~ ^(jriver-mediacenter|jriver-mediaserver|jriver-xvnc-mediacenter|jriver-x11vnc)$ ]] \
  480. && [[ -z $_repoinstall && -z $_rpminstall ]] \
  481. && [[ ! -x $(command -v "mediacenter$_mversion") ]]; then
  482. err "You are attempting to install a service that depends on JRiver Media Center"
  483. err "without installing JRiver Media Center"
  484. err "Automatically enabling --repo-install"
  485. _repoinstall="true"
  486. fi
  487. done
  488. }
  489. _checkUser() {
  490. debug "Running: ${FUNCNAME[0]}"
  491. if [[ "$_exec_user" == "root" && -z "$_service_user" && "${_services[*]}" ]]; then
  492. err "Attempting to install services as the root user"
  493. err "This is not recommended and we are exiting now to prevent permission hell"
  494. err "You can override this safety check by manually specifying --user root"
  495. return 1
  496. fi
  497. }
  498. # Enable/disable sanity checks
  499. if _checkServices && _checkMCInstalled && _checkUser; then
  500. debug "Sanity checks passed!"
  501. return 0
  502. else
  503. err "Sanity checks failed!"
  504. exit 1
  505. fi
  506. }
  507. #######################################
  508. # Installs JRiver Media Center from a repository
  509. # Returns:
  510. # 0 if JRiver Media Center installed sucessfully
  511. #######################################
  512. _installMCFromRepo() {
  513. debug "Running: ${FUNCNAME[0]}"
  514. echo "Installing JRiver Media Center from repo..."
  515. local _mcpkg
  516. # Add repository files
  517. _addRepo() {
  518. # Add repositories to OS-specific package managers
  519. if [[ "$ID" =~ ^(fedora|centos)$ ]]; then
  520. _bash_cmd 'cat <<-EOF > /etc/yum.repos.d/jriver.repo
  521. [jriver]
  522. name=JRiver Media Center repo by BryanC
  523. baseurl=https://repos.bryanroessler.com/jriver
  524. gpgcheck=0
  525. EOF'
  526. elif [[ "$ID" =~ ^(ubuntu|debian)$ ]]; then
  527. wget -q "http://dist.jriver.com/mediacenter@jriver.com.gpg.key" -O- | _ifSudo apt-key add - > /dev/null 2>&1
  528. _bash_cmd 'cat <<-EOF > /etc/apt/sources.list.d/jriver.list
  529. deb [arch=amd64,i386,armhf] http://dist.jriver.com/latest/mediacenter/ jessie main
  530. EOF'
  531. fi
  532. }
  533. _addRepo
  534. # Update package list
  535. [[ -n $_debug ]] && echo "Updating package list"
  536. if ! _pkg_update > /dev/null 2>&1; then
  537. err "Package update failed!"
  538. exit 1
  539. fi
  540. # If user specifies a version, use that
  541. if [[ -n $_mcversion ]]; then
  542. _setVersion
  543. local _specific_version="true"
  544. fi
  545. local _mcpkg
  546. # Fedora/CentOS use a universal package name -- easy
  547. if [[ "$ID" =~ ^(fedora|centos)$ ]]; then
  548. _mcpkg="MediaCenter"
  549. fi
  550. # Ubuntu/Debian incorporate the mversion into the package name -- more fun!
  551. if [[ "$ID" =~ ^(ubuntu|debian)$ ]]; then
  552. if [[ -z $_mversion ]]; then
  553. # Try parsing the latest mversion from the repo
  554. if _mcpkg=$(apt-get install mediacenter?? -s -q0 | grep "selecting" | tail -1| awk '{print $3}'); then
  555. _mcpkg="${_mcpkg%\'}"
  556. _mcpkg="${_mcpkg#\'}"
  557. # Scrape Interact
  558. else
  559. _setVersion
  560. _mcpkg="mediacenter$_mversion"
  561. fi
  562. else
  563. _mcpkg="mediacenter$_mversion"
  564. fi
  565. # Sanity check
  566. if [[ ! "$_mcpkg" =~ ^mediacenter[0-9][0-9]$ ]]; then
  567. err "Could not parse MC package name"
  568. exit 1
  569. fi
  570. fi
  571. if [[ -n $_specific_version ]]; then
  572. if [[ "$ID" =~ ^(fedora|centos)$ ]]; then
  573. if [[ -n $_debug ]]; then
  574. _installPackage "$_mcpkg-$_mcversion"
  575. else
  576. _installPackage "$_mcpkg-$_mcversion" > /dev/null 2>&1
  577. fi
  578. elif [[ "$ID" =~ ^(ubuntu|debian)$ ]]; then
  579. if [[ -n $_debug ]]; then
  580. _installPackage "$_mcpkg=$_mcversion"
  581. else
  582. _installPackage "$_mcpkg=$_mcversion" > /dev/null 2>&1
  583. fi
  584. fi
  585. else
  586. if [[ -n $_debug ]]; then
  587. _installPackage "$_mcpkg"
  588. else
  589. _installPackage "$_mcpkg" > /dev/null 2>&1
  590. fi
  591. fi
  592. # shellcheck disable=SC2181
  593. # Rationale: More compact to check this once
  594. if [[ $? -eq 0 ]]; then
  595. echo "JRiver Media Center installed successfully"
  596. return 0
  597. else
  598. err "JRiver Media Center installation failed"
  599. exit 1
  600. fi
  601. }
  602. #######################################
  603. # Acquire the source DEB package from JRiver's servers
  604. # Returns:
  605. # 0 if DEB file downloaded successfully, 1 if failed
  606. #######################################
  607. _acquireDeb() {
  608. debug "Running: ${FUNCNAME[0]}"
  609. local _debfilename="$_outputdir/SOURCES/MediaCenter-${_mcversion}-amd64.deb"
  610. # If necessary, create SOURCES dir
  611. [[ ! -d "$_outputdir/SOURCES" ]] && mkdir -p "$_outputdir/SOURCES"
  612. # If deb file already exists, skip download
  613. if [[ -f "$_debfilename" ]]; then
  614. echo "Using local DEB file: $_debfilename"
  615. # Else check beta repo
  616. elif [[ -n $_betapass ]]; then
  617. if wget -q -O "$_debfilename" \
  618. "https://files.jriver.com/mediacenter/channels/v${_mversion}/beta/${_betapass}/MediaCenter-${_mcversion}-amd64.deb"; then
  619. true
  620. fi
  621. # Else check test repo
  622. elif wget -q -O "$_debfilename" \
  623. "https://files.jriver.com/mediacenter/test/MediaCenter-${_mcversion}-amd64.deb"; then
  624. true
  625. # Else check latest repo
  626. elif wget -q -O "$_debfilename" \
  627. "https://files.jriver.com/mediacenter/channels/v${_mversion}/latest/MediaCenter-${_mcversion}-amd64.deb"; then
  628. true
  629. else
  630. err "Cannot find DEB file. Exiting..."
  631. exit 1
  632. fi
  633. if [[ ! -f "$_debfilename" ]]; then
  634. err "Downloaded DEB file missing or corrupted, exiting..."
  635. exit 1
  636. fi
  637. }
  638. #######################################
  639. # Creates a SPEC file and builds the RPM from the source DEB using rpmbuild
  640. # Requires:
  641. # _outputdir
  642. # ID
  643. # _mcversion
  644. # _mversion
  645. # _installPackage
  646. # Globals:
  647. # _mcrpm
  648. # Returns:
  649. # 0 if rpmbuild is successful, 1 if not
  650. #######################################
  651. _buildRPM() {
  652. debug "Running: ${FUNCNAME[0]}"
  653. # install build dependencies
  654. _installPackage wget dpkg rpm-build
  655. # If necessary, make build directories
  656. [[ ! -d "$_outputdir/SPECS" ]] && mkdir -p "$_outputdir/SPECS"
  657. # rpmbuild uses rpm to check for build dependencies
  658. # this will fail on non-rpm distros
  659. if [[ "$ID" =~ ^(fedora|centos)$ ]]; then
  660. local _build_requires=$'BuildRequires: rpm >= 4.11.0\nBuildRequires: dpkg'
  661. else
  662. local _build_requires=''
  663. fi
  664. if [[ "$ID" == "fedora" && -n $_rpminstall ]]; then
  665. # TODO: find out why this is required since it's not easily available on CentOS
  666. local _requires='Requires: pangox-compat >= 0.0.2'
  667. fi
  668. # Create spec file
  669. bash -c "cat <<EOF > $_outputdir/SPECS/mediacenter.spec
  670. Name: MediaCenter
  671. Version: $_mcversion
  672. Release: 1
  673. Summary: JRiver Media Center
  674. Group: Applications/Media
  675. Source0: http://files.jriver.com/mediacenter/channels/v$_mversion/latest/MediaCenter-$_mcversion-amd64.deb
  676. $_build_requires
  677. BuildArch: x86_64
  678. %define _rpmfilename %%{ARCH}/%%{NAME}-%%{version}.%%{ARCH}.rpm
  679. AutoReq: 0
  680. Requires: glibc >= 2.19
  681. Requires: alsa-lib >= 1.0.28
  682. Requires: libuuid >= 2.25
  683. Requires: libX11 >= 1.6
  684. Requires: libX11-common >= 1.6
  685. Requires: libXext >= 1.3
  686. Requires: libxcb >= 1.1
  687. Requires: libXdmcp >= 1.1
  688. Requires: libstdc++ >= 4.9
  689. Requires: gtk3 >= 3.14
  690. Requires: mesa-libGL
  691. Requires: libglvnd-glx
  692. Requires: pango >= 1.36
  693. $_requires
  694. Requires: libXScrnSaver
  695. Requires: xdg-utils
  696. Requires: libgomp >= 4.9
  697. Requires: nss >= 3.26
  698. Requires: nspr >= 4.12
  699. Requires: ca-certificates
  700. Requires: python3
  701. Recommends: vorbis-tools >= 1.4.0
  702. Provides: mediacenter$_mversion
  703. License: Copyright 1998-2020, JRiver, Inc. All rights reserved. Protected by U.S. patents #7076468 and #7062468
  704. URL: http://www.jriver.com/
  705. %define __provides_exclude_from ^%{_libdir}/jriver/.*/.*\\.so.*$
  706. %description
  707. Media Center is more than a world class player.
  708. %global __os_install_post %{nil}
  709. %prep
  710. %build
  711. %install
  712. dpkg -x %{S:0} %{buildroot}
  713. %post -p /sbin/ldconfig
  714. %postun -p /sbin/ldconfig
  715. %files
  716. %{_bindir}/mediacenter$_mversion
  717. %{_libdir}/jriver
  718. %{_datadir}
  719. %exclude %{_datadir}/applications/media_center_packageinstaller_$_mversion.desktop
  720. /etc/security/limits.d/*
  721. EOF"
  722. declare -g _mcrpm="$_outputdir/RPMS/x86_64/MediaCenter-$_mcversion.x86_64.rpm"
  723. # skip rebuilding the rpm if it already exists
  724. if [[ -f "$_mcrpm" ]]; then
  725. echo "$_mcrpm already exists. Skipping build step..."
  726. return 0 # this is fine
  727. else
  728. # Run rpmbuild
  729. echo "Building version $_mcversion, please wait..."
  730. if [[ -n $_debug ]]; then
  731. rpmbuild --define="%_topdir $_outputdir" --define="%_libdir /usr/lib" -bb "$_outputdir/SPECS/mediacenter.spec"
  732. else
  733. rpmbuild --quiet --define="%_topdir $_outputdir" --define="%_libdir /usr/lib" -bb "$_outputdir/SPECS/mediacenter.spec" > /dev/null 2>&1
  734. fi
  735. # Check return code
  736. # shellcheck disable=SC2181
  737. if [[ $? -ne 0 || ! -f "$_mcrpm" ]]; then
  738. err "Build failed. Exiting..."
  739. exit 1
  740. else
  741. echo "Build successful. The RPM file is located at: $_mcrpm"
  742. fi
  743. fi
  744. }
  745. #######################################
  746. # Copy the RPM to createrepo-webroot and runs createrepo as the createrepo-user
  747. # Arguments:
  748. # Requires one argument, the path to the RPM file (typically _mcrpm)
  749. # Requires:
  750. # _createrepo_webroot
  751. # Returns:
  752. # 0 if createrepo is successful, 1 if not
  753. #######################################
  754. _runCreaterepo() {
  755. debug "Running: ${FUNCNAME[0]}"
  756. _installPackage createrepo_c
  757. local _rpmfile="$1"
  758. # If the webroot does not exist, create it
  759. if [[ ! -d "$_createrepo_webroot" ]]; then
  760. if ! _cr_mkdir_cmd "$_createrepo_webroot"; then
  761. err "Could not create the createrepo-webroot path!"
  762. err "Make sure that the createrepo-webroot is writeable by createrepo-user"
  763. return 1
  764. fi
  765. fi
  766. # Copy built rpms to webroot
  767. if ! _cr_cp_cmd "$_rpmfile" "$_createrepo_webroot"; then
  768. err "Could not copy the RPM to the createrepo-webroot path"
  769. err "Make sure that the createrepo-webroot path is writeable by createrepo-user"
  770. return 1
  771. fi
  772. # Run createrepo
  773. if _createrepo_cmd "$_createrepo_webroot"; then
  774. echo "Successfully updated repo"
  775. return 0
  776. else
  777. err "Update repo failed"
  778. return 1
  779. fi
  780. }
  781. #######################################
  782. # Symlink certificates where JRiver Media Center expects them to be on Fedora/CentOS
  783. # Returns:
  784. # 0 if symlinking is unecessary or successful, 1 if not
  785. #######################################
  786. _symlinkCerts() {
  787. debug "Running: ${FUNCNAME[0]}"
  788. if [[ ! -f /etc/ssl/certs/ca-certificates.crt && \
  789. -f /etc/pki/ca-trust/extracted/pem/tls-ca-bundle.pem ]]; then
  790. if ! _ln_cmd /etc/pki/ca-trust/extracted/pem/tls-ca-bundle.pem /etc/ssl/certs/ca-certificates.crt; then
  791. err "Symlinking certificates failed"
  792. return 1
  793. fi
  794. fi
  795. }
  796. #######################################
  797. # Automatically restore the mjr license file if it is found next to installJRMC or _restorefile
  798. # is set
  799. # Requires:
  800. # _restorefile OR _basedir
  801. # _mversion
  802. # Returns:
  803. # 0 if license restored successfully or skipped, 1 if unsuccessful
  804. #######################################
  805. _restoreLicense() {
  806. debug "Running: ${FUNCNAME[0]}"
  807. local _mjr
  808. # Allow user to drop an mjr file next to installJRMC
  809. if [[ -z $_restorefile ]]; then
  810. for _mjr in "$_basedir"/*.mjr; do
  811. [[ $_mjr -nt $_restorefile ]] && _restorefile="$_mjr"
  812. done
  813. fi
  814. # Restore license
  815. if [[ -f "$_restorefile" ]]; then
  816. if ! "mediacenter${_mversion}" /RestoreFromFile "$_restorefile"; then
  817. err "Automatic license restore failed"
  818. return 1
  819. fi
  820. fi
  821. }
  822. #######################################
  823. # Opens ports using the system firewall tool
  824. # Arguments
  825. # Takes one argument, the pre-specified name of the service to enable
  826. # Requires:
  827. # ID
  828. # _bash_cmd
  829. # _firewall_cmd
  830. # _port
  831. # Returns:
  832. # 0 if ports opened sucessfully, 1 if not
  833. #######################################
  834. _openFirewall() {
  835. debug "Running: ${FUNCNAME[0]}" "$@"
  836. # Create OS-specific port rules based on argument (service) name
  837. local -a _f_ports # for firewall_cmd
  838. local _u_ports # for ufw
  839. if [[ "$1" == "jriver" ]]; then
  840. _f_ports=("52100-52200/tcp" "1900/udp")
  841. _u_ports="52100:52200/tcp|1900/udp"
  842. elif [[ "$1" =~ ^(jriver-x11vnc|jriver-xvnc)$ ]]; then
  843. _f_ports=("$_port/tcp")
  844. _u_ports="$_port/tcp"
  845. else
  846. err "_openFirewall unrecognized service name"
  847. exit 1
  848. fi
  849. # Open the ports
  850. if [[ "$ID" =~ ^(fedora|centos)$ ]]; then
  851. [[ ! -x $(command -v firewall-cmd) ]] && _installPackage firewalld
  852. if ! _firewall_cmd --get-services | grep -q "$1"; then
  853. _firewall_cmd --permanent --new-service="$1" > /dev/null 2>&1
  854. _firewall_cmd --permanent --service="$1" --set-description="$1 installed by installJRMC" > /dev/null 2>&1
  855. _firewall_cmd --permanent --service="$1" --set-short="$1" > /dev/null 2>&1
  856. for _f_port in "${_f_ports[@]}"; do
  857. _firewall_cmd --permanent --service="$1" --add-port="$_f_port" > /dev/null 2>&1
  858. done
  859. _firewall_cmd --add-service "$1" --permanent > /dev/null 2>&1
  860. _firewall_cmd --reload > /dev/null 2>&1
  861. fi
  862. elif [[ "$ID" =~ ^(ubuntu|debian)$ ]]; then
  863. # Debian ufw package state is broken on fresh installations
  864. [[ ! -x $(command -v ufw) ]] && _installPackage ufw
  865. if [[ ! -f "/etc/ufw/applications.d/$1" ]]; then
  866. _bash_cmd "cat <<-EOF > /etc/ufw/applications.d/$1
  867. [$1]
  868. title=$1
  869. description=$1 installed by installJRMC
  870. ports=$_u_ports
  871. EOF"
  872. fi
  873. _firewall_cmd app update "$1"
  874. _firewall_cmd allow "$1" > /dev/null 2>&1
  875. fi
  876. # shellcheck disable=SC2181
  877. # Rationale: much more concise to check exit codes at the end
  878. if [[ $? -ne 0 ]]; then
  879. err "Firewall ports could not be opened"
  880. return 1
  881. fi
  882. }
  883. #######################################
  884. # Create the x11vnc password file
  885. # Globals:
  886. # _novncauth
  887. # Returns:
  888. # 0 if password created sucessfully, 1 if not
  889. #######################################
  890. _setX11VNCPass() {
  891. debug "Running: ${FUNCNAME[0]}"
  892. _vncpassfile="$HOME/.vnc/jrmc_passwd"
  893. [[ ! -d "${_vncpassfile%/*}" ]] && mkdir -p "${_vncpassfile%/*}"
  894. if [[ -f "$_vncpassfile" ]]; then
  895. if [[ -z $_vncpass ]]; then
  896. err "Refusing to overwrite existing $_vncpassfile with an empty password"
  897. err "Remove existing $_vncpassfile or set --vncpass to use an empty password"
  898. exit 1
  899. else
  900. rm -f "$_vncpassfile"
  901. fi
  902. fi
  903. if [[ -n $_vncpass ]]; then
  904. if ! x11vnc -storepasswd "$_vncpass" "$_vncpassfile"; then
  905. err "Could not create VNC password file"
  906. return 1
  907. fi
  908. else
  909. _novncauth="true"
  910. fi
  911. }
  912. #######################################
  913. # Create the Xvnc password file
  914. # Returns:
  915. # 0 if password created sucessfully, 1 if not
  916. #######################################
  917. _setVNCPass() {
  918. debug "Running: ${FUNCNAME[0]}"
  919. _vncpassfile="$HOME/.vnc/jrmc_passwd"
  920. [[ ! -d "${_vncpassfile%/*}" ]] && mkdir -p "${_vncpassfile%/*}"
  921. if [[ -f "$_vncpassfile" ]]; then
  922. if [[ -z $_vncpass ]]; then
  923. err "Refusing to overwrite existing $_vncpassfile with an empty password"
  924. err "Remove existing $_vncpassfile or set --vncpass to use an empty password"
  925. exit 1
  926. else
  927. rm -f "$_vncpassfile"
  928. fi
  929. fi
  930. if [[ -n $_vncpass ]]; then
  931. if ! echo "$_vncpass" | vncpasswd -f > "$_vncpassfile"; then
  932. err "Could not create VNC password file"
  933. return 1
  934. fi
  935. else
  936. _novncauth="true"
  937. fi
  938. }
  939. #######################################
  940. # Set display and port variables
  941. # Globals:
  942. # _display
  943. # _displaynum
  944. # _next_display
  945. # _next_displaynum
  946. #######################################
  947. _setDisplay() {
  948. # Check _display, else DISPLAY, else set to :0 by default
  949. if [[ -n $_display ]]; then
  950. _next_display="$_display"
  951. elif [[ -n $DISPLAY ]]; then
  952. _display="${DISPLAY}"
  953. _displaynum="${_display#:}" # strip colon
  954. _displaynum="${_displaynum%.*}" # strip suffix
  955. _next_displaynum=$(( _displaynum + 1 ))
  956. _next_display=":$_next_displaynum"
  957. else
  958. _display=":0"
  959. _next_display=":1"
  960. fi
  961. _displaynum="${_display#:}" # strip colon
  962. _displaynum="${_displaynum%.*}" # strip suffix
  963. _next_displaynum=$(( _displaynum + 1 ))
  964. }
  965. #######################################
  966. # Create associated service variables based on service name
  967. # Requires:
  968. # _service_user
  969. # Globals:
  970. # _service_fname
  971. # _timer_fname
  972. # _service_name
  973. # _timer_name
  974. # _user_specifier
  975. #######################################
  976. _servicePrep() {
  977. if [[ "$_service_user" == "root" ]]; then
  978. _service_fname="/usr/lib/systemd/system/${1}.service"
  979. _timer_fname="/usr/lib/systemd/system/${1}.timer"
  980. _service_name="jriver-${1}.service"
  981. _timer_name="jriver-${1}}.timer"
  982. _user_specifier=""
  983. else
  984. _service_fname="/usr/lib/systemd/system/${1}@.service"
  985. _timer_fname="/usr/lib/systemd/system/${1}@.timer"
  986. _service_name="${1}@$_service_user.service"
  987. _timer_name="${1}@$_service_user.timer"
  988. _user_specifier="User=%I"
  989. fi
  990. }
  991. #######################################
  992. # SERVICES
  993. #######################################
  994. #######################################
  995. # Starts and enables (at startup) a JRiver Media Center service
  996. # Arguments:
  997. # Passes arguments as startup options to /usr/bin/mediacenter26
  998. # Requires:
  999. # XAUTHORITY
  1000. #######################################
  1001. _service_jriver-mediacenter() {
  1002. debug "Running: ${FUNCNAME[0]}"
  1003. _bash_cmd "cat <<-EOF > $_service_fname
  1004. [Unit]
  1005. Description=JRiver Media Center $_mversion
  1006. After=graphical.target
  1007. [Service]
  1008. $_user_specifier
  1009. Type=simple
  1010. Environment=DISPLAY=$_display
  1011. Environment=XAUTHORITY=$XAUTHORITY
  1012. ExecStart=/usr/bin/mediacenter$_mversion $*
  1013. Restart=always
  1014. RestartSec=10
  1015. KillSignal=SIGHUP
  1016. TimeoutStopSec=30
  1017. [Install]
  1018. WantedBy=graphical.target
  1019. EOF"
  1020. _systemctl_reload && \
  1021. _systemctl_start "$_service_name" && \
  1022. _systemctl_enable "$_service_name" && \
  1023. _openFirewall "jriver"
  1024. }
  1025. #######################################
  1026. # Starts and enables (at startup) a JRiver Media Server service
  1027. #######################################
  1028. _service_jriver-mediaserver() {
  1029. debug "Running: ${FUNCNAME[0]}"
  1030. _service_jriver-mediacenter "/MediaServer"
  1031. }
  1032. #######################################
  1033. # Starts and enables (at startup) JRiver Media Center in a new Xvnc session
  1034. #######################################
  1035. _service_jriver-xvnc() {
  1036. debug "Running: ${FUNCNAME[0]}"
  1037. _installPackage tigervnc-server
  1038. _setVNCPass
  1039. local _port=$(( _next_displaynum + 5900 ))
  1040. if [[ -n $_novncauth ]]; then
  1041. _exec_start_cmd="/usr/bin/vncserver $_next_display -geometry 1440x900 -alwaysshared -name jriver$_next_display -SecurityTypes None -autokill -xstartup /usr/bin/mediacenter$_mversion"
  1042. else
  1043. _exec_start_cmd="/usr/bin/vncserver $_next_display -geometry 1440x900 -alwaysshared -rfbauth $HOME/.vnc/jrmc_passwd -autokill -xstartup /usr/bin/mediacenter$_mversion"
  1044. fi
  1045. _bash_cmd "cat <<-EOF > $_service_fname
  1046. [Unit]
  1047. Description=Remote desktop service (VNC)
  1048. After=syslog.target network.target
  1049. [Service]
  1050. Type=simple
  1051. $_user_specifier
  1052. ExecStartPre=/bin/sh -c '/usr/bin/vncserver -kill $_next_display > /dev/null 2>&1 || :'
  1053. ExecStart=$_exec_start_cmd
  1054. ExecStop=/usr/bin/vncserver -kill $_next_display
  1055. Restart=always
  1056. [Install]
  1057. WantedBy=multi-user.target
  1058. EOF"
  1059. _systemctl_reload && \
  1060. _systemctl_start "$_service_name" && \
  1061. _systemctl_enable "$_service_name" && \
  1062. echo "Xvnc running on localhost:$_port" && \
  1063. _openFirewall "jriver-xvnc" && \
  1064. _openFirewall "jriver"
  1065. }
  1066. #######################################
  1067. # Starts and enables (at startup) JRiver Media Server and x11vnc sharing the local desktop
  1068. #######################################
  1069. _service_jriver-x11vnc() {
  1070. debug "Running: ${FUNCNAME[0]}"
  1071. _installPackage x11vnc
  1072. _setX11VNCPass
  1073. local _port=$(( _displaynum + 5900 ))
  1074. # Get current desktop resolution
  1075. # TODO: may need to break this out into its own function and get smarter at identifying multi-monitors
  1076. _getResolution() {
  1077. debug "Running: ${FUNCNAME[0]}"
  1078. _installPackage xorg-x11-utils
  1079. _res=$(xdpyinfo | grep dimensions | awk '{print $2}')
  1080. }
  1081. _getResolution
  1082. if [[ -n $_novncauth ]]; then
  1083. _exec_start_cmd="/usr/bin/x11vnc -display $_display -noscr -geometry $_res -auth guess -forever -bg -nopw"
  1084. else
  1085. _exec_start_cmd="/usr/bin/x11vnc -display $_display -noscr -geometry $_res -auth guess -forever -bg -rfbauth $HOME/.vnc/jrmc_passwd"
  1086. fi
  1087. _bash_cmd "cat <<-EOF > $_service_fname
  1088. [Unit]
  1089. Description=x11vnc
  1090. After=multi.service
  1091. [Service]
  1092. $_user_specifier
  1093. Type=forking
  1094. Environment=DISPLAY=$_display
  1095. ExecStart=$_exec_start_cmd
  1096. Restart=always
  1097. RestartSec=10
  1098. [Install]
  1099. WantedBy=multi-user.target
  1100. EOF"
  1101. _systemctl_reload && \
  1102. _systemctl_start "$_service_name" && \
  1103. _systemctl_enable "$_service_name" && \
  1104. echo "x11vnc running on localhost:$_port" && \
  1105. _openFirewall "jriver-x11vnc"
  1106. }
  1107. #######################################
  1108. # Starts and enables (at startup) an hourly service to build the latest version of JRiver Media
  1109. # Center RPM from the source DEB and create/update an RPM repository
  1110. #######################################
  1111. _service_jriver-createrepo() {
  1112. debug "Running: ${FUNCNAME[0]}"
  1113. _bash_cmd "cat <<-EOF > $_service_fname
  1114. [Unit]
  1115. Description=Builds JRiver Media Center RPM file, moves it to the repo dir, and runs createrepo
  1116. [Service]
  1117. $_user_specifier
  1118. ExecStart=$_basedir/installJRMC --outputdir $_outputdir --createrepo --createrepo-webroot $_createrepo_webroot --createrepo-user $_createrepo_user
  1119. [Install]
  1120. WantedBy=default.target
  1121. EOF"
  1122. _bash_cmd "cat <<-EOF > $_timer_fname
  1123. [Unit]
  1124. Description=Run JRiver MC rpmbuild hourly
  1125. [Timer]
  1126. OnCalendar=hourly
  1127. Persistent=true
  1128. [Install]
  1129. WantedBy=timers.target
  1130. EOF"
  1131. _systemctl_reload && \
  1132. _systemctl_start "$_timer_name" && \
  1133. _systemctl_enable "$_timer_name"
  1134. }
  1135. #######################################
  1136. # CONTAINERS
  1137. #######################################
  1138. _containerCreaterepo() {
  1139. :
  1140. }
  1141. _containerVNC() {
  1142. :
  1143. }
  1144. _containerMC() {
  1145. :
  1146. }
  1147. #######################################
  1148. # Complete uninstall
  1149. #######################################
  1150. _uninstall() {
  1151. debug "Running: ${FUNCNAME[0]}"
  1152. read -r -p "Do you really want to uninstall JRiver Media Center? [y/N] " _response
  1153. _response=${_response,,} # tolower
  1154. [[ ! "$_response" =~ ^(yes|y)$ ]] && echo "Cancelling uninstall..." && exit 0
  1155. # Uninstall services
  1156. echo "Stopping and removing all associated Media Center services"
  1157. for _service in "${_available_services[@]}"; do
  1158. _servicePrep "$_service"
  1159. _systemctl_disable "$_service_name"
  1160. _systemctl_disable "$_timer_name"
  1161. [[ -f "$_service_fname" ]] && _rm_cmd "$_service_fname"
  1162. [[ -f "$_timer_fname" ]] && _rm_cmd "$_timer_fname"
  1163. done
  1164. echo "Removing repo files"
  1165. [[ -f "/etc/yum.repos.d/jriver.repo" ]] \
  1166. && _rm_cmd "/etc/yum.repos.d/jriver.repo"
  1167. [[ -f "/etc/apt/sources.list.d/jriver.list" ]] \
  1168. && _rm_cmd "/etc/apt/sources.list.d/jriver.list"
  1169. echo "Removing firewall rules"
  1170. if [[ -x $(command -v firewall-cmd) ]]; then
  1171. _firewall_cmd --permanent --remove-service=jriver
  1172. _firewall_cmd --permanent --delete-service=jriver
  1173. _firewall_cmd --reload
  1174. elif [[ -x $(command -v ufw) ]]; then
  1175. _firewall_cmd delete allow jriver
  1176. [[ -f "/etc/ufw/applications.d/jriver" ]] \
  1177. && _rm_cmd /etc/ufw/applications.d/jriver
  1178. fi
  1179. echo "Uninstalling Media Center"
  1180. if [[ "$ID" =~ ^(fedora|centos)$ ]]; then
  1181. _pkg_remove MediaCenter
  1182. elif [[ "$ID" =~ ^(ubuntu|debian)$ ]]; then
  1183. _pkg_remove "mediacenter$_mversion"
  1184. fi
  1185. echo "JRiver Media Center has been completely uninstalled"
  1186. echo "If you wish to remove your library files: rm -rf $HOME/.jriver"
  1187. echo "If you wish to remove your rpmbuild output files: rm -rf $_outputdir"
  1188. }
  1189. __main() {
  1190. # Parse input
  1191. _parseInput "$@"
  1192. # Sanity checks
  1193. _sanityChecks
  1194. # Set user variables
  1195. _setUser
  1196. # Build some OS-specific commands based on the selected OS
  1197. _buildCommands
  1198. # Install MC using package manager
  1199. if [[ -n $_repoinstall ]]; then
  1200. _installPackage rpmfusion-free-release epel-release
  1201. _installMCFromRepo
  1202. _symlinkCerts
  1203. _restoreLicense
  1204. _openFirewall "jriver"
  1205. fi
  1206. # Set version to install/uninstall
  1207. _setVersion
  1208. # Uninstall and exit
  1209. if [[ -n $_uninstall ]]; then
  1210. _uninstall
  1211. exit $?
  1212. fi
  1213. # Build RPM from source DEB
  1214. if [[ -n $_rpmbuild ]]; then
  1215. _installPackage epel-release
  1216. _acquireDeb
  1217. _buildRPM
  1218. fi
  1219. # Run createrepo
  1220. if [[ -n $_createrepo ]]; then
  1221. _runCreaterepo "$_mcrpm"
  1222. fi
  1223. # Install the rpm
  1224. if [[ -n $_rpminstall ]]; then
  1225. if [[ "$ID" =~ ^(fedora|centos)$ ]]; then
  1226. _installPackage rpmfusion-free-release epel-release
  1227. _installPackage --noquery "$_mcrpm"
  1228. _symlinkCerts
  1229. _restoreLicense
  1230. _openFirewall "jriver"
  1231. fi
  1232. fi
  1233. # Install services
  1234. _setDisplay
  1235. for _service in "${_services[@]}"; do
  1236. _servicePrep "$_service"
  1237. "_service_$_service"
  1238. done
  1239. # Install containers
  1240. for _container in "${_containers[@]}"; do
  1241. "_container_$_container"
  1242. done
  1243. }
  1244. }
  1245. # Allow this file to be executed directly if not being sourced
  1246. if [[ "${BASH_SOURCE[0]}" == "${0}" ]]; then
  1247. _basedir=$(dirname "$(readlink -f "$0")")
  1248. installJRMC
  1249. __main "$@"
  1250. fi