#include "afs.h"
#include "net.h"
#include "server.h"
+#include "daemon.h"
#include "ipc.h"
#include "list.h"
#include "sched.h"
#include "sideband.h"
#include "command.h"
-/** The osl tables used by afs. \sa \ref blob.c. */
-enum afs_table_num {
- /** Contains audio file information. See \ref aft.c. */
- TBLNUM_AUDIO_FILES,
- /** The table for the paraslash attributes. See \ref attribute.c. */
- TBLNUM_ATTRIBUTES,
- /*
- * Moods and playlists organize the current set of admissible files in
- * an osl table which contains only volatile columns. Each row consists
- * of a pointer to an audio file and the score value of this file.
- */
- TBLNUM_SCORES,
- /**
- * A standard blob table containing the mood definitions. For details
- * see \ref mood.c.
- */
- TBLNUM_MOODS,
- /** A blob table containing lyrics on a per-song basis. */
- TBLNUM_LYRICS,
- /** Another blob table for images (for example album cover art). */
- TBLNUM_IMAGES,
- /** Yet another blob table for storing standard playlists. */
- TBLNUM_PLAYLIST,
- /** How many tables are in use? */
- NUM_AFS_TABLES
+static struct afs_table afs_tables[] = {
+ {.init = aft_init, .name = "audio_files"},
+ {.init = attribute_init, .name = "attributes"},
+ {.init = score_init, .name = "scores"},
+ {.init = moods_init, .name = "moods"},
+ {.init = lyrics_init, .name = "lyrics"},
+ {.init = images_init, .name = "images"},
+ {.init = playlists_init, .name = "playlists"},
};
-static struct afs_table afs_tables[NUM_AFS_TABLES] = {
- [TBLNUM_AUDIO_FILES] = {.init = aft_init, .name = "audio_files"},
- [TBLNUM_ATTRIBUTES] = {.init = attribute_init, .name = "attributes"},
- [TBLNUM_SCORES] = {.init = score_init, .name = "scores"},
- [TBLNUM_MOODS] = {.init = moods_init, .name = "moods"},
- [TBLNUM_LYRICS] = {.init = lyrics_init, .name = "lyrics"},
- [TBLNUM_IMAGES] = {.init = images_init, .name = "images"},
- [TBLNUM_PLAYLIST] = {.init = playlists_init, .name = "playlists"},
-};
+#define NUM_AFS_TABLES ARRAY_SIZE(afs_tables)
struct command_task {
/** The file descriptor for the local socket. */
}
} else {
if (!strncmp(arg, "p/", 2)) {
- ret = playlist_open(arg + 2);
- if (ret < 0 && errmsg)
- *errmsg = make_message( "could not open %s",
- arg);
+ ret = playlist_open(arg + 2, errmsg);
mode = PLAY_MODE_PLAYLIST;
} else if (!strncmp(arg, "m/", 2)) {
ret = change_current_mood(arg + 2, errmsg);
*/
if (arg != current_mop) {
free(current_mop);
- if (arg) {
- current_mop = para_strdup(arg);
- mutex_lock(mmd_mutex);
- strncpy(mmd->afs_mode_string, arg,
- sizeof(mmd->afs_mode_string));
- mmd->afs_mode_string[sizeof(mmd->afs_mode_string) - 1] = '\0';
- mmd->events++;
- mutex_unlock(mmd_mutex);
- } else {
- mutex_lock(mmd_mutex);
- strcpy(mmd->afs_mode_string, "dummy");
- mmd->events++;
- mutex_unlock(mmd_mutex);
- current_mop = NULL;
- }
+ current_mop = arg? para_strdup(arg) : NULL;
}
+ /* Notify the server about the mood/playlist change. */
+ mutex_lock(mmd_mutex);
+ strncpy(mmd->afs_mode_string, arg? arg: "dummy",
+ sizeof(mmd->afs_mode_string));
+ mmd->afs_mode_string[sizeof(mmd->afs_mode_string) - 1] = '\0';
+ mmd->events++;
+ mutex_unlock(mmd_mutex);
return 1;
}
int i, ret;
get_database_dir();
- PARA_NOTICE_LOG("opening %d osl tables in %s\n", NUM_AFS_TABLES,
+ PARA_NOTICE_LOG("opening %zu osl tables in %s\n", NUM_AFS_TABLES,
database_dir);
for (i = 0; i < NUM_AFS_TABLES; i++) {
ret = afs_tables[i].open(database_dir);
return ret;
}
-static int afs_signal_post_select(struct sched *s, __a_unused void *context)
+static int afs_signal_post_monitor(struct sched *s, __a_unused void *context)
{
int signum, ret;
PARA_EMERG_LOG("para_server died\n");
goto shutdown;
}
- signum = para_next_signal(&s->rfds);
+ signum = para_next_signal();
if (signum == 0)
return 0;
if (signum == SIGHUP) {
signal_task->task = task_register(&(struct task_info) {
.name = "signal",
- .pre_select = signal_pre_select,
- .post_select = afs_signal_post_select,
+ .pre_monitor = signal_pre_monitor,
+ .post_monitor = afs_signal_post_monitor,
.context = signal_task,
}, s);
struct timeval connect_time;
};
-static void command_pre_select(struct sched *s, void *context)
+static void command_pre_monitor(struct sched *s, void *context)
{
struct command_task *ct = context;
struct afs_client *client;
- para_fd_set(server_socket, &s->rfds, &s->max_fileno);
- para_fd_set(ct->fd, &s->rfds, &s->max_fileno);
+ sched_monitor_readfd(server_socket, s);
+ sched_monitor_readfd(ct->fd, s);
list_for_each_entry(client, &afs_client_list, node)
- para_fd_set(client->fd, &s->rfds, &s->max_fileno);
+ sched_monitor_readfd(client->fd, s);
}
/**
return ret;
}
-static int execute_server_command(fd_set *rfds)
+static int execute_server_command(void)
{
char buf[8];
size_t n;
- int ret = read_nonblock(server_socket, buf, sizeof(buf) - 1, rfds, &n);
+ int ret = read_nonblock(server_socket, buf, sizeof(buf) - 1, &n);
if (ret < 0 || n == 0)
return ret;
}
/* returns 0 if no data available, 1 else */
-static int execute_afs_command(int fd, fd_set *rfds)
+static int execute_afs_command(int fd)
{
uint32_t cookie;
int query_shmid;
char buf[sizeof(cookie) + sizeof(query_shmid)];
size_t n;
- int ret = read_nonblock(fd, buf, sizeof(buf), rfds, &n);
+ int ret = read_nonblock(fd, buf, sizeof(buf), &n);
if (ret < 0)
goto err;
/** Shutdown connection if query has not arrived until this many seconds. */
#define AFS_CLIENT_TIMEOUT 3
-static int command_post_select(struct sched *s, void *context)
+static int command_post_monitor(struct sched *s, void *context)
{
struct command_task *ct = context;
struct sockaddr_un unix_addr;
ret = task_get_notification(ct->task);
if (ret < 0)
return ret;
- ret = execute_server_command(&s->rfds);
+ ret = execute_server_command();
if (ret < 0) {
PARA_EMERG_LOG("%s\n", para_strerror(-ret));
task_notify_all(s, -ret);
}
/* Check the list of connected clients. */
list_for_each_entry_safe(client, tmp, &afs_client_list, node) {
- ret = execute_afs_command(client->fd, &s->rfds);
+ ret = execute_afs_command(client->fd);
if (ret == 0) { /* prevent bogus connection flooding */
struct timeval diff;
tv_diff(now, &client->connect_time, &diff);
free(client);
}
/* Accept connections on the local socket. */
- ret = para_accept(ct->fd, &s->rfds, &unix_addr, sizeof(unix_addr), &fd);
+ ret = para_accept(ct->fd, &unix_addr, sizeof(unix_addr), &fd);
if (ret < 0)
PARA_NOTICE_LOG("%s\n", para_strerror(-ret));
if (ret <= 0)
close(fd);
return 0;
}
- client = para_malloc(sizeof(*client));
+ client = alloc(sizeof(*client));
client->fd = fd;
client->connect_time = *now;
para_list_add(&client->node, &afs_client_list);
ct->task = task_register(&(struct task_info) {
.name = "afs command",
- .pre_select = command_pre_select,
- .post_select = command_post_select,
+ .pre_monitor = command_pre_monitor,
+ .post_monitor = command_post_monitor,
.context = ct,
}, s);
}
+static int afs_poll(struct pollfd *fds, nfds_t nfds, int timeout)
+{
+ mutex_lock(mmd_mutex);
+ daemon_set_loglevel(mmd->loglevel);
+ mutex_unlock(mmd_mutex);
+ return xpoll(fds, nfds, timeout);
+}
+
/**
* Initialize the audio file selector process.
*
init_admissible_files(OPT_STRING_VAL(AFS_INITIAL_MODE));
register_command_task(&s);
s.default_timeout = 1000;
+ s.poll_function = afs_poll;
ret = write(socket_fd, "\0", 1);
if (ret != 1) {
if (ret == 0)