diff options
-rw-r--r-- | doc/todo | 1 | ||||
-rw-r--r-- | polyp/modargs.c | 23 | ||||
-rw-r--r-- | polyp/pacat.c | 53 | ||||
-rw-r--r-- | polyp/sample.c | 29 | ||||
-rw-r--r-- | polyp/sample.h | 6 |
5 files changed, 76 insertions, 36 deletions
@@ -7,7 +7,6 @@ - make mcalign merge chunks - option to use default fragment size on alsa drivers - improve module-oss-mmap latency measurement -- pacat sample type args - filter capture data in client through alignment - add radio module - make autoload list use idxset diff --git a/polyp/modargs.c b/polyp/modargs.c index e1c2c9b8..d58b391b 100644 --- a/polyp/modargs.c +++ b/polyp/modargs.c @@ -263,28 +263,9 @@ int pa_modargs_get_sample_spec(struct pa_modargs *ma, struct pa_sample_spec *rss return -1; ss.channels = (uint8_t) channels; - if ((format = pa_modargs_get_value(ma, "format", NULL))) { - if (strcmp(format, "s16le") == 0) - ss.format = PA_SAMPLE_S16LE; - else if (strcmp(format, "s16be") == 0) - ss.format = PA_SAMPLE_S16BE; - else if (strcmp(format, "s16ne") == 0 || strcmp(format, "s16") == 0 || strcmp(format, "16") == 0) - ss.format = PA_SAMPLE_S16NE; - else if (strcmp(format, "u8") == 0 || strcmp(format, "8") == 0) - ss.format = PA_SAMPLE_U8; - else if (strcmp(format, "float32") == 0 || strcmp(format, "float32ne") == 0) - ss.format = PA_SAMPLE_FLOAT32; - else if (strcmp(format, "float32le") == 0) - ss.format = PA_SAMPLE_FLOAT32LE; - else if (strcmp(format, "float32be") == 0) - ss.format = PA_SAMPLE_FLOAT32BE; - else if (strcmp(format, "ulaw") == 0) - ss.format = PA_SAMPLE_ULAW; - else if (strcmp(format, "alaw") == 0) - ss.format = PA_SAMPLE_ALAW; - else + if ((format = pa_modargs_get_value(ma, "format", NULL))) + if ((ss.format = pa_parse_sample_format(format)) < 0) return -1; - } if (!pa_sample_spec_valid(&ss)) return -1; diff --git a/polyp/pacat.c b/polyp/pacat.c index 67242b26..a2687116 100644 --- a/polyp/pacat.c +++ b/polyp/pacat.c @@ -58,6 +58,12 @@ static char *stream_name = NULL, *client_name = NULL, *device = NULL; static int verbose = 0; static pa_volume_t volume = PA_VOLUME_NORM; +static struct pa_sample_spec sample_spec = { + .format = PA_SAMPLE_S16LE, + .rate = 44100, + .channels = 2 +}; + /* A shortcut for terminating the application */ static void quit(int ret) { assert(mainloop_api); @@ -141,12 +147,6 @@ static void stream_state_callback(struct pa_stream *s, void *userdata) { /* This is called whenever the context status changes */ static void context_state_callback(struct pa_context *c, void *userdata) { - static const struct pa_sample_spec ss = { - .format = PA_SAMPLE_S16LE, - .rate = 44100, - .channels = 2 - }; - assert(c); switch (pa_context_get_state(c)) { @@ -162,7 +162,7 @@ static void context_state_callback(struct pa_context *c, void *userdata) { if (verbose) fprintf(stderr, "Connection established.\n"); - stream = pa_stream_new(c, stream_name, &ss); + stream = pa_stream_new(c, stream_name, &sample_spec); assert(stream); pa_stream_set_state_callback(stream, stream_state_callback, NULL); @@ -335,14 +335,22 @@ static void help(const char *argv0) { " -d, --device=DEVICE The name of the sink/source to connect to\n" " -n, --client-name=NAME How to call this client on the server\n" " --stream-name=NAME How to call this stream on the server\n" - " --volume=VOLUME Specify the initial (linear) volume in range 0...256\n", + " --volume=VOLUME Specify the initial (linear) volume in range 0...256\n" + " --rate=SAMPLERATE The sample rate in Hz (defaults to 44100)\n" + " --format=SAMPLEFORMAT The sample type, one of s16le, s16be, u8, float32le,\n" + " float32be, ulaw, alaw (defaults to s16ne)\n" + " --channels=CHANNELS The number of channels, 1 for mono, 2 for stereo\n" + " (defaults to 2)\n", argv0); } enum { ARG_VERSION = 256, ARG_STREAM_NAME, - ARG_VOLUME + ARG_VOLUME, + ARG_SAMPLERATE, + ARG_SAMPLEFORMAT, + ARG_CHANNELS }; int main(int argc, char *argv[]) { @@ -361,6 +369,9 @@ int main(int argc, char *argv[]) { {"help", 0, NULL, 'h'}, {"verbose", 0, NULL, 'v'}, {"volume", 1, NULL, ARG_VOLUME}, + {"rate", 1, NULL, ARG_SAMPLERATE}, + {"format", 1, NULL, ARG_SAMPLEFORMAT}, + {"channels", 1, NULL, ARG_CHANNELS}, {NULL, 0, NULL, 0} }; @@ -425,6 +436,18 @@ int main(int argc, char *argv[]) { break; } + case ARG_CHANNELS: + sample_spec.channels = atoi(optarg); + break; + + case ARG_SAMPLEFORMAT: + sample_spec.format = pa_parse_sample_format(optarg); + break; + + case ARG_SAMPLERATE: + sample_spec.rate = atoi(optarg); + break; + default: goto quit; } @@ -435,9 +458,17 @@ int main(int argc, char *argv[]) { if (!stream_name) stream_name = strdup(client_name); + + if (!pa_sample_spec_valid(&sample_spec)) { + fprintf(stderr, "Invalid sample specification\n"); + goto quit; + } - if (verbose) - fprintf(stderr, "Opening a %s stream.\n", mode == RECORD ? "recording" : "playback"); + if (verbose) { + char t[PA_SAMPLE_SPEC_SNPRINT_MAX]; + pa_sample_spec_snprint(t, sizeof(t), &sample_spec); + fprintf(stderr, "Opening a %s stream with sample specification '%s'.\n", mode == RECORD ? "recording" : "playback", t); + } /* Set up a new main loop */ if (!(m = pa_mainloop_new())) { diff --git a/polyp/sample.c b/polyp/sample.c index 65ae8ff3..8c30386b 100644 --- a/polyp/sample.c +++ b/polyp/sample.c @@ -26,6 +26,7 @@ #include <stdio.h> #include <assert.h> #include <math.h> +#include <string.h> #include "sample.h" @@ -68,10 +69,10 @@ pa_usec_t pa_bytes_to_usec(uint64_t length, const struct pa_sample_spec *spec) { int pa_sample_spec_valid(const struct pa_sample_spec *spec) { assert(spec); - if (!spec->rate || !spec->channels) + if (spec->rate <= 0 || spec->channels <= 0) return 0; - if (spec->format >= PA_SAMPLE_MAX) + if (spec->format >= PA_SAMPLE_MAX || spec->format < 0) return 0; return 1; @@ -134,3 +135,27 @@ void pa_bytes_snprint(char *s, size_t l, unsigned v) { else snprintf(s, l, "%u B", (unsigned) v); } + +enum pa_sample_format pa_parse_sample_format(const char *format) { + + if (strcmp(format, "s16le") == 0) + return PA_SAMPLE_S16LE; + else if (strcmp(format, "s16be") == 0) + return PA_SAMPLE_S16BE; + else if (strcmp(format, "s16ne") == 0 || strcmp(format, "s16") == 0 || strcmp(format, "16") == 0) + return PA_SAMPLE_S16NE; + else if (strcmp(format, "u8") == 0 || strcmp(format, "8") == 0) + return PA_SAMPLE_U8; + else if (strcmp(format, "float32") == 0 || strcmp(format, "float32ne") == 0) + return PA_SAMPLE_FLOAT32; + else if (strcmp(format, "float32le") == 0) + return PA_SAMPLE_FLOAT32LE; + else if (strcmp(format, "float32be") == 0) + return PA_SAMPLE_FLOAT32BE; + else if (strcmp(format, "ulaw") == 0) + return PA_SAMPLE_ULAW; + else if (strcmp(format, "alaw") == 0) + return PA_SAMPLE_ALAW; + + return -1; +} diff --git a/polyp/sample.h b/polyp/sample.h index 912cdaa0..7e810386 100644 --- a/polyp/sample.h +++ b/polyp/sample.h @@ -42,7 +42,8 @@ enum pa_sample_format { PA_SAMPLE_S16BE, /**< Signed 16 Bit PCM, big endian */ PA_SAMPLE_FLOAT32LE, /**< 32 Bit IEEE floating point, little endian, range -1..1 */ PA_SAMPLE_FLOAT32BE, /**< 32 Bit IEEE floating point, big endian, range -1..1 */ - PA_SAMPLE_MAX /**< Upper limit of valid sample types */ + PA_SAMPLE_MAX, /**< Upper limit of valid sample types */ + PA_SAMPLE_INVALID = -1 /**< An invalid value */ }; #ifdef WORDS_BIGENDIAN @@ -119,6 +120,9 @@ double pa_volume_to_dB(pa_volume_t v); /** Pretty print a byte size value. (i.e. "2.5 MB") */ void pa_bytes_snprint(char *s, size_t l, unsigned v); +/** Parse a sample format text */ +enum pa_sample_format pa_parse_sample_format(const char *format); + PA_C_DECL_END #endif |