installJRMC 47 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485
  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.8"
  21. _boardurl="https://yabb.jriver.com/interact/index.php/board,64.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. /etc/security/limits.d/*
  720. EOF"
  721. declare -g _mcrpm="$_outputdir/RPMS/x86_64/MediaCenter-$_mcversion.x86_64.rpm"
  722. # skip rebuilding the rpm if it already exists
  723. if [[ -f "$_mcrpm" ]]; then
  724. echo "$_mcrpm already exists. Skipping build step..."
  725. return 0 # this is fine
  726. else
  727. # Run rpmbuild
  728. echo "Building version $_mcversion, please wait..."
  729. if [[ -n $_debug ]]; then
  730. rpmbuild --define="%_topdir $_outputdir" --define="%_libdir /usr/lib" -bb "$_outputdir/SPECS/mediacenter.spec"
  731. else
  732. rpmbuild --quiet --define="%_topdir $_outputdir" --define="%_libdir /usr/lib" -bb "$_outputdir/SPECS/mediacenter.spec" > /dev/null 2>&1
  733. fi
  734. # Check return code
  735. # shellcheck disable=SC2181
  736. if [[ $? -ne 0 || ! -f "$_mcrpm" ]]; then
  737. err "Build failed. Exiting..."
  738. exit 1
  739. else
  740. echo "Build successful. The RPM file is located at: $_mcrpm"
  741. fi
  742. fi
  743. }
  744. #######################################
  745. # Copy the RPM to createrepo-webroot and runs createrepo as the createrepo-user
  746. # Arguments:
  747. # Requires one argument, the path to the RPM file (typically _mcrpm)
  748. # Requires:
  749. # _createrepo_webroot
  750. # Returns:
  751. # 0 if createrepo is successful, 1 if not
  752. #######################################
  753. _runCreaterepo() {
  754. debug "Running: ${FUNCNAME[0]}"
  755. _installPackage createrepo_c
  756. local _rpmfile="$1"
  757. # If the webroot does not exist, create it
  758. if [[ ! -d "$_createrepo_webroot" ]]; then
  759. if ! _cr_mkdir_cmd "$_createrepo_webroot"; then
  760. err "Could not create the createrepo-webroot path!"
  761. err "Make sure that the createrepo-webroot is writeable by createrepo-user"
  762. return 1
  763. fi
  764. fi
  765. # Copy built rpms to webroot
  766. if ! _cr_cp_cmd "$_rpmfile" "$_createrepo_webroot"; then
  767. err "Could not copy the RPM to the createrepo-webroot path"
  768. err "Make sure that the createrepo-webroot path is writeable by createrepo-user"
  769. return 1
  770. fi
  771. # Run createrepo
  772. if _createrepo_cmd "$_createrepo_webroot"; then
  773. echo "Successfully updated repo"
  774. return 0
  775. else
  776. err "Update repo failed"
  777. return 1
  778. fi
  779. }
  780. #######################################
  781. # Symlink certificates where JRiver Media Center expects them to be on Fedora/CentOS
  782. # Returns:
  783. # 0 if symlinking is unecessary or successful, 1 if not
  784. #######################################
  785. _symlinkCerts() {
  786. debug "Running: ${FUNCNAME[0]}"
  787. if [[ ! -f /etc/ssl/certs/ca-certificates.crt && \
  788. -f /etc/pki/ca-trust/extracted/pem/tls-ca-bundle.pem ]]; then
  789. if ! _ln_cmd /etc/pki/ca-trust/extracted/pem/tls-ca-bundle.pem /etc/ssl/certs/ca-certificates.crt; then
  790. err "Symlinking certificates failed"
  791. return 1
  792. fi
  793. fi
  794. }
  795. #######################################
  796. # Automatically restore the mjr license file if it is found next to installJRMC or _restorefile
  797. # is set
  798. # Requires:
  799. # _restorefile OR _basedir
  800. # _mversion
  801. # Returns:
  802. # 0 if license restored successfully or skipped, 1 if unsuccessful
  803. #######################################
  804. _restoreLicense() {
  805. debug "Running: ${FUNCNAME[0]}"
  806. local _mjr
  807. # Allow user to drop an mjr file next to installJRMC
  808. if [[ -z $_restorefile ]]; then
  809. for _mjr in "$_basedir"/*.mjr; do
  810. [[ $_mjr -nt $_restorefile ]] && _restorefile="$_mjr"
  811. done
  812. fi
  813. # Restore license
  814. if [[ -f "$_restorefile" ]]; then
  815. if ! "mediacenter${_mversion}" /RestoreFromFile "$_restorefile"; then
  816. err "Automatic license restore failed"
  817. return 1
  818. fi
  819. fi
  820. }
  821. #######################################
  822. # Opens ports using the system firewall tool
  823. # Arguments
  824. # Takes one argument, the pre-specified name of the service to enable
  825. # Requires:
  826. # ID
  827. # _bash_cmd
  828. # _firewall_cmd
  829. # _port
  830. # Returns:
  831. # 0 if ports opened sucessfully, 1 if not
  832. #######################################
  833. _openFirewall() {
  834. debug "Running: ${FUNCNAME[0]}" "$@"
  835. # Create OS-specific port rules based on argument (service) name
  836. local -a _f_ports # for firewall_cmd
  837. local _u_ports # for ufw
  838. if [[ "$1" == "jriver" ]]; then
  839. _f_ports=("52100-52200/tcp" "1900/udp")
  840. _u_ports="52100:52200/tcp|1900/udp"
  841. elif [[ "$1" =~ ^(jriver-x11vnc|jriver-xvnc)$ ]]; then
  842. _f_ports=("$_port/tcp")
  843. _u_ports="$_port/tcp"
  844. else
  845. err "_openFirewall unrecognized service name"
  846. exit 1
  847. fi
  848. # Open the ports
  849. if [[ "$ID" =~ ^(fedora|centos)$ ]]; then
  850. [[ ! -x $(command -v firewall-cmd) ]] && _installPackage firewalld
  851. if ! _firewall_cmd --get-services | grep -q "$1"; then
  852. _firewall_cmd --permanent --new-service="$1" > /dev/null 2>&1
  853. _firewall_cmd --permanent --service="$1" --set-description="$1 installed by installJRMC" > /dev/null 2>&1
  854. _firewall_cmd --permanent --service="$1" --set-short="$1" > /dev/null 2>&1
  855. for _f_port in "${_f_ports[@]}"; do
  856. _firewall_cmd --permanent --service="$1" --add-port="$_f_port" > /dev/null 2>&1
  857. done
  858. _firewall_cmd --add-service "$1" --permanent > /dev/null 2>&1
  859. _firewall_cmd --reload > /dev/null 2>&1
  860. fi
  861. elif [[ "$ID" =~ ^(ubuntu|debian)$ ]]; then
  862. # Debian ufw package state is broken on fresh installations
  863. [[ ! -x $(command -v ufw) ]] && _installPackage ufw
  864. if [[ ! -f "/etc/ufw/applications.d/$1" ]]; then
  865. _bash_cmd "cat <<-EOF > /etc/ufw/applications.d/$1
  866. [$1]
  867. title=$1
  868. description=$1 installed by installJRMC
  869. ports=$_u_ports
  870. EOF"
  871. fi
  872. _firewall_cmd app update "$1"
  873. _firewall_cmd allow "$1" > /dev/null 2>&1
  874. fi
  875. # shellcheck disable=SC2181
  876. # Rationale: much more concise to check exit codes at the end
  877. if [[ $? -ne 0 ]]; then
  878. err "Firewall ports could not be opened"
  879. return 1
  880. fi
  881. }
  882. #######################################
  883. # Create the x11vnc password file
  884. # Globals:
  885. # _novncauth
  886. # Returns:
  887. # 0 if password created sucessfully, 1 if not
  888. #######################################
  889. _setX11VNCPass() {
  890. debug "Running: ${FUNCNAME[0]}"
  891. _vncpassfile="$HOME/.vnc/jrmc_passwd"
  892. [[ ! -d "${_vncpassfile%/*}" ]] && mkdir -p "${_vncpassfile%/*}"
  893. if [[ -f "$_vncpassfile" ]]; then
  894. if [[ -z $_vncpass ]]; then
  895. err "Refusing to overwrite existing $_vncpassfile with an empty password"
  896. err "Remove existing $_vncpassfile or set --vncpass to use an empty password"
  897. exit 1
  898. else
  899. rm -f "$_vncpassfile"
  900. fi
  901. fi
  902. if [[ -n $_vncpass ]]; then
  903. if ! x11vnc -storepasswd "$_vncpass" "$_vncpassfile"; then
  904. err "Could not create VNC password file"
  905. return 1
  906. fi
  907. else
  908. _novncauth="true"
  909. fi
  910. }
  911. #######################################
  912. # Create the Xvnc password file
  913. # Returns:
  914. # 0 if password created sucessfully, 1 if not
  915. #######################################
  916. _setVNCPass() {
  917. debug "Running: ${FUNCNAME[0]}"
  918. _vncpassfile="$HOME/.vnc/jrmc_passwd"
  919. [[ ! -d "${_vncpassfile%/*}" ]] && mkdir -p "${_vncpassfile%/*}"
  920. if [[ -f "$_vncpassfile" ]]; then
  921. if [[ -z $_vncpass ]]; then
  922. err "Refusing to overwrite existing $_vncpassfile with an empty password"
  923. err "Remove existing $_vncpassfile or set --vncpass to use an empty password"
  924. exit 1
  925. else
  926. rm -f "$_vncpassfile"
  927. fi
  928. fi
  929. if [[ -n $_vncpass ]]; then
  930. if ! echo "$_vncpass" | vncpasswd -f > "$_vncpassfile"; then
  931. err "Could not create VNC password file"
  932. return 1
  933. fi
  934. else
  935. _novncauth="true"
  936. fi
  937. }
  938. #######################################
  939. # Set display and port variables
  940. # Globals:
  941. # _display
  942. # _displaynum
  943. # _next_display
  944. # _next_displaynum
  945. #######################################
  946. _setDisplay() {
  947. # Check _display, else DISPLAY, else set to :0 by default
  948. if [[ -n $_display ]]; then
  949. _next_display="$_display"
  950. elif [[ -n $DISPLAY ]]; then
  951. _display="${DISPLAY}"
  952. _displaynum="${_display#:}" # strip colon
  953. _displaynum="${_displaynum%.*}" # strip suffix
  954. _next_displaynum=$(( _displaynum + 1 ))
  955. _next_display=":$_next_displaynum"
  956. else
  957. _display=":0"
  958. _next_display=":1"
  959. fi
  960. _displaynum="${_display#:}" # strip colon
  961. _displaynum="${_displaynum%.*}" # strip suffix
  962. _next_displaynum=$(( _displaynum + 1 ))
  963. }
  964. #######################################
  965. # Create associated service variables based on service name
  966. # Requires:
  967. # _service_user
  968. # Globals:
  969. # _service_fname
  970. # _timer_fname
  971. # _service_name
  972. # _timer_name
  973. # _user_specifier
  974. #######################################
  975. _servicePrep() {
  976. if [[ "$_service_user" == "root" ]]; then
  977. _service_fname="/usr/lib/systemd/system/${1}.service"
  978. _timer_fname="/usr/lib/systemd/system/${1}.timer"
  979. _service_name="jriver-${1}.service"
  980. _timer_name="jriver-${1}}.timer"
  981. _user_specifier=""
  982. else
  983. _service_fname="/usr/lib/systemd/system/${1}@.service"
  984. _timer_fname="/usr/lib/systemd/system/${1}@.timer"
  985. _service_name="${1}@$_service_user.service"
  986. _timer_name="${1}@$_service_user.timer"
  987. _user_specifier="User=%I"
  988. fi
  989. }
  990. #######################################
  991. # SERVICES
  992. #######################################
  993. #######################################
  994. # Starts and enables (at startup) a JRiver Media Center service
  995. # Arguments:
  996. # Passes arguments as startup options to /usr/bin/mediacenter26
  997. # Requires:
  998. # XAUTHORITY
  999. #######################################
  1000. _service_jriver-mediacenter() {
  1001. debug "Running: ${FUNCNAME[0]}"
  1002. _bash_cmd "cat <<-EOF > $_service_fname
  1003. [Unit]
  1004. Description=JRiver Media Center $_mversion
  1005. After=graphical.target
  1006. [Service]
  1007. $_user_specifier
  1008. Type=simple
  1009. Environment=DISPLAY=$_display
  1010. Environment=XAUTHORITY=$XAUTHORITY
  1011. ExecStart=/usr/bin/mediacenter$_mversion $*
  1012. Restart=always
  1013. RestartSec=10
  1014. KillSignal=SIGHUP
  1015. TimeoutStopSec=30
  1016. [Install]
  1017. WantedBy=graphical.target
  1018. EOF"
  1019. _systemctl_reload && \
  1020. _systemctl_start "$_service_name" && \
  1021. _systemctl_enable "$_service_name" && \
  1022. _openFirewall "jriver"
  1023. }
  1024. #######################################
  1025. # Starts and enables (at startup) a JRiver Media Server service
  1026. #######################################
  1027. _service_jriver-mediaserver() {
  1028. debug "Running: ${FUNCNAME[0]}"
  1029. _service_jriver-mediacenter "/MediaServer"
  1030. }
  1031. #######################################
  1032. # Starts and enables (at startup) JRiver Media Center in a new Xvnc session
  1033. #######################################
  1034. _service_jriver-xvnc() {
  1035. debug "Running: ${FUNCNAME[0]}"
  1036. _installPackage tigervnc-server
  1037. _setVNCPass
  1038. local _port=$(( _next_displaynum + 5900 ))
  1039. if [[ -n $_novncauth ]]; then
  1040. _exec_start_cmd="/usr/bin/vncserver $_next_display -geometry 1440x900 -alwaysshared -name jriver$_next_display -SecurityTypes None -autokill -xstartup /usr/bin/mediacenter$_mversion"
  1041. else
  1042. _exec_start_cmd="/usr/bin/vncserver $_next_display -geometry 1440x900 -alwaysshared -rfbauth $HOME/.vnc/jrmc_passwd -autokill -xstartup /usr/bin/mediacenter$_mversion"
  1043. fi
  1044. _bash_cmd "cat <<-EOF > $_service_fname
  1045. [Unit]
  1046. Description=Remote desktop service (VNC)
  1047. After=syslog.target network.target
  1048. [Service]
  1049. Type=simple
  1050. $_user_specifier
  1051. ExecStartPre=/bin/sh -c '/usr/bin/vncserver -kill $_next_display > /dev/null 2>&1 || :'
  1052. ExecStart=$_exec_start_cmd
  1053. ExecStop=/usr/bin/vncserver -kill $_next_display
  1054. Restart=always
  1055. [Install]
  1056. WantedBy=multi-user.target
  1057. EOF"
  1058. _systemctl_reload && \
  1059. _systemctl_start "$_service_name" && \
  1060. _systemctl_enable "$_service_name" && \
  1061. echo "Xvnc running on localhost:$_port" && \
  1062. _openFirewall "jriver-xvnc" && \
  1063. _openFirewall "jriver"
  1064. }
  1065. #######################################
  1066. # Starts and enables (at startup) JRiver Media Server and x11vnc sharing the local desktop
  1067. #######################################
  1068. _service_jriver-x11vnc() {
  1069. debug "Running: ${FUNCNAME[0]}"
  1070. _installPackage x11vnc
  1071. _setX11VNCPass
  1072. local _port=$(( _displaynum + 5900 ))
  1073. # Get current desktop resolution
  1074. # TODO: may need to break this out into its own function and get smarter at identifying multi-monitors
  1075. _getResolution() {
  1076. debug "Running: ${FUNCNAME[0]}"
  1077. _installPackage xorg-x11-utils
  1078. _res=$(xdpyinfo | grep dimensions | awk '{print $2}')
  1079. }
  1080. _getResolution
  1081. if [[ -n $_novncauth ]]; then
  1082. _exec_start_cmd="/usr/bin/x11vnc -display $_display -noscr -geometry $_res -auth guess -forever -bg -nopw"
  1083. else
  1084. _exec_start_cmd="/usr/bin/x11vnc -display $_display -noscr -geometry $_res -auth guess -forever -bg -rfbauth $HOME/.vnc/jrmc_passwd"
  1085. fi
  1086. _bash_cmd "cat <<-EOF > $_service_fname
  1087. [Unit]
  1088. Description=x11vnc
  1089. After=multi.service
  1090. [Service]
  1091. $_user_specifier
  1092. Type=forking
  1093. Environment=DISPLAY=$_display
  1094. ExecStart=$_exec_start_cmd
  1095. Restart=always
  1096. RestartSec=10
  1097. [Install]
  1098. WantedBy=multi-user.target
  1099. EOF"
  1100. _systemctl_reload && \
  1101. _systemctl_start "$_service_name" && \
  1102. _systemctl_enable "$_service_name" && \
  1103. echo "x11vnc running on localhost:$_port" && \
  1104. _openFirewall "jriver-x11vnc"
  1105. }
  1106. #######################################
  1107. # Starts and enables (at startup) an hourly service to build the latest version of JRiver Media
  1108. # Center RPM from the source DEB and create/update an RPM repository
  1109. #######################################
  1110. _service_jriver-createrepo() {
  1111. debug "Running: ${FUNCNAME[0]}"
  1112. _bash_cmd "cat <<-EOF > $_service_fname
  1113. [Unit]
  1114. Description=Builds JRiver Media Center RPM file, moves it to the repo dir, and runs createrepo
  1115. [Service]
  1116. $_user_specifier
  1117. ExecStart=$_basedir/installJRMC --outputdir $_outputdir --createrepo --createrepo-webroot $_createrepo_webroot --createrepo-user $_createrepo_user
  1118. [Install]
  1119. WantedBy=default.target
  1120. EOF"
  1121. _bash_cmd "cat <<-EOF > $_timer_fname
  1122. [Unit]
  1123. Description=Run JRiver MC rpmbuild hourly
  1124. [Timer]
  1125. OnCalendar=hourly
  1126. Persistent=true
  1127. [Install]
  1128. WantedBy=timers.target
  1129. EOF"
  1130. _systemctl_reload && \
  1131. _systemctl_start "$_timer_name" && \
  1132. _systemctl_enable "$_timer_name"
  1133. }
  1134. #######################################
  1135. # CONTAINERS
  1136. #######################################
  1137. _containerCreaterepo() {
  1138. :
  1139. }
  1140. _containerVNC() {
  1141. :
  1142. }
  1143. _containerMC() {
  1144. :
  1145. }
  1146. #######################################
  1147. # Complete uninstall
  1148. #######################################
  1149. _uninstall() {
  1150. debug "Running: ${FUNCNAME[0]}"
  1151. read -r -p "Do you really want to uninstall JRiver Media Center? [y/N] " _response
  1152. _response=${_response,,} # tolower
  1153. [[ ! "$_response" =~ ^(yes|y)$ ]] && echo "Cancelling uninstall..." && exit 0
  1154. # Uninstall services
  1155. echo "Stopping and removing all associated Media Center services"
  1156. for _service in "${_available_services[@]}"; do
  1157. _servicePrep "$_service"
  1158. _systemctl_disable "$_service_name"
  1159. _systemctl_disable "$_timer_name"
  1160. [[ -f "$_service_fname" ]] && _rm_cmd "$_service_fname"
  1161. [[ -f "$_timer_fname" ]] && _rm_cmd "$_timer_fname"
  1162. done
  1163. echo "Removing repo files"
  1164. [[ -f "/etc/yum.repos.d/jriver.repo" ]] \
  1165. && _rm_cmd "/etc/yum.repos.d/jriver.repo"
  1166. [[ -f "/etc/apt/sources.list.d/jriver.list" ]] \
  1167. && _rm_cmd "/etc/apt/sources.list.d/jriver.list"
  1168. echo "Removing firewall rules"
  1169. if [[ -x $(command -v firewall-cmd) ]]; then
  1170. _firewall_cmd --permanent --remove-service=jriver
  1171. _firewall_cmd --permanent --delete-service=jriver
  1172. _firewall_cmd --reload
  1173. elif [[ -x $(command -v ufw) ]]; then
  1174. _firewall_cmd delete allow jriver
  1175. [[ -f "/etc/ufw/applications.d/jriver" ]] \
  1176. && _rm_cmd /etc/ufw/applications.d/jriver
  1177. fi
  1178. echo "Uninstalling Media Center"
  1179. if [[ "$ID" =~ ^(fedora|centos)$ ]]; then
  1180. _pkg_remove MediaCenter
  1181. elif [[ "$ID" =~ ^(ubuntu|debian)$ ]]; then
  1182. _pkg_remove "mediacenter$_mversion"
  1183. fi
  1184. echo "JRiver Media Center has been completely uninstalled"
  1185. echo "If you wish to remove your library files: rm -rf $HOME/.jriver"
  1186. echo "If you wish to remove your rpmbuild output files: rm -rf $_outputdir"
  1187. }
  1188. __main() {
  1189. # Parse input
  1190. _parseInput "$@"
  1191. # Sanity checks
  1192. _sanityChecks
  1193. # Set user variables
  1194. _setUser
  1195. # Build some OS-specific commands based on the selected OS
  1196. _buildCommands
  1197. # Install MC using package manager
  1198. if [[ -n $_repoinstall ]]; then
  1199. _installPackage rpmfusion-free-release epel-release
  1200. _installMCFromRepo
  1201. _symlinkCerts
  1202. _restoreLicense
  1203. _openFirewall "jriver"
  1204. fi
  1205. # Set version to install/uninstall
  1206. _setVersion
  1207. # Uninstall and exit
  1208. if [[ -n $_uninstall ]]; then
  1209. _uninstall
  1210. exit $?
  1211. fi
  1212. # Build RPM from source DEB
  1213. if [[ -n $_rpmbuild ]]; then
  1214. _installPackage epel-release
  1215. _acquireDeb
  1216. _buildRPM
  1217. fi
  1218. # Run createrepo
  1219. if [[ -n $_createrepo ]]; then
  1220. _runCreaterepo "$_mcrpm"
  1221. fi
  1222. # Install the rpm
  1223. if [[ -n $_rpminstall ]]; then
  1224. if [[ "$ID" =~ ^(fedora|centos)$ ]]; then
  1225. _installPackage rpmfusion-free-release epel-release
  1226. _installPackage --noquery "$_mcrpm"
  1227. _symlinkCerts
  1228. _restoreLicense
  1229. _openFirewall "jriver"
  1230. fi
  1231. fi
  1232. # Install services
  1233. _setDisplay
  1234. for _service in "${_services[@]}"; do
  1235. _servicePrep "$_service"
  1236. "_service_$_service"
  1237. done
  1238. # Install containers
  1239. for _container in "${_containers[@]}"; do
  1240. "_container_$_container"
  1241. done
  1242. }
  1243. }
  1244. # Allow this file to be executed directly if not being sourced
  1245. if [[ "${BASH_SOURCE[0]}" == "${0}" ]]; then
  1246. _basedir=$(dirname "$(readlink -f "$0")")
  1247. installJRMC
  1248. __main "$@"
  1249. fi