From cf85794e2349631f6d997592bceca2174c044f0c Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Tue, 18 Apr 2006 13:20:50 +0000 Subject: * allow the user to set the jack client name * take the number of channels for the sink from the number of physical ports in the jack server * name the polypaudio ports in the jack server after their channel position in polypaudio git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@737 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/modules/module-jack-sink.c | 76 ++++++++++++++++++++++++------------------ 1 file changed, 44 insertions(+), 32 deletions(-) diff --git a/src/modules/module-jack-sink.c b/src/modules/module-jack-sink.c index 3d372551..4f7a66eb 100644 --- a/src/modules/module-jack-sink.c +++ b/src/modules/module-jack-sink.c @@ -52,10 +52,10 @@ PA_MODULE_DESCRIPTION("Jack Sink") PA_MODULE_VERSION(PACKAGE_VERSION) PA_MODULE_USAGE( "sink_name= " - "server_name= " + "server_name= " + "client_name= " "channels= " "connect=" - "port_prefix=" ) #define DEFAULT_SINK_NAME "jack_out" @@ -82,15 +82,15 @@ struct userdata { pa_io_event *io_event; jack_nframes_t frames_in_buffer; - struct timeval timestamp; + jack_nframes_t timestamp; }; static const char* const valid_modargs[] = { "sink_name", "server_name", + "client_name", "channels", "connect", - "port_prefix", NULL }; @@ -193,7 +193,7 @@ static int jack_process(jack_nframes_t nframes, void *arg) { pthread_cond_wait(&u->cond, &u->mutex); u->frames_in_buffer = nframes; - pa_gettimeofday(&u->timestamp); + u->timestamp = jack_get_current_transport_frame(u->client); pthread_mutex_unlock(&u->mutex); } @@ -203,20 +203,26 @@ static int jack_process(jack_nframes_t nframes, void *arg) { static pa_usec_t sink_get_latency_cb(pa_sink *s) { struct userdata *u; - pa_usec_t t, delta; + jack_nframes_t n, l, d; + assert(s); u = s->userdata; if (jack_transport_query(u->client, NULL) != JackTransportRolling) return 0; - delta = pa_timeval_age(&u->timestamp); - t = pa_bytes_to_usec(jack_port_get_total_latency(u->client, u->port[0]) * pa_frame_size(&s->sample_spec), &s->sample_spec); + n = jack_get_current_transport_frame(u->client); + + if (n < u->timestamp) + return 0; + + d = n - u->timestamp; + l = jack_port_get_total_latency(u->client, u->port[0]) + u->frames_in_buffer; - if (t > delta) - return t - delta; - else + if (d >= l) return 0; + + return pa_bytes_to_usec((l - d) * pa_frame_size(&s->sample_spec), &s->sample_spec); } static void jack_error_func(const char*t) { @@ -226,13 +232,14 @@ static void jack_error_func(const char*t) { int pa__init(pa_core *c, pa_module*m) { struct userdata *u = NULL; pa_sample_spec ss; + pa_channel_map cm; pa_modargs *ma = NULL; jack_status_t status; - const char *server_name; - uint32_t channels; + const char *server_name, *client_name; + uint32_t channels = 0; int connect = 1; - const char *pfx; unsigned i; + const char **ports = NULL, **p; assert(c); assert(m); @@ -244,18 +251,13 @@ int pa__init(pa_core *c, pa_module*m) { goto fail; } - channels = c->default_sample_spec.channels; - if (pa_modargs_get_value_u32(ma, "channels", &channels) < 0 || channels <= 0 || channels >= PA_CHANNELS_MAX) { - pa_log(__FILE__": failed to parse channels= argument."); - goto fail; - } - if (pa_modargs_get_value_boolean(ma, "connect", &connect) < 0) { pa_log(__FILE__": failed to parse connect= argument."); goto fail; } server_name = pa_modargs_get_value(ma, "server_name", NULL); + client_name = pa_modargs_get_value(ma, "client_name", "polypaudio"); u = pa_xnew0(struct userdata, 1); m->userdata = u; @@ -273,11 +275,25 @@ int pa__init(pa_core *c, pa_module*m) { pa_make_nonblock_fd(u->pipe_fds[1]); - if (!(u->client = jack_client_open("polypaudio", server_name ? JackServerName : JackNullOption, &status, server_name))) { + if (!(u->client = jack_client_open(client_name, server_name ? JackServerName : JackNullOption, &status, server_name))) { pa_log(__FILE__": jack_client_open() failed."); goto fail; } + ports = jack_get_ports(u->client, NULL, NULL, JackPortIsPhysical|JackPortIsInput); + + channels = 0; + for (p = ports; *p; p++) + channels++; + + if (!channels) + channels = c->default_sample_spec.channels; + + if (pa_modargs_get_value_u32(ma, "channels", &channels) < 0 || channels <= 0 || channels >= PA_CHANNELS_MAX) { + pa_log(__FILE__": failed to parse channels= argument."); + goto fail; + } + pa_log_info(__FILE__": Successfully connected as '%s'", jack_get_client_name(u->client)); ss.channels = u->channels = channels; @@ -286,20 +302,16 @@ int pa__init(pa_core *c, pa_module*m) { assert(pa_sample_spec_valid(&ss)); - pfx = pa_modargs_get_value(ma, "port_prefix", "channel"); + pa_channel_map_init_auto(&cm, channels); for (i = 0; i < ss.channels; i++) { - char tmp[64]; - - snprintf(tmp, sizeof(tmp), "%s_%i", pfx, i+1); - - if (!(u->port[i] = jack_port_register(u->client, tmp, JACK_DEFAULT_AUDIO_TYPE, JackPortIsOutput/*|JackPortIsTerminal*/, 0))) { + if (!(u->port[i] = jack_port_register(u->client, pa_channel_position_to_string(cm.map[i]), JACK_DEFAULT_AUDIO_TYPE, JackPortIsOutput|JackPortIsTerminal, 0))) { pa_log(__FILE__": jack_port_register() failed."); goto fail; } } - if (!(u->sink = pa_sink_new(c, __FILE__, pa_modargs_get_value(ma, "sink_name", DEFAULT_SINK_NAME), 0, &ss, NULL))) { + if (!(u->sink = pa_sink_new(c, __FILE__, pa_modargs_get_value(ma, "sink_name", DEFAULT_SINK_NAME), 0, &ss, &cm))) { pa_log(__FILE__": failed to create sink."); goto fail; } @@ -318,11 +330,9 @@ int pa__init(pa_core *c, pa_module*m) { } if (connect) { - const char **p, **ports = jack_get_ports(u->client, NULL, NULL, JackPortIsPhysical|JackPortIsInput); - for (i = 0, p = ports; i < ss.channels; i++, p++) { - if (!p) { + if (!*p) { pa_log(__FILE__": not enough physical output ports, leaving unconnected."); break; } @@ -335,11 +345,11 @@ int pa__init(pa_core *c, pa_module*m) { } } - free(ports); } u->io_event = c->mainloop->io_new(c->mainloop, u->pipe_fds[0], PA_IO_EVENT_INPUT, io_event_cb, u); + free(ports); pa_modargs_free(ma); return 0; @@ -347,6 +357,8 @@ int pa__init(pa_core *c, pa_module*m) { fail: if (ma) pa_modargs_free(ma); + + free(ports); pa__done(c, m); -- cgit