mirror of
https://gitlab.freedesktop.org/pulseaudio/pulseaudio.git
synced 2025-11-03 09:01:50 -05:00
* 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
This commit is contained in:
parent
8b99a067a8
commit
cf85794e23
1 changed files with 44 additions and 32 deletions
|
|
@ -52,10 +52,10 @@ PA_MODULE_DESCRIPTION("Jack Sink")
|
||||||
PA_MODULE_VERSION(PACKAGE_VERSION)
|
PA_MODULE_VERSION(PACKAGE_VERSION)
|
||||||
PA_MODULE_USAGE(
|
PA_MODULE_USAGE(
|
||||||
"sink_name=<name of sink> "
|
"sink_name=<name of sink> "
|
||||||
"server_name=<server name> "
|
"server_name=<jack server name> "
|
||||||
|
"client_name=<jack client name> "
|
||||||
"channels=<number of channels> "
|
"channels=<number of channels> "
|
||||||
"connect=<connect ports?>"
|
"connect=<connect ports?>"
|
||||||
"port_prefix=<port prefix>"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
#define DEFAULT_SINK_NAME "jack_out"
|
#define DEFAULT_SINK_NAME "jack_out"
|
||||||
|
|
@ -82,15 +82,15 @@ struct userdata {
|
||||||
pa_io_event *io_event;
|
pa_io_event *io_event;
|
||||||
|
|
||||||
jack_nframes_t frames_in_buffer;
|
jack_nframes_t frames_in_buffer;
|
||||||
struct timeval timestamp;
|
jack_nframes_t timestamp;
|
||||||
};
|
};
|
||||||
|
|
||||||
static const char* const valid_modargs[] = {
|
static const char* const valid_modargs[] = {
|
||||||
"sink_name",
|
"sink_name",
|
||||||
"server_name",
|
"server_name",
|
||||||
|
"client_name",
|
||||||
"channels",
|
"channels",
|
||||||
"connect",
|
"connect",
|
||||||
"port_prefix",
|
|
||||||
NULL
|
NULL
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -193,7 +193,7 @@ static int jack_process(jack_nframes_t nframes, void *arg) {
|
||||||
pthread_cond_wait(&u->cond, &u->mutex);
|
pthread_cond_wait(&u->cond, &u->mutex);
|
||||||
|
|
||||||
u->frames_in_buffer = nframes;
|
u->frames_in_buffer = nframes;
|
||||||
pa_gettimeofday(&u->timestamp);
|
u->timestamp = jack_get_current_transport_frame(u->client);
|
||||||
|
|
||||||
pthread_mutex_unlock(&u->mutex);
|
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) {
|
static pa_usec_t sink_get_latency_cb(pa_sink *s) {
|
||||||
struct userdata *u;
|
struct userdata *u;
|
||||||
pa_usec_t t, delta;
|
jack_nframes_t n, l, d;
|
||||||
|
|
||||||
assert(s);
|
assert(s);
|
||||||
u = s->userdata;
|
u = s->userdata;
|
||||||
|
|
||||||
if (jack_transport_query(u->client, NULL) != JackTransportRolling)
|
if (jack_transport_query(u->client, NULL) != JackTransportRolling)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
delta = pa_timeval_age(&u->timestamp);
|
n = jack_get_current_transport_frame(u->client);
|
||||||
t = pa_bytes_to_usec(jack_port_get_total_latency(u->client, u->port[0]) * pa_frame_size(&s->sample_spec), &s->sample_spec);
|
|
||||||
|
|
||||||
if (t > delta)
|
if (n < u->timestamp)
|
||||||
return t - delta;
|
|
||||||
else
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
d = n - u->timestamp;
|
||||||
|
l = jack_port_get_total_latency(u->client, u->port[0]) + u->frames_in_buffer;
|
||||||
|
|
||||||
|
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) {
|
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) {
|
int pa__init(pa_core *c, pa_module*m) {
|
||||||
struct userdata *u = NULL;
|
struct userdata *u = NULL;
|
||||||
pa_sample_spec ss;
|
pa_sample_spec ss;
|
||||||
|
pa_channel_map cm;
|
||||||
pa_modargs *ma = NULL;
|
pa_modargs *ma = NULL;
|
||||||
jack_status_t status;
|
jack_status_t status;
|
||||||
const char *server_name;
|
const char *server_name, *client_name;
|
||||||
uint32_t channels;
|
uint32_t channels = 0;
|
||||||
int connect = 1;
|
int connect = 1;
|
||||||
const char *pfx;
|
|
||||||
unsigned i;
|
unsigned i;
|
||||||
|
const char **ports = NULL, **p;
|
||||||
|
|
||||||
assert(c);
|
assert(c);
|
||||||
assert(m);
|
assert(m);
|
||||||
|
|
@ -244,18 +251,13 @@ int pa__init(pa_core *c, pa_module*m) {
|
||||||
goto fail;
|
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) {
|
if (pa_modargs_get_value_boolean(ma, "connect", &connect) < 0) {
|
||||||
pa_log(__FILE__": failed to parse connect= argument.");
|
pa_log(__FILE__": failed to parse connect= argument.");
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
server_name = pa_modargs_get_value(ma, "server_name", NULL);
|
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);
|
u = pa_xnew0(struct userdata, 1);
|
||||||
m->userdata = u;
|
m->userdata = u;
|
||||||
|
|
@ -273,11 +275,25 @@ int pa__init(pa_core *c, pa_module*m) {
|
||||||
|
|
||||||
pa_make_nonblock_fd(u->pipe_fds[1]);
|
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.");
|
pa_log(__FILE__": jack_client_open() failed.");
|
||||||
goto fail;
|
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));
|
pa_log_info(__FILE__": Successfully connected as '%s'", jack_get_client_name(u->client));
|
||||||
|
|
||||||
ss.channels = u->channels = channels;
|
ss.channels = u->channels = channels;
|
||||||
|
|
@ -286,20 +302,16 @@ int pa__init(pa_core *c, pa_module*m) {
|
||||||
|
|
||||||
assert(pa_sample_spec_valid(&ss));
|
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++) {
|
for (i = 0; i < ss.channels; i++) {
|
||||||
char tmp[64];
|
if (!(u->port[i] = jack_port_register(u->client, pa_channel_position_to_string(cm.map[i]), JACK_DEFAULT_AUDIO_TYPE, JackPortIsOutput|JackPortIsTerminal, 0))) {
|
||||||
|
|
||||||
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))) {
|
|
||||||
pa_log(__FILE__": jack_port_register() failed.");
|
pa_log(__FILE__": jack_port_register() failed.");
|
||||||
goto fail;
|
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.");
|
pa_log(__FILE__": failed to create sink.");
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
|
@ -318,11 +330,9 @@ int pa__init(pa_core *c, pa_module*m) {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (connect) {
|
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++) {
|
for (i = 0, p = ports; i < ss.channels; i++, p++) {
|
||||||
|
|
||||||
if (!p) {
|
if (!*p) {
|
||||||
pa_log(__FILE__": not enough physical output ports, leaving unconnected.");
|
pa_log(__FILE__": not enough physical output ports, leaving unconnected.");
|
||||||
break;
|
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);
|
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);
|
pa_modargs_free(ma);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
@ -348,6 +358,8 @@ fail:
|
||||||
if (ma)
|
if (ma)
|
||||||
pa_modargs_free(ma);
|
pa_modargs_free(ma);
|
||||||
|
|
||||||
|
free(ports);
|
||||||
|
|
||||||
pa__done(c, m);
|
pa__done(c, m);
|
||||||
|
|
||||||
return -1;
|
return -1;
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue