/*
- * Copyright (C) 2007-2009 Andre Noll <maan@systemlinux.org>
+ * Copyright (C) 2007-2011 Andre Noll <maan@systemlinux.org>
*
* Licensed under the GPL v2. For licencing details see COPYING.
*/
/** \file aft.c Audio file table functions. */
+#include <regex.h>
#include <dirent.h> /* readdir() */
#include <openssl/rc4.h>
-
+#include <sys/mman.h>
+#include <fnmatch.h>
+#include <sys/shm.h>
#include <osl.h>
+
#include "para.h"
#include "error.h"
#include "crypt.h"
#include "string.h"
-#include <sys/mman.h>
-#include <fnmatch.h>
-#include <sys/shm.h>
-
#include "afh.h"
#include "afs.h"
#include "net.h"
-#include "vss.h"
#include "fd.h"
#include "ipc.h"
#include "portable_io.h"
*
* \sa osl_compare_func, uint32_compare().
*/
-int aft_hash_compare(const struct osl_object *obj1, const struct osl_object *obj2)
+static int aft_hash_compare(const struct osl_object *obj1, const struct osl_object *obj2)
{
return hash_compare((HASH_TYPE *)obj1->data, (HASH_TYPE *)obj2->data);
}
return 4 * (afhi->chunks_total + 1);
}
-static void save_chunk_table(struct afh_info *afhi, char *buf)
+static uint32_t save_chunk_table(struct afh_info *afhi, char *buf)
{
int i;
-
- for (i = 0; i <= afhi->chunks_total; i++)
- write_u32(buf + 4 * i, afhi->chunk_table[i]);
+ uint32_t max = 0, old = 0;
+
+ for (i = 0; i <= afhi->chunks_total; i++) {
+ uint32_t val = afhi->chunk_table[i];
+ write_u32(buf + 4 * i, val);
+ /*
+ * If the first chunk is the header, do not consider it for the
+ * calculation of the largest chunk size.
+ */
+ if (i == 0 || (i == 1 && afhi->header_len > 0)) {
+ old = val;
+ continue;
+ }
+ max = PARA_MAX(max, val - old);
+ old = val;
+ }
+ return max;
}
static void load_chunk_table(struct afh_info *afhi, char *buf)
*
* \return Standard.
*/
-int aft_get_row_of_hash(HASH_TYPE *hash, struct osl_row **row)
+static int aft_get_row_of_hash(HASH_TYPE *hash, struct osl_row **row)
{
const struct osl_object obj = {.data = hash, .size = HASH_SIZE};
return osl(osl_get_row(audio_file_table, AFTCOL_HASH, &obj, row));
*
* \return Positive on success, negative on errors.
*/
-int get_afsi_object_of_path(const char *path, struct osl_object *obj)
+static int get_afsi_object_of_path(const char *path, struct osl_object *obj)
{
struct osl_row *row;
int ret = aft_get_row_of_path(path, &row);
ret = shm_attach(shmid, ATTACH_RW, &shm_afd);
if (ret < 0)
goto err;
- *(struct audio_file_data *)shm_afd = *afd;
buf = shm_afd;
buf += sizeof(*afd);
- save_chunk_table(&afd->afhi, buf);
+ afd->max_chunk_size = save_chunk_table(&afd->afhi, buf);
+ *(struct audio_file_data *)shm_afd = *afd;
shm_detach(shm_afd);
return shmid;
err:
return ret;
}
+/**
+ * Extract a afd stored in a shared memory area.
+ *
+ * Attach the shared memory area given by \a shmid, load the audio file data
+ * stored therein and detach the area afterwards. Called by vss, after
+ * receiving a positive response to the request for the next audio file.
+ +
+ * \param shmid The identifier of the shared memory area containing the afd.
+ * \param afd Result pointer.
+ *
+ * \return Standard.
+ */
int load_afd(int shmid, struct audio_file_data *afd)
{
void *shm_afd;
ret = get_audio_file_path_of_row(aft_row, &path);
if (ret < 0)
return ret;
+ PARA_NOTICE_LOG("%s\n", path);
ret = get_afsi_object_of_row(aft_row, &afsi_obj);
if (ret < 0)
return ret;
i++;
break;
}
- if (!strncmp(arg, "-n", 2)) {
- ret = para_atoi32(arg + 2, &cto.num_played);
+ if (!strncmp(arg, "-n=", 3)) {
+ ret = para_atoi32(arg + 3, &cto.num_played);
if (ret < 0)
return ret;
continue;
}
- if (!strncmp(arg, "-l", 2)) {
- ret = para_atoi64(arg + 2, &cto.last_played);
+ if (!strncmp(arg, "-l=", 3)) {
+ ret = para_atoi64(arg + 3, &cto.last_played);
if (ret < 0)
return ret;
continue;
}
- if (!strncmp(arg, "-y", 2)) {
- ret = para_atoi32(arg + 2, &cto.lyrics_id);
+ if (!strncmp(arg, "-y=", 3)) {
+ ret = para_atoi32(arg + 3, &cto.lyrics_id);
if (ret < 0)
return ret;
continue;
}
- if (!strncmp(arg, "-i", 2)) {
- ret = para_atoi32(arg + 2, &cto.image_id);
+ if (!strncmp(arg, "-i=", 3)) {
+ ret = para_atoi32(arg + 3, &cto.image_id);
if (ret < 0)
return ret;
continue;
}
- if (!strncmp(arg, "-a", 2)) {
+ if (!strncmp(arg, "-a=", 3)) {
int32_t val;
- ret = para_atoi32(arg + 2, &val);
+ ret = para_atoi32(arg + 3, &val);
if (ret < 0)
return ret;
if (val < 0 || val > 255)
return ret;
}
-void afs_stat_callback(int fd, const struct osl_object *query)
+static void afs_stat_callback(int fd, const struct osl_object *query)
{
int *parser_friendly = query->data;
char *buf = *parser_friendly?
pass_buffer_as_shm(buf, strlen(buf), &fd);
}
+/**
+ * Get the current afs status items from the afs process and send it using RC4.
+ *
+ * \param rc4c The rc4 context for data encryption.
+ * \param parser_friendly Whether parser-friendly output format should be used.
+ *
+ * As the contents of the afs status items change in time and the command
+ * handler only has a COW version created at fork time, it can not send
+ * up-to-date afs status items directly. Therefore the usual callback mechanism
+ * is used to pass the status items from the afs process to the command handler
+ * via a shared memory area and a pipe.
+ */
int send_afs_status(struct rc4_context *rc4c, int parser_friendly)
{
struct osl_object query = {.data = &parser_friendly,
}
}
+/**
+ * Initialize the audio file table.
+ *
+ * \param t Pointer to the structure to be initialized.
+ */
void aft_init(struct afs_table *t)
{
- t->name = audio_file_table_desc.name;
t->open = aft_open;
t->close = aft_close;
t->create = aft_create;