/*
- * Copyright (C) 2011-2013 Andre Noll <maan@systemlinux.org>
+ * Copyright (C) 2011 Andre Noll <maan@tuebingen.mpg.de>
*
* Licensed under the GPL v2. For licencing details see COPYING.
*/
#include <regex.h>
#include <sys/types.h>
-#include <stdbool.h>
+#include <lopsub.h>
+#include "recv_cmd.lsg.h"
#include "para.h"
#include "error.h"
#include "list.h"
#include "sched.h"
-#include "ggo.h"
#include "buffer_tree.h"
#include "recv.h"
-#include "afh_recv.cmdline.h"
#include "string.h"
#include "fd.h"
#include "afh.h"
long unsigned last_chunk;
struct timeval stream_start;
uint32_t current_chunk;
+ void *afh_context;
};
static int afh_execute(struct btr_node *btrn, const char *cmd, char **result)
*result = NULL;
if (!strcmp(cmd, "seconds_total")) {
- *result = make_message("%lu", pard->afhi.seconds_total);
+ *result = make_message("%" PRIu32, pard->afhi.seconds_total);
return 1;
}
if (!strcmp(cmd, "chunks_total")) {
- *result = make_message("%lu", pard->afhi.chunks_total);
+ *result = make_message("%" PRIu32, pard->afhi.chunks_total);
return 1;
}
if (!strcmp(cmd, "afhi")) {
return ret;
if (x >= pard->afhi.chunks_total)
return -ERRNO_TO_PARA_ERROR(EINVAL);
- pard->first_chunk = pard->current_chunk = x;
- rn->task.error = 0;
+ pard->first_chunk = afh_get_start_chunk(x, &pard->afhi,
+ pard->audio_format_num);
+ pard->current_chunk = pard->first_chunk;
return 1;
}
return -E_BTR_NAVAIL;
}
-static void *afh_recv_parse_config(int argc, char **argv)
-{
- struct afh_recv_args_info *tmp = para_calloc(sizeof(*tmp));
-
- if (!afh_recv_cmdline_parser(argc, argv, tmp))
- return tmp;
- free(tmp);
- return NULL;
-}
-
-static void afh_recv_free_config(void *conf)
-{
- if (!conf)
- return;
- afh_recv_cmdline_parser_free(conf);
- free(conf);
-}
-
static int afh_recv_open(struct receiver_node *rn)
{
- struct afh_recv_args_info *conf = rn->conf;
+ struct lls_parse_result *lpr = rn->lpr;
struct private_afh_recv_data *pard;
struct afh_info *afhi;
- char *filename = conf->filename_arg;
-
+ const char *fn = RECV_CMD_OPT_STRING_VAL(AFH, FILENAME, lpr);
+ int32_t bc = RECV_CMD_OPT_INT32_VAL(AFH, BEGIN_CHUNK, lpr);
+ const struct lls_opt_result *r_e = RECV_CMD_OPT_RESULT(AFH, END_CHUNK, lpr);
int ret;
- if (!filename || *filename == '\0')
+ if (!fn || *fn == '\0')
return -E_AFH_RECV_BAD_FILENAME;
rn->private_data = pard = para_calloc(sizeof(*pard));
afhi = &pard->afhi;
- ret = mmap_full_file(filename, O_RDONLY, &pard->map,
+ ret = mmap_full_file(fn, O_RDONLY, &pard->map,
&pard->map_size, &pard->fd);
if (ret < 0)
goto out;
- ret = compute_afhi(filename, pard->map, pard->map_size,
+ ret = compute_afhi(fn, pard->map, pard->map_size,
pard->fd, afhi);
if (ret < 0)
goto out_unmap;
ret = -ERRNO_TO_PARA_ERROR(EINVAL);
if (afhi->chunks_total == 0)
goto out_clear_afhi;
- if (PARA_ABS(conf->begin_chunk_arg) >= afhi->chunks_total)
+ if (PARA_ABS(bc) >= afhi->chunks_total)
goto out_clear_afhi;
- if (conf->begin_chunk_arg >= 0)
- pard->first_chunk = conf->begin_chunk_arg;
+ if (bc >= 0)
+ pard->first_chunk = afh_get_start_chunk(bc, &pard->afhi,
+ pard->audio_format_num);
else
- pard->first_chunk = afhi->chunks_total + conf->begin_chunk_arg;
- if (conf->end_chunk_given) {
+ pard->first_chunk = afh_get_start_chunk(afhi->chunks_total + bc,
+ &pard->afhi, pard->audio_format_num);
+ if (lls_opt_given(r_e)) {
+ int32_t ec = lls_int32_val(0, r_e);
ret = -ERRNO_TO_PARA_ERROR(EINVAL);
- if (PARA_ABS(conf->end_chunk_arg) > afhi->chunks_total)
+ if (PARA_ABS(ec) > afhi->chunks_total)
goto out_clear_afhi;
- if (conf->end_chunk_arg >= 0)
- pard->last_chunk = conf->end_chunk_arg;
+ if (ec >= 0)
+ pard->last_chunk = ec;
else
- pard->last_chunk = afhi->chunks_total + conf->end_chunk_arg;
+ pard->last_chunk = afhi->chunks_total + ec;
} else
pard->last_chunk = afhi->chunks_total - 1;
ret = -ERRNO_TO_PARA_ERROR(EINVAL);
clear_afhi(&pard->afhi);
para_munmap(pard->map, pard->map_size);
close(pard->fd);
+ afh_close(pard->afh_context, pard->audio_format_num);
freep(&rn->private_data);
}
-static void afh_recv_pre_select(struct sched *s, struct task *t)
+static void afh_recv_pre_select(struct sched *s, void *context)
{
- struct receiver_node *rn = container_of(t, struct receiver_node, task);
+ struct receiver_node *rn = context;
struct private_afh_recv_data *pard = rn->private_data;
struct afh_info *afhi = &pard->afhi;
- struct afh_recv_args_info *conf = rn->conf;
+ struct lls_parse_result *lpr = rn->lpr;
struct timeval chunk_time;
- int state = generic_recv_pre_select(s, t);
+ int state = generic_recv_pre_select(s, rn);
+ unsigned j_given = RECV_CMD_OPT_GIVEN(AFH, JUST_IN_TIME, lpr);
if (state <= 0)
return;
- if (!conf->just_in_time_given) {
+ if (!j_given) {
sched_min_delay(s);
return;
}
sched_request_barrier_or_min_delay(&chunk_time, s);
}
-static int afh_recv_post_select(__a_unused struct sched *s, struct task *t)
+static int afh_recv_post_select(__a_unused struct sched *s, void *context)
{
- struct receiver_node *rn = container_of(t, struct receiver_node, task);
- struct afh_recv_args_info *conf = rn->conf;
+ struct receiver_node *rn = context;
+ struct lls_parse_result *lpr = rn->lpr;
struct private_afh_recv_data *pard = rn->private_data;
struct btr_node *btrn = rn->btrn;
struct afh_info *afhi = &pard->afhi;
int ret;
char *buf;
- const char *start, *end;
+ const char *start;
size_t size;
struct timeval chunk_time;
+ unsigned j_given = RECV_CMD_OPT_GIVEN(AFH, JUST_IN_TIME, lpr);
+ unsigned H_given = RECV_CMD_OPT_GIVEN(AFH, NO_HEADER, lpr);
ret = btr_node_status(btrn, 0, BTR_NT_ROOT);
if (ret <= 0)
goto out;
- if (pard->first_chunk > 0 && !conf->no_header_given) {
+ if (pard->first_chunk > 0 && !H_given) {
char *header;
afh_get_header(afhi, pard->audio_format_num, pard->map,
pard->map_size, &header, &size);
afh_free_header(header, pard->audio_format_num);
}
}
- if (!conf->just_in_time_given) {
- afh_get_chunk(pard->first_chunk, afhi, pard->map, &start, &size);
- afh_get_chunk(pard->last_chunk, afhi, pard->map, &end, &size);
- end += size;
- PARA_INFO_LOG("adding %zu bytes\n", end - start);
- btr_add_output_dont_free(start, end - start, btrn);
+ if (!j_given) {
+ long unsigned n;
+ for (n = pard->first_chunk; n < pard->last_chunk; n++) {
+ ret = afh_get_chunk(n, afhi, pard->audio_format_num,
+ pard->map, pard->map_size, &start, &size,
+ &pard->afh_context);
+ if (ret < 0)
+ goto out;
+ PARA_INFO_LOG("adding %zu bytes\n", size);
+ btr_add_output_dont_free(start, size, btrn);
+ }
ret = -E_RECV_EOF;
goto out;
}
if (ret > 0)
goto out;
}
- afh_get_chunk(pard->current_chunk, afhi, pard->map, &start, &size);
+ ret = afh_get_chunk(pard->current_chunk, afhi,
+ pard->audio_format_num, pard->map,
+ pard->map_size, &start, &size,
+ &pard->afh_context);
+ if (ret < 0)
+ goto out;
PARA_DEBUG_LOG("adding chunk %u\n", pard->current_chunk);
btr_add_output_dont_free(start, size, btrn);
if (pard->current_chunk >= pard->last_chunk) {
return ret;
}
-/**
- * The init function of the afh receiver.
- *
- * \param r Pointer to the receiver struct to initialize.
- *
- * This initializes all function pointers of \a r.
- */
-void afh_recv_init(struct receiver *r)
-{
- struct afh_recv_args_info dummy;
-
- afh_init();
- afh_recv_cmdline_parser_init(&dummy);
- r->open = afh_recv_open;
- r->close = afh_recv_close;
- r->pre_select = afh_recv_pre_select;
- r->post_select = afh_recv_post_select;
- r->parse_config = afh_recv_parse_config;
- r->free_config = afh_recv_free_config;
- r->execute = afh_execute;
- r->help = (struct ggo_help) {
- .short_help = afh_recv_args_info_help,
- .detailed_help = afh_recv_args_info_detailed_help
- };
- afh_recv_cmdline_parser_free(&dummy);
-}
+/** See \ref recv_init(). */
+const struct receiver lsg_recv_cmd_com_afh_user_data = {
+ .init = afh_init,
+ .open = afh_recv_open,
+ .close = afh_recv_close,
+ .pre_select = afh_recv_pre_select,
+ .post_select = afh_recv_post_select,
+ .execute = afh_execute,
+};