PleasingFungus / Silicon-Zeroes

Issue repository for Silicon Zeroes. (Contains no actual code.)
12 stars 0 forks source link

Crash at startup on Linux when searching for an ALSA device #127

Open iamgreaser opened 6 years ago

iamgreaser commented 6 years ago

I have a setup which works fine as long as whatever you're using uses the default device and makes no attempt whatsoever to try to steal the sound card.

Regardless, it seems to be doing exactly what it should not be doing.

ALSA lib pcm_dmix.c:1099:(snd_pcm_dmix_open) unable to open slave
ALSA lib pcm_dmix.c:1099:(snd_pcm_dmix_open) unable to open slave

My setup's a bit odd. I have a 5.1 JACK setup and two methods for getting stereo ALSA routed to JACK (loopback bridge + raw JACK plugin). I have tried both approaches and both break.

Are you able to force the audio system to use default on ALSA?

PleasingFungus commented 6 years ago

Hm, that sounds like a Linux crash bug, all right! I've reached out to my local Linux expert - hopefully he'll have some advice.

amonakov commented 6 years ago

See also #114 (FMOD Studio ALSA backend bug). It seems it doesn't properly choose the default device.

amonakov commented 6 years ago

... although judging from the (lack of meaningful) response to the previous bug, we might as well take it in our own hands.

The following LD_PRELOAD hack can be used to override FMOD's default device selection. Normally it just dumps the list of output devices found by FMOD to stdout, but when FMODSUX_SETDRIVER environment variable is set, it will use its value to set FMOD output device.

It works for me as a workaround for #114 — please try if it helps in your case as well.

// gcc -shared -fpic -Os -o /tmp/Si0s.so this.c -ldl
#define _GNU_SOURCE 1
#include <dlfcn.h>
#include <stdlib.h>
#include <stdio.h>

int FMOD_System_GetNumDrivers(void *, int *);
int FMOD_System_GetDriverInfo(void *, int, char *, int, void *, int *, int *, int *);
int FMOD_System_SetDriver(void *, int);

int FMOD_System_Create(void** sys)
{
  __typeof(FMOD_System_Create) *real_create = dlsym(RTLD_NEXT, "FMOD_System_Create");
  if (!real_create) {
    fprintf(stderr, "dlsym: %s\n", dlerror());
    abort();
  }
  int ret, drv, numdrv;
  if ((ret = real_create(sys)))
    return ret;
  const char *drvstr = getenv("FMODSUX_SETDRIVER");
  if (drvstr && sscanf(drvstr, "%d", &drv) == 1)
    FMOD_System_SetDriver(*sys, drv);
  else if (!FMOD_System_GetNumDrivers(*sys, &numdrv))
    for (drv = 0; drv < numdrv; drv++) {
      char namebuf[50];
      int rate, mode, nch;
      if (!FMOD_System_GetDriverInfo(*sys, drv, namebuf, sizeof namebuf, 0, &rate, &mode, &nch))
    printf("%2d: mode %d, %d/%dch: %s\n", drv, mode, rate, nch, namebuf);
    }
  return 0;
}

Edited to add: credit goes to @SolraBizna for posting a similar hack for Don't Starve back in 2013. Thank you!