[mpd] Fix idle command (idle events got lost if they happened while the
client was not in idle mode)
This commit is contained in:
parent
4fe4bee809
commit
1e24b3656a
457
src/mpd.c
457
src/mpd.c
|
@ -20,6 +20,7 @@
|
|||
# include <config.h>
|
||||
#endif
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
|
@ -141,11 +142,66 @@ static const char * const ffmpeg_mime_types[] = { "application/flv", "applicatio
|
|||
NULL
|
||||
};
|
||||
|
||||
/* Provide for connection specfic authentication. */
|
||||
struct mpd_cmd_ctx {
|
||||
/*
|
||||
* MPD client connection data
|
||||
*/
|
||||
struct mpd_client_ctx
|
||||
{
|
||||
// True if the connection is already authenticated or does not need authentication
|
||||
int authenticated;
|
||||
|
||||
// The events the client needs to be notified of
|
||||
short events;
|
||||
|
||||
// True if the client is waiting for idle events
|
||||
bool is_idle;
|
||||
|
||||
// The events the client is waiting for (set by the idle command)
|
||||
short idle_events;
|
||||
|
||||
// The output buffer for the client (used to send data to the client)
|
||||
struct evbuffer *evbuffer;
|
||||
|
||||
struct mpd_client_ctx *next;
|
||||
};
|
||||
|
||||
// List of all connected mpd clients
|
||||
struct mpd_client_ctx *mpd_clients;
|
||||
|
||||
static void
|
||||
free_mpd_client_ctx(void *ctx)
|
||||
{
|
||||
struct mpd_client_ctx *client_ctx = ctx;
|
||||
struct mpd_client_ctx *client;
|
||||
struct mpd_client_ctx *prev;
|
||||
|
||||
if (!client_ctx)
|
||||
return;
|
||||
|
||||
client = mpd_clients;
|
||||
prev = NULL;
|
||||
|
||||
while (client)
|
||||
{
|
||||
if (client == client_ctx)
|
||||
{
|
||||
DPRINTF(E_DBG, L_MPD, "Removing mpd client\n");
|
||||
|
||||
if (prev)
|
||||
prev->next = client->next;
|
||||
else
|
||||
mpd_clients = client->next;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
prev = client;
|
||||
client = client->next;
|
||||
}
|
||||
|
||||
free(client_ctx);
|
||||
}
|
||||
|
||||
struct output
|
||||
{
|
||||
unsigned short shortid;
|
||||
|
@ -181,17 +237,6 @@ free_outputs(struct output *outputs)
|
|||
}
|
||||
}
|
||||
|
||||
struct idle_client
|
||||
{
|
||||
struct evbuffer *evbuffer;
|
||||
short events;
|
||||
|
||||
struct idle_client *next;
|
||||
};
|
||||
|
||||
struct idle_client *idle_clients;
|
||||
|
||||
|
||||
/*
|
||||
* Creates a new string for the given path that starts with a '/'.
|
||||
* If 'path' already starts with a '/' the returned string is a duplicate
|
||||
|
@ -550,7 +595,7 @@ mpd_add_db_media_file_info(struct evbuffer *evbuf, struct db_media_file_info *db
|
|||
* Command handler function for 'currentsong'
|
||||
*/
|
||||
static int
|
||||
mpd_command_currentsong(struct evbuffer *evbuf, int argc, char **argv, char **errmsg)
|
||||
mpd_command_currentsong(struct evbuffer *evbuf, int argc, char **argv, char **errmsg, struct mpd_client_ctx *ctx)
|
||||
{
|
||||
|
||||
struct player_status status;
|
||||
|
@ -585,111 +630,89 @@ mpd_command_currentsong(struct evbuffer *evbuf, int argc, char **argv, char **er
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
mpd_notify_idle_client(struct mpd_client_ctx *client_ctx, short events);
|
||||
/*
|
||||
*
|
||||
* Example input:
|
||||
* idle "database" "mixer" "options" "output" "player" "playlist" "sticker" "update"
|
||||
*/
|
||||
static int
|
||||
mpd_command_idle(struct evbuffer *evbuf, int argc, char **argv, char **errmsg)
|
||||
mpd_command_idle(struct evbuffer *evbuf, int argc, char **argv, char **errmsg, struct mpd_client_ctx *ctx)
|
||||
{
|
||||
struct idle_client *client;
|
||||
int i;
|
||||
|
||||
client = (struct idle_client*)malloc(sizeof(struct idle_client));
|
||||
if (!client)
|
||||
{
|
||||
DPRINTF(E_LOG, L_MPD, "Out of memory for idle_client\n");
|
||||
return ACK_ERROR_UNKNOWN;
|
||||
}
|
||||
|
||||
client->evbuffer = evbuf;
|
||||
client->events = 0;
|
||||
client->next = idle_clients;
|
||||
ctx->idle_events = 0;
|
||||
ctx->is_idle = true;
|
||||
|
||||
if (argc > 1)
|
||||
{
|
||||
for (i = 1; i < argc; i++)
|
||||
{
|
||||
if (0 == strcmp(argv[i], "database"))
|
||||
{
|
||||
client->events |= LISTENER_DATABASE;
|
||||
}
|
||||
ctx->idle_events |= LISTENER_DATABASE;
|
||||
else if (0 == strcmp(argv[i], "update"))
|
||||
{
|
||||
client->events |= LISTENER_UPDATE;
|
||||
}
|
||||
ctx->idle_events |= LISTENER_UPDATE;
|
||||
else if (0 == strcmp(argv[i], "player"))
|
||||
{
|
||||
client->events |= LISTENER_PLAYER;
|
||||
}
|
||||
ctx->idle_events |= LISTENER_PLAYER;
|
||||
else if (0 == strcmp(argv[i], "playlist"))
|
||||
{
|
||||
client->events |= LISTENER_QUEUE;
|
||||
}
|
||||
ctx->idle_events |= LISTENER_QUEUE;
|
||||
else if (0 == strcmp(argv[i], "mixer"))
|
||||
{
|
||||
client->events |= LISTENER_VOLUME;
|
||||
}
|
||||
ctx->idle_events |= LISTENER_VOLUME;
|
||||
else if (0 == strcmp(argv[i], "output"))
|
||||
{
|
||||
client->events |= LISTENER_SPEAKER;
|
||||
}
|
||||
ctx->idle_events |= LISTENER_SPEAKER;
|
||||
else if (0 == strcmp(argv[i], "options"))
|
||||
{
|
||||
client->events |= LISTENER_OPTIONS;
|
||||
}
|
||||
ctx->idle_events |= LISTENER_OPTIONS;
|
||||
else if (0 == strcmp(argv[i], "stored_playlist"))
|
||||
{
|
||||
client->events |= LISTENER_STORED_PLAYLIST;
|
||||
}
|
||||
ctx->idle_events |= LISTENER_STORED_PLAYLIST;
|
||||
else
|
||||
{
|
||||
DPRINTF(E_DBG, L_MPD, "Idle command for '%s' not supported\n", argv[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
client->events = LISTENER_PLAYER | LISTENER_QUEUE | LISTENER_VOLUME | LISTENER_SPEAKER | LISTENER_OPTIONS | LISTENER_DATABASE | LISTENER_UPDATE | LISTENER_STORED_PLAYLIST;
|
||||
ctx->idle_events = LISTENER_PLAYER | LISTENER_QUEUE | LISTENER_VOLUME | LISTENER_SPEAKER | LISTENER_OPTIONS | LISTENER_DATABASE | LISTENER_UPDATE | LISTENER_STORED_PLAYLIST;
|
||||
|
||||
idle_clients = client;
|
||||
// If events the client listens to occurred since the last idle call (or since the client connected,
|
||||
// if it is the first idle call), notify immediately.
|
||||
if (ctx->events & ctx->idle_events)
|
||||
mpd_notify_idle_client(ctx, ctx->events);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
mpd_remove_idle_client(struct evbuffer *evbuf)
|
||||
{
|
||||
struct idle_client *client;
|
||||
struct idle_client *prev;
|
||||
|
||||
client = idle_clients;
|
||||
prev = NULL;
|
||||
|
||||
while (client)
|
||||
{
|
||||
if (client->evbuffer == evbuf)
|
||||
{
|
||||
DPRINTF(E_DBG, L_MPD, "Removing idle client for evbuffer\n");
|
||||
|
||||
if (prev)
|
||||
prev->next = client->next;
|
||||
else
|
||||
idle_clients = client->next;
|
||||
|
||||
free(client);
|
||||
break;
|
||||
}
|
||||
|
||||
prev = client;
|
||||
client = client->next;
|
||||
}
|
||||
}
|
||||
//static void
|
||||
//mpd_remove_client(struct evbuffer *evbuf)
|
||||
//{
|
||||
// struct idle_client *client;
|
||||
// struct idle_client *prev;
|
||||
//
|
||||
// client = idle_clients;
|
||||
// prev = NULL;
|
||||
//
|
||||
// while (client)
|
||||
// {
|
||||
// if (client->evbuffer == evbuf)
|
||||
// {
|
||||
// DPRINTF(E_DBG, L_MPD, "Removing idle client for evbuffer\n");
|
||||
//
|
||||
// if (prev)
|
||||
// prev->next = client->next;
|
||||
// else
|
||||
// idle_clients = client->next;
|
||||
//
|
||||
// free(client);
|
||||
// break;
|
||||
// }
|
||||
//
|
||||
// prev = client;
|
||||
// client = client->next;
|
||||
// }
|
||||
//}
|
||||
|
||||
static int
|
||||
mpd_command_noidle(struct evbuffer *evbuf, int argc, char **argv, char **errmsg)
|
||||
mpd_command_noidle(struct evbuffer *evbuf, int argc, char **argv, char **errmsg, struct mpd_client_ctx *ctx)
|
||||
{
|
||||
mpd_remove_idle_client(evbuf);
|
||||
ctx->is_idle = false;
|
||||
ctx->idle_events = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -716,7 +739,7 @@ mpd_command_noidle(struct evbuffer *evbuf, int argc, char **argv, char **errmsg)
|
|||
* nextsongid: 2
|
||||
*/
|
||||
static int
|
||||
mpd_command_status(struct evbuffer *evbuf, int argc, char **argv, char **errmsg)
|
||||
mpd_command_status(struct evbuffer *evbuf, int argc, char **argv, char **errmsg, struct mpd_client_ctx *ctx)
|
||||
{
|
||||
struct player_status status;
|
||||
int queue_length;
|
||||
|
@ -808,7 +831,7 @@ mpd_command_status(struct evbuffer *evbuf, int argc, char **argv, char **errmsg)
|
|||
* Command handler function for 'stats'
|
||||
*/
|
||||
static int
|
||||
mpd_command_stats(struct evbuffer *evbuf, int argc, char **argv, char **errmsg)
|
||||
mpd_command_stats(struct evbuffer *evbuf, int argc, char **argv, char **errmsg, struct mpd_client_ctx *ctx)
|
||||
{
|
||||
struct query_params qp;
|
||||
struct filecount_info fci;
|
||||
|
@ -856,7 +879,7 @@ mpd_command_stats(struct evbuffer *evbuf, int argc, char **argv, char **errmsg)
|
|||
* 1 = enable consume
|
||||
*/
|
||||
static int
|
||||
mpd_command_consume(struct evbuffer *evbuf, int argc, char **argv, char **errmsg)
|
||||
mpd_command_consume(struct evbuffer *evbuf, int argc, char **argv, char **errmsg, struct mpd_client_ctx *ctx)
|
||||
{
|
||||
int enable;
|
||||
int ret;
|
||||
|
@ -885,7 +908,7 @@ mpd_command_consume(struct evbuffer *evbuf, int argc, char **argv, char **errmsg
|
|||
* 1 = enable shuffle
|
||||
*/
|
||||
static int
|
||||
mpd_command_random(struct evbuffer *evbuf, int argc, char **argv, char **errmsg)
|
||||
mpd_command_random(struct evbuffer *evbuf, int argc, char **argv, char **errmsg, struct mpd_client_ctx *ctx)
|
||||
{
|
||||
int enable;
|
||||
int ret;
|
||||
|
@ -914,7 +937,7 @@ mpd_command_random(struct evbuffer *evbuf, int argc, char **argv, char **errmsg)
|
|||
* 1 = repeat all
|
||||
*/
|
||||
static int
|
||||
mpd_command_repeat(struct evbuffer *evbuf, int argc, char **argv, char **errmsg)
|
||||
mpd_command_repeat(struct evbuffer *evbuf, int argc, char **argv, char **errmsg, struct mpd_client_ctx *ctx)
|
||||
{
|
||||
int enable;
|
||||
int ret;
|
||||
|
@ -945,7 +968,7 @@ mpd_command_repeat(struct evbuffer *evbuf, int argc, char **argv, char **errmsg)
|
|||
* Sets the volume, expects argument argv[1] to be an integer 0-100
|
||||
*/
|
||||
static int
|
||||
mpd_command_setvol(struct evbuffer *evbuf, int argc, char **argv, char **errmsg)
|
||||
mpd_command_setvol(struct evbuffer *evbuf, int argc, char **argv, char **errmsg, struct mpd_client_ctx *ctx)
|
||||
{
|
||||
int volume;
|
||||
int ret;
|
||||
|
@ -984,7 +1007,7 @@ mpd_command_setvol(struct evbuffer *evbuf, int argc, char **argv, char **errmsg)
|
|||
* 1 = repeat song
|
||||
*/
|
||||
static int
|
||||
mpd_command_single(struct evbuffer *evbuf, int argc, char **argv, char **errmsg)
|
||||
mpd_command_single(struct evbuffer *evbuf, int argc, char **argv, char **errmsg, struct mpd_client_ctx *ctx)
|
||||
{
|
||||
int enable;
|
||||
struct player_status status;
|
||||
|
@ -1021,7 +1044,7 @@ mpd_command_single(struct evbuffer *evbuf, int argc, char **argv, char **errmsg)
|
|||
* "replay_gain_mode: off".
|
||||
*/
|
||||
static int
|
||||
mpd_command_replay_gain_status(struct evbuffer *evbuf, int argc, char **argv, char **errmsg)
|
||||
mpd_command_replay_gain_status(struct evbuffer *evbuf, int argc, char **argv, char **errmsg, struct mpd_client_ctx *ctx)
|
||||
{
|
||||
evbuffer_add(evbuf, "replay_gain_mode: off\n", 22);
|
||||
return 0;
|
||||
|
@ -1034,7 +1057,7 @@ mpd_command_replay_gain_status(struct evbuffer *evbuf, int argc, char **argv, ch
|
|||
* According to the mpd protocoll specification this function is deprecated.
|
||||
*/
|
||||
static int
|
||||
mpd_command_volume(struct evbuffer *evbuf, int argc, char **argv, char **errmsg)
|
||||
mpd_command_volume(struct evbuffer *evbuf, int argc, char **argv, char **errmsg, struct mpd_client_ctx *ctx)
|
||||
{
|
||||
struct player_status status;
|
||||
int volume;
|
||||
|
@ -1067,7 +1090,7 @@ mpd_command_volume(struct evbuffer *evbuf, int argc, char **argv, char **errmsg)
|
|||
* Skips to the next song in the playqueue
|
||||
*/
|
||||
static int
|
||||
mpd_command_next(struct evbuffer *evbuf, int argc, char **argv, char **errmsg)
|
||||
mpd_command_next(struct evbuffer *evbuf, int argc, char **argv, char **errmsg, struct mpd_client_ctx *ctx)
|
||||
{
|
||||
int ret;
|
||||
|
||||
|
@ -1096,7 +1119,7 @@ mpd_command_next(struct evbuffer *evbuf, int argc, char **argv, char **errmsg)
|
|||
* 1 = pause
|
||||
*/
|
||||
static int
|
||||
mpd_command_pause(struct evbuffer *evbuf, int argc, char **argv, char **errmsg)
|
||||
mpd_command_pause(struct evbuffer *evbuf, int argc, char **argv, char **errmsg, struct mpd_client_ctx *ctx)
|
||||
{
|
||||
int pause;
|
||||
struct player_status status;
|
||||
|
@ -1140,7 +1163,7 @@ mpd_command_pause(struct evbuffer *evbuf, int argc, char **argv, char **errmsg)
|
|||
* where to start playback.
|
||||
*/
|
||||
static int
|
||||
mpd_command_play(struct evbuffer *evbuf, int argc, char **argv, char **errmsg)
|
||||
mpd_command_play(struct evbuffer *evbuf, int argc, char **argv, char **errmsg, struct mpd_client_ctx *ctx)
|
||||
{
|
||||
int songpos;
|
||||
struct player_status status;
|
||||
|
@ -1202,7 +1225,7 @@ mpd_command_play(struct evbuffer *evbuf, int argc, char **argv, char **errmsg)
|
|||
* where to start playback.
|
||||
*/
|
||||
static int
|
||||
mpd_command_playid(struct evbuffer *evbuf, int argc, char **argv, char **errmsg)
|
||||
mpd_command_playid(struct evbuffer *evbuf, int argc, char **argv, char **errmsg, struct mpd_client_ctx *ctx)
|
||||
{
|
||||
uint32_t id;
|
||||
struct player_status status;
|
||||
|
@ -1258,7 +1281,7 @@ mpd_command_playid(struct evbuffer *evbuf, int argc, char **argv, char **errmsg)
|
|||
* Skips to the previous song in the playqueue
|
||||
*/
|
||||
static int
|
||||
mpd_command_previous(struct evbuffer *evbuf, int argc, char **argv, char **errmsg)
|
||||
mpd_command_previous(struct evbuffer *evbuf, int argc, char **argv, char **errmsg, struct mpd_client_ctx *ctx)
|
||||
{
|
||||
int ret;
|
||||
|
||||
|
@ -1286,7 +1309,7 @@ mpd_command_previous(struct evbuffer *evbuf, int argc, char **argv, char **errms
|
|||
* (fractions allowed).
|
||||
*/
|
||||
static int
|
||||
mpd_command_seek(struct evbuffer *evbuf, int argc, char **argv, char **errmsg)
|
||||
mpd_command_seek(struct evbuffer *evbuf, int argc, char **argv, char **errmsg, struct mpd_client_ctx *ctx)
|
||||
{
|
||||
uint32_t songpos;
|
||||
float seek_target_sec;
|
||||
|
@ -1335,7 +1358,7 @@ mpd_command_seek(struct evbuffer *evbuf, int argc, char **argv, char **errmsg)
|
|||
* (fractions allowed).
|
||||
*/
|
||||
static int
|
||||
mpd_command_seekid(struct evbuffer *evbuf, int argc, char **argv, char **errmsg)
|
||||
mpd_command_seekid(struct evbuffer *evbuf, int argc, char **argv, char **errmsg, struct mpd_client_ctx *ctx)
|
||||
{
|
||||
struct player_status status;
|
||||
uint32_t id;
|
||||
|
@ -1390,7 +1413,7 @@ mpd_command_seekid(struct evbuffer *evbuf, int argc, char **argv, char **errmsg)
|
|||
* Seeks the current song to the position in seconds given in argument argv[1] (fractions allowed).
|
||||
*/
|
||||
static int
|
||||
mpd_command_seekcur(struct evbuffer *evbuf, int argc, char **argv, char **errmsg)
|
||||
mpd_command_seekcur(struct evbuffer *evbuf, int argc, char **argv, char **errmsg, struct mpd_client_ctx *ctx)
|
||||
{
|
||||
float seek_target_sec;
|
||||
int seek_target_msec;
|
||||
|
@ -1429,7 +1452,7 @@ mpd_command_seekcur(struct evbuffer *evbuf, int argc, char **argv, char **errmsg
|
|||
* Stop playback.
|
||||
*/
|
||||
static int
|
||||
mpd_command_stop(struct evbuffer *evbuf, int argc, char **argv, char **errmsg)
|
||||
mpd_command_stop(struct evbuffer *evbuf, int argc, char **argv, char **errmsg, struct mpd_client_ctx *ctx)
|
||||
{
|
||||
int ret;
|
||||
|
||||
|
@ -1491,7 +1514,7 @@ mpd_queue_add(char *path, int recursive)
|
|||
* Expects argument argv[1] to be a path to a single file or directory.
|
||||
*/
|
||||
static int
|
||||
mpd_command_add(struct evbuffer *evbuf, int argc, char **argv, char **errmsg)
|
||||
mpd_command_add(struct evbuffer *evbuf, int argc, char **argv, char **errmsg, struct mpd_client_ctx *ctx)
|
||||
{
|
||||
struct media_file_info mfi;
|
||||
int ret;
|
||||
|
@ -1534,7 +1557,7 @@ mpd_command_add(struct evbuffer *evbuf, int argc, char **argv, char **errmsg)
|
|||
* it must be an integer representing the position in the playqueue.
|
||||
*/
|
||||
static int
|
||||
mpd_command_addid(struct evbuffer *evbuf, int argc, char **argv, char **errmsg)
|
||||
mpd_command_addid(struct evbuffer *evbuf, int argc, char **argv, char **errmsg, struct mpd_client_ctx *ctx)
|
||||
{
|
||||
struct media_file_info mfi;
|
||||
int ret;
|
||||
|
@ -1585,7 +1608,7 @@ mpd_command_addid(struct evbuffer *evbuf, int argc, char **argv, char **errmsg)
|
|||
* Stops playback and removes all songs from the playqueue
|
||||
*/
|
||||
static int
|
||||
mpd_command_clear(struct evbuffer *evbuf, int argc, char **argv, char **errmsg)
|
||||
mpd_command_clear(struct evbuffer *evbuf, int argc, char **argv, char **errmsg, struct mpd_client_ctx *ctx)
|
||||
{
|
||||
int ret;
|
||||
|
||||
|
@ -1607,7 +1630,7 @@ mpd_command_clear(struct evbuffer *evbuf, int argc, char **argv, char **errmsg)
|
|||
* should be removed.
|
||||
*/
|
||||
static int
|
||||
mpd_command_delete(struct evbuffer *evbuf, int argc, char **argv, char **errmsg)
|
||||
mpd_command_delete(struct evbuffer *evbuf, int argc, char **argv, char **errmsg, struct mpd_client_ctx *ctx)
|
||||
{
|
||||
int start_pos;
|
||||
int end_pos;
|
||||
|
@ -1646,7 +1669,7 @@ mpd_command_delete(struct evbuffer *evbuf, int argc, char **argv, char **errmsg)
|
|||
* Removes the song with given id from the playqueue. Expects argument argv[1] to be an integer (song id).
|
||||
*/
|
||||
static int
|
||||
mpd_command_deleteid(struct evbuffer *evbuf, int argc, char **argv, char **errmsg)
|
||||
mpd_command_deleteid(struct evbuffer *evbuf, int argc, char **argv, char **errmsg, struct mpd_client_ctx *ctx)
|
||||
{
|
||||
uint32_t songid;
|
||||
int ret;
|
||||
|
@ -1676,7 +1699,7 @@ mpd_command_deleteid(struct evbuffer *evbuf, int argc, char **argv, char **errms
|
|||
|
||||
//Moves the song at FROM or range of songs at START:END to TO in the playlist.
|
||||
static int
|
||||
mpd_command_move(struct evbuffer *evbuf, int argc, char **argv, char **errmsg)
|
||||
mpd_command_move(struct evbuffer *evbuf, int argc, char **argv, char **errmsg, struct mpd_client_ctx *ctx)
|
||||
{
|
||||
int start_pos;
|
||||
int end_pos;
|
||||
|
@ -1719,7 +1742,7 @@ mpd_command_move(struct evbuffer *evbuf, int argc, char **argv, char **errmsg)
|
|||
}
|
||||
|
||||
static int
|
||||
mpd_command_moveid(struct evbuffer *evbuf, int argc, char **argv, char **errmsg)
|
||||
mpd_command_moveid(struct evbuffer *evbuf, int argc, char **argv, char **errmsg, struct mpd_client_ctx *ctx)
|
||||
{
|
||||
uint32_t songid;
|
||||
uint32_t to_pos;
|
||||
|
@ -1763,7 +1786,7 @@ mpd_command_moveid(struct evbuffer *evbuf, int argc, char **argv, char **errmsg)
|
|||
* The order of the songs is always the not shuffled order.
|
||||
*/
|
||||
static int
|
||||
mpd_command_playlistid(struct evbuffer *evbuf, int argc, char **argv, char **errmsg)
|
||||
mpd_command_playlistid(struct evbuffer *evbuf, int argc, char **argv, char **errmsg, struct mpd_client_ctx *ctx)
|
||||
{
|
||||
struct query_params query_params;
|
||||
struct db_queue_item queue_item;
|
||||
|
@ -1823,7 +1846,7 @@ mpd_command_playlistid(struct evbuffer *evbuf, int argc, char **argv, char **err
|
|||
* The order of the songs is always the not shuffled order.
|
||||
*/
|
||||
static int
|
||||
mpd_command_playlistinfo(struct evbuffer *evbuf, int argc, char **argv, char **errmsg)
|
||||
mpd_command_playlistinfo(struct evbuffer *evbuf, int argc, char **argv, char **errmsg, struct mpd_client_ctx *ctx)
|
||||
{
|
||||
struct query_params query_params;
|
||||
struct db_queue_item queue_item;
|
||||
|
@ -1882,7 +1905,7 @@ mpd_command_playlistinfo(struct evbuffer *evbuf, int argc, char **argv, char **e
|
|||
* Lists all changed songs in the queue since the given playlist version in argv[1].
|
||||
*/
|
||||
static int
|
||||
mpd_command_plchanges(struct evbuffer *evbuf, int argc, char **argv, char **errmsg)
|
||||
mpd_command_plchanges(struct evbuffer *evbuf, int argc, char **argv, char **errmsg, struct mpd_client_ctx *ctx)
|
||||
{
|
||||
struct query_params query_params;
|
||||
struct db_queue_item queue_item;
|
||||
|
@ -1923,7 +1946,7 @@ mpd_command_plchanges(struct evbuffer *evbuf, int argc, char **argv, char **errm
|
|||
* Lists all changed songs in the queue since the given playlist version in argv[1] without metadata.
|
||||
*/
|
||||
static int
|
||||
mpd_command_plchangesposid(struct evbuffer *evbuf, int argc, char **argv, char **errmsg)
|
||||
mpd_command_plchangesposid(struct evbuffer *evbuf, int argc, char **argv, char **errmsg, struct mpd_client_ctx *ctx)
|
||||
{
|
||||
struct query_params query_params;
|
||||
struct db_queue_item queue_item;
|
||||
|
@ -1961,7 +1984,7 @@ mpd_command_plchangesposid(struct evbuffer *evbuf, int argc, char **argv, char *
|
|||
* Lists all songs in the playlist given by virtual-path in argv[1].
|
||||
*/
|
||||
static int
|
||||
mpd_command_listplaylist(struct evbuffer *evbuf, int argc, char **argv, char **errmsg)
|
||||
mpd_command_listplaylist(struct evbuffer *evbuf, int argc, char **argv, char **errmsg, struct mpd_client_ctx *ctx)
|
||||
{
|
||||
char path[PATH_MAX];
|
||||
struct playlist_info *pli;
|
||||
|
@ -2029,7 +2052,7 @@ mpd_command_listplaylist(struct evbuffer *evbuf, int argc, char **argv, char **e
|
|||
* Lists all songs in the playlist given by virtual-path in argv[1] with metadata.
|
||||
*/
|
||||
static int
|
||||
mpd_command_listplaylistinfo(struct evbuffer *evbuf, int argc, char **argv, char **errmsg)
|
||||
mpd_command_listplaylistinfo(struct evbuffer *evbuf, int argc, char **argv, char **errmsg, struct mpd_client_ctx *ctx)
|
||||
{
|
||||
char path[PATH_MAX];
|
||||
struct playlist_info *pli;
|
||||
|
@ -2099,7 +2122,7 @@ mpd_command_listplaylistinfo(struct evbuffer *evbuf, int argc, char **argv, char
|
|||
* Lists all playlists with their last modified date.
|
||||
*/
|
||||
static int
|
||||
mpd_command_listplaylists(struct evbuffer *evbuf, int argc, char **argv, char **errmsg)
|
||||
mpd_command_listplaylists(struct evbuffer *evbuf, int argc, char **argv, char **errmsg, struct mpd_client_ctx *ctx)
|
||||
{
|
||||
struct query_params qp;
|
||||
struct db_playlist_info dbpli;
|
||||
|
@ -2152,7 +2175,7 @@ mpd_command_listplaylists(struct evbuffer *evbuf, int argc, char **argv, char **
|
|||
* Adds the playlist given by virtual-path in argv[1] to the queue.
|
||||
*/
|
||||
static int
|
||||
mpd_command_load(struct evbuffer *evbuf, int argc, char **argv, char **errmsg)
|
||||
mpd_command_load(struct evbuffer *evbuf, int argc, char **argv, char **errmsg, struct mpd_client_ctx *ctx)
|
||||
{
|
||||
char path[PATH_MAX];
|
||||
struct playlist_info *pli;
|
||||
|
@ -2199,7 +2222,7 @@ mpd_command_load(struct evbuffer *evbuf, int argc, char **argv, char **errmsg)
|
|||
}
|
||||
|
||||
static int
|
||||
mpd_command_playlistadd(struct evbuffer *evbuf, int argc, char **argv, char **errmsg)
|
||||
mpd_command_playlistadd(struct evbuffer *evbuf, int argc, char **argv, char **errmsg, struct mpd_client_ctx *ctx)
|
||||
{
|
||||
char *vp_playlist;
|
||||
char *vp_item;
|
||||
|
@ -2243,7 +2266,7 @@ mpd_command_playlistadd(struct evbuffer *evbuf, int argc, char **argv, char **er
|
|||
}
|
||||
|
||||
static int
|
||||
mpd_command_rm(struct evbuffer *evbuf, int argc, char **argv, char **errmsg)
|
||||
mpd_command_rm(struct evbuffer *evbuf, int argc, char **argv, char **errmsg, struct mpd_client_ctx *ctx)
|
||||
{
|
||||
char *virtual_path;
|
||||
int ret;
|
||||
|
@ -2283,7 +2306,7 @@ mpd_command_rm(struct evbuffer *evbuf, int argc, char **argv, char **errmsg)
|
|||
}
|
||||
|
||||
static int
|
||||
mpd_command_save(struct evbuffer *evbuf, int argc, char **argv, char **errmsg)
|
||||
mpd_command_save(struct evbuffer *evbuf, int argc, char **argv, char **errmsg, struct mpd_client_ctx *ctx)
|
||||
{
|
||||
char *virtual_path;
|
||||
int ret;
|
||||
|
@ -2442,7 +2465,7 @@ mpd_get_query_params_find(int argc, char **argv, struct query_params *qp)
|
|||
}
|
||||
|
||||
static int
|
||||
mpd_command_count(struct evbuffer *evbuf, int argc, char **argv, char **errmsg)
|
||||
mpd_command_count(struct evbuffer *evbuf, int argc, char **argv, char **errmsg, struct mpd_client_ctx *ctx)
|
||||
{
|
||||
struct query_params qp;
|
||||
struct filecount_info fci;
|
||||
|
@ -2480,7 +2503,7 @@ mpd_command_count(struct evbuffer *evbuf, int argc, char **argv, char **errmsg)
|
|||
}
|
||||
|
||||
static int
|
||||
mpd_command_find(struct evbuffer *evbuf, int argc, char **argv, char **errmsg)
|
||||
mpd_command_find(struct evbuffer *evbuf, int argc, char **argv, char **errmsg, struct mpd_client_ctx *ctx)
|
||||
{
|
||||
struct query_params qp;
|
||||
struct db_media_file_info dbmfi;
|
||||
|
@ -2526,7 +2549,7 @@ mpd_command_find(struct evbuffer *evbuf, int argc, char **argv, char **errmsg)
|
|||
}
|
||||
|
||||
static int
|
||||
mpd_command_findadd(struct evbuffer *evbuf, int argc, char **argv, char **errmsg)
|
||||
mpd_command_findadd(struct evbuffer *evbuf, int argc, char **argv, char **errmsg, struct mpd_client_ctx *ctx)
|
||||
{
|
||||
struct query_params qp;
|
||||
struct player_status status;
|
||||
|
@ -2560,7 +2583,7 @@ mpd_command_findadd(struct evbuffer *evbuf, int argc, char **argv, char **errmsg
|
|||
}
|
||||
|
||||
static int
|
||||
mpd_command_list(struct evbuffer *evbuf, int argc, char **argv, char **errmsg)
|
||||
mpd_command_list(struct evbuffer *evbuf, int argc, char **argv, char **errmsg, struct mpd_client_ctx *ctx)
|
||||
{
|
||||
struct query_params qp;
|
||||
struct db_group_info dbgri;
|
||||
|
@ -2813,7 +2836,7 @@ mpd_add_directory(struct evbuffer *evbuf, int directory_id, int listall, int lis
|
|||
}
|
||||
|
||||
static int
|
||||
mpd_command_listall(struct evbuffer *evbuf, int argc, char **argv, char **errmsg)
|
||||
mpd_command_listall(struct evbuffer *evbuf, int argc, char **argv, char **errmsg, struct mpd_client_ctx *ctx)
|
||||
{
|
||||
int dir_id;
|
||||
char parent[PATH_MAX];
|
||||
|
@ -2853,7 +2876,7 @@ mpd_command_listall(struct evbuffer *evbuf, int argc, char **argv, char **errmsg
|
|||
}
|
||||
|
||||
static int
|
||||
mpd_command_listallinfo(struct evbuffer *evbuf, int argc, char **argv, char **errmsg)
|
||||
mpd_command_listallinfo(struct evbuffer *evbuf, int argc, char **argv, char **errmsg, struct mpd_client_ctx *ctx)
|
||||
{
|
||||
int dir_id;
|
||||
char parent[PATH_MAX];
|
||||
|
@ -2897,7 +2920,7 @@ mpd_command_listallinfo(struct evbuffer *evbuf, int argc, char **argv, char **er
|
|||
* Lists the contents of the directory given in argv[1].
|
||||
*/
|
||||
static int
|
||||
mpd_command_lsinfo(struct evbuffer *evbuf, int argc, char **argv, char **errmsg)
|
||||
mpd_command_lsinfo(struct evbuffer *evbuf, int argc, char **argv, char **errmsg, struct mpd_client_ctx *ctx)
|
||||
{
|
||||
int dir_id;
|
||||
char parent[PATH_MAX];
|
||||
|
@ -2949,7 +2972,7 @@ mpd_command_lsinfo(struct evbuffer *evbuf, int argc, char **argv, char **errmsg)
|
|||
// If the root directory was passed as argument add the stored playlists to the response
|
||||
if (ret == 0 && print_playlists)
|
||||
{
|
||||
return mpd_command_listplaylists(evbuf, argc, argv, errmsg);
|
||||
return mpd_command_listplaylists(evbuf, argc, argv, errmsg, ctx);
|
||||
}
|
||||
|
||||
return ret;
|
||||
|
@ -3084,7 +3107,7 @@ mpd_get_query_params_search(int argc, char **argv, struct query_params *qp)
|
|||
* Example request: "search artist foo album bar"
|
||||
*/
|
||||
static int
|
||||
mpd_command_search(struct evbuffer *evbuf, int argc, char **argv, char **errmsg)
|
||||
mpd_command_search(struct evbuffer *evbuf, int argc, char **argv, char **errmsg, struct mpd_client_ctx *ctx)
|
||||
{
|
||||
struct query_params qp;
|
||||
struct db_media_file_info dbmfi;
|
||||
|
@ -3130,7 +3153,7 @@ mpd_command_search(struct evbuffer *evbuf, int argc, char **argv, char **errmsg)
|
|||
}
|
||||
|
||||
static int
|
||||
mpd_command_searchadd(struct evbuffer *evbuf, int argc, char **argv, char **errmsg)
|
||||
mpd_command_searchadd(struct evbuffer *evbuf, int argc, char **argv, char **errmsg, struct mpd_client_ctx *ctx)
|
||||
{
|
||||
struct query_params qp;
|
||||
struct player_status status;
|
||||
|
@ -3168,7 +3191,7 @@ mpd_command_searchadd(struct evbuffer *evbuf, int argc, char **argv, char **errm
|
|||
* Initiates an init-rescan (scans for new files)
|
||||
*/
|
||||
static int
|
||||
mpd_command_update(struct evbuffer *evbuf, int argc, char **argv, char **errmsg)
|
||||
mpd_command_update(struct evbuffer *evbuf, int argc, char **argv, char **errmsg, struct mpd_client_ctx *ctx)
|
||||
{
|
||||
if (argc > 1 && strlen(argv[1]) > 0)
|
||||
{
|
||||
|
@ -3185,7 +3208,7 @@ mpd_command_update(struct evbuffer *evbuf, int argc, char **argv, char **errmsg)
|
|||
|
||||
/*
|
||||
static int
|
||||
mpd_command_rescan(struct evbuffer *evbuf, int argc, char **argv, char **errmsg)
|
||||
mpd_command_rescan(struct evbuffer *evbuf, int argc, char **argv, char **errmsg, struct mpd_client_ctx *ctx)
|
||||
{
|
||||
int ret;
|
||||
|
||||
|
@ -3205,7 +3228,7 @@ mpd_command_rescan(struct evbuffer *evbuf, int argc, char **argv, char **errmsg)
|
|||
*/
|
||||
|
||||
static int
|
||||
mpd_command_password(struct evbuffer *evbuf, int argc, char **argv, char **errmsg)
|
||||
mpd_command_password(struct evbuffer *evbuf, int argc, char **argv, char **errmsg, struct mpd_client_ctx *ctx)
|
||||
{
|
||||
char *required_password;
|
||||
char *supplied_password = "";
|
||||
|
@ -3270,7 +3293,7 @@ outputs_enum_cb(uint64_t id, const char *name, int relvol, int absvol, struct sp
|
|||
* Expects argument argv[1] to be the id of the speaker to disable.
|
||||
*/
|
||||
static int
|
||||
mpd_command_disableoutput(struct evbuffer *evbuf, int argc, char **argv, char **errmsg)
|
||||
mpd_command_disableoutput(struct evbuffer *evbuf, int argc, char **argv, char **errmsg, struct mpd_client_ctx *ctx)
|
||||
{
|
||||
struct outputs outputs;
|
||||
struct output *output;
|
||||
|
@ -3354,7 +3377,7 @@ mpd_command_disableoutput(struct evbuffer *evbuf, int argc, char **argv, char **
|
|||
* Expects argument argv[1] to be the id of the speaker to enable.
|
||||
*/
|
||||
static int
|
||||
mpd_command_enableoutput(struct evbuffer *evbuf, int argc, char **argv, char **errmsg)
|
||||
mpd_command_enableoutput(struct evbuffer *evbuf, int argc, char **argv, char **errmsg, struct mpd_client_ctx *ctx)
|
||||
{
|
||||
struct outputs outputs;
|
||||
struct output *output;
|
||||
|
@ -3439,7 +3462,7 @@ mpd_command_enableoutput(struct evbuffer *evbuf, int argc, char **argv, char **e
|
|||
* Expects argument argv[1] to be the id of the speaker to enable/disable.
|
||||
*/
|
||||
static int
|
||||
mpd_command_toggleoutput(struct evbuffer *evbuf, int argc, char **argv, char **errmsg)
|
||||
mpd_command_toggleoutput(struct evbuffer *evbuf, int argc, char **argv, char **errmsg, struct mpd_client_ctx *ctx)
|
||||
{
|
||||
struct outputs outputs;
|
||||
struct output *output;
|
||||
|
@ -3558,7 +3581,7 @@ speaker_enum_cb(uint64_t id, const char *name, int relvol, int absvol, struct sp
|
|||
* Returns a lists with the avaiable speakers.
|
||||
*/
|
||||
static int
|
||||
mpd_command_outputs(struct evbuffer *evbuf, int argc, char **argv, char **errmsg)
|
||||
mpd_command_outputs(struct evbuffer *evbuf, int argc, char **argv, char **errmsg, struct mpd_client_ctx *ctx)
|
||||
{
|
||||
player_speaker_enumerate(speaker_enum_cb, evbuf);
|
||||
|
||||
|
@ -3609,7 +3632,7 @@ outputvolume_set(uint32_t shortid, int volume, char **errmsg)
|
|||
}
|
||||
|
||||
static int
|
||||
mpd_command_outputvolume(struct evbuffer *evbuf, int argc, char **argv, char **errmsg)
|
||||
mpd_command_outputvolume(struct evbuffer *evbuf, int argc, char **argv, char **errmsg, struct mpd_client_ctx *ctx)
|
||||
{
|
||||
uint32_t shortid;
|
||||
int volume;
|
||||
|
@ -3752,7 +3775,7 @@ mpd_find_channel(const char *name)
|
|||
}
|
||||
|
||||
static int
|
||||
mpd_command_channels(struct evbuffer *evbuf, int argc, char **argv, char **errmsg)
|
||||
mpd_command_channels(struct evbuffer *evbuf, int argc, char **argv, char **errmsg, struct mpd_client_ctx *ctx)
|
||||
{
|
||||
int i;
|
||||
|
||||
|
@ -3767,7 +3790,7 @@ mpd_command_channels(struct evbuffer *evbuf, int argc, char **argv, char **errms
|
|||
}
|
||||
|
||||
static int
|
||||
mpd_command_sendmessage(struct evbuffer *evbuf, int argc, char **argv, char **errmsg)
|
||||
mpd_command_sendmessage(struct evbuffer *evbuf, int argc, char **argv, char **errmsg, struct mpd_client_ctx *ctx)
|
||||
{
|
||||
const char *channelname;
|
||||
const char *message;
|
||||
|
@ -3799,7 +3822,7 @@ mpd_command_sendmessage(struct evbuffer *evbuf, int argc, char **argv, char **er
|
|||
* not raise an error.
|
||||
*/
|
||||
static int
|
||||
mpd_command_ignore(struct evbuffer *evbuf, int argc, char **argv, char **errmsg)
|
||||
mpd_command_ignore(struct evbuffer *evbuf, int argc, char **argv, char **errmsg, struct mpd_client_ctx *ctx)
|
||||
{
|
||||
//do nothing
|
||||
DPRINTF(E_DBG, L_MPD, "Ignore command %s\n", argv[0]);
|
||||
|
@ -3807,7 +3830,7 @@ mpd_command_ignore(struct evbuffer *evbuf, int argc, char **argv, char **errmsg)
|
|||
}
|
||||
|
||||
static int
|
||||
mpd_command_commands(struct evbuffer *evbuf, int argc, char **argv, char **errmsg);
|
||||
mpd_command_commands(struct evbuffer *evbuf, int argc, char **argv, char **errmsg, struct mpd_client_ctx *ctx);
|
||||
|
||||
/*
|
||||
* Command handler function for 'tagtypes'
|
||||
|
@ -3815,7 +3838,7 @@ mpd_command_commands(struct evbuffer *evbuf, int argc, char **argv, char **errms
|
|||
* tagtype: Artist
|
||||
*/
|
||||
static int
|
||||
mpd_command_tagtypes(struct evbuffer *evbuf, int argc, char **argv, char **errmsg)
|
||||
mpd_command_tagtypes(struct evbuffer *evbuf, int argc, char **argv, char **errmsg, struct mpd_client_ctx *ctx)
|
||||
{
|
||||
evbuffer_add_printf(evbuf,
|
||||
"tagtype: Artist\n"
|
||||
|
@ -3839,7 +3862,7 @@ mpd_command_tagtypes(struct evbuffer *evbuf, int argc, char **argv, char **errms
|
|||
* therefor the function reports only ffmpeg as available.
|
||||
*/
|
||||
static int
|
||||
mpd_command_decoders(struct evbuffer *evbuf, int argc, char **argv, char **errmsg)
|
||||
mpd_command_decoders(struct evbuffer *evbuf, int argc, char **argv, char **errmsg, struct mpd_client_ctx *ctx)
|
||||
{
|
||||
int i;
|
||||
|
||||
|
@ -3872,7 +3895,7 @@ struct mpd_command
|
|||
* @param errmsg error message set by this function if an error occured
|
||||
* @return 0 if successful, one of ack values if an error occured
|
||||
*/
|
||||
int (*handler)(struct evbuffer *evbuf, int argc, char **argv, char **errmsg);
|
||||
int (*handler)(struct evbuffer *evbuf, int argc, char **argv, char **errmsg, struct mpd_client_ctx *ctx);
|
||||
};
|
||||
|
||||
static struct mpd_command mpd_handlers[] =
|
||||
|
@ -4376,7 +4399,7 @@ mpd_find_command(const char *name)
|
|||
}
|
||||
|
||||
static int
|
||||
mpd_command_commands(struct evbuffer *evbuf, int argc, char **argv, char **errmsg)
|
||||
mpd_command_commands(struct evbuffer *evbuf, int argc, char **argv, char **errmsg, struct mpd_client_ctx *ctx)
|
||||
{
|
||||
int i;
|
||||
|
||||
|
@ -4413,7 +4436,7 @@ mpd_read_cb(struct bufferevent *bev, void *ctx)
|
|||
int close_cmd;
|
||||
char *argv[COMMAND_ARGV_MAX];
|
||||
int argc;
|
||||
struct mpd_cmd_ctx *cmd_ctx = (struct mpd_cmd_ctx *)ctx;
|
||||
struct mpd_client_ctx *client_ctx = (struct mpd_client_ctx *)ctx;
|
||||
|
||||
/* Get the input evbuffer, contains the command sequence received from the client */
|
||||
input = bufferevent_get_input(bev);
|
||||
|
@ -4486,16 +4509,16 @@ mpd_read_cb(struct bufferevent *bev, void *ctx)
|
|||
}
|
||||
else if (strcmp(command->mpdcommand, "password") == 0)
|
||||
{
|
||||
ret = command->handler(output, argc, argv, &errmsg);
|
||||
cmd_ctx->authenticated = ret == 0;
|
||||
ret = command->handler(output, argc, argv, &errmsg, client_ctx);
|
||||
client_ctx->authenticated = ret == 0;
|
||||
}
|
||||
else if (!cmd_ctx->authenticated)
|
||||
else if (!client_ctx->authenticated)
|
||||
{
|
||||
errmsg = safe_asprintf("Not authenticated");
|
||||
ret = ACK_ERROR_PERMISSION;
|
||||
}
|
||||
else
|
||||
ret = command->handler(output, argc, argv, &errmsg);
|
||||
ret = command->handler(output, argc, argv, &errmsg, client_ctx);
|
||||
|
||||
/*
|
||||
* If an error occurred, add the ACK line to the response buffer and exit the loop
|
||||
|
@ -4540,8 +4563,6 @@ mpd_read_cb(struct bufferevent *bev, void *ctx)
|
|||
static void
|
||||
mpd_event_cb(struct bufferevent *bev, short events, void *ctx)
|
||||
{
|
||||
struct evbuffer *evbuf;
|
||||
|
||||
if (events & BEV_EVENT_ERROR)
|
||||
{
|
||||
DPRINTF(E_LOG, L_MPD, "Error from bufferevent: %s\n",
|
||||
|
@ -4550,8 +4571,6 @@ mpd_event_cb(struct bufferevent *bev, short events, void *ctx)
|
|||
|
||||
if (events & (BEV_EVENT_EOF | BEV_EVENT_ERROR))
|
||||
{
|
||||
evbuf = bufferevent_get_output(bev);
|
||||
mpd_remove_idle_client(evbuf);
|
||||
bufferevent_free(bev);
|
||||
}
|
||||
}
|
||||
|
@ -4658,25 +4677,27 @@ mpd_accept_conn_cb(struct evconnlistener *listener,
|
|||
*/
|
||||
struct event_base *base = evconnlistener_get_base(listener);
|
||||
struct bufferevent *bev = bufferevent_socket_new(base, sock, BEV_OPT_CLOSE_ON_FREE);
|
||||
struct mpd_cmd_ctx *cmd_ctx = (struct mpd_cmd_ctx *)malloc(sizeof(struct mpd_cmd_ctx));
|
||||
char addr_str[INET6_ADDRSTRLEN];
|
||||
struct mpd_client_ctx *client_ctx = calloc(1, sizeof(struct mpd_client_ctx));
|
||||
|
||||
if (!cmd_ctx)
|
||||
if (!client_ctx)
|
||||
{
|
||||
DPRINTF(E_LOG, L_MPD, "Out of memory for command context\n");
|
||||
bufferevent_free(bev);
|
||||
return;
|
||||
}
|
||||
|
||||
cmd_ctx->authenticated = !cfg_getstr(cfg_getsec(cfg, "library"), "password");
|
||||
if (!cmd_ctx->authenticated)
|
||||
client_ctx->authenticated = !cfg_getstr(cfg_getsec(cfg, "library"), "password");
|
||||
if (!client_ctx->authenticated)
|
||||
{
|
||||
sockaddr_to_string(address, addr_str, sizeof(addr_str));
|
||||
cmd_ctx->authenticated = peer_address_is_trusted(addr_str);
|
||||
client_ctx->authenticated = peer_address_is_trusted(addr_str);
|
||||
}
|
||||
client_ctx->next = mpd_clients;
|
||||
mpd_clients = client_ctx;
|
||||
|
||||
bev = bufferevent_filter_new(bev, mpd_input_filter, NULL, BEV_OPT_CLOSE_ON_FREE, free, cmd_ctx);
|
||||
bufferevent_setcb(bev, mpd_read_cb, NULL, mpd_event_cb, cmd_ctx);
|
||||
bev = bufferevent_filter_new(bev, mpd_input_filter, NULL, BEV_OPT_CLOSE_ON_FREE, free_mpd_client_ctx, client_ctx);
|
||||
bufferevent_setcb(bev, mpd_read_cb, NULL, mpd_event_cb, client_ctx);
|
||||
bufferevent_enable(bev, EV_READ | EV_WRITE);
|
||||
|
||||
/*
|
||||
|
@ -4684,6 +4705,9 @@ mpd_accept_conn_cb(struct evconnlistener *listener,
|
|||
* of the supported mpd protocol and not the server version.
|
||||
*/
|
||||
evbuffer_add(bufferevent_get_output(bev), "OK MPD 0.18.0\n", 14);
|
||||
client_ctx->evbuffer = bufferevent_get_output(bev);
|
||||
|
||||
DPRINTF(E_INFO, L_MPD, "New mpd client connection accepted\n");
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -4701,54 +4725,42 @@ mpd_accept_error_cb(struct evconnlistener *listener, void *ctx)
|
|||
}
|
||||
|
||||
static int
|
||||
mpd_notify_idle_client(struct idle_client *client, enum listener_event_type type)
|
||||
mpd_notify_idle_client(struct mpd_client_ctx *client_ctx, short events)
|
||||
{
|
||||
if (!(client->events & type))
|
||||
if (!client_ctx->is_idle)
|
||||
{
|
||||
DPRINTF(E_DBG, L_MPD, "Client not listening for event: %d\n", type);
|
||||
client_ctx->events |= events;
|
||||
return 1;
|
||||
}
|
||||
|
||||
switch (type)
|
||||
if (!(client_ctx->idle_events & events))
|
||||
{
|
||||
case LISTENER_DATABASE:
|
||||
evbuffer_add(client->evbuffer, "changed: database\n", 18);
|
||||
break;
|
||||
|
||||
case LISTENER_UPDATE:
|
||||
evbuffer_add(client->evbuffer, "changed: update\n", 16);
|
||||
break;
|
||||
|
||||
case LISTENER_PLAYER:
|
||||
evbuffer_add(client->evbuffer, "changed: player\n", 16);
|
||||
break;
|
||||
|
||||
case LISTENER_QUEUE:
|
||||
evbuffer_add(client->evbuffer, "changed: playlist\n", 18);
|
||||
break;
|
||||
|
||||
case LISTENER_VOLUME:
|
||||
evbuffer_add(client->evbuffer, "changed: mixer\n", 15);
|
||||
break;
|
||||
|
||||
case LISTENER_SPEAKER:
|
||||
evbuffer_add(client->evbuffer, "changed: output\n", 16);
|
||||
break;
|
||||
|
||||
case LISTENER_OPTIONS:
|
||||
evbuffer_add(client->evbuffer, "changed: options\n", 17);
|
||||
break;
|
||||
|
||||
case LISTENER_STORED_PLAYLIST:
|
||||
evbuffer_add(client->evbuffer, "changed: stored_playlist\n", 25);
|
||||
break;
|
||||
|
||||
default:
|
||||
DPRINTF(E_WARN, L_MPD, "Unsupported event type (%d) in notify idle clients.\n", type);
|
||||
return -1;
|
||||
DPRINTF(E_DBG, L_MPD, "Client not listening for events: %d\n", events);
|
||||
return 1;
|
||||
}
|
||||
|
||||
evbuffer_add(client->evbuffer, "OK\n", 3);
|
||||
if (events & LISTENER_DATABASE)
|
||||
evbuffer_add(client_ctx->evbuffer, "changed: database\n", 18);
|
||||
if (events & LISTENER_UPDATE)
|
||||
evbuffer_add(client_ctx->evbuffer, "changed: update\n", 16);
|
||||
if (events & LISTENER_PLAYER)
|
||||
evbuffer_add(client_ctx->evbuffer, "changed: player\n", 16);
|
||||
if (events & LISTENER_QUEUE)
|
||||
evbuffer_add(client_ctx->evbuffer, "changed: playlist\n", 18);
|
||||
if (events & LISTENER_VOLUME)
|
||||
evbuffer_add(client_ctx->evbuffer, "changed: mixer\n", 15);
|
||||
if (events & LISTENER_SPEAKER)
|
||||
evbuffer_add(client_ctx->evbuffer, "changed: output\n", 16);
|
||||
if (events & LISTENER_OPTIONS)
|
||||
evbuffer_add(client_ctx->evbuffer, "changed: options\n", 17);
|
||||
if (events & LISTENER_STORED_PLAYLIST)
|
||||
evbuffer_add(client_ctx->evbuffer, "changed: stored_playlist\n", 25);
|
||||
|
||||
evbuffer_add(client_ctx->evbuffer, "OK\n", 3);
|
||||
|
||||
client_ctx->is_idle = false;
|
||||
client_ctx->idle_events = 0;
|
||||
client_ctx->events = 0;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -4757,42 +4769,20 @@ static enum command_state
|
|||
mpd_notify_idle(void *arg, int *retval)
|
||||
{
|
||||
enum listener_event_type type;
|
||||
struct idle_client *client;
|
||||
struct idle_client *prev;
|
||||
struct idle_client *next;
|
||||
struct mpd_client_ctx *client;
|
||||
int i;
|
||||
int ret;
|
||||
|
||||
type = *(enum listener_event_type *)arg;
|
||||
DPRINTF(E_DBG, L_MPD, "Notify clients waiting for idle results: %d\n", type);
|
||||
|
||||
prev = NULL;
|
||||
next = NULL;
|
||||
i = 0;
|
||||
client = idle_clients;
|
||||
client = mpd_clients;
|
||||
while (client)
|
||||
{
|
||||
DPRINTF(E_DBG, L_MPD, "Notify client #%d\n", i);
|
||||
|
||||
next = client->next;
|
||||
|
||||
ret = mpd_notify_idle_client(client, type);
|
||||
|
||||
if (ret == 0)
|
||||
{
|
||||
if (prev)
|
||||
prev->next = next;
|
||||
else
|
||||
idle_clients = next;
|
||||
|
||||
free(client);
|
||||
}
|
||||
else
|
||||
{
|
||||
prev = client;
|
||||
}
|
||||
|
||||
client = next;
|
||||
mpd_notify_idle_client(client, type);
|
||||
client = client->next;
|
||||
i++;
|
||||
}
|
||||
|
||||
|
@ -5076,7 +5066,7 @@ int mpd_init(void)
|
|||
pthread_set_name_np(tid_mpd, "mpd");
|
||||
#endif
|
||||
|
||||
idle_clients = NULL;
|
||||
mpd_clients = NULL;
|
||||
listener_add(mpd_listener_cb, LISTENER_PLAYER | LISTENER_QUEUE | LISTENER_VOLUME | LISTENER_SPEAKER | LISTENER_OPTIONS | LISTENER_DATABASE | LISTENER_UPDATE | LISTENER_STORED_PLAYLIST);
|
||||
|
||||
return 0;
|
||||
|
@ -5104,7 +5094,6 @@ int mpd_init(void)
|
|||
/* Thread: main */
|
||||
void mpd_deinit(void)
|
||||
{
|
||||
struct idle_client *temp;
|
||||
unsigned short port;
|
||||
unsigned short http_port;
|
||||
int ret;
|
||||
|
@ -5127,11 +5116,9 @@ void mpd_deinit(void)
|
|||
|
||||
listener_remove(mpd_listener_cb);
|
||||
|
||||
while (idle_clients)
|
||||
while (mpd_clients)
|
||||
{
|
||||
temp = idle_clients;
|
||||
idle_clients = idle_clients->next;
|
||||
free(temp);
|
||||
free_mpd_client_ctx(mpd_clients);
|
||||
}
|
||||
|
||||
http_port = cfg_getint(cfg_getsec(cfg, "mpd"), "http_port");
|
||||
|
|
Loading…
Reference in New Issue