|
|
|
Started: 11/12/2008 5:40 AM | |  | |
|  | Can't open capture device on Linux I have tried a lot of things, and no matter what I do, alcCaptureOpenDevice() returns NULL. Except when I choose the standard ALSA capture device, but then I get no sound. alGetError and alcGetError both returns AL_NO_ERROR which is quite odd, when it doesn't work.
I hope someone can help me with this, because I'm growing very frustrated.
I'm working on Kubuntu 8.10 using the precompiled openal.
The code works fine on Windows XP with Visual Studio 2005.
Here is the code that I'm using. The initialization is split in two functions. They are called in the order below. The first one opens the output device, and that works fine on both Linux and Windows. The second opens the capture device, and that only works on Windows.
Don't let the Qt code fool you. I have tried using the exact same chars coming from alcGetString(NULL, ALC_CAPTURE_DEVICE_SPECIFIER) as the specifier for the device without any luck.
I have tried running the application under KDE 4 and Fluxbox (to test if a KDE sound service had grabbed the sound card). No difference.
I'm hoping one of you have an idea about something I can do to move on. I'm running out of things to test and debug.
bool OpenALConnector::init() {
ALDeviceList pDeviceList;
const int deviceCount = pDeviceList.getNumDevices();
if (deviceCount == 0) {
QMessageBox::critical(0, tr("Sound error"), tr("No available sound device"));
return false;
}
ALCdevice *pDevice = 0;
if (deviceCount == 1) {
// No need to ask the user
pDevice = alcOpenDevice(pDeviceList.getDeviceName(0).toAscii().constData());
} else {
// More than one to choose from
QStringList deviceNames;
for (int i = 0; i < deviceCount; ++i) {
const QString name(pDeviceList.getDeviceName(i));
if (i == pDeviceList.getDefaultDevice())
deviceNames << tr("%1 (default device)").arg(name);
else
deviceNames << name;
}
bool ok;
const QString chosenName(QInputDialog::getItem(0, tr("Sound Device..."), tr("Choose sound device"), deviceNames, 0, false, &ok));
if (!ok || chosenName.isEmpty()) {
// User cancelled the dialog
return false;
} else {
const int i = deviceNames.indexOf(chosenName);
if (i < 0)
// ??? This shouldn't be possible
return false;
pDevice = alcOpenDevice(pDeviceList.getDeviceName(i).toAscii().constData());
}
}
if (pDevice == 0) {
QMessageBox::critical(0, tr("Sound error"), tr("Failed to open sound device"));
return false;
}
ALCcontext* pContext = alcCreateContext(pDevice, 0);
if (pContext == 0) {
alcCloseDevice(pDevice);
QMessageBox::critical(0, tr("Sound error"), tr("Failed to use sound device"));
return false;
}
qDebug("Opened %s device", alcGetString(pDevice, ALC_DEVICE_SPECIFIER));
alcMakeContextCurrent(pContext);
// Minor optimization: Don't do 3D spatialization
alDistanceModel(AL_NONE);
return true;
}
bool Transmitter::init() {
ALCcontext* const pContext = alcGetCurrentContext();
ALCdevice* const pDevice = alcGetContextsDevice(pContext);
if (alcIsExtensionPresent(pDevice, "ALC_EXT_CAPTURE") == AL_FALSE) {
QMessageBox::critical(0, "Sound Problem", "Failed to detect Capture Extension\n");
return false;
}
// Get list of available Capture Devices
const ALchar *pDeviceList = alcGetString(NULL, ALC_CAPTURE_DEVICE_SPECIFIER);
QStringList devices;
while (pDeviceList != 0 && *pDeviceList != '\0') {
devices << pDeviceList;
pDeviceList += strlen(pDeviceList) + 1;
}
// Get the name of the 'default' capture device
QString defaultCaptureDevice(alcGetString(NULL, ALC_CAPTURE_DEFAULT_DEVICE_SPECIFIER));
// Choose the output device
QString device;
int deviceNo;
if (devices.count() == 1) {
// Not much to choose from
device = devices.at(deviceNo = 0);
} else {
QStringList deviceNames;
foreach (const QString& name, devices) {
if (name == defaultCaptureDevice)
deviceNames << tr("%1 (default device)").arg(name);
else
deviceNames << name;
}
bool ok;
const QString chosenName(QInputDialog::getItem(0, tr("Sound Device..."), tr("Choose recording device"), deviceNames, 0, false, &ok));
if (!ok || chosenName.isEmpty()) {
// User cancelled the dialog
return false;
}
const int i = deviceNames.indexOf(chosenName);
if (i < 0)
// ??? This shouldn't be possible
return false;
device = devices.at(i);
qDebug() << "Device chosen:" << device << chosenName;
}
// Open the default Capture device to record a 8000Hz 16bit Mono Stream using an internal buffer
// of mBufferSize Samples (== mBufferSize * 2 bytes)
mCaptureDevice = alcCaptureOpenDevice(device.toAscii().constData(), mSampleRate, AL_FORMAT_MONO16, mBufferSize);
ALenum error1 = alGetError(), error2 = alcGetError(mCaptureDevice);
if (mCaptureDevice == 0 || error1 != AL_NO_ERROR || error2 != AL_NO_ERROR) {
const QString errorMsg1(alGetString(error1));
const QString errorMsg2(alGetString(error2));
QMessageBox::critical(0, "Sound Problem",
QString("Failed to open capture device %1\nError message: %2 (%3)\nMessage 2: %4 (%5)")
.arg(device).arg(errorMsg1).arg(error1).arg(errorMsg2).arg(error2));
return false;
}
return true;
}
I hope someone can spot something I'm doing wrong here.  |  |
Started: 11/12/2008 5:42 AM | |  | |
|  | Can't open capture device on Linux, take 2
I have tried a lot of things, and no matter what I do, alcCaptureOpenDevice() returns NULL. Except when I choose the standard ALSA capture device, but then I get no sound. alGetError and alcGetError both returns AL_NO_ERROR which is quite odd, when it doesn't work.
I hope someone can help me with this, because I'm growing very frustrated.
I'm working on Kubuntu 8.10 using the precompiled openal.
The code works fine on Windows XP with Visual Studio 2005.
Here is the code that I'm using. The initialization is split in two functions. They are called in the order below. The first one opens the output device, and that works fine on both Linux and Windows. The second opens the capture device, and that only works on Windows.
Don't let the Qt code fool you. I have tried using the exact same chars coming from alcGetString(NULL, ALC_CAPTURE_DEVICE_SPECIFIER) as the specifier for the device without any luck.
I have tried running the application under KDE 4 and Fluxbox (to test if a KDE sound service had grabbed the sound card). No difference.
I'm hoping one of you have an idea about something I can do to move on. I'm running out of things to test and debug.
bool OpenALConnector::init() {
ALDeviceList pDeviceList;
const int deviceCount = pDeviceList.getNumDevices();
if (deviceCount == 0) {
QMessageBox::critical(0, tr("Sound error"), tr("No available sound device"));
return false;
}
ALCdevice *pDevice = 0;
if (deviceCount == 1) {
// No need to ask the user
pDevice = alcOpenDevice(pDeviceList.getDeviceName(0).toAscii().constData());
} else {
// More than one to choose from
QStringList deviceNames;
for (int i = 0; i < deviceCount; ++i) {
const QString name(pDeviceList.getDeviceName(i));
if (i == pDeviceList.getDefaultDevice())
deviceNames << tr("%1 (default device)").arg(name);
else
deviceNames << name;
}
bool ok;
const QString chosenName(QInputDialog::getItem(0, tr("Sound Device..."), tr("Choose sound device"), deviceNames, 0, false, &ok));
if (!ok || chosenName.isEmpty()) {
// User cancelled the dialog
return false;
} else {
const int i = deviceNames.indexOf(chosenName);
if (i < 0)
// ??? This shouldn't be possible
return false;
pDevice = alcOpenDevice(pDeviceList.getDeviceName(i).toAscii().constData());
}
}
if (pDevice == 0) {
QMessageBox::critical(0, tr("Sound error"), tr("Failed to open sound device"));
return false;
}
ALCcontext* pContext = alcCreateContext(pDevice, 0);
if (pContext == 0) {
alcCloseDevice(pDevice);
QMessageBox::critical(0, tr("Sound error"), tr("Failed to use sound device"));
return false;
}
qDebug("Opened %s device", alcGetString(pDevice, ALC_DEVICE_SPECIFIER));
alcMakeContextCurrent(pContext);
// Minor optimization: Don't do 3D spatialization
alDistanceModel(AL_NONE);
return true;
}
bool Transmitter::init() {
ALCcontext* const pContext = alcGetCurrentContext();
ALCdevice* const pDevice = alcGetContextsDevice(pContext);
if (alcIsExtensionPresent(pDevice, "ALC_EXT_CAPTURE") == AL_FALSE) {
QMessageBox::critical(0, "Sound Problem", "Failed to detect Capture Extension\n");
return false;
}
// Get list of available Capture Devices
const ALchar *pDeviceList = alcGetString(NULL, ALC_CAPTURE_DEVICE_SPECIFIER);
QStringList devices;
while (pDeviceList != 0 && *pDeviceList != '\0') {
devices << pDeviceList;
pDeviceList += strlen(pDeviceList) + 1;
}
// Get the name of the 'default' capture device
QString defaultCaptureDevice(alcGetString(NULL, ALC_CAPTURE_DEFAULT_DEVICE_SPECIFIER));
// Choose the output device
QString device;
int deviceNo;
if (devices.count() == 1) {
// Not much to choose from
device = devices.at(deviceNo = 0);
} else {
QStringList deviceNames;
foreach (const QString& name, devices) {
if (name == defaultCaptureDevice)
deviceNames << tr("%1 (default device)").arg(name);
else
deviceNames << name;
}
bool ok;
const QString chosenName(QInputDialog::getItem(0, tr("Sound Device..."), tr("Choose recording device"), deviceNames, 0, false, &ok));
if (!ok || chosenName.isEmpty()) {
// User cancelled the dialog
return false;
}
const int i = deviceNames.indexOf(chosenName);
if (i < 0)
// ??? This shouldn't be possible
return false;
device = devices.at(i);
qDebug() << "Device chosen:" << device << chosenName;
}
// Open the default Capture device to record a 8000Hz 16bit Mono Stream using an internal buffer
// of mBufferSize Samples (== mBufferSize * 2 bytes)
mCaptureDevice = alcCaptureOpenDevice(device.toAscii().constData(), mSampleRate, AL_FORMAT_MONO16, mBufferSize);
ALenum error1 = alGetError(), error2 = alcGetError(mCaptureDevice);
if (mCaptureDevice == 0 || error1 != AL_NO_ERROR || error2 != AL_NO_ERROR) {
const QString errorMsg1(alGetString(error1));
const QString errorMsg2(alGetString(error2));
QMessageBox::critical(0, "Sound Problem",
QString("Failed to open capture device %1\nError message: %2 (%3)\nMessage 2: %4 (%5)")
.arg(device).arg(errorMsg1).arg(error1).arg(errorMsg2).arg(error2));
return false;
}
return true;
}
I hope someone can spot something I'm doing wrong here.
 |  |
Posted: 11/12/2008 11:38 AM | |  | |
|  |
From:
Posted: Wednesday, November 12, 2008 5:42 AM
Subject: Can't open capture device on Linux, take 2
I have tried a lot of things, and no matter what I do, alcCaptureOpenDevice() returns NULL. Except when I choose the standard ALSA capture device, but then I get no sound. alGetError and alcGetError both returns AL_NO_ERROR which is quite odd, when it doesn't work.
Just to note, alGetError() is only valid for checking al* function
errors, so an error won't be set on it due to alc* calls.
alcGetError() is used to check for alc* errors.
IIRC, *buntu 8.10 includes OpenAL-Soft.. you're sure you're
not using the old 0.0.8 version? If you can, it might also help
to try the GIT version of OpenAL-Soft as that will make sure to
set some alc error if opening fails. Also, is there any output to the console when capture fails to open?  |  |
Posted: 11/13/2008 1:40 AM | |  | |
|  | I have tried removing the kubuntu openal package (which was version 1.3.something) and compile the most recent openal soft myself.
That gave me the option of using OSS and nothing else as the devices, and it had no clue about the actual devices I have here, which is a Sound Blaster Live and a USB headset.
It looks very much like Linux is just not supported like Windows and OS X. That is too bad, but I'm not in a position to change this. I will have to advice my company that we must move on in the search for true portability on the audio system. I will ask about this in another thread.
But thank you for your answer anyway.  |  |
Posted: 11/13/2008 2:03 AM | |  | |
|  |
From:
Posted: Thursday, November 13, 2008 1:40 AM
Subject: Can't open capture device on Linux, take 2
I have tried removing the kubuntu openal package (which was version 1.3.something) and compile the most recent openal soft myself.
That gave me the option of using OSS and nothing else as the devices, and it had no clue about the actual devices I have here, which is a Sound Blaster Live and a USB headset.
It looks very much like Linux is just not supported like Windows and OS X. That is too bad, but I'm not in a position to change this. I will have to advice my company that we must move on in the search for true portability on the audio system. I will ask about this in another thread.
But thank you for your answer anyway.
Linux is very well supported by OpenAL Soft (as that's its main target). The manually-compiled version only giving you the option to use OSS sounds like ALSA support didn't enable when you ran cmake, which is generally caused by missing ALSA headers. In Ubuntu, you need to install the *-devel packages to get the headers, since they're removed from the main package.  |  |
|
|
|
|
|
|