This file is part of polypaudio.
polypaudio is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published
+ it under the terms of the GNU Lesser General Public License as published
by the Free Software Foundation; either version 2 of the License,
or (at your option) any later version.
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
- You should have received a copy of the GNU General Public License
+ You should have received a copy of the GNU Lesser General Public License
along with polypaudio; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
USA.
#include <polyp/polyplib-error.h>
#include <polyp/mainloop.h>
#include <polyp/mainloop-signal.h>
+#include <polyp/polyplib-version.h>
+
+#if PA_API_VERSION != 6
+#error Invalid Polypaudio API version
+#endif
static enum { RECORD, PLAYBACK } mode = PLAYBACK;
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);
mainloop_api->io_enable(stdio_event, PA_IO_EVENT_OUTPUT);
if (buffer) {
- fprintf(stderr, "Buffer overrrun, dropping incoming data\n");
+ fprintf(stderr, "Buffer overrun, dropping incoming data\n");
return;
}
case PA_STREAM_FAILED:
default:
- fprintf(stderr, "Stream errror: %s\n", pa_strerror(pa_context_errno(pa_stream_get_context(s))));
+ fprintf(stderr, "Stream error: %s\n", pa_strerror(pa_context_errno(pa_stream_get_context(s))));
quit(1);
}
}
/* 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)) {
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);
pa_stream_set_read_callback(stream, stream_read_callback, NULL);
if (mode == PLAYBACK)
- pa_stream_connect_playback(stream, device, NULL, volume);
+ pa_stream_connect_playback(stream, device, NULL, 0, volume);
else
- pa_stream_connect_record(stream, device, NULL);
+ pa_stream_connect_record(stream, device, NULL, 0);
break;
/* Show the current latency */
static void stream_get_latency_callback(struct pa_stream *s, const struct pa_latency_info *i, void *userdata) {
- double total;
+ pa_usec_t total;
+ int negative = 0;
assert(s);
if (!i) {
return;
}
- if (mode == PLAYBACK)
- total = (double) i->sink_usec + i->buffer_usec + i->transport_usec;
- else
- total = (double) i->source_usec + i->buffer_usec + i->transport_usec - i->sink_usec;
+ total = pa_stream_get_latency(s, i, &negative);
fprintf(stderr, "Latency: buffer: %0.0f usec; sink: %0.0f usec; source: %0.0f usec; transport: %0.0f usec; total: %0.0f usec; synchronized clocks: %s.\n",
- (float) i->buffer_usec, (float) i->sink_usec, (float) i->source_usec, (float) i->transport_usec, total,
+ (float) i->buffer_usec, (float) i->sink_usec, (float) i->source_usec, (float) i->transport_usec, (float) total * (negative?-1:1),
i->synchronized_clocks ? "yes" : "no");
}
/* Someone requested that the latency is shown */
static void sigusr1_signal_callback(struct pa_mainloop_api*m, struct pa_signal_event *e, int sig, void *userdata) {
fprintf(stderr, "Got SIGUSR1, requesting latency.\n");
- pa_operation_unref(pa_stream_get_latency(stream, stream_get_latency_callback, NULL));
+ pa_operation_unref(pa_stream_get_latency_info(stream, stream_get_latency_callback, NULL));
}
static void help(const char *argv0) {
- printf("%s [options]\n"
+ printf("%s [options]\n\n"
" -h, --help Show this help\n"
" --version Show version\n\n"
" -r, --record Create a connection for recording\n"
" -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[]) {
{"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}
};
goto quit;
case ARG_VERSION:
- printf("pacat "PACKAGE_VERSION"\n");
+ printf("pacat "PACKAGE_VERSION"\nCompiled with libpolyp %s\nLinked with libpolyp %s\n", pa_get_headers_version(), pa_get_library_version());
ret = 0;
goto quit;
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;
}
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())) {