Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add al_set_audio_output_device for audio output device selection #1542

Draft
wants to merge 9 commits into
base: master
Choose a base branch
from
2 changes: 2 additions & 0 deletions addons/audio/allegro5/allegro_audio.h
Original file line number Diff line number Diff line change
Expand Up @@ -368,6 +368,8 @@ ALLEGRO_KCM_AUDIO_FUNC(void, al_fill_silence, (void *buf, unsigned int samples,
ALLEGRO_KCM_AUDIO_FUNC(int, al_get_num_audio_output_devices, (void));
ALLEGRO_KCM_AUDIO_FUNC(const ALLEGRO_AUDIO_DEVICE *, al_get_audio_output_device, (int index));
ALLEGRO_KCM_AUDIO_FUNC(const char *, al_get_audio_device_name, (const ALLEGRO_AUDIO_DEVICE * device));
ALLEGRO_KCM_AUDIO_FUNC(const bool, al_set_audio_output_device, (const ALLEGRO_AUDIO_DEVICE* device));


/* Simple audio layer */
ALLEGRO_KCM_AUDIO_FUNC(bool, al_reserve_samples, (int reserve_samples));
Expand Down
1 change: 1 addition & 0 deletions addons/audio/allegro5/internal/aintern_audio.h
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,7 @@ struct ALLEGRO_AUDIO_DRIVER {
void (*deallocate_recorder)(struct ALLEGRO_AUDIO_RECORDER *);

_AL_LIST* (*get_output_devices)(void);
int (*set_output_device)(ALLEGRO_AUDIO_DEVICE*);
};

extern ALLEGRO_AUDIO_DRIVER *_al_kcm_driver;
Expand Down
3 changes: 2 additions & 1 deletion addons/audio/alsa.c
Original file line number Diff line number Diff line change
Expand Up @@ -1021,7 +1021,8 @@ ALLEGRO_AUDIO_DRIVER _al_kcm_alsa_driver =
alsa_allocate_recorder,
alsa_deallocate_recorder,

alsa_get_output_devices
alsa_get_output_devices,
NULL,
};

/* vim: set sts=3 sw=3 et: */
11 changes: 11 additions & 0 deletions addons/audio/aqueue.m
Original file line number Diff line number Diff line change
Expand Up @@ -129,6 +129,16 @@ static void property_listener(void *inClientData, AudioSessionPropertyID inID, U
}
#endif

static int _aqueue_set_audio_output_device(ALLEGRO_AUDIO_DEVICE* output_device) {
AudioObjectPropertyAddress propertyAddress;
propertyAddress.mSelector = kAudioHardwarePropertyDefaultOutputDevice;
propertyAddress.mScope = kAudioDevicePropertyScopeOutput;
propertyAddress.mElement = kAudioObjectPropertyElementMaster;

return AudioObjectSetPropertyData(kAudioObjectSystemObject, &propertyAddress, 0, NULL,
sizeof(AudioDeviceID), output_device->identifier) != noErr;
}

static bool _aqueue_device_has_scope(AudioObjectID deviceID, AudioObjectPropertyScope scope)
{
AudioObjectPropertyAddress propertyAddress = {
Expand Down Expand Up @@ -679,5 +689,6 @@ static void _aqueue_deallocate_recorder(ALLEGRO_AUDIO_RECORDER *recorder)
_aqueue_deallocate_recorder,

_aqueue_get_output_devices,
_aqueue_set_audio_output_device,
};

11 changes: 10 additions & 1 deletion addons/audio/audio.c
Original file line number Diff line number Diff line change
Expand Up @@ -233,9 +233,18 @@ const ALLEGRO_AUDIO_DEVICE* al_get_audio_output_device(int index)
return NULL;
}

/* Function: al_set_audio_output_device
*/
const bool al_set_audio_output_device(const ALLEGRO_AUDIO_DEVICE *device)
{
if (!al_is_audio_installed()) return false;
if (_al_kcm_driver->set_output_device) return _al_kcm_driver->set_output_device(device) == 0;
return false;
}

/* Function: al_get_audio_device_name
*/
const char* al_get_audio_device_name(const ALLEGRO_AUDIO_DEVICE * device)
const char* al_get_audio_device_name(const ALLEGRO_AUDIO_DEVICE *device)
{
return device ? device->name : NULL;
}
Expand Down
47 changes: 47 additions & 0 deletions addons/audio/dsound.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -265,6 +265,52 @@ static void* _dsound_update(ALLEGRO_THREAD *self, void *arg)
return NULL;
}

static int _dsound_set_audio_output_device(ALLEGRO_AUDIO_DEVICE* output_device) {
ALLEGRO_VOICE* voice = al_get_default_voice();
ALLEGRO_DS_DATA* ex_data = (ALLEGRO_DS_DATA*)voice->extra;
MAKE_UNION(&ex_data->ds8_buffer, LPDIRECTSOUNDBUFFER8*);

HRESULT hr;
LPVOID ptr1, ptr2;
DWORD block1_bytes, block2_bytes;

IDirectSound8* old_device = device;
LPDIRECTSOUNDBUFFER8 old_buffer = ex_data->ds8_buffer;

hr = old_buffer->Lock(0, voice->buffer_size, &ptr1, &block1_bytes, &ptr2, &block2_bytes, DSBLOCK_ENTIREBUFFER);
if (FAILED(hr)) {
ALLEGRO_ERROR("Failed to lock DIRECTSOUNDBUFFER8: %s\n", ds_get_error(hr));
printf(ds_get_error(hr));
return 1;
}

hr = DirectSoundCreate8((LPCGUID)output_device->identifier, &device, NULL);
if (FAILED(hr)) {
ALLEGRO_ERROR("DirectSoundCreate8 failed: %s\n", ds_get_error(hr));
return 1;
}

hr = device->SetCooperativeLevel(get_window(), DSSCL_PRIORITY);
if (FAILED(hr)) {
ALLEGRO_ERROR("SetCooperativeLevel failed: %s\n", ds_get_error(hr));
return 1;
}

hr = device->CreateSoundBuffer(&ex_data->desc, &ex_data->ds_buffer, NULL);
if (FAILED(hr)) {
ALLEGRO_ERROR("CreateSoundBuffer failed: %s\n", ds_get_error(hr));
return 1;
}

ex_data->ds_buffer->QueryInterface(_al_IID_IDirectSoundBuffer8, u.v);
ex_data->ds8_buffer->SetVolume(DSBVOLUME_MAX);

old_buffer->Unlock(ptr1, block1_bytes, ptr2, block2_bytes);
old_buffer->Stop();
old_device->Release();

return 0;
}

/* The open method starts up the driver and should lock the device, using the
previously set parameters, or defaults. It shouldn't need to start sending
Expand Down Expand Up @@ -879,6 +925,7 @@ ALLEGRO_AUDIO_DRIVER _al_kcm_dsound_driver = {
_dsound_close_recorder,

_dsound_get_output_devices,
_dsound_set_audio_output_device,
};

} /* End extern "C" */
Expand Down
3 changes: 2 additions & 1 deletion addons/audio/openal.c
Original file line number Diff line number Diff line change
Expand Up @@ -663,7 +663,8 @@ ALLEGRO_AUDIO_DRIVER _al_kcm_openal_driver = {
NULL,
NULL,

NULL
NULL,
NULL,
};

/* vim: set sts=3 sw=3 et: */
3 changes: 2 additions & 1 deletion addons/audio/opensl.c
Original file line number Diff line number Diff line change
Expand Up @@ -722,5 +722,6 @@ ALLEGRO_AUDIO_DRIVER _al_kcm_opensl_driver = {
NULL,
NULL,

NULL
NULL,
NULL,
};
3 changes: 2 additions & 1 deletion addons/audio/oss.c
Original file line number Diff line number Diff line change
Expand Up @@ -623,7 +623,8 @@ ALLEGRO_AUDIO_DRIVER _al_kcm_oss_driver =
NULL,
NULL,

NULL
NULL,
NULL,
};

/* vim: set sts=3 sw=3 et: */
3 changes: 2 additions & 1 deletion addons/audio/pulseaudio.c
Original file line number Diff line number Diff line change
Expand Up @@ -575,7 +575,8 @@ ALLEGRO_AUDIO_DRIVER _al_kcm_pulseaudio_driver =
pulseaudio_allocate_recorder,
pulseaudio_deallocate_recorder,

pulseaudio_get_output_devices
pulseaudio_get_output_devices,
NULL,
};

/* vim: set sts=3 sw=3 et: */
1 change: 1 addition & 0 deletions addons/audio/sdl_audio.c
Original file line number Diff line number Diff line change
Expand Up @@ -269,4 +269,5 @@ ALLEGRO_AUDIO_DRIVER _al_kcm_sdl_driver =
sdl_deallocate_recorder,

sdl_get_output_devices,
NULL,
};
4 changes: 4 additions & 0 deletions docs/src/refman/audio.txt
Original file line number Diff line number Diff line change
Expand Up @@ -1412,7 +1412,11 @@ Get the user friendly display name of the device.

Since: 5.2.8

### API: al_set_audio_output_device

Select the audio output device to use. Currently only implemented on Windows and MacOS/iOS.

Since: 5.2.10

## Voices

Expand Down
25 changes: 25 additions & 0 deletions examples/ex_audio_simple.c
Original file line number Diff line number Diff line change
Expand Up @@ -94,8 +94,19 @@ int main(int argc, const char *argv[])
}
}

{
int count = al_get_num_audio_output_devices(); // returns -1 for unsupported backends
log_printf("audio device count: %d\n", count);
for (int i = 0; i < count; i++)
{
const ALLEGRO_AUDIO_DEVICE* device = al_get_audio_output_device(i);
log_printf(" --- audio device: %s\n", al_get_audio_device_name(device));
}
}

log_printf(
"Press digits to play sounds.\n"
"Press F1-F12 keys to select audio output device\n"
"Space to stop sounds.\n"
"Add Alt to play sounds repeatedly.\n"
"'p' to pan the last played sound.\n"
Expand All @@ -115,6 +126,17 @@ int main(int argc, const char *argv[])
}
}

if (event.keyboard.keycode >= ALLEGRO_KEY_F1 && event.keyboard.keycode <= ALLEGRO_KEY_F12) {
int device_index = (event.keyboard.keycode - ALLEGRO_KEY_F1 + 12) % 12;
const ALLEGRO_AUDIO_DEVICE* device = al_get_audio_output_device(device_index);

if (device) {
log_printf("Selected device #%d %s\n", device_index, al_get_audio_device_name(device));

al_set_audio_output_device(device);
}
}

if (event.keyboard.keycode >= ALLEGRO_KEY_0 && event.keyboard.keycode <= ALLEGRO_KEY_9) {
bool loop = event.keyboard.modifiers & ALLEGRO_KEYMOD_ALT;
bool bidir = event.keyboard.modifiers & ALLEGRO_KEYMOD_CTRL;
Expand Down Expand Up @@ -208,6 +230,9 @@ int main(int argc, const char *argv[])
al_draw_text(font, al_map_rgb_f(1., 0.5, 0.5), 12, y,
ALLEGRO_ALIGN_LEFT, "1-9 - play the sounds");
y += dy;
al_draw_text(font, al_map_rgb_f(1., 0.5, 0.5), 12, y,
ALLEGRO_ALIGN_LEFT, "F1 - F12 select audio output device");
y += dy;
al_draw_text(font, al_map_rgb_f(1., 0.5, 0.5), 12, y,
ALLEGRO_ALIGN_LEFT, "SPACE - stop all sounds");
y += dy;
Expand Down