Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 6 additions & 2 deletions NEWS
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
0.36 (not yet released)
* add command "tags"
* add commands "tags", "playlistlength", "searchplaylist", "stickernames", "stickertypes", "stickernamestypes", "searchsticker"
* complete command "sticker" API with "playlist" & "tags" entities subcommands (get/set/delete/list/find/inc/dec)
* fix a bug in "sticker" API "delete" subcommand where "name" parameter is mandatory
* update documentation
* concatenate multiple tag values
* require libmpdclient 2.23 or newer

0.35 (2023/12/21)
* fix null pointer dereference on bad status format
Expand All @@ -9,7 +13,7 @@
* add commands "lsdirs", "addplaylist", "delplaylist", "moveplaylist", "renplaylist", "clearplaylist"
* add "playlist" option "--with-prio"
* bash completion: pass "--" to mpc to allow parameters with dash
* bash completion: fix filenames with paranetheses
* bash completion: fix filenames with parentheses
* bash completion: override $MPC_FORMAT

0.34 (2021/11/30)
Expand Down
103 changes: 85 additions & 18 deletions doc/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -252,19 +252,19 @@ Playlist Commands

:command:`save <file>` - Saves playlist as <file>.

:command:`addplaylist <playlist> <file>` - Adds a song from the music database to the
playlist. The playlist will be created if it does not exist.
Can also read input from pipes.
:command:`addplaylist <playlist> <file>` - Adds a song from the music database to the playlist. The playlist will be created if it does not exist. Can also read input from pipes.

:command:`delplaylist <playlist> <songpos>` - Removes the song at given position from the playlist. Can
also read input from pipes.
:command:`delplaylist <playlist> <songpos>` - Removes the song at given position from the playlist. Can also read input from pipes.

:command:`moveplaylist <playlist> <from> <to>` - Moves the song at given <from> position
to the <to> position in the playlist.
:command:`moveplaylist <playlist> <from> <to>` - Moves the song at given <from> position to the <to> position in the playlist.

:command:`renplaylist <playlist> <new playlist>` - Rename a playlist.
:command:`renplaylist <playlist> <new playlist>` - Rename the playlist.

:command:`clearplaylist <playlist>` - Clear the playlist name (i.e. truncate playlist.m3u).
:command:`clearplaylist <playlist>` - Clear the playlist.

:command:`searchplaylist <playlist> <expression>` - Search the playlist for songs matching the expression.

:command:`playlistlength <playlist>` - Show the number of songs and their total playtime (in seconds) in the playlist.

Database Commands
^^^^^^^^^^^^^^^^^
Expand Down Expand Up @@ -363,23 +363,90 @@ Mount Commands
Sticker Commands
^^^^^^^^^^^^^^^^^

The :command:`sticker` command allows you to get and set song
stickers.
The :command:`sticker` command allows you to get and set stickers on "songs", "playlists" and several MPD "tags".

1. "song" API

:command:`sticker <file> set <key> <value>` - Set the value of a song
sticker.
:command:`sticker <file> set <name> <value>` - Set the value of a song sticker.

:command:`sticker <file> get <key>` - Print the value of a song
sticker.
:command:`sticker <file> get <name>` - Print the value of a song sticker.

:command:`sticker <file> list` - List all stickers of a song.

:command:`sticker <file> delete <key>` - Delete a song sticker.
:command:`sticker <file> delete <name>` - Delete a song sticker.

:command:`sticker <file> inc <name> <value>` - Increment the sticker of the song by the given value.

:command:`sticker <file> dec <name> <value>` - Decrement the sticker of the song by the given value.

:command:`sticker <dir> find <name>` - Search for stickers with the specified name, below the given directory.
Search for any values of the ``rated`` stickers under the ``Wolfgang Amadeus Mozart`` MPD folder::

mpc sticker "Wolfgang Amadeus Mozart" find rated

Search for any values of the ``rated`` stickers under any MPD folders::

mpc sticker "" find rated


2. "playlist" API

:command:`sticker <playlist> playlist-set <name> <value>` - Set the value of a playlist sticker.

:command:`sticker <playlist> playlist-get <name>` - Print the value of a playlist sticker.

:command:`sticker <playlist> playlist-list` - List all stickers of a playlist.

:command:`sticker <playlist> playlist-delete <name>` - Delete a playlist sticker.

:command:`sticker <playlist> playlist-inc <name> <value>` - Increment the sticker of the playlist by the given value.

Increments the ``played`` sticker of the ``Christmas Playlist`` playlist by ``1``::

mpc sticker "Christmas Playlist" playlist-inc played 1

:command:`sticker <playlist> playlist-dec <name> <value>` - Decrement the sticker of the playlist by the given value.

:command:`sticker <dir> playlist-find <name>` - Search for stickers with the specified name, below the given directory.

3. "tags" API

:command:`sticker <uri> tag-set <tag> <name> <value>` - Set the value of a playlist sticker.

:command:`sticker <uri> tag-get <tag> <name>` - Print the value of a tag sticker.

:command:`sticker <uri> tag-list <tag>` - List all stickers of a tag.

:command:`sticker <uri> tag-delete <tag> <name>` - Delete a tag sticker.

:command:`sticker <uri> tag-inc <tag> <name> <value>` - Increment the sticker of the tag by the given value.

Increments the ``played`` sticker of the ``Kraftwerk`` artist by 1::

mpc sticker "Kraftwerk" tag-inc Artist played 1

:command:`sticker <uri> tag-dec <tag> <name> <value>` - Decrement the sticker of the tag by the given value.

:command:`sticker <dir> tag-find <tag> <name>` - Search for stickers of the tag with the specified name, below the specified directory.

4. Misc commands

:command:`stickernames` - Display the list of unique sticker names.

:command:`stickertypes` - Display the list of available sticker types.

:command:`stickernamestypes <type>` - Display the list of unique sticker names for this sticker type.

:command:`searchsticker <type> <uri> <name> <oper> <value>` - Search for MPD <type> entities @<uri> having stickers matching the expression "<name> <oper> <value>".
Valid <oper> are ``=``, ``>``, ``<``, ``eq``, ``gt``, ``lt``, ``contains``, ``starts_with``

Search for any songs in the ``Wolfgang Amadeus Mozart`` MPD folder having sticker ``rated`` equals to ``Good``::

:command:`sticker <dir> find <key>` - Search for stickers with the
specified name, below the specified directory.
mpc searchsticker song "Wolfgang Amadeus Mozart" rated = Good

Search for any playlist having sticker ``played`` greater than 100::

mpc searchsticker playlist "" played gt 100

Output Commands
^^^^^^^^^^^^^^^
Expand Down
27 changes: 27 additions & 0 deletions src/command.c
Original file line number Diff line number Diff line change
Expand Up @@ -843,6 +843,33 @@ cmd_clearplaylist(int argc, char **argv, struct mpd_connection *conn)
return 0;
}

int
cmd_playlistlength(int argc, char **argv, struct mpd_connection *conn)
{
(void)argc; // silence warning about unused argument
const char* playlist = argv[0];

if (!mpd_send_playlistlength(conn, playlist))
return -1;

struct mpd_pair* pair = mpd_recv_pair_named(conn, "songs");
if (pair != NULL) {
printf("songs: %s\n", pair->value);
mpd_return_pair(conn, pair);
}

pair = mpd_recv_pair_named(conn, "playtime");
if (pair != NULL) {
printf("playtime: %s\n", pair->value);
mpd_return_pair(conn, pair);
}

if (!mpd_response_finish(conn))
return -1;

return 0;
}

int
cmd_load(int argc, char **argv, struct mpd_connection *conn)
{
Expand Down
25 changes: 7 additions & 18 deletions src/command.h
Original file line number Diff line number Diff line change
Expand Up @@ -50,23 +50,12 @@ int cmd_toggle(int argc, char **argv, struct mpd_connection *conn);
int cmd_partitionlist(int argc, char **argv, struct mpd_connection *conn);
int cmd_partitionmake(int argc, char **argv, struct mpd_connection *conn);
int cmd_partitiondelete(int argc, char **argv, struct mpd_connection *conn);

int
cmd_replaygain(int argc, char **argv, struct mpd_connection *conn);

int
cmd_channels(int argc, char **argv, struct mpd_connection *conn);

int
cmd_sendmessage(int argc, char **argv, struct mpd_connection *conn);

int
cmd_waitmessage(int argc, char **argv, struct mpd_connection *conn);

int
cmd_subscribe(int argc, char **argv, struct mpd_connection *conn);

int
cmd_tags(int argc, char **argv, struct mpd_connection *conn);
int cmd_replaygain(int argc, char **argv, struct mpd_connection *conn);
int cmd_channels(int argc, char **argv, struct mpd_connection *conn);
int cmd_sendmessage(int argc, char **argv, struct mpd_connection *conn);
int cmd_waitmessage(int argc, char **argv, struct mpd_connection *conn);
int cmd_subscribe(int argc, char **argv, struct mpd_connection *conn);
int cmd_tags(int argc, char **argv, struct mpd_connection *conn);
int cmd_playlistlength(int argc, char **argv, struct mpd_connection *conn);

#endif /* COMMAND_H */
10 changes: 8 additions & 2 deletions src/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ static const struct command {
/** NULL means they won't be shown in help */
const char *help;
} mpc_table [] = {
/* command, min, max, pipe, handler, usage, help */
/* command, min, max, pipe, handler, usage, help */
{"add", 0, -1, 1, cmd_add, "<uri>", "Add a song to the queue"},
{"addplaylist", 2, -1, 3, cmd_addplaylist, "<file> <uri> ...", "Add a song to the playlist"},
{"albumart", 1, 1, 0, cmd_albumart, "<uri>", "Download album art for the given song and write to stdout." },
Expand Down Expand Up @@ -95,6 +95,7 @@ static const struct command {
{"pause-if-playing", 0, 0, 0, cmd_pause_if_playing, "", "Pauses the currently playing song; exits with failure if not playing"},
{"play", 0, 1, 2, cmd_play, "[<position>]", "Start playing at <position>"},
{"playlist", 0, 1, 0, cmd_playlist, "[<playlist>]", "Print <playlist>"},
{"playlistlength", 1, 1, 0, cmd_playlistlength, "<file>", "Show the number of songs and their total playtime (seconds) in the playlist"},
{"prev", 0, 0, 0, cmd_prev, "", "Play the previous song in the queue"},
{"prio", 2, -1, 2, cmd_prio, "<prio> <position/range> ...", "Change song priorities in the queue"},
{"queued", 0, 0, 0, cmd_queued, "", "Show the next queued song"},
Expand All @@ -109,14 +110,19 @@ static const struct command {
{"search", 1, -1, 0, cmd_search, "<type> <query>", "Search for a song"},
{"searchadd", 1, -1, 0, cmd_searchadd, "<type> <query>", "Search songs and add them to the queue"},
{"searchplay", 1, -1, 0, cmd_searchplay, "<pattern>", "Find and play a song in the queue"},
{"searchplaylist", 2, 2, 0, cmd_searchplaylist, "<file> <expression>", "Search the playlist for songs matching the expression"},
{"seek", 1, 1, 0, cmd_seek, "[+-][HH:MM:SS]|<0-100>%", "Seeks to the specified position"},
{"seekthrough", 1, 1, 0, cmd_seek_through, "[+-][HH:MM:SS]", "Seeks by an amount of time within the song and playlist"},
{"sendmessage", 2, 2, 0, cmd_sendmessage, "<channel> <message>", "Send a message to the specified channel." },
{"shuffle", 0, 0, 0, cmd_shuffle, "", "Shuffle the queue"},
{"single", 0, 1, 0, cmd_single, "<on|once|off>", "Toggle single mode, or specify state"},
{"stats", 0, -1, 0, cmd_stats, "", "Display statistics about MPD"},
{"status", 0, -1, 0, cmd_status, "", NULL}, /* status was added for pedantic reasons */
{"sticker", 2, -1, 0, cmd_sticker, "<uri> <get|set|list|delete|find> [args..]", "Sticker management"},
{"sticker", 2, -1, 0, cmd_sticker, "<uri> <get[-playlist|-tag]|set[-playlist|-tag]|list[-playlist|-tag]|delete[-playlist|-tag]|find[-playlist|-tag]|inc[-playlist|-tag]|dec[-playlist|-tag]> [args..]", "Sticker management"},
{"stickernames", 0, 0, 0, cmd_stickernames, "", "Display the list of unique sticker names"},
{"stickertypes", 0, 0, 0, cmd_stickertypes, "", "Display the list of available sticker types"},
{"stickernamestypes",1, 1, 0, cmd_stickernamestypes,"<type>", "Display the list of unique sticker names for this sticker type"},
{"searchsticker", 5, 5, 0, cmd_searchsticker, "<type> <uri> <name> <oper> <value>", "Search for MPD <type> entities having sticker <name> <oper> to <value> set at <uri>"},
{"stop", 0, 0, 0, cmd_stop, "", "Stop playback"},
{"subscribe", 1, 1, 0, cmd_subscribe, "<channel>", "Subscribe to the specified channel and continuously receive messages." },
{"tab", 1, 1, 0, cmd_tab, "<path>", NULL},
Expand Down
29 changes: 28 additions & 1 deletion src/search.c
Original file line number Diff line number Diff line change
Expand Up @@ -170,7 +170,6 @@ cmd_search(int argc, char **argv, struct mpd_connection *conn)
return do_search(argc, argv, conn, false);
}


int
cmd_searchadd(int argc, char **argv, struct mpd_connection *conn)
{
Expand All @@ -188,3 +187,31 @@ cmd_findadd(int argc, char **argv, struct mpd_connection *conn)
{
return do_searchadd(argc, argv, conn, true);
}

int
cmd_searchplaylist(int argc, char **argv, struct mpd_connection *conn)
{
(void)argc; // silence warning about unused argument
const char* playlist = argv[0];
const char* expression = argv[1];

/* ask MPD to omit the tags which are not used by the
`--format` to reduce network transfer for tag values we're
not going to use anyway */
if (!mpd_command_list_begin(conn, false) ||
!send_tag_types_for_format(conn, options.custom_format ? options.format : NULL))
printErrorAndExit(conn);

mpd_playlist_search_begin(conn, playlist, expression);

if (!mpd_playlist_search_commit(conn))
printErrorAndExit(conn);

if (!mpd_command_list_end(conn))
printErrorAndExit(conn);

print_entity_list(conn, MPD_ENTITY_TYPE_SONG, options.custom_format);

my_finishCommand(conn);
return 0;
}
3 changes: 3 additions & 0 deletions src/search.h
Original file line number Diff line number Diff line change
Expand Up @@ -23,4 +23,7 @@ cmd_find(int argc, char **argv, struct mpd_connection *conn);
int
cmd_findadd(int argc, char **argv, struct mpd_connection *conn);

int
cmd_searchplaylist(int argc, char **argv, struct mpd_connection *conn);

#endif
Loading
Loading