@@ -284,6 +284,11 @@ pub const DisplayCallback = struct {
284284 ptr : * anyopaque = undefined ,
285285};
286286
287+ pub const PanelChangeCallback = struct {
288+ func : ? * const fn (ptr : * anyopaque , display : * Display , from : ? * Element , to : * Element , gpa : Allocator ) Allocator.Error ! void = null ,
289+ ptr : * anyopaque = undefined ,
290+ };
291+
287292pub const BoolCallback = struct {
288293 func : ? * const fn (ptr : * anyopaque , display : * Display , element : * Element ) bool = null ,
289294 ptr : * anyopaque = undefined ,
@@ -2474,6 +2479,7 @@ pub const TextSize = enum {
24742479pub const Display = struct {
24752480 window : * sdl.SDL_Window ,
24762481 renderer : * sdl.SDL_Renderer ,
2482+ mix : * mixer.MIX_Mixer ,
24772483 allocator : Allocator ,
24782484 quit : bool = false ,
24792485 need_relayout : bool = true ,
@@ -2580,6 +2586,7 @@ pub const Display = struct {
25802586 keybindings : std .AutoHashMapUnmanaged (c_uint , Callback ) = .empty ,
25812587 on_resized : BoolCallback ,
25822588 event_hook : U32Callback ,
2589+ on_panel_change : PanelChangeCallback ,
25832590
25842591 pub fn create (
25852592 gpa : Allocator ,
@@ -2601,6 +2608,7 @@ pub const Display = struct {
26012608 display .scrolling = null ;
26022609 display .text_height = FONT_SIZE ;
26032610 display .on_resized = .{ .func = null };
2611+ display .on_panel_change = .{ .func = null };
26042612 display .current_language = .unknown ;
26052613 display .need_relayout = true ;
26062614 display .quit = false ;
@@ -2647,9 +2655,22 @@ pub const Display = struct {
26472655 }
26482656
26492657 if (! mixer .MIX_Init ()) {
2650- err ("mixer setup font failed. {s}" , .{sdl .SDL_GetError ()});
2658+ err ("mixer setup failed. {s}" , .{sdl .SDL_GetError ()});
26512659 return error .AudioInitFailed ;
26522660 }
2661+ const a : mixer.SDL_AudioSpec = .{
2662+ .freq = 44100 ,
2663+ .format = mixer .SDL_AUDIO_S16LE ,
2664+ .channels = 2 ,
2665+ };
2666+
2667+ const md = mixer .MIX_CreateMixerDevice (mixer .SDL_AUDIO_DEVICE_DEFAULT_PLAYBACK , & a );
2668+ if (md == null ) {
2669+ err ("create mixer device failed. {s}" , .{sdl .SDL_GetError ()});
2670+ return error .AudioInitFailed ;
2671+ }
2672+ display .mix = md .? ;
2673+ //mixer.MIX_SetMasterGain(display.mix, DEFAULT_SOUND_VOLUME);
26532674
26542675 debug ("Initialising resource loader" , .{});
26552676 display .resources = try init_resource_loader (
@@ -2827,6 +2848,7 @@ pub const Display = struct {
28272848
28282849 sdl .SDL_DestroyRenderer (self .renderer );
28292850 sdl .SDL_DestroyWindow (self .window );
2851+ mixer .MIX_DestroyMixer (self .mix );
28302852 mixer .MIX_Quit ();
28312853 sdl .TTF_Quit ();
28322854 sdl .SDL_Quit ();
@@ -2898,27 +2920,33 @@ pub const Display = struct {
28982920 /// Mark a top level panel as visible, and all other
28992921 /// top level panels as not visible. The visibility of the
29002922 /// _background_ and _menu_ panel is not altered.
2901- pub fn choose_panel (self : * Display , name : []const u8 ) void {
2923+ pub fn choose_panel (self : * Display , gpa : Allocator , name : []const u8 ) void {
2924+ const old_panel = self .current_panel ();
2925+
29022926 var found = false ;
29032927 try self .update_screen_metrics (false );
29042928 for (self .root .type .panel .children .items ) | element | {
2905- if (element .type != .panel ) {
2906- continue ;
2907- }
2908- if (std .mem .eql (u8 , "background" , element .name )) {
2909- continue ;
2910- }
2911- if (std .mem .eql (u8 , "menu" , element .name )) {
2912- continue ;
2913- }
2929+ if (element .type != .panel ) continue ;
2930+ if (std .mem .eql (u8 , "background" , element .name )) continue ;
2931+ if (std .mem .eql (u8 , "menu" , element .name )) continue ;
2932+
29142933 if (std .mem .eql (u8 , name , element .name )) {
29152934 if (element .visible != .visible ) {
2916- debug ("choose_panel({s}) showing panel." , .{name });
2935+ if (old_panel ) | old | {
2936+ debug ("choose panel. {s} -> {s}" , .{ old .name , name });
2937+ } else {
2938+ debug ("choose panel. ... -> {s}" , .{name });
2939+ }
29172940 element .visible = .visible ;
29182941 if (element .on_resized .func != null ) {
29192942 self .need_relayout = true ;
29202943 _ = element .on_resized .func .? (element .on_resized .ptr , self , element );
29212944 }
2945+ if (self .on_panel_change .func ) | f | {
2946+ f (self .on_panel_change .ptr , self , old_panel , element , gpa ) catch | e | {
2947+ trace ("panel handler error. to {s} {any}" , .{ element .name , e });
2948+ };
2949+ }
29222950 }
29232951 } else {
29242952 if (element .visible != .hidden ) {
@@ -2951,7 +2979,6 @@ pub const Display = struct {
29512979 continue ;
29522980 }
29532981 if (element .visible == .visible ) {
2954- debug ("current_panel() found panel {s}." , .{element .name });
29552982 return element ;
29562983 }
29572984 }
@@ -3704,38 +3731,54 @@ pub const Display = struct {
37043731 bundle : * Resources ,
37053732 name : []const u8 ,
37063733 ) (Error || Allocator .Error || Resources .Error )! ? * AudioInfo {
3707- if (name .len == 0 ) return null ;
3734+ if (name .len == 0 ) {
3735+ err ("play_bundle_resource(\" {s}\" ) resource name empty" , .{name });
3736+ return null ;
3737+ }
3738+
3739+ // Load audio from memory cache if possible
3740+ var item : ? * AudioInfo = null ;
3741+ if (self .audio .get (name )) | i | {
3742+ i .references += 1 ;
3743+ item = i ;
3744+ } else {
3745+ // Load audio from resource bundle
3746+ var start = std .time .milliTimestamp ();
3747+ const resource = try bundle .lookupOne (name , .audio , gpa );
3748+ if (resource == null ) {
3749+ err ("search audio named \" {s}\" not found." , .{name });
3750+ return null ;
3751+ }
3752+ var end = std .time .milliTimestamp ();
3753+ debug ("search audio named \" {s}\" in {d}ms" , .{ name , end - start });
3754+
3755+ start = end ;
3756+ const audio = try sdl_load_resource (bundle , resource .? , gpa );
3757+ errdefer gpa .free (audio );
3758+ end = std .time .milliTimestamp ();
3759+
3760+ debug ("read audio named \" {s}\" size {d} in {d}ms" , .{
3761+ name ,
3762+ audio .len ,
3763+ end - start ,
3764+ });
37083765
3709- if (self .audio .get (name )) | item | {
3710- item .references += 1 ;
3711- return item ;
3766+ const ai = try AudioInfo .create (gpa , name , audio );
3767+ ai .references += 1 ;
3768+ try self .audio .put (gpa , ai .name , ai );
3769+ item = ai ;
37123770 }
37133771
3714- var start = std . time . milliTimestamp ( );
3715- const resource = try bundle . lookupOne ( name , .audio , gpa );
3716- if (resource == null ) {
3717- debug ( "search audio named \" {s}\" not found. " , .{name });
3772+ const amem = mixer . SDL_IOFromConstMem ( item .? . audio . ptr , item .? . audio . len );
3773+ const buff = mixer . MIX_LoadAudio_IO ( self . mix , amem , true , true );
3774+ if (buff == null ) {
3775+ err ( "loadaudio_io for \" {s}\" failed " , .{name });
37183776 return null ;
37193777 }
3720- var end = std .time .milliTimestamp ();
3721- debug ("search audio named \" {s}\" in {d}ms" , .{ name , end - start });
37223778
3723- start = end ;
3724- const audio = try sdl_load_resource (bundle , resource .? , gpa );
3725- errdefer gpa .free (audio );
3726- end = std .time .milliTimestamp ();
3779+ _ = mixer .MIX_PlayAudio (self .mix , buff .? );
37273780
3728- debug ("read audio named \" {s}\" size {d} in {d}ms" , .{
3729- name ,
3730- audio .len ,
3731- end - start ,
3732- });
3733-
3734- const ai = try AudioInfo .create (gpa , name , audio );
3735- ai .references += 1 ;
3736- try self .audio .put (gpa , ai .name , ai );
3737-
3738- return ai ;
3781+ return item ;
37393782 }
37403783
37413784 pub const SurfaceInfo = struct {
0 commit comments