mirror of
https://github.com/Ryujinx/libsoundio.git
synced 2024-12-22 22:25:28 +00:00
WASAPI: use stream name for session display name
This commit is contained in:
parent
1bb10e6a13
commit
d1f27fad83
17
README.md
17
README.md
|
@ -24,7 +24,7 @@ behavior on every platform.
|
|||
- [PulseAudio](http://www.freedesktop.org/wiki/Software/PulseAudio/)
|
||||
- [ALSA](http://www.alsa-project.org/)
|
||||
- [CoreAudio](https://developer.apple.com/library/mac/documentation/MusicAudio/Conceptual/CoreAudioOverview/Introduction/Introduction.html)
|
||||
- (in progress) [WASAPI](https://msdn.microsoft.com/en-us/library/windows/desktop/dd371455%28v=vs.85%29.aspx)
|
||||
- [WASAPI](https://msdn.microsoft.com/en-us/library/windows/desktop/dd371455%28v=vs.85%29.aspx)
|
||||
- Dummy (silence)
|
||||
* Exposes both raw devices and shared devices. Raw devices give you the best
|
||||
performance but prevent other applications from using them. Shared devices
|
||||
|
@ -260,24 +260,9 @@ For each backend, do the following:
|
|||
back correctly. If possible use the `--in-device` and `--out-device`
|
||||
parameters to test a USB microphone in raw mode.
|
||||
|
||||
```
|
||||
make test
|
||||
```
|
||||
|
||||
For more detailed output:
|
||||
|
||||
```
|
||||
make
|
||||
./unit_tests
|
||||
```
|
||||
|
||||
To see test coverage, install lcov, run `make coverage` and then
|
||||
view `coverage/index.html` in a browser.
|
||||
|
||||
## Roadmap
|
||||
|
||||
0. implement WASAPI (Windows) backend, get examples working
|
||||
- set display name of output stream
|
||||
- move the bulk of the `outstream_open_wasapi` code to the thread and
|
||||
have them communicate back and forth. because the thread has to do
|
||||
weird thread-local com stuff, and all that com stuff really needs to be
|
||||
|
|
|
@ -24,8 +24,13 @@ static void panic(const char *format, ...) {
|
|||
}
|
||||
|
||||
static int usage(char *exe) {
|
||||
fprintf(stderr, "Usage: %s [--backend dummy|alsa|pulseaudio|jack|coreaudio|wasapi] [--device id] [--raw]\n",
|
||||
exe);
|
||||
fprintf(stderr, "Usage: %s [options]\n"
|
||||
"Options:\n"
|
||||
" [--backend dummy|alsa|pulseaudio|jack|coreaudio|wasapi]\n"
|
||||
" [--device id]\n"
|
||||
" [--raw]\n"
|
||||
" [--name stream_name]\n"
|
||||
, exe);
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
|
@ -107,6 +112,7 @@ int main(int argc, char **argv) {
|
|||
enum SoundIoBackend backend = SoundIoBackendNone;
|
||||
char *device_id = NULL;
|
||||
bool raw = false;
|
||||
char *stream_name = NULL;
|
||||
for (int i = 1; i < argc; i += 1) {
|
||||
char *arg = argv[i];
|
||||
if (arg[0] == '-' && arg[1] == '-') {
|
||||
|
@ -135,6 +141,8 @@ int main(int argc, char **argv) {
|
|||
}
|
||||
} else if (strcmp(arg, "--device") == 0) {
|
||||
device_id = argv[i];
|
||||
} else if (strcmp(arg, "--name") == 0) {
|
||||
stream_name = argv[i];
|
||||
} else {
|
||||
return usage(exe);
|
||||
}
|
||||
|
@ -186,6 +194,7 @@ int main(int argc, char **argv) {
|
|||
struct SoundIoOutStream *outstream = soundio_outstream_create(device);
|
||||
outstream->write_callback = write_callback;
|
||||
outstream->underflow_callback = underflow_callback;
|
||||
outstream->name = stream_name;
|
||||
|
||||
if (soundio_device_supports_format(device, SoundIoFormatFloat32NE)) {
|
||||
outstream->format = SoundIoFormatFloat32NE;
|
||||
|
|
|
@ -453,6 +453,7 @@ struct SoundIoOutStream {
|
|||
// PulseAudio uses this for the stream name.
|
||||
// JACK uses this for the client name of the client that connects when you
|
||||
// open the stream.
|
||||
// WASAPI uses this for the session display name.
|
||||
// Must not contain a colon (":").
|
||||
const char *name;
|
||||
|
||||
|
@ -521,6 +522,7 @@ struct SoundIoInStream {
|
|||
// PulseAudio uses this for the stream name.
|
||||
// JACK uses this for the client name of the client that connects when you
|
||||
// open the stream.
|
||||
// WASAPI uses this for the session display name.
|
||||
// Must not contain a colon (":").
|
||||
const char *name;
|
||||
|
||||
|
|
|
@ -415,6 +415,9 @@ static int outstream_open_jack(struct SoundIoPrivate *si, struct SoundIoOutStrea
|
|||
if (sij->is_shutdown)
|
||||
return SoundIoErrorBackendDisconnected;
|
||||
|
||||
if (!outstream->name)
|
||||
outstream->name = "SoundIoOutStream";
|
||||
|
||||
outstream->software_latency = device->software_latency_current;
|
||||
osj->period_size = sij->period_size;
|
||||
|
||||
|
@ -617,6 +620,9 @@ static int instream_open_jack(struct SoundIoPrivate *si, struct SoundIoInStreamP
|
|||
if (sij->is_shutdown)
|
||||
return SoundIoErrorBackendDisconnected;
|
||||
|
||||
if (!instream->name)
|
||||
instream->name = "SoundIoInStream";
|
||||
|
||||
instream->software_latency = device->software_latency_current;
|
||||
isj->period_size = sij->period_size;
|
||||
|
||||
|
|
|
@ -672,6 +672,9 @@ static int outstream_open_pa(SoundIoPrivate *si, SoundIoOutStreamPrivate *os) {
|
|||
if ((unsigned)outstream->layout.channel_count > PA_CHANNELS_MAX)
|
||||
return SoundIoErrorIncompatibleBackend;
|
||||
|
||||
if (!outstream->name)
|
||||
outstream->name = "SoundIoOutStream";
|
||||
|
||||
SoundIoPulseAudio *sipa = &si->backend_data.pulseaudio;
|
||||
ospa->stream_ready.store(false);
|
||||
|
||||
|
@ -883,6 +886,8 @@ static int instream_open_pa(SoundIoPrivate *si, SoundIoInStreamPrivate *is) {
|
|||
return SoundIoErrorInvalid;
|
||||
if ((unsigned)instream->layout.channel_count > PA_CHANNELS_MAX)
|
||||
return SoundIoErrorIncompatibleBackend;
|
||||
if (!instream->name)
|
||||
instream->name = "SoundIoInStream";
|
||||
|
||||
SoundIoPulseAudio *sipa = &si->backend_data.pulseaudio;
|
||||
ispa->stream_ready = false;
|
||||
|
|
|
@ -473,9 +473,6 @@ int soundio_outstream_open(struct SoundIoOutStream *outstream) {
|
|||
if (!outstream->sample_rate)
|
||||
outstream->sample_rate = soundio_device_nearest_sample_rate(device, 48000);
|
||||
|
||||
if (!outstream->name)
|
||||
outstream->name = "SoundIoOutStream";
|
||||
|
||||
SoundIoOutStreamPrivate *os = (SoundIoOutStreamPrivate *)outstream;
|
||||
outstream->bytes_per_frame = soundio_get_bytes_per_frame(outstream->format, outstream->layout.channel_count);
|
||||
outstream->bytes_per_sample = soundio_get_bytes_per_sample(outstream->format);
|
||||
|
@ -559,9 +556,6 @@ int soundio_instream_open(struct SoundIoInStream *instream) {
|
|||
if (!instream->sample_rate)
|
||||
instream->sample_rate = soundio_device_nearest_sample_rate(device, 48000);
|
||||
|
||||
if (!instream->name)
|
||||
instream->name = "SoundIoInStream";
|
||||
|
||||
|
||||
instream->bytes_per_frame = soundio_get_bytes_per_frame(instream->format, instream->layout.channel_count);
|
||||
instream->bytes_per_sample = soundio_get_bytes_per_sample(instream->format);
|
||||
|
|
|
@ -109,6 +109,25 @@ static int from_lpwstr(LPWSTR lpwstr, char **out_str, int *out_str_len) {
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int to_lpwstr(const char *str, int str_len, LPWSTR *out_lpwstr) {
|
||||
DWORD flags = 0;
|
||||
int w_len = MultiByteToWideChar(CP_UTF8, flags, str, str_len, nullptr, 0);
|
||||
if (w_len <= 0)
|
||||
return SoundIoErrorEncodingString;
|
||||
|
||||
LPWSTR buf = allocate<wchar_t>(w_len + 1);
|
||||
if (!buf)
|
||||
return SoundIoErrorNoMem;
|
||||
|
||||
if (MultiByteToWideChar(CP_UTF8, flags, str, str_len, buf, w_len) != w_len) {
|
||||
free(buf);
|
||||
return SoundIoErrorEncodingString;
|
||||
}
|
||||
|
||||
*out_lpwstr = buf;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void from_channel_mask_layout(UINT channel_mask, SoundIoChannelLayout *layout) {
|
||||
layout->channel_count = 0;
|
||||
if (channel_mask & SPEAKER_FRONT_LEFT)
|
||||
|
@ -1000,6 +1019,8 @@ static void outstream_destroy_wasapi(struct SoundIoPrivate *si, struct SoundIoOu
|
|||
|
||||
if (osw->audio_render_client)
|
||||
IUnknown_Release(osw->audio_render_client);
|
||||
if (osw->audio_session_control)
|
||||
IUnknown_Release(osw->audio_session_control);
|
||||
if (osw->audio_clock_adjustment)
|
||||
IUnknown_Release(osw->audio_clock_adjustment);
|
||||
if (osw->audio_client)
|
||||
|
@ -1010,6 +1031,8 @@ static void outstream_destroy_wasapi(struct SoundIoPrivate *si, struct SoundIoOu
|
|||
soundio_os_cond_destroy(osw->cond);
|
||||
soundio_os_mutex_destroy(osw->mutex);
|
||||
|
||||
free(osw->stream_name);
|
||||
|
||||
CoUninitialize();
|
||||
}
|
||||
|
||||
|
@ -1172,6 +1195,27 @@ static int outstream_open_wasapi(struct SoundIoPrivate *si, struct SoundIoOutStr
|
|||
}
|
||||
}
|
||||
|
||||
if (outstream->name) {
|
||||
if (FAILED(hr = IAudioClient_GetService(osw->audio_client, IID_IAudioSessionControl,
|
||||
(void **)&osw->audio_session_control)))
|
||||
{
|
||||
outstream_destroy_wasapi(si, os);
|
||||
return SoundIoErrorOpeningDevice;
|
||||
}
|
||||
|
||||
int err;
|
||||
if ((err = to_lpwstr(outstream->name, strlen(outstream->name), &osw->stream_name))) {
|
||||
outstream_destroy_wasapi(si, os);
|
||||
return err;
|
||||
}
|
||||
if (FAILED(hr = IAudioSessionControl_SetDisplayName(osw->audio_session_control,
|
||||
osw->stream_name, nullptr)))
|
||||
{
|
||||
outstream_destroy_wasapi(si, os);
|
||||
return SoundIoErrorOpeningDevice;
|
||||
}
|
||||
}
|
||||
|
||||
if (FAILED(hr = IAudioClient_GetService(osw->audio_client, IID_IAudioRenderClient,
|
||||
(void **)&osw->audio_render_client)))
|
||||
{
|
||||
|
@ -1515,6 +1559,27 @@ static int instream_open_wasapi(struct SoundIoPrivate *si, struct SoundIoInStrea
|
|||
}
|
||||
}
|
||||
|
||||
if (instream->name) {
|
||||
if (FAILED(hr = IAudioClient_GetService(isw->audio_client, IID_IAudioSessionControl,
|
||||
(void **)&isw->audio_session_control)))
|
||||
{
|
||||
instream_destroy_wasapi(si, is);
|
||||
return SoundIoErrorOpeningDevice;
|
||||
}
|
||||
|
||||
int err;
|
||||
if ((err = to_lpwstr(instream->name, strlen(instream->name), &isw->stream_name))) {
|
||||
instream_destroy_wasapi(si, is);
|
||||
return err;
|
||||
}
|
||||
if (FAILED(hr = IAudioSessionControl_SetDisplayName(isw->audio_session_control,
|
||||
isw->stream_name, nullptr)))
|
||||
{
|
||||
instream_destroy_wasapi(si, is);
|
||||
return SoundIoErrorOpeningDevice;
|
||||
}
|
||||
}
|
||||
|
||||
if (FAILED(hr = IAudioClient_GetService(isw->audio_client, IID_IAudioCaptureClient,
|
||||
(void **)&isw->audio_capture_client)))
|
||||
{
|
||||
|
|
|
@ -23,6 +23,7 @@
|
|||
#include <mmreg.h>
|
||||
#include <audioclient.h>
|
||||
#include <audiosessiontypes.h>
|
||||
#include <audiopolicy.h>
|
||||
|
||||
int soundio_wasapi_init(struct SoundIoPrivate *si);
|
||||
|
||||
|
@ -53,6 +54,8 @@ struct SoundIoOutStreamWasapi {
|
|||
IAudioClient *audio_client;
|
||||
IAudioClockAdjustment *audio_clock_adjustment;
|
||||
IAudioRenderClient *audio_render_client;
|
||||
IAudioSessionControl *audio_session_control;
|
||||
LPWSTR stream_name;
|
||||
bool need_resample;
|
||||
SoundIoOsThread *thread;
|
||||
SoundIoOsMutex *mutex;
|
||||
|
@ -70,6 +73,8 @@ struct SoundIoOutStreamWasapi {
|
|||
struct SoundIoInStreamWasapi {
|
||||
IAudioClient *audio_client;
|
||||
IAudioCaptureClient *audio_capture_client;
|
||||
IAudioSessionControl *audio_session_control;
|
||||
LPWSTR stream_name;
|
||||
SoundIoOsThread *thread;
|
||||
SoundIoOsMutex *mutex;
|
||||
SoundIoOsCond *cond;
|
||||
|
|
Loading…
Reference in a new issue