### mpd_command_list_begin / mpd_command_list_end Source: https://context7.com/musicplayerdaemon/libmpdclient/llms.txt Functions for batching multiple commands into a single round-trip to the MPD server, reducing latency. `mpd_command_list_begin` starts the batch, and `mpd_command_list_end` sends the commands and prepares for receiving responses. ```APIDOC ## mpd_command_list_begin / mpd_command_list_end ### Description Send multiple commands in a single round-trip to reduce latency. ### Functions - `mpd_command_list_begin(struct mpd_connection *conn, bool allow_partial)`: Begins a command list. If `allow_partial` is true, each command gets an OK response. - `mpd_command_list_end(struct mpd_connection *conn)`: Ends the command list and sends all buffered commands to the server. ### Parameters #### `mpd_command_list_begin` - **conn** (`struct mpd_connection *`): A pointer to the MPD connection structure. - **allow_partial** (`bool`): If true, each command in the list will receive an OK response. ### Example ```c #include #include void batch_commands(struct mpd_connection *conn) { /* Begin a command list (OK mode: each command gets an OK response) */ mpd_command_list_begin(conn, true); mpd_send_status(conn); mpd_send_current_song(conn); mpd_command_list_end(conn); /* Receive responses in order */ struct mpd_status *status = mpd_recv_status(conn); if (status) { printf("State: %d, Volume: %d\n", mpd_status_get_state(status), mpd_status_get_volume(status)); mpd_status_free(status); } mpd_response_next(conn); /* advance to next sub-response */ struct mpd_song *song; while ((song = mpd_recv_song(conn)) != NULL) { printf("Now playing: %s\n", mpd_song_get_uri(song)); mpd_song_free(song); } mpd_response_finish(conn); } ``` ``` -------------------------------- ### Manage MPD Playback Queue with libmpdclient Source: https://context7.com/musicplayerdaemon/libmpdclient/llms.txt Demonstrates various functions for adding, deleting, moving, and shuffling songs in the MPD queue. Includes listing queue contents and retrieving specific songs. ```c #include #include #include void manage_queue(struct mpd_connection *conn) { /* Append a song to the end of the queue */ mpd_run_add(conn, "Artist/Album/01 - Song.flac"); /* Append a directory recursively */ mpd_run_add(conn, "Artist/Album"); /* Add and get back the new song's stable ID */ int song_id = mpd_run_add_id(conn, "Artist/Album/02 - Song.flac"); printf("Added song with ID: %d\n", song_id); /* Insert at position 0 (front of queue) */ mpd_run_add_id_to(conn, "Artist/Album/03 - Song.flac", 0); /* Delete by position */ mpd_run_delete(conn, 0); /* Delete by stable ID */ mpd_run_delete_id(conn, song_id); /* Delete a range of songs [2, 5) */ mpd_run_delete_range(conn, 2, 5); /* Move song from position 3 to position 0 */ mpd_run_move(conn, 3, 0); /* Swap two songs */ mpd_run_swap_id(conn, 10, 20); /* Shuffle the entire queue */ mpd_run_shuffle(conn); /* Clear the queue */ mpd_run_clear(conn); /* List all songs in the queue with metadata */ if (!mpd_send_list_queue_meta(conn)) return; struct mpd_song *song; while ((song = mpd_recv_song(conn)) != NULL) { printf("[%u] %s - %s\n", mpd_song_get_pos(song), mpd_song_get_tag(song, MPD_TAG_ARTIST, 0), mpd_song_get_tag(song, MPD_TAG_TITLE, 0)); mpd_song_free(song); } mpd_response_finish(conn); /* Get a single song by position */ struct mpd_song *s = mpd_run_get_queue_song_pos(conn, 2); if (s) { printf("Song at pos 2: %s\n", mpd_song_get_uri(s)); mpd_song_free(s); } /* Set playback range (start/end offsets in seconds) for a song in queue */ mpd_run_range_id(conn, song_id, 30.0f, 90.0f); } ``` -------------------------------- ### Establish MPD Connection with libmpdclient Source: https://context7.com/musicplayerdaemon/libmpdclient/llms.txt Connect to an MPD server using host, port, and timeout. Always check for connection errors after creation and free the connection when done. Environment variables MPD_HOST, MPD_PORT, and MPD_TIMEOUT can be used if NULL/0 are passed. ```c #include #include #include int main(void) { /* Connect to localhost:6600 with a 30-second timeout */ struct mpd_connection *conn = mpd_connection_new("localhost", 6600, 30000); if (conn == NULL) { fprintf(stderr, "Out of memory\n"); return EXIT_FAILURE; } /* Always check for connection errors */ if (mpd_connection_get_error(conn) != MPD_ERROR_SUCCESS) { fprintf(stderr, "Connection error: %s\n", mpd_connection_get_error_message(conn)); mpd_connection_free(conn); return EXIT_FAILURE; } /* Print the MPD server protocol version */ const unsigned *ver = mpd_connection_get_server_version(conn); printf("Connected to MPD protocol %u.%u.%u\n", ver[0], ver[1], ver[2]); /* Enable TCP keepalives for long-lived connections */ mpd_connection_set_keepalive(conn, true); /* Adjust timeout to 10 seconds after connection */ mpd_connection_set_timeout(conn, 10000); mpd_connection_free(conn); return EXIT_SUCCESS; } /* Output: Connected to MPD protocol 0 23 5 */ ``` -------------------------------- ### Stickers: mpd_run_sticker_set / mpd_send_sticker_get / mpd_send_sticker_find Source: https://context7.com/musicplayerdaemon/libmpdclient/llms.txt Functions for managing per-song custom metadata, known as stickers. Stickers are client-defined key/value pairs attached to MPD objects. This includes setting, incrementing, getting, listing, finding, and deleting stickers. ```APIDOC ## Stickers ### Description Per-song custom metadata. Stickers are arbitrary client-defined key/value pairs attached to MPD objects (typically songs). They are stored by MPD but not interpreted by it. ### Functions - `mpd_run_sticker_set(struct mpd_connection *conn, const char *type, const char *path, const char *name, const char *value)`: Sets a sticker. - `mpd_send_sticker_inc(struct mpd_connection *conn, const char *type, const char *path, const char *name, long long increment)`: Increments a sticker value. - `mpd_send_sticker_get(struct mpd_connection *conn, const char *type, const char *path, const char *name)`: Sends a request to get a specific sticker. - `mpd_send_sticker_list(struct mpd_connection *conn, const char *type, const char *path)`: Sends a request to list all stickers for a given object. - `mpd_send_sticker_find(struct mpd_connection *conn, const char *type, const char *path, const char *name)`: Finds all objects of a given type and path that have a specific sticker. - `mpd_run_sticker_delete(struct mpd_connection *conn, const char *type, const char *path, const char *name)`: Deletes a sticker. ### Parameters #### `mpd_run_sticker_set`, `mpd_send_sticker_inc`, `mpd_send_sticker_get`, `mpd_send_sticker_list`, `mpd_send_sticker_find`, `mpd_run_sticker_delete` - **conn** (`struct mpd_connection *`): A pointer to the MPD connection structure. - **type** (`const char *`): The type of the MPD object (e.g., "song"). - **path** (`const char *`): The path or URI of the MPD object. - **name** (`const char *`): The name of the sticker. - **value** (`const char *`): The value of the sticker (for `mpd_run_sticker_set`). - **increment** (`long long`): The amount to increment the sticker by (for `mpd_send_sticker_inc`). ### Return Value - `mpd_run_sticker_set`, `mpd_run_sticker_delete`: Returns true on success, false on error. - `mpd_send_sticker_get`, `mpd_send_sticker_list`, `mpd_send_sticker_find`: These functions send commands. Responses are received using `mpd_recv_sticker` and `mpd_return_sticker`. ### Example ```c #include #include void sticker_examples(struct mpd_connection *conn) { const char *uri = "Rock/Band/song.mp3"; /* Set a play count sticker */ mpd_run_sticker_set(conn, "song", uri, "playcount", "42"); /* Increment playcount by 1 */ mpd_send_sticker_inc(conn, "song", uri, "playcount", 1); mpd_response_finish(conn); /* Get a sticker value */ mpd_send_sticker_get(conn, "song", uri, "playcount"); struct mpd_pair *pair = mpd_recv_sticker(conn); if (pair) { size_t name_len; const char *value = mpd_parse_sticker(pair->value, &name_len); printf("playcount = %s\n", value); mpd_return_sticker(conn, pair); } mpd_response_finish(conn); /* List all stickers on a song */ mpd_send_sticker_list(conn, "song", uri); while ((pair = mpd_recv_sticker(conn)) != NULL) { size_t name_len; const char *val = mpd_parse_sticker(pair->value, &name_len); printf("Sticker: %.*s = %s\n", (int)name_len, pair->value, val); mpd_return_sticker(conn, pair); } mpd_response_finish(conn); /* Find all songs in a directory with a specific sticker */ mpd_send_sticker_find(conn, "song", "Rock/Band", "rating"); while ((pair = mpd_recv_sticker(conn)) != NULL) { printf("Has rating sticker\n"); mpd_return_sticker(conn, pair); } mpd_response_finish(conn); /* Delete a sticker */ mpd_run_sticker_delete(conn, "song", uri, "playcount"); } ``` ``` -------------------------------- ### Configure MPD Playback Modes with mpd_run_* Functions Source: https://context7.com/musicplayerdaemon/libmpdclient/llms.txt Configure playlist traversal modes like repeat, random shuffle, single-song, and consume. Crossfade and MixRamp settings can also be adjusted. Ensure a valid mpd_connection is established. ```c #include void set_playback_modes(struct mpd_connection *conn) { /* Enable repeat mode */ mpd_run_repeat(conn, true); /* Enable random/shuffle mode */ mpd_run_random(conn, true); /* Single mode: stop after current song (MPD_SINGLE_ON), or play once then disable (MPD_SINGLE_ONESHOT) */ mpd_run_single_state(conn, MPD_SINGLE_ONESHOT); /* Consume mode: remove each song after it plays */ mpd_run_consume_state(conn, MPD_CONSUME_ON); /* Crossfade: 5 second overlap between songs */ mpd_run_crossfade(conn, 5); /* MixRamp: overlap at -17dB threshold (requires MixRamp tags) */ mpd_run_mixrampdb(conn, -17.0f); mpd_run_mixrampdelay(conn, 2.0f); } ``` -------------------------------- ### Low-level async connection with mpd_async Source: https://context7.com/musicplayerdaemon/libmpdclient/llms.txt Use this for non-blocking I/O integration with event loops. It requires manual event polling and I/O handling. ```c #include #include #include #include #include #include #include #include void async_example(int fd) { /* Create async connection from an already-connected socket */ struct mpd_async *async = mpd_async_new(fd); if (!async) { perror("mpd_async_new"); return; } /* Queue a command without blocking */ mpd_async_send_command(async, "status", NULL); /* Poll until the fd is readable */ struct pollfd pfd = { .fd = mpd_async_get_fd(async), .events = POLLIN }; while (true) { /* Ask what events to wait for */ enum mpd_async_event want = mpd_async_events(async); pfd.events = 0; if (want & MPD_ASYNC_EVENT_READ) pfd.events |= POLLIN; if (want & MPD_ASYNC_EVENT_WRITE) pfd.events |= POLLOUT; poll(&pfd, 1, 1000); enum mpd_async_event got = 0; if (pfd.revents & POLLIN) got |= MPD_ASYNC_EVENT_READ; if (pfd.revents & POLLOUT) got |= MPD_ASYNC_EVENT_WRITE; if (pfd.revents & POLLHUP) got |= MPD_ASYNC_EVENT_HUP; if (pfd.revents & POLLERR) got |= MPD_ASYNC_EVENT_ERROR; if (!mpd_async_io(async, got)) { fprintf(stderr, "I/O error: %s\n", mpd_async_get_error_message(async)); break; } /* Try to receive a line */ char *line = mpd_async_recv_line(async); if (line) { printf("Received: %s\n", line); if (strcmp(line, "OK") == 0) break; } } mpd_async_free(async); } ``` -------------------------------- ### Manage MPD Stickers with libmpdclient Source: https://context7.com/musicplayerdaemon/libmpdclient/llms.txt Use functions like `mpd_run_sticker_set`, `mpd_send_sticker_get`, `mpd_send_sticker_inc`, `mpd_send_sticker_list`, `mpd_send_sticker_find`, and `mpd_run_sticker_delete` to manage per-song custom metadata (stickers). Stickers are arbitrary key/value pairs attached to MPD objects. ```c #include #include void sticker_examples(struct mpd_connection *conn) { const char *uri = "Rock/Band/song.mp3"; /* Set a play count sticker */ mpd_run_sticker_set(conn, "song", uri, "playcount", "42"); /* Increment playcount by 1 */ mpd_send_sticker_inc(conn, "song", uri, "playcount", 1); mpd_response_finish(conn); /* Get a sticker value */ mpd_send_sticker_get(conn, "song", uri, "playcount"); struct mpd_pair *pair = mpd_recv_sticker(conn); if (pair) { size_t name_len; const char *value = mpd_parse_sticker(pair->value, &name_len); printf("playcount = %s\n", value); mpd_return_sticker(conn, pair); } mpd_response_finish(conn); /* List all stickers on a song */ mpd_send_sticker_list(conn, "song", uri); while ((pair = mpd_recv_sticker(conn)) != NULL) { size_t name_len; const char *val = mpd_parse_sticker(pair->value, &name_len); printf("Sticker: %.*s = %s\n", (int)name_len, pair->value, val); mpd_return_sticker(conn, pair); } mpd_response_finish(conn); /* Find all songs in a directory with a specific sticker */ mpd_send_sticker_find(conn, "song", "Rock/Band", "rating"); while ((pair = mpd_recv_sticker(conn)) != NULL) { printf("Has rating sticker\n"); mpd_return_sticker(conn, pair); } mpd_response_finish(conn); /* Delete a sticker */ mpd_run_sticker_delete(conn, "song", uri, "playcount"); } ``` -------------------------------- ### Search MPD Database with Various Constraints Source: https://context7.com/musicplayerdaemon/libmpdclient/llms.txt Build and execute database searches with tag, URI, modification-time, and expression constraints. Results are streamed back with mpd_recv_song(). ```c #include #include #include void search_examples(struct mpd_connection *conn) { /* --- Exact tag search --- */ mpd_search_db_songs(conn, true); /* exact=true */ mpd_search_add_tag_constraint(conn, MPD_OPERATOR_DEFAULT, MPD_TAG_ARTIST, "Pink Floyd"); mpd_search_add_tag_constraint(conn, MPD_OPERATOR_DEFAULT, MPD_TAG_ALBUM, "The Wall"); mpd_search_commit(conn); struct mpd_song *song; while ((song = mpd_recv_song(conn)) != NULL) { printf("%s\n", mpd_song_get_uri(song)); mpd_song_free(song); } mpd_response_finish(conn); /* --- Substring search with sort and window --- */ mpd_search_db_songs(conn, false); /* exact=false (substring) */ mpd_search_add_any_tag_constraint(conn, MPD_OPERATOR_DEFAULT, "beethoven"); mpd_search_add_sort_tag(conn, MPD_TAG_ALBUM, false); /* sort ascending */ mpd_search_add_window(conn, 0, 20); /* first 20 results */ mpd_search_commit(conn); while ((song = mpd_recv_song(conn)) != NULL) { printf("%s — %s\n", mpd_song_get_tag(song, MPD_TAG_TITLE, 0), mpd_song_get_tag(song, MPD_TAG_ALBUM, 0)); mpd_song_free(song); } mpd_response_finish(conn); /* --- Expression search (MPD >= 0.21) --- */ mpd_search_db_songs(conn, false); mpd_search_add_expression(conn, "(Artist == 'The Beatles')"); mpd_search_commit(conn); while ((song = mpd_recv_song(conn)) != NULL) { printf("%s\n", mpd_song_get_uri(song)); mpd_song_free(song); } mpd_response_finish(conn); /* --- Search by modification date --- */ time_t since = time(NULL) - 7 * 24 * 3600; /* last 7 days */ mpd_search_db_songs(conn, false); mpd_search_add_modified_since_constraint(conn, MPD_OPERATOR_DEFAULT, since); mpd_search_commit(conn); while ((song = mpd_recv_song(conn)) != NULL) { printf("Recent: %s\n", mpd_song_get_uri(song)); mpd_song_free(song); } mpd_response_finish(conn); /* --- List all unique artists --- */ mpd_search_db_tags(conn, MPD_TAG_ARTIST); mpd_search_commit(conn); struct mpd_pair *pair; while ((pair = mpd_recv_pair_tag(conn, MPD_TAG_ARTIST)) != NULL) { printf("Artist: %s\n", pair->value); mpd_return_pair(conn, pair); } mpd_response_finish(conn); /* --- Add search results directly to queue --- */ mpd_search_add_db_songs(conn, true); mpd_search_add_tag_constraint(conn, MPD_OPERATOR_DEFAULT, MPD_TAG_GENRE, "Jazz"); mpd_search_commit(conn); /* no recv needed; songs go directly into queue */ mpd_response_finish(conn); } ``` -------------------------------- ### Control MPD Playback State with mpd_run_* Functions Source: https://context7.com/musicplayerdaemon/libmpdclient/llms.txt Use these functions to control MPD's playback state. They combine sending commands and finishing responses for convenience. Ensure a valid mpd_connection is established before calling. ```c #include #include void control_playback(struct mpd_connection *conn) { /* Start playback */ if (!mpd_run_play(conn)) { fprintf(stderr, "play failed: %s\n", mpd_connection_get_error_message(conn)); mpd_connection_clear_error(conn); } /* Play a specific queue position (0-based) */ mpd_run_play_pos(conn, 3); /* Play a specific song by its stable ID */ mpd_run_play_id(conn, 42); /* Pause / resume */ mpd_run_pause(conn, true); /* pause */ mpd_run_pause(conn, false); /* resume */ /* Skip tracks */ mpd_next(conn); mpd_previous(conn); /* Stop playback */ mpd_run_stop(conn); /* Seek to 1 minute 30 seconds in a song by id */ mpd_run_seek_id(conn, 42, 90); /* Seek with float precision */ mpd_run_seek_id_float(conn, 42, 90.5f); /* Seek relative: skip forward 10 seconds from current position */ mpd_run_seek_current(conn, 10.0f, true); } ``` -------------------------------- ### Batch MPD Commands with mpd_command_list_begin Source: https://context7.com/musicplayerdaemon/libmpdclient/llms.txt Execute multiple MPD commands in a single network round-trip using `mpd_command_list_begin` and `mpd_command_list_end` to reduce latency. Ensure to process responses in order using functions like `mpd_recv_status` and `mpd_recv_song`. ```c #include #include void batch_commands(struct mpd_connection *conn) { /* Begin a command list (OK mode: each command gets an OK response) */ mpd_command_list_begin(conn, true); mpd_send_status(conn); mpd_send_current_song(conn); mpd_command_list_end(conn); /* Receive responses in order */ struct mpd_status *status = mpd_recv_status(conn); if (status) { printf("State: %d, Volume: %d\n", mpd_status_get_state(status), mpd_status_get_volume(status)); mpd_status_free(status); } mpd_response_next(conn); /* advance to next sub-response */ struct mpd_song *song; while ((song = mpd_recv_song(conn)) != NULL) { printf("Now playing: %s\n", mpd_song_get_uri(song)); mpd_song_free(song); } mpd_response_finish(conn); } ``` -------------------------------- ### mpd_send_list_meta, mpd_run_update, mpd_run_rescan Source: https://context7.com/musicplayerdaemon/libmpdclient/llms.txt Browse the music database by listing directory contents and trigger database rescans. ```APIDOC ## mpd_send_list_meta / mpd_run_update ### Description List directories and files in the music database, and trigger a database rescan. ### Method This is a sequence of C function calls. ### Parameters This section is not directly applicable as these are C function calls, not HTTP endpoints. ### Request Example ```c #include #include void browse_and_update(struct mpd_connection *conn) { /* List root directory contents */ if (!mpd_send_list_meta(conn, NULL)) return; struct mpd_entity *entity; while ((entity = mpd_recv_entity(conn)) != NULL) { switch (mpd_entity_get_type(entity)) { case MPD_ENTITY_TYPE_SONG: { const struct mpd_song *s = mpd_entity_get_song(entity); printf("Song: %s\n", mpd_song_get_uri(s)); break; } case MPD_ENTITY_TYPE_DIRECTORY: { const struct mpd_directory *d = mpd_entity_get_directory(entity); printf("Directory: %s\n", mpd_directory_get_path(d)); break; } case MPD_ENTITY_TYPE_PLAYLIST: { const struct mpd_playlist *p = mpd_entity_get_playlist(entity); printf("Playlist: %s\n", mpd_playlist_get_path(p)); break; } default: break; } mpd_entity_free(entity); } mpd_response_finish(conn); /* Update the entire music database */ unsigned job_id = mpd_run_update(conn, NULL); printf("Update job ID: %u\n", job_id); /* Update only a subdirectory */ mpd_run_update(conn, "Classical/Beethoven"); /* Rescan (re-reads even unmodified files) */ mpd_run_rescan(conn, NULL); } ``` ### Response Results are streamed back via `mpd_recv_entity()` for browsing, and `mpd_run_update`/`mpd_run_rescan` return job IDs or status. ``` -------------------------------- ### Basic playback commands Source: https://context7.com/musicplayerdaemon/libmpdclient/llms.txt Control MPD's playback state using functions like `mpd_run_play`, `mpd_run_stop`, `mpd_run_pause`, `mpd_run_next`, and `mpd_run_previous`. These functions combine sending commands and finishing responses for convenience. ```APIDOC ## Basic playback commands Control MPD's playback state. The `mpd_run_*` functions combine the send and response-finish steps into a single call for convenience. ### Functions: - `mpd_run_play(conn)`: Starts playback. - `mpd_run_play_pos(conn, pos)`: Plays a specific queue position (0-based). - `mpd_run_play_id(conn, id)`: Plays a specific song by its stable ID. - `mpd_run_pause(conn, state)`: Pauses (true) or resumes (false) playback. - `mpd_run_next(conn)`: Skips to the next track. - `mpd_run_previous(conn)`: Skips to the previous track. - `mpd_run_stop(conn)`: Stops playback. - `mpd_run_seek_id(conn, id, time)`: Seeks to a specific time (in seconds) within a song identified by its ID. - `mpd_run_seek_id_float(conn, id, time)`: Seeks to a specific time (in seconds, with float precision) within a song identified by its ID. - `mpd_run_seek_current(conn, time, relative)`: Seeks relative to the current position by a specified time (in seconds). `relative` should be true for relative seeking. ``` -------------------------------- ### Synchronize Queue Changes with mpd_send_queue_changes_meta Source: https://context7.com/musicplayerdaemon/libmpdclient/llms.txt Fetches metadata for songs that have changed in the queue since a specified version. Includes a bandwidth-efficient variant to retrieve only position and ID. ```c #include #include void sync_queue(struct mpd_connection *conn, unsigned known_version) { /* Get full metadata for changed songs since known_version */ if (!mpd_send_queue_changes_meta(conn, known_version)) return; struct mpd_song *song; while ((song = mpd_recv_song(conn)) != NULL) { printf("Changed: pos=%u id=%u uri=%s\n", mpd_song_get_pos(song), mpd_song_get_id(song), mpd_song_get_uri(song)); mpd_song_free(song); } mpd_response_finish(conn); /* Bandwidth-efficient variant: only position + id */ if (!mpd_send_queue_changes_brief(conn, known_version)) return; unsigned pos, id; while (mpd_recv_queue_change_brief(conn, &pos, &id)) printf("Changed brief: pos=%u id=%u\n", pos, id); mpd_response_finish(conn); } ``` -------------------------------- ### Browse and Update MPD Database Source: https://context7.com/musicplayerdaemon/libmpdclient/llms.txt List directories and files in the music database, and trigger a database rescan. Use mpd_send_list_meta to browse and mpd_run_update or mpd_run_rescan to update. ```c #include #include void browse_and_update(struct mpd_connection *conn) { /* List root directory contents */ if (!mpd_send_list_meta(conn, NULL)) return; struct mpd_entity *entity; while ((entity = mpd_recv_entity(conn)) != NULL) { switch (mpd_entity_get_type(entity)) { case MPD_ENTITY_TYPE_SONG: { const struct mpd_song *s = mpd_entity_get_song(entity); printf("Song: %s\n", mpd_song_get_uri(s)); break; } case MPD_ENTITY_TYPE_DIRECTORY: { const struct mpd_directory *d = mpd_entity_get_directory(entity); printf("Directory: %s\n", mpd_directory_get_path(d)); break; } case MPD_ENTITY_TYPE_PLAYLIST: { const struct mpd_playlist *p = mpd_entity_get_playlist(entity); printf("Playlist: %s\n", mpd_playlist_get_path(p)); break; } default: break; } mpd_entity_free(entity); } mpd_response_finish(conn); /* Update the entire music database */ unsigned job_id = mpd_run_update(conn, NULL); printf("Update job ID: %u\n", job_id); /* Update only a subdirectory */ mpd_run_update(conn, "Classical/Beethoven"); /* Rescan (re-reads even unmodified files) */ mpd_run_rescan(conn, NULL); } ``` -------------------------------- ### Playback mode options Source: https://context7.com/musicplayerdaemon/libmpdclient/llms.txt Configure playlist traversal modes including repeat, random shuffle, single-song, and consume (auto-remove played songs). ```APIDOC ## Playback mode options Configure playlist traversal modes: repeat, random shuffle, single-song, and consume (auto-remove played songs). ### Functions: - `mpd_run_repeat(conn, state)`: Enables (true) or disables (false) repeat mode. - `mpd_run_random(conn, state)`: Enables (true) or disables (false) random/shuffle mode. - `mpd_run_single_state(conn, state)`: Configures single-song mode. Use `MPD_SINGLE_ON` to play once then stop, or `MPD_SINGLE_ONESHOT` to play once then disable. - `mpd_run_consume_state(conn, state)`: Enables (e.g., `MPD_CONSUME_ON`) or disables consume mode, where each song is removed after it plays. - `mpd_run_crossfade(conn, seconds)`: Sets the crossfade duration in seconds. - `mpd_run_mixrampdb(conn, db)`: Sets the MixRamp threshold in decibels (dB). Requires MixRamp tags. - `mpd_run_mixrampdelay(conn, seconds)`: Sets the MixRamp delay in seconds. ``` -------------------------------- ### Fetch MPD Server Status with mpd_run_status Source: https://context7.com/musicplayerdaemon/libmpdclient/llms.txt Retrieves the full player status including playback state, volume, elapsed time, queue version, and audio format details. Remember to free the returned mpd_status object using mpd_status_free. ```c #include #include void print_status(struct mpd_connection *conn) { struct mpd_status *status = mpd_run_status(conn); if (status == NULL) { fprintf(stderr, "status failed: %s\n", mpd_connection_get_error_message(conn)); return; } printf("Volume: %d%%\n", mpd_status_get_volume(status)); printf("Repeat: %s\n", mpd_status_get_repeat(status) ? "on" : "off"); printf("Random: %s\n", mpd_status_get_random(status) ? "on" : "off"); printf("Queue length: %u\n", mpd_status_get_queue_length(status)); printf("Queue version: %u\n", mpd_status_get_queue_version(status)); enum mpd_state state = mpd_status_get_state(status); if (state == MPD_STATE_PLAY || state == MPD_STATE_PAUSE) { printf("State: %s\n", state == MPD_STATE_PLAY ? "playing" : "paused"); printf("Song position: %d\n", mpd_status_get_song_pos(status)); printf("Song ID: %d\n", mpd_status_get_song_id(status)); printf("Elapsed: %u ms\n", mpd_status_get_elapsed_ms(status)); printf("Total: %u s\n", mpd_status_get_total_time(status)); printf("Bitrate: %u kbps\n", mpd_status_get_kbit_rate(status)); const struct mpd_audio_format *af = mpd_status_get_audio_format(status); if (af != NULL) printf("Audio: %uHz %ubit %uch\n", af->sample_rate, af->bits, af->channels); } if (mpd_status_get_error(status) != NULL) printf("MPD error msg: %s\n", mpd_status_get_error(status)); mpd_status_free(status); } /* Example output: Volume: 75% Repeat: off Random: on Queue length: 42 State: playing Elapsed: 34500 ms Total: 243 s Bitrate: 320 kbps Audio: 44100Hz 24bit 2ch */ ``` -------------------------------- ### mpd_connection_new Source: https://context7.com/musicplayerdaemon/libmpdclient/llms.txt Establishes a synchronous connection to an MPD server via TCP or Unix socket. It's crucial to check for connection errors after creation using `mpd_connection_get_error()`. ```APIDOC ## mpd_connection_new ### Description Opens a blocking TCP or Unix socket connection to an MPD server. Pass `NULL`/`0` to use the `MPD_HOST`, `MPD_PORT`, and `MPD_TIMEOUT` environment variables. Returns a non-NULL `mpd_connection` even on connection failure — always check `mpd_connection_get_error()` after creation. ### Method `mpd_connection_new(const char *host, unsigned short port, unsigned int timeout_ms)` ### Parameters #### Path Parameters None #### Query Parameters None #### Request Body None ### Request Example ```c #include #include #include int main(void) { /* Connect to localhost:6600 with a 30-second timeout */ struct mpd_connection *conn = mpd_connection_new("localhost", 6600, 30000); if (conn == NULL) { fprintf(stderr, "Out of memory\n"); return EXIT_FAILURE; } /* Always check for connection errors */ if (mpd_connection_get_error(conn) != MPD_ERROR_SUCCESS) { fprintf(stderr, "Connection error: %s\n", mpd_connection_get_error_message(conn)); mpd_connection_free(conn); return EXIT_FAILURE; } /* Print the MPD server protocol version */ const unsigned *ver = mpd_connection_get_server_version(conn); printf("Connected to MPD protocol %u.%u.%u\n", ver[0], ver[1], ver[2]); /* Enable TCP keepalives for long-lived connections */ mpd_connection_set_keepalive(conn, true); /* Adjust timeout to 10 seconds after connection */ mpd_connection_set_timeout(conn, 10000); mpd_connection_free(conn); return EXIT_SUCCESS; } ``` ### Response #### Success Response (200) Returns a `struct mpd_connection *` pointer. This pointer is valid even if a connection error occurred; use `mpd_connection_get_error()` to check for errors. #### Response Example ``` Connected to MPD protocol 0 23 5 ``` ``` -------------------------------- ### Output Device Management Source: https://context7.com/musicplayerdaemon/libmpdclient/llms.txt Functions for enumerating and toggling MPD's audio output devices. ```APIDOC ## Output Device Management ### Description Functions for enumerating and toggling MPD's audio output devices. ### Functions - `mpd_send_outputs(conn)`: Sends a command to list all audio output devices. - `mpd_recv_output(conn)`: Receives and parses an audio output device entry. - `mpd_output_get_id(output)`: Gets the ID of the output device. - `mpd_output_get_name(output)`: Gets the name of the output device. - `mpd_output_get_enabled(output)`: Checks if the output device is enabled. - `mpd_output_get_plugin(output)`: Gets the plugin name for the output device. - `mpd_output_first_attribute(output)`: Gets the first attribute of the output device. - `mpd_output_next_attribute(output)`: Gets the next attribute of the output device. - `mpd_output_free(output)`: Frees memory associated with an output object. - `mpd_run_enable_output(conn, output_id)`: Enables a specific audio output device. - `mpd_run_disable_output(conn, output_id)`: Disables a specific audio output device. - `mpd_run_toggle_output(conn, output_id)`: Toggles the enabled state of a specific audio output device. - `mpd_run_output_set(conn, output_id, name, value)`: Sets a runtime attribute for a specific output device. ### Example Usage ```c #include #include void manage_outputs(struct mpd_connection *conn) { /* List all audio output devices */ if (!mpd_send_outputs(conn)) return; struct mpd_output *output; while ((output = mpd_recv_output(conn)) != NULL) { printf("Output %u: %s [%s] plugin=%s\n", mpd_output_get_id(output), mpd_output_get_name(output), mpd_output_get_enabled(output) ? "enabled" : "disabled", mpd_output_get_plugin(output) ? mpd_output_get_plugin(output) : "?"); /* Iterate output attributes */ const struct mpd_pair *attr = mpd_output_first_attribute(output); while (attr != NULL) { printf(" attr: %s = %s\n", attr->name, attr->value); attr = mpd_output_next_attribute(output); } mpd_output_free(output); } mpd_response_finish(conn); /* Enable output 0, disable output 1 */ mpd_run_enable_output(conn, 0); mpd_run_disable_output(conn, 1); /* Toggle output 0 */ mpd_run_toggle_output(conn, 0); /* Set a runtime output attribute (e.g., HTTPD port) */ mpd_run_output_set(conn, 0, "port", "8080"); } ``` ``` -------------------------------- ### Handle MPD Server-Push Events with mpd_run_idle Source: https://context7.com/musicplayerdaemon/libmpdclient/llms.txt Use `mpd_run_idle` and `mpd_run_idle_mask` to enter MPD's idle mode and receive push notifications for state changes. `mpd_run_noidle` can be used for non-blocking polls. ```c #include #include void event_loop(struct mpd_connection *conn) { /* Block until any event occurs */ enum mpd_idle events = mpd_run_idle(conn); if (events == 0) { fprintf(stderr, "idle error: %s\n", mpd_connection_get_error_message(conn)); return; } if (events & MPD_IDLE_PLAYER) printf("Player state changed\n"); if (events & MPD_IDLE_QUEUE) printf("Queue changed\n"); if (events & MPD_IDLE_MIXER) printf("Volume changed\n"); if (events & MPD_IDLE_DATABASE) printf("Database updated\n"); if (events & MPD_IDLE_STORED_PLAYLIST) printf("Stored playlists changed\n"); if (events & MPD_IDLE_OUTPUT) printf("Audio outputs changed\n"); if (events & MPD_IDLE_OPTIONS) printf("Playback options changed\n"); /* Listen only for player and queue events */ events = mpd_run_idle_mask(conn, MPD_IDLE_PLAYER | MPD_IDLE_QUEUE); printf("Events received: 0x%x\n", events); /* Non-blocking poll: send noidle then read what happened */ mpd_send_idle(conn); /* ... do other work using the fd from mpd_connection_get_fd(conn) ... */ events = mpd_run_noidle(conn); printf("Events while working: 0x%x\n", events); } ``` -------------------------------- ### Manage MPD Audio Outputs Source: https://context7.com/musicplayerdaemon/libmpdclient/llms.txt Enumerate and toggle MPD's audio output devices. This allows for dynamic control over where audio is routed. Ensure the connection is valid before proceeding. ```c #include #include void manage_outputs(struct mpd_connection *conn) { /* List all audio output devices */ if (!mpd_send_outputs(conn)) return; struct mpd_output *output; while ((output = mpd_recv_output(conn)) != NULL) { printf("Output %u: %s [%s] plugin=%s\n", mpd_output_get_id(output), mpd_output_get_name(output), mpd_output_get_enabled(output) ? "enabled" : "disabled", mpd_output_get_plugin(output) ? mpd_output_get_plugin(output) : "?"); /* Iterate output attributes */ const struct mpd_pair *attr = mpd_output_first_attribute(output); while (attr != NULL) { printf(" attr: %s = %s\n", attr->name, attr->value); attr = mpd_output_next_attribute(output); } mpd_output_free(output); } mpd_response_finish(conn); /* Enable output 0, disable output 1 */ mpd_run_enable_output(conn, 0); mpd_run_disable_output(conn, 1); /* Toggle output 0 */ mpd_run_toggle_output(conn, 0); /* Set a runtime output attribute (e.g., HTTPD port) */ mpd_run_output_set(conn, 0, "port", "8080"); } ``` -------------------------------- ### Manage MPD Playlists Source: https://context7.com/musicplayerdaemon/libmpdclient/llms.txt Use these functions to create, load, modify, and delete persistent .m3u playlist files on the MPD server. Ensure the MPD server is accessible and the connection is established before calling these functions. ```c #include #include void manage_playlists(struct mpd_connection *conn) { /* List all stored playlists */ mpd_send_list_playlists(conn); struct mpd_playlist *pl; while ((pl = mpd_recv_playlist(conn)) != NULL) { printf("Playlist: %s (modified: %ld)\n", mpd_playlist_get_path(pl), (long)mpd_playlist_get_last_modified(pl)); mpd_playlist_free(pl); } mpd_response_finish(conn); /* Load a stored playlist into the queue */ mpd_run_load(conn, "my_favorites"); /* Load only a portion (songs 0..9) */ mpd_run_load_range(conn, "my_favorites", 0, 10); /* Save the current queue to a new playlist */ mpd_run_save(conn, "session_2024"); /* Save with mode control (create / replace / append) */ mpd_run_save_queue(conn, "session_2024", MPD_QUEUE_SAVE_MODE_REPLACE); /* Add a song to a stored playlist */ mpd_run_playlist_add(conn, "my_favorites", "Artist/Album/Song.mp3"); /* Delete a song at position 3 from a stored playlist */ mpd_run_playlist_delete(conn, "my_favorites", 3); /* Rename a playlist */ mpd_run_rename(conn, "session_2024", "session_backup"); /* Remove a stored playlist entirely */ mpd_run_rm(conn, "session_backup"); } ```