Browse Source

jack alsa: implement ALSA_DRIVER_FEAT_START_CLOSED

if enabled with '-x' option starts jackd with all devices closed, when
configured, user must provide number of channels for all devices, otherwise
we would not be able to create any jack ports.

we need to create all jack ports, since the only way to start any device
in this condition is to connect a jack port and issue a call
jack_client_reload_master

Change-Id: I63736eff20a2f2db7405ad512fec11e7bd0a9860
Signed-off-by: Adam Miartus <amiartus@de.adit-jv.com>
(cherry picked from commit 55d03f05d0)
Signed-off-by: Timo Wischer <twischer@de.adit-jv.com>
pull/608/head
Adam Miartus Timo Wischer 6 years ago
parent
commit
99bb68b8a2
3 changed files with 55 additions and 37 deletions
  1. +48
    -32
      linux/alsa/JackAlsaDriver.cpp
  2. +6
    -5
      linux/alsa/alsa_driver.c
  3. +1
    -0
      linux/alsa/alsa_driver.h

+ 48
- 32
linux/alsa/JackAlsaDriver.cpp View File

@@ -360,9 +360,29 @@ int JackAlsaDriver::Open(alsa_driver_info_t info)
return -1;
}

// ALSA driver may have changed the in/out values
fCaptureChannels = ((alsa_driver_t *)fDriver)->capture_nchannels;
fPlaybackChannels = ((alsa_driver_t *)fDriver)->playback_nchannels;
/* this feature caused driver to skip opening alsa devices, therefore populate channels from user input */
if (info.features & ALSA_DRIVER_FEAT_START_CLOSED) {
for (size_t i = 0; i < std::max(info.devices_capture_size, info.devices_playback_size); ++i) {
if (i < info.devices_capture_size && info.devices[i].capture_channels < 1) {
jack_error ("invalid or missing channels parameter with '-x' option 'start-closed' for device C: '%s'", info.devices[i].capture_name);
Close();
return -1;
}

if (i < info.devices_playback_size && info.devices[i].playback_channels < 1) {
jack_error ("invalid or missing channels parameter with '-x' option 'start-closed' for device P: '%s'", info.devices[i].playback_name);
Close();
return -1;
}

fCaptureChannels += info.devices[i].capture_channels;
fPlaybackChannels += info.devices[i].playback_channels;
}
/* in case we really opened alsa devices, channel information is generated by driver */
} else {
fCaptureChannels = ((alsa_driver_t *)fDriver)->capture_nchannels;
fPlaybackChannels = ((alsa_driver_t *)fDriver)->playback_nchannels;
}

#ifndef __QNXNTO__
if (JackServerGlobals::on_device_reservation_loop != NULL) {
@@ -565,7 +585,11 @@ int JackAlsaDriver::TargetState(int init, int connections_count)
if (connections_count > 0) {
state = SND_PCM_STATE_RUNNING;
} else if (init) {
state = SND_PCM_STATE_RUNNING;
if (driver->features & ALSA_DRIVER_FEAT_START_CLOSED) {
state = SND_PCM_STATE_NOTREADY;
} else {
state = SND_PCM_STATE_RUNNING;
}
} else if (driver->features & ALSA_DRIVER_FEAT_CLOSE_IDLE_DEVS) {
state = SND_PCM_STATE_NOTREADY;
} else {
@@ -838,8 +862,8 @@ SERVER_EXPORT const jack_driver_desc_t* driver_get_descriptor ()
NULL);

strcpy(value.str, "none");
jack_driver_descriptor_add_parameter(desc, &filler, "inchannels", 'i', JackDriverParamString, &value, NULL, "List of device capture channels (defaults to hardware max)", NULL);
jack_driver_descriptor_add_parameter(desc, &filler, "outchannels", 'o', JackDriverParamString, &value, NULL, "List of device playback channels (defaults to hardware max)", NULL);
jack_driver_descriptor_add_parameter(desc, &filler, "inchannels", 'i', JackDriverParamString, &value, NULL, "List of device capture channels (defaults to hw max)", NULL);
jack_driver_descriptor_add_parameter(desc, &filler, "outchannels", 'o', JackDriverParamString, &value, NULL, "List of device playback channels (defaults to hw max)", NULL);

value.i = FALSE;
jack_driver_descriptor_add_parameter(desc, &filler, "shorts", 'S', JackDriverParamBool, &value, NULL, "Try 16-bit samples before 32-bit", NULL);
@@ -862,6 +886,9 @@ SERVER_EXPORT const jack_driver_desc_t* driver_get_descriptor ()
"ALSA MIDI driver",
NULL);

value.i = 0;
jack_driver_descriptor_add_parameter(desc, &filler, "start-closed", 'x', JackDriverParamBool, &value, NULL, "Start with all devices closed", NULL);

value.i = 0;
jack_driver_descriptor_add_parameter(desc, &filler, "close-idle-devs", 'c', JackDriverParamBool, &value, NULL, "Close idle devices on alsa driver restart request", NULL);

@@ -878,8 +905,7 @@ struct array_string_t
discard_duplicate,
};

uint64_t size;
char **data;
std::vector<char*> data;
};

void array_string_free(struct array_string_t *obj)
@@ -887,49 +913,35 @@ void array_string_free(struct array_string_t *obj)
if (obj == NULL) {
return;
}
if (obj->data == NULL) {
return;
}
for (size_t i = 0; i < obj->size; ++i) {
for (size_t i = 0; i < obj->data.size(); ++i) {
free(obj->data[i]);
}
free(obj->data);
obj->data = NULL;
obj->size = 0;
}

struct array_string_t array_string_split(const char *str, const char sep, array_string_t::flags flags = array_string_t::none)
{
struct array_string_t result;
result.size = 0;

std::stringstream stream;
stream << std::string(str);
if (stream.str().find(sep) == std::string::npos) {
result.data = (char**) calloc(1, sizeof(char*));
result.data[0] = (char*) calloc(JACK_CLIENT_NAME_SIZE + 1, sizeof(char));
result.size = 1;
result.data.push_back((char*) calloc(JACK_CLIENT_NAME_SIZE + 1, sizeof(char)));
strncpy(result.data[0], str, JACK_CLIENT_NAME_SIZE);
result.data[0][JACK_CLIENT_NAME_SIZE] = '\0';
return result;
}

std::string driver;
std::vector<char*> drivers;
while (std::getline(stream, driver, sep)) {
driver.erase(std::remove_if(driver.begin(), driver.end(), isspace), driver.end());
if (std::find(drivers.begin(), drivers.end(), driver) != drivers.end() && (flags & array_string_t::discard_duplicate))
if (std::find(result.data.begin(), result.data.end(), driver) != result.data.end() && (flags & array_string_t::discard_duplicate))
continue;
char *str = (char*) calloc(JACK_CLIENT_NAME_SIZE + 1, sizeof(char));
strncpy(str, driver.c_str(), JACK_CLIENT_NAME_SIZE);
str[JACK_CLIENT_NAME_SIZE] = '\0';
drivers.push_back(str);
result.data.push_back(str);
}

result.data = (char**) calloc(driver.size(), sizeof(char*));
result.size = drivers.size();
memcpy(result.data, drivers.data(), result.size * sizeof(char*));

return result;
}

@@ -1059,6 +1071,10 @@ SERVER_EXPORT Jack::JackDriverClientInterface* driver_initialize(Jack::JackLocke
info.midi_name = strdup(param->value.str);
break;

case 'x':
info.features |= param->value.i ? ALSA_DRIVER_FEAT_START_CLOSED : 0;
break;

case 'c':
info.features |= param->value.i ? ALSA_DRIVER_FEAT_CLOSE_IDLE_DEVS : 0;
break;
@@ -1107,20 +1123,20 @@ SERVER_EXPORT Jack::JackDriverClientInterface* driver_initialize(Jack::JackLocke
free(playback_channels_param);
}

info.devices_capture_size = capture_names.size;
info.devices_playback_size = playback_names.size;
info.devices_capture_size = capture_names.data.size();
info.devices_playback_size = playback_names.data.size();
info.devices = (alsa_device_info_t*) calloc(std::max(info.devices_capture_size, info.devices_playback_size), sizeof(alsa_device_info_t));
for (size_t i = 0; i < std::max(info.devices_capture_size, info.devices_playback_size); ++i) {
if (i < capture_names.size) {
if (i < capture_names.data.size()) {
info.devices[i].capture_name = strdup(capture_names.data[i]);
}
if (i < capture_channels.size) {
if (i < capture_channels.data.size()) {
info.devices[i].capture_channels = atoi(capture_channels.data[i]);
}
if (i < playback_names.size) {
if (i < playback_names.data.size()) {
info.devices[i].playback_name = strdup(playback_names.data[i]);
}
if (i < playback_channels.size) {
if (i < playback_channels.data.size()) {
info.devices[i].playback_channels = atoi(playback_channels.data[i]);
}
}


+ 6
- 5
linux/alsa/alsa_driver.c View File

@@ -1156,9 +1156,10 @@ alsa_driver_set_parameters (alsa_driver_t *driver,
}
#endif

alsa_driver_setup_io_function_pointers (driver, device);

/* do only on first start */
if (device->max_nchannels == 0) {
alsa_driver_setup_io_function_pointers (driver, device);

/* Allocate and initialize structures that rely on the
channels counts.
@@ -1182,7 +1183,7 @@ alsa_driver_set_parameters (alsa_driver_t *driver,
bitset_create (&device->channels_done, device->max_nchannels);
bitset_create (&device->channels_not_done, device->max_nchannels);

if (device->playback_handle) {
if (device->playback_name) {
device->playback_addr = (char **)
malloc (sizeof (char *) * device->playback_nchannels);
memset (device->playback_addr, 0,
@@ -1206,7 +1207,7 @@ alsa_driver_set_parameters (alsa_driver_t *driver,
driver->dither_state = (dither_state_t *) calloc (device->playback_nchannels, sizeof (dither_state_t));
}

if (device->capture_handle) {
if (device->capture_name) {
device->capture_addr = (char **)
malloc (sizeof (char *) * device->capture_nchannels);
memset (device->capture_addr, 0,
@@ -1388,7 +1389,7 @@ alsa_driver_open (alsa_driver_t *driver)
alsa_device_t *device = &driver->devices[i];
int do_capture = 0, do_playback = 0;

if (!device->capture_handle && (i <driver->devices_c_count) && (device->capture_target_state != SND_PCM_STATE_NOTREADY)) {
if (!device->capture_handle && (i < driver->devices_c_count) && (device->capture_target_state != SND_PCM_STATE_NOTREADY)) {
err = alsa_driver_open_device (driver, &driver->devices[i], SND_PCM_STREAM_CAPTURE);
if (err < 0) {
jack_error ("\n\nATTENTION: Opening of the capture device \"%s\" failed.",
@@ -1399,7 +1400,7 @@ alsa_driver_open (alsa_driver_t *driver)
do_capture = 1;
}

if (!device->playback_handle && (i <driver->devices_p_count) && (device->playback_target_state != SND_PCM_STATE_NOTREADY)) {
if (!device->playback_handle && (i < driver->devices_p_count) && (device->playback_target_state != SND_PCM_STATE_NOTREADY)) {
err = alsa_driver_open_device (driver, &driver->devices[i], SND_PCM_STREAM_PLAYBACK);
if (err < 0) {
jack_error ("\n\nATTENTION: Opening of the playback device \"%s\" failed.",


+ 1
- 0
linux/alsa/alsa_driver.h View File

@@ -69,6 +69,7 @@ typedef int32_t alsa_driver_default_format_t;
#define SND_PCM_STATE_NOTREADY (SND_PCM_STATE_LAST + 1)
#endif

#define ALSA_DRIVER_FEAT_START_CLOSED (1 << 0)
#define ALSA_DRIVER_FEAT_CLOSE_IDLE_DEVS (1 << 1)
#define ALSA_DRIVER_FEAT_UNLINKED_DEVS (1 << 2)



Loading…
Cancel
Save