mirror of
https://github.com/Ryujinx/libsoundio.git
synced 2024-12-22 18:45:29 +00:00
Merge pull request #164 from tokyovigilante/master
Add hardware volume control support to Core Audio and WASAPI backends
This commit is contained in:
commit
1778b8d10f
|
@ -536,7 +536,8 @@ struct SoundIoOutStream {
|
|||
/// For JACK, this value is always equal to
|
||||
/// SoundIoDevice::software_latency_current of the device.
|
||||
double software_latency;
|
||||
|
||||
/// Core Audio and WASAPI only: current output Audio Unit volume. Float, 0.0-1.0.
|
||||
float volume;
|
||||
/// Defaults to NULL. Put whatever you want here.
|
||||
void *userdata;
|
||||
/// In this callback, you call ::soundio_outstream_begin_write and
|
||||
|
@ -1057,6 +1058,9 @@ SOUNDIO_EXPORT int soundio_outstream_pause(struct SoundIoOutStream *outstream, b
|
|||
SOUNDIO_EXPORT int soundio_outstream_get_latency(struct SoundIoOutStream *outstream,
|
||||
double *out_latency);
|
||||
|
||||
SOUNDIO_EXPORT int soundio_outstream_set_volume(struct SoundIoOutStream *outstream,
|
||||
double volume);
|
||||
|
||||
|
||||
|
||||
// Input Streams
|
||||
|
|
|
@ -1045,6 +1045,11 @@ static int outstream_open_ca(struct SoundIoPrivate *si, struct SoundIoOutStreamP
|
|||
return SoundIoErrorOpeningDevice;
|
||||
}
|
||||
|
||||
if ((os_err = AudioUnitGetParameter (osca->instance, kHALOutputParam_Volume, kAudioUnitScope_Global, 0, &outstream->volume))) {
|
||||
outstream_destroy_ca(si, os);
|
||||
return SoundIoErrorOpeningDevice;
|
||||
}
|
||||
|
||||
osca->hardware_latency = dca->latency_frames / (double)outstream->sample_rate;
|
||||
|
||||
return 0;
|
||||
|
@ -1115,6 +1120,18 @@ static int outstream_get_latency_ca(struct SoundIoPrivate *si, struct SoundIoOut
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int outstream_set_volume_ca(struct SoundIoPrivate *si, struct SoundIoOutStreamPrivate *os, float volume) {
|
||||
struct SoundIoOutStreamCoreAudio *osca = &os->backend_data.coreaudio;
|
||||
struct SoundIoOutStream *outstream = &os->pub;
|
||||
|
||||
OSStatus os_err;
|
||||
if ((os_err = AudioUnitSetParameter (osca->instance, kHALOutputParam_Volume, kAudioUnitScope_Global, 0, volume, 0))) {
|
||||
return SoundIoErrorIncompatibleDevice;
|
||||
}
|
||||
outstream->volume = volume;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static OSStatus on_instream_device_overload(AudioObjectID in_object_id, UInt32 in_number_addresses,
|
||||
const AudioObjectPropertyAddress in_addresses[], void *in_client_data)
|
||||
{
|
||||
|
@ -1456,6 +1473,7 @@ int soundio_coreaudio_init(struct SoundIoPrivate *si) {
|
|||
si->outstream_clear_buffer = outstream_clear_buffer_ca;
|
||||
si->outstream_pause = outstream_pause_ca;
|
||||
si->outstream_get_latency = outstream_get_latency_ca;
|
||||
si->outstream_set_volume = outstream_set_volume_ca;
|
||||
|
||||
si->instream_open = instream_open_ca;
|
||||
si->instream_destroy = instream_destroy_ca;
|
||||
|
|
|
@ -52,6 +52,7 @@ struct SoundIoOutStreamCoreAudio {
|
|||
int frames_left;
|
||||
int write_frame_count;
|
||||
double hardware_latency;
|
||||
float volume;
|
||||
struct SoundIoChannelArea areas[SOUNDIO_MAX_CHANNELS];
|
||||
};
|
||||
|
||||
|
|
|
@ -272,6 +272,7 @@ void soundio_disconnect(struct SoundIo *soundio) {
|
|||
si->outstream_clear_buffer = NULL;
|
||||
si->outstream_pause = NULL;
|
||||
si->outstream_get_latency = NULL;
|
||||
si->outstream_set_volume = NULL;
|
||||
|
||||
si->instream_open = NULL;
|
||||
si->instream_destroy = NULL;
|
||||
|
@ -560,6 +561,13 @@ int soundio_outstream_get_latency(struct SoundIoOutStream *outstream, double *ou
|
|||
return si->outstream_get_latency(si, os, out_latency);
|
||||
}
|
||||
|
||||
int soundio_outstream_set_volume(struct SoundIoOutStream *outstream, double volume) {
|
||||
struct SoundIo *soundio = outstream->device->soundio;
|
||||
struct SoundIoPrivate *si = (struct SoundIoPrivate *)soundio;
|
||||
struct SoundIoOutStreamPrivate *os = (struct SoundIoOutStreamPrivate *)outstream;
|
||||
return si->outstream_set_volume(si, os, volume);
|
||||
}
|
||||
|
||||
static void default_instream_error_callback(struct SoundIoInStream *is, int err) {
|
||||
soundio_panic("libsoundio: %s", soundio_strerror(err));
|
||||
}
|
||||
|
|
|
@ -152,7 +152,7 @@ struct SoundIoPrivate {
|
|||
int (*outstream_clear_buffer)(struct SoundIoPrivate *, struct SoundIoOutStreamPrivate *);
|
||||
int (*outstream_pause)(struct SoundIoPrivate *, struct SoundIoOutStreamPrivate *, bool pause);
|
||||
int (*outstream_get_latency)(struct SoundIoPrivate *, struct SoundIoOutStreamPrivate *, double *out_latency);
|
||||
|
||||
int (*outstream_set_volume)(struct SoundIoPrivate *, struct SoundIoOutStreamPrivate *, float volume);
|
||||
|
||||
int (*instream_open)(struct SoundIoPrivate *, struct SoundIoInStreamPrivate *);
|
||||
void (*instream_destroy)(struct SoundIoPrivate *, struct SoundIoInStreamPrivate *);
|
||||
|
|
29
src/wasapi.c
29
src/wasapi.c
|
@ -1181,6 +1181,8 @@ static void force_device_scan_wasapi(struct SoundIoPrivate *si) {
|
|||
static void outstream_thread_deinit(struct SoundIoPrivate *si, struct SoundIoOutStreamPrivate *os) {
|
||||
struct SoundIoOutStreamWasapi *osw = &os->backend_data.wasapi;
|
||||
|
||||
if (osw->audio_volume_control)
|
||||
IUnknown_Release(osw->audio_volume_control);
|
||||
if (osw->audio_render_client)
|
||||
IUnknown_Release(osw->audio_render_client);
|
||||
if (osw->audio_session_control)
|
||||
|
@ -1378,6 +1380,17 @@ static int outstream_do_open(struct SoundIoPrivate *si, struct SoundIoOutStreamP
|
|||
return SoundIoErrorOpeningDevice;
|
||||
}
|
||||
|
||||
if (FAILED(hr = IAudioClient_GetService(osw->audio_client, IID_ISimpleAudioVolume,
|
||||
(void **)&osw->audio_volume_control)))
|
||||
{
|
||||
return SoundIoErrorOpeningDevice;
|
||||
}
|
||||
|
||||
if (FAILED(hr = osw->audio_volume_control->GetMasterVolume(&volume)))
|
||||
{
|
||||
return SoundIoErrorOpeningDevice;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -1706,6 +1719,21 @@ static int outstream_get_latency_wasapi(struct SoundIoPrivate *si, struct SoundI
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int outstream_set_volume_wasapi(struct SoundIoPrivate *si, struct SoundIoOutStreamPrivate *os, float volume)
|
||||
{
|
||||
struct SoundIoOutStream *outstream = &os->pub;
|
||||
struct SoundIoOutStreamWasapi *osw = &os->backend_data.wasapi;
|
||||
|
||||
HRESULT hr;
|
||||
if (FAILED(hr = osw->audio_volume_control->SetMasterVolume(&volume)))
|
||||
{
|
||||
return SoundIoErrorIncompatibleDevice;
|
||||
}
|
||||
|
||||
outstream->volume = volume;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void instream_thread_deinit(struct SoundIoPrivate *si, struct SoundIoInStreamPrivate *is) {
|
||||
struct SoundIoInStreamWasapi *isw = &is->backend_data.wasapi;
|
||||
|
||||
|
@ -2295,6 +2323,7 @@ int soundio_wasapi_init(struct SoundIoPrivate *si) {
|
|||
si->outstream_clear_buffer = outstream_clear_buffer_wasapi;
|
||||
si->outstream_pause = outstream_pause_wasapi;
|
||||
si->outstream_get_latency = outstream_get_latency_wasapi;
|
||||
si->outstream_set_volume = outstream_set_volume_wasapi;
|
||||
|
||||
si->instream_open = instream_open_wasapi;
|
||||
si->instream_destroy = instream_destroy_wasapi;
|
||||
|
|
|
@ -56,6 +56,7 @@ struct SoundIoOutStreamWasapi {
|
|||
IAudioClockAdjustment *audio_clock_adjustment;
|
||||
IAudioRenderClient *audio_render_client;
|
||||
IAudioSessionControl *audio_session_control;
|
||||
ISimpleAudioVolume *audio_volume_control;
|
||||
LPWSTR stream_name;
|
||||
bool need_resample;
|
||||
struct SoundIoOsThread *thread;
|
||||
|
@ -76,6 +77,7 @@ struct SoundIoOutStreamWasapi {
|
|||
int open_err;
|
||||
bool started;
|
||||
UINT32 min_padding_frames;
|
||||
float volume;
|
||||
struct SoundIoChannelArea areas[SOUNDIO_MAX_CHANNELS];
|
||||
};
|
||||
|
||||
|
|
Loading…
Reference in a new issue