### Apache full example configuration
Source: https://jcorporation.github.io/myMPD/070-additional-topics/behind-a-reverse-proxy.html
A complete virtual host configuration example combining proxying, authentication, and access control.
```apache
MergeSlashes OFF
ServerName yourserver.example.com
ProxyRequests Off
ProxyPreserveHost on
ProxyVia On
Require host localhost
Require ip 192.168.1.0/24
AuthType Basic
AuthName "Authentication Required"
AuthUserFile /etc/apache2/.passwds/mympd
Require valid-user
ProxyPass /mympd/ws/ ws://127.0.0.1:8080/ws/
Redirect /mympd /mympd/
ProxyPass /mympd/ http://127.0.0.1:8080/
ProxyPassReverse /mympd/ http://127.0.0.1:8080/
```
--------------------------------
### Install PulseAudio packages
Source: https://jcorporation.github.io/myMPD/070-additional-topics/multiroom-audio-using-pulseaudio-rtp.html
Install PulseAudio and utilities on all systems (NAS and receivers) using apt.
```bash
apt install pulseaudio,pulseaudio-utils,pulsemixer
```
--------------------------------
### Install myMPD from ports
Source: https://jcorporation.github.io/myMPD/010-installation/compiling/freebsd.html
Compile, install, and clean up the build files for myMPD.
```bash
make install
make clean
```
--------------------------------
### Configure myMPD Repository and Install
Source: https://jcorporation.github.io/myMPD/010-installation/prebuild-packages-debian.html
This script retrieves the OS version, imports the repository signing key, verifies the fingerprint, adds the repository to the sources list, and installs myMPD. Replace 'Debian' with 'xUbuntu' in the repository URL for Ubuntu installations.
```bash
# Get Debian VERSION_ID from os-release file
. /etc/os-release
echo $VERSION_ID
# Download the signing key and install it in a dedicated keyring
# Debian Bookworm and older
curl http://download.opensuse.org/repositories/home:/jcorporation/Debian_$VERSION_ID/Release.key | gpg --no-default-keyring --keyring /usr/share/keyrings/jcorporation.github.io.gpg --import
# Debian Trixie
curl http://download.opensuse.org/repositories/home:/jcorporation/Debian_$VERSION_ID/Release.key | gpg --dearmor --output /usr/share/keyrings/jcorporation.github.io.gpg
# ⚠️ VERIFY the fingerprint of the downloaded key (A37A ADC4 0A1C C6BE FB75 372F AA09 B8CC E895 BD7D - home:jcorporation OBS Project )
gpg --no-default-keyring --keyring /usr/share/keyrings/jcorporation.github.io.gpg --fingerprint
# Make the imported keyring world-readable
chmod 644 /usr/share/keyrings/jcorporation.github.io.gpg
# Add the myMPD APT repository and ensure releases are signed with the repository's official keys
cat < /etc/apt/sources.list.d/jcorporation.list
deb [signed-by=/usr/share/keyrings/jcorporation.github.io.gpg] http://download.opensuse.org/repositories/home:/jcorporation/Debian_$VERSION_ID/ ./
EOF
cat /etc/apt/sources.list.d/jcorporation.list
# Install MyMPD
apt update
apt install mympd
```
--------------------------------
### Start first myMPD instance with environment variables
Source: https://jcorporation.github.io/myMPD/070-additional-topics/multiple-myMPD-instances-on-same-host.html
Configure and start the first myMPD instance, connecting to the MPD socket at /run/mpd1/socket, listening on HTTP port 8001 without SSL, and using /var/lib/mympd1 as the working directory and /var/cache/mympd1 as the cache directory.
```bash
export MPD_HOST=/run/mpd1/socket
export MYMPD_HTTP_PORT=8001
export MYMPD_SSL=false
mympd -w /var/lib/mympd1 -a /var/cache/mympd1
```
--------------------------------
### Build myMPD with cmake
Source: https://jcorporation.github.io/myMPD/010-installation/compiling/cmake.html
Commands to configure, build, and install myMPD. Run cmake as user, build in the 'build' directory, and install with sudo.
```bash
# Build as user
cmake -B build -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=/usr .
# binaries are placed in build/bin
cmake --build build
# Run install as root
sudo cmake --install build
```
--------------------------------
### Install dependencies via build.sh
Source: https://jcorporation.github.io/myMPD/010-installation/compiling/index.html
Run this command as root to automatically install build dependencies on supported distributions.
```bash
./build.sh installdeps
```
--------------------------------
### Start second myMPD instance with environment variables
Source: https://jcorporation.github.io/myMPD/070-additional-topics/multiple-myMPD-instances-on-same-host.html
Configure and start the second myMPD instance, connecting to the MPD socket at /run/mpd2/socket, listening on HTTP port 8002 and SSL port 4432 with SSL enabled, and using /var/lib/mympd2 as the working directory and /var/cache/mympd2 as the cache directory.
```bash
export MPD_HOST=/run/mpd2/socket
export MYMPD_HTTP_PORT=8002
export MYMPD_SSL_PORT=4432
export MYMPD_SSL=true
mympd -w /var/lib/mympd2 -a /var/cache/mympd2
```
--------------------------------
### Start the application
Source: https://jcorporation.github.io/myMPD/jsdoc/init.js.html
Calls appInitStart to begin the myMPD application initialization.
```javascript
appInitStart();
```
--------------------------------
### Install myMPD package
Source: https://jcorporation.github.io/myMPD/010-installation/compiling/freebsd.html
Install the built myMPD package using the pkg manager.
```bash
pkg install myMPD
```
--------------------------------
### Run myMPD on Termux
Source: https://jcorporation.github.io/myMPD/010-installation/compiling/termux.html
Run myMPD normally after the initial setup; the environment variables are only needed for the first start.
```shell
$HOME/myMPD/release/bin/mympd -w $HOME/.config/mympd
```
--------------------------------
### Start myMPD manually with systemd-run
Source: https://jcorporation.github.io/myMPD/030-running.html
Starts myMPD in a console session on systems using systemd without a static mympd user.
```bash
systemd-run -t -p DynamicUser=yes -p StateDirectory=mympd -p CacheDirectory=mympd /usr/bin/mympd
```
--------------------------------
### Custom navbar icons examples
Source: https://jcorporation.github.io/myMPD/060-references/customization.html
Examples of custom navbar icon definitions. The first opens the Filesystem view under Browse, the second opens the Radio Favorites view.
```json
{
"ligature": "library_music",
"title":"Browse",
"options": ["Browse", "Filesystem"]
},
{
"ligature": "radio",
"title":"Radio Favorites",
"options": ["Browse", "Radio", "Favorites"]
}
```
--------------------------------
### MYMPD_API_PLAYER_PLAY
Source: https://jcorporation.github.io/myMPD/060-references/api/methods.html
Starts playing. This method is not protected and takes no parameters.
```APIDOC
## MYMPD_API_PLAYER_PLAY
### Description
Starts playing.
### Parameters
None
```
--------------------------------
### MEASURE_START
Source: https://jcorporation.github.io/myMPD/doxygen/html/lib_2utility_8h.html
Starts time measurement by recording the current monotonic clock time.
```APIDOC
## MEASURE_START
### Description
Starts time measurement by recording the current monotonic clock time.
### Macro Definition
#define MEASURE_START (void)clock_gettime(CLOCK_MONOTONIC, &tic);
```
--------------------------------
### Select and build myMPD in buildroot
Source: https://jcorporation.github.io/myMPD/010-installation/compiling/openwrt.html
Use menuconfig to select the package and then run the make command to build it.
```bash
make menuconfig
make -j$(nproc) BUILD_LOG=1
```
--------------------------------
### Example API call: MYMPD_API_PLAYER_STATE
Source: https://jcorporation.github.io/myMPD/060-references/api/index.html
A JSON-RPC 2 request to get the player state. The id is 0 and params is an empty object.
```json
{"jsonrpc":"2.0","id":0,"method":"MYMPD_API_PLAYER_STATE","params":{}}
```
--------------------------------
### mympd_api_timer_calc_starttime
Source: https://jcorporation.github.io/myMPD/doxygen/html/mympd__api_2timer_8h_source.html
Calculates the start time for a timer based on the start hour, start minute, and interval. This function returns the start time as an integer.
```APIDOC
## mympd_api_timer_calc_starttime
### Description
Calculates the start time for a timer based on the start hour, start minute, and interval. This function returns the start time as an integer.
### Function Signature
int mympd_api_timer_calc_starttime(int start_hour, int start_minute, int interval)
### Parameters
- **start_hour** (int) - Required - The start hour (0-23). n- **start_minute** (int) - Required - The start minute (0-59). n- **interval** (int) - Required - The interval in seconds.
### Return Value
- **int** - Returns the calculated start time.
```
--------------------------------
### mymp d_api_timer_calc_starttime
Source: https://jcorporation.github.io/myMPD/doxygen/html/mympd__api_2timer_8h.html
Calculates the offset from now for the next start time for a timer based on the given start hour, start minute, and reschedule interval.
```APIDOC
## mympd_api_timer_calc_starttime
### Description
Calculates the offset from now for next start time for a timer.
### Function Signature
int mympd_api_timer_calc_starttime(int _start_hour_, int _start_minute_, int _interval_)
### Parameters
- **_start_hour_** (int) - Required - Start hour
- **_start_minute_** (int) - Required - Start minute
- **_interval_** (int) - Required - Reschedule interval
### Returns
- **int** - Unix timestamp of next start
```
--------------------------------
### appInitStart - Start the myMPD app
Source: https://jcorporation.github.io/myMPD/jsdoc/init.js.html
Initializes the app by loading assets, adding a hashchange event listener for routing, creating pre-generated elements, handling webapp manifest shortcuts, setting up a ResizeObserver for table height updates, setting mobile view, translating the splash screen alert, setting log level based on debugMode, and registering or unregistering the service worker depending on debugMode and protocol.
```JavaScript
function appInitStart() {
getAssets();
//add app routing event handler
window.addEventListener('hashchange', function() {
if (app.goto === false) {
appRoute();
}
else {
app.goto = false;
}
}, false);
// create pre-generated elements
createPreGeneratedElements();
//webapp manifest shortcuts
const params = new URLSearchParams(window.location.search);
const action = params.get('action');
switch(action) {
case 'clickPlay':
clickPlay();
break;
case 'clickStop':
clickStop();
break;
case 'clickNext':
clickNext();
break;
// No Default
}
//update table height on window resize
const resizeObserver = new ResizeObserver(function() {
requestAnimationFrame(() => {
const list = elGetById(app.id + 'List');
if (list) {
setScrollViewHeight(list);
}
});
});
resizeObserver.observe(document.querySelector('body'));
setMobileView();
i18nHtml(elGetById('splashScreenAlert'));
//set loglevel
if (debugMode === true) {
settings.loglevel = 7;
}
//serviceworker handling
if ('serviceWorker' in navigator) {
//add serviceworker
if (debugMode === false &&
window.location.protocol === 'https:')
{
window.addEventListener('load', function() {
navigator.serviceWorker.register('sw.js', {scope: subdir + '/'}).then(function(registration) {
//Registration was successful
logDebug('ServiceWorker registration successful.');
registration.update();
}, function(err) {
//Registration failed
logError('ServiceWorker registration failed: ' + err);
});
});
}
//debugMode - delete serviceworker
if (debugMode === true) {
let serviceWorkerExists = false;
navigator.serviceWorker.getRegistrations().then(function(registrations) {
for (const registration of registrations) {
registration.unregister();
serviceWorkerExists = true;
}
if (serviceWorkerExists === true) {
clearAndReload();
}
});
}
}
}
```
--------------------------------
### appInitStart()
Source: https://jcorporation.github.io/myMPD/jsdoc/module-init_js.html
Starts the app. This function is called to begin the application's main initialization process.
```APIDOC
## appInitStart()
### Description
Starts the app.
### Method
Function call
### Endpoint
appInitStart()
### Parameters
None
### Returns
void
```
--------------------------------
### appInit()
Source: https://jcorporation.github.io/myMPD/jsdoc/module-init_js.html
Initializes the html elements. This function is called to set up the user interface elements during app startup.
```APIDOC
## appInit()
### Description
Initializes the html elements.
### Method
Function call
### Endpoint
appInit()
### Parameters
None
### Returns
void
```
--------------------------------
### Initialize partition modal event listeners
Source: https://jcorporation.github.io/myMPD/jsdoc/modalPartitions.js.html
Sets up click and show event listeners for the partition modal. Handles delete actions and partition switching.
```javascript
function initModalPartitions() {
elGetById('modalPartitionsPartitionsList').addEventListener('click', function(event) {
event.stopPropagation();
event.preventDefault();
if (event.target.nodeName === 'A') {
const action = getData(event.target, 'action');
const partition = getData(event.target.parentNode.parentNode, 'partition');
switch(action) {
case 'delete':
deletePartition(event.target, partition);
break;
default:
logError('Invalid action: ' + action);
}
return;
}
const target = event.target.closest('TR');
if (checkTargetClick(target) === true) {
switchPartition(getData(target, 'partition'));
}
}, false);
elGetById('modalPartitions').addEventListener('show.bs.modal', function () {
showListPartitions();
});
}
```
--------------------------------
### Show splash screen and initialize app
Source: https://jcorporation.github.io/myMPD/jsdoc/init.js.html
Displays the splash screen, fetches settings, and initializes the app after settings are parsed.
```javascript
//show splash screen
elShowId('splashScreen');
domCache.body.classList.add('overflow-hidden');
elGetById('splashScreenAlert').textContent = tn('Fetch myMPD settings');
//initialize app
appInited = false;
settingsParsed = 'no';
sendAPI("MYMPD_API_SETTINGS_GET", {}, function(obj) {
parseSettings(obj);
if (settingsParsed === 'parsed') {
//connect to websocket in background
setTimeout(function() {
webSocketConnect();
}, 0);
//app initialized
elGetById('splashScreenAlert').textContent = tn('Applying settings');
elGetById('splashScreen').classList.add('hide-fade');
setTimeout(function() {
elHideId('splashScreen');
elGetById('splashScreen').classList.remove('hide-fade');
domCache.body.classList.remove('overflow-hidden');
}, 500);
appInit();
appInited = true;
appRoute();
logDebug('Startup duration: ' + (Date.now() - startTime) + 'ms');
}
}, true);
```
--------------------------------
### Notifications: mympd.notify_client and mympd.notify_partition
Source: https://jcorporation.github.io/myMPD/050-scripting/functions/util.html
Sends a notification to the client that started the script or to all clients in the partition from which the client started the script. Severity can be a number or string.
```lua
-- Send a notification to the client that has started the script
mympd.notify_client(severity, message)
-- Send a notification to all clients in the partition from which the client started the script
mympd.notify_partition(severity, message)
```
--------------------------------
### initViewBrowseFilesystem
Source: https://jcorporation.github.io/myMPD/jsdoc/viewBrowseFilesystem.js.html
Initializes the browse filesystem view, sets up breadcrumb click listeners, and activates the view.
```javascript
function initViewBrowseFilesystem() {
initSearchSimple('BrowseFilesystem');
elGetById('BrowseFilesystemBreadcrumb').addEventListener('click', function(event) {
if (event.target.nodeName === 'A') {
event.preventDefault();
const uri = getData(event.target, 'uri');
const offset = browseFilesystemHistory[uri] !== undefined
? browseFilesystemHistory[uri].offset
: 0;
const scrollPos = browseFilesystemHistory[uri] !== undefined
? browseFilesystemHistory[uri].scrollPos
: 0;
appGoto('Browse', 'Filesystem', undefined, offset, app.current.limit, uri, app.current.sort, 'dir', '', scrollPos);
}
}, false);
setView('BrowseFilesystem');
}
```
--------------------------------
### Create directories for myMPD images
Source: https://jcorporation.github.io/myMPD/070-additional-topics/mpd-satellite-setup.html
Initializes the background and thumbnail directories for myMPD images on the central server.
```bash
mkdir /srv/mpd/images/backgrounds /srv/mpd/images/thumbs
```
--------------------------------
### removeFromQueueRange(start, endopt)
Source: https://jcorporation.github.io/myMPD/jsdoc/module-queue_js.html
Removes a range of songs from the queue. The start parameter is inclusive, and the optional end parameter is exclusive; use -1 for an open end.
```APIDOC
## removeFromQueueRange(start, endopt)
### Description
Removes a song range from the queue.
### Method
Function call
### Parameters
- **start** (number) - Required - Start of the range (including).
- **end** (number) - Optional - End of the range (excluding), -1 for open end.
### Returns
void
```
--------------------------------
### log_init(void)
Source: https://jcorporation.github.io/myMPD/doxygen/html/log_8c.html
Initializes the logging sub-system. This function should be called before using other logging functions.
```APIDOC
## log_init(void)
### Description
Initializes the logging sub-system.
### Parameters
None.
```
--------------------------------
### mympd.tmpvar_get
Source: https://jcorporation.github.io/myMPD/jsdoc/globales.js.html
Get a tmp variable.
```lua
local value, expiration = mympd.tmpvar_get(key)
```
--------------------------------
### handleHome function
Source: https://jcorporation.github.io/myMPD/jsdoc/viewHome.js.html
Initializes the home screen by requesting the icon list from the API.
```javascript
function handleHome() {
sendAPI("MYMPD_API_HOME_ICON_LIST", {}, parseHomeIcons, false);
}
```
--------------------------------
### getTimestamp()
Source: https://jcorporation.github.io/myMPD/jsdoc/module-utility_js.html
Gets a unix timestamp.
```APIDOC
## getTimestamp()
### Description
Gets a unix timestamp.
### Returns
- **number** - the unix timestamp
```
--------------------------------
### Create PulseAudio systemd unit file and enable service
Source: https://jcorporation.github.io/myMPD/070-additional-topics/multiroom-audio-using-pulseaudio-rtp.html
Create a systemd unit file for PulseAudio to run as a system service, then reload and enable it.
```bash
# cat < /lib/systemd/system/pulseaudio.service
[Unit]
Description=PulseAudio Daemon
After=network.target
[Install]
WantedBy=multi-user.target
[Service]
Type=simple
PrivateTmp=true
ExecStart=/usr/bin/pulseaudio --system --realtime --disallow-exit --no-cpu-limit --disable-shm
EOF
systemctl daemon-reload
systemctl enable pulseaudio
```
--------------------------------
### stickerdb_find_stickers_by_name()
Source: https://jcorporation.github.io/myMPD/doxygen/html/stickerdb_8h.html
Gets all stickers by name.
```APIDOC
## stickerdb_find_stickers_by_name()
### Description
Gets all stickers by name.
### Function Signature
rax * stickerdb_find_stickers_by_name(struct t_stickerdb_state *_stickerdb_, enum mympd_sticker_type _type_, const char *_name_)
### Parameters
- **_stickerdb_** (struct t_stickerdb_state *) - pointer to the stickerdb state
- **_type_** (enum mympd_sticker_type) - MPD sticker type
- **_name_** (const char *) - sticker name
### Returns
- **rax *** - newly allocated radix tree or NULL on error
```
--------------------------------
### getScriptList
Source: https://jcorporation.github.io/myMPD/jsdoc/modalScripts.js.html
Gets the list of scripts from the API.
```javascript
function getScriptList(all) {
sendAPI("MYMPD_API_SCRIPT_LIST", {
"all": all
}, parseScriptList, true);
}
```
--------------------------------
### Download OpenWrt SDK dependencies
Source: https://jcorporation.github.io/myMPD/010-installation/compiling/openwrt.html
Run these commands within the unpacked OpenWrt SDK directory to fetch the necessary package recipes.
```bash
scripts/feeds update -a
scripts/feeds install libflac libid3tag liblua5.3 libopenssl libpcre2
```
--------------------------------
### stickerdb_get_names()
Source: https://jcorporation.github.io/myMPD/doxygen/html/stickerdb_8c.html
Gets all sticker names by type.
```APIDOC
## stickerdb_get_names()
### Description
Gets all sticker names by type
### Function Signature
bool stickerdb_get_names(struct t_stickerdb_state * _stickerdb_, enum mympd_sticker_type _type_, struct t_list * _sticker_names_)
### Parameters
- **stickerdb** (struct t_stickerdb_state *) - Required - pointer to the stickerdb state
- **type** (enum mympd_sticker_type) - Required - MPD sticker type
- **sticker_names** (struct t_list *) - Required - List to populate
### Returns
true on success, else false
```
--------------------------------
### initLocalPlayback() → {void}
Source: https://jcorporation.github.io/myMPD/jsdoc/module-localplayback_js.html
Initializes the local playback related elements.
```APIDOC
## initLocalPlayback() → {void}
### Description
Initializes the local playback related elements.
### Parameters
None.
### Returns
- **void** - No return value.
### Source
- localplayback.js, line 12
```
--------------------------------
### stickerdb_get_int64()
Source: https://jcorporation.github.io/myMPD/doxygen/html/stickerdb_8c.html
Gets an int64_t value sticker.
```APIDOC
## stickerdb_get_int64()
### Description
Gets an int64_t value sticker.
### Function Signature
int64_t stickerdb_get_int64(struct t_stickerdb_state * _stickerdb_, enum mympd_sticker_type _type_, const char * _uri_, const char * _name_)
### Parameters
- **stickerdb** (struct t_stickerdb_state *) - Required - pointer to the stickerdb state
- **type** (enum mympd_sticker_type) - Required - MPD sticker type
- **uri** (const char *) - Required - sticker uri
- **name** (const char *) - Required - sticker name
### Returns
sticker value or 0 on error
```
--------------------------------
### stickerdb_find_stickers_by_name_value()
Source: https://jcorporation.github.io/myMPD/doxygen/html/stickerdb_8h.html
Gets all stickers by name and value.
```APIDOC
## stickerdb_find_stickers_by_name_value()
### Description
Gets all stickers by name and value.
### Function Signature
rax * stickerdb_find_stickers_by_name_value(struct t_stickerdb_state *_stickerdb_, enum mympd_sticker_type _type_, const char *_name_, enum mpd_sticker_operator _op_, const char *_value_)
### Parameters
- **_stickerdb_** (struct t_stickerdb_state *) - pointer to the stickerdb state
- **_type_** (enum mympd_sticker_type) - MPD sticker type
- **_name_** (const char *) - sticker name
- **_op_** (enum mpd_sticker_operator) - compare operator: MPD_STICKER_OP_EQ, MPD_STICKER_OP_GT, MPD_STICKER_OP_LT
- **_value_** (const char *) - sticker value
### Returns
- **rax *** - newly allocated radix tree or NULL on error
```
--------------------------------
### Initialize Playback View
Source: https://jcorporation.github.io/myMPD/jsdoc/viewPlayback.js.html
Sets up event listeners for the playback list tags to enable navigation.
```javascript
function initViewPlayback() {
elGetById('PlaybackListTags').addEventListener('click', function(event) {
if ((event.target.nodeName === 'P' && event.target.classList.contains('clickable') === true) ||
(event.target.nodeName === 'SPAN' && event.target.parentNode.classList.contains('clickable') === true)
) {
gotoBrowse(event);
}
}, false);
}
```
--------------------------------
### album_cache_get_album
Source: https://jcorporation.github.io/myMPD/doxygen/html/cache__rax__album_8c.html
Gets the album from the album cache.
```APIDOC
## album_cache_get_album
### Description
Gets the album from the album cache.
### Function Signature
struct t_album *album_cache_get_album(struct t_cache *album_cache, sds key)
### Parameters
- **album_cache** (struct t_cache*) - Pointer to t_cache struct.
- **key** (sds) - The album key.
### Returns
mpd_song struct representing the album or NULL on error.
```
--------------------------------
### gotoFilesystem function
Source: https://jcorporation.github.io/myMPD/jsdoc/browse.js.html
Navigates to the filesystem view by clearing the search string and calling appGoto with the specified URI and type.
```javascript
function gotoFilesystem(uri, type) {
elGetById('BrowseFilesystemSearchStr').value = '';
appGoto('Browse', 'Filesystem', undefined, 0, undefined, uri, {'tag':'', 'desc': false}, type, '');
}
```
--------------------------------
### album_get_unknown
Source: https://jcorporation.github.io/myMPD/doxygen/html/album_8c.html
Gets the unknown marker for an album.
```APIDOC
## album_get_unknown()
### Description
Gets the unknown marker for an album.
### Function Signature
bool album_get_unknown(const struct t_album *album)
### Parameters
- **album** (const struct t_album *) - Required - t_album struct representing the album.
### Returns
- **bool** - True if it is an unknown album, else false.
```
--------------------------------
### Initializes outputs HTML elements (initOutputs)
Source: https://jcorporation.github.io/myMPD/jsdoc/outputs.js.html
Sets up event listeners for the volume slider and the outputs dropdown. It sends MYMPD_API_PLAYER_OUTPUT_LIST when the volume menu is shown, handles clicks on the output list to either toggle an output or open attributes, and toggles the button state.
```javascript
"use strict";
// SPDX-License-Identifier: GPL-3.0-or-later
// myMPD (c) 2018-2026 Juergen Mang
// https://github.com/jcorporation/mympd
// @module outputs_js
function initOutputs() {
domCache.volumeBar.addEventListener('change', function() {
setVolume();
}, false);
elGetById('volumeMenu').parentNode.addEventListener('show.bs.dropdown', function() {
sendAPI("MYMPD_API_PLAYER_OUTPUT_LIST", {}, parseOutputs, true);
});
elGetById('outputs').addEventListener('click', function(event) {
if (event.target.nodeName === 'A') {
event.preventDefault();
BSN.Dropdown.getInstance(elGetById('volumeMenu')).toggle();
showModalOutputAttributes(getData(event.target.parentNode, 'output-name'));
}
else {
const target = event.target.nodeName === 'BUTTON' ? event.target : event.target.parentNode;
event.preventDefault();
sendAPI("MYMPD_API_PLAYER_OUTPUT_TOGGLE", {
"outputId": Number(getData(target, 'output-id')),
"enabled": (target.classList.contains('active') ? false : true)
}, null, false);
toggleBtn(target, undefined);
}
}, false);
}
```
--------------------------------
### Initialize Modal Partition Outputs
Source: https://jcorporation.github.io/myMPD/jsdoc/modalPartitionOutputs.js.html
Initializes the event listeners for the partition outputs modal, including click handling for selection and loading data when the modal is shown.
```javascript
function initModalPartitionOutputs() {
elGetById('modalPartitionOutputsList').addEventListener('click', function(event) {
event.stopPropagation();
event.preventDefault();
if (event.target.nodeName === 'BUTTON') {
toggleBtnChk(event.target, undefined);
}
else if (event.target.nodeName === 'TD') {
const target = event.target.parentNode.firstChild.firstChild;
toggleBtnChk(target, undefined);
}
}, false);
elGetById('modalPartitionOutputs').addEventListener('show.bs.modal', function() {
//get all outputs
sendAPIpartition("default", "MYMPD_API_PLAYER_OUTPUT_LIST", {}, function(allOutputs) {
const outputList = elGetById('modalPartitionOutputsList');
if (checkResult(allOutputs, outputList, 'modalTable') === false) {
return;
}
//get partition specific outputs
sendAPI("MYMPD_API_PLAYER_OUTPUT_LIST", {}, function(partitionOutputs) {
parsePartitionOutputsList(allOutputs, partitionOutputs);
uiElements.modalPartitionOutputs.show();
}, true);
}, true);
});
}
```
--------------------------------
### dirname(uri)
Source: https://jcorporation.github.io/myMPD/jsdoc/module-utility_js.html
Gets the directory from the given uri.
```APIDOC
## dirname(uri)
### Description
Gets the directory from the given uri.
### Parameters
- **uri** (string) - Required - the uri
### Returns
- **string** - directory part of the uri
```
--------------------------------
### Initialize myMPD status with mympd.init()
Source: https://jcorporation.github.io/myMPD/050-scripting/functions/mympd_init.html
Call this function to populate the mympd_state table with the current configuration and status values of myMPD and MPD. It returns a response code and a result table.
```lua
mympd.init()
```
--------------------------------
### mympd_api_get_elapsed_seconds
Source: https://jcorporation.github.io/myMPD/doxygen/html/status_8h.html
Function to get elapsed seconds from mpd_status.
```APIDOC
## mympd_api_get_elapsed_seconds
### Description
Replacement for deprecated mpd_status_get_elapsed_time. Returns the elapsed seconds from the given mpd_status struct.
### Signature
unsigned mympd_api_get_elapsed_seconds(struct mpd_status *status)
### Parameters
- **status** (struct mpd_status *) - Required - Pointer to mpd_status struct.
### Returns
- **unsigned** - Elapsed seconds.
```
--------------------------------
### json_get_int64()
Source: https://jcorporation.github.io/myMPD/doxygen/html/json__query_8h.html
Gets an int64_t value by json path.
```APIDOC
## json_get_int64()
### Description
Gets an int64_t value by json path.
### Function Signature
bool json_get_int64(sds _s_, const char *_path_, int64_t _min_, int64_t _max_, int64_t *_result_, struct t_json_parse_error *_error_)
### Parameters
- **s** (sds) - Required - json object to parse
- **path** (const char *) - Required - mjson path expression
- **min** (int64_t) - Required - minimum value (including)
- **max** (int64_t) - Required - maximum value (including)
- **result** (int64_t *) - Required - pointer to int64_t with the result
- **error** (struct t_json_parse_error *) - Required - pointer to t_json_parse_error
### Returns
- **bool** - true on success, else false
```
--------------------------------
### mympd.init()
Source: https://jcorporation.github.io/myMPD/050-scripting/functions/mympd_init.html
Populates the lua table mympd_state with configuration values and current status of myMPD and MPD. No parameters required.
```APIDOC
## mympd.init()
### Description
Populates the lua table `mympd_state` with configuration values and current status of myMPD and MPD.
### Method
Function call
### Endpoint
mympd.init()
### Parameters
No parameters required.
### Returns
| FIELD | TYPE | DESCRIPTION |
|-------|------|-------------|
| rc | integer | response code: 0 = success, 1 = error |
| result | lua table | jsonrpc result or error as lua table |
### mympd_state Table
The lua table `mympd_state` is populated with the following fields:
| KEY | TYPE | DESCRIPTION |
|-----|------|-------------|
| `auto_play` | Boolean | true = enabled, false = disabled |
| `consume_state` | Integer | MPD consume state: 0 = off, 1 = on, 2 = oneshot, 3 = unknown |
| `current_album` | String | myMPD AlbumId |
| `crossfade` | Integer | MPD crossfade option |
| `current_song` | Table | Current MPD song |
| `elapsed_time` | Integer | Elapsed time of current song |
| `jukebox_ignore_hated` | Boolean | Ignore hated songs for jukebox |
| `jukebox_last_played` | Integer | Don’t add songs that are played in the last x hours |
| `jukebox_max_song_duration` | Integer | Only songs with this minimum length will be considered. |
| `jukebox_min_song_duration` | Integer | If greater then zero: Only songs with this maximum length will be considered. |
| `jukebox_mode` | Integer | Jukebox mode: 0 = off, 1 = song, 2 = album, 3 = script |
| `jukebox_playlist` | String | Jukebox playlist: Database or MPD playlist name |
| `jukebox_queue_length` | Integer | Number of songs in the queue before the jukebox add’s more songs. |
| `jukebox_uniq_tag` | String | Build the jukebox queue with this tag as uniq constraint: Song, Album, Artist |
| `listenbrainz_token` | String | ListenBrainz Token |
| `mixrampdelay` | Float | Mixramp delay |
| `mixrampdb` | Float | Mixramp DB |
| `music_directory` | String | Path to the mpd music directory |
| `mympd_uri` | String | Canonical myMPD uri |
| `mympd_uri_plain` | String | Canonical myMPD uri (http://) |
| `next_song_id` | Integer | Next song id in queue |
| `next_song_pos` | Integer | Next song position in queue |
| `play_state` | Integer | Player state: 0 = unknown, 1 = stop, 2 = play, 3 = pause |
| `playlist_directory` | String | path to the mpd playlist directory |
| `queue_length` | Integer | Length of the queue |
| `queue_version` | Integer | Version of the queue |
| `repeat` | Boolean | MPD repeat option |
| `replaygain` | Integer | 0 = off, 1 = track, 2 = album, 3 = auto, 4 = unknown |
| `random` | Boolean | MPD random option |
| `single_state` | Integer | MPD single state: 0 = off, 1 = on, 2 = oneshot, 3 = unknown |
| `song_id` | Integer | Song id of current song |
| `song_pos` | Integer | Current song position in queue |
| `start_time` | Integer | Current song start playing timestamp |
| `total_time` | Integer | Total time of current song |
| `volume` | Integer | 0 - 100 percent |
### mympd_state.current_song
| KEY | TYPE | DESCRIPTION |
|-----|------|-------------|
| `uri` | String | Song uri |
| `Duration` | Integer | Song duration in seconds |
| Tag | Tag value(s) | MPD tag name with values. |
```
--------------------------------
### json_get_int()
Source: https://jcorporation.github.io/myMPD/doxygen/html/json__query_8h.html
Gets an int value by json path.
```APIDOC
## json_get_int()
### Description
Gets an int value by json path.
### Function Signature
bool json_get_int(sds _s_, const char *_path_, int _min_, int _max_, int *_result_, struct t_json_parse_error *_error_)
### Parameters
- **s** (sds) - Required - json object to parse
- **path** (const char *) - Required - mjson path expression
- **min** (int) - Required - minimum value (including)
- **max** (int) - Required - maximum value (including)
- **result** (int *) - Required - pointer to int with the result
- **error** (struct t_json_parse_error *) - Required - pointer to t_json_parse_error
### Returns
- **bool** - true on success, else false
```
--------------------------------
### initModalAbout: Populate shortcuts tab and add modal event listener
Source: https://jcorporation.github.io/myMPD/jsdoc/modalAbout.js.html
Initializes the about modal by clearing the shortcuts tab, sorting keymap entries by order, and rendering each key or section header. Adds a 'show.bs.modal' event listener that sends MYMPD_API_STATS and calls getServerinfo().
```javascript
function initModalAbout() {
const tab = elGetById('modalAboutTabShortcuts');
elClear(tab);
const keys = Object.keys(keymap).sort((a, b) => {
return keymap[a].order - keymap[b].order;
});
for (const key of keys) {
if (keymap[key].cmd === undefined) {
tab.appendChild(
elCreateNode('div', {"class": ["row", "mb-2", "mt-3"]},
elCreateNode('div', {"class": ["col-12"]},
elCreateTextTn('h5', {}, keymap[key].desc)
)
)
);
tab.appendChild(
elCreateEmpty('div', {"class": ["row"]})
);
continue;
}
const col = elCreateEmpty('div', {"class": ["col", "col-6", "mb-3", "align-items-center"]});
if (keymap[key].feature !== undefined) {
col.classList.add(keymap[key].feature);
}
const k = elCreateText('div', {"class": ["key", "float-start", "rounded-2"]}, (keymap[key].key !== undefined ? keymap[key].key : key));
if (keymap[key].key && keymap[key].key.length > 1) {
k.classList.add('mi', 'mi-sm');
}
col.appendChild(k);
col.appendChild(
elCreateTextTn('div', {}, keymap[key].desc)
);
tab.lastChild.appendChild(col);
}
elGetById('modalAbout').addEventListener('show.bs.modal', function () {
sendAPI("MYMPD_API_STATS", {}, parseStats, false);
getServerinfo();
}, false);
}
```
--------------------------------
### Application Settings Initialization
Source: https://jcorporation.github.io/myMPD/jsdoc/settings.js.html
Initializes preset dropdowns, notification severity, and MPD connection status.
```javascript
//presets
populatePresetDropdowns();
// Set severity for filtering notifications and logs
elGetById('modalNotificationsSeveritySelect').value = settings.loglevel;
//parse mpd settings if connected
if (settings.partition.mpdConnected === true) {
parseMPDSettings();
}
else {
logWarn('Skip parsing MPD settings');
}
```
--------------------------------
### MYMPD_API_SCRIPT_TMP_GET
Source: https://jcorporation.github.io/myMPD/060-references/api/methods.html
Gets a temporary variable. This method is not protected.
```APIDOC
## MYMPD_API_SCRIPT_TMP_GET
### Description
Gets a temporary variable.
### Parameters
#### Request Body
- **key** (String) - Required - Variable name. Example: tmp-var
```
--------------------------------
### MYMPD_API_SCRIPT_GET
Source: https://jcorporation.github.io/myMPD/060-references/api/methods.html
Gets options from a timer. This method is not protected.
```APIDOC
## MYMPD_API_SCRIPT_GET
### Description
Gets options from a timer.
### Parameters
#### Request Body
- **script** (String) - Required - Name of the script. Example: testscript
```
--------------------------------
### Script with arguments: load playlist and broadcast message
Source: https://jcorporation.github.io/myMPD/050-scripting/index.html
Shows how to use a script argument named 'playlist' and broadcast a message to all connected clients.
```lua
-- load a playlist
mympd.api("MYMPD_API_QUEUE_REPLACE_PLAYLIST", {plist = mympd_arguments.playlist})
-- start playing
mympd.api("MYMPD_API_PLAYER_PLAY")
-- broadcast message to all connected myMPD clients
return("Loaded playlist:" .. mympd_arguments.playlist)
```
--------------------------------
### mympd_api_settings_get()
Source: https://jcorporation.github.io/myMPD/doxygen/html/settings_8h.html
Prints all settings. This function takes the mympd state, partition state, a buffer to append the response, and a request ID, and returns the pointer to the buffer.
```APIDOC
## mympd_api_settings_get()
### Description
Prints all settings.
### Function Signature
sds mympd_api_settings_get(struct t_mympd_state *mympd_state, struct t_partition_state *partition_state, sds buffer, unsigned request_id)
### Parameters
- **mympd_state** (struct t_mympd_state *) - Required - Pointer to mympd state.
- **partition_state** (struct t_partition_state *) - Required - Pointer to partition state.
- **buffer** (sds) - Required - Already allocated sds string to append the response.
- **request_id** (unsigned) - Required - JSON-RPC request id.
### Returns
- **sds** - Pointer to buffer.
```
--------------------------------
### MYMPD_API_LYRICS_GET
Source: https://jcorporation.github.io/myMPD/060-references/api/methods.html
Gets all lyrics from uri. This method is not protected.
```APIDOC
## MYMPD_API_LYRICS_GET
### Description
Gets all lyrics from uri.
### Protected
No
### Parameters
#### Query Parameters
- **uri** (String) - Required - Relativ song uri. Example: Alben/Einstürzende_Neubauten/Ende_Neu/01.Was_ist_ist.mp3
```
--------------------------------
### initModalHomeWidget() → {void}
Source: https://jcorporation.github.io/myMPD/jsdoc/module-modalHomeWidget_js.html
Initializes the modalHomeWidget. No parameters are required.
```APIDOC
## initModalHomeWidget() → {void}
### Description
Initializes the modalHomeWidget.
### Method
Function call
### Parameters
None
### Returns
void
### Source
modalHomeWidget.js, line 12
```
--------------------------------
### get_lua_global_config
Source: https://jcorporation.github.io/myMPD/doxygen/html/interface_8h.html
Gets the config struct from lua userdata.
```APIDOC
## get_lua_global_config
### Description
Gets the config struct from lua userdata.
### Function Signature
struct t_config * get_lua_global_config(lua_State *lua_vm)
### Parameters
- **lua_vm** (lua_State*) - Required - lua instance
### Returns
- pointer to mympd config struct
```
--------------------------------
### Build myMPD package with SDK
Source: https://jcorporation.github.io/myMPD/010-installation/compiling/openwrt.html
Execute the make command to compile the package after copying the packaging files into the SDK directory.
```bash
make -j$(nproc) BUILD_LOG=1
```
--------------------------------
### album_get_total_time
Source: https://jcorporation.github.io/myMPD/doxygen/html/album_8c.html
Gets the album duration from the album struct.
```APIDOC
## album_get_total_time()
### Description
Gets the album duration.
### Function Signature
unsigned album_get_total_time(const struct t_album *album)
### Parameters
- **album** (const struct t_album *) - Required - t_album struct representing the album.
### Returns
- **unsigned** - Album duration.
```
--------------------------------
### mympd.gpio_get(gpio)
Source: https://jcorporation.github.io/myMPD/050-scripting/functions/mygpiod.html
Gets the active state of a GPIO.
```APIDOC
## mympd.gpio_get(gpio)
### Description
Gets the active state of a GPIO.
### Parameters
- **gpio** (integer) - Required - The GPIO number.
### Return Value
- **state** (string) - The active state ("active" or "inactive").
### Example
```lua
local state = mympd.gpio_get(gpio)
```
```
--------------------------------
### signal_eventfd_init
Source: https://jcorporation.github.io/myMPD/doxygen/html/signal_8h.html
Initializes the eventfd and installs a minimal signal handler for SIGTERM, SIGINT, and SIGHUP. Returns true on success, else false.
```APIDOC
## signal_eventfd_init
### Description
Initializes the eventfd and installs a minimal signal handler for SIGTERM, SIGINT, and SIGHUP.
### Function Signature
bool signal_eventfd_init(void)
### Parameters
None
### Returns
- **bool** - true on success, else false
```
--------------------------------
### mympd_api_timer_calc_starttime
Source: https://jcorporation.github.io/myMPD/doxygen/html/mympd__api_2timer_8c.html
Calculates the offset from now for the next start time for a timer.
```APIDOC
## mympd_api_timer_calc_starttime
### Description
Calculates the offset from now for the next start time for a timer.
### Function Signature
int mympd_api_timer_calc_starttime(int _start_hour_, int _start_minute_, int _interval_)
### Parameters
- **_start_hour_** (int) - Required - Start hour.
- **_start_minute_** (int) - Required - Start minute.
- **_interval_** (int) - Required - Reschedule interval.
### Returns
- **int** - Unix timestamp of next start.
```
--------------------------------
### Switch to a partition and save to localStorage
Source: https://jcorporation.github.io/myMPD/jsdoc/modalPartitions.js.html
Sets the current partition in local settings and attempts to persist it to localStorage. Logs an error if saving fails.
```javascript
function switchPartition(partition) {
//save localSettings in browsers localStorage
localSettings.partition = partition;
try {
localStorage.setItem('partition', partition);
}
catch(err) {
const obj = {
"error": {
"message": "Can not save settings to localStorage: %{error}",
"data": {
"error": err.message
}
}
};
}
}
```
--------------------------------
### Show new partition tab
Source: https://jcorporation.github.io/myMPD/jsdoc/modalPartitions.js.html
Switches the modal to the 'new partition' tab, clears the name input, and focuses it.
```javascript
function showNewPartition() {
cleanupModalId('modalPartitions');
elGetById('modalPartitionsListTab').classList.remove('active');
elGetById('modalPartitionsNewTab').classList.add('active');
elHideId('modalPartitionsListFooter');
elShowId('modalPartitionsNewFooter');
const nameEl = elGetById('modalPartitionsNameInput');
nameEl.value = '';
setFocus(nameEl);
}
```
--------------------------------
### jsonrpc_notify_start()
Source: https://jcorporation.github.io/myMPD/doxygen/html/json__rpc_8h.html
Creates the start of a JSON-RPC notification with a specified event.
```APIDOC
## jsonrpc_notify_start()
### Description
Creates the start of a jsonrpc notification.
### Signature
sds jsonrpc_notify_start(sds _buffer_, enum jsonrpc_events _event_)
### Parameters
- **buffer** (sds) - Required - pointer to already allocated sds string
- **event** (enum jsonrpc_events) - Required - the event to use
### Returns
pointer to buffer with jsonrpc string
```
--------------------------------
### http_client_response_init()
Source: https://jcorporation.github.io/myMPD/doxygen/html/http__client_8h.html
Initializes the mg_client_response_t structure.
```APIDOC
## Function: http_client_response_init()
### Description
Initializes the http_client_response_t structure.
### Signature
```c
void http_client_response_init(struct mg_client_response_t *mg_client_response)
```
### Parameters
- **mg_client_response** (struct mg_client_response_t*) - pointer to the response structure to initialize
### Returns
Nothing (void)
```
--------------------------------
### Configure MPD on central server (/etc/mpd.conf)
Source: https://jcorporation.github.io/myMPD/070-additional-topics/mpd-satellite-setup.html
Sets the music and playlist directories and defines the database plugin and sticker file location on the central server.
```text
music_directory "/srv/mpd/music"
playlist_directory "/srv/mpd/playlists"
database {
plugin "simple"
path "/var/lib/mpd/tag_cache"
cache_directory "/var/lib/mpd/cache"
}
sticker_file "/var/lib/mpd/sticker.sql"
bind_to_address "0.0.0.0"
```
--------------------------------
### getScrollPosY(elopt) → {number}
Source: https://jcorporation.github.io/myMPD/jsdoc/module-elements_js.html
Gets the y-scrolling position.
```APIDOC
## getScrollPosY(elopt) → {number}
### Description
Gets the y-scrolling position.
### Parameters
- `el` (HTMLElement | Element) - Optional - element
### Returns
- the vertical scrolling position (number)
```
--------------------------------
### getBtnChkValueId(id)
Source: https://jcorporation.github.io/myMPD/jsdoc/module-elements_js.html
Gets the enabled state of a check button.
```APIDOC
## getBtnChkValueId(id)
### Description
Gets the enabled state of a check button.
### Parameters
- **id** (string) - Required - check button id
### Returns
- **boolean** - enabled = true, disabled = false
```
--------------------------------
### list_init()
Source: https://jcorporation.github.io/myMPD/doxygen/html/list_8c.html
Inits an already allocated list.
```APIDOC
## list_init()
### Description
Inits an already allocated list.
### Signature
void list_init(struct t_list *l)
### Parameters
- **l** (struct t_list *) - Pointer to the list to initialize.
```
--------------------------------
### getBtnChkValue(btn)
Source: https://jcorporation.github.io/myMPD/jsdoc/module-elements_js.html
Gets the enabled state of a check button.
```APIDOC
## getBtnChkValue(btn)
### Description
Gets the enabled state of a check button.
### Parameters
- **btn** (HTMLElement | EventTarget) - Required - check button id
### Returns
- **boolean** - enabled = true, disabled = false
```