/* The DIVE software is covered by a license. The use of the software */ /* represents acceptance of the terms and conditions in the license. */ /* ****************************************************************** */ /* Copyright (c) 1994, Swedish Institute of Computer Science */ /*---------------------------------------------------------------------------- * File: clock.c * Project: SICS DIVE * Copyright: SICS * Version: clock.c,v 1.24 1996/08/27 14:21:07 olof Exp * * This Application creates a clock into a world. * Primary contact -- Emmanuel Frécon - emmanuel@sics.se * *---------------------------------------------------------------------------*/ #include #include #include #include #include #include "dive/dive.h" #include "dive/lammopt.h" #include "dive/ai_util.h" #include "dive/vrx.h" #include "dive/menu.h" #include "dive/statistics.h" #ifndef DEFAULT_STARTING_WORLD #define DEFAULT_STARTING_WORLD "local" #endif #define CLOCK_URL "http://www.sics.se/dive/manual/examples/clock.vr" /*========================================================================== External variables ==========================================================================*/ /*========================================================================== Local variables ==========================================================================*/ static char rcsid[] = "clock.c,v 1.24 1996/08/27 14:21:07 olof Exp"; static void print_rcsid() {if (1) printf("%s\n", rcsid); else print_rcsid();} static struct { int hour; int min; int sec; objid_t clock_id; objid_t sec_id; objid_t min_id; objid_t hour_id; } ClockData = { 0, 0, 0, }; /* Macros to update clock hands */ #define update_hour(id, hours) \ distr_abs_fixedXYZ(id, 0.0, 0.0, ((hours)%12)*(M_PI/6), LOCAL_C, NULL, NULL) #define update_hand(id, seconds) \ distr_abs_fixedXYZ(id, 0.0, 0.0, seconds*(M_PI/30), LOCAL_C, NULL, NULL) /* ------------------------------------------------------------------------ * on_timer * * Executes each alarm wakeup and counts seconds, minutes and hours and * rotate hands accordingly. * * ------------------------------------------------------------------------ */ static void on_timer(void *arg) { if (!find_entity(&ClockData.clock_id)) dive_exit(0); ClockData.sec ++; if (ClockData.sec == 60) { ClockData.sec = 0; ClockData.min ++; if (ClockData.min == 60) { ClockData.min = 0; ClockData.hour ++; if (ClockData.hour == 24) { ClockData.hour = 0; } update_hour(&ClockData.hour_id, ClockData.hour); } update_hand(&ClockData.min_id, ClockData.min); } update_hand(&ClockData.sec_id, ClockData.sec); } /* ------------------------------------------------------------------------ * set_current_time * * Adjust clock hands according to curretn system time. * * ------------------------------------------------------------------------ */ static void set_current_time() { time_t t; struct tm *tm; /* Get current system time and update our own structure */ t = time(NULL); tm = localtime(&t); ClockData.hour = tm->tm_hour; ClockData.min = tm->tm_min; ClockData.sec = tm->tm_sec; /* Update the position of the clock hands */ update_hour(&ClockData.hour_id, ClockData.hour); update_hand(&ClockData.min_id, ClockData.min); update_hand(&ClockData.sec_id, ClockData.sec); } /* ------------------------------------------------------------------------ * interaction_cb * * An interaction signal has occured, if it was sent to the clock we update * it with the current local time of the machine. * * ------------------------------------------------------------------------ */ static void interaction_cb(objid_t *dest_id, interaction_type_t type, objid_t *pid, objid_t *src_id, point_t *pt, objid_t *viewid,void *arg) { /* No source or no destination! */ if (!src_id || !dest_id) return ; /* If the destination identifier is not the board of the clock */ if (!objid_eq(dest_id, &ClockData.clock_id)) return ; switch (type) { case DIVE_IA_SELECT: /* Setup clock to current time when button is pressed */ set_current_time(); break; default: break; } } static void clock_exit(void *arg) { distr_entity_remove(&ClockData.clock_id, NULL); } /* ------------------------------------------------------------------------ * clock_init * * Initialization function, read a clock file, identify its components * and initialize to current time. * * ------------------------------------------------------------------------ */ static void clock_init(objid_t *wid) { entity *obj; /* Read the clock from a file */ if (distr_readURL(wid, CLOCK_URL, NULL, &ClockData.clock_id) < 0) dive_error("clock_init: Could not read clock data from %s.", CLOCK_URL); /* Find the ids of the clock components, see CLOCK_URL. */ if (obj = find_sub_byname(&ClockData.clock_id, "Hour Hand")) ClockData.hour_id = obj->id; else dive_error("clock_init: Hour hand not found in %s.", CLOCK_URL); if (obj = find_sub_byname(&ClockData.clock_id, "Minute Hand")) ClockData.min_id = obj->id; else dive_error("clock_init: Minute hand not found in %s.", CLOCK_URL); if (obj = find_sub_byname(&ClockData.clock_id, "Second Hand")) ClockData.sec_id = obj->id; else dive_error("clock_init: Second hand not found in %s.", CLOCK_URL); /* Initialize clock to current time */ set_current_time(); /* Register to be called each time a select interaction signal is sent to the clock */ callback_register_filter(INTERACTION_SIGNAL, interaction_cb, 0, &ClockData.clock_id, NULL, 0x0, NULL); dive_add_exit_fn(clock_exit, NULL); } /* ------------------------------------------------------------------------ * main * * Init system, setup clock and run forever. * * ------------------------------------------------------------------------ */ void main(int argc, char *argv[]) { char *start_world; objid_t wid; /* Parse the command line arguments */ start_world = std_init(NULL, 0, argc, argv); /* Connect to a world, the new world will get identifier wid */ objid_zero(&wid); distr_world_connect(start_world, &wid, NULL); /* Read and initialize clock: it will appear in the new world */ clock_init(&wid); /* Initialize alarm frequency. */ alarm_init(1000); /* Once a second */ /* Register to be called each time the alarm wakeups. */ alarm_add(on_timer, NULL); /* GO! */ threads_main_loop(); }