refactor
This commit is contained in:
2
Makefile
2
Makefile
@@ -1,7 +1,7 @@
|
||||
.PHONY: all clean install uninstall
|
||||
|
||||
PROG= mpdws
|
||||
SRCS= mpd_ws.h mpd_ws.c main.c
|
||||
SRCS= mpdws.h mpdws.c main.c
|
||||
NOMAN=
|
||||
|
||||
CPPFLAGS+= -I/usr/local/include
|
||||
|
||||
2
main.c
2
main.c
@@ -1,4 +1,4 @@
|
||||
#include "mpd_ws.h"
|
||||
#include "mpdws.h"
|
||||
#include <stdio.h>
|
||||
|
||||
int main() {
|
||||
|
||||
351
mpd_ws.c
351
mpd_ws.c
@@ -1,351 +0,0 @@
|
||||
#include "mpd_ws.h"
|
||||
#include <signal.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <sys/select.h>
|
||||
#include <syslog.h>
|
||||
#include <time.h>
|
||||
#include <unistd.h>
|
||||
|
||||
/* Global server instance for signal handling */
|
||||
static struct mpd_ws_server *g_server = NULL;
|
||||
|
||||
/* Signal handler */
|
||||
static void signal_handler(int sig) {
|
||||
(void)sig; /* Suppress unused param warning */
|
||||
if (g_server) {
|
||||
g_server->running = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* WebSocket callback */
|
||||
static int ws_callback(struct lws *wsi, enum lws_callback_reasons reason,
|
||||
void *user, void *in, size_t len) {
|
||||
(void)user; /* Suppress unused param warnings */
|
||||
(void)in;
|
||||
(void)len;
|
||||
|
||||
struct mpd_ws_server *server =
|
||||
(struct mpd_ws_server *)lws_context_user(lws_get_context(wsi));
|
||||
|
||||
switch (reason) {
|
||||
case LWS_CALLBACK_ESTABLISHED:
|
||||
client_add(server, wsi);
|
||||
/* Send current song to new client */
|
||||
if (strlen(server->current_song) > 0) {
|
||||
lws_callback_on_writable(wsi);
|
||||
}
|
||||
break;
|
||||
|
||||
case LWS_CALLBACK_CLOSED:
|
||||
client_remove(server, wsi);
|
||||
break;
|
||||
|
||||
case LWS_CALLBACK_SERVER_WRITEABLE:
|
||||
if (strlen(server->current_song) > 0) {
|
||||
unsigned char buf[LWS_PRE + MAX_MESSAGE_SIZE];
|
||||
size_t msg_len = strlen(server->current_song);
|
||||
memcpy(&buf[LWS_PRE], server->current_song, msg_len);
|
||||
lws_write(wsi, &buf[LWS_PRE], msg_len, LWS_WRITE_TEXT);
|
||||
}
|
||||
break;
|
||||
|
||||
case LWS_CALLBACK_RECEIVE:
|
||||
/* Ignore client input */
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* WebSocket protocols */
|
||||
static struct lws_protocols protocols[] = {
|
||||
{"mpd-protocol", ws_callback, 0, MAX_MESSAGE_SIZE, 0, NULL, 0},
|
||||
{NULL, NULL, 0, 0, 0, NULL, 0}};
|
||||
|
||||
/* Initialize the server */
|
||||
int mpd_ws_init(struct mpd_ws_server *server) {
|
||||
memset(server, 0, sizeof(*server));
|
||||
|
||||
/* Setup signal handlers */
|
||||
g_server = server;
|
||||
signal(SIGINT, signal_handler);
|
||||
signal(SIGTERM, signal_handler);
|
||||
|
||||
/* Initialize syslog */
|
||||
openlog("mpd_ws", LOG_PID | LOG_NDELAY, LOG_DAEMON);
|
||||
|
||||
/* Create WebSocket context */
|
||||
struct lws_context_creation_info info = {0};
|
||||
info.port = WEBSOCKET_PORT;
|
||||
info.protocols = protocols;
|
||||
info.gid = -1;
|
||||
info.uid = -1;
|
||||
info.user = server;
|
||||
|
||||
server->ws_context = lws_create_context(&info);
|
||||
if (!server->ws_context) {
|
||||
syslog(LOG_ERR, "Failed to create WebSocket context");
|
||||
return -1;
|
||||
}
|
||||
|
||||
syslog(LOG_INFO, "WebSocket server listening on port %d", WEBSOCKET_PORT);
|
||||
|
||||
/* Connect to MPD */
|
||||
mpd_ws_connect(server);
|
||||
|
||||
server->running = 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Main server loop */
|
||||
void mpd_ws_run(struct mpd_ws_server *server) {
|
||||
time_t last_reconnect = 0;
|
||||
|
||||
while (server->running) {
|
||||
/* Service WebSocket events */
|
||||
lws_service(server->ws_context, 10);
|
||||
|
||||
/* Handle MPD reconnection */
|
||||
if (!mpd_ws_is_connected(server)) {
|
||||
time_t now = time(NULL);
|
||||
if (now - last_reconnect >= RECONNECT_INTERVAL_SEC) {
|
||||
if (mpd_ws_connect(server) == 0) {
|
||||
mpd_ws_update_song(server);
|
||||
mpd_ws_start_idle(server);
|
||||
}
|
||||
last_reconnect = now;
|
||||
}
|
||||
sleep(SELECT_TIMEOUT_SEC);
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Start idle mode if not active */
|
||||
if (!server->mpd_idle_active) {
|
||||
if (mpd_ws_start_idle(server) < 0) {
|
||||
mpd_ws_disconnect(server);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
/* Check for MPD events */
|
||||
fd_set readfds;
|
||||
int mpd_fd = mpd_connection_get_fd(server->mpd_conn);
|
||||
struct timeval timeout = {0, SELECT_TIMEOUT_SEC};
|
||||
|
||||
FD_ZERO(&readfds);
|
||||
FD_SET(mpd_fd, &readfds);
|
||||
|
||||
int result = select(mpd_fd + 1, &readfds, NULL, NULL, &timeout);
|
||||
if (result > 0 && FD_ISSET(mpd_fd, &readfds)) {
|
||||
mpd_ws_process_idle(server);
|
||||
if (!mpd_ws_is_connected(server)) {
|
||||
mpd_ws_disconnect(server);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Cleanup and shutdown */
|
||||
void mpd_ws_cleanup(struct mpd_ws_server *server) {
|
||||
syslog(LOG_INFO, "Shutting down");
|
||||
|
||||
mpd_ws_disconnect(server);
|
||||
|
||||
if (server->ws_context) {
|
||||
lws_context_destroy(server->ws_context);
|
||||
}
|
||||
|
||||
/* Free client list */
|
||||
while (server->clients) {
|
||||
struct client_session *next = server->clients->next;
|
||||
free(server->clients);
|
||||
server->clients = next;
|
||||
}
|
||||
|
||||
closelog();
|
||||
}
|
||||
|
||||
/* Stop the server */
|
||||
void mpd_ws_stop(struct mpd_ws_server *server) { server->running = 0; }
|
||||
|
||||
/* Connect to MPD */
|
||||
int mpd_ws_connect(struct mpd_ws_server *server) {
|
||||
if (server->mpd_conn) {
|
||||
mpd_connection_free(server->mpd_conn);
|
||||
}
|
||||
|
||||
server->mpd_conn = mpd_connection_new(MPD_HOST, MPD_PORT, 0);
|
||||
if (mpd_connection_get_error(server->mpd_conn) != MPD_ERROR_SUCCESS) {
|
||||
syslog(LOG_ERR, "Failed to connect to MPD: %s",
|
||||
mpd_connection_get_error_message(server->mpd_conn));
|
||||
mpd_connection_free(server->mpd_conn);
|
||||
server->mpd_conn = NULL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
server->mpd_idle_active = 0;
|
||||
syslog(LOG_INFO, "Connected to MPD at %s:%d", MPD_HOST, MPD_PORT);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Disconnect from MPD */
|
||||
void mpd_ws_disconnect(struct mpd_ws_server *server) {
|
||||
if (server->mpd_conn) {
|
||||
if (server->mpd_idle_active) {
|
||||
mpd_send_noidle(server->mpd_conn);
|
||||
mpd_response_finish(server->mpd_conn);
|
||||
}
|
||||
mpd_connection_free(server->mpd_conn);
|
||||
server->mpd_conn = NULL;
|
||||
}
|
||||
server->mpd_idle_active = 0;
|
||||
}
|
||||
|
||||
/* Check if MPD is connected */
|
||||
int mpd_ws_is_connected(struct mpd_ws_server *server) {
|
||||
return server->mpd_conn &&
|
||||
mpd_connection_get_error(server->mpd_conn) == MPD_ERROR_SUCCESS;
|
||||
}
|
||||
|
||||
/* Update current song and broadcast */
|
||||
void mpd_ws_update_song(struct mpd_ws_server *server) {
|
||||
if (!mpd_ws_is_connected(server)) {
|
||||
return;
|
||||
}
|
||||
|
||||
mpd_command_list_begin(server->mpd_conn, false);
|
||||
mpd_send_current_song(server->mpd_conn);
|
||||
mpd_command_list_end(server->mpd_conn);
|
||||
|
||||
struct mpd_song *song = mpd_recv_song(server->mpd_conn);
|
||||
if (mpd_connection_get_error(server->mpd_conn) != MPD_ERROR_SUCCESS) {
|
||||
syslog(LOG_ERR, "Failed to get current song: %s",
|
||||
mpd_connection_get_error_message(server->mpd_conn));
|
||||
return;
|
||||
}
|
||||
|
||||
/* Create song message */
|
||||
if (song == NULL) {
|
||||
snprintf(server->current_song, MAX_MESSAGE_SIZE, "Now Playing: No song");
|
||||
} else {
|
||||
const char *artist = mpd_song_get_tag(song, MPD_TAG_ARTIST, 0);
|
||||
const char *title = mpd_song_get_tag(song, MPD_TAG_TITLE, 0);
|
||||
|
||||
if (artist && title) {
|
||||
snprintf(server->current_song, MAX_MESSAGE_SIZE, "Now Playing: %s - %s",
|
||||
artist, title);
|
||||
} else if (title) {
|
||||
snprintf(server->current_song, MAX_MESSAGE_SIZE, "Now Playing: %s",
|
||||
title);
|
||||
} else {
|
||||
const char *uri = mpd_song_get_uri(song);
|
||||
snprintf(server->current_song, MAX_MESSAGE_SIZE, "Now Playing: %s",
|
||||
uri ? uri : "Unknown");
|
||||
}
|
||||
}
|
||||
|
||||
syslog(LOG_DEBUG, "Broadcasting: %s", server->current_song);
|
||||
|
||||
/* Only broadcast if song actually changed */
|
||||
if (strcmp(server->current_song, server->previous_song) != 0) {
|
||||
client_broadcast(server, server->current_song);
|
||||
strlcpy(server->previous_song, server->current_song,
|
||||
sizeof(server->previous_song));
|
||||
}
|
||||
|
||||
if (song) {
|
||||
mpd_song_free(song);
|
||||
}
|
||||
mpd_response_finish(server->mpd_conn);
|
||||
}
|
||||
|
||||
/* Start MPD idle mode */
|
||||
int mpd_ws_start_idle(struct mpd_ws_server *server) {
|
||||
if (!mpd_ws_is_connected(server)) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (!mpd_send_idle_mask(server->mpd_conn, MPD_IDLE_PLAYER)) {
|
||||
syslog(LOG_ERR, "Failed to send idle command: %s",
|
||||
mpd_connection_get_error_message(server->mpd_conn));
|
||||
return -1;
|
||||
}
|
||||
|
||||
server->mpd_idle_active = 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Process MPD idle response */
|
||||
void mpd_ws_process_idle(struct mpd_ws_server *server) {
|
||||
if (!mpd_ws_is_connected(server) || !server->mpd_idle_active) {
|
||||
return;
|
||||
}
|
||||
|
||||
enum mpd_idle events = mpd_recv_idle(server->mpd_conn, false);
|
||||
server->mpd_idle_active = 0;
|
||||
|
||||
if (mpd_connection_get_error(server->mpd_conn) != MPD_ERROR_SUCCESS) {
|
||||
syslog(LOG_WARNING, "MPD idle error: %s",
|
||||
mpd_connection_get_error_message(server->mpd_conn));
|
||||
return;
|
||||
}
|
||||
|
||||
if (events & MPD_IDLE_PLAYER) {
|
||||
mpd_ws_update_song(server);
|
||||
}
|
||||
|
||||
/* Restart idle mode */
|
||||
mpd_ws_start_idle(server);
|
||||
}
|
||||
|
||||
/* Add client */
|
||||
void client_add(struct mpd_ws_server *server, struct lws *wsi) {
|
||||
struct client_session *client = malloc(sizeof(struct client_session));
|
||||
if (!client) {
|
||||
syslog(LOG_ERR, "Failed to allocate client session");
|
||||
return;
|
||||
}
|
||||
|
||||
client->wsi = wsi;
|
||||
client->next = server->clients;
|
||||
server->clients = client;
|
||||
|
||||
syslog(LOG_INFO, "Client connected");
|
||||
}
|
||||
|
||||
/* Remove client */
|
||||
void client_remove(struct mpd_ws_server *server, struct lws *wsi) {
|
||||
struct client_session **current = &server->clients;
|
||||
|
||||
while (*current) {
|
||||
if ((*current)->wsi == wsi) {
|
||||
struct client_session *to_remove = *current;
|
||||
*current = (*current)->next;
|
||||
free(to_remove);
|
||||
syslog(LOG_INFO, "Client disconnected");
|
||||
return;
|
||||
}
|
||||
current = &(*current)->next;
|
||||
}
|
||||
}
|
||||
|
||||
/* Broadcast message to all clients */
|
||||
void client_broadcast(struct mpd_ws_server *server, const char *message) {
|
||||
struct client_session *client = server->clients;
|
||||
size_t len = strlen(message);
|
||||
|
||||
while (client) {
|
||||
unsigned char buf[LWS_PRE + MAX_MESSAGE_SIZE];
|
||||
memcpy(&buf[LWS_PRE], message, len);
|
||||
|
||||
if (lws_write(client->wsi, &buf[LWS_PRE], len, LWS_WRITE_TEXT) < 0) {
|
||||
syslog(LOG_WARNING, "Failed to write to websocket");
|
||||
}
|
||||
client = client->next;
|
||||
}
|
||||
}
|
||||
244
mpdws.c
Normal file
244
mpdws.c
Normal file
@@ -0,0 +1,244 @@
|
||||
#include "mpdws.h"
|
||||
#include <signal.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <sys/select.h>
|
||||
#include <syslog.h>
|
||||
#include <time.h>
|
||||
#include <unistd.h>
|
||||
|
||||
static struct mpd_ws_server *g_server = NULL;
|
||||
|
||||
static void signal_handler(int sig) {
|
||||
(void)sig;
|
||||
if (g_server)
|
||||
g_server->running = 0;
|
||||
}
|
||||
|
||||
static void broadcast_current_song(struct mpd_ws_server *server) {
|
||||
struct client_session *client = server->clients;
|
||||
size_t len = strlen(server->current_song);
|
||||
|
||||
while (client) {
|
||||
unsigned char buf[LWS_PRE + MAX_MESSAGE_SIZE];
|
||||
memcpy(&buf[LWS_PRE], server->current_song, len);
|
||||
lws_write(client->wsi, &buf[LWS_PRE], len, LWS_WRITE_TEXT);
|
||||
client = client->next;
|
||||
}
|
||||
}
|
||||
|
||||
static int ws_callback(struct lws *wsi, enum lws_callback_reasons reason,
|
||||
void *user, void *in, size_t len) {
|
||||
(void)user;
|
||||
(void)in;
|
||||
(void)len;
|
||||
|
||||
struct mpd_ws_server *server =
|
||||
(struct mpd_ws_server *)lws_context_user(lws_get_context(wsi));
|
||||
|
||||
switch (reason) {
|
||||
case LWS_CALLBACK_ESTABLISHED: {
|
||||
struct client_session *client = malloc(sizeof(*client));
|
||||
if (client) {
|
||||
client->wsi = wsi;
|
||||
client->next = server->clients;
|
||||
server->clients = client;
|
||||
syslog(LOG_INFO, "Client connected");
|
||||
if (strlen(server->current_song) > 0) {
|
||||
lws_callback_on_writable(wsi);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
case LWS_CALLBACK_CLOSED: {
|
||||
struct client_session **current = &server->clients;
|
||||
while (*current) {
|
||||
if ((*current)->wsi == wsi) {
|
||||
struct client_session *to_remove = *current;
|
||||
*current = (*current)->next;
|
||||
free(to_remove);
|
||||
syslog(LOG_INFO, "Client disconnected");
|
||||
break;
|
||||
}
|
||||
current = &(*current)->next;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case LWS_CALLBACK_SERVER_WRITEABLE:
|
||||
if (strlen(server->current_song) > 0) {
|
||||
unsigned char buf[LWS_PRE + MAX_MESSAGE_SIZE];
|
||||
size_t msg_len = strlen(server->current_song);
|
||||
memcpy(&buf[LWS_PRE], server->current_song, msg_len);
|
||||
lws_write(wsi, &buf[LWS_PRE], msg_len, LWS_WRITE_TEXT);
|
||||
}
|
||||
break;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct lws_protocols protocols[] = {
|
||||
{"mpd-protocol", ws_callback, 0, MAX_MESSAGE_SIZE, 0, NULL, 0},
|
||||
{NULL, NULL, 0, 0, 0, NULL, 0}};
|
||||
|
||||
static int connect_mpd(struct mpd_ws_server *server) {
|
||||
if (server->mpd_conn) {
|
||||
if (server->mpd_idle_active) {
|
||||
mpd_send_noidle(server->mpd_conn);
|
||||
mpd_response_finish(server->mpd_conn);
|
||||
}
|
||||
mpd_connection_free(server->mpd_conn);
|
||||
}
|
||||
|
||||
server->mpd_conn = mpd_connection_new(MPD_HOST, MPD_PORT, 0);
|
||||
server->mpd_idle_active = 0;
|
||||
|
||||
if (mpd_connection_get_error(server->mpd_conn) != MPD_ERROR_SUCCESS) {
|
||||
syslog(LOG_ERR, "MPD connection failed: %s",
|
||||
mpd_connection_get_error_message(server->mpd_conn));
|
||||
mpd_connection_free(server->mpd_conn);
|
||||
server->mpd_conn = NULL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
syslog(LOG_INFO, "Connected to MPD at %s:%d", MPD_HOST, MPD_PORT);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void update_current_song(struct mpd_ws_server *server) {
|
||||
if (!server->mpd_conn ||
|
||||
mpd_connection_get_error(server->mpd_conn) != MPD_ERROR_SUCCESS) {
|
||||
return;
|
||||
}
|
||||
|
||||
mpd_send_current_song(server->mpd_conn);
|
||||
struct mpd_song *song = mpd_recv_song(server->mpd_conn);
|
||||
|
||||
if (mpd_connection_get_error(server->mpd_conn) != MPD_ERROR_SUCCESS) {
|
||||
mpd_response_finish(server->mpd_conn);
|
||||
return;
|
||||
}
|
||||
|
||||
char new_song[MAX_MESSAGE_SIZE];
|
||||
if (!song) {
|
||||
snprintf(new_song, sizeof(new_song), "Now Playing: No song");
|
||||
} else {
|
||||
const char *artist = mpd_song_get_tag(song, MPD_TAG_ARTIST, 0);
|
||||
const char *title = mpd_song_get_tag(song, MPD_TAG_TITLE, 0);
|
||||
|
||||
snprintf(new_song, sizeof(new_song), "Now Playing: %s - %s", artist, title);
|
||||
mpd_song_free(song);
|
||||
}
|
||||
|
||||
// Only send song if it's changed
|
||||
if (strcmp(new_song, server->current_song) != 0) {
|
||||
strlcpy(server->current_song, new_song, sizeof(server->current_song));
|
||||
broadcast_current_song(server);
|
||||
syslog(LOG_DEBUG, "Broadcasting: %s", server->current_song);
|
||||
}
|
||||
|
||||
mpd_response_finish(server->mpd_conn);
|
||||
}
|
||||
|
||||
int mpd_ws_init(struct mpd_ws_server *server) {
|
||||
memset(server, 0, sizeof(*server));
|
||||
|
||||
g_server = server;
|
||||
signal(SIGINT, signal_handler);
|
||||
signal(SIGTERM, signal_handler);
|
||||
openlog("mpd_ws", LOG_PID | LOG_NDELAY, LOG_DAEMON);
|
||||
|
||||
struct lws_context_creation_info info = {0};
|
||||
info.port = WEBSOCKET_PORT;
|
||||
info.protocols = protocols;
|
||||
info.gid = info.uid = -1;
|
||||
info.user = server;
|
||||
|
||||
server->ws_context = lws_create_context(&info);
|
||||
if (!server->ws_context) {
|
||||
syslog(LOG_ERR, "Failed to create WebSocket context");
|
||||
return -1;
|
||||
}
|
||||
|
||||
syslog(LOG_INFO, "WebSocket server listening on port %d", WEBSOCKET_PORT);
|
||||
connect_mpd(server);
|
||||
server->running = 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
void mpd_ws_run(struct mpd_ws_server *server) {
|
||||
time_t last_reconnect = 0;
|
||||
|
||||
while (server->running) {
|
||||
lws_service(server->ws_context, 10);
|
||||
|
||||
// Handle MPD connection
|
||||
if (!server->mpd_conn ||
|
||||
mpd_connection_get_error(server->mpd_conn) != MPD_ERROR_SUCCESS) {
|
||||
time_t now = time(NULL);
|
||||
if (now - last_reconnect >= RECONNECT_INTERVAL_SEC) {
|
||||
if (connect_mpd(server) == 0) {
|
||||
update_current_song(server);
|
||||
}
|
||||
last_reconnect = now;
|
||||
}
|
||||
sleep(SELECT_TIMEOUT_SEC);
|
||||
continue;
|
||||
}
|
||||
|
||||
// Start idle if needed
|
||||
if (!server->mpd_idle_active) {
|
||||
if (mpd_send_idle_mask(server->mpd_conn, MPD_IDLE_PLAYER)) {
|
||||
server->mpd_idle_active = 1;
|
||||
} else {
|
||||
connect_mpd(server);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
// Check for MPD events
|
||||
fd_set readfds;
|
||||
int mpd_fd = mpd_connection_get_fd(server->mpd_conn);
|
||||
struct timeval timeout = {0, SELECT_TIMEOUT_SEC};
|
||||
|
||||
FD_ZERO(&readfds);
|
||||
FD_SET(mpd_fd, &readfds);
|
||||
|
||||
if (select(mpd_fd + 1, &readfds, NULL, NULL, &timeout) > 0 &&
|
||||
FD_ISSET(mpd_fd, &readfds)) {
|
||||
|
||||
enum mpd_idle events = mpd_recv_idle(server->mpd_conn, false);
|
||||
server->mpd_idle_active = 0;
|
||||
|
||||
if (mpd_connection_get_error(server->mpd_conn) == MPD_ERROR_SUCCESS) {
|
||||
if (events & MPD_IDLE_PLAYER) {
|
||||
update_current_song(server);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void mpd_ws_cleanup(struct mpd_ws_server *server) {
|
||||
syslog(LOG_INFO, "Shutting down");
|
||||
|
||||
if (server->mpd_conn) {
|
||||
if (server->mpd_idle_active) {
|
||||
mpd_send_noidle(server->mpd_conn);
|
||||
mpd_response_finish(server->mpd_conn);
|
||||
}
|
||||
mpd_connection_free(server->mpd_conn);
|
||||
}
|
||||
|
||||
if (server->ws_context) {
|
||||
lws_context_destroy(server->ws_context);
|
||||
}
|
||||
|
||||
while (server->clients) {
|
||||
struct client_session *next = server->clients->next;
|
||||
free(server->clients);
|
||||
server->clients = next;
|
||||
}
|
||||
|
||||
closelog();
|
||||
}
|
||||
Reference in New Issue
Block a user