mirror of
https://github.com/love2d/love.git
synced 2026-08-16 08:11:02 +02:00
Add love.audio.setOutputDevice
This commit is contained in:
@@ -78,6 +78,11 @@ bool Audio::setMixWithSystem(bool mix)
|
||||
#endif
|
||||
}
|
||||
|
||||
void Audio::setOutputDevice(const char */*name*/)
|
||||
{
|
||||
throw love::Exception("Re-setting output device is not supported.");
|
||||
}
|
||||
|
||||
StringMap<Audio::DistanceModel, Audio::DISTANCE_MAX_ENUM>::Entry Audio::distanceModelEntries[] =
|
||||
{
|
||||
{"none", Audio::DISTANCE_NONE},
|
||||
|
||||
@@ -307,6 +307,11 @@ public:
|
||||
*/
|
||||
virtual void getOutputDevices(std::vector<std::string> &list) = 0;
|
||||
|
||||
/**
|
||||
* Set the output device to specified device name.
|
||||
*/
|
||||
virtual void setOutputDevice(const char *name);
|
||||
|
||||
private:
|
||||
|
||||
static StringMap<DistanceModel, DISTANCE_MAX_ENUM>::Entry distanceModelEntries[];
|
||||
|
||||
@@ -98,7 +98,7 @@ static const char *getDeviceSpecifier(ALCdevice *device)
|
||||
#ifndef ALC_ALL_DEVICES_SPECIFIER
|
||||
constexpr ALCenum ALC_ALL_DEVICES_SPECIFIER = 0x1013;
|
||||
#endif
|
||||
static ALCenum deviceEnum = alcIsExtensionPresent(nullptr, "ALC_ENUMERATE_ALL_EXT")
|
||||
static ALCenum deviceEnum = alcIsExtensionPresent(nullptr, "ALC_ENUMERATE_ALL_EXT") == ALC_TRUE
|
||||
? ALC_ALL_DEVICES_SPECIFIER
|
||||
: ALC_DEVICE_SPECIFIER;
|
||||
|
||||
@@ -112,6 +112,9 @@ Audio::Audio()
|
||||
, poolThread(nullptr)
|
||||
, distanceModel(DISTANCE_INVERSE_CLAMPED)
|
||||
{
|
||||
attribs.push_back(0);
|
||||
attribs.push_back(0);
|
||||
|
||||
// Before opening new device, check if recording
|
||||
// is requested.
|
||||
if (getRequestRecordingPermission())
|
||||
@@ -134,12 +137,11 @@ Audio::Audio()
|
||||
throw love::Exception("Could not open device.");
|
||||
|
||||
#ifdef ALC_EXT_EFX
|
||||
ALint attribs[4] = { ALC_MAX_AUXILIARY_SENDS, MAX_SOURCE_EFFECTS, 0, 0 };
|
||||
#else
|
||||
ALint *attribs = nullptr;
|
||||
attribs.insert(attribs.begin(), ALC_MAX_AUXILIARY_SENDS);
|
||||
attribs.insert(attribs.begin() + 1, MAX_SOURCE_EFFECTS);
|
||||
#endif
|
||||
|
||||
context = alcCreateContext(device, attribs);
|
||||
context = alcCreateContext(device, attribs.data());
|
||||
|
||||
if (context == nullptr)
|
||||
throw love::Exception("Could not create context.");
|
||||
@@ -350,6 +352,29 @@ void Audio::getOutputDevices(std::vector<std::string> &list)
|
||||
}
|
||||
}
|
||||
|
||||
void Audio::setOutputDevice(const char* name)
|
||||
{
|
||||
#undef ALC_SOFT_reopen_device
|
||||
#ifndef ALC_SOFT_reopen_device
|
||||
typedef ALCboolean (ALC_APIENTRY*LPALCREOPENDEVICESOFT)(ALCdevice *device,
|
||||
const ALCchar *deviceName, const ALCint *attribs);
|
||||
#endif
|
||||
static LPALCREOPENDEVICESOFT alcReopenDeviceSOFT = alcIsExtensionPresent(device, "ALC_SOFT_reopen_device") == ALC_TRUE
|
||||
? (LPALCREOPENDEVICESOFT) alcGetProcAddress(device, "alcReopenDeviceSOFT")
|
||||
: nullptr;
|
||||
|
||||
if (alcReopenDeviceSOFT == nullptr)
|
||||
{
|
||||
// Default implementation throws exception. To make
|
||||
// error message consistent, call the base class.
|
||||
love::audio::Audio::setOutputDevice(name);
|
||||
return;
|
||||
}
|
||||
|
||||
if (alcReopenDeviceSOFT(device, (const ALCchar *) name, attribs.data()) == ALC_FALSE)
|
||||
throw love::Exception("Cannot set output device: %s", alcGetString(device, alcGetError(device)));
|
||||
}
|
||||
|
||||
void Audio::setVolume(float volume)
|
||||
{
|
||||
alListenerf(AL_GAIN, volume);
|
||||
|
||||
@@ -129,6 +129,7 @@ public:
|
||||
|
||||
std::string getOutputDevice();
|
||||
void getOutputDevices(std::vector<std::string> &list);
|
||||
void setOutputDevice(const char *name);
|
||||
|
||||
private:
|
||||
void initializeEFX();
|
||||
@@ -140,6 +141,7 @@ private:
|
||||
|
||||
// The OpenAL context.
|
||||
ALCcontext *context;
|
||||
std::vector<ALCint> attribs;
|
||||
|
||||
// The OpenAL effects
|
||||
struct EffectMapStorage
|
||||
|
||||
@@ -568,6 +568,27 @@ int w_getOutputDevices(lua_State* L)
|
||||
return 1;
|
||||
}
|
||||
|
||||
int w_setOutputDevice(lua_State* L)
|
||||
{
|
||||
const char *device = luaL_optstring(L, 1, nullptr);
|
||||
|
||||
try
|
||||
{
|
||||
instance()->setOutputDevice(device);
|
||||
luax_pushboolean(L, true);
|
||||
return 1;
|
||||
}
|
||||
catch (love::Exception& e)
|
||||
{
|
||||
luax_pushboolean(L, false);
|
||||
lua_pushstring(L, e.what());
|
||||
return 2;
|
||||
}
|
||||
|
||||
// To avoid compiler warning
|
||||
return 0;
|
||||
}
|
||||
|
||||
// List of functions to wrap.
|
||||
static const luaL_Reg functions[] =
|
||||
{
|
||||
@@ -601,6 +622,7 @@ static const luaL_Reg functions[] =
|
||||
{ "setMixWithSystem", w_setMixWithSystem },
|
||||
{ "getOutputDevice", w_getOutputDevice },
|
||||
{ "getOutputDevices", w_getOutputDevices },
|
||||
{ "setOutputDevice", w_setOutputDevice },
|
||||
|
||||
{ 0, 0 }
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user