/* -*- LPC -*- */
/*
* $Locker: $
* $Id: chime_handler.c,v 1.6 2002/03/16 14:56:23 wodan Exp $
*
*/
#define CREATOR "Ceres"
/**
* This handler deals with clocks which chime. It uses a single 15 minute
* callout to make all clocks on Discworld which choose to chime chime the
* quarter, half or hours.
*
* @author Ceres
*/
#include <am_time.h>
#include <chime.h>
#define FIFTEEN_MINS (AM_SECONDS_PER_MINUTE * 15)
class chime {
object ob;
int type;
string mess;
}
void do_chime(class chime record, int type);
class chime *chime_list;
int last_strike;
/** @ignore yes */
void create() {
int next_chime;
chime_list = ({ });
// time to the next quarter
next_chime = 301 - (time() % 300);
remove_call_out("check_time");
call_out("check_time", next_chime);
}
/**
* Register a clock to do chimes. The num parameter specifes when to
* chime. If it is 1 then the clock chimes every hour, if it is
* 2 the clock chimes ever half hour, if it is 4 the
* clock chimes every quarter hour. Anything else and
* the clock never chimes. NB: if you set it to chime the quarter hours
* it will only chime the quarter hours, it will not chime the hours
* or the half hours. You need to call this function three times to
* get your clock to chime the hour, half and quarter hours.
* <p>
* The function "chime" will be called on the clock
* when the chime occurs. The message will be passed in as the first
* argument, the second will be the type of chime (CHIME_HOUR, CHIME_HALF_HOUR,
* CHIME_QUARTER_HOUR).
*
* @param ob the object being registered
* @param num when to chime
* @param mess the message to chime with
*
* @return 1 for success, 0 for failure.
*/
int register_for_chimes(object ob, int num, string mess) {
class chime record;
// check if this object is already registered. If they use a new
// message it's considered a new chime.
foreach(record in chime_list) {
if(record->ob == ob && record->type == num && record->mess == mess) {
record->type = num;
record->mess = mess;
return 1;
}
}
record = new(class chime);
record->ob = ob;
record->type = num;
record->mess = mess;
chime_list += ({ record });
return 1;
}
/** @ignore yes
*
* This function checks the registered objects and sets up a call to
* do_chime() for each one that needs a call.
*/
void check_time() {
int next_chime, minute;
class chime record;
minute = AM_TIME_HANDLER->query_am_minute(time());
foreach(record in chime_list) {
catch{
if(minute % 60 < 5)
do_chime(record, CHIME_HOUR);
else if(minute % 30 < 5 && record->type > CHIME_HOUR)
do_chime(record, CHIME_HALF_HOUR);
else if(minute % 15 < 5 && record->type == CHIME_QUARTER_HOUR)
do_chime(record, CHIME_QUARTER_HOUR);
};
}
next_chime = (FIFTEEN_MINS + 1) - (time() % FIFTEEN_MINS);
remove_call_out("check_time");
call_out("check_time", next_chime);
}
/** @ignore yes
*
* This actually calls the chime function in an object.
*/
void do_chime(class chime record, int type) {
if(!record || !record->ob)
return;
(record->ob)->chime(record->mess, type);
}
/** @ignore yes
* Restart the chime callout, just in case it got dropped on the floor.
*/
void reset() {
int next_chime;
class chime record;
next_chime = (FIFTEEN_MINS + 1) - (time() % FIFTEEN_MINS);
remove_call_out("check_time");
call_out("check_time", next_chime);
// Clean up the chime_list.
foreach(record in chime_list) {
if(!record->ob)
chime_list -= ({ record });
}
}
/** @ignore yes
* these two are not here because the handler can be saved, but to keep
* the info over updates.
*/
mapping query_dynamic_auto_load() {
mapping tmp;
tmp = ([ "chime_list" : chime_list ]);
return tmp;
}
/** @ignore yes */
void init_dynamic_arg(mapping maps) {
if (maps["chime_list"])
chime_list = maps["chime_list"];
}
/** @ignore yes */
mixed stats() {
return ({ ({ "chime count", sizeof(chime_list) }) });
}