syndilights/blccc-1.99/src/blondemand.c

392 lines
11 KiB
C

/* blccc - Blinkenlights Chaos Control Center
*
* Copyright (c) 2001-2002 Sven Neumann <sven@gimp.org>
*
* 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 <stdlib.h>
#include <unistd.h>
#include <blib/blib.h>
#include "bltypes.h"
#include "blloveletters.h"
#include "blondemand.h"
#define TICK 250
enum
{
PROP_0,
PROP_ADVANCED,
PROP_LOVELETTERS
};
static void bl_on_demand_class_init (BlOnDemandClass *class);
static void bl_on_demand_set_property (GObject *object,
guint property_id,
const GValue *value,
GParamSpec *pspec);
static gboolean bl_on_demand_query (gint width,
gint height,
gint channels,
gint maxval);
static gboolean bl_on_demand_prepare (BModule *module,
GError **error);
static void bl_on_demand_relax (BModule *module);
static void bl_on_demand_start (BModule *module);
static gint bl_on_demand_tick (BModule *module);
static void bl_on_demand_event (BModule *module,
BModuleEvent *event);
static void bl_on_demand_describe (BModule *module,
const gchar **title,
const gchar **description,
const gchar **author);
static void bl_on_demand_paint (BModule *module);
static BModuleClass *parent_class = NULL;
GType
bl_on_demand_get_type (void)
{
static GType type = 0;
if (! type)
{
static const GTypeInfo info =
{
sizeof (BlOnDemandClass),
NULL, /* base_init */
NULL, /* base_finalize */
(GClassInitFunc) bl_on_demand_class_init,
NULL, /* class_finalize */
NULL, /* class_data */
sizeof (BlOnDemand),
0, /* n_preallocs */
NULL /* instance_init */
};
type = g_type_register_static (B_TYPE_MOVIE_PLAYER,
"BlOnDemand", &info, 0);
}
return type;
}
static void
bl_on_demand_class_init (BlOnDemandClass *klass)
{
GObjectClass *object_class;
GParamSpec *param_spec;
BModuleClass *module_class;
BMoviePlayerClass *player_class;
object_class = G_OBJECT_CLASS (klass);
module_class = B_MODULE_CLASS (klass);
player_class = B_MOVIE_PLAYER_CLASS (klass);
parent_class = g_type_class_peek_parent (klass);
object_class->set_property = bl_on_demand_set_property;
param_spec = g_param_spec_boolean ("advanced", NULL,
"Use advanced features (pause/restart).",
FALSE,
G_PARAM_CONSTRUCT | G_PARAM_WRITABLE);
g_object_class_install_property (object_class, PROP_ADVANCED, param_spec);
param_spec = b_param_spec_filename ("loveletters", NULL,
"The filename of the loveletters list.",
NULL,
G_PARAM_CONSTRUCT | G_PARAM_WRITABLE);
g_object_class_install_property (object_class, PROP_LOVELETTERS, param_spec);
module_class->max_players = 1;
module_class->query = bl_on_demand_query;
module_class->prepare = bl_on_demand_prepare;
module_class->relax = bl_on_demand_relax;
module_class->start = bl_on_demand_start;
module_class->tick = bl_on_demand_tick;
module_class->event = bl_on_demand_event;
module_class->describe = bl_on_demand_describe;
player_class->request_stop = parent_class->start; /* loop the movie */
}
static void
bl_on_demand_set_property (GObject *object,
guint property_id,
const GValue *value,
GParamSpec *pspec)
{
BlOnDemand *on_demand = BL_ON_DEMAND (object);
switch (property_id)
{
case PROP_ADVANCED:
on_demand->advanced = g_value_get_boolean (value);
break;
case PROP_LOVELETTERS:
if (on_demand->filename)
g_object_unref (on_demand->filename);
on_demand->filename = g_value_dup_string (value);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
break;
}
}
static gboolean
bl_on_demand_query (gint width,
gint height,
gint channels,
gint maxval)
{
return (width > 2 * MAX_ON_DEMAND_CHARS && height > 3 &&
channels == 1 && maxval == 255);
}
static gboolean
bl_on_demand_prepare (BModule *module,
GError **error)
{
BlOnDemand *on_demand = BL_ON_DEMAND (module);
if (!on_demand->filename)
{
g_set_error (error, 0, 0, "No loveletters file configured");
return FALSE;
}
B_MOVIE_PLAYER (module)->clear = FALSE;
on_demand->loveletters =
bl_loveletters_new_from_file (on_demand->filename, error);
on_demand->movie_active = FALSE;
on_demand->movie_paused = FALSE;
return (on_demand->loveletters != NULL);
}
static void
bl_on_demand_relax (BModule *module)
{
BlOnDemand *on_demand = BL_ON_DEMAND (module);
if (on_demand->loveletters)
{
g_object_unref (on_demand->loveletters);
on_demand->loveletters = NULL;
}
if (on_demand->movie_active)
{
parent_class->relax (module);
on_demand->movie_active = FALSE;
}
}
static void
bl_on_demand_start (BModule *module)
{
BlOnDemand *on_demand = BL_ON_DEMAND (module);
on_demand->chars = -1;
on_demand->movie_active = FALSE;
bl_on_demand_paint (module);
b_module_ticker_start (module, TICK);
}
static gint
bl_on_demand_tick (BModule *module)
{
BlOnDemand *on_demand = BL_ON_DEMAND (module);
if (on_demand->movie_active && !on_demand->movie_paused)
return parent_class->tick (module);
if (!on_demand->movie_active)
bl_on_demand_paint (module);
return TICK;
}
static void
bl_on_demand_event (BModule *module,
BModuleEvent *event)
{
BlOnDemand *on_demand = BL_ON_DEMAND (module);
const gchar *movie;
/* in DAU mode, ignore keys when a movie has been started */
if (!on_demand->advanced && on_demand->movie_active)
return;
if (event->type != B_EVENT_TYPE_KEY)
return;
switch (event->key)
{
case B_KEY_0 ... B_KEY_9:
if (on_demand->chars < 0)
return;
on_demand->code[on_demand->chars] = event->key + '0';
on_demand->chars++;
if (on_demand->chars < MAX_ON_DEMAND_CHARS)
break;
/* else fallthru */
case B_KEY_HASH:
if (on_demand->movie_active)
{
on_demand->movie_paused = (on_demand->movie_paused == FALSE);
if (!on_demand->movie_paused)
{
b_module_fill (module, 0);
parent_class->start (module);
}
}
if (on_demand->chars <= 0)
return;
if (on_demand->movie_active)
{
parent_class->relax (module);
on_demand->movie_active = FALSE;
}
on_demand->code[on_demand->chars] = '\0';
on_demand->chars = -1;
movie = bl_loveletters_lookup (on_demand->loveletters, on_demand->code);
if (movie)
{
GError *error = NULL;
g_object_set (module, "movie", movie, NULL);
if (parent_class->prepare (module, &error))
{
g_printerr ("Starting loveletter for ID '%s'.\n",
on_demand->code);
on_demand->movie_active = TRUE;
on_demand->movie_paused = FALSE;
b_module_fill (module, 0);
parent_class->start (module);
return;
}
else
{
g_printerr ("Error preparing BlOnDemand: %s\n", error->message);
g_clear_error (&error);
on_demand->movie_active = FALSE;
}
}
else
{
g_printerr ("No loveletter found for ID '%s'.\n", on_demand->code);
}
break;
case B_KEY_ASTERISK:
on_demand->chars = 0;
if (on_demand->movie_active)
{
B_MOVIE_PLAYER (module)->current = NULL;
on_demand->movie_paused = TRUE;
}
break;
}
bl_on_demand_paint (module);
}
static void
bl_on_demand_describe (BModule *module,
const gchar **title,
const gchar **description,
const gchar **author)
{
*title = "BlOnDemand";
*author = "Sven Neumann";
if (BL_ON_DEMAND (module)->advanced)
*description = "Interactive movie player (advcanced)";
else
*description = "Interactive movie player (DAU mode)";
}
static void
bl_on_demand_paint (BModule *module)
{
gint n;
gint w = module->width / 2;
gint h = module->height / 2;
gint v = module->maxval / 2;
gint l = MIN (w / 2, h / 2);
b_module_fill (module, 0);
h--;
n = BL_ON_DEMAND (module)->chars;
if (n < 0)
{
b_module_draw_line (module, w - l, h , w + l, h , v + rand()%v);
b_module_draw_line (module, w - l, h - l, w + l, h + l, v + rand()%v);
b_module_draw_line (module, w - l, h + l, w + l, h -l , v + rand()%v);
}
else
{
guchar *d = module->buffer + (h / 2) * module->width;
gint x, i;
x = w - MAX_ON_DEMAND_CHARS;
for (i = 0; i < MAX_ON_DEMAND_CHARS; i++, x += 2)
d[x] = (i < n) ? module->maxval : module->maxval / 2;
}
if (n > 0 || BL_ON_DEMAND (module)->movie_active)
{
b_module_draw_line (module,
w - l , h + l/2, w + l , h + l/2 , v + rand()%v);
b_module_draw_line (module,
w - l , h + l , w + l , h + l , v + rand()%v);
b_module_draw_line (module,
w - l/2, h , w - l/2, h + 3*l/2, v + rand()%v);
b_module_draw_line (module,
w + l/2, h , w + l/2, h + 3*l/2, v + rand()%v);
}
b_module_paint (module);
}