int jiveL_set_video_mode(lua_State *L) { JiveSurface *srf; Uint16 w, h, bpp; bool isfull; /* stack is: * 1: framework * 2: w * 3: h * 4: bpp * 5: fullscreen */ w = luaL_optinteger(L, 2, 0); h = luaL_optinteger(L, 3, 0); bpp = luaL_optinteger(L, 4, 16); isfull = lua_toboolean(L, 5); if (w == screen_w && h == screen_h && bpp == screen_bpp && isfull == screen_isfull) { return 0; } /* update video mode */ srf = jive_surface_set_video_mode(w, h, bpp, isfull); if (!srf) { LOG_ERROR(log_ui_draw, "Video mode not supported: %dx%d\n", w, h); SDL_Quit(); exit(-1); } /* store new screen surface */ lua_getfield(L, 1, "screen"); tolua_pushusertype(L, srf, "Surface"); lua_setfield(L, -2, "surface"); lua_getfield(L, -1, "bounds"); lua_pushvalue(L, 2); /* width */ lua_rawseti(L, -2, 3); lua_pushvalue(L, 3); /* height */ lua_rawseti(L, -2, 4); lua_pop(L, 2); screen_w = w; screen_h = h; screen_bpp = bpp; screen_isfull = isfull; next_jive_origin++; return 0; }
static int jiveL_initSDL(lua_State *L) { const SDL_VideoInfo *video_info; #ifndef JIVE_NO_DISPLAY JiveSurface *srf, *splash; Uint16 splash_w, splash_h; bool fullscreen = false; char splashfile[32] = "jive/splash.png"; #endif /* logging */ log_ui_draw = LOG_CATEGORY_GET("squeezeplay.ui.draw"); log_ui = LOG_CATEGORY_GET("squeezeplay.ui"); /* linux fbcon does not need a mouse */ SDL_putenv("SDL_NOMOUSE=1"); #ifdef JIVE_NO_DISPLAY # define JIVE_SDL_FEATURES (SDL_INIT_EVENTLOOP) #else # define JIVE_SDL_FEATURES (SDL_INIT_VIDEO) #endif /* initialise SDL */ if (SDL_Init(JIVE_SDL_FEATURES) < 0) { LOG_ERROR(log_ui_draw, "SDL_Init(V|T|A): %s\n", SDL_GetError()); SDL_Quit(); exit(-1); } /* report video info */ if ((video_info = SDL_GetVideoInfo())) { LOG_INFO(log_ui_draw, "%d,%d %d bits/pixel %d bytes/pixel [R<<%d G<<%d B<<%d]", video_info->current_w, video_info->current_h, video_info->vfmt->BitsPerPixel, video_info->vfmt->BytesPerPixel, video_info->vfmt->Rshift, video_info->vfmt->Gshift, video_info->vfmt->Bshift); LOG_INFO(log_ui_draw, "Hardware acceleration %s available", video_info->hw_available?"is":"is not"); LOG_INFO(log_ui_draw, "Window Manager %s available", video_info->wm_available?"is":"is not"); } /* Register callback for additional events (used for multimedia keys)*/ SDL_EventState(SDL_SYSWMEVENT,SDL_ENABLE); SDL_SetEventFilter(filter_events); // Secific magic for windows|linux|macos platform_init(L); #ifndef JIVE_NO_DISPLAY /* open window */ SDL_WM_SetCaption("SqueezePlay", "SqueezePlay"); SDL_ShowCursor(SDL_DISABLE); SDL_EnableKeyRepeat (100, 100); SDL_EnableUNICODE(1); #ifdef SCREEN_ROTATION_ENABLED screen_w = video_info->current_h; screen_h = video_info->current_w; #else screen_w = video_info->current_w; screen_h = video_info->current_h; #endif screen_bpp = video_info->vfmt->BitsPerPixel; if (video_info->wm_available) { /* desktop build */ JiveSurface *icon; /* load the icon */ icon = jive_surface_load_image("jive/app.png"); if (icon) { jive_surface_set_wm_icon(icon); jive_surface_free(icon); } splash = jive_surface_load_image(splashfile); if (splash) { jive_surface_get_size(splash, &splash_w, &splash_h); screen_w = splash_w; screen_h = splash_h; } } else { /* product build and full screen...*/ sprintf(splashfile, "jive/splash%dx%d.png", screen_w, screen_h); splash = jive_surface_load_image(splashfile); if(!splash) { sprintf(splashfile,"jive/splash.png"); splash = jive_surface_load_image(splashfile); } if (splash) { jive_surface_get_size(splash, &splash_w, &splash_h); } fullscreen = true; } srf = jive_surface_set_video_mode(screen_w, screen_h, screen_bpp, fullscreen); if (!srf) { LOG_ERROR(log_ui_draw, "Video mode not supported: %dx%d\n", screen_w, screen_h); SDL_Quit(); exit(-1); } if (splash) { jive_surface_blit(splash, srf, (screen_w - splash_w) > 0 ?((screen_w - splash_w) / 2):0, (screen_w - splash_w) > 0 ?((screen_w - splash_w) / 2):0); jive_surface_flip(srf); LOG_INFO(log_ui_draw, "Splash %s %dx%d Screen %dx%d", splashfile,splash_w,splash_h,screen_w,screen_h); } lua_getfield(L, 1, "screen"); if (lua_isnil(L, -1)) { LOG_ERROR(log_ui_draw, "no screen table"); SDL_Quit(); exit(-1); } /* store screen surface */ tolua_pushusertype(L, srf, "Surface"); lua_setfield(L, -2, "surface"); lua_getfield(L, -1, "bounds"); lua_pushinteger(L, screen_w); lua_rawseti(L, -2, 3); lua_pushinteger(L, screen_h); lua_rawseti(L, -2, 4); lua_pop(L, 2); /* background image */ jive_background = jive_tile_fill_color(0x000000FF); /* jive.ui.style = {} */ lua_getglobal(L, "jive"); lua_getfield(L, -1, "ui"); lua_newtable(L); lua_setfield(L, -2, "style"); lua_pop(L, 2); ui_watchdog = watchdog_get(); watchdog_keepalive(ui_watchdog, 6); /* 60 seconds to start */ #endif /* JIVE_NO_DISPLAY */ return 0; }
int jiveL_set_video_mode(lua_State *L) { JiveSurface *srf; Uint16 w, h, bpp; bool isfull; const SDL_VideoInfo *video_info; /* stack is: * 1: framework * 2: w * 3: h * 4: bpp * 5: fullscreen */ w = luaL_optinteger(L, 2, 0); h = luaL_optinteger(L, 3, 0); bpp = luaL_optinteger(L, 4, 16); isfull = lua_toboolean(L, 5); // force fullscreen if no window manager is available - this prevents sdl crashing on some hardware video_info = SDL_GetVideoInfo(); if (!video_info->wm_available) { isfull = true; } if (w == screen_w && h == screen_h && bpp == screen_bpp && isfull == screen_isfull) { return 0; } /* update video mode */ srf = jive_surface_set_video_mode(w, h, bpp, isfull); /* store new screen surface */ lua_getfield(L, 1, "screen"); JiveSurface **p = (JiveSurface **)lua_newuserdata(L, sizeof(JiveSurface *)); *p = jive_surface_ref(srf); luaL_getmetatable(L, "JiveSurface"); lua_setmetatable(L, -2); lua_setfield(L, -2, "surface"); lua_getfield(L, -1, "bounds"); lua_pushvalue(L, 2); /* width */ lua_rawseti(L, -2, 3); lua_pushvalue(L, 3); /* height */ lua_rawseti(L, -2, 4); lua_pop(L, 2); screen_w = w; screen_h = h; screen_bpp = bpp; screen_isfull = isfull; next_jive_origin++; return 0; }
static int process_event(lua_State *L, SDL_Event *event) { JiveEvent jevent; Uint32 now; memset(&jevent, 0, sizeof(JiveEvent)); jevent.ticks = now = jive_jiffies(); switch (event->type) { case SDL_QUIT: jiveL_quit(L); exit(0); break; case SDL_MOUSEBUTTONDOWN: /* map the mouse scroll wheel to up/down */ if (event->button.button == SDL_BUTTON_WHEELUP) { jevent.type = JIVE_EVENT_SCROLL; --(jevent.u.scroll.rel); break; } else if (event->button.button == SDL_BUTTON_WHEELDOWN) { jevent.type = JIVE_EVENT_SCROLL; ++(jevent.u.scroll.rel); break; } // Fall through case SDL_MOUSEBUTTONUP: if (event->button.button == SDL_BUTTON_LEFT) { if (event->button.state == SDL_PRESSED) { jevent.type = JIVE_EVENT_MOUSE_DOWN; jevent.u.mouse.x = event->button.x; jevent.u.mouse.y = event->button.y; } else { jevent.type = JIVE_EVENT_MOUSE_UP; jevent.u.mouse.x = event->button.x; jevent.u.mouse.y = event->button.y; } } if (event->type == SDL_MOUSEBUTTONDOWN) { if (mouse_state == MOUSE_STATE_NONE) { mouse_state = MOUSE_STATE_DOWN; mouse_timeout_arg = (event->button.y << 16) | event->button.x; mouse_timeout = now + HOLD_TIMEOUT; mouse_long_timeout = now + LONG_HOLD_TIMEOUT; mouse_origin_x = event->button.x; mouse_origin_y = event->button.y; break; } } else /* SDL_MOUSEBUTTONUP */ { if (mouse_state == MOUSE_STATE_DOWN) { /* * MOUSE_PRESSED and MOUSE_UP events */ JiveEvent up; memset(&up, 0, sizeof(JiveEvent)); up.type = JIVE_EVENT_MOUSE_PRESS; up.ticks = jive_jiffies(); up.u.mouse.x = event->button.x; up.u.mouse.y = event->button.y; do_dispatch_event(L, &up); } mouse_timeout = 0; mouse_long_timeout = 0; mouse_state = MOUSE_STATE_NONE; } break; case SDL_MOUSEMOTION: /* show mouse cursor */ if (pointer_timeout == 0) { SDL_ShowCursor(SDL_ENABLE); } pointer_timeout = now + POINTER_TIMEOUT; if (event->motion.state & SDL_BUTTON(1)) { if ( (mouse_state == MOUSE_STATE_DOWN || mouse_state == MOUSE_STATE_SENT)) { jevent.type = JIVE_EVENT_MOUSE_DRAG; jevent.u.mouse.x = event->motion.x; jevent.u.mouse.y = event->motion.y; } } else { jevent.type = JIVE_EVENT_MOUSE_MOVE; jevent.u.mouse.x = event->motion.x; jevent.u.mouse.y = event->motion.y; } break; case SDL_KEYDOWN: if (event->key.keysym.mod == KMOD_NONE || event->key.keysym.mod == KMOD_NUM) { if (event->key.keysym.sym == SDLK_UP) { jevent.type = JIVE_EVENT_SCROLL; --(jevent.u.scroll.rel); break; } else if (event->key.keysym.sym == SDLK_DOWN) { jevent.type = JIVE_EVENT_SCROLL; ++(jevent.u.scroll.rel); break; } } // Fall through case SDL_KEYUP: { struct jive_keymap *entry = keymap; #ifdef EMULATE_IR if (event->key.keysym.mod & (KMOD_ALT|KMOD_MODE)) { struct jive_keyir *ir = irmap; while (ir->keysym != SDLK_UNKNOWN) { if (ir->keysym == event->key.keysym.sym) { break; } ir++; } if (ir->keysym == SDLK_UNKNOWN) { break; } if (event->type == SDL_KEYDOWN) { jevent.type = JIVE_EVENT_IR_DOWN; jevent.u.ir.code = ir->code; } else { JiveEvent irup; jevent.type = JIVE_EVENT_IR_PRESS; jevent.u.ir.code = ir->code; memset(&irup, 0, sizeof(JiveEvent)); irup.type = JIVE_EVENT_IR_UP; irup.ticks = jive_jiffies(); irup.u.ir.code = ir->code; jive_queue_event(&irup); } break; } #endif while (entry->keysym != SDLK_UNKNOWN) { if (entry->keysym == event->key.keysym.sym) { if (event->type == SDL_KEYDOWN && (!entry->mod || entry->mod == event->key.keysym.mod)) { // match a key with same modifiers if present on keydown break; } if (event->type == SDL_KEYUP && (key_mask & entry->keycode)) { // match a key which is currently marked as down ignoring modifiers as they may have changed break; } } entry++; } if (entry->keysym == SDLK_UNKNOWN) { // handle regular character keys ('a', 't', etc..) if (event->type == SDL_KEYDOWN && event->key.keysym.unicode != 0) { jevent.type = JIVE_EVENT_CHAR_PRESS; if (event->key.keysym.sym == SDLK_BACKSPACE) { //special case for Backspace, where value set is not ascii value, instead pass backspace ascii value jevent.u.text.unicode = 8; } else { jevent.u.text.unicode = event->key.keysym.unicode; } } } /* handle pgup/upgn and cursors as repeatable keys */ else if (entry->keysym == SDLK_PAGEUP || entry->keysym == SDLK_PAGEDOWN || entry->keysym == SDLK_UP || entry->keysym == SDLK_DOWN || entry->keysym == SDLK_LEFT || entry->keysym == SDLK_RIGHT) { if (event->type == SDL_KEYDOWN) { jevent.type = JIVE_EVENT_KEY_PRESS; jevent.ticks = jive_jiffies(); jevent.u.key.code = entry->keycode; } } else if (event->type == SDL_KEYDOWN) { if (key_mask & entry->keycode) { // ignore key repeats return 0; } if (key_mask == 0) { key_state = KEY_STATE_NONE; } switch (key_state) { case KEY_STATE_NONE: key_state = KEY_STATE_DOWN; // fall through case KEY_STATE_DOWN: { key_mask |= entry->keycode; jevent.type = JIVE_EVENT_KEY_DOWN; jevent.u.key.code = entry->keycode; key_timeout = now + HOLD_TIMEOUT; break; } case KEY_STATE_SENT: break; } } else /* SDL_KEYUP */ { if (! (key_mask & entry->keycode)) { // ignore repeated key ups return 0; } switch (key_state) { case KEY_STATE_NONE: break; case KEY_STATE_DOWN: { /* * KEY_PRESSED and KEY_UP events */ JiveEvent keyup; jevent.type = JIVE_EVENT_KEY_PRESS; jevent.u.key.code = key_mask; memset(&keyup, 0, sizeof(JiveEvent)); keyup.type = JIVE_EVENT_KEY_UP; keyup.ticks = jive_jiffies(); keyup.u.key.code = entry->keycode; jive_queue_event(&keyup); key_state = KEY_STATE_SENT; break; } case KEY_STATE_SENT: { /* * KEY_UP event */ jevent.type = JIVE_EVENT_KEY_UP; jevent.u.key.code = entry->keycode; break; } } key_timeout = 0; key_mask &= ~(entry->keycode); if (key_mask == 0) { key_state = KEY_STATE_NONE; } } break; } case SDL_USEREVENT: assert(event->user.code == JIVE_USER_EVENT_EVENT); memcpy(&jevent, event->user.data1, sizeof(JiveEvent)); free(event->user.data1); break; case SDL_VIDEORESIZE: { JiveSurface *srf; int bpp = 16; screen_w = event->resize.w; screen_h = event->resize.h; srf = jive_surface_set_video_mode(screen_w, screen_h, bpp, jive_surface_isSDLFullScreen(NULL)); if (!srf) { LOG_ERROR(log_ui_draw, "Video mode not supported: %dx%d\n", screen_w, screen_h); SDL_Quit(); exit(-1); } lua_getfield(L, 1, "screen"); lua_getfield(L, -1, "bounds"); lua_pushinteger(L, screen_w); lua_rawseti(L, -2, 3); lua_pushinteger(L, screen_h); lua_rawseti(L, -2, 4); lua_pop(L, 1); tolua_pushusertype(L, srf, "Surface"); lua_setfield(L, -2, "surface"); lua_pop(L, 1); next_jive_origin++; jevent.type = JIVE_EVENT_WINDOW_RESIZE; /* Avoid mouse_up causing a mouse press event to occur */ mouse_state = MOUSE_STATE_NONE; break; } default: return 0; } return do_dispatch_event(L, &jevent); }
static int jiveL_initSDL(lua_State *L) { const SDL_VideoInfo *video_info; JiveSurface *srf, *splash, *icon; Uint16 splash_w, splash_h; /* logging */ log_ui_draw = LOG_CATEGORY_GET("jivelite.ui.draw"); log_ui = LOG_CATEGORY_GET("jivelite.ui"); /* linux fbcon does not need a mouse */ SDL_putenv("SDL_NOMOUSE=1"); /* allow the screensaver */ SDL_putenv("SDL_VIDEO_ALLOW_SCREENSAVER=1"); /* initialise SDL */ if (SDL_Init(SDL_INIT_VIDEO) < 0) { LOG_ERROR(log_ui_draw, "SDL_Init(V|T|A): %s\n", SDL_GetError()); SDL_Quit(); exit(-1); } /* report video info */ if ((video_info = SDL_GetVideoInfo())) { LOG_INFO(log_ui_draw, "%d,%d %d bits/pixel %d bytes/pixel [R<<%d G<<%d B<<%d]", video_info->current_w, video_info->current_h, video_info->vfmt->BitsPerPixel, video_info->vfmt->BytesPerPixel, video_info->vfmt->Rshift, video_info->vfmt->Gshift, video_info->vfmt->Bshift); LOG_INFO(log_ui_draw, "Hardware acceleration %s available", video_info->hw_available?"is":"is not"); LOG_INFO(log_ui_draw, "Window manager %s available", video_info->wm_available?"is":"is not"); } /* Register callback for additional events (used for multimedia keys)*/ SDL_EventState(SDL_SYSWMEVENT,SDL_ENABLE); SDL_SetEventFilter(filter_events); platform_init(L); /* open window */ SDL_WM_SetCaption("JiveLite Alpha", "JiveLite Alpha"); SDL_ShowCursor(SDL_DISABLE); SDL_EnableKeyRepeat (100, 100); SDL_EnableUNICODE(1); /* load the icon */ icon = jive_surface_load_image("jive/app.png"); if (icon) { jive_surface_set_wm_icon(icon); jive_surface_free(icon); } screen_w = video_info->current_w; screen_h = video_info->current_h; screen_bpp = video_info->vfmt->BitsPerPixel; splash = jive_surface_load_image("jive/splash.png"); if (splash) { jive_surface_get_size(splash, &splash_w, &splash_h); if (video_info->wm_available) { screen_w = splash_w; screen_h = splash_h; } } srf = jive_surface_set_video_mode(screen_w, screen_h, screen_bpp, video_info->wm_available ? false : true); if (!srf) { SDL_Quit(); exit(-1); } if (splash) { jive_surface_blit(splash, srf, MAX(0, (screen_w - splash_w) / 2), MAX(0, (screen_h - splash_h) / 2)); jive_surface_flip(srf); } lua_getfield(L, 1, "screen"); if (lua_isnil(L, -1)) { LOG_ERROR(log_ui_draw, "no screen table"); SDL_Quit(); exit(-1); } /* store screen surface */ JiveSurface **p = (JiveSurface **)lua_newuserdata(L, sizeof(JiveSurface *)); *p = jive_surface_ref(srf); luaL_getmetatable(L, "JiveSurface"); lua_setmetatable(L, -2); lua_setfield(L, -2, "surface"); lua_getfield(L, -1, "bounds"); lua_pushinteger(L, screen_w); lua_rawseti(L, -2, 3); lua_pushinteger(L, screen_h); lua_rawseti(L, -2, 4); lua_pop(L, 2); /* background image */ jive_background = jive_tile_fill_color(0x000000FF); /* jive.ui.style = {} */ lua_getglobal(L, "jive"); lua_getfield(L, -1, "ui"); lua_newtable(L); lua_setfield(L, -2, "style"); lua_pop(L, 2); return 0; }