Logo Search packages:      
Sourcecode: lebiniou version File versions  Download package

SDL.c

/*
 *  Copyright 1994-2011 Olivier Girondel
 *
 *  This file is part of lebiniou.
 *
 *  lebiniou is free software: you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation, either version 2 of the License, or
 *  (at your option) any later version.
 *
 *  lebiniou is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with lebiniou. If not, see <http://www.gnu.org/licenses/>.
 */

#include "SDL.h"

#define NO_MOUSE_CURSOR

u_long id = 1095629101;
u_long options = BE_NONE;


u_short out_width;
u_short out_height;
#define out_buffsize (out_width * out_height)
static struct SwsContext *sws_context = NULL;
static uint8_t *bufp = NULL, *dstbufp = NULL;
static uint8_t *bufp_src[3] = {NULL, NULL, NULL}; /* FIXME not 4 ? */
static uint8_t *dstbufp_src[3] = {NULL, NULL, NULL}; /* FIXME only first is used ? */

static Uint32 colors[256];


static void
biniou_sdl_set_videomode(const u_short width, const u_short height, const Uint32 flags)
{
  drv.sc = SDL_SetVideoMode(width, height, 0, flags);
  if (NULL == drv.sc)
    xerror("Couldn't set %dx%d video mode: %s\n", width, height, SDL_GetError());
#ifdef DEBUG
  else 
    printf("[+] Set screen %dx%d at %dbpp\n",
         width, height, drv.sc->format->BitsPerPixel);
#endif
  drv.must_lock_screen = SDL_MUSTLOCK(drv.sc);
#ifdef XDEBUG
  printf("[+] Do we have to lock the screen ? %s\n", drv.must_lock_screen ? "yes" : "no");
#endif
}


void
set_cmap(Context_t *ctx)
{
  u_short c = 0;

  for (c = 0; c < 256; c++) {
    const rgba_t *rgba = &ctx->cf->cur->colors[c];
    colors[c] = SDL_MapRGBA(drv.sc->format,
                      rgba->col.r,
                      rgba->col.g,
                      rgba->col.b,
                      rgba->col.a);
  }
}


static inline void
SDL_refresh_32bpp(Context_t *ctx, SDL_Surface *sc)
{
  Buffer8_t *src = active_buffer(ctx);
  u_long k = 0;
  Pixel_t *cptr = NULL;
  Uint32 *buf;
  int srcstride[3] = {WIDTH*4, 0, 0};
  int dststride[3] = {out_width*4, 0, 0};
  int ret;

  if (bufp == NULL) {
    bufp = xcalloc(4*BUFFSIZE, sizeof(uint8_t));
    bufp_src[0] = bufp;
  }
  if (dstbufp == NULL) {
    dstbufp = xcalloc(4*out_buffsize, sizeof(uint8_t));
    dstbufp_src[0] = sc->pixels;
  }

  /* XXX les 2 flips, c'est sale --oliv3 */
  Buffer8_flip_x(src);
  cptr = src->buffer;

  buf = (Uint32 *)bufp;
  for (k = 0; k < BUFFSIZE; k++)
    *buf++ = colors[*cptr++];

  Buffer8_flip_x(src);

  if (NULL == sws_context)
    sws_context = sws_getContext(WIDTH, HEIGHT, PIX_FMT_RGB32,
                         out_width, out_height, PIX_FMT_RGB32,
                         SWS_FAST_BILINEAR, NULL, NULL, NULL);
  if (NULL == sws_context)
    xerror("sws_getContext\n");

  ret = sws_scale(sws_context, (const uint8_t * const *)bufp_src, srcstride, 0, HEIGHT, dstbufp_src, dststride);
  if (ret < 0)
    xerror("sws_scale\n");
}


static void
SDL_get_event(Context_t *ctx)
{
  // TODO middle = change color, right = erase (3x3)

  SDL_Event evt;

  while (SDL_PollEvent(&evt)) {
    BKey_t key;

    switch (evt.type) {
    case SDL_KEYDOWN:
      if (NULL != ctx->events_cb) {
      key.val = evt.key.keysym.sym;
      key.mod = evt.key.keysym.mod;
      
      ctx->events_cb(ctx, &key);
      }
      break;
      
    case SDL_QUIT:
      Context_send_event(ctx, BT_CONTEXT, BC_QUIT, BA_NONE);
      break;
                  
    case SDL_MOUSEMOTION:
      switch (evt.motion.state) {
      case SDL_BUTTON_LEFT:
      ctx->params3d.xe = evt.motion.x;
      ctx->params3d.ye = evt.motion.y;
      Params3d_rotate(&ctx->params3d);
      break;

      default:
      break;
      }
      break;

    case SDL_MOUSEBUTTONDOWN:
      /* printf("type= %d, button= %d\n", evt.button.type, evt.button.button); */
      switch (evt.button.button) {
      case SDL_BUTTON_LEFT:
      ctx->params3d.xs = evt.motion.x;
      ctx->params3d.ys = evt.motion.y;
      break;
      
      case SDL_BUTTON_WHEELUP:
      ctx->params3d.scale_factor /= 0.9;
      /* printf("scale: %d\n", ctx->params3d->scale_factor); */
      break;

      case SDL_BUTTON_WHEELDOWN:
      if (ctx->params3d.scale_factor > 11)
        ctx->params3d.scale_factor *= 0.9;
      break;

      default:
      break;
      }
      break;
                  
    case SDL_VIDEORESIZE:
      out_width = (evt.resize.w >= 8) ? evt.resize.w : out_width;
      out_height = (evt.resize.h >= 8) ? evt.resize.h : out_height;

      sws_freeContext(sws_context);
      sws_context = NULL;
      xfree(bufp);
      xfree(dstbufp);

      biniou_sdl_set_videomode(out_width, out_height, drv.sc->flags);
      break;

    default:
      break;
    }
  }
}


void
run(Context_t *ctx)
{
  lock_screen(drv);
  SDL_refresh_32bpp(ctx, drv.sc);

  if (ctx->osd_mode != OSD_NONE) {
    osd(ctx);
    
    if (ctx->random_mode != BR_NONE)
      osd_random_mode_elapsed(ctx);
  }

  unlock_screen(drv);
  SDL_get_event(ctx);
}


void
create(__attribute__ ((unused)) Context_t *ctx)
{
  char *window_title;
  char *icon_file;
  SDL_Surface *icon = NULL;
  Uint32 flags = 0;
  Uint32 colorkey;

  /* Initialize SDL */
  if (!SDL_WasInit(SDL_INIT_VIDEO))
    if (SDL_Init(SDL_INIT_VIDEO) < 0)
      xerror("Couldn't initialize SDL: %s\n", SDL_GetError());

  ttf_init();

  /* XXX hardcoded icon name */
  icon_file = g_strdup_printf("%s/lebiniou.bmp", TO_STRING(DATADIR));
  icon = SDL_LoadBMP(icon_file);
  g_free(icon_file);
  colorkey = SDL_MapRGB(icon->format, 0, 0, 0);
  SDL_SetColorKey(icon, SDL_SRCCOLORKEY, colorkey);
  SDL_WM_SetIcon(icon, NULL);
  SDL_FreeSurface(icon);

  flags = SDL_HWSURFACE | SDL_ANYFORMAT | SDL_HWPALETTE |
    SDL_DOUBLEBUF | SDL_HWACCEL |
    SDL_RLEACCEL;

  flags |= SDL_RESIZABLE;
  out_width = WIDTH;
  out_height = HEIGHT;
  biniou_sdl_set_videomode(out_width, out_height, flags);

  window_title = g_strdup_printf("Le Biniou (%dx%d)", WIDTH, HEIGHT);
  SDL_WM_SetCaption(window_title, NULL);

  g_free(window_title);

#ifdef NO_MOUSE_CURSOR
  SDL_ShowCursor(SDL_DISABLE);
#endif
  SDL_EnableKeyRepeat(SDL_DEFAULT_REPEAT_DELAY, SDL_DEFAULT_REPEAT_INTERVAL);
}


void
destroy(__attribute__ ((unused)) Context_t *ctx)
{
  sws_freeContext(sws_context);
  xfree(bufp);
  xfree(dstbufp);
  SDL_FreeSurface(drv.sc);
  ttf_quit();
  SDL_Quit();
}


void
fullscreen(const int fs)
{
  int do_it = drv.sc->flags & SDL_FULLSCREEN;

  /* houlala c'est loin l'algebre de bool en C... */
  do_it = (fs && !do_it) || (!fs && do_it);

  if (do_it) {
    printf("[S] Toggle full-screen\n");
    SDL_WM_ToggleFullScreen(drv.sc);
  }
}


void
switch_cursor()
{
  int on;

  on = SDL_ShowCursor(SDL_QUERY);
  SDL_ShowCursor(on ? SDL_DISABLE : SDL_ENABLE);
}

Generated by  Doxygen 1.6.0   Back to index