4
4
#define HANDLE_MPV_RETURN (errorCode ) handleMpvRetr((errorCode),__func__,__FILE__,__LINE__)
5
5
#define HANDLE_SDL_RETURN (errorCode ) handleSdlRetr((errorCode),__func__,__FILE__,__LINE__)
6
6
7
- static void *get_proc_address_mpv (void *fn_ctx, const char *name) {
7
+ static void *getProAddressMpv (void *fn_ctx, const char *name) {
8
8
return reinterpret_cast <void *>(SDL_GL_GetProcAddress (name));
9
9
}
10
10
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 };
13
13
SDL_PushEvent (&event);
14
14
}
15
15
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 };
18
18
SDL_PushEvent (&event);
19
19
}
20
20
21
21
App::~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 );
31
36
}
32
-
33
37
34
38
void 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
+ }
36
102
}
37
103
38
104
const char *App::step (bool &quit) {
@@ -69,15 +135,16 @@ const char *App::step(bool &quit) {
69
135
default :
70
136
// Happens when there is new work for the render thread (such as
71
137
// rendering a new video frame or redrawing it).
72
- if (event.type == wakeup_on_mpv_render_update ) {
138
+ if (event.type == fWakeupOnMpvRenderUpdate ) {
73
139
uint64_t flags = mpv_render_context_update (fMpvRenderContext );
74
140
if (flags & MPV_RENDER_UPDATE_FRAME) {
75
141
redrawNeeded = 1 ;
76
142
}
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.
80
145
processMpvEvents ();
146
+ } else {
147
+ handleSdlEvent (event);
81
148
}
82
149
}
83
150
if (redrawNeeded) {
@@ -107,7 +174,10 @@ bool App::handleSdlRetr(int errorCode, const char *func, const char *filename, i
107
174
return true ;
108
175
}
109
176
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;
111
181
fMpvHandle = mpv_create ();
112
182
113
183
if (fMpvHandle == nullptr ) {
@@ -127,22 +197,26 @@ const char *App::setup(const char *input_file) {
127
197
128
198
SDL_SetHint (SDL_HINT_NO_SIGNAL_HANDLERS, " 1" );
129
199
130
- if (HANDLE_SDL_RETURN (SDL_Init (SDL_INIT_VIDEO))) {
200
+ if (HANDLE_SDL_RETURN (SDL_InitSubSystem (SDL_INIT_VIDEO))) {
131
201
return " unable to initialize sdl" ;
132
202
}
133
203
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
+ }
137
209
}
138
210
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
+ }
142
216
}
143
217
144
218
mpv_opengl_init_params initParams{
145
- .get_proc_address = get_proc_address_mpv
219
+ .get_proc_address = getProAddressMpv
146
220
};
147
221
int one = 1 ;
148
222
mpv_render_param params[] = {
@@ -172,23 +246,23 @@ const char *App::setup(const char *input_file) {
172
246
// work as possible, and merely wake up another thread to do actual work.
173
247
// On SDL, waking up the mainloop is the ideal course of action. SDL's
174
248
// 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 )) {
179
253
return " unable to register events" ;
180
254
}
181
255
182
256
// When normal mpv events are available.
183
- mpv_set_wakeup_callback (fMpvHandle , on_mpv_events , this );
257
+ mpv_set_wakeup_callback (fMpvHandle , onMpvEvent , this );
184
258
185
259
// When there is a need to call mpv_render_context_update(), which can
186
260
// request a new frame to be rendered.
187
261
// (Separate from the normal event handling mechanism for the sake of
188
262
// 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 );
190
264
191
- if (!scheduleMpvCommandAsync2 (" loadfile" , input_file )) {
265
+ if (!scheduleMpvCommandAsync2 (" loadfile" , inputFile )) {
192
266
return " unable to schedule loadfile command" ;
193
267
}
194
268
@@ -240,4 +314,20 @@ void App::processMpvEvents() {
240
314
fprintf (stderr, " received mpv event %s\n " , mpv_event_name (mp_event->event_id ));
241
315
}
242
316
}
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