Skip to main content

OpenAL

Go Search
Home
ALchemy
Beta - Audigy [CLOSED]
Beta - Linux
Beta - Windows
Developer
E-MU
MarCom
OpenAL
Open Source
PR
  
Creative Labs: Connect > OpenAL > OpenAL > Can't open capture device on Linux  

OpenAL

Modify settings and columns
Note : This discussion forum has been CLOSED.

For questions about developing software using OpenAL please subscribe to the 'OpenAL' mailing list at http://opensource.creative.com/mailman/listinfo/openal

For questions about creating a custom OpenAL library, please subscribe to the 'OpenAL-Devel' mailing list at http://opensource.creative.com/mailman/listinfo/openal-devel
  
View: 
Post
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.