├── .github ├── ISSUE_TEMPLATE │ ├── bug_report.md │ └── feature_request.md └── workflows │ ├── ci.yml │ ├── disabled │ ├── audit.yml │ ├── collection.yml │ └── miri.yml │ ├── download.yml │ └── typo.yml ├── .gitignore ├── .gitmodules ├── CHANGELOG.md ├── Cargo.lock ├── Cargo.toml ├── LICENSE ├── README.md ├── assets ├── README.md ├── audio │ ├── song_1.mp3 │ ├── song_2.mp3 │ ├── song_3.mp3 │ ├── song_4.flac │ ├── song_5.m4a │ ├── song_6.ogg │ └── song_7.mp3 ├── festival │ ├── README.md │ └── gui │ │ └── state │ │ ├── settings0_new.bin │ │ ├── settings0_real.bin │ │ ├── settings1_new.bin │ │ ├── settings1_real.bin │ │ ├── settings2_new.bin │ │ ├── settings2_real.bin │ │ ├── settings3_new.bin │ │ ├── settings3_real.bin │ │ ├── state0_new.bin │ │ ├── state0_real.bin │ │ ├── state1_new.bin │ │ └── state1_real.bin ├── fonts │ ├── JuliaMono-Regular.ttf │ ├── SourceCodePro-Regular.otf │ ├── SourceHanSansCN-Regular.otf │ ├── SourceHanSansJP-Regular.otf │ └── SourceHanSansKR-Regular.otf ├── images │ ├── art │ │ └── unknown.png │ ├── comparison │ │ ├── cached.png │ │ ├── cold.png │ │ ├── error.png │ │ └── open.png │ ├── diagram │ │ ├── doubly.png │ │ ├── frontend.png │ │ └── overview.png │ ├── icon │ │ ├── 1024.png │ │ ├── 2048.png │ │ ├── 256.png │ │ ├── 512.png │ │ ├── banner_1280_640.png │ │ ├── icon.ico │ │ ├── icon@2x.png │ │ └── no_bg_512.png │ ├── screenshot │ │ ├── festival-home.png │ │ ├── festival-linux.png │ │ ├── festival-macos.png │ │ └── festival-windows.png │ ├── test.jpg │ └── test │ │ ├── 512.bmp │ │ ├── 512.ico │ │ ├── 512.jpg │ │ ├── 512.png │ │ ├── 512.tiff │ │ └── 512.webp ├── shukusai │ ├── README.md │ └── state │ │ ├── audio0_new.bin │ │ ├── audio0_real.bin │ │ ├── collection0_new.bin │ │ ├── collection0_real.bin │ │ ├── collection1_new.bin │ │ ├── collection1_real.bin │ │ ├── collection2_new.bin │ │ ├── collection2_real.bin │ │ ├── collection3_new.bin │ │ └── collection3_real.bin └── tls │ ├── README.md │ ├── cert.pem │ └── key.pem ├── cli ├── CMD.txt ├── Cargo.toml ├── README.md ├── config │ ├── README.md │ └── festival-cli.toml ├── mdbook │ ├── README.md │ ├── book.toml │ ├── docs.zip │ ├── src │ │ ├── SUMMARY.md │ │ ├── authorization.md │ │ ├── command-line.md │ │ ├── config.md │ │ ├── disk.md │ │ ├── intro.md │ │ ├── json-rpc.md │ │ └── tor.md │ └── zip.sh └── src │ ├── auth.rs │ ├── cli.rs │ ├── config.rs │ ├── config │ ├── README.md │ └── v1.0.0.toml │ ├── constants.rs │ ├── docs.rs │ ├── macros.rs │ ├── main.rs │ └── rpc.rs ├── comparison ├── README.md ├── cached.R ├── cold.R ├── error.R └── open.R ├── daemon ├── CMD.txt ├── CMD_SIGNAL.txt ├── Cargo.lock ├── Cargo.toml ├── README.md ├── config │ ├── README.md │ ├── festivald.service │ └── festivald.toml ├── mdbook │ ├── README.md │ ├── book.toml │ ├── docs.zip │ ├── src │ │ ├── SUMMARY.md │ │ ├── api-stability │ │ │ ├── api-stability.md │ │ │ ├── json-rpc.md │ │ │ ├── marker.md │ │ │ ├── misc.md │ │ │ └── rest.md │ │ ├── audio.md │ │ ├── authorization │ │ │ ├── authorization.md │ │ │ ├── authorization.png │ │ │ ├── documentation.md │ │ │ ├── json-rpc.md │ │ │ └── rest.md │ │ ├── command-line │ │ │ ├── command-line.md │ │ │ ├── flags.md │ │ │ └── signal.md │ │ ├── common-objects │ │ │ ├── album.md │ │ │ ├── artist.md │ │ │ ├── collection.md │ │ │ ├── common-objects.md │ │ │ ├── entry.md │ │ │ ├── key.md │ │ │ ├── playlist.md │ │ │ └── song.md │ │ ├── config.md │ │ ├── disk.md │ │ ├── intro.md │ │ ├── json-rpc │ │ │ ├── collection │ │ │ │ ├── collection.md │ │ │ │ ├── collection_brief.md │ │ │ │ ├── collection_brief_albums.md │ │ │ │ ├── collection_brief_artists.md │ │ │ │ ├── collection_brief_songs.md │ │ │ │ ├── collection_entries.md │ │ │ │ ├── collection_full.md │ │ │ │ ├── collection_full_albums.md │ │ │ │ ├── collection_full_artists.md │ │ │ │ ├── collection_full_songs.md │ │ │ │ ├── collection_health.md │ │ │ │ ├── collection_new.md │ │ │ │ ├── collection_perf.md │ │ │ │ └── collection_resource_size.md │ │ │ ├── current │ │ │ │ ├── current.md │ │ │ │ ├── current_album.md │ │ │ │ ├── current_artist.md │ │ │ │ ├── current_entry.md │ │ │ │ └── current_song.md │ │ │ ├── daemon │ │ │ │ ├── daemon.md │ │ │ │ ├── daemon_config.md │ │ │ │ ├── daemon_methods.md │ │ │ │ ├── daemon_no_auth_rest.md │ │ │ │ ├── daemon_no_auth_rpc.md │ │ │ │ ├── daemon_remove_cache.md │ │ │ │ ├── daemon_save.md │ │ │ │ ├── daemon_seen_ips.md │ │ │ │ ├── daemon_shutdown.md │ │ │ │ └── daemon_state.md │ │ │ ├── json-rpc.md │ │ │ ├── key │ │ │ │ ├── key.md │ │ │ │ ├── key_album.md │ │ │ │ ├── key_album_artist.md │ │ │ │ ├── key_album_entries.md │ │ │ │ ├── key_album_songs.md │ │ │ │ ├── key_artist.md │ │ │ │ ├── key_artist_albums.md │ │ │ │ ├── key_artist_entries.md │ │ │ │ ├── key_artist_songs.md │ │ │ │ ├── key_entry.md │ │ │ │ ├── key_other_albums.md │ │ │ │ ├── key_other_entries.md │ │ │ │ ├── key_other_songs.md │ │ │ │ ├── key_song.md │ │ │ │ ├── key_song_album.md │ │ │ │ └── key_song_artist.md │ │ │ ├── map │ │ │ │ ├── map.md │ │ │ │ ├── map_album.md │ │ │ │ ├── map_album_entries.md │ │ │ │ ├── map_album_songs.md │ │ │ │ ├── map_artist.md │ │ │ │ ├── map_artist_albums.md │ │ │ │ ├── map_artist_entries.md │ │ │ │ ├── map_artist_songs.md │ │ │ │ ├── map_entry.md │ │ │ │ └── map_song.md │ │ │ ├── playback │ │ │ │ ├── back.md │ │ │ │ ├── clear.md │ │ │ │ ├── next.md │ │ │ │ ├── pause.md │ │ │ │ ├── play.md │ │ │ │ ├── playback.md │ │ │ │ ├── previous.md │ │ │ │ ├── repeat.md │ │ │ │ ├── seek.md │ │ │ │ ├── shuffle.md │ │ │ │ ├── skip.md │ │ │ │ ├── stop.md │ │ │ │ ├── toggle.md │ │ │ │ ├── volume.md │ │ │ │ ├── volume_down.md │ │ │ │ └── volume_up.md │ │ │ ├── playlist │ │ │ │ ├── playlist.md │ │ │ │ ├── playlist_add_key_album.md │ │ │ │ ├── playlist_add_key_artist.md │ │ │ │ ├── playlist_add_key_song.md │ │ │ │ ├── playlist_add_map_album.md │ │ │ │ ├── playlist_add_map_artist.md │ │ │ │ ├── playlist_add_map_song.md │ │ │ │ ├── playlist_brief.md │ │ │ │ ├── playlist_clone.md │ │ │ │ ├── playlist_full.md │ │ │ │ ├── playlist_get_index.md │ │ │ │ ├── playlist_new.md │ │ │ │ ├── playlist_remove.md │ │ │ │ ├── playlist_remove_index.md │ │ │ │ └── playlist_single.md │ │ │ ├── queue │ │ │ │ ├── queue.md │ │ │ │ ├── queue_add_key_album.md │ │ │ │ ├── queue_add_key_artist.md │ │ │ │ ├── queue_add_key_song.md │ │ │ │ ├── queue_add_map_album.md │ │ │ │ ├── queue_add_map_artist.md │ │ │ │ ├── queue_add_map_song.md │ │ │ │ ├── queue_add_playlist.md │ │ │ │ ├── queue_add_rand_album.md │ │ │ │ ├── queue_add_rand_artist.md │ │ │ │ ├── queue_add_rand_entry.md │ │ │ │ ├── queue_add_rand_song.md │ │ │ │ ├── queue_remove_range.md │ │ │ │ └── queue_set_index.md │ │ │ ├── quick-start.md │ │ │ ├── rand │ │ │ │ ├── rand.md │ │ │ │ ├── rand_album.md │ │ │ │ ├── rand_artist.md │ │ │ │ ├── rand_entry.md │ │ │ │ └── rand_song.md │ │ │ ├── search │ │ │ │ ├── index.md │ │ │ │ ├── search.md │ │ │ │ ├── search_album.md │ │ │ │ ├── search_artist.md │ │ │ │ ├── search_entry.md │ │ │ │ └── search_song.md │ │ │ └── state │ │ │ │ ├── state.md │ │ │ │ ├── state_audio.md │ │ │ │ ├── state_playing.md │ │ │ │ ├── state_queue_entry.md │ │ │ │ ├── state_queue_key.md │ │ │ │ ├── state_queue_song.md │ │ │ │ ├── state_repeat.md │ │ │ │ ├── state_runtime.md │ │ │ │ └── state_volume.md │ │ ├── quick-start.md │ │ ├── rest │ │ │ ├── art │ │ │ │ ├── album.md │ │ │ │ ├── art.md │ │ │ │ └── artist.md │ │ │ ├── collection.md │ │ │ ├── current │ │ │ │ ├── album.md │ │ │ │ ├── art.md │ │ │ │ ├── artist.md │ │ │ │ ├── current.md │ │ │ │ └── song.md │ │ │ ├── key │ │ │ │ ├── album.md │ │ │ │ ├── art.md │ │ │ │ ├── artist.md │ │ │ │ ├── key.md │ │ │ │ └── song.md │ │ │ ├── map │ │ │ │ ├── album.md │ │ │ │ ├── artist.md │ │ │ │ ├── map.md │ │ │ │ └── song.md │ │ │ ├── playlist.md │ │ │ ├── quick-start.md │ │ │ ├── rand │ │ │ │ ├── album.md │ │ │ │ ├── art.md │ │ │ │ ├── artist.md │ │ │ │ ├── rand.md │ │ │ │ └── song.md │ │ │ └── rest.md │ │ ├── systemd.md │ │ └── tor.md │ └── zip.sh └── src │ ├── cert.rs │ ├── cli.rs │ ├── config.rs │ ├── config │ ├── README.md │ └── v1.0.0.toml │ ├── constants.rs │ ├── docs.rs │ ├── macros.rs │ ├── main.rs │ ├── ptr.rs │ ├── resp.rs │ ├── rest.rs │ ├── router.rs │ ├── rpc.rs │ ├── seen.rs │ ├── shutdown.rs │ ├── statics.rs │ └── zip.rs ├── deny.toml ├── external └── README.md ├── gui ├── CMD.txt ├── Cargo.toml ├── README.md ├── build.rs ├── mdbook │ ├── book.toml │ ├── docs.zip │ ├── src │ │ ├── SUMMARY.md │ │ ├── command-line.md │ │ ├── disk.md │ │ ├── intro.md │ │ ├── key-mouse-shortcuts.md │ │ └── playlists.md │ └── zip.sh └── src │ ├── README.md │ ├── cli.rs │ ├── constants.rs │ ├── data │ ├── album.rs │ ├── artist.rs │ ├── debug.rs │ ├── exit.rs │ ├── gui.rs │ ├── key.rs │ ├── mod.rs │ ├── playlist.rs │ ├── search_sort.rs │ ├── settings.rs │ ├── settings0.rs │ ├── settings1.rs │ ├── settings2.rs │ ├── state.rs │ ├── state0.rs │ ├── tab.rs │ └── window.rs │ ├── docs.rs │ ├── func │ ├── file.rs │ ├── gui.rs │ ├── init.rs │ └── mod.rs │ ├── main.rs │ ├── text.rs │ └── ui │ ├── albums.rs │ ├── artist.rs │ ├── exit.rs │ ├── macros.rs │ ├── mod.rs │ ├── playlists.rs │ ├── queue.rs │ ├── search.rs │ ├── settings.rs │ ├── songs.rs │ ├── update.rs │ └── view.rs ├── pgp ├── README.md └── hinto-janai.asc ├── rpc ├── Cargo.toml ├── README.md └── src │ ├── base64.rs │ ├── hash.rs │ ├── lib.rs │ ├── macros.rs │ ├── method.rs │ ├── param.rs │ ├── resource.rs │ └── resp.rs ├── shukusai ├── CHANGELOG.md ├── Cargo.toml ├── README.md ├── build.rs └── src │ ├── audio │ ├── append.rs │ ├── audio.rs │ ├── media_controls.rs │ ├── mod.rs │ ├── msg.rs │ ├── output.rs │ ├── repeat.rs │ ├── resampler.rs │ ├── seek.rs │ └── volume.rs │ ├── ccd │ ├── ccd.rs │ ├── convert.rs │ ├── img │ │ ├── daemon.rs │ │ ├── gui.rs │ │ └── mod.rs │ ├── mime.rs │ ├── mod.rs │ ├── msg.rs │ ├── perf.rs │ ├── sort.rs │ ├── the_loop.rs │ ├── thread.rs │ └── walk.rs │ ├── collection │ ├── album.rs │ ├── art │ │ ├── daemon.rs │ │ ├── gui.rs │ │ └── mod.rs │ ├── artist.rs │ ├── collection.rs │ ├── entry.rs │ ├── image.rs │ ├── json.rs │ ├── key.rs │ ├── map.rs │ ├── metadata.rs │ ├── mod.rs │ ├── plural.rs │ ├── rpc.rs │ ├── slice.rs │ ├── song.rs │ ├── v0 │ │ ├── README.md │ │ ├── album.rs │ │ ├── art.rs │ │ ├── artist.rs │ │ ├── collection.rs │ │ ├── map.rs │ │ ├── mod.rs │ │ ├── plural.rs │ │ └── song.rs │ ├── v1 │ │ ├── README.md │ │ ├── album.rs │ │ ├── artist.rs │ │ ├── collection.rs │ │ ├── mod.rs │ │ ├── plural.rs │ │ └── song.rs │ └── v2 │ │ ├── README.md │ │ ├── album.rs │ │ ├── artist.rs │ │ ├── collection.rs │ │ ├── mod.rs │ │ ├── plural.rs │ │ └── song.rs │ ├── constants.rs │ ├── frontend │ ├── daemon.rs │ ├── gui.rs │ ├── mod.rs │ └── web.rs │ ├── kernel │ ├── kernel.rs │ ├── mod.rs │ └── msg.rs │ ├── lib.rs │ ├── logger.rs │ ├── macros.rs │ ├── panic.rs │ ├── search │ ├── kind.rs │ ├── mod.rs │ ├── msg.rs │ └── search.rs │ ├── serde.rs │ ├── signal.rs │ ├── sort │ ├── mod.rs │ └── sort.rs │ ├── state │ ├── audio.rs │ ├── mod.rs │ ├── phase.rs │ ├── playlist.rs │ ├── reset.rs │ └── statics.rs │ ├── thread.rs │ ├── validate.rs │ └── watch │ ├── mod.rs │ ├── msg.rs │ └── watch.rs ├── tui ├── Cargo.toml ├── README.md └── src │ └── main.rs ├── typos.toml ├── utils ├── Festival.AppDir │ ├── .DirIcon │ ├── AppRun │ ├── festival.desktop │ ├── festival.png │ └── usr │ │ ├── bin │ │ └── Festival │ │ └── share │ │ └── metainfo │ │ └── festival.appdata.xml ├── Festival.app.skel │ └── Contents │ │ ├── Info.plist │ │ ├── MacOS │ │ └── festival │ │ └── Resources │ │ └── Festival.icns ├── Festival.dmg.skel │ └── Applications ├── README.md ├── longest.sh ├── mk_app.sh ├── mk_appimage.sh ├── mk_dmg.sh └── prepare.sh ├── web ├── Cargo.toml ├── README.md └── src │ └── main.rs └── x.sh /.github/ISSUE_TEMPLATE/bug_report.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Bug Report 3 | about: Create a bug report 4 | title: '' 5 | labels: bug 6 | assignees: '' 7 | 8 | --- 9 | 10 | ## OS & Version 11 | 1. Goto the `Settings` tab 12 | 2. Click on the version text 13 | 3. Paste it here 14 | 15 | ## Bug 16 | What is the bug? 17 | 18 | ## Steps 19 | Steps to reproduce the behavior: 20 | 1. Go to '...' 21 | 2. Click on '....' 22 | 3. See error 23 | 24 | ## Screenshots 25 | If possible, add screenshots to help explain the bug. 26 | 27 | ## Crash report 28 | If Festival is crashing, you may have a file here: 29 | 30 | - Windows: `C:\Users\YOUR_USER_NAME\AppData\Roaming\Festival\data\gui\txt\crash.txt` 31 | - macOS: `/Users/YOUR_USER_NAME/Library/Application Support/Festival/gui/txt/crash.txt` 32 | - Linux: `/home/YOUR_USER_NAME/.local/share/festival/gui/txt/crash.txt` 33 | 34 | If you do, please upload or copy-paste `crash.txt` here: 35 | ``` 36 | paste inside here. 37 | ``` 38 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/feature_request.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Feature Request 3 | about: Request a feature 4 | title: '' 5 | labels: feature 6 | assignees: '' 7 | 8 | --- 9 | 10 | ## Feature 11 | Describe the feature you're requesting. 12 | 13 | ## Screenshots 14 | Add any other context or screenshots about the feature request. 15 | -------------------------------------------------------------------------------- /.github/workflows/disabled/audit.yml: -------------------------------------------------------------------------------- 1 | # This runs `cargo audit` on everything. 2 | 3 | name: Audit 4 | 5 | on: 6 | push: 7 | branches: [ "main" ] 8 | pull_request: 9 | branches: [ "main" ] 10 | 11 | env: 12 | CARGO_TERM_COLOR: always 13 | 14 | jobs: 15 | audit: 16 | 17 | runs-on: ubuntu-latest 18 | 19 | steps: 20 | - uses: actions/checkout@v4 21 | with: 22 | submodules: recursive 23 | - name: Install dependencies 24 | run: cargo install cargo-audit 25 | - name: Audit 26 | run: cargo audit 27 | -------------------------------------------------------------------------------- /.github/workflows/disabled/collection.yml: -------------------------------------------------------------------------------- 1 | # This tests creation of the `Collection`. 2 | # 3 | # These tests are ignored in the regular workflows. 4 | # 5 | # `Serialize And Convert` must be ran after `New`. 6 | # It depends on an actual `collection.bin` existing on the FS. 7 | 8 | name: Collection 9 | 10 | on: 11 | push: 12 | branches: [ "main" ] 13 | pull_request: 14 | branches: [ "main" ] 15 | 16 | env: 17 | CARGO_TERM_COLOR: always 18 | RUSTFLAGS: -Awarnings 19 | 20 | jobs: 21 | collection: 22 | runs-on: ubuntu-latest 23 | steps: 24 | - name: Cache 25 | uses: actions/cache@v3.2.3 26 | with: 27 | path: | 28 | ~/.cargo 29 | target 30 | key: collection 31 | - uses: actions/checkout@v3 32 | with: 33 | submodules: recursive 34 | - name: Install dependencies 35 | run: | 36 | sudo apt update 37 | sudo apt install -y libgtk-3-dev 38 | - name: Vecs 39 | run: cargo test --all-features -- --ignored --exact "ccd::metadata::tests::vecs" 40 | - name: New 41 | run: cargo test --all-features -- --ignored --exact "ccd::ccd::tests::new_collection" 42 | - name: Serialize And Convert 43 | run: cargo test --all-features -- --ignored --exact "ccd::ccd::tests::serialize_and_convert_collection" 44 | -------------------------------------------------------------------------------- /.github/workflows/disabled/miri.yml: -------------------------------------------------------------------------------- 1 | # This runs `miri` 2 | 3 | name: Miri 4 | 5 | on: 6 | push: 7 | branches: [ "main" ] 8 | pull_request: 9 | branches: [ "main" ] 10 | 11 | env: 12 | CARGO_TERM_COLOR: always 13 | 14 | jobs: 15 | miri: 16 | runs-on: ubuntu-latest 17 | steps: 18 | - name: Cache 19 | uses: actions/cache@v3.2.3 20 | with: 21 | path: | 22 | ~/.cargo 23 | target 24 | key: miri 25 | - uses: actions/checkout@v3 26 | with: 27 | submodules: recursive 28 | - name: Install dependencies 29 | run: | 30 | sudo apt update 31 | sudo apt install -y libgtk-3-dev 32 | rustup toolchain install nightly --component miri 33 | rustup override set nightly 34 | cargo miri setup 35 | - name: Miri 36 | env: 37 | RUSTFLAGS: "-A warnings" 38 | run: cargo miri test --all-features 39 | -------------------------------------------------------------------------------- /.github/workflows/typo.yml: -------------------------------------------------------------------------------- 1 | # This catches typos. 2 | 3 | name: Typo 4 | 5 | on: 6 | push: 7 | branches: [ "main" ] 8 | pull_request: 9 | branches: [ "main" ] 10 | 11 | env: 12 | CARGO_TERM_COLOR: always 13 | RUST_BACKTRACE: "full" 14 | 15 | jobs: 16 | typo: 17 | runs-on: ubuntu-latest 18 | steps: 19 | - name: Checkout 20 | uses: actions/checkout@v4 21 | - name: Spell Check 22 | uses: crate-ci/typos@master 23 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | target/ 2 | /assets/images/art/a.jpg 3 | /assets/images/art/b.jpg 4 | /assets/images/art/c.jpg 5 | /assets/images/art/d.jpg 6 | /assets/images/art/e.jpg 7 | /assets/images/art/f.jpg 8 | /assets/images/art/g.jpg 9 | /assets/images/art/h.jpg 10 | /assets/images/art/i.jpg 11 | /assets/albums/ 12 | /utils/Festival*AppImage 13 | /utils/*.dmg 14 | /gui/mdbook/docs/ 15 | /daemon/mdbook/docs/ 16 | /cli/mdbook/docs/ 17 | -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "external/egui"] 2 | path = external/egui 3 | url = https://github.com/hinto-janai/egui.git 4 | [submodule "external/egui-notify"] 5 | path = external/egui-notify 6 | url = https://github.com/hinto-janai/egui-notify 7 | [submodule "external/Symphonia"] 8 | path = external/Symphonia 9 | url = https://github.com/hinto-janai/Symphonia 10 | [submodule "external/json-rpc"] 11 | path = external/json-rpc 12 | url = https://github.com/hinto-janai/json-rpc 13 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2023 hinto-janai 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /assets/README.md: -------------------------------------------------------------------------------- 1 | # Assets 2 | Various images, audio, icons that `Festival` needs either directly or for testing purposes. 3 | 4 | | File/Folder | Purpose | 5 | |--------------------|---------| 6 | | `audio/` | Audio files in various formats, for testing 7 | | `fonts/` | Fonts used in `festival-gui` 8 | | `images/` | Images used throughout `Festival` 9 | | `festival/` | Mimic of `~/.local/share/festival/${FRONTEND}` containing real `Frontend` data, for testing 10 | | `shukusai/` | Mimic of `~/.local/share/festival` containing real `shukusai` data, for testing 11 | | `tls/` | x509 TLS cert + key 12 | -------------------------------------------------------------------------------- /assets/audio/song_1.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hinto-janai/festival/8d7e26d55e7677e3d38d6c51c51683830e9cbd61/assets/audio/song_1.mp3 -------------------------------------------------------------------------------- /assets/audio/song_2.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hinto-janai/festival/8d7e26d55e7677e3d38d6c51c51683830e9cbd61/assets/audio/song_2.mp3 -------------------------------------------------------------------------------- /assets/audio/song_3.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hinto-janai/festival/8d7e26d55e7677e3d38d6c51c51683830e9cbd61/assets/audio/song_3.mp3 -------------------------------------------------------------------------------- /assets/audio/song_4.flac: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hinto-janai/festival/8d7e26d55e7677e3d38d6c51c51683830e9cbd61/assets/audio/song_4.flac -------------------------------------------------------------------------------- /assets/audio/song_5.m4a: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hinto-janai/festival/8d7e26d55e7677e3d38d6c51c51683830e9cbd61/assets/audio/song_5.m4a -------------------------------------------------------------------------------- /assets/audio/song_6.ogg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hinto-janai/festival/8d7e26d55e7677e3d38d6c51c51683830e9cbd61/assets/audio/song_6.ogg -------------------------------------------------------------------------------- /assets/audio/song_7.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hinto-janai/festival/8d7e26d55e7677e3d38d6c51c51683830e9cbd61/assets/audio/song_7.mp3 -------------------------------------------------------------------------------- /assets/festival/README.md: -------------------------------------------------------------------------------- 1 | This directory contains test data for testing and (de)serialization purposes, but only `Frontend`-specific files. 2 | 3 | Folders & files are laid out in the same way as the real files, with this folder serving as `Festival`'s project root, i.e, this folder is `~/.local/share/festival`. 4 | 5 | All `shukusai` data structures are located at `../shukusai`. 6 | 7 | So instead of `gui/state/collection.bin`, it is located at `../shukusai/state/collection.bin`. 8 | -------------------------------------------------------------------------------- /assets/festival/gui/state/settings0_new.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hinto-janai/festival/8d7e26d55e7677e3d38d6c51c51683830e9cbd61/assets/festival/gui/state/settings0_new.bin -------------------------------------------------------------------------------- /assets/festival/gui/state/settings0_real.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hinto-janai/festival/8d7e26d55e7677e3d38d6c51c51683830e9cbd61/assets/festival/gui/state/settings0_real.bin -------------------------------------------------------------------------------- /assets/festival/gui/state/settings1_new.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hinto-janai/festival/8d7e26d55e7677e3d38d6c51c51683830e9cbd61/assets/festival/gui/state/settings1_new.bin -------------------------------------------------------------------------------- /assets/festival/gui/state/settings1_real.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hinto-janai/festival/8d7e26d55e7677e3d38d6c51c51683830e9cbd61/assets/festival/gui/state/settings1_real.bin -------------------------------------------------------------------------------- /assets/festival/gui/state/settings2_new.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hinto-janai/festival/8d7e26d55e7677e3d38d6c51c51683830e9cbd61/assets/festival/gui/state/settings2_new.bin -------------------------------------------------------------------------------- /assets/festival/gui/state/settings2_real.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hinto-janai/festival/8d7e26d55e7677e3d38d6c51c51683830e9cbd61/assets/festival/gui/state/settings2_real.bin -------------------------------------------------------------------------------- /assets/festival/gui/state/settings3_new.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hinto-janai/festival/8d7e26d55e7677e3d38d6c51c51683830e9cbd61/assets/festival/gui/state/settings3_new.bin -------------------------------------------------------------------------------- /assets/festival/gui/state/settings3_real.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hinto-janai/festival/8d7e26d55e7677e3d38d6c51c51683830e9cbd61/assets/festival/gui/state/settings3_real.bin -------------------------------------------------------------------------------- /assets/festival/gui/state/state0_new.bin: -------------------------------------------------------------------------------- 1 | -----BEGIN FESTIVAL----- -------------------------------------------------------------------------------- /assets/festival/gui/state/state0_real.bin: -------------------------------------------------------------------------------- 1 | -----BEGIN FESTIVAL-----asdf -------------------------------------------------------------------------------- /assets/festival/gui/state/state1_new.bin: -------------------------------------------------------------------------------- 1 | -----BEGIN FESTIVAL----- -------------------------------------------------------------------------------- /assets/festival/gui/state/state1_real.bin: -------------------------------------------------------------------------------- 1 | -----BEGIN FESTIVAL-----asdf -------------------------------------------------------------------------------- /assets/fonts/JuliaMono-Regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hinto-janai/festival/8d7e26d55e7677e3d38d6c51c51683830e9cbd61/assets/fonts/JuliaMono-Regular.ttf -------------------------------------------------------------------------------- /assets/fonts/SourceCodePro-Regular.otf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hinto-janai/festival/8d7e26d55e7677e3d38d6c51c51683830e9cbd61/assets/fonts/SourceCodePro-Regular.otf -------------------------------------------------------------------------------- /assets/fonts/SourceHanSansCN-Regular.otf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hinto-janai/festival/8d7e26d55e7677e3d38d6c51c51683830e9cbd61/assets/fonts/SourceHanSansCN-Regular.otf -------------------------------------------------------------------------------- /assets/fonts/SourceHanSansJP-Regular.otf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hinto-janai/festival/8d7e26d55e7677e3d38d6c51c51683830e9cbd61/assets/fonts/SourceHanSansJP-Regular.otf -------------------------------------------------------------------------------- /assets/fonts/SourceHanSansKR-Regular.otf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hinto-janai/festival/8d7e26d55e7677e3d38d6c51c51683830e9cbd61/assets/fonts/SourceHanSansKR-Regular.otf -------------------------------------------------------------------------------- /assets/images/art/unknown.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hinto-janai/festival/8d7e26d55e7677e3d38d6c51c51683830e9cbd61/assets/images/art/unknown.png -------------------------------------------------------------------------------- /assets/images/comparison/cached.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hinto-janai/festival/8d7e26d55e7677e3d38d6c51c51683830e9cbd61/assets/images/comparison/cached.png -------------------------------------------------------------------------------- /assets/images/comparison/cold.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hinto-janai/festival/8d7e26d55e7677e3d38d6c51c51683830e9cbd61/assets/images/comparison/cold.png -------------------------------------------------------------------------------- /assets/images/comparison/error.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hinto-janai/festival/8d7e26d55e7677e3d38d6c51c51683830e9cbd61/assets/images/comparison/error.png -------------------------------------------------------------------------------- /assets/images/comparison/open.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hinto-janai/festival/8d7e26d55e7677e3d38d6c51c51683830e9cbd61/assets/images/comparison/open.png -------------------------------------------------------------------------------- /assets/images/diagram/doubly.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hinto-janai/festival/8d7e26d55e7677e3d38d6c51c51683830e9cbd61/assets/images/diagram/doubly.png -------------------------------------------------------------------------------- /assets/images/diagram/frontend.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hinto-janai/festival/8d7e26d55e7677e3d38d6c51c51683830e9cbd61/assets/images/diagram/frontend.png -------------------------------------------------------------------------------- /assets/images/diagram/overview.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hinto-janai/festival/8d7e26d55e7677e3d38d6c51c51683830e9cbd61/assets/images/diagram/overview.png -------------------------------------------------------------------------------- /assets/images/icon/1024.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hinto-janai/festival/8d7e26d55e7677e3d38d6c51c51683830e9cbd61/assets/images/icon/1024.png -------------------------------------------------------------------------------- /assets/images/icon/2048.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hinto-janai/festival/8d7e26d55e7677e3d38d6c51c51683830e9cbd61/assets/images/icon/2048.png -------------------------------------------------------------------------------- /assets/images/icon/256.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hinto-janai/festival/8d7e26d55e7677e3d38d6c51c51683830e9cbd61/assets/images/icon/256.png -------------------------------------------------------------------------------- /assets/images/icon/512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hinto-janai/festival/8d7e26d55e7677e3d38d6c51c51683830e9cbd61/assets/images/icon/512.png -------------------------------------------------------------------------------- /assets/images/icon/banner_1280_640.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hinto-janai/festival/8d7e26d55e7677e3d38d6c51c51683830e9cbd61/assets/images/icon/banner_1280_640.png -------------------------------------------------------------------------------- /assets/images/icon/icon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hinto-janai/festival/8d7e26d55e7677e3d38d6c51c51683830e9cbd61/assets/images/icon/icon.ico -------------------------------------------------------------------------------- /assets/images/icon/icon@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hinto-janai/festival/8d7e26d55e7677e3d38d6c51c51683830e9cbd61/assets/images/icon/icon@2x.png -------------------------------------------------------------------------------- /assets/images/icon/no_bg_512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hinto-janai/festival/8d7e26d55e7677e3d38d6c51c51683830e9cbd61/assets/images/icon/no_bg_512.png -------------------------------------------------------------------------------- /assets/images/screenshot/festival-home.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hinto-janai/festival/8d7e26d55e7677e3d38d6c51c51683830e9cbd61/assets/images/screenshot/festival-home.png -------------------------------------------------------------------------------- /assets/images/screenshot/festival-linux.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hinto-janai/festival/8d7e26d55e7677e3d38d6c51c51683830e9cbd61/assets/images/screenshot/festival-linux.png -------------------------------------------------------------------------------- /assets/images/screenshot/festival-macos.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hinto-janai/festival/8d7e26d55e7677e3d38d6c51c51683830e9cbd61/assets/images/screenshot/festival-macos.png -------------------------------------------------------------------------------- /assets/images/screenshot/festival-windows.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hinto-janai/festival/8d7e26d55e7677e3d38d6c51c51683830e9cbd61/assets/images/screenshot/festival-windows.png -------------------------------------------------------------------------------- /assets/images/test.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hinto-janai/festival/8d7e26d55e7677e3d38d6c51c51683830e9cbd61/assets/images/test.jpg -------------------------------------------------------------------------------- /assets/images/test/512.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hinto-janai/festival/8d7e26d55e7677e3d38d6c51c51683830e9cbd61/assets/images/test/512.bmp -------------------------------------------------------------------------------- /assets/images/test/512.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hinto-janai/festival/8d7e26d55e7677e3d38d6c51c51683830e9cbd61/assets/images/test/512.ico -------------------------------------------------------------------------------- /assets/images/test/512.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hinto-janai/festival/8d7e26d55e7677e3d38d6c51c51683830e9cbd61/assets/images/test/512.jpg -------------------------------------------------------------------------------- /assets/images/test/512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hinto-janai/festival/8d7e26d55e7677e3d38d6c51c51683830e9cbd61/assets/images/test/512.png -------------------------------------------------------------------------------- /assets/images/test/512.tiff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hinto-janai/festival/8d7e26d55e7677e3d38d6c51c51683830e9cbd61/assets/images/test/512.tiff -------------------------------------------------------------------------------- /assets/images/test/512.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hinto-janai/festival/8d7e26d55e7677e3d38d6c51c51683830e9cbd61/assets/images/test/512.webp -------------------------------------------------------------------------------- /assets/shukusai/README.md: -------------------------------------------------------------------------------- 1 | This directory contains test data for testing and (de)serialization purposes, e.g, the `Collection`. 2 | 3 | Folders & files are laid out in the same way as the real files, with this folder serving a `Frontend`'s root, e.g `~/.local/share/festival/gui`. 4 | 5 | All `shukusai` data structures (e.g `Collection`) are inside here instead of the `../festival`, since there's no reason to test the same structures for every `Frontend`. 6 | -------------------------------------------------------------------------------- /assets/shukusai/state/audio0_new.bin: -------------------------------------------------------------------------------- 1 | -----BEGIN FESTIVAL-----0:000:00 -------------------------------------------------------------------------------- /assets/shukusai/state/audio0_real.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hinto-janai/festival/8d7e26d55e7677e3d38d6c51c51683830e9cbd61/assets/shukusai/state/audio0_real.bin -------------------------------------------------------------------------------- /assets/shukusai/state/collection0_new.bin: -------------------------------------------------------------------------------- 1 | -----BEGIN FESTIVAL-----0000 -------------------------------------------------------------------------------- /assets/shukusai/state/collection0_real.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hinto-janai/festival/8d7e26d55e7677e3d38d6c51c51683830e9cbd61/assets/shukusai/state/collection0_real.bin -------------------------------------------------------------------------------- /assets/shukusai/state/collection1_new.bin: -------------------------------------------------------------------------------- 1 | -----BEGIN FESTIVAL-----0000 -------------------------------------------------------------------------------- /assets/shukusai/state/collection1_real.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hinto-janai/festival/8d7e26d55e7677e3d38d6c51c51683830e9cbd61/assets/shukusai/state/collection1_real.bin -------------------------------------------------------------------------------- /assets/shukusai/state/collection2_new.bin: -------------------------------------------------------------------------------- 1 | -----BEGIN FESTIVAL-----0000 -------------------------------------------------------------------------------- /assets/shukusai/state/collection2_real.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hinto-janai/festival/8d7e26d55e7677e3d38d6c51c51683830e9cbd61/assets/shukusai/state/collection2_real.bin -------------------------------------------------------------------------------- /assets/shukusai/state/collection3_new.bin: -------------------------------------------------------------------------------- 1 | -----BEGIN FESTIVAL-----0000 -------------------------------------------------------------------------------- /assets/shukusai/state/collection3_real.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hinto-janai/festival/8d7e26d55e7677e3d38d6c51c51683830e9cbd61/assets/shukusai/state/collection3_real.bin -------------------------------------------------------------------------------- /assets/tls/README.md: -------------------------------------------------------------------------------- 1 | # TLS 2 | x509 PEM certificate and key for testing. 3 | 4 | Made with: 5 | ```bash 6 | openssl req -x509 -newkey rsa:4096 -keyout key.pem -out cert.pem -sha256 -days 3650 -nodes -subj "/C=XX/ST=StateName/L=CityName/O=CompanyName/OU=CompanySectionName/CN=CommonNameOrHostname 7 | ``` 8 | -------------------------------------------------------------------------------- /cli/config/README.md: -------------------------------------------------------------------------------- 1 | # Config 2 | `festival-cli.toml` is `festival-cli`'s config file. It is in the [`TOML`](https://en.wikipedia.org/wiki/TOML) format. 3 | 4 | Values will be loaded from this file on startup. 5 | 6 | If overlapping `--command-flags` are provided, they will be used instead. 7 | 8 | It is located at: 9 | 10 | | Platform | Example | 11 | |----------|--------------------------------------------------------------------------| 12 | | Windows | `C:\Users\USER\AppData\Roaming\Festival\config\daemon\festivald.toml` | 13 | | macOS | `/Users/USER/Library/Application Support/Festival/daemon/festivald.toml` | 14 | | Linux | `/home/USER/.local/share/festival/daemon/festivald.toml` | 15 | -------------------------------------------------------------------------------- /cli/mdbook/README.md: -------------------------------------------------------------------------------- 1 | # mdbook 2 | Source to build the documentation for [`festival-cli`](https://docs.festival.pm/cli). 3 | 4 | Build: 5 | ```bash 6 | mdbook build 7 | ``` 8 | -------------------------------------------------------------------------------- /cli/mdbook/book.toml: -------------------------------------------------------------------------------- 1 | [book] 2 | authors = ["hinto-janai"] 3 | language = "en" 4 | multilingual = false 5 | src = "src" 6 | title = "festival-cli v1.0.0" 7 | 8 | [build] 9 | build-dir = "docs" 10 | 11 | [output.html] 12 | default-theme = "ayu" 13 | preferred-dark-theme = "ayu" 14 | git-repository-url = "https://github.com/hinto-janai/festival" 15 | site-url = "/cli/" 16 | -------------------------------------------------------------------------------- /cli/mdbook/docs.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hinto-janai/festival/8d7e26d55e7677e3d38d6c51c51683830e9cbd61/cli/mdbook/docs.zip -------------------------------------------------------------------------------- /cli/mdbook/src/SUMMARY.md: -------------------------------------------------------------------------------- 1 | # Summary 2 | 3 | [Intro](intro.md) 4 | 5 | * [Disk](disk.md) 6 | * [Config](config.md) 7 | * [Command Line](command-line.md) 8 | * [Authorization](authorization.md) 9 | * [JSON-RPC](json-rpc.md) 10 | * [Tor](tor.md) 11 | -------------------------------------------------------------------------------- /cli/mdbook/src/authorization.md: -------------------------------------------------------------------------------- 1 | # Authorization 2 | `festivald` has a [`Basic access authentication`](https://en.wikipedia.org/wiki/Basic_access_authentication) option, with a username + password setup. 3 | 4 | If enabled, `festival-cli` must also use `--authorization` or setup the [`authorization`](config.md) config option to connect to it. 5 | 6 | `festival-cli` must connect to `festivald` over `HTTPS` or [`.onion`](tor.md) if authorization is enabled or `festival-cli` will refuse to start. 7 | 8 | ## Syntax 9 | The username & password syntax is specified [here](https://en.wikipedia.org/wiki/Basic_access_authentication). 10 | 11 | The "authorization" value must be: 12 | 1. The username 13 | 2. Followed by a single colon ":" 14 | 3. Then the password 15 | 16 | For example: 17 | ```plaintext 18 | my_user:my_pass 19 | ``` 20 | 21 | A request including this information looks like: 22 | ```bash 23 | festival-cli --authorization my_user:my_pass 24 | ``` 25 | 26 | Alternatively, you can input an absolute PATH to a file `festival-cli` can access, containing the string, e.g: 27 | ```bash 28 | festival-cli --authorization /path/to/auth.txt 29 | ``` 30 | In this case, `festival-cli` will read the file and attempt to parse it with the same syntax, i.e, the file should contain: 31 | ```plaintext 32 | my_user:my_pass 33 | ``` 34 | -------------------------------------------------------------------------------- /cli/mdbook/src/command-line.md: -------------------------------------------------------------------------------- 1 | # Command Line 2 | Arguments passed to `festival-cli` will always take priority over the same [configuration](config.md) options read from disk. 3 | 4 | See [`JSON-RPC`](json-rpc.md) for method command-line syntax. 5 | 6 | ```plaintext 7 | {{#include ../../CMD.txt}} 8 | ``` 9 | -------------------------------------------------------------------------------- /cli/mdbook/src/config.md: -------------------------------------------------------------------------------- 1 | # Config 2 | `festival-cli` reads and loads its configuration file, `festival-cli.toml`, on startup. It controls various behaviors of `festival-cli`. 3 | 4 | Exactly where this file is depends on the OS, more details in the [`Disk`](disk.md) section. 5 | 6 | [`Command Line`](command-line.md) flags will override any overlapping config values. 7 | 8 | ## `festival-cli.toml` 9 | This is the default configuration file `festival-cli` creates and uses. 10 | 11 | If `festival-cli` is started with no `--flags`, e.g: 12 | ```bash 13 | festival-cli 14 | ``` 15 | Then it will be equivalent to this config file. 16 | 17 | ```toml 18 | {{#include ../../config/festival-cli.toml}} 19 | ``` 20 | -------------------------------------------------------------------------------- /cli/mdbook/src/intro.md: -------------------------------------------------------------------------------- 1 | # Intro 2 | `festival-cli` is a [`JSON-RPC 2.0`](https://www.jsonrpc.org/specification) client for [`festivald`](https://docs.festival.pm/daemon). 3 | 4 | `festivald` is a music server that plays on the device it is running on, and is remotely controlled by clients. 5 | 6 | `festival-cli` is a client that reduces the verbosity of `JSON-RPC` requests, so instead of: 7 | ```bash 8 | curl http://localhost:18425 -d '{"jsonrpc":"2.0","id":0,"method":"collection_new","params":{"paths":null}}' 9 | ``` 10 | You can use: 11 | ```bash 12 | festival-cli collection_new 13 | ``` 14 | 15 | The typical invocation of `festival-cli`: 16 | 1. Reads the [config](config.md) file 17 | 2. Reads the [command-line](command-line.md) options 18 | 3. Connects and sends a request to `festivald` 19 | 4. Prints out the `JSON` response 20 | 21 | A public instance of `festivald` with [`Creative Commons`](https://creativecommons.org/licenses/by-nc-nd/4.0/) licensed music is available at: 22 | ```http 23 | https://daemon.festival.pm 24 | ``` 25 | 26 | For a general quick start, see the next section: [Quick Start](quick-start.md). 27 | 28 | ### Purpose 29 | `festival-cli` is solely for connecting to, sending requests, and receiving `JSON-RPC 2.0` responses from a `festivald`. 30 | 31 | For more information on `festivald`'s API, see here: [https://docs.festival.pm/daemon](https://docs.festival.pm/daemon). 32 | 33 | `festival-cli` doesn't have any options for interacting with `festivald`'s `REST` API. A generic HTTP client is better suited for this job, like `curl`, `wget`, or a web browser. 34 | 35 | ### Documentation 36 | To open this documentation locally: 37 | ```bash 38 | festival-cli --docs 39 | ``` 40 | -------------------------------------------------------------------------------- /cli/mdbook/zip.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | # Build the documentation, and zip it. 4 | 5 | set -ex 6 | 7 | [[ -e docs.zip ]] && rm docs.zip 8 | 9 | mdbook build && zip -r9 docs.zip docs 10 | -------------------------------------------------------------------------------- /cli/src/auth.rs: -------------------------------------------------------------------------------- 1 | //---------------------------------------------------------------------------------------------------- Use 2 | use zeroize::{ZeroizeOnDrop,Zeroize}; 3 | use std::pin::Pin; 4 | use serde::Serialize; 5 | 6 | //---------------------------------------------------------------------------------------------------- Hash 7 | #[derive(Zeroize,ZeroizeOnDrop,PartialEq,Debug,Serialize)] 8 | // Contains `Basic ` 9 | pub struct Auth(String); 10 | 11 | impl Auth { 12 | /// Encode input in base64 13 | pub fn new(input: String) -> Self { 14 | Self(rpc::base64::encode_with_authorization_basic_header(input)) 15 | } 16 | 17 | pub fn as_str(&self) -> &str { 18 | self.0.as_str() 19 | } 20 | } 21 | 22 | 23 | //---------------------------------------------------------------------------------------------------- TESTS 24 | #[cfg(test)] 25 | mod tests { 26 | use super::*; 27 | } 28 | -------------------------------------------------------------------------------- /cli/src/config/README.md: -------------------------------------------------------------------------------- 1 | # Config 2 | Archives of `festival-cli`'s configuration over different version, for (de)serialization testing. 3 | -------------------------------------------------------------------------------- /cli/src/docs.rs: -------------------------------------------------------------------------------- 1 | //---------------------------------------------------------------------------------------------------- Use 2 | use serde::{Serialize,Deserialize}; 3 | use disk::Empty; 4 | use std::path::{Path,PathBuf}; 5 | use shukusai::constants::FESTIVAL; 6 | use crate::constants::SUB_DIR; 7 | use const_format::formatcp; 8 | use once_cell::sync::OnceCell; 9 | 10 | //---------------------------------------------------------------------------------------------------- Docs 11 | disk::empty!(Docs, disk::Dir::Data, FESTIVAL, formatcp!("{SUB_DIR}/docs"), "__docs"); 12 | #[derive(Debug,PartialEq,Eq,PartialOrd,Ord,Serialize,Deserialize)] 13 | pub struct Docs; 14 | 15 | const DOCS_ZIP: &[u8] = include_bytes!("../mdbook/docs.zip"); 16 | pub static DOCS_PATH: OnceCell = OnceCell::new(); 17 | 18 | impl Docs { 19 | pub fn create() -> Result { 20 | let mut path = Self::base_path()?; 21 | let _ = std::fs::remove_dir_all(&path); 22 | Self::mkdir()?; 23 | 24 | let mut zip = zip::ZipArchive::new(std::io::Cursor::new(DOCS_ZIP))?; 25 | 26 | // The `ZIP` contains `/docs`, so pop it out. 27 | path.pop(); 28 | zip.extract(&path)?; 29 | path.push("docs"); 30 | 31 | Ok(path) 32 | } 33 | 34 | pub fn create_open() -> Result<(), anyhow::Error> { 35 | match crate::docs::Docs::create() { 36 | Ok(mut path) => { 37 | path.push("index.html"); 38 | Ok(open::that_detached(path)?) 39 | }, 40 | Err(e) => Err(e), 41 | } 42 | } 43 | } 44 | 45 | //---------------------------------------------------------------------------------------------------- TESTS 46 | //#[cfg(test)] 47 | //mod tests { 48 | // #[test] 49 | // fn __TEST__() { 50 | // } 51 | //} 52 | -------------------------------------------------------------------------------- /cli/src/macros.rs: -------------------------------------------------------------------------------- 1 | // Top-level convenience macros. 2 | 3 | //---------------------------------------------------------------------------------------------------- Use 4 | 5 | //---------------------------------------------------------------------------------------------------- __NAME__ 6 | // Exit the whole program with an error message WITHOUT running destructors. 7 | #[macro_export] 8 | macro_rules! exit { 9 | ($($msg:tt)*) => {{ 10 | ::std::eprintln!("festival-cli error: {}", ::std::format_args!($($msg)*)); 11 | ::std::process::exit(1); 12 | }} 13 | } 14 | 15 | //---------------------------------------------------------------------------------------------------- TESTS 16 | //#[cfg(test)] 17 | //mod tests { 18 | // #[test] 19 | // fn __TEST__() { 20 | // } 21 | //} 22 | -------------------------------------------------------------------------------- /cli/src/main.rs: -------------------------------------------------------------------------------- 1 | mod auth; 2 | mod cli; 3 | mod config; 4 | mod constants; 5 | mod docs; 6 | mod macros; 7 | mod rpc; 8 | 9 | fn main() { 10 | // Handle regular CLI arguments (exit if needed). 11 | let (config_cmd, rpc, debug, dry_run) = crate::cli::Cli::get(); 12 | 13 | // Read config: `festival-cli.toml`. 14 | let mut config_builder = crate::config::ConfigBuilder::file_or(); 15 | 16 | // Merge config + command-line. 17 | if let Some(mut config_cmd) = config_cmd { 18 | config_builder.merge(&mut config_cmd); 19 | } 20 | 21 | // Build config. 22 | let config = config_builder.build(debug); 23 | 24 | let Some(rpc) = rpc else { 25 | crate::exit!("missing method"); 26 | }; 27 | 28 | // Connect to `festivald`, send request, print response. 29 | crate::rpc::request(config, debug, dry_run, rpc); 30 | } 31 | -------------------------------------------------------------------------------- /comparison/cached.R: -------------------------------------------------------------------------------- 1 | library(ggplot2) 2 | 3 | # Festival. 4 | x.festival <- c(0) 5 | y.festival <- c(0, 1) 6 | 7 | # Lollypop. 8 | x.lollypop <- c(0) 9 | y.lollypop <- c(0, 94) 10 | 11 | # MusicBee. 12 | x.musicbee <- c(0) 13 | y.musicbee <- c(0, 20) 14 | 15 | # GNOME Music. 16 | x.gnome <- c(0) 17 | y.gnome <- c(0, 50) 18 | 19 | # iTunes. 20 | x.itunes <- c(0) 21 | y.itunes <- c(0, 135) 22 | 23 | # Data. 24 | input.data <- rbind( 25 | data.frame(x = x.festival, y = y.festival, series = "Festival (1s)"), 26 | data.frame(x = x.musicbee, y = y.musicbee, series = "MusicBee (20s)"), 27 | data.frame(x = x.gnome, y = y.gnome, series = "GNOME Music (50s)"), 28 | data.frame(x = x.lollypop, y = y.lollypop, series = "Lollypop (94s)"), 29 | data.frame(x = x.itunes, y = y.itunes, series = "iTunes (135s)") 30 | ) 31 | 32 | # Bar plot. 33 | p <- ggplot(aes(x = x, y = y, fill = series), data = input.data) + 34 | geom_col(position = "dodge", width = 15) + 35 | scale_x_discrete(labels = NULL) + 36 | scale_y_continuous(breaks = scales::pretty_breaks(n = 25)) + 37 | theme(text = element_text(size = 30)) + 38 | theme(plot.title = element_text(color = "black", size = 40, face = "bold")) + 39 | labs(title = "New Collection (cached)", y = "Seconds (less is better)", x = NULL, fill = NULL) + 40 | scale_fill_manual(values = c("#D82C6A", "#4F89C2", "#195750", "#957DAD", "#FB931F")) 41 | 42 | # Create PNG. 43 | png("cached.png", width = 1000, height = 1000, pointsize = 50, res = 75) 44 | print(p) 45 | dev.off() 46 | -------------------------------------------------------------------------------- /comparison/cold.R: -------------------------------------------------------------------------------- 1 | library(ggplot2) 2 | 3 | # Festival. 4 | x.festival <- c(0) 5 | y.festival <- c(0, 2.25) 6 | 7 | # Lollypop. 8 | x.lollypop <- c(0) 9 | y.lollypop <- c(0, 60) 10 | 11 | # MusicBee. 12 | x.musicbee <- c(0) 13 | y.musicbee <- c(0, 35) 14 | 15 | # GNOME Music. 16 | x.gnome <- c(0) 17 | y.gnome <- c(0, 50) 18 | 19 | # iTunes. 20 | x.itunes <- c(0) 21 | y.itunes <- c(0, 135) 22 | 23 | # Data. 24 | input.data <- rbind( 25 | data.frame(x = x.festival, y = y.festival, series = "Festival (2.25s)"), 26 | data.frame(x = x.musicbee, y = y.musicbee, series = "MusicBee (35s)"), 27 | data.frame(x = x.gnome, y = y.gnome, series = "GNOME Music (50s)"), 28 | data.frame(x = x.lollypop, y = y.lollypop, series = "Lollypop (60s)"), 29 | data.frame(x = x.itunes, y = y.itunes, series = "iTunes (135s)") 30 | ) 31 | 32 | # Bar plot. 33 | p <- ggplot(aes(x = x, y = y, fill = series), data = input.data) + 34 | geom_col(position = "dodge", width = 15) + 35 | scale_x_discrete(labels = NULL) + 36 | scale_y_continuous(breaks = scales::pretty_breaks(n = 25)) + 37 | theme(text = element_text(size = 30)) + 38 | theme(plot.title = element_text(color = "black", size = 40, face = "bold")) + 39 | labs(title = "New Collection (cold)", y = "Seconds (less is better)", x = NULL, fill = NULL) + 40 | scale_fill_manual(values = c("#D82C6A", "#4F89C2", "#195750", "#957DAD", "#FB931F")) 41 | 42 | # Create PNG. 43 | png("cold.png", width = 1000, height = 1000, pointsize = 50, res = 75) 44 | print(p) 45 | dev.off() 46 | -------------------------------------------------------------------------------- /comparison/error.R: -------------------------------------------------------------------------------- 1 | library(ggplot2) 2 | 3 | # Festival. 4 | x.festival <- c(0) 5 | y.festival <- c(0, 0) 6 | 7 | # Lollypop. 8 | x.lollypop <- c(0) 9 | y.lollypop <- c(0, 0) 10 | 11 | # MusicBee. 12 | x.musicbee <- c(0) 13 | y.musicbee <- c(0, 118) 14 | 15 | # GNOME Music. 16 | x.gnome <- c(0) 17 | y.gnome <- c(0, 33) 18 | 19 | # iTunes. 20 | x.itunes <- c(0) 21 | y.itunes <- c(0, 35) 22 | 23 | # Data. 24 | input.data <- rbind( 25 | data.frame(x = x.festival, y = y.festival, series = "Festival (0)"), 26 | data.frame(x = x.musicbee, y = y.musicbee, series = "MusicBee (118)"), 27 | data.frame(x = x.gnome, y = y.gnome, series = "GNOME Music (33)"), 28 | data.frame(x = x.lollypop, y = y.lollypop, series = "Lollypop (0)"), 29 | data.frame(x = x.itunes, y = y.itunes, series = "iTunes (35)") 30 | ) 31 | 32 | # Bar plot. 33 | p <- ggplot(aes(x = x, y = y, fill = series), data = input.data) + 34 | geom_col(position = "dodge", width = 15) + 35 | scale_x_discrete(labels = NULL) + 36 | scale_y_continuous(breaks = scales::pretty_breaks(n = 25)) + 37 | theme(text = element_text(size = 30)) + 38 | theme(plot.title = element_text(color = "black", size = 40, face = "bold")) + 39 | labs(title = "Error", y = "Errors (less is better)", x = NULL, fill = NULL) + 40 | scale_fill_manual(values = c("#D82C6A", "#4F89C2", "#195750", "#957DAD", "#FB931F")) 41 | 42 | # Create PNG. 43 | png("error.png", width = 1000, height = 1000, pointsize = 50, res = 75) 44 | print(p) 45 | dev.off() 46 | -------------------------------------------------------------------------------- /comparison/open.R: -------------------------------------------------------------------------------- 1 | library(ggplot2) 2 | 3 | # Festival. 4 | x.festival <- c(0) 5 | y.festival <- c(0, 0.28) 6 | 7 | # Lollypop. 8 | x.lollypop <- c(0) 9 | y.lollypop <- c(0, 2.45) 10 | 11 | # MusicBee. 12 | x.musicbee <- c(0) 13 | y.musicbee <- c(0, 1.95) 14 | 15 | # GNOME Music. 16 | x.gnome <- c(0) 17 | y.gnome <- c(0, 50) 18 | 19 | # iTunes. 20 | x.itunes <- c(0) 21 | y.itunes <- c(0, 17.5) 22 | 23 | # Data. 24 | input.data <- rbind( 25 | data.frame(x = x.festival, y = y.festival, series = "Festival (0.28s)"), 26 | data.frame(x = x.musicbee, y = y.musicbee, series = "MusicBee (1.96s)"), 27 | data.frame(x = x.gnome, y = y.gnome, series = "GNOME Music (50s)"), 28 | data.frame(x = x.lollypop, y = y.lollypop, series = "Lollypop (2.45s)"), 29 | data.frame(x = x.itunes, y = y.itunes, series = "iTunes (17.5s)") 30 | ) 31 | 32 | # Bar plot. 33 | p <- ggplot(aes(x = x, y = y, fill = series), data = input.data) + 34 | geom_col(position = "dodge", width = 15) + 35 | scale_x_discrete(labels = NULL) + 36 | scale_y_continuous(breaks = scales::pretty_breaks(n = 25)) + 37 | theme(text = element_text(size = 30)) + 38 | theme(plot.title = element_text(color = "black", size = 40, face = "bold")) + 39 | labs(title = "Open", y = "Seconds (less is better)", x = NULL, fill = NULL) + 40 | scale_fill_manual(values = c("#D82C6A", "#4F89C2", "#195750", "#957DAD", "#FB931F")) 41 | 42 | # Create PNG. 43 | png("open.png", width = 1000, height = 1000, pointsize = 50, res = 75) 44 | print(p) 45 | dev.off() 46 | -------------------------------------------------------------------------------- /daemon/config/README.md: -------------------------------------------------------------------------------- 1 | # Config 2 | `festivald.toml` is `festivald`'s config file. It is in the [`TOML`](https://en.wikipedia.org/wiki/TOML) format. 3 | 4 | Values will be loaded from this file on startup. 5 | 6 | If overlapping `--command-flags` are provided, they will be used instead. 7 | 8 | It is located at: 9 | 10 | | Platform | Example | 11 | |----------|--------------------------------------------------------------------------| 12 | | Windows | `C:\Users\USER\AppData\Roaming\Festival\config\daemon\festivald.toml` | 13 | | macOS | `/Users/USER/Library/Application Support/Festival/daemon/festivald.toml` | 14 | | Linux | `/home/USER/.local/share/festival/daemon/festivald.toml` | 15 | 16 | # `systemd` service 17 | `festivald.service` is a relatively hardened [`systemd`](https://en.wikipedia.org/wiki/Systemd) service file for `festivald`. 18 | 19 | `${USER}` should be replaced by a user that has access to an audio server (like PulseAudio). 20 | 21 | It should be placed at: 22 | ``` 23 | /etc/systemd/system/festivald.service 24 | ``` 25 | and launched with: 26 | ```bash 27 | sudo systemctl start festivald 28 | ``` 29 | -------------------------------------------------------------------------------- /daemon/config/festivald.service: -------------------------------------------------------------------------------- 1 | #===================# 2 | # festivald.service # 3 | #=======================================================# 4 | # This is a systemd user service file for `festivald`. # 5 | # It is relatively hardened for public usage. # 6 | # # 7 | # ${USER} should be replaced by a user that has # 8 | # access to an audio server (like PulseAudio). # 9 | #=======================================================# 10 | 11 | [Unit] 12 | Description=Festival Daemon 13 | After=network-online.target 14 | StartLimitIntervalSec=300 15 | StartLimitBurst=5 16 | 17 | [Service] 18 | User=${USER} # <- Replace Me 19 | Type=simple 20 | ExecStart=/usr/bin/festivald 21 | 22 | ## Wait 35 seconds before sending SIGTERM on exit 23 | KillSignal=SIGTERM 24 | TimeoutStopSec=35s 25 | SendSIGKILL=true 26 | 27 | ## Hardening 28 | CapabilityBoundingSet=~CAP_NET_ADMIN CAP_SYS_PTRACE CAP_SYS_ADMIN CAP_KILL CAP_SYS_PACCT CAP_SYS_BOOT CAP_SYS_CHROOT CAP_LEASE CAP_MKNOD CAP_CHOWN CAP_FSETID CAP_SETFCAP CAP_SETUID CAP_SETGID CAP_SETPCAP CAP_SYS_TIME CAP_IPC_LOCK CAP_LINUX_IMMUTABLE CAP_FOWNER CAP_IPC_OWNER CAP_SYS_RESOURCE 29 | RestrictNamespaces=true 30 | ProtectHostname=true 31 | ProtectClock=true 32 | ProtectKernelModules=true 33 | ProtectKernelLogs=true 34 | ProtectProc=invisible 35 | ProcSubset=pid 36 | ProtectControlGroups=true 37 | ProtectKernelTunables=true 38 | PrivateUsers=true 39 | NoNewPrivileges=true 40 | PrivateTmp=true 41 | ProtectSystem=strict 42 | 43 | [Install] 44 | WantedBy=default.target 45 | -------------------------------------------------------------------------------- /daemon/mdbook/README.md: -------------------------------------------------------------------------------- 1 | # mdbook 2 | Source to build the documentation for [`festivald`](https://docs.festival.pm/daemon). 3 | 4 | Build: 5 | ```bash 6 | mdbook build 7 | ``` 8 | -------------------------------------------------------------------------------- /daemon/mdbook/book.toml: -------------------------------------------------------------------------------- 1 | [book] 2 | authors = ["hinto-janai"] 3 | language = "en" 4 | multilingual = false 5 | src = "src" 6 | title = "festivald v1.0.0" 7 | 8 | [build] 9 | build-dir = "docs" 10 | 11 | [output.html] 12 | default-theme = "ayu" 13 | preferred-dark-theme = "ayu" 14 | git-repository-url = "https://github.com/hinto-janai/festival" 15 | site-url = "/daemon/" 16 | -------------------------------------------------------------------------------- /daemon/mdbook/docs.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hinto-janai/festival/8d7e26d55e7677e3d38d6c51c51683830e9cbd61/daemon/mdbook/docs.zip -------------------------------------------------------------------------------- /daemon/mdbook/src/api-stability/api-stability.md: -------------------------------------------------------------------------------- 1 | # API Stability 2 | Some notes on what parts of `festivald`'s API can/cannot be relied upon. 3 | 4 | In general - **things may be added, but never removed.** 5 | 6 | If something is unstable, it will be [`marked`](marker.md) as such. 7 | 8 | Anything that feels like an API but isn't _explicitly_ marked in `festivald`'s documentation should be assumed to be [`🔴 Unstable`](marker.md). 9 | 10 | ## Breaking Changes 11 | Breaking changes to the [`stable`](marker.md) API may occur in 3 situations: 12 | 13 | 1. `festivald v2.0.0` release 14 | 2. There is a fundamental/security bug that must be fixed in `festivald` 15 | 3. There is a _difference_ between this documentation and the actual `festivald` input/output 16 | 17 | These will be noted in release notes if they ever occur. 18 | -------------------------------------------------------------------------------- /daemon/mdbook/src/api-stability/json-rpc.md: -------------------------------------------------------------------------------- 1 | # JSON-RPC 2 | [`JSON-RPC`](../json-rpc/json-rpc.md)-specific API stability edge cases. 3 | 4 | ### Naming 5 | All method names, parameter names, and field names are in `lower_case_snake_case`. 6 | 7 | This is [`🟢 Stable`](marker.md). 8 | 9 | ### Ordering 10 | The ordering of [non-stable](marker.md) output/object fields is [`🔴 Unstable`](marker.md). 11 | 12 | The ordering of [`🟢 Stable`](marker.md) output/object fields is [`🟢 Stable`](marker.md). 13 | 14 | Old `v1.0.0` JSON-RPC example: 15 | ```json 16 | // 🟡 Incomplete Response 17 | { 18 | "jsonrpc": "2.0", 19 | "result": { 20 | "field1": "Output field 1", 21 | "field2": "Output field 2" 22 | }, 23 | "id": 0, 24 | } 25 | 26 | // 🟢 Stable Response 27 | { 28 | "jsonrpc": "2.0", 29 | "result": { 30 | "field1": "Output field 1", // Will always be 1, then 2. 31 | "field2": "Output field 2" 32 | }, 33 | "id": 0, 34 | } 35 | ``` 36 | 37 | New `v1.1.0` JSON-RPC example: 38 | ```json 39 | // 🟡 Incomplete Response 40 | { 41 | "jsonrpc": "2.0", 42 | "result": { 43 | "field3": "Output field 3", // Ordering may 44 | "field1": "Output field 1", // shift around 45 | "field4": "Output field 4", // on incomplete 46 | "field2": "Output field 2" // methods. 47 | }, 48 | "id": 0, 49 | } 50 | 51 | // 🟢 Stable Response 52 | { 53 | "jsonrpc": "2.0", 54 | "result": { 55 | "field1": "Output field 1", // Still 1, 2. 56 | "field2": "Output field 2" 57 | }, 58 | "id": 0, 59 | } 60 | ``` 61 | -------------------------------------------------------------------------------- /daemon/mdbook/src/api-stability/marker.md: -------------------------------------------------------------------------------- 1 | # Marker 2 | In the documentation for all [`Objects`](../common-objects/common-objects.md), [`JSON-RPC` methods](../json-rpc/json-rpc.md), and [`REST` endpoints](../rest/rest.md) there will be a "marker" defining the stability of that API. It will be 1 of the 4 listed markers here. 3 | 4 | ## 🟢 Stable 5 | This marks that this API's input/output will never change, and can be relied upon. 6 | 7 | ## 🟡 Incomplete 8 | This marks that the output of this API may have additions in the future. 9 | 10 | The existing inputs/outputs **will not change**, however, additional output may appear. 11 | 12 | ## 🔴 Unstable 13 | This marks that this API may in the future: 14 | - Have additions to input/output 15 | - Have subtractions to input/output 16 | - Be renamed 17 | - Be completely removed 18 | 19 | It should not be relied across different `festivald` versions. 20 | 21 | ## ⚫️ Deprecated 22 | This marks that this API has been superseded by a better one. 23 | 24 | The old API will continue to exist, but it is recommended to use the newer one. 25 | 26 | -------------------------------------------------------------------------------- /daemon/mdbook/src/audio.md: -------------------------------------------------------------------------------- 1 | # Audio 2 | Miscellaneous parts of `festivald` related to audio. 3 | 4 | ### Audio Output Device 5 | `festivald` automatically connects to the "default" audio output device on the machine it is running on. 6 | 7 | If a connection failure occurs during playback, it will continue to play, frequently attempting to reconnect. 8 | 9 | If started without any audio output devices available, it will attempt to reconnect every 5 seconds, forever. 10 | 11 | Thus, reconnecting hardware/interfaces mid-playback should be fine. 12 | 13 | This behavior is [`🔴 Unstable`](api-stability/marker.md) and may change in the future. 14 | 15 | Ideally, an enumeration and customizable selection of all audio devices would be available. 16 | 17 | ### Audio State 18 | By default, `festivald` will save audio state upon clean [shutdown](json-rpc/daemon/daemon_shutdown.md) (or `CTRL+C/SIGINT`), and recover audio state upon startup. 19 | 20 | This means audio will start playing exactly where it left off, and the queue will be intact. 21 | 22 | This can be disabled with the [`recover_audio_state`](config.md) config option or the [`--disable-restore-audio-state`](command-line/command-line.md) command-line flag. 23 | 24 | ### Media Controls 25 | By default, `festivald` will hook into the OS's native media controls to display some metadata and allow for playback via the OS's interface or via keyboard play/pause/stop/etc signals. 26 | 27 | This can be disabled with the [`media_controls`](config.md) config option or the [`--disable-media-controls`](command-line/command-line.md) command-line flag. 28 | -------------------------------------------------------------------------------- /daemon/mdbook/src/authorization/authorization.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hinto-janai/festival/8d7e26d55e7677e3d38d6c51c51683830e9cbd61/daemon/mdbook/src/authorization/authorization.png -------------------------------------------------------------------------------- /daemon/mdbook/src/authorization/documentation.md: -------------------------------------------------------------------------------- 1 | # Documentation 2 | The [`no_auth_docs`](../config.md) config option or [`--no-auth-docs`](../command-line/command-line.md) command-line flag will allow documentation to be served without authorization, while still requiring authorization for everything else. 3 | 4 | ## Example 5 | `festivald.toml`: 6 | ```toml 7 | authorization = "user:pass" 8 | no_auth_docs = true 9 | ``` 10 | 11 | Unauthorized client: 12 | ```bash 13 | # Even though we didn't specify `-u user:pass`, 14 | # `festivald` will let us download/read docs. 15 | curl https://localhost:18425 16 | 17 | # BUT if `REST` requires authentication, this will not work. 18 | curl https://localhost:18425/rand/album 19 | ``` 20 | 21 | Authorized client: 22 | ```bash 23 | # This _does_ have authentication, 24 | # so it can do whatever it wants. 25 | curl https://localhost:18425/rand/album -u user:pass 26 | ``` 27 | -------------------------------------------------------------------------------- /daemon/mdbook/src/command-line/command-line.md: -------------------------------------------------------------------------------- 1 | # Command Line 2 | `festivald` takes in `--flags` for many purposes. 3 | 4 | Arguments passed to `festivald` will always take priority over the same [configuration](../config.md) options read from disk. 5 | 6 | `festivald` also has a `signal` sub-command. For example, to send a signal to a `festivald` running on the same local machine, you can run: 7 | ```bash 8 | ./festivald signal --play 9 | ``` 10 | All these "signal"-related `--flags` live in the [`signal`](signal.md) sub-command. 11 | 12 | ## Examples 13 | Here are some command-line usage examples. 14 | 15 | #### Start `festivald` on `http://localhost:18425` (by default) 16 | ```bash 17 | ./festivald 18 | ``` 19 | 20 | #### Print the PATH used by `festivald` 21 | ```bash 22 | ./festivald --path 23 | ``` 24 | 25 | #### Delete all data created/used by `festivald` 26 | ```bash 27 | ./festivald --delete 28 | ``` 29 | 30 | #### Set log level, disable everything except [`JSON-RPC`](../json-rpc/json-rpc.md), start `festivald` 31 | ```bash 32 | ./festivald --log-level DEBUG --disable-watch --disable-media-controls --disable-rest --disable-docs 33 | ``` 34 | -------------------------------------------------------------------------------- /daemon/mdbook/src/command-line/flags.md: -------------------------------------------------------------------------------- 1 | # Top-level flags 2 | ```plaintext 3 | {{#include ../../../CMD.txt}} 4 | ``` 5 | -------------------------------------------------------------------------------- /daemon/mdbook/src/command-line/signal.md: -------------------------------------------------------------------------------- 1 | # Sub-command: `signal` 2 | ```plaintext 3 | {{#include ../../../CMD_SIGNAL.txt}} 4 | ``` 5 | -------------------------------------------------------------------------------- /daemon/mdbook/src/common-objects/artist.md: -------------------------------------------------------------------------------- 1 | # Artist 2 | 3 | #### 🟡 Incomplete 4 | This API's output may have [additions](../api-stability/marker.md) in the future. 5 | 6 | --- 7 | 8 | A unique "artist" inside your [`Collection`](collection.md). 9 | 10 | Uniqueness is defined by the `Artist`'s `name`. 11 | 12 | `Artist` objects hold [keys](key.md) to all of their [`Album`](album.md)'s and [`Song`](song.md)'s, acting as a relation link. 13 | 14 | The keys inside `albums` is sorted by `Release date`. 15 | 16 | The keys inside `songs` is sorted by `Track + Disc order`. 17 | 18 | | Field | Type | Description | 19 | |---------|-------------------------------------------|-------------| 20 | | name | string | The `Artist`'s name 21 | | key | `Artist` key (unsigned integer) | The `Artist` key associated with this `Artist` 22 | | runtime | unsigned integer | The total runtime of all songs owned by this `Artist` in seconds 23 | | albums | array of `Album` keys (unsigned integers) | Keys to all `Album`'s owned by this `Artist`, in release order 24 | | songs | array of `Song` keys (unsigned integers) | Keys to all `Songs`'s owned by this `Artist`, in `Album` release order, then `Song` track order 25 | 26 | #### Example 27 | ```json 28 | { 29 | "name": "Artist Name", 30 | "key": 65, 31 | "runtime": 7583, 32 | "albums": [ 33 | 255, 34 | 263 35 | ], 36 | "songs": [ 37 | 2829, 38 | 2832, 39 | 2835, 40 | 2841 41 | ] 42 | } 43 | ``` 44 | -------------------------------------------------------------------------------- /daemon/mdbook/src/common-objects/entry.md: -------------------------------------------------------------------------------- 1 | # Entry 2 | 3 | #### 🟢 Stable 4 | This API is [stable](../api-stability/marker.md) since `festivald v1.0.0`. 5 | 6 | --- 7 | 8 | An "absolute" key to: 9 | - a particular [`Song`](song.md) 10 | - in a particular [`Album`](album.md) 11 | - by a particular [`Artist`](artist.md) 12 | 13 | This object contains all the relational data of a `Song`, along with its filesystem PATH. 14 | 15 | | Field | Type | Description | 16 | |------------|---------------------------------|-------------| 17 | | path | string (PATH) | The PATH of this `Song` on the filesystem `festivald` is running on 18 | | key_artist | `Artist` key (unsigned integer) | The `Artist` key 19 | | key_album | `Album` key (unsigned integer) | The `Album` key 20 | | key_song | `Song` key (unsigned integer) | This `Song`'s key 21 | | artist | string | The `Artist` name 22 | | album | string | The `Album` title 23 | | song | string | This `Song`'s title 24 | 25 | #### Example 26 | ```json 27 | { 28 | "path": "/home/hinto/Music/song.mp3", 29 | "key_artist": 0, 30 | "key_album": 0, 31 | "key_song": 0, 32 | "artist": "Artist Name", 33 | "album": "Album Title", 34 | "song": "Song Title" 35 | } 36 | ``` 37 | -------------------------------------------------------------------------------- /daemon/mdbook/src/common-objects/song.md: -------------------------------------------------------------------------------- 1 | # Song 2 | 3 | #### 🟡 Incomplete 4 | This API's output may have [additions](../api-stability/marker.md) in the future. 5 | 6 | --- 7 | 8 | A `Song` inside an [`Album`](album.md), owned by an [`Artist`](artist.md). 9 | 10 | `Song` objects hold [keys](key.md) to the `Album` it is in, acting as a relation link. 11 | 12 | | Field | Type | Description | 13 | |-------------|----------------------------------------|-------------| 14 | | title | string | The title of this `Song` 15 | | key | `Song` key (unsigned integer) | The `Song` key associated with this `Song` 16 | | album | `Album` key (unsigned integer) | The `Album` key of the `Album` this `Song` is from 17 | | runtime | unsigned integer | The total runtime of this `Song` in seconds 18 | | sample_rate | unsigned integer | The sample rate of this `Song` in hertz, e.g: `44100` 19 | | track | optional (maybe null) unsigned integer | Track number of this `Song`, `null` if not found 20 | | disc | optional (maybe null) unsigned integer | Disc number this `Song` belongs to, `null` if not found 21 | | mime | string | Audio MIME type of this `Song` 22 | | extension | string | File extension of this `Song` 23 | 24 | #### Example 25 | ```json 26 | { 27 | "title": "Song Title", 28 | "key": 401, 29 | "album": 42, 30 | "runtime": 132, 31 | "sample_rate": 44100, 32 | "track": 5, 33 | "disc": null, 34 | "mime": "audio/x-flac", 35 | "extension": "flac" 36 | } 37 | ``` 38 | -------------------------------------------------------------------------------- /daemon/mdbook/src/config.md: -------------------------------------------------------------------------------- 1 | # Config 2 | `festivald` reads and loads its configuration file `festivald.toml` on startup. 3 | 4 | It controls various behaviors of `festivald`. 5 | 6 | Exactly where this file is depends on the OS, more details in the [`Disk`](disk.md) section. 7 | 8 | [`Command Line`](command-line/command-line.md) flags will override any overlapping config values. 9 | 10 | ## `festivald.toml` 11 | This is the default configuration file `festivald` creates and uses. 12 | 13 | If `festivald` is started with no `--flags`, e.g: 14 | ```bash 15 | ./festivald 16 | ``` 17 | Then it will be equivalent to this config file. 18 | 19 | ```toml 20 | {{#include ../../config/festivald.toml}} 21 | ``` 22 | -------------------------------------------------------------------------------- /daemon/mdbook/src/json-rpc/collection/collection.md: -------------------------------------------------------------------------------- 1 | # Collection 2 | Methods related for creating and viewing various info about the [`Collection`](../../common-objects/collection.md). 3 | -------------------------------------------------------------------------------- /daemon/mdbook/src/json-rpc/collection/collection_brief_albums.md: -------------------------------------------------------------------------------- 1 | # collection_brief_albums 2 | 3 | #### 🟢 Stable 4 | This API is [stable](../../api-stability/marker.md) since `festivald v1.0.0`. 5 | 6 | --- 7 | 8 | Retrieve an array of every [`Album`](../../common-objects/album.md) title in the current [`Collection`](../../common-objects/collection.md). 9 | 10 | The returned array of `string`'s is in [`lexicographical`](https://en.wikipedia.org/wiki/Lexicographic_order) order. 11 | 12 | #### Inputs 13 | `None` 14 | 15 | #### Outputs 16 | | Field | Type | Description | 17 | |--------|---------------------|-------------| 18 | | len | unsigned integer | How many `Album`'s there are 19 | | albums | array of `string`'s | The title of every `Album` in the `Collection` 20 | 21 | #### Example Request 22 | ```bash 23 | festival-cli collection_brief_albums 24 | ``` 25 | ```bash 26 | curl http://localhost:18425 -d '{"jsonrpc":"2.0","id":0,"method":"collection_brief_albums"}' 27 | ``` 28 | 29 | #### Example Response 30 | ```json 31 | { 32 | "jsonrpc": "2.0", 33 | "result": { 34 | "len": 3, 35 | "albums": [ 36 | "aaa", 37 | "bbb", 38 | "ccc" 39 | ] 40 | }, 41 | "id": 0 42 | } 43 | ``` 44 | -------------------------------------------------------------------------------- /daemon/mdbook/src/json-rpc/collection/collection_brief_artists.md: -------------------------------------------------------------------------------- 1 | # collection_brief_artists 2 | 3 | #### 🟢 Stable 4 | This API is [stable](../../api-stability/marker.md) since `festivald v1.0.0`. 5 | 6 | --- 7 | 8 | Retrieve an array of every [`Artist`](../../common-objects/artist.md) name in the current [`Collection`](../../common-objects/collection.md). 9 | 10 | The returned array of `string`'s is in [`lexicographical`](https://en.wikipedia.org/wiki/Lexicographic_order) order. 11 | 12 | #### Inputs 13 | `None` 14 | 15 | #### Outputs 16 | | Field | Type | Description | 17 | |---------|---------------------|-------------| 18 | | len | unsigned integer | How many `Artist`'s there are 19 | | artists | array of `string`'s | The title of every `Artist` in the `Collection` 20 | 21 | #### Example Request 22 | ```bash 23 | festival-cli collection_brief_artists 24 | ``` 25 | ```bash 26 | curl http://localhost:18425 -d '{"jsonrpc":"2.0","id":0,"method":"collection_brief_artists"}' 27 | ``` 28 | 29 | #### Example Response 30 | ```json 31 | { 32 | "jsonrpc": "2.0", 33 | "result": { 34 | "len": 3, 35 | "artists": [ 36 | "aaa", 37 | "bbb", 38 | "ccc" 39 | ] 40 | }, 41 | "id": 0 42 | } 43 | ``` 44 | -------------------------------------------------------------------------------- /daemon/mdbook/src/json-rpc/collection/collection_brief_songs.md: -------------------------------------------------------------------------------- 1 | # collection_brief_songs 2 | 3 | #### 🟢 Stable 4 | This API is [stable](../../api-stability/marker.md) since `festivald v1.0.0`. 5 | 6 | --- 7 | 8 | Retrieve an array of every [`Song`](../../common-objects/song.md) title in the current [`Collection`](../../common-objects/collection.md). 9 | 10 | The returned array of `string`'s is in [`lexicographical`](https://en.wikipedia.org/wiki/Lexicographic_order) order. 11 | 12 | #### Inputs 13 | `None` 14 | 15 | #### Outputs 16 | | Field | Type | Description | 17 | |-------|---------------------|-------------| 18 | | len | unsigned integer | How many `Song`'s there are 19 | | songs | array of `string`'s | The title of every `Song` in the `Collection` 20 | 21 | #### Example Request 22 | ```bash 23 | festival-cli collection_brief_songs 24 | ``` 25 | ```bash 26 | curl http://localhost:18425 -d '{"jsonrpc":"2.0","id":0,"method":"collection_brief_songs"}' 27 | ``` 28 | 29 | #### Example Response 30 | ```json 31 | { 32 | "jsonrpc": "2.0", 33 | "result": { 34 | "len": 3, 35 | "songs": [ 36 | "aaa", 37 | "bbb", 38 | "ccc" 39 | ] 40 | }, 41 | "id": 0 42 | } 43 | ``` 44 | -------------------------------------------------------------------------------- /daemon/mdbook/src/json-rpc/collection/collection_full_artists.md: -------------------------------------------------------------------------------- 1 | # collection_full_artists 2 | 3 | #### 🟡 Incomplete 4 | This API's output may have [additions](../../api-stability/marker.md) in the future. 5 | 6 | --- 7 | 8 | Retrieve an array of every [`Artist`](../../common-objects/artist.md) object in the current [`Collection`](../../common-objects/collection.md). 9 | 10 | The returned array is in incrementing key order, as in: 11 | ``` 12 | Artist 0, 13 | Artist 1, 14 | Artist 2, 15 | 16 | [... etc ...] 17 | ``` 18 | 19 | #### Inputs 20 | `None` 21 | 22 | #### Outputs 23 | | Field | Type | Description | 24 | |---------|---------------------------|-------------| 25 | | len | unsigned integer | How many `Artist`'s there are 26 | | artists | array of `Artist` objects | Every `Artist` in the `Collection` 27 | 28 | #### Example Request 29 | ```bash 30 | festival-cli collection_full_artists 31 | ``` 32 | ```bash 33 | curl http://localhost:18425 -d '{"jsonrpc":"2.0","id":0,"method":"collection_full_artists"}' 34 | ``` 35 | 36 | #### Example Response 37 | ```json 38 | { 39 | "jsonrpc": "2.0", 40 | "result": { 41 | "len": 1, 42 | "artists": [ 43 | { 44 | "name": "Artist Name", 45 | "key": 0, 46 | "runtime": 3561, 47 | "albums": [ 48 | 0, 49 | 1 50 | ], 51 | "songs": [ 52 | 0, 53 | 1, 54 | 5, 55 | 20, 56 | 22, 57 | 23 58 | ] 59 | } 60 | ] 61 | }, 62 | "id": 0 63 | } 64 | ``` 65 | -------------------------------------------------------------------------------- /daemon/mdbook/src/json-rpc/collection/collection_perf.md: -------------------------------------------------------------------------------- 1 | # collection_perf 2 | 3 | #### 🟢 Stable 4 | This API is [stable](../../api-stability/marker.md) since `festivald v1.0.0`. 5 | 6 | --- 7 | 8 | View some performance stats about the latest [`Collection`](../../common-objects/collection.md) [reset](collection_new.md). 9 | 10 | #### Inputs 11 | 12 | `None` 13 | 14 | #### Outputs 15 | 16 | | Field | Type | Description | 17 | |-------|------------------|-------------| 18 | | bytes | unsigned integer | Total size of the `Collection` (`collection.bin` only, not audio/art) in bytes 19 | | user | float | `Collection` creation time in seconds, for the user 20 | | sys | float | `Collection` creation time in seconds, for the system `festivald` is running on 21 | 22 | #### Example Request 23 | ```bash 24 | festival-cli collection_perf 25 | ``` 26 | ```bash 27 | curl http://localhost:18425 -d '{"jsonrpc":"2.0","id":0,"method":"collection_perf"}' 28 | ``` 29 | 30 | #### Example Response 31 | ```json 32 | { 33 | "jsonrpc": "2.0", 34 | "result": { 35 | "bytes": 2554823, 36 | "user": 0.45682073, 37 | "sys": 0.48661286 38 | }, 39 | "id": 0 40 | } 41 | ``` 42 | -------------------------------------------------------------------------------- /daemon/mdbook/src/json-rpc/collection/collection_resource_size.md: -------------------------------------------------------------------------------- 1 | # collection_resource_size 2 | 3 | #### 🟢 Stable 4 | This API is [stable](../../api-stability/marker.md) since `festivald v1.0.0`. 5 | 6 | --- 7 | 8 | View the size of the current [`Collection`](../../common-objects/collection.md)'s _underlying_ resources (audio files and art). 9 | 10 | The output of this method reflects the live audio file size, not the one at the time of the `Collection` creation. For example, if an underlying audio file is changed: 11 | ``` 12 | my_song_file.flac (5MB) -> my_song_file.flac (33MB) 13 | ``` 14 | Then this method will reflect that change. 15 | 16 | However, `Art` is cached by `festivald` and only updated upon a `Collection` [reset](collection_new.md). 17 | 18 | #### Inputs 19 | `None` 20 | 21 | #### Outputs 22 | 23 | | Field | Type | Description | 24 | |-------|------------------|-------------| 25 | | audio | unsigned integer | Total size of the `Collection`'s underlying audio files in bytes 26 | | art | unsigned integer | Total size of the `Collection`'s underlying `Album` art in bytes 27 | 28 | #### Example Request 29 | ```bash 30 | festival-cli collection_resource_size 31 | ``` 32 | ```bash 33 | curl http://localhost:18425 -d '{"jsonrpc":"2.0","id":0,"method":"collection_resource_size"}' 34 | ``` 35 | 36 | #### Example Response 37 | ```json 38 | { 39 | "jsonrpc": "2.0", 40 | "result": { 41 | "audio": 315060491209, 42 | "art": 877030803 43 | }, 44 | "id": 0 45 | } 46 | ``` 47 | -------------------------------------------------------------------------------- /daemon/mdbook/src/json-rpc/current/current.md: -------------------------------------------------------------------------------- 1 | # Current 2 | Access the _currently_ set [`Song`](../../common-objects/song.md), its [`Album`](../../common-objects/album.md), or its [`Artist`](../../common-objects/artist.md), or in [`Entry`](../../common-objects/entry.md) form. 3 | 4 | If no `Song` is set, a JSON-RPC [`error`](../json-rpc.md#example-json-rpc-20-failed-response) will be returned. 5 | -------------------------------------------------------------------------------- /daemon/mdbook/src/json-rpc/current/current_album.md: -------------------------------------------------------------------------------- 1 | # current_album 2 | 3 | #### 🟡 Incomplete 4 | This API's output may have [additions](../../api-stability/marker.md) in the future. 5 | 6 | --- 7 | 8 | Access the [`Album`](../../common-objects/album.md) of the currently set [`Song`](../../common-objects/song.md). 9 | 10 | #### Inputs 11 | 12 | `None` 13 | 14 | #### Outputs 15 | 16 | | Field | Type | Description | 17 | |-------|----------------|-------------| 18 | | album | `Album` object | See [`Album`](../../common-objects/album.md) 19 | 20 | #### Example Request 21 | ```bash 22 | festival-cli current_album 23 | ``` 24 | ```bash 25 | curl http://localhost:18425 -d '{"jsonrpc":"2.0","id":0,"method":"current_album"}' 26 | ``` 27 | 28 | #### Example Response 29 | ```json 30 | { 31 | "jsonrpc": "2.0", 32 | "result": { 33 | "album": { 34 | "title": "RAINBOW", 35 | "key": 237, 36 | "artist": 65, 37 | "release": "????-??-??", 38 | "runtime": 1090, 39 | "song_count": 6, 40 | "songs": [ 41 | 2594, 42 | 2540, 43 | 2600, 44 | 2496, 45 | 2557, 46 | 2500 47 | ], 48 | "discs": 0, 49 | "art": 7753, 50 | "genre": null 51 | } 52 | }, 53 | "id": 0 54 | } 55 | ``` 56 | -------------------------------------------------------------------------------- /daemon/mdbook/src/json-rpc/current/current_artist.md: -------------------------------------------------------------------------------- 1 | # current_artist 2 | 3 | #### 🟡 Incomplete 4 | This API's output may have [additions](../../api-stability/marker.md) in the future. 5 | 6 | --- 7 | 8 | Access the [`Artist`](../../common-objects/artist.md) of the currently set [`Song`](../../common-objects/song.md). 9 | 10 | #### Inputs 11 | 12 | `None` 13 | 14 | #### Outputs 15 | 16 | | Field | Type | Description | 17 | |--------|-----------------|-------------| 18 | | artist | `Artist` object | See [`Artist`](../../common-objects/artist.md) 19 | 20 | #### Example Request 21 | ```bash 22 | festival-cli current_artist 23 | ``` 24 | ```bash 25 | curl http://localhost:18425 -d '{"jsonrpc":"2.0","id":0,"method":"current_artist"}' 26 | ``` 27 | 28 | #### Example Response 29 | ```json 30 | { 31 | "jsonrpc": "2.0", 32 | "result": { 33 | "artist": { 34 | "name": "Rex Orange County", 35 | "key": 65, 36 | "runtime": 7583, 37 | "albums": [ 38 | 237 39 | ], 40 | "songs": [ 41 | 2800, 42 | 2803, 43 | 2809 44 | ] 45 | } 46 | }, 47 | "id": 0 48 | } 49 | ``` 50 | -------------------------------------------------------------------------------- /daemon/mdbook/src/json-rpc/current/current_entry.md: -------------------------------------------------------------------------------- 1 | # current_entry 2 | 3 | #### 🟢 Stable 4 | This API is [stable](../../api-stability/marker.md) since `festivald v1.0.0`. 5 | 6 | --- 7 | 8 | Access the currently set [`Song`](../../common-objects/song.md), in [`Entry`](../../common-objects/entry.md) form. 9 | 10 | #### Inputs 11 | 12 | `None` 13 | 14 | #### Outputs 15 | 16 | | Field | Type | Description | 17 | |-------|----------------|-------------| 18 | | entry | `Entry` object | See [`Entry`](../../common-objects/entry.md) 19 | 20 | #### Example Request 21 | ```bash 22 | festival-cli current_entry 23 | ``` 24 | ```bash 25 | curl http://localhost:18425 -d '{"jsonrpc":"2.0","id":0,"method":"current_entry"}' 26 | ``` 27 | 28 | #### Example Response 29 | ```json 30 | { 31 | "jsonrpc": "2.0", 32 | "result": { 33 | "entry": { 34 | "path": "/home/hinto/Music/Rex Orange County/RAINBOW/SUNFLOWER.mp3", 35 | "key_artist": 65, 36 | "key_album": 237, 37 | "key_song": 2539, 38 | "artist": "Rex Orange County", 39 | "album": "RAINBOW", 40 | "song": "SUNFLOWER" 41 | } 42 | }, 43 | "id": 0 44 | } 45 | ``` 46 | -------------------------------------------------------------------------------- /daemon/mdbook/src/json-rpc/current/current_song.md: -------------------------------------------------------------------------------- 1 | # current_song 2 | 3 | #### 🟡 Incomplete 4 | This API's output may have [additions](../../api-stability/marker.md) in the future. 5 | 6 | --- 7 | 8 | Access the currently set [`Song`](../../common-objects/song.md). 9 | 10 | #### Inputs 11 | 12 | `None` 13 | 14 | #### Outputs 15 | 16 | | Field | Type | Description | 17 | |-------|---------------|-------------| 18 | | song | `Song` object | See [`Song`](../../common-objects/song.md) 19 | 20 | #### Example Request 21 | ```bash 22 | festival-cli current_song 23 | ``` 24 | ```bash 25 | curl http://localhost:18425 -d '{"jsonrpc":"2.0","id":0,"method":"current_song"}' 26 | ``` 27 | 28 | #### Example Response 29 | ```json 30 | { 31 | "jsonrpc": "2.0", 32 | "result": { 33 | "song": { 34 | "title": "SUNFLOWER", 35 | "key": 2594, 36 | "album": 237, 37 | "runtime": 252, 38 | "sample_rate": 44100, 39 | "track": 1, 40 | "disc": null, 41 | "mime": "audio/mpeg", 42 | "extension": "mp3" 43 | } 44 | }, 45 | "id": 0 46 | } 47 | ``` 48 | -------------------------------------------------------------------------------- /daemon/mdbook/src/json-rpc/daemon/daemon.md: -------------------------------------------------------------------------------- 1 | # Daemon 2 | These methods are for retrieving/modifying `festivald` in "system"-related ways. 3 | -------------------------------------------------------------------------------- /daemon/mdbook/src/json-rpc/daemon/daemon_no_auth_rest.md: -------------------------------------------------------------------------------- 1 | # daemon_no_auth_rest 2 | 3 | #### 🔴 Unstable 4 | This API's output may be [changed](../../api-stability/marker.md) in the future. 5 | 6 | --- 7 | 8 | Retrieve all [`REST` resources](../../rest/rest.md) this `festivald` allows [without authorization](../../authorization/rest.md), set in the [`no_auth_rest`](../../config.md) option 9 | 10 | The reason why this method is `🔴 Unstable` is because it will output _all_ `REST` resources, even `🔴 Unstable` ones, which may not exist in the future. 11 | 12 | Ordering of the resource names [should not be relied upon](../../api-stability/rest.md). 13 | 14 | #### Inputs 15 | `None` 16 | 17 | #### Outputs 18 | | Field | Type | Description | 19 | |-------|---------------------|-------------| 20 | | len | unsigned integer | Total amount of methods 21 | | rest | array of `string`'s | The names of all the `REST` resources this `festivald` allows without authorization 22 | 23 | #### Example Request 24 | ```bash 25 | festival-cli daemon_no_auth_rest 26 | ``` 27 | ```bash 28 | curl http://localhost:18425 -d '{"jsonrpc":"2.0","id":0,"method":"daemon_no_auth_rest"}' 29 | ``` 30 | 31 | #### Example Response 32 | ```json 33 | { 34 | "jsonrpc": "2.0", 35 | "result": { 36 | "len": 2, 37 | "rest": [ 38 | "song", 39 | "art" 40 | ] 41 | }, 42 | "id": 0 43 | } 44 | ``` 45 | -------------------------------------------------------------------------------- /daemon/mdbook/src/json-rpc/daemon/daemon_no_auth_rpc.md: -------------------------------------------------------------------------------- 1 | # daemon_no_auth_rpc 2 | 3 | #### 🔴 Unstable 4 | This API's output may be [changed](../../api-stability/marker.md) in the future. 5 | 6 | --- 7 | 8 | Retrieve all [`JSON-RPC` methods](../json-rpc.md) this `festivald` allows [without authorization](../../authorization/json-rpc.md), set in the [`no_auth_rpc`](../../config.md) option 9 | 10 | The reason why this method is `🔴 Unstable` is because it will output _all_ methods, even `🔴 Unstable` ones, which may not exist in the future. 11 | 12 | Ordering of the method names [should not be relied upon](../../api-stability/json-rpc.md). 13 | 14 | #### Inputs 15 | `None` 16 | 17 | #### Outputs 18 | | Field | Type | Description | 19 | |-------|---------------------|-------------| 20 | | len | unsigned integer | Total amount of methods 21 | | rpc | array of `string`'s | The names of all the methods this `festivald` allows without authorization 22 | 23 | #### Example Request 24 | ```bash 25 | festival-cli daemon_no_auth_rpc 26 | ``` 27 | ```bash 28 | curl http://localhost:18425 -d '{"jsonrpc":"2.0","id":0,"method":"daemon_no_auth_rpc"}' 29 | ``` 30 | 31 | #### Example Response 32 | ```json 33 | { 34 | "jsonrpc": "2.0", 35 | "result": { 36 | "len": 3, 37 | "rpc": [ 38 | "collection_brief_artists", 39 | "key_artist_entries", 40 | "search_album" 41 | ] 42 | }, 43 | "id": 0 44 | } 45 | ``` 46 | -------------------------------------------------------------------------------- /daemon/mdbook/src/json-rpc/daemon/daemon_remove_cache.md: -------------------------------------------------------------------------------- 1 | # daemon_remove_cache 2 | 3 | #### 🟢 Stable 4 | This API is [stable](../../api-stability/marker.md) since `festivald v1.0.0`. 5 | 6 | --- 7 | 8 | Remove all the cached [`REST resource`](../../rest/rest.md) files on disk. 9 | 10 | Warning: If there is a connection currently using this cache, it will error. 11 | 12 | #### Inputs 13 | `None` 14 | 15 | #### Outputs 16 | The output is an un-named array containing: 17 | 18 | | Field | Type | Description | 19 | |-------|------------------|-------------| 20 | | path | string (PATH) | A file that was removed 21 | | bytes | unsigned integer | How many bytes that file was 22 | 23 | #### Example Request 24 | ```bash 25 | festival-cli daemon_remove_cache 26 | ``` 27 | ```bash 28 | curl http://localhost:18425 -d '{"jsonrpc":"2.0","id":0,"method":"daemon_remove_cache"}' 29 | ``` 30 | 31 | #### Example Response 32 | ``` 33 | { 34 | "jsonrpc": "2.0", 35 | "result": [ 36 | { 37 | "path": "/home/hinto/.cache/festival/daemon/zip/artist/Artist Name.zip" 38 | "bytes": 345673 39 | }, 40 | { 41 | "path": "/home/hinto/.cache/festival/daemon/zip/album/Album Title.zip" 42 | "bytes": 345673 43 | } 44 | ], 45 | "id": 0 46 | } 47 | ``` 48 | -------------------------------------------------------------------------------- /daemon/mdbook/src/json-rpc/daemon/daemon_save.md: -------------------------------------------------------------------------------- 1 | # daemon_save 2 | 3 | #### 🟡 Incomplete 4 | This API's output may have [additions](../../api-stability/marker.md) in the future. 5 | 6 | --- 7 | 8 | Save `festivald` data to disk. 9 | 10 | Currently this saves: 11 | - [Audio state](../state/state_audio.md) 12 | - [Playlists](../../common-objects/playlist.md) 13 | 14 | The [`Collection`](../../common-objects/collection.md) is always saved automatically after creation. 15 | 16 | #### Inputs 17 | `None` 18 | 19 | #### Outputs 20 | `null` if everything went ok. 21 | 22 | #### Example Request 23 | ```bash 24 | festival-cli daemon_save 25 | ``` 26 | ```bash 27 | curl http://localhost:18425 -d '{"jsonrpc":"2.0","id":0,"method":"daemon_save"}' 28 | ``` 29 | 30 | #### Example Response 31 | ```json 32 | { 33 | "jsonrpc": "2.0", 34 | "result": null, // <--- everything went ok. 35 | "id": 0 36 | } 37 | ``` 38 | -------------------------------------------------------------------------------- /daemon/mdbook/src/json-rpc/daemon/daemon_seen_ips.md: -------------------------------------------------------------------------------- 1 | # daemon_seen_ips 2 | 3 | #### 🟢 Stable 4 | This API is [stable](../../api-stability/marker.md) since `festivald v1.0.0`. 5 | 6 | --- 7 | 8 | Retrieve an array of the IP addresses `festivald` has seen. 9 | 10 | #### Inputs 11 | 12 | `None` 13 | 14 | #### Outputs 15 | The output is an un-named array containing: 16 | 17 | | Field | Type | Description | 18 | |-----------|-----------------------|-------------| 19 | | ip | string (IPv4 address) | IP address `festivald` has seen 20 | | count | unsigned integer | How many connections this IP has made to `festivald` 21 | 22 | #### Example Request 23 | ```bash 24 | festival-cli daemon_seen_ips 25 | ``` 26 | ```bash 27 | curl http://localhost:18425 -d '{"jsonrpc":"2.0","id":0,"method":"daemon_seen_ips"}' 28 | ``` 29 | 30 | #### Example Response 31 | ``` 32 | { 33 | "jsonrpc": "2.0", 34 | "result": [ 35 | { 36 | "ip": "127.0.0.1", 37 | "count": 14 38 | }, 39 | { 40 | "ip": "192.168.2.1", 41 | "count": 2 42 | } 43 | ], 44 | "id": 0 45 | } 46 | ``` 47 | -------------------------------------------------------------------------------- /daemon/mdbook/src/json-rpc/daemon/daemon_shutdown.md: -------------------------------------------------------------------------------- 1 | # daemon_shutdown 2 | 3 | #### 🟡 Incomplete 4 | This API's output may have [additions](../../api-stability/marker.md) in the future. 5 | 6 | --- 7 | 8 | Send a shutdown signal to `festivald`. 9 | 10 | `festivald` will: 11 | - Reject future connections 12 | - Wait for a [`Collection`](../../common-objects/collection.md) [reset](../collection/collection_new.md) to finish if occurring 13 | - [Clean cache](../daemon/daemon_remove_cache.md) 14 | - [Save](../daemon/daemon_save.md) state to disk 15 | 16 | Then shutdown. 17 | 18 | #### Inputs 19 | `None` 20 | 21 | #### Outputs 22 | | Field | Type | Description | 23 | |---------------------|------------------|-------------| 24 | | uptime | unsigned integer | Uptime of `festivald` in seconds 25 | | uptime_readable | string | Uptime of `festivald` in human-readable time (60 is `1 minute`) 26 | | total_requests | unsigned integer | Total amount of requests `festivald` has received since starting 27 | | total_connections | unsigned integer | Total amount of connections `festivald` has received since starting 28 | 29 | #### Example Request 30 | ```bash 31 | festival-cli daemon_shutdown 32 | ``` 33 | ```bash 34 | curl http://localhost:18425 -d '{"jsonrpc":"2.0","id":0,"method":"daemon_shutdown"}' 35 | ``` 36 | 37 | #### Example Response 38 | ```json 39 | { 40 | "jsonrpc": "2.0", 41 | "result": { 42 | "uptime": 4, 43 | "uptime_readable": "4 seconds", 44 | "total_requests": 1, 45 | "total_connections": 1 46 | }, 47 | "id": "festival-cli" 48 | } 49 | ``` 50 | -------------------------------------------------------------------------------- /daemon/mdbook/src/json-rpc/key/key.md: -------------------------------------------------------------------------------- 1 | # Key 2 | Use [`key`](../../common-objects/key.md)'s to retrieve various [`Common Objects`](../../common-objects/common-objects.md). 3 | 4 | If the key is invalid, a JSON-RPC [`error`](../json-rpc.md#example-json-rpc-20-failed-response) will be returned. 5 | 6 | To use regular `string`'s as input instead (`Artist` name, `Album` title, `Song` title, etc), see [`Map`](../map/map.md). 7 | -------------------------------------------------------------------------------- /daemon/mdbook/src/json-rpc/key/key_album.md: -------------------------------------------------------------------------------- 1 | # key_album 2 | 3 | #### 🟡 Incomplete 4 | This API's output may have [additions](../../api-stability/marker.md) in the future. 5 | 6 | --- 7 | 8 | Input an `Album` [key](../../common-objects/key.md), retrieve an [`Album`](../../common-objects/album.md). 9 | 10 | #### Inputs 11 | 12 | | Field | Type | Description | 13 | |-------|------------------------------------------------|-------------| 14 | | key | `Album` key (unsigned integer) | See [`Key`](../../common-objects/key.md) 15 | 16 | #### Outputs 17 | 18 | | Field | Type | Description | 19 | |-------|----------------|-------------| 20 | | album | `Album` object | See [`Album`](../../common-objects/album.md) 21 | 22 | #### Example Request 23 | ```bash 24 | festival-cli key_album --key 237 25 | ``` 26 | ```bash 27 | curl http://localhost:18425 -d '{"jsonrpc":"2.0","id":0,"method":"key_album","params":{"key":237}}' 28 | ``` 29 | 30 | #### Example Response 31 | ```json 32 | { 33 | "jsonrpc": "2.0", 34 | "result": { 35 | "album": { 36 | "title": "RAINBOW", 37 | "key": 237, 38 | "artist": 65, 39 | "release": "????-??-??", 40 | "runtime": 1090, 41 | "song_count": 6, 42 | "songs": [ 43 | 2594, 44 | 2540, 45 | 2600, 46 | 2496, 47 | 2557, 48 | 2500 49 | ], 50 | "discs": 0, 51 | "art": 7753, 52 | "genre": null 53 | } 54 | }, 55 | "id": 0 56 | } 57 | ``` 58 | -------------------------------------------------------------------------------- /daemon/mdbook/src/json-rpc/key/key_album_artist.md: -------------------------------------------------------------------------------- 1 | # key_album_artist 2 | 3 | #### 🟡 Incomplete 4 | This API's output may have [additions](../../api-stability/marker.md) in the future. 5 | 6 | --- 7 | 8 | Input an [`Album`](../../common-objects/album.md) [key](../../common-objects/key.md), retrieve its [`Artist`](../../common-objects/artist.md). 9 | 10 | #### Inputs 11 | 12 | | Field | Type | Description | 13 | |-------|-----------------------------------------------|-------------| 14 | | key | `Album` key (unsigned integer) | See [`Key`](../../common-objects/key.md) 15 | 16 | #### Outputs 17 | 18 | | Field | Type | Description | 19 | |--------|-----------------|-------------| 20 | | artist | `Artist` object | See [`Artist`](../../common-objects/artist.md) 21 | 22 | #### Example Request 23 | ```bash 24 | festival-cli key_album_artist --key 237 25 | ``` 26 | ```bash 27 | curl http://localhost:18425 -d '{"jsonrpc":"2.0","id":0,"method":"key_album_artist","params":{"key":237}}' 28 | ``` 29 | 30 | #### Example Response 31 | ```json 32 | { 33 | "jsonrpc": "2.0", 34 | "result": { 35 | "artist": { 36 | "name": "Rex Orange County", 37 | "key": 65, 38 | "runtime": 7583, 39 | "albums": [ 40 | 237 41 | ], 42 | "songs": [ 43 | 2800, 44 | 2803, 45 | 2809 46 | ] 47 | } 48 | }, 49 | "id": 0 50 | } 51 | ``` 52 | -------------------------------------------------------------------------------- /daemon/mdbook/src/json-rpc/key/key_artist.md: -------------------------------------------------------------------------------- 1 | # key_artist 2 | 3 | #### 🟡 Incomplete 4 | This API's output may have [additions](../../api-stability/marker.md) in the future. 5 | 6 | --- 7 | 8 | Input an `Artist` [key](../../common-objects/key.md), retrieve an [`Artist`](../../common-objects/artist.md). 9 | 10 | #### Inputs 11 | 12 | | Field | Type | Description | 13 | |-------|------------------------------------------------|-------------| 14 | | key | `Artist` key (unsigned integer) | See [`Key`](../../common-objects/key.md) 15 | 16 | #### Outputs 17 | 18 | | Field | Type | Description | 19 | |--------|-----------------|-------------| 20 | | artist | `Artist` object | See [`Artist`](../../common-objects/artist.md) 21 | 22 | #### Example Request 23 | ```bash 24 | festival-cli key_artist --key 65 25 | ``` 26 | ```bash 27 | curl http://localhost:18425 -d '{"jsonrpc":"2.0","id":0,"method":"key_artist","params":{"key":65}}' 28 | ``` 29 | 30 | #### Example Response 31 | ```json 32 | { 33 | "jsonrpc": "2.0", 34 | "result": { 35 | "artist": { 36 | "name": "Rex Orange County", 37 | "key": 65, 38 | "runtime": 7583, 39 | "albums": [ 40 | 237 41 | ], 42 | "songs": [ 43 | 2800, 44 | 2803, 45 | 2809 46 | ] 47 | } 48 | }, 49 | "id": 0 50 | } 51 | ``` 52 | -------------------------------------------------------------------------------- /daemon/mdbook/src/json-rpc/key/key_entry.md: -------------------------------------------------------------------------------- 1 | # key_entry 2 | 3 | #### 🟢 Stable 4 | This API is [stable](../../api-stability/marker.md) since `festivald v1.0.0`. 5 | 6 | --- 7 | 8 | Input a `Song` [key](../../common-objects/key.md), retrieve an [`Entry`](../../common-objects/entry.md). 9 | 10 | #### Inputs 11 | 12 | | Field | Type | Description | 13 | |-------|------------------------------------------------|-------------| 14 | | key | `Song` key (unsigned integer) | See [`Key`](../key.md) 15 | 16 | #### Outputs 17 | 18 | | Field | Type | Description | 19 | |-------|----------------|-------------| 20 | | entry | `Entry` object | See [`Entry`](../../common-objects/entry.md) 21 | 22 | #### Example Request 23 | ```bash 24 | festival-cli key_entry --key 5151 25 | ``` 26 | ```bash 27 | curl http://localhost:18425 -d '{"jsonrpc":"2.0","id":0,"method":"key_entry","params":{"key":5151}}' 28 | ``` 29 | 30 | #### Example Response 31 | ```json 32 | { 33 | "jsonrpc": "2.0", 34 | "result": { 35 | "entry": { 36 | "path": "/home/hinto/Music/song.flac", 37 | "key_artist": 108, 38 | "key_album": 488, 39 | "key_song": 5151, 40 | "artist": "Artist Name", 41 | "album": "Album Title", 42 | "song": "Song Title" 43 | } 44 | }, 45 | "id": 0 46 | } 47 | ``` 48 | -------------------------------------------------------------------------------- /daemon/mdbook/src/json-rpc/key/key_song.md: -------------------------------------------------------------------------------- 1 | # key_song 2 | 3 | #### 🟡 Incomplete 4 | This API's output may have [additions](../../api-stability/marker.md) in the future. 5 | 6 | --- 7 | 8 | Input a `Song` [key](../../common-objects/key.md), retrieve a [`Song`](../../common-objects/song.md). 9 | 10 | #### Inputs 11 | 12 | | Field | Type | Description | 13 | |-------|------------------------------------------------|-------------| 14 | | key | `Song` key (unsigned integer) | See [`Key`](../key.md) 15 | 16 | #### Outputs 17 | 18 | | Field | Type | Description | 19 | |-------|---------------|-------------| 20 | | song | `Song` object | See [`Song`](../../common-objects/song.md) 21 | 22 | #### Example Request 23 | ```bash 24 | festival-cli key_song --key 2594 25 | ``` 26 | ```bash 27 | curl http://localhost:18425 -d '{"jsonrpc":"2.0","id":0,"method":"key_song","params":{"key":2594}}' 28 | ``` 29 | 30 | #### Example Response 31 | ```json 32 | { 33 | "jsonrpc": "2.0", 34 | "result": { 35 | "song": { 36 | "title": "SUNFLOWER", 37 | "key": 2594, 38 | "album": 237, 39 | "runtime": 252, 40 | "sample_rate": 44100, 41 | "track": 1, 42 | "disc": null, 43 | "mime": "audio/mpeg", 44 | "extension": "mp3" 45 | } 46 | }, 47 | "id": 0 48 | } 49 | ``` 50 | -------------------------------------------------------------------------------- /daemon/mdbook/src/json-rpc/key/key_song_album.md: -------------------------------------------------------------------------------- 1 | # key_song_album 2 | 3 | #### 🟡 Incomplete 4 | This API's output may have [additions](../../api-stability/marker.md) in the future. 5 | 6 | --- 7 | 8 | Input a [`Song`](../../common-objects/song.md) [key](../../common-objects/key.md), retrieve its [`Album`](../../common-objects/album.md). 9 | 10 | #### Inputs 11 | 12 | | Field | Type | Description | 13 | |-------|----------------------------------------------|-------------| 14 | | key | `Song` key (unsigned integer) | See [`Key`](../../common-objects/key.md) 15 | 16 | #### Outputs 17 | 18 | | Field | Type | Description | 19 | |-------|----------------|-------------| 20 | | album | `Album` object | See [`Album`](../../common-objects/album.md) 21 | 22 | #### Example Request 23 | ```bash 24 | festival-cli key_song_album --key 2540 25 | ``` 26 | ```bash 27 | curl http://localhost:18425 -d '{"jsonrpc":"2.0","id":0,"method":"key_song_album","params":{"key":2540}}' 28 | ``` 29 | 30 | #### Example Response 31 | ```json 32 | { 33 | "jsonrpc": "2.0", 34 | "result": { 35 | "album": { 36 | "title": "Pony", 37 | "key": 241, 38 | "artist": 62, 39 | "release": "2019-09-19", 40 | "runtime": 2032, 41 | "song_count": 10, 42 | "songs": [ 43 | 2540, 44 | 2545, 45 | 2548, 46 | 2553, 47 | 2558, 48 | 2567, 49 | 2573, 50 | 2578, 51 | 2581, 52 | 2587 53 | ], 54 | "discs": 0, 55 | "art": 190830, 56 | "genre": "Alternative & Indie" 57 | } 58 | }, 59 | "id": 0 60 | } 61 | ``` 62 | -------------------------------------------------------------------------------- /daemon/mdbook/src/json-rpc/key/key_song_artist.md: -------------------------------------------------------------------------------- 1 | # key_song_artist 2 | 3 | #### 🟡 Incomplete 4 | This API's output may have [additions](../../api-stability/marker.md) in the future. 5 | 6 | --- 7 | 8 | Input a [`Song`](../../common-objects/song.md) [key](../../common-objects/key.md), retrieve its [`Artist`](../../common-objects/artist.md). 9 | 10 | #### Inputs 11 | 12 | | Field | Type | Description | 13 | |-------|----------------------------------------------|-------------| 14 | | key | `Song` key (unsigned integer) | See [`Key`](../../common-objects/key.md) 15 | 16 | #### Outputs 17 | 18 | | Field | Type | Description | 19 | |--------|-----------------|-------------| 20 | | artist | `Artist` object | See [`Artist`](../../common-objects/artist.md) 21 | 22 | #### Example Request 23 | ```bash 24 | festival-cli key_song_artist --key 2800 25 | ``` 26 | ```bash 27 | curl http://localhost:18425 -d '{"jsonrpc":"2.0","id":0,"method":"key_song_artist","params":{"key":2800}}' 28 | ``` 29 | 30 | #### Example Response 31 | ```json 32 | { 33 | "jsonrpc": "2.0", 34 | "result": { 35 | "artist": { 36 | "name": "Rex Orange County", 37 | "key": 65, 38 | "runtime": 7583, 39 | "albums": [ 40 | 237 41 | ], 42 | "songs": [ 43 | 2800, 44 | 2803, 45 | 2809 46 | ] 47 | } 48 | }, 49 | "id": 0 50 | } 51 | ``` 52 | -------------------------------------------------------------------------------- /daemon/mdbook/src/json-rpc/map/map_album.md: -------------------------------------------------------------------------------- 1 | # map_album 2 | 3 | #### 🟡 Incomplete 4 | This API's output may have [additions](../../api-stability/marker.md) in the future. 5 | 6 | --- 7 | 8 | Input an [`Artist`](../../common-objects/artist.md) name and [`Album`](../../common-objects/album.md) title, retrieve an [`Album`](../../common-objects/album.md) object. 9 | 10 | #### Inputs 11 | 12 | | Field | Type | Description | 13 | |--------|--------|-------------| 14 | | artist | string | `Artist` name 15 | | album | string | `Album` title 16 | 17 | #### Outputs 18 | 19 | | Field | Type | Description | 20 | |-------|-----------------|-------------| 21 | | album | `Album` object | See [`Album`](../../common-objects/album.md) 22 | 23 | #### Example Request 24 | ```bash 25 | festival-cli map_album --artist "Rex Orange County" --album RAINBOW 26 | ``` 27 | ```bash 28 | curl http://localhost:18425 -d '{"jsonrpc":"2.0","id":0,"method":"map_album","params":{"artist":"Rex Orange County","album":"RAINBOW"}}' 29 | ``` 30 | 31 | #### Example Response 32 | ```json 33 | { 34 | "jsonrpc": "2.0", 35 | "result": { 36 | "album": { 37 | "title": "RAINBOW", 38 | "key": 237, 39 | "artist": 65, 40 | "release": "????-??-??", 41 | "runtime": 1090, 42 | "song_count": 6, 43 | "songs": [ 44 | 2594, 45 | 2540, 46 | 2600, 47 | 2496, 48 | 2557, 49 | 2500 50 | ], 51 | "discs": 0, 52 | "art": 7753, 53 | "genre": null 54 | } 55 | }, 56 | "id": 0 57 | } 58 | ``` 59 | -------------------------------------------------------------------------------- /daemon/mdbook/src/json-rpc/map/map_artist.md: -------------------------------------------------------------------------------- 1 | # map_artist 2 | 3 | #### 🟡 Incomplete 4 | This API's output may have [additions](../../api-stability/marker.md) in the future. 5 | 6 | --- 7 | 8 | Input an [`Artist`](../../common-objects/artist.md) name, retrieve an `Artist` object. 9 | 10 | #### Inputs 11 | 12 | | Field | Type | Description | 13 | |--------|--------|-------------| 14 | | artist | string | `Artist` name 15 | 16 | #### Outputs 17 | 18 | | Field | Type | Description | 19 | |--------|-----------------|-------------| 20 | | artist | `Artist` object | See [`Artist`](../../common-objects/artist.md) 21 | 22 | #### Example Request 23 | ```bash 24 | festival-cli map_artist --artist "Rex Orange County" 25 | ``` 26 | ```bash 27 | curl http://localhost:18425 -d '{"jsonrpc":"2.0","id":0,"method":"map_artist","params":{"artist":"Rex Orange County"}}' 28 | ``` 29 | 30 | #### Example Response 31 | ```json 32 | { 33 | "jsonrpc": "2.0", 34 | "result": { 35 | "artist": { 36 | "name": "Rex Orange County", 37 | "key": 65, 38 | "runtime": 7583, 39 | "albums": [ 40 | 237 41 | ], 42 | "songs": [ 43 | 2800, 44 | 2803, 45 | 2809 46 | ] 47 | } 48 | }, 49 | "id": 0 50 | } 51 | ``` 52 | -------------------------------------------------------------------------------- /daemon/mdbook/src/json-rpc/map/map_entry.md: -------------------------------------------------------------------------------- 1 | # map_entry 2 | 3 | #### 🟢 Stable 4 | This API is [stable](../../api-stability/marker.md) since `festivald v1.0.0`. 5 | 6 | --- 7 | 8 | Input an [`Artist`](../../common-objects/artist.md) name, [`Album`](../../common-objects/album.md) title, and [`Song`](../../common-objects/song.md) title, retrieve an [`Entry`](../../common-objects/entry.md) object. 9 | 10 | #### Inputs 11 | 12 | | Field | Type | Description | 13 | |--------|--------|-------------| 14 | | artist | string | `Artist` name 15 | | album | string | `Album` title 16 | | song | string | `Song` title 17 | 18 | #### Outputs 19 | 20 | | Field | Type | Description | 21 | |-------|----------------|-------------| 22 | | entry | `Entry` object | See [`Entry`](../../common-objects/entry.md) 23 | 24 | #### Example Request 25 | ```bash 26 | festival-cli map_entry --artist "Rex Orange County" --album RAINBOW --song SUNFLOWER 27 | ``` 28 | ```bash 29 | curl http://localhost:18425 -d '{"jsonrpc":"2.0","id":0,"method":"map_entry","params":{"artist":"Rex Orange County","album":"RAINBOW","song":"SUNFLOWER"}}' 30 | ``` 31 | 32 | #### Example Response 33 | ```json 34 | { 35 | "jsonrpc": "2.0", 36 | "result": { 37 | "entry": { 38 | "path": "/home/hinto/Music/Rex Orange County/RAINBOW/SUNFLOWER.mp3", 39 | "key_artist": 65, 40 | "key_album": 237, 41 | "key_song": 2539, 42 | "artist": "Rex Orange County", 43 | "album": "RAINBOW", 44 | "song": "SUNFLOWER" 45 | } 46 | }, 47 | "id": 0 48 | } 49 | ``` 50 | -------------------------------------------------------------------------------- /daemon/mdbook/src/json-rpc/map/map_song.md: -------------------------------------------------------------------------------- 1 | # map_song 2 | 3 | #### 🟡 Incomplete 4 | This API's output may have [additions](../../api-stability/marker.md) in the future. 5 | 6 | --- 7 | 8 | Input an [`Artist`](../../common-objects/artist.md) name, [`Album`](../../common-objects/album.md) title, and [`Song`](../../common-objects/song.md) title, retrieve a `Song` object. 9 | 10 | #### Inputs 11 | 12 | | Field | Type | Description | 13 | |--------|--------|-------------| 14 | | artist | string | `Artist` name 15 | | album | string | `Album` title 16 | | song | string | `Song` title 17 | 18 | #### Outputs 19 | 20 | | Field | Type | Description | 21 | |-------|---------------|-------------| 22 | | song | `Song` object | See [`Song`](../../common-objects/song.md) 23 | 24 | #### Example Request 25 | ```bash 26 | festival-cli map_song --artist "Rex Orange County" --album RAINBOW --song SUNFLOWER 27 | ``` 28 | ```bash 29 | curl http://localhost:18425 -d '{"jsonrpc":"2.0","id":0,"method":"map_song","params":{"artist":"Rex Orange County","album":"RAINBOW","song":"SUNFLOWER"}}' 30 | ``` 31 | 32 | #### Example Response 33 | ```json 34 | { 35 | "jsonrpc": "2.0", 36 | "result": { 37 | "song": { 38 | "title": "SUNFLOWER", 39 | "key": 2539, 40 | "album": 237, 41 | "runtime": 252, 42 | "sample_rate": 44100, 43 | "track": 1, 44 | "disc": null, 45 | "mime": "audio/mpeg", 46 | "extension": "mp3" 47 | } 48 | }, 49 | "id": 0 50 | } 51 | ``` 52 | -------------------------------------------------------------------------------- /daemon/mdbook/src/json-rpc/playback/back.md: -------------------------------------------------------------------------------- 1 | # back 2 | 3 | #### 🟡 Incomplete 4 | This API's output may have [additions](../../api-stability/marker.md) in the future. 5 | 6 | --- 7 | 8 | Go backwards a variable amount of [`Song`](../../common-objects/song.md)'s in the [queue](../queue/queue.md). 9 | 10 | This method ignores the [`previous_threshold`](../../config.md) config option, it will _always_ go back. 11 | 12 | #### Inputs 13 | | Field | Type | Description | 14 | |-----------|------------------|-------------| 15 | | back | unsigned integer | How many `Song`'s to go backwards. This will _not_ wrap around if we hit the 1st `Song` in the queue. 16 | 17 | #### Outputs 18 | `null` if everything went ok. 19 | 20 | #### Example Request 21 | ```bash 22 | festival-cli back --back 10 23 | ``` 24 | ```bash 25 | curl http://localhost:18425 -d '{"jsonrpc":"2.0","id":0,"method":"back","params":{"back":10}}' 26 | ``` 27 | 28 | #### Example Response 29 | ```json 30 | { 31 | "jsonrpc": "2.0", 32 | "result": null, // <--- everything went ok. 33 | "id": 0 34 | } 35 | ``` 36 | -------------------------------------------------------------------------------- /daemon/mdbook/src/json-rpc/playback/clear.md: -------------------------------------------------------------------------------- 1 | # clear 2 | 3 | #### 🟡 Incomplete 4 | This API's output may have [additions](../../api-stability/marker.md) in the future. 5 | 6 | --- 7 | 8 | Clear the [queue](../queue/queue.md). 9 | 10 | #### Inputs 11 | | Field | Type | Description | 12 | |----------|---------|-------------| 13 | | playback | boolean | If there is a [`Song`](../../common-objects/song.md) currently set and playing, should we continue playback? 14 | 15 | #### Outputs 16 | | Field | Type | Description | 17 | |-------|------------------|-------------| 18 | | len | unsigned integer | Amount of `Song`'s cleared from the queue 19 | 20 | #### Example Request 21 | ```bash 22 | festival-cli clear 23 | ``` 24 | ```bash 25 | curl http://localhost:18425 -d '{"jsonrpc":"2.0","id":0,"method":"clear","params":{"playback":false}}' 26 | ``` 27 | 28 | #### Example Response 29 | ```json 30 | { 31 | "jsonrpc": "2.0", 32 | "result": { 33 | "len": 207 34 | }, 35 | "id": 0 36 | } 37 | ``` 38 | -------------------------------------------------------------------------------- /daemon/mdbook/src/json-rpc/playback/next.md: -------------------------------------------------------------------------------- 1 | # next 2 | 3 | #### 🟡 Incomplete 4 | This API's output may have [additions](../../api-stability/marker.md) in the future. 5 | 6 | --- 7 | 8 | Skip to the next song in the [queue](../queue/queue.md). 9 | 10 | Ends the queue (or repeats if a [`repeat`](../playback/repeat.md) mode is on) if at the last song. 11 | 12 | Does nothing if the queue is empty. 13 | 14 | #### Inputs 15 | `None` 16 | 17 | #### Outputs 18 | `null` if everything went ok. 19 | 20 | #### Example Request 21 | ```bash 22 | festival-cli next 23 | ``` 24 | ```bash 25 | curl http://localhost:18425 -d '{"jsonrpc":"2.0","id":0,"method":"next"}' 26 | ``` 27 | 28 | #### Example Response 29 | ```json 30 | { 31 | "jsonrpc": "2.0", 32 | "result": null, // <--- everything went ok. 33 | "id": 0 34 | } 35 | ``` 36 | -------------------------------------------------------------------------------- /daemon/mdbook/src/json-rpc/playback/pause.md: -------------------------------------------------------------------------------- 1 | # pause 2 | 3 | #### 🟡 Incomplete 4 | This API's output may have [additions](../../api-stability/marker.md) in the future. 5 | 6 | --- 7 | 8 | Pause playback. 9 | 10 | #### Inputs 11 | `None` 12 | 13 | #### Outputs 14 | `null` if everything went ok. 15 | 16 | #### Example Request 17 | ```bash 18 | festival-cli pause 19 | ``` 20 | ```bash 21 | curl http://localhost:18425 -d '{"jsonrpc":"2.0","id":0,"method":"pause"}' 22 | ``` 23 | 24 | #### Example Response 25 | ```json 26 | { 27 | "jsonrpc": "2.0", 28 | "result": null, // <--- everything went ok. 29 | "id": 0 30 | } 31 | ``` 32 | -------------------------------------------------------------------------------- /daemon/mdbook/src/json-rpc/playback/play.md: -------------------------------------------------------------------------------- 1 | # play 2 | 3 | #### 🟡 Incomplete 4 | This API's output may have [additions](../../api-stability/marker.md) in the future. 5 | 6 | --- 7 | 8 | Start playback. 9 | 10 | #### Inputs 11 | `None` 12 | 13 | #### Outputs 14 | `null` if everything went ok. 15 | 16 | #### Example Request 17 | ```bash 18 | festival-cli play 19 | ``` 20 | ```bash 21 | curl http://localhost:18425 -d '{"jsonrpc":"2.0","id":0,"method":"play"}' 22 | ``` 23 | 24 | #### Example Response 25 | ```json 26 | { 27 | "jsonrpc": "2.0", 28 | "result": null, // <--- everything went ok. 29 | "id": 0 30 | } 31 | ``` 32 | -------------------------------------------------------------------------------- /daemon/mdbook/src/json-rpc/playback/playback.md: -------------------------------------------------------------------------------- 1 | # Playback Control 2 | Methods for controlling `festivald` audio playback, shuffling, seeking, etc. 3 | 4 | Most of the responses of these methods will be the [generic](../../common-objects/common-objects.md#generic-response) `null` response, indicating success. 5 | 6 | See [`Queue`](../queue/queue.md) for adding/removing `Song`'s from the queue. 7 | -------------------------------------------------------------------------------- /daemon/mdbook/src/json-rpc/playback/previous.md: -------------------------------------------------------------------------------- 1 | # previous 2 | 3 | #### 🟡 Incomplete 4 | This API's output may have [additions](../../api-stability/marker.md) in the future. 5 | 6 | --- 7 | 8 | Set the current [`Song`](../../common-objects/song.md) to the previous in the [queue](../queue/queue.md). 9 | 10 | If `threshold` is not specified, the [`previous_threshold`](../../config.md) config option will be used. 11 | 12 | #### Inputs 13 | | Field | Type | Description | 14 | |-----------|----------------------------------------|-------------| 15 | | threshold | optional (maybe-null) unsigned integer | If the current `Song` runtime (seconds) has passed this number, this method will reset the current `Song` instead of skipping backwards. Setting this to `0` will make this method always go to the previous `Song`. 16 | 17 | #### Outputs 18 | `null` if everything went ok. 19 | 20 | #### Example Request 21 | ```bash 22 | festival-cli previous --threshold 0 23 | ``` 24 | ```bash 25 | curl http://localhost:18425 -d '{"jsonrpc":"2.0","id":0,"method":"previous","params":{"threshold":0}}' 26 | ``` 27 | 28 | #### Example Response 29 | ```json 30 | { 31 | "jsonrpc": "2.0", 32 | "result": null, // <--- everything went ok. 33 | "id": 0 34 | } 35 | ``` 36 | -------------------------------------------------------------------------------- /daemon/mdbook/src/json-rpc/playback/repeat.md: -------------------------------------------------------------------------------- 1 | # repeat 2 | 3 | #### 🟢 Stable 4 | This API is [stable](../../api-stability/marker.md) since `festivald v1.0.0`. 5 | 6 | --- 7 | 8 | Set the playback repeat mode. 9 | 10 | #### Inputs 11 | | Field | Type | Description | 12 | |-------|---------------------------------------|-------------| 13 | | mode | string, one of `off`, `song`, `queue` | The repeat mode to set. `off` turns off repeating, `song` turns on [`Song`](../../common-objects/song.md) repeating, `queue` turns on [`queue`](../queue/queue.md) repeating. 14 | 15 | #### Outputs 16 | | Field | Type | Description | 17 | |----------|---------------------------------------|-------------| 18 | | previous | string, one of `off`, `song`, `queue` | What the repeat mode was set to previously 19 | | current | string, one of `off`, `song`, `queue` | What the repeat mode is now set at 20 | 21 | 22 | #### Example Request 23 | ```bash 24 | festival-cli repeat --mode off 25 | ``` 26 | ```bash 27 | curl http://localhost:18425 -d '{"jsonrpc":"2.0","id":0,"method":"repeat","params":{"mode":"off"}}' 28 | ``` 29 | 30 | #### Example Response 31 | ```json 32 | { 33 | "jsonrpc": "2.0", 34 | "result": { 35 | "previous": "off", 36 | "current": "song" 37 | }, 38 | "id": 0 39 | } 40 | ``` 41 | -------------------------------------------------------------------------------- /daemon/mdbook/src/json-rpc/playback/seek.md: -------------------------------------------------------------------------------- 1 | # seek 2 | 3 | #### 🟡 Incomplete 4 | This API's output may have [additions](../../api-stability/marker.md) in the future. 5 | 6 | --- 7 | 8 | Seek forwards/backwards or to an absolute second in the current [`Song`](../../common-objects/song.md). 9 | 10 | Seeking forwards pass the remaining `Song` length will finish the `Song`. 11 | 12 | Seeking to an absolute position longer than the `Song` length will also finish the `Song`. 13 | 14 | Seeking backwards more than already-played `Song` length will reset the `Song`. 15 | 16 | #### Inputs 17 | | Field | Type | Description | 18 | |--------|--------------------------------------------------|-------------| 19 | | kind | string, one of `forward`, `backward`, `absolute` | The "type" of seeking we should do. `forward` means advance the current `Song` by the provided `second`. `backward` means go back in the current `Song` by the provided `second`. `absolute` means skip to the exact `second` in the `Song`, e.g, to skip to the 1 minute mark in the current `Song`, you would use `absolute` + `60`. 20 | | second | unsigned integer | The `second` to seek forward/backwards/to. 21 | 22 | #### Outputs 23 | `null` if everything went ok. 24 | 25 | #### Example Request 26 | ```bash 27 | festival-cli seek --kind absolute --second 60 28 | ``` 29 | ```bash 30 | curl http://localhost:18425 -d '{"jsonrpc":"2.0","id":0,"method":"seek","params":{"kind":"absolute","second":60}}' 31 | ``` 32 | 33 | #### Example Response 34 | ```json 35 | { 36 | "jsonrpc": "2.0", 37 | "result": null, // <--- everything went ok. 38 | "id": 0 39 | } 40 | ``` 41 | -------------------------------------------------------------------------------- /daemon/mdbook/src/json-rpc/playback/shuffle.md: -------------------------------------------------------------------------------- 1 | # shuffle 2 | 3 | #### 🟡 Incomplete 4 | This API's output may have [additions](../../api-stability/marker.md) in the future. 5 | 6 | --- 7 | 8 | Shuffle the current [queue](../queue/queue.md), then set the current `Song` to the 1st `Song` in the queue. 9 | 10 | #### Inputs 11 | `None` 12 | 13 | #### Outputs 14 | `null` if everything went ok. 15 | 16 | #### Example Request 17 | ```bash 18 | festival-cli shuffle 19 | ``` 20 | ```bash 21 | curl http://localhost:18425 -d '{"jsonrpc":"2.0","id":0,"method":"shuffle"}' 22 | ``` 23 | 24 | #### Example Response 25 | ```json 26 | { 27 | "jsonrpc": "2.0", 28 | "result": null, // <--- everything went ok. 29 | "id": 0 30 | } 31 | ``` 32 | -------------------------------------------------------------------------------- /daemon/mdbook/src/json-rpc/playback/skip.md: -------------------------------------------------------------------------------- 1 | # skip 2 | 3 | #### 🟡 Incomplete 4 | This API's output may have [additions](../../api-stability/marker.md) in the future. 5 | 6 | --- 7 | 8 | Skip forward a variable amount of [`Song`](../../common-objects/song.md)'s in the [queue](../queue/queue.md). 9 | 10 | #### Inputs 11 | | Field | Type | Description | 12 | |-------|------------------|-------------| 13 | | skip | unsigned integer | How many `Song`'s to skip. If greater than the rest of the `Song`'s in the queue, the queue will end (unless a [`repeat`](../playback/repeat.md) mode is on). 14 | 15 | 16 | #### Outputs 17 | `null` if everything went ok. 18 | 19 | #### Example Request 20 | ```bash 21 | festival-cli skip --skip 3 22 | ``` 23 | ```bash 24 | curl http://localhost:18425 -d '{"jsonrpc":"2.0","id":0,"method":"skip","params":{"skip":3}}' 25 | ``` 26 | 27 | #### Example Response 28 | ```json 29 | { 30 | "jsonrpc": "2.0", 31 | "result": null, // <--- everything went ok. 32 | "id": 0 33 | } 34 | ``` 35 | -------------------------------------------------------------------------------- /daemon/mdbook/src/json-rpc/playback/stop.md: -------------------------------------------------------------------------------- 1 | # stop 2 | 3 | #### 🟡 Incomplete 4 | This API's output may have [additions](../../api-stability/marker.md) in the future. 5 | 6 | --- 7 | 8 | Clear the [queue](../queue/queue.md) and stop playback. 9 | 10 | #### Inputs 11 | `None` 12 | 13 | #### Outputs 14 | | Field | Type | Description | 15 | |-------|------------------|-------------| 16 | | len | unsigned integer | Amount of `Song`'s cleared from the queue 17 | 18 | #### Example Request 19 | ```bash 20 | festival-cli stop 21 | ``` 22 | ```bash 23 | curl http://localhost:18425 -d '{"jsonrpc":"2.0","id":0,"method":"stop"}' 24 | ``` 25 | 26 | #### Example Response 27 | ```json 28 | { 29 | "jsonrpc": "2.0", 30 | "result": { 31 | "len": 207 32 | }, 33 | "id": 0 34 | } 35 | ``` 36 | -------------------------------------------------------------------------------- /daemon/mdbook/src/json-rpc/playback/toggle.md: -------------------------------------------------------------------------------- 1 | # toggle 2 | 3 | #### 🟡 Incomplete 4 | This API's output may have [additions](../../api-stability/marker.md) in the future. 5 | 6 | --- 7 | 8 | Toggle playback. 9 | 10 | #### Inputs 11 | `None` 12 | 13 | #### Outputs 14 | `null` if everything went ok. 15 | 16 | #### Example Request 17 | ```bash 18 | festival-cli toggle 19 | ``` 20 | ```bash 21 | curl http://localhost:18425 -d '{"jsonrpc":"2.0","id":0,"method":"toggle"}' 22 | ``` 23 | 24 | #### Example Response 25 | ```json 26 | { 27 | "jsonrpc": "2.0", 28 | "result": null, // <--- everything went ok. 29 | "id": 0 30 | } 31 | ``` 32 | -------------------------------------------------------------------------------- /daemon/mdbook/src/json-rpc/playback/volume.md: -------------------------------------------------------------------------------- 1 | # volume 2 | 3 | #### 🟢 Stable 4 | This API is [stable](../../api-stability/marker.md) since `festivald v1.0.0`. 5 | 6 | --- 7 | 8 | Set the playback volume. 9 | 10 | #### Inputs 11 | | Field | Type | Description | 12 | |-----------|------------------|-------------| 13 | | volume | unsigned integer | The volume % to set. Must be in-between `0..100`. If greater than `100`, it will set the volume to `100`. 14 | 15 | #### Outputs 16 | | Field | Type | Description | 17 | |----------|------------------|-------------| 18 | | previous | unsigned integer | What the volume was set to previously 19 | | current | unsigned integer | What the volume is now set at 20 | 21 | #### Example Request 22 | ```bash 23 | festival-cli volume --volume 15 24 | ``` 25 | ```bash 26 | curl http://localhost:18425 -d '{"jsonrpc":"2.0","id":0,"method":"volume","params":{"volume":15}}' 27 | ``` 28 | 29 | #### Example Response 30 | ```json 31 | { 32 | "jsonrpc": "2.0", 33 | "result": { 34 | "previous": 0, 35 | "current": 15 36 | }, 37 | "id": "festival-cli" 38 | } 39 | ``` 40 | -------------------------------------------------------------------------------- /daemon/mdbook/src/json-rpc/playback/volume_down.md: -------------------------------------------------------------------------------- 1 | # volume_down 2 | 3 | #### 🟢 Stable 4 | This API is [stable](../../api-stability/marker.md) since `festivald v1.0.0`. 5 | 6 | --- 7 | 8 | Lower the playback volume. 9 | 10 | #### Inputs 11 | | Field | Type | Description | 12 | |-------|------------------|-------------| 13 | | down | unsigned integer | The number to lower the volume by. Must be in-between `0..100`. Volume cannot go lower than `0`. 14 | 15 | #### Outputs 16 | | Field | Type | Description | 17 | |----------|------------------|-------------| 18 | | previous | unsigned integer | What the volume was set to previously 19 | | current | unsigned integer | What the volume is now set at 20 | 21 | #### Example Request 22 | ```bash 23 | festival-cli volume_down --down 15 24 | ``` 25 | ```bash 26 | curl http://localhost:18425 -d '{"jsonrpc":"2.0","id":0,"method":"volume_down","params":{"down":15}}' 27 | ``` 28 | 29 | #### Example Response 30 | ```json 31 | { 32 | "jsonrpc": "2.0", 33 | "result": { 34 | "previous": 15, 35 | "current": 0 36 | }, 37 | "id": "festival-cli" 38 | } 39 | ``` 40 | -------------------------------------------------------------------------------- /daemon/mdbook/src/json-rpc/playback/volume_up.md: -------------------------------------------------------------------------------- 1 | # volume_up 2 | 3 | #### 🟢 Stable 4 | This API is [stable](../../api-stability/marker.md) since `festivald v1.0.0`. 5 | 6 | --- 7 | 8 | Raise the playback volume. 9 | 10 | #### Inputs 11 | | Field | Type | Description | 12 | |-------|------------------|-------------| 13 | | up | unsigned integer | The number to raise the volume by. Must be in-between `0..100`. If greater than `100`, it will set the volume to `100`. Volume cannot go higher than `100`. 14 | 15 | #### Outputs 16 | | Field | Type | Description | 17 | |----------|------------------|-------------| 18 | | previous | unsigned integer | What the volume was set to previously 19 | | current | unsigned integer | What the volume is now set at 20 | 21 | #### Example Request 22 | ```bash 23 | festival-cli volume_up --up 15 24 | ``` 25 | ```bash 26 | curl http://localhost:18425 -d '{"jsonrpc":"2.0","id":0,"method":"volume_up","params":{"up":15}}' 27 | ``` 28 | 29 | #### Example Response 30 | ```json 31 | { 32 | "jsonrpc": "2.0", 33 | "result": { 34 | "previous": 0, 35 | "current": 15 36 | }, 37 | "id": "festival-cli" 38 | } 39 | ``` 40 | -------------------------------------------------------------------------------- /daemon/mdbook/src/json-rpc/playlist/playlist.md: -------------------------------------------------------------------------------- 1 | # Playlist 2 | Methods related for creating/modifying/viewing various info about [`Playlist`](../../common-objects/playlist.md)'s. 3 | 4 | ### Append 5 | `Playlist` methods are similar to the [`Queue`](../queue/queue.md) methods, all `Playlist` methods involving appending requires an `append` type as input. 6 | 7 | These `append` types are the exact same as the `Queue`, see [`Queue/Append`](../queue/queue.md#append) for more info. 8 | -------------------------------------------------------------------------------- /daemon/mdbook/src/json-rpc/playlist/playlist_brief.md: -------------------------------------------------------------------------------- 1 | # playlist_brief 2 | 3 | #### 🟢 Stable 4 | This API is [stable](../../api-stability/marker.md) since `festivald v1.0.0`. 5 | 6 | --- 7 | 8 | Retrieve the names of all [`Playlist`](../../common-objects/playlist.md)'s. 9 | 10 | Names are sorted in [lexicographical order](https://en.wikipedia.org/wiki/Lexicographic_order). 11 | 12 | #### Inputs 13 | `None` 14 | 15 | #### Outputs 16 | | Field | Type | Description | 17 | |-----------|---------------------|-------------| 18 | | len | unsigned integer | How many `Playlist`'s there are 19 | | playlists | array of `string`'s | The names of all `Playlist`'s 20 | 21 | #### Example Request 22 | ```bash 23 | festival-cli playlist_brief 24 | ``` 25 | ```bash 26 | curl http://localhost:18425 -d '{"jsonrpc":"2.0","id":0,"method":"playlist_brief"}' 27 | ``` 28 | 29 | #### Example Response 30 | ```json 31 | { 32 | "jsonrpc": "2.0", 33 | "result": { 34 | "len": 3, 35 | "playlists": [ 36 | "Playlist A", 37 | "Playlist B", 38 | "Playlist C" 39 | ] 40 | }, 41 | "id": 0 42 | } 43 | ``` 44 | -------------------------------------------------------------------------------- /daemon/mdbook/src/json-rpc/playlist/playlist_get_index.md: -------------------------------------------------------------------------------- 1 | # playlist_get_index 2 | 3 | #### 🟢 Stable 4 | This API is [stable](../../api-stability/marker.md) since `festivald v1.0.0`. 5 | 6 | --- 7 | 8 | Retrieve a single [`Playlist Entry`](../../common-objects/playlist.md) from a [`Playlist`](../../common-objects/playlist.md), using its index number. 9 | 10 | This method errors if the `playlist` does not exist or if `index` is out-of-bounds. 11 | 12 | #### Inputs 13 | | Field | Type | Description | 14 | |----------|------------------|-------------| 15 | | playlist | string | The name of the `Playlist` 16 | | index | unsigned integer | The index of the entry in the playlist 17 | 18 | #### Outputs 19 | | Field | Type | Description | 20 | |-------|-------------------------|-------------| 21 | | entry | `Playlist Entry` object | The `Playlist Entry` that was at `index` 22 | 23 | #### Example Request 24 | Retrieve the 1st entry in playlist "Hello" 25 | ```bash 26 | festival-cli playlist_get_index --playlist Hello --index 0 27 | ``` 28 | ```bash 29 | curl http://localhost:18425 -d '{"jsonrpc":"2.0","id":0,"method":"playlist_get_index","params":{"playlist":"Hello","index":0}}' 30 | ``` 31 | 32 | #### Example Response 33 | ```json 34 | { 35 | "jsonrpc": "2.0", 36 | "result": { 37 | "entry": { 38 | "valid": { 39 | "key_artist": 65, 40 | "key_album": 237, 41 | "key_song": 2539, 42 | "artist": "Rex Orange County", 43 | "album": "RAINBOW", 44 | "song": "SUNFLOWER" 45 | } 46 | } 47 | }, 48 | "id": 0 49 | } 50 | ``` 51 | -------------------------------------------------------------------------------- /daemon/mdbook/src/json-rpc/playlist/playlist_remove_index.md: -------------------------------------------------------------------------------- 1 | # playlist_remove_index 2 | 3 | #### 🟢 Stable 4 | This API is [stable](../../api-stability/marker.md) since `festivald v1.0.0`. 5 | 6 | --- 7 | 8 | Remove a single [`Playlist Entry`](../../common-objects/playlist.md) from a [`Playlist`](../../common-objects/playlist.md), using its index number. 9 | 10 | This method errors if the `playlist` does not exist or if `index` is out-of-bounds. 11 | 12 | #### Inputs 13 | | Field | Type | Description | 14 | |----------|------------------|-------------| 15 | | playlist | string | The name of the `Playlist` 16 | | index | unsigned integer | The index of the entry in the playlist 17 | 18 | #### Outputs 19 | | Field | Type | Description | 20 | |-------|-------------------------|-------------| 21 | | entry | `Playlist Entry` object | The `Playlist Entry` that was removed 22 | 23 | #### Example Request 24 | Remove the 1st entry in playlist "Hello" 25 | ```bash 26 | festival-cli playlist_remove_index --playlist Hello --index 0 27 | ``` 28 | ```bash 29 | curl http://localhost:18425 -d '{"jsonrpc":"2.0","id":0,"method":"playlist_remove_index","params":{"playlist":"Hello","index":0}}' 30 | ``` 31 | 32 | #### Example Response 33 | ```json 34 | { 35 | "jsonrpc": "2.0", 36 | "result": { 37 | "entry": { 38 | "valid": { 39 | "key_artist": 65, 40 | "key_album": 237, 41 | "key_song": 2539, 42 | "artist": "Rex Orange County", 43 | "album": "RAINBOW", 44 | "song": "SUNFLOWER" 45 | } 46 | } 47 | }, 48 | "id": 0 49 | } 50 | ``` 51 | -------------------------------------------------------------------------------- /daemon/mdbook/src/json-rpc/queue/queue_set_index.md: -------------------------------------------------------------------------------- 1 | # queue_set_index 2 | 3 | #### 🟡 Incomplete 4 | This API's output may have [additions](../../api-stability/marker.md) in the future. 5 | 6 | --- 7 | 8 | Set the current `Song` to a queue index. 9 | 10 | If the `index` is out-of-bounds (queue has 10 songs, index is `10` or greater), this method will do nothing. 11 | 12 | #### Inputs 13 | | Field | Type | Description | 14 | |--------|------------------|-------------| 15 | | index | unsigned integer | An index in the queue (1st `Song` is index `0`, 2nd `Song` is index `1`, etc). The current state of the "queue" can be viewed with [`state_audio`](../state/state_audio.md). 16 | 17 | #### Outputs 18 | | Field | Type | Description | 19 | |---------------|------------------|-------------| 20 | | out_of_bounds | boolean | If the provided index was equal to or greater than the queue length. 21 | | index | unsigned integer | The provided `index` 22 | | queue_len | unsigned integer | The queue length 23 | 24 | #### Example Request 25 | Set the current `Song` to index `4`. 26 | ```bash 27 | festival-cli queue_set_index --index 123 28 | ``` 29 | ```bash 30 | curl http://localhost:18425 -d '{"jsonrpc":"2.0","id":0,"method":"queue_set_index","params":{"index":123}' 31 | ``` 32 | 33 | #### Example Response 34 | ```json 35 | { 36 | "jsonrpc": "2.0", 37 | "result": { 38 | "out_of_bounds": true, 39 | "index": 123, 40 | "queue_len": 0 41 | }, 42 | "id": 0 43 | } 44 | ``` 45 | -------------------------------------------------------------------------------- /daemon/mdbook/src/json-rpc/rand/rand.md: -------------------------------------------------------------------------------- 1 | # Rand 2 | Access a random [`Song`](../../common-objects/song.md), [`Album`](../../common-objects/album.md), or [`Artist`](../../common-objects/artist.md), or in [`Entry`](../../common-objects/entry.md) form. 3 | 4 | If the [`Collection`](../../common-objects/collection.md) is empty, a JSON-RPC [`error`](../json-rpc.md#example-json-rpc-20-failed-response) will be returned. 5 | 6 | Repeating is not prevented, so there is nothing preventing you from retrieving the same object multiple times in a row. 7 | -------------------------------------------------------------------------------- /daemon/mdbook/src/json-rpc/rand/rand_album.md: -------------------------------------------------------------------------------- 1 | # rand_album 2 | 3 | #### 🟡 Incomplete 4 | This API's output may have [additions](../../api-stability/marker.md) in the future. 5 | 6 | --- 7 | 8 | Access a random [`Album`](../../common-objects/album.md) in your [`Collection`](../../common-objects/collection.md). 9 | 10 | #### Inputs 11 | 12 | `None` 13 | 14 | #### Outputs 15 | 16 | | Field | Type | Description | 17 | |-------|----------------|-------------| 18 | | album | `Album` object | See [`Album`](../../common-objects/album.md) 19 | 20 | #### Example Request 21 | ```bash 22 | festival-cli rand_album 23 | ``` 24 | ```bash 25 | curl http://localhost:18425 -d '{"jsonrpc":"2.0","id":0,"method":"rand_album"}' 26 | ``` 27 | 28 | #### Example Response 29 | ```json 30 | { 31 | "jsonrpc": "2.0", 32 | "result": { 33 | "album": { 34 | "title": "hug", 35 | "key": 243, 36 | "artist": 65, 37 | "release": "2016", 38 | "runtime": 1276, 39 | "song_count": 5, 40 | "songs": [ 41 | 2541, 42 | 2546, 43 | 2550, 44 | 2554, 45 | 2556 46 | ], 47 | "discs": 0, 48 | "art": 220954, 49 | "genre": null 50 | } 51 | }, 52 | "id": 0 53 | } 54 | ``` 55 | -------------------------------------------------------------------------------- /daemon/mdbook/src/json-rpc/rand/rand_artist.md: -------------------------------------------------------------------------------- 1 | # rand_artist 2 | 3 | #### 🟡 Incomplete 4 | This API's output may have [additions](../../api-stability/marker.md) in the future. 5 | 6 | --- 7 | 8 | Access a random [`Artist`](../../common-objects/artist.md) in your [`Collection`](../../common-objects/collection.md). 9 | 10 | #### Inputs 11 | 12 | `None` 13 | 14 | #### Outputs 15 | 16 | | Field | Type | Description | 17 | |--------|-----------------|-------------| 18 | | artist | `Artist` object | See [`Artist`](../../common-objects/artist.md) 19 | 20 | #### Example Request 21 | ```bash 22 | festival-cli rand_artist 23 | ``` 24 | ```bash 25 | curl http://localhost:18425 -d '{"jsonrpc":"2.0","id":0,"method":"rand_artist"}' 26 | ``` 27 | 28 | #### Example Response 29 | ```json 30 | { 31 | "jsonrpc": "2.0", 32 | "result": { 33 | "artist": { 34 | "name": "カネコアヤノ", 35 | "key": 65, 36 | "runtime": 4709, 37 | "albums": [ 38 | 276, 39 | 256 40 | ], 41 | "songs": [ 42 | 2883, 43 | 2504, 44 | 2859, 45 | 2863, 46 | 2866, 47 | 2869, 48 | 2873, 49 | 2874, 50 | 2693, 51 | 2694 52 | ] 53 | } 54 | }, 55 | "id": 0 56 | } 57 | ``` 58 | -------------------------------------------------------------------------------- /daemon/mdbook/src/json-rpc/rand/rand_entry.md: -------------------------------------------------------------------------------- 1 | # rand_entry 2 | 3 | #### 🟢 Stable 4 | This API is [stable](../../api-stability/marker.md) since `festivald v1.0.0`. 5 | 6 | --- 7 | 8 | Access a random [`Entry`](../../common-objects/entry.md) in your [`Collection`](../../common-objects/collection.md). 9 | 10 | #### Inputs 11 | 12 | `None` 13 | 14 | #### Outputs 15 | 16 | | Field | Type | Description | 17 | |-------|----------------|-------------| 18 | | entry | `Entry` object | See [`Entry`](../../common-objects/entry.md) 19 | 20 | #### Example Request 21 | ```bash 22 | festival-cli rand_entry 23 | ``` 24 | ```bash 25 | curl http://localhost:18425 -d '{"jsonrpc":"2.0","id":0,"method":"rand_entry"}' 26 | ``` 27 | 28 | #### Example Response 29 | ```json 30 | { 31 | "jsonrpc": "2.0", 32 | "result": { 33 | "entry": { 34 | "path": "/home/hinto/Music/カネコアヤノ/祝祭/Home Alone.flac", 35 | "key_artist": 65, 36 | "key_album": 269, 37 | "key_song": 2825, 38 | "artist": "カネコアヤノ", 39 | "album": "祝祭", 40 | "song": "Home Alone" 41 | } 42 | }, 43 | "id": 0 44 | } 45 | ``` 46 | -------------------------------------------------------------------------------- /daemon/mdbook/src/json-rpc/rand/rand_song.md: -------------------------------------------------------------------------------- 1 | # rand_song 2 | 3 | #### 🟡 Incomplete 4 | This API's output may have [additions](../../api-stability/marker.md) in the future. 5 | 6 | --- 7 | 8 | Access a random [`Song`](../../common-objects/song.md) in your [`Collection`](../../common-objects/collection.md). 9 | 10 | #### Inputs 11 | 12 | `None` 13 | 14 | #### Outputs 15 | 16 | | Field | Type | Description | 17 | |-------|---------------|-------------| 18 | | song | `Song` object | See [`Song`](../../common-objects/song.md) 19 | 20 | #### Example Request 21 | ```bash 22 | festival-cli rand_song 23 | ``` 24 | ```bash 25 | curl http://localhost:18425 -d '{"jsonrpc":"2.0","id":0,"method":"rand_song"}' 26 | ``` 27 | 28 | #### Example Response 29 | ```json 30 | { 31 | "jsonrpc": "2.0", 32 | "result": { 33 | "song": { 34 | "title": "Home Alone", 35 | "key": 2825, 36 | "album": 269, 37 | "runtime": 182, 38 | "sample_rate": 48000, 39 | "track": 1, 40 | "disc": 1, 41 | "mime": "audio/x-flac", 42 | "extension": "flac" 43 | } 44 | }, 45 | "id": 0 46 | } 47 | ``` 48 | -------------------------------------------------------------------------------- /daemon/mdbook/src/json-rpc/search/index.md: -------------------------------------------------------------------------------- 1 | # Search 2 | Fuzzy similarity searches for [`Song`](../../common-objects/song.md)'s, [`Album`](../../common-objects/album.md)'s, [`Artist`](../../common-objects/artist.md)'s, and [`Entry`](../../common-objects/entry.md)'s. 3 | 4 | In general: input a `string`, receive some objects that are similar to the input. 5 | 6 | If you know the _exact_ `string` for a `Song`, `Album`, or `Artist`, consider using the [`Map`](../map/map.md) methods instead for a direct lookup. 7 | 8 | If you know the _exact_ [`key`](../../common-objects/key.md), use the [`Key`](../key/key.md) methods instead. 9 | 10 | ### Kind 11 | These are different "kinds" of searches you can do, affecting the result output. 12 | 13 | Each `search` method requires one of these as input. 14 | 15 | All of these return objects sorted from most-to-least similar. 16 | 17 | | Kind | Description | 18 | |---------|-------------| 19 | | `all` | ALL objects will be returned 20 | | `sim60` | Only objects `60%` similar 21 | | `sim70` | Only objects `70%` similar 22 | | `sim80` | Only objects `80%` similar 23 | | `top25` | Only the top 25 results 24 | | `top5` | Only the top 5 results 25 | | `top1` | Only the top result 26 | 27 | ### Warning 28 | The output array may return empty given no matches or an empty [`Collection`](../../common-objects/collection.md): 29 | ```json 30 | { 31 | "jsonrpc": "2.0", 32 | "result": { 33 | "songs": [] 34 | }, 35 | "id": 0 36 | } 37 | ``` 38 | -------------------------------------------------------------------------------- /daemon/mdbook/src/json-rpc/search/search_artist.md: -------------------------------------------------------------------------------- 1 | # search_artist 2 | 3 | #### 🟡 Incomplete 4 | This API's output may have [additions](../../api-stability/marker.md) in the future. 5 | 6 | --- 7 | 8 | Input a `string`, retrieve an array of [`Artist`](../../common-objects/artist.md)'s, sorted by how similar their names are to the input. 9 | 10 | #### Inputs 11 | 12 | | Field | Type | Description | 13 | |-------|--------------------------------------------------------------------------|-------------| 14 | | input | string | The string to match against, to use as input 15 | | kind | string, one of `all`, `sim60`, `sim70`, `sim80`, `top25`, `top5`, `top1` | See [`Search/Kind`](../search/index.md#Kind) 16 | 17 | #### Outputs 18 | 19 | | Field | Type | Description | 20 | |---------|---------------------------|-------------| 21 | | artists | array of `Artist` objects | An array of `Artist` objects, sorted by most similar name first 22 | 23 | #### Example Request 24 | ```bash 25 | festival-cli search_artist --input twice --kind sim70 26 | ``` 27 | ```bash 28 | curl http://localhost:18425 -d '{"jsonrpc":"2.0","id":0,"method":"search_artist","params":{"input":"twice","kind":"sim70"}}' 29 | ``` 30 | 31 | #### Example Response 32 | ```json 33 | { 34 | "jsonrpc": "2.0", 35 | "result": { 36 | "artists": [ 37 | { 38 | "name": "TWICE", 39 | "key": 106, 40 | "runtime": 343, 41 | "albums": [ 42 | 598 43 | ], 44 | "songs": [ 45 | 5411 46 | ] 47 | } 48 | ] 49 | }, 50 | "id": 0 51 | } 52 | ``` 53 | -------------------------------------------------------------------------------- /daemon/mdbook/src/json-rpc/state/state.md: -------------------------------------------------------------------------------- 1 | # State Retrieval 2 | These methods are for retrieving state (mostly audio state), and do not mutate any part of the system. 3 | -------------------------------------------------------------------------------- /daemon/mdbook/src/json-rpc/state/state_playing.md: -------------------------------------------------------------------------------- 1 | # state_playing 2 | 3 | #### 🟢 Stable 4 | This API is [stable](../../api-stability/marker.md) since `festivald v1.0.0`. 5 | 6 | --- 7 | 8 | Retrieve playback status. 9 | 10 | #### Inputs 11 | 12 | `None` 13 | 14 | #### Outputs 15 | 16 | | Field | Type | Description | 17 | |---------|---------|-------------| 18 | | playing | boolean | Are we currently playing? 19 | 20 | 21 | #### Example Request 22 | ```bash 23 | festival-cli state_playing 24 | ``` 25 | ```bash 26 | curl http://localhost:18425 -d '{"jsonrpc":"2.0","id":0,"method":"state_playing"}' 27 | ``` 28 | 29 | #### Example Response 30 | ```json 31 | { 32 | "jsonrpc": "2.0", 33 | "result": { 34 | "playing": true 35 | }, 36 | "id": 0 37 | } 38 | ``` 39 | -------------------------------------------------------------------------------- /daemon/mdbook/src/json-rpc/state/state_queue_key.md: -------------------------------------------------------------------------------- 1 | # state_queue_key 2 | 3 | #### 🟢 Stable 4 | This API is [stable](../../api-stability/marker.md) since `festivald v1.0.0`. 5 | 6 | --- 7 | 8 | Retrieve state about the queue. 9 | 10 | This returns the queue as [`Song`](../../common-objects/song.md) [`key`](../../common-objects/key.md)'s. 11 | 12 | Returned `key`'s are in order of what will be played next. 13 | 14 | #### Inputs 15 | 16 | `None` 17 | 18 | #### Outputs 19 | 20 | | Field | Type | Description | 21 | |-------|------------------------------------------|-------------| 22 | | len | unsigned integer | Length of the queue 23 | | keys | array of `Song` keys (unsigned integers) | Array of the queue's `Song`'s as keys 24 | 25 | #### Example Request 26 | ```bash 27 | festival-cli state_queue_key 28 | ``` 29 | ```bash 30 | curl http://localhost:18425 -d '{"jsonrpc":"2.0","id":0,"method":"state_queue_key"}' 31 | ``` 32 | 33 | #### Example Response 34 | ```json 35 | { 36 | "jsonrpc": "2.0", 37 | "result": { 38 | "len": 5, 39 | "keys": [ 40 | 2896, 41 | 2899, 42 | 2904, 43 | 2906, 44 | 2911 45 | ] 46 | }, 47 | "id": 0 48 | } 49 | ``` 50 | -------------------------------------------------------------------------------- /daemon/mdbook/src/json-rpc/state/state_queue_song.md: -------------------------------------------------------------------------------- 1 | # state_queue_song 2 | 3 | #### 🟡 Incomplete 4 | This API's output may have [additions](../../api-stability/marker.md) in the future. 5 | 6 | --- 7 | 8 | Retrieve state about the queue. 9 | 10 | This returns the queue as full [`Song`](../../common-objects/song.md) objects. 11 | 12 | Returned `Song`'s are in order of what will be played next. 13 | 14 | #### Inputs 15 | 16 | `None` 17 | 18 | #### Outputs 19 | 20 | | Field | Type | Description | 21 | |-------|-------------------------|-------------| 22 | | len | unsigned integer | Length of the queue 23 | | songs | array of `Song` objects | Array of the queue's `Song`'s 24 | 25 | #### Example Request 26 | ```bash 27 | festival-cli state_queue_song 28 | ``` 29 | ```bash 30 | curl http://localhost:18425 -d '{"jsonrpc":"2.0","id":0,"method":"state_queue_song"}' 31 | ``` 32 | 33 | #### Example Response 34 | ```json 35 | { 36 | "jsonrpc": "2.0", 37 | "result": { 38 | "len": 2, 39 | "songs": [ 40 | { 41 | "title": "SUNFLOWER", 42 | "key": 2539, 43 | "album": 237, 44 | "runtime": 252, 45 | "sample_rate": 44100, 46 | "track": 1, 47 | "disc": null, 48 | "mime": "audio/mpeg", 49 | "extension": "mp3" 50 | }, 51 | { 52 | "title": "BEST FRIEND", 53 | "key": 2517, 54 | "album": 237, 55 | "runtime": 262, 56 | "sample_rate": 44100, 57 | "track": 2, 58 | "disc": null, 59 | "mime": "audio/mpeg", 60 | "extension": "mp3" 61 | } 62 | ] 63 | }, 64 | "id": 0 65 | } 66 | ``` 67 | -------------------------------------------------------------------------------- /daemon/mdbook/src/json-rpc/state/state_repeat.md: -------------------------------------------------------------------------------- 1 | # state_repeat 2 | 3 | #### 🟢 Stable 4 | This API is [stable](../../api-stability/marker.md) since `festivald v1.0.0`. 5 | 6 | --- 7 | 8 | Retrieve the currently set [`repeat`](../playback/repeat.md) mode. 9 | 10 | #### Inputs 11 | 12 | `None` 13 | 14 | #### Outputs 15 | 16 | | Field | Type | Description | 17 | |-------|---------------------------------------|-------------| 18 | | mode | string, one of `off`, `song`, `queue` | The currently set repeat mode. `off` mean repeat is off, `song` means [`Song`](../../common-objects/song.md) repeating, `queue` means [`queue`](../queue/queue.md) repeating. 19 | 20 | #### Example Request 21 | ```bash 22 | festival-cli state_repeat 23 | ``` 24 | ```bash 25 | curl http://localhost:18425 -d '{"jsonrpc":"2.0","id":0,"method":"state_repeat"}' 26 | ``` 27 | 28 | #### Example Response 29 | ```json 30 | { 31 | "jsonrpc": "2.0", 32 | "result": { 33 | "mode": "off" 34 | }, 35 | "id": 0 36 | } 37 | ``` 38 | -------------------------------------------------------------------------------- /daemon/mdbook/src/json-rpc/state/state_runtime.md: -------------------------------------------------------------------------------- 1 | # state_runtime 2 | 3 | #### 🟢 Stable 4 | This API is [stable](../../api-stability/marker.md) since `festivald v1.0.0`. 5 | 6 | --- 7 | 8 | Retrieve the elapsed runtime & total runtime of the currently set [`Song`](../../common-objects/key.md). 9 | 10 | This will return `0` values (`0:00`) if there is no `Song` set. 11 | 12 | #### Inputs 13 | 14 | `None` 15 | 16 | #### Outputs 17 | 18 | | Field | Type | Description | 19 | |------------------|------------------|-------------| 20 | | elapsed | unsigned integer | Elapsed runtime of current `Song` in seconds 21 | | runtime | unsigned integer | Total runtime of current `Song` in seconds 22 | | elapsed_readable | string | Human-readable version of `elapsed` (`5` would be `0:05`) 23 | | runtime_readable | string | Human-readable version of `runtime` (`60` would be `1:00`) 24 | 25 | #### Example Request 26 | ```bash 27 | festival-cli state_runtime 28 | ``` 29 | ```bash 30 | curl http://localhost:18425 -d '{"jsonrpc":"2.0","id":0,"method":"state_runtime"}' 31 | ``` 32 | 33 | #### Example Response 1 34 | Song is set: 35 | ```json 36 | { 37 | "jsonrpc": "2.0", 38 | "result": { 39 | "elapsed": 12, 40 | "runtime": 125, 41 | "elapsed_readable": "0:12", 42 | "runtime_readable": "2:05" 43 | }, 44 | "id": 0 45 | } 46 | ``` 47 | 48 | #### Example Response 2 49 | Song is not set: 50 | ```json 51 | { 52 | "jsonrpc": "2.0", 53 | "result": { 54 | "elapsed": 0, 55 | "runtime": 0, 56 | "elapsed_readable": "0:00", 57 | "runtime_readable": "0:00" 58 | }, 59 | "id": 0 60 | } 61 | ``` 62 | -------------------------------------------------------------------------------- /daemon/mdbook/src/json-rpc/state/state_volume.md: -------------------------------------------------------------------------------- 1 | # state_volume 2 | 3 | #### 🟢 Stable 4 | This API is [stable](../../api-stability/marker.md) since `festivald v1.0.0`. 5 | 6 | --- 7 | 8 | Retrieve the current volume level. 9 | 10 | #### Inputs 11 | 12 | `None` 13 | 14 | #### Outputs 15 | 16 | | Field | Type | Description | 17 | |-----------|-----------------------------------------------------|-------------| 18 | | volume | unsigned integer in between `0..100` | The current volume level 19 | 20 | 21 | #### Example Request 22 | ```bash 23 | festival-cli state_volume 24 | ``` 25 | ```bash 26 | curl http://localhost:18425 -d '{"jsonrpc":"2.0","id":0,"method":"state_volume"}' 27 | ``` 28 | 29 | #### Example Response 30 | ```json 31 | { 32 | "jsonrpc": "2.0", 33 | "result": { 34 | "volume": 25 35 | }, 36 | "id": 0 37 | } 38 | ``` 39 | -------------------------------------------------------------------------------- /daemon/mdbook/src/rest/art/album.md: -------------------------------------------------------------------------------- 1 | # /art/$ARTIST_NAME/$ALBUM_TITLE 2 | 3 | #### 🟢 Stable 4 | This API is [stable](../../api-stability/marker.md) since `festivald v1.0.0`. 5 | 6 | --- 7 | 8 | Download an `Album`'s art, using the [`Artist`](../../common-objects/artist.md)'s name, and [`Album`](../../common-objects/album.md) title 9 | 10 | #### Input 11 | | Input | Type | 12 | |---------------|--------| 13 | | `Artist` name | string | 14 | | `Album` title | string | 15 | 16 | #### Output 17 | Album art in original format. 18 | 19 | #### Example Input 20 | ```http 21 | http://localhost:18425/art/Artist Name/Album Title 22 | ``` 23 | 24 | #### Example Output 25 | ```plaintext 26 | Art - Artist Name - Album Title.png 27 | ``` 28 | -------------------------------------------------------------------------------- /daemon/mdbook/src/rest/art/art.md: -------------------------------------------------------------------------------- 1 | # /art 2 | This is the same as the [`/map`](../map/map.md) endpoint, but only for downloading `Album` art. 3 | -------------------------------------------------------------------------------- /daemon/mdbook/src/rest/art/artist.md: -------------------------------------------------------------------------------- 1 | # /art/$ARTIST_NAME 2 | 3 | #### 🟢 Stable 4 | This API is [stable](../../api-stability/marker.md) since `festivald v1.0.0`. 5 | 6 | --- 7 | 8 | Download all the `Album` art owned by this `Artist`, using the [`Artist`](../../common-objects/artist.md)'s name. 9 | 10 | #### Input 11 | | Input | Type | 12 | |---------------|--------| 13 | | `Artist` name | string | 14 | 15 | #### Output 16 | `ZIP` of all the art owned by this `Artist`. 17 | 18 | #### Example Input 19 | ```http 20 | http://localhost:18425/art/Artist Name 21 | ``` 22 | 23 | #### Example Output 24 | File: 25 | ```plaintext 26 | Art - Artist Name.zip 27 | ``` 28 | 29 | Extracted: 30 | ```plaintext 31 | Art - Artist Name/ 32 | ├─ Album Name 1.jpg 33 | │─ Album Name 2.png 34 | ├─ Album Name 3.webp 35 | ``` 36 | -------------------------------------------------------------------------------- /daemon/mdbook/src/rest/current/album.md: -------------------------------------------------------------------------------- 1 | # /current/album 2 | 3 | #### 🟢 Stable 4 | This API is [stable](../../api-stability/marker.md) since `festivald v1.0.0`. 5 | 6 | --- 7 | 8 | Download the `Album` of the currently set `Song` (including art if found). 9 | 10 | #### Input 11 | `None` 12 | 13 | #### Output 14 | Album in archive (including art if found). 15 | 16 | #### Example Input 17 | ```http 18 | http://localhost:18425/current/album 19 | ``` 20 | 21 | #### Example Output 22 | File: 23 | ```plaintext 24 | Artist Name - Album Title.zip 25 | ``` 26 | 27 | Extracted: 28 | ```plaintext 29 | Artist Name - Album Title/ 30 | ├─ Album Name.jpg 31 | ├─ Song Name 1.mp3 32 | ├─ Song Name 2.flac 33 | ├─ Song Name 3.ogg 34 | ``` 35 | -------------------------------------------------------------------------------- /daemon/mdbook/src/rest/current/art.md: -------------------------------------------------------------------------------- 1 | # /current/art 2 | 3 | #### 🟢 Stable 4 | This API is [stable](../../api-stability/marker.md) since `festivald v1.0.0`. 5 | 6 | --- 7 | 8 | Download the `Album` art of the currently set `Song`. 9 | 10 | If no art was found, this will respond with an `HTTP` error. 11 | 12 | #### Input 13 | `None` 14 | 15 | #### Output 16 | Art in original format. 17 | 18 | #### Example Input 19 | ```http 20 | http://localhost:18425/current/art 21 | ``` 22 | 23 | #### Example Output 24 | ```plaintext 25 | Artist Name - Album Title.jpg 26 | ``` 27 | -------------------------------------------------------------------------------- /daemon/mdbook/src/rest/current/artist.md: -------------------------------------------------------------------------------- 1 | # /current/artist 2 | 3 | #### 🟢 Stable 4 | This API is [stable](../../api-stability/marker.md) since `festivald v1.0.0`. 5 | 6 | --- 7 | 8 | Download the `Artist` of the currently set `Song`. 9 | 10 | #### Input 11 | `None` 12 | 13 | #### Output 14 | `ZIP` of all artist's albums (including art if found). 15 | 16 | #### Example Input 17 | ```http 18 | http://localhost:18425/current/artist 19 | ``` 20 | 21 | #### Example Output 22 | File: 23 | ```plaintext 24 | Artist Name.zip 25 | ``` 26 | 27 | Extracted: 28 | ```plaintext 29 | Artist Name/ 30 | ├─ Album Name 1/ 31 | │ ├─ Album Name 1.jpg 32 | │ ├─ Song Name 1.mp3 33 | │ ├─ Song Name 2.flac 34 | │ ├─ Song Name 3.ogg 35 | │ 36 | │─ Album Name 2/ 37 | │ ├─ Album Name 2.png 38 | │ ├─ Song Name 4.mp3 39 | │ ├─ Song Name 5.flac 40 | │ ├─ Song Name 6.ogg 41 | │ 42 | ├─ Album Name 3/ 43 | ├─ Song Name 7.mp3 44 | ├─ Song Name 8.flac 45 | ├─ Song Name 9.ogg 46 | ``` 47 | -------------------------------------------------------------------------------- /daemon/mdbook/src/rest/current/current.md: -------------------------------------------------------------------------------- 1 | # /current 2 | Download the currently set `Artist`, `Album`, `Song`, or art. 3 | 4 | Returns an `HTTP` error if no [`Song`](../../common-objects/song.md) is currently [set](../state/state_audio.md). 5 | -------------------------------------------------------------------------------- /daemon/mdbook/src/rest/current/song.md: -------------------------------------------------------------------------------- 1 | # /current/song 2 | 3 | #### 🟢 Stable 4 | This API is [stable](../../api-stability/marker.md) since `festivald v1.0.0`. 5 | 6 | --- 7 | 8 | Download the currently set `Song`. 9 | 10 | #### Input 11 | `None` 12 | 13 | #### Output 14 | Song in original format. 15 | 16 | #### Example Input 17 | ```http 18 | http://localhost:18425/current/song 19 | ``` 20 | 21 | #### Example Output 22 | ```plaintext 23 | Artist Name - Album Title - Song Title.flac 24 | ``` 25 | -------------------------------------------------------------------------------- /daemon/mdbook/src/rest/key/album.md: -------------------------------------------------------------------------------- 1 | # /key/album/$ALBUM_KEY 2 | 3 | #### 🟢 Stable 4 | This API is [stable](../../api-stability/marker.md) since `festivald v1.0.0`. 5 | 6 | --- 7 | 8 | Download an `Album` using an [`Album key`](../../common-objects/key.md). 9 | 10 | #### Input 11 | | Input | Type | 12 | |-----------|------------------| 13 | | Album key | unsigned integer | 14 | 15 | #### Output 16 | Album in `ZIP` (including art if found). 17 | 18 | #### Example Input 19 | ```http 20 | http://localhost:18425/key/album/123 21 | ``` 22 | 23 | #### Example Output 24 | File: 25 | ```plaintext 26 | Artist Name - Album Title.zip 27 | ``` 28 | 29 | Extracted: 30 | ```plaintext 31 | Artist Name - Album Title/ 32 | ├─ Album Title.jpg 33 | ├─ Song Title 1.mp3 34 | ├─ Song Title 2.flac 35 | ├─ Song Title 3.ogg 36 | ``` 37 | -------------------------------------------------------------------------------- /daemon/mdbook/src/rest/key/art.md: -------------------------------------------------------------------------------- 1 | # /key/art/$ALBUM_KEY 2 | 3 | #### 🟢 Stable 4 | This API is [stable](../../api-stability/marker.md) since `festivald v1.0.0`. 5 | 6 | --- 7 | 8 | Download this `Album`'s art, using an [`Album key`](../../common-objects/key.md). 9 | 10 | #### Input 11 | | Input | Type | 12 | |-------------|------------------| 13 | | `Album` key | unsigned integer | 14 | 15 | #### Output 16 | Art in original format. 17 | 18 | #### Example Input 19 | ```http 20 | http://localhost:18425/key/art/123 21 | ``` 22 | 23 | #### Example Output 24 | File: 25 | ```plaintext 26 | Artist Name - Album Title.jpg 27 | ``` 28 | -------------------------------------------------------------------------------- /daemon/mdbook/src/rest/key/artist.md: -------------------------------------------------------------------------------- 1 | # /key/artist/$ARTIST_KEY 2 | 3 | #### 🟢 Stable 4 | This API is [stable](../../api-stability/marker.md) since `festivald v1.0.0`. 5 | 6 | --- 7 | 8 | Download an `Artist`, using an [`Artist key`](../../common-objects/key.md). 9 | 10 | #### Input 11 | | Input | Type | 12 | |--------------|------------------| 13 | | `Artist` key | unsigned integer | 14 | 15 | #### Output 16 | `ZIP` of all artist's albums (including art if found). 17 | 18 | #### Example Input 19 | ```http 20 | http://localhost:18425/key/artist/123 21 | ``` 22 | 23 | #### Example Output 24 | File: 25 | ```plaintext 26 | Artist Name.zip 27 | ``` 28 | 29 | Extracted: 30 | ```plaintext 31 | Artist Name/ 32 | ├─ Album Title 1/ 33 | │ ├─ Album Title 1.jpg 34 | │ ├─ Song Title 1.mp3 35 | │ ├─ Song Title 2.flac 36 | │ ├─ Song Title 3.ogg 37 | │ 38 | │─ Album Title 2/ 39 | │ ├─ Album Title 2.png 40 | │ ├─ Song Title 4.mp3 41 | │ ├─ Song Title 5.flac 42 | │ ├─ Song Title 6.ogg 43 | │ 44 | ├─ Album Title 3/ 45 | ├─ Song Title 7.mp3 46 | ├─ Song Title 8.flac 47 | ├─ Song Title 9.ogg 48 | ``` 49 | -------------------------------------------------------------------------------- /daemon/mdbook/src/rest/key/key.md: -------------------------------------------------------------------------------- 1 | # /key 2 | Access audio files and/or art via a [`key`](../../common-objects/key.md). 3 | 4 | This endpoint expects 2 more endpoints/inputs: 5 | - [`${COMMON_OBJECT}`](../../common-objects/common-objects.md) 6 | - [`${KEY}`](../../common-objects/key.md) 7 | 8 | Where `${COMMON_OBJECT}` is one of: 9 | - `artist` 10 | - `album` 11 | - `song` 12 | - `art` 13 | 14 | The `key` must be the key number associated with the object. 15 | 16 | See [`Common Objects/Key`](../../common-objects/key.md) for more information on keys. 17 | -------------------------------------------------------------------------------- /daemon/mdbook/src/rest/key/song.md: -------------------------------------------------------------------------------- 1 | # /key/song/$SONG_KEY 2 | 3 | #### 🟢 Stable 4 | This API is [stable](../../api-stability/marker.md) since `festivald v1.0.0`. 5 | 6 | --- 7 | 8 | Download a `Song` using a [`Song key`](../../common-objects/key.md). 9 | 10 | #### Input 11 | | Input | Type | 12 | |------------|------------------| 13 | | `Song` key | unsigned integer | 14 | 15 | #### Output 16 | Song in original format. 17 | 18 | #### Example Input 19 | ```http 20 | http://localhost:18425/key/song/123 21 | ``` 22 | 23 | #### Example Output 24 | ```plaintext 25 | Artist Name - Album Title - Song Title.flac 26 | ``` 27 | -------------------------------------------------------------------------------- /daemon/mdbook/src/rest/map/album.md: -------------------------------------------------------------------------------- 1 | # /map/$ARTIST_NAME/$ALBUM_TITLE 2 | 3 | #### 🟢 Stable 4 | This API is [stable](../../api-stability/marker.md) since `festivald v1.0.0`. 5 | 6 | --- 7 | 8 | Download an `Album` using the [`Artist`](../../common-objects/artist.md)'s name, and [`Album`](../../common-objects/album.md) title. 9 | 10 | #### Input 11 | | Input | Type | 12 | |---------------|--------| 13 | | `Artist` name | string | 14 | | `Album` title | string | 15 | 16 | #### Output 17 | Album in `ZIP` (including art if found). 18 | 19 | #### Example Input 20 | ```http 21 | http://localhost:18425/map/Artist Name/Album Title 22 | ``` 23 | 24 | #### Example Output 25 | File: 26 | ```plaintext 27 | Artist Name - Album Title.zip 28 | ``` 29 | 30 | Extracted: 31 | ```plaintext 32 | Artist Name - Album Title/ 33 | ├─ Album Title.jpg 34 | ├─ Song Title 1.mp3 35 | ├─ Song Title 2.flac 36 | ├─ Song Title 3.ogg 37 | ``` 38 | -------------------------------------------------------------------------------- /daemon/mdbook/src/rest/map/artist.md: -------------------------------------------------------------------------------- 1 | # /map/$ARTIST_NAME 2 | 3 | #### 🟢 Stable 4 | This API is [stable](../../api-stability/marker.md) since `festivald v1.0.0`. 5 | 6 | --- 7 | 8 | Download an `Artist`, using the [`Artist`](../../common-objects/artist.md)'s name. 9 | 10 | #### Input 11 | | Input | Type | 12 | |---------------|--------| 13 | | `Artist` name | string | 14 | 15 | #### Output 16 | `ZIP` of all artist's albums (including art if found). 17 | 18 | #### Example Input 19 | ```http 20 | http://localhost:18425/map/Artist Name 21 | ``` 22 | 23 | #### Example Output 24 | File: 25 | ```plaintext 26 | Artist Name.zip 27 | ``` 28 | 29 | Extracted: 30 | ```plaintext 31 | Artist Name/ 32 | ├─ Album Title 1/ 33 | │ ├─ Album Title 1.jpg 34 | │ ├─ Song Title 1.mp3 35 | │ ├─ Song Title 2.flac 36 | │ ├─ Song Title 3.ogg 37 | │ 38 | │─ Album Title 2/ 39 | │ ├─ Album Title 2.png 40 | │ ├─ Song Title 4.mp3 41 | │ ├─ Song Title 5.flac 42 | │ ├─ Song Title 6.ogg 43 | │ 44 | ├─ Album Title 3/ 45 | ├─ Song Title 7.mp3 46 | ├─ Song Title 8.flac 47 | ├─ Song Title 9.ogg 48 | ``` 49 | -------------------------------------------------------------------------------- /daemon/mdbook/src/rest/map/map.md: -------------------------------------------------------------------------------- 1 | # /map 2 | This is the same as the [`/key`](../key/key.md) endpoint, but instead of numbers, you can directly use: 3 | - `Artist` names 4 | - `Album` titles 5 | - `Song` titles 6 | 7 | So instead of: 8 | ``` 9 | http://localhost:18425/key/song/123 10 | ``` 11 | you can use: 12 | ``` 13 | http://localhost:18425/map/Artist Name/Artist Title/Song Title 14 | ``` 15 | Browsers will secretly percent-encode this URL, so it'll actually be: 16 | ``` 17 | http://localhost:18425/map/Artist%20Name/Artist%20Title/Song%20Title 18 | ``` 19 | This is fine, `festivald` will decode it, along with any other percent encoding, so you can use spaces or any other UTF-8 characters directly in the URL: 20 | ``` 21 | http://localhost:18425/map/артист/❤️/ヒント じゃない 22 | ``` 23 | 24 | The reason `Artist` names and `Album` titles have to be specified is to prevent collisions. 25 | 26 | If there's 2 songs in your `Collection` called: `Hello World`, which one should `festivald` return? 27 | 28 | Since `Artist` names are unique, and `Album` titles within `Artist`'s are unique, they serve as an identifier. 29 | 30 | Also note: words are case-sensitive and must be exact. 31 | 32 | If you have an `Album` called `Hello World`, none of these inputs will work: 33 | - `Hello world` 34 | - `hello World` 35 | - `HELlo World` 36 | - `HelloWorld` 37 | - `H3ll0 W0rld` 38 | 39 | The input must _exactly_ be `Hello World`. 40 | -------------------------------------------------------------------------------- /daemon/mdbook/src/rest/map/song.md: -------------------------------------------------------------------------------- 1 | # /map/$ARTIST_NAME/$ALBUM_TITLE/$SONG_TITLE 2 | 3 | #### 🟢 Stable 4 | This API is [stable](../../api-stability/marker.md) since `festivald v1.0.0`. 5 | 6 | --- 7 | 8 | Download a `Song`, using the [`Artist`](../../common-objects/artist.md)'s name, [`Album`](../../common-objects/album.md) title, and [`Song`](../../common-objects/song.md) title. 9 | 10 | #### Input 11 | | Input | Type | 12 | |---------------|--------| 13 | | `Artist` name | string | 14 | | `Album` title | string | 15 | | `Song` title | string | 16 | 17 | #### Output 18 | | Output | Type | 19 | |-------------------------|------------| 20 | | Song in original format | audio file | 21 | 22 | #### Example Input 23 | ```http 24 | http://localhost:18425/map/Artist Name/Album Title/Song Title 25 | ``` 26 | 27 | #### Example Output 28 | ```plaintext 29 | Artist Name - Album Title - Song Title.flac 30 | ``` 31 | -------------------------------------------------------------------------------- /daemon/mdbook/src/rest/playlist.md: -------------------------------------------------------------------------------- 1 | # /playlist/$PLAYLIST_NAME 2 | 3 | #### 🟢 Stable 4 | This API is [stable](../api-stability/marker.md) since `festivald v1.0.0`. 5 | 6 | --- 7 | 8 | Download all the [`Song`](../common-objects/song.md)'s in a [`Playlist`](../common-objects/playlist.md). 9 | 10 | [`Invalid Entry`](../common-objects/playlist.html#playlist-entry)'s will be ignored. 11 | 12 | Each `Song` file will be prefixed with its index in the playlist. 13 | 14 | The formatting is as such: 15 | ```bash 16 | ${INDEX}${SEPARATOR}${ARTIST_NAME}${SEPARATOR}${ALBUM_TITLE}${SEPARATOR}${SONG_TITLE}.${SONG_EXTENSION} 17 | ``` 18 | For example, if the [`filename_separator`](../config.md) was left as the default ` - `: 19 | ```plaintext 20 | 11 - Artist Name - Album Title - Song Title.mp3 21 | ``` 22 | 23 | Index starts at `0`. 24 | 25 | #### Input 26 | | Input | Type | 27 | |-----------------|--------| 28 | | `Playlist` name | string | 29 | 30 | #### Output 31 | Playlist (valid `Song` files only) in `ZIP`. 32 | 33 | #### Example Input 34 | ```http 35 | http://localhost:18425/playlist/My Playlist 2 36 | ``` 37 | 38 | #### Example Output 39 | File: 40 | ```plaintext 41 | Playlist - My Playlist 2.zip 42 | ``` 43 | 44 | Extracted: 45 | ```plaintext 46 | Playlist - My Playlist 2/ 47 | ├─ 0 - Artist Name - Album Title - Song Name.mp3 48 | ├─ 1 - Artist Name - Album Title - Song Name.flac 49 | ├─ 2 - Artist Name - Album Title - Song Name.ogg 50 | ``` 51 | -------------------------------------------------------------------------------- /daemon/mdbook/src/rest/rand/album.md: -------------------------------------------------------------------------------- 1 | # /rand/album 2 | 3 | #### 🟢 Stable 4 | This API is [stable](../../api-stability/marker.md) since `festivald v1.0.0`. 5 | 6 | --- 7 | 8 | Download a random `Album`. 9 | 10 | #### Input 11 | `None` 12 | 13 | #### Output 14 | Album in `ZIP` (including art if found). 15 | 16 | #### Example Input 17 | ```http 18 | http://localhost:18425/rand/album 19 | ``` 20 | 21 | #### Example Output 22 | File: 23 | ```plaintext 24 | Artist Name - Album Title.zip 25 | ``` 26 | 27 | Extracted: 28 | ```plaintext 29 | Artist Name - Album Title/ 30 | ├─ Album Name.jpg 31 | ├─ Song Name 1.mp3 32 | ├─ Song Name 2.flac 33 | ├─ Song Name 3.ogg 34 | ``` 35 | -------------------------------------------------------------------------------- /daemon/mdbook/src/rest/rand/art.md: -------------------------------------------------------------------------------- 1 | # /rand/art 2 | 3 | #### 🟢 Stable 4 | This API is [stable](../../api-stability/marker.md) since `festivald v1.0.0`. 5 | 6 | --- 7 | 8 | Download a random `Album` art. 9 | 10 | If no art was found, the response will be an `HTTP` error. 11 | 12 | #### Input 13 | `None` 14 | 15 | #### Output 16 | Art in original format. 17 | 18 | #### Example Input 19 | ```http 20 | http://localhost:18425/rand/art 21 | ``` 22 | 23 | #### Example Output 24 | ```plaintext 25 | Artist Name - Album Title.jpg 26 | ``` 27 | -------------------------------------------------------------------------------- /daemon/mdbook/src/rest/rand/artist.md: -------------------------------------------------------------------------------- 1 | # /rand/artist 2 | 3 | #### 🟢 Stable 4 | This API is [stable](../../api-stability/marker.md) since `festivald v1.0.0`. 5 | 6 | --- 7 | 8 | Download a random `Artist`. 9 | 10 | #### Input 11 | `None` 12 | 13 | #### Output 14 | `ZIP` of all artist's albums (including art if found). 15 | 16 | #### Example Input 17 | ```http 18 | http://localhost:18425/rand/artist 19 | ``` 20 | 21 | #### Example Output 22 | File: 23 | ```plaintext 24 | Artist Name.zip 25 | ``` 26 | 27 | Extracted: 28 | ```plaintext 29 | Artist Name/ 30 | ├─ Album Name 1/ 31 | │ ├─ Album Name 1.jpg 32 | │ ├─ Song Name 1.mp3 33 | │ ├─ Song Name 2.flac 34 | │ ├─ Song Name 3.ogg 35 | │ 36 | │─ Album Name 2/ 37 | │ ├─ Album Name 2.png 38 | │ ├─ Song Name 4.mp3 39 | │ ├─ Song Name 5.flac 40 | │ ├─ Song Name 6.ogg 41 | │ 42 | ├─ Album Name 3/ 43 | ├─ Song Name 7.mp3 44 | ├─ Song Name 8.flac 45 | ├─ Song Name 9.ogg 46 | ``` 47 | -------------------------------------------------------------------------------- /daemon/mdbook/src/rest/rand/rand.md: -------------------------------------------------------------------------------- 1 | # /rand 2 | Download a random `Artist`, `Album`, `Song` or art. 3 | 4 | This will return an `HTTP` error if the [`Collection`](../../common-objects/collection.md) is empty. 5 | 6 | Repeating is allowed, so you may encounter the same object multiple times in a row. 7 | -------------------------------------------------------------------------------- /daemon/mdbook/src/rest/rand/song.md: -------------------------------------------------------------------------------- 1 | # /rand/song 2 | 3 | #### 🟢 Stable 4 | This API is [stable](../../api-stability/marker.md) since `festivald v1.0.0`. 5 | 6 | --- 7 | 8 | Download a random `Song`. 9 | 10 | #### Input 11 | `None` 12 | 13 | #### Output 14 | Song in original format. 15 | 16 | #### Example Input 17 | ```http 18 | http://localhost:18425/rand/song 19 | ``` 20 | 21 | #### Example Output 22 | ```plaintext 23 | Artist Name - Album Title - Song Title.flac 24 | ``` 25 | -------------------------------------------------------------------------------- /daemon/mdbook/src/systemd.md: -------------------------------------------------------------------------------- 1 | # `systemd` 2 | This is a relatively hardened [`systemd`](https://en.wikipedia.org/wiki/Systemd) service file for `festivald`. 3 | 4 | `${USER}` should be replaced by a user that has access to an audio server (like PulseAudio). 5 | 6 | It should be placed at: 7 | ``` 8 | /etc/systemd/system/festivald.service 9 | ``` 10 | and launched with: 11 | ```bash 12 | sudo systemctl start festivald 13 | ``` 14 | 15 | ## `festivald.service` 16 | ```toml 17 | {{#include ../../config/festivald.service}} 18 | ``` 19 | -------------------------------------------------------------------------------- /daemon/mdbook/zip.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | # Build the documentation, and zip it. 4 | 5 | set -ex 6 | 7 | [[ -e docs.zip ]] && rm docs.zip 8 | 9 | mdbook build && zip -r9 docs.zip docs 10 | -------------------------------------------------------------------------------- /daemon/src/cert.rs: -------------------------------------------------------------------------------- 1 | //---------------------------------------------------------------------------------------------------- Use 2 | use zeroize::Zeroize; 3 | use anyhow::anyhow; 4 | use tokio_native_tls::{ 5 | TlsAcceptor, 6 | native_tls::{ 7 | Identity, 8 | TlsAcceptor as TlsAcceptorNative, 9 | }, 10 | }; 11 | use std::path::{ 12 | Path,PathBuf, 13 | }; 14 | 15 | //---------------------------------------------------------------------------------------------------- 16 | pub fn get_tls_acceptor(path_cert: &Path, path_key: &Path) -> Result<&'static TlsAcceptor, anyhow::Error> { 17 | // Read cert. 18 | let mut cert = std::fs::read(path_cert)?; 19 | 20 | // Read key. 21 | let mut key = std::fs::read(path_key)?; 22 | 23 | let acceptor = TlsAcceptor::from(build_cert(cert, key)?); 24 | let acceptor: &'static TlsAcceptor = Box::leak(Box::new(acceptor)); 25 | 26 | Ok(acceptor) 27 | } 28 | 29 | fn build_cert(mut cert: Vec, mut key: Vec) -> Result { 30 | // Build. 31 | let identity = Identity::from_pkcs8(&cert, &key)?; 32 | let acceptor = TlsAcceptorNative::builder(identity).build()?; 33 | 34 | // Zeroize cert + key. 35 | cert.zeroize(); 36 | key.zeroize(); 37 | 38 | Ok(acceptor) 39 | } 40 | 41 | //---------------------------------------------------------------------------------------------------- TESTS 42 | #[cfg(test)] 43 | mod tests { 44 | use super::*; 45 | 46 | const CERT: &[u8] = include_bytes!("../../assets/tls/cert.pem"); 47 | const KEY: &[u8] = include_bytes!("../../assets/tls/key.pem"); 48 | 49 | #[test] 50 | fn cert() { 51 | build_cert(CERT.into(), KEY.into()).unwrap(); 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /daemon/src/config/README.md: -------------------------------------------------------------------------------- 1 | # Config 2 | Archives of `festivald`'s configuration over different version, for (de)serialization testing. 3 | -------------------------------------------------------------------------------- /daemon/src/docs.rs: -------------------------------------------------------------------------------- 1 | //---------------------------------------------------------------------------------------------------- Use 2 | use serde::{Serialize,Deserialize}; 3 | use disk::Empty; 4 | use std::path::{Path,PathBuf}; 5 | use shukusai::constants::{ 6 | FESTIVAL,FRONTEND_SUB_DIR, 7 | }; 8 | use const_format::formatcp; 9 | use once_cell::sync::OnceCell; 10 | 11 | //---------------------------------------------------------------------------------------------------- Docs 12 | disk::empty!(Docs, disk::Dir::Data, FESTIVAL, formatcp!("{FRONTEND_SUB_DIR}/docs"), "__docs"); 13 | #[derive(Debug,PartialEq,Eq,PartialOrd,Ord,Serialize,Deserialize)] 14 | pub struct Docs; 15 | 16 | const DOCS_ZIP: &[u8] = include_bytes!("../mdbook/docs.zip"); 17 | pub static DOCS_PATH: OnceCell = OnceCell::new(); 18 | 19 | impl Docs { 20 | pub fn create() -> Result { 21 | let mut path = Self::base_path()?; 22 | let _ = std::fs::remove_dir_all(&path); 23 | Self::mkdir()?; 24 | 25 | let mut zip = zip::ZipArchive::new(std::io::Cursor::new(DOCS_ZIP))?; 26 | 27 | // The `ZIP` contains `/docs`, so pop it out. 28 | path.pop(); 29 | zip.extract(&path)?; 30 | path.push("docs"); 31 | 32 | Ok(path) 33 | } 34 | 35 | pub fn create_open() -> Result<(), anyhow::Error> { 36 | match crate::docs::Docs::create() { 37 | Ok(mut path) => { 38 | path.push("index.html"); 39 | Ok(open::that_detached(path)?) 40 | }, 41 | Err(e) => Err(e), 42 | } 43 | } 44 | } 45 | 46 | //---------------------------------------------------------------------------------------------------- TESTS 47 | //#[cfg(test)] 48 | //mod tests { 49 | // #[test] 50 | // fn __TEST__() { 51 | // } 52 | //} 53 | -------------------------------------------------------------------------------- /daemon/src/macros.rs: -------------------------------------------------------------------------------- 1 | // Top-level convenience macros. 2 | 3 | //---------------------------------------------------------------------------------------------------- Use 4 | 5 | //---------------------------------------------------------------------------------------------------- __NAME__ 6 | // Exit the whole program with an error message WITHOUT running destructors. 7 | #[macro_export] 8 | macro_rules! exit { 9 | ($($msg:tt)*) => {{ 10 | ::std::eprintln!("festivald error: {}", ::std::format_args!($($msg)*)); 11 | ::std::process::exit(1); 12 | }} 13 | } 14 | 15 | //---------------------------------------------------------------------------------------------------- TESTS 16 | //#[cfg(test)] 17 | //mod tests { 18 | // #[test] 19 | // fn __TEST__() { 20 | // } 21 | //} 22 | -------------------------------------------------------------------------------- /daemon/src/seen.rs: -------------------------------------------------------------------------------- 1 | //---------------------------------------------------------------------------------------------------- Use 2 | use anyhow::anyhow; 3 | use log::{error,info,warn,debug,trace}; 4 | use std::collections::BTreeMap; 5 | use tokio::sync::{ 6 | RwLock, 7 | }; 8 | use std::net::{ 9 | Ipv4Addr, 10 | SocketAddrV4, 11 | }; 12 | 13 | //---------------------------------------------------------------------------------------------------- 14 | // Global map of seen IPs and their connection count. 15 | pub static SEEN_IPS: RwLock> = RwLock::const_new(BTreeMap::new()); 16 | 17 | pub async fn add(addr: &std::net::SocketAddrV4) { 18 | SEEN_IPS.write().await.entry(*addr.ip()).and_modify(|c| { *c += 1 }).or_insert(1); 19 | } 20 | 21 | pub async fn seen(addr: &std::net::SocketAddrV4) -> bool { 22 | match SEEN_IPS.read().await.get(addr.ip()) { 23 | Some(k) => k > &1, 24 | None => false, 25 | } 26 | } 27 | 28 | pub async fn count(addr: &std::net::SocketAddrV4) -> u64 { 29 | match SEEN_IPS.read().await.get(addr.ip()) { 30 | Some(k) => *k, 31 | None => 0, 32 | } 33 | } 34 | 35 | //---------------------------------------------------------------------------------------------------- TESTS 36 | //#[cfg(test)] 37 | //mod tests { 38 | // #[test] 39 | // fn __TEST__() { 40 | // } 41 | //} 42 | -------------------------------------------------------------------------------- /external/README.md: -------------------------------------------------------------------------------- 1 | # External libraries (with patches) 2 | 3 | Some external libraries that with some custom patches for some features `Festival` needs. 4 | 5 | | Fork branch | Purpose | 6 | |-------------|---------| 7 | | `festival` | The main patched fork that `Festival` uses 8 | | `master` | Up-to-date, un-modified upstream branch 9 | -------------------------------------------------------------------------------- /gui/README.md: -------------------------------------------------------------------------------- 1 | # Festival 2 | `Festival`, the native desktop GUI client. 3 | 4 | View documentation at: https://docs.festival.pm/gui. 5 | -------------------------------------------------------------------------------- /gui/build.rs: -------------------------------------------------------------------------------- 1 | #[cfg(windows)] 2 | fn main() -> std::io::Result<()> { 3 | // Include `VCVCRUNTIME140.dll`. 4 | static_vcruntime::metabuild(); 5 | 6 | // Set `File Explorer` icon and other Windows metadata. 7 | let mut res = winres::WindowsResource::new(); 8 | res.set_icon("../assets/images/icon/icon.ico"); 9 | res.set_language(0x0009 /* english */); 10 | 11 | // This is the name of the program when right 12 | // clicking it in the taskbar... for some reason. 13 | res.set("FileDescription", "Festival"); 14 | res.set("ProductName", "Festival"); 15 | res.set("LegalCopyright", "Copyright (c) 2023-2024 hinto-janai"); 16 | res.compile() 17 | } 18 | 19 | #[cfg(unix)] 20 | fn main() {} 21 | -------------------------------------------------------------------------------- /gui/mdbook/book.toml: -------------------------------------------------------------------------------- 1 | [book] 2 | authors = ["hinto-janai"] 3 | language = "en" 4 | multilingual = false 5 | src = "src" 6 | title = "Festival GUI v1.4.0" 7 | 8 | [build] 9 | build-dir = "docs" 10 | 11 | [output.html] 12 | default-theme = "ayu" 13 | preferred-dark-theme = "ayu" 14 | git-repository-url = "https://github.com/hinto-janai/festival" 15 | site-url = "/gui/" 16 | -------------------------------------------------------------------------------- /gui/mdbook/docs.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hinto-janai/festival/8d7e26d55e7677e3d38d6c51c51683830e9cbd61/gui/mdbook/docs.zip -------------------------------------------------------------------------------- /gui/mdbook/src/SUMMARY.md: -------------------------------------------------------------------------------- 1 | # Summary 2 | 3 | - [Intro](intro.md) 4 | - [Key/Mouse shortcuts](key-mouse-shortcuts.md) 5 | - [Command Line](command-line.md) 6 | - [Disk](disk.md) 7 | - [Playlists](playlists.md) 8 | -------------------------------------------------------------------------------- /gui/mdbook/src/command-line.md: -------------------------------------------------------------------------------- 1 | # Command Line 2 | Festival has some command line flags, useful for adjusting playback. 3 | 4 | Some examples: 5 | 6 | Play the next song: 7 | ```bash 8 | ./festival --next 9 | ``` 10 | 11 | Seek backwards 25 seconds in the current song: 12 | ```bash 13 | ./festival --seek-backward 25 14 | ``` 15 | 16 | Skip 3 songs into the queue: 17 | ```bash 18 | ./festival --skip 3 19 | ``` 20 | 21 | Play the 10th song in the queue: 22 | ```bash 23 | ./festival --index 10 24 | ``` 25 | 26 | --- 27 | 28 | The full list of commands: 29 | ``` 30 | {{#include ../../CMD.txt}} 31 | ``` 32 | -------------------------------------------------------------------------------- /gui/mdbook/src/intro.md: -------------------------------------------------------------------------------- 1 | # Festival GUI 2 | `Festival`, the standalone GUI client. 3 | 4 | To view this documentation locally, run: 5 | ```bash 6 | festival --docs 7 | ``` 8 | -------------------------------------------------------------------------------- /gui/mdbook/src/key-mouse-shortcuts.md: -------------------------------------------------------------------------------- 1 | # Key/Mouse shortcuts 2 | 3 | | Key/Mouse | Action | 4 | |-----------------|-------------------------------------| 5 | | `[A-Za-z0-9]` | Jump to search tab | 6 | | CTRL+S | Save Changes | 7 | | CTRL+Z | Reset Changes | 8 | | CTRL+C | Reset Collection | 9 | | CTRL+A | Add Scan Directory | 10 | | CTRL+W | Rotate Album Sort | 11 | | CTRL+E | Rotate Artist Sort | 12 | | CTRL+R | Rotate Song Sort | 13 | | CTRL+D | Goto Last Tab | 14 | | Up | Last Tab | 15 | | Down | Next Tab | 16 | | Right | Last Sub-Tab | 17 | | Left | Next Sub-Tab | 18 | | Primary Mouse | Set Artist, Album, Song | 19 | | Secondary Mouse | Add Artist, Album, Song to Queue | 20 | | Middle Mouse | Copy Artist, Album, Song text | 21 | | CTRL+Primary | Add Artist, Album, Song to Playlist | 22 | | CTRL+Secondary | Open Album/Song Directory | 23 | | CTRL+Middle | Copy Artist/Album/Song PATH | 24 | 25 | *Note: `CTRL` is `Control` on macOS.* 26 | -------------------------------------------------------------------------------- /gui/mdbook/src/playlists.md: -------------------------------------------------------------------------------- 1 | # Playlists 2 | Festival's playlists are not necessarily tied to a `Collection`. 3 | 4 | For example, after a `Collection` reset, the songs in a playlist may not exist anymore. 5 | 6 | The way Festival handles this is to continue holding onto the "invalid" playlist indefinitely. 7 | 8 | Upon every `Collection` reset, Festival will check _every_ "invalid" playlist entry and attempt to "recover" it. 9 | 10 | If a matching song with the correct metadata is found after a `Collection` reset, any "invalid" playlist entry that was referencing it will automatically recover. 11 | 12 | -------------------------------------------------------------------------------- /gui/mdbook/zip.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | # Build the documentation, and zip it. 4 | 5 | set -ex 6 | 7 | [[ -e docs.zip ]] && rm docs.zip 8 | 9 | mdbook build && zip -r9 docs.zip docs 10 | -------------------------------------------------------------------------------- /gui/src/README.md: -------------------------------------------------------------------------------- 1 | # GUI 2 | A slightly patched version of `egui` located at `/external/` is used for `GUI`. 3 | 4 | Since a `Collection` might contain songs of various languages, multiple fonts are needed, or they will show up as unknown square blobs. Thankfully, `egui` allows embedding arbitrary fonts. The extra fonts are located at: `/assets/fonts/`. 5 | 6 | ## Files 7 | | File | Purpose | 8 | |----------------|---------| 9 | | `main.rs` | Barebones `main()` that spawns `Kernel` and turns into `GUI` 10 | | `cli.rs` | CLI handling 11 | | `constants.rs` | General constants 12 | | `text.rs` | Constant `&'static str`'s for `GUI` text 13 | 14 | ## Folders 15 | | Folder | Purpose | 16 | |----------------|---------| 17 | | `data/` | Main data definitions 18 | | `func/` | Functions on `Gui`, initialization, misc functions 19 | | `ui/` | The actual `egui` code & main `eframe::App::update()` loop 20 | -------------------------------------------------------------------------------- /gui/src/data/album.rs: -------------------------------------------------------------------------------- 1 | //---------------------------------------------------------------------------------------------------- Use 2 | use bincode::{Decode, Encode}; 3 | use serde::{Deserialize, Serialize}; 4 | use strum::{AsRefStr, Display, EnumCount, EnumIter, EnumString, EnumVariantNames, IntoStaticStr}; 5 | 6 | //---------------------------------------------------------------------------------------------------- Settings 7 | #[derive( 8 | Copy, 9 | Clone, 10 | Debug, 11 | Default, 12 | Hash, 13 | PartialEq, 14 | Eq, 15 | PartialOrd, 16 | Ord, 17 | Serialize, 18 | Deserialize, 19 | Encode, 20 | Decode, 21 | AsRefStr, 22 | Display, 23 | EnumCount, 24 | EnumIter, 25 | EnumString, 26 | EnumVariantNames, 27 | IntoStaticStr, 28 | )] 29 | #[strum(serialize_all = "snake_case")] 30 | #[serde(rename_all = "snake_case")] 31 | /// Does the user want a certain amount of `Album`'s per row or a static pixel size? 32 | pub enum AlbumSizing { 33 | #[default] 34 | /// Album art will be `x` pixels wide 35 | Pixel, 36 | 37 | /// `x` amount of albums per row 38 | /// 39 | /// (pixel size will scale to fit them) 40 | Row, 41 | } 42 | 43 | //---------------------------------------------------------------------------------------------------- TESTS 44 | //#[cfg(test)] 45 | //mod test { 46 | // #[test] 47 | // fn _() { 48 | // } 49 | //} 50 | -------------------------------------------------------------------------------- /gui/src/data/exit.rs: -------------------------------------------------------------------------------- 1 | //---------------------------------------------------------------------------------------------------- Use 2 | use std::sync::{atomic::AtomicBool, atomic::AtomicU8}; 3 | 4 | //---------------------------------------------------------------------------------------------------- Shared state between `GUI` and the `Exit` thread. 5 | // How many seconds to wait for the `Collection` 6 | // to be saved to disk before force-quitting the `GUI`. 7 | const EXIT_COUNTDOWN_START: u8 = 30; 8 | 9 | /// How long before we force quit without saving. 10 | pub static EXIT_COUNTDOWN: AtomicU8 = AtomicU8::new(EXIT_COUNTDOWN_START); 11 | 12 | /// The exit thread, or another thread has signaled 13 | /// that the main `GUI` process should exit. 14 | pub static SHOULD_EXIT: AtomicBool = AtomicBool::new(false); 15 | -------------------------------------------------------------------------------- /gui/src/data/mod.rs: -------------------------------------------------------------------------------- 1 | mod album; 2 | pub use album::*; 3 | 4 | mod state; 5 | pub use state::*; 6 | mod state0; 7 | pub use state0::*; 8 | 9 | mod settings; 10 | pub use settings::*; 11 | mod settings0; 12 | pub use settings0::*; 13 | mod settings1; 14 | pub use settings1::*; 15 | mod settings2; 16 | pub use settings2::*; 17 | 18 | mod gui; 19 | pub use gui::*; 20 | 21 | mod tab; 22 | pub use tab::*; 23 | 24 | mod key; 25 | pub use key::*; 26 | 27 | mod debug; 28 | pub use debug::*; 29 | 30 | mod search_sort; 31 | pub use search_sort::*; 32 | 33 | mod artist; 34 | pub use artist::*; 35 | 36 | mod window; 37 | pub use window::*; 38 | 39 | mod exit; 40 | pub use exit::*; 41 | 42 | mod playlist; 43 | pub use playlist::*; 44 | -------------------------------------------------------------------------------- /gui/src/func/file.rs: -------------------------------------------------------------------------------- 1 | //---------------------------------------------------------------------------------------------------- Use 2 | use benri::{atomic_store, lock}; 3 | use log::info; 4 | use std::path::PathBuf; 5 | use std::sync::{atomic::AtomicBool, Arc, Mutex}; 6 | 7 | //---------------------------------------------------------------------------------------------------- __NAME__ 8 | pub fn spawn_rfd_thread(rfd_open: Arc, rfd_new: Arc>>) { 9 | std::thread::spawn(move || { 10 | atomic_store!(rfd_open, true); 11 | 12 | match rfd::FileDialog::new() 13 | .set_title("Add folder to the Collection") 14 | .pick_folder() 15 | { 16 | Some(path) => { 17 | info!("RFD - Selected PATH: {}", path.display()); 18 | lock!(rfd_new).replace(path); 19 | } 20 | None => info!("RFD - No PATH selected"), 21 | } 22 | 23 | atomic_store!(rfd_open, false); 24 | }); 25 | } 26 | 27 | //---------------------------------------------------------------------------------------------------- TESTS 28 | //#[cfg(test)] 29 | //mod tests { 30 | // #[test] 31 | // fn __TEST__() { 32 | // } 33 | //} 34 | -------------------------------------------------------------------------------- /gui/src/func/mod.rs: -------------------------------------------------------------------------------- 1 | mod file; 2 | use file::*; 3 | 4 | mod gui; 5 | 6 | mod init; 7 | -------------------------------------------------------------------------------- /gui/src/main.rs: -------------------------------------------------------------------------------- 1 | #![allow(clippy::len_zero, clippy::type_complexity, clippy::module_inception)] 2 | // Hide console in Windows 3 | #![cfg_attr(not(debug_assertions), windows_subsystem = "windows")] 4 | 5 | mod cli; 6 | mod constants; 7 | mod data; 8 | mod docs; 9 | mod func; 10 | mod text; 11 | mod ui; 12 | 13 | fn main() { 14 | // Handle CLI arguments. 15 | let (disable_watch, disable_media_controls, log) = { 16 | if std::env::args_os().len() == 1 { 17 | (false, false, log::LevelFilter::Info) 18 | } else { 19 | crate::cli::Cli::get() 20 | } 21 | }; 22 | 23 | // Init logger. 24 | shukusai::logger::init_logger(log); 25 | 26 | // Set `umask` (`rwxr-x---`) 27 | disk::umask(0o027); 28 | 29 | // Start `egui/eframe`. 30 | if let Err(e) = eframe::run_native( 31 | shukusai::constants::FESTIVAL, 32 | crate::data::Gui::options(), 33 | Box::new(move |cc| { 34 | // Set `Festival`'s `GUI_CONTEXT`. 35 | shukusai::frontend::gui::GUI_CONTEXT 36 | .set(cc.egui_ctx.clone()) 37 | .expect("GUI_CONTEXT.set() failed"); 38 | 39 | let (to_kernel, from_kernel) = 40 | match shukusai::kernel::Kernel::spawn(!disable_watch, !disable_media_controls) { 41 | Ok((to, from)) => (to, from), 42 | Err(e) => panic!("Kernel::spawn() failed: {e}"), 43 | }; 44 | 45 | // Start `GUI`. 46 | Box::new(crate::data::Gui::init(cc, to_kernel, from_kernel)) 47 | }), 48 | ) { 49 | panic!("eframe::run_native() failed: {e}"); 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /gui/src/ui/mod.rs: -------------------------------------------------------------------------------- 1 | mod albums; 2 | mod artist; 3 | mod exit; 4 | mod macros; 5 | mod playlists; 6 | mod queue; 7 | mod search; 8 | mod settings; 9 | mod songs; 10 | mod update; 11 | mod view; 12 | -------------------------------------------------------------------------------- /pgp/README.md: -------------------------------------------------------------------------------- 1 | # PGP 2 | This is the `PGP` key that signs the releases of `Festival`. 3 | -------------------------------------------------------------------------------- /pgp/hinto-janai.asc: -------------------------------------------------------------------------------- 1 | -----BEGIN PGP PUBLIC KEY BLOCK----- 2 | 3 | mDMEY/uGgxYJKwYBBAHaRw8BAQdAnxjwGrbJPfqAseSO6no55MyV5f71uoEqJr/T 4 | KmLvgT20KGhpbnRvLmphbmFpIDxoaW50by5qYW5haUBwcm90b25tYWlsLmNvbT6I 5 | kAQTFggAOBYhBDHFFFqvpajfHB2yptR84F+hdaSZBQJj+4aDAhsDBQsJCAcCBhUK 6 | CQgLAgQWAgMBAh4BAheAAAoJENR84F+hdaSZh/MBAPtNC4Cs0DcGBr/nwmLxZDGG 7 | 6ZP0beaFjV1AbfzHOSS3AQCIPLFoQonxRTlWGpIeyK5FUn3kMf+eAUDoT9HQisrd 8 | Dbg4BGP7hoMSCisGAQQBl1UBBQEBB0BbtNHDkRLV8zJ5jGtT0DWdfQam2pRp9THf 9 | mctPLlU/EwMBCAeIeAQYFggAIBYhBDHFFFqvpajfHB2yptR84F+hdaSZBQJj+4aD 10 | AhsMAAoJENR84F+hdaSZwhYA/25Cu7D8hIfeCTZ73FJPPqq7teaYQ2/ZvsODYDlF 11 | l8WxAQCytzKQP+vRX6Zh1xIXbYat50lsLyCjgE52J/EG8eiDAA== 12 | =HkB6 13 | -----END PGP PUBLIC KEY BLOCK----- 14 | -------------------------------------------------------------------------------- /rpc/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "rpc" 3 | version = "1.0.0" 4 | edition = "2021" 5 | authors = ["hinto.janai "] 6 | homepage = "https://festival.pm" 7 | documentation = "https://docs.rs/shukusai" 8 | repository = "https://github.com/hinto-janai/festival" 9 | keywords = ["music", "player", "audio", "festival", "shukusai"] 10 | categories = ["multimedia"] 11 | readme = "README.md" 12 | license = "MIT" 13 | description = "JSON-RPC 2.0 types for Festival" 14 | rust-version = "1.70" 15 | 16 | [dependencies] 17 | ### Personal Libraries. 18 | shukusai = { workspace = true, features = ["daemon", "panic"] } 19 | benri = { workspace = true } 20 | disk = { workspace = true } 21 | readable = { workspace = true } 22 | json-rpc = { workspace = true } 23 | 24 | ### Shared. 25 | anyhow = { workspace = true } 26 | bincode = { workspace = true } 27 | clap = { workspace = true } 28 | const_format = { workspace = true } 29 | compact_str = { workspace = true } 30 | crossbeam = { workspace = true } 31 | image = { workspace = true } 32 | log = { workspace = true } 33 | paste = { workspace = true } 34 | rand = { workspace = true } 35 | serde = { workspace = true } 36 | serde_json = { workspace = true } 37 | once_cell = { workspace = true } 38 | seq-macro = { workspace = true } 39 | strum = { workspace = true } 40 | termimad = { workspace = true } 41 | zeroize = { workspace = true } 42 | 43 | ### Regular libraries. 44 | base64 = { version = "0.21.2" } 45 | hex = { version = "0.4.3" } 46 | sha2 = { version = "0.10.7" } 47 | -------------------------------------------------------------------------------- /rpc/README.md: -------------------------------------------------------------------------------- 1 | # RPC 2 | These are Rust types that map to `JSON-RPC 2.0` data. 3 | 4 | It also contains some shared code between `festivald` & `festival-cli`, not for public use. 5 | 6 | For `festivald`'s JSON-RPC documentation, see [`daemon/`](https://github.com/hinto-janai/festival/tree/main/daemon). 7 | 8 | For `festival-cli`'s documentation, see [`cli/`](https://github.com/hinto-janai/festival/tree/main/cli). 9 | -------------------------------------------------------------------------------- /rpc/src/base64.rs: -------------------------------------------------------------------------------- 1 | //---------------------------------------------------------------------------------------------------- Use 2 | use base64::{ 3 | Engine, 4 | engine::general_purpose::STANDARD, 5 | }; 6 | use zeroize::Zeroize; 7 | 8 | //---------------------------------------------------------------------------------------------------- Base64 Encode 9 | /// 1. Takes in `String` input 10 | /// 2. Prefixes it with `Basic ` 11 | /// 3. Encodes it in `base64` 12 | pub fn encode_with_authorization_basic_header(mut input: String) -> String { 13 | let mut encode = STANDARD.encode(input.as_bytes()); 14 | 15 | input.zeroize(); 16 | 17 | let basic = format!("Basic {encode}"); 18 | 19 | encode.zeroize(); 20 | 21 | basic 22 | } 23 | 24 | //---------------------------------------------------------------------------------------------------- TESTS 25 | #[cfg(test)] 26 | mod tests { 27 | use super::*; 28 | 29 | #[test] 30 | fn encode() { 31 | const INPUT: &str = "my_username:my_password"; 32 | const EXPECTED: &str = "Basic bXlfdXNlcm5hbWU6bXlfcGFzc3dvcmQ="; 33 | 34 | let encoded = encode_with_authorization_basic_header(INPUT.into()); 35 | 36 | assert_eq!(encoded, EXPECTED); 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /rpc/src/lib.rs: -------------------------------------------------------------------------------- 1 | mod macros; 2 | 3 | mod method; 4 | pub use method::Method; 5 | pub use method::Rpc; 6 | 7 | /// Structs that represent the parameters of a [`Method`] 8 | pub mod param; 9 | 10 | /// Structs that represent the responses expected from a given [`Method`] 11 | pub mod resp; 12 | 13 | /// REST resources 14 | pub mod resource; 15 | 16 | /// Base64 operations 17 | pub mod base64; 18 | /// Hashing operations 19 | pub mod hash; 20 | -------------------------------------------------------------------------------- /rpc/src/resource.rs: -------------------------------------------------------------------------------- 1 | //---------------------------------------------------------------------------------------------------- Use 2 | use serde::{Serialize,Deserialize}; 3 | use anyhow::anyhow; 4 | use log::{error,info,warn,debug,trace}; 5 | use disk::{Bincode2,Json}; 6 | use strum::{ 7 | AsRefStr, 8 | Display, 9 | EnumCount, 10 | EnumIter, 11 | EnumString, 12 | EnumVariantNames, 13 | IntoStaticStr, 14 | }; 15 | 16 | //---------------------------------------------------------------------------------------------------- __NAME__ 17 | #[derive(Copy,Clone,Debug,Hash,PartialEq,Eq,PartialOrd,Ord,Serialize,Deserialize)] 18 | #[derive(AsRefStr,Display,EnumCount,EnumIter,EnumString,EnumVariantNames,IntoStaticStr)] 19 | #[strum(serialize_all = "snake_case")] 20 | #[serde(rename_all = "snake_case")] 21 | /// Enum of all the the "resources" provided by the REST API. 22 | pub enum Resource { 23 | Collection, 24 | Playlist, 25 | Artist, 26 | Album, 27 | Song, 28 | Art, 29 | } 30 | 31 | impl Resource { 32 | pub fn from_str_not_c(s: &str) -> Option { 33 | match s { 34 | "playlist" => Some(Self::Playlist), 35 | "artist" => Some(Self::Artist), 36 | "album" => Some(Self::Album), 37 | "song" => Some(Self::Song), 38 | "art" => Some(Self::Art), 39 | _ => None, 40 | } 41 | } 42 | } 43 | 44 | //---------------------------------------------------------------------------------------------------- TESTS 45 | //#[cfg(test)] 46 | //mod tests { 47 | // #[test] 48 | // fn __TEST__() { 49 | // } 50 | //} 51 | -------------------------------------------------------------------------------- /shukusai/CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # shukusai CHANGELOG 2 | The `cargo` version of `shukusai` is mostly meaningless. 3 | 4 | Practically, it acts as a "general" marker for when new things get implemented. 5 | 6 | This is mostly for personal reference so I can see when important internal changes get made. 7 | 8 | Types of changes: 9 | - `Added` for new features 10 | - `Changed` for changes in existing functionality 11 | - `Deprecated` for soon-to-be removed features 12 | - `Removed` for now removed features 13 | - `Fixed` for any bug fixes 14 | - `Security` in case of vulnerabilities 15 | - `Other` other note-worthy details 16 | 17 | --- 18 | 19 | # shukusai v0.0.5 20 | ## Added 21 | - `Song` field: `mime: Arc`, the `MIME` type of this `Song` 22 | - `Song` field: `extension: Arc`, the file extension of this `Song` 23 | - Public `JSON` definitions for various internal structures 24 | - `shukusai::collection::Entry`, similar to `shukusai::state::Entry` for playlists but includes `path: PathBuf` 25 | - Various new `Kernel` calls 26 | - `Search` for `Sim80`, `Sim60`, `Top5` 27 | 28 | ## Changed 29 | - `Collection v2` -> `Collection v3` 30 | 31 | ## Other 32 | - `festivald v1.0.0` & `festival-cli v1.0.0` start here, with `Collection v3`, `Audio v0`, `Playlists v0` 33 | 34 | --- 35 | -------------------------------------------------------------------------------- /shukusai/build.rs: -------------------------------------------------------------------------------- 1 | // This sets the git `COMMIT` environment variable. 2 | fn main() { 3 | println!("cargo:rerun-if-changed=../.git/refs/heads/"); 4 | 5 | let output = std::process::Command::new("git") 6 | .arg("rev-parse") 7 | .arg("HEAD") 8 | .output() 9 | .unwrap(); 10 | 11 | let commit = String::from_utf8(output.stdout).unwrap(); 12 | 13 | println!("cargo:rustc-env=COMMIT={commit}"); 14 | } 15 | -------------------------------------------------------------------------------- /shukusai/src/audio/mod.rs: -------------------------------------------------------------------------------- 1 | mod msg; 2 | pub(crate) use msg::*; 3 | 4 | mod audio; 5 | pub(crate) use audio::*; 6 | pub use audio::{PREVIOUS_THRESHOLD, PREVIOUS_THRESHOLD_DEFAULT}; 7 | 8 | // Public 9 | mod volume; 10 | pub use volume::Volume; 11 | mod append; 12 | pub use append::*; 13 | mod repeat; 14 | pub use repeat::*; 15 | mod seek; 16 | pub use seek::*; 17 | 18 | // Symphonia-related. 19 | pub(super) mod output; 20 | #[cfg(not(target_os = "linux"))] 21 | pub(super) mod resampler; 22 | 23 | // `souvlaki` Media Controls 24 | pub(super) mod media_controls; 25 | -------------------------------------------------------------------------------- /shukusai/src/audio/seek.rs: -------------------------------------------------------------------------------- 1 | //---------------------------------------------------------------------------------------------------- Use 2 | use bincode::{Decode, Encode}; 3 | use serde::{Deserialize, Serialize}; 4 | use strum::{AsRefStr, Display, EnumCount, EnumIter, EnumString, EnumVariantNames, IntoStaticStr}; 5 | 6 | //---------------------------------------------------------------------------------------------------- Seek 7 | #[derive( 8 | Copy, 9 | Clone, 10 | Debug, 11 | Hash, 12 | Eq, 13 | Ord, 14 | PartialEq, 15 | PartialOrd, 16 | Serialize, 17 | Deserialize, 18 | Encode, 19 | Decode, 20 | AsRefStr, 21 | Display, 22 | EnumCount, 23 | EnumIter, 24 | EnumString, 25 | EnumVariantNames, 26 | IntoStaticStr, 27 | )] 28 | #[strum(serialize_all = "snake_case")] 29 | #[serde(rename_all = "snake_case")] 30 | /// The different we can seek audio. 31 | pub enum Seek { 32 | /// Seek forwards a specified amount 33 | Forward, 34 | /// Seek backwards a specified amount 35 | Backward, 36 | /// Seek to an absolute second timestamp 37 | Absolute, 38 | } 39 | -------------------------------------------------------------------------------- /shukusai/src/ccd/img/mod.rs: -------------------------------------------------------------------------------- 1 | // Each `Frontend` will handle art differently. 2 | // These are the different implementations for each. 3 | 4 | #[cfg(feature = "gui")] 5 | mod gui; 6 | #[cfg(feature = "gui")] 7 | pub(crate) use gui::*; 8 | 9 | #[cfg(not(feature = "gui"))] 10 | #[cfg(feature = "daemon")] 11 | mod daemon; 12 | #[cfg(not(feature = "gui"))] 13 | #[cfg(feature = "daemon")] 14 | pub(crate) use daemon::*; 15 | -------------------------------------------------------------------------------- /shukusai/src/ccd/mod.rs: -------------------------------------------------------------------------------- 1 | mod mime; 2 | 3 | /// Collection creation performance 4 | pub mod perf; 5 | 6 | mod thread; 7 | pub(crate) use thread::*; 8 | 9 | mod msg; 10 | pub(crate) use msg::*; 11 | 12 | mod ccd; 13 | pub(crate) use ccd::*; 14 | 15 | //----- CCD internal functions. 16 | mod sort; 17 | mod the_loop; 18 | mod walk; 19 | 20 | //----- Frontend specific. 21 | mod img; 22 | pub(crate) use img::*; 23 | 24 | #[cfg(feature = "gui")] 25 | mod convert; 26 | #[cfg(feature = "gui")] 27 | pub(super) use convert::*; 28 | -------------------------------------------------------------------------------- /shukusai/src/ccd/msg.rs: -------------------------------------------------------------------------------- 1 | //---------------------------------------------------------------------------------------------------- Use 2 | use crate::{collection::Collection, state::Phase}; 3 | use std::sync::Arc; 4 | 5 | //---------------------------------------------------------------------------------------------------- Kernel Messages. 6 | // Since `CCD` stuff are one-shot operations, there's no 7 | // need for `Kernel` to have a channel since it can just start `CCD` 8 | // with a function specific to whatever job it needs to do: 9 | pub(crate) enum CcdToKernel { 10 | NewCollection(Arc), // Here's the new (or modified) `Collection`. 11 | UpdatePhase((f64, Phase)), // I'm starting a new phase. Set your `%` to this, and phase to this. 12 | UpdateIncrement((f64, Arc)), // Increment your `%` by this much, and update the working string to this. 13 | } 14 | 15 | //---------------------------------------------------------------------------------------------------- TESTS 16 | //#[cfg(test)] 17 | //mod tests { 18 | // #[test] 19 | // fn __TEST__() { 20 | // } 21 | //} 22 | -------------------------------------------------------------------------------- /shukusai/src/collection/art/mod.rs: -------------------------------------------------------------------------------- 1 | // Each `Frontend` will handle art differently. 2 | // These are the different implementations for each. 3 | 4 | #[cfg(feature = "gui")] 5 | mod gui; 6 | #[cfg(feature = "gui")] 7 | pub use gui::*; 8 | 9 | #[cfg(not(feature = "gui"))] 10 | #[cfg(feature = "daemon")] 11 | mod daemon; 12 | #[cfg(not(feature = "gui"))] 13 | #[cfg(feature = "daemon")] 14 | pub use daemon::*; 15 | -------------------------------------------------------------------------------- /shukusai/src/collection/image.rs: -------------------------------------------------------------------------------- 1 | //---------------------------------------------------------------------------------------------------- Use 2 | use crate::constants::{FESTIVAL, FRONTEND_SUB_DIR, IMAGE_SUB_DIR}; 3 | 4 | use const_format::formatcp; 5 | use serde::{Deserialize, Serialize}; 6 | 7 | //---------------------------------------------------------------------------------------------------- __NAME__ 8 | disk::plain!( 9 | Image, 10 | disk::Dir::Data, 11 | FESTIVAL, 12 | formatcp!("{FRONTEND_SUB_DIR}/{IMAGE_SUB_DIR}"), 13 | "timestamp.txt" 14 | ); 15 | #[derive(Copy, Clone, Debug, Default, PartialEq, PartialOrd, Serialize, Deserialize)] 16 | /// File representing resized images from the `Collection`. 17 | /// 18 | /// This file holds the timestamp of the `Collection` the images in the same directory refer too. 19 | /// 20 | /// This gets written within `festival/${FRONTEND}/image/` as `timestamp.txt`. 21 | /// 22 | /// Some other parts of Festival require a hard PATH 23 | /// to an image file to display it (`GUI` with `souvlaki`). 24 | /// 25 | /// So, `CCD` will write all the images contained in a newly created `Collection` 26 | /// to this cache location as individual files. The name of the files is just 27 | /// `AlbumKey.jpg` where `AlbumKey` is the actual internal index, e.g, if we 28 | /// were saving `AlbumKey(123)`, that album's art would be saved as `123.jpg`. 29 | /// 30 | /// This is optional and it isn't the end of the world if we don't have these images. 31 | pub struct Image(pub u64); 32 | -------------------------------------------------------------------------------- /shukusai/src/collection/mod.rs: -------------------------------------------------------------------------------- 1 | mod album; 2 | mod art; 3 | mod artist; 4 | mod collection; 5 | mod entry; 6 | mod image; 7 | mod key; 8 | mod map; 9 | mod plural; 10 | mod song; 11 | pub use crate::collection::image::*; 12 | pub use album::*; 13 | pub use art::*; 14 | pub use artist::*; 15 | pub use collection::*; 16 | pub use entry::*; 17 | pub use key::*; 18 | pub use map::*; 19 | pub use plural::*; 20 | pub use song::*; 21 | 22 | mod metadata; 23 | pub use metadata::metadata; 24 | 25 | // Previous Collection versions. 26 | #[cfg(feature = "gui")] 27 | pub(crate) mod v0; 28 | #[cfg(feature = "gui")] 29 | pub(crate) mod v1; 30 | #[cfg(feature = "gui")] 31 | pub(crate) mod v2; 32 | 33 | /// `struct` representations for JSON output 34 | pub mod json; 35 | /// 1:1 copies of JSON-RPC calls 36 | pub mod rpc; 37 | 38 | // Pointer related code. To be used... eventually... maybe. 39 | //mod decode; 40 | //pub(crate) use decode::*; 41 | //mod ptr; 42 | //pub(crate) use ptr::*; 43 | 44 | // Playlist/Queue code. To be used SOMEDAY. 45 | //mod slice; 46 | //pub use slice::*; 47 | -------------------------------------------------------------------------------- /shukusai/src/collection/rpc.rs: -------------------------------------------------------------------------------- 1 | //---------------------------------------------------------------------------------------------------- Use 2 | use crate::collection::Collection; 3 | use disk::Bincode2; 4 | 5 | //---------------------------------------------------------------------------------------------------- 6 | /// Read `Collection` from disk, output same output as the `state_collection_full` JSON-RPC call. 7 | pub fn state_collection_full() -> Result { 8 | // SAFETY: memmap is used. 9 | let collection = unsafe { Collection::from_file_memmap() }?; 10 | 11 | Ok(serde_json::to_string_pretty(&collection)?) 12 | } 13 | -------------------------------------------------------------------------------- /shukusai/src/collection/v0/README.md: -------------------------------------------------------------------------------- 1 | # Collection0 2 | This is version 0 of the `Collection`. The struct isn't name `Collection0` since there's so many recursive structs, so instead a simple namespace `v0::` prefix will be used. 3 | 4 | This code and data definitions exist here solely for backwards compatibility. 5 | -------------------------------------------------------------------------------- /shukusai/src/collection/v0/map.rs: -------------------------------------------------------------------------------- 1 | //---------------------------------------------------------------------------------------------------- Use 2 | use crate::collection::v0::{Album, Artist, Song}; 3 | use crate::collection::{AlbumKey, ArtistKey, SongKey}; 4 | use bincode::{Decode, Encode}; 5 | use serde::{Deserialize, Serialize}; 6 | use std::collections::HashMap; 7 | 8 | //---------------------------------------------------------------------------------------------------- Map 9 | #[derive(Clone, Debug, Default, Serialize, Deserialize, PartialEq, Encode, Decode)] 10 | #[serde(transparent)] 11 | /// A [`HashMap`] that knows all [`Artist`]'s, [`Album`]'s and [`Song`]'s. 12 | /// 13 | /// No public functions are implemented on this type directly, 14 | /// use [`Collection`]'s functions instead. 15 | pub(crate) struct Map(pub(crate) HashMap); 16 | 17 | impl Map { 18 | #[inline(always)] 19 | pub(crate) fn new() -> Self { 20 | Self::default() 21 | } 22 | } 23 | 24 | //---------------------------------------------------------------------------------------------------- AlbumMap 25 | #[derive(Clone, Debug, Default, Serialize, Deserialize, PartialEq, Encode, Decode)] 26 | #[serde(transparent)] 27 | pub(crate) struct AlbumMap(pub(crate) HashMap); 28 | 29 | //---------------------------------------------------------------------------------------------------- SongMap 30 | #[derive(Clone, Debug, Default, Serialize, Deserialize, PartialEq, Encode, Decode)] 31 | #[serde(transparent)] 32 | pub(crate) struct SongMap(pub(crate) HashMap); 33 | -------------------------------------------------------------------------------- /shukusai/src/collection/v0/mod.rs: -------------------------------------------------------------------------------- 1 | mod album; 2 | pub(crate) use album::*; 3 | mod artist; 4 | pub(crate) use artist::*; 5 | mod art; 6 | pub(crate) use art::*; 7 | mod collection; 8 | pub(crate) use collection::*; 9 | mod map; 10 | pub(crate) use map::*; 11 | mod plural; 12 | pub(crate) use plural::*; 13 | mod song; 14 | pub(crate) use song::*; 15 | -------------------------------------------------------------------------------- /shukusai/src/collection/v1/README.md: -------------------------------------------------------------------------------- 1 | # Collection1 2 | This is version 1 of the `Collection`. 3 | 4 | This code and data definitions exist here solely for backwards compatibility. 5 | 6 | Things added in `v2` that need conversion from `v1`: 7 | 8 | - `key: ArtistKey` in `Artist` 9 | - `key: AlbumKey` in `Album` 10 | - `key: SongKey` in `Song` 11 | - `genre: Option>` in `Album` 12 | 13 | `festivald` & `festival-cli` & `rpc/` all also started on `Collection2`. 14 | 15 | This means the public JSON API of those things are defined in `Collection2`. 16 | -------------------------------------------------------------------------------- /shukusai/src/collection/v1/mod.rs: -------------------------------------------------------------------------------- 1 | mod album; 2 | pub(crate) use album::*; 3 | mod artist; 4 | pub(crate) use artist::*; 5 | mod collection; 6 | pub(crate) use collection::*; 7 | mod song; 8 | pub(crate) use song::*; 9 | mod plural; 10 | pub(crate) use plural::*; 11 | -------------------------------------------------------------------------------- /shukusai/src/collection/v2/README.md: -------------------------------------------------------------------------------- 1 | # Collection2 2 | This is version 2 of the `Collection`. 3 | 4 | This code and data definitions exist here solely for backwards compatibility. 5 | 6 | Things added in `v3` that need conversion from `v2`: 7 | 8 | - `mime: Arc` in `Song` 9 | - `extension: Arc` in `Song` 10 | 11 | `festivald` & `festival-cli` & `rpc/` all also started on `Collection3`. 12 | 13 | This means the public JSON API of those things are defined in `Collection3`. 14 | -------------------------------------------------------------------------------- /shukusai/src/collection/v2/mod.rs: -------------------------------------------------------------------------------- 1 | mod album; 2 | pub(crate) use album::*; 3 | mod artist; 4 | pub(crate) use artist::*; 5 | mod collection; 6 | pub(crate) use collection::*; 7 | mod song; 8 | pub(crate) use song::*; 9 | mod plural; 10 | pub(crate) use plural::*; 11 | -------------------------------------------------------------------------------- /shukusai/src/frontend/daemon.rs: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /shukusai/src/frontend/mod.rs: -------------------------------------------------------------------------------- 1 | /// `festival-gui`-specific 2 | #[cfg(feature = "gui")] 3 | pub mod gui; 4 | 5 | /// `festivald`-specific 6 | #[cfg(feature = "daemon")] 7 | pub mod daemon; 8 | 9 | /// `festival-web`-specific 10 | #[cfg(feature = "web")] 11 | pub mod web; 12 | -------------------------------------------------------------------------------- /shukusai/src/frontend/web.rs: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /shukusai/src/kernel/mod.rs: -------------------------------------------------------------------------------- 1 | mod kernel; 2 | pub use kernel::*; 3 | 4 | mod msg; 5 | pub use msg::*; 6 | -------------------------------------------------------------------------------- /shukusai/src/macros.rs: -------------------------------------------------------------------------------- 1 | macro_rules! assert_size_of { 2 | ($($type:ty => $size:expr),*) => { 3 | $( 4 | assert_eq!(std::mem::size_of::<$type>(), $size); 5 | )* 6 | }; 7 | } 8 | pub(crate) use assert_size_of; 9 | -------------------------------------------------------------------------------- /shukusai/src/search/mod.rs: -------------------------------------------------------------------------------- 1 | mod msg; 2 | pub(crate) use msg::*; 3 | 4 | mod search; 5 | pub(crate) use search::*; 6 | 7 | mod kind; 8 | pub use kind::*; 9 | -------------------------------------------------------------------------------- /shukusai/src/search/msg.rs: -------------------------------------------------------------------------------- 1 | //---------------------------------------------------------------------------------------------------- Use 2 | use crate::collection::{Collection, Keychain}; 3 | use crate::search::SearchKind; 4 | use std::sync::Arc; 5 | 6 | //---------------------------------------------------------------------------------------------------- Kernel Messages. 7 | pub(crate) enum SearchToKernel { 8 | // Here's the search (similarity) response. 9 | Resp(Keychain), 10 | } 11 | 12 | pub(crate) enum KernelToSearch { 13 | Search((String, SearchKind)), // Start a search on string input. 14 | // NewCache(String), // Here's a new `String` key from a recently created `Collection`, add it to your cache. 15 | // NewCacheVec(Vec), // Here's a `Vec` of `String` keys, add it to cache 16 | DropCollection, // Drop your pointer. 17 | NewCollection(Arc), // Here's a new `Collection` pointer. 18 | } 19 | 20 | //---------------------------------------------------------------------------------------------------- TESTS 21 | //#[cfg(test)] 22 | //mod tests { 23 | // #[test] 24 | // fn __TEST__() { 25 | // } 26 | //} 27 | -------------------------------------------------------------------------------- /shukusai/src/sort/mod.rs: -------------------------------------------------------------------------------- 1 | mod sort; 2 | pub use sort::*; 3 | -------------------------------------------------------------------------------- /shukusai/src/state/mod.rs: -------------------------------------------------------------------------------- 1 | mod audio; 2 | pub use audio::*; 3 | 4 | mod reset; 5 | pub use reset::*; 6 | 7 | mod statics; 8 | pub use statics::*; 9 | 10 | mod phase; 11 | pub use phase::*; 12 | 13 | mod playlist; 14 | pub use playlist::*; 15 | -------------------------------------------------------------------------------- /shukusai/src/watch/mod.rs: -------------------------------------------------------------------------------- 1 | mod watch; 2 | pub(crate) use watch::*; 3 | 4 | mod msg; 5 | pub(crate) use msg::*; 6 | -------------------------------------------------------------------------------- /shukusai/src/watch/msg.rs: -------------------------------------------------------------------------------- 1 | use crate::audio::Volume; 2 | 3 | //---------------------------------------------------------------------------------------------------- Kernel Messages. 4 | #[derive(Debug, PartialEq, Eq)] 5 | pub(crate) enum WatchToKernel { 6 | // Signals. 7 | Toggle, // Toggle playback. 8 | Play, // Play playback (ignored if already). 9 | Pause, // Pause playback (ignored if already). 10 | Next, // Skip to next song in queue. 11 | Previous, // Skip to previous song in queue. 12 | Stop, // Clear queue and stop playback. 13 | 14 | // Shuffle. 15 | Shuffle, 16 | 17 | // Repeat. 18 | RepeatSong, 19 | RepeatQueue, 20 | RepeatOff, 21 | 22 | // Content signals. 23 | Volume(Volume), 24 | Clear(bool), 25 | Seek(u64), 26 | SeekForward(u64), 27 | SeekBackward(u64), 28 | Index(usize), 29 | Skip(usize), 30 | Back(usize), 31 | // ArtistKey(usize), 32 | // AlbumKey(usize), 33 | // SongKey(usize), 34 | // Artist(String), 35 | // Album(String), 36 | // Song(String), 37 | } 38 | 39 | //---------------------------------------------------------------------------------------------------- TESTS 40 | //#[cfg(test)] 41 | //mod tests { 42 | // #[test] 43 | // fn __TEST__() { 44 | // } 45 | //} 46 | -------------------------------------------------------------------------------- /tui/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "festival-tui" 3 | version = "0.0.0" 4 | edition = "2021" 5 | authors = ["hinto.janai "] 6 | homepage = "https://festival.pm" 7 | documentation = "https://docs.rs/shukusai" 8 | repository = "https://github.com/hinto-janai/festival" 9 | keywords = ["music", "player", "audio", "festival", "shukusai"] 10 | categories = ["multimedia"] 11 | readme = "README.md" 12 | license = "MIT" 13 | description = "Music player TUI" 14 | rust-version = "1.70" 15 | 16 | [dependencies] 17 | -------------------------------------------------------------------------------- /tui/README.md: -------------------------------------------------------------------------------- 1 | # `festival-tui` 2 | Standalone TUI. 3 | 4 | Not yet implemented. 5 | -------------------------------------------------------------------------------- /tui/src/main.rs: -------------------------------------------------------------------------------- 1 | fn main() { 2 | println!("not yet implemented"); 3 | } 4 | -------------------------------------------------------------------------------- /typos.toml: -------------------------------------------------------------------------------- 1 | [default] 2 | extend-ignore-identifiers-re = [ 3 | "seeked", 4 | "Seeked", 5 | ] 6 | 7 | [files] 8 | extend-exclude = [ 9 | # Doc output. 10 | "daemon/mdbook/docs/", 11 | "gui/mdbook/docs/", 12 | "cli/mdbook/docs/", 13 | 14 | "daemon/src/cert.rs", 15 | "external/", 16 | ] 17 | -------------------------------------------------------------------------------- /utils/Festival.AppDir/.DirIcon: -------------------------------------------------------------------------------- 1 | festival.png -------------------------------------------------------------------------------- /utils/Festival.AppDir/AppRun: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hinto-janai/festival/8d7e26d55e7677e3d38d6c51c51683830e9cbd61/utils/Festival.AppDir/AppRun -------------------------------------------------------------------------------- /utils/Festival.AppDir/festival.desktop: -------------------------------------------------------------------------------- 1 | [Desktop Entry] 2 | Name=Festival 3 | GenericName=Music player 4 | Comment=A music player for local album collections 5 | Exec=Festival 6 | Icon=festival 7 | Type=Application 8 | Categories=AudioVideo;Audio;Player; 9 | StartupWMClass=Festival 10 | Terminal=false 11 | -------------------------------------------------------------------------------- /utils/Festival.AppDir/festival.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hinto-janai/festival/8d7e26d55e7677e3d38d6c51c51683830e9cbd61/utils/Festival.AppDir/festival.png -------------------------------------------------------------------------------- /utils/Festival.AppDir/usr/bin/Festival: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hinto-janai/festival/8d7e26d55e7677e3d38d6c51c51683830e9cbd61/utils/Festival.AppDir/usr/bin/Festival -------------------------------------------------------------------------------- /utils/Festival.AppDir/usr/share/metainfo/festival.appdata.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | pm.festival.Festival 4 | 5 | Festival 6 | Music player 7 | 8 | MIT 9 | MIT 10 | 11 | 12 | 1280 13 | 14 | 15 | 16 |

17 | Music player. 18 |

19 |
20 | 21 | festival.desktop 22 |
23 | -------------------------------------------------------------------------------- /utils/Festival.app.skel/Contents/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | English 7 | CFBundleDisplayName 8 | Festival 9 | CFBundleExecutable 10 | festival 11 | CFBundleIconFile 12 | Festival.icns 13 | CFBundleIdentifier 14 | pm.festival.Festival 15 | CFBundleInfoDictionaryVersion 16 | 6.0 17 | CFBundleName 18 | Festival 19 | CFBundlePackageType 20 | APPL 21 | CFBundleShortVersionString 22 | 1.2.3 23 | CFBundleVersion 24 | 20230604.130639 25 | CSResourcesFileMapped 26 | 27 | LSApplicationCategoryType 28 | public.app-category.utilities 29 | LSRequiresCarbon 30 | 31 | NSHighResolutionCapable 32 | 33 | 34 | 35 | -------------------------------------------------------------------------------- /utils/Festival.app.skel/Contents/MacOS/festival: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hinto-janai/festival/8d7e26d55e7677e3d38d6c51c51683830e9cbd61/utils/Festival.app.skel/Contents/MacOS/festival -------------------------------------------------------------------------------- /utils/Festival.app.skel/Contents/Resources/Festival.icns: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hinto-janai/festival/8d7e26d55e7677e3d38d6c51c51683830e9cbd61/utils/Festival.app.skel/Contents/Resources/Festival.icns -------------------------------------------------------------------------------- /utils/Festival.dmg.skel/Applications: -------------------------------------------------------------------------------- 1 | /Applications -------------------------------------------------------------------------------- /utils/README.md: -------------------------------------------------------------------------------- 1 | ## Utilities 2 | Some utility scripts. 3 | 4 | | File/Folder | Purpose | 5 | |--------------------|---------| 6 | | Festival.AppDir | Skeleton `.AppDir` for creating an `.AppImage` for Linux 7 | | longest.sh | Find the longest PATH and line count file in the repo 8 | | skel | A skeleton directory with the proper naming scheme + folder structure for packaging for all OS's 9 | | mk_appimage.sh | Create a `Festival.AppImage` from the `Festival.AppDir` 10 | | mk_app.sh | Create a macOS `Festival.app` 11 | | mk_dmg.sh | Create a macOS `.dmg` from the above `Festival.app` 12 | | mk_tmpenv.sh | Copy `skel/` to `/tmp` with the packaging scripts 13 | | package.sh | Package the contents of `skel`, sign, etc. Checks if all files exist and have the proper naming schemes 14 | | prepare.sh | Changes version across repo, commits README.md + CHANGELOG.md 15 | -------------------------------------------------------------------------------- /utils/longest.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | # Finds the longest PATH and file with 4 | # the most amount of lines in this repo. 5 | # This is used for left-padding the filename 6 | # in the `shukusai/src/logger.rs` file. 7 | 8 | # Exit on failure. 9 | set -e 10 | 11 | # `cd` to root. 12 | [[ $PWD == */festival/utils ]] && cd .. 13 | [[ $PWD == */festival ]] 14 | 15 | # Use `fd` if found. 16 | if [[ -f /usr/bin/fd ]]; then 17 | FIND=$(fd .*.rs "cli" "daemon" "gui" "web" "shukusai") 18 | else 19 | FIND=$(find "cli" "daemon" "gui" "web" "shukusai" -type f -iname *.rs) 20 | fi 21 | 22 | # PATH. 23 | echo "Longest PATH" 24 | echo "$FIND" | awk '{ print length(), $0 | "sort -n" }' | tail -n 1 25 | 26 | # Lines. 27 | echo 28 | echo "Most lines" 29 | wc -l $FIND | sort -h | tail -n 2 | head -n 1 30 | -------------------------------------------------------------------------------- /utils/mk_dmg.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | # Make a `Festival-${VERSION}.dmg` out of the `Festival.app` for macOS. 4 | # 5 | # This assumes you're running on macOS. 6 | 7 | set -ex 8 | 9 | # Check current directory. 10 | [[ $PWD == */festival ]] && cd utils 11 | [[ $PWD == */festival/utils ]] 12 | 13 | # Set variables. 14 | VERSION="$(grep -m1 "version" ../gui/Cargo.toml | grep -o "[0-9].[0-9].[0-9]")" 15 | APP="${PWD}/Festival.app" 16 | 17 | [[ $1 ]] && DMG="$1" || DMG="Festival-${VERSION}.dmg" 18 | 19 | # Remove old `.dmg` 20 | [[ -e $DMG ]] && rm -r "$DMG" 21 | 22 | # Create `.dmg` 23 | hdiutil create -fs HFS+ -srcfolder Festival.app -volname "Festival-${VERSION}" "$DMG" 24 | 25 | # Wipe binary. 26 | rm "${APP}/Contents/MacOS/festival" 27 | touch "${APP}/Contents/MacOS/festival" 28 | -------------------------------------------------------------------------------- /utils/prepare.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | # prepare new [festival] version in: 4 | # 1. README.md 5 | # 2. CHANGELOG.md 6 | # 3. Cargo.toml 7 | 8 | # $1 = new_version 9 | set -ex 10 | sudo -v 11 | [[ $1 = v* ]] 12 | [[ $PWD = */festival/utils ]] && cd .. 13 | [[ $PWD = */festival ]] 14 | 15 | # get old FESTIVAL_VER 16 | OLD_VER="v$(grep -m1 "version" Cargo.toml | grep -o "[0-9].[0-9].[0-9]")" 17 | OLD_VER_NUM="$(grep -m1 "version" Cargo.toml | grep -o "[0-9].[0-9].[0-9]")" 18 | 19 | # sed change 20 | sed -i "s/$OLD_VER/$1/g" README.md 21 | sed -i "s/^version = \"$OLD_VER_NUM\"/version = \"$1\"/" Cargo.toml 22 | 23 | # changelog 24 | cat << EOM > CHANGELOG.md.new 25 | # $1 26 | ## Updates 27 | * 28 | 29 | ## Fixes 30 | * 31 | 32 | 33 | --- 34 | 35 | 36 | EOM 37 | cat CHANGELOG.md >> CHANGELOG.md.new 38 | mv -f CHANGELOG.md.new CHANGELOG.md 39 | 40 | # commit 41 | git add CHANGELOG.md README.md 42 | git commit -m "prepare $1" 43 | -------------------------------------------------------------------------------- /web/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "festival-web" 3 | version = "0.0.0" 4 | edition = "2021" 5 | authors = ["hinto.janai "] 6 | homepage = "https://festival.pm" 7 | documentation = "https://docs.rs/shukusai" 8 | repository = "https://github.com/hinto-janai/festival" 9 | keywords = ["music", "player", "audio", "festival", "shukusai"] 10 | categories = ["multimedia"] 11 | readme = "README.md" 12 | license = "MIT" 13 | description = "Music player (web client)" 14 | rust-version = "1.70" 15 | 16 | [dependencies] 17 | -------------------------------------------------------------------------------- /web/README.md: -------------------------------------------------------------------------------- 1 | # `festival-web` 2 | `Festival` web server. 3 | 4 | Not yet implemented. 5 | -------------------------------------------------------------------------------- /web/src/main.rs: -------------------------------------------------------------------------------- 1 | fn main() { 2 | println!("not yet implemented"); 3 | } 4 | --------------------------------------------------------------------------------