Finding all the devices I can use to play PCM with ALSA
Asked Answered
F

3

7

I use ALSA to play PCM samples. I open the PCM stream with this function:

int snd_pcm_open(snd_pcm_t** pcmp,
        const char* name,
        snd_pcm_stream_t stream,
        int mode);

I'm currently using "default" as the name parameter. I would like to be able to choose other devices. What I cannot understand is how I can determine what are the names of the other available devices.

I attached a USB microphone to my system and aplay and amixer seems to detect the new device. How do I determine the name of that device? Is there any ALSA function to get a list of available devices with their respective names?

Fourchette answered 28/7, 2011 at 21:41 Comment(0)
T
15

I think you can use snd_device_name_hint for enumerating devices. Here is an example. Beware that I haven't compiled it !

char **hints;
/* Enumerate sound devices */
int err = snd_device_name_hint(-1, "pcm", (void***)&hints);
if (err != 0)
   return;//Error! Just return

char** n = hints;
while (*n != NULL) {

    char *name = snd_device_name_get_hint(*n, "NAME");

    if (name != NULL && 0 != strcmp("null", name)) {
        //Copy name to another buffer and then free it
        free(name);
    }
    n++;
}//End of while

//Free hint buffer too
snd_device_name_free_hint((void**)hints);
Trophy answered 29/7, 2011 at 8:1 Comment(2)
name isn't freed when in the second part of the if statement 0 != strcmp("null", name) when the name does equal "null". Perhaps add an extra if inside the if to do someting usefull with name when it doesn't equal "null", but always free it.Anxiety
The type of hints and n should be void**. Then you could also get rid of the casts.Unseemly
W
5

It was my first requirements to a linux/unix projects where I need to know about all of the available audio devices capability and name. Then I need to use these devices to capture and plaback the audio. What I have done is pretty simple. There is a linux/unix command which is used to find the devices through alsa utility in linux.

It is:

aplay -l

Now what I did is just make a programme to give the out as like as this by alsa.

For everyone's help I have made a (.so) library and a sample Application demonstrating the use of this library in c++.

The output of my library is like-

[root@~]# ./IdeaAudioEngineTest
HDA Intel plughw:0,0
HDA Intel plughw:0,2
USB Audio Device plughw:1,0

This library can also capture and playback the real-time audio data.

It is available with documentation in IdeaAudio library with Duplex Alsa Audio

Wharfage answered 1/8, 2013 at 12:23 Comment(7)
Hi :) the lib looks nice but is there any Java wrapper for it?Propinquity
sorry, currently we don't have it.Wharfage
Ok then; Do you know how to get speakers or headphone paths; I tried many times but path like hw:0,0 or even hw:0,1 always returns microphone :( I have duplex jack which supports both headphones or microphone ...Propinquity
The execution of IdeaAudioEngineTest will return all of the plugged in capture and playback devices name. Then you just need to use them on library capture and playback API as input. Complete source code of this project is available [here|github.com/robelsharma/IdeaAudio/].Wharfage
thanks but I meant is there to use aplay util to get speakers/headphone device paths?Propinquity
We did it programmatic way. How we did it can be found here github.com/robelsharma/IdeaAudio/blob/master/IdeaLib/… in AvailableAudioDevices() function.Wharfage
@Robel Sharma: Nice, but it fails to detect devices that are currently in use (the snd_ctl_open call fails). Probably the optimal solution is to ferret away a copy of the info for the device you're about to open, and copy it into subsequent enumerations of available devices. Painful, but it seems to be the only way to get device info in alsa.Fuchs
X
3

Just for grins, your program reformatted:

#include <stdio.h>
#include <limits.h>
#include <stdlib.h>
#include <unistd.h>

#include <alsa/asoundlib.h>

void listdev(char *devname)

{

    char** hints;
    int    err;
    char** n;
    char*  name;
    char*  desc;
    char*  ioid;

    /* Enumerate sound devices */
    err = snd_device_name_hint(-1, devname, (void***)&hints);
    if (err != 0) {

        fprintf(stderr, "*** Cannot get device names\n");
        exit(1);

    }

    n = hints;
    while (*n != NULL) {

        name = snd_device_name_get_hint(*n, "NAME");
        desc = snd_device_name_get_hint(*n, "DESC");
        ioid = snd_device_name_get_hint(*n, "IOID");

        printf("Name of device: %s\n", name);
        printf("Description of device: %s\n", desc);
        printf("I/O type of device: %s\n", ioid);
        printf("\n");

        if (name && strcmp("null", name)) free(name);
        if (desc && strcmp("null", desc)) free(desc);
        if (ioid && strcmp("null", ioid)) free(ioid);
        n++;

    }

    //Free hint buffer too
    snd_device_name_free_hint((void**)hints);

}

int main(void)

{

    printf("PCM devices:\n");
    printf("\n");
    listdev("pcm");

    printf("MIDI devices:\n");
    printf("\n");
    listdev("rawmidi");

    return 0;

}
Xenon answered 6/7, 2019 at 5:54 Comment(1)
If you used void ** for the type of hints and n instead of char ** you wouldn't need the casts.Unseemly

© 2022 - 2024 — McMap. All rights reserved.