play_cmdline_objs="play.cmdline"
play_errlist_objs="play time fd string"
play_ldflags=""
+write_writers="file"
+
########################################################################### ssl
dnl @synopsis CHECK_SSL
if test "$have_alsa" = "yes"; then
extras="$extras para_play"
play_ldflags="$play_ldflags -lasound"
+ write_writers="$write_writers alsa"
fi
########################################################################### ortp
have_ortp="yes"
AC_DEFINE_UNQUOTED(INIT_PLAY_ERRLISTS,
objlist_to_errlist($play_errlist_objs), errors used by para_play)
+enum="$(for i in $write_writers; do printf "${i}_WRITE, " | tr '[a-z]' '[A-Z]'; done)"
+AC_DEFINE_UNQUOTED(WRITER_ENUM, $enum NUM_SUPPORTED_WRITERS,
+ enum of supported writers)
+names="$(for i in $write_writers; do printf '\"'$i'\", ' ; done)"
+AC_DEFINE_UNQUOTED(WRITER_NAMES, $names, supported writer names)
+inits="$(for i in $write_writers; do printf 'extern void '$i'_writer_init(struct writer *); '; done)"
+AC_DEFINE_UNQUOTED(DECLARE_WRITER_INITS, $inits, init functions of the supported writers)
+array="$(for i in $write_writers; do printf '{.init = '$i'_writer_init},'; done)"
+AC_DEFINE_UNQUOTED(WRITER_ARRAY, $array, array of supported writers)
+
gui_cmdline_objs="gui.cmdline"
gui_errlist_objs="exec close_on_fork signal string stat ringbuffer fd"
gui_other_objs="gui gui_common gui_theme"
#include "string.h"
#include "error.h"
-#define FORMAT SND_PCM_FORMAT_S16_LE
-
-struct private_alsa_data {
- snd_pcm_t *handle;
- size_t bytes_per_frame;
-};
-
+/*
+files:
+~~~~~~
+write.c
+write.h wr
+write_common.c
+write_common.h: decratation of the wng funcs
+alsa_writer.c
+*/
+
+/* write.h */
+enum writer_enum {WRITER_ENUM};
+
+/* write.h */
struct writer_node {
struct writer *writer;
void *private_data;
int chunk_bytes;
};
+/* write.h */
struct writer {
+ void (*init)(struct writer *w);
int (*open)(struct writer_node *);
int (*write)(char *data, size_t nbytes, struct writer_node *);
void (*close)(struct writer_node *);
void (*shutdown)(struct writer_node *);
};
+/* write.h */
struct writer_node_group {
unsigned num_writers;
struct writer_node *writer_nodes;
int eof;
};
-
+/* write.h */
#define FOR_EACH_WRITER_NODE(i, wng) for (i = 0; i < (wng)->num_writers; i++)
+#define FOR_EACH_WRITER(i) for (i = 0; i < NUM_SUPPORTED_WRITERS; i++)
-#define NUM_WRITERS 1
-static struct writer writers[NUM_WRITERS];
-#define FOR_EACH_WRITER(i) for (i = 0; i < NUM_WRITERS, i++)
+DECLARE_WRITER_INITS;
+/* write.c */
static unsigned char *audiobuf;
static struct timeval *start_time;
static struct gengetopt_args_info conf;
+/* write.c */
INIT_PLAY_ERRLISTS;
+/* write.c */
void para_log(int ll, const char* fmt,...)
{
va_list argp;
va_end(argp);
}
+/* write.c */
/**
* read WAV_HEADER_LEN bytes from stdin to audio buffer
*
return 1;
}
+/* alsa_writer.c */
+#define FORMAT SND_PCM_FORMAT_S16_LE
+struct private_alsa_data {
+ snd_pcm_t *handle;
+ size_t bytes_per_frame;
+};
+
/*
* open and prepare the PCM handle for writing
*
return period_size * pad->bytes_per_frame;
}
+/* alsa_writer.c */
/**
* push out pcm frames
* \param data pointer do data to be written
return result * pad->bytes_per_frame;
}
+/* alsa_writer.c */
static void alsa_close(struct writer_node *wn)
{
struct private_alsa_data *pad = wn->private_data;
free(pad);
}
+/* alsa_writer.c */
void alsa_writer_init(struct writer *w)
{
w->open = alsa_open;
}
+
+
+/* file_writer.c */
+
+struct private_file_writer_data {
+ int fd;
+};
+static int file_writer_open(struct writer_node *w)
+{
+ struct private_file_writer_data *pfwd = para_calloc(
+ sizeof(struct private_file_writer_data));
+ char *tmp = para_tmpname(), *home = para_homedir(),
+ *filename = make_message("%s/.paraslash/%s", home, tmp);
+
+ free(home);
+ free(tmp);
+ w->private_data = pfwd;
+ pfwd->fd = open(filename, O_WRONLY | O_CREAT, S_IRUSR | S_IWUSR);
+ free(filename);
+ if (pfwd->fd >= 0)
+ return 8192;
+ free(pfwd);
+ return -E_FW_OPEN;
+}
+
+static int file_writer_write(char *data, size_t nbytes, struct writer_node *wn)
+{
+ struct private_file_writer_data *pfwd = wn->private_data;
+ int ret = write(pfwd->fd, data, nbytes);
+ if (ret < 0)
+ ret = -E_FW_WRITE;
+ return ret;
+}
+
+static void file_writer_close(struct writer_node *wn)
+{
+ struct private_file_writer_data *pfwd = wn->private_data;
+ close(pfwd->fd);
+ free(pfwd);
+}
+
+void file_writer_init(struct writer *w)
+{
+ w->open = file_writer_open;
+ w->write = file_writer_write;
+ w->close = file_writer_close;
+ w->shutdown = NULL; /* nothing to do */
+}
+
+
+/* write.c */
/**
* check if current time is later than start_time
* \param diff pointer to write remaining time to
return tv_diff(start_time, &now, diff) > 0? 1 : 0;
}
+/* write.c */
/**
* sleep until time given at command line
*
while (start_time_in_future(delay));
}
+/* write.c */
static int read_stdin(char *buf, size_t bytes_to_load, size_t *loaded)
{
ssize_t ret;
return 1;
}
+/* write_common.c */
+
+const char *writer_names[] ={WRITER_NAMES};
+static struct writer writers[NUM_SUPPORTED_WRITERS] = {WRITER_ARRAY};
+
int wng_write(struct writer_node_group *g, char *buf, size_t *loaded)
{
int ret, i, need_more_writes = 1;
return ret;
}
+/* write_common.c */
int wng_open(struct writer_node_group *g)
{
int i, ret = 1;
return ret;
}
+/* write_common.c */
void wng_close(struct writer_node_group *g)
{
int i;
}
}
+/* write.c */
/**
* play raw pcm data
* \param loaded number of bytes already loaded
return ret;
}
+/* writer_node.c */
struct writer_node_group *wng_new(unsigned num_writers)
{
struct writer_node_group *g = para_calloc(sizeof(struct writer_node_group));
return g;
}
+/* writer_node.c */
void wng_destroy(struct writer_node_group *g)
{
if (!g)
free(g);
}
+void init_supported_writers(void)
+{
+ int i;
+
+ FOR_EACH_WRITER(i)
+ writers[i].init(&writers[i]);
+}
+
+int check_writer_arg(const char *arg)
+{
+ int i, ret = -E_PLAY_SYNTAX;
+ char *a = para_strdup(arg), *p = strchr(a, ':');
+ if (p)
+ *p = '\0';
+ p++;
+ FOR_EACH_WRITER(i) {
+ if (strcmp(writer_names[i], a))
+ continue;
+ ret = i;
+ goto out;
+ }
+out:
+ free(a);
+ return ret;
+}
+
+struct writer_node_group *setup_default_wng(void)
+{
+ struct writer_node_group *wng = wng_new(1);
+ enum writer_enum default_writer;
+
+ if (NUM_SUPPORTED_WRITERS == 1)
+ default_writer = FILE_WRITE;
+ else
+ default_writer = 1;
+ wng->writer_nodes[0].writer = &writers[default_writer];
+ PARA_INFO_LOG("using default writer: %s\n",
+ writer_names[default_writer]);
+ return wng;
+}
+
+/* write.c */
+
+struct writer_node_group *check_args(void)
+{
+ int i, ret = -E_PLAY_SYNTAX;
+ static struct timeval tv;
+ struct writer_node_group *wng = NULL;
+
+ if (conf.list_writers_given) {
+ char *msg = NULL;
+ FOR_EACH_WRITER(i) {
+ char *tmp = make_message("%s%s%s",
+ i? msg : "",
+ i? " " : "",
+ writer_names[i]);
+ free(msg);
+ msg = tmp;
+ }
+ fprintf(stderr, "%s\n", msg);
+ free(msg);
+ exit(EXIT_SUCCESS);
+ }
+ if (conf.prebuffer_arg < 0 || conf.prebuffer_arg > 100)
+ goto out;
+ if (conf.start_time_given) {
+ long unsigned sec, usec;
+ if (sscanf(conf.start_time_arg, "%lu:%lu",
+ &sec, &usec) != 2)
+ goto out;
+ tv.tv_sec = sec;
+ tv.tv_usec = usec;
+ start_time = &tv;
+ }
+ if (!conf.writer_given) {
+ wng = setup_default_wng();
+ ret = 1;
+ goto out;
+ }
+ wng = wng_new(conf.writer_given);
+ for (i = 0; i < conf.writer_given; i++) {
+ ret = check_writer_arg(conf.writer_arg[i]);
+ if (ret < 0)
+ goto out;
+ wng->writer_nodes[i].writer = &writers[ret];
+ }
+ ret = 1;
+out:
+ if (ret > 0)
+ return wng;
+ free(wng);
+ return NULL;
+}
+
/**
* test if audio buffer contains a valid wave header
*
return 0;
}
+/* write.c */
int main(int argc, char *argv[])
{
- struct timeval tv;
int ret = -E_PLAY_SYNTAX;
struct writer_node_group *wng = NULL;
cmdline_parser(argc, argv, &conf);
- if (conf.prebuffer_arg < 0 || conf.prebuffer_arg > 100)
+ wng = check_args();
+ if (!wng)
goto out;
- if (conf.start_time_given) {
- if (sscanf(conf.start_time_arg, "%lu:%lu",
- &tv.tv_sec, &tv.tv_usec) != 2)
- goto out;
- start_time = &tv;
- }
- /* call init for each supported writer */
- alsa_writer_init(&writers[0]);
-
- wng = wng_new(1);
- wng->writer_nodes[0].writer = &writers[0]; /* alsa */
-
+ init_supported_writers();
audiobuf = para_malloc(WAV_HEADER_LEN);
ret = read_wav_header();
if (ret < 0)