add audio.get_output_devices_names, set_input_device, set_output_device
This commit is contained in:
parent
b11bdf0bcc
commit
6df27b8992
@ -30,13 +30,14 @@ const char* alc_error_to_string(ALCenum error) {
|
||||
}
|
||||
}
|
||||
|
||||
static void check_alc_errors(ALCdevice* device, const char* context) {
|
||||
static bool check_alc_errors(ALCdevice* device, const char* context) {
|
||||
ALCenum error = alcGetError(device);
|
||||
if (error == ALC_NO_ERROR) {
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
logger.error() << context << ": " << alc_error_to_string(error) << "("
|
||||
<< error << ")";
|
||||
return true;
|
||||
}
|
||||
|
||||
ALSound::ALSound(
|
||||
@ -419,6 +420,8 @@ int ALSpeaker::getPriority() const {
|
||||
return priority;
|
||||
}
|
||||
|
||||
static bool alc_enumeration_ext = false;
|
||||
|
||||
ALAudio::ALAudio(ALCdevice* device, ALCcontext* context)
|
||||
: device(device), context(context) {
|
||||
ALCint size;
|
||||
@ -431,9 +434,15 @@ ALAudio::ALAudio(ALCdevice* device, ALCcontext* context)
|
||||
maxSources = attrs[i + 1];
|
||||
}
|
||||
}
|
||||
auto devices = getAvailableDevices();
|
||||
logger.info() << "devices:";
|
||||
for (auto& name : devices) {
|
||||
auto outputDevices = getOutputDeviceNames();
|
||||
logger.info() << "output devices:";
|
||||
for (auto& name : outputDevices) {
|
||||
logger.info() << " " << name;
|
||||
}
|
||||
|
||||
auto inputDevices = getInputDeviceNames();
|
||||
logger.info() << "input devices:";
|
||||
for (auto& name : inputDevices) {
|
||||
logger.info() << " " << name;
|
||||
}
|
||||
}
|
||||
@ -482,35 +491,59 @@ std::unique_ptr<Stream> ALAudio::openStream(
|
||||
std::vector<std::string> ALAudio::getInputDeviceNames() {
|
||||
std::vector<std::string> devices;
|
||||
|
||||
if (alcIsExtensionPresent(nullptr, "ALC_ENUMERATION_EXT")) {
|
||||
auto deviceList = alcGetString(nullptr, ALC_CAPTURE_DEVICE_SPECIFIER);
|
||||
if (deviceList == nullptr) {
|
||||
logger.warning() << "no input devices found";
|
||||
return devices;
|
||||
}
|
||||
while (*deviceList) {
|
||||
std::string deviceName(deviceList);
|
||||
devices.push_back(deviceName);
|
||||
deviceList += deviceName.length() + 1;
|
||||
}
|
||||
} else {
|
||||
if (!alc_enumeration_ext) {
|
||||
logger.warning() << "enumeration extension is not available";
|
||||
return devices;
|
||||
}
|
||||
|
||||
auto deviceList = alcGetString(nullptr, ALC_CAPTURE_DEVICE_SPECIFIER);
|
||||
if (deviceList == nullptr) {
|
||||
logger.warning() << "no input devices found";
|
||||
return devices;
|
||||
}
|
||||
while (*deviceList) {
|
||||
std::string deviceName(deviceList);
|
||||
devices.push_back(deviceName);
|
||||
deviceList += deviceName.length() + 1;
|
||||
}
|
||||
|
||||
return devices;
|
||||
}
|
||||
|
||||
std::vector<std::string> ALAudio::getOutputDeviceNames() {
|
||||
std::vector<std::string> devices;
|
||||
|
||||
if (!alc_enumeration_ext) {
|
||||
logger.warning() << "enumeration extension is not available";
|
||||
return devices;
|
||||
}
|
||||
|
||||
auto deviceList = alcGetString(nullptr, ALC_ALL_DEVICES_SPECIFIER);
|
||||
if (deviceList == nullptr) {
|
||||
logger.warning() << "no input devices found";
|
||||
return devices;
|
||||
}
|
||||
while (*deviceList) {
|
||||
std::string deviceName(deviceList);
|
||||
devices.push_back(deviceName);
|
||||
deviceList += deviceName.length() + 1;
|
||||
}
|
||||
|
||||
return devices;
|
||||
}
|
||||
|
||||
std::unique_ptr<InputDevice> ALAudio::openInputDevice(
|
||||
uint sampleRate, uint channels, uint bitsPerSample
|
||||
const char* deviceName, uint sampleRate, uint channels, uint bitsPerSample
|
||||
) {
|
||||
uint bps = bitsPerSample >> 3;
|
||||
ALCdevice* device = alcCaptureOpenDevice(
|
||||
nullptr,
|
||||
deviceName,
|
||||
sampleRate,
|
||||
AL::to_al_format(channels, bitsPerSample),
|
||||
sampleRate * channels * bps / 8
|
||||
);
|
||||
check_alc_errors(device, "alcCaptureOpenDevice");
|
||||
if (check_alc_errors(device, "alcCaptureOpenDevice"))
|
||||
return nullptr;
|
||||
|
||||
return std::make_unique<ALInputDevice>(
|
||||
this, device, channels, bitsPerSample
|
||||
@ -518,6 +551,8 @@ std::unique_ptr<InputDevice> ALAudio::openInputDevice(
|
||||
}
|
||||
|
||||
std::unique_ptr<ALAudio> ALAudio::create() {
|
||||
alc_enumeration_ext = alcIsExtensionPresent(nullptr, "ALC_ENUMERATION_EXT");
|
||||
|
||||
ALCdevice* device = alcOpenDevice(nullptr);
|
||||
if (device == nullptr) return nullptr;
|
||||
ALCcontext* context = alcCreateContext(device, nullptr);
|
||||
@ -574,22 +609,35 @@ void ALAudio::freeBuffer(uint buffer) {
|
||||
freebuffers.push_back(buffer);
|
||||
}
|
||||
|
||||
std::vector<std::string> ALAudio::getAvailableDevices() const {
|
||||
std::vector<std::string> devicesVec;
|
||||
|
||||
const ALCchar* devices;
|
||||
devices = alcGetString(device, ALC_DEVICE_SPECIFIER);
|
||||
if (!AL_GET_ERROR()) {
|
||||
return devicesVec;
|
||||
void ALAudio::setOutputDevice(const std::string& deviceName) {
|
||||
ALCdevice* newDevice = alcOpenDevice(deviceName.c_str());
|
||||
if (newDevice == nullptr) {
|
||||
logger.error() << "failed to open output device: " << deviceName;
|
||||
return;
|
||||
}
|
||||
|
||||
const char* ptr = devices;
|
||||
do {
|
||||
devicesVec.emplace_back(ptr);
|
||||
ptr += devicesVec.back().size() + 1;
|
||||
} while (ptr[0]);
|
||||
ALCcontext* newContext = alcCreateContext(newDevice, nullptr);
|
||||
if (!alcMakeContextCurrent(newContext)) {
|
||||
logger.error() << "failed to make context current for device: "
|
||||
<< deviceName;
|
||||
alcCloseDevice(newDevice);
|
||||
return;
|
||||
}
|
||||
|
||||
return devicesVec;
|
||||
// Clean up old device and context
|
||||
alcMakeContextCurrent(nullptr);
|
||||
check_alc_errors(device, "alcMakeContextCurrent");
|
||||
alcDestroyContext(context);
|
||||
check_alc_errors(device, "alcDestroyContext");
|
||||
if (!alcCloseDevice(device)) {
|
||||
logger.error() << "old device not closed";
|
||||
}
|
||||
|
||||
// Update to new device and context
|
||||
device = newDevice;
|
||||
context = newContext;
|
||||
|
||||
logger.info() << "switched output device to: " << deviceName;
|
||||
}
|
||||
|
||||
void ALAudio::setListener(
|
||||
|
||||
@ -172,8 +172,6 @@ namespace audio {
|
||||
void freeSource(uint source);
|
||||
void freeBuffer(uint buffer);
|
||||
|
||||
std::vector<std::string> getAvailableDevices() const;
|
||||
|
||||
std::unique_ptr<Sound> createSound(
|
||||
std::shared_ptr<PCM> pcm, bool keepPCM
|
||||
) override;
|
||||
@ -183,11 +181,17 @@ namespace audio {
|
||||
) override;
|
||||
|
||||
std::unique_ptr<InputDevice> openInputDevice(
|
||||
uint sampleRate, uint channels, uint bitsPerSample
|
||||
const char* deviceName,
|
||||
uint sampleRate,
|
||||
uint channels,
|
||||
uint bitsPerSample
|
||||
) override;
|
||||
|
||||
std::vector<std::string> getOutputDeviceNames() override;
|
||||
std::vector<std::string> getInputDeviceNames() override;
|
||||
|
||||
void setOutputDevice(const std::string& deviceName) override;
|
||||
|
||||
void setListener(
|
||||
glm::vec3 position,
|
||||
glm::vec3 velocity,
|
||||
|
||||
@ -77,7 +77,7 @@ namespace audio {
|
||||
) override;
|
||||
|
||||
std::unique_ptr<InputDevice> openInputDevice(
|
||||
uint sampleRate, uint channels, uint bitsPerSample
|
||||
const char* deviceName, uint sampleRate, uint channels, uint bitsPerSample
|
||||
) override {
|
||||
return nullptr;
|
||||
}
|
||||
@ -85,6 +85,12 @@ namespace audio {
|
||||
std::vector<std::string> getInputDeviceNames() override {
|
||||
return {};
|
||||
}
|
||||
std::vector<std::string> getOutputDeviceNames() override {
|
||||
return {};
|
||||
}
|
||||
|
||||
void setOutputDevice(const std::string& deviceName) override {
|
||||
}
|
||||
|
||||
void setListener(
|
||||
glm::vec3 position, glm::vec3 velocity, glm::vec3 at, glm::vec3 up
|
||||
|
||||
@ -183,7 +183,7 @@ void audio::initialize(bool enabled, AudioSettings& settings) {
|
||||
}, true));
|
||||
}
|
||||
|
||||
input_device = backend->openInputDevice(44100, 1, 16);
|
||||
input_device = backend->openInputDevice(nullptr, 44100, 1, 16);
|
||||
if (input_device) {
|
||||
input_device->startCapture();
|
||||
}
|
||||
@ -254,15 +254,43 @@ std::unique_ptr<Stream> audio::open_stream(
|
||||
}
|
||||
|
||||
std::unique_ptr<InputDevice> audio::open_input_device(
|
||||
uint sampleRate, uint channels, uint bitsPerSample
|
||||
const char* deviceName, uint sampleRate, uint channels, uint bitsPerSample
|
||||
) {
|
||||
return backend->openInputDevice(sampleRate, channels, bitsPerSample);
|
||||
return backend->openInputDevice(
|
||||
deviceName, sampleRate, channels, bitsPerSample
|
||||
);
|
||||
}
|
||||
|
||||
std::vector<std::string> audio::get_input_devices_names() {
|
||||
return backend->getInputDeviceNames();
|
||||
}
|
||||
|
||||
std::vector<std::string> audio::get_output_devices_names() {
|
||||
return backend->getOutputDeviceNames();
|
||||
}
|
||||
|
||||
void audio::set_input_device(const std::string& deviceName) {
|
||||
auto newDevice = backend->openInputDevice(
|
||||
deviceName.empty() ? nullptr : deviceName.c_str(), 44100, 1, 16
|
||||
);
|
||||
if (newDevice == nullptr) {
|
||||
logger.error() << "could not open input device: " << deviceName;
|
||||
return;
|
||||
}
|
||||
|
||||
if (input_device) {
|
||||
input_device->stopCapture();
|
||||
}
|
||||
input_device = std::move(newDevice);
|
||||
if (input_device) {
|
||||
input_device->startCapture();
|
||||
}
|
||||
}
|
||||
|
||||
void audio::set_output_device(const std::string& deviceName) {
|
||||
backend->setOutputDevice(deviceName);
|
||||
}
|
||||
|
||||
void audio::set_listener(
|
||||
glm::vec3 position, glm::vec3 velocity, glm::vec3 lookAt, glm::vec3 up
|
||||
) {
|
||||
|
||||
@ -362,7 +362,10 @@ namespace audio {
|
||||
std::shared_ptr<PCMStream> stream, bool keepSource
|
||||
) = 0;
|
||||
virtual std::unique_ptr<InputDevice> openInputDevice(
|
||||
uint sampleRate, uint channels, uint bitsPerSample
|
||||
const char* deviceName,
|
||||
uint sampleRate,
|
||||
uint channels,
|
||||
uint bitsPerSample
|
||||
) = 0;
|
||||
virtual void setListener(
|
||||
glm::vec3 position,
|
||||
@ -371,6 +374,8 @@ namespace audio {
|
||||
glm::vec3 up
|
||||
) = 0;
|
||||
virtual std::vector<std::string> getInputDeviceNames() = 0;
|
||||
virtual std::vector<std::string> getOutputDeviceNames() = 0;
|
||||
virtual void setOutputDevice(const std::string& deviceName) = 0;
|
||||
virtual void update(double delta) = 0;
|
||||
|
||||
/// @brief Check if backend is an abstraction that does not internally
|
||||
@ -432,13 +437,23 @@ namespace audio {
|
||||
/// @param bitsPerSample number of bits per sample (8 or 16)
|
||||
/// @return new InputDevice instance or nullptr
|
||||
std::unique_ptr<InputDevice> open_input_device(
|
||||
uint sampleRate, uint channels, uint bitsPerSample
|
||||
const char* deviceName,
|
||||
uint sampleRate,
|
||||
uint channels,
|
||||
uint bitsPerSample
|
||||
);
|
||||
|
||||
/// @brief Retrieve names of available audio input devices
|
||||
/// @return list of device names
|
||||
std::vector<std::string> get_input_devices_names();
|
||||
|
||||
/// @brief Retrieve names of available audio output devices
|
||||
/// @return list of device names
|
||||
std::vector<std::string> get_output_devices_names();
|
||||
|
||||
void set_input_device(const std::string& deviceName);
|
||||
void set_output_device(const std::string& deviceName);
|
||||
|
||||
/// @brief Configure 3D listener
|
||||
/// @param position listener position
|
||||
/// @param velocity listener velocity (used for Doppler effect)
|
||||
|
||||
@ -419,6 +419,29 @@ static int l_audio_get_input_devices_names(lua::State* L) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int l_audio_get_output_devices_names(lua::State* L) {
|
||||
auto device_names = audio::get_output_devices_names();
|
||||
lua::createtable(L, device_names.size(), 0);
|
||||
int index = 1;
|
||||
for (const auto& name : device_names) {
|
||||
lua::pushstring(L, name.c_str());
|
||||
lua::rawseti(L, index++);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int l_audio_set_input_device(lua::State* L) {
|
||||
auto device_name = lua::tostring(L, 1);
|
||||
audio::set_input_device(device_name);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int l_audio_set_output_device(lua::State* L) {
|
||||
auto device_name = lua::tostring(L, 1);
|
||||
audio::set_output_device(device_name);
|
||||
return 0;
|
||||
}
|
||||
|
||||
const luaL_Reg audiolib[] = {
|
||||
{"play_sound", lua::wrap<l_audio_play_sound>},
|
||||
{"play_sound_2d", lua::wrap<l_audio_play_sound_2d>},
|
||||
@ -446,5 +469,8 @@ const luaL_Reg audiolib[] = {
|
||||
{"count_streams", lua::wrap<l_audio_count_streams>},
|
||||
{"fetch_input", lua::wrap<l_audio_fetch_input>},
|
||||
{"get_input_devices_names", lua::wrap<l_audio_get_input_devices_names>},
|
||||
{"get_output_devices_names", lua::wrap<l_audio_get_output_devices_names>},
|
||||
{"set_input_device", lua::wrap<l_audio_set_input_device>},
|
||||
{"set_output_device", lua::wrap<l_audio_set_output_device>},
|
||||
{nullptr, nullptr}
|
||||
};
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user