installJRMC 47 KB

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