├── .github └── FUNDING.yml ├── .gitignore ├── .gitlab-ci.yml ├── AUTHORS ├── CHANGELOG.md ├── CNAME ├── INSTALL.md ├── Install ├── LICENSE ├── NOTICE ├── README.md ├── SECURITY.md ├── Uninstall ├── VERSION ├── _config.yml ├── api ├── README.md ├── get_core_ip.py ├── get_zone_attributes.py ├── get_zone_remaining.py ├── list_album_tracks.py ├── list_albums.py ├── list_artist_albums.py ├── list_artist_tracks.py ├── list_artists.py ├── list_composer_albums.py ├── list_composers.py ├── list_genre_albums.py ├── list_genre_artists.py ├── list_genres.py ├── list_playlist_tracks.py ├── list_playlists.py ├── list_radio.py ├── list_tags.py ├── list_tracks.py ├── list_zones.py ├── now_playing.py ├── play_album.py ├── play_album_track.py ├── play_artist.py ├── play_artist_album.py ├── play_artist_track.py ├── play_composer.py ├── play_composer_album.py ├── play_genre.py ├── play_genre_album.py ├── play_genre_artist.py ├── play_playlist.py ├── play_radio.py ├── play_tag.py ├── play_track.py ├── set_default.py ├── set_volume.py ├── transfer_zone.py ├── zone_command.py ├── zone_group.py └── zone_properties.py ├── bin ├── get_core_ip ├── get_zone_info ├── get_zone_remaining ├── get_zone_volume ├── get_zones ├── list_album_tracks ├── list_albums ├── list_artist_albums ├── list_artist_tracks ├── list_artists ├── list_composer_albums ├── list_composers ├── list_genre_albums ├── list_genre_artists ├── list_genres ├── list_playlist_tracks ├── list_playlists ├── list_radio ├── list_tags ├── list_tracks ├── list_zones ├── now_playing ├── play_album ├── play_album_track ├── play_artist ├── play_artist_album ├── play_artist_track ├── play_composer ├── play_composer_album ├── play_genre ├── play_genre_album ├── play_genre_artist ├── play_playlist ├── play_radio ├── play_tag ├── play_track ├── roon ├── roon_fade ├── roonanim ├── roongui ├── roontui ├── set_volume ├── set_zone ├── set_zone_group ├── transfer_zone ├── wait_for_pid └── zone_command ├── bundle ├── RoonControl.app │ └── Contents │ │ ├── Info.plist │ │ ├── MacOS │ │ └── RoonControl │ │ ├── PkgInfo │ │ ├── Resources │ │ ├── RoonControl.icns │ │ ├── Script Libraries │ │ │ └── Dialog Toolkit Plus.scptd │ │ │ │ └── Contents │ │ │ │ ├── Info.plist │ │ │ │ ├── Resources │ │ │ │ ├── ScriptingDictionary.sdef │ │ │ │ ├── Scripts │ │ │ │ │ ├── main.recover.rtf │ │ │ │ │ └── main.scpt │ │ │ │ └── description.rtfd │ │ │ │ │ └── TXT.rtf │ │ │ │ └── Script Debugger.plist │ │ └── Scripts │ │ │ └── main.scpt │ │ └── _CodeSignature │ │ └── CodeResources └── Tools │ ├── converticon │ ├── plist2xml │ ├── script2bundle │ └── xml2plist ├── chkinst ├── clean ├── etc ├── Graceful.flf ├── discover ├── install-figlet ├── install-fzf ├── install-gum ├── install-roon-gui ├── install-roon-tui ├── postinstall ├── preremove ├── roon_api.ini-dist ├── roon_faded └── upgrade-venv ├── icons ├── globe.png ├── instagram.png ├── linkedin.png ├── mastodon.png ├── twitter.png └── youtube.png ├── linInstall ├── macInstall ├── man ├── README.md ├── man1 │ ├── get_core_ip.1 │ ├── get_zone_info.1 │ ├── get_zone_remaining.1 │ ├── get_zone_volume.1 │ ├── get_zones.1 │ ├── list_album_tracks.1 │ ├── list_albums.1 │ ├── list_artist_albums.1 │ ├── list_artist_tracks.1 │ ├── list_artists.1 │ ├── list_composer_albums.1 │ ├── list_composers.1 │ ├── list_genre_albums.1 │ ├── list_genre_artists.1 │ ├── list_genres.1 │ ├── list_playlist_tracks.1 │ ├── list_playlists.1 │ ├── list_radio.1 │ ├── list_tags.1 │ ├── list_tracks.1 │ ├── list_zones.1 │ ├── now_playing.1 │ ├── play_album.1 │ ├── play_album_track.1 │ ├── play_artist.1 │ ├── play_artist_album.1 │ ├── play_artist_track.1 │ ├── play_composer.1 │ ├── play_composer_album.1 │ ├── play_genre.1 │ ├── play_genre_album.1 │ ├── play_genre_artist.1 │ ├── play_playlist.1 │ ├── play_radio.1 │ ├── play_tag.1 │ ├── play_track.1 │ ├── roon.1 │ ├── roon_fade.1 │ ├── roonanim.1 │ ├── roontui.1 │ ├── set_volume.1 │ ├── set_zone.1 │ ├── set_zone_group.1 │ ├── transfer_zone.1 │ └── zone_command.1 └── man5 │ └── roon_faded.5 ├── markdown ├── README.md ├── get_core_ip.1.md ├── get_zone_info.1.md ├── get_zone_remaining.1.md ├── get_zone_volume.1.md ├── get_zones.1.md ├── list_album_tracks.1.md ├── list_albums.1.md ├── list_artist_albums.1.md ├── list_artist_tracks.1.md ├── list_artists.1.md ├── list_composer_albums.1.md ├── list_composers.1.md ├── list_genre_albums.1.md ├── list_genre_artists.1.md ├── list_genres.1.md ├── list_playlist_tracks.1.md ├── list_playlists.1.md ├── list_radio.1.md ├── list_tags.1.md ├── list_tracks.1.md ├── list_zones.1.md ├── now_playing.1.md ├── play_album.1.md ├── play_album_track.1.md ├── play_artist.1.md ├── play_artist_album.1.md ├── play_artist_track.1.md ├── play_composer.1.md ├── play_composer_album.1.md ├── play_genre.1.md ├── play_genre_album.1.md ├── play_genre_artist.1.md ├── play_playlist.1.md ├── play_radio.1.md ├── play_tag.1.md ├── play_track.1.md ├── roon.1.md ├── roon_fade.1.md ├── roon_faded.5.md ├── roonanim.1.md ├── roontui.1.md ├── set_volume.1.md ├── set_zone.1.md ├── set_zone_group.1.md ├── transfer_zone.1.md └── zone_command.1.md ├── mkpkg ├── mkrelease ├── patches ├── README.md ├── mkpatch-pyroon ├── mkpatch-roonapi ├── pyroon-listmedia.patch ├── roon-web-controller │ ├── README.md │ ├── roon-web-controller-alpha.patch │ └── roon-web-controller.patch ├── roonapi-listmedia-site.patch ├── roonapi-listmedia.patch └── roonapi │ ├── README.md │ ├── roonapi.py │ └── roonapisocket.py ├── pkg ├── debian │ ├── postinst │ ├── preinst │ └── prerm ├── release.md └── rpm │ └── RoonCommandLine.spec ├── rooncommand.desktop ├── screenshots ├── Roon_List_Artist_Tracks.png ├── Roon_Play_Artist_Track.png ├── Roon_Set_Zone.png └── Roon_UI.png ├── test └── test.sh ├── usage.txt └── viewman /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | github: doctorfree 2 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | dist/* 2 | releases/* 3 | test/__pycache__/* 4 | test/*.py 5 | tmp/* 6 | # vim files 7 | .*.sw[a-z] 8 | *.un~ 9 | Session.vim 10 | .netrwhist 11 | -------------------------------------------------------------------------------- /.gitlab-ci.yml: -------------------------------------------------------------------------------- 1 | # A pipeline is composed of independent jobs that run scripts, grouped into stages. 2 | # Stages run in sequential order, but jobs within stages run in parallel. 3 | # 4 | # For more information, see: https://docs.gitlab.com/ee/ci/yaml/index.html#stages 5 | 6 | stages: 7 | - build 8 | - release 9 | 10 | build: 11 | stage: build 12 | image: ubuntu:latest 13 | before_script: 14 | - echo $CI_JOB_ID 15 | - echo BUILD_JOB_ID=$CI_JOB_ID >> build.env 16 | - cat VERSION >> build.env 17 | script: 18 | - ./mkpkg 19 | only: 20 | - tags 21 | artifacts: 22 | paths: 23 | - dist/*.deb 24 | - dist/*.rpm 25 | - dist/*.tgz 26 | - dist/*.zip 27 | reports: 28 | dotenv: build.env 29 | 30 | release: 31 | stage: release 32 | image: registry.gitlab.com/gitlab-org/release-cli:latest 33 | script: 34 | - echo 'running release_job' 35 | - echo 'Previous Job ID:' 36 | - echo $BUILD_JOB_ID 37 | - echo 'VERSION:' 38 | - echo $VERSION 39 | - echo 'RELEASE:' 40 | - echo $RELEASE 41 | needs: 42 | - job: build 43 | artifacts: true 44 | release: 45 | name: 'RoonCommandLine Version $VERSION release $RELEASE' 46 | description: './pkg/release.md' 47 | tag_name: 'v${VERSION}r${RELEASE}' 48 | assets: 49 | links: 50 | - name: 'RoonCommandLine_${VERSION}-${RELEASE}.deb - Debian format installation package (Ubuntu Linux, etc)' 51 | url: 'https://gitlab.com/doctorfree/RoonCommandLine/-/jobs/${BUILD_JOB_ID}/artifacts/file/dist/RoonCommandLine_${VERSION}-${RELEASE}.deb' 52 | link_type: 'package' 53 | - name: 'RoonCommandLine_${VERSION}-${RELEASE}.rpm - RPM format installation package (CentOS/Fedora Linux etc)' 54 | url: 'https://gitlab.com/doctorfree/RoonCommandLine/-/jobs/${BUILD_JOB_ID}/artifacts/file/dist/RoonCommandLine_${VERSION}-${RELEASE}.rpm' 55 | link_type: 'package' 56 | - name: 'RoonCommandLine_${VERSION}-${RELEASE}.tgz - Compressed tar format distribution archive' 57 | url: 'https://gitlab.com/doctorfree/RoonCommandLine/-/jobs/${BUILD_JOB_ID}/artifacts/file/dist/RoonCommandLine_${VERSION}-${RELEASE}.tgz' 58 | link_type: 'other' 59 | - name: 'RoonCommandLine_${VERSION}-${RELEASE}.zip - Zip format distribution archive' 60 | url: 'https://gitlab.com/doctorfree/RoonCommandLine/-/jobs/${BUILD_JOB_ID}/artifacts/file/dist/RoonCommandLine_${VERSION}-${RELEASE}.zip' 61 | link_type: 'other' 62 | only: 63 | - tags 64 | -------------------------------------------------------------------------------- /AUTHORS: -------------------------------------------------------------------------------- 1 | RoonCommandLine is written and maintained by: 2 | Ronald Joe Record 3 | 4 | Python Roon API is written and maintained by: 5 | Greg Dowling 6 | 7 | roon-tui is written and maintained by: 8 | TheAppgineer Github Organization 9 | -------------------------------------------------------------------------------- /CNAME: -------------------------------------------------------------------------------- 1 | readme.rooncommand.dev -------------------------------------------------------------------------------- /INSTALL.md: -------------------------------------------------------------------------------- 1 | # INSTALL 2 | 3 | See the [Installation section of the README](README.md#installation) 4 | for RoonCommandLine Installation instructions. 5 | -------------------------------------------------------------------------------- /NOTICE: -------------------------------------------------------------------------------- 1 | Python Roon API Command Line Tools 2 | Copyright 2021, Ronald Joe Record 3 | 4 | This product includes software developed at https://github.com/pavoni/pyroon 5 | -------------------------------------------------------------------------------- /SECURITY.md: -------------------------------------------------------------------------------- 1 | # Security Policy 2 | 3 | I take the security of my projects seriously. If you discover any security 4 | vulnerabilities or have concerns regarding the security practices advised in 5 | this repository, please reach out to me immediately. I appreciate your efforts 6 | in responsibly disclosing the issue and will make every effort to address it promptly. 7 | 8 | ## Reporting a Vulnerability 9 | 10 | To report a security vulnerability, please follow these steps: 11 | 12 | 1. Go to the **Security** tab of this repository on GitHub. 13 | 2. Click on **"Report a vulnerability"**. 14 | 3. Provide a clear description of the vulnerability and its potential impact. Be as detailed as possible. 15 | 4. If applicable, include steps or a PoC (Proof of Concept) to reproduce the vulnerability. 16 | 5. Submit the report. 17 | 18 | Once I receive the private report notification, I will promptly investigate and assess the reported vulnerability. 19 | 20 | Please do not disclose any potential vulnerabilities in public repositories, 21 | issue trackers, or forums until we have had a chance to review and address the issue. 22 | 23 | ## Scope 24 | 25 | This security policy applies to all the code and files within this repository 26 | and its dependencies actively maintained by me. If you encounter a security 27 | issue in a dependency that is not directly maintained by me, please follow 28 | responsible disclosure practices and report it to the respective project. 29 | 30 | While I strive to ensure the security of this project, please note that as an 31 | individual developer, there may be limitations on resources, response times, and mitigations. 32 | 33 | Thank you for your help in making this project more secure. 34 | -------------------------------------------------------------------------------- /Uninstall: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # 3 | # shellcheck disable=SC1090,SC2220,SC2207,SC2068,SC2001 4 | 5 | uninstall() { 6 | LOCAL="/usr/local" 7 | APPL=${LOCAL}/share/applications 8 | DOC=${LOCAL}/share/doc 9 | ROON=${LOCAL}/Roon 10 | ROONBIN=${ROON}/bin 11 | 12 | [ -d /usr/local/bin ] && { 13 | cd /usr/local/bin || exit 1 14 | for command in "${ROONBIN}"/* 15 | do 16 | [ "${command}" == "${ROONBIN}/*" ] && continue 17 | b=$(basename "${command}") 18 | [ -L "$b" ] && { 19 | /bin/ls -l "$b" | grep ${ROON} > /dev/null && sudo rm -f "$b" 20 | } 21 | done 22 | } 23 | 24 | sudo rm -rf ${ROON} 25 | sudo rm -rf ${DOC}/RoonCommandLine 26 | sudo rm -f ${APPL}/rooncommand.desktop 27 | 28 | echo "" 29 | echo "RoonCommandLine uninstalled" 30 | } 31 | 32 | have_fade=$(type -p roon_fade) 33 | [ "${have_fade}" ] && roon_fade off 34 | 35 | plat=$(uname -s) 36 | if [ "$plat" == "Darwin" ] 37 | then 38 | uninstall 39 | else 40 | debian= 41 | have_apt=$(type -p apt) 42 | have_dpkg=$(type -p dpkg) 43 | have_rpm=$(type -p rpm) 44 | have_yum=$(type -p yum) 45 | [ -f /etc/os-release ] && . /etc/os-release 46 | [ "${ID_LIKE}" == "debian" ] && debian=1 47 | [ "${debian}" ] || [ -f /etc/debian_version ] && debian=1 48 | 49 | PKG=rooncommandline 50 | [ "${debian}" ] || PKG=RoonCommandLine 51 | 52 | if [ "${debian}" ] 53 | then 54 | if [ "${have_apt}" ] 55 | then 56 | sudo apt remove "${PKG}" -y > /dev/null 2>&1 57 | else 58 | if [ "${have_dpkg}" ] 59 | then 60 | sudo dpkg -r "${PKG}" > /dev/null 2>&1 61 | else 62 | echo "Cannot locate either apt or dpkg to remove. Skipping." 63 | fi 64 | fi 65 | else 66 | if [ "${have_yum}" ] 67 | then 68 | sudo yum remove "${PKG}" > /dev/null 2>&1 69 | else 70 | if [ "${have_rpm}" ] 71 | then 72 | sudo rpm -e "${PKG}" > /dev/null 2>&1 73 | else 74 | echo "Cannot locate either yum or rpm to remove. Skipping." 75 | fi 76 | fi 77 | fi 78 | uninstall 79 | fi 80 | -------------------------------------------------------------------------------- /VERSION: -------------------------------------------------------------------------------- 1 | VERSION=2.1.4 2 | RELEASE=1 3 | -------------------------------------------------------------------------------- /_config.yml: -------------------------------------------------------------------------------- 1 | remote_theme: doctorfree/jekyll-theme-neoman 2 | plugins: 3 | - jekyll-remote-theme 4 | 5 | title: RoonCommandLine 6 | email: ronaldrecord@gmail.com 7 | description: >- # this means to ignore newlines until "baseurl:" 8 | The Roon Command Line project provides Bash and Python scripts to enable 9 | command line control of the Roon audio system over a local network. 10 | baseurl: "" 11 | url: "https://rooncommand.dev" 12 | twitter_username: ronrecord 13 | github_username: doctorfree 14 | 15 | show_downloads: false 16 | # google_analytics: -------------------------------------------------------------------------------- /api/README.md: -------------------------------------------------------------------------------- 1 | # RoonCommandLine/api 2 | 3 | Python scripts to access the Python Roon API 4 | 5 | ## Contents 6 | 7 | [**get_core_ip.py**](get_core_ip.py) - retrieve the Roon Core IP address 8 | 9 | [**get_zone_attributes.py**](get_zone_attributes.py) - get zone attributes 10 | 11 | [**get_zone_remaining.py**](get_zone_remaining.py) - get remaining play time in zone 12 | 13 | [**now_playing.py**](now_playing.py) - display now playing track in zone or all zones 14 | 15 | [**play_album.py**](play_album.py) - play a specified album in my Roon library 16 | 17 | [**play_artist.py**](play_artist.py) - play a specified artist in my Roon library 18 | 19 | [**play_artist_album.py**](play_artist_album.py) - play album by artist 20 | 21 | [**play_artist_track.py**](play_artist_track.py) - play track by artist 22 | 23 | [**play_composer_album.py**](play_composer_album.py) - play album by composer 24 | 25 | [**play_composer.py**](play_composer.py) - play composer 26 | 27 | [**play_genre_album.py**](play_genre_album.py) - play album in genre 28 | 29 | [**play_genre_artist.py**](play_genre_artist.py) - play artist in genre 30 | 31 | [**play_genre.py**](play_genre.py) - play a specified genre in my Roon library 32 | 33 | [**play_playlist.py**](play_playlist.py) - play a specified playlist in my Roon library 34 | 35 | [**play_radio.py**](play_radio.py) - play Live Radio in a Roon zone 36 | 37 | [**play_tag.py**](play_tag.py) - play a specified tag in my Roon library (not yet working) 38 | 39 | [**list_albums.py**](list_albums.py) - list available Albums in your Roon Library 40 | 41 | [**list_artists.py**](list_artists.py) - list available Artists in your Roon Library 42 | 43 | [**list_artist_albums.py**](list_artist_albums.py) - list albums by artist 44 | 45 | [**list_artist_tracks.py**](list_artist_tracks.py) - list tracks by artist 46 | 47 | [**list_composer_albums.py**](list_composer_albums.py) - list albums by composer 48 | 49 | [**list_composers.py**](list_composers.py) - list composers 50 | 51 | [**list_genre_albums.py**](list_genre_albums.py) - list albums by genre 52 | 53 | [**list_genre_artists.py**](list_genre_artists.py) - list artists by genre 54 | 55 | [**list_playlist_tracks.py**](list_playlist_tracks.py) - list tracks in playlist 56 | 57 | [**list_genres.py**](list_genres.py) - list available Genres in your Roon Library 58 | 59 | [**list_playlists.py**](list_playlists.py) - list available Roon Playlists 60 | 61 | [**list_radio.py**](list_radio.py) - list available Roon Live Radio Stations 62 | 63 | [**list_tags.py**](list_tags.py) - list available Roon Library tags 64 | 65 | [**list_zones.py**](list_zones.py) - list available Roon Zones 66 | 67 | [**set_default.py**](set_default.py) - set RoonCommandLine defaults 68 | 69 | [**set_volume.py**](set_volume.py) - set the volume in the selected Roon Zone 70 | 71 | [**zone_command.py**](zone_command.py) - send commands to selected Roon Zone (play, pause, mute, next track, etc) 72 | 73 | [**zone_group.py**](zone_group.py) - group and ungroup zones specified in `roon_api.ini` 74 | 75 | [**zone_properties.py**](zone_properties.py) - display information and properties of specified Roon zone 76 | -------------------------------------------------------------------------------- /api/get_core_ip.py: -------------------------------------------------------------------------------- 1 | import configparser 2 | import time 3 | from roonapi import RoonApi, RoonDiscovery 4 | 5 | config = configparser.ConfigParser() 6 | config.read('/usr/local/Roon/etc/roon_api.ini') 7 | 8 | tokenfile = config['DEFAULT']['TokenFileName'] 9 | version = config['DEFAULT']['RoonCommandLineVersion'] 10 | release = config['DEFAULT']['RoonCommandLineRelease'] 11 | fullver = version + "-" + release 12 | 13 | app = { 14 | "extension_id": "roon_command_line", 15 | "display_name": "Python library for Roon", 16 | "display_version": fullver, 17 | "publisher": "RoonCommandLine", 18 | "email": "roon@ronrecord.com", 19 | "website": "https://github.com/doctorfree/RoonCommandLine", 20 | } 21 | 22 | discover = RoonDiscovery(None) 23 | server = discover.first() 24 | discover.stop() 25 | 26 | apis = [RoonApi(app, None, server[0], server[1], False)] 27 | auth_api = [] 28 | 29 | print("\nWaiting for authorization - in Roon, click Settings -> Extensions -> Enable\n", flush=True) 30 | while len(auth_api) == 0: 31 | auth_api = [api for api in apis if api.token is not None] 32 | time.sleep(10) 33 | 34 | api = auth_api[0] 35 | 36 | for api in apis: 37 | api.stop() 38 | 39 | print("\nRoonCoreIP =", api.host) 40 | print("RoonCorePort =", api._port) 41 | 42 | # save the token for next time 43 | with open(tokenfile, "w") as f: 44 | f.write(str(api.token)) 45 | -------------------------------------------------------------------------------- /api/get_zone_remaining.py: -------------------------------------------------------------------------------- 1 | import argparse 2 | import configparser 3 | from os import path 4 | import signal 5 | import sys 6 | from roonapi import RoonApi 7 | # 8 | # Get the volume of a zone's outputs 9 | # 10 | 11 | def signal_handler(sig, frame): 12 | sys.exit(0) 13 | signal.signal(signal.SIGINT, signal_handler) 14 | 15 | config = configparser.ConfigParser() 16 | config.read('/usr/local/Roon/etc/roon_api.ini') 17 | 18 | # Set to IP address of your Roon Core 19 | server = config['DEFAULT']['RoonCoreIP'] 20 | # Set to Port of your Roon Core 21 | port = config['DEFAULT']['RoonCorePort'] 22 | # Name of the file that holds a Roon API token 23 | tokenfile = config['DEFAULT']['TokenFileName'] 24 | 25 | parser = argparse.ArgumentParser() 26 | parser.add_argument("-z", "--zone", help="zone selection") 27 | args = parser.parse_args() 28 | 29 | if args.zone: 30 | target_zone = args.zone 31 | else: 32 | target_zone = config['DEFAULT']['DefaultZone'] 33 | 34 | zone_name = target_zone 35 | 36 | version = config['DEFAULT']['RoonCommandLineVersion'] 37 | release = config['DEFAULT']['RoonCommandLineRelease'] 38 | fullver = version + "-" + release 39 | 40 | appinfo = { 41 | "extension_id": "roon_command_line", 42 | "display_name": "Python library for Roon", 43 | "display_version": fullver, 44 | "publisher": "RoonCommandLine", 45 | "email": "roon@ronrecord.com", 46 | "website": "https://github.com/doctorfree/RoonCommandLine", 47 | } 48 | 49 | # Can be None if you don't yet have a token 50 | if path.exists(tokenfile): 51 | token = open(tokenfile).read() 52 | else: 53 | token = "None" 54 | 55 | roonapi = RoonApi(appinfo, token, server, port) 56 | 57 | # save the token for next time 58 | with open(tokenfile, "w") as f: 59 | f.write(str(roonapi.token)) 60 | 61 | # get target zone output_id 62 | outputs = roonapi.outputs 63 | 64 | output_id = None 65 | for (k, v) in outputs.items(): 66 | if target_zone in v["display_name"]: 67 | zone_name = v["display_name"] 68 | output_id = k 69 | 70 | remaining = None 71 | state = "Unknown" 72 | if output_id is None: 73 | err = "No zone found matching " + target_zone 74 | sys.exit(err) 75 | else: 76 | zone = roonapi.zone_by_output_id(output_id) 77 | if zone is not None: 78 | if "state" in zone: 79 | state = zone["state"] 80 | if "length" in zone["now_playing"]: 81 | length = zone["now_playing"]["length"] 82 | else: 83 | length = None 84 | if "seek_position" in zone["now_playing"]: 85 | position = zone["now_playing"]["seek_position"] 86 | else: 87 | position = None 88 | if length is not None: 89 | if position is not None: 90 | remaining = length - position 91 | 92 | if remaining is not None: 93 | print(zone_name + ": Time remaining = " + str(remaining) + 94 | " seconds, State = " + state) 95 | else: 96 | print(zone_name + ": State = " + state) 97 | -------------------------------------------------------------------------------- /api/list_radio.py: -------------------------------------------------------------------------------- 1 | import argparse 2 | import configparser 3 | from os import path 4 | import signal 5 | import sys 6 | from roonapi import RoonApi 7 | 8 | def signal_handler(sig, frame): 9 | sys.exit(0) 10 | signal.signal(signal.SIGINT, signal_handler) 11 | 12 | config = configparser.ConfigParser() 13 | config.read('/usr/local/Roon/etc/roon_api.ini') 14 | 15 | # Set to IP address of your Roon Core 16 | server = config['DEFAULT']['RoonCoreIP'] 17 | # Set to Port of your Roon Core 18 | port = config['DEFAULT']['RoonCorePort'] 19 | # Name of the file that holds a Roon API token 20 | tokenfile = config['DEFAULT']['TokenFileName'] 21 | 22 | parser = argparse.ArgumentParser() 23 | parser.add_argument("-r", "--radio", help="radio search term") 24 | parser.add_argument( 25 | "-q", 26 | "--quiet", 27 | default=False, 28 | action="store_true", 29 | help="list stations without other output" 30 | ) 31 | parser.add_argument("-z", "--zone", help="zone selection") 32 | args = parser.parse_args() 33 | 34 | if args.radio: 35 | searchterm = args.radio 36 | else: 37 | searchterm = config['DEFAULT']['DefaultRadio'] 38 | if args.quiet: 39 | verbose = False 40 | else: 41 | verbose = True 42 | if args.zone: 43 | target_zone = args.zone 44 | else: 45 | target_zone = config['DEFAULT']['DefaultZone'] 46 | 47 | version = config['DEFAULT']['RoonCommandLineVersion'] 48 | release = config['DEFAULT']['RoonCommandLineRelease'] 49 | fullver = version + "-" + release 50 | 51 | appinfo = { 52 | "extension_id": "roon_command_line", 53 | "display_name": "Python library for Roon", 54 | "display_version": fullver, 55 | "publisher": "RoonCommandLine", 56 | "email": "roon@ronrecord.com", 57 | "website": "https://github.com/doctorfree/RoonCommandLine", 58 | } 59 | 60 | # Can be None if you don't yet have a token 61 | if path.exists(tokenfile): 62 | token = open(tokenfile).read() 63 | else: 64 | token = "None" 65 | 66 | roonapi = RoonApi(appinfo, token, server, port) 67 | 68 | # save the token for next time 69 | with open(tokenfile, "w") as f: 70 | f.write(str(roonapi.token)) 71 | 72 | # get target zone output_id 73 | outputs = roonapi.outputs 74 | 75 | output_id = None 76 | for (k, v) in outputs.items(): 77 | if target_zone in v["display_name"]: 78 | output_id = k 79 | 80 | if output_id is None: 81 | err = "No zone found matching " + target_zone 82 | sys.exit(err) 83 | 84 | # List matching stations 85 | stations = roonapi.list_media(output_id, ["My Live Radio", searchterm]) 86 | 87 | if stations: 88 | print(*stations, sep="\n") 89 | else: 90 | if verbose: 91 | print("No stations found matching ", searchterm) 92 | -------------------------------------------------------------------------------- /api/list_tags.py: -------------------------------------------------------------------------------- 1 | import argparse 2 | import configparser 3 | from os import path 4 | import signal 5 | import sys 6 | from roonapi import RoonApi 7 | 8 | def signal_handler(sig, frame): 9 | sys.exit(0) 10 | signal.signal(signal.SIGINT, signal_handler) 11 | 12 | config = configparser.ConfigParser() 13 | config.read('/usr/local/Roon/etc/roon_api.ini') 14 | 15 | # Set to IP address of your Roon Core 16 | server = config['DEFAULT']['RoonCoreIP'] 17 | # Set to Port of your Roon Core 18 | port = config['DEFAULT']['RoonCorePort'] 19 | # Name of the file that holds a Roon API token 20 | tokenfile = config['DEFAULT']['TokenFileName'] 21 | 22 | parser = argparse.ArgumentParser() 23 | parser.add_argument("-t", "--tag", help="tag search term") 24 | parser.add_argument( 25 | "-q", 26 | "--quiet", 27 | default=False, 28 | action="store_true", 29 | help="list tags without other output" 30 | ) 31 | parser.add_argument("-z", "--zone", help="zone selection") 32 | args = parser.parse_args() 33 | 34 | if args.tag: 35 | searchterm = args.tag 36 | else: 37 | searchterm = config['DEFAULT']['DefaultTag'] 38 | if args.quiet: 39 | verbose = False 40 | else: 41 | verbose = True 42 | if args.zone: 43 | target_zone = args.zone 44 | else: 45 | target_zone = config['DEFAULT']['DefaultZone'] 46 | 47 | version = config['DEFAULT']['RoonCommandLineVersion'] 48 | release = config['DEFAULT']['RoonCommandLineRelease'] 49 | fullver = version + "-" + release 50 | 51 | appinfo = { 52 | "extension_id": "roon_command_line", 53 | "display_name": "Python library for Roon", 54 | "display_version": fullver, 55 | "publisher": "RoonCommandLine", 56 | "email": "roon@ronrecord.com", 57 | "website": "https://github.com/doctorfree/RoonCommandLine", 58 | } 59 | 60 | # Can be None if you don't yet have a token 61 | if path.exists(tokenfile): 62 | token = open(tokenfile).read() 63 | else: 64 | token = "None" 65 | 66 | roonapi = RoonApi(appinfo, token, server, port) 67 | 68 | # save the token for next time 69 | with open(tokenfile, "w") as f: 70 | f.write(str(roonapi.token)) 71 | 72 | # get target zone output_id 73 | outputs = roonapi.outputs 74 | 75 | output_id = None 76 | for (k, v) in outputs.items(): 77 | if target_zone in v["display_name"]: 78 | output_id = k 79 | 80 | if output_id is None: 81 | err = "No zone found matching " + target_zone 82 | sys.exit(err) 83 | 84 | # List matching tags 85 | tags = roonapi.list_media(output_id, ["Library", "Tags", searchterm]) 86 | 87 | if tags: 88 | print(*tags, sep="\n") 89 | else: 90 | if verbose: 91 | print("No tags found matching ", searchterm) 92 | -------------------------------------------------------------------------------- /api/play_tag.py: -------------------------------------------------------------------------------- 1 | import argparse 2 | import configparser 3 | from os import path 4 | import signal 5 | import sys 6 | from roonapi import RoonApi 7 | 8 | def signal_handler(sig, frame): 9 | sys.exit(0) 10 | signal.signal(signal.SIGINT, signal_handler) 11 | 12 | config = configparser.ConfigParser() 13 | config.read('/usr/local/Roon/etc/roon_api.ini') 14 | 15 | # Set to IP address of your Roon Core 16 | server = config['DEFAULT']['RoonCoreIP'] 17 | # Set to Port of your Roon Core 18 | port = config['DEFAULT']['RoonCorePort'] 19 | # Name of the file that holds a Roon API token 20 | tokenfile = config['DEFAULT']['TokenFileName'] 21 | 22 | parser = argparse.ArgumentParser() 23 | parser.add_argument("-t", "--tag", help="tag selection") 24 | parser.add_argument("-z", "--zone", help="zone selection") 25 | args = parser.parse_args() 26 | 27 | if args.tag: 28 | tag = args.tag 29 | else: 30 | tag = config['DEFAULT']['DefaultTag'] 31 | if args.zone: 32 | target_zone = args.zone 33 | else: 34 | target_zone = config['DEFAULT']['DefaultZone'] 35 | 36 | version = config['DEFAULT']['RoonCommandLineVersion'] 37 | release = config['DEFAULT']['RoonCommandLineRelease'] 38 | fullver = version + "-" + release 39 | 40 | appinfo = { 41 | "extension_id": "roon_command_line", 42 | "display_name": "Python library for Roon", 43 | "display_version": fullver, 44 | "publisher": "RoonCommandLine", 45 | "email": "roon@ronrecord.com", 46 | "website": "https://github.com/doctorfree/RoonCommandLine", 47 | } 48 | 49 | # Can be None if you don't yet have a token 50 | if path.exists(tokenfile): 51 | token = open(tokenfile).read() 52 | else: 53 | token = "None" 54 | 55 | roonapi = RoonApi(appinfo, token, server, port) 56 | 57 | # save the token for next time 58 | with open(tokenfile, "w") as f: 59 | f.write(str(roonapi.token)) 60 | 61 | # get target zone output_id 62 | outputs = roonapi.outputs 63 | 64 | output_id = None 65 | for (k, v) in outputs.items(): 66 | if target_zone in v["display_name"]: 67 | output_id = k 68 | 69 | if output_id is None: 70 | err = "No zone found matching " + target_zone 71 | sys.exit(err) 72 | else: 73 | # Play tag (not yet working) 74 | tags = roonapi.list_media(output_id, ["Library", "Tags", tag]) 75 | if tags: 76 | print("\nTags matching", tag, ":\n") 77 | print(*tags, sep="\n") 78 | if len(tags) == 1: 79 | tag = tags[0] 80 | print("\nPlaying media by tag is not yet working. Found tag for", tag, "\n") 81 | else: 82 | print("\nTo play a tag by name either specify the full name") 83 | print("or enough of a substring to provide a single match") 84 | else: 85 | print("\nNo tags matching", tag, "\n") 86 | -------------------------------------------------------------------------------- /api/play_track.py: -------------------------------------------------------------------------------- 1 | import argparse 2 | import configparser 3 | from os import path 4 | import signal 5 | import sys 6 | from roonapi import RoonApi 7 | 8 | def signal_handler(sig, frame): 9 | sys.exit(0) 10 | signal.signal(signal.SIGINT, signal_handler) 11 | 12 | config = configparser.ConfigParser() 13 | config.read('/usr/local/Roon/etc/roon_api.ini') 14 | 15 | # Set to IP address of your Roon Core 16 | server = config['DEFAULT']['RoonCoreIP'] 17 | # Set to Port of your Roon Core 18 | port = config['DEFAULT']['RoonCorePort'] 19 | # Name of the file that holds a Roon API token 20 | tokenfile = config['DEFAULT']['TokenFileName'] 21 | 22 | parser = argparse.ArgumentParser() 23 | parser.add_argument("-t", "--track", help="track title") 24 | parser.add_argument("-z", "--zone", help="zone selection") 25 | args = parser.parse_args() 26 | 27 | if args.track: 28 | tracktitle = args.track 29 | else: 30 | print("\nTrack title required. Exiting.\n") 31 | sys.exit(0) 32 | if args.zone: 33 | target_zone = args.zone 34 | else: 35 | target_zone = config['DEFAULT']['DefaultZone'] 36 | 37 | version = config['DEFAULT']['RoonCommandLineVersion'] 38 | release = config['DEFAULT']['RoonCommandLineRelease'] 39 | fullver = version + "-" + release 40 | 41 | appinfo = { 42 | "extension_id": "roon_command_line", 43 | "display_name": "Python library for Roon", 44 | "display_version": fullver, 45 | "publisher": "RoonCommandLine", 46 | "email": "roon@ronrecord.com", 47 | "website": "https://github.com/doctorfree/RoonCommandLine", 48 | } 49 | 50 | # Can be None if you don't yet have a token 51 | if path.exists(tokenfile): 52 | token = open(tokenfile).read() 53 | else: 54 | token = "None" 55 | 56 | roonapi = RoonApi(appinfo, token, server, port) 57 | 58 | # Save the token for next time 59 | with open(tokenfile, "w") as f: 60 | f.write(str(roonapi.token)) 61 | 62 | # Get target zone output_id 63 | outputs = roonapi.outputs 64 | 65 | output_id = None 66 | for (k, v) in outputs.items(): 67 | if target_zone in v["display_name"]: 68 | output_id = k 69 | 70 | if output_id is None: 71 | err = "No zone found matching " + target_zone 72 | sys.exit(err) 73 | 74 | roonapi.play_media(output_id, ["Library", "Tracks", tracktitle], None, False) 75 | -------------------------------------------------------------------------------- /api/set_default.py: -------------------------------------------------------------------------------- 1 | import argparse 2 | import configparser 3 | 4 | config = configparser.RawConfigParser(comment_prefixes='/', allow_no_value=True) 5 | config.optionxform=str 6 | config.read('/usr/local/Roon/etc/roon_api.ini') 7 | 8 | parser = argparse.ArgumentParser() 9 | parser.add_argument("-A", "--album", help="set default album") 10 | parser.add_argument("-a", "--artist", help="set default artist") 11 | parser.add_argument("-c", "--composer", help="set default composer") 12 | parser.add_argument("-g", "--genre", help="set default genre") 13 | parser.add_argument("-p", "--playlist", help="set default playlist") 14 | parser.add_argument("-r", "--radio", help="set default radio") 15 | parser.add_argument("-t", "--tag", help="set default tag") 16 | parser.add_argument("-z", "--zone", help="set default zone") 17 | args = parser.parse_args() 18 | 19 | if args.album: 20 | config['DEFAULT']['DefaultAlbum'] = args.album 21 | if args.artist: 22 | config['DEFAULT']['DefaultArtist'] = args.artist 23 | if args.composer: 24 | config['DEFAULT']['DefaultComposer'] = args.composer 25 | if args.genre: 26 | config['DEFAULT']['DefaultGenre'] = args.genre 27 | if args.playlist: 28 | config['DEFAULT']['DefaultPlaylist'] = args.playlist 29 | if args.radio: 30 | config['DEFAULT']['DefaultRadio'] = args.radio 31 | if args.tag: 32 | config['DEFAULT']['DefaultTag'] = args.tag 33 | if args.zone: 34 | config['DEFAULT']['DefaultZone'] = args.zone 35 | 36 | with open('/usr/local/Roon/etc/roon_api.ini', 'w') as configfile: 37 | config.write(configfile) 38 | -------------------------------------------------------------------------------- /api/transfer_zone.py: -------------------------------------------------------------------------------- 1 | import argparse 2 | import configparser 3 | from os import path 4 | import signal 5 | import sys 6 | from roonapi import RoonApi 7 | 8 | def signal_handler(sig, frame): 9 | sys.exit(0) 10 | signal.signal(signal.SIGINT, signal_handler) 11 | 12 | config = configparser.ConfigParser() 13 | config.read('/usr/local/Roon/etc/roon_api.ini') 14 | 15 | # Set to IP address of your Roon Core 16 | server = config['DEFAULT']['RoonCoreIP'] 17 | # Set to Port of your Roon Core 18 | port = config['DEFAULT']['RoonCorePort'] 19 | # Name of the file that holds a Roon API token 20 | tokenfile = config['DEFAULT']['TokenFileName'] 21 | 22 | parser = argparse.ArgumentParser() 23 | parser.add_argument("-f", "--source", help="from zone") 24 | parser.add_argument("-t", "--to", help="to zone") 25 | args = parser.parse_args() 26 | 27 | if args.source: 28 | fromzone = args.source 29 | else: 30 | fromzone = config['DEFAULT']['DefaultZone'] 31 | if args.to: 32 | tozone = args.to 33 | else: 34 | tozone = config['DEFAULT']['DefaultZone'] 35 | 36 | version = config['DEFAULT']['RoonCommandLineVersion'] 37 | release = config['DEFAULT']['RoonCommandLineRelease'] 38 | fullver = version + "-" + release 39 | 40 | appinfo = { 41 | "extension_id": "roon_command_line", 42 | "display_name": "Python library for Roon", 43 | "display_version": fullver, 44 | "publisher": "RoonCommandLine", 45 | "email": "roon@ronrecord.com", 46 | "website": "https://github.com/doctorfree/RoonCommandLine", 47 | } 48 | 49 | # Can be None if you don't yet have a token 50 | if path.exists(tokenfile): 51 | token = open(tokenfile).read() 52 | else: 53 | token = "None" 54 | 55 | roonapi = RoonApi(appinfo, token, server, port) 56 | 57 | # save the token for next time 58 | with open(tokenfile, "w") as f: 59 | f.write(str(roonapi.token)) 60 | 61 | # get to and from zone output_ids 62 | outputs = roonapi.outputs 63 | 64 | from_output_id = None 65 | to_output_id = None 66 | for (k, v) in outputs.items(): 67 | if fromzone in v["display_name"]: 68 | from_output_id = k 69 | if tozone in v["display_name"]: 70 | to_output_id = k 71 | 72 | if from_output_id is None: 73 | err = "No zone found matching " + fromzone 74 | sys.exit(err) 75 | 76 | if to_output_id is None: 77 | err = "No zone found matching " + tozone 78 | sys.exit(err) 79 | else: 80 | # Transfer zones 81 | print("Transfering from zone", fromzone, "to zone", tozone) 82 | roonapi.transfer_zone(from_output_id, to_output_id) 83 | -------------------------------------------------------------------------------- /api/zone_group.py: -------------------------------------------------------------------------------- 1 | import argparse 2 | import configparser 3 | from os import path 4 | import signal 5 | import sys 6 | from roonapi import RoonApi 7 | 8 | def signal_handler(sig, frame): 9 | sys.exit(0) 10 | signal.signal(signal.SIGINT, signal_handler) 11 | 12 | config = configparser.ConfigParser() 13 | config.read('/usr/local/Roon/etc/roon_api.ini') 14 | 15 | # Set to IP address of your Roon Core 16 | server = config['DEFAULT']['RoonCoreIP'] 17 | # Set to Port of your Roon Core 18 | port = config['DEFAULT']['RoonCorePort'] 19 | # Name of the file that holds a Roon API token 20 | tokenfile = config['DEFAULT']['TokenFileName'] 21 | 22 | parser = argparse.ArgumentParser() 23 | parser.add_argument("-c", "--command", help="command selection") 24 | parser.add_argument("-z", "--zone", help="zone selection") 25 | args = parser.parse_args() 26 | 27 | if args.command: 28 | zone_command = args.command 29 | else: 30 | zone_command = "group" 31 | if args.zone: 32 | target_zone = config['ZONEGROUPS'][args.zone] 33 | else: 34 | target_zone = config['ZONEGROUPS']['Group_1'] 35 | 36 | group_zones = target_zone.split(",") 37 | for i in range(len(group_zones)): 38 | group_zones[i] = group_zones[i].strip() 39 | 40 | version = config['DEFAULT']['RoonCommandLineVersion'] 41 | release = config['DEFAULT']['RoonCommandLineRelease'] 42 | fullver = version + "-" + release 43 | 44 | appinfo = { 45 | "extension_id": "roon_command_line", 46 | "display_name": "Python library for Roon", 47 | "display_version": fullver, 48 | "publisher": "RoonCommandLine", 49 | "email": "roon@ronrecord.com", 50 | "website": "https://github.com/doctorfree/RoonCommandLine", 51 | } 52 | 53 | # Can be None if you don't yet have a token 54 | if path.exists(tokenfile): 55 | token = open(tokenfile).read() 56 | else: 57 | token = "None" 58 | 59 | roonapi = RoonApi(appinfo, token, server, port) 60 | 61 | # save the token for next time 62 | with open(tokenfile, "w") as f: 63 | f.write(str(roonapi.token)) 64 | 65 | # get target zone output_id 66 | outputs = roonapi.outputs 67 | 68 | output_ids = [] 69 | output_names = [] 70 | zone_name = None 71 | # get the first zone in this grouping 72 | for (k, v) in outputs.items(): 73 | if v["display_name"] == group_zones[0]: 74 | zone_name = v["display_name"] 75 | output_ids.append(k) 76 | output_names.append(zone_name) 77 | 78 | if zone_name is None: 79 | err = "Unable to locate zone name " + group_zones[0] 80 | sys.exit(err) 81 | else: 82 | # get the other zones in this grouping 83 | for (k, v) in outputs.items(): 84 | if v["display_name"] in group_zones[1:]: 85 | zone_name = v["display_name"] 86 | output_ids.append(k) 87 | output_names.append(zone_name) 88 | if zone_command == "ungroup": 89 | print("Ungrouping zones:", output_names) 90 | roonapi.ungroup_outputs(output_ids) 91 | else: 92 | print("Grouping zones:", output_names) 93 | roonapi.group_outputs(output_ids) 94 | -------------------------------------------------------------------------------- /bin/get_core_ip: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | ROON=/usr/local/Roon 4 | ROONAPI=${ROON}/api 5 | CORE=get_core_ip.py 6 | 7 | [ -d $ROONAPI ] || exit 1 8 | 9 | cd $ROONAPI || exit 1 10 | 11 | [ -f $CORE ] || exit 2 12 | 13 | # echo "When prompted for authorization, go to a Roon Remote client window," 14 | # echo "click on 'Settings' then click on 'Extensions' then 'Enable' the extension" 15 | 16 | # Use a Python virtual environment 17 | [ -f ${ROON}/venv/bin/activate ] && source ${ROON}/venv/bin/activate 18 | [[ ":$PATH:" == *":/usr/local/Roon/venv/bin:"* ]] || { 19 | export PATH=/usr/local/Roon/venv/bin:${PATH} 20 | } 21 | 22 | have_python3=$(type -p python3) 23 | if [ "${have_python3}" ] 24 | then 25 | python3 $CORE 26 | else 27 | python $CORE 28 | fi 29 | sleep 4 30 | -------------------------------------------------------------------------------- /bin/get_zone_remaining: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # 3 | # shellcheck disable=SC1090,SC2220 4 | 5 | ROON=/usr/local/Roon 6 | ROONAPI=${ROON}/api 7 | ROONETC=${ROON}/etc 8 | ROONCONF=${ROONETC}/pyroonconf 9 | SCRIPT=get_zone_remaining.py 10 | 11 | [ -d ${ROONAPI} ] || exit 1 12 | 13 | cd ${ROONAPI} || exit 1 14 | 15 | [ -f $SCRIPT ] || exit 2 16 | 17 | # Use a Python virtual environment 18 | [ -f ${ROON}/venv/bin/activate ] && source ${ROON}/venv/bin/activate 19 | [[ ":$PATH:" == *":/usr/local/Roon/venv/bin:"* ]] || { 20 | export PATH=/usr/local/Roon/venv/bin:${PATH} 21 | } 22 | 23 | DEFZONE=$(grep ^DefaultZone ${ROONETC}/roon_api.ini | awk -F '=' ' { print $2 } ') 24 | # Remove leading and trailing spaces in DEFZONE 25 | DEFZONE="$(echo -e "${DEFZONE}" | sed -e 's/^[[:space:]]*//' -e 's/[[:space:]]*$//')" 26 | 27 | # Get the zone if it is set 28 | if [ -f ${ROONCONF} ] 29 | then 30 | . ${ROONCONF} 31 | else 32 | ${ROON}/bin/set_zone "${DEFZONE}" 33 | . ${ROONCONF} 34 | fi 35 | 36 | ZONE= 37 | # Parse the arguments to get the command and zone 38 | while getopts "z:" flag; do 39 | case $flag in 40 | z) 41 | ZONE="$OPTARG" 42 | ;; 43 | esac 44 | done 45 | 46 | [ "${ZONE}" ] && { 47 | if [ "${ZONE}" == "default" ]; then 48 | ROON_ZONE="${DEFZONE}" 49 | else 50 | [ "${ZONE}" == "last" ] || ROON_ZONE="${ZONE}" 51 | fi 52 | } 53 | [ "${ROON_ZONE}" ] || ROON_ZONE="${DEFZONE}" 54 | 55 | have_python3=$(type -p python3) 56 | if [ "${have_python3}" ] 57 | then 58 | python3 $SCRIPT -z "$ROON_ZONE" 59 | else 60 | python $SCRIPT -z "$ROON_ZONE" 61 | fi 62 | 63 | -------------------------------------------------------------------------------- /bin/get_zone_volume: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # 3 | # shellcheck disable=SC1090,SC2220 4 | 5 | ROON=/usr/local/Roon 6 | ROONAPI=${ROON}/api 7 | ROONETC=${ROON}/etc 8 | ROONCONF=${ROONETC}/pyroonconf 9 | SCRIPT=get_zone_attributes.py 10 | 11 | [ -d ${ROONAPI} ] || exit 1 12 | 13 | cd ${ROONAPI} || exit 1 14 | 15 | [ -f $SCRIPT ] || exit 2 16 | 17 | # Use a Python virtual environment 18 | [ -f ${ROON}/venv/bin/activate ] && source ${ROON}/venv/bin/activate 19 | [[ ":$PATH:" == *":/usr/local/Roon/venv/bin:"* ]] || { 20 | export PATH=/usr/local/Roon/venv/bin:${PATH} 21 | } 22 | 23 | DEFZONE=$(grep ^DefaultZone ${ROONETC}/roon_api.ini | awk -F '=' ' { print $2 } ') 24 | # Remove leading and trailing spaces in DEFZONE 25 | DEFZONE="$(echo -e "${DEFZONE}" | sed -e 's/^[[:space:]]*//' -e 's/[[:space:]]*$//')" 26 | 27 | # Get the zone if it is set 28 | if [ -f ${ROONCONF} ]; then 29 | . ${ROONCONF} 30 | else 31 | ${ROON}/bin/set_zone "${DEFZONE}" 32 | . ${ROONCONF} 33 | fi 34 | 35 | grparg= 36 | number= 37 | ZONE= 38 | # Parse the arguments to get the command and zone 39 | while getopts "gnz:" flag; do 40 | case $flag in 41 | g) 42 | grparg="-g" 43 | ;; 44 | n) 45 | number=1 46 | ;; 47 | z) 48 | ZONE="$OPTARG" 49 | ;; 50 | esac 51 | done 52 | 53 | [ "${ZONE}" ] && { 54 | if [ "${ZONE}" == "default" ]; then 55 | ROON_ZONE="${DEFZONE}" 56 | else 57 | [ "${ZONE}" == "last" ] || ROON_ZONE="${ZONE}" 58 | fi 59 | } 60 | [ "${ROON_ZONE}" ] || ROON_ZONE="${DEFZONE}" 61 | 62 | have_jq=$(type -p jq) 63 | have_python3=$(type -p python3) 64 | 65 | if [ "${have_python3}" ]; then 66 | PYTHON=python3 67 | else 68 | PYTHON=python 69 | fi 70 | if [ "${have_jq}" ]; then 71 | if [ "${number}" ]; then 72 | ${PYTHON} $SCRIPT ${grparg} -z "$ROON_ZONE" | jq -r '.[].volume.value?' 73 | else 74 | ${PYTHON} $SCRIPT ${grparg} -z "$ROON_ZONE" | \ 75 | jq -r '.[]? | "\(.display_name): Volume = \(.volume.value), Min = \(.volume.min), Max = \(.volume.max)"' 76 | fi 77 | else 78 | # TODO: Parse returned JSON without jq 79 | ${PYTHON} $SCRIPT ${grparg} -z "$ROON_ZONE" 80 | fi 81 | -------------------------------------------------------------------------------- /bin/get_zones: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # 3 | # shellcheck disable=SC1090,SC2220 4 | 5 | ROON=/usr/local/Roon 6 | ROONAPI=${ROON}/api 7 | ROONETC=${ROON}/etc 8 | ROONCONF=${ROONETC}/pyroonconf 9 | LIST=list_zones.py 10 | ZONE= 11 | 12 | [ -d ${ROONAPI} ] || exit 1 13 | 14 | cd ${ROONAPI} || exit 1 15 | 16 | [ -f $LIST ] || exit 2 17 | 18 | # Use a Python virtual environment 19 | [ -f ${ROON}/venv/bin/activate ] && source ${ROON}/venv/bin/activate 20 | [[ ":$PATH:" == *":/usr/local/Roon/venv/bin:"* ]] || { 21 | export PATH=/usr/local/Roon/venv/bin:${PATH} 22 | } 23 | 24 | DEFZONE=$(grep ^DefaultZone ${ROONETC}/roon_api.ini | awk -F '=' ' { print $2 } ') 25 | # Remove leading and trailing spaces in DEFZONE 26 | DEFZONE="$(echo -e "${DEFZONE}" | sed -e 's/^[[:space:]]*//' -e 's/[[:space:]]*$//')" 27 | 28 | if [ -f ${ROONCONF} ] 29 | then 30 | . ${ROONCONF} 31 | else 32 | ${ROON}/bin/set_zone "${DEFZONE}" 33 | . ${ROONCONF} 34 | fi 35 | 36 | [ "$1" ] && ZONE="$*" 37 | 38 | [ "${ZONE}" ] && { 39 | if [ "${ZONE}" == "default" ]; then 40 | ZONE="${DEFZONE}" 41 | else 42 | [ "${ZONE}" == "last" ] && ZONE="${ROON_ZONE}" 43 | fi 44 | } 45 | 46 | # Get all zones if no zone is specified 47 | [ "${ZONE}" ] || ZONE="__all__" 48 | 49 | have_python3=$(type -p python3) 50 | if [ "${have_python3}" ] 51 | then 52 | python3 $LIST -g -z "${ZONE}" 53 | else 54 | python $LIST -g -z "${ZONE}" 55 | fi 56 | -------------------------------------------------------------------------------- /bin/list_album_tracks: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # 3 | # shellcheck disable=SC1090,SC2220 4 | 5 | ROON=/usr/local/Roon 6 | ROONAPI=${ROON}/api 7 | ROONETC=${ROON}/etc 8 | ROONCONF=${ROONETC}/pyroonconf 9 | LIST=list_album_tracks.py 10 | ALBUM= 11 | TRACK= 12 | EXALBUM= 13 | EXTRACK= 14 | 15 | [ -d ${ROONAPI} ] || exit 1 16 | 17 | cd ${ROONAPI} || exit 1 18 | 19 | [ -f $LIST ] || exit 2 20 | 21 | # First argument is album, second is track 22 | # Third optional argument is album exclusion string (optional) 23 | # Fourth optional argument is track exclusion string (optional) 24 | [ "$1" ] && ALBUM="$1" 25 | [ "$2" ] && TRACK="$2" 26 | [ "$3" ] && EXALBUM="$3" 27 | [ "$4" ] && EXTRACK="$4" 28 | 29 | # Use a Python virtual environment 30 | [ -f ${ROON}/venv/bin/activate ] && source ${ROON}/venv/bin/activate 31 | [[ ":$PATH:" == *":/usr/local/Roon/venv/bin:"* ]] || { 32 | export PATH=/usr/local/Roon/venv/bin:${PATH} 33 | } 34 | 35 | DEFZONE=$(grep ^DefaultZone ${ROONETC}/roon_api.ini | awk -F '=' ' { print $2 } ') 36 | # Remove leading and trailing spaces in DEFZONE 37 | DEFZONE="$(echo -e "${DEFZONE}" | sed -e 's/^[[:space:]]*//' -e 's/[[:space:]]*$//')" 38 | 39 | # Get the zone if it is set 40 | if [ -f ${ROONCONF} ] 41 | then 42 | . ${ROONCONF} 43 | else 44 | ${ROON}/bin/set_zone "${DEFZONE}" 45 | . ${ROONCONF} 46 | fi 47 | [ "${ROON_ZONE}" ] || ROON_ZONE="${DEFZONE}" 48 | 49 | # Get the default album if one is not provided 50 | [ "${ALBUM}" ] || { 51 | ALBUM=$(grep ^Defaultalbum ${ROONETC}/roon_api.ini | awk -F '=' ' { print $2 } ') 52 | # Remove leading and trailing spaces in ALBUM 53 | ALBUM="$(echo -e "${ALBUM}" | sed -e 's/^[[:space:]]*//' -e 's/[[:space:]]*$//')" 54 | } 55 | 56 | [ "${TRACK}" ] || TRACK="__all__" 57 | 58 | # Construct the exclusion args if passed 59 | EXARGS= 60 | [ "${EXTRACK}" ] && EXARGS="-X ${EXTRACK}" 61 | [ "${EXALBUM}" ] && EXARGS="-x ${EXALBUM} ${EXARGS}" 62 | 63 | have_python3=$(type -p python3) 64 | if [ "${have_python3}" ] 65 | then 66 | python3 $LIST -t "$TRACK" -a "$ALBUM" -z "$ROON_ZONE" $EXARGS 67 | else 68 | python $LIST -t "$TRACK" -a "$ALBUM" -z "$ROON_ZONE" $EXARGS 69 | fi 70 | -------------------------------------------------------------------------------- /bin/list_artist_albums: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # 3 | # shellcheck disable=SC1090,SC2220 4 | 5 | ROON=/usr/local/Roon 6 | ROONAPI=${ROON}/api 7 | ROONETC=${ROON}/etc 8 | ROONCONF=${ROONETC}/pyroonconf 9 | LIST=list_artist_albums.py 10 | ARTIST= 11 | ALBUM= 12 | EXARTIST= 13 | EXALBUM= 14 | 15 | [ -d ${ROONAPI} ] || exit 1 16 | 17 | cd ${ROONAPI} || exit 1 18 | 19 | [ -f $LIST ] || exit 2 20 | 21 | # First argument is artist, second is album (required) 22 | # Third optional argument is artist exclusion string (optional) 23 | # Fourth optional argument is album exclusion string (optional) 24 | [ "$1" ] && ARTIST="$1" 25 | [ "$2" ] && ALBUM="$2" 26 | [ "$3" ] && EXARTIST="$3" 27 | [ "$4" ] && EXALBUM="$4" 28 | 29 | # Use a Python virtual environment 30 | [ -f ${ROON}/venv/bin/activate ] && source ${ROON}/venv/bin/activate 31 | [[ ":$PATH:" == *":/usr/local/Roon/venv/bin:"* ]] || { 32 | export PATH=/usr/local/Roon/venv/bin:${PATH} 33 | } 34 | 35 | DEFZONE=$(grep ^DefaultZone ${ROONETC}/roon_api.ini | awk -F '=' ' { print $2 } ') 36 | # Remove leading and trailing spaces in DEFZONE 37 | DEFZONE="$(echo -e "${DEFZONE}" | sed -e 's/^[[:space:]]*//' -e 's/[[:space:]]*$//')" 38 | 39 | # Get the zone if it is set 40 | if [ -f ${ROONCONF} ] 41 | then 42 | . ${ROONCONF} 43 | else 44 | ${ROON}/bin/set_zone "${DEFZONE}" 45 | . ${ROONCONF} 46 | fi 47 | [ "${ROON_ZONE}" ] || ROON_ZONE="${DEFZONE}" 48 | 49 | # Get the default artist if one is not provided 50 | [ "${ARTIST}" ] || { 51 | ARTIST=$(grep ^DefaultArtist ${ROONETC}/roon_api.ini | awk -F '=' ' { print $2 } ') 52 | # Remove leading and trailing spaces in ARTIST 53 | ARTIST="$(echo -e "${ARTIST}" | sed -e 's/^[[:space:]]*//' -e 's/[[:space:]]*$//')" 54 | } 55 | 56 | [ "${ALBUM}" ] || ALBUM="__all__" 57 | 58 | # Construct the exclusion args if passed 59 | EXARGS= 60 | [ "${EXALBUM}" ] && EXARGS="-X ${EXALBUM}" 61 | [ "${EXARTIST}" ] && EXARGS="-x ${EXARTIST} ${EXARGS}" 62 | 63 | have_python3=$(type -p python3) 64 | if [ "${have_python3}" ] 65 | then 66 | python3 $LIST -A "$ALBUM" -a "$ARTIST" -z "$ROON_ZONE" $EXARGS 67 | else 68 | python $LIST -A "$ALBUM" -a "$ARTIST" -z "$ROON_ZONE" $EXARGS 69 | fi 70 | -------------------------------------------------------------------------------- /bin/list_artist_tracks: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # 3 | # shellcheck disable=SC1090,SC2220 4 | 5 | ROON=/usr/local/Roon 6 | ROONAPI=${ROON}/api 7 | ROONETC=${ROON}/etc 8 | ROONCONF=${ROONETC}/pyroonconf 9 | LIST=list_artist_tracks.py 10 | ARTIST= 11 | TRACK= 12 | EXARTIST= 13 | EXTRACK= 14 | 15 | [ -d ${ROONAPI} ] || exit 1 16 | 17 | cd ${ROONAPI} || exit 1 18 | 19 | [ -f $LIST ] || exit 2 20 | 21 | # First argument is artist, second is track 22 | # Third optional argument is artist exclusion string (optional) 23 | # Fourth optional argument is track exclusion string (optional) 24 | [ "$1" ] && ARTIST="$1" 25 | [ "$2" ] && TRACK="$2" 26 | [ "$3" ] && EXARTIST="$3" 27 | [ "$4" ] && EXTRACK="$4" 28 | 29 | # Use a Python virtual environment 30 | [ -f ${ROON}/venv/bin/activate ] && source ${ROON}/venv/bin/activate 31 | [[ ":$PATH:" == *":/usr/local/Roon/venv/bin:"* ]] || { 32 | export PATH=/usr/local/Roon/venv/bin:${PATH} 33 | } 34 | 35 | DEFZONE=$(grep ^DefaultZone ${ROONETC}/roon_api.ini | awk -F '=' ' { print $2 } ') 36 | # Remove leading and trailing spaces in DEFZONE 37 | DEFZONE="$(echo -e "${DEFZONE}" | sed -e 's/^[[:space:]]*//' -e 's/[[:space:]]*$//')" 38 | 39 | # Get the zone if it is set 40 | if [ -f ${ROONCONF} ] 41 | then 42 | . ${ROONCONF} 43 | else 44 | ${ROON}/bin/set_zone "${DEFZONE}" 45 | . ${ROONCONF} 46 | fi 47 | [ "${ROON_ZONE}" ] || ROON_ZONE="${DEFZONE}" 48 | 49 | # Get the default artist if one is not provided 50 | [ "${ARTIST}" ] || { 51 | ARTIST=$(grep ^DefaultArtist ${ROONETC}/roon_api.ini | awk -F '=' ' { print $2 } ') 52 | # Remove leading and trailing spaces in ARTIST 53 | ARTIST="$(echo -e "${ARTIST}" | sed -e 's/^[[:space:]]*//' -e 's/[[:space:]]*$//')" 54 | } 55 | 56 | [ "${TRACK}" ] || TRACK="__all__" 57 | 58 | # Construct the exclusion args if passed 59 | EXARGS= 60 | [ "${EXTRACK}" ] && EXARGS="-X ${EXTRACK}" 61 | [ "${EXARTIST}" ] && EXARGS="-x ${EXARTIST} ${EXARGS}" 62 | 63 | have_python3=$(type -p python3) 64 | if [ "${have_python3}" ] 65 | then 66 | python3 $LIST -t "$TRACK" -a "$ARTIST" -z "$ROON_ZONE" $EXARGS 67 | else 68 | python $LIST -t "$TRACK" -a "$ARTIST" -z "$ROON_ZONE" $EXARGS 69 | fi 70 | -------------------------------------------------------------------------------- /bin/list_artists: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # 3 | # shellcheck disable=SC1090,SC2220 4 | 5 | ROON=/usr/local/Roon 6 | ROONAPI=${ROON}/api 7 | ROONETC=${ROON}/etc 8 | ROONCONF=${ROONETC}/pyroonconf 9 | LIST=list_artists.py 10 | ARTIST= 11 | EXARTIST= 12 | 13 | [ -d ${ROONAPI} ] || exit 1 14 | 15 | cd ${ROONAPI} || exit 1 16 | 17 | [ -f $LIST ] || exit 2 18 | 19 | ZONE= 20 | listargs= 21 | # Parse the arguments to get the zone 22 | while getopts "qz:" flag; do 23 | case $flag in 24 | q) 25 | listargs="-q" 26 | ;; 27 | z) 28 | ZONE="$OPTARG" 29 | ;; 30 | esac 31 | done 32 | shift $(( OPTIND - 1 )) 33 | 34 | [ "$1" ] && ARTIST="$1" 35 | [ "$2" ] && EXARTIST="$2" 36 | 37 | # Use a Python virtual environment 38 | [ -f ${ROON}/venv/bin/activate ] && source ${ROON}/venv/bin/activate 39 | [[ ":$PATH:" == *":/usr/local/Roon/venv/bin:"* ]] || { 40 | export PATH=/usr/local/Roon/venv/bin:${PATH} 41 | } 42 | 43 | DEFZONE=$(grep ^DefaultZone ${ROONETC}/roon_api.ini | awk -F '=' ' { print $2 } ') 44 | # Remove leading and trailing spaces in DEFZONE 45 | DEFZONE="$(echo -e "${DEFZONE}" | sed -e 's/^[[:space:]]*//' -e 's/[[:space:]]*$//')" 46 | 47 | # Get the zone if it is set 48 | if [ -f ${ROONCONF} ] 49 | then 50 | . ${ROONCONF} 51 | else 52 | ${ROON}/bin/set_zone "${DEFZONE}" 53 | . ${ROONCONF} 54 | fi 55 | 56 | [ "${ZONE}" ] && { 57 | if [ "${ZONE}" == "default" ]; then 58 | ROON_ZONE="${DEFZONE}" 59 | else 60 | [ "${ZONE}" == "last" ] || ROON_ZONE="${ZONE}" 61 | fi 62 | } 63 | # Use all zones if no zone is specified or set 64 | [ "${ROON_ZONE}" ] || ROON_ZONE="__all__" 65 | 66 | [ "${ARTIST}" ] || ARTIST="__all__" 67 | 68 | # Construct the exclusion args if passed 69 | EXARGS="${listargs}" 70 | [ "${EXARTIST}" ] && EXARGS="${EXARGS} -x ${EXARTIST}" 71 | 72 | have_python3=$(type -p python3) 73 | if [ "${have_python3}" ] 74 | then 75 | python3 $LIST -a "$ARTIST" -z "$ROON_ZONE" $EXARGS 76 | else 77 | python $LIST -a "$ARTIST" -z "$ROON_ZONE" $EXARGS 78 | fi 79 | -------------------------------------------------------------------------------- /bin/list_composer_albums: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # 3 | # shellcheck disable=SC1090,SC2220 4 | 5 | ROON=/usr/local/Roon 6 | ROONAPI=${ROON}/api 7 | ROONETC=${ROON}/etc 8 | ROONCONF=${ROONETC}/pyroonconf 9 | LIST=list_composer_albums.py 10 | COMPOSER= 11 | ALBUM= 12 | EXCOMPOSER= 13 | EXALBUM= 14 | 15 | [ -d ${ROONAPI} ] || exit 1 16 | 17 | cd ${ROONAPI} || exit 1 18 | 19 | [ -f $LIST ] || exit 2 20 | 21 | # First argument is composer, second is album (required) 22 | # Third optional argument is composer exclusion string (optional) 23 | # Fourth optional argument is album exclusion string (optional) 24 | [ "$1" ] && COMPOSER="$1" 25 | [ "$2" ] && ALBUM="$2" 26 | [ "$3" ] && EXCOMPOSER="$3" 27 | [ "$4" ] && EXALBUM="$4" 28 | 29 | # Use a Python virtual environment 30 | [ -f ${ROON}/venv/bin/activate ] && source ${ROON}/venv/bin/activate 31 | [[ ":$PATH:" == *":/usr/local/Roon/venv/bin:"* ]] || { 32 | export PATH=/usr/local/Roon/venv/bin:${PATH} 33 | } 34 | 35 | DEFZONE=$(grep ^DefaultZone ${ROONETC}/roon_api.ini | awk -F '=' ' { print $2 } ') 36 | # Remove leading and trailing spaces in DEFZONE 37 | DEFZONE="$(echo -e "${DEFZONE}" | sed -e 's/^[[:space:]]*//' -e 's/[[:space:]]*$//')" 38 | 39 | # Get the zone if it is set 40 | if [ -f ${ROONCONF} ] 41 | then 42 | . ${ROONCONF} 43 | else 44 | ${ROON}/bin/set_zone "${DEFZONE}" 45 | . ${ROONCONF} 46 | fi 47 | [ "${ROON_ZONE}" ] || ROON_ZONE="${DEFZONE}" 48 | 49 | # Get the default composer if one is not provided 50 | [ "${COMPOSER}" ] || { 51 | COMPOSER=$(grep ^DefaultComposer ${ROONETC}/roon_api.ini | awk -F '=' ' { print $2 } ') 52 | # Remove leading and trailing spaces in COMPOSER 53 | COMPOSER="$(echo -e "${COMPOSER}" | sed -e 's/^[[:space:]]*//' -e 's/[[:space:]]*$//')" 54 | } 55 | 56 | [ "${ALBUM}" ] || ALBUM="__all__" 57 | 58 | # Construct the exclusion args if passed 59 | EXARGS= 60 | [ "${EXALBUM}" ] && EXARGS="-X ${EXALBUM}" 61 | [ "${EXCOMPOSER}" ] && EXARGS="-x ${EXCOMPOSER} ${EXARGS}" 62 | 63 | have_python3=$(type -p python3) 64 | if [ "${have_python3}" ] 65 | then 66 | python3 $LIST -a "$ALBUM" -c "$COMPOSER" -z "$ROON_ZONE" $EXARGS 67 | else 68 | python $LIST -a "$ALBUM" -c "$COMPOSER" -z "$ROON_ZONE" $EXARGS 69 | fi 70 | -------------------------------------------------------------------------------- /bin/list_composers: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # 3 | # shellcheck disable=SC1090,SC2220 4 | 5 | ROON=/usr/local/Roon 6 | ROONAPI=${ROON}/api 7 | ROONETC=${ROON}/etc 8 | ROONCONF=${ROONETC}/pyroonconf 9 | LIST=list_composers.py 10 | COMPOSER= 11 | EXCOMPOSER= 12 | 13 | [ -d ${ROONAPI} ] || exit 1 14 | 15 | cd ${ROONAPI} || exit 1 16 | 17 | [ -f $LIST ] || exit 2 18 | 19 | ZONE= 20 | listargs= 21 | # Parse the arguments to get the zone 22 | while getopts "qz:" flag; do 23 | case $flag in 24 | q) 25 | listargs="-q" 26 | ;; 27 | z) 28 | ZONE="$OPTARG" 29 | ;; 30 | esac 31 | done 32 | shift $(( OPTIND - 1 )) 33 | 34 | [ "$1" ] && COMPOSER="$1" 35 | [ "$2" ] && EXCOMPOSER="$2" 36 | 37 | # Use a Python virtual environment 38 | [ -f ${ROON}/venv/bin/activate ] && source ${ROON}/venv/bin/activate 39 | [[ ":$PATH:" == *":/usr/local/Roon/venv/bin:"* ]] || { 40 | export PATH=/usr/local/Roon/venv/bin:${PATH} 41 | } 42 | 43 | DEFZONE=$(grep ^DefaultZone ${ROONETC}/roon_api.ini | awk -F '=' ' { print $2 } ') 44 | # Remove leading and trailing spaces in DEFZONE 45 | DEFZONE="$(echo -e "${DEFZONE}" | sed -e 's/^[[:space:]]*//' -e 's/[[:space:]]*$//')" 46 | 47 | # Get the zone if it is set 48 | if [ -f ${ROONCONF} ] 49 | then 50 | . ${ROONCONF} 51 | else 52 | ${ROON}/bin/set_zone "${DEFZONE}" 53 | . ${ROONCONF} 54 | fi 55 | 56 | [ "${ZONE}" ] && { 57 | if [ "${ZONE}" == "default" ]; then 58 | ROON_ZONE="${DEFZONE}" 59 | else 60 | [ "${ZONE}" == "last" ] || ROON_ZONE="${ZONE}" 61 | fi 62 | } 63 | # Use all zones if no zone is specified or set 64 | [ "${ROON_ZONE}" ] || ROON_ZONE="__all__" 65 | 66 | [ "${COMPOSER}" ] || COMPOSER="__all__" 67 | 68 | # Construct the exclusion args if passed 69 | EXARGS="${listargs}" 70 | [ "${EXCOMPOSER}" ] && EXARGS="${EXARGS} -x ${EXCOMPOSER}" 71 | 72 | have_python3=$(type -p python3) 73 | if [ "${have_python3}" ] 74 | then 75 | python3 $LIST -c "$COMPOSER" -z "$ROON_ZONE" $EXARGS 76 | else 77 | python $LIST -c "$COMPOSER" -z "$ROON_ZONE" $EXARGS 78 | fi 79 | -------------------------------------------------------------------------------- /bin/list_genre_albums: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # 3 | # shellcheck disable=SC1090,SC2220 4 | 5 | ROON=/usr/local/Roon 6 | ROONAPI=${ROON}/api 7 | ROONETC=${ROON}/etc 8 | ROONCONF=${ROONETC}/pyroonconf 9 | LIST=list_genre_albums.py 10 | GENRE= 11 | ALBUM= 12 | EXGENRE= 13 | EXALBUM= 14 | 15 | [ -d ${ROONAPI} ] || exit 1 16 | 17 | cd ${ROONAPI} || exit 1 18 | 19 | [ -f $LIST ] || exit 2 20 | 21 | # First argument is genre, second is album (required) 22 | # Third optional argument is genre exclusion string (optional) 23 | # Fourth optional argument is album exclusion string (optional) 24 | [ "$1" ] && GENRE="$1" 25 | [ "$2" ] && ALBUM="$2" 26 | [ "$3" ] && EXGENRE="$3" 27 | [ "$4" ] && EXALBUM="$4" 28 | 29 | # Use a Python virtual environment 30 | [ -f ${ROON}/venv/bin/activate ] && source ${ROON}/venv/bin/activate 31 | [[ ":$PATH:" == *":/usr/local/Roon/venv/bin:"* ]] || { 32 | export PATH=/usr/local/Roon/venv/bin:${PATH} 33 | } 34 | 35 | DEFZONE=$(grep ^DefaultZone ${ROONETC}/roon_api.ini | awk -F '=' ' { print $2 } ') 36 | # Remove leading and trailing spaces in DEFZONE 37 | DEFZONE="$(echo -e "${DEFZONE}" | sed -e 's/^[[:space:]]*//' -e 's/[[:space:]]*$//')" 38 | 39 | # Get the zone if it is set 40 | if [ -f ${ROONCONF} ] 41 | then 42 | . ${ROONCONF} 43 | else 44 | ${ROON}/bin/set_zone "${DEFZONE}" 45 | . ${ROONCONF} 46 | fi 47 | [ "${ROON_ZONE}" ] || ROON_ZONE="${DEFZONE}" 48 | 49 | # Get the default genre if one is not provided 50 | [ "${GENRE}" ] || { 51 | GENRE=$(grep ^DefaultGenre ${ROONETC}/roon_api.ini | awk -F '=' ' { print $2 } ') 52 | # Remove leading and trailing spaces in GENRE 53 | GENRE="$(echo -e "${GENRE}" | sed -e 's/^[[:space:]]*//' -e 's/[[:space:]]*$//')" 54 | } 55 | 56 | [ "${ALBUM}" ] || ALBUM="__all__" 57 | 58 | # Construct the exclusion args if passed 59 | EXARGS= 60 | [ "${EXALBUM}" ] && EXARGS="-X ${EXALBUM}" 61 | [ "${EXGENRE}" ] && EXARGS="-x ${EXGENRE} ${EXARGS}" 62 | 63 | have_python3=$(type -p python3) 64 | if [ "${have_python3}" ] 65 | then 66 | python3 $LIST -a "$ALBUM" -g "$GENRE" -z "$ROON_ZONE" $EXARGS 67 | else 68 | python $LIST -a "$ALBUM" -g "$GENRE" -z "$ROON_ZONE" $EXARGS 69 | fi 70 | -------------------------------------------------------------------------------- /bin/list_genre_artists: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # 3 | # shellcheck disable=SC1090,SC2220 4 | 5 | ROON=/usr/local/Roon 6 | ROONAPI=${ROON}/api 7 | ROONETC=${ROON}/etc 8 | ROONCONF=${ROONETC}/pyroonconf 9 | LIST=list_genre_artists.py 10 | GENRE= 11 | ARTIST= 12 | EXGENRE= 13 | EXARTIST= 14 | 15 | [ -d ${ROONAPI} ] || exit 1 16 | 17 | cd ${ROONAPI} || exit 1 18 | 19 | [ -f $LIST ] || exit 2 20 | 21 | # First argument is genre, second is artist (required) 22 | # Third optional argument is genre exclusion string (optional) 23 | # Fourth optional argument is artist exclusion string (optional) 24 | [ "$1" ] && GENRE="$1" 25 | [ "$2" ] && ARTIST="$2" 26 | [ "$3" ] && EXGENRE="$3" 27 | [ "$4" ] && EXARTIST="$4" 28 | 29 | # Use a Python virtual environment 30 | [ -f ${ROON}/venv/bin/activate ] && source ${ROON}/venv/bin/activate 31 | [[ ":$PATH:" == *":/usr/local/Roon/venv/bin:"* ]] || { 32 | export PATH=/usr/local/Roon/venv/bin:${PATH} 33 | } 34 | 35 | DEFZONE=$(grep ^DefaultZone ${ROONETC}/roon_api.ini | awk -F '=' ' { print $2 } ') 36 | # Remove leading and trailing spaces in DEFZONE 37 | DEFZONE="$(echo -e "${DEFZONE}" | sed -e 's/^[[:space:]]*//' -e 's/[[:space:]]*$//')" 38 | 39 | # Get the zone if it is set 40 | if [ -f ${ROONCONF} ] 41 | then 42 | . ${ROONCONF} 43 | else 44 | ${ROON}/bin/set_zone "${DEFZONE}" 45 | . ${ROONCONF} 46 | fi 47 | [ "${ROON_ZONE}" ] || ROON_ZONE="${DEFZONE}" 48 | 49 | # Get the default genre if one is not provided 50 | [ "${GENRE}" ] || { 51 | GENRE=$(grep ^DefaultGenre ${ROONETC}/roon_api.ini | awk -F '=' ' { print $2 } ') 52 | # Remove leading and trailing spaces in GENRE 53 | GENRE="$(echo -e "${GENRE}" | sed -e 's/^[[:space:]]*//' -e 's/[[:space:]]*$//')" 54 | } 55 | 56 | [ "${ARTIST}" ] || ARTIST="__all__" 57 | 58 | # Construct the exclusion args if passed 59 | EXARGS= 60 | [ "${EXARTIST}" ] && EXARGS="-X ${EXARTIST}" 61 | [ "${EXGENRE}" ] && EXARGS="-x ${EXGENRE} ${EXARGS}" 62 | 63 | have_python3=$(type -p python3) 64 | if [ "${have_python3}" ] 65 | then 66 | python3 $LIST -a "$ARTIST" -g "$GENRE" -z "$ROON_ZONE" $EXARGS 67 | else 68 | python $LIST -a "$ARTIST" -g "$GENRE" -z "$ROON_ZONE" $EXARGS 69 | fi 70 | -------------------------------------------------------------------------------- /bin/list_genres: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # 3 | # shellcheck disable=SC1090,SC2220 4 | 5 | ROON=/usr/local/Roon 6 | ROONAPI=${ROON}/api 7 | ROONETC=${ROON}/etc 8 | ROONCONF=${ROONETC}/pyroonconf 9 | LIST=list_genres.py 10 | GENRE= 11 | EXGENRE= 12 | 13 | [ -d ${ROONAPI} ] || exit 1 14 | 15 | cd ${ROONAPI} || exit 1 16 | 17 | [ -f $LIST ] || exit 2 18 | 19 | ZONE= 20 | listargs= 21 | # Parse the arguments to get the zone 22 | while getopts "qz:" flag; do 23 | case $flag in 24 | q) 25 | listargs="-q" 26 | ;; 27 | z) 28 | ZONE="$OPTARG" 29 | ;; 30 | esac 31 | done 32 | shift $(( OPTIND - 1 )) 33 | 34 | [ "$1" ] && GENRE="$1" 35 | [ "$2" ] && EXGENRE="$2" 36 | 37 | # Use a Python virtual environment 38 | [ -f ${ROON}/venv/bin/activate ] && source ${ROON}/venv/bin/activate 39 | [[ ":$PATH:" == *":/usr/local/Roon/venv/bin:"* ]] || { 40 | export PATH=/usr/local/Roon/venv/bin:${PATH} 41 | } 42 | 43 | DEFZONE=$(grep ^DefaultZone ${ROONETC}/roon_api.ini | awk -F '=' ' { print $2 } ') 44 | # Remove leading and trailing spaces in DEFZONE 45 | DEFZONE="$(echo -e "${DEFZONE}" | sed -e 's/^[[:space:]]*//' -e 's/[[:space:]]*$//')" 46 | 47 | # Get the zone if it is set 48 | if [ -f ${ROONCONF} ] 49 | then 50 | . ${ROONCONF} 51 | else 52 | ${ROON}/bin/set_zone "${DEFZONE}" 53 | . ${ROONCONF} 54 | fi 55 | 56 | [ "${ZONE}" ] && { 57 | if [ "${ZONE}" == "default" ]; then 58 | ROON_ZONE="${DEFZONE}" 59 | else 60 | [ "${ZONE}" == "last" ] || ROON_ZONE="${ZONE}" 61 | fi 62 | } 63 | # Use all zones if no zone is specified or set 64 | [ "${ROON_ZONE}" ] || ROON_ZONE="__all__" 65 | 66 | [ "${GENRE}" ] || GENRE="__all__" 67 | 68 | # Construct the exclusion args if passed 69 | EXARGS="${listargs}" 70 | [ "${EXGENRE}" ] && EXARGS="${EXARGS} -x ${EXGENRE}" 71 | 72 | have_python3=$(type -p python3) 73 | if [ "${have_python3}" ] 74 | then 75 | python3 $LIST -g "$GENRE" -z "$ROON_ZONE" $EXARGS 76 | else 77 | python $LIST -g "$GENRE" -z "$ROON_ZONE" $EXARGS 78 | fi 79 | -------------------------------------------------------------------------------- /bin/list_playlist_tracks: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # 3 | # shellcheck disable=SC1090,SC2220 4 | 5 | ROON=/usr/local/Roon 6 | ROONAPI=${ROON}/api 7 | ROONETC=${ROON}/etc 8 | ROONCONF=${ROONETC}/pyroonconf 9 | LIST=list_playlist_tracks.py 10 | PLAYLIST= 11 | TRACK= 12 | EXPLAYLIST= 13 | EXTRACK= 14 | 15 | [ -d ${ROONAPI} ] || exit 1 16 | 17 | cd ${ROONAPI} || exit 1 18 | 19 | [ -f $LIST ] || exit 2 20 | 21 | # First argument is playlist, second is track 22 | # Third optional argument is playlist exclusion string (optional) 23 | # Fourth optional argument is track exclusion string (optional) 24 | [ "$1" ] && PLAYLIST="$1" 25 | [ "$2" ] && TRACK="$2" 26 | [ "$3" ] && EXPLAYLIST="$3" 27 | [ "$4" ] && EXTRACK="$4" 28 | 29 | # Use a Python virtual environment 30 | [ -f ${ROON}/venv/bin/activate ] && source ${ROON}/venv/bin/activate 31 | [[ ":$PATH:" == *":/usr/local/Roon/venv/bin:"* ]] || { 32 | export PATH=/usr/local/Roon/venv/bin:${PATH} 33 | } 34 | 35 | DEFZONE=$(grep ^DefaultZone ${ROONETC}/roon_api.ini | awk -F '=' ' { print $2 } ') 36 | # Remove leading and trailing spaces in DEFZONE 37 | DEFZONE="$(echo -e "${DEFZONE}" | sed -e 's/^[[:space:]]*//' -e 's/[[:space:]]*$//')" 38 | 39 | # Get the zone if it is set 40 | if [ -f ${ROONCONF} ] 41 | then 42 | . ${ROONCONF} 43 | else 44 | ${ROON}/bin/set_zone "${DEFZONE}" 45 | . ${ROONCONF} 46 | fi 47 | [ "${ROON_ZONE}" ] || ROON_ZONE="${DEFZONE}" 48 | 49 | # Get the default playlist if one is not provided 50 | [ "${PLAYLIST}" ] || { 51 | PLAYLIST=$(grep ^DefaultPlaylist ${ROONETC}/roon_api.ini | awk -F '=' ' { print $2 } ') 52 | # Remove leading and trailing spaces in PLAYLIST 53 | PLAYLIST="$(echo -e "${PLAYLIST}" | sed -e 's/^[[:space:]]*//' -e 's/[[:space:]]*$//')" 54 | } 55 | 56 | [ "${TRACK}" ] || TRACK="__all__" 57 | 58 | # Construct the exclusion args if passed 59 | EXARGS= 60 | [ "${EXTRACK}" ] && EXARGS="-X ${EXTRACK}" 61 | [ "${EXPLAYLIST}" ] && EXARGS="-x ${EXPLAYLIST} ${EXARGS}" 62 | 63 | have_python3=$(type -p python3) 64 | if [ "${have_python3}" ] 65 | then 66 | python3 $LIST -t "$TRACK" -p "$PLAYLIST" -z "$ROON_ZONE" $EXARGS 67 | else 68 | python $LIST -t "$TRACK" -p "$PLAYLIST" -z "$ROON_ZONE" $EXARGS 69 | fi 70 | -------------------------------------------------------------------------------- /bin/list_playlists: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # 3 | # shellcheck disable=SC1090,SC2220 4 | 5 | ROON=/usr/local/Roon 6 | ROONAPI=${ROON}/api 7 | ROONETC=${ROON}/etc 8 | ROONCONF=${ROONETC}/pyroonconf 9 | LIST=list_playlists.py 10 | PLAYLIST= 11 | EXPLAYLIST= 12 | 13 | [ -d ${ROONAPI} ] || exit 1 14 | 15 | cd ${ROONAPI} || exit 1 16 | 17 | [ -f $LIST ] || exit 2 18 | 19 | ZONE= 20 | listargs= 21 | # Parse the arguments to get the zone 22 | while getopts "qz:" flag; do 23 | case $flag in 24 | q) 25 | listargs="-q" 26 | ;; 27 | z) 28 | ZONE="$OPTARG" 29 | ;; 30 | esac 31 | done 32 | shift $(( OPTIND - 1 )) 33 | 34 | [ "$1" ] && PLAYLIST="$1" 35 | [ "$2" ] && EXPLAYLIST="$2" 36 | 37 | # Use a Python virtual environment 38 | [ -f ${ROON}/venv/bin/activate ] && source ${ROON}/venv/bin/activate 39 | [[ ":$PATH:" == *":/usr/local/Roon/venv/bin:"* ]] || { 40 | export PATH=/usr/local/Roon/venv/bin:${PATH} 41 | } 42 | 43 | DEFZONE=$(grep ^DefaultZone ${ROONETC}/roon_api.ini | awk -F '=' ' { print $2 } ') 44 | # Remove leading and trailing spaces in DEFZONE 45 | DEFZONE="$(echo -e "${DEFZONE}" | sed -e 's/^[[:space:]]*//' -e 's/[[:space:]]*$//')" 46 | 47 | # Get the zone if it is set 48 | if [ -f ${ROONCONF} ] 49 | then 50 | . ${ROONCONF} 51 | else 52 | ${ROON}/bin/set_zone "${DEFZONE}" 53 | . ${ROONCONF} 54 | fi 55 | 56 | [ "${ZONE}" ] && { 57 | if [ "${ZONE}" == "default" ]; then 58 | ROON_ZONE="${DEFZONE}" 59 | else 60 | [ "${ZONE}" == "last" ] || ROON_ZONE="${ZONE}" 61 | fi 62 | } 63 | # Use all zones if no zone is specified or set 64 | [ "${ROON_ZONE}" ] || ROON_ZONE="__all__" 65 | 66 | # If no playlist search term is provided then list all 67 | [ "${PLAYLIST}" ] || PLAYLIST="__all__" 68 | 69 | # Construct the exclusion args if passed 70 | EXARGS="${listargs}" 71 | [ "${EXPLAYLIST}" ] && EXARGS="${EXARGS} -x ${EXPLAYLIST}" 72 | 73 | have_python3=$(type -p python3) 74 | if [ "${have_python3}" ] 75 | then 76 | python3 $LIST -p "$PLAYLIST" -z "$ROON_ZONE" $EXARGS 77 | else 78 | python $LIST -p "$PLAYLIST" -z "$ROON_ZONE" $EXARGS 79 | fi 80 | 81 | -------------------------------------------------------------------------------- /bin/list_radio: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # 3 | # shellcheck disable=SC1090,SC2220 4 | 5 | ROON=/usr/local/Roon 6 | ROONAPI=${ROON}/api 7 | ROONETC=${ROON}/etc 8 | ROONCONF=${ROONETC}/pyroonconf 9 | LIST=list_radio.py 10 | RADIO= 11 | 12 | [ -d ${ROONAPI} ] || exit 1 13 | 14 | cd ${ROONAPI} || exit 1 15 | 16 | [ -f $LIST ] || exit 2 17 | 18 | ZONE= 19 | listargs= 20 | # Parse the arguments to get the zone 21 | while getopts "qz:" flag; do 22 | case $flag in 23 | q) 24 | listargs="-q" 25 | ;; 26 | z) 27 | ZONE="$OPTARG" 28 | ;; 29 | esac 30 | done 31 | shift $(( OPTIND - 1 )) 32 | 33 | [ "$1" ] && RADIO="$*" 34 | 35 | # Use a Python virtual environment 36 | [ -f ${ROON}/venv/bin/activate ] && source ${ROON}/venv/bin/activate 37 | [[ ":$PATH:" == *":/usr/local/Roon/venv/bin:"* ]] || { 38 | export PATH=/usr/local/Roon/venv/bin:${PATH} 39 | } 40 | 41 | DEFZONE=$(grep ^DefaultZone ${ROONETC}/roon_api.ini | awk -F '=' ' { print $2 } ') 42 | # Remove leading and trailing spaces in DEFZONE 43 | DEFZONE="$(echo -e "${DEFZONE}" | sed -e 's/^[[:space:]]*//' -e 's/[[:space:]]*$//')" 44 | 45 | # Get the zone if it is set 46 | if [ -f ${ROONCONF} ] 47 | then 48 | . ${ROONCONF} 49 | else 50 | ${ROON}/bin/set_zone "${DEFZONE}" 51 | . ${ROONCONF} 52 | fi 53 | 54 | [ "${ZONE}" ] && { 55 | if [ "${ZONE}" == "default" ]; then 56 | ROON_ZONE="${DEFZONE}" 57 | else 58 | [ "${ZONE}" == "last" ] || ROON_ZONE="${ZONE}" 59 | fi 60 | } 61 | # Use all zones if no zone is specified or set 62 | [ "${ROON_ZONE}" ] || ROON_ZONE="__all__" 63 | 64 | [ "${RADIO}" ] || RADIO="__all__" 65 | 66 | have_python3=$(type -p python3) 67 | if [ "${have_python3}" ] 68 | then 69 | python3 $LIST -r "$RADIO" -z "$ROON_ZONE" ${listargs} 70 | else 71 | python $LIST -r "$RADIO" -z "$ROON_ZONE" ${listargs} 72 | fi 73 | 74 | -------------------------------------------------------------------------------- /bin/list_tags: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # 3 | # shellcheck disable=SC1090,SC2220 4 | 5 | ROON=/usr/local/Roon 6 | ROONAPI=${ROON}/api 7 | ROONETC=${ROON}/etc 8 | ROONCONF=${ROONETC}/pyroonconf 9 | LIST=list_tags.py 10 | TAG= 11 | 12 | [ -d ${ROONAPI} ] || exit 1 13 | 14 | cd ${ROONAPI} || exit 1 15 | 16 | [ -f $LIST ] || exit 2 17 | 18 | ZONE= 19 | listargs= 20 | # Parse the arguments to get the zone 21 | while getopts "qz:" flag; do 22 | case $flag in 23 | q) 24 | listargs="-q" 25 | ;; 26 | z) 27 | ZONE="$OPTARG" 28 | ;; 29 | esac 30 | done 31 | shift $(( OPTIND - 1 )) 32 | 33 | [ "$1" ] && TAG="$*" 34 | 35 | # Use a Python virtual environment 36 | [ -f ${ROON}/venv/bin/activate ] && source ${ROON}/venv/bin/activate 37 | [[ ":$PATH:" == *":/usr/local/Roon/venv/bin:"* ]] || { 38 | export PATH=/usr/local/Roon/venv/bin:${PATH} 39 | } 40 | 41 | DEFZONE=$(grep ^DefaultZone ${ROONETC}/roon_api.ini | awk -F '=' ' { print $2 } ') 42 | # Remove leading and trailing spaces in DEFZONE 43 | DEFZONE="$(echo -e "${DEFZONE}" | sed -e 's/^[[:space:]]*//' -e 's/[[:space:]]*$//')" 44 | 45 | # Get the zone if it is set 46 | if [ -f ${ROONCONF} ] 47 | then 48 | . ${ROONCONF} 49 | else 50 | ${ROON}/bin/set_zone "${DEFZONE}" 51 | . ${ROONCONF} 52 | fi 53 | 54 | [ "${ZONE}" ] && { 55 | if [ "${ZONE}" == "default" ]; then 56 | ROON_ZONE="${DEFZONE}" 57 | else 58 | [ "${ZONE}" == "last" ] || ROON_ZONE="${ZONE}" 59 | fi 60 | } 61 | # Use all zones if no zone is specified or set 62 | [ "${ROON_ZONE}" ] || ROON_ZONE="__all__" 63 | 64 | [ "${TAG}" ] || TAG="__all__" 65 | 66 | have_python3=$(type -p python3) 67 | if [ "${have_python3}" ] 68 | then 69 | python3 $LIST -t "$TAG" -z "$ROON_ZONE" ${listargs} 70 | else 71 | python $LIST -t "$TAG" -z "$ROON_ZONE" ${listargs} 72 | fi 73 | 74 | -------------------------------------------------------------------------------- /bin/list_tracks: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # 3 | # shellcheck disable=SC1090,SC2220 4 | 5 | ROON=/usr/local/Roon 6 | ROONAPI=${ROON}/api 7 | ROONETC=${ROON}/etc 8 | ROONCONF=${ROONETC}/pyroonconf 9 | LIST=list_tracks.py 10 | TRACK= 11 | EXTRACK= 12 | 13 | [ -d ${ROONAPI} ] || exit 1 14 | 15 | cd ${ROONAPI} || exit 1 16 | 17 | [ -f $LIST ] || exit 2 18 | 19 | listargs= 20 | ZONE= 21 | # Parse the arguments to get the zone 22 | while getopts "qz:" flag; do 23 | case $flag in 24 | z) 25 | ZONE="$OPTARG" 26 | ;; 27 | q) 28 | listargs="-q" 29 | ;; 30 | esac 31 | done 32 | shift $(( OPTIND - 1 )) 33 | 34 | # First argument is track search term 35 | # Second argument is track exclusion string (optional) 36 | [ "$1" ] && TRACK="$1" 37 | [ "$2" ] && EXTRACK="$2" 38 | 39 | # Use a Python virtual environment 40 | [ -f ${ROON}/venv/bin/activate ] && source ${ROON}/venv/bin/activate 41 | [[ ":$PATH:" == *":/usr/local/Roon/venv/bin:"* ]] || { 42 | export PATH=/usr/local/Roon/venv/bin:${PATH} 43 | } 44 | 45 | DEFZONE=$(grep ^DefaultZone ${ROONETC}/roon_api.ini | awk -F '=' ' { print $2 } ') 46 | # Remove leading and trailing spaces in DEFZONE 47 | DEFZONE="$(echo -e "${DEFZONE}" | sed -e 's/^[[:space:]]*//' -e 's/[[:space:]]*$//')" 48 | 49 | # Get the zone if it is set 50 | if [ -f ${ROONCONF} ] 51 | then 52 | . ${ROONCONF} 53 | else 54 | ${ROON}/bin/set_zone "${DEFZONE}" 55 | . ${ROONCONF} 56 | fi 57 | 58 | [ "${ZONE}" ] && { 59 | if [ "${ZONE}" == "default" ]; then 60 | ROON_ZONE="${DEFZONE}" 61 | else 62 | [ "${ZONE}" == "last" ] || ROON_ZONE="${ZONE}" 63 | fi 64 | } 65 | # Use all zones if no zone is specified or set 66 | [ "${ROON_ZONE}" ] || ROON_ZONE="__all__" 67 | 68 | [ "${TRACK}" ] || TRACK="__all__" 69 | 70 | # Construct the exclusion args if passed 71 | EXARGS= 72 | [ "${EXTRACK}" ] && EXARGS="-x ${EXTRACK}" 73 | 74 | have_python3=$(type -p python3) 75 | if [ "${have_python3}" ] 76 | then 77 | python3 $LIST -t "$TRACK" -z "$ROON_ZONE" $EXARGS 78 | else 79 | python $LIST -t "$TRACK" -z "$ROON_ZONE" $EXARGS 80 | fi 81 | -------------------------------------------------------------------------------- /bin/list_zones: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # 3 | # shellcheck disable=SC1090,SC2220 4 | 5 | ROON=/usr/local/Roon 6 | ROONAPI=${ROON}/api 7 | ROONETC=${ROON}/etc 8 | ROONCONF=${ROONETC}/pyroonconf 9 | LIST=list_zones.py 10 | 11 | [ -d ${ROONAPI} ] || exit 1 12 | 13 | cd ${ROONAPI} || exit 1 14 | 15 | [ -f $LIST ] || exit 2 16 | 17 | ZONE= 18 | listargs= 19 | # Parse the arguments to get the zone 20 | while getopts "q" flag; do 21 | case $flag in 22 | q) 23 | listargs="-q" 24 | ;; 25 | esac 26 | done 27 | shift $(( OPTIND - 1 )) 28 | 29 | # Use a Python virtual environment 30 | [ -f ${ROON}/venv/bin/activate ] && source ${ROON}/venv/bin/activate 31 | [[ ":$PATH:" == *":/usr/local/Roon/venv/bin:"* ]] || { 32 | export PATH=/usr/local/Roon/venv/bin:${PATH} 33 | } 34 | 35 | DEFZONE=$(grep ^DefaultZone ${ROONETC}/roon_api.ini | awk -F '=' ' { print $2 } ') 36 | # Remove leading and trailing spaces in DEFZONE 37 | DEFZONE="$(echo -e "${DEFZONE}" | sed -e 's/^[[:space:]]*//' -e 's/[[:space:]]*$//')" 38 | 39 | if [ -f ${ROONCONF} ] 40 | then 41 | . ${ROONCONF} 42 | else 43 | ${ROON}/bin/set_zone "${DEFZONE}" 44 | . ${ROONCONF} 45 | fi 46 | 47 | [ "$1" ] && ZONE="$*" 48 | 49 | [ "${ZONE}" ] && { 50 | if [ "${ZONE}" == "default" ]; then 51 | ZONE="${DEFZONE}" 52 | else 53 | [ "${ZONE}" == "last" ] && ZONE="${ROON_ZONE}" 54 | fi 55 | } 56 | 57 | # List all zones if no zones are specified 58 | [ "${ZONE}" ] || ZONE="__all__" 59 | 60 | have_python3=$(type -p python3) 61 | if [ "${have_python3}" ] 62 | then 63 | python3 $LIST -z "$ZONE" ${listargs} 64 | else 65 | python $LIST -z "$ZONE" ${listargs} 66 | fi 67 | -------------------------------------------------------------------------------- /bin/play_album: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # 3 | # shellcheck disable=SC1090,SC2220 4 | 5 | ROON=/usr/local/Roon 6 | ROONAPI=${ROON}/api 7 | ROONETC=${ROON}/etc 8 | ROONCONF=${ROONETC}/pyroonconf 9 | PLAY=play_album.py 10 | ALBUM= 11 | EXALBUM= 12 | ZONE= 13 | 14 | [ -d ${ROONAPI} ] || exit 1 15 | 16 | cd ${ROONAPI} || exit 1 17 | 18 | [ -f $PLAY ] || exit 2 19 | 20 | # Parse the arguments to get the zone 21 | while getopts "z:" flag; do 22 | case $flag in 23 | z) 24 | ZONE="$OPTARG" 25 | ;; 26 | esac 27 | done 28 | shift $(( OPTIND - 1 )) 29 | 30 | [ "$1" ] && ALBUM="$1" 31 | [ "$2" ] && EXALBUM="$2" 32 | 33 | # Use a Python virtual environment 34 | [ -f ${ROON}/venv/bin/activate ] && source ${ROON}/venv/bin/activate 35 | [[ ":$PATH:" == *":/usr/local/Roon/venv/bin:"* ]] || { 36 | export PATH=/usr/local/Roon/venv/bin:${PATH} 37 | } 38 | 39 | DEFZONE=$(grep ^DefaultZone ${ROONETC}/roon_api.ini | awk -F '=' ' { print $2 } ') 40 | # Remove leading and trailing spaces in DEFZONE 41 | DEFZONE="$(echo -e "${DEFZONE}" | sed -e 's/^[[:space:]]*//' -e 's/[[:space:]]*$//')" 42 | 43 | # Get the zone if it is set 44 | if [ -f ${ROONCONF} ] 45 | then 46 | . ${ROONCONF} 47 | else 48 | ${ROON}/bin/set_zone "${DEFZONE}" 49 | . ${ROONCONF} 50 | fi 51 | 52 | [ "${ZONE}" ] && { 53 | if [ "${ZONE}" == "default" ]; then 54 | ROON_ZONE="${DEFZONE}" 55 | else 56 | [ "${ZONE}" == "last" ] || ROON_ZONE="${ZONE}" 57 | fi 58 | } 59 | # Use all zones if no zone is specified or set 60 | [ "${ROON_ZONE}" ] || ROON_ZONE="__all__" 61 | 62 | # Get the default album if one is not provided 63 | [ "${ALBUM}" ] || { 64 | ALBUM=$(grep ^DefaultAlbum ${ROONETC}/roon_api.ini | awk -F '=' ' { print $2 } ') 65 | # Remove leading and trailing spaces in ALBUM 66 | ALBUM="$(echo -e "${ALBUM}" | sed -e 's/^[[:space:]]*//' -e 's/[[:space:]]*$//')" 67 | } 68 | # Construct the exclusion args if passed 69 | EXARGS= 70 | [ "${EXALBUM}" ] && EXARGS="-x ${EXALBUM}" 71 | 72 | have_python3=$(type -p python3) 73 | if [ "${have_python3}" ] 74 | then 75 | python3 $PLAY -a "$ALBUM" -z "$ROON_ZONE" $EXARGS 76 | else 77 | python $PLAY -a "$ALBUM" -z "$ROON_ZONE" $EXARGS 78 | fi 79 | 80 | ${ROON}/bin/list_album_tracks "${ALBUM}" 81 | -------------------------------------------------------------------------------- /bin/play_album_track: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # 3 | # shellcheck disable=SC1090,SC2220 4 | 5 | ROON=/usr/local/Roon 6 | ROONAPI=${ROON}/api 7 | ROONETC=${ROON}/etc 8 | ROONCONF=${ROONETC}/pyroonconf 9 | PLAY=play_album_track.py 10 | ALBUM= 11 | TRACK= 12 | EXALBUM= 13 | 14 | [ -d ${ROONAPI} ] || exit 1 15 | 16 | cd ${ROONAPI} || exit 1 17 | 18 | [ -f $PLAY ] || exit 2 19 | 20 | ZONE= 21 | # Parse the arguments to get the zone 22 | while getopts "z:" flag; do 23 | case $flag in 24 | z) 25 | ZONE="$OPTARG" 26 | ;; 27 | esac 28 | done 29 | shift $(( OPTIND - 1 )) 30 | 31 | [ "$1" ] && ALBUM="$1" 32 | [ "$2" ] && TRACK="$2" 33 | [ "$3" ] && EXALBUM="$3" 34 | 35 | [ "${ALBUM}" ] || { 36 | printf "\nAlbum title required. Exiting.\n" 37 | exit 1 38 | } 39 | [ "${TRACK}" ] || TRACK="__all__" 40 | 41 | # Use a Python virtual environment 42 | [ -f ${ROON}/venv/bin/activate ] && source ${ROON}/venv/bin/activate 43 | [[ ":$PATH:" == *":/usr/local/Roon/venv/bin:"* ]] || { 44 | export PATH=/usr/local/Roon/venv/bin:${PATH} 45 | } 46 | 47 | DEFZONE=$(grep ^DefaultZone ${ROONETC}/roon_api.ini | awk -F '=' ' { print $2 } ') 48 | # Remove leading and trailing spaces in DEFZONE 49 | DEFZONE="$(echo -e "${DEFZONE}" | sed -e 's/^[[:space:]]*//' -e 's/[[:space:]]*$//')" 50 | 51 | # Get the zone if it is set 52 | if [ -f ${ROONCONF} ] 53 | then 54 | . ${ROONCONF} 55 | else 56 | ${ROON}/bin/set_zone "${DEFZONE}" 57 | . ${ROONCONF} 58 | fi 59 | 60 | [ "${ZONE}" ] && { 61 | if [ "${ZONE}" == "default" ]; then 62 | ROON_ZONE="${DEFZONE}" 63 | else 64 | [ "${ZONE}" == "last" ] || ROON_ZONE="${ZONE}" 65 | fi 66 | } 67 | # Use all zones if no zone is specified or set 68 | [ "${ROON_ZONE}" ] || ROON_ZONE="__all__" 69 | 70 | [ "${EXALBUM}" ] && EXARGS="-x ${EXALBUM}" 71 | 72 | have_python3=$(type -p python3) 73 | if [ "${have_python3}" ] 74 | then 75 | PYTHON=python3 76 | else 77 | PYTHON=python 78 | fi 79 | 80 | ${PYTHON} $PLAY -a "$ALBUM" -t "$TRACK" -z "$ROON_ZONE" "$EXARGS" 81 | -------------------------------------------------------------------------------- /bin/play_artist: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # 3 | # shellcheck disable=SC1090,SC2220 4 | 5 | ROON=/usr/local/Roon 6 | ROONAPI=${ROON}/api 7 | ROONETC=${ROON}/etc 8 | ROONCONF=${ROONETC}/pyroonconf 9 | PLAY=play_artist.py 10 | ARTIST= 11 | EXARTIST= 12 | 13 | [ -d ${ROONAPI} ] || exit 1 14 | 15 | cd ${ROONAPI} || exit 1 16 | 17 | [ -f $PLAY ] || exit 2 18 | 19 | SHUFFLED= 20 | ZONE= 21 | # Parse the arguments to get the play order and zone 22 | while getopts "sz:" flag; do 23 | case $flag in 24 | z) 25 | ZONE="$OPTARG" 26 | ;; 27 | s) 28 | SHUFFLED="-s" 29 | ;; 30 | esac 31 | done 32 | shift $(( OPTIND - 1 )) 33 | 34 | [ "$1" ] && ARTIST="$1" 35 | [ "$2" ] && EXARTIST="$2" 36 | 37 | # Use a Python virtual environment 38 | [ -f ${ROON}/venv/bin/activate ] && source ${ROON}/venv/bin/activate 39 | [[ ":$PATH:" == *":/usr/local/Roon/venv/bin:"* ]] || { 40 | export PATH=/usr/local/Roon/venv/bin:${PATH} 41 | } 42 | 43 | DEFZONE=$(grep ^DefaultZone ${ROONETC}/roon_api.ini | awk -F '=' ' { print $2 } ') 44 | # Remove leading and trailing spaces in DEFZONE 45 | DEFZONE="$(echo -e "${DEFZONE}" | sed -e 's/^[[:space:]]*//' -e 's/[[:space:]]*$//')" 46 | 47 | # Get the zone if it is set 48 | if [ -f ${ROONCONF} ] 49 | then 50 | . ${ROONCONF} 51 | else 52 | ${ROON}/bin/set_zone "${DEFZONE}" 53 | . ${ROONCONF} 54 | fi 55 | 56 | [ "${ZONE}" ] && { 57 | if [ "${ZONE}" == "default" ]; then 58 | ROON_ZONE="${DEFZONE}" 59 | else 60 | [ "${ZONE}" == "last" ] || ROON_ZONE="${ZONE}" 61 | fi 62 | } 63 | # Use all zones if no zone is specified or set 64 | [ "${ROON_ZONE}" ] || ROON_ZONE="__all__" 65 | 66 | # Get the default artist if one is not provided 67 | [ "${ARTIST}" ] || { 68 | ARTIST=$(grep ^DefaultArtist ${ROONETC}/roon_api.ini | awk -F '=' ' { print $2 } ') 69 | # Remove leading and trailing spaces in ARTIST 70 | ARTIST="$(echo -e "${ARTIST}" | sed -e 's/^[[:space:]]*//' -e 's/[[:space:]]*$//')" 71 | } 72 | # Construct the exclusion args if passed 73 | EXARGS="${SHUFFLED}" 74 | [ "${EXARTIST}" ] && EXARGS="-x ${EXARTIST} ${EXARGS}" 75 | 76 | have_python3=$(type -p python3) 77 | if [ "${have_python3}" ] 78 | then 79 | python3 $PLAY -a "${ARTIST}" -z "$ROON_ZONE" $EXARGS 80 | else 81 | python $PLAY -a "${ARTIST}" -z "$ROON_ZONE" $EXARGS 82 | fi 83 | 84 | -------------------------------------------------------------------------------- /bin/play_artist_album: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # 3 | # shellcheck disable=SC1090,SC2220 4 | 5 | ROON=/usr/local/Roon 6 | ROONAPI=${ROON}/api 7 | ROONETC=${ROON}/etc 8 | ROONCONF=${ROONETC}/pyroonconf 9 | PLAY=play_artist_album.py 10 | ARTIST= 11 | ALBUM= 12 | EXARTIST= 13 | EXALBUM= 14 | 15 | [ -d ${ROONAPI} ] || exit 1 16 | 17 | cd ${ROONAPI} || exit 1 18 | 19 | [ -f $PLAY ] || exit 2 20 | 21 | ZONE= 22 | # Parse the arguments to get the zone 23 | while getopts "z:" flag; do 24 | case $flag in 25 | z) 26 | ZONE="$OPTARG" 27 | ;; 28 | esac 29 | done 30 | shift $(( OPTIND - 1 )) 31 | 32 | # First argument is artist, second is album (required) 33 | # Third optional argument is artist exclusion string (optional) 34 | # Fourth optional argument is album exclusion string (optional) 35 | [ "$1" ] && ARTIST="$1" 36 | [ "$2" ] && ALBUM="$2" 37 | [ "$3" ] && EXARTIST="$3" 38 | [ "$4" ] && EXALBUM="$4" 39 | 40 | # Use a Python virtual environment 41 | [ -f ${ROON}/venv/bin/activate ] && source ${ROON}/venv/bin/activate 42 | [[ ":$PATH:" == *":/usr/local/Roon/venv/bin:"* ]] || { 43 | export PATH=/usr/local/Roon/venv/bin:${PATH} 44 | } 45 | 46 | DEFZONE=$(grep ^DefaultZone ${ROONETC}/roon_api.ini | awk -F '=' ' { print $2 } ') 47 | # Remove leading and trailing spaces in DEFZONE 48 | DEFZONE="$(echo -e "${DEFZONE}" | sed -e 's/^[[:space:]]*//' -e 's/[[:space:]]*$//')" 49 | 50 | # Get the zone if it is set 51 | if [ -f ${ROONCONF} ] 52 | then 53 | . ${ROONCONF} 54 | else 55 | ${ROON}/bin/set_zone "${DEFZONE}" 56 | . ${ROONCONF} 57 | fi 58 | 59 | [ "${ZONE}" ] && { 60 | if [ "${ZONE}" == "default" ]; then 61 | ROON_ZONE="${DEFZONE}" 62 | else 63 | [ "${ZONE}" == "last" ] || ROON_ZONE="${ZONE}" 64 | fi 65 | } 66 | # Use all zones if no zone is specified or set 67 | [ "${ROON_ZONE}" ] || ROON_ZONE="__all__" 68 | 69 | # Get the default artist if one is not provided 70 | [ "${ARTIST}" ] || { 71 | ARTIST=$(grep ^DefaultArtist ${ROONETC}/roon_api.ini | awk -F '=' ' { print $2 } ') 72 | # Remove leading and trailing spaces in ARTIST 73 | ARTIST="$(echo -e "${ARTIST}" | sed -e 's/^[[:space:]]*//' -e 's/[[:space:]]*$//')" 74 | } 75 | 76 | [ "${ALBUM}" ] || ALBUM="__all__" 77 | 78 | # Construct the exclusion args if passed 79 | EXARGS= 80 | [ "${EXALBUM}" ] && EXARGS="-X ${EXALBUM}" 81 | [ "${EXARTIST}" ] && EXARGS="-x ${EXARTIST} ${EXARGS}" 82 | 83 | have_python3=$(type -p python3) 84 | if [ "${have_python3}" ] 85 | then 86 | python3 $PLAY -A "$ALBUM" -a "$ARTIST" -z "$ROON_ZONE" $EXARGS 87 | else 88 | python $PLAY -A "$ALBUM" -a "$ARTIST" -z "$ROON_ZONE" $EXARGS 89 | fi 90 | 91 | ${ROON}/bin/list_album_tracks "${ALBUM}" 92 | -------------------------------------------------------------------------------- /bin/play_artist_track: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # 3 | # shellcheck disable=SC1090,SC2220 4 | 5 | ROON=/usr/local/Roon 6 | ROONAPI=${ROON}/api 7 | ROONETC=${ROON}/etc 8 | ROONCONF=${ROONETC}/pyroonconf 9 | PLAY=play_artist_track.py 10 | ARTIST= 11 | TRACK= 12 | EXARTIST= 13 | EXTRACK= 14 | 15 | [ -d ${ROONAPI} ] || exit 1 16 | 17 | cd ${ROONAPI} || exit 1 18 | 19 | [ -f $PLAY ] || exit 2 20 | 21 | ZONE= 22 | # Parse the arguments to get the zone 23 | while getopts "z:" flag; do 24 | case $flag in 25 | z) 26 | ZONE="$OPTARG" 27 | ;; 28 | esac 29 | done 30 | shift $(( OPTIND - 1 )) 31 | 32 | # First argument is artist, second is track 33 | # Third optional argument is artist exclusion string (optional) 34 | # Fourth optional argument is track exclusion string (optional) 35 | [ "$1" ] && ARTIST="$1" 36 | [ "$2" ] && TRACK="$2" 37 | [ "$3" ] && EXARTIST="$3" 38 | [ "$4" ] && EXTRACK="$4" 39 | 40 | # Use a Python virtual environment 41 | [ -f ${ROON}/venv/bin/activate ] && source ${ROON}/venv/bin/activate 42 | [[ ":$PATH:" == *":/usr/local/Roon/venv/bin:"* ]] || { 43 | export PATH=/usr/local/Roon/venv/bin:${PATH} 44 | } 45 | 46 | DEFZONE=$(grep ^DefaultZone ${ROONETC}/roon_api.ini | awk -F '=' ' { print $2 } ') 47 | # Remove leading and trailing spaces in DEFZONE 48 | DEFZONE="$(echo -e "${DEFZONE}" | sed -e 's/^[[:space:]]*//' -e 's/[[:space:]]*$//')" 49 | 50 | # Get the zone if it is set 51 | if [ -f ${ROONCONF} ] 52 | then 53 | . ${ROONCONF} 54 | else 55 | ${ROON}/bin/set_zone "${DEFZONE}" 56 | . ${ROONCONF} 57 | fi 58 | 59 | [ "${ZONE}" ] && { 60 | if [ "${ZONE}" == "default" ]; then 61 | ROON_ZONE="${DEFZONE}" 62 | else 63 | [ "${ZONE}" == "last" ] || ROON_ZONE="${ZONE}" 64 | fi 65 | } 66 | # Use all zones if no zone is specified or set 67 | [ "${ROON_ZONE}" ] || ROON_ZONE="__all__" 68 | 69 | # Get the default artist if one is not provided 70 | [ "${ARTIST}" ] || { 71 | ARTIST=$(grep ^DefaultArtist ${ROONETC}/roon_api.ini | awk -F '=' ' { print $2 } ') 72 | # Remove leading and trailing spaces in ARTIST 73 | ARTIST="$(echo -e "${ARTIST}" | sed -e 's/^[[:space:]]*//' -e 's/[[:space:]]*$//')" 74 | } 75 | 76 | [ "${TRACK}" ] || TRACK="__all__" 77 | 78 | # Construct the exclusion args if passed 79 | EXARGS= 80 | [ "${EXTRACK}" ] && EXARGS="-X ${EXTRACK}" 81 | [ "${EXARTIST}" ] && EXARGS="-x ${EXARTIST} ${EXARGS}" 82 | 83 | have_python3=$(type -p python3) 84 | if [ "${have_python3}" ] 85 | then 86 | python3 $PLAY -t "$TRACK" -a "$ARTIST" -z "$ROON_ZONE" $EXARGS 87 | else 88 | python $PLAY -t "$TRACK" -a "$ARTIST" -z "$ROON_ZONE" $EXARGS 89 | fi 90 | -------------------------------------------------------------------------------- /bin/play_composer: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # 3 | # shellcheck disable=SC1090,SC2220 4 | 5 | ROON=/usr/local/Roon 6 | ROONAPI=${ROON}/api 7 | ROONETC=${ROON}/etc 8 | ROONCONF=${ROONETC}/pyroonconf 9 | PLAY=play_composer.py 10 | COMPOSER= 11 | EXCOMPOSER= 12 | 13 | [ -d ${ROONAPI} ] || exit 1 14 | 15 | cd ${ROONAPI} || exit 1 16 | 17 | [ -f $PLAY ] || exit 2 18 | 19 | ZONE= 20 | # Parse the arguments to get the zone 21 | while getopts "z:" flag; do 22 | case $flag in 23 | z) 24 | ZONE="$OPTARG" 25 | ;; 26 | esac 27 | done 28 | shift $(( OPTIND - 1 )) 29 | 30 | [ "$1" ] && COMPOSER="$1" 31 | [ "$2" ] && EXCOMPOSER="$2" 32 | 33 | # Use a Python virtual environment 34 | [ -f ${ROON}/venv/bin/activate ] && source ${ROON}/venv/bin/activate 35 | [[ ":$PATH:" == *":/usr/local/Roon/venv/bin:"* ]] || { 36 | export PATH=/usr/local/Roon/venv/bin:${PATH} 37 | } 38 | 39 | DEFZONE=$(grep ^DefaultZone ${ROONETC}/roon_api.ini | awk -F '=' ' { print $2 } ') 40 | # Remove leading and trailing spaces in DEFZONE 41 | DEFZONE="$(echo -e "${DEFZONE}" | sed -e 's/^[[:space:]]*//' -e 's/[[:space:]]*$//')" 42 | 43 | # Get the zone if it is set 44 | if [ -f ${ROONCONF} ] 45 | then 46 | . ${ROONCONF} 47 | else 48 | ${ROON}/bin/set_zone "${DEFZONE}" 49 | . ${ROONCONF} 50 | fi 51 | 52 | [ "${ZONE}" ] && { 53 | if [ "${ZONE}" == "default" ]; then 54 | ROON_ZONE="${DEFZONE}" 55 | else 56 | [ "${ZONE}" == "last" ] || ROON_ZONE="${ZONE}" 57 | fi 58 | } 59 | # Use all zones if no zone is specified or set 60 | [ "${ROON_ZONE}" ] || ROON_ZONE="__all__" 61 | 62 | # Get the default composer if one is not provided 63 | [ "${COMPOSER}" ] || { 64 | COMPOSER=$(grep ^DefaultComposer ${ROONETC}/roon_api.ini | awk -F '=' ' { print $2 } ') 65 | # Remove leading and trailing spaces in COMPOSER 66 | COMPOSER="$(echo -e "${COMPOSER}" | sed -e 's/^[[:space:]]*//' -e 's/[[:space:]]*$//')" 67 | } 68 | 69 | # Construct the exclusion args if passed 70 | EXARGS= 71 | [ "${EXCOMPOSER}" ] && EXARGS="-x ${EXCOMPOSER}" 72 | 73 | have_python3=$(type -p python3) 74 | if [ "${have_python3}" ] 75 | then 76 | python3 $PLAY -c "$COMPOSER" -z "$ROON_ZONE" $EXARGS 77 | else 78 | python $PLAY -c "$COMPOSER" -z "$ROON_ZONE" $EXARGS 79 | fi 80 | -------------------------------------------------------------------------------- /bin/play_composer_album: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # 3 | # shellcheck disable=SC1090,SC2220 4 | 5 | ROON=/usr/local/Roon 6 | ROONAPI=${ROON}/api 7 | ROONETC=${ROON}/etc 8 | ROONCONF=${ROONETC}/pyroonconf 9 | PLAY=play_composer_album.py 10 | COMPOSER= 11 | ALBUM= 12 | EXCOMPOSER= 13 | EXALBUM= 14 | 15 | [ -d ${ROONAPI} ] || exit 1 16 | 17 | cd ${ROONAPI} || exit 1 18 | 19 | [ -f $PLAY ] || exit 2 20 | 21 | ZONE= 22 | # Parse the arguments to get the zone 23 | while getopts "z:" flag; do 24 | case $flag in 25 | z) 26 | ZONE="$OPTARG" 27 | ;; 28 | esac 29 | done 30 | shift $(( OPTIND - 1 )) 31 | 32 | # First argument is composer, second is album (required) 33 | # Third optional argument is composer exclusion string (optional) 34 | # Fourth optional argument is album exclusion string (optional) 35 | [ "$1" ] && COMPOSER="$1" 36 | [ "$2" ] && ALBUM="$2" 37 | [ "$3" ] && EXCOMPOSER="$3" 38 | [ "$4" ] && EXALBUM="$4" 39 | 40 | # Use a Python virtual environment 41 | [ -f ${ROON}/venv/bin/activate ] && source ${ROON}/venv/bin/activate 42 | [[ ":$PATH:" == *":/usr/local/Roon/venv/bin:"* ]] || { 43 | export PATH=/usr/local/Roon/venv/bin:${PATH} 44 | } 45 | 46 | DEFZONE=$(grep ^DefaultZone ${ROONETC}/roon_api.ini | awk -F '=' ' { print $2 } ') 47 | # Remove leading and trailing spaces in DEFZONE 48 | DEFZONE="$(echo -e "${DEFZONE}" | sed -e 's/^[[:space:]]*//' -e 's/[[:space:]]*$//')" 49 | 50 | # Get the zone if it is set 51 | if [ -f ${ROONCONF} ] 52 | then 53 | . ${ROONCONF} 54 | else 55 | ${ROON}/bin/set_zone "${DEFZONE}" 56 | . ${ROONCONF} 57 | fi 58 | 59 | [ "${ZONE}" ] && { 60 | if [ "${ZONE}" == "default" ]; then 61 | ROON_ZONE="${DEFZONE}" 62 | else 63 | [ "${ZONE}" == "last" ] || ROON_ZONE="${ZONE}" 64 | fi 65 | } 66 | # Use all zones if no zone is specified or set 67 | [ "${ROON_ZONE}" ] || ROON_ZONE="__all__" 68 | 69 | # Get the default composer if one is not provided 70 | [ "${COMPOSER}" ] || { 71 | COMPOSER=$(grep ^DefaultComposer ${ROONETC}/roon_api.ini | awk -F '=' ' { print $2 } ') 72 | # Remove leading and trailing spaces in COMPOSER 73 | COMPOSER="$(echo -e "${COMPOSER}" | sed -e 's/^[[:space:]]*//' -e 's/[[:space:]]*$//')" 74 | } 75 | 76 | [ "${ALBUM}" ] || ALBUM="__all__" 77 | 78 | # Construct the exclusion args if passed 79 | EXARGS= 80 | [ "${EXALBUM}" ] && EXARGS="-X ${EXALBUM}" 81 | [ "${EXCOMPOSER}" ] && EXARGS="-x ${EXCOMPOSER} ${EXARGS}" 82 | 83 | have_python3=$(type -p python3) 84 | if [ "${have_python3}" ] 85 | then 86 | python3 $PLAY -a "$ALBUM" -c "$COMPOSER" -z "$ROON_ZONE" $EXARGS 87 | else 88 | python $PLAY -a "$ALBUM" -c "$COMPOSER" -z "$ROON_ZONE" $EXARGS 89 | fi 90 | 91 | ${ROON}/bin/list_album_tracks "${ALBUM}" 92 | -------------------------------------------------------------------------------- /bin/play_genre: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # 3 | # shellcheck disable=SC1090,SC2220 4 | 5 | ROON=/usr/local/Roon 6 | ROONAPI=${ROON}/api 7 | ROONETC=${ROON}/etc 8 | ROONCONF=${ROONETC}/pyroonconf 9 | PLAY=play_genre.py 10 | GENRE= 11 | EXGENRE= 12 | 13 | [ -d ${ROONAPI} ] || exit 1 14 | 15 | cd ${ROONAPI} || exit 1 16 | 17 | [ -f $PLAY ] || exit 2 18 | 19 | SHUFFLED= 20 | ZONE= 21 | # Parse the arguments to get the play order and zone 22 | while getopts "sz:" flag; do 23 | case $flag in 24 | z) 25 | ZONE="$OPTARG" 26 | ;; 27 | s) 28 | SHUFFLED="-s" 29 | ;; 30 | esac 31 | done 32 | shift $(( OPTIND - 1 )) 33 | 34 | [ "$1" ] && GENRE="$1" 35 | [ "$2" ] && EXGENRE="$2" 36 | 37 | # Use a Python virtual environment 38 | [ -f ${ROON}/venv/bin/activate ] && source ${ROON}/venv/bin/activate 39 | [[ ":$PATH:" == *":/usr/local/Roon/venv/bin:"* ]] || { 40 | export PATH=/usr/local/Roon/venv/bin:${PATH} 41 | } 42 | 43 | DEFZONE=$(grep ^DefaultZone ${ROONETC}/roon_api.ini | awk -F '=' ' { print $2 } ') 44 | # Remove leading and trailing spaces in DEFZONE 45 | DEFZONE="$(echo -e "${DEFZONE}" | sed -e 's/^[[:space:]]*//' -e 's/[[:space:]]*$//')" 46 | 47 | # Get the zone if it is set 48 | if [ -f ${ROONCONF} ] 49 | then 50 | . ${ROONCONF} 51 | else 52 | ${ROON}/bin/set_zone "${DEFZONE}" 53 | . ${ROONCONF} 54 | fi 55 | 56 | [ "${ZONE}" ] && { 57 | if [ "${ZONE}" == "default" ]; then 58 | ROON_ZONE="${DEFZONE}" 59 | else 60 | [ "${ZONE}" == "last" ] || ROON_ZONE="${ZONE}" 61 | fi 62 | } 63 | # Use all zones if no zone is specified or set 64 | [ "${ROON_ZONE}" ] || ROON_ZONE="__all__" 65 | 66 | # Get the default genre if one is not provided 67 | [ "${GENRE}" ] || { 68 | GENRE=$(grep ^DefaultGenre ${ROONETC}/roon_api.ini | awk -F '=' ' { print $2 } ') 69 | # Remove leading and trailing spaces in GENRE 70 | GENRE="$(echo -e "${GENRE}" | sed -e 's/^[[:space:]]*//' -e 's/[[:space:]]*$//')" 71 | } 72 | 73 | # Construct the exclusion args if passed 74 | EXARGS="${SHUFFLED}" 75 | [ "${EXGENRE}" ] && EXARGS="-x ${EXGENRE} ${EXARGS}" 76 | 77 | have_python3=$(type -p python3) 78 | if [ "${have_python3}" ] 79 | then 80 | python3 $PLAY -g "$GENRE" -z "$ROON_ZONE" $EXARGS 81 | else 82 | python $PLAY -g "$GENRE" -z "$ROON_ZONE" $EXARGS 83 | fi 84 | 85 | -------------------------------------------------------------------------------- /bin/play_genre_album: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # 3 | # shellcheck disable=SC1090,SC2220 4 | 5 | ROON=/usr/local/Roon 6 | ROONAPI=${ROON}/api 7 | ROONETC=${ROON}/etc 8 | ROONCONF=${ROONETC}/pyroonconf 9 | PLAY=play_genre_album.py 10 | GENRE= 11 | ALBUM= 12 | EXGENRE= 13 | EXALBUM= 14 | 15 | [ -d ${ROONAPI} ] || exit 1 16 | 17 | cd ${ROONAPI} || exit 1 18 | 19 | [ -f $PLAY ] || exit 2 20 | 21 | ZONE= 22 | # Parse the arguments to get the zone 23 | while getopts "z:" flag; do 24 | case $flag in 25 | z) 26 | ZONE="$OPTARG" 27 | ;; 28 | esac 29 | done 30 | shift $(( OPTIND - 1 )) 31 | 32 | # First argument is genre, second is album (required) 33 | # Third optional argument is genre exclusion string (optional) 34 | # Fourth optional argument is album exclusion string (optional) 35 | [ "$1" ] && GENRE="$1" 36 | [ "$2" ] && ALBUM="$2" 37 | [ "$3" ] && EXGENRE="$3" 38 | [ "$4" ] && EXALBUM="$4" 39 | 40 | # Use a Python virtual environment 41 | [ -f ${ROON}/venv/bin/activate ] && source ${ROON}/venv/bin/activate 42 | [[ ":$PATH:" == *":/usr/local/Roon/venv/bin:"* ]] || { 43 | export PATH=/usr/local/Roon/venv/bin:${PATH} 44 | } 45 | 46 | DEFZONE=$(grep ^DefaultZone ${ROONETC}/roon_api.ini | awk -F '=' ' { print $2 } ') 47 | # Remove leading and trailing spaces in DEFZONE 48 | DEFZONE="$(echo -e "${DEFZONE}" | sed -e 's/^[[:space:]]*//' -e 's/[[:space:]]*$//')" 49 | 50 | # Get the zone if it is set 51 | if [ -f ${ROONCONF} ] 52 | then 53 | . ${ROONCONF} 54 | else 55 | ${ROON}/bin/set_zone "${DEFZONE}" 56 | . ${ROONCONF} 57 | fi 58 | 59 | [ "${ZONE}" ] && { 60 | if [ "${ZONE}" == "default" ]; then 61 | ROON_ZONE="${DEFZONE}" 62 | else 63 | [ "${ZONE}" == "last" ] || ROON_ZONE="${ZONE}" 64 | fi 65 | } 66 | # Use all zones if no zone is specified or set 67 | [ "${ROON_ZONE}" ] || ROON_ZONE="__all__" 68 | 69 | # Get the default genre if one is not provided 70 | [ "${GENRE}" ] || { 71 | GENRE=$(grep ^DefaultGenre ${ROONETC}/roon_api.ini | awk -F '=' ' { print $2 } ') 72 | # Remove leading and trailing spaces in GENRE 73 | GENRE="$(echo -e "${GENRE}" | sed -e 's/^[[:space:]]*//' -e 's/[[:space:]]*$//')" 74 | } 75 | 76 | [ "${ALBUM}" ] || ALBUM="__all__" 77 | 78 | # Construct the exclusion args if passed 79 | EXARGS= 80 | [ "${EXALBUM}" ] && EXARGS="-X ${EXALBUM}" 81 | [ "${EXGENRE}" ] && EXARGS="-x ${EXGENRE} ${EXARGS}" 82 | 83 | have_python3=$(type -p python3) 84 | if [ "${have_python3}" ] 85 | then 86 | python3 $PLAY -a "$ALBUM" -g "$GENRE" -z "$ROON_ZONE" $EXARGS 87 | else 88 | python $PLAY -a "$ALBUM" -g "$GENRE" -z "$ROON_ZONE" $EXARGS 89 | fi 90 | 91 | ${ROON}/bin/list_album_tracks "${ALBUM}" 92 | -------------------------------------------------------------------------------- /bin/play_genre_artist: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # 3 | # shellcheck disable=SC1090,SC2220 4 | 5 | ROON=/usr/local/Roon 6 | ROONAPI=${ROON}/api 7 | ROONETC=${ROON}/etc 8 | ROONCONF=${ROONETC}/pyroonconf 9 | PLAY=play_genre_artist.py 10 | GENRE= 11 | ARTIST= 12 | EXGENRE= 13 | EXARTIST= 14 | 15 | [ -d ${ROONAPI} ] || exit 1 16 | 17 | cd ${ROONAPI} || exit 1 18 | 19 | [ -f $PLAY ] || exit 2 20 | 21 | ZONE= 22 | # Parse the arguments to get the zone 23 | while getopts "z:" flag; do 24 | case $flag in 25 | z) 26 | ZONE="$OPTARG" 27 | ;; 28 | esac 29 | done 30 | shift $(( OPTIND - 1 )) 31 | 32 | # First argument is genre, second is artist (required) 33 | # Third optional argument is genre exclusion string (optional) 34 | # Fourth optional argument is artist exclusion string (optional) 35 | [ "$1" ] && GENRE="$1" 36 | [ "$2" ] && ARTIST="$2" 37 | [ "$3" ] && EXGENRE="$3" 38 | [ "$4" ] && EXARTIST="$4" 39 | 40 | # Use a Python virtual environment 41 | [ -f ${ROON}/venv/bin/activate ] && source ${ROON}/venv/bin/activate 42 | [[ ":$PATH:" == *":/usr/local/Roon/venv/bin:"* ]] || { 43 | export PATH=/usr/local/Roon/venv/bin:${PATH} 44 | } 45 | 46 | DEFZONE=$(grep ^DefaultZone ${ROONETC}/roon_api.ini | awk -F '=' ' { print $2 } ') 47 | # Remove leading and trailing spaces in DEFZONE 48 | DEFZONE="$(echo -e "${DEFZONE}" | sed -e 's/^[[:space:]]*//' -e 's/[[:space:]]*$//')" 49 | 50 | # Get the zone if it is set 51 | if [ -f ${ROONCONF} ] 52 | then 53 | . ${ROONCONF} 54 | else 55 | ${ROON}/bin/set_zone "${DEFZONE}" 56 | . ${ROONCONF} 57 | fi 58 | 59 | [ "${ZONE}" ] && { 60 | if [ "${ZONE}" == "default" ]; then 61 | ROON_ZONE="${DEFZONE}" 62 | else 63 | [ "${ZONE}" == "last" ] || ROON_ZONE="${ZONE}" 64 | fi 65 | } 66 | # Use all zones if no zone is specified or set 67 | [ "${ROON_ZONE}" ] || ROON_ZONE="__all__" 68 | 69 | # Get the default genre if one is not provided 70 | [ "${GENRE}" ] || { 71 | GENRE=$(grep ^DefaultGenre ${ROONETC}/roon_api.ini | awk -F '=' ' { print $2 } ') 72 | # Remove leading and trailing spaces in GENRE 73 | GENRE="$(echo -e "${GENRE}" | sed -e 's/^[[:space:]]*//' -e 's/[[:space:]]*$//')" 74 | } 75 | 76 | [ "${ARTIST}" ] || ARTIST="__all__" 77 | 78 | # Construct the exclusion args if passed 79 | EXARGS= 80 | [ "${EXARTIST}" ] && EXARGS="-X ${EXARTIST}" 81 | [ "${EXGENRE}" ] && EXARGS="-x ${EXGENRE} ${EXARGS}" 82 | 83 | have_python3=$(type -p python3) 84 | if [ "${have_python3}" ] 85 | then 86 | python3 $PLAY -a "$ARTIST" -g "$GENRE" -z "$ROON_ZONE" $EXARGS 87 | else 88 | python $PLAY -a "$ARTIST" -g "$GENRE" -z "$ROON_ZONE" $EXARGS 89 | fi 90 | -------------------------------------------------------------------------------- /bin/play_playlist: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # 3 | # shellcheck disable=SC1090,SC2220 4 | 5 | ROON=/usr/local/Roon 6 | ROONAPI=${ROON}/api 7 | ROONETC=${ROON}/etc 8 | ROONCONF=${ROONETC}/pyroonconf 9 | PLAY=play_playlist.py 10 | PLAYLIST= 11 | EXPLAYLIST= 12 | ZONE= 13 | 14 | [ -d ${ROONAPI} ] || exit 1 15 | 16 | cd ${ROONAPI} || exit 1 17 | 18 | [ -f $PLAY ] || exit 2 19 | 20 | SHUFFLED= 21 | # Parse the arguments to get the play order 22 | while getopts "sz:" flag; do 23 | case $flag in 24 | z) 25 | ZONE="$OPTARG" 26 | ;; 27 | s) 28 | SHUFFLED="-s" 29 | ;; 30 | esac 31 | done 32 | shift $(( OPTIND - 1 )) 33 | 34 | [ "$1" ] && PLAYLIST="$1" 35 | [ "$2" ] && EXPLAYLIST="$2" 36 | 37 | # Use a Python virtual environment 38 | [ -f ${ROON}/venv/bin/activate ] && source ${ROON}/venv/bin/activate 39 | [[ ":$PATH:" == *":/usr/local/Roon/venv/bin:"* ]] || { 40 | export PATH=/usr/local/Roon/venv/bin:${PATH} 41 | } 42 | 43 | DEFZONE=$(grep ^DefaultZone ${ROONETC}/roon_api.ini | awk -F '=' ' { print $2 } ') 44 | # Remove leading and trailing spaces in DEFZONE 45 | DEFZONE="$(echo -e "${DEFZONE}" | sed -e 's/^[[:space:]]*//' -e 's/[[:space:]]*$//')" 46 | 47 | # Get the zone if it is set 48 | if [ -f ${ROONCONF} ] 49 | then 50 | . ${ROONCONF} 51 | else 52 | ${ROON}/bin/set_zone "${DEFZONE}" 53 | . ${ROONCONF} 54 | fi 55 | 56 | [ "${ZONE}" ] && { 57 | if [ "${ZONE}" == "default" ]; then 58 | ROON_ZONE="${DEFZONE}" 59 | else 60 | [ "${ZONE}" == "last" ] || ROON_ZONE="${ZONE}" 61 | fi 62 | } 63 | # Use all zones if no zone is specified or set 64 | [ "${ROON_ZONE}" ] || ROON_ZONE="__all__" 65 | 66 | # Get the default playlist if one is not provided 67 | [ "${PLAYLIST}" ] || { 68 | PLAYLIST=$(grep ^DefaultPlaylist ${ROONETC}/roon_api.ini | awk -F '=' ' { print $2 } ') 69 | # Remove leading and trailing spaces in PLAYLIST 70 | PLAYLIST="$(echo -e "${PLAYLIST}" | sed -e 's/^[[:space:]]*//' -e 's/[[:space:]]*$//')" 71 | } 72 | 73 | # Construct the exclusion args if passed 74 | EXARGS="${SHUFFLED}" 75 | [ "${EXPLAYLIST}" ] && EXARGS="-x ${EXPLAYLIST} ${EXARGS}" 76 | 77 | have_python3=$(type -p python3) 78 | if [ "${have_python3}" ] 79 | then 80 | python3 $PLAY -p "$PLAYLIST" -z "$ROON_ZONE" $EXARGS 81 | else 82 | python $PLAY -p "$PLAYLIST" -z "$ROON_ZONE" $EXARGS 83 | fi 84 | 85 | ${ROON}/bin/list_playlist_tracks "${PLAYLIST}" 86 | -------------------------------------------------------------------------------- /bin/play_radio: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # 3 | # shellcheck disable=SC1090,SC2220 4 | 5 | ROON=/usr/local/Roon 6 | ROONAPI=${ROON}/api 7 | ROONETC=${ROON}/etc 8 | ROONCONF=${ROONETC}/pyroonconf 9 | PLAY=play_radio.py 10 | RADIO= 11 | 12 | [ -d ${ROONAPI} ] || exit 1 13 | 14 | cd ${ROONAPI} || exit 1 15 | 16 | [ -f $PLAY ] || exit 2 17 | 18 | ZONE= 19 | # Parse the arguments to get the zone 20 | while getopts "z:" flag; do 21 | case $flag in 22 | z) 23 | ZONE="$OPTARG" 24 | ;; 25 | esac 26 | done 27 | shift $(( OPTIND - 1 )) 28 | 29 | [ "$1" ] && RADIO="$*" 30 | 31 | # Use a Python virtual environment 32 | [ -f ${ROON}/venv/bin/activate ] && source ${ROON}/venv/bin/activate 33 | [[ ":$PATH:" == *":/usr/local/Roon/venv/bin:"* ]] || { 34 | export PATH=/usr/local/Roon/venv/bin:${PATH} 35 | } 36 | 37 | DEFZONE=$(grep ^DefaultZone ${ROONETC}/roon_api.ini | awk -F '=' ' { print $2 } ') 38 | # Remove leading and trailing spaces in DEFZONE 39 | DEFZONE="$(echo -e "${DEFZONE}" | sed -e 's/^[[:space:]]*//' -e 's/[[:space:]]*$//')" 40 | 41 | # Get the zone if it is set 42 | if [ -f ${ROONCONF} ] 43 | then 44 | . ${ROONCONF} 45 | else 46 | ${ROON}/bin/set_zone "${DEFZONE}" 47 | . ${ROONCONF} 48 | fi 49 | 50 | [ "${ZONE}" ] && { 51 | if [ "${ZONE}" == "default" ]; then 52 | ROON_ZONE="${DEFZONE}" 53 | else 54 | [ "${ZONE}" == "last" ] || ROON_ZONE="${ZONE}" 55 | fi 56 | } 57 | # Use all zones if no zone is specified or set 58 | [ "${ROON_ZONE}" ] || ROON_ZONE="__all__" 59 | 60 | # Get the default radio stream if one is not provided 61 | [ "${RADIO}" ] || { 62 | RADIO=$(grep ^DefaultRadio ${ROONETC}/roon_api.ini | awk -F '=' ' { print $2 } ') 63 | # Remove leading and trailing spaces in RADIO 64 | RADIO="$(echo -e "${RADIO}" | sed -e 's/^[[:space:]]*//' -e 's/[[:space:]]*$//')" 65 | } 66 | 67 | have_python3=$(type -p python3) 68 | if [ "${have_python3}" ] 69 | then 70 | python3 $PLAY -r "${RADIO}" -z "$ROON_ZONE" 71 | else 72 | python $PLAY -r "${RADIO}" -z "$ROON_ZONE" 73 | fi 74 | 75 | -------------------------------------------------------------------------------- /bin/play_tag: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # 3 | # shellcheck disable=SC1090,SC2220 4 | 5 | ROON=/usr/local/Roon 6 | ROONAPI=${ROON}/api 7 | ROONETC=${ROON}/etc 8 | ROONCONF=${ROONETC}/pyroonconf 9 | PLAY=play_tag.py 10 | TAG= 11 | 12 | [ -d ${ROONAPI} ] || exit 1 13 | 14 | cd ${ROONAPI} || exit 1 15 | 16 | [ -f $PLAY ] || exit 2 17 | 18 | ZONE= 19 | # Parse the arguments to get the zone 20 | while getopts "z:" flag; do 21 | case $flag in 22 | z) 23 | ZONE="$OPTARG" 24 | ;; 25 | esac 26 | done 27 | shift $(( OPTIND - 1 )) 28 | 29 | [ "$1" ] && TAG="$*" 30 | 31 | # Use a Python virtual environment 32 | [ -f ${ROON}/venv/bin/activate ] && source ${ROON}/venv/bin/activate 33 | [[ ":$PATH:" == *":/usr/local/Roon/venv/bin:"* ]] || { 34 | export PATH=/usr/local/Roon/venv/bin:${PATH} 35 | } 36 | 37 | DEFZONE=$(grep ^DefaultZone ${ROONETC}/roon_api.ini | awk -F '=' ' { print $2 } ') 38 | # Remove leading and trailing spaces in DEFZONE 39 | DEFZONE="$(echo -e "${DEFZONE}" | sed -e 's/^[[:space:]]*//' -e 's/[[:space:]]*$//')" 40 | 41 | # Get the zone if it is set 42 | if [ -f ${ROONCONF} ] 43 | then 44 | . ${ROONCONF} 45 | else 46 | ${ROON}/bin/set_zone "${DEFZONE}" 47 | . ${ROONCONF} 48 | fi 49 | 50 | [ "${ZONE}" ] && { 51 | if [ "${ZONE}" == "default" ]; then 52 | ROON_ZONE="${DEFZONE}" 53 | else 54 | [ "${ZONE}" == "last" ] || ROON_ZONE="${ZONE}" 55 | fi 56 | } 57 | # Use all zones if no zone is specified or set 58 | [ "${ROON_ZONE}" ] || ROON_ZONE="__all__" 59 | 60 | # Get the default tag if one is not provided 61 | [ "${TAG}" ] || { 62 | TAG=$(grep ^DefaultTag ${ROONETC}/roon_api.ini | awk -F '=' ' { print $2 } ') 63 | # Remove leading and trailing spaces in TAG 64 | TAG="$(echo -e "${TAG}" | sed -e 's/^[[:space:]]*//' -e 's/[[:space:]]*$//')" 65 | } 66 | 67 | have_python3=$(type -p python3) 68 | if [ "${have_python3}" ] 69 | then 70 | python3 $PLAY -t "$TAG" -z "$ROON_ZONE" 71 | else 72 | python $PLAY -t "$TAG" -z "$ROON_ZONE" 73 | fi 74 | 75 | -------------------------------------------------------------------------------- /bin/play_track: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # 3 | # shellcheck disable=SC1090,SC2220 4 | 5 | ROON=/usr/local/Roon 6 | ROONAPI=${ROON}/api 7 | ROONETC=${ROON}/etc 8 | ROONCONF=${ROONETC}/pyroonconf 9 | PLAY=play_track.py 10 | TRACK= 11 | 12 | [ -d ${ROONAPI} ] || exit 1 13 | 14 | cd ${ROONAPI} || exit 1 15 | 16 | [ -f $PLAY ] || exit 2 17 | 18 | ZONE= 19 | # Parse the arguments to get the zone 20 | while getopts "z:" flag; do 21 | case $flag in 22 | z) 23 | ZONE="$OPTARG" 24 | ;; 25 | esac 26 | done 27 | shift $(( OPTIND - 1 )) 28 | 29 | # Argument is track title (required) 30 | [ "$1" ] && TRACK="$1" 31 | 32 | [ "${TRACK}" ] || { 33 | printf "\nTrack title required. Exiting.\n" 34 | exit 1 35 | } 36 | 37 | # Use a Python virtual environment 38 | [ -f ${ROON}/venv/bin/activate ] && source ${ROON}/venv/bin/activate 39 | [[ ":$PATH:" == *":/usr/local/Roon/venv/bin:"* ]] || { 40 | export PATH=/usr/local/Roon/venv/bin:${PATH} 41 | } 42 | 43 | DEFZONE=$(grep ^DefaultZone ${ROONETC}/roon_api.ini | awk -F '=' ' { print $2 } ') 44 | # Remove leading and trailing spaces in DEFZONE 45 | DEFZONE="$(echo -e "${DEFZONE}" | sed -e 's/^[[:space:]]*//' -e 's/[[:space:]]*$//')" 46 | 47 | # Get the zone if it is set 48 | if [ -f ${ROONCONF} ] 49 | then 50 | . ${ROONCONF} 51 | else 52 | ${ROON}/bin/set_zone "${DEFZONE}" 53 | . ${ROONCONF} 54 | fi 55 | 56 | [ "${ZONE}" ] && { 57 | if [ "${ZONE}" == "default" ]; then 58 | ROON_ZONE="${DEFZONE}" 59 | else 60 | [ "${ZONE}" == "last" ] || ROON_ZONE="${ZONE}" 61 | fi 62 | } 63 | # Use all zones if no zone is specified or set 64 | [ "${ROON_ZONE}" ] || ROON_ZONE="__all__" 65 | 66 | have_python3=$(type -p python3) 67 | if [ "${have_python3}" ] 68 | then 69 | PYTHON=python3 70 | else 71 | PYTHON=python 72 | fi 73 | 74 | ${PYTHON} $PLAY -t "$TRACK" -z "$ROON_ZONE" 75 | -------------------------------------------------------------------------------- /bin/roongui: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | have_flat=$(type -p flatpak) 4 | 5 | if [ "${have_flat}" ]; then 6 | flatpak info com.theappgineer.community_remote >/dev/null 2>&1 7 | if [ $? -eq 0 ]; then 8 | flatpak run com.theappgineer.community_remote >/dev/null 2>&1 & 9 | else 10 | echo "The flatpak for com.theappgineer.community_remote not installed" 11 | echo "Install with the command:" 12 | echo " flatpak install -y --noninteractive flathub com.theappgineer.community_remote" 13 | echo "Then rerun roongui" 14 | exit 1 15 | fi 16 | else 17 | echo "Cannot locate flatpak. Exiting." 18 | exit 1 19 | fi 20 | -------------------------------------------------------------------------------- /bin/set_volume: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # 3 | # shellcheck disable=SC1090,SC2220 4 | 5 | ROON=/usr/local/Roon 6 | ROONAPI=${ROON}/api 7 | ROONETC=${ROON}/etc 8 | ROONCONF=${ROONETC}/pyroonconf 9 | SCRIPT=set_volume.py 10 | VOLUME="-v 50" 11 | GROUPED= 12 | RELATIVE= 13 | STEP= 14 | ZONE= 15 | 16 | [ -d ${ROONAPI} ] || exit 1 17 | 18 | cd ${ROONAPI} || exit 1 19 | 20 | [ -f $SCRIPT ] || exit 2 21 | 22 | # Use a Python virtual environment 23 | [ -f ${ROON}/venv/bin/activate ] && source ${ROON}/venv/bin/activate 24 | [[ ":$PATH:" == *":/usr/local/Roon/venv/bin:"* ]] || { 25 | export PATH=/usr/local/Roon/venv/bin:${PATH} 26 | } 27 | 28 | DEFZONE=$(grep ^DefaultZone ${ROONETC}/roon_api.ini | awk -F '=' ' { print $2 } ') 29 | # Remove leading and trailing spaces in DEFZONE 30 | DEFZONE="$(echo -e "${DEFZONE}" | sed -e 's/^[[:space:]]*//' -e 's/[[:space:]]*$//')" 31 | 32 | # Get the zone if it is set 33 | if [ -f ${ROONCONF} ] 34 | then 35 | . ${ROONCONF} 36 | else 37 | ${ROON}/bin/set_zone "${DEFZONE}" 38 | . ${ROONCONF} 39 | fi 40 | 41 | # Parse the arguments to get the command and zone 42 | while getopts "gp:rsv:z:" flag; do 43 | case $flag in 44 | g) 45 | GROUPED="-g" 46 | ;; 47 | p) 48 | VOLUME="-p $OPTARG" 49 | ;; 50 | r) 51 | RELATIVE="-r" 52 | ;; 53 | s) 54 | STEP="-s" 55 | ;; 56 | v) 57 | VOLUME="-v $OPTARG" 58 | ;; 59 | z) 60 | ZONE="$OPTARG" 61 | ;; 62 | esac 63 | done 64 | 65 | [ "${ZONE}" ] && { 66 | if [ "${ZONE}" == "default" ]; then 67 | ROON_ZONE="${DEFZONE}" 68 | else 69 | [ "${ZONE}" == "last" ] || ROON_ZONE="${ZONE}" 70 | fi 71 | } 72 | [ "${ROON_ZONE}" ] || ROON_ZONE="${DEFZONE}" 73 | 74 | have_python3=$(type -p python3) 75 | if [ "${have_python3}" ] 76 | then 77 | python3 $SCRIPT ${GROUPED} ${RELATIVE} ${STEP} ${VOLUME} -z "$ROON_ZONE" 78 | else 79 | python $SCRIPT ${GROUPED} ${RELATIVE} ${STEP} ${VOLUME} -z "$ROON_ZONE" 80 | fi 81 | 82 | -------------------------------------------------------------------------------- /bin/set_zone: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # 3 | # shellcheck disable=SC1090,SC2220,SC2207 4 | 5 | ROON=/usr/local/Roon 6 | ROONAPI=${ROON}/api 7 | ROONCONF=${ROON}/etc/pyroonconf 8 | SCRIPT="zone_command.py" 9 | 10 | [ -f ${ROONAPI}/${SCRIPT} ] || { 11 | echo "Roon Command Line scripts not installed. Missing ${ROONAPI}/$SCRIPT" 12 | exit 1 13 | } 14 | cd ${ROONAPI} || exit 1 15 | 16 | # Verify this is a valid zone name 17 | [ "$1" ] || { 18 | echo "No zone specified on command line. Exiting." 19 | exit 1 20 | } 21 | MY_ZONE="$*" 22 | 23 | # Use a Python virtual environment 24 | [ -f ${ROON}/venv/bin/activate ] && source ${ROON}/venv/bin/activate 25 | [[ ":$PATH:" == *":/usr/local/Roon/venv/bin:"* ]] || { 26 | export PATH=/usr/local/Roon/venv/bin:${PATH} 27 | } 28 | 29 | have_python3=$(type -p python3) 30 | if [ "${have_python3}" ] 31 | then 32 | ZONE=$(python3 $SCRIPT -c "verify" -z "$MY_ZONE") 33 | else 34 | ZONE=$(python $SCRIPT -c "verify" -z "$MY_ZONE") 35 | fi 36 | 37 | [ "$ZONE" ] || { 38 | echo "No zone matching $MY_ZONE" 39 | exit 1 40 | } 41 | 42 | # Check the global site directories 43 | PYTHONUSERBASE= 44 | if [ "${have_python3}" ] 45 | then 46 | SITES=($(python3 -c 'import site; print(site.getsitepackages())' | tr -d '[],')) 47 | else 48 | SITES=($(python -c 'import site; print(site.getsitepackages())' | tr -d '[],')) 49 | fi 50 | for site in ${SITES[@]} 51 | do 52 | site=$(echo "${site}" | sed -e "s/\'//g") 53 | [ -d "${site}/roonapi" ] && { 54 | PYTHONUSERBASE=$(echo "${site}" | awk -F "/lib/" ' { print $1 } ') 55 | break 56 | } 57 | done 58 | 59 | if [ -f $ROONCONF ] 60 | then 61 | grep -v ^ROON_ZONE $ROONCONF > /tmp/roonconf$$ 62 | echo "ROON_ZONE=\"$ZONE\"" >> /tmp/roonconf$$ 63 | cp /tmp/roonconf$$ $ROONCONF 64 | rm -f /tmp/roonconf$$ 65 | [ "$PYTHONUSERBASE" ] && { 66 | grep PYTHONUSERBASE $ROONCONF > /dev/null || { 67 | echo "export PYTHONUSERBASE=$PYTHONUSERBASE" >> $ROONCONF 68 | } 69 | } 70 | else 71 | echo "ROON_ZONE=\"$ZONE\"" > $ROONCONF 72 | [ "$PYTHONUSERBASE" ] && { 73 | echo "export PYTHONUSERBASE=$PYTHONUSERBASE" >> $ROONCONF 74 | } 75 | fi 76 | 77 | exit 0 78 | -------------------------------------------------------------------------------- /bin/set_zone_group: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # 3 | # shellcheck disable=SC1090,SC2220 4 | 5 | ROON=/usr/local/Roon 6 | ROONAPI=${ROON}/api 7 | ROONETC=${ROON}/etc 8 | ROONCONF=${ROONETC}/pyroonconf 9 | SCRIPT="zone_group.py" 10 | 11 | [ -f ${ROONAPI}/${SCRIPT} ] || { 12 | echo "Roon Command Line scripts not installed. Missing $ROONAPI/$SCRIPT" 13 | exit 1 14 | } 15 | cd ${ROONAPI} || exit 1 16 | 17 | # Verify this is a valid zone grouping command 18 | [ "$1" ] || { 19 | echo "No zone grouping command specified on command line. Exiting." 20 | exit 1 21 | } 22 | [ "$1" == "group" ] || [ "$1" == "ungroup" ] || { 23 | echo "Zone grouping command must be 'group' or 'ungroup'. Exiting." 24 | exit 1 25 | } 26 | ZONE_COMMAND="$1" 27 | 28 | # Verify this is a valid zone group name 29 | [ "$2" ] || { 30 | echo "No zone grouping specified on command line. Exiting." 31 | exit 1 32 | } 33 | ROON_ZONE_GROUP="Group_$2" 34 | found_group= 35 | for gn in $(grep ^Group_ "${ROONETC}"/roon_api.ini | awk -F '=' ' { print $1 } ') 36 | do 37 | gn="$(echo -e "${gn}" | sed -e 's/^[[:space:]]*//' -e 's/[[:space:]]*$//')" 38 | [ "$ROON_ZONE_GROUP" == "$gn" ] && found_group=1 39 | done 40 | [ "$found_group" ] || { 41 | echo "No matching zone grouping found. Exiting." 42 | exit 1 43 | } 44 | 45 | # Use a Python virtual environment 46 | [ -f ${ROON}/venv/bin/activate ] && source ${ROON}/venv/bin/activate 47 | [[ ":$PATH:" == *":/usr/local/Roon/venv/bin:"* ]] || { 48 | export PATH=/usr/local/Roon/venv/bin:${PATH} 49 | } 50 | 51 | if [ -f ${ROONCONF} ] 52 | then 53 | . ${ROONCONF} 54 | else 55 | DEFZONE=$(grep ^DefaultZone ${ROONETC}/roon_api.ini | awk -F '=' ' { print $2 } ') 56 | ${ROON}/bin/set_zone "${DEFZONE}" 57 | . ${ROONCONF} 58 | fi 59 | 60 | have_python3=$(type -p python3) 61 | if [ "${have_python3}" ] 62 | then 63 | python3 $SCRIPT -c "$ZONE_COMMAND" -z "$ROON_ZONE_GROUP" 64 | else 65 | python $SCRIPT -c "$ZONE_COMMAND" -z "$ROON_ZONE_GROUP" 66 | fi 67 | 68 | exit 0 69 | -------------------------------------------------------------------------------- /bin/transfer_zone: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # 3 | # shellcheck disable=SC1090,SC2220 4 | 5 | ROON=/usr/local/Roon 6 | ROONAPI=${ROON}/api 7 | ROONETC=${ROON}/etc 8 | ROONCONF=${ROONETC}/pyroonconf 9 | TRAN=transfer_zone.py 10 | FROM_ZONE= 11 | TO_ZONE= 12 | 13 | [ -d ${ROONAPI} ] || exit 1 14 | 15 | cd ${ROONAPI} || exit 1 16 | 17 | [ -f $TRAN ] || exit 2 18 | 19 | # First argument is from zone, second is to zone (required) 20 | # If only one argument, use default zone as from and argument as to 21 | if [ "$2" ]; then 22 | FROM_ZONE="$1" 23 | TO_ZONE="$2" 24 | else 25 | TO_ZONE="$1" 26 | fi 27 | [ "${TO_ZONE}" ] || { 28 | printf "\nUsage: transfer_zone " 29 | printf "\nAt least required. Exiting.\n" 30 | exit 1 31 | } 32 | 33 | # Use a Python virtual environment 34 | [ -f ${ROON}/venv/bin/activate ] && source ${ROON}/venv/bin/activate 35 | [[ ":$PATH:" == *":/usr/local/Roon/venv/bin:"* ]] || { 36 | export PATH=/usr/local/Roon/venv/bin:${PATH} 37 | } 38 | 39 | # Get the zone if it is set 40 | if [ -f ${ROONCONF} ] 41 | then 42 | . ${ROONCONF} 43 | else 44 | DEFZONE=$(grep ^DefaultZone ${ROONETC}/roon_api.ini | awk -F '=' ' { print $2 } ') 45 | ${ROON}/bin/set_zone "${DEFZONE}" 46 | . ${ROONCONF} 47 | fi 48 | 49 | # Get the default from zone if one is not provided 50 | [ "${FROM_ZONE}" ] || { 51 | FROM_ZONE="${ROON_ZONE}" 52 | # Remove leading and trailing spaces in FROM_ZONE 53 | FROM_ZONE="$(echo -e "${FROM_ZONE}" | sed -e 's/^[[:space:]]*//' -e 's/[[:space:]]*$//')" 54 | } 55 | 56 | have_python3=$(type -p python3) 57 | if [ "${have_python3}" ] 58 | then 59 | python3 $TRAN -f "$FROM_ZONE" -t "$TO_ZONE" 60 | else 61 | python $TRAN -f "$FROM_ZONE" -t "$TO_ZONE" 62 | fi 63 | ${ROON}/bin/set_zone "${TO_ZONE}" 64 | -------------------------------------------------------------------------------- /bin/wait_for_pid: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # 3 | # wait_for_pid - wait for pid provided by first argument to exit 4 | # then send signal to parent pid 5 | # 6 | # Useful when a process needs to wait on a child to exit but also 7 | # needs to continue to execute (e.g. the parent is acting as the 8 | # controller of the child, issuing commands over a socket). The 9 | # parent cannot suspend execution to wait for the child to exit. 10 | # Instead, the parent can spawn this process to wait on the pid. 11 | 12 | wait_pid=$1 13 | 14 | # Can't use 'wait', that requires this process be the parent of the pid 15 | # Use tail instead of wait 16 | tail --pid=${wait_pid} -f /dev/null 17 | 18 | kill -USR1 ${PPID} 19 | -------------------------------------------------------------------------------- /bin/zone_command: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # 3 | # shellcheck disable=SC1090,SC2220 4 | 5 | ROON=/usr/local/Roon 6 | ROONAPI=${ROON}/api 7 | ROONETC=${ROON}/etc 8 | ROONCONF=${ROONETC}/pyroonconf 9 | SCRIPT=zone_command.py 10 | COMMAND="play" 11 | 12 | [ -d ${ROONAPI} ] || exit 1 13 | 14 | cd ${ROONAPI} || exit 1 15 | 16 | [ -f $SCRIPT ] || exit 2 17 | 18 | # Use a Python virtual environment 19 | [ -f ${ROON}/venv/bin/activate ] && source ${ROON}/venv/bin/activate 20 | [[ ":$PATH:" == *":/usr/local/Roon/venv/bin:"* ]] || { 21 | export PATH=/usr/local/Roon/venv/bin:${PATH} 22 | } 23 | 24 | DEFZONE=$(grep ^DefaultZone ${ROONETC}/roon_api.ini | awk -F '=' ' { print $2 } ') 25 | # Remove leading and trailing spaces in DEFZONE 26 | DEFZONE="$(echo -e "${DEFZONE}" | sed -e 's/^[[:space:]]*//' -e 's/[[:space:]]*$//')" 27 | 28 | # Get the zone if it is set 29 | if [ -f ${ROONCONF} ] 30 | then 31 | . ${ROONCONF} 32 | else 33 | ${ROON}/bin/set_zone "${DEFZONE}" 34 | . ${ROONCONF} 35 | fi 36 | 37 | # Parse the arguments to get the command and zone 38 | ZONE= 39 | while getopts "c:z:" flag; do 40 | case $flag in 41 | c) 42 | COMMAND="$OPTARG" 43 | ;; 44 | z) 45 | ZONE="$OPTARG" 46 | ;; 47 | esac 48 | done 49 | 50 | [ "${ZONE}" ] && { 51 | if [ "${ZONE}" == "default" ]; then 52 | ROON_ZONE="${DEFZONE}" 53 | else 54 | [ "${ZONE}" == "last" ] || ROON_ZONE="${ZONE}" 55 | fi 56 | } 57 | [ "${ROON_ZONE}" ] || ROON_ZONE="${DEFZONE}" 58 | 59 | have_python3=$(type -p python3) 60 | if [ "${have_python3}" ] 61 | then 62 | python3 $SCRIPT -c "$COMMAND" -z "$ROON_ZONE" 63 | else 64 | python $SCRIPT -c "$COMMAND" -z "$ROON_ZONE" 65 | fi 66 | 67 | -------------------------------------------------------------------------------- /bundle/RoonControl.app/Contents/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleAllowMixedLocalizations 6 | 7 | CFBundleDevelopmentRegion 8 | en 9 | CFBundleExecutable 10 | RoonControl 11 | CFBundleGetInfoString 12 | 2.0.1, Copyright 2021 Ronald Joe Record 13 | CFBundleIconFile 14 | RoonControl 15 | CFBundleIdentifier 16 | com.ronrecord 17 | CFBundleInfoDictionaryVersion 18 | 6.0 19 | CFBundleName 20 | Roon Command Line Control 21 | CFBundlePackageType 22 | APPL 23 | CFBundleSignature 24 | aplt 25 | LSRequiresCarbon 26 | 27 | NSUIElement 28 | 29 | OSAAppletShowStartupScreen 30 | 31 | WindowState 32 | 33 | name 34 | ScriptWindowState 35 | positionOfDivider 36 | 689 37 | savedFrame 38 | 7 106 1249 891 0 0 1600 1002 39 | selectedTabView 40 | result 41 | 42 | 43 | 44 | -------------------------------------------------------------------------------- /bundle/RoonControl.app/Contents/MacOS/RoonControl: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/doctorfree/RoonCommandLine/fdb70992b27aeff8997f2b290590d9dfa28135fa/bundle/RoonControl.app/Contents/MacOS/RoonControl -------------------------------------------------------------------------------- /bundle/RoonControl.app/Contents/PkgInfo: -------------------------------------------------------------------------------- 1 | APPLaplt -------------------------------------------------------------------------------- /bundle/RoonControl.app/Contents/Resources/RoonControl.icns: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/doctorfree/RoonCommandLine/fdb70992b27aeff8997f2b290590d9dfa28135fa/bundle/RoonControl.app/Contents/Resources/RoonControl.icns -------------------------------------------------------------------------------- /bundle/RoonControl.app/Contents/Resources/Script Libraries/Dialog Toolkit Plus.scptd/Contents/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleIconFile 6 | applet 7 | CFBundleIdentifier 8 | au.com.myriad-com.lib.Dialog-Toolkit-Plus 9 | CFBundleShortVersionString 10 | 1.1.2 11 | CFBundleVersion 12 | 5 13 | LSMinimumSystemVersion 14 | 10.10.0 15 | NSHumanReadableCopyright 16 | Copyright © 2014-19 Myriad Communications, All Rights Reserved 17 | OSAAppleScriptObjCEnabled 18 | 19 | OSAScriptingDefinition 20 | ScriptingDictionary 21 | TemplateForCFBundleIdentifier 22 | au.com.myriad-com.lib.Dialog-Toolkit2 23 | WindowState 24 | 25 | bundleDividerCollapsed 26 | 27 | bundlePositionOfDivider 28 | 697 29 | dividerCollapsed 30 | 31 | eventLogLevel 32 | -1 33 | name 34 | ScriptWindowState 35 | positionOfDivider 36 | 609 37 | savedFrame 38 | 186 393 996 860 0 0 2560 1417 39 | selectedTab 40 | log 41 | 42 | 43 | 44 | -------------------------------------------------------------------------------- /bundle/RoonControl.app/Contents/Resources/Script Libraries/Dialog Toolkit Plus.scptd/Contents/Resources/Scripts/main.scpt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/doctorfree/RoonCommandLine/fdb70992b27aeff8997f2b290590d9dfa28135fa/bundle/RoonControl.app/Contents/Resources/Script Libraries/Dialog Toolkit Plus.scptd/Contents/Resources/Scripts/main.scpt -------------------------------------------------------------------------------- /bundle/RoonControl.app/Contents/Resources/Script Libraries/Dialog Toolkit Plus.scptd/Contents/Resources/description.rtfd/TXT.rtf: -------------------------------------------------------------------------------- 1 | {\rtf1\ansi\ansicpg1252\cocoartf1671\cocoasubrtf500 2 | {\fonttbl} 3 | {\colortbl;\red255\green255\blue255;} 4 | {\*\expandedcolortbl;;} 5 | } -------------------------------------------------------------------------------- /bundle/RoonControl.app/Contents/Resources/Scripts/main.scpt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/doctorfree/RoonCommandLine/fdb70992b27aeff8997f2b290590d9dfa28135fa/bundle/RoonControl.app/Contents/Resources/Scripts/main.scpt -------------------------------------------------------------------------------- /bundle/Tools/converticon: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | icon_name="$1" 4 | iconutil --convert iconset ${icon_name}.icns 5 | rm ${icon_name}.icns 6 | iconutil --convert icns ${icon_name}.iconset 7 | rm -R ${icon_name}.iconset 8 | -------------------------------------------------------------------------------- /bundle/Tools/plist2xml: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # 3 | # https://fileinfo.com/extension/plist 4 | # 5 | 6 | plist_name="$1" 7 | 8 | [ -f ${plist_name}.plist ] || { 9 | echo "Cannot locate ${plist_name}.plist - exiting." 10 | exit 1 11 | } 12 | 13 | echo "Converting ${plist_name}.plist from binary to XML format" 14 | plutil -convert xml1 ${plist_name}.plist 15 | -------------------------------------------------------------------------------- /bundle/Tools/script2bundle: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # @brief convert apple/shell script to bundle 4 | # @version 0.1 5 | # @auther gongqijian 6 | # @date 2013/05/09 7 | 8 | set -e 9 | 10 | if [ $# -lt 1 ]; then 11 | echo "Usage: $(basename $0) script-file [appname]" 12 | echo "Exampel:" 13 | echo " $(basename $0) example.applescript example" 14 | echo " $(basename $0) example.scpt example" 15 | echo " $(basename $0) example.sh example" 16 | exit 1 17 | fi 18 | 19 | dir=$(cd $(dirname "$1"); pwd) 20 | scpt=$(basename "$1") 21 | app=$2 22 | 23 | function mk-apple-script-bundle() { 24 | [ ! -n "$app" ] && app=${scpt%*.scpt} 25 | osacompile -o "$dir/$app.app" "$dir/$scpt" 26 | defaults write "$dir/$app.app"/Contents/Info LSUIElement -string 1 27 | } 28 | 29 | function mk-shell-script-bundle() { 30 | [ ! -n "$app" ] && app=${scpt%*.sh} 31 | contents_dir=$app.app/Contents/MacOS 32 | mkdir -p $contents_dir 33 | cp $scpt $contents_dir 34 | chmod 755 $contents_dir/$scpt 35 | 36 | cat >$app.app/Contents/Info.plist< 38 | 39 | 40 | 41 | CFBundlePackageType 42 | APPL 43 | CFBundleExecutable 44 | $scpt 45 | LSUIElement 46 | 1 47 | 48 | 49 | EOF 50 | } 51 | 52 | suffix=${scpt##*.} 53 | 54 | case $suffix in 55 | applescript | scpt) 56 | mk-apple-script-bundle 57 | ;; 58 | sh) 59 | mk-shell-script-bundle 60 | ;; 61 | *) 62 | echo "unknow suffix '$suffix'" 63 | exit 2 64 | esac 65 | 66 | echo "done!" 67 | exit 0 68 | -------------------------------------------------------------------------------- /bundle/Tools/xml2plist: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # 3 | # https://fileinfo.com/extension/plist 4 | # 5 | 6 | plist_name="$1" 7 | 8 | [ -f ${plist_name}.plist ] || { 9 | echo "Cannot locate ${plist_name}.plist - exiting." 10 | exit 1 11 | } 12 | 13 | echo "Converting ${plist_name}.plist from XML to binary format" 14 | plutil -convert binary1 ${plist_name}.plist 15 | -------------------------------------------------------------------------------- /chkinst: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | ROON="/usr/local/Roon" 4 | 5 | install= 6 | rooninst= 7 | uptodate=1 8 | verbose= 9 | 10 | [ "$1" == "-i" ] && install=1 11 | [ "$1" == "-I" ] && { 12 | install=1 13 | rooninst=1 14 | } 15 | [ "$1" == "-v" ] && verbose=1 16 | 17 | for dir in api bin etc 18 | do 19 | [ -d $dir ] || { 20 | echo "$dir does not exist or is not a directory. Skipping." 21 | continue 22 | } 23 | cd $dir 24 | HERE=`pwd` 25 | for i in * 26 | do 27 | [ -f ${ROON}/$dir/$i ] || { 28 | if [ "${install}" ] 29 | then 30 | echo "Installing $dir/$i" 31 | sudo cp $i ${ROON}/$dir/$i 32 | [ "${dir}" == "bin" ] && { 33 | cd /usr/local/bin 34 | sudo ln -s ${ROON}/bin/$i $i 35 | cd ${HERE} 36 | } 37 | else 38 | echo "$dir/$i not installed." 39 | fi 40 | uptodate= 41 | continue 42 | } 43 | if [ "$dir/$i" == "bin/roon" ] 44 | then 45 | delta=`diff $i ${ROON}/$dir/$i | wc -l` 46 | [ ${delta} -gt 8 ] && { 47 | if [ "${install}" ] 48 | then 49 | if [ "${rooninst}" ] 50 | then 51 | echo "Installing $dir/$i" 52 | echo "Edit ${ROON}/$dir/$i with 'server' and 'user'" 53 | sudo cp $i ${ROON}/$dir/$i 54 | else 55 | echo "$dir/$i differs from installed version." 56 | echo "$dir/$i must be installed manually in order" 57 | echo "to set 'server' and 'user' appropriately." 58 | fi 59 | else 60 | if [ "${verbose}" ] 61 | then 62 | echo "$dir/$i differs from installed version:" 63 | echo "" 64 | diff $i ${ROON}/$dir/$i 65 | echo "" 66 | else 67 | echo "$dir/$i differs from installed version." 68 | fi 69 | fi 70 | uptodate= 71 | continue 72 | } 73 | else 74 | diff $i ${ROON}/$dir/$i > /dev/null || { 75 | if [ "${install}" ] 76 | then 77 | echo "Installing $dir/$i" 78 | sudo cp $i ${ROON}/$dir/$i 79 | else 80 | if [ "${verbose}" ] 81 | then 82 | echo "$dir/$i differs from installed version:" 83 | echo "" 84 | diff $i ${ROON}/$dir/$i 85 | echo "" 86 | else 87 | echo "$dir/$i differs from installed version." 88 | fi 89 | fi 90 | uptodate= 91 | continue 92 | } 93 | fi 94 | done 95 | cd .. 96 | done 97 | 98 | [ "${uptodate}" ] && echo "Roon installation up to date!" 99 | -------------------------------------------------------------------------------- /clean: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | sudo rm -rf dist releases test/__pycache__ 4 | -------------------------------------------------------------------------------- /etc/install-figlet: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # 3 | 4 | pathadd() { 5 | if [ -d "$1" ] && [[ ":$PATH:" != *":$1:"* ]]; then 6 | PATH="$1${PATH:+":$PATH"}" 7 | fi 8 | } 9 | 10 | pathadd "${HOME}/.local/bin" 11 | pathadd "/usr/local/bin" 12 | export PATH 13 | 14 | have_figlet=$(type -p figlet) 15 | [ "${have_figlet}" ] || { 16 | darwin= 17 | platform=$(uname -s) 18 | [ "${platform}" == "Darwin" ] && darwin=1 19 | have_brew=$(type -p brew) 20 | if [ "${have_brew}" ] && [ "${darwin}" ]; then 21 | printf "\nInstalling figlet with Homebrew\n" 22 | brew install figlet >/dev/null 2>&1 23 | else 24 | have_make=$(type -p make) 25 | if [ "${have_make}" ]; then 26 | printf "\nInstalling figlet\n" 27 | uid=$(id -u) 28 | SUDO="sudo" 29 | if [ "${EUID}" ]; then 30 | [ ${EUID} -eq 0 ] && SUDO= 31 | else 32 | [ ${uid} -eq 0 ] && SUDO= 33 | fi 34 | HERE=$(pwd) 35 | git clone https://github.com/cmatsuoka/figlet /tmp/figlet$$ > /dev/null 2>&1 36 | cd /tmp/figlet$$ 37 | ${SUDO} make install > /dev/null 2>&1 38 | cd "${HERE}" 39 | ${SUDO} rm -rf /tmp/figlet$$ 40 | else 41 | printf "\nInstallation of figlet requires 'make' but 'make' not found." 42 | printf "\nInstall 'make' and try again. Skipping installation of figlet.\n" 43 | fi 44 | fi 45 | } 46 | -------------------------------------------------------------------------------- /etc/install-fzf: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # 3 | # Install fzf fuzzy finder 4 | 5 | pathadd() { 6 | if [ -d "$1" ] && [[ ":$PATH:" != *":$1:"* ]]; then 7 | PATH="$1${PATH:+":$PATH"}" 8 | fi 9 | } 10 | 11 | pathadd "${HOME}/.local/bin" 12 | pathadd "${HOME}/.fzf/bin" 13 | export PATH 14 | 15 | have_git=$(type -p git) 16 | [ "${have_git}" ] || { 17 | printf "\nERROR: cannot locate required git command" 18 | printf "\nInstall git and re-run this install script\n\n" 19 | exit 1 20 | } 21 | 22 | have_fzf=$(type -p fzf) 23 | [ -d ${HOME}/.local/bin ] || mkdir -p ${HOME}/.local/bin 24 | 25 | [ -f ${HOME}/.local/bin/fzf ] && { 26 | mv ${HOME}/.local/bin/fzf ${HOME}/.local/bin/fzf-bak$$ 27 | } 28 | [ "${have_fzf}" ] || { 29 | printf "\nInstalling fzf fuzzy finder\n" 30 | [ -d ${HOME}/.fzf ] && mv ${HOME}/.fzf ${HOME}/.fzf$$ 31 | git clone --depth 1 https://github.com/junegunn/fzf.git \ 32 | ${HOME}/.fzf >/dev/null 2>&1 33 | [ -f ${HOME}/.fzf/install ] && chmod 755 ${HOME}/.fzf/install 34 | [ -x ${HOME}/.fzf/install ] && ${HOME}/.fzf/install --all >/dev/null 2>&1 35 | } 36 | if [ -f ${HOME}/.fzf/bin/fzf ]; then 37 | ln -s ${HOME}/.fzf/bin/fzf ${HOME}/.local/bin/fzf 38 | rm -f ${HOME}/.local/bin/fzf-bak$$ 39 | else 40 | [ -f ${HOME}/.local/bin/fzf-bak$$ ] && { 41 | mv ${HOME}/.local/bin/fzf-bak$$ ${HOME}/.local/bin/fzf 42 | } 43 | fi 44 | -------------------------------------------------------------------------------- /etc/install-roon-gui: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # 3 | # Install roon-gui, a GUI front-end for Roon on Linux (uses Flatpak) 4 | # 5 | # Run with the command: 6 | # flatpak run com.theappgineer.community_remote 7 | 8 | set_download_url() { 9 | OWNER=TheAppgineer 10 | PROJECT=community_remote 11 | API_URL="https://api.github.com/repos/${OWNER}/${PROJECT}/releases/latest" 12 | [ "${have_curl}" ] && [ "${have_jq}" ] && { 13 | DL_URL=$(curl --silent ${AUTH_HEADER} "${API_URL}" \ 14 | | jq --raw-output '.assets | .[]?.browser_download_url' \ 15 | | grep "community_remote-linux") 16 | } 17 | } 18 | 19 | get_roon_gui_release() { 20 | DL_URL= 21 | set_download_url 22 | echo "${DL_URL}" | awk -F '/' '{ print $8 }' 23 | } 24 | 25 | install_roon_gui() { 26 | flatpak remote-add --if-not-exists \ 27 | flathub https://dl.flathub.org/repo/flathub.flatpakrepo 28 | flatpak install -y --noninteractive flathub com.theappgineer.community_remote 29 | } 30 | 31 | pathadd() { 32 | if [ -d "$1" ] && [[ ":$PATH:" != *":$1:"* ]]; then 33 | PATH="$1${PATH:+":$PATH"}" 34 | fi 35 | } 36 | 37 | pathadd "${HOME}/.local/bin" 38 | export PATH 39 | 40 | # Use a Github API token if one is set 41 | [ "${GITHUB_TOKEN}" ] || { 42 | [ "${GH_API_TOKEN}" ] && export GITHUB_TOKEN="${GH_API_TOKEN}" 43 | [ "${GITHUB_TOKEN}" ] || { 44 | [ "${GH_TOKEN}" ] && export GITHUB_TOKEN="${GH_TOKEN}" 45 | } 46 | } 47 | if [ "${GITHUB_TOKEN}" ]; then 48 | AUTH_HEADER="-H \"Authorization: Bearer ${GITHUB_TOKEN}\"" 49 | else 50 | AUTH_HEADER= 51 | fi 52 | 53 | have_brew=$(type -p brew) 54 | have_curl=$(type -p curl) 55 | have_jq=$(type -p jq) 56 | have_wget=$(type -p wget) 57 | 58 | [ "$1" == "version" ] && { 59 | get_roon_gui_release 60 | exit 0 61 | } 62 | 63 | arm= 64 | darwin= 65 | mach=$(uname -m) 66 | platform=$(uname -s) 67 | [ "${platform}" == "Darwin" ] && darwin=1 68 | [ "${mach}" == "arm64" ] && arm=1 69 | [ "${darwin}" ] || { 70 | [ "${arm}" ] && { 71 | echo "Arm architecture not yet supported. Exiting." 72 | exit 1 73 | } 74 | } 75 | 76 | ROON="/usr/local/Roon" 77 | install_roon_gui 78 | -------------------------------------------------------------------------------- /etc/preremove: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # 3 | # Preremoval script for rooncommandline 4 | # 5 | # Author: Ronald Joe Record 6 | # 7 | 8 | set -e 9 | 10 | ROON=/usr/local/Roon 11 | ROONAPI=${ROON}/api 12 | ROONBIN=${ROON}/bin 13 | ROONETC=${ROON}/etc 14 | ROONCONF=${ROONETC}/pyroonconf 15 | ROON_INI=${ROONETC}/roon_api.ini 16 | 17 | # Locate the global site directories 18 | ROON_SITE_DIR= 19 | PYTHONUSERBASE= 20 | 21 | [ -f ${ROON}/venv/bin/activate ] && source ${ROON}/venv/bin/activate 22 | [[ ":$PATH:" == *":/usr/local/Roon/venv/bin:"* ]] || { 23 | export PATH=/usr/local/Roon/venv/bin:${PATH} 24 | } 25 | # Check the global site directories 26 | if type -p python3 > /dev/null 27 | then 28 | SITES=($(python3 -c 'import site; print(site.getsitepackages())' | tr -d '[],')) 29 | else 30 | SITES=($(python -c 'import site; print(site.getsitepackages())' | tr -d '[],')) 31 | fi 32 | for site in ${SITES[@]} 33 | do 34 | site=`echo $site | sed -e "s/'//g"` 35 | [ -d ${site}/roonapi ] && { 36 | ROON_SITE_DIR=${site}/roonapi 37 | break 38 | } 39 | done 40 | 41 | rm -f ${ROONCONF} ${ROON_INI} ${ROONBIN}/*.orig ${ROONETC}/* 42 | 43 | if [ "$ROON_SITE_DIR" ] 44 | then 45 | # Roll back the Python Roon API patch if it was applied 46 | cd $ROON_SITE_DIR 47 | for i in *.orig 48 | do 49 | [ "$i" == "*.orig" ] && continue 50 | j=`echo $i | sed -e "s/.orig//"` 51 | mv $i $j 52 | done 53 | else 54 | echo "Could not locate the roonapi Python module installation directory" 55 | echo "Python Roon API patch not reversed." 56 | fi 57 | 58 | [ -d /usr/local/bin ] && { 59 | cd /usr/local/bin 60 | for command in ${ROONBIN}/* 61 | do 62 | [ "${command}" == "${ROONBIN}/*" ] && continue 63 | b=`basename ${command}` 64 | [ -L $b ] && { 65 | readlink $b | grep ${ROON} > /dev/null && rm -f $b 66 | } 67 | done 68 | } 69 | echo "" 70 | echo "Roon Command Line uninstalled" 71 | 72 | exit 0 73 | -------------------------------------------------------------------------------- /etc/roon_api.ini-dist: -------------------------------------------------------------------------------- 1 | [DEFAULT] 2 | DefaultAlbum = Catch the Wind 3 | DefaultArtist = Jethro Tull 4 | DefaultComposer = Wolfgang Amadeus Mozart 5 | DefaultGenre = Classical 6 | DefaultPlaylist = Bowie Favs 7 | DefaultRadio = Radio Paradise 8 | DefaultTag = Prog 9 | DefaultZone = __DEF_ZONE__ 10 | TokenFileName = /usr/local/Roon/etc/roontoken.txt 11 | RoonCoreIP = XX.X.X.XX 12 | RoonCorePort = __CORE_PORT__ 13 | RoonCommandLineVersion = __VERSION__ 14 | RoonCommandLineRelease = __RELEASE__ 15 | 16 | [ZONEGROUPS] 17 | # Zone Groups can be anything of the form "Group_". 18 | # I am using numbers. Whatever you use, that will be the argument to the 19 | # set_zone_group command, e.g. "roon -G 1 -c group" or "roon -G 3 -c ungroup". 20 | # Use the command "roon -l zones" to get a listing of your enabled zone names. 21 | # Add as many zone groupings in this section as you like, each with a unique 22 | # key of the form "Group_*". 23 | # 24 | # Example zone grouping 25 | # Group_0 = Mac Pro DAC, Mac Pro Line Out 26 | # Group_1 = Mac Pro DAC, Kitchen 27 | # Group_2 = HomePod Max, HomePod Mini Left, HomePod Mini Right 28 | # Group_3 = Kitchen, Mac Pro Line Out 29 | # Group_4 = Mac Pro Line Out, Mac Pro DAC, Kitchen 30 | Group_0 = __ALL_ZONES__ 31 | Group_1 = __GROUP_ONE__ 32 | Group_2 = __GROUP_TWO__ 33 | Group_3 = __GROUP_REE__ 34 | Group_4 = __GROUP_FOR__ 35 | 36 | -------------------------------------------------------------------------------- /etc/upgrade-venv: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | ROON=/usr/local/Roon 4 | PIPARGS="--no-cache-dir --upgrade --force-reinstall" 5 | 6 | if [[ $EUID -eq 0 ]] 7 | then 8 | SUDO= 9 | else 10 | SUDO=sudo 11 | fi 12 | 13 | export PATH=$PATH:/usr/local/bin 14 | if [ -x /home/linuxbrew/.linuxbrew/bin/brew ]; then 15 | eval "$(/home/linuxbrew/.linuxbrew/bin/brew shellenv)" 16 | else 17 | if [ -x /opt/homebrew/bin/brew ]; then 18 | eval "$(/opt/homebrew/bin/brew shellenv)" 19 | else 20 | [ -x /usr/local/bin/brew ] && eval "$(/usr/local/bin/brew shellenv)" 21 | fi 22 | fi 23 | 24 | have_python3=$(type -p python3) 25 | if [ "${have_python3}" ]; then 26 | PYTHON=python3 27 | else 28 | have_python=$(type -p python) 29 | if [ "${have_python}" ]; then 30 | PYTHON=python 31 | else 32 | echo "ERROR: unable to locate Python executable in PATH" 33 | exit 1 34 | fi 35 | fi 36 | 37 | [ -d ${ROON} ] || { 38 | echo "ERROR: RoonCommandLine not installed." 39 | exit 1 40 | } 41 | 42 | # Remove previously installed Python virtual environment 43 | ${SUDO} rm -rf ${ROON}/venv 44 | 45 | # Create the RoonCommandLine Python virtual environment 46 | ${SUDO} ${PYTHON} -m venv ${ROON}/venv >/dev/null 2>&1 47 | # Use the RoonCommandLine Python virtual environment 48 | [ -f ${ROON}/venv/bin/activate ] && source ${ROON}/venv/bin/activate 49 | [[ ":$PATH:" == *":/usr/local/Roon/venv/bin:"* ]] || { 50 | export PATH=/usr/local/Roon/venv/bin:${PATH} 51 | } 52 | [ -x ${ROON}/venv/bin/python ] && export PYTHON=${ROON}/venv/bin/python 53 | # Make sure we have pip installed 54 | ${SUDO} ${PYTHON} -m ensurepip --upgrade >/dev/null 2>&1 55 | [ -x ${ROON}/venv/bin/pip ] || { 56 | PYOUT="/tmp/get-pip$$.py" 57 | PYURL="https://bootstrap.pypa.io/get-pip.py" 58 | have_curl=$(type -p curl) 59 | if [ "${have_curl}" ]; then 60 | curl -sSL -o ${PYOUT} ${PYURL} 61 | else 62 | have_wget=$(type -p wget) 63 | if [ "${have_wget}" ]; then 64 | wget -q -O ${PYOUT} ${PYURL} 65 | else 66 | echo "WARNING: Unable to locate curl or wget to download pip install script" 67 | fi 68 | fi 69 | if [ -f ${PYOUT} ]; then 70 | ${SUDO} ${PYTHON} ${PYOUT} 71 | else 72 | echo "WARNING: pip install script not found" 73 | fi 74 | rm -f ${PYOUT} 75 | } 76 | [ -x ${ROON}/venv/bin/pip ] || { 77 | echo "WARNING: ${ROON}/venv/bin/pip not found or not executable" 78 | } 79 | 80 | ${SUDO} ${PYTHON} -m pip install ${PIPARGS} roonapi >/dev/null 2>&1 81 | ${SUDO} ${PYTHON} -m pip install ${PIPARGS} rich-cli >/dev/null 2>&1 82 | -------------------------------------------------------------------------------- /icons/globe.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/doctorfree/RoonCommandLine/fdb70992b27aeff8997f2b290590d9dfa28135fa/icons/globe.png -------------------------------------------------------------------------------- /icons/instagram.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/doctorfree/RoonCommandLine/fdb70992b27aeff8997f2b290590d9dfa28135fa/icons/instagram.png -------------------------------------------------------------------------------- /icons/linkedin.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/doctorfree/RoonCommandLine/fdb70992b27aeff8997f2b290590d9dfa28135fa/icons/linkedin.png -------------------------------------------------------------------------------- /icons/mastodon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/doctorfree/RoonCommandLine/fdb70992b27aeff8997f2b290590d9dfa28135fa/icons/mastodon.png -------------------------------------------------------------------------------- /icons/twitter.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/doctorfree/RoonCommandLine/fdb70992b27aeff8997f2b290590d9dfa28135fa/icons/twitter.png -------------------------------------------------------------------------------- /icons/youtube.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/doctorfree/RoonCommandLine/fdb70992b27aeff8997f2b290590d9dfa28135fa/icons/youtube.png -------------------------------------------------------------------------------- /man/README.md: -------------------------------------------------------------------------------- 1 | # RoonCommandLine/man 2 | 3 | This directory contains automatically generated man format output files 4 | generated by pandoc using the utility script 5 | [md2man](https://github.com/doctorfree/DoctorFreeScripts/-/blob/master/scripts/md2man.sh) 6 | in the [DoctorFreeScripts repository](https://github.com/doctorfree/DoctorFreeScripts) 7 | is used as a pandoc wrapper. 8 | 9 | The man page format output can be found at ./man?/.? 10 | and corresponding markdown input at ../markdown/.?.md 11 | 12 | For example, the man page output for the `roon` command would be found at 13 | ./man1/roon.1 and the corresponding markdown input used to generate the 14 | roon man page would be found at ../markdown/roon.1.md 15 | 16 | ## Contents 17 | 18 | - [**roon.1**](man1/roon.1) - Roon man page man format output generated by pandoc 19 | - [**get_core_ip.1**](man1/get_core_ip.1) - Get the Roon Core IP address 20 | - [**get_zone_info.1**](man1/get_zone_info.1) - Get Roon Zone Info 21 | - [**get_zones.1**](man1/get_zones.1) - Get the Roon Zones 22 | - [**list_albums.1**](man1/list_albums.1) - List Roon Library Albums 23 | - [**list_artists.1**](man1/list_artists.1) - List Roon Library Artists 24 | - [**list_genres.1**](man1/list_genres.1) - List Roon Library Genres 25 | - [**list_playlists.1**](man1/list_playlists.1) - List Roon Library Playlists 26 | - [**list_radio.1**](man1/list_radio.1) - List Roon Live Radio Channels 27 | - [**list_tags.1**](man1/list_tags.1) - List Roon Library Tags 28 | - [**list_zones.1**](man1/list_zones.1) - List Roon Zones 29 | - [**now_playing.1**](man1/now_playing.1) - Get Roon Zone Now Playing Info 30 | - [**play_album.1**](man1/play_album.1) - Play Roon Library Album 31 | - [**play_artist.1**](man1/play_artist.1) - Play Roon Library Artist 32 | - [**play_genre.1**](man1/play_genre.1) - Play Roon Library Genre 33 | - [**play_playlist.1**](man1/play_playlist.1) - Play Roon Library Playlist 34 | - [**play_radio.1**](man1/play_radio.1) - Play Roon Live Radio Channel 35 | - [**play_tag.1**](man1/play_tag.1) - Play Roon Library Tag 36 | - [**set_volume.1**](man1/set_volume.1) - Set the Roon Zone volume level 37 | - [**set_zone.1**](man1/set_zone.1) - Set the Roon Zone 38 | - [**set_zone_group.1**](man1/set_zone_group.1) - Set the Roon Zone Group 39 | - [**zone_command.1**](man1/zone_command.1) - Execute a Roon command 40 | -------------------------------------------------------------------------------- /man/man1/get_core_ip.1: -------------------------------------------------------------------------------- 1 | .\" Automatically generated by Pandoc 2.19.2 2 | .\" 3 | .\" Define V font for inline verbatim, using C font in formats 4 | .\" that render this, and otherwise B font. 5 | .ie "\f[CB]x\f[]"x" \{\ 6 | . ftr V B 7 | . ftr VI BI 8 | . ftr VB B 9 | . ftr VBI BI 10 | .\} 11 | .el \{\ 12 | . ftr V CR 13 | . ftr VI CI 14 | . ftr VB CB 15 | . ftr VBI CBI 16 | .\} 17 | .TH "GET_CORE_IP" "1" "December 05, 2021" "get_core_ip 2.0.1" "User Manual" 18 | .hy 19 | .SH NAME 20 | .PP 21 | get_core_ip - Get the Roon Core IP address 22 | .SH SYNOPSIS 23 | .PP 24 | \f[B]get_core_ip\f[R] 25 | .SH DESCRIPTION 26 | .PP 27 | Automatically discover a Roon Core System on the local network and 28 | retrieve the Roon Core IP address 29 | .SH AUTHORS 30 | .PP 31 | Written by Ronald Record 32 | .SH LICENSING 33 | .PP 34 | GET_CORE_IP is distributed under an Open Source license. 35 | See the file LICENSE in the GET_CORE_IP source distribution for 36 | information on terms & conditions for accessing and otherwise using 37 | GET_CORE_IP and for a DISCLAIMER OF ALL WARRANTIES. 38 | .SH BUGS 39 | .PP 40 | Submit bug reports online at: 41 | 42 | .SH SEE ALSO 43 | .PP 44 | \f[B]get_zone_info\f[R](1), \f[B]get_zones\f[R](1), 45 | \f[B]list_albums\f[R](1), \f[B]list_artist_albums\f[R](1), 46 | \f[B]list_artists\f[R](1), \f[B]list_composers\f[R](1), 47 | \f[B]list_genre_albums\f[R](1), \f[B]list_genre_artists\f[R](1), 48 | \f[B]list_genres\f[R](1), \f[B]list_playlists\f[R](1), 49 | \f[B]list_radio\f[R](1), \f[B]list_tags\f[R](1), 50 | \f[B]list_zones\f[R](1), \f[B]play_album\f[R](1), 51 | \f[B]play_artist\f[R](1), \f[B]play_artist_album\f[R](1), 52 | \f[B]play_artist_track\f[R](1), \f[B]play_composer\f[R](1), 53 | \f[B]play_genre\f[R](1), \f[B]play_genre_album\f[R](1), 54 | \f[B]play_genre_artist\f[R](1), \f[B]play_playlist\f[R](1), 55 | \f[B]play_radio\f[R](1), \f[B]play_tag\f[R](1), \f[B]roon\f[R](1), 56 | \f[B]set_zone\f[R](1), \f[B]set_zone_group\f[R](1), 57 | \f[B]zone_command\f[R](1) 58 | .PP 59 | Full documentation and sources at: 60 | 61 | -------------------------------------------------------------------------------- /man/man1/get_zone_remaining.1: -------------------------------------------------------------------------------- 1 | .\" Automatically generated by Pandoc 2.19.2 2 | .\" 3 | .\" Define V font for inline verbatim, using C font in formats 4 | .\" that render this, and otherwise B font. 5 | .ie "\f[CB]x\f[]"x" \{\ 6 | . ftr V B 7 | . ftr VI BI 8 | . ftr VB B 9 | . ftr VBI BI 10 | .\} 11 | .el \{\ 12 | . ftr V CR 13 | . ftr VI CI 14 | . ftr VB CB 15 | . ftr VBI CBI 16 | .\} 17 | .TH "GET_ZONE_REMAINING" "1" "December 05, 2022" "get_zone_remaining 2.0.1" "User Manual" 18 | .hy 19 | .SH NAME 20 | .PP 21 | get_zone_remaining - Get remaining time in seconds for track playing in 22 | Roon Zone 23 | .SH SYNOPSIS 24 | .PP 25 | \f[B]get_zone_remaining\f[R] [ \f[B]-z\f[R] ZONE ] 26 | .SH DESCRIPTION 27 | .PP 28 | Retrieves remaining time in seconds for track playing in specified zone 29 | or default zone if no zone is specified. 30 | .SH COMMAND LINE OPTIONS 31 | .TP 32 | \f[B]-z ZONE\f[R] 33 | If a \f[I]ZONE\f[R] is specified then retrieve remaining time in seconds 34 | for that zone. 35 | If no \f[I]ZONE\f[R] is sprovided on the command line then retrieve 36 | remaining time for the default zone. 37 | \[aq]-z default\[aq] indicates the default zone, \[aq]-z last\[aq] the 38 | last zone used 39 | .SH EXAMPLES 40 | .TP 41 | \f[B]get_zone_remaining\f[R] 42 | Displays remaining time for the default zone 43 | .TP 44 | \f[B]get_zone_remaining -z Kitchen\f[R] 45 | Displays remaining playing time for the Roon zone named 46 | \[dq]Kitchen\[dq] 47 | .SH AUTHORS 48 | .PP 49 | Written by Ronald Record 50 | .SH LICENSING 51 | .PP 52 | GET_ZONE_REMAINING is distributed under an Open Source license. 53 | See the file LICENSE in the GET_ZONE_REMAINING source distribution for 54 | information on terms & conditions for accessing and otherwise using 55 | GET_ZONE_REMAINING and for a DISCLAIMER OF ALL WARRANTIES. 56 | .SH BUGS 57 | .PP 58 | Submit bug reports online at: 59 | 60 | .SH SEE ALSO 61 | .PP 62 | \f[B]get_core_ip\f[R](1), \f[B]get_zones\f[R](1), 63 | \f[B]list_albums\f[R](1), \f[B]list_artist_albums\f[R](1), 64 | \f[B]list_artists\f[R](1), \f[B]list_composers\f[R](1), 65 | \f[B]list_genre_albums\f[R](1), \f[B]list_genre_artists\f[R](1), 66 | \f[B]list_genres\f[R](1), \f[B]list_playlists\f[R](1), 67 | \f[B]list_radio\f[R](1), \f[B]list_tags\f[R](1), 68 | \f[B]list_zones\f[R](1), \f[B]now_playing\f[R](1), 69 | \f[B]play_album\f[R](1), \f[B]play_artist\f[R](1), 70 | \f[B]play_artist_album\f[R](1), \f[B]play_artist_track\f[R](1), 71 | \f[B]play_composer\f[R](1), \f[B]play_genre\f[R](1), 72 | \f[B]play_genre_album\f[R](1), \f[B]play_genre_artist\f[R](1), 73 | \f[B]play_playlist\f[R](1), \f[B]play_radio\f[R](1), 74 | \f[B]play_tag\f[R](1), \f[B]roon\f[R](1), \f[B]set_zone\f[R](1), 75 | \f[B]set_zone_group\f[R](1), \f[B]zone_command\f[R](1) 76 | .PP 77 | Full documentation and sources at: 78 | 79 | -------------------------------------------------------------------------------- /man/man1/get_zones.1: -------------------------------------------------------------------------------- 1 | .\" Automatically generated by Pandoc 2.19.2 2 | .\" 3 | .\" Define V font for inline verbatim, using C font in formats 4 | .\" that render this, and otherwise B font. 5 | .ie "\f[CB]x\f[]"x" \{\ 6 | . ftr V B 7 | . ftr VI BI 8 | . ftr VB B 9 | . ftr VBI BI 10 | .\} 11 | .el \{\ 12 | . ftr V CR 13 | . ftr VI CI 14 | . ftr VB CB 15 | . ftr VBI CBI 16 | .\} 17 | .TH "GET_ZONES" "1" "December 05, 2021" "get_zones 2.0.1" "User Manual" 18 | .hy 19 | .SH NAME 20 | .PP 21 | get_zones - Get the Roon Zones 22 | .SH SYNOPSIS 23 | .PP 24 | \f[B]get_zones\f[R] [ ZONE ] 25 | .SH DESCRIPTION 26 | .PP 27 | Retrieves a comma separated list of Roon zones. 28 | If no zone is specified, \f[I]get_zones\f[R] returns a comma separated 29 | list of all zones. 30 | .SH COMMAND LINE OPTIONS 31 | .TP 32 | \f[B]ZONE\f[R] 33 | If a zone is specified on the command line then only that zone is 34 | returned. 35 | A case-sensitive substring can be used to retrieve all zone names that 36 | contain that string. 37 | .SH EXAMPLES 38 | .TP 39 | \f[B]get_zones HomePod\f[R] 40 | Retrieves a comma separated list of all Roon zone names containing the 41 | string \[dq]HomePod\[dq] 42 | .SH AUTHORS 43 | .PP 44 | Written by Ronald Record 45 | .SH LICENSING 46 | .PP 47 | GET_ZONES is distributed under an Open Source license. 48 | See the file LICENSE in the GET_ZONES source distribution for 49 | information on terms & conditions for accessing and otherwise using 50 | GET_ZONES and for a DISCLAIMER OF ALL WARRANTIES. 51 | .SH BUGS 52 | .PP 53 | Submit bug reports online at: 54 | 55 | .SH SEE ALSO 56 | .PP 57 | \f[B]get_core_ip\f[R](1), \f[B]get_zone_info\f[R](1), 58 | \f[B]now_playing\f[R](1), \f[B]list_albums\f[R](1), 59 | \f[B]list_artist_albums\f[R](1), \f[B]list_artists\f[R](1), 60 | \f[B]list_composers\f[R](1), \f[B]list_genre_albums\f[R](1), 61 | \f[B]list_genre_artists\f[R](1), \f[B]list_genres\f[R](1), 62 | \f[B]list_playlists\f[R](1), \f[B]list_radio\f[R](1), 63 | \f[B]list_tags\f[R](1), \f[B]list_zones\f[R](1), 64 | \f[B]play_album\f[R](1), \f[B]play_artist\f[R](1), 65 | \f[B]play_artist_album\f[R](1), \f[B]play_artist_track\f[R](1), 66 | \f[B]play_composer\f[R](1), \f[B]play_genre\f[R](1), 67 | \f[B]play_genre_album\f[R](1), \f[B]play_genre_artist\f[R](1), 68 | \f[B]play_playlist\f[R](1), \f[B]play_radio\f[R](1), 69 | \f[B]play_tag\f[R](1), \f[B]roon\f[R](1), \f[B]set_zone\f[R](1), 70 | \f[B]set_zone_group\f[R](1), \f[B]zone_command\f[R](1) 71 | .PP 72 | Full documentation and sources at: 73 | 74 | -------------------------------------------------------------------------------- /man/man1/roonanim.1: -------------------------------------------------------------------------------- 1 | .\" Automatically generated by Pandoc 2.19.2 2 | .\" 3 | .\" Define V font for inline verbatim, using C font in formats 4 | .\" that render this, and otherwise B font. 5 | .ie "\f[CB]x\f[]"x" \{\ 6 | . ftr V B 7 | . ftr VI BI 8 | . ftr VB B 9 | . ftr VBI BI 10 | .\} 11 | .el \{\ 12 | . ftr V CR 13 | . ftr VI CI 14 | . ftr VB CB 15 | . ftr VBI CBI 16 | .\} 17 | .TH "ROONANIM" "1" "June 10, 2024" "roonanim 2.0.1" "User Manual" 18 | .hy 19 | .SH NAME 20 | .PP 21 | roonanim - display animated splash screen 22 | .SH SYNOPSIS 23 | .PP 24 | \f[B]roonanim\f[R] [-a] [-f] [-k] [-q] [-z] [-u] 25 | .SH DESCRIPTION 26 | .PP 27 | The \f[V]RoonCommandLine\f[R] animated splash screen is displayed with 28 | the command \f[B]roonanim -a -q\f[R] on \f[V]roon\f[R] command menu 29 | startup and when the \f[V]About\f[R] page is displayed. 30 | .SH COMMAND LINE OPTIONS 31 | .TP 32 | \f[B]-a\f[R] 33 | Indicates animate display 34 | .TP 35 | \f[B]-f\f[R] 36 | Indicates fullscreen mode 37 | .TP 38 | \f[B]-k\f[R] 39 | Indicates do not exit 40 | .TP 41 | \f[B]-q\f[R] 42 | Indicates quick display, do not sleep 43 | .TP 44 | \f[B]-z\f[R] 45 | Indicates zoom display 46 | .TP 47 | \f[B]-u\f[R] 48 | Displays this usage message and exits 49 | .SH AUTHORS 50 | .PP 51 | Written by Ronald Record 52 | .SH LICENSING 53 | .PP 54 | ROONANIM is distributed under an Open Source license. 55 | See the file LICENSE in the ROONANIM source distribution for information 56 | on terms & conditions for accessing and otherwise using ROONANIM and for 57 | a DISCLAIMER OF ALL WARRANTIES. 58 | .SH BUGS 59 | .PP 60 | Submit bug reports online at: 61 | 62 | .SH SEE ALSO 63 | .PP 64 | \f[B]get_zone_info\f[R](1), \f[B]get_zones\f[R](1), 65 | \f[B]list_albums\f[R](1), \f[B]list_artist_albums\f[R](1), 66 | \f[B]list_artists\f[R](1), \f[B]list_composers\f[R](1), 67 | \f[B]list_genre_albums\f[R](1), \f[B]list_genre_artists\f[R](1), 68 | \f[B]list_genres\f[R](1), \f[B]list_playlists\f[R](1), 69 | \f[B]list_radio\f[R](1), \f[B]list_tags\f[R](1), 70 | \f[B]list_zones\f[R](1), \f[B]play_album\f[R](1), 71 | \f[B]play_artist\f[R](1), \f[B]play_artist_album\f[R](1), 72 | \f[B]play_artist_track\f[R](1), \f[B]play_composer\f[R](1), 73 | \f[B]play_genre\f[R](1), \f[B]play_genre_album\f[R](1), 74 | \f[B]play_genre_artist\f[R](1), \f[B]play_playlist\f[R](1), 75 | \f[B]play_radio\f[R](1), \f[B]play_tag\f[R](1), \f[B]roon\f[R](1), 76 | \f[B]set_zone\f[R](1), \f[B]set_zone_group\f[R](1), 77 | \f[B]zone_command\f[R](1) 78 | .PP 79 | Full documentation and sources at: 80 | 81 | -------------------------------------------------------------------------------- /man/man1/set_zone.1: -------------------------------------------------------------------------------- 1 | .\" Automatically generated by Pandoc 2.19.2 2 | .\" 3 | .\" Define V font for inline verbatim, using C font in formats 4 | .\" that render this, and otherwise B font. 5 | .ie "\f[CB]x\f[]"x" \{\ 6 | . ftr V B 7 | . ftr VI BI 8 | . ftr VB B 9 | . ftr VBI BI 10 | .\} 11 | .el \{\ 12 | . ftr V CR 13 | . ftr VI CI 14 | . ftr VB CB 15 | . ftr VBI CBI 16 | .\} 17 | .TH "SET_ZONE" "1" "December 05, 2021" "set_zone 2.0.1" "User Manual" 18 | .hy 19 | .SH NAME 20 | .PP 21 | set_zone - Set the default Roon playback Zone 22 | .SH SYNOPSIS 23 | .PP 24 | \f[B]set_zone\f[R] [ ZONE ] 25 | .SH DESCRIPTION 26 | .PP 27 | Sets the default Roon playback zone. 28 | Current playback, if active, is unaffected. 29 | Subsequent Roon commands, if no zone is specified on the command line, 30 | will take effect in the specified default Roon zone. 31 | If the Roon zone specified on the command line does not match a 32 | configured Roon zone exactly then the first Roon zone name containing 33 | the \f[I]ZONE\f[R] substring will be set as the default Roon zone. 34 | .SH COMMAND LINE OPTIONS 35 | .TP 36 | \f[B]ZONE\f[R] 37 | Set the default Roon playback zone to \f[I]ZONE\f[R] 38 | .SH EXAMPLES 39 | .TP 40 | \f[B]set_zone HomePod\f[R] 41 | Will set the default Roon zone to \[dq]HomePod\[dq] if a zone by that 42 | name exists. 43 | If no zone named \[dq]HomePod\[dq] exists then Roon zones are searched 44 | for a zone name containing the string \[dq]HomePod\[dq] and the first 45 | matching Roon zone name is set as the default Roon zone. 46 | .SH AUTHORS 47 | .PP 48 | Written by Ronald Record 49 | .SH LICENSING 50 | .PP 51 | SET_ZONE is distributed under an Open Source license. 52 | See the file LICENSE in the SET_ZONE source distribution for information 53 | on terms & conditions for accessing and otherwise using SET_ZONE and for 54 | a DISCLAIMER OF ALL WARRANTIES. 55 | .SH BUGS 56 | .PP 57 | Submit bug reports online at: 58 | 59 | .SH SEE ALSO 60 | .PP 61 | \f[B]get_core_ip\f[R](1), \f[B]get_zone_info\f[R](1), 62 | \f[B]get_zones\f[R](1), \f[B]list_albums\f[R](1), 63 | \f[B]list_artist_albums\f[R](1), \f[B]list_artists\f[R](1), 64 | \f[B]list_composers\f[R](1), \f[B]list_genre_albums\f[R](1), 65 | \f[B]list_genre_artists\f[R](1), \f[B]list_genres\f[R](1), 66 | \f[B]list_playlists\f[R](1), \f[B]list_radio\f[R](1), 67 | \f[B]list_tags\f[R](1), \f[B]list_zones\f[R](1), 68 | \f[B]play_album\f[R](1), \f[B]play_artist\f[R](1), 69 | \f[B]play_artist_album\f[R](1), \f[B]play_artist_track\f[R](1), 70 | \f[B]play_composer\f[R](1), \f[B]play_genre\f[R](1), 71 | \f[B]play_genre_album\f[R](1), \f[B]play_genre_artist\f[R](1), 72 | \f[B]play_playlist\f[R](1), \f[B]play_radio\f[R](1), 73 | \f[B]play_tag\f[R](1), \f[B]roon\f[R](1), \f[B]set_zone\f[R](1), 74 | \f[B]set_zone_group\f[R](1), \f[B]zone_command\f[R](1) 75 | .PP 76 | Full documentation and sources at: 77 | 78 | -------------------------------------------------------------------------------- /markdown/README.md: -------------------------------------------------------------------------------- 1 | # RoonCommandLine/markdown 2 | 3 | This directory contains markdown format input files used by pandoc to automatically 4 | generate man format man pages. The utility script 5 | [md2man](https://github.com/doctorfree/DoctorFreeScripts/-/blob/master/scripts/md2man.sh) 6 | in the [DoctorFreeScripts repository](https://github.com/doctorfree/DoctorFreeScripts) 7 | is used as a pandoc wrapper. 8 | 9 | The man page format output can be found at ../man/man?/.? 10 | For example, the man page output for the `roon` command would be found at 11 | ../man/man1/roon.1 12 | 13 | ## Contents 14 | 15 | - [**roon.1.md**](roon.1.md) - Markdown input for auto-generation of the Roon man page 16 | - [**get_core_ip.1.md**](get_core_ip.1.md) - Get the Roon Core IP address 17 | - [**get_zone_info.1.md**](get_zone_info.1.md) - Get Roon Zone Info 18 | - [**get_zones.1.md**](get_zones.1.md) - Get the Roon Zones 19 | - [**list_albums.1.md**](list_albums.1.md) - List Roon Library Albums 20 | - [**list_artists.1.md**](list_artists.1.md) - List Roon Library Artists 21 | - [**list_genres.1.md**](list_genres.1.md) - List Roon Library Genres 22 | - [**list_playlists.1.md**](list_playlists.1.md) - List Roon Library Playlists 23 | - [**list_radio.1.md**](list_radio.1.md) - List Roon Live Radio Channels 24 | - [**list_tags.1.md**](list_tags.1.md) - List Roon Library Tags 25 | - [**list_tracks.1.md**](list_tracks.1.md) - List Roon Library Tracks 26 | - [**list_zones.1.md**](list_zones.1.md) - List Roon Zones 27 | - [**now_playing.1.md**](now_playing.1.md) - Get Roon Zone Now Playing Info 28 | - [**play_album.1.md**](play_album.1.md) - Play Roon Library Album 29 | - [**play_artist.1.md**](play_artist.1.md) - Play Roon Library Artist 30 | - [**play_genre.1.md**](play_genre.1.md) - Play Roon Library Genre 31 | - [**play_playlist.1.md**](play_playlist.1.md) - Play Roon Library Playlist 32 | - [**play_radio.1.md**](play_radio.1.md) - Play Roon Live Radio Channel 33 | - [**play_tag.1.md**](play_tag.1.md) - Play Roon Library Tag 34 | - [**set_volume.1.md**](set_volume.1.md) - Set the Roon Zone volume level 35 | - [**set_zone.1.md**](set_zone.1.md) - Set the Roon Zone 36 | - [**set_zone_group.1.md**](set_zone_group.1.md) - Set the Roon Zone Group 37 | - [**zone_command.1.md**](zone_command.1.md) - Execute a Roon command 38 | -------------------------------------------------------------------------------- /markdown/get_core_ip.1.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: GET_CORE_IP 3 | section: 1 4 | header: User Manual 5 | footer: get_core_ip 2.0.1 6 | date: December 05, 2021 7 | --- 8 | # NAME 9 | get_core_ip - Get the Roon Core IP address 10 | 11 | # SYNOPSIS 12 | **get_core_ip** 13 | 14 | # DESCRIPTION 15 | Automatically discover a Roon Core System on the local network and retrieve the Roon Core IP address 16 | 17 | # AUTHORS 18 | Written by Ronald Record github@ronrecord.com 19 | 20 | # LICENSING 21 | GET_CORE_IP is distributed under an Open Source license. 22 | See the file LICENSE in the GET_CORE_IP source distribution 23 | for information on terms & conditions for accessing and 24 | otherwise using GET_CORE_IP and for a DISCLAIMER OF ALL WARRANTIES. 25 | 26 | # BUGS 27 | Submit bug reports online at: https://github.com/doctorfree/RoonCommandLine/issues 28 | 29 | # SEE ALSO 30 | **get_zone_info**(1), **get_zones**(1), **list_albums**(1), **list_artist_albums**(1), **list_artists**(1), **list_composers**(1), **list_genre_albums**(1), **list_genre_artists**(1), **list_genres**(1), **list_playlists**(1), **list_radio**(1), **list_tags**(1), **list_zones**(1), **play_album**(1), **play_artist**(1), **play_artist_album**(1), **play_artist_track**(1), **play_composer**(1), **play_genre**(1), **play_genre_album**(1), **play_genre_artist**(1), **play_playlist**(1), **play_radio**(1), **play_tag**(1), **roon**(1), **set_zone**(1), **set_zone_group**(1), **zone_command**(1) 31 | 32 | Full documentation and sources at: https://github.com/doctorfree/RoonCommandLine 33 | 34 | -------------------------------------------------------------------------------- /markdown/get_zone_info.1.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: GET_ZONE_INFO 3 | section: 1 4 | header: User Manual 5 | footer: get_zone_info 2.0.1 6 | date: December 05, 2021 7 | --- 8 | # NAME 9 | get_zone_info - Get Roon Zone Info 10 | 11 | # SYNOPSIS 12 | **get_zone_info** [ **-ahlnpsv** ] [ **-z** ZONE ] 13 | 14 | # DESCRIPTION 15 | Retrieves information on specified zone or all zones if no zone is specified. If a zone is specified using the `-z zone` option then extended information on that zone is displayed. If the `-l` flag is provided then only the listing of zone grouping is displayed. 16 | 17 | # COMMAND LINE OPTIONS 18 | **-a** 19 | : indicates display all zone info types 20 | 21 | **-n** 22 | : indicates display now playing zone info 23 | 24 | **-p** 25 | : indicates display zone properties 26 | 27 | **-s** 28 | : indicates display zone settings 29 | 30 | **-l** 31 | : indicates output a comma separated list of zones 32 | 33 | **-v** 34 | : indicates verbose output 35 | 36 | **-h** 37 | : displays a usage message and exits 38 | 39 | **-z ZONE** 40 | : If a *ZONE* is specified then retrieve info/grouping for that zone only. If no *ZONE* is sprovided on the command line then retrieve info/grouping for all zones. '-z default' indicates the default zone, '-z last' the last zone used 41 | 42 | # EXAMPLES 43 | **get_zone_info** 44 | : Displays info and zone groupings for all zones 45 | 46 | **get_zone_info -l** 47 | : Retrieves a comma separated list of zone groupings for all zones 48 | 49 | **get_zone_info -n -z default** 50 | : Displays now playing information for the default Roon zone 51 | 52 | **get_zone_info -z Kitchen** 53 | : Displays extensive information on the Roon zone named "Kitchen" 54 | 55 | # AUTHORS 56 | Written by Ronald Record github@ronrecord.com 57 | 58 | # LICENSING 59 | GET_ZONE_INFO is distributed under an Open Source license. 60 | See the file LICENSE in the GET_ZONE_INFO source distribution 61 | for information on terms & conditions for accessing and 62 | otherwise using GET_ZONE_INFO and for a DISCLAIMER OF ALL WARRANTIES. 63 | 64 | # BUGS 65 | Submit bug reports online at: https://github.com/doctorfree/RoonCommandLine/issues 66 | 67 | # SEE ALSO 68 | **get_core_ip**(1), **get_zones**(1), **list_albums**(1), **list_artist_albums**(1), **list_artists**(1), **list_composers**(1), **list_genre_albums**(1), **list_genre_artists**(1), **list_genres**(1), **list_playlists**(1), **list_radio**(1), **list_tags**(1), **list_zones**(1), **now_playing**(1), **play_album**(1), **play_artist**(1), **play_artist_album**(1), **play_artist_track**(1), **play_composer**(1), **play_genre**(1), **play_genre_album**(1), **play_genre_artist**(1), **play_playlist**(1), **play_radio**(1), **play_tag**(1), **roon**(1), **set_zone**(1), **set_zone_group**(1), **zone_command**(1) 69 | 70 | Full documentation and sources at: https://github.com/doctorfree/RoonCommandLine 71 | 72 | -------------------------------------------------------------------------------- /markdown/get_zone_remaining.1.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: GET_ZONE_REMAINING 3 | section: 1 4 | header: User Manual 5 | footer: get_zone_remaining 2.0.1 6 | date: December 05, 2022 7 | --- 8 | # NAME 9 | get_zone_remaining - Get remaining time in seconds for track playing in Roon Zone 10 | 11 | # SYNOPSIS 12 | **get_zone_remaining** [ **-z** ZONE ] 13 | 14 | # DESCRIPTION 15 | Retrieves remaining time in seconds for track playing in specified zone or default zone if no zone is specified. 16 | 17 | # COMMAND LINE OPTIONS 18 | **-z ZONE** 19 | : If a *ZONE* is specified then retrieve remaining time in seconds for that zone. If no *ZONE* is sprovided on the command line then retrieve remaining time for the default zone. '-z default' indicates the default zone, '-z last' the last zone used 20 | 21 | # EXAMPLES 22 | **get_zone_remaining** 23 | : Displays remaining time for the default zone 24 | 25 | **get_zone_remaining -z Kitchen** 26 | : Displays remaining playing time for the Roon zone named "Kitchen" 27 | 28 | # AUTHORS 29 | Written by Ronald Record github@ronrecord.com 30 | 31 | # LICENSING 32 | GET_ZONE_REMAINING is distributed under an Open Source license. 33 | See the file LICENSE in the GET_ZONE_REMAINING source distribution 34 | for information on terms & conditions for accessing and 35 | otherwise using GET_ZONE_REMAINING and for a DISCLAIMER OF ALL WARRANTIES. 36 | 37 | # BUGS 38 | Submit bug reports online at: https://github.com/doctorfree/RoonCommandLine/issues 39 | 40 | # SEE ALSO 41 | **get_core_ip**(1), **get_zones**(1), **list_albums**(1), **list_artist_albums**(1), **list_artists**(1), **list_composers**(1), **list_genre_albums**(1), **list_genre_artists**(1), **list_genres**(1), **list_playlists**(1), **list_radio**(1), **list_tags**(1), **list_zones**(1), **now_playing**(1), **play_album**(1), **play_artist**(1), **play_artist_album**(1), **play_artist_track**(1), **play_composer**(1), **play_genre**(1), **play_genre_album**(1), **play_genre_artist**(1), **play_playlist**(1), **play_radio**(1), **play_tag**(1), **roon**(1), **set_zone**(1), **set_zone_group**(1), **zone_command**(1) 42 | 43 | Full documentation and sources at: https://github.com/doctorfree/RoonCommandLine 44 | 45 | -------------------------------------------------------------------------------- /markdown/get_zone_volume.1.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: GET_ZONE_VOLUME 3 | section: 1 4 | header: User Manual 5 | footer: get_zone_volume 2.0.1 6 | date: December 05, 2022 7 | --- 8 | # NAME 9 | get_zone_volume - Get current volume level and range for specified Roon Zone 10 | 11 | # SYNOPSIS 12 | **get_zone_volume** [**-g**] [**-n**] [ **-z** ZONE ] 13 | 14 | # DESCRIPTION 15 | Retrieves the current volume level and volume range of specified zone or default zone if no zone is specified. If the zone is grouped, and `-g` is provided as a command line argument, then all grouped zones are queried for volume levels and ranges. The `-n` switch indicates return only the volume level value without description or other values. 16 | 17 | # COMMAND LINE OPTIONS 18 | **-g** 19 | : If *-g* is specified then retrieve volume levels and volume ranges for all zones in a grouped zone. If no *-g* is provided on the command line then retrieve volume level and range for only the specified zone regardless of whether it is grouped. 20 | 21 | **-n** 22 | : If *-n* is specified then only return the volume level for specified zone or zone grouping. 23 | 24 | **-z ZONE** 25 | : If a *ZONE* is specified then retrieve volume level and volume range for that zone. If no *ZONE* is provided on the command line then retrieve volume level and range for the default zone. '-z default' indicates the default zone, '-z last' the last zone used 26 | 27 | # EXAMPLES 28 | **get_zone_volume** 29 | : Displays volume level and volume range for the default zone 30 | 31 | **get_zone_volume -z Kitchen** 32 | : Displays volume level and volume range for the Roon zone named "Kitchen" 33 | 34 | **get_zone_volume -n -z Kitchen** 35 | : Displays only the volume level for the Roon zone named "Kitchen" 36 | 37 | **get_zone_volume -g -z Kitchen** 38 | : Displays volume level and volume range for the Roon zone named "Kitchen" and any grouped zones 39 | 40 | # AUTHORS 41 | Written by Ronald Record github@ronrecord.com 42 | 43 | # LICENSING 44 | GET_ZONE_VOLUME is distributed under an Open Source license. 45 | See the file LICENSE in the GET_ZONE_VOLUME source distribution 46 | for information on terms & conditions for accessing and 47 | otherwise using GET_ZONE_VOLUME and for a DISCLAIMER OF ALL WARRANTIES. 48 | 49 | # BUGS 50 | Submit bug reports online at: https://github.com/doctorfree/RoonCommandLine/issues 51 | 52 | # SEE ALSO 53 | **get_core_ip**(1), **get_zones**(1), **list_albums**(1), **list_artist_albums**(1), **list_artists**(1), **list_composers**(1), **list_genre_albums**(1), **list_genre_artists**(1), **list_genres**(1), **list_playlists**(1), **list_radio**(1), **list_tags**(1), **list_zones**(1), **now_playing**(1), **play_album**(1), **play_artist**(1), **play_artist_album**(1), **play_artist_track**(1), **play_composer**(1), **play_genre**(1), **play_genre_album**(1), **play_genre_artist**(1), **play_playlist**(1), **play_radio**(1), **play_tag**(1), **roon**(1), **set_zone**(1), **set_zone_group**(1), **zone_command**(1) 54 | 55 | Full documentation and sources at: https://github.com/doctorfree/RoonCommandLine 56 | 57 | -------------------------------------------------------------------------------- /markdown/get_zones.1.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: GET_ZONES 3 | section: 1 4 | header: User Manual 5 | footer: get_zones 2.0.1 6 | date: December 05, 2021 7 | --- 8 | # NAME 9 | get_zones - Get the Roon Zones 10 | 11 | # SYNOPSIS 12 | **get_zones** [ ZONE ] 13 | 14 | # DESCRIPTION 15 | Retrieves a comma separated list of Roon zones. If no zone is specified, *get_zones* returns a comma separated list of all zones. 16 | 17 | # COMMAND LINE OPTIONS 18 | **ZONE** 19 | : If a zone is specified on the command line then only that zone is returned. A case-sensitive substring can be used to retrieve all zone names that contain that string. 20 | 21 | # EXAMPLES 22 | **get_zones HomePod** 23 | : Retrieves a comma separated list of all Roon zone names containing the string "HomePod" 24 | 25 | # AUTHORS 26 | Written by Ronald Record github@ronrecord.com 27 | 28 | # LICENSING 29 | GET_ZONES is distributed under an Open Source license. 30 | See the file LICENSE in the GET_ZONES source distribution 31 | for information on terms & conditions for accessing and 32 | otherwise using GET_ZONES and for a DISCLAIMER OF ALL WARRANTIES. 33 | 34 | # BUGS 35 | Submit bug reports online at: https://github.com/doctorfree/RoonCommandLine/issues 36 | 37 | # SEE ALSO 38 | **get_core_ip**(1), **get_zone_info**(1), **now_playing**(1), **list_albums**(1), **list_artist_albums**(1), **list_artists**(1), **list_composers**(1), **list_genre_albums**(1), **list_genre_artists**(1), **list_genres**(1), **list_playlists**(1), **list_radio**(1), **list_tags**(1), **list_zones**(1), **play_album**(1), **play_artist**(1), **play_artist_album**(1), **play_artist_track**(1), **play_composer**(1), **play_genre**(1), **play_genre_album**(1), **play_genre_artist**(1), **play_playlist**(1), **play_radio**(1), **play_tag**(1), **roon**(1), **set_zone**(1), **set_zone_group**(1), **zone_command**(1) 39 | 40 | Full documentation and sources at: https://github.com/doctorfree/RoonCommandLine 41 | 42 | -------------------------------------------------------------------------------- /markdown/list_genres.1.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: LIST_GENRES 3 | section: 1 4 | header: User Manual 5 | footer: list_genres 2.0.1 6 | date: December 05, 2021 7 | --- 8 | # NAME 9 | list_genres - List Roon Library Genres 10 | 11 | # SYNOPSIS 12 | **list_genres** [ -q ] [ -z ZONE ] [ GENRE ] [ EXGENRE ] 13 | 14 | # DESCRIPTION 15 | Lists Roon Library genres matching the specified genre name or substring 16 | 17 | # COMMAND LINE OPTIONS 18 | **-q** 19 | : Specifies quiet output 20 | 21 | **-z ZONE** 22 | : Specifies the Roon zone, '-z default' indicates the default zone, '-z last' the last zone used 23 | 24 | **GENRE** 25 | : Provide an genre name, in quotes if it contains spaces, or a case-sensitive substring. All Roon library genre names matching the provided genre name or containing the substring will be returned 26 | 27 | **EXGENRE** 28 | : Provide a genre exclusion string, in quotes if it contains spaces. No Roon library genre names including the provided genre exclusion string will be listed 29 | 30 | # EXAMPLES 31 | **list_genres Rock** 32 | : Will return a list of Roon library genre names, one per line, that contain the string "Rock" 33 | 34 | **list_genres Rock Pop** 35 | : Will return a list of Roon library genre names, one per line, that contain the string "Rock" but not "Pop" 36 | 37 | # AUTHORS 38 | Written by Ronald Record github@ronrecord.com 39 | 40 | # LICENSING 41 | LIST_GENRES is distributed under an Open Source license. 42 | See the file LICENSE in the LIST_GENRES source distribution 43 | for information on terms & conditions for accessing and 44 | otherwise using LIST_GENRES and for a DISCLAIMER OF ALL WARRANTIES. 45 | 46 | # BUGS 47 | Submit bug reports online at: https://github.com/doctorfree/RoonCommandLine/issues 48 | 49 | # SEE ALSO 50 | **get_core_ip**(1), **get_zone_info**(1), **get_zones**(1), **list_albums**(1), **list_artist_albums**(1), **list_artists**(1), **list_composers**(1), **list_genre_albums**(1), **list_genre_artists**(1), **list_genres**(1), **list_playlists**(1), **list_radio**(1), **list_tags**(1), **list_zones**(1), **play_album**(1), **play_artist**(1), **play_artist_album**(1), **play_artist_track**(1), **play_composer**(1), **play_genre**(1), **play_genre_album**(1), **play_genre_artist**(1), **play_playlist**(1), **play_radio**(1), **play_tag**(1), **roon**(1), **set_zone**(1), **set_zone_group**(1), **zone_command**(1) 51 | 52 | Full documentation and sources at: https://github.com/doctorfree/RoonCommandLine 53 | 54 | The corresponding Python script, */usr/local/Roon/api/list_genres.py*, 55 | can be invoked directly as: 56 | 57 | **python3 /usr/local/Roon/api/list_genres.py [ options]** 58 | 59 | Where [ options ] are described in the following usage message: 60 | 61 | ~~~~ 62 | usage: list_genres.py [-h] [-g GENRE] [-x EXGENRE] [-z ZONE] 63 | 64 | optional arguments: 65 | -h, --help show this help message and exit 66 | -g GENRE, --genre GENRE 67 | genre search term 68 | -x EXGENRE, --exgenre EXGENRE 69 | genre exclude search term 70 | -z ZONE, --zone ZONE zone selection 71 | ~~~~ 72 | -------------------------------------------------------------------------------- /markdown/list_radio.1.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: LIST_RADIO 3 | section: 1 4 | header: User Manual 5 | footer: list_radio 2.0.1 6 | date: December 05, 2021 7 | --- 8 | # NAME 9 | list_radio - List Roon Live Radio Channels 10 | 11 | # SYNOPSIS 12 | **list_radio** [ -q ] [ -z ZONE ] [ RADIO ] 13 | 14 | # DESCRIPTION 15 | Lists Roon Live Radio channels matching the specified radio station name or substring 16 | 17 | # COMMAND LINE OPTIONS 18 | **-q** 19 | : Specifies quiet output 20 | 21 | **-z ZONE** 22 | : Specifies the Roon zone, '-z default' indicates the default zone, '-z last' the last zone used 23 | 24 | **RADIO** 25 | : Provide a radio station name, in quotes if it contains spaces, or a case-sensitive substring. All Roon radio station names matching the provided radio station name or containing the substring will be returned 26 | 27 | # EXAMPLES 28 | **list_radio WKRP** 29 | : Will return a list of Roon radio station names, one per line, that contain the string "WKRP" 30 | 31 | # AUTHORS 32 | Written by Ronald Record github@ronrecord.com 33 | 34 | # LICENSING 35 | LIST_RADIO is distributed under an Open Source license. 36 | See the file LICENSE in the LIST_RADIO source distribution 37 | for information on terms & conditions for accessing and 38 | otherwise using LIST_RADIO and for a DISCLAIMER OF ALL WARRANTIES. 39 | 40 | # BUGS 41 | Submit bug reports online at: https://github.com/doctorfree/RoonCommandLine/issues 42 | 43 | # SEE ALSO 44 | **get_core_ip**(1), **get_zone_info**(1), **get_zones**(1), **list_albums**(1), **list_artist_albums**(1), **list_artists**(1), **list_composers**(1), **list_genre_albums**(1), **list_genre_artists**(1), **list_genres**(1), **list_playlists**(1), **list_radio**(1), **list_tags**(1), **list_zones**(1), **play_album**(1), **play_artist**(1), **play_artist_album**(1), **play_artist_track**(1), **play_composer**(1), **play_genre**(1), **play_genre_album**(1), **play_genre_artist**(1), **play_playlist**(1), **play_radio**(1), **play_tag**(1), **roon**(1), **set_zone**(1), **set_zone_group**(1), **zone_command**(1) 45 | 46 | Full documentation and sources at: https://github.com/doctorfree/RoonCommandLine 47 | 48 | The corresponding Python script, */usr/local/Roon/api/list_radio.py*, 49 | can be invoked directly as: 50 | 51 | **python3 /usr/local/Roon/api/list_radio.py [ options]** 52 | 53 | Where [ options ] are described in the following usage message: 54 | 55 | ~~~~ 56 | usage: list_radio.py [-h] [-r RADIO] [-z ZONE] 57 | 58 | optional arguments: 59 | -h, --help show this help message and exit 60 | -r RADIO, --radio RADIO 61 | radio search term 62 | -z ZONE, --zone ZONE zone selection 63 | ~~~~ 64 | -------------------------------------------------------------------------------- /markdown/list_tags.1.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: LIST_TAGS 3 | section: 1 4 | header: User Manual 5 | footer: list_tags 2.0.1 6 | date: December 05, 2021 7 | --- 8 | # NAME 9 | list_tags - List Roon Library Tags 10 | 11 | # SYNOPSIS 12 | **list_tags** [ -q ] [ -z ZONE ] [ TAG ] 13 | 14 | # DESCRIPTION 15 | Lists Roon Library tags matching the specified tag name or substring 16 | 17 | # COMMAND LINE OPTIONS 18 | **-q** 19 | : Specifies quiet output 20 | 21 | **-z ZONE** 22 | : Specifies the Roon zone, '-z default' indicates the default zone, '-z last' the last zone used 23 | 24 | **TAG** 25 | : Provide an tag name, in quotes if it contains spaces, or a case-sensitive substring. All Roon library tag names matching the provided tag name or containing the substring will be returned 26 | 27 | # EXAMPLES 28 | **list_tags Prog** 29 | : Will return a list of Roon library tag names, one per line, that contain the string "Prog" 30 | 31 | # AUTHORS 32 | Written by Ronald Record github@ronrecord.com 33 | 34 | # LICENSING 35 | LIST_TAGS is distributed under an Open Source license. 36 | See the file LICENSE in the LIST_TAGS source distribution 37 | for information on terms & conditions for accessing and 38 | otherwise using LIST_TAGS and for a DISCLAIMER OF ALL WARRANTIES. 39 | 40 | # BUGS 41 | Submit bug reports online at: https://github.com/doctorfree/RoonCommandLine/issues 42 | 43 | # SEE ALSO 44 | **get_core_ip**(1), **get_zone_info**(1), **get_zones**(1), **list_albums**(1), **list_artist_albums**(1), **list_artists**(1), **list_composers**(1), **list_genre_albums**(1), **list_genre_artists**(1), **list_genres**(1), **list_playlists**(1), **list_radio**(1), **list_tags**(1), **list_zones**(1), **play_album**(1), **play_artist**(1), **play_artist_album**(1), **play_artist_track**(1), **play_composer**(1), **play_genre**(1), **play_genre_album**(1), **play_genre_artist**(1), **play_playlist**(1), **play_radio**(1), **play_tag**(1), **roon**(1), **set_zone**(1), **set_zone_group**(1), **zone_command**(1) 45 | 46 | Full documentation and sources at: https://github.com/doctorfree/RoonCommandLine 47 | 48 | The corresponding Python script, */usr/local/Roon/api/list_tags.py*, 49 | can be invoked directly as: 50 | 51 | **python3 /usr/local/Roon/api/list_tags.py [ options]** 52 | 53 | Where [ options ] are described in the following usage message: 54 | 55 | ~~~~ 56 | usage: list_tags.py [-h] [-t TAG] [-z ZONE] 57 | 58 | optional arguments: 59 | -h, --help show this help message and exit 60 | -t TAG, --tag TAG tag search term 61 | -z ZONE, --zone ZONE zone selection 62 | ~~~~ 63 | -------------------------------------------------------------------------------- /markdown/list_tracks.1.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: LIST_TRACKS 3 | section: 1 4 | header: User Manual 5 | footer: list_tracks 2.0.1 6 | date: May 28, 2024 7 | --- 8 | # NAME 9 | list_tracks - List Roon Library Tracks 10 | 11 | # SYNOPSIS 12 | **list_tracks** [-q] [-z ZONE] [TRACK] [EXCLUDE] 13 | 14 | # DESCRIPTION 15 | Lists Roon Library tracks matching the specified track name or substring. Optionally, an exclusion string can be provided as the second argument. Track names containing the exclusion string will not be listed. 16 | 17 | # COMMAND LINE OPTIONS 18 | **-q** 19 | : specifies quiet output 20 | 21 | **-z** 'ZONE' 22 | : specifies the zone, '-z default' indicates the default zone, '-z last' the last zone used 23 | 24 | **TRACK** 25 | : Provide a track name, in quotes if it contains spaces, or a case-sensitive substring. All Roon library track names matching the provided track name or containing the substring will be listed 26 | 27 | **EXCLUDE** 28 | : Provide a track exclusion string, in quotes if it contains spaces. No Roon library track names including the provided track exclusion string will be listed 29 | 30 | # EXAMPLES 31 | **list_tracks Moon** 32 | : Will return a list of Roon library track names, one per line, that contain the string "Moon" 33 | 34 | **list_tracks Moon Light** 35 | : Will return a list of Roon library track names, one per line, that contain the string "Moon" but do not contain the string "Light" 36 | 37 | # AUTHORS 38 | Written by Ronald Record github@ronrecord.com 39 | 40 | # LICENSING 41 | LIST_TRACKS is distributed under an Open Source license. 42 | See the file LICENSE in the LIST_TRACKS source distribution 43 | for information on terms & conditions for accessing and 44 | otherwise using LIST_TRACKS and for a DISCLAIMER OF ALL WARRANTIES. 45 | 46 | # BUGS 47 | Submit bug reports online at: https://github.com/doctorfree/RoonCommandLine/issues 48 | 49 | # SEE ALSO 50 | **get_core_ip**(1), **get_zone_info**(1), **get_zones**(1), **list_albums**(1), **list_artist_albums**(1), **list_artists**(1), **list_composers**(1), **list_genre_albums**(1), **list_genre_artists**(1), **list_genres**(1), **list_playlists**(1), **list_radio**(1), **list_tags**(1), **list_zones**(1), **play_album**(1), **play_artist**(1), **play_artist_album**(1), **play_artist_track**(1), **play_composer**(1), **play_genre**(1), **play_genre_album**(1), **play_genre_artist**(1), **play_playlist**(1), **play_radio**(1), **play_tag**(1), **roon**(1), **set_zone**(1), **set_zone_group**(1), **zone_command**(1) 51 | 52 | Full documentation and sources at: https://github.com/doctorfree/RoonCommandLine 53 | -------------------------------------------------------------------------------- /markdown/list_zones.1.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: LIST_ZONES 3 | section: 1 4 | header: User Manual 5 | footer: list_zones 2.0.1 6 | date: December 05, 2021 7 | --- 8 | # NAME 9 | list_zones - List Roon Zones 10 | 11 | # SYNOPSIS 12 | **list_zones** [ -q ] [ ZONE ] 13 | 14 | # DESCRIPTION 15 | Lists all Roon zones, zone groupings, and configured zone grouping presets. If a zone is specified on the command line then only that zone and its groupings will be retrieved. A case-sensitive substring can be used as the ZONE argument in which case all zones that contain that substring along with their groupings will be returned. 16 | 17 | # COMMAND LINE OPTIONS 18 | **-q** 19 | : Specifies quiet output 20 | 21 | **ZONE** 22 | : The zone name or case-sensitive substring to match, 'default' indicates the default zone, 'last' the last zone used 23 | 24 | # EXAMPLES 25 | **list_zones HomePod** 26 | : Will return a list of zones and zone groupings for all zone names containing the string "HomePod" 27 | 28 | # AUTHORS 29 | Written by Ronald Record github@ronrecord.com 30 | 31 | # LICENSING 32 | LIST_ZONES is distributed under an Open Source license. 33 | See the file LICENSE in the LIST_ZONES source distribution 34 | for information on terms & conditions for accessing and 35 | otherwise using LIST_ZONES and for a DISCLAIMER OF ALL WARRANTIES. 36 | 37 | # BUGS 38 | Submit bug reports online at: https://github.com/doctorfree/RoonCommandLine/issues 39 | 40 | # SEE ALSO 41 | **get_core_ip**(1), **get_zone_info**(1), **get_zones**(1), **list_albums**(1), **list_artist_albums**(1), **list_artists**(1), **list_composers**(1), **list_genre_albums**(1), **list_genre_artists**(1), **list_genres**(1), **list_playlists**(1), **list_radio**(1), **list_tags**(1), **list_zones**(1), **play_album**(1), **play_artist**(1), **play_artist_album**(1), **play_artist_track**(1), **play_composer**(1), **play_genre**(1), **play_genre_album**(1), **play_genre_artist**(1), **play_playlist**(1), **play_radio**(1), **play_tag**(1), **roon**(1), **set_zone**(1), **set_zone_group**(1), **zone_command**(1) 42 | 43 | Full documentation and sources at: https://github.com/doctorfree/RoonCommandLine 44 | 45 | The corresponding Python script, */usr/local/Roon/api/list_zones.py*, 46 | can be invoked directly as: 47 | 48 | **python3 /usr/local/Roon/api/list_zones.py [ options]** 49 | 50 | Where [ options ] are described in the following usage message: 51 | 52 | ~~~~ 53 | usage: list_zones.py [-h] [-g] [-i] [-z ZONE] 54 | 55 | optional arguments: 56 | -h, --help show this help message and exit 57 | -g, --get Get a comma separated list of zones 58 | -i, --info Get zone info 59 | -z ZONE, --zone ZONE Zone selection 60 | ~~~~ 61 | -------------------------------------------------------------------------------- /markdown/now_playing.1.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: NOW_PLAYING 3 | section: 1 4 | header: User Manual 5 | footer: now_playing 2.0.1 6 | date: April 24, 2022 7 | --- 8 | # NAME 9 | now_playing - Get track, artist, and album now playing in specified Roon zone 10 | 11 | # SYNOPSIS 12 | **now_playing** [ **-a** ] [ **-h** ] [ **-p** ] [ **-P** ] [ **-z** ZONE ] 13 | 14 | # DESCRIPTION 15 | Retrieves now playing information on specified zone or all zones if no zone is specified. Only actively playing zones are displayed if **-p** is provided, only paused zones if **-P** is provided. If the **-a** flag is provided then all zone states are displayed regardless of their state. 16 | 17 | # COMMAND LINE OPTIONS 18 | 19 | **-a** 20 | : Display all zone states 21 | 22 | **-h** 23 | : Display a usage message and exit 24 | 25 | **-p** 26 | : Display only zones in the playing state 27 | 28 | **-P** 29 | : Display only zones in the paused state 30 | 31 | **-z ZONE** 32 | : If a *ZONE* is specified then retrieve now playing information for that zone only. If no *ZONE* is provided on the command line then retrieve now playing information for all zones. '-z default' indicates the default zone, '-z last' the last zone used 33 | 34 | # EXAMPLES 35 | **now_playing** 36 | : Displays now playing info for all zones with active playing state 37 | 38 | **now_playing -z Kitchen** 39 | : Displays now playing info for the Roon zone named "Kitchen" 40 | 41 | **now_playing -a** 42 | : Displays now playing info for all zones regardless of state 43 | 44 | **now_playing -p** 45 | : Displays now playing info for all zones in the playing state 46 | 47 | # AUTHORS 48 | Written by Ronald Record github@ronrecord.com 49 | 50 | # LICENSING 51 | NOW_PLAYING is distributed under an Open Source license. 52 | See the file LICENSE in the NOW_PLAYING source distribution 53 | for information on terms & conditions for accessing and 54 | otherwise using NOW_PLAYING and for a DISCLAIMER OF ALL WARRANTIES. 55 | 56 | # BUGS 57 | Submit bug reports online at: https://github.com/doctorfree/RoonCommandLine/issues 58 | 59 | # SEE ALSO 60 | **get_core_ip**(1), **get_zone_info**(1), **get_zones**(1), **list_albums**(1), **list_artist_albums**(1), **list_artists**(1), **list_composers**(1), **list_genre_albums**(1), **list_genre_artists**(1), **list_genres**(1), **list_playlists**(1), **list_radio**(1), **list_tags**(1), **list_zones**(1), **play_album**(1), **play_artist**(1), **play_artist_album**(1), **play_artist_track**(1), **play_composer**(1), **play_genre**(1), **play_genre_album**(1), **play_genre_artist**(1), **play_playlist**(1), **play_radio**(1), **play_tag**(1), **roon**(1), **set_zone**(1), **set_zone_group**(1), **zone_command**(1) 61 | 62 | Full documentation and sources at: https://github.com/doctorfree/RoonCommandLine 63 | 64 | -------------------------------------------------------------------------------- /markdown/play_tag.1.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: PLAY_TAG 3 | section: 1 4 | header: User Manual 5 | footer: play_tag 2.0.1 6 | date: December 05, 2021 7 | --- 8 | # NAME 9 | play_tag - Play Roon Library Tag 10 | 11 | # SYNOPSIS 12 | **play_tag** [ -z ZONE ] [ TAG ] 13 | 14 | # DESCRIPTION 15 | Plays the Roon Library tag named *TAG*. If no library tag name matches *TAG* exactly, search for Roon Library tag whose name contains the case-sensitive string *TAG*. If there is a unique match on the search substring then *play_tag* will play that tag. If more than one Roon Library tag name matches the search substring then *play_tag* will return a list of matching tag names. To play an tag using the substring search facility, enough of a substring must be supplied to uniquely match a Roon Library tag name. 16 | 17 | # COMMAND LINE OPTIONS 18 | **-z ZONE** 19 | : Specify the Roon Zone in which to play. If no zone is specified the default zone will be used. '-z default' indicates the default zone, '-z last' the last zone used 20 | 21 | **TAG** 22 | : Provide an tag name, in quotes if it contains spaces, or a case-sensitive substring. A Roon library tag name matching the provided tag name or containing the substring will be played if a unique match is found. 23 | 24 | # EXAMPLES 25 | **play_tag Moon** 26 | : Will play Roon library tag name "Moon" if it exists. If not then it will play the Roon library tag whose name contains the string "Moon" if only one match is found. 27 | 28 | # AUTHORS 29 | Written by Ronald Record github@ronrecord.com 30 | 31 | # LICENSING 32 | PLAY_TAG is distributed under an Open Source license. 33 | See the file LICENSE in the PLAY_TAG source distribution 34 | for information on terms & conditions for accessing and 35 | otherwise using PLAY_TAG and for a DISCLAIMER OF ALL WARRANTIES. 36 | 37 | # BUGS 38 | Submit bug reports online at: https://github.com/doctorfree/RoonCommandLine/issues 39 | 40 | # SEE ALSO 41 | **get_core_ip**(1), **get_zone_info**(1), **get_zones**(1), **list_albums**(1), **list_artist_albums**(1), **list_artists**(1), **list_composers**(1), **list_genre_albums**(1), **list_genre_artists**(1), **list_genres**(1), **list_playlists**(1), **list_radio**(1), **list_tags**(1), **list_zones**(1), **play_album**(1), **play_artist**(1), **play_artist_album**(1), **play_artist_track**(1), **play_composer**(1), **play_genre**(1), **play_genre_album**(1), **play_genre_artist**(1), **play_playlist**(1), **play_radio**(1), **play_tag**(1), **roon**(1), **set_zone**(1), **set_zone_group**(1), **zone_command**(1) 42 | 43 | Full documentation and sources at: https://github.com/doctorfree/RoonCommandLine 44 | 45 | The corresponding Python script, */usr/local/Roon/api/play_tag.py*, 46 | can be invoked directly as: 47 | 48 | **python3 /usr/local/Roon/api/play_tag.py [ options]** 49 | 50 | Where [ options ] are described in the following usage message: 51 | 52 | ~~~~ 53 | usage: play_tag.py [-h] [-t TAG] [-z ZONE] 54 | 55 | optional arguments: 56 | -h, --help show this help message and exit 57 | -t TAG, --tag TAG tag selection 58 | -z ZONE, --zone ZONE zone selection 59 | ~~~~ 60 | -------------------------------------------------------------------------------- /markdown/play_track.1.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: PLAY_TRACK 3 | section: 1 4 | header: User Manual 5 | footer: play_track 2.0.1 6 | date: May 22, 2024 7 | --- 8 | # NAME 9 | play_track - Play specified Roon Library track 10 | 11 | # SYNOPSIS 12 | **play_track** [ -z ZONE ] [ TRACK ] 13 | 14 | # DESCRIPTION 15 | Plays Roon Library track matching the specified track name or substring. This command is invoked by "roon [-T track]". 16 | 17 | # COMMAND LINE OPTIONS 18 | **-z ZONE** 19 | : Specify the Roon Zone in which to play. If no zone is specified the default zone will be used. '-z default' indicates the default zone, '-z last' the last zone used 20 | 21 | **TRACK** 22 | : Provide a track name, in quotes if it contains spaces, or a case-sensitive substring. All Roon library track names matching the provided track name or containing the substring will be returned and the first one returned will be played. 23 | 24 | # EXAMPLES 25 | **play_track Yesterday** 26 | : Will play the first track returned in a list of all Roon library track names with titles containing the string "Yesterday" 27 | 28 | **play_track "Love Me Do"** 29 | : Will play the first track returned in a list of all Roon library track names with titles containing the string "Love Me Do" 30 | 31 | # AUTHORS 32 | Written by Ronald Record github@ronrecord.com 33 | 34 | # LICENSING 35 | PLAY_TRACK is distributed under an Open Source license. 36 | See the file LICENSE in the PLAY_TRACK source distribution 37 | for information on terms & conditions for accessing and 38 | otherwise using PLAY_TRACK and for a DISCLAIMER OF ALL WARRANTIES. 39 | 40 | # BUGS 41 | Submit bug reports online at: https://github.com/doctorfree/RoonCommandLine/issues 42 | 43 | # SEE ALSO 44 | **get_core_ip**(1), **get_zone_info**(1), **get_zones**(1), **list_albums**(1), **list_artist_albums**(1), **list_artists**(1), **list_composers**(1), **list_genre_albums**(1), **list_genre_artists**(1), **list_genres**(1), **list_playlists**(1), **list_radio**(1), **list_tags**(1), **list_zones**(1), **play_album**(1), **play_artist**(1), **play_artist_album**(1), **play_artist_track**(1), **play_composer**(1), **play_genre**(1), **play_genre_album**(1), **play_genre_artist**(1), **play_playlist**(1), **play_radio**(1), **play_tag**(1), **roon**(1), **set_zone**(1), **set_zone_group**(1), **zone_command**(1) 45 | 46 | Full documentation and sources at: https://github.com/doctorfree/RoonCommandLine 47 | 48 | The corresponding Python script, */usr/local/Roon/api/play_track.py*, 49 | can be invoked directly as: 50 | 51 | **python3 /usr/local/Roon/api/play_track.py [ options]** 52 | 53 | Where [ options ] are described in the following usage message: 54 | 55 | ~~~~ 56 | usage: play_track.py [-h] [-t TRACK] [-z ZONE] 57 | 58 | optional arguments: 59 | -h, --help show this help message and exit 60 | -t TRACK, --track TRACK 61 | track search term 62 | -z ZONE, --zone ZONE zone selection 63 | ~~~~ 64 | -------------------------------------------------------------------------------- /markdown/roon_faded.5.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: ROON_FADED 3 | section: 5 4 | header: User Manual 5 | footer: roon_faded 2.0.1 6 | date: December 05, 2022 7 | --- 8 | # NAME 9 | roon_faded - Roon zone volume fading daemon 10 | 11 | # SYNOPSIS 12 | **roon_faded** [ **-l** ] [ **-z** ZONE ] 13 | 14 | # DESCRIPTION 15 | Monitors zone playing state and time remaining for each track played in order to perform volume fading on specified zone or default zone if no zone is specified. If the `-l` flag is provided then logging is enabled. Launched by **roon_fade on**, exits with **roon_fade off**. 16 | 17 | Currently `roon_faded` will detect zone groupings and changes to zone groupings while running. Should the zone grouping or fade duration change while `roon_faded` is running it will adjust appropriately in order to fade audio in the currently playing zones and for the desired duration. However, `roon_faded` is limited in its ability to adapt to real-time changes during fade. For example, manual volume changes made in the Roon client will not be detected nor will zone transfers. 18 | 19 | # COMMAND LINE OPTIONS 20 | **-l** 21 | : Enable logging 22 | 23 | **-z ZONE** 24 | : If a *ZONE* is specified then perform fading for that zone. If no *ZONE* is provided on the command line then perform fading on the default zone. 25 | 26 | # EXAMPLES 27 | **roon_faded** is controlled by **roon_fade** and is not intended to be launched directly. 28 | 29 | **roon_fade -l on** 30 | : Enables fading in the default zone, enables logging, launches **roon_faded** 31 | 32 | **roon_fade off** 33 | : Disables fading in the default zone, causes **roon_faded** to exit 34 | 35 | **roon_fade -z Kitchen on** 36 | : Enables fading in the Roon zone named *Kitchen*, launches **roon_faded** 37 | 38 | # AUTHORS 39 | Written by Ronald Record github@ronrecord.com 40 | 41 | # LICENSING 42 | ROON_FADED is distributed under an Open Source license. 43 | See the file LICENSE in the ROON_FADED source distribution 44 | for information on terms & conditions for accessing and 45 | otherwise using ROON_FADED and for a DISCLAIMER OF ALL WARRANTIES. 46 | 47 | # BUGS 48 | Submit bug reports online at: https://github.com/doctorfree/RoonCommandLine/issues 49 | 50 | # SEE ALSO 51 | **roon_fade**(1), **get_core_ip**(1), **get_zones**(1), **list_albums**(1), **list_artist_albums**(1), **list_artists**(1), **list_composers**(1), **list_genre_albums**(1), **list_genre_artists**(1), **list_genres**(1), **list_playlists**(1), **list_radio**(1), **list_tags**(1), **list_zones**(1), **now_playing**(1), **play_album**(1), **play_artist**(1), **play_artist_album**(1), **play_artist_track**(1), **play_composer**(1), **play_genre**(1), **play_genre_album**(1), **play_genre_artist**(1), **play_playlist**(1), **play_radio**(1), **play_tag**(1), **roon**(1), **set_zone**(1), **set_zone_group**(1), **zone_command**(1) 52 | 53 | Full documentation and sources at: https://github.com/doctorfree/RoonCommandLine 54 | 55 | -------------------------------------------------------------------------------- /markdown/roonanim.1.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: ROONANIM 3 | section: 1 4 | header: User Manual 5 | footer: roonanim 2.0.1 6 | date: June 10, 2024 7 | --- 8 | # NAME 9 | roonanim - display animated splash screen 10 | 11 | # SYNOPSIS 12 | **roonanim** [-a] [-f] [-k] [-q] [-z] [-u] 13 | 14 | # DESCRIPTION 15 | The `RoonCommandLine` animated splash screen is displayed with the command **roonanim -a -q** on `roon` command menu startup and when the `About` page is displayed. 16 | 17 | # COMMAND LINE OPTIONS 18 | **-a** 19 | : Indicates animate display 20 | 21 | **-f** 22 | : Indicates fullscreen mode 23 | 24 | **-k** 25 | : Indicates do not exit 26 | 27 | **-q** 28 | : Indicates quick display, do not sleep 29 | 30 | **-z** 31 | : Indicates zoom display 32 | 33 | **-u** 34 | : Displays this usage message and exits 35 | 36 | # AUTHORS 37 | Written by Ronald Record github@ronrecord.com 38 | 39 | # LICENSING 40 | ROONANIM is distributed under an Open Source license. 41 | See the file LICENSE in the ROONANIM source distribution 42 | for information on terms & conditions for accessing and 43 | otherwise using ROONANIM and for a DISCLAIMER OF ALL WARRANTIES. 44 | 45 | # BUGS 46 | Submit bug reports online at: https://github.com/doctorfree/RoonCommandLine/issues 47 | 48 | # SEE ALSO 49 | **get_zone_info**(1), **get_zones**(1), **list_albums**(1), **list_artist_albums**(1), **list_artists**(1), **list_composers**(1), **list_genre_albums**(1), **list_genre_artists**(1), **list_genres**(1), **list_playlists**(1), **list_radio**(1), **list_tags**(1), **list_zones**(1), **play_album**(1), **play_artist**(1), **play_artist_album**(1), **play_artist_track**(1), **play_composer**(1), **play_genre**(1), **play_genre_album**(1), **play_genre_artist**(1), **play_playlist**(1), **play_radio**(1), **play_tag**(1), **roon**(1), **set_zone**(1), **set_zone_group**(1), **zone_command**(1) 50 | 51 | Full documentation and sources at: https://github.com/doctorfree/RoonCommandLine 52 | 53 | -------------------------------------------------------------------------------- /markdown/set_zone.1.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: SET_ZONE 3 | section: 1 4 | header: User Manual 5 | footer: set_zone 2.0.1 6 | date: December 05, 2021 7 | --- 8 | # NAME 9 | set_zone - Set the default Roon playback Zone 10 | 11 | # SYNOPSIS 12 | **set_zone** [ ZONE ] 13 | 14 | # DESCRIPTION 15 | Sets the default Roon playback zone. Current playback, if active, is unaffected. Subsequent Roon commands, if no zone is specified on the command line, will take effect in the specified default Roon zone. If the Roon zone specified on the command line does not match a configured Roon zone exactly then the first Roon zone name containing the *ZONE* substring will be set as the default Roon zone. 16 | 17 | # COMMAND LINE OPTIONS 18 | **ZONE** 19 | : Set the default Roon playback zone to *ZONE* 20 | 21 | # EXAMPLES 22 | **set_zone HomePod** 23 | : Will set the default Roon zone to "HomePod" if a zone by that name exists. If no zone named "HomePod" exists then Roon zones are searched for a zone name containing the string "HomePod" and the first matching Roon zone name is set as the default Roon zone. 24 | 25 | # AUTHORS 26 | Written by Ronald Record github@ronrecord.com 27 | 28 | # LICENSING 29 | SET_ZONE is distributed under an Open Source license. 30 | See the file LICENSE in the SET_ZONE source distribution 31 | for information on terms & conditions for accessing and 32 | otherwise using SET_ZONE and for a DISCLAIMER OF ALL WARRANTIES. 33 | 34 | # BUGS 35 | Submit bug reports online at: https://github.com/doctorfree/RoonCommandLine/issues 36 | 37 | # SEE ALSO 38 | **get_core_ip**(1), **get_zone_info**(1), **get_zones**(1), **list_albums**(1), **list_artist_albums**(1), **list_artists**(1), **list_composers**(1), **list_genre_albums**(1), **list_genre_artists**(1), **list_genres**(1), **list_playlists**(1), **list_radio**(1), **list_tags**(1), **list_zones**(1), **play_album**(1), **play_artist**(1), **play_artist_album**(1), **play_artist_track**(1), **play_composer**(1), **play_genre**(1), **play_genre_album**(1), **play_genre_artist**(1), **play_playlist**(1), **play_radio**(1), **play_tag**(1), **roon**(1), **set_zone**(1), **set_zone_group**(1), **zone_command**(1) 39 | 40 | Full documentation and sources at: https://github.com/doctorfree/RoonCommandLine 41 | 42 | -------------------------------------------------------------------------------- /markdown/set_zone_group.1.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: SET_ZONE_GROUP 3 | section: 1 4 | header: User Manual 5 | footer: set_zone_group 2.0.1 6 | date: December 05, 2021 7 | --- 8 | # NAME 9 | set_zone_group - Set one of the Roon Zone groupings specified in **roon_api.ini** 10 | 11 | # SYNOPSIS 12 | **set_zone_group** [ group|ungroup ] [ ZONEGROUP ] 13 | 14 | # DESCRIPTION 15 | Groups or Ungroups the specified Roon Zone Grouping using one of the Zone Grouping presets in **/usr/local/Roon/etc/roon_api.ini** 16 | 17 | # COMMAND LINE OPTIONS 18 | **group|ungroup** 19 | : The first argument to *set_zone_group* must be either "group" or "ungroup", indicating whether to group or ungroup the specified *ZONEGROUP* preset 20 | 21 | **ZONEGROUP** 22 | : The second argument to *set_zone_group* specifies the Zone Grouping preset to use. These are configured in the file **/usr/local/Roon/etc/roon_api.ini**. By default these Zone Grouping presets are named *Group_1*, *Group_2*, etc but can be any name of the form "Group_<string>". The *ZONEGROUP* argument should match one of the <string> Zone Grouping preset names. For example, to address Zone Grouping preset *Group_3*, specify *ZONEGROUP* as "3". 23 | 24 | # EXAMPLES 25 | **set_zone_group group 4** 26 | : Group Roon Zones according to the Zone Grouping preset named *Group_4* in **roon_api.ini** 27 | 28 | **set_zone_group ungroup 2** 29 | : Ungroup Roon Zones according to the Zone Grouping preset named *Group_2* in **roon_api.ini** 30 | 31 | # AUTHORS 32 | Written by Ronald Record github@ronrecord.com 33 | 34 | # LICENSING 35 | SET_ZONE_GROUP is distributed under an Open Source license. 36 | See the file LICENSE in the SET_ZONE_GROUP source distribution 37 | for information on terms & conditions for accessing and 38 | otherwise using SET_ZONE_GROUP and for a DISCLAIMER OF ALL WARRANTIES. 39 | 40 | # BUGS 41 | Submit bug reports online at: https://github.com/doctorfree/RoonCommandLine/issues 42 | 43 | # SEE ALSO 44 | **get_core_ip**(1), **get_zone_info**(1), **get_zones**(1), **list_albums**(1), **list_artist_albums**(1), **list_artists**(1), **list_composers**(1), **list_genre_albums**(1), **list_genre_artists**(1), **list_genres**(1), **list_playlists**(1), **list_radio**(1), **list_tags**(1), **list_zones**(1), **play_album**(1), **play_artist**(1), **play_artist_album**(1), **play_artist_track**(1), **play_composer**(1), **play_genre**(1), **play_genre_album**(1), **play_genre_artist**(1), **play_playlist**(1), **play_radio**(1), **play_tag**(1), **roon**(1), **set_zone**(1), **set_zone_group**(1), **zone_command**(1) 45 | 46 | Full documentation and sources at: https://github.com/doctorfree/RoonCommandLine 47 | 48 | -------------------------------------------------------------------------------- /markdown/transfer_zone.1.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: TRANSFER_ZONE 3 | section: 1 4 | header: User Manual 5 | footer: transfer_zone 2.0.1 6 | date: February 20, 2024 7 | --- 8 | # NAME 9 | transfer_zone - Transfer the current queue from one zone to another 10 | 11 | from_zone_or_output_id - The source zone or output 12 | to_zone_or_output_id - The destination zone or output 13 | """ 14 | data = { 15 | "from_zone_or_output_id": from_zone_or_output_id, 16 | "to_zone_or_output_id": to_zone_or_output_id, 17 | } 18 | return self._request(SERVICE_TRANSPORT + "/transfer_zone", data) 19 | 20 | 21 | # SYNOPSIS 22 | **transfer_zone** [ FROM_ZONE ] TO_ZONE 23 | 24 | # DESCRIPTION 25 | Transfers the current queue from one Roon zone to another. The first argument specifies the source zone and the second argument specifies the destination zone. If no source zone is specified then the source zone is set to the last played zone and the destination zone is set to the first argument. 26 | 27 | # COMMAND LINE OPTIONS 28 | **FROM_ZONE** 29 | : The source Roon zone can be specified on the command line as the first argument. If no second argument is provided then the source zone is the last played zone. 30 | 31 | **TO_ZONE** 32 | : The destination Roon zone can be specified on the command line as the second argument or, if no source zone is provided as the first argument then the first argument is taken to be the destination zone. 33 | 34 | # EXAMPLES 35 | **transfer_zone HomePod "WiiM Pro"** 36 | : Transfers the current queue from the Roon zone "HomePod" to the Roon zone "WiiM Pro" 37 | 38 | # AUTHORS 39 | Written by Ronald Record github@ronrecord.com 40 | 41 | # LICENSING 42 | TRANSFER_ZONE is distributed under an Open Source license. 43 | See the file LICENSE in the TRANSFER_ZONE source distribution 44 | for information on terms & conditions for accessing and 45 | otherwise using TRANSFER_ZONE and for a DISCLAIMER OF ALL WARRANTIES. 46 | 47 | # BUGS 48 | Submit bug reports online at: https://github.com/doctorfree/RoonCommandLine/issues 49 | 50 | # SEE ALSO 51 | **get_core_ip**(1), **get_zone_info**(1), **now_playing**(1), **list_albums**(1), **list_artist_albums**(1), **list_artists**(1), **list_composers**(1), **list_genre_albums**(1), **list_genre_artists**(1), **list_genres**(1), **list_playlists**(1), **list_radio**(1), **list_tags**(1), **list_zones**(1), **play_album**(1), **play_artist**(1), **play_artist_album**(1), **play_artist_track**(1), **play_composer**(1), **play_genre**(1), **play_genre_album**(1), **play_genre_artist**(1), **play_playlist**(1), **play_radio**(1), **play_tag**(1), **roon**(1), **set_zone**(1), **set_zone_group**(1), **zone_command**(1) 52 | 53 | Full documentation and sources at: https://github.com/doctorfree/RoonCommandLine 54 | 55 | -------------------------------------------------------------------------------- /mkrelease: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | [ -f VERSION ] || { 4 | echo "VERSION file missing. Exiting." 5 | exit 1 6 | } 7 | . ./VERSION 8 | 9 | usage() { 10 | printf "\nUsage: mkrelease [-c] [-d] [-p] [-u]" 11 | printf "\nWhere:" 12 | printf "\n\t-c indicates clean first" 13 | printf "\n\t-d indicates create draft release" 14 | printf "\n\t-p indicates skip package creation step" 15 | printf "\n\t-u displays this usage message and exits\n" 16 | exit 1 17 | } 18 | 19 | CLEAN= 20 | DRAFT= 21 | PACKAGE=1 22 | while getopts "cdpu" flag; do 23 | case $flag in 24 | c) 25 | CLEAN=1 26 | ;; 27 | d) 28 | DRAFT="--draft" 29 | ;; 30 | p) 31 | PACKAGE= 32 | ;; 33 | u) 34 | usage 35 | ;; 36 | esac 37 | done 38 | shift $(( OPTIND - 1 )) 39 | 40 | [ "$CLEAN" ] && ./clean 41 | [ "$PACKAGE" ] && ./mkpkg 42 | 43 | ANNO="RoonCommandLine Version ${VERSION} Release ${RELEASE}" 44 | gittag v${VERSION}r${RELEASE} ${ANNO} 45 | 46 | echo "Creating release for version ${VERSION} release ${RELEASE}" 47 | 48 | gh release create v${VERSION}r${RELEASE} ${DRAFT} \ 49 | --title "${ANNO}" \ 50 | --notes-file pkg/release.md \ 51 | releases/${VERSION}/* 52 | 53 | git fetch --tags origin 54 | -------------------------------------------------------------------------------- /patches/README.md: -------------------------------------------------------------------------------- 1 | # RoonCommandLine/patches 2 | 3 | Patches to the Python Roon API. Currently these patches add a method to search and display a list of objects in your Roon library matching the search criteria. For instance, display a list of Playlists that contain the term "Best". 4 | 5 | ## Contents 6 | 7 | [**roonapi-listmedia.patch**](roonapi-listmedia.patch) - Python Roon API patch to be applied to the installed Python module (e.g. after "pip install roonapi") 8 | 9 | [**pyroon-listmedia.patch**](pyroon-listmedia.patch) - Python Roon API patch to be applied to a cloned git repository 10 | 11 | [**mkpatch-pyroon**](mkpatch-pyroon) - Shell script used to create the pyroon patch above 12 | 13 | [**mkpatch-roonapi**](mkpatch-roonapi) - Shell script used to create the roonapi patch above 14 | 15 | [**roon-web-controller**](roon-web-controller) - Patches for the roon-web-controller project 16 | -------------------------------------------------------------------------------- /patches/mkpatch-pyroon: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | SRCDIR=$HOME/src 4 | RCLDIR=$SRCDIR/RoonCommandLine 5 | PYRDIR=pyroon/roonapi 6 | SUFF="orig" 7 | 8 | cd $SRCDIR 9 | 10 | [ -f ${PYRDIR}/roonapi.py.${SUFF} ] || { 11 | SUFF="00" 12 | [ -f ${PYRDIR}/roonapi.py.${SUFF} ] || { 13 | echo "Cannot locate backup for file ${PYRDIR}/roonapi.py. Exiting." 14 | exit 1 15 | } 16 | } 17 | 18 | [ -d ${RCLDIR} ] || mkdir ${RCLDIR} 19 | [ -d ${RCLDIR}/patches ] || mkdir ${RCLDIR}/patches 20 | 21 | OUT=${RCLDIR}/patches/pyroon-listmedia.patch 22 | rm -f $OUT 23 | touch $OUT 24 | for i in ${PYRDIR}/*.${SUFF} 25 | do 26 | j=`echo $i | sed -e "s/.${SUFF}//"` 27 | diff -Naur $i $j >> $OUT 28 | done 29 | -------------------------------------------------------------------------------- /patches/mkpatch-roonapi: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Check Python's global directories 4 | have_python3=`type -p python3` 5 | if [ "${have_python3}" ] 6 | then 7 | SITES=($(python3 -c 'import site; print(site.getsitepackages())' | tr -d '[],')) 8 | else 9 | SITES=($(python -c 'import site; print(site.getsitepackages())' | tr -d '[],')) 10 | fi 11 | for site in ${SITES[@]} 12 | do 13 | site=`echo $site | sed -e "s/\'//g"` 14 | [ -d "${site}/roonapi" ] && { 15 | PYDIR=`echo ${site} | awk -F "/dist-packages/" ' { print $1 } '` 16 | USERSITE=$PYDIR/dist-packages 17 | break 18 | } 19 | done 20 | [ -d $USERSITE/roonapi ] || { 21 | echo "Roon API Python module not found. Exiting." 22 | exit 1 23 | } 24 | 25 | cd $PYDIR 26 | 27 | [ -d ~/src/RoonCommandLine/patches ] || mkdir ~/src/RoonCommandLine/patches 28 | 29 | OUT=$HOME/src/RoonCommandLine/patches/roonapi-listmedia.patch 30 | rm -f $OUT 31 | touch $OUT 32 | for i in dist-packages/roonapi/*.orig 33 | do 34 | j=`echo $i | sed -e "s/.orig//"` 35 | diff -Naur $i $j >> $OUT 36 | done 37 | -------------------------------------------------------------------------------- /patches/roon-web-controller/README.md: -------------------------------------------------------------------------------- 1 | # RoonCommandLine/patches/roon-web-controller 2 | 3 | Patches to the roon-web-controller. These have nothing to do with the RoonCommandLine 4 | project, I just used this as a convenient place to store them. These patches get 5 | applied to the roon-web-controller project. 6 | 7 | ## Contents 8 | 9 | [**roon-web-controller.patch**](roon-web-controller.patch) - Patch to be applied to the roon-web-controller project, version 1 10 | 11 | [**roon-web-controller-alpha.patch**](roon-web-controller-alpha.patch) - Patch to be applied to the roon-web-controller project, version 2 alpha 12 | -------------------------------------------------------------------------------- /patches/roon-web-controller/roon-web-controller-alpha.patch: -------------------------------------------------------------------------------- 1 | --- ./backend/app.js.orig 2021-04-17 11:58:41.646056743 -0700 2 | +++ ./backend/app.js 2021-04-17 11:58:41.696054995 -0700 3 | @@ -50,7 +50,7 @@ 4 | setting.express.port = 10000; 5 | setting.express.public = "/public"; 6 | } else { 7 | - setting.express.port = 8080; 8 | + setting.express.port = 8082; 9 | setting.express.public = "../dist"; 10 | } 11 | 12 | -------------------------------------------------------------------------------- /patches/roon-web-controller/roon-web-controller.patch: -------------------------------------------------------------------------------- 1 | --- ./launch-chromium-touch.sh.00 2021-04-17 14:25:51.151507116 -0700 2 | +++ ./launch-chromium-touch.sh 2021-04-17 12:26:36.479428076 -0700 3 | @@ -0,0 +1,8 @@ 4 | +#!/bin/bash 5 | + 6 | +DISPLAY=:0 /usr/bin/chromium-browser \ 7 | + --noerrdialogs \ 8 | + --kiosk \ 9 | + --incognito \ 10 | + --window-position=1920,0 \ 11 | + http://localhost:8082 12 | --- ./roon-web-controller.service.00 2021-04-17 12:22:54.653639135 -0700 13 | +++ ./roon-web-controller.service 2021-04-17 12:04:29.877053916 -0700 14 | @@ -0,0 +1,11 @@ 15 | +[Unit] 16 | +Description=NodeJS app - Roon Web Controller 17 | +After=network.target 18 | + 19 | +[Service] 20 | +User=pi 21 | +WorkingDirectory=/home/pi/src/roon-web-controller 22 | +ExecStart=/usr/bin/node app.js -p 8082 23 | + 24 | +[Install] 25 | +WantedBy=multi-user.target 26 | --- ./config/local.json.00 2021-04-17 12:23:46.732596085 -0700 27 | +++ ./config/local.json 2021-04-17 11:59:36.314287177 -0700 28 | @@ -0,0 +1,5 @@ 29 | +{ 30 | + "server": { 31 | + "port": "8082" 32 | + } 33 | +} 34 | -------------------------------------------------------------------------------- /patches/roonapi/README.md: -------------------------------------------------------------------------------- 1 | # RoonCommandLine/patches/roonapi 2 | 3 | If the installation script did not apply the patches to the Python Roon API correctly, 4 | you can use these files as replacements for the installed Python Roon API in order 5 | to add the media listing features of the Roon Command Line. Locate the Python Roon API 6 | installation folder and copy these files to that location, replacing the existing ones. 7 | Common locations for the Python Roon API dist-packages folder include 8 | 9 | $HOME/.local/lib/python3.8/dist-packages/roonapi/ 10 | 11 | or 12 | 13 | $HOME/Python3/lib/python3.8/dist-packages/roonapi/ 14 | 15 | The Python User dist-packages location can be found by executing the command: 16 | 17 | $ python -m site --user-site 18 | 19 | If that path does not contain the Python Roon API dist-packages module then a list 20 | of locations Python searches for dist-packages can be found by executing: 21 | 22 | $ python -c 'import site; print(site.getsitepackages())' | tr -d '[],' 23 | 24 | ## Contents 25 | 26 | [**roonapi.py**](roonapi.py) - Python Roon API with already applied patch to be copied to the installed roonapi Python module (e.g. after "pip install roonapi") 27 | 28 | [**roonapisocket.py**](roonapisocket.py) - Python Roon API with already applied patch to be copied to the installed roonapi Python module 29 | -------------------------------------------------------------------------------- /pkg/debian/postinst: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # postinst script for rooncommandline 3 | # 4 | # see: dh_installdeb(1) 5 | 6 | set -e 7 | 8 | # summary of how this script can be called: 9 | # * `configure' 10 | # * `abort-upgrade' 11 | # * `abort-remove' `in-favour' 12 | # 13 | # * `abort-remove' 14 | # * `abort-deconfigure' `in-favour' 15 | # `removing' 16 | # 17 | # for details, see https://www.debian.org/doc/debian-policy/ or 18 | # the debian-policy package 19 | 20 | 21 | case "$1" in 22 | configure) 23 | if [ -x /usr/local/Roon/etc/postinstall ] 24 | then 25 | /usr/local/Roon/etc/postinstall 26 | fi 27 | ;; 28 | 29 | abort-upgrade|abort-remove|abort-deconfigure) 30 | ;; 31 | 32 | *) 33 | echo "postinst called with unknown argument \`$1'" >&2 34 | exit 1 35 | ;; 36 | esac 37 | 38 | exit 0 39 | -------------------------------------------------------------------------------- /pkg/debian/preinst: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # preinst script for rooncommandline 3 | # 4 | 5 | set -e 6 | 7 | case "$1" in 8 | install|upgrade) 9 | export PATH=$PATH:/usr/local/bin 10 | if [ -x /home/linuxbrew/.linuxbrew/bin/brew ] 11 | then 12 | eval "$(/home/linuxbrew/.linuxbrew/bin/brew shellenv)" 13 | else 14 | [ -x /usr/local/bin/brew ] && eval "$(/usr/local/bin/brew shellenv)" 15 | fi 16 | have_python3= 17 | if type -p python3 > /dev/null 18 | then 19 | inst_python3=1 20 | else 21 | inst_python3= 22 | fi 23 | if [ "${inst_python3}" ] 24 | then 25 | have_python3=1 26 | else 27 | if type -p python > /dev/null 28 | then 29 | inst_python=1 30 | else 31 | inst_python= 32 | fi 33 | if [ "${inst_python}" ] 34 | then 35 | [[ "$(python --version)" =~ "Python 3" ]] && have_python3=1 36 | fi 37 | fi 38 | have_pip= 39 | if type -p pip3 > /dev/null 40 | then 41 | inst_pip3=1 42 | else 43 | inst_pip3= 44 | fi 45 | if [ "${inst_pip3}" ] 46 | then 47 | have_pip=1 48 | else 49 | if type -p pip > /dev/null 50 | then 51 | inst_pip=1 52 | else 53 | inst_pip= 54 | fi 55 | [ "${inst_pip}" ] && have_pip=1 56 | fi 57 | [ "${have_pip}" ] && [ "${have_python3}" ] || { 58 | echo "RoonCommandLine requires Python 3 and Pip" 59 | echo "Install Python 3 and restart this installation" 60 | exit 1 61 | } 62 | if [ -f /usr/local/Roon/etc/roon_api.ini ] 63 | then 64 | cp /usr/local/Roon/etc/roon_api.ini /tmp/_roon_api_ini_.save 65 | fi 66 | if [ -f /usr/local/Roon/etc/pyroonconf ] 67 | then 68 | cp /usr/local/Roon/etc/pyroonconf /tmp/_pyroonconf_.save 69 | fi 70 | ;; 71 | 72 | *) 73 | ;; 74 | esac 75 | 76 | exit 0 77 | -------------------------------------------------------------------------------- /pkg/debian/prerm: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # prerm script for rooncommandline 3 | # 4 | # see: dh_installdeb(1) 5 | 6 | set -e 7 | 8 | # summary of how this script can be called: 9 | # * `remove' 10 | # * `upgrade' 11 | # * `failed-upgrade' 12 | # * `remove' `in-favour' 13 | # * `deconfigure' `in-favour' 14 | # `removing' 15 | # 16 | # for details, see https://www.debian.org/doc/debian-policy/ or 17 | # the debian-policy package 18 | 19 | 20 | case "$1" in 21 | remove) 22 | if [ -x /usr/local/Roon/etc/preremove ] 23 | then 24 | /usr/local/Roon/etc/preremove 25 | fi 26 | rm -rf /usr/local/Roon/venv 27 | ;; 28 | upgrade|deconfigure) 29 | ROONETC=/usr/local/Roon/etc 30 | ROONCONF=${ROONETC}/pyroonconf 31 | ROON_INI=${ROONETC}/roon_api.ini 32 | [ -f ${ROON_INI} ] && { 33 | cp ${ROON_INI} /tmp/_roon_api_ini_.save 34 | } 35 | [ -f ${ROONCONF} ] && { 36 | cp ${ROONCONF} /tmp/_pyroonconf_.save 37 | } 38 | if [ -x /usr/local/Roon/etc/preremove ] 39 | then 40 | /usr/local/Roon/etc/preremove 41 | fi 42 | ;; 43 | 44 | failed-upgrade) 45 | ;; 46 | 47 | *) 48 | echo "prerm called with unknown argument \`$1'" >&2 49 | exit 1 50 | ;; 51 | esac 52 | 53 | exit 0 54 | -------------------------------------------------------------------------------- /pkg/rpm/RoonCommandLine.spec: -------------------------------------------------------------------------------- 1 | Name: RoonCommandLine 2 | Version: %{_version} 3 | Release: %{_release} 4 | Summary: Command line control of the Roon audio system 5 | License: MIT 6 | BuildArch: noarch 7 | Requires: python3-pip, jq, git 8 | URL: https://github.com/doctorfree/RoonCommandLine 9 | Vendor: Doctorwhen's Bodacious Laboratory 10 | Packager: ronaldrecord@gmail.com 11 | 12 | %global __os_install_post %{nil} 13 | 14 | %description 15 | Manage your Roon Audio System from the command line 16 | 17 | %prep 18 | 19 | %build 20 | 21 | %install 22 | cp -a %{_sourcedir}/usr %{buildroot}/usr 23 | 24 | %pre 25 | exec 1>/proc/${PPID}/fd/1 26 | exec 2>/proc/${PPID}/fd/2 27 | export PATH=$PATH:/usr/local/bin 28 | if [ -x /home/linuxbrew/.linuxbrew/bin/brew ]; then 29 | eval "$(/home/linuxbrew/.linuxbrew/bin/brew shellenv)" 30 | else 31 | [ -x /usr/local/bin/brew ] && eval "$(/usr/local/bin/brew shellenv)" 32 | fi 33 | have_python3= 34 | if type -p python3 > /dev/null 35 | then 36 | inst_python3=1 37 | else 38 | inst_python3= 39 | fi 40 | if [ "${inst_python3}" ]; then 41 | have_python3=1 42 | else 43 | if type -p python > /dev/null 44 | then 45 | inst_python=1 46 | else 47 | inst_python= 48 | fi 49 | if [ "${inst_python}" ]; then 50 | [[ "$(python --version)" =~ "Python 3" ]] && have_python3=1 51 | fi 52 | fi 53 | have_pip= 54 | if type -p pip3 > /dev/null 55 | then 56 | inst_pip3=1 57 | else 58 | inst_pip3= 59 | fi 60 | if [ "${inst_pip3}" ]; then 61 | have_pip=1 62 | else 63 | if type -p pip > /dev/null 64 | then 65 | inst_pip=1 66 | else 67 | inst_pip= 68 | fi 69 | [ "${inst_pip}" ] && have_pip=1 70 | fi 71 | [ "${have_pip}" ] && [ "${have_python3}" ] || { 72 | echo "RoonCommandLine requires Python 3 and Pip" 73 | echo "Install Python 3 and restart this installation" 74 | exit 1 75 | } 76 | if [ -f /usr/local/Roon/etc/roon_api.ini ]; then 77 | cp /usr/local/Roon/etc/roon_api.ini /tmp/_roon_api_ini_.save 78 | fi 79 | if [ -f /usr/local/Roon/etc/pyroonconf ]; then 80 | cp /usr/local/Roon/etc/pyroonconf /tmp/_pyroonconf_.save 81 | fi 82 | 83 | %post 84 | exec 1>/proc/${PPID}/fd/1 85 | exec 2>/proc/${PPID}/fd/2 86 | if [ -x /usr/local/Roon/etc/postinstall ]; then 87 | /usr/local/Roon/etc/postinstall 88 | fi 89 | 90 | %preun 91 | exec 1>/proc/${PPID}/fd/1 92 | exec 2>/proc/${PPID}/fd/2 93 | if [ $1 -gt 0 ]; then 94 | ROONETC=/usr/local/Roon/etc 95 | ROONCONF=${ROONETC}/pyroonconf 96 | ROON_INI=${ROONETC}/roon_api.ini 97 | [ -f ${ROON_INI} ] && { 98 | cp ${ROON_INI} /tmp/_roon_api_ini_.save 99 | } 100 | [ -f ${ROONCONF} ] && { 101 | cp ${ROONCONF} /tmp/_pyroonconf_.save 102 | } 103 | fi 104 | if [ -x /usr/local/Roon/etc/preremove ]; then 105 | /usr/local/Roon/etc/preremove 106 | fi 107 | rm -rf /usr/local/Roon/venv 108 | 109 | %files 110 | /usr 111 | 112 | %changelog 113 | -------------------------------------------------------------------------------- /rooncommand.desktop: -------------------------------------------------------------------------------- 1 | [Desktop Entry] 2 | Name=RoonCommand 3 | Type=Application 4 | GenericName=Roon Command 5 | GenericName[ca]=Emulador de terminal 6 | GenericName[cs]=Emulátor terminálu 7 | GenericName[es]=Emulador de terminal 8 | 9 | Comment=Roon Command 10 | Comment[ca]=Emulador de terminal 11 | Comment[cs]=Emulátor terminálu 12 | Comment[de]=Befehlszeile verwenden 13 | Comment[el]=Προσομοιωτής τερματικού 14 | Comment[es]=Emulador de terminal 15 | Comment[fr]=RoonCommand 16 | Comment[lt]=RoonCommand emuliatorius 17 | Comment[pl]=Emulator terminala 18 | Comment[pt]=Emulador de terminal 19 | Comment[pt_BR]=Emulador de terminal 20 | Comment[ru_RU]=Эмулятор терминала 21 | Comment[ja]=ターミナル エミュレータ 22 | 23 | Icon=utilities-terminal 24 | Exec=qterminal --name Roon --title Roon --execute="/usr/local/Roon/bin/roon" 25 | Terminal=false 26 | Categories=Qt;System;TerminalEmulator; 27 | Actions=Dropdown; 28 | 29 | [Desktop Action Dropdown] 30 | Name=Drop-down RoonCommand 31 | Exec=qterminal --drop 32 | Icon=utilities-terminal 33 | 34 | Name[en_GB]=Drop-down Roon Command 35 | Name[bg]=Падащ терминал 36 | Name[ca]=Roon Command desplegable 37 | Name[ca@valencia]=Roon Command desplegable 38 | Name[cs]=Vysouvací terminál 39 | Name[da]=Roon Command der ruller ned 40 | Name[de]=Aufklapp-Roon Command 41 | Name[el]=Αναπτυσσόμενο τερματικό 42 | Name[es]=Roon Command desplegable 43 | Name[et]=Lahtikeriv terminal 44 | Name[fr]=Roon Command déroulant 45 | Name[hr]=Spuštajući terminal 46 | Name[hu]=Legördülő terminál 47 | Name[it]=Roon Command a discesa 48 | Name[ja]=ドロップダウン式ターミナル 49 | Name[km]=ស្ថានីយ​ទម្លាក់​ចុះ 50 | Name[ko]=위에서 내려오는 터미널 51 | Name[lt]=Išskleidžiamasis terminalas 52 | Name[nb]=Nedtrekksterminal 53 | Name[nds]=Utklapp-Konsool 54 | Name[nl]=Uitvouwbare terminalemulator 55 | Name[pa]=ਲਟਕਦਾ ਟਰਮੀਨਲ 56 | Name[pl]=Rozwijany emulator terminala 57 | Name[pt]=Roon Command suspenso 58 | Name[pt_BR]=Roon Command suspenso 59 | Name[ro]=Roon Command derulant 60 | Name[ru]=Выпадающий терминал 61 | Name[sk]=Rozbaľovací terminál 62 | Name[sv]=Rullgardinsterminal 63 | Name[th]=เทอร์มินัลแบบหย่อนลง 64 | Name[tr]=Yukarıdan Açılan Uçbirim 65 | Name[uk]=Спадний термінал 66 | Name[x-test]=xxDrop-down RoonCommand 67 | Name[zh_CN]=拉幕式终端 68 | Name[zh_TW]=下拉式終端機 69 | -------------------------------------------------------------------------------- /screenshots/Roon_List_Artist_Tracks.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/doctorfree/RoonCommandLine/fdb70992b27aeff8997f2b290590d9dfa28135fa/screenshots/Roon_List_Artist_Tracks.png -------------------------------------------------------------------------------- /screenshots/Roon_Play_Artist_Track.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/doctorfree/RoonCommandLine/fdb70992b27aeff8997f2b290590d9dfa28135fa/screenshots/Roon_Play_Artist_Track.png -------------------------------------------------------------------------------- /screenshots/Roon_Set_Zone.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/doctorfree/RoonCommandLine/fdb70992b27aeff8997f2b290590d9dfa28135fa/screenshots/Roon_Set_Zone.png -------------------------------------------------------------------------------- /screenshots/Roon_UI.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/doctorfree/RoonCommandLine/fdb70992b27aeff8997f2b290590d9dfa28135fa/screenshots/Roon_UI.png -------------------------------------------------------------------------------- /test/test.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | ROON=/usr/local/Roon 4 | ROONAPI=${ROON}/api 5 | ROONETC=${ROON}/etc 6 | ROONCONF=${ROONETC}/pyroonconf 7 | ZONE= 8 | 9 | SCRIPT_PATH="$( cd "$(dirname "$0")" ; pwd -P )" 10 | have_real=$(type -p realpath) 11 | [ "${have_real}" ] && SCRIPT_PATH="$(realpath "$SCRIPT_PATH")" 12 | 13 | [ -d $ROONAPI ] || exit 1 14 | cd $ROONAPI || exit 1 15 | 16 | TEST="${SCRIPT_PATH}/$1" 17 | [ -f $TEST ] || { 18 | if [ -f ${TEST}.py ]; then 19 | TEST="${TEST}.py" 20 | else 21 | echo "Cannot locate test Python script: $1" 22 | exit 2 23 | fi 24 | } 25 | shift 26 | 27 | # Use a Python virtual environment 28 | [ -f ${ROON}/venv/bin/activate ] && source ${ROON}/venv/bin/activate 29 | [[ ":$PATH:" == *":/usr/local/Roon/venv/bin:"* ]] || { 30 | export PATH=/usr/local/Roon/venv/bin:${PATH} 31 | } 32 | 33 | if [ -f ${ROONCONF} ] 34 | then 35 | . ${ROONCONF} 36 | else 37 | DEFZONE=$(grep ^DefaultZone ${ROONETC}/roon_api.ini | awk -F '=' ' { print $2 } ') 38 | # Remove leading and trailing spaces in DEFZONE 39 | DEFZONE="$(echo -e "${DEFZONE}" | sed -e 's/^[[:space:]]*//' -e 's/[[:space:]]*$//')" 40 | ${ROON}/bin/set_zone "${DEFZONE}" 41 | . ${ROONCONF} 42 | fi 43 | 44 | [ "${ROON_ZONE}" ] || ROON_ZONE="__all__" 45 | 46 | have_python3=$(type -p python3) 47 | if [ "${have_python3}" ] 48 | then 49 | python3 $TEST -z "${ROON_ZONE}" $@ 50 | else 51 | python $TEST -z "${ROON_ZONE}" $@ 52 | fi 53 | -------------------------------------------------------------------------------- /viewman: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | MANDIR=`pwd`/man 4 | page="$1" 5 | 6 | [ "${page}" ] || { 7 | echo 'Usage: viewman ' 8 | echo 'Where is an existing man page in man/man?/name.?' 9 | exit 1 10 | } 11 | 12 | plat=`uname -s` 13 | if [ "$plat" == "Darwin" ] 14 | then 15 | man -M ${MANDIR} $1 16 | else 17 | for manpage in ${MANDIR}/man*/${page}.? 18 | do 19 | [ "${manpage}" == "${MANDIR}/man*/${page}.?" ] && continue 20 | man -l ${manpage} 21 | done 22 | fi 23 | 24 | --------------------------------------------------------------------------------