syndilights/blib-1.1.7/modules/bclock.c

374 lines
8.5 KiB
C

/* blib - Library of useful things to hack the Blinkenlights
*
* Copyright (c) 2002 The Blinkenlights Crew
* Daniel Mack <daniel@yoobay.net>
*
* This program 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.
*
* This program 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 this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#include "config.h"
#include <stdlib.h>
#include <string.h>
#include <math.h>
#include <time.h>
#include <sys/time.h>
#include <glib.h>
#include <gmodule.h>
#include <blib/blib.h>
#include "digits.h"
#define TIMEOUT 75
#define DEFAULT_MODE CLOCK_MODE_DIGITAL
typedef enum
{
CLOCK_MODE_DIGITAL,
CLOCK_MODE_ANALOG,
CLOCK_MODE_LAST
} BClockMode;
enum
{
PROP_0,
PROP_MODE
};
#define B_TYPE_CLOCK_MODE (b_clock_mode_get_type ())
#define B_TYPE_CLOCK (b_type_clock)
#define B_CLOCK(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), B_TYPE_CLOCK, BClock))
#define B_CLOCK_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), B_TYPE_CLOCK, BClockClass))
#define B_IS_CLOCK(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), B_TYPE_CLOCK))
typedef struct _BClock BClock;
typedef struct _BClockClass BClockClass;
struct _BClock
{
BModule parent_instance;
guint epoche;
gint mode;
gboolean colon;
};
struct _BClockClass
{
BModuleClass parent_class;
};
static GType b_clock_get_type (GTypeModule *module);
static void b_clock_class_init (BClockClass *klass);
static void b_clock_set_property (GObject *object,
guint property_id,
const GValue *value,
GParamSpec *pspec);
static gboolean b_clock_query (gint width,
gint height,
gint channels,
gint maxval);
static gboolean b_clock_prepare (BModule *module,
GError **error);
static void b_clock_relax (BModule *module);
static void b_clock_start (BModule *module);
static gint b_clock_tick (BModule *module);
static void b_clock_describe (BModule *module,
const gchar **title,
const gchar **description,
const gchar **author);
static gboolean b_clock_gettime (BClock *clock);
static GType b_type_clock = 0;
static const GEnumValue clock_mode_enum_values[] =
{
{ CLOCK_MODE_DIGITAL, "digital", NULL },
{ CLOCK_MODE_ANALOG, "analog", NULL },
{ 0, NULL, NULL }
};
GType
b_clock_mode_get_type (void)
{
static GType enum_type = 0;
if (!enum_type)
enum_type = g_enum_register_static ("BClockMode",
clock_mode_enum_values);
return enum_type;
}
G_MODULE_EXPORT gboolean
b_module_register (GTypeModule *module)
{
b_clock_get_type (module);
return TRUE;
}
GType
b_clock_get_type (GTypeModule *module)
{
if (!b_type_clock)
{
static const GTypeInfo clock_info =
{
sizeof (BClockClass),
NULL, /* base_init */
NULL, /* base_finalize */
(GClassInitFunc) b_clock_class_init,
NULL, /* class_finalize */
NULL, /* class_data */
sizeof (BClock),
0, /* n_preallocs */
NULL /* instance_init */
};
b_type_clock = g_type_module_register_type (module,
B_TYPE_MODULE, "BClock",
&clock_info, 0);
}
return b_type_clock;
}
static void
b_clock_class_init (BClockClass *klass)
{
GObjectClass *object_class;
BModuleClass *module_class;
GParamSpec *param_spec;
object_class = G_OBJECT_CLASS (klass);
module_class = B_MODULE_CLASS (klass);
object_class->set_property = b_clock_set_property;
param_spec = g_param_spec_enum ("mode", NULL,
"Clock mode (analog/digital)",
B_TYPE_CLOCK_MODE, DEFAULT_MODE,
G_PARAM_CONSTRUCT | G_PARAM_WRITABLE);
g_object_class_install_property (object_class, PROP_MODE, param_spec);
module_class->query = b_clock_query;
module_class->prepare = b_clock_prepare;
module_class->relax = b_clock_relax;
module_class->start = b_clock_start;
module_class->tick = b_clock_tick;
module_class->describe = b_clock_describe;
}
static void
b_clock_set_property (GObject *object,
guint property_id,
const GValue *value,
GParamSpec *pspec)
{
BClock *line = B_CLOCK (object);
switch (property_id)
{
case PROP_MODE:
line->mode = g_value_get_enum (value);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
break;
}
}
static gboolean
b_clock_query (gint width,
gint height,
gint channels,
gint maxval)
{
return (width > 0 && height > 3 && channels == 1 && maxval == 255);
}
static gboolean
b_clock_prepare (BModule *module,
GError **error)
{
return TRUE;
}
static void
b_clock_relax (BModule *module)
{
}
static void
b_clock_start (BModule *module)
{
b_clock_gettime (B_CLOCK (module));
b_module_ticker_start (module, b_clock_tick (module));
}
static gboolean
b_clock_gettime (BClock *clock)
{
struct timeval tv;
gettimeofday (&tv, NULL);
if (tv.tv_sec != clock->epoche)
{
clock->epoche = tv.tv_sec;
return TRUE;
}
return FALSE;
}
static gint
b_clock_tick (BModule *module)
{
gint h, m, s;
BClock *clock = B_CLOCK (module);
const BFont *digits = &b_digits_3x5;
struct tm *tm;
if (!b_clock_gettime (clock))
return TIMEOUT;
b_module_fill (module, 0);
tm = localtime ((time_t *) &clock->epoche);
h = tm->tm_hour;
m = tm->tm_min;
s = tm->tm_sec;
/* g_print ("%02d:%02d:%02d\n", h, m, s); */
switch (clock->mode)
{
case CLOCK_MODE_DIGITAL:
{
gchar *text;
gint len, i, n, x, y, x0, y0;
if (module->width > 20)
{
text = g_strdup_printf ("%02d:%02d:%02d", h, m, s);
}
else
{
text = g_strdup_printf (clock->colon ? "%02d:%02d" : "%02d %02d",
h, m);
clock->colon = !clock->colon;
}
len = strlen (text);
x0 = 0;
y0 = module->height / 4;
for (n = 0; n < len; n++)
{
for (i = 0; i < digits->num_digits && digits->digits_str[i] != text[n]; i++);
if (len * digits->advance > module->width)
{
if (text[n-1] == ':' || text[n-1] == ' ')
x0--;
if (text[n] == ':' || text[n] == ' ')
x0--;
}
if (i < digits->num_digits)
for (x = 0; x < digits->width; x++)
for (y = 0; y < digits->height; y++)
if (digits->data[i][y * digits->width + x] != '0')
b_module_draw_point (module,
x0 + x, y0 + y, module->maxval);
x0 += digits->advance;
}
g_free (text);
}
break;
case CLOCK_MODE_ANALOG:
{
gint x0, y0, r, x, y, a;
x0 = module->width / 2;
y0 = module->height / 2;
r = MIN (x0, y0 / module->aspect);
for (a = 0; a < 360; a += 30)
{
x = cos (a/180.0 * G_PI) * r + x0 + 0.5;
y = (sin (a/180.0 * G_PI) * r) * module->aspect + y0 + 0.5;
b_module_draw_point (module, x, y, 0x7f);
}
/* 1st hand */
a = h;
a += 45;
a *= 30;
x = cos (a/180.0 * G_PI) * (r - 4) + x0 + 0.5;
y = (sin (a/180.0 * G_PI) * (r - 4)) * module->aspect + y0 + 0.5;
b_module_draw_line (module, x0, y0, x, y, 0x80);
/* 2nd hand */
a = m;
a += 45;
a *= 6;
x = cos (a/180.0 * G_PI) * (r - 2) + x0 + 0.5;
y = (sin (a/180.0 * G_PI) * (r - 2)) * module->aspect + y0 + 0.5;
b_module_draw_line (module, x0, y0, x, y, 0xe0);
/* 3rd hand */
a = s;
a += 9;
a *= 6;
x = cos (a/180.0 * G_PI) * (r - 1) + x0 + 0.5;
y = (sin (a/180.0 * G_PI) * (r - 1)) * module->aspect + y0 + 0.5;
b_module_draw_line (module, x0, y0, x, y, 0xff);
}
break;
}
b_module_paint (module);
return TIMEOUT;
}
static void
b_clock_describe (BModule *module,
const gchar **title,
const gchar **description,
const gchar **author)
{
*title = "BClock";
*description = "BKloppte BClock";
*author = "Daniel Mack";
}