installJRMC 47 KB

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