aboutsummaryrefslogtreecommitdiffstats
path: root/src/command.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/command.c')
-rw-r--r--src/command.c282
1 files changed, 173 insertions, 109 deletions
diff --git a/src/command.c b/src/command.c
index d30b63594..cbc77edc1 100644
--- a/src/command.c
+++ b/src/command.c
@@ -32,7 +32,7 @@
#include "volume.h"
#include "stats.h"
#include "permission.h"
-#include "buffer2array.h"
+#include "tokenizer.h"
#include "stored_playlist.h"
#include "ack.h"
#include "output_command.h"
@@ -58,7 +58,6 @@
#include <stdlib.h>
#include <errno.h>
-#define COMMAND_STATUS_VOLUME "volume"
#define COMMAND_STATUS_STATE "state"
#define COMMAND_STATUS_REPEAT "repeat"
#define COMMAND_STATUS_SINGLE "single"
@@ -400,7 +399,7 @@ handle_play(struct client *client, int argc, char *argv[])
if (argc == 2 && !check_int(client, &song, argv[1], need_positive))
return COMMAND_RETURN_ERROR;
- result = playPlaylist(&g_playlist, song);
+ result = playlist_play(&g_playlist, song);
return print_playlist_result(client, result);
}
@@ -413,7 +412,7 @@ handle_playid(struct client *client, int argc, char *argv[])
if (argc == 2 && !check_int(client, &id, argv[1], need_positive))
return COMMAND_RETURN_ERROR;
- result = playPlaylistById(&g_playlist, id);
+ result = playlist_play_id(&g_playlist, id);
return print_playlist_result(client, result);
}
@@ -421,7 +420,7 @@ static enum command_return
handle_stop(G_GNUC_UNUSED struct client *client,
G_GNUC_UNUSED int argc, G_GNUC_UNUSED char *argv[])
{
- stopPlaylist(&g_playlist);
+ playlist_stop(&g_playlist);
return COMMAND_RETURN_OK;
}
@@ -441,11 +440,11 @@ handle_pause(struct client *client,
bool pause_flag;
if (!check_bool(client, &pause_flag, argv[1]))
return COMMAND_RETURN_ERROR;
- playerSetPause(pause_flag);
- return COMMAND_RETURN_OK;
- }
- playerPause();
+ pc_set_pause(pause_flag);
+ } else
+ pc_pause();
+
return COMMAND_RETURN_OK;
}
@@ -454,10 +453,14 @@ handle_status(struct client *client,
G_GNUC_UNUSED int argc, G_GNUC_UNUSED char *argv[])
{
const char *state = NULL;
+ struct player_status player_status;
int updateJobId;
+ char *error;
int song;
- switch (getPlayerState()) {
+ pc_get_status(&player_status);
+
+ switch (player_status.state) {
case PLAYER_STATE_STOP:
state = "stop";
break;
@@ -470,7 +473,7 @@ handle_status(struct client *client,
}
client_printf(client,
- COMMAND_STATUS_VOLUME ": %i\n"
+ "volume: %i\n"
COMMAND_STATUS_REPEAT ": %i\n"
COMMAND_STATUS_RANDOM ": %i\n"
COMMAND_STATUS_SINGLE ": %i\n"
@@ -480,32 +483,36 @@ handle_status(struct client *client,
COMMAND_STATUS_CROSSFADE ": %i\n"
COMMAND_STATUS_STATE ": %s\n",
volume_level_get(),
- getPlaylistRepeatStatus(&g_playlist),
- getPlaylistRandomStatus(&g_playlist),
- getPlaylistSingleStatus(&g_playlist),
- getPlaylistConsumeStatus(&g_playlist),
- getPlaylistVersion(&g_playlist),
- getPlaylistLength(&g_playlist),
- (int)(getPlayerCrossFade() + 0.5),
+ playlist_get_repeat(&g_playlist),
+ playlist_get_random(&g_playlist),
+ playlist_get_single(&g_playlist),
+ playlist_get_consume(&g_playlist),
+ playlist_get_version(&g_playlist),
+ playlist_get_length(&g_playlist),
+ (int)(pc_get_cross_fade() + 0.5),
state);
- song = getPlaylistCurrentSong(&g_playlist);
+ song = playlist_get_current_song(&g_playlist);
if (song >= 0) {
client_printf(client,
COMMAND_STATUS_SONG ": %i\n"
COMMAND_STATUS_SONGID ": %u\n",
- song, getPlaylistSongId(&g_playlist, song));
+ song, playlist_get_song_id(&g_playlist, song));
}
- if (getPlayerState() != PLAYER_STATE_STOP) {
- const struct audio_format *af = player_get_audio_format();
+ if (player_status.state != PLAYER_STATE_STOP) {
client_printf(client,
COMMAND_STATUS_TIME ": %i:%i\n"
- COMMAND_STATUS_BITRATE ": %li\n"
+ "elapsed: %1.3f\n"
+ COMMAND_STATUS_BITRATE ": %u\n"
COMMAND_STATUS_AUDIO ": %u:%u:%u\n",
- getPlayerElapsedTime(), getPlayerTotalTime(),
- getPlayerBitRate(),
- af->sample_rate, af->bits, af->channels);
+ (int)(player_status.elapsed_time + 0.5),
+ (int)(player_status.total_time + 0.5),
+ player_status.elapsed_time,
+ player_status.bit_rate,
+ player_status.audio_format.sample_rate,
+ player_status.audio_format.bits,
+ player_status.audio_format.channels);
}
if ((updateJobId = isUpdatingDB())) {
@@ -514,18 +521,20 @@ handle_status(struct client *client,
updateJobId);
}
- if (getPlayerError() != PLAYER_ERROR_NOERROR) {
+ error = pc_get_error_message();
+ if (error != NULL) {
client_printf(client,
COMMAND_STATUS_ERROR ": %s\n",
- getPlayerErrorStr());
+ error);
+ g_free(error);
}
- song = getPlaylistNextSong(&g_playlist);
+ song = playlist_get_next_song(&g_playlist);
if (song >= 0) {
client_printf(client,
COMMAND_STATUS_NEXTSONG ": %i\n"
COMMAND_STATUS_NEXTSONGID ": %u\n",
- song, getPlaylistSongId(&g_playlist, song));
+ song, playlist_get_song_id(&g_playlist, song));
}
return COMMAND_RETURN_OK;
@@ -569,7 +578,7 @@ handle_add(struct client *client, G_GNUC_UNUSED int argc, char *argv[])
return COMMAND_RETURN_ERROR;
}
- result = addToPlaylist(&g_playlist, uri, NULL);
+ result = playlist_append_uri(&g_playlist, uri, NULL);
return print_playlist_result(client, result);
}
@@ -605,7 +614,7 @@ handle_addid(struct client *client, int argc, char *argv[])
return COMMAND_RETURN_ERROR;
}
- result = addToPlaylist(&g_playlist, uri, &added_id);
+ result = playlist_append_uri(&g_playlist, uri, &added_id);
}
if (result != PLAYLIST_RESULT_SUCCESS)
@@ -615,11 +624,11 @@ handle_addid(struct client *client, int argc, char *argv[])
int to;
if (!check_int(client, &to, argv[2], check_integer, argv[2]))
return COMMAND_RETURN_ERROR;
- result = moveSongInPlaylistById(&g_playlist, added_id, to);
+ result = playlist_move_id(&g_playlist, added_id, to);
if (result != PLAYLIST_RESULT_SUCCESS) {
enum command_return ret =
print_playlist_result(client, result);
- deleteFromPlaylistById(&g_playlist, added_id);
+ playlist_delete_id(&g_playlist, added_id);
return ret;
}
}
@@ -631,13 +640,13 @@ handle_addid(struct client *client, int argc, char *argv[])
static enum command_return
handle_delete(struct client *client, G_GNUC_UNUSED int argc, char *argv[])
{
- int song;
+ unsigned start, end;
enum playlist_result result;
- if (!check_int(client, &song, argv[1], need_positive))
+ if (!check_range(client, &start, &end, argv[1], need_range))
return COMMAND_RETURN_ERROR;
- result = deleteFromPlaylist(&g_playlist, song);
+ result = playlist_delete_range(&g_playlist, start, end);
return print_playlist_result(client, result);
}
@@ -650,7 +659,7 @@ handle_deleteid(struct client *client, G_GNUC_UNUSED int argc, char *argv[])
if (!check_int(client, &id, argv[1], need_positive))
return COMMAND_RETURN_ERROR;
- result = deleteFromPlaylistById(&g_playlist, id);
+ result = playlist_delete_id(&g_playlist, id);
return print_playlist_result(client, result);
}
@@ -671,7 +680,7 @@ handle_shuffle(G_GNUC_UNUSED struct client *client,
argv[1], need_range))
return COMMAND_RETURN_ERROR;
- shufflePlaylist(&g_playlist, start, end);
+ playlist_shuffle(&g_playlist, start, end);
return COMMAND_RETURN_OK;
}
@@ -679,7 +688,7 @@ static enum command_return
handle_clear(G_GNUC_UNUSED struct client *client,
G_GNUC_UNUSED int argc, G_GNUC_UNUSED char *argv[])
{
- clearPlaylist(&g_playlist);
+ playlist_clear(&g_playlist);
return COMMAND_RETURN_OK;
}
@@ -869,6 +878,30 @@ handle_find(struct client *client, int argc, char *argv[])
}
static enum command_return
+handle_findadd(struct client *client, int argc, char *argv[])
+{
+ int ret;
+ struct locate_item_list *list =
+ locate_item_list_parse(argv + 1, argc - 1);
+ if (list == NULL || list->length == 0) {
+ if (list != NULL)
+ locate_item_list_free(list);
+
+ command_error(client, ACK_ERROR_ARG, "incorrect arguments");
+ return COMMAND_RETURN_ERROR;
+ }
+
+ ret = findAddIn(client, NULL, list);
+ if (ret == -1)
+ command_error(client, ACK_ERROR_NO_EXIST,
+ "directory or file not found");
+
+ locate_item_list_free(list);
+
+ return ret;
+}
+
+static enum command_return
handle_search(struct client *client, int argc, char *argv[])
{
int ret;
@@ -993,14 +1026,35 @@ handle_playlistmove(struct client *client, G_GNUC_UNUSED int argc, char *argv[])
static enum command_return
handle_update(struct client *client, G_GNUC_UNUSED int argc, char *argv[])
{
- char *path = NULL;
+ const char *path = NULL;
unsigned ret;
assert(argc <= 2);
if (argc == 2)
- path = g_strdup(argv[1]);
+ path = argv[1];
- ret = directory_update_init(path);
+ ret = update_enqueue(path, false);
+ if (ret > 0) {
+ client_printf(client, "updating_db: %i\n", ret);
+ return COMMAND_RETURN_OK;
+ } else {
+ command_error(client, ACK_ERROR_UPDATE_ALREADY,
+ "already updating");
+ return COMMAND_RETURN_ERROR;
+ }
+}
+
+static enum command_return
+handle_rescan(struct client *client, G_GNUC_UNUSED int argc, char *argv[])
+{
+ const char *path = NULL;
+ unsigned ret;
+
+ assert(argc <= 2);
+ if (argc == 2)
+ path = argv[1];
+
+ ret = update_enqueue(path, true);
if (ret > 0) {
client_printf(client, "updating_db: %i\n", ret);
return COMMAND_RETURN_OK;
@@ -1020,7 +1074,7 @@ handle_next(G_GNUC_UNUSED struct client *client,
int single = g_playlist.queue.single;
g_playlist.queue.single = false;
- nextSongInPlaylist(&g_playlist);
+ playlist_next(&g_playlist);
g_playlist.queue.single = single;
return COMMAND_RETURN_OK;
@@ -1030,7 +1084,7 @@ static enum command_return
handle_previous(G_GNUC_UNUSED struct client *client,
G_GNUC_UNUSED int argc, G_GNUC_UNUSED char *argv[])
{
- previousSongInPlaylist(&g_playlist);
+ playlist_previous(&g_playlist);
return COMMAND_RETURN_OK;
}
@@ -1052,25 +1106,6 @@ handle_listall(struct client *client, G_GNUC_UNUSED int argc, char *argv[])
}
static enum command_return
-handle_volume(struct client *client, G_GNUC_UNUSED int argc, char *argv[])
-{
- int change;
- bool success;
-
- if (!check_int(client, &change, argv[1], need_integer))
- return COMMAND_RETURN_ERROR;
-
- success = volume_level_change(change, true);
- if (!success) {
- command_error(client, ACK_ERROR_SYSTEM,
- "problems setting volume");
- return COMMAND_RETURN_ERROR;
- }
-
- return COMMAND_RETURN_OK;
-}
-
-static enum command_return
handle_setvol(struct client *client, G_GNUC_UNUSED int argc, char *argv[])
{
int level;
@@ -1079,7 +1114,12 @@ handle_setvol(struct client *client, G_GNUC_UNUSED int argc, char *argv[])
if (!check_int(client, &level, argv[1], need_integer))
return COMMAND_RETURN_ERROR;
- success = volume_level_change(level, 0);
+ if (level < 0 || level > 100) {
+ command_error(client, ACK_ERROR_ARG, "Invalid volume value");
+ return COMMAND_RETURN_ERROR;
+ }
+
+ success = volume_level_change(level);
if (!success) {
command_error(client, ACK_ERROR_SYSTEM,
"problems setting volume");
@@ -1103,7 +1143,7 @@ handle_repeat(struct client *client, G_GNUC_UNUSED int argc, char *argv[])
return COMMAND_RETURN_ERROR;
}
- setPlaylistRepeatStatus(&g_playlist, status);
+ playlist_set_repeat(&g_playlist, status);
return COMMAND_RETURN_OK;
}
@@ -1121,7 +1161,7 @@ handle_single(struct client *client, G_GNUC_UNUSED int argc, char *argv[])
return COMMAND_RETURN_ERROR;
}
- setPlaylistSingleStatus(&g_playlist, status);
+ playlist_set_single(&g_playlist, status);
return COMMAND_RETURN_OK;
}
@@ -1139,7 +1179,7 @@ handle_consume(struct client *client, G_GNUC_UNUSED int argc, char *argv[])
return COMMAND_RETURN_ERROR;
}
- setPlaylistConsumeStatus(&g_playlist, status);
+ playlist_set_consume(&g_playlist, status);
return COMMAND_RETURN_OK;
}
@@ -1157,7 +1197,7 @@ handle_random(struct client *client, G_GNUC_UNUSED int argc, char *argv[])
return COMMAND_RETURN_ERROR;
}
- setPlaylistRandomStatus(&g_playlist, status);
+ playlist_set_random(&g_playlist, status);
return COMMAND_RETURN_OK;
}
@@ -1172,7 +1212,7 @@ static enum command_return
handle_clearerror(G_GNUC_UNUSED struct client *client,
G_GNUC_UNUSED int argc, G_GNUC_UNUSED char *argv[])
{
- clearPlayerError();
+ pc_clear_error();
return COMMAND_RETURN_OK;
}
@@ -1196,17 +1236,17 @@ handle_list(struct client *client, int argc, char *argv[])
/* for compatibility with < 0.12.0 */
if (argc == 3) {
- if (tagType != TAG_ITEM_ALBUM) {
+ if (tagType != TAG_ALBUM) {
command_error(client, ACK_ERROR_ARG,
"should be \"%s\" for 3 arguments",
- tag_item_names[TAG_ITEM_ALBUM]);
+ tag_item_names[TAG_ALBUM]);
return COMMAND_RETURN_ERROR;
}
locate_item_list_parse(argv + 1, argc - 1);
conditionals = locate_item_list_new(1);
- conditionals->items[0].tag = TAG_ITEM_ARTIST;
+ conditionals->items[0].tag = TAG_ARTIST;
conditionals->items[0].needle = g_strdup(argv[2]);
} else {
conditionals =
@@ -1241,7 +1281,7 @@ handle_move(struct client *client, G_GNUC_UNUSED int argc, char *argv[])
return COMMAND_RETURN_ERROR;
if (!check_int(client, &to, argv[2], check_integer, argv[2]))
return COMMAND_RETURN_ERROR;
- result = moveSongRangeInPlaylist(&g_playlist, start, end, to);
+ result = playlist_move_range(&g_playlist, start, end, to);
return print_playlist_result(client, result);
}
@@ -1255,7 +1295,7 @@ handle_moveid(struct client *client, G_GNUC_UNUSED int argc, char *argv[])
return COMMAND_RETURN_ERROR;
if (!check_int(client, &to, argv[2], check_integer, argv[2]))
return COMMAND_RETURN_ERROR;
- result = moveSongInPlaylistById(&g_playlist, id, to);
+ result = playlist_move_id(&g_playlist, id, to);
return print_playlist_result(client, result);
}
@@ -1269,7 +1309,7 @@ handle_swap(struct client *client, G_GNUC_UNUSED int argc, char *argv[])
return COMMAND_RETURN_ERROR;
if (!check_int(client, &song2, argv[2], check_integer, argv[2]))
return COMMAND_RETURN_ERROR;
- result = swapSongsInPlaylist(&g_playlist, song1, song2);
+ result = playlist_swap_songs(&g_playlist, song1, song2);
return print_playlist_result(client, result);
}
@@ -1283,7 +1323,7 @@ handle_swapid(struct client *client, G_GNUC_UNUSED int argc, char *argv[])
return COMMAND_RETURN_ERROR;
if (!check_int(client, &id2, argv[2], check_integer, argv[2]))
return COMMAND_RETURN_ERROR;
- result = swapSongsInPlaylistById(&g_playlist, id1, id2);
+ result = playlist_swap_songs_id(&g_playlist, id1, id2);
return print_playlist_result(client, result);
}
@@ -1298,7 +1338,7 @@ handle_seek(struct client *client, G_GNUC_UNUSED int argc, char *argv[])
if (!check_int(client, &seek_time, argv[2], check_integer, argv[2]))
return COMMAND_RETURN_ERROR;
- result = seekSongInPlaylist(&g_playlist, song, seek_time);
+ result = playlist_seek_song(&g_playlist, song, seek_time);
return print_playlist_result(client, result);
}
@@ -1313,7 +1353,7 @@ handle_seekid(struct client *client, G_GNUC_UNUSED int argc, char *argv[])
if (!check_int(client, &seek_time, argv[2], check_integer, argv[2]))
return COMMAND_RETURN_ERROR;
- result = seekSongInPlaylistById(&g_playlist, id, seek_time);
+ result = playlist_seek_song_id(&g_playlist, id, seek_time);
return print_playlist_result(client, result);
}
@@ -1363,7 +1403,7 @@ handle_crossfade(struct client *client, G_GNUC_UNUSED int argc, char *argv[])
if (!check_unsigned(client, &xfade_time, argv[1]))
return COMMAND_RETURN_ERROR;
- setPlayerCrossFade(xfade_time);
+ pc_set_cross_fade(xfade_time);
return COMMAND_RETURN_OK;
}
@@ -1684,6 +1724,7 @@ static const struct command commands[] = {
{ "disableoutput", PERMISSION_ADMIN, 1, 1, handle_disableoutput },
{ "enableoutput", PERMISSION_ADMIN, 1, 1, handle_enableoutput },
{ "find", PERMISSION_READ, 2, -1, handle_find },
+ { "findadd", PERMISSION_READ, 2, -1, handle_findadd},
{ "idle", PERMISSION_READ, 0, -1, handle_idle },
{ "kill", PERMISSION_ADMIN, -1, -1, handle_kill },
{ "list", PERMISSION_READ, 1, -1, handle_list },
@@ -1719,6 +1760,7 @@ static const struct command commands[] = {
{ "random", PERMISSION_CONTROL, 1, 1, handle_random },
{ "rename", PERMISSION_CONTROL, 2, 2, handle_rename },
{ "repeat", PERMISSION_CONTROL, 1, 1, handle_repeat },
+ { "rescan", PERMISSION_ADMIN, 0, 1, handle_rescan },
{ "rm", PERMISSION_CONTROL, 1, 1, handle_rm },
{ "save", PERMISSION_CONTROL, 1, 1, handle_save },
{ "search", PERMISSION_READ, 2, -1, handle_search },
@@ -1738,7 +1780,6 @@ static const struct command commands[] = {
{ "tagtypes", PERMISSION_READ, 0, 0, handle_tagtypes },
{ "update", PERMISSION_ADMIN, 0, 1, handle_update },
{ "urlhandlers", PERMISSION_READ, 0, 0, handle_urlhandlers },
- { "volume", PERMISSION_CONTROL, 1, 1, handle_volume },
};
static const unsigned num_commands = sizeof(commands) / sizeof(commands[0]);
@@ -1892,48 +1933,71 @@ command_checked_lookup(struct client *client, unsigned permission,
}
enum command_return
-command_process(struct client *client, char *commandString)
+command_process(struct client *client, unsigned num, char *line)
{
+ GError *error = NULL;
int argc;
char *argv[COMMAND_ARGV_MAX] = { NULL };
const struct command *cmd;
enum command_return ret = COMMAND_RETURN_ERROR;
- if (!(argc = buffer2array(commandString, argv, COMMAND_ARGV_MAX)))
- return COMMAND_RETURN_OK;
+ command_list_num = num;
- cmd = command_checked_lookup(client, client_get_permission(client),
- argc, argv);
- if (cmd)
- ret = cmd->handler(client, argc, argv);
+ /* get the command name (first word on the line) */
- current_command = NULL;
+ argv[0] = tokenizer_next_word(&line, &error);
+ if (argv[0] == NULL) {
+ current_command = "";
+ if (*line == 0)
+ command_error(client, ACK_ERROR_UNKNOWN,
+ "No command given");
+ else {
+ command_error(client, ACK_ERROR_UNKNOWN,
+ "%s", error->message);
+ g_error_free(error);
+ }
+ current_command = NULL;
- return ret;
-}
+ return COMMAND_RETURN_ERROR;
+ }
-enum command_return
-command_process_list(struct client *client,
- bool list_ok, GSList *list)
-{
- enum command_return ret = COMMAND_RETURN_OK;
+ argc = 1;
- command_list_num = 0;
+ /* now parse the arguments (quoted or unquoted) */
+
+ while (argc < (int)G_N_ELEMENTS(argv) &&
+ (argv[argc] =
+ tokenizer_next_param(&line, &error)) != NULL)
+ ++argc;
+
+ /* some error checks; we have to set current_command because
+ command_error() expects it to be set */
+
+ current_command = argv[0];
+
+ if (argc >= (int)G_N_ELEMENTS(argv)) {
+ command_error(client, ACK_ERROR_ARG, "Too many arguments");
+ current_command = NULL;
+ return COMMAND_RETURN_ERROR;
+ }
- for (GSList *cur = list; cur != NULL; cur = g_slist_next(cur)) {
- char *cmd = cur->data;
-
- g_debug("command_process_list: process command \"%s\"",
- cmd);
- ret = command_process(client, cmd);
- g_debug("command_process_list: command returned %i", ret);
- if (ret != COMMAND_RETURN_OK || client_is_expired(client))
- break;
- else if (list_ok)
- client_puts(client, "list_OK\n");
- command_list_num++;
+ if (*line != 0) {
+ command_error(client, ACK_ERROR_ARG,
+ "%s", error->message);
+ current_command = NULL;
+ g_error_free(error);
+ return COMMAND_RETURN_ERROR;
}
+ /* look up and invoke the command handler */
+
+ cmd = command_checked_lookup(client, client_get_permission(client),
+ argc, argv);
+ if (cmd)
+ ret = cmd->handler(client, argc, argv);
+
+ current_command = NULL;
command_list_num = 0;
+
return ret;
}