@@ -81,6 +81,62 @@ int getDisplayNumber(void) {
81
81
return displayNumber;
82
82
}
83
83
84
+ extern void mixaudio (void *userdata, Uint8 *stream, int len) {
85
+ NativeMix ((short *)stream, len / 4 );
86
+ }
87
+
88
+ static SDL_AudioDeviceID audioDev = 0 ;
89
+
90
+ // Must be called after NativeInit().
91
+ static void InitSDLAudioDevice (const std::string &name = " " ) {
92
+ SDL_AudioSpec fmt, ret_fmt;
93
+ memset (&fmt, 0 , sizeof (fmt));
94
+ fmt.freq = 44100 ;
95
+ fmt.format = AUDIO_S16;
96
+ fmt.channels = 2 ;
97
+ fmt.samples = 2048 ;
98
+ fmt.callback = &mixaudio;
99
+ fmt.userdata = nullptr ;
100
+
101
+ std::string startDevice = name;
102
+ if (startDevice.empty ()) {
103
+ startDevice = g_Config.sAudioDevice ;
104
+ }
105
+
106
+ audioDev = 0 ;
107
+ if (!startDevice.empty ()) {
108
+ audioDev = SDL_OpenAudioDevice (startDevice.c_str (), 0 , &fmt, &ret_fmt, SDL_AUDIO_ALLOW_FREQUENCY_CHANGE);
109
+ if (audioDev <= 0 ) {
110
+ WLOG (" Failed to open audio device: %s" , startDevice.c_str ());
111
+ }
112
+ }
113
+ if (audioDev <= 0 ) {
114
+ audioDev = SDL_OpenAudioDevice (nullptr , 0 , &fmt, &ret_fmt, SDL_AUDIO_ALLOW_FREQUENCY_CHANGE);
115
+ }
116
+ if (audioDev <= 0 ) {
117
+ ELOG (" Failed to open audio: %s" , SDL_GetError ());
118
+ } else {
119
+ if (ret_fmt.samples != fmt.samples ) // Notify, but still use it
120
+ ELOG (" Output audio samples: %d (requested: %d)" , ret_fmt.samples , fmt.samples );
121
+ if (ret_fmt.freq != fmt.freq || ret_fmt.format != fmt.format || ret_fmt.channels != fmt.channels ) {
122
+ ELOG (" Sound buffer format does not match requested format." );
123
+ ELOG (" Output audio freq: %d (requested: %d)" , ret_fmt.freq , fmt.freq );
124
+ ELOG (" Output audio format: %d (requested: %d)" , ret_fmt.format , fmt.format );
125
+ ELOG (" Output audio channels: %d (requested: %d)" , ret_fmt.channels , fmt.channels );
126
+ ELOG (" Provided output format does not match requirement, turning audio off" );
127
+ SDL_CloseAudioDevice (audioDev);
128
+ }
129
+ SDL_PauseAudioDevice (audioDev, 0 );
130
+ }
131
+ }
132
+
133
+ static void StopSDLAudioDevice () {
134
+ if (audioDev > 0 ) {
135
+ SDL_PauseAudioDevice (audioDev, 1 );
136
+ SDL_CloseAudioDevice (audioDev);
137
+ }
138
+ }
139
+
84
140
// Simple implementations of System functions
85
141
86
142
@@ -120,6 +176,9 @@ void System_SendMessage(const char *command, const char *parameter) {
120
176
g_QuitRequested = true ;
121
177
} else if (!strcmp (command, " setclipboardtext" )) {
122
178
SDL_SetClipboardText (parameter);
179
+ } else if (!strcmp (command, " audio_resetDevice" )) {
180
+ StopSDLAudioDevice ();
181
+ InitSDLAudioDevice ();
123
182
}
124
183
}
125
184
@@ -221,6 +280,24 @@ std::string System_GetProperty(SystemProperty prop) {
221
280
}
222
281
case SYSPROP_CLIPBOARD_TEXT:
223
282
return SDL_HasClipboardText () ? SDL_GetClipboardText () : " " ;
283
+ case SYSPROP_AUDIO_DEVICE_LIST:
284
+ {
285
+ std::string result;
286
+ for (int i = 0 ; i < SDL_GetNumAudioDevices (0 ); ++i) {
287
+ const char *name = SDL_GetAudioDeviceName (i, 0 );
288
+ if (!name) {
289
+ continue ;
290
+ }
291
+
292
+ if (i == 0 ) {
293
+ result = name;
294
+ } else {
295
+ result.append (1 , ' \0 ' );
296
+ result.append (name);
297
+ }
298
+ }
299
+ return result;
300
+ }
224
301
default :
225
302
return " " ;
226
303
}
@@ -258,10 +335,6 @@ bool System_GetPropertyBool(SystemProperty prop) {
258
335
}
259
336
}
260
337
261
- extern void mixaudio (void *userdata, Uint8 *stream, int len) {
262
- NativeMix ((short *)stream, len / 4 );
263
- }
264
-
265
338
// returns -1 on failure
266
339
static int parseInt (const char *str) {
267
340
int val;
@@ -573,32 +646,8 @@ int main(int argc, char *argv[]) {
573
646
// Ensure that the swap interval is set after context creation (needed for kmsdrm)
574
647
SDL_GL_SetSwapInterval (1 );
575
648
576
- SDL_AudioSpec fmt, ret_fmt;
577
- memset (&fmt, 0 , sizeof (fmt));
578
- fmt.freq = 44100 ;
579
- fmt.format = AUDIO_S16;
580
- fmt.channels = 2 ;
581
- fmt.samples = 2048 ;
582
- fmt.callback = &mixaudio;
583
- fmt.userdata = (void *)0 ;
584
-
585
- if (SDL_OpenAudio (&fmt, &ret_fmt) < 0 ) {
586
- ELOG (" Failed to open audio: %s" , SDL_GetError ());
587
- } else {
588
- if (ret_fmt.samples != fmt.samples ) // Notify, but still use it
589
- ELOG (" Output audio samples: %d (requested: %d)" , ret_fmt.samples , fmt.samples );
590
- if (ret_fmt.freq != fmt.freq || ret_fmt.format != fmt.format || ret_fmt.channels != fmt.channels ) {
591
- ELOG (" Sound buffer format does not match requested format." );
592
- ELOG (" Output audio freq: %d (requested: %d)" , ret_fmt.freq , fmt.freq );
593
- ELOG (" Output audio format: %d (requested: %d)" , ret_fmt.format , fmt.format );
594
- ELOG (" Output audio channels: %d (requested: %d)" , ret_fmt.channels , fmt.channels );
595
- ELOG (" Provided output format does not match requirement, turning audio off" );
596
- SDL_CloseAudio ();
597
- }
598
- }
649
+ InitSDLAudioDevice ();
599
650
600
- // Audio must be unpaused _after_ NativeInit()
601
- SDL_PauseAudio (0 );
602
651
if (joystick_enabled) {
603
652
joystick = new SDLJoystick ();
604
653
} else {
@@ -852,6 +901,29 @@ int main(int argc, char *argv[]) {
852
901
break ;
853
902
}
854
903
break ;
904
+
905
+ #if SDL_VERSION_ATLEAST(2, 0, 4)
906
+ case SDL_AUDIODEVICEADDED:
907
+ // Automatically switch to the new device.
908
+ if (event.adevice .iscapture == 0 ) {
909
+ const char *name = SDL_GetAudioDeviceName (event.adevice .which , 0 );
910
+ if (!name) {
911
+ break ;
912
+ }
913
+ if (g_Config.bAutoAudioDevice || g_Config.sAudioDevice == name) {
914
+ StopSDLAudioDevice ();
915
+ InitSDLAudioDevice (name ? name : " " );
916
+ }
917
+ }
918
+ break ;
919
+ case SDL_AUDIODEVICEREMOVED:
920
+ if (event.adevice .iscapture == 0 && event.adevice .which == audioDev) {
921
+ StopSDLAudioDevice ();
922
+ InitSDLAudioDevice ();
923
+ }
924
+ break ;
925
+ #endif
926
+
855
927
default :
856
928
if (joystick) {
857
929
joystick->ProcessInput (event);
@@ -927,8 +999,10 @@ int main(int argc, char *argv[]) {
927
999
graphicsContext->ShutdownFromRenderThread ();
928
1000
delete graphicsContext;
929
1001
930
- SDL_PauseAudio (1 );
931
- SDL_CloseAudio ();
1002
+ if (audioDev > 0 ) {
1003
+ SDL_PauseAudioDevice (audioDev, 1 );
1004
+ SDL_CloseAudioDevice (audioDev);
1005
+ }
932
1006
SDL_Quit ();
933
1007
#if PPSSPP_PLATFORM(RPI)
934
1008
bcm_host_deinit ();
0 commit comments