installJRMC 46 KB

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