summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--doc/todo1
-rw-r--r--polyp/modargs.c23
-rw-r--r--polyp/pacat.c53
-rw-r--r--polyp/sample.c29
-rw-r--r--polyp/sample.h6
5 files changed, 76 insertions, 36 deletions
diff --git a/doc/todo b/doc/todo
index 668f54d2..e2cb2fe6 100644
--- a/doc/todo
+++ b/doc/todo
@@ -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