#include <fnmatch.h>
#include "afh.h"
#include "afs.h"
+#include "net.h"
#include "string.h"
-
-int mp3_get_file_info(char *map, size_t numbytes,
- struct audio_format_info *afi); /* FXIME */
+#include "vss.h"
#define AFS_AUDIO_FILE_DIR "/home/mp3"
-static void *audio_file_table;
+static struct osl_table *audio_file_table;
/**
- * Describes the structure of the mmapped-afs info struct.
+ * Describes the layout of the mmapped-afs info struct.
*
* \sa struct afs_info.
*/
*/
void save_afsi(struct afs_info *afsi, struct osl_object *obj)
{
- struct afs_info default_afs_info = {
- .last_played = time(NULL) - 365 * 24 * 60 * 60,
- .attributes = 0,
- .num_played = 0,
- .image_id = 0,
- .lyrics_id = 0,
- .audio_format_id = 5, /* FIXME */
- };
char *buf = obj->data;
- if (!afsi)
- afsi = &default_afs_info;
-
write_u64(buf + AFSI_LAST_PLAYED_OFFSET, afsi->last_played);
write_u64(buf + AFSI_ATTRIBUTES_OFFSET, afsi->attributes);
write_u32(buf + AFSI_NUM_PLAYED_OFFSET, afsi->num_played);
}
};
-static const struct osl_table_description audio_file_table_desc = {
- .dir = DATABASE_DIR,
+static struct osl_table_description audio_file_table_desc = {
.name = "audio_files",
.num_columns = NUM_AFT_COLUMNS,
.flags = OSL_LARGE_TABLE,
int aft_get_row_of_path(char *path, struct osl_row **row)
{
struct osl_object obj = {.data = path, .size = strlen(path) + 1};
+
+ PARA_NOTICE_LOG("audio_file_table: %p\n", audio_file_table);
return osl_get_row(audio_file_table, AFTCOL_PATH, &obj, row);
}
w->image_id_width, afsi->image_id,
w->lyrics_id_width, afsi->lyrics_id,
w->bitrate_width, afhi->bitrate,
- "mp3", /* FIXME */
+ audio_format_name(afsi->audio_format_id),
w->frequency_width, afhi->frequency,
afhi->channels,
duration_buf,
image_line,
lyrics_line,
afhi->bitrate,
- "mp3", /* FIXME */
+ audio_format_name(afsi->audio_format_id),
afhi->frequency,
afhi->channels,
duration_buf,
* full list: list everything, including afsi, afhi, atts as clear text
*
* */
-int com_afs_ls(__a_unused int fd, int argc, const char **argv)
+int com_afs_ls(int fd, int argc, char * const * const argv)
{
int i, ret;
unsigned flags = 0;
ret = send_option_arg_callback_request(&query, opts.num_patterns,
argv + i, com_ls_callback, &ls_output);
if (ret >= 0 && ls_output.data) {
- printf("%s\n", (char *)ls_output.data);
+ send_buffer(fd, (char *)ls_output.data);
free(ls_output.data);
}
return ret;
func);
}
-static void *find_hash_sister(HASH_TYPE *hash)
+static struct osl_row *find_hash_sister(HASH_TYPE *hash)
{
const struct osl_object obj = {.data = hash, .size = HASH_SIZE};
struct osl_row *row;
return row;
}
-#define AFTROW_HEADER_SIZE 4
-
enum aft_row_offsets {
AFTROW_AFHI_OFFSET_POS = 0,
AFTROW_CHUNKS_OFFSET_POS = 2,
- AFTROW_HASH_OFFSET = AFTROW_HEADER_SIZE,
- AFTROW_FLAGS_OFFSET = (AFTROW_HASH_OFFSET + HASH_SIZE),
- AFTROW_PATH_OFFSET = (AFTROW_FLAGS_OFFSET + 4)
+ AFTROW_AUDIO_FORMAT_OFFSET = 4,
+ AFTROW_FLAGS_OFFSET = 5,
+ AFTROW_HASH_OFFSET = 9,
+ AFTROW_PATH_OFFSET = (AFTROW_HASH_OFFSET + HASH_SIZE),
};
/* never save the afsi, as the server knows it too. Note that afhi might be NULL.
* In this case, afhi won't be stored in the buffer */
static void save_audio_file_info(HASH_TYPE *hash, const char *path,
- struct audio_format_info *afhi,
- uint32_t flags, struct osl_object *obj)
+ struct audio_format_info *afhi, uint32_t flags,
+ uint8_t audio_format_num, struct osl_object *obj)
{
size_t path_len = strlen(path) + 1;
size_t afhi_size = sizeof_afhi_buf(afhi);
char *buf = para_malloc(size);
uint16_t pos;
- memcpy(buf + AFTROW_HASH_OFFSET, hash, HASH_SIZE);
+ write_u8(buf + AFTROW_AUDIO_FORMAT_OFFSET, audio_format_num);
write_u32(buf + AFTROW_FLAGS_OFFSET, flags);
+
+ memcpy(buf + AFTROW_HASH_OFFSET, hash, HASH_SIZE);
strcpy(buf + AFTROW_PATH_OFFSET, path);
pos = AFTROW_PATH_OFFSET + path_len;
PARA_DEBUG_LOG("size: %zu, afhi starts at %d\n", size, pos);
- PARA_DEBUG_LOG("last afhi byte: %p, pos %d\n", buf + pos + afhi_size - 1,
+ PARA_DEBUG_LOG("last afhi byte: %p, pos %zu\n", buf + pos + afhi_size - 1,
pos + afhi_size - 1);
write_u16(buf + AFTROW_AFHI_OFFSET_POS, pos);
save_afhi(afhi, buf + pos);
#define ADD_FLAG_FORCE 2
#define ADD_FLAG_VERBOSE 4
+/* TODO: change log messages so that they get written to the result buffer */
+
static int com_add_callback(const struct osl_object *query,
__a_unused struct osl_object *result)
{
int ret;
char afsi_buf[AFSI_SIZE];
uint32_t flags = read_u32(buf + AFTROW_FLAGS_OFFSET);
+ struct afs_info default_afsi = {.last_played = 0};
hash = (HASH_TYPE *)buf + AFTROW_HASH_OFFSET;
hash_to_asc(hash, asc);;
return ret;
}
/* new entry, use default afsi */
+ default_afsi.last_played = time(NULL) - 365 * 24 * 60 * 60;
+ default_afsi.audio_format_id = read_u8(buf + AFTROW_AUDIO_FORMAT_OFFSET);
+
if (flags & ADD_FLAG_VERBOSE)
PARA_NOTICE_LOG("adding %s\n", path);
objs[AFTCOL_AFSI].data = &afsi_buf;
objs[AFTCOL_AFSI].size = AFSI_SIZE;
- save_afsi(NULL, &objs[AFTCOL_AFSI]);
+ save_afsi(&default_afsi, &objs[AFTCOL_AFSI]);
ret = osl_add_and_get_row(audio_file_table, objs, &aft_row);
if (ret < 0)
return ret;
uint32_t flags;
};
+static int path_brother_callback(const struct osl_object *query,
+ struct osl_object *result)
+{
+ char *path = query->data;
+ struct osl_row *path_brother;
+ int ret = aft_get_row_of_path(path, &path_brother);
+ if (ret < 0)
+ return ret;
+ result->data = para_malloc(sizeof(path_brother));
+ result->size = sizeof(path_brother);
+ *(struct osl_row **)(result->data) = path_brother;
+ return 1;
+}
+
+static int hash_sister_callback(const struct osl_object *query,
+ struct osl_object *result)
+{
+ HASH_TYPE *hash = query->data;
+ struct osl_row *hash_sister;
+
+ hash_sister = find_hash_sister(hash);
+ if (!hash_sister)
+ return -E_RB_KEY_NOT_FOUND;
+ result->data = para_malloc(sizeof(hash_sister));
+ result->size = sizeof(hash_sister);
+ *(struct osl_row **)(result->data) = hash_sister;
+ return 1;
+}
+
+
static int add_one_audio_file(const char *arg, const void *private_data)
{
int ret;
+ uint8_t format_num = -1;
const struct private_add_data *pad = private_data;
struct audio_format_info afhi, *afhi_ptr = NULL;
- struct osl_row *pb, *hs; /* path brother/hash sister */
- struct osl_object map, obj = {.data = NULL};
+ struct osl_row *pb = NULL, *hs = NULL; /* path brother/hash sister */
+ struct osl_object map, obj, query, result;
char *path;
HASH_TYPE hash[HASH_SIZE];
ret = verify_path(arg, &path);
if (ret < 0)
return ret;
- ret = aft_get_row_of_path(path, &pb);
+ query.data = path;
+ query.size = strlen(path) + 1;
+ ret = send_callback_request(path_brother_callback, &query, &result);
if (ret < 0 && ret != -E_RB_KEY_NOT_FOUND)
goto out_free;
+ if (ret >= 0) {
+ pb = *(struct osl_row **)result.data;
+ free(result.data);
+ }
ret = 1;
if (pb && (pad->flags & ADD_FLAG_LAZY)) { /* lazy is really cheap */
if (pad->flags & ADD_FLAG_VERBOSE)
- PARA_NOTICE_LOG("lazy-ignore: %s\n", path);
+ ret = send_va_buffer(pad->fd, "lazy-ignore: %s\n", path);
goto out_free;
}
- /* we still want to add this file. Compute its hash and look it up */
+ /* We still want to add this file. Compute its hash. */
ret = mmap_full_file(path, O_RDONLY, &map);
if (ret < 0)
goto out_free;
hash_function(map.data, map.size, hash);
- hs = find_hash_sister(hash);
- /*
- * return success if we're pretty sure that we already know this file
- */
+
+ /* Check whether database contains file with the same hash. */
+ query.data = hash;
+ query.size = HASH_SIZE;
+ ret = send_callback_request(hash_sister_callback, &query, &result);
+ if (ret < 0 && ret != -E_RB_KEY_NOT_FOUND)
+ goto out_free;
+ if (ret >= 0) {
+ hs = *(struct osl_row **)result.data;
+ free(result.data);
+ }
+ /* Return success if we already know this file. */
ret = 1;
if (pb && hs && hs == pb && (!(pad->flags & ADD_FLAG_FORCE))) {
if (pad->flags & ADD_FLAG_VERBOSE)
- PARA_NOTICE_LOG("not forcing update: %s\n", path);
+ ret = send_va_buffer(pad->fd,
+ "not forcing update: %s\n", path);
goto out_unmap;
}
/*
* there is a hash sister unless in FORCE mode.
*/
if (!hs || (pad->flags & ADD_FLAG_FORCE)) {
- ret = mp3_get_file_info(map.data, map.size, &afhi);
+ ret = compute_afhi(path, map.data, map.size, &afhi);
if (ret < 0) {
- PARA_WARNING_LOG("audio format of %s not recognized, skipping\n", path);
- ret = 1;
+ ret = send_va_buffer(pad->fd,
+ "audio format of %s not recognized\n", path);
goto out_unmap;
}
+ format_num = ret;
afhi_ptr = &afhi;
}
munmap(map.data, map.size);
- save_audio_file_info(hash, path, afhi_ptr, pad->flags, &obj);
- /* ask parent to consider this entry for adding */
+ save_audio_file_info(hash, path, afhi_ptr, pad->flags, format_num, &obj);
+ /* Ask afs to consider this entry for adding. */
ret = send_callback_request(com_add_callback, &obj, NULL);
goto out_free;
return ret;
}
-int com_add(int fd, int argc, const char **argv)
+int com_add(int fd, int argc, char * const * const argv)
{
int i, ret;
struct private_add_data pad = {.fd = fd, .flags = 0};
struct stat statbuf;
+ PARA_NOTICE_LOG("argv[1]: %s\n", argv[1]);
for (i = 1; i < argc; i++) {
const char *arg = argv[i];
if (arg[0] != '-')
return 1;
}
-int com_touch(__a_unused int fd, int argc, const char **argv)
+int com_touch(__a_unused int fd, int argc, char * const * const argv)
{
struct com_touch_options cto = {
.num_played = -1,
*
* */
-int com_afs_rm(__a_unused int fd, int argc, const char **argv)
+int com_afs_rm(__a_unused int fd, int argc, char * const * const argv)
{
struct com_rm_options cro = {.flags = 0};
struct osl_object options = {.data = &cro, .size = sizeof(cro)};
/**
* Open the audio file table.
*
- * \param ti Gets initialized by this function
+ * \param ti Gets initialized by this function.
+ * \param db The database directory.
*
* \return Positive on success, negative on errors.
*
* \sa osl_open_table().
*/
-int aft_init(struct table_info *ti)
+int aft_init(struct table_info *ti, const char *db)
{
int ret;
+ audio_file_table_desc.dir = db;
ti->desc = &audio_file_table_desc;
ret = osl_open_table(ti->desc, &ti->table);
if (ret >= 0) {
PARA_INFO_LOG("audio file table contains %d files\n", num);
return ret;
}
+ PARA_INFO_LOG("failed to open audio file table\n");
audio_file_table = NULL;
return ret == -E_NOENT? 1 : ret;
}