[Solved] "no channels" error in Linux/ALSA


#1

Hello,

When trying to connect to the sound card in Linux, I get the "no channels" error. I have no issue in Windows with this same code.

AudioDeviceManager *audioDeviceManager = new AudioDeviceManager;
String result = audioDeviceManager->initialiseWithDefaultDevices(0, 2); // result ends up being "no channels"

I traced as far as I could and it looks like juce is using an obsolete function:

snd_pcm_hw_params_get_channels_max

When I step in to that function, I see that it is getting a non-zero value, but it's not being passed back to the caller, probably because it's declared with this weird macro not to be a pointer:

__OLD_GET(snd_pcm_hw_params_get_channels_max, unsigned int, unsigned int);

I also see it marked as obsolete in pcm.c

OBSOLETE1(snd_pcm_hw_params_get_channels_max, ALSA_0.9, ALSA_0.9.0rc4);

I don't get what's going on but the result is that it sees no channels even though when I'm in this function, it's a high number like 1000. Has anyone looked into what call this should be replaced with?


#2

Hi pinkboi, which distribution are you using? If I step into the function on my ubuntu 14.04, I correctly get the version with the int pointer. It's strange because on my system there is also an old/deprecated version of the function which only takes one argument and will return the max channels as a return-value. However, JUCE does not seem to be using this. Looking at the header files pcm.h and pcm_old.h it seems that you need to make sure that ALSA_PCM_OLD_HW_PARAMS_API is not defined. Could it be that something in your code could be defining this?

However, there may be a related issue where I am not entirely sure how to interpret the ALSA API documentation of snd_pcm_hw_params_get_channels_max. Does the parameter val need to point to integer with defined value? If yes, what does the value mean? Currently, I'm setting this value to zero (modules/juce_audio_devices/native/juce_linux_ALSA.cpp line 98). Can you try setting the maxChansOut/maxChansIn variable to something really high and seeing what happens?

 


#3

A fairly new kubuntu installation (I think 15.04)


uname -a
Linux pinkboi-ThinkPad-T520 3.19.0-21-generic #21-Ubuntu SMP Sun Jun 14 18:31:11 UTC 2015 x86_64 x86_64 x86_64 GNU/Linux
 


#4

ALSA_PCM_OLD_HW_PARAMS_API isn't defined or even mentioned anywhere in my code. It looks like whatever it's set to, val gets reset to 0. It's really weird.


#5

Are you running ubuntu in a virtual machine? If yes, which one? If no, what sound card do you have.


#6

I'm not running it in a virutal machine but I figured it out. Alsa is weird and behaves differently depending on how you link to it. By linking it directly to JUCE rather than to my project, the problem went away. Weird.


#7

Could you be a bit more specific when you say "linking it directly to JUCE rathan than to my project"? Just so that other users can find a solution if they happen to stumble upon this problem. Thanks!


#8

This isn't letting me put html links in so apologies for the awkward links.

I have to link to alsa when building juce instead of linking my project that uses juce to alsa. I had to make my own cmake project to build juce to fix other problems I was having with juce (http://www.juce.com/forum/topic/differing-name-mangling-issues-creating-shared-object-linux).

Here are other people talking about the same problem:

https://www.mail-archive.com/alsa-devel@lists.sourceforge.net/msg10939.html
https://www.mail-archive.com/alsa-devel%40lists.sourceforge.net/msg10957.html


#9

After more research: ALSA lib uses an obsucure linux feature called "symbol versioning". See for example this comment on this site:

by default alsa-lib uses --with-versioned, which will create 2 sets of functions,
one for the old ABI that was deprecated over 10 years ago, and the current one,
with versioning symbols. since musl's symlinker previously didn't support
symbol versioning at all, the effect was that we got the wrong (old) functions
used instead of the new ones, which caused serious breakage.
musl now implements the subset of symbol versioning needed to get the default
symbol version, so this isn't strictly needed anymore - however using the versioned
stuff still bloats up the library with obsolete ancient junk nobody uses.

The problem is that if you link to a library (lets call it libfoo) which dynamically links to the old version of the symbols then all of the code dynamically links to libfoo will get the old version of the symbols. One option is to link to the static alsalib as this only contains the new version. Another option is to specifically link to alsa when building JUCE.