Browse Source

nonblock alsa open, different play/capture devices, fixes for port registration with excessive name length

git-svn-id: svn+ssh://jackaudio.org/trunk/jack@408 0c269be4-1314-0410-8aa9-9f06e86f4224
tags/0.109.0
pbd 23 years ago
parent
commit
f9e9ec8302
5 changed files with 95 additions and 42 deletions
  1. +2
    -2
      configure.in
  2. +69
    -35
      drivers/alsa/alsa_driver.c
  3. +2
    -1
      jack/alsa_driver.h
  4. +11
    -4
      jack/jack.h
  5. +11
    -0
      libjack/port.c

+ 2
- 2
configure.in View File

@@ -13,8 +13,8 @@ dnl micro version = incremented when implementation-only
dnl changes are made
dnl ---
JACK_MAJOR_VERSION=0
JACK_MINOR_VERSION=71
JACK_MICRO_VERSION=6
JACK_MINOR_VERSION=72
JACK_MICRO_VERSION=0

dnl ---
dnl HOWTO: updating the jack protocal version


+ 69
- 35
drivers/alsa/alsa_driver.c View File

@@ -85,13 +85,14 @@ alsa_driver_check_card_type (alsa_driver_t *driver)

snd_ctl_card_info_alloca (&card_info);

if ((err = snd_ctl_open (&driver->ctl_handle, driver->alsa_name, 0)) < 0) {
jack_error ("control open \"%s\" (%s)", driver->alsa_name, snd_strerror(err));
// XXX: I don't know the "right" way to do this. Which to use driver->alsa_name_playback or driver->alsa_name_capture.
if ((err = snd_ctl_open (&driver->ctl_handle, driver->alsa_name_playback, 0)) < 0) {
jack_error ("control open \"%s\" (%s)", driver->alsa_name_playback, snd_strerror(err));
return -1;
}
if ((err = snd_ctl_card_info(driver->ctl_handle, card_info)) < 0) {
jack_error ("control hardware info \"%s\" (%s)", driver->alsa_name, snd_strerror (err));
jack_error ("control hardware info \"%s\" (%s)", driver->alsa_name_playback, snd_strerror (err));
snd_ctl_close (driver->ctl_handle);
return -1;
}
@@ -254,7 +255,7 @@ alsa_driver_setup_io_function_pointers (alsa_driver_t *driver)
}

static int
alsa_driver_configure_stream (alsa_driver_t *driver,
alsa_driver_configure_stream (alsa_driver_t *driver, char *device_name,
const char *stream_name,
snd_pcm_t *handle,
snd_pcm_hw_params_t *hw_params,
@@ -286,7 +287,7 @@ alsa_driver_configure_stream (alsa_driver_t *driver,
if ((err = snd_pcm_hw_params_set_format (handle, hw_params, SND_PCM_FORMAT_S16)) < 0) {
jack_error ("Sorry. The audio interface \"%s\""
"doesn't support either of the two hardware sample formats that jack can use.",
driver->alsa_name);
device_name);
return -1;
}
}
@@ -401,7 +402,7 @@ alsa_driver_set_parameters (alsa_driver_t *driver, jack_nframes_t frames_per_cyc
driver->user_nperiods = user_nperiods;
if (driver->capture_handle) {
if (alsa_driver_configure_stream (driver, "capture",
if (alsa_driver_configure_stream (driver, driver->alsa_name_capture, "capture",
driver->capture_handle,
driver->capture_hw_params,
driver->capture_sw_params,
@@ -412,7 +413,7 @@ alsa_driver_set_parameters (alsa_driver_t *driver, jack_nframes_t frames_per_cyc
}

if (driver->playback_handle) {
if (alsa_driver_configure_stream (driver, "playback",
if (alsa_driver_configure_stream (driver, driver->alsa_name_playback, "playback",
driver->playback_handle,
driver->playback_hw_params,
driver->playback_sw_params,
@@ -459,9 +460,9 @@ alsa_driver_set_parameters (alsa_driver_t *driver, jack_nframes_t frames_per_cyc
/* Check that we are using the same sample format on both streams */
if (p_format != c_format) {
jack_error ("Sorry. The PCM device \"%s\""
"doesn't support the same sample format for capture and playback."
"We cannot use this PCM device.", driver->alsa_name);
jack_error ("Sorry. The PCM device \"%s\" and \"%s\""
"don't support the same sample format for capture and playback."
"We cannot use this PCM device.", driver->alsa_name_playback, driver->alsa_name_capture );
return -1;
}

@@ -506,9 +507,19 @@ alsa_driver_set_parameters (alsa_driver_t *driver, jack_nframes_t frames_per_cyc
}

if (driver->interleaved) {
const snd_pcm_channel_area_t *my_areas;
snd_pcm_uframes_t offset, frames;
if (snd_pcm_mmap_begin(driver->playback_handle, &my_areas, &offset, &frames) < 0) {
jack_error ("ALSA: %s: mmap areas info error", driver->alsa_name_playback);
return -1;
}
driver->playback_interleave_skip = my_areas[0].step / 8;
if (snd_pcm_mmap_begin(driver->capture_handle, &my_areas, &offset, &frames) < 0) {
jack_error ("ALSA: %s: mmap areas info error", driver->alsa_name_playback);
return -1;
}
driver->capture_interleave_skip = my_areas[0].step / 8;
driver->interleave_unit = snd_pcm_format_physical_width (driver->sample_format) / 8;
driver->playback_interleave_skip = driver->interleave_unit * driver->playback_nchannels;
driver->capture_interleave_skip = driver->interleave_unit * driver->capture_nchannels;
} else {
driver->interleave_unit = 0; /* NOT USED */
driver->playback_interleave_skip = snd_pcm_format_physical_width (driver->sample_format) / 8;
@@ -599,7 +610,7 @@ alsa_driver_get_channel_addresses (alsa_driver_t *driver,
if ((err = snd_pcm_mmap_begin (driver->capture_handle, &driver->capture_areas,
(snd_pcm_uframes_t *) capture_offset,
(snd_pcm_uframes_t *) capture_avail)) < 0) {
jack_error ("ALSA-HW: %s: mmap areas info error", driver->alsa_name);
jack_error ("ALSA: %s: mmap areas info error", driver->alsa_name_capture);
return -1;
}
@@ -613,7 +624,7 @@ alsa_driver_get_channel_addresses (alsa_driver_t *driver,
if ((err = snd_pcm_mmap_begin (driver->playback_handle, &driver->playback_areas,
(snd_pcm_uframes_t *) playback_offset,
(snd_pcm_uframes_t *) playback_avail)) < 0) {
jack_error ("ALSA-HW: %s: mmap areas info error ", driver->alsa_name);
jack_error ("ALSA: %s: mmap areas info error ", driver->alsa_name_playback);
return -1;
}
@@ -639,14 +650,14 @@ alsa_driver_audio_start (alsa_driver_t *driver)

if (driver->playback_handle) {
if ((err = snd_pcm_prepare (driver->playback_handle)) < 0) {
jack_error ("ALSA-HW: prepare error for playback on \"%s\" (%s)", driver->alsa_name, snd_strerror(err));
jack_error ("ALSA: prepare error for playback on \"%s\" (%s)", driver->alsa_name_playback, snd_strerror(err));
return -1;
}
}

if (driver->capture_handle && driver->capture_and_playback_not_synced) {
if ((err = snd_pcm_prepare (driver->capture_handle)) < 0) {
jack_error ("ALSA-HW: prepare error for capture on \"%s\" (%s)", driver->alsa_name, snd_strerror(err));
jack_error ("ALSA: prepare error for capture on \"%s\" (%s)", driver->alsa_name_capture, snd_strerror(err));
return -1;
}
}
@@ -663,7 +674,7 @@ alsa_driver_audio_start (alsa_driver_t *driver)
pavail = snd_pcm_avail_update (driver->playback_handle);

if (pavail != driver->buffer_frames) {
jack_error ("ALSA-HW: full buffer not available at start");
jack_error ("ALSA: full buffer not available at start");
return -1;
}
@@ -822,7 +833,8 @@ alsa_driver_wait (alsa_driver_t *driver, int extra_fd, int *status, float *delay
int need_capture;
int need_playback;
unsigned int i;
jack_time_t poll_enter, poll_ret;
jack_time_t poll_enter;
jack_time_t poll_ret = 0;

*status = -1;
*delayed_usecs = 0;
@@ -1432,7 +1444,8 @@ alsa_driver_delete (alsa_driver_t *driver)
driver->hw->release (driver->hw);
driver->hw = 0;
}
free(driver->alsa_name);
free(driver->alsa_name_playback);
free(driver->alsa_name_capture);
free(driver->alsa_driver);

alsa_driver_release_channel_dependent_memory (driver);
@@ -1440,7 +1453,7 @@ alsa_driver_delete (alsa_driver_t *driver)
}

static jack_driver_t *
alsa_driver_new (char *name, char *alsa_device,
alsa_driver_new (char *name, char *playback_alsa_device, char *capture_alsa_device,
jack_client_t *client,
jack_nframes_t frames_per_cycle,
jack_nframes_t user_nperiods,
@@ -1457,8 +1470,8 @@ alsa_driver_new (char *name, char *alsa_device,

alsa_driver_t *driver;

printf ("creating alsa driver ... %s|%lu|%lu|%lu|%s|%s|%s\n",
alsa_device, frames_per_cycle, user_nperiods, rate,
printf ("creating alsa driver ... %s|%s|%lu|%lu|%lu|%s|%s|%s\n",
playback_alsa_device, capture_alsa_device, frames_per_cycle, user_nperiods, rate,
hw_monitoring ? "hwmon":"swmon", hw_metering ? "hwmeter":"swmeter", soft_mode ? "soft-mode":"rt");

driver = (alsa_driver_t *) calloc (1, sizeof (alsa_driver_t));
@@ -1507,15 +1520,27 @@ alsa_driver_new (char *name, char *alsa_device,
driver->clock_sync_listeners = 0;

if (playing) {
if (snd_pcm_open (&driver->playback_handle, alsa_device, SND_PCM_STREAM_PLAYBACK, 0) < 0) {
if (snd_pcm_open (&driver->playback_handle, playback_alsa_device, SND_PCM_STREAM_PLAYBACK, SND_PCM_NONBLOCK) < 0) {
if (errno == -EBUSY) {
jack_error ("the playback device \"%s\" is already in use. Please stop the application using it and "
"run JACK again", playback_alsa_device);
return NULL;
}
driver->playback_handle = NULL;
}
snd_pcm_nonblock (driver->playback_handle, 0);
}

if (capturing) {
if (snd_pcm_open (&driver->capture_handle, alsa_device, SND_PCM_STREAM_CAPTURE, 0) < 0) {
if (snd_pcm_open (&driver->capture_handle, capture_alsa_device, SND_PCM_STREAM_CAPTURE, SND_PCM_NONBLOCK) < 0) {
if (errno == -EBUSY) {
jack_error ("the capture device \"%s\" is already in use. Please stop the application using it and "
"run JACK again", capture_alsa_device);
return NULL;
}
driver->capture_handle = NULL;
}
snd_pcm_nonblock (driver->capture_handle, 0);
}

fprintf (stderr, "open\n");
@@ -1556,7 +1581,8 @@ alsa_driver_new (char *name, char *alsa_device,
}
}

driver->alsa_name = strdup (alsa_device);
driver->alsa_name_playback = strdup (playback_alsa_device);
driver->alsa_name_capture = strdup (capture_alsa_device);

if (alsa_driver_check_card_type (driver)) {
if (driver->capture_handle) {
@@ -1687,8 +1713,8 @@ alsa_usage ()
" -H,--hwmon \tuse hardware monitoring, if available (default: no)\n"
" -M,--hwmeter \tuse hardware metering, if available (default: no)\n"
" -D,--duplex \tduplex I/O (default: yes)\n"
" -C,--capture \tcapture input (default: duplex)\n"
" -P,--playback\tplayback output (default: duplex)\n"
" -C,--capture [name] \tcapture input and optionally set the capture device (default: duplex)\n"
" -P,--playback [name] \tplayback output and optionally set the playback device (default: duplex)\n"
" -s,--softmode\tsoft-mode, no xrun handling (default: off)\n"
" -m,--monitor \tprovide monitor ports for the output (default: off)\n"
" -z,--dither \tdithering mode:\n"
@@ -1744,7 +1770,8 @@ driver_initialize (jack_client_t *client, int argc, char **argv)
jack_nframes_t srate = 48000;
jack_nframes_t frames_per_interrupt = 1024;
unsigned long user_nperiods = 2;
char *pcm_name = "default";
char *playback_pcm_name = "default";
char *capture_pcm_name = "default";
int hw_monitoring = FALSE;
int hw_metering = FALSE;
int capture = FALSE;
@@ -1757,13 +1784,13 @@ driver_initialize (jack_client_t *client, int argc, char **argv)
char optstring[2]; /* string made from opt char */
struct option long_options[] =
{
{ "capture", 0, NULL, 'C' },
{ "capture", 2, NULL, 'C' },
{ "duplex", 0, NULL, 'D' },
{ "device", 1, NULL, 'd' },
{ "hwmon", 0, NULL, 'H' },
{ "hwmeter", 0, NULL, 'M' },
{ "help", 0, NULL, 'h' },
{ "playback", 0, NULL, 'P' },
{ "playback", 2, NULL, 'P' },
{ "period", 1, NULL, 'p' },
{ "rate", 1, NULL, 'r' },
{ "nperiods", 1, NULL, 'n' },
@@ -1778,7 +1805,8 @@ driver_initialize (jack_client_t *client, int argc, char **argv)
*/
if ((envvar = getenv ("JACK_ALSA_DEVICE")) != NULL) {
pcm_name = envvar;
playback_pcm_name = envvar;
capture_pcm_name = envvar;
}

if ((envvar = getenv ("JACK_ALSA_HWMON")) != NULL) {
@@ -1827,13 +1855,16 @@ driver_initialize (jack_client_t *client, int argc, char **argv)
optind = 0;
opterr = 0;

while ((opt = getopt_long(argc, argv, "-CDd:HMPp:r:n:msz::",
while ((opt = getopt_long(argc, argv, "-C::Dd:HMP::p:r:n:msz::",
long_options, NULL))
!= EOF) {
switch (opt) {

case 'C':
capture = TRUE;
if (optarg != NULL) {
capture_pcm_name = optarg;
}
break;

case 'D':
@@ -1842,7 +1873,8 @@ driver_initialize (jack_client_t *client, int argc, char **argv)
break;

case 'd':
pcm_name = optarg;
playback_pcm_name = optarg;
capture_pcm_name = optarg;
break;

case 'H':
@@ -1863,6 +1895,9 @@ driver_initialize (jack_client_t *client, int argc, char **argv)
case 'P':
playback = TRUE;
if (optarg != NULL) {
playback_pcm_name = optarg;
}
break;

case 'p':
@@ -1910,7 +1945,7 @@ driver_initialize (jack_client_t *client, int argc, char **argv)
playback = TRUE;
}

return alsa_driver_new ("alsa_pcm", pcm_name, client, frames_per_interrupt,
return alsa_driver_new ("alsa_pcm", playback_pcm_name, capture_pcm_name, client, frames_per_interrupt,
user_nperiods, srate, hw_monitoring, hw_metering, capture,
playback, dither, soft_mode, monitor);
}
@@ -1920,4 +1955,3 @@ driver_finish (jack_driver_t *driver)
{
alsa_driver_delete ((alsa_driver_t *) driver);
}


+ 2
- 1
jack/alsa_driver.h View File

@@ -70,7 +70,8 @@ typedef struct {
jack_nframes_t playback_frame_latency;

unsigned long *silent;
char *alsa_name;
char *alsa_name_playback;
char *alsa_name_capture;
char *alsa_driver;
snd_pcm_uframes_t buffer_frames;
unsigned long channels_not_done;


+ 11
- 4
jack/jack.h View File

@@ -176,10 +176,14 @@ int jack_deactivate (jack_client_t *client);
* the data may be of any type. Ports may be connected to each other
* in various ways.
*
* A port has a short name, which may be any non-NULL and non-zero
* length string, and is passed as the first argument. A port's full
* name is the name of the client concatenated with a colon (:) and
* then its short name.
* A port has a short name, a non-NULL and non-zero length string, and
* is passed as the first argument. A port's full name is the name of
* the client concatenated with a colon (:) and then its short
* name. There are limits to the length of the name, and exceeding
* them will cause registration of the port to fail and the function
* to return NULL. The limit is derived from the size of a full port
* name, which also has to include the client name and a separator
* character.
*
* A port has a type, which may be any non-NULL and non-zero length
* string, and is passed as the second argument. For types that are
@@ -189,6 +193,9 @@ int jack_deactivate (jack_client_t *client);
* 'buffer_size' is ignored.
*
* The 'flags' argument is formed from a bitmask of JackPortFlags values.
*
* @return a valid jack_port_t* on success, NULL otherwise.
* returns NULL.
*/
jack_port_t *jack_port_register (jack_client_t *,
const char *port_name,


+ 11
- 0
libjack/port.c View File

@@ -116,9 +116,20 @@ jack_port_register (jack_client_t *client,
{
jack_request_t req;
jack_port_t *port = 0;
int length ;

req.type = RegisterPort;

length = strlen ( (const char *) client->control->name ) + 1 + strlen ( port_name ) ;
if ( length >= sizeof (req.x.port_info.name) ) {
jack_error ("\"%s:%s\" is too long to be used as a JACK port name.\n"
"Please use %lu characters or less.",
client->control->name ,
port_name ,
sizeof (req.x.port_info.name) - 1);
return NULL ;
}

strcpy ((char *) req.x.port_info.name, (const char *) client->control->name);
strcat ((char *) req.x.port_info.name, ":");
strcat ((char *) req.x.port_info.name, port_name);


Loading…
Cancel
Save