struct vg_audio_system{
SDL_AudioDeviceID sdl_output_device;
+ char *force_device_name; /* NULL: using default */
void *audio_pool,
*decode_buffer;
audio_lock_checker_store(0);
SDL_AtomicUnlock( &vg_audio.sl_sync );
}
-
static void audio_mixer_callback( void *user, u8 *stream, int frame_count );
-static void vg_audio_init(void)
-{
- /* TODO: Move here? */
- vg_console_reg_var( "debug_audio", &vg_audio.debug_ui,
- k_var_dtype_i32, VG_VAR_CHEAT );
- vg_console_reg_var( "debug_dsp", &vg_audio.debug_dsp,
- k_var_dtype_i32, VG_VAR_CHEAT );
- vg_console_reg_var( "volume", &vg_audio.external_global_volume,
- k_var_dtype_f32, VG_VAR_PERSISTENT );
-
- /* allocate memory */
- /* 32mb fixed */
- vg_audio.audio_pool =
- vg_create_linear_allocator( vg_mem.rtmemory, 1024*1024*32,
- VG_MEMORY_SYSTEM );
-
- /* fixed */
- u32 decode_size = AUDIO_DECODE_SIZE * AUDIO_CHANNELS;
- vg_audio.decode_buffer = vg_linear_alloc( vg_mem.rtmemory, decode_size );
-
- vg_dsp_init();
+static void vg_audio_device_init(void){
SDL_AudioSpec spec_desired, spec_got;
spec_desired.callback = audio_mixer_callback;
spec_desired.channels = 2;
spec_desired.userdata = NULL;
vg_audio.sdl_output_device =
- SDL_OpenAudioDevice( NULL, 0, &spec_desired, &spec_got,0 );
+ SDL_OpenAudioDevice( vg_audio.force_device_name, 0,
+ &spec_desired, &spec_got,0 );
+
+ vg_info( "Start audio device (%u, F32, %u) @%s\n",
+ spec_desired.freq,
+ AUDIO_FRAME_SIZE,
+ vg_audio.force_device_name );
if( vg_audio.sdl_output_device ){
SDL_PauseAudioDevice( vg_audio.sdl_output_device, 0 );
+ vg_success( "Unpaused device %d.\n", vg_audio.sdl_output_device );
}
else{
- vg_fatal_error(
+ vg_error(
"SDL_OpenAudioDevice failed. Your default audio device must support:\n"
" Frequency: 44100 hz\n"
" Buffer size: 512\n"
}
}
+
+static void vg_audio_init(void){
+ vg_console_reg_var( "debug_audio", &vg_audio.debug_ui,
+ k_var_dtype_i32, VG_VAR_CHEAT );
+ vg_console_reg_var( "debug_dsp", &vg_audio.debug_dsp,
+ k_var_dtype_i32, VG_VAR_CHEAT );
+ vg_console_reg_var( "volume", &vg_audio.external_global_volume,
+ k_var_dtype_f32, VG_VAR_PERSISTENT );
+
+ /* allocate memory */
+ /* 32mb fixed */
+ vg_audio.audio_pool =
+ vg_create_linear_allocator( vg_mem.rtmemory, 1024*1024*32,
+ VG_MEMORY_SYSTEM );
+
+ /* fixed */
+ u32 decode_size = AUDIO_DECODE_SIZE * AUDIO_CHANNELS;
+ vg_audio.decode_buffer = vg_linear_alloc( vg_mem.rtmemory, decode_size );
+
+ vg_dsp_init();
+ vg_audio_device_init();
+}
+
static void vg_audio_free(void)
{
vg_dsp_free();
u32 option_count;
const char *label;
}
- vsync, quality, screenmode;
+ vsync, quality, screenmode, audio_devices;
+ i32 temp_audio_choice;
int windowed_before[4];
}
.options = vg_settings_quality_enum, .option_count = 3 },
.screenmode = { .label = "Type",
.actual_value = &vg.screen_mode,
- .options = vg_settings_screen_mode_enum, .option_count=3 }
-
+ .options = vg_settings_screen_mode_enum, .option_count=3 },
+ .audio_devices = { .label = "Audio Device",
+ .actual_value = &vg_settings.temp_audio_choice,
+ .options = NULL, .option_count = 0 }
};
static void vg_settings_ui_draw_diff( ui_rect orig ){
}
}
+static void vg_settings_audio_apply(void){
+ if( vg_settings_enum_diff( &vg_settings.audio_devices ) ){
+ if( vg_audio.sdl_output_device ){
+ vg_info( "Closing audio device %d\n", vg_audio.sdl_output_device );
+ SDL_CloseAudioDevice( vg_audio.sdl_output_device );
+ }
+
+ if( vg_audio.force_device_name ){
+ free( vg_audio.force_device_name );
+ vg_audio.force_device_name = NULL;
+ }
+
+ if( vg_settings.audio_devices.new_value == -1 ){ }
+ else if( vg_settings.audio_devices.new_value == -2 ){
+ vg_fatal_error( "Programming error\n" );
+ }
+ else {
+ struct ui_enum_opt *selected = NULL, *oi;
+
+ for( int i=0; i<vg_settings.audio_devices.option_count; i ++ ){
+ oi = &vg_settings.audio_devices.options[i];
+
+ if( oi->value == vg_settings.audio_devices.new_value ){
+ selected = oi;
+ break;
+ }
+ }
+
+ int len = strlen(oi->alias);
+ vg_audio.force_device_name = malloc(len+1);
+ memcpy( vg_audio.force_device_name, (void *)oi->alias, len+1 );
+ }
+
+ vg_audio_device_init();
+ *vg_settings.audio_devices.actual_value =
+ vg_settings.audio_devices.new_value;
+ }
+}
+
+static void vg_settings_audio_gui( ui_rect panel ){
+ ui_rect rq;
+ ui_standard_widget( panel, rq, 1 );
+ vg_settings_enum( &vg_settings.audio_devices, rq );
+
+ const char *string = "Apply";
+
+ ui_rect last_row;
+ ui_px height = (vg_ui.font->glyph_height + 18) * k_ui_scale;
+ ui_split( panel, k_ui_axis_h, -height, k_ui_padding,
+ panel, last_row );
+
+ if( ui_button( last_row, string ) == 1 )
+ vg_settings_audio_apply();
+}
+
+static void vg_settings_open(void){
+ vg.settings_open = 1;
+
+ ui_settings_ranged_i32_init( &vg_settings.fps_limit );
+ ui_settings_enum_init( &vg_settings.vsync );
+ ui_settings_enum_init( &vg_settings.quality );
+ ui_settings_enum_init( &vg_settings.screenmode );
+
+ /* Create audio options */
+ int count = SDL_GetNumAudioDevices( 0 );
+
+ struct ui_enum_opt *options = malloc( sizeof(struct ui_enum_opt)*(count+1) );
+ vg_settings.audio_devices.options = options;
+ vg_settings.audio_devices.option_count = count+1;
+
+ struct ui_enum_opt *o0 = &options[0];
+ o0->alias = "OS Default";
+ o0->value = -1;
+
+ for( int i=0; i<count; i ++ ){
+ struct ui_enum_opt *oi = &options[i+1];
+
+ const char *device_name = SDL_GetAudioDeviceName( i, 0 );
+ int len = strlen(device_name);
+
+ oi->alias = malloc( len+1 );
+ memcpy( (void *)oi->alias, device_name, len+1 );
+ oi->value = i;
+ }
+
+ if( vg_audio.force_device_name ){
+ vg_settings.temp_audio_choice = -2;
+
+ for( int i=0; i<count; i ++ ){
+ struct ui_enum_opt *oi = &options[i+1];
+ if( !strcmp( oi->alias, vg_audio.force_device_name ) ){
+ vg_settings.temp_audio_choice = oi->value;
+ break;
+ }
+ }
+ }
+ else {
+ vg_settings.temp_audio_choice = -1;
+ }
+
+ ui_settings_enum_init( &vg_settings.audio_devices );
+}
+
+static void vg_settings_close(void){
+ vg.settings_open = 0;
+
+ struct ui_enum_opt *options = vg_settings.audio_devices.options;
+ for( int i=1; i < vg_settings.audio_devices.option_count; i ++ )
+ free( (void *)options[i].alias );
+ free( vg_settings.audio_devices.options );
+}
+
static void vg_settings_gui(void){
ui_rect null;
ui_rect screen = { 0, 0, vg.window_x, vg.window_y };
ui_split( title, k_ui_axis_v, title[2]-title[3], 2, title, quit_button );
if( ui_button_text( quit_button, "X", 1 ) == 1 ){
- vg.settings_open = 0;
+ vg_settings_close();
return;
}
if( page == 0 ){
vg_settings_video_gui( panel );
}
+ else if( page == 1 )
+ vg_settings_audio_gui( panel );
}
static int cmd_vg_settings_toggle( int argc, const char *argv[] ){
- vg.settings_open = !vg.settings_open;
-
- if( vg.settings_open ){
- ui_settings_ranged_i32_init( &vg_settings.fps_limit );
- ui_settings_enum_init( &vg_settings.vsync );
- ui_settings_enum_init( &vg_settings.quality );
- ui_settings_enum_init( &vg_settings.screenmode );
- }
+ vg_settings_open();
return 0;
}