44#define HANDLE_MPV_RETURN (errorCode ) handleMpvRetr((errorCode),__func__,__FILE__,__LINE__)
55#define HANDLE_SDL_RETURN (errorCode ) handleSdlRetr((errorCode),__func__,__FILE__,__LINE__)
66
7- static void *get_proc_address_mpv (void *fn_ctx, const char *name) {
7+ static void *getProAddressMpv (void *fn_ctx, const char *name) {
88 return reinterpret_cast <void *>(SDL_GL_GetProcAddress (name));
99}
1010
11- static void on_mpv_events (void *ctx) {
12- SDL_Event event = {.type = reinterpret_cast <App*>(ctx)->wakeup_on_mpv_events };
11+ static void onMpvEvent (void *ctx) {
12+ SDL_Event event = {.type = reinterpret_cast <App*>(ctx)->fWakeupOnMpvEvents };
1313 SDL_PushEvent (&event);
1414}
1515
16- static void on_mpv_render_update (void *ctx) {
17- SDL_Event event = {.type = reinterpret_cast <App*>(ctx)->wakeup_on_mpv_render_update };
16+ static void onMpvRenderUpdate (void *ctx) {
17+ SDL_Event event = {.type = reinterpret_cast <App*>(ctx)->fWakeupOnMpvRenderUpdate };
1818 SDL_PushEvent (&event);
1919}
2020
2121App::~App () {
22- if (fMpvRenderContext != nullptr ) {
23- // Destroy the GL renderer and all the GL objects it allocated. If video
24- // is still running, the video track will be deselected.
25- mpv_render_context_free (fMpvRenderContext );
26- }
27-
28- if (fMpvHandle != nullptr ) {
29- mpv_destroy (fMpvHandle );
30- }
22+ teardown ();
23+ }
24+ void App::serializeUserInteractionEventFB (const uint8_t *&out,size_t &size, flatbuffers::Offset<void > e) {
25+ fFlatBufferBuilder .FinishSizePrefixed (e);
26+ size = fFlatBufferBuilder .GetSize ();
27+ out = fFlatBufferBuilder .GetBufferPointer ();
28+ }
29+ void App::sendUserInteractionEvent (flatbuffers::Offset<void > e) {
30+ const uint8_t *ptr = nullptr ;
31+ size_t sz = 0 ;
32+ serializeUserInteractionEventFB (ptr,sz,e);
33+ fprintf (stderr," sz=%d,%.*s\n " ,(int )sz,(int )sz,ptr);
34+ fwrite (ptr,1 ,sz,fUserInteractionOutput );
35+ fflush (fUserInteractionOutput );
3136}
32-
3337
3438void App::handleSdlEvent (SDL_Event &event) {
35-
39+ fFlatBufferBuilder .Clear ();
40+ switch (event.type ) {
41+ case SDL_EVENT_MOUSE_MOTION:
42+ {
43+ auto const ev = event.motion ;
44+ auto const pos = UserInteractionFB::SingleVec2 (ev.x ,ev.y );
45+ auto const e = UserInteractionFB::CreateEventMouseMotion (fFlatBufferBuilder ,&pos,ev.which ,ev.which == SDL_TOUCH_MOUSEID).Union ();
46+ sendUserInteractionEvent (e);
47+ }
48+ break ;
49+ case SDL_EVENT_MOUSE_WHEEL:
50+ {
51+ auto const ev = event.wheel ;
52+ auto const pos = UserInteractionFB::SingleVec2 (ev.x ,ev.y );
53+ auto const e = UserInteractionFB::CreateEventMouseWheel (fFlatBufferBuilder , &pos, ev.which , ev.which == SDL_TOUCH_MOUSEID).Union ();
54+ sendUserInteractionEvent (e);
55+ }
56+ break ;
57+ case SDL_EVENT_MOUSE_BUTTON_DOWN:
58+ case SDL_EVENT_MOUSE_BUTTON_UP:
59+ {
60+ auto const ev = event.button ;
61+ UserInteractionFB::MouseButton b = UserInteractionFB::MouseButton_None;
62+ switch (ev.button ) {
63+ case SDL_BUTTON_LEFT:
64+ b = UserInteractionFB::MouseButton_Left;
65+ break ;
66+ case SDL_BUTTON_RIGHT:
67+ b = UserInteractionFB::MouseButton_Right;
68+ break ;
69+ case SDL_BUTTON_MIDDLE:
70+ b = UserInteractionFB::MouseButton_Middle;
71+ break ;
72+ case SDL_BUTTON_X1:
73+ b = UserInteractionFB::MouseButton_X1;
74+ break ;
75+ case SDL_BUTTON_X2:
76+ b = UserInteractionFB::MouseButton_X2;
77+ break ;
78+ }
79+ auto const pos = UserInteractionFB::SingleVec2 (ev.x ,ev.y );
80+ auto const e = UserInteractionFB::CreateEventMouseButton (fFlatBufferBuilder ,&pos,ev.which ,ev.which == SDL_TOUCH_MOUSEID,b).Union ();
81+ sendUserInteractionEvent (e);
82+ }
83+ break ;
84+ case SDL_EVENT_TEXT_INPUT:
85+ {
86+ auto const ev = event.text ;
87+ auto const t = fFlatBufferBuilder .CreateString (ev.text );
88+ auto const e = UserInteractionFB::CreateEventTextInput (fFlatBufferBuilder ,t).Union ();
89+ sendUserInteractionEvent (e);
90+ }
91+ break ;
92+ // case SDL_EVENT_KEY_DOWN:
93+ // case SDL_EVENT_KEY_UP:
94+ // {
95+ // ImGui_ImplSDL3_UpdateKeyModifiers((SDL_Keymod)event->key.keysym.mod);
96+ // ImGuiKey key = ImGui_ImplSDL3_KeycodeToImGuiKey(event->key.keysym.sym);
97+ // io.AddKeyEvent(key, (event->type == SDL_EVENT_KEY_DOWN));
98+ // io.SetKeyEventNativeData(key, event->key.keysym.sym, event->key.keysym.scancode, event->key.keysym.scancode); // To support legacy indexing (<1.87 user code). Legacy backend uses SDLK_*** as indices to IsKeyXXX() functions.
99+ // return true;
100+ // }
101+ }
36102}
37103
38104const char *App::step (bool &quit) {
@@ -69,15 +135,16 @@ const char *App::step(bool &quit) {
69135 default :
70136 // Happens when there is new work for the render thread (such as
71137 // rendering a new video frame or redrawing it).
72- if (event.type == wakeup_on_mpv_render_update ) {
138+ if (event.type == fWakeupOnMpvRenderUpdate ) {
73139 uint64_t flags = mpv_render_context_update (fMpvRenderContext );
74140 if (flags & MPV_RENDER_UPDATE_FRAME) {
75141 redrawNeeded = 1 ;
76142 }
77- }
78- // Happens when at least 1 new event is in the mpv event queue.
79- if (event.type == wakeup_on_mpv_events) {
143+ } else if (event.type == fWakeupOnMpvEvents ) {
144+ // Happens when at least 1 new event is in the mpv event queue.
80145 processMpvEvents ();
146+ } else {
147+ handleSdlEvent (event);
81148 }
82149 }
83150 if (redrawNeeded) {
@@ -107,7 +174,10 @@ bool App::handleSdlRetr(int errorCode, const char *func, const char *filename, i
107174 return true ;
108175}
109176
110- const char *App::setup (const char *input_file) {
177+ // FIXME allow multiple calls to setup?
178+ const char *App::setup (const char *inputFile, FILE *userInteractionOutput) {
179+ teardown ();
180+ fUserInteractionOutput = userInteractionOutput;
111181 fMpvHandle = mpv_create ();
112182
113183 if (fMpvHandle == nullptr ) {
@@ -127,22 +197,26 @@ const char *App::setup(const char *input_file) {
127197
128198 SDL_SetHint (SDL_HINT_NO_SIGNAL_HANDLERS, " 1" );
129199
130- if (HANDLE_SDL_RETURN (SDL_Init (SDL_INIT_VIDEO))) {
200+ if (HANDLE_SDL_RETURN (SDL_InitSubSystem (SDL_INIT_VIDEO))) {
131201 return " unable to initialize sdl" ;
132202 }
133203
134- fSdlWindow = SDL_CreateWindow (" imzero sdl2 mpv video player" , 1920 , 1080 , SDL_WINDOW_OPENGL | SDL_WINDOW_RESIZABLE);
135- if (!fSdlWindow ) {
136- return " unable to create sdl windo" ;
204+ if (fSdlWindow == nullptr ) {
205+ fSdlWindow = SDL_CreateWindow (" imzero sdl2 mpv video player" , 1920 , 1080 , SDL_WINDOW_OPENGL | SDL_WINDOW_RESIZABLE);
206+ if (!fSdlWindow ) {
207+ return " unable to create sdl window" ;
208+ }
137209 }
138210
139- fSdlGlContext = SDL_GL_CreateContext (fSdlWindow );
140- if (!fSdlGlContext ) {
141- return " unable to create sdl gl context" ;
211+ if (fSdlGlContext == nullptr ) {
212+ fSdlGlContext = SDL_GL_CreateContext (fSdlWindow );
213+ if (!fSdlGlContext ) {
214+ return " unable to create sdl gl context" ;
215+ }
142216 }
143217
144218 mpv_opengl_init_params initParams{
145- .get_proc_address = get_proc_address_mpv
219+ .get_proc_address = getProAddressMpv
146220 };
147221 int one = 1 ;
148222 mpv_render_param params[] = {
@@ -172,23 +246,23 @@ const char *App::setup(const char *input_file) {
172246 // work as possible, and merely wake up another thread to do actual work.
173247 // On SDL, waking up the mainloop is the ideal course of action. SDL's
174248 // SDL_PushEvent() is thread-safe, so we use that.
175- wakeup_on_mpv_render_update = SDL_RegisterEvents (1 );
176- wakeup_on_mpv_events = SDL_RegisterEvents (1 );
177- if (wakeup_on_mpv_render_update == static_cast <Uint32>(-1 ) ||
178- wakeup_on_mpv_events == static_cast <Uint32>(-1 )) {
249+ fWakeupOnMpvRenderUpdate = SDL_RegisterEvents (1 );
250+ fWakeupOnMpvEvents = SDL_RegisterEvents (1 );
251+ if (fWakeupOnMpvRenderUpdate == static_cast <Uint32>(-1 ) ||
252+ fWakeupOnMpvEvents == static_cast <Uint32>(-1 )) {
179253 return " unable to register events" ;
180254 }
181255
182256 // When normal mpv events are available.
183- mpv_set_wakeup_callback (fMpvHandle , on_mpv_events , this );
257+ mpv_set_wakeup_callback (fMpvHandle , onMpvEvent , this );
184258
185259 // When there is a need to call mpv_render_context_update(), which can
186260 // request a new frame to be rendered.
187261 // (Separate from the normal event handling mechanism for the sake of
188262 // users which run OpenGL on a different thread.)
189- mpv_render_context_set_update_callback (fMpvRenderContext , on_mpv_render_update , this );
263+ mpv_render_context_set_update_callback (fMpvRenderContext , onMpvRenderUpdate , this );
190264
191- if (!scheduleMpvCommandAsync2 (" loadfile" , input_file )) {
265+ if (!scheduleMpvCommandAsync2 (" loadfile" , inputFile )) {
192266 return " unable to schedule loadfile command" ;
193267 }
194268
@@ -240,4 +314,20 @@ void App::processMpvEvents() {
240314 fprintf (stderr, " received mpv event %s\n " , mpv_event_name (mp_event->event_id ));
241315 }
242316 }
243- }
317+ }
318+
319+ void App::teardown () {
320+ if (fMpvRenderContext != nullptr ) {
321+ // Destroy the GL renderer and all the GL objects it allocated. If video
322+ // is still running, the video track will be deselected.
323+ mpv_render_context_free (fMpvRenderContext );
324+ fMpvRenderContext = nullptr ;
325+ }
326+
327+ if (fMpvHandle != nullptr ) {
328+ mpv_destroy (fMpvHandle );
329+ fMpvHandle = nullptr ;
330+ }
331+
332+ fUserInteractionOutput = nullptr ;
333+ }
0 commit comments