Browse Source

allowed for duplex/capture/playback in alsa driver

git-svn-id: svn+ssh://jackaudio.org/trunk/jack@120 0c269be4-1314-0410-8aa9-9f06e86f4224
tags/0.109.0
pbd 24 years ago
parent
commit
ac19b71d02
2 changed files with 367 additions and 215 deletions
  1. +366
    -214
      alsa_driver.c
  2. +1
    -1
      configure.in

+ 366
- 214
alsa_driver.c View File

@@ -292,71 +292,112 @@ static int
alsa_driver_set_parameters (alsa_driver_t *driver, nframes_t frames_per_cycle, nframes_t user_nperiods, nframes_t rate)

{
int p_noninterleaved;
int c_noninterleaved;
snd_pcm_format_t c_format, p_format;
int p_noninterleaved = 0;
int c_noninterleaved = 0;
snd_pcm_format_t c_format = 0;
snd_pcm_format_t p_format = 0;
int dir;
unsigned int p_period_size, c_period_size;
unsigned int p_nfragments, c_nfragments;
unsigned int p_period_size = 0;
unsigned int c_period_size = 0;
unsigned int p_nfragments = 0;
unsigned int c_nfragments = 0;
channel_t chn;

driver->frame_rate = rate;
driver->frames_per_cycle = frames_per_cycle;
driver->user_nperiods = user_nperiods;
if (alsa_driver_configure_stream (driver, "capture",
driver->capture_handle,
driver->capture_hw_params,
driver->capture_sw_params,
&driver->capture_nchannels)) {
jack_error ("ALSA: cannot configure capture channel");
return -1;
if (driver->capture_handle) {
if (alsa_driver_configure_stream (driver, "capture",
driver->capture_handle,
driver->capture_hw_params,
driver->capture_sw_params,
&driver->capture_nchannels)) {
jack_error ("ALSA: cannot configure capture channel");
return -1;
}
}
if (alsa_driver_configure_stream (driver, "playback",
driver->playback_handle,
driver->playback_hw_params,
driver->playback_sw_params,
&driver->playback_nchannels)) {
jack_error ("ALSA: cannot configure playback channel");
return -1;

if (driver->playback_handle) {
if (alsa_driver_configure_stream (driver, "playback",
driver->playback_handle,
driver->playback_hw_params,
driver->playback_sw_params,
&driver->playback_nchannels)) {
jack_error ("ALSA: cannot configure playback channel");
return -1;
}
}
/* check the fragment size, since thats non-negotiable */
p_period_size = snd_pcm_hw_params_get_period_size (driver->playback_hw_params, &dir);
c_period_size = snd_pcm_hw_params_get_period_size (driver->capture_hw_params, &dir);
if (driver->playback_handle) {
p_period_size = snd_pcm_hw_params_get_period_size (driver->playback_hw_params, &dir);
p_nfragments = snd_pcm_hw_params_get_periods (driver->playback_hw_params, &dir);
p_format = (snd_pcm_format_t) snd_pcm_hw_params_get_format (driver->playback_hw_params);
p_noninterleaved = (snd_pcm_hw_params_get_access (driver->playback_hw_params) == SND_PCM_ACCESS_MMAP_NONINTERLEAVED);

if (p_period_size != driver->frames_per_cycle) {
jack_error ("alsa_pcm: requested an interrupt every %u frames but got %uc frames for playback",
driver->frames_per_cycle,p_period_size);
return -1;
}
}

if (driver->capture_handle) {
c_period_size = snd_pcm_hw_params_get_period_size (driver->capture_hw_params, &dir);
c_nfragments = snd_pcm_hw_params_get_periods (driver->capture_hw_params, &dir);
c_format = (snd_pcm_format_t) snd_pcm_hw_params_get_format (driver->capture_hw_params);
c_noninterleaved = (snd_pcm_hw_params_get_access (driver->capture_hw_params) == SND_PCM_ACCESS_MMAP_NONINTERLEAVED);
if (c_period_size != driver->frames_per_cycle || p_period_size != driver->frames_per_cycle) {
jack_error ("alsa_pcm: requested an interrupt every %u frames but got %uc%up frames",
driver->frames_per_cycle, c_period_size, p_period_size);
return -1;
if (c_period_size != driver->frames_per_cycle) {
jack_error ("alsa_pcm: requested an interrupt every %u frames but got %uc frames for capture",
driver->frames_per_cycle,p_period_size);
return -1;
}
}

p_nfragments = snd_pcm_hw_params_get_periods (driver->playback_hw_params, &dir);
c_nfragments = snd_pcm_hw_params_get_periods (driver->capture_hw_params, &dir);
if (driver->capture_handle && driver->playback_handle) {
if (p_nfragments != c_nfragments) {
jack_error ("alsa_pcm: different period counts for playback and capture!");
return -1;
}

if (p_nfragments != c_nfragments) {
jack_error ("alsa_pcm: different period counts for playback and capture!");
return -1;
}
/* 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);
return -1;
}

driver->nfragments = c_nfragments;
driver->buffer_frames = driver->frames_per_cycle * driver->nfragments;
/* check interleave setup */
if (c_noninterleaved != p_noninterleaved) {
jack_error ("ALSA: the playback and capture components for this PCM device differ "
"in their use of channel interleaving. We cannot use this PCM device.");
return -1;
}
driver->nfragments = c_nfragments;
driver->interleaved = !c_noninterleaved;
driver->sample_format = c_format;

/* Check that we are using the same sample format on both streams */
} else if (driver->capture_handle) {

p_format = (snd_pcm_format_t) snd_pcm_hw_params_get_format (driver->playback_hw_params);
c_format = (snd_pcm_format_t) snd_pcm_hw_params_get_format (driver->capture_hw_params);
driver->nfragments = c_nfragments;
driver->interleaved = !c_noninterleaved;
driver->sample_format = c_format;

if (p_format != c_format) {
jack_error ("Sorry. The audio interface \"%s\""
"doesn't support the same sample format for capture and playback."
"this JACK/ALSA driver cannot use this hardware.", driver->alsa_name);
return -1;
} else {
driver->nfragments = p_nfragments;
driver->interleaved = !p_noninterleaved;
driver->sample_format = p_format;
}

driver->sample_format = p_format;
driver->buffer_frames = driver->frames_per_cycle * driver->nfragments;
driver->sample_bytes = snd_pcm_format_physical_width (driver->sample_format) / 8;
driver->bytes_per_cycle = driver->sample_bytes * driver->frames_per_cycle;

@@ -370,19 +411,6 @@ alsa_driver_set_parameters (alsa_driver_t *driver, nframes_t frames_per_cycle, n
exit (1);
}

/* check interleave setup */

p_noninterleaved = (snd_pcm_hw_params_get_access (driver->playback_hw_params) == SND_PCM_ACCESS_MMAP_NONINTERLEAVED);
c_noninterleaved = (snd_pcm_hw_params_get_access (driver->capture_hw_params) == SND_PCM_ACCESS_MMAP_NONINTERLEAVED);

if (c_noninterleaved != p_noninterleaved) {
jack_error ("ALSA: the playback and capture components of this audio interface differ "
"in their use of channel interleaving. Ardour cannot use this h/w.");
return -1;
}

driver->interleaved = !c_noninterleaved;

if (driver->interleaved) {
driver->interleave_unit = snd_pcm_format_physical_width (driver->sample_format) / 8;
driver->playback_interleave_skip = driver->interleave_unit * driver->playback_nchannels;
@@ -407,22 +435,6 @@ alsa_driver_set_parameters (alsa_driver_t *driver, nframes_t frames_per_cycle, n
the channels counts.
*/

driver->playback_addr = (char **) malloc (sizeof (char *) * driver->playback_nchannels);
driver->capture_addr = (char **) malloc (sizeof (char *) * driver->capture_nchannels);

memset (driver->playback_addr, 0, sizeof (char *) * driver->playback_nchannels);
memset (driver->capture_addr, 0, sizeof (char *) * driver->capture_nchannels);
driver->silent = (unsigned long *) malloc (sizeof (unsigned long) * driver->playback_nchannels);

for (chn = 0; chn < driver->playback_nchannels; chn++) {
driver->silent[chn] = 0;
}

driver->clock_sync_data = (ClockSyncStatus *) malloc (sizeof (ClockSyncStatus) *
driver->capture_nchannels > driver->playback_nchannels ?
driver->capture_nchannels : driver->playback_nchannels);
/* set up the bit pattern that is used to record which
channels require action on every cycle. any bits that are
not set after the engine's process() call indicate channels
@@ -433,10 +445,31 @@ alsa_driver_set_parameters (alsa_driver_t *driver, nframes_t frames_per_cycle, n
*/

driver->channel_done_bits = 0;
for (chn = 0; chn < driver->playback_nchannels; chn++) {
driver->channel_done_bits |= (1<<chn);

if (driver->playback_handle) {
driver->playback_addr = (char **) malloc (sizeof (char *) * driver->playback_nchannels);
memset (driver->playback_addr, 0, sizeof (char *) * driver->playback_nchannels);
driver->silent = (unsigned long *) malloc (sizeof (unsigned long) * driver->playback_nchannels);
for (chn = 0; chn < driver->playback_nchannels; chn++) {
driver->silent[chn] = 0;
}

for (chn = 0; chn < driver->playback_nchannels; chn++) {
driver->channel_done_bits |= (1<<chn);
}
}

if (driver->capture_handle) {
driver->capture_addr = (char **) malloc (sizeof (char *) * driver->capture_nchannels);
memset (driver->capture_addr, 0, sizeof (char *) * driver->capture_nchannels);
}

driver->clock_sync_data = (ClockSyncStatus *) malloc (sizeof (ClockSyncStatus) *
driver->capture_nchannels > driver->playback_nchannels ?
driver->capture_nchannels : driver->playback_nchannels);

driver->period_interval = (unsigned long) floor ((((float) driver->frames_per_cycle) / driver->frame_rate) * 1000.0);

if (driver->engine) {
@@ -477,7 +510,7 @@ alsa_driver_get_channel_addresses (alsa_driver_t *driver,
const snd_pcm_channel_area_t *a = &driver->capture_areas[chn];
driver->capture_addr[chn] = (char *) a->addr + ((a->first + a->step * *capture_offset) / 8);
}
}
}

if (playback_avail) {
if ((err = snd_pcm_mmap_begin (driver->playback_handle, &driver->playback_areas,
@@ -491,8 +524,8 @@ alsa_driver_get_channel_addresses (alsa_driver_t *driver,
const snd_pcm_channel_area_t *a = &driver->playback_areas[chn];
driver->playback_addr[chn] = (char *) a->addr + ((a->first + a->step * *playback_offset) / 8);
}
}
}
return 0;
}
@@ -504,12 +537,14 @@ alsa_driver_audio_start (alsa_driver_t *driver)
snd_pcm_uframes_t poffset, pavail;
channel_t chn;

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));
return -1;
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));
return -1;
}
}

if (driver->capture_and_playback_not_synced) {
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));
return -1;
@@ -520,33 +555,35 @@ alsa_driver_audio_start (alsa_driver_t *driver)
driver->hw->set_input_monitor_mask (driver->hw, driver->input_monitor_mask);
}

/* fill playback buffer with zeroes, and mark
all fragments as having data.
*/
pavail = snd_pcm_avail_update (driver->playback_handle);

if (pavail != driver->buffer_frames) {
jack_error ("ALSA-HW: full buffer not available at start");
return -1;
}

if (alsa_driver_get_channel_addresses (driver, 0, &pavail, 0, &poffset)) {
return -1;
}
if (driver->playback_handle) {
/* fill playback buffer with zeroes, and mark
all fragments as having data.
*/
pavail = snd_pcm_avail_update (driver->playback_handle);

for (chn = 0; chn < driver->playback_nchannels; chn++) {
if (pavail != driver->buffer_frames) {
jack_error ("ALSA-HW: full buffer not available at start");
return -1;
}
if (alsa_driver_get_channel_addresses (driver, 0, &pavail, 0, &poffset)) {
return -1;
}
for (chn = 0; chn < driver->playback_nchannels; chn++) {
alsa_driver_silence_on_channel (driver, chn, driver->buffer_frames);
}
snd_pcm_mmap_commit (driver->playback_handle, poffset, driver->buffer_frames);
if ((err = snd_pcm_start (driver->playback_handle)) < 0) {
jack_error ("could not start playback (%s)", snd_strerror (err));
return -1;
}
}

snd_pcm_mmap_commit (driver->playback_handle, poffset, driver->buffer_frames);

if ((err = snd_pcm_start (driver->playback_handle)) < 0) {
jack_error ("could not start playback (%s)", snd_strerror (err));
return -1;
}

if (driver->capture_and_playback_not_synced) {
if (driver->capture_handle && driver->capture_and_playback_not_synced) {
if ((err = snd_pcm_start (driver->capture_handle)) < 0) {
jack_error ("could not start capture (%s)", snd_strerror (err));
return -1;
@@ -561,8 +598,18 @@ alsa_driver_audio_start (alsa_driver_t *driver)
}
}

driver->playback_nfds = snd_pcm_poll_descriptors_count (driver->playback_handle);
driver->capture_nfds = snd_pcm_poll_descriptors_count (driver->capture_handle);
if (driver->playback_handle) {
driver->playback_nfds = snd_pcm_poll_descriptors_count (driver->playback_handle);
} else {
driver->playback_nfds = 0;
}

if (driver->capture_handle) {
driver->capture_nfds = snd_pcm_poll_descriptors_count (driver->capture_handle);
} else {
driver->capture_nfds = 0;
}

if (driver->pfd)
free (driver->pfd);
driver->pfd = (struct pollfd *) malloc (sizeof (struct pollfd) *
@@ -577,15 +624,19 @@ alsa_driver_audio_stop (alsa_driver_t *driver)
{
int err;

if ((err = snd_pcm_drop (driver->playback_handle)) < 0) {
jack_error ("alsa_pcm: channel flush for playback failed (%s)", snd_strerror (err));
return -1;
if (driver->playback_handle) {
if ((err = snd_pcm_drop (driver->playback_handle)) < 0) {
jack_error ("alsa_pcm: channel flush for playback failed (%s)", snd_strerror (err));
return -1;
}
}

if (driver->capture_and_playback_not_synced) {
if ((err = snd_pcm_drop (driver->capture_handle)) < 0) {
jack_error ("alsa_pcm: channel flush for capture failed (%s)", snd_strerror (err));
return -1;
if (!driver->playback_handle || driver->capture_and_playback_not_synced) {
if (driver->capture_handle) {
if ((err = snd_pcm_drop (driver->capture_handle)) < 0) {
jack_error ("alsa_pcm: channel flush for capture failed (%s)", snd_strerror (err));
return -1;
}
}
}
@@ -602,8 +653,15 @@ alsa_driver_xrun_recovery (alsa_driver_t *driver)
int res;

snd_pcm_status_alloca(&status);
if ((res = snd_pcm_status(driver->capture_handle, status)) < 0) {
jack_error("status error: %s", snd_strerror(res));

if (driver->capture_handle) {
if ((res = snd_pcm_status(driver->capture_handle, status)) < 0) {
jack_error("status error: %s", snd_strerror(res));
}
} else {
if ((res = snd_pcm_status(driver->playback_handle, status)) < 0) {
jack_error("status error: %s", snd_strerror(res));
}
}

if (snd_pcm_status_get_state(status) == SND_PCM_STATE_XRUN) {
@@ -614,13 +672,6 @@ alsa_driver_xrun_recovery (alsa_driver_t *driver)
fprintf(stderr, "alsa_pcm: xrun of at least %.3f msecs\n", diff.tv_sec * 1000 + diff.tv_usec / 1000.0);
}

#if ENGINE
if (!engine->xrun_recoverable ()) {
/* don't report an error here, its distracting */
return -1;
}
#endif

if (alsa_driver_audio_stop (driver) || alsa_driver_audio_start (driver)) {
return -1;

@@ -667,11 +718,11 @@ alsa_driver_wait (alsa_driver_t *driver, int fd, int *status)
int i;

*status = -1;
need_capture = 1;
need_capture = driver->capture_handle ? 1 : 0;
if (fd >= 0) {
need_playback = 0;
} else {
need_playback = 1;
need_playback = driver->playback_handle ? 1 : 0;
}

again:
@@ -779,27 +830,36 @@ alsa_driver_wait (alsa_driver_t *driver, int fd, int *status)
}
}
if (p_timed_out == driver->playback_nfds && c_timed_out == driver->capture_nfds) {
if ((p_timed_out && (p_timed_out == driver->playback_nfds)) &&
(c_timed_out && (c_timed_out == driver->capture_nfds))){
jack_error ("ALSA: poll time out");
return 0;
}

}

if ((capture_avail = snd_pcm_avail_update (driver->capture_handle)) < 0) {
if (capture_avail == -EPIPE) {
xrun_detected = TRUE;
} else {
jack_error ("unknown ALSA avail_update return value (%u)", capture_avail);
if (driver->capture_handle) {
if ((capture_avail = snd_pcm_avail_update (driver->capture_handle)) < 0) {
if (capture_avail == -EPIPE) {
xrun_detected = TRUE;
} else {
jack_error ("unknown ALSA avail_update return value (%u)", capture_avail);
}
}
} else {
capture_avail = INT_MAX; /* odd, but see min() computation below */
}

if ((playback_avail = snd_pcm_avail_update (driver->playback_handle)) < 0) {
if (playback_avail == -EPIPE) {
xrun_detected = TRUE;
} else {
jack_error ("unknown ALSA avail_update return value (%u)", playback_avail);
if (driver->playback_handle) {
if ((playback_avail = snd_pcm_avail_update (driver->playback_handle)) < 0) {
if (playback_avail == -EPIPE) {
xrun_detected = TRUE;
} else {
jack_error ("unknown ALSA avail_update return value (%u)", playback_avail);
}
}
} else {
playback_avail = INT_MAX; /* odd, but see min() computation below */
}

if (xrun_detected) {
@@ -829,20 +889,61 @@ alsa_driver_process (alsa_driver_t *driver, nframes_t nframes)
channel_t chn;
GSList *node;
jack_engine_t *engine = driver->engine;
static int cnt = 0;

cnt++;

while (nframes) {

capture_avail = (nframes > driver->frames_per_cycle) ? driver->frames_per_cycle : nframes;
playback_avail = (nframes > driver->frames_per_cycle) ? driver->frames_per_cycle : nframes;
if (alsa_driver_get_channel_addresses (driver,
(snd_pcm_uframes_t *) &capture_avail,
(snd_pcm_uframes_t *) &playback_avail,
&capture_offset, &playback_offset) < 0) {
return -1;
}
if (driver->capture_handle) {

if (driver->playback_handle) {

/* DUPLEX */

capture_avail = (nframes > driver->frames_per_cycle) ? driver->frames_per_cycle : nframes;
playback_avail = (nframes > driver->frames_per_cycle) ? driver->frames_per_cycle : nframes;

contiguous = capture_avail < playback_avail ? capture_avail : playback_avail;
if (alsa_driver_get_channel_addresses (driver,
(snd_pcm_uframes_t *) &capture_avail,
(snd_pcm_uframes_t *) &playback_avail,
&capture_offset, &playback_offset) < 0) {
return -1;
}

contiguous = capture_avail < playback_avail ? capture_avail : playback_avail;

} else {

/* CAPTURE ONLY */

capture_avail = (nframes > driver->frames_per_cycle) ? driver->frames_per_cycle : nframes;
if (alsa_driver_get_channel_addresses (driver,
(snd_pcm_uframes_t *) &capture_avail,
(snd_pcm_uframes_t *) 0,
&capture_offset, 0) < 0) {
return -1;
}

contiguous = capture_avail;
}

} else {

/* PLAYBACK ONLY */

playback_avail = (nframes > driver->frames_per_cycle) ? driver->frames_per_cycle : nframes;
if (alsa_driver_get_channel_addresses (driver,
(snd_pcm_uframes_t *) 0,
(snd_pcm_uframes_t *) &playback_avail,
0, &playback_offset) < 0) {
return -1;
}
contiguous = playback_avail;
}

driver->channels_not_done = driver->channel_done_bits;

@@ -853,19 +954,21 @@ alsa_driver_process (alsa_driver_t *driver, nframes_t nframes)
GSList *node;
int ret;

for (chn = 0, node = driver->capture_ports; node; node = g_slist_next (node), chn++) {
port = (jack_port_t *) node->data;
if (!jack_port_connected (port)) {
continue;
if (driver->capture_handle) {
for (chn = 0, node = driver->capture_ports; node; node = g_slist_next (node), chn++) {
port = (jack_port_t *) node->data;
if (!jack_port_connected (port)) {
continue;
}
alsa_driver_read_from_channel (driver, chn, jack_port_get_buffer (port, nframes), nframes);
}
alsa_driver_read_from_channel (driver, chn, jack_port_get_buffer (port, nframes), nframes);
snd_pcm_mmap_commit (driver->capture_handle, capture_offset, contiguous);
}

snd_pcm_mmap_commit (driver->capture_handle, capture_offset, contiguous);
if ((ret = engine->process (engine, contiguous)) != 0) {
engine->process_unlock (engine);
alsa_driver_audio_stop (driver);
@@ -875,19 +978,22 @@ alsa_driver_process (alsa_driver_t *driver, nframes_t nframes)
return ret;
}

/* now move data from ports to channels */
for (chn = 0, node = driver->playback_ports; node; node = g_slist_next (node), chn++) {
jack_port_t *port = (jack_port_t *) node->data;

if (!jack_port_connected (port)) {
continue;
if (driver->playback_handle) {
/* now move data from ports to channels */
for (chn = 0, node = driver->playback_ports; node; node = g_slist_next (node), chn++) {
jack_port_t *port = (jack_port_t *) node->data;
if (!jack_port_connected (port)) {
continue;
}
alsa_driver_write_to_channel (driver, chn, jack_port_get_buffer (port, contiguous), contiguous);
}

alsa_driver_write_to_channel (driver, chn, jack_port_get_buffer (port, contiguous), contiguous);
}

engine->process_unlock (engine);
}

@@ -903,15 +1009,17 @@ alsa_driver_process (alsa_driver_t *driver, nframes_t nframes)
if (!driver->hw_monitoring) {

if (driver->all_monitor_in) {
for (chn = 0; chn < driver->playback_nchannels; chn++) {
alsa_driver_copy_channel (driver, chn, chn, contiguous);
}
} else if (driver->input_monitor_mask) {
for (chn = 0; chn < driver->playback_nchannels; chn++) {
if (driver->input_monitor_mask & (1<<chn)) {
if (driver->playback_handle) {
if (driver->all_monitor_in) {
for (chn = 0; chn < driver->playback_nchannels; chn++) {
alsa_driver_copy_channel (driver, chn, chn, contiguous);
}
} else if (driver->input_monitor_mask) {
for (chn = 0; chn < driver->playback_nchannels; chn++) {
if (driver->input_monitor_mask & (1<<chn)) {
alsa_driver_copy_channel (driver, chn, chn, contiguous);
}
}
}
}

@@ -922,12 +1030,14 @@ alsa_driver_process (alsa_driver_t *driver, nframes_t nframes)
}
}

if (driver->channels_not_done) {
alsa_driver_silence_untouched_channels (driver, contiguous);
if (driver->playback_handle) {
if (driver->channels_not_done) {
alsa_driver_silence_untouched_channels (driver, contiguous);
}
snd_pcm_mmap_commit (driver->playback_handle, playback_offset, contiguous);
}

snd_pcm_mmap_commit (driver->playback_handle, playback_offset, contiguous);

nframes -= contiguous;
}
@@ -1131,7 +1241,9 @@ alsa_driver_new (char *name, char *alsa_device,
nframes_t frames_per_cycle,
nframes_t user_nperiods,
nframes_t rate,
int hw_monitoring)
int hw_monitoring,
int capturing,
int playing)
{
int err;

@@ -1152,6 +1264,8 @@ alsa_driver_new (char *name, char *alsa_device,
driver->start = (JackDriverStartFunction) alsa_driver_audio_start;
driver->stop = (JackDriverStopFunction) alsa_driver_audio_stop;

driver->playback_handle = NULL;
driver->capture_handle = NULL;
driver->ctl_handle = 0;
driver->hw = 0;
driver->capture_and_playback_not_synced = FALSE;
@@ -1177,25 +1291,33 @@ alsa_driver_new (char *name, char *alsa_device,

pthread_mutex_init (&driver->clock_sync_lock, 0);
driver->clock_sync_listeners = 0;
if ((err = snd_pcm_open (&driver->playback_handle, alsa_device, SND_PCM_STREAM_PLAYBACK, 0)) < 0) {
jack_error ("ALSA: Cannot open PCM device %s/%s", name, alsa_device);
free (driver);
return 0;
}

driver->alsa_name = strdup (alsa_device);
if (playing) {
if ((err = snd_pcm_open (&driver->playback_handle, alsa_device, SND_PCM_STREAM_PLAYBACK, 0)) < 0) {
jack_error ("ALSA: Cannot open PCM device %s/%s", name, alsa_device);
free (driver);
return 0;
}
}

if ((err = snd_pcm_open (&driver->capture_handle, alsa_device, SND_PCM_STREAM_CAPTURE, 0)) < 0) {
snd_pcm_close (driver->playback_handle);
jack_error ("ALSA: Cannot open PCM device %s", name);
free (driver);
return 0;
if (capturing) {
if ((err = snd_pcm_open (&driver->capture_handle, alsa_device, SND_PCM_STREAM_CAPTURE, 0)) < 0) {
snd_pcm_close (driver->playback_handle);
jack_error ("ALSA: Cannot open PCM device %s", name);
free (driver);
return 0;
}
}

driver->alsa_name = strdup (alsa_device);

if (alsa_driver_check_card_type (driver)) {
snd_pcm_close (driver->capture_handle);
snd_pcm_close (driver->playback_handle);
if (driver->capture_handle) {
snd_pcm_close (driver->capture_handle);
}
if (driver->playback_handle) {
snd_pcm_close (driver->playback_handle);
}
free (driver);
return 0;
}
@@ -1205,28 +1327,32 @@ alsa_driver_new (char *name, char *alsa_device,
driver->playback_sw_params = 0;
driver->capture_sw_params = 0;

if ((err = snd_pcm_hw_params_malloc (&driver->playback_hw_params)) < 0) {
jack_error ("ALSA: could no allocate playback hw params structure");
alsa_driver_delete (driver);
return 0;
}
if (driver->playback_handle) {
if ((err = snd_pcm_hw_params_malloc (&driver->playback_hw_params)) < 0) {
jack_error ("ALSA: could no allocate playback hw params structure");
alsa_driver_delete (driver);
return 0;
}

if ((err = snd_pcm_hw_params_malloc (&driver->capture_hw_params)) < 0) {
jack_error ("ALSA: could no allocate capture hw params structure");
alsa_driver_delete (driver);
return 0;
if ((err = snd_pcm_sw_params_malloc (&driver->playback_sw_params)) < 0) {
jack_error ("ALSA: could no allocate playback sw params structure");
alsa_driver_delete (driver);
return 0;
}
}

if ((err = snd_pcm_sw_params_malloc (&driver->playback_sw_params)) < 0) {
jack_error ("ALSA: could no allocate playback sw params structure");
alsa_driver_delete (driver);
return 0;
}
if (driver->capture_handle) {
if ((err = snd_pcm_hw_params_malloc (&driver->capture_hw_params)) < 0) {
jack_error ("ALSA: could no allocate capture hw params structure");
alsa_driver_delete (driver);
return 0;
}

if ((err = snd_pcm_sw_params_malloc (&driver->capture_sw_params)) < 0) {
jack_error ("ALSA: could no allocate capture sw params structure");
alsa_driver_delete (driver);
return 0;
if ((err = snd_pcm_sw_params_malloc (&driver->capture_sw_params)) < 0) {
jack_error ("ALSA: could no allocate capture sw params structure");
alsa_driver_delete (driver);
return 0;
}
}

if (alsa_driver_set_parameters (driver, frames_per_cycle, user_nperiods, rate)) {
@@ -1234,10 +1360,12 @@ alsa_driver_new (char *name, char *alsa_device,
return 0;
}

if (snd_pcm_link (driver->capture_handle, driver->playback_handle) != 0) {
driver->capture_and_playback_not_synced = TRUE;
} else {
driver->capture_and_playback_not_synced = FALSE;
driver->capture_and_playback_not_synced = FALSE;

if (driver->capture_handle && driver->playback_handle) {
if (snd_pcm_link (driver->capture_handle, driver->playback_handle) != 0) {
driver->capture_and_playback_not_synced = TRUE;
}
}

alsa_driver_hw_specific (driver, hw_monitoring);
@@ -1310,7 +1438,9 @@ alsa PCM driver args:
-p frames-per-period (default: 1024)
-n periods-per-hardware-buffer (default: 2)
-H (use hardware monitoring if available, default: no)

-D (duplex, default: yes)
-C (capture, default: duplex)
-P (playback, default: duplex)
");
}

@@ -1322,6 +1452,8 @@ driver_initialize (int argc, char **argv)
unsigned long user_nperiods = 2;
char *pcm_name = "default";
int hw_monitoring = FALSE;
int capture = FALSE;
int playback = FALSE;
int i;

/* grrrr ... getopt() cannot be called in more than one "loop"
@@ -1332,6 +1464,19 @@ driver_initialize (int argc, char **argv)
for (i = 1; i < argc; i++) {
if (argv[i][0] == '-') {
switch (argv[i][1]) {
case 'D':
capture = TRUE;
playback = TRUE;
break;

case 'C':
capture = TRUE;
break;

case 'P':
playback = TRUE;
break;

case 'd':
pcm_name = argv[i+1];
i++;
@@ -1366,8 +1511,15 @@ driver_initialize (int argc, char **argv)
}
}

/* duplex is the default */

if (!capture && !playback) {
capture = TRUE;
playback = TRUE;
}

return alsa_driver_new ("alsa_pcm", pcm_name, frames_per_interrupt,
user_nperiods, srate, hw_monitoring);
user_nperiods, srate, hw_monitoring, capture, playback);
}

void


+ 1
- 1
configure.in View File

@@ -4,7 +4,7 @@ AC_INIT(client.c)
AC_CONFIG_AUX_DIR(.)

JACK_MAJOR_VERSION=0
JACK_MINOR_VERSION=13
JACK_MINOR_VERSION=14
JACK_MICRO_VERSION=0

BETA=


Loading…
Cancel
Save