124 lines
3.6 KiB
C++
124 lines
3.6 KiB
C++
/*
|
|
*******************************************************************************
|
|
* INCLUDE
|
|
*******************************************************************************
|
|
*/
|
|
#include "SoundCard.h"
|
|
#include <Poco/Format.h>
|
|
|
|
namespace Video
|
|
{
|
|
namespace ALSA
|
|
{
|
|
/*
|
|
*******************************************************************************
|
|
* CLASS DEFINE
|
|
*******************************************************************************
|
|
*/
|
|
SoundCard::SoundCard(int index): _index(index)
|
|
{
|
|
initialize();
|
|
}
|
|
|
|
SoundCard::~SoundCard()
|
|
{
|
|
}
|
|
|
|
void SoundCard::initialize()
|
|
{
|
|
_info.device = Poco::format("hw:%d", _index);
|
|
int rc;
|
|
snd_ctl_t* handle;
|
|
if ((rc = snd_ctl_open(&handle, _info.device.c_str(), 0)) < 0)
|
|
throw Poco::InvalidAccessException("SoundCard: Cannot open device");
|
|
|
|
snd_ctl_card_info_t* info;
|
|
snd_ctl_card_info_alloca(&info);
|
|
if ((rc = snd_ctl_card_info(handle, info)) < 0)
|
|
throw Poco::InvalidAccessException("SoundCard: Cannot get card info");
|
|
|
|
_info.id = snd_ctl_card_info_get_id(info);
|
|
_info.name = snd_ctl_card_info_get_name(info);
|
|
_info.longname = snd_ctl_card_info_get_longname(info);
|
|
_info.driver = snd_ctl_card_info_get_driver(info);
|
|
_info.components = snd_ctl_card_info_get_components(info);
|
|
_info.mixername = snd_ctl_card_info_get_mixername(info);
|
|
|
|
snd_ctl_close(handle);
|
|
|
|
auto enumerateCapabilities = [](snd_pcm_t* pcm, Info& info)
|
|
{
|
|
snd_pcm_hw_params_t* params;
|
|
snd_pcm_hw_params_alloca(¶ms);
|
|
snd_pcm_hw_params_any(pcm, params);
|
|
|
|
for (int access = 0; access <= SND_PCM_ACCESS_LAST; access++)
|
|
info.access[access] = (snd_pcm_hw_params_test_access(pcm, params, (snd_pcm_access_t)access) == 0);
|
|
|
|
for (int format = 0; format <= SND_PCM_FORMAT_LAST; format++)
|
|
{
|
|
if (snd_pcm_hw_params_test_format(pcm, params, (snd_pcm_format_t)format) == 0)
|
|
info.formats.push_back((snd_pcm_format_t)format);
|
|
}
|
|
|
|
for (unsigned int rate = 1000; rate <= 384000; rate += 1000)
|
|
{
|
|
if (snd_pcm_hw_params_test_rate(pcm, params, rate, 0) == 0)
|
|
info.sampleRates.push_back(rate);
|
|
}
|
|
|
|
for (int channels = 1; channels <= 16; channels++)
|
|
{
|
|
if (snd_pcm_hw_params_test_channels(pcm, params, channels) == 0)
|
|
{
|
|
info.channels = channels;
|
|
break;
|
|
}
|
|
}
|
|
|
|
for (snd_pcm_uframes_t val = 16; val <= 1048576; val *= 2)
|
|
{
|
|
if (snd_pcm_hw_params_test_buffer_size(pcm, params, val) == 0)
|
|
info.bufferSizes.push_back(val);
|
|
}
|
|
};
|
|
|
|
snd_pcm_t* pcm;
|
|
int err = snd_pcm_open(&pcm, _info.device.c_str(), SND_PCM_STREAM_CAPTURE, 0);
|
|
if (err < 0)
|
|
_info.supportCapture = false;
|
|
else
|
|
{
|
|
_info.supportCapture = true;
|
|
enumerateCapabilities(pcm, _info);
|
|
snd_pcm_close(pcm);
|
|
}
|
|
|
|
err = snd_pcm_open(&pcm, _info.device.c_str(), SND_PCM_STREAM_PLAYBACK, 0);
|
|
if (err < 0)
|
|
_info.supportPlayback = false;
|
|
else
|
|
{
|
|
_info.supportPlayback = true;
|
|
if (!_info.supportCapture)
|
|
enumerateCapabilities(pcm, _info);
|
|
snd_pcm_close(pcm);
|
|
}
|
|
}
|
|
|
|
SoundCard::Info& SoundCard::info()
|
|
{
|
|
return _info;
|
|
}
|
|
|
|
SoundCard::SoundCards SoundCard::getSoundCards()
|
|
{
|
|
SoundCards cards;
|
|
int id = -1;
|
|
while (snd_card_next(&id), id >= 0)
|
|
cards.push_back(new SoundCard(id));
|
|
|
|
return cards;
|
|
}
|
|
}
|
|
}
|