From fc9acf32d63a670f7304b35ba583891834b4eaa2 Mon Sep 17 00:00:00 2001 From: lif <> Date: Mon, 16 Dec 2024 00:55:03 -0800 Subject: [PATCH] start using appstate now that it exists in sdl3 preview callback api --- main.c | 326 +++++++++++++++++++++++++++++---------------------------- 1 file changed, 168 insertions(+), 158 deletions(-) diff --git a/main.c b/main.c index 1257ad2..bc6618d 100644 --- a/main.c +++ b/main.c @@ -20,6 +20,7 @@ #include "mgba/feature/commandline.h" #include +#include #define NUM_CHANNELS 3 #define FRAMESKIP_LIMIT 20 @@ -32,10 +33,6 @@ #error "unknown pixel format" #endif -static SDL_Window* window = NULL; -static SDL_Renderer* renderer = NULL; -static SDL_Camera* camera = NULL; -static SDL_CameraSpec spec; static SDL_Texture* textures[NUM_CHANNELS] = { NULL, NULL, NULL }; static bool texture_updated = false; static SDL_CameraID front_camera = 0; @@ -47,6 +44,13 @@ static SDL_Surface* screens[NUM_CHANNELS] = { NULL, NULL, NULL }; static struct mCore* cores[NUM_CHANNELS] = { NULL, NULL, NULL }; static unsigned keys = 0; +struct AppState { + SDL_Camera* camera; + SDL_Window* window; + SDL_Renderer* renderer; + int cam_idx, spec_idx; +}; + enum mColorFormat pixfmt_sdl_to_mgba(uint32_t sdl_fmt) { switch (sdl_fmt) { case SDL_PIXELFORMAT_ABGR1555: return mCOLOR_BGR5; @@ -134,149 +138,109 @@ void myRequestImageBlue(struct mImageSource* self, const void** buf, size_t* str struct mImageSource gb_img_src[3]; -bool SelectCamera(SDL_Renderer* renderer) { - SDL_Event event; - +bool SelectCamera(struct AppState* st) { int devcount = 0; - int cam_idx = 0, spec_idx = 0; + SDL_CameraID *devices = SDL_GetCameras(&devcount); - while (camera == NULL) { - if (cam_idx >= devcount) { - cam_idx = 0; - } else if (cam_idx < 0) { - cam_idx = devcount - 1; - } + SDL_Renderer* renderer = st->renderer; - SDL_CameraID *devices = SDL_GetCameras(&devcount); - if (!devices) { - SDL_Log("SDL_GetCameras failed: %s", SDL_GetError()); - return false; - } + if (st->cam_idx >= devcount) { + st->cam_idx = 0; + } else if (st->cam_idx < 0) { + st->cam_idx = devcount - 1; + } - if (devcount == 0) { - SDL_free(devices); + if (!devices) { + SDL_Log("SDL_GetCameras failed: %s", SDL_GetError()); + return false; + } - SDL_SetRenderDrawColor(renderer, 0, 0, 0, 0); - SDL_RenderClear(renderer); - - SDL_SetRenderDrawColor(renderer, 255, 255, 255, 255); - SDL_RenderDebugText(renderer, 4, 4, "connect a camera"); - - SDL_RenderPresent(renderer); - - if (!SDL_WaitEvent(&event)) { - SDL_Log("Error waiting for event: %s", SDL_GetError()); - return false; - } - if (event.type == SDL_EVENT_QUIT) { - SDL_Log("Quit!"); - return false; - } - - continue; - } - - const SDL_CameraID device = devices[cam_idx]; - const char *name = SDL_GetCameraName(device); - - const SDL_CameraPosition position = SDL_GetCameraPosition(device); - const char *posstr = ""; - - char snprintfbuf[20]; - - int formats_len = 0; - - SDL_CameraSpec** formats = SDL_GetCameraSupportedFormats(device, &formats_len); - if (spec_idx >= formats_len) { - spec_idx = 0; - } else if (spec_idx < 0) { - spec_idx = formats_len - 1; - } - SDL_CameraSpec* format = formats[spec_idx]; - const char* pixfmt_name = SDL_GetPixelFormatName(format->format); - if (strncmp("SDL_PIXELFORMAT_", pixfmt_name, 16) == 0) { - pixfmt_name += 16; - } - - if (position == SDL_CAMERA_POSITION_FRONT_FACING) { - front_camera = device; - posstr = "[frontfacing]"; - } else if (position == SDL_CAMERA_POSITION_BACK_FACING) { - back_camera = device; - posstr = "[backfacing]"; - } + if (devcount == 0) { + SDL_free(devices); SDL_SetRenderDrawColor(renderer, 0, 0, 0, 0); SDL_RenderClear(renderer); SDL_SetRenderDrawColor(renderer, 255, 255, 255, 255); - SDL_RenderDebugText(renderer, 4, 4, "camera: (up/down)"); - snprintf(snprintfbuf, sizeof(snprintfbuf), "%d. %s", cam_idx, posstr); - SDL_RenderDebugText(renderer, 8, 16, snprintfbuf); - SDL_RenderDebugText(renderer, 4, 28, name); - SDL_free((void*)name); - - SDL_RenderDebugText(renderer, 4, 52, "mode: (left/right)"); - snprintf( - snprintfbuf, - sizeof(snprintfbuf), - "%d.", - spec_idx - ); - SDL_RenderDebugText(renderer, 8, 64, snprintfbuf); - - snprintf( - snprintfbuf, - sizeof(snprintfbuf), - "%dx%d", - format->width, - format->height - ); - SDL_RenderDebugText(renderer, 4, 76, snprintfbuf); - - snprintf( - snprintfbuf, - sizeof(snprintfbuf), - "%.1f Hz", - ((float)format->framerate_numerator / (float)format->framerate_denominator) - ); - SDL_RenderDebugText(renderer, 4, 88, snprintfbuf); - SDL_RenderDebugText(renderer, 4, 100, pixfmt_name); - - SDL_RenderDebugText(renderer, 4, 124, "confirm: (enter)"); - - if (!SDL_WaitEvent(&event)) { - SDL_Log("Error waiting for event: %s", SDL_GetError()); - return false; - } - - switch (event.type) { - case SDL_EVENT_QUIT: - SDL_Log("Quit!"); - return false; - - case SDL_EVENT_KEY_DOWN: - switch (event.key.key) { - case SDLK_UP: cam_idx -= 1; break; - case SDLK_DOWN: cam_idx += 1; break; - case SDLK_LEFT: spec_idx -= 1; break; - case SDLK_RIGHT: spec_idx += 1; break; - case SDLK_RETURN: - camera = SDL_OpenCamera(device, format); - break; - default: break; - } - break; - - default: break; - } - - SDL_free(formats); - SDL_free(devices); + SDL_RenderDebugText(renderer, 4, 4, "connect a camera"); SDL_RenderPresent(renderer); } + const SDL_CameraID device = devices[st->cam_idx]; + const char *name = SDL_GetCameraName(device); + + const SDL_CameraPosition position = SDL_GetCameraPosition(device); + const char *posstr = ""; + + char snprintfbuf[20]; + + int formats_len = 0; + + SDL_CameraSpec** formats = SDL_GetCameraSupportedFormats(device, &formats_len); + if (st->spec_idx >= formats_len) { + st->spec_idx = 0; + } else if (st->spec_idx < 0) { + st->spec_idx = formats_len - 1; + } + SDL_CameraSpec* format = formats[st->spec_idx]; + const char* pixfmt_name = SDL_GetPixelFormatName(format->format); + if (strncmp("SDL_PIXELFORMAT_", pixfmt_name, 16) == 0) { + pixfmt_name += 16; + } + + if (position == SDL_CAMERA_POSITION_FRONT_FACING) { + front_camera = device; + posstr = "[frontfacing]"; + } else if (position == SDL_CAMERA_POSITION_BACK_FACING) { + back_camera = device; + posstr = "[backfacing]"; + } + + SDL_SetRenderDrawColor(renderer, 0, 0, 0, 0); + SDL_RenderClear(renderer); + + SDL_SetRenderDrawColor(renderer, 255, 255, 255, 255); + SDL_RenderDebugText(renderer, 4, 4, "camera: (up/down)"); + snprintf(snprintfbuf, sizeof(snprintfbuf), "%d. %s", st->cam_idx, posstr); + SDL_RenderDebugText(renderer, 8, 16, snprintfbuf); + SDL_RenderDebugText(renderer, 4, 28, name); + SDL_free((void*)name); + + SDL_RenderDebugText(renderer, 4, 52, "mode: (left/right)"); + snprintf( + snprintfbuf, + sizeof(snprintfbuf), + "%d.", + st->spec_idx + ); + SDL_RenderDebugText(renderer, 8, 64, snprintfbuf); + + snprintf( + snprintfbuf, + sizeof(snprintfbuf), + "%dx%d", + format->width, + format->height + ); + SDL_RenderDebugText(renderer, 4, 76, snprintfbuf); + + snprintf( + snprintfbuf, + sizeof(snprintfbuf), + "%.1f Hz", + ((float)format->framerate_numerator / (float)format->framerate_denominator) + ); + SDL_RenderDebugText(renderer, 4, 88, snprintfbuf); + SDL_RenderDebugText(renderer, 4, 100, pixfmt_name); + + SDL_RenderDebugText(renderer, 4, 124, "confirm: (enter)"); + + SDL_free(formats); + SDL_free(devices); + + SDL_RenderPresent(renderer); + return true; } @@ -287,6 +251,10 @@ SDL_AppResult SDL_AppInit(void** appstate, int argc, char *argv[]) { struct mArguments args; bool parsed = mArgumentsParse(&args, argc, argv, NULL, 0); + struct AppState* st = malloc(sizeof(struct AppState)); + memset(st, 0, sizeof(struct AppState)); + *appstate = st; + /* Enable standard application logging */ SDL_SetLogPriority(SDL_LOG_CATEGORY_APPLICATION, SDL_LOG_PRIORITY_INFO); @@ -338,25 +306,20 @@ SDL_AppResult SDL_AppInit(void** appstate, int argc, char *argv[]) { return SDL_APP_FAILURE; } - window = SDL_CreateWindow("cgbwebcam", w, h, SDL_WINDOW_RESIZABLE); - if (!window) { + st->window = SDL_CreateWindow("cgbwebcam", w, h, SDL_WINDOW_RESIZABLE); + if (!st->window) { SDL_Log("Couldn't create window: %s", SDL_GetError()); return SDL_APP_FAILURE; } - renderer = SDL_CreateRenderer(window, NULL); - if (!renderer) { + st->renderer = SDL_CreateRenderer(st->window, NULL); + if (!st->renderer) { SDL_Log("Couldn't create renderer: %s", SDL_GetError()); return SDL_APP_FAILURE; } SDL_SetLogPriorities(SDL_LOG_PRIORITY_VERBOSE); - if (!SelectCamera(renderer)) { - SDL_Log("Failed to open camera device: %s", SDL_GetError()); - return SDL_APP_FAILURE; - } - for (i = 0; i < NUM_CHANNELS; i++) { int j; struct mCore* core = cores[i]; @@ -367,7 +330,7 @@ SDL_AppResult SDL_AppInit(void** appstate, int argc, char *argv[]) { screens[i] = screen; /* Create texture with appropriate format */ - texture = SDL_CreateTextureFromSurface(renderer, screens[0]); + texture = SDL_CreateTextureFromSurface(st->renderer, screens[0]); if (!texture) { SDL_Log("Couldn't create texture: %s", SDL_GetError()); return SDL_APP_FAILURE; @@ -412,14 +375,14 @@ SDL_AppResult SDL_AppInit(void** appstate, int argc, char *argv[]) { return SDL_APP_CONTINUE; /* start the main app loop. */ } -static SDL_AppResult FlipCamera(void) { +static SDL_AppResult FlipCamera(struct AppState* st) { static Uint64 last_flip = 0; if ((SDL_GetTicks() - last_flip) < 3000) { /* must wait at least 3 seconds between flips. */ return SDL_APP_CONTINUE; } - if (camera) { - const SDL_CameraID current = SDL_GetCameraID(camera); + if (st->camera) { + const SDL_CameraID current = SDL_GetCameraID(st->camera); SDL_CameraID nextcam = 0; if (current == front_camera) { nextcam = back_camera; @@ -430,10 +393,10 @@ static SDL_AppResult FlipCamera(void) { if (nextcam) { SDL_Log("Flip camera!"); - SDL_CloseCamera(camera); + SDL_CloseCamera(st->camera); - camera = SDL_OpenCamera(nextcam, NULL); - if (!camera) { + st->camera = SDL_OpenCamera(nextcam, NULL); + if (!st->camera) { SDL_Log("Failed to open camera device: %s", SDL_GetError()); return SDL_APP_FAILURE; } @@ -446,12 +409,43 @@ static SDL_AppResult FlipCamera(void) { } SDL_AppResult SDL_AppEvent(void *appstate, SDL_Event *event) { + struct AppState* st = (struct AppState*)appstate; + + if (st->camera == NULL) { + switch (event->type) { + case SDL_EVENT_QUIT: + SDL_Log("Quit!"); + return false; + + case SDL_EVENT_KEY_DOWN: + switch (event->key.key) { + case SDLK_UP: st->cam_idx -= 1; break; + case SDLK_DOWN: st->cam_idx += 1; break; + case SDLK_LEFT: st->spec_idx -= 1; break; + case SDLK_RIGHT: st->spec_idx += 1; break; + case SDLK_RETURN: { + SDL_CameraID *devices = SDL_GetCameras(NULL); + SDL_CameraID device = devices[st->cam_idx]; + SDL_CameraSpec** formats = SDL_GetCameraSupportedFormats(device, NULL); + st->camera = SDL_OpenCamera(device, formats[st->spec_idx]); + SDL_free(devices); + SDL_free(formats); + break; + } + default: break; + } + break; + + default: break; + } + } + switch (event->type) { case SDL_EVENT_KEY_DOWN: { const SDL_Keycode sym = event->key.key; switch (sym) { case SDLK_ESCAPE: case SDLK_AC_BACK: return SDL_APP_SUCCESS; - case SDLK_SPACE: FlipCamera(); break; + case SDLK_SPACE: FlipCamera(st); break; case SDLK_UP: keys |= 0x40; break; case SDLK_DOWN: keys |= 0x80; break; case SDLK_LEFT: keys |= 0x20; break; @@ -481,19 +475,21 @@ SDL_AppResult SDL_AppEvent(void *appstate, SDL_Event *event) { case SDL_EVENT_MOUSE_BUTTON_DOWN: /* !!! FIXME: only flip if clicked in the area of a "flip" icon. */ - return FlipCamera(); + return FlipCamera(st); case SDL_EVENT_QUIT: SDL_Log("Quit!"); return SDL_APP_SUCCESS; - case SDL_EVENT_CAMERA_DEVICE_APPROVED: + case SDL_EVENT_CAMERA_DEVICE_APPROVED: { + SDL_CameraSpec spec; SDL_Log("Camera approved!"); - if (!SDL_GetCameraFormat(camera, &spec)) { + if (!SDL_GetCameraFormat(st->camera, &spec)) { SDL_Log("Couldn't get camera spec: %s", SDL_GetError()); return SDL_APP_FAILURE; } break; + } case SDL_EVENT_CAMERA_DEVICE_DENIED: SDL_Log("Camera denied!"); @@ -523,12 +519,24 @@ SDL_AppResult SDL_AppEvent(void *appstate, SDL_Event *event) { } SDL_AppResult SDL_AppIterate(void* appstate) { + struct AppState* st = (struct AppState*)appstate; + + if (st->camera == NULL) { + if (!SelectCamera(st)) { + SDL_Log("Failed to show camera device menu: %s", SDL_GetError()); + return SDL_APP_FAILURE; + } + return SDL_APP_CONTINUE; + } + + SDL_Renderer* renderer = st->renderer; + int i; static int since_last_present = 0; if (scaled != NULL) { Uint64 timestampNS = 0; - SDL_Surface *frame = camera ? SDL_AcquireCameraFrame(camera, ×tampNS) : NULL; + SDL_Surface *frame = st->camera ? SDL_AcquireCameraFrame(st->camera, ×tampNS) : NULL; if (frame) { struct SDL_Rect srcrect, dstrect; @@ -551,7 +559,7 @@ SDL_AppResult SDL_AppIterate(void* appstate) { SDL_Log("failed to scale: %s", SDL_GetError()); } - SDL_ReleaseCameraFrame(camera, frame); + SDL_ReleaseCameraFrame(st->camera, frame); SDL_SetSurfaceColorMod(scaled, 255, 0, 0); SDL_BlitSurface(scaled, NULL, filtered[0], NULL); @@ -606,6 +614,7 @@ SDL_AppResult SDL_AppIterate(void* appstate) { } void SDL_AppQuit(void* appstate, SDL_AppResult result) { + struct AppState* st = (struct AppState*)appstate; int i; for (i = 0; i < NUM_CHANNELS; i++) { mCoreConfigDeinit(&cores[i]->config); @@ -613,7 +622,8 @@ void SDL_AppQuit(void* appstate, SDL_AppResult result) { SDL_DestroyTexture(textures[i]); } - SDL_CloseCamera(camera); - SDL_DestroyRenderer(renderer); - SDL_DestroyWindow(window); + SDL_CloseCamera(st->camera); + SDL_DestroyRenderer(st->renderer); + SDL_DestroyWindow(st->window); + free(st); }