installJRMC 48 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473
  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 _parseInput() for available options
  16. # Returns:
  17. # 0 if critical functions complete successfully
  18. #######################################
  19. installJRMC() {
  20. _scriptversion="0.9.5"
  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. [[ ! -v 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|-d)$ ]]; 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() { [[ -v _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. debug "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" =~ ^(debian|ubuntu|linuxmint)$ ]]; 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. [[ ! -v _service_user ]] && _service_user="$_exec_user"
  299. [[ ! -v _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 [[ -v _noquery ]] || ! _pkg_query "$_pkg" > /dev/null 2>&1; then
  340. if [[ -v _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 [[ -v _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 [[ -v _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" =~ ^(debian|ubuntu|linuxmint)$ ]]; then
  387. _pkg="x11-utils"
  388. elif [[ "$1" == "rpm-build" && "$ID" =~ ^(debian|ubuntu|linuxmint)$ ]]; then
  389. _pkg="rpm"
  390. elif [[ "$1" == "createrepo_c" && "$ID" =~ ^(debian|ubuntu|linuxmint)$ ]]; 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" =~ ^(debian|ubuntu|linuxmint)$ ]]; 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 [[ ! -v _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. && [[ ! -v _repoinstall && ! -v _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" && ! -v _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. [[ ! -v _debug ]] && \
  516. echo "This may take a few minutes"; \
  517. echo "Use --debug for verbose output"
  518. local _mcpkg
  519. # Add repository files
  520. _addRepo() {
  521. debug "Running: ${FUNCNAME[0]}"
  522. # Add repositories to OS-specific package managers
  523. if [[ "$ID" =~ ^(fedora|centos)$ ]]; then
  524. _bash_cmd 'cat <<- EOF > /etc/yum.repos.d/jriver.repo
  525. [jriver]
  526. name=JRiver Media Center repo by BryanC
  527. baseurl=https://repos.bryanroessler.com/jriver
  528. gpgcheck=0
  529. EOF'
  530. elif [[ "$ID" =~ ^(debian|ubuntu|linuxmint)$ ]]; then
  531. _installPackage wget
  532. wget -q "http://dist.jriver.com/mediacenter@jriver.com.gpg.key" -O- | _ifSudo apt-key add - > /dev/null 2>&1
  533. _bash_cmd 'cat <<- EOF > /etc/apt/sources.list.d/jriver.list
  534. deb [arch=amd64,i386,armhf] http://dist.jriver.com/latest/mediacenter/ buster main
  535. EOF'
  536. fi
  537. }
  538. _addRepo
  539. # Update package list
  540. debug "Updating package list"
  541. if ! _pkg_update > /dev/null 2>&1; then
  542. err "Package update failed!"
  543. exit 1
  544. fi
  545. # If user specifies a version, use that
  546. if [[ -v _mcversion ]]; then
  547. _setVersion
  548. local _specific_version="true"
  549. fi
  550. local _mcpkg
  551. # Fedora/CentOS use a universal package name -- easy
  552. if [[ "$ID" =~ ^(fedora|centos)$ ]]; then
  553. _mcpkg="MediaCenter"
  554. fi
  555. # Ubuntu/Debian incorporate the mversion into the package name -- more fun!
  556. if [[ "$ID" =~ ^(debian|ubuntu|linuxmint)$ ]]; then
  557. if [[ ! -v _mversion ]]; then
  558. # Try parsing the latest mversion from the repo
  559. if _mcpkg=$(apt-get install mediacenter?? -s -q0 | grep "selecting" | tail -1| awk '{print $3}'); then
  560. _mcpkg="${_mcpkg%\'}"
  561. _mcpkg="${_mcpkg#\'}"
  562. # Scrape Interact
  563. else
  564. _setVersion
  565. _mcpkg="mediacenter$_mversion"
  566. fi
  567. else
  568. _mcpkg="mediacenter$_mversion"
  569. fi
  570. # Sanity check
  571. if [[ ! "$_mcpkg" =~ ^mediacenter[0-9][0-9]$ ]]; then
  572. err "Could not parse MC package name"
  573. exit 1
  574. fi
  575. fi
  576. if [[ -v _specific_version ]]; then
  577. if [[ "$ID" =~ ^(fedora|centos)$ ]]; then
  578. if [[ -v _debug ]]; then
  579. _installPackage "$_mcpkg-$_mcversion"
  580. else
  581. _installPackage "$_mcpkg-$_mcversion" > /dev/null 2>&1
  582. fi
  583. elif [[ "$ID" =~ ^(debian|ubuntu|linuxmint)$ ]]; then
  584. if [[ -v _debug ]]; then
  585. _installPackage "$_mcpkg=$_mcversion"
  586. else
  587. _installPackage "$_mcpkg=$_mcversion" > /dev/null 2>&1
  588. fi
  589. fi
  590. else
  591. if [[ -v _debug ]]; then
  592. _installPackage "$_mcpkg"
  593. else
  594. _installPackage "$_mcpkg" > /dev/null 2>&1
  595. fi
  596. fi
  597. # shellcheck disable=SC2181
  598. # Rationale: More compact to check this once
  599. if [[ $? -eq 0 ]]; then
  600. echo "JRiver Media Center installed successfully"
  601. return 0
  602. else
  603. err "JRiver Media Center installation failed"
  604. exit 1
  605. fi
  606. }
  607. #######################################
  608. # Acquire the source DEB package from JRiver's servers
  609. # Returns:
  610. # 0 if DEB file downloaded successfully, 1 if failed
  611. #######################################
  612. _acquireDeb() {
  613. debug "Running: ${FUNCNAME[0]}"
  614. local _debfilename="$_outputdir/SOURCES/MediaCenter-${_mcversion}-amd64.deb"
  615. # If necessary, create SOURCES dir
  616. [[ ! -d "$_outputdir/SOURCES" ]] && mkdir -p "$_outputdir/SOURCES"
  617. # If deb file already exists, skip download
  618. if [[ -f "$_debfilename" ]]; then
  619. echo "Using local DEB file: $_debfilename"
  620. # Else check beta repo
  621. elif [[ -v _betapass ]]; then
  622. if wget -q -O "$_debfilename" \
  623. "https://files.jriver.com/mediacenter/channels/v${_mversion}/beta/${_betapass}/MediaCenter-${_mcversion}-amd64.deb"; then
  624. true
  625. fi
  626. # Else check test repo
  627. elif wget -q -O "$_debfilename" \
  628. "https://files.jriver.com/mediacenter/test/MediaCenter-${_mcversion}-amd64.deb"; then
  629. true
  630. # Else check latest repo
  631. elif wget -q -O "$_debfilename" \
  632. "https://files.jriver.com/mediacenter/channels/v${_mversion}/latest/MediaCenter-${_mcversion}-amd64.deb"; then
  633. true
  634. else
  635. err "Cannot find DEB file. Exiting..."
  636. exit 1
  637. fi
  638. if [[ ! -f "$_debfilename" ]]; then
  639. err "Downloaded DEB file missing or corrupted, exiting..."
  640. exit 1
  641. fi
  642. }
  643. #######################################
  644. # Creates a SPEC file and builds the RPM from the source DEB using rpmbuild
  645. # Requires:
  646. # _outputdir
  647. # ID
  648. # _mcversion
  649. # _mversion
  650. # _installPackage
  651. # Globals:
  652. # _mcrpm
  653. # Returns:
  654. # 0 if rpmbuild is successful, 1 if not
  655. #######################################
  656. _buildRPM() {
  657. debug "Running: ${FUNCNAME[0]}"
  658. # install build dependencies
  659. _installPackage wget dpkg rpm-build
  660. # If necessary, make build directories
  661. [[ ! -d "$_outputdir/SPECS" ]] && mkdir -p "$_outputdir/SPECS"
  662. # rpmbuild uses rpm to check for build dependencies
  663. # this will fail on non-rpm distros
  664. if [[ "$ID" =~ ^(fedora|centos)$ ]]; then
  665. local _build_requires=$'BuildRequires: rpm >= 4.11.0\nBuildRequires: dpkg'
  666. else
  667. local _build_requires=''
  668. fi
  669. if [[ "$ID" == "fedora" && -v _rpminstall ]]; then
  670. # TODO: find out why this is required since it's not easily available on CentOS
  671. local _requires='Requires: pangox-compat >= 0.0.2'
  672. fi
  673. # Create spec file
  674. cat <<- EOF > "$_outputdir/SPECS/mediacenter.spec"
  675. Name: MediaCenter
  676. Version: $_mcversion
  677. Release: 1
  678. Summary: JRiver Media Center
  679. Group: Applications/Media
  680. Source0: http://files.jriver.com/mediacenter/channels/v$_mversion/latest/MediaCenter-$_mcversion-amd64.deb
  681. $_build_requires
  682. BuildArch: x86_64
  683. %define _rpmfilename %%{ARCH}/%%{NAME}-%%{version}.%%{ARCH}.rpm
  684. AutoReq: 0
  685. Requires: glibc >= 2.19
  686. Requires: alsa-lib >= 1.0.28
  687. Requires: libuuid >= 2.25
  688. Requires: libX11 >= 1.6
  689. Requires: libX11-common >= 1.6
  690. Requires: libXext >= 1.3
  691. Requires: libxcb >= 1.1
  692. Requires: libXdmcp >= 1.1
  693. Requires: libstdc++ >= 4.9
  694. Requires: gtk3 >= 3.14
  695. Requires: mesa-libGL
  696. Requires: libglvnd-glx
  697. Requires: pango >= 1.36
  698. $_requires
  699. Requires: libXScrnSaver
  700. Requires: xdg-utils
  701. Requires: libgomp >= 4.9
  702. Requires: nss >= 3.26
  703. Requires: nspr >= 4.12
  704. Requires: ca-certificates
  705. Requires: python3
  706. Recommends: vorbis-tools >= 1.4.0
  707. Recommends: lame >= 3.0
  708. Provides: mediacenter$_mversion
  709. License: Copyright 1998-2020, JRiver, Inc. All rights reserved. Protected by U.S. patents #7076468 and #7062468
  710. URL: http://www.jriver.com/
  711. %define __provides_exclude_from ^%{_libdir}/jriver/.*/.*\\.so.*$
  712. %description
  713. Media Center is more than a world class player.
  714. %global __os_install_post %{nil}
  715. %prep
  716. %build
  717. %install
  718. dpkg -x %{S:0} %{buildroot}
  719. %post -p /sbin/ldconfig
  720. %postun -p /sbin/ldconfig
  721. %files
  722. %{_bindir}/mediacenter$_mversion
  723. %{_libdir}/jriver
  724. %{_datadir}
  725. %exclude %{_datadir}/applications/media_center_packageinstaller_$_mversion.desktop
  726. /etc/security/limits.d/*
  727. EOF
  728. declare -g _mcrpm="$_outputdir/RPMS/x86_64/MediaCenter-$_mcversion.x86_64.rpm"
  729. # skip rebuilding the rpm if it already exists
  730. if [[ -f "$_mcrpm" ]]; then
  731. echo "$_mcrpm already exists. Skipping build step..."
  732. return 0
  733. else
  734. # Run rpmbuild
  735. echo "Building version $_mcversion, please wait..."
  736. if [[ -v _debug ]]; then
  737. rpmbuild --define="%_topdir $_outputdir" --define="%_libdir /usr/lib" -bb "$_outputdir/SPECS/mediacenter.spec"
  738. else
  739. rpmbuild --quiet --define="%_topdir $_outputdir" --define="%_libdir /usr/lib" -bb "$_outputdir/SPECS/mediacenter.spec" > /dev/null 2>&1
  740. fi
  741. # Check return code
  742. # shellcheck disable=SC2181
  743. if [[ $? -ne 0 || ! -f "$_mcrpm" ]]; then
  744. err "Build failed. Exiting..."
  745. exit 1
  746. else
  747. echo "Build successful. The RPM file is located at: $_mcrpm"
  748. fi
  749. fi
  750. }
  751. #######################################
  752. # Copy the RPM to createrepo-webroot and runs createrepo as the createrepo-user
  753. # Arguments:
  754. # Requires one argument, the path to the RPM file (typically _mcrpm)
  755. # Requires:
  756. # _createrepo_webroot
  757. # Returns:
  758. # 0 if createrepo is successful, 1 if not
  759. #######################################
  760. _runCreaterepo() {
  761. debug "Running: ${FUNCNAME[0]}"
  762. _installPackage createrepo_c
  763. local _rpmfile="$1"
  764. # If the webroot does not exist, create it
  765. if [[ ! -d "$_createrepo_webroot" ]]; then
  766. if ! _cr_mkdir_cmd "$_createrepo_webroot"; then
  767. err "Could not create the createrepo-webroot path!"
  768. err "Make sure that the createrepo-webroot is writeable by createrepo-user"
  769. return 1
  770. fi
  771. fi
  772. # Copy built rpms to webroot
  773. if ! _cr_cp_cmd -f "$_rpmfile" "$_createrepo_webroot"; then
  774. err "Could not copy the RPM to the createrepo-webroot path"
  775. err "Make sure that the createrepo-webroot path is writeable by createrepo-user"
  776. return 1
  777. fi
  778. # Run createrepo
  779. if _createrepo_cmd "$_createrepo_webroot"; then
  780. echo "Successfully updated repo"
  781. return 0
  782. else
  783. err "Update repo failed"
  784. return 1
  785. fi
  786. }
  787. #######################################
  788. # Symlink certificates where JRiver Media Center expects them to be on Fedora/CentOS
  789. # Returns:
  790. # 0 if symlinking is unecessary or successful, 1 if not
  791. #######################################
  792. _symlinkCerts() {
  793. debug "Running: ${FUNCNAME[0]}"
  794. if [[ ! -f /etc/ssl/certs/ca-certificates.crt && \
  795. -f /etc/pki/ca-trust/extracted/pem/tls-ca-bundle.pem ]]; then
  796. if ! _ln_cmd /etc/pki/ca-trust/extracted/pem/tls-ca-bundle.pem /etc/ssl/certs/ca-certificates.crt; then
  797. err "Symlinking certificates failed"
  798. return 1
  799. fi
  800. fi
  801. }
  802. #######################################
  803. # Automatically restore the mjr license file if it is found next to installJRMC or _restorefile
  804. # is set
  805. # Requires:
  806. # _restorefile OR _basedir
  807. # _mversion
  808. # Returns:
  809. # 0 if license restored successfully or skipped, 1 if unsuccessful
  810. #######################################
  811. _restoreLicense() {
  812. debug "Running: ${FUNCNAME[0]}"
  813. local _mjr
  814. # Allow user to drop an mjr file next to installJRMC
  815. if [[ ! -v _restorefile ]]; then
  816. for _mjr in "$_basedir"/*.mjr; do
  817. [[ $_mjr -nt $_restorefile ]] && _restorefile="$_mjr"
  818. done
  819. fi
  820. # Restore license
  821. if [[ -f "$_restorefile" ]]; then
  822. if ! "mediacenter${_mversion}" /RestoreFromFile "$_restorefile"; then
  823. err "Automatic license restore failed"
  824. return 1
  825. fi
  826. fi
  827. }
  828. #######################################
  829. # Opens ports using the system firewall tool
  830. # Arguments
  831. # Takes one argument, the pre-specified name of the service to enable
  832. # Requires:
  833. # ID
  834. # _bash_cmd
  835. # _firewall_cmd
  836. # _port
  837. # Returns:
  838. # 0 if ports opened sucessfully, 1 if not
  839. #######################################
  840. _openFirewall() {
  841. debug "Running: ${FUNCNAME[0]}" "$@"
  842. # Create OS-specific port rules based on argument (service) name
  843. local -a _f_ports # for firewall_cmd
  844. local _u_ports # for ufw
  845. if [[ "$1" == "jriver" ]]; then
  846. _f_ports=("52100-52200/tcp" "1900/udp")
  847. _u_ports="52100:52200/tcp|1900/udp"
  848. elif [[ "$1" =~ ^(jriver-x11vnc|jriver-xvnc)$ ]]; then
  849. _f_ports=("$_port/tcp")
  850. _u_ports="$_port/tcp"
  851. else
  852. err "_openFirewall unrecognized service name"
  853. exit 1
  854. fi
  855. # Open the ports
  856. if [[ "$ID" =~ ^(fedora|centos)$ ]]; then
  857. [[ ! -x $(command -v firewall-cmd) ]] && _installPackage firewalld
  858. if ! _firewall_cmd --get-services | grep -q "$1"; then
  859. _firewall_cmd --permanent --new-service="$1" > /dev/null 2>&1
  860. _firewall_cmd --permanent --service="$1" --set-description="$1 installed by installJRMC" > /dev/null 2>&1
  861. _firewall_cmd --permanent --service="$1" --set-short="$1" > /dev/null 2>&1
  862. for _f_port in "${_f_ports[@]}"; do
  863. _firewall_cmd --permanent --service="$1" --add-port="$_f_port" > /dev/null 2>&1
  864. done
  865. _firewall_cmd --add-service "$1" --permanent > /dev/null 2>&1
  866. _firewall_cmd --reload > /dev/null 2>&1
  867. fi
  868. elif [[ "$ID" =~ ^(debian|ubuntu|linuxmint)$ ]]; then
  869. # Debian ufw package state is broken on fresh installations
  870. [[ ! -x $(command -v ufw) ]] && _installPackage ufw
  871. if [[ ! -f "/etc/ufw/applications.d/$1" ]]; then
  872. _bash_cmd "cat <<- EOF > /etc/ufw/applications.d/$1
  873. [$1]
  874. title=$1
  875. description=$1 installed by installJRMC
  876. ports=$_u_ports
  877. EOF"
  878. fi
  879. _firewall_cmd app update "$1"
  880. _firewall_cmd allow "$1" > /dev/null 2>&1
  881. fi
  882. # shellcheck disable=SC2181
  883. # Rationale: much more concise to check exit codes at the end
  884. if [[ $? -ne 0 ]]; then
  885. err "Firewall ports could not be opened"
  886. return 1
  887. fi
  888. }
  889. #######################################
  890. # Create the x11vnc password file
  891. # Globals:
  892. # _novncauth
  893. # Returns:
  894. # 0 if password created sucessfully, 1 if not
  895. #######################################
  896. _setX11VNCPass() {
  897. debug "Running: ${FUNCNAME[0]}"
  898. _vncpassfile="$HOME/.vnc/jrmc_passwd"
  899. [[ ! -d "${_vncpassfile%/*}" ]] && mkdir -p "${_vncpassfile%/*}"
  900. if [[ -f "$_vncpassfile" ]]; then
  901. if [[ ! -v _vncpass ]]; then
  902. err "Refusing to overwrite existing $_vncpassfile with an empty password"
  903. err "Remove existing $_vncpassfile or set --vncpass to use an empty password"
  904. exit 1
  905. else
  906. rm -f "$_vncpassfile"
  907. fi
  908. fi
  909. if [[ -v _vncpass ]]; then
  910. if ! x11vnc -storepasswd "$_vncpass" "$_vncpassfile"; then
  911. err "Could not create VNC password file"
  912. return 1
  913. fi
  914. else
  915. _novncauth="true"
  916. fi
  917. }
  918. #######################################
  919. # Create the Xvnc password file
  920. # Returns:
  921. # 0 if password created sucessfully, 1 if not
  922. #######################################
  923. _setVNCPass() {
  924. debug "Running: ${FUNCNAME[0]}"
  925. _vncpassfile="$HOME/.vnc/jrmc_passwd"
  926. [[ ! -d "${_vncpassfile%/*}" ]] && mkdir -p "${_vncpassfile%/*}"
  927. if [[ -f "$_vncpassfile" ]]; then
  928. if [[ ! -v _vncpass ]]; then
  929. err "Refusing to overwrite existing $_vncpassfile with an empty password"
  930. err "Remove existing $_vncpassfile or set --vncpass to use an empty password"
  931. exit 1
  932. else
  933. rm -f "$_vncpassfile"
  934. fi
  935. fi
  936. if [[ -v _vncpass ]]; then
  937. if ! echo "$_vncpass" | vncpasswd -f > "$_vncpassfile"; then
  938. err "Could not create VNC password file"
  939. return 1
  940. fi
  941. else
  942. _novncauth="true"
  943. fi
  944. }
  945. #######################################
  946. # Set display and port variables
  947. # Globals:
  948. # _display
  949. # _displaynum
  950. # _next_display
  951. # _next_displaynum
  952. #######################################
  953. _setDisplay() {
  954. debug "Running: ${FUNCNAME[0]}"
  955. # Check _display, else DISPLAY, else set to :0 by default
  956. if [[ -v _display ]]; then
  957. _next_display="$_display"
  958. elif [[ -v DISPLAY ]]; then
  959. _display="${DISPLAY}"
  960. _displaynum="${_display#:}" # strip colon
  961. _displaynum="${_displaynum%.*}" # strip suffix
  962. _next_displaynum=$(( _displaynum + 1 ))
  963. _next_display=":$_next_displaynum"
  964. else
  965. _display=":0"
  966. _next_display=":1"
  967. fi
  968. _displaynum="${_display#:}" # strip colon
  969. _displaynum="${_displaynum%.*}" # strip suffix
  970. _next_displaynum=$(( _displaynum + 1 ))
  971. }
  972. #######################################
  973. # Create associated service variables based on service name
  974. # Requires:
  975. # _service_user
  976. # Globals:
  977. # _service_fname
  978. # _timer_fname
  979. # _service_name
  980. # _timer_name
  981. # _user_specifier
  982. #######################################
  983. _servicePrep() {
  984. debug "Running: ${FUNCNAME[0]}"
  985. if [[ "$_service_user" == "root" ]]; then
  986. _service_fname="/usr/lib/systemd/system/${1}.service"
  987. _timer_fname="/usr/lib/systemd/system/${1}.timer"
  988. _service_name="jriver-${1}.service"
  989. _timer_name="jriver-${1}}.timer"
  990. _user_specifier=""
  991. else
  992. _service_fname="/usr/lib/systemd/system/${1}@.service"
  993. _timer_fname="/usr/lib/systemd/system/${1}@.timer"
  994. _service_name="${1}@$_service_user.service"
  995. _timer_name="${1}@$_service_user.timer"
  996. _user_specifier="User=%I"
  997. fi
  998. }
  999. #######################################
  1000. # SERVICES
  1001. #######################################
  1002. #######################################
  1003. # Starts and enables (at startup) a JRiver Media Center service
  1004. # Arguments:
  1005. # Passes arguments as startup options to /usr/bin/mediacenter26
  1006. # Requires:
  1007. # XAUTHORITY
  1008. #######################################
  1009. _service_jriver-mediacenter() {
  1010. debug "Running: ${FUNCNAME[0]}"
  1011. _bash_cmd "cat <<- EOF > $_service_fname
  1012. [Unit]
  1013. Description=JRiver Media Center $_mversion
  1014. After=graphical.target
  1015. [Service]
  1016. $_user_specifier
  1017. Type=simple
  1018. Environment=DISPLAY=$_display
  1019. Environment=XAUTHORITY=$XAUTHORITY
  1020. ExecStart=/usr/bin/mediacenter$_mversion $*
  1021. Restart=always
  1022. RestartSec=10
  1023. KillSignal=SIGHUP
  1024. TimeoutStopSec=30
  1025. [Install]
  1026. WantedBy=graphical.target
  1027. EOF"
  1028. _systemctl_reload && \
  1029. _systemctl_start "$_service_name" && \
  1030. _systemctl_enable "$_service_name" && \
  1031. _openFirewall "jriver"
  1032. }
  1033. #######################################
  1034. # Starts and enables (at startup) a JRiver Media Server service
  1035. #######################################
  1036. _service_jriver-mediaserver() {
  1037. debug "Running: ${FUNCNAME[0]}"
  1038. _service_jriver-mediacenter "/MediaServer"
  1039. }
  1040. #######################################
  1041. # Starts and enables (at startup) JRiver Media Center in a new Xvnc session
  1042. #######################################
  1043. _service_jriver-xvnc-mediacenter() {
  1044. debug "Running: ${FUNCNAME[0]}"
  1045. _installPackage tigervnc-server
  1046. _setVNCPass
  1047. local _port=$(( _next_displaynum + 5900 ))
  1048. if [[ -v _novncauth ]]; then
  1049. _exec_start_cmd="/usr/bin/vncserver $_next_display -geometry 1440x900 -alwaysshared -name jriver$_next_display -SecurityTypes None -autokill -xstartup /usr/bin/mediacenter$_mversion"
  1050. else
  1051. _exec_start_cmd="/usr/bin/vncserver $_next_display -geometry 1440x900 -alwaysshared -rfbauth $HOME/.vnc/jrmc_passwd -autokill -xstartup /usr/bin/mediacenter$_mversion"
  1052. fi
  1053. _bash_cmd "cat <<- EOF > $_service_fname
  1054. [Unit]
  1055. Description=Remote desktop service (VNC)
  1056. After=syslog.target network.target
  1057. [Service]
  1058. Type=simple
  1059. $_user_specifier
  1060. ExecStartPre=/bin/sh -c '/usr/bin/vncserver -kill $_next_display > /dev/null 2>&1 || :'
  1061. ExecStart=$_exec_start_cmd
  1062. ExecStop=/usr/bin/vncserver -kill $_next_display
  1063. Restart=always
  1064. [Install]
  1065. WantedBy=multi-user.target
  1066. EOF"
  1067. _systemctl_reload && \
  1068. _systemctl_start "$_service_name" && \
  1069. _systemctl_enable "$_service_name" && \
  1070. echo "Xvnc running on localhost:$_port" && \
  1071. _openFirewall "jriver-xvnc" && \
  1072. _openFirewall "jriver"
  1073. }
  1074. #######################################
  1075. # Starts and enables (at startup) JRiver Media Server and x11vnc sharing the local desktop
  1076. #######################################
  1077. _service_jriver-x11vnc() {
  1078. debug "Running: ${FUNCNAME[0]}"
  1079. _installPackage x11vnc
  1080. _setX11VNCPass
  1081. local _port=$(( _displaynum + 5900 ))
  1082. # Get current desktop resolution
  1083. # TODO: may need to break this out into its own function and get smarter at identifying multi-monitors
  1084. _getResolution() {
  1085. debug "Running: ${FUNCNAME[0]}"
  1086. _installPackage xorg-x11-utils
  1087. _res=$(xdpyinfo | grep dimensions | awk '{print $2}')
  1088. }
  1089. _getResolution
  1090. if [[ -v _novncauth ]]; then
  1091. _exec_start_cmd="/usr/bin/x11vnc -display $_display -noscr -geometry $_res -auth guess -forever -bg -nopw"
  1092. else
  1093. _exec_start_cmd="/usr/bin/x11vnc -display $_display -noscr -geometry $_res -auth guess -forever -bg -rfbauth $HOME/.vnc/jrmc_passwd"
  1094. fi
  1095. _bash_cmd "cat <<-EOF > $_service_fname
  1096. [Unit]
  1097. Description=x11vnc
  1098. After=multi.service
  1099. [Service]
  1100. $_user_specifier
  1101. Type=forking
  1102. Environment=DISPLAY=$_display
  1103. ExecStart=$_exec_start_cmd
  1104. Restart=always
  1105. RestartSec=10
  1106. [Install]
  1107. WantedBy=multi-user.target
  1108. EOF"
  1109. _systemctl_reload && \
  1110. _systemctl_start "$_service_name" && \
  1111. _systemctl_enable "$_service_name" && \
  1112. echo "x11vnc running on localhost:$_port" && \
  1113. _openFirewall "jriver-x11vnc"
  1114. }
  1115. #######################################
  1116. # Starts and enables (at startup) an hourly service to build the latest version of JRiver Media
  1117. # Center RPM from the source DEB and create/update an RPM repository
  1118. #######################################
  1119. _service_jriver-createrepo() {
  1120. debug "Running: ${FUNCNAME[0]}"
  1121. _bash_cmd "cat <<-EOF > $_service_fname
  1122. [Unit]
  1123. Description=Builds JRiver Media Center RPM file, moves it to the repo dir, and runs createrepo
  1124. [Service]
  1125. $_user_specifier
  1126. ExecStart=$_basedir/installJRMC --outputdir $_outputdir --createrepo --createrepo-webroot $_createrepo_webroot --createrepo-user $_createrepo_user
  1127. [Install]
  1128. WantedBy=default.target
  1129. EOF"
  1130. _bash_cmd "cat <<-EOF > $_timer_fname
  1131. [Unit]
  1132. Description=Run JRiver MC rpmbuild hourly
  1133. [Timer]
  1134. OnCalendar=hourly
  1135. Persistent=true
  1136. [Install]
  1137. WantedBy=timers.target
  1138. EOF"
  1139. _systemctl_reload && \
  1140. _systemctl_start "$_timer_name" && \
  1141. _systemctl_enable "$_timer_name"
  1142. }
  1143. #######################################
  1144. # CONTAINERS
  1145. #######################################
  1146. _containerCreaterepo() {
  1147. :
  1148. }
  1149. _containerVNC() {
  1150. :
  1151. }
  1152. _containerMC() {
  1153. :
  1154. }
  1155. #######################################
  1156. # Complete uninstall
  1157. #######################################
  1158. _uninstall() {
  1159. debug "Running: ${FUNCNAME[0]}"
  1160. read -r -p "Do you really want to uninstall JRiver Media Center? [y/N] " _response
  1161. _response=${_response,,} # tolower
  1162. [[ ! "$_response" =~ ^(yes|y)$ ]] && echo "Cancelling uninstall..." && exit 0
  1163. # Uninstall services
  1164. echo "Stopping and removing all associated Media Center services"
  1165. for _service in "${_available_services[@]}"; do
  1166. _servicePrep "$_service"
  1167. _systemctl_disable "$_service_name"
  1168. _systemctl_disable "$_timer_name"
  1169. [[ -f "$_service_fname" ]] && _rm_cmd "$_service_fname"
  1170. [[ -f "$_timer_fname" ]] && _rm_cmd "$_timer_fname"
  1171. done
  1172. echo "Removing repo files"
  1173. [[ -f "/etc/yum.repos.d/jriver.repo" ]] \
  1174. && _rm_cmd "/etc/yum.repos.d/jriver.repo"
  1175. [[ -f "/etc/apt/sources.list.d/jriver.list" ]] \
  1176. && _rm_cmd "/etc/apt/sources.list.d/jriver.list"
  1177. echo "Removing firewall rules"
  1178. if [[ -x $(command -v firewall-cmd) ]]; then
  1179. _firewall_cmd --permanent --remove-service=jriver
  1180. _firewall_cmd --permanent --delete-service=jriver
  1181. _firewall_cmd --reload
  1182. elif [[ -x $(command -v ufw) ]]; then
  1183. _firewall_cmd delete allow jriver
  1184. [[ -f "/etc/ufw/applications.d/jriver" ]] \
  1185. && _rm_cmd /etc/ufw/applications.d/jriver
  1186. fi
  1187. echo "Uninstalling Media Center"
  1188. if [[ "$ID" =~ ^(fedora|centos)$ ]]; then
  1189. _pkg_remove MediaCenter
  1190. elif [[ "$ID" =~ ^(debian|ubuntu|linuxmint)$ ]]; then
  1191. _pkg_remove "mediacenter$_mversion"
  1192. fi
  1193. echo "JRiver Media Center has been completely uninstalled"
  1194. echo "If you wish to remove your library files: rm -rf $HOME/.jriver"
  1195. echo "If you wish to remove your rpmbuild output files: rm -rf $_outputdir"
  1196. }
  1197. _main() {
  1198. # Parse input
  1199. _parseInput "$@"
  1200. # Sanity checks
  1201. _sanityChecks
  1202. # Set user variables
  1203. _setUser
  1204. # Build some OS-specific commands based on the selected OS
  1205. _buildCommands
  1206. # Install MC using package manager
  1207. if [[ -v _repoinstall ]]; then
  1208. [[ "$ID" =~ ^(fedora|centos)$ ]] && _installPackage rpmfusion-free-release epel-release
  1209. _installMCFromRepo
  1210. _symlinkCerts
  1211. _restoreLicense
  1212. _openFirewall "jriver"
  1213. fi
  1214. # Set version to install/uninstall
  1215. _setVersion
  1216. # Uninstall and exit
  1217. if [[ -v _uninstall ]]; then
  1218. _uninstall
  1219. exit $?
  1220. fi
  1221. # Build RPM from source DEB
  1222. if [[ -v _rpmbuild ]]; then
  1223. _installPackage epel-release
  1224. _acquireDeb
  1225. _buildRPM
  1226. fi
  1227. # Run createrepo
  1228. if [[ -v _createrepo ]]; then
  1229. _runCreaterepo "$_mcrpm"
  1230. fi
  1231. # Install the rpm
  1232. if [[ -v _rpminstall ]]; then
  1233. if [[ "$ID" =~ ^(fedora|centos)$ ]]; then
  1234. _installPackage rpmfusion-free-release epel-release
  1235. _installPackage --noquery "$_mcrpm"
  1236. _symlinkCerts
  1237. _restoreLicense
  1238. _openFirewall "jriver"
  1239. fi
  1240. fi
  1241. # Install services
  1242. _setDisplay
  1243. for _service in "${_services[@]}"; do
  1244. _servicePrep "$_service"
  1245. "_service_$_service"
  1246. done
  1247. # Install containers
  1248. for _container in "${_containers[@]}"; do
  1249. "_container_$_container"
  1250. done
  1251. }
  1252. }
  1253. # Allow this file to be executed directly if not being sourced
  1254. if [[ "${BASH_SOURCE[0]}" == "${0}" ]]; then
  1255. _basedir=$(dirname "$(readlink -f "$0")")
  1256. installJRMC
  1257. _main "$@"
  1258. fi