Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ADIT alsa improvement backports #949

Open
wants to merge 12 commits into
base: master
Choose a base branch
from
Open
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
200 changes: 102 additions & 98 deletions linux/alsa/alsa_driver.c
Original file line number Diff line number Diff line change
Expand Up @@ -2062,6 +2062,97 @@ discover_alsa_using_apps ()
}
}

static int
alsa_driver_open (alsa_driver_t *driver, bool is_capture)
Copy link
Contributor

@imaami imaami Dec 19, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Using SND_PCM_STREAM_PLAYBACK and SND_PCM_STREAM_CAPTURE as arguments to a boolean function parameter makes the whole thing unnecessarily complicated, and is at least in theory susceptible to breakage if the ALSA API changes (unlikely but not impossible). You can remove a lot of the if-else boilerplate by being more straightforward with the typing, and adding a couple of variables:

static int
alsa_driver_open (alsa_driver_t *driver, snd_pcm_stream_t stream)
{
	snd_pcm_t **phandle;
	const char *name;

	if (stream == SND_PCM_STREAM_CAPTURE) {
		phandle = &driver->capture_handle;
		name = driver->alsa_name_capture;
	} else {
		phandle = &driver->playback_handle;
		name = driver->alsa_name_playback;
	}

	err = snd_pcm_open (phandle, name, stream, SND_PCM_NONBLOCK);

	if (err < 0) {
		switch (errno) {
		case EBUSY:
#ifdef __ANDROID__
			jack_error ("\n\nATTENTION: The device \"%s\" is "
				    "already in use. Please stop the"
				    " application using it and "
				    "run JACK again", name);
#else
			current_apps = discover_alsa_using_apps ();
			if (current_apps) {
				jack_error ("\n\nATTENTION: The device \"%s\" is "
					    "already in use. The following applications "
					    " are using your soundcard(s) so you should "
					    " check them and stop them as necessary before "
					    " trying to start JACK again:\n\n%s", name,
					    current_apps);
				free (current_apps);
			} else {
				jack_error ("\n\nATTENTION: The device \"%s\" is "
					    "already in use. Please stop the"
					    " application using it and "
					    "run JACK again", name);
			}
#endif
			break;

		case EPERM:
			jack_error ("you do not have permission to open "
				    "the audio device \"%s\" for playback", name);
			break;

		case EINVAL:
			jack_error ("the state of handle or the mode is invalid "
				    "or invalid state change occured \"%s\" for playback", name);
			break;

		case ENOENT:
			jack_error ("device \"%s\"  does not exist for playback", name);
			break;

		case ENOMEM:
			jack_error ("Not enough memory available for allocation for \"%s\" for playback",
				    name);
			break;

		case SND_ERROR_INCOMPATIBLE_VERSION:
			jack_error ("Version mismatch \"%s\" for playback", name);
			break;
		}

		alsa_driver_delete (driver);
		*phandle = NULL;
	}

	if (*phandle)
		snd_pcm_nonblock (*phandle, 0);

	return err;
}

{
int err = 0;
char* current_apps;

if(is_capture) {
err = snd_pcm_open (&driver->capture_handle,
driver->alsa_name_capture,
SND_PCM_STREAM_CAPTURE,
SND_PCM_NONBLOCK);
} else {
err = snd_pcm_open (&driver->playback_handle,
driver->alsa_name_playback,
SND_PCM_STREAM_PLAYBACK,
SND_PCM_NONBLOCK);
}
if (err < 0) {
switch (errno) {
case EBUSY:
#ifdef __ANDROID__
jack_error ("\n\nATTENTION: The device \"%s\" is "
"already in use. Please stop the"
" application using it and "
"run JACK again",
is_capture ? driver->alsa_name_capture : driver->alsa_name_playback);
#else
current_apps = discover_alsa_using_apps ();
if (current_apps) {
jack_error ("\n\nATTENTION: The device \"%s\" is "
"already in use. The following applications "
" are using your soundcard(s) so you should "
" check them and stop them as necessary before "
" trying to start JACK again:\n\n%s",
is_capture ? driver->alsa_name_capture : driver->alsa_name_playback,
current_apps);
free (current_apps);
} else {
jack_error ("\n\nATTENTION: The device \"%s\" is "
"already in use. Please stop the"
" application using it and "
"run JACK again",
is_capture ? driver->alsa_name_capture : driver->alsa_name_playback);
}
#endif
break;

case EPERM:
jack_error ("you do not have permission to open "
"the audio device \"%s\" for playback",
is_capture ? driver->alsa_name_capture : driver->alsa_name_playback);
break;

case EINVAL:
jack_error ("the state of handle or the mode is invalid "
"or invalid state change occured \"%s\" for playback",
is_capture ? driver->alsa_name_capture : driver->alsa_name_playback);
break;

case ENOENT:
jack_error ("device \"%s\" does not exist for playback",
is_capture ? driver->alsa_name_capture : driver->alsa_name_playback);
break;

case ENOMEM:
jack_error ("Not enough memory available for allocation for \"%s\" for playback",
is_capture ? driver->alsa_name_capture : driver->alsa_name_playback);
break;

case SND_ERROR_INCOMPATIBLE_VERSION:
jack_error ("Version mismatch \"%s\" for playback",
is_capture ? driver->alsa_name_capture : driver->alsa_name_playback);
break;
}
alsa_driver_delete (driver);
if(is_capture) {
driver->capture_handle = NULL;
} else {
driver->playback_handle = NULL;
}
}

if (is_capture && driver->capture_handle) {
snd_pcm_nonblock (driver->capture_handle, 0);
} else if(!is_capture && driver->playback_handle) {
snd_pcm_nonblock (driver->playback_handle, 0);
}

return err;
}

jack_driver_t *
alsa_driver_new (char *name, char *playback_alsa_device,
char *capture_alsa_device,
Expand All @@ -2085,7 +2176,6 @@ alsa_driver_new (char *name, char *playback_alsa_device,
)
{
int err;
char* current_apps;
alsa_driver_t *driver;

jack_info ("creating alsa driver ... %s|%s|%" PRIu32 "|%" PRIu32
Expand Down Expand Up @@ -2176,105 +2266,19 @@ alsa_driver_new (char *name, char *playback_alsa_device,
alsa_driver_hw_specific (driver, hw_monitoring, hw_metering);

if (playing) {
if (snd_pcm_open (&driver->playback_handle,
playback_alsa_device,
SND_PCM_STREAM_PLAYBACK,
SND_PCM_NONBLOCK) < 0) {
switch (errno) {
case EBUSY:
#ifdef __ANDROID__
jack_error ("\n\nATTENTION: The playback device \"%s\" is "
"already in use. Please stop the"
" application using it and "
"run JACK again",
playback_alsa_device);
#else
current_apps = discover_alsa_using_apps ();
if (current_apps) {
jack_error ("\n\nATTENTION: The playback device \"%s\" is "
"already in use. The following applications "
" are using your soundcard(s) so you should "
" check them and stop them as necessary before "
" trying to start JACK again:\n\n%s",
playback_alsa_device,
current_apps);
free (current_apps);
} else {
jack_error ("\n\nATTENTION: The playback device \"%s\" is "
"already in use. Please stop the"
" application using it and "
"run JACK again",
playback_alsa_device);
}
#endif
alsa_driver_delete (driver);
return NULL;

case EPERM:
jack_error ("you do not have permission to open "
"the audio device \"%s\" for playback",
playback_alsa_device);
alsa_driver_delete (driver);
return NULL;
break;
}

driver->playback_handle = NULL;
}

if (driver->playback_handle) {
snd_pcm_nonblock (driver->playback_handle, 0);
err = alsa_driver_open(driver, SND_PCM_STREAM_PLAYBACK);
if(err < 0) {
jack_error ("\n\nATTENTION: Opening of the playback device \"%s\" failed.",
playback_alsa_device);
return NULL;
}
}

if (capturing) {
if (snd_pcm_open (&driver->capture_handle,
capture_alsa_device,
SND_PCM_STREAM_CAPTURE,
SND_PCM_NONBLOCK) < 0) {
switch (errno) {
case EBUSY:
#ifdef __ANDROID__
jack_error ("\n\nATTENTION: The capture (recording) device \"%s\" is "
"already in use",
capture_alsa_device);
#else
current_apps = discover_alsa_using_apps ();
if (current_apps) {
jack_error ("\n\nATTENTION: The capture device \"%s\" is "
"already in use. The following applications "
" are using your soundcard(s) so you should "
" check them and stop them as necessary before "
" trying to start JACK again:\n\n%s",
capture_alsa_device,
current_apps);
free (current_apps);
} else {
jack_error ("\n\nATTENTION: The capture (recording) device \"%s\" is "
"already in use. Please stop the"
" application using it and "
"run JACK again",
capture_alsa_device);
}
alsa_driver_delete (driver);
return NULL;
#endif
break;

case EPERM:
jack_error ("you do not have permission to open "
"the audio device \"%s\" for capture",
capture_alsa_device);
alsa_driver_delete (driver);
return NULL;
break;
}

driver->capture_handle = NULL;
}

if (driver->capture_handle) {
snd_pcm_nonblock (driver->capture_handle, 0);
if(capturing) {
err = alsa_driver_open(driver, SND_PCM_STREAM_CAPTURE);
if(err < 0) {
jack_error ("\n\nATTENTION: Opening of the capture device \"%s\" failed.",
capture_alsa_device);
return NULL;
}
}

Expand Down