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

osd.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"
#include "pictures.h"
#include "colormaps.h"

#define FONT "/usr/share/fonts/truetype/freefont/FreeMono.ttf"

static TTF_Font *font = NULL;
#define PTSIZE     14

extern u_short out_width, out_height;

static char enabled = 1;

void
ttf_init()
{
  /* Initialize the TTF library */
  if (!TTF_WasInit())
    if (TTF_Init() < 0)
      xerror("Couldn't initialize TTF: %s\n", SDL_GetError());
      
  /* Open the font file with the requested point size */
  font = TTF_OpenFont(FONT, PTSIZE);
  if (font == NULL) {
    printf("[!] %s, OSD is disabled.\n", SDL_GetError());
    enabled = 0;
  } else {
    TTF_SetFontStyle(font, TTF_STYLE_NORMAL);
    /* TTF_SetFontStyle(font, TTF_STYLE_BOLD); */
  }
}

#define OSD_BUFFLEN 512
#define BORDER      10
#define ARROW       "->"

static inline void
reset(char *buff)
{
  memset(buff, '\0', (OSD_BUFFLEN+1)*sizeof(char));
}


static SDL_Color white = { 0xFF, 0xFF, 0xFF, 0 };
static SDL_Color black = { 0, 0, 0, 0 };
static SDL_Color red   = { 0xFF, 0, 0, 0 };


u_short
osd_print(const u_short x, u_short y,
        const u_char rev_x, const u_char rev_y,
        const u_char mode, const int disabled, const char *fmt, ...)
{
  char str[OSD_BUFFLEN+1];
  va_list ap;
  SDL_Surface *text = NULL;
  SDL_Rect    dstrect;
  SDL_Color   fg_color;

  memset((void *)str, '\0', OSD_BUFFLEN*sizeof(char));
  assert(fmt != NULL);
  va_start(ap, fmt);
  vsprintf(str, fmt, ap); /* TODO vsnprintf */
  va_end(ap);

  fg_color = (disabled) ? red : white;

  text = ((mode == 1) || (mode == 2)) ? TTF_RenderText_Blended(font, str, black)
    : TTF_RenderText_Shaded(font, str, fg_color, black);

  if (text != NULL) {
    if (mode == 3) {
      dstrect.x = (rev_x) ? (out_width - x - text->w) : x;
      dstrect.y = (rev_y) ? (out_height - y - text->h) : y;
      dstrect.w = text->w;
      dstrect.h = text->h;
      SDL_BlitSurface(text, NULL, drv.sc, &dstrect);
      SDL_FreeSurface(text);
    } else {
      int dx, dy;
      
      dstrect.w = text->w;
      dstrect.h = text->h;
      for (dx = -2; dx <= 2; dx ++) {
      for (dy = -2; dy <= 2; dy ++) {
        dstrect.x = (rev_x) ? (out_width - x - text->w) : x;
        dstrect.y = (rev_y) ? (out_height - y - text->h) : y;
        dstrect.x += dx;
        dstrect.y += dy;
        SDL_BlitSurface(text, NULL, drv.sc, &dstrect);
      }
      }
      SDL_FreeSurface(text);

      text = TTF_RenderText_Blended(font, str, fg_color);
      dstrect.x = (rev_x) ? (out_width - x - text->w) : x;
      dstrect.y = (rev_y) ? (out_height - y - text->h) : y;
      SDL_BlitSurface(text, NULL, drv.sc, &dstrect);
      SDL_FreeSurface(text);
    }
    y += TTF_FontLineSkip(font) - 1; /* FIXME why -1 ?? --oliv3 */
  }

  return y;
}


static void
osd_info(const Context_t *ctx) {
  char buff[OSD_BUFFLEN+1];
  int dst_y = 0;

  struct timeval now;
  char *now_str;

  float elapsed;
  u_short d, h, m, s;

  const Sequence_t *cur_seq = ctx->sm->cur;

  /* Display readable localtime */
  /* TODO error checking */
  gettimeofday(&now, NULL);
  /* XXX TODO error + bounds checking */
  now_str = ctime((time_t *)&now.tv_sec);
  now_str[strlen(now_str)-1] = '\0';

  dst_y = osd_print(BORDER, dst_y, 0, 0, ctx->osd_mode, 0, "%s", now_str);

  /* Uptime */
  elapsed = b_timer_elapsed(ctx->timer);
  d = (u_short)(elapsed / (3600*24));
  elapsed -= d*3600*24;
  h = (u_short)(elapsed / 3600);
  elapsed -= h*3600;
  m = (u_short)(elapsed / 60);
  elapsed -= m*60;
  s = (u_short)elapsed;
  elapsed -= s;
  dst_y = osd_print(BORDER, dst_y, 0, 0, ctx->osd_mode, 0, "Up: %1dd %02d:%02d:%02d.%02d",
         d, h, m, s, (u_short)(elapsed*100));

  /* Display sequence name */
  dst_y = osd_print(BORDER, dst_y, 0, 0, ctx->osd_mode, 0, "Sequence: %s",
         (cur_seq->name != NULL) ? cur_seq->name : "(none)");

#ifdef FEAT_BANKS
  /* Display current bankset:bank:sequence_name */
  dst_y = osd_print(BORDER, dst_y, 0, 0, ctx->osd_mode, 0, "Bank: %d:%d",
                ctx->sm->cur_bankset, ctx->bank);
#endif

  /* Display colormap and picture (if any) */
  assert(colormaps != NULL);
  dst_y = osd_print(BORDER, dst_y, 0, 0, ctx->osd_mode, 0, "Colormap: %s",
                (cur_seq->cmap_id) ? Colormaps_name(cur_seq->cmap_id) : "(default)");

  if (NULL != pictures)
      dst_y = osd_print(BORDER, dst_y, 0, 0, ctx->osd_mode, 0, "Picture: %s",
                  (cur_seq->picture_id) ? Pictures_name(cur_seq->picture_id) : "(default)");

  /* Display auto* stuff */
  reset(buff);
  if (ctx->random_mode != BR_NONE) {
    const char *what = NULL;

    if (ctx->random_mode == BR_SCHEMES)
      what = "Schemes";
    else if (ctx->random_mode == BR_SEQUENCES)
      what = "Sequences";
    else if (ctx->random_mode == BR_BOTH)
      what = "Schemes+Sequences";
    snprintf(buff, OSD_BUFFLEN*sizeof(char), "Auto mode: %s", what);
  } else
    snprintf(buff, OSD_BUFFLEN*sizeof(char), "Auto mode: Off");
  dst_y = osd_print(BORDER, dst_y, 0, 0, ctx->osd_mode, 0, "%s", buff);
  
  /* Display random cmap/picture */
  if (colormaps->size > 1)
    dst_y = osd_print(BORDER, dst_y, 0, 0, ctx->osd_mode, 0, "Random colormap: %s",   
                  ((ctx->sm->cur->auto_colormaps) ? "On" : "Off"));
  
  if ((pictures != NULL) && (pictures->size > 1))
    (void)osd_print(BORDER, dst_y, 0, 0, ctx->osd_mode, 0, "Random picture: %s",   
                (ctx->sm->cur->auto_pictures ? "On" : "Off"));
}


static void
osd_fps(const Context_t *ctx) {
  (void)osd_print(BORDER, 0, 1, 1, ctx->osd_mode, 0, "%03d FPS (%03d)", (int)Context_fps(ctx), ctx->max_fps);
}


static void
osd_sequence(const Context_t *ctx)
{
  char buff[OSD_BUFFLEN+1];
  const Sequence_t *cur_seq;
  GList *tmp;
  u_short dst_y = 0;
  u_char lens_there = 0;

  cur_seq = ctx->sm->cur;
  tmp = g_list_first(cur_seq->layers);

  while (tmp != NULL) {
    Layer_t *layer = (Layer_t *)tmp->data;
    Plugin_t *P = layer->plugin;

    if (P != NULL) {
      char *name = Plugin_dname(P);
      const char *mode = LayerMode_to_OSD_string(layer->mode);
      const char *arrow = (P == plugins->selected) ? ARROW : "";

      reset(buff);
      if ((cur_seq->lens != NULL) && (P == cur_seq->lens)) {
      lens_there = 1;
      snprintf(buff, OSD_BUFFLEN*sizeof(char), "%s %s - %s", arrow, name, mode);
      }
      else {
      const char lens_there_c = (lens_there) ? ' ' : '|';
      snprintf(buff, OSD_BUFFLEN*sizeof(char), "%s %s %c %s", arrow, name, lens_there_c, mode);
      }
      xfree(name);

      dst_y = osd_print(BORDER, dst_y, 1, 0, ctx->osd_mode, 0, "%s", buff);
    }
    tmp = g_list_next(tmp);
  }

  cur_seq = ctx->sm->cur;
}


static void
osd_plugins(const Context_t *ctx)
{
#define SHOW 5 /* number of plugins to display before/after the current plugin */
  short n;
  short start;
  u_short dst_y = 2*SHOW*TTF_FontLineSkip(font) - 2*SHOW;

  start = plugins->selected_idx - SHOW;
  while (start < 0)
    start += plugins->size;

  for (n = 0; (n <= 2*SHOW+1) && (n < plugins->size); ) {
    const char *arrow;
    char *name;
    int disabled;

    disabled = (*(plugins->plugins[start])->options & BEQ_DISABLED) ? 1 : 0;
    arrow = (n == SHOW) ? ARROW : "  ";

    name = Plugin_dname(plugins->plugins[start]);
    (void)osd_print(BORDER, dst_y, 0, 1, ctx->osd_mode, disabled, "%02d %s %s", start, arrow, name);
    xfree(name);
    dst_y -= TTF_FontLineSkip(font) - 1;
    n++;

    start++;
    if (start == plugins->size)
      start = 0;
  }
}


void
osd_random_mode_elapsed(const Context_t *ctx)
{
  float pct = Alarm_elapsed_pct(ctx->a_random);
  u_char color = 255; /* TODO colormap->max */
  u_short height = (u_short)((1.0 - pct) * out_height);
  SDL_Rect r;
  
  r.x = out_width-PB_WIDTH;
  r.y = out_height-height;
  r.w = PB_WIDTH;
  r.h = height;

  SDL_FillRect(drv.sc, &r, color); 
}


static void
osd_plugin_desc(const Context_t *ctx)
{
  char *dsc = NULL;
  int skip = TTF_FontLineSkip(font) - 1;

  if (NULL == plugins->selected->desc)
    dsc = "NO DESCRIPTION";
  else
    dsc = plugins->selected->desc;

  (void)osd_print(BORDER, skip, 1, 1, ctx->osd_mode, 0, "%s", dsc);
}


void
osd(const Context_t *ctx) {
  if (!enabled)
    return;

  osd_info(ctx);

  if (ctx->sync_fps)
    osd_fps(ctx);

  osd_sequence(ctx);

  if (ctx->osd_mode != OSD_MINI)
    osd_plugins(ctx);

  if (ctx->osd_mode > OSD_MINI)
    osd_plugin_desc(ctx);
}


void
ttf_quit()
{
  if (NULL != font)
    TTF_CloseFont(font);
  TTF_Quit();
}

Generated by  Doxygen 1.6.0   Back to index