# Technical Documentation: clangen/musikcube > ℹ️ **Provenance:** Hybrid Fusion: `clangen/musikcube` (README + 5 In-Tree Chapters) · [CodeWiki Reference](https://codewiki.google/github.com/clangen/musikcube) · Recency: Active (< 180 days) ## 1. Project Overview & Quickstart (clangen/musikcube) # musikcube a cross-platform, terminal-based audio engine, library, player and server written in c++. musikcube compiles and runs easily on windows, macos and linux. it also runs well on a raspberry pi with raspbian, and can be setup as a streaming audio server. check out the [installation guide](https://github.com/clangen/musikcube/wiki/installing) to get up and running. be sure to also read through a [the user guide](https://github.com/clangen/musikcube/wiki/user-guide), which describes app's navigation paradigm and lists all the default keyboard shortcuts. if you want to build it from source, [the instructions are here](https://github.com/clangen/musikcube/wiki/building). # screenshots it looks something like this on windows: and this on macos: and on linux: here's a demo (made with asciinema): [](https://asciinema.org/a/129748) while the main musikcube app runs in the console, you can also stream audio from (and even remote control) musikcube using the `musikdroid` android app, which can be downloaded in the `releases` section above. it looks like this: # installation binaries are available in the [releases](https://github.com/clangen/musikcube/releases) page. while macos binaries are provided, you can also install via homebrew as follows: - `brew install musikcube` on freebsd musikcube can be installed as follows: - `pkg install musikcube` on openbsd musikcube can be installed as follows: - `pkg_add install musikcube` on windows, you can install via chocolatey: - `choco install musikcube` then run using shell, Win+R dialog or by typing in Start Menu `musikcube` or `mcube`. # raspberry pi musikcube runs well on a raspberry pi, connected to your home stereo. [see here for detailed setup instructions](https://github.com/clangen/musikcube/wiki/raspberry-pi). # compiling if you'd like to compile the project yourself, you can check out the [build instructions](https://github.com/clangen/musikcube/wiki/building). # keyboard shortcuts a list of all keyboard shortcuts can be found in the [user guide](https://github.com/clangen/musikcube/wiki/user-guide) # streaming server musikcube ships with a streaming audio server enabled by default. it runs a websocket server on port 7905, used for metadata retrieval. an http server runs on port 7906, and is used to serve (optionally transcoded) audio data to clients. **it's important to understand that, out of the box, the server (and remote api) should NOT be considered safe for use outside of a local network**. the websockets service only supports a simple password challenge, and the audio http server just handles Basic authorization. it does not provide ssl or tls. the server also stores the password in plain text in a settings file on the local machine. you can fix some of this using a reverse proxy to provide ssl termination. details in the [ssl-server-setup section](https://github.com/clangen/musikcube/wiki/ssl-server-setup). while this improves things, you should exercise caution exposing these services over the internet. if you're interested in writing your own frontend, [api documentation is available here](https://github.com/clangen/musikcube/wiki/remote-api-documentation). # sdk the musikcube sdk is a set of small, pure-virtual c++ classes and a handful of enums and constants. they're still in the process of being slimmed down. you can see what they currently look like here: https://github.com/clangen/musikcube/tree/master/src/musikcore/sdk # dependencies musikcube would not be possible without the following excellent free, open source, and (in the case of some macos and win32 APIs) non-free projects and libraries: | core | decoders | outputs | metadata | networking | miscellaneous | ui | |-----------------------------------------------------------|-----------------------------------------------------------------|------------------------------------------------------------------------------------------------------------------------------------------------|--------------------------------------------|--------------------------------------------------------------------------------|--------------------------------------------------------------------|---------------------------------------------------------------------------| | [sqlite](https://www.sqlite.org/) | [ffmpeg](https://ffmpeg.org/) | [alsa](https://www.alsa-project.org) | [taglib](http://taglib.org/) | [websocketpp](https://github.com/zaphoyd/websocketpp) | [rxjava](https://github.com/ReactiveX/RxJava) | [ncurses](https://www.gnu.org/software/ncurses/) | | [utfcpp](https://github.com/nemtrif/utfcpp) | [libopenmpt](https://lib.openmpt.org/libopenmpt/) | [pulseaudio](https://www.freedesktop.org/wiki/Software/PulseAudio/) | [glide](https://github.com/bumptech/glide) | [libmicrohttpd](https://www.gnu.org/software/libmicrohttpd/) | [rxandroid](https://github.com/ReactiveX/RxAndroid) | [pdcurses (win32a variant)](https://www.projectpluto.com/win32a.htm) | | [nlohmann json](https://github.com/nlohmann/json) | [libgme](https://bitbucket.org/mpyne/game-music-emu/wiki/Home) | [core audio](https://developer.apple.com/library/content/documentation/MusicAudio/Conceptual/CoreAudioOverview/Introduction/Introduction.html) | | [libcurl](https://curl.haxx.se/libcurl/) | [stetho](http://facebook.github.io/stetho/) | [recycler-fast-scroll](https://github.com/plusCubed/recycler-fast-scroll) | | [kissfft](http://kissfft.sourceforge.net/) | [exoplayer](https://github.com/google/ExoPlayer) | [wasapi](https://msdn.microsoft.com/en-us/library/windows/desktop/dd371455(v=vs.85).aspx) | | [openssl](https://www.openssl.org/ ) | [fabric](http://fabric.io) | | | [sigslot](http://sigslot.sourceforge.net/) | | [directsound](https://msdn.microsoft.com/en-us/library/windows/desktop/ee416960(v=vs.85).aspx) | | [nv-websocket-client](https://github.com/TakahikoKawasaki/nv-websocket-client) | [AndroidVideoCache](https://github.com/danikula/AndroidVideoCache) | | | [wcwidth.c](http://www.cl.cam.ac.uk/~mgk25/ucs/wcwidth.c) | | [waveout](https://msdn.microsoft.com/en-us/library/windows/desktop/dd743876(v=vs.85).aspx) | | [okhttp](http://square.github.io/okhttp/) | | | | | | [pipewire](https://pipewire.org/) | | | | | # license ``` Copyright (c) 2004-2023 musikcube team All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. * Neither the name of the author nor the names of other contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ``` ## 2. In-Tree Documentation Chapters (clangen/musikcube) ## File: README.md # musikcube a cross-platform, terminal-based audio engine, library, player and server written in c++. musikcube compiles and runs easily on windows, macos and linux. it also runs well on a raspberry pi with raspbian, and can be setup as a streaming audio server. check out the [installation guide](https://github.com/clangen/musikcube/wiki/installing) to get up and running. be sure to also read through a [the user guide](https://github.com/clangen/musikcube/wiki/user-guide), which describes app's navigation paradigm and lists all the default keyboard shortcuts. if you want to build it from source, [the instructions are here](https://github.com/clangen/musikcube/wiki/building). # screenshots it looks something like this on windows: and this on macos: and on linux: here's a demo (made with asciinema): [](https://asciinema.org/a/129748) while the main musikcube app runs in the console, you can also stream audio from (and even remote control) musikcube using the `musikdroid` android app, which can be downloaded in the `releases` section above. it looks like this: # installation binaries are available in the [releases](https://github.com/clangen/musikcube/releases) page. while macos binaries are provided, you can also install via homebrew as follows: - `brew install musikcube` on freebsd musikcube can be installed as follows: - `pkg install musikcube` on openbsd musikcube can be installed as follows: - `pkg_add install musikcube` on windows, you can install via chocolatey: - `choco install musikcube` then run using shell, Win+R dialog or by typing in Start Menu `musikcube` or `mcube`. # raspberry pi musikcube runs well on a raspberry pi, connected to your home stereo. [see here for detailed setup instructions](https://github.com/clangen/musikcube/wiki/raspberry-pi). # compiling if you'd like to compile the project yourself, you can check out the [build instructions](https://github.com/clangen/musikcube/wiki/building). # keyboard shortcuts a list of all keyboard shortcuts can be found in the [user guide](https://github.com/clangen/musikcube/wiki/user-guide) # streaming server musikcube ships with a streaming audio server enabled by default. it runs a websocket server on port 7905, used for metadata retrieval. an http server runs on port 7906, and is used to serve (optionally transcoded) audio data to clients. **it's important to understand that, out of the box, the server (and remote api) should NOT be considered safe for use outside of a local network**. the websockets service only supports a simple password challenge, and the audio http server just handles Basic authorization. it does not provide ssl or tls. the server also stores the password in plain text in a settings file on the local machine. you can fix some of this using a reverse proxy to provide ssl termination. details in the [ssl-server-setup section](https://github.com/clangen/musikcube/wiki/ssl-server-setup). while this improves things, you should exercise caution exposing these services over the internet. if you're interested in writing your own frontend, [api documentation is available here](https://github.com/clangen/musikcube/wiki/remote-api-documentation). # sdk the musikcube sdk is a set of small, pure-virtual c++ classes and a handful of enums and constants. they're still in the process of being slimmed down. you can see what they currently look like here: https://github.com/clangen/musikcube/tree/master/src/musikcore/sdk # dependencies musikcube would not be possible without the following excellent free, open source, and (in the case of some macos and win32 APIs) non-free projects and libraries: | core | decoders | outputs | metadata | networking | miscellaneous | ui | |-----------------------------------------------------------|-----------------------------------------------------------------|------------------------------------------------------------------------------------------------------------------------------------------------|--------------------------------------------|--------------------------------------------------------------------------------|--------------------------------------------------------------------|---------------------------------------------------------------------------| | [sqlite](https://www.sqlite.org/) | [ffmpeg](https://ffmpeg.org/) | [alsa](https://www.alsa-project.org) | [taglib](http://taglib.org/) | [websocketpp](https://github.com/zaphoyd/websocketpp) | [rxjava](https://github.com/ReactiveX/RxJava) | [ncurses](https://www.gnu.org/software/ncurses/) | | [utfcpp](https://github.com/nemtrif/utfcpp) | [libopenmpt](https://lib.openmpt.org/libopenmpt/) | [pulseaudio](https://www.freedesktop.org/wiki/Software/PulseAudio/) | [glide](https://github.com/bumptech/glide) | [libmicrohttpd](https://www.gnu.org/software/libmicrohttpd/) | [rxandroid](https://github.com/ReactiveX/RxAndroid) | [pdcurses (win32a variant)](https://www.projectpluto.com/win32a.htm) | | [nlohmann json](https://github.com/nlohmann/json) | [libgme](https://bitbucket.org/mpyne/game-music-emu/wiki/Home) | [core audio](https://developer.apple.com/library/content/documentation/MusicAudio/Conceptual/CoreAudioOverview/Introduction/Introduction.html) | | [libcurl](https://curl.haxx.se/libcurl/) | [stetho](http://facebook.github.io/stetho/) | [recycler-fast-scroll](https://github.com/plusCubed/recycler-fast-scroll) | | [kissfft](http://kissfft.sourceforge.net/) | [exoplayer](https://github.com/google/ExoPlayer) | [wasapi](https://msdn.microsoft.com/en-us/library/windows/desktop/dd371455(v=vs.85).aspx) | | [openssl](https://www.openssl.org/ ) | [fabric](http://fabric.io) | | | [sigslot](http://sigslot.sourceforge.net/) | | [directsound](https://msdn.microsoft.com/en-us/library/windows/desktop/ee416960(v=vs.85).aspx) | | [nv-websocket-client](https://github.com/TakahikoKawasaki/nv-websocket-client) | [AndroidVideoCache](https://github.com/danikula/AndroidVideoCache) | | | [wcwidth.c](http://www.cl.cam.ac.uk/~mgk25/ucs/wcwidth.c) | | [waveout](https://msdn.microsoft.com/en-us/library/windows/desktop/dd743876(v=vs.85).aspx) | | [okhttp](http://square.github.io/okhttp/) | | | | | | [pipewire](https://pipewire.org/) | | | | | # license ``` Copyright (c) 2004-2023 musikcube team All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. * Neither the name of the author nor the names of other contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ``` --- ## File: doc/build-standalone-unix.md # Overview By default when you build `musikcube` it's almost exclusively tied to your Linux distribution and version. If you try to copy the binaries compiled from `Ubuntu` to `Fedora`, for example, they probably won't work. It turns out that building a single C++ app once that works across many Linux distributions and versions can be very challenging, especially when there are external dependencies involved. The difficulties have been documented and discussed countless times and include, but are not limited to: 1. Incompatible `GLIBC`/`GLIBCXX` versions 2. Incompatible versions of required dependencies 3. Incompatible locations of required dependencies (e.g. `/lib` vs `/usr/lib` vs `/usr/local/lib`) 4. Incompatible filenames for required depdencies (eg `libfoo.so.3` vs `libfoo.so`) 5. General unavailability of required dependencies (i.e. "dependency `foo` doesn't exist in `Ubuntu`'s `apt`") In an ideal world we wouldn't have to worry about these problems, and `musikcube` would be available via all major Linux distribution package management systems. In practice, however, it's not. It can take tremendous time and effort to get packages accepted upstream by maintainers. For example, see the [DebianMentorsFaq](https://wiki.debian.org/DebianMentorsFaq). So, for now, we've developed a process that allows us to compile "generic" binaries once per CPU architecture that should generally work across most modern Linux distributions without hassle. In short, we do the following: 1. Compile using an operating system with versions of `GLIBC` and `GLIBCXX` that should work on any Linux distribution from 2018 to now. We currently use `Debian Buster`. 2. Include modern versions of fundamental dependencies (`openssl`, `curl`, `ffmpeg` and others), compiled from source, omitting any unused/extraneous functionality. 3. Ensure the app is "relocatable" on the filesystem; all libraries are loaded via relative paths so you can put the `musikcube` directory wherever you want and it'll still run. This is done by manually rewriting `rpath` values for shared libraries and executables where necessary. The rest of this document will describe how we produce these builds, which are what we distribute on our [Github project page](https://github.com/clangen/musikcube/releases) for all releases. Regular build instructions can be found on the [Github project page, here](https://github.com/clangen/musikcube/wiki/building), and have fewer weird prerequisites. # Instructions ## Install `Debian Buster` It's probably easiest to just install a `docker` image and use that, but an install straight to physical hardware (or a virtual machine) will work just fine. ## Install dependencies ### From `apt-get`: - `sudo apt update` - `sudo apt dist-upgrade` - `sudo apt install build-essential g++ gcc git libasound2-dev libev-dev libncurses-dev libopus-dev libopus-dev libopus0 libpulse-dev libsndio-dev libssl-dev libsystemd-dev libvorbis-dev libvorbis-dev libvorbis0a libvorbisenc2 portaudio19-dev rpm wget zlib1g-dev libdbus-1-dev libudev-dev libglib2.0-dev patchelf libstdc++6-i386-cross nodejs` ### Compile from source: Install the following from source, as the distro-provided packages are too old: - `cmake` v3.27.4+ - `pipewire` v0.3.x (optional -- only if you want to use `pipewire`) - Note: `wireplumber`, a `pipewire` sub-project, requires a version of `glib-2.0` newer than what `Debian Buster` provides. That's fine because we just need the `pipewire` libraries. Just edit `meson_options.txt` and remove `'wireplumber'` from the `session-managers` option. ## Provision your build directory A couple build steps assume that you'll be building from the `/build` directory. This can either be a physical directory or a symlink to elsewhere. This is currently a hard-requirement, but may not be in the future. Sorry. - `cd /build` - `git clone https://github.com/clangen/musikcube.git --recursive` ## Compile third-party dependencies As mentioned above, a number of larger third-party dependencies are compiled from source, stripping unused functionality to ensure they are as small and efficient as possible. Doing this manually is really annoying, so it's all been automated behind a script. - `cd /build` - `./musikcube/script/build-vendor-libraries.sh` This process may take a while, but when it completes you'll be left with a `/build/vendor-${arch}` directory that will contain all build artifacts. The `musikcube` app compile will reference this directory during its build process. ## Compile `musikcube` Now that we have all required dependencies available it's time to compile the app itself. As mentioned above we want the resulting binary to be relocatable on the filesystem, so some special pre- and post-processing must happen. Specifically: we need to gather copies of all dependencies and rewrite their `rpaths` if necessary. We also need to collect and include resource files like themes and localization files, then create `.deb`, `.rpm`, and `.tar.bz2` archives for distribution. As in the previous step all of this complexity has been hidden behind a script. - `cd /build/musikcube` - `./script/archive-standalone-nix.sh x.y.z` - `x.y.z` is the version of `musikcube` we'd like to appear in the filename. You can use anything you want, e.g. `0.0.0` - The build process will automatically discover and use the `/build/vendor-${arch}` directory created in the previous step. After the script has completed you should have a set of "relocatable" binaries in `/build/musikcube/dist/x.y.z/` that will work on most Linux distributions released in 2018 or later. --- ## File: doc/crosscompile-rpi.md # Prerequisites Cross compiling depends on: - A working "standalone" build environment ([see here](build-standalone-unix.md)) - A working Raspberry Pi `Buster` environment, either via `chroot` ([see here](rpi-buster-chroot.md)) or on a physical device # Gather dependencies from a Raspbian install The cross-compile toolchain ships with a minimal system "image" that does not include all of the third-party dependencies we need to compile musikcube. To obtain these dependencies we need to boot into the chroot environment and execute a script to download and collect the latest versions of the headers and libraries so we can add them to the cross-compile toolchain. 1. Enter the `chroot` environment (or boot your device) 2. `apt-get update` 3. `sudo apt-get dist-upgrade` 4. `cd /build/sysroot` 5. `node /build/musikcube/script/create-crosscompile-sysroot.js` After this process completes you will be left with a file called `sysroot.tar`. # Install the cross-compile toolchain The cross-compile toochains that ship with Debian and Ubuntu generally do not fully support `armv6`, which means we cannot use them to generate builds for older Raspberry Pi devices. Instead, we'll install a better maintained toolchain from the following github project: https://github.com/tttapa/docker-arm-cross-toolchain 1. `cd /build` 2. `cp /path/to/generated/sysroot/sysroot.tar .` 3. `node /build/musikcube/script/install-crosscompile-tools.js` This will download the cross-compile tools to the current directory, extract them, then use the `sysroot.tar` to populate the tools' environments. # Use cross-compile toolchain to compile dependencies In order to facilite easy, efficient distribution of musikcube binaries, we compile various dependencies ourselves, omitting unused features and ensuring the entire package is "relocatable," meaning users can run them from anywhere (i.e. they don't need to be installed to `/usr/` or `/usr/local/` to work properly). 1. `cd /build` 2. `CROSSCOMPILE=rpi-armv6 ./musikcube/script/build-vendor-libraries.sh` When this has finished, you'll be left with a `vendor-rpi-armv6` directory that the main app compile will reference. # Build the main app Now that we have all of our dependencies available it's time to compile the main app. 1. `cd /build/musikcube` 2. `CROSSCOMPILE=rpi-armv6 ./script/archive-standalone-nix.sh 3.0.2` --- ## File: doc/rpi-buster-chroot.md # Forward - stolen from here: https://medium.com/@crmoratelli/architectural-chroot-for-faster-compilation-and-deployment-on-raspberry-pi-76224327659d # Install dependencies - `sudo apt install qemu-kvm qemu-user-static binfmt-support qemu-user-static qemu-utils kpartx e2fsprogs` # Create a new directory - `mkdir rpi-buster-chroot` # Download image - `wget https://downloads.raspberrypi.org/raspios_oldstable_lite_armhf/images/raspios_oldstable_lite_armhf-2023-05-03/2023-05-03-raspios-buster-armhf-lite.img.xz` # Extract image - `xz -d -v 2023-05-03-raspios-buster-armhf-lite.img.xz` # Expand the image - `qemu-img resize -f raw 2023-05-03-raspios-buster-armhf-lite.img 16G` # Expand the partition within the image - `fdisk 2023-05-03-raspios-buster-armhf-lite.img` - `Command: p` [prints the partition table. note partition #2's "Start" value.] - `Command: d` [delete a partition] - `Command: 2` [delete the Linux partition, which should be #2] - `Command: n` [add new partition] - `Command: p` [primary partition] - `Command: 2` [partition number] - `Command: ` [enter start value from first step] - `Command: ` [press enter to accept default value] - `Command: N` [to *NOT* remove the ext4 signature] - `Command: w` [write table to file] # Create a mount point - `mkdir os-mount` # Mount both disk image partitions via loopback - `sudo kpartx -a -v 2023-05-03-raspios-buster-armhf-lite.img` output, note device names: ``` add map loop4p1 (253:0): 0 524288 linear 7:4 8192 add map loop4p2 (253:1): 0 33021952 linear 7:4 532480 <== THIS IS OUR ACTUAL OS ``` # Mount the second partition to the filesystem - `sudo mount /dev/mapper/loop4p2 ./os-mount` # Resize the ext filesystem - `sudo /sbin/resize2fs /dev/mapper/loop4p2` # Inject qemu and setup special mount points - `sudo cp /usr/bin/qemu-arm-static ./os-mount/usr/bin` - `sudo mount -o bind /dev ./os-mount/dev` - `sudo mount -o bind /proc ./os-mount/proc` - `sudo mount -o bind /sys ./os-mount/sys` # Magic: register `qemu-arm-static` as the arm interpreter in the kernel > Must be root, no `sudo` - `su` - `echo ':arm:M::\x7fELF\x01\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x28\x00:\xff\xff\xff\xff\xff\xff\xff\x00\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xff\xff\xff:/usr/bin/qemu-arm-static:' > /proc/sys/fs/binfmt_misc/register` - `exit` # Enter the chroot - `sudo chroot ./os-mount /usr/bin/qemu-arm-static /usr/bin/bash` > If you get an error about /usr/bin/bash not found, try /bin/bash instead # Shutdown - `sudo umount ./os-mount/dev` - `sudo umount ./os-mount/proc` - `sudo umount ./os-mount/sys` - `sudo umount ./os-mount` - `sudo kpartx -d -v 2023-05-03-raspios-buster-armhf-lite.img` --- ## File: src/plugins/server/README.md # musikcube server plugin a playback remote and streaming audio server for `musikcube` using web sockets and vanilla http. * [`musikcube`](https://github.com/clangen/musikcube) for windows, macOS, linux and freebsd are all supported. * [`musikdroid`](https://github.com/clangen/musikcube/tree/master/src/musikdroid) is a client implementation written for android. * [api documentation can be found here](https://github.com/clangen/musikcube/wiki/remote-api-documentation). the code is somewhat ugly, but it works pretty well. i currently have it running 24/7 on a raspberry pi with an [iqaudio dac+](http://iqaudio.co.uk/audio/8-pi-dac-0712411999643.html), paired with a first generation moto g as a remote. the backend plugin uses [`websocketpp`](https://github.com/zaphoyd/websocketpp) and [`libmicrohttpd`](https://www.gnu.org/software/libmicrohttpd/). the android client uses [`nv-websocket-client`](https://github.com/TakahikoKawasaki/nv-websocket-client) and [`exoplayer`](https://github.com/google/ExoPlayer). --- METRICS --- - Files Extracted: 6 - Estimated Token Budget: ~8050 tokens - Recency Window: Active (< 180 days) - Canonical Reference: https://codewiki.google/github.com/clangen/musikcube