installJRMC 47 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497
  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 support -- do not own one so difficult to test
  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.5"
  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() {
  179. echo "Error: $*" >&2
  180. }
  181. #######################################
  182. # Call this at the beginning of every function in order to track
  183. #######################################
  184. debug() {
  185. [[ -n $_debug ]] && echo "Debug: $*"
  186. }
  187. #######################################
  188. # Prepend this to any command that you wish to execute with sudo
  189. # Requires:
  190. # _exec_user
  191. #######################################
  192. _ifSudo() {
  193. if [[ "$_exec_user" != "root" ]]; then
  194. sudo "$@"
  195. else
  196. "$@"
  197. fi
  198. }
  199. #######################################
  200. # Sources /etc/os-release so we know which OS we're running on
  201. # Used in: _buildCommands()
  202. #######################################
  203. _getOS() {
  204. debug "Running: ${FUNCNAME[0]}"
  205. if [[ -e "/etc/os-release" ]]; then
  206. source "/etc/os-release"
  207. else
  208. err "No /etc/os-release found"
  209. err "Your OS is unsupported"
  210. _printHelpAndExit 1
  211. fi
  212. [[ -n $_debug ]] && echo "Platform: $ID $VERSION_ID"
  213. }
  214. #######################################
  215. # Creates some OS-specific functions to query, install, and remove packages and edit
  216. # firewalls, run bash, remove and copy files, etc.
  217. # Requires:
  218. # ID
  219. # _createrepo_user
  220. # _createrepo_webroot
  221. # Globals:
  222. # _bash_cmd
  223. # _rm_cmd
  224. # _cp_cmd
  225. # _mkdir_cmd
  226. # _ln_cmd
  227. # _createrepo_cmd
  228. # _pkg_install
  229. # _pkg_reinstall
  230. # _pkg_install_nogpg
  231. # _pkg_remove
  232. # _pkg_update
  233. # _pkg_query
  234. # _firewall_cmd
  235. # _systemctl_reload
  236. # _systemctl_enable
  237. # _systemctl_disable
  238. #######################################
  239. _buildCommands() {
  240. # Detect OS
  241. _getOS
  242. debug "Running: ${FUNCNAME[0]}"
  243. # Agnostic commands
  244. _bash_cmd(){ _ifSudo bash -c "$@"; }
  245. _rm_cmd(){ _ifSudo rm -rf "$@"; }
  246. _cp_cmd(){ _ifSudo cp -n "$@"; }
  247. _mkdir_cmd(){ _ifSudo mkdir -p "$@"; }
  248. _ln_cmd(){ _ifSudo ln -s "$@"; }
  249. _systemctl_reload(){ _ifSudo systemctl daemon-reload; }
  250. _systemctl_start(){
  251. echo "Starting $*"
  252. if ! _ifSudo systemctl start "$@"; then
  253. err "Could not start $*"
  254. err "Check service status using \"sudo systemctl status $*\""
  255. return 1
  256. fi
  257. }
  258. _systemctl_enable(){ _ifSudo systemctl enable "$@"; }
  259. _systemctl_disable(){ _ifSudo systemctl disable --now "$@"; }
  260. # OS-specific commands
  261. if [[ "$ID" =~ ^(fedora|centos)$ ]]; then
  262. _pkg_install(){ _ifSudo dnf install -y "$@"; }
  263. _pkg_reinstall(){ _ifSudo dnf reinstall -y "$@"; }
  264. _pkg_install_nogpg(){ _ifSudo dnf install --nogpgcheck -y "$@"; }
  265. _pkg_remove(){ _ifSudo dnf remove -y "$@"; }
  266. _pkg_update(){ _ifSudo dnf makecache; }
  267. _pkg_query(){ _ifSudo rpm -q "$@"; }
  268. _firewall_cmd(){ _ifSudo firewall-cmd "$@"; }
  269. elif [[ "$ID" =~ ^(ubuntu|debian)$ ]]; then
  270. _pkg_install(){ _ifSudo apt-get install -y -q0 "$@"; }
  271. _pkg_reinstall(){ _ifSudo apt-get reinstall -y -q0 "$@"; }
  272. _pkg_install_nogpg(){ _ifSudo apt-get install -y -q0 "$@"; }
  273. _pkg_remove(){ _ifSudo apt-get remove -y -q0 "$@"; }
  274. _pkg_update(){ _ifSudo apt-get update -y -q0; }
  275. _pkg_query(){ _ifSudo dpkg -s "$@"; }
  276. _firewall_cmd(){ _ifSudo ufw "$@"; }
  277. fi
  278. # Some additional commands specifically for createrepo (primarily to handle user rights)
  279. # Could also go in runCreaterepo() but let's leave it here for now
  280. if [[ $_createrepo_user != "root" ]]; then
  281. if [[ -d "$_createrepo_webroot/repodata" ]]; then
  282. _createrepo_cmd(){ sudo -u "$_createrepo_user" createrepo -q --update "$@"; }
  283. else
  284. _createrepo_cmd(){ sudo -u "$_createrepo_user" createrepo -q "$@"; }
  285. fi
  286. _cr_mkdir_cmd(){ sudo -u "$_createrepo_user" mkdir -p "$@"; }
  287. _cr_cp_cmd(){ sudo -u "$_createrepo_user" cp -n "$@"; }
  288. else
  289. if [[ -d "$_createrepo_webroot/repodata" ]]; then
  290. _createrepo_cmd(){ createrepo -q --update "$@"; }
  291. else
  292. _createrepo_cmd(){ createrepo -q "$@"; }
  293. fi
  294. fi
  295. }
  296. #######################################
  297. # Sets default user variables
  298. # Requires:
  299. # _exec_user
  300. # Globals
  301. # _service_user
  302. # _createrepo_user
  303. #######################################
  304. _setUser() {
  305. [[ -z $_service_user ]] && _service_user="$_exec_user"
  306. [[ -z $_createrepo_user ]] && _createrepo_user="$_exec_user"
  307. }
  308. #######################################
  309. # Installs a package using the system package manager
  310. # Arguments:
  311. # One or more package names
  312. # Options:
  313. # --noquery, -n: Do not query the package state (useful if installing a local RPM)
  314. # Returns:
  315. # Will exit 1 if failed
  316. #######################################
  317. _installPackage() {
  318. debug "Running: ${FUNCNAME[0]}" "$@"
  319. if _input=$(getopt -o +n -l noquery -- "$@"); then
  320. eval set -- "$_input"
  321. while true; do
  322. case "$1" in
  323. --noquery|-n)
  324. local _noquery="true"
  325. ;;
  326. --)
  327. shift
  328. break
  329. ;;
  330. esac
  331. shift
  332. done
  333. else
  334. err "Incorrect options provided"
  335. _printHelpAndExit 1
  336. fi
  337. # We will add packages to this array if their command is not available
  338. local -a _pkg_array
  339. local -a _url_pkg_array
  340. # parse arguments (packages)
  341. for _pkg in "$@"; do
  342. # Clean up package name and handle OS-specific tweaks
  343. _packageQuirks "$_pkg"
  344. # Insert the package name to test if already installed
  345. if [[ "$_pkg" != "" ]]; then
  346. if [[ -n $_noquery ]] || ! _pkg_query "$_pkg" > /dev/null 2>&1; then
  347. if [[ -n $_url_pkg ]]; then
  348. _url_pkg_array+=("$_url_pkg")
  349. else
  350. _pkg_array+=("$_pkg")
  351. fi
  352. fi
  353. fi
  354. done
  355. # Install from package name (with gpg check)
  356. if [[ ${#_pkg_array[@]} -ge 1 ]]; then
  357. echo "Installing:" "${_pkg_array[@]}"
  358. if [[ -n $_debug ]]; then
  359. if ! _pkg_install "${_pkg_array[@]}"; then
  360. err "Failed to install package"
  361. exit 1
  362. fi
  363. elif ! _pkg_install "${_pkg_array[@]}" > /dev/null 2>&1; then
  364. err "Failed to install package."
  365. _printHelpAndExit 1
  366. fi
  367. fi
  368. # Install from package url (without gpg check)
  369. if [[ ${#_url_pkg_array[@]} -ge 1 ]]; then
  370. echo "Installing:" "${_url_pkg_array[@]}"
  371. if [[ -n $_debug ]]; then
  372. if ! _pkg_install_nogpg "${_url_pkg_array[@]}"; then
  373. err "Failed to install required package from url"
  374. exit 1
  375. fi
  376. elif ! _pkg_install_nogpg "${_url_pkg_array[@]}" > /dev/null 2>&1; then
  377. err "Failed to install required package from url"
  378. _printHelpAndExit 1
  379. fi
  380. fi
  381. }
  382. #######################################
  383. # Handles OS-specific package name tweaks and source urls
  384. # Arguments:
  385. # A package name
  386. # Globals:
  387. # _pkg
  388. # _url_pkg
  389. #######################################
  390. _packageQuirks() {
  391. debug "Running: ${FUNCNAME[0]}" "$@"
  392. unset _url_pkg
  393. if [[ "$1" == "xorg-x11-utils" && "$ID" =~ ^(ubuntu|debian)$ ]]; then
  394. _pkg="x11-utils"
  395. elif [[ "$1" == "rpm-build" && "$ID" =~ ^(ubuntu|debian)$ ]]; then
  396. _pkg="rpm"
  397. elif [[ "$1" == "createrepo_c" && "$ID" =~ ^(ubuntu|debian)$ ]]; then
  398. _pkg="createrepo"
  399. elif [[ "$1" == "rpmfusion-free-release" ]]; then
  400. if [[ "$ID" == "fedora" ]]; then
  401. # As of MC26 and Fedora 32 I don't believe that the rpmfusion repo is necessary
  402. #_url_pkg="https://download1.rpmfusion.org/free/$ID/rpmfusion-free-release-$VERSION_ID.noarch.rpm"
  403. #_pkg="$1"
  404. _pkg=""
  405. elif [[ "$ID" == "centos" ]]; then
  406. _url_pkg="https://download1.rpmfusion.org/free/el/rpmfusion-free-release-$VERSION_ID.noarch.rpm"
  407. _pkg="$1"
  408. else
  409. _pkg=""
  410. fi
  411. elif [[ "$1" == "epel-release" && "$ID" != "centos" ]]; then
  412. _pkg=""
  413. elif [[ "$1" == "tigervnc-server" && "$ID" =~ ^(ubuntu|debian)$ ]]; then
  414. _pkg="tigervnc-standalone-server"
  415. else
  416. _pkg="$1"
  417. fi
  418. }
  419. #######################################
  420. # Get our MC working version from input argument or scraping Interact
  421. # Requires:
  422. # _boardurl
  423. # _installPackage
  424. # Globals:
  425. # _mcversion (i.e. "26.0.12")
  426. # _mversion (i.e. "26")
  427. #######################################
  428. _setVersion() {
  429. debug "Running: ${FUNCNAME[0]}"
  430. if [[ -z "$_mcversion" ]]; then
  431. _installPackage wget
  432. # Get latest version from Interact
  433. echo "Scraping latest MC version number from Interact..."
  434. if ! _mcversion=$(wget -qO- "$_boardurl" | grep -o "[0-9][0-9]\.[0-9]\.[0-9]\+" | head -n 1); then
  435. err "MC version could not be scraped. Please specify a version manually using --mcversion or check your --boardurl"
  436. _printHelpAndExit 1
  437. fi
  438. fi
  439. echo "Using version: $_mcversion"
  440. # Extract major version number
  441. _mversion="${_mcversion%%.*}"
  442. # Saving this substituion in case it's needed in the future
  443. #_variation="${_mcversion##*.}"
  444. }
  445. #######################################
  446. # Check if an argument exists in an array
  447. # Arguments:
  448. # The first argument is the string to match to the following arguments
  449. # Example:
  450. # _inArray "zebra" "${animals_arr[@]}"
  451. # Returns:
  452. # 0 if a match is found, 1 if not
  453. #######################################
  454. _inArray() {
  455. local _match="$1"
  456. shift
  457. local _item
  458. for _item in "$@"; do
  459. [[ "$_item" == "$_match" ]] && return 0
  460. done
  461. return 1
  462. }
  463. #######################################
  464. # Clean up nonsensical user input
  465. # Notes:
  466. # I try to keep this function as short as possible and provide better input options and
  467. # sensible defaults than workarounds
  468. # Test:
  469. # _installJRMC should run sucessfully even without running _sanityChecks()
  470. #######################################
  471. _sanityChecks() {
  472. debug "Running: ${FUNCNAME[0]}"
  473. # Check for bad service name
  474. _checkServices() {
  475. debug "Running: ${FUNCNAME[0]}"
  476. for _service in "${_services[@]}"; do
  477. if ! _inArray "$_service" "${_available_services[@]}"; then
  478. echo "Incorrect service type provided"
  479. _printHelpAndExit 1
  480. fi
  481. done
  482. }
  483. _checkMCInstalled() {
  484. debug "Running: ${FUNCNAME[0]}"
  485. for _service in "${_services[@]}"; do
  486. if [[ "$_service" =~ ^(jriver-mediacenter|jriver-mediaserver|jriver-xvnc-mediacenter|jriver-x11vnc)$ ]] \
  487. && [[ -z $_repoinstall && -z $_rpminstall ]] \
  488. && [[ ! -x $(command -v "mediacenter$_mversion") ]]; then
  489. err "You are attempting to install a service that depends on JRiver Media Center"
  490. err "without installing JRiver Media Center"
  491. err "Automatically enabling --repo-install"
  492. _repoinstall="true"
  493. fi
  494. done
  495. }
  496. _checkUser() {
  497. debug "Running: ${FUNCNAME[0]}"
  498. if [[ "$_exec_user" == "root" && -z "$_service_user" && "${_services[*]}" ]]; then
  499. err "Attempting to install services as the root user"
  500. err "This is not recommended and we are exiting now to prevent permission hell"
  501. err "You can override this safety check by manually specifying --user root"
  502. return 1
  503. fi
  504. }
  505. # Enable/disable sanity checks
  506. if _checkServices && _checkMCInstalled && _checkUser; then
  507. debug "Sanity checks passed!"
  508. return 0
  509. else
  510. err "Sanity checks failed!"
  511. exit 1
  512. fi
  513. }
  514. #######################################
  515. # Installs JRiver Media Center from a repository
  516. # Returns:
  517. # 0 if JRiver Media Center installed sucessfully
  518. #######################################
  519. _installMCFromRepo() {
  520. debug "Running: ${FUNCNAME[0]}"
  521. echo "Installing JRiver Media Center from repo..."
  522. local _mcpkg
  523. # Add repository files
  524. _addRepo() {
  525. # Add repositories to OS-specific package managers
  526. if [[ "$ID" =~ ^(fedora|centos)$ ]]; then
  527. _bash_cmd 'cat <<-EOF > /etc/yum.repos.d/jriver.repo
  528. [jriver]
  529. name=JRiver Media Center repo by BryanC
  530. baseurl=https://repos.bryanroessler.com/jriver
  531. gpgcheck=0
  532. EOF'
  533. elif [[ "$ID" =~ ^(ubuntu|debian)$ ]]; then
  534. wget -q "http://dist.jriver.com/mediacenter@jriver.com.gpg.key" -O- | _ifSudo apt-key add - > /dev/null 2>&1
  535. _bash_cmd 'cat <<-EOF > /etc/apt/sources.list.d/jriver.list
  536. deb [arch=amd64,i386,armhf] http://dist.jriver.com/latest/mediacenter/ jessie main
  537. EOF'
  538. fi
  539. }
  540. _addRepo
  541. # Update package list
  542. [[ -n $_debug ]] && echo "Updating package list"
  543. if ! _pkg_update > /dev/null 2>&1; then
  544. err "Package update failed!"
  545. exit 1
  546. fi
  547. # If user specifies a version, use that
  548. if [[ -n $_mcversion ]]; then
  549. _setVersion
  550. local _specific_version="true"
  551. fi
  552. local _mcpkg
  553. # Fedora/CentOS use a universal package name -- easy
  554. if [[ "$ID" =~ ^(fedora|centos)$ ]]; then
  555. _mcpkg="MediaCenter"
  556. fi
  557. # Ubuntu/Debian incorporate the mversion into the package name -- more fun!
  558. if [[ "$ID" =~ ^(ubuntu|debian)$ ]]; then
  559. if [[ -z $_mversion ]]; then
  560. # Try parsing the latest mversion from the repo
  561. if _mcpkg=$(apt-get install mediacenter?? -s -q0 | grep "selecting" | tail -1| awk '{print $3}'); then
  562. _mcpkg="${_mcpkg%\'}"
  563. _mcpkg="${_mcpkg#\'}"
  564. # Scrape Interact
  565. else
  566. _setVersion
  567. _mcpkg="mediacenter$_mversion"
  568. fi
  569. else
  570. _mcpkg="mediacenter$_mversion"
  571. fi
  572. # Sanity check
  573. if [[ ! "$_mcpkg" =~ ^mediacenter[0-9][0-9]$ ]]; then
  574. err "Could not parse MC package name"
  575. exit 1
  576. fi
  577. fi
  578. if [[ -n $_specific_version ]]; then
  579. if [[ "$ID" =~ ^(fedora|centos)$ ]]; then
  580. if [[ -n $_debug ]]; then
  581. _installPackage "$_mcpkg-$_mcversion"
  582. else
  583. _installPackage "$_mcpkg-$_mcversion" > /dev/null 2>&1
  584. fi
  585. elif [[ "$ID" =~ ^(ubuntu|debian)$ ]]; then
  586. if [[ -n $_debug ]]; then
  587. _installPackage "$_mcpkg=$_mcversion"
  588. else
  589. _installPackage "$_mcpkg=$_mcversion" > /dev/null 2>&1
  590. fi
  591. fi
  592. else
  593. if [[ -n $_debug ]]; then
  594. _installPackage "$_mcpkg"
  595. else
  596. _installPackage "$_mcpkg" > /dev/null 2>&1
  597. fi
  598. fi
  599. # shellcheck disable=SC2181
  600. # Rationale: More compact to check this once
  601. if [[ $? -eq 0 ]]; then
  602. echo "JRiver Media Center installed successfully"
  603. return 0
  604. else
  605. err "JRiver Media Center installation failed"
  606. exit 1
  607. fi
  608. }
  609. #######################################
  610. # Acquire the source DEB package from JRiver's servers
  611. # Returns:
  612. # 0 if DEB file downloaded successfully, 1 if failed
  613. #######################################
  614. _acquireDeb() {
  615. debug "Running: ${FUNCNAME[0]}"
  616. local _debfilename="$_outputdir/SOURCES/MediaCenter-${_mcversion}-amd64.deb"
  617. # If necessary, create SOURCES dir
  618. [[ ! -d "$_outputdir/SOURCES" ]] && mkdir -p "$_outputdir/SOURCES"
  619. # If deb file already exists, skip download
  620. if [[ -f "$_debfilename" ]]; then
  621. echo "Using local DEB file: $_debfilename"
  622. # Else check beta repo
  623. elif [[ -n $_betapass ]]; then
  624. if wget -q -O "$_debfilename" \
  625. "https://files.jriver.com/mediacenter/channels/v${_mversion}/beta/${_betapass}/MediaCenter-${_mcversion}-amd64.deb"; then
  626. true
  627. fi
  628. # Else check test repo
  629. elif wget -q -O "$_debfilename" \
  630. "https://files.jriver.com/mediacenter/test/MediaCenter-${_mcversion}-amd64.deb"; then
  631. true
  632. # Else check latest repo
  633. elif wget -q -O "$_debfilename" \
  634. "https://files.jriver.com/mediacenter/channels/v${_mversion}/latest/MediaCenter-${_mcversion}-amd64.deb"; then
  635. true
  636. else
  637. err "Cannot find DEB file. Exiting..."
  638. exit 1
  639. fi
  640. if [[ ! -f "$_debfilename" ]]; then
  641. err "Downloaded DEB file missing or corrupted, exiting..."
  642. exit 1
  643. fi
  644. }
  645. #######################################
  646. # Creates a SPEC file and builds the RPM from the source DEB using rpmbuild
  647. # Requires:
  648. # _outputdir
  649. # ID
  650. # _mcversion
  651. # _mversion
  652. # _installPackage
  653. # Globals:
  654. # _mcrpm
  655. # Returns:
  656. # 0 if rpmbuild is successful, 1 if not
  657. #######################################
  658. _buildRPM() {
  659. debug "Running: ${FUNCNAME[0]}"
  660. # install build dependencies
  661. _installPackage wget dpkg rpm-build
  662. # If necessary, make build directories
  663. [[ ! -d "$_outputdir/SPECS" ]] && mkdir -p "$_outputdir/SPECS"
  664. # rpmbuild uses rpm to check for build dependencies
  665. # this will fail on non-rpm distros
  666. if [[ "$ID" =~ ^(fedora|centos)$ ]]; then
  667. local _build_requires=$'BuildRequires: rpm >= 4.11.0\nBuildRequires: dpkg'
  668. else
  669. local _build_requires=''
  670. fi
  671. if [[ "$ID" == "fedora" && -n $_rpminstall ]]; then
  672. # TODO: find out why this is required since it's not easily available on CentOS
  673. local _requires='Requires: pangox-compat >= 0.0.2'
  674. fi
  675. # Create spec file
  676. bash -c "cat <<EOF > $_outputdir/SPECS/mediacenter.spec
  677. Name: MediaCenter
  678. Version: $_mcversion
  679. Release: 1
  680. Summary: JRiver Media Center
  681. Group: Applications/Media
  682. Source0: http://files.jriver.com/mediacenter/channels/v$_mversion/latest/MediaCenter-$_mcversion-amd64.deb
  683. $_build_requires
  684. BuildArch: x86_64
  685. %define _rpmfilename %%{ARCH}/%%{NAME}-%%{version}.%%{ARCH}.rpm
  686. AutoReq: 0
  687. Requires: glibc >= 2.19
  688. Requires: alsa-lib >= 1.0.28
  689. Requires: libuuid >= 2.25
  690. Requires: libX11 >= 1.6
  691. Requires: libX11-common >= 1.6
  692. Requires: libXext >= 1.3
  693. Requires: libxcb >= 1.1
  694. Requires: libXdmcp >= 1.1
  695. Requires: libstdc++ >= 4.9
  696. Requires: gtk3 >= 3.14
  697. Requires: mesa-libGL
  698. Requires: libglvnd-glx
  699. Requires: pango >= 1.36
  700. $_requires
  701. Requires: libXScrnSaver
  702. Requires: xdg-utils
  703. Requires: libgomp >= 4.9
  704. Requires: gstreamer1 >= 1.4.4
  705. Requires: gstreamer1-plugins-base >= 1.4.4
  706. Requires: nss >= 3.26
  707. Requires: nspr >= 4.12
  708. Requires: ca-certificates
  709. Requires: python3
  710. Recommends: vorbis-tools >= 1.4.0
  711. Provides: mediacenter$_mversion
  712. License: Copyright 1998-2020, JRiver, Inc. All rights reserved. Protected by U.S. patents #7076468 and #7062468
  713. URL: http://www.jriver.com/
  714. %description
  715. Media Center is more than a world class player.
  716. %global __os_install_post %{nil}
  717. %prep
  718. %build
  719. %install
  720. dpkg -x %{S:0} %{buildroot}
  721. %post -p /sbin/ldconfig
  722. %postun -p /sbin/ldconfig
  723. %files
  724. %{_bindir}/mediacenter$_mversion
  725. %{_libdir}/jriver
  726. %{_datadir}
  727. /etc/security/limits.d/*
  728. EOF"
  729. declare -g _mcrpm="$_outputdir/RPMS/x86_64/MediaCenter-$_mcversion.x86_64.rpm"
  730. # skip rebuilding the rpm if it already exists
  731. if [[ -f "$_mcrpm" ]]; then
  732. echo "$_mcrpm already exists. Skipping build step..."
  733. return 0 # this is fine
  734. else
  735. # Run rpmbuild
  736. echo "Building version $_mcversion, please wait..."
  737. if [[ -n $_debug ]]; then
  738. rpmbuild --define="%_topdir $_outputdir" --define="%_libdir /usr/lib" -bb "$_outputdir/SPECS/mediacenter.spec"
  739. else
  740. rpmbuild --quiet --define="%_topdir $_outputdir" --define="%_libdir /usr/lib" -bb "$_outputdir/SPECS/mediacenter.spec" > /dev/null 2>&1
  741. fi
  742. # Check return code
  743. # shellcheck disable=SC2181
  744. if [[ $? -ne 0 || ! -f "$_mcrpm" ]]; then
  745. err "Build failed. Exiting..."
  746. exit 1
  747. else
  748. echo "Build successful. The RPM file is located at: $_mcrpm"
  749. fi
  750. fi
  751. }
  752. #######################################
  753. # Copy the RPM to createrepo-webroot and runs createrepo as the createrepo-user
  754. # Arguments:
  755. # Requires one argument, the path to the RPM file (typically _mcrpm)
  756. # Requires:
  757. # _createrepo_webroot
  758. # Returns:
  759. # 0 if createrepo is successful, 1 if not
  760. #######################################
  761. _runCreaterepo() {
  762. debug "Running: ${FUNCNAME[0]}"
  763. _installPackage createrepo_c
  764. local _rpmfile="$1"
  765. # If the webroot does not exist, create it
  766. if [[ ! -d "$_createrepo_webroot" ]]; then
  767. if ! _cr_mkdir_cmd "$_createrepo_webroot"; then
  768. err "Could not create the createrepo-webroot path!"
  769. err "Make sure that the createrepo-webroot is writeable by createrepo-user"
  770. return 1
  771. fi
  772. fi
  773. # Copy built rpms to webroot
  774. if ! _cr_cp_cmd "$_rpmfile" "$_createrepo_webroot"; then
  775. err "Could not copy the RPM to the createrepo-webroot path"
  776. err "Make sure that the createrepo-webroot path is writeable by createrepo-user"
  777. return 1
  778. fi
  779. # Run createrepo
  780. if _createrepo_cmd "$_createrepo_webroot"; then
  781. echo "Successfully updated repo"
  782. return 0
  783. else
  784. err "Update repo failed"
  785. return 1
  786. fi
  787. }
  788. #######################################
  789. # Symlink certificates where JRiver Media Center expects them to be on Fedora/CentOS
  790. # them on Debian/Ubuntu
  791. # Returns:
  792. # 0 if symlinking is unecessary or successful, 1 if not
  793. #######################################
  794. _symlinkCerts() {
  795. debug "Running: ${FUNCNAME[0]}"
  796. if [[ ! -f /etc/ssl/certs/ca-certificates.crt && \
  797. -f /etc/pki/ca-trust/extracted/pem/tls-ca-bundle.pem ]]; then
  798. if ! _ln_cmd /etc/pki/ca-trust/extracted/pem/tls-ca-bundle.pem /etc/ssl/certs/ca-certificates.crt; then
  799. err "Symlinking certificates failed"
  800. return 1
  801. fi
  802. fi
  803. }
  804. #######################################
  805. # Automatically restore the mjr license file if it is found next to installJRMC or _restorefile
  806. # is set
  807. # Requires:
  808. # _restorefile OR _basedir
  809. # _mversion
  810. # Returns:
  811. # 0 if license restored successfully or skipped, 1 if unsuccessful
  812. #######################################
  813. _restoreLicense() {
  814. debug "Running: ${FUNCNAME[0]}"
  815. local _mjr
  816. # Allow user to drop an mjr file next to installJRMC
  817. if [[ -z $_restorefile ]]; then
  818. for _mjr in "$_basedir"/*.mjr; do
  819. [[ $_mjr -nt $_restorefile ]] && _restorefile="$_mjr"
  820. done
  821. fi
  822. # Restore license
  823. if [[ -f "$_restorefile" ]]; then
  824. if ! "mediacenter${_mversion}" /RestoreFromFile "$_restorefile"; then
  825. err "Automatic license restore failed"
  826. return 1
  827. fi
  828. fi
  829. }
  830. #######################################
  831. # Opens ports using the system firewall tool
  832. # Arguments
  833. # Takes one argument, the pre-specified name of the service to enable
  834. # Requires:
  835. # ID
  836. # _bash_cmd
  837. # _firewall_cmd
  838. # _port
  839. # Returns:
  840. # 0 if ports opened sucessfully, 1 if not
  841. #######################################
  842. _openFirewall() {
  843. debug "Running: ${FUNCNAME[0]}" "$@"
  844. # Create OS-specific port rules based on argument (service) name
  845. local -a _f_ports # for firewall_cmd
  846. local _u_ports # for ufw
  847. if [[ "$1" == "jriver" ]]; then
  848. _f_ports=("52100-52200/tcp" "1900/udp")
  849. _u_ports="52100:52200/tcp|1900/udp"
  850. elif [[ "$1" =~ ^(jriver-x11vnc|jriver-xvnc)$ ]]; then
  851. _f_ports=("$_port/tcp")
  852. _u_ports="$_port/tcp"
  853. else
  854. err "_openFirewall unrecognized service name"
  855. exit 1
  856. fi
  857. # Open the ports
  858. if [[ "$ID" =~ ^(fedora|centos)$ ]]; then
  859. [[ ! -x $(command -v firewall-cmd) ]] && _installPackage firewalld
  860. if ! _firewall_cmd --get-services | grep -q "$1"; then
  861. _firewall_cmd --permanent --new-service="$1" > /dev/null 2>&1
  862. _firewall_cmd --permanent --service="$1" --set-description="$1 installed by installJRMC" > /dev/null 2>&1
  863. _firewall_cmd --permanent --service="$1" --set-short="$1" > /dev/null 2>&1
  864. for _f_port in "${_f_ports[@]}"; do
  865. _firewall_cmd --permanent --service="$1" --add-port="$_f_port" > /dev/null 2>&1
  866. done
  867. _firewall_cmd --add-service "$1" --permanent > /dev/null 2>&1
  868. _firewall_cmd --reload > /dev/null 2>&1
  869. fi
  870. elif [[ "$ID" =~ ^(ubuntu|debian)$ ]]; then
  871. # Debian ufw package state is broken on fresh installations
  872. [[ ! -x $(command -v ufw) ]] && _installPackage ufw
  873. if [[ ! -f "/etc/ufw/applications.d/$1" ]]; then
  874. _bash_cmd "cat <<-EOF > /etc/ufw/applications.d/$1
  875. [$1]
  876. title=$1
  877. description=$1 installed by installJRMC
  878. ports=$_u_ports
  879. EOF"
  880. fi
  881. _firewall_cmd app update "$1"
  882. _firewall_cmd allow "$1" > /dev/null 2>&1
  883. fi
  884. # shellcheck disable=SC2181
  885. # Rationale: much more concise to check exit codes at the end
  886. if [[ $? -ne 0 ]]; then
  887. err "Firewall ports could not be opened"
  888. return 1
  889. fi
  890. }
  891. #######################################
  892. # Create the x11vnc password file
  893. # Globals:
  894. # _novncauth
  895. # Returns:
  896. # 0 if password created sucessfully, 1 if not
  897. #######################################
  898. _setX11VNCPass() {
  899. debug "Running: ${FUNCNAME[0]}"
  900. _vncpassfile="$HOME/.vnc/jrmc_passwd"
  901. [[ ! -d "${_vncpassfile%/*}" ]] && mkdir -p "${_vncpassfile%/*}"
  902. if [[ -f "$_vncpassfile" ]]; then
  903. if [[ -z $_vncpass ]]; then
  904. err "Refusing to overwrite existing $_vncpassfile with an empty password"
  905. err "Remove existing $_vncpassfile or set --vncpass to use an empty password"
  906. exit 1
  907. else
  908. rm -f "$_vncpassfile"
  909. fi
  910. fi
  911. if [[ -n $_vncpass ]]; then
  912. if ! x11vnc -storepasswd "$_vncpass" "$_vncpassfile"; then
  913. err "Could not create VNC password file"
  914. return 1
  915. fi
  916. else
  917. _novncauth="true"
  918. fi
  919. }
  920. #######################################
  921. # Create the Xvnc password file
  922. # Returns:
  923. # 0 if password created sucessfully, 1 if not
  924. #######################################
  925. _setVNCPass() {
  926. debug "Running: ${FUNCNAME[0]}"
  927. _vncpassfile="$HOME/.vnc/jrmc_passwd"
  928. [[ ! -d "${_vncpassfile%/*}" ]] && mkdir -p "${_vncpassfile%/*}"
  929. if [[ -f "$_vncpassfile" ]]; then
  930. if [[ -z $_vncpass ]]; then
  931. err "Refusing to overwrite existing $_vncpassfile with an empty password"
  932. err "Remove existing $_vncpassfile or set --vncpass to use an empty password"
  933. exit 1
  934. else
  935. rm -f "$_vncpassfile"
  936. fi
  937. fi
  938. if [[ -n $_vncpass ]]; then
  939. if ! echo "$_vncpass" | vncpasswd -f > "$_vncpassfile"; then
  940. err "Could not create VNC password file"
  941. return 1
  942. fi
  943. else
  944. _novncauth="true"
  945. fi
  946. }
  947. #######################################
  948. # Set display and port variables
  949. # Globals:
  950. # _display
  951. # _displaynum
  952. # _next_display
  953. # _next_displaynum
  954. #######################################
  955. _setDisplay() {
  956. # Check _display, else DISPLAY, else set to :0 by default
  957. if [[ -n $_display ]]; then
  958. _next_display="$_display"
  959. elif [[ -n $DISPLAY ]]; then
  960. _display="${DISPLAY}"
  961. _displaynum="${_display#:}" # strip colon
  962. _displaynum="${_displaynum%.*}" # strip suffix
  963. _next_displaynum=$(( _displaynum + 1 ))
  964. _next_display=":$_next_displaynum"
  965. else
  966. _display=":0"
  967. _next_display=":1"
  968. fi
  969. _displaynum="${_display#:}" # strip colon
  970. _displaynum="${_displaynum%.*}" # strip suffix
  971. _next_displaynum=$(( _displaynum + 1 ))
  972. }
  973. #######################################
  974. # Create associated service variables based on service name
  975. # Requires:
  976. # _service_user
  977. # Globals:
  978. # _service_fname
  979. # _timer_fname
  980. # _service_name
  981. # _timer_name
  982. # _user_specifier
  983. #######################################
  984. _servicePrep() {
  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() {
  1044. debug "Running: ${FUNCNAME[0]}"
  1045. _installPackage tigervnc-server
  1046. _setVNCPass
  1047. local _port=$(( _next_displaynum + 5900 ))
  1048. if [[ -n $_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 [[ -n $_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" =~ ^(ubuntu|debian)$ ]]; 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 [[ -n $_repoinstall ]]; then
  1208. _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 [[ -n $_uninstall ]]; then
  1218. _uninstall
  1219. exit $?
  1220. fi
  1221. # Build RPM from source DEB
  1222. if [[ -n $_rpmbuild ]]; then
  1223. _installPackage epel-release
  1224. _acquireDeb
  1225. _buildRPM
  1226. fi
  1227. # Run createrepo
  1228. if [[ -n $_createrepo ]]; then
  1229. _runCreaterepo "$_mcrpm"
  1230. fi
  1231. # Install the rpm
  1232. if [[ -n $_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