home *** CD-ROM | disk | FTP | other *** search
/ Club Amiga de Montreal - CAM / CAM_CD_1.iso / files / 181.lha / Ticker / Ticker.c < prev    next >
C/C++ Source or Header  |  1988-04-28  |  8KB  |  255 lines

  1. /*
  2.         Ticker - Written by Ray Lambert - This source was an exercise in
  3.             learning to work with devices.  In this program the timer.device
  4.             is used to maintain an on-screen clock.  timer.device will be
  5.             programmed to send a message to a port that Ticker creates
  6.             every time the 'minute' advances in the system clock.  timer.device
  7.             will also be polled for the time every sixty seconds or so when
  8.             the time display is updated.  I've put many comments in here to
  9.             make it easy to learn from this piece of code.  This program
  10.             is PUBLIC DOMAIN.  Enjoy!            Ray
  11.  
  12.  
  13.         Compilering:  Ticker was written with Lattice C then converted to Manx.
  14.             It should still compile under Lattice with little or no modification.
  15.  
  16.             Manx produces a smaller executable code size.  Use the make file
  17.             (Ticker.make) with Manx ( eg. MAKE -f Ticker.make ). 
  18.  
  19.             With Lattice use: LC -v -L Ticker
  20.  
  21.  
  22.         Running Ticker: Using the supplied icon Ticker can be easily run from
  23.             Workbench.  From the CLI however you will have to use the AmigaDOS
  24.             RUN command ( eg.  RUN Ticker ).  If you need to close the CLI that
  25.             Ticker is RUN from however, you will have to use RUNBACK (PD) or
  26.             the ARP replacement for RUN called ARUN.  If you use ARUN you must
  27.             specify the NOIO option ( eg. ARUN Ticker NOIO ).
  28. */
  29.  
  30. #include <intuition/intuition.h>
  31. #include <devices/timer.h>
  32. #include <exec/ports.h>
  33. #include <exec/memory.h>
  34. #include <functions.h>        /* remove this for Lattice! */
  35.  
  36. struct IntuitionBase *IntuitionBase;
  37. struct Window *W=0L;
  38. struct IntuiMessage *Imsg;
  39. int timeropen=0;    /* flag to let clean_exit() know if the timer.device
  40.     was succesfully opened...  'Should we CloseDevice(timer.device)??' */
  41.  
  42. struct NewWindow NW = {0,0,149,10,0,1,CLOSEWINDOW+ACTIVEWINDOW+
  43.     REFRESHWINDOW+INACTIVEWINDOW,WINDOWDRAG+WINDOWDEPTH+WINDOWCLOSE+
  44.     SIMPLE_REFRESH,0L,0L,0L,0L,0L,149,10,149,10,WBENCHSCREEN};
  45.  
  46. struct timerequest *t_req=0L;
  47. struct timerequest *t_dev=0L;
  48.  
  49.     /* defines to work with the timerequest structs less painful :) */
  50. #define TIMEVAL tr_time
  51. #define SECS TIMEVAL.tv_secs
  52. #define MICROS TIMEVAL.tv_micro
  53. #define IOCOMMAND tr_node.io_Command
  54. #define IOFLAGS tr_node.io_Flags
  55. #define IOERROR tr_node.io_Error
  56. #define REPLYPORT tr_node.io_Message.mn_ReplyPort
  57. #define DEVICE tr_node.io_Device
  58. #define UNIT tr_node.io_Unit
  59.  
  60. struct MsgPort *TimerPort=0L;
  61.  
  62. void clean_exit(xcode)
  63. int xcode;
  64. {
  65. /* close our window */
  66.     if (W) CloseWindow(W);
  67. /* close timer.device */
  68.     if (timeropen) CloseDevice(t_dev);
  69. /* remove our message port from the system */
  70.     if (TimerPort)
  71.         {
  72.         /* remove the port */
  73.             RemPort(TimerPort);
  74.         /* free it's signal bits */
  75.             FreeSignal(TimerPort->mp_SigBit);
  76.         /* free the memory it occupied */
  77.             FreeMem(TimerPort,sizeof(struct MsgPort));
  78.         }
  79. /* free the memory allocated to the timerequest structs */
  80.     if (t_req) FreeMem(t_req,sizeof(struct timerequest));
  81.     if (t_dev) FreeMem(t_dev,sizeof(struct timerequest));
  82. /* close intuition.library */
  83.     if (IntuitionBase) CloseLibrary((struct Library *)IntuitionBase);
  84. /* exit to system */
  85.     exit(xcode);
  86. }
  87.  
  88. struct IntuiText fatal_mess = {0,1,JAM2,124,15,0L,
  89.     (UBYTE *)"Ticker Fatal Error!",0L};
  90. struct IntuiText fatal_body = {0,1,JAM2,70,35,0L,0L,&fatal_mess};
  91. struct IntuiText fatal_ack = {0,1,JAM2,6,3,0L,(UBYTE *)"Acknowledged",0L};
  92.  
  93. void fatal(message, ecode)
  94. UBYTE *message;
  95. int ecode;
  96. {    /* a fatal error has occured, put up requester and clean_exit() */
  97.     fatal_body.IText=message;
  98.     fatal_body.LeftEdge=((400-IntuiTextLength(&fatal_body))>>1);
  99.     AutoRequest(0L,&fatal_body,&fatal_ack,&fatal_ack,0L,0L,400,90);
  100.     clean_exit(ecode);
  101. }
  102.  
  103. int create_port()    /* create and add our message port to the system */
  104. {
  105. /* allocate a signal bit */
  106.     int sigbit=AllocSignal(-1);
  107.     if (sigbit==-1) return(0);
  108. /* allocate memory for the port struct */
  109.     TimerPort=(struct MsgPort *)AllocMem(sizeof(struct MsgPort),
  110.             MEMF_CLEAR+MEMF_PUBLIC);
  111.     if (!TimerPort)
  112.         {
  113.             FreeSignal(sigbit);
  114.             return(0);
  115.         }
  116. /* initialize the port struct */
  117.     TimerPort->mp_Node.ln_Name="TickerPort";
  118.     TimerPort->mp_Node.ln_Pri=0;
  119.     TimerPort->mp_Node.ln_Type=NT_MSGPORT;
  120.     TimerPort->mp_Flags=PA_SIGNAL;
  121.     TimerPort->mp_SigBit=sigbit;
  122.     TimerPort->mp_SigTask=(struct Task *)FindTask(0L);
  123. /* add the port to the system list */
  124.     AddPort(TimerPort);
  125.     return(1);
  126. }
  127.  
  128. UBYTE TimeStr[10];
  129.  
  130. struct IntuiText TimeIText = {1,0,JAM2,30,1,0L,TimeStr,0L};
  131.  
  132. ULONG timer_sig;
  133. ULONG window_sig;
  134.  
  135. void update_time()
  136. {
  137.     int hour;
  138.     int minute;
  139.     int seconds;
  140.     char ampm;
  141.  
  142. /* send request to timer.device to get current system time */
  143.     t_req->REPLYPORT=t_dev->REPLYPORT;
  144.     t_req->DEVICE=t_dev->DEVICE;
  145.     t_req->UNIT=t_dev->UNIT;
  146.     t_req->IOCOMMAND=TR_GETSYSTIME;
  147.     t_req->IOFLAGS=IOF_QUICK;
  148.     t_req->SECS=0L;
  149.     t_req->MICROS=0L;
  150.     if (DoIO(t_req)) return;
  151. /* clear message port */
  152.     WaitIO(t_req);
  153. /* calculate hour */
  154.     hour=((t_req->SECS%86400L)/3600L);
  155. /* decide if it's am or pm */
  156.     if (hour<12)
  157.         ampm='a';    
  158.     else
  159.         ampm='p';
  160. /* convert hour to 12 hour format */
  161.     if (hour==0) hour=12;
  162.     if (hour>12) hour-=12;
  163. /* calculate minute */
  164.     minute=((t_req->SECS%3600L)/60L);
  165. /* display hours:minutes */
  166.     sprintf(TimeStr," %02d:%02d%c ",hour,minute,ampm);
  167.     PrintIText(W->RPort,&TimeIText,0,0);
  168. /* initialize a timer.device request to signal the next display update */
  169.     t_req->REPLYPORT=t_dev->REPLYPORT;
  170.     t_req->DEVICE=t_dev->DEVICE;
  171.     t_req->UNIT=t_dev->UNIT;
  172.     t_req->IOCOMMAND=TR_ADDREQUEST;
  173.     t_req->IOFLAGS=0L;
  174.     t_req->MICROS=0L;
  175. /* calculate amount of seconds until system clock advances it's 'minutes' */
  176.     seconds=(t_req->SECS%60L);
  177.     t_req->SECS=(60L-(long)seconds);
  178. /* send the request */
  179.     SendIO(t_req);
  180. /* clear the signal bit for the TimerPort */
  181.     SetSignal(0L,timer_sig);
  182. }
  183.  
  184. void _main()
  185. {
  186.     LONG class=0L;
  187.     ULONG signal;
  188.  
  189. /* open intuition.library */
  190.     IntuitionBase=(struct IntuitionBase *)OpenLibrary("intuition.library",0L);
  191.     if (!IntuitionBase) clean_exit(500);
  192. /* create new message port for communication with timer.device */
  193.     if (!create_port()) fatal("Can't allocate message port",20);
  194. /* allocate memory for two timerequest structs */
  195.     t_req=(struct timerequest *)
  196.         AllocMem(sizeof(struct timerequest),MEMF_CLEAR);
  197.     t_dev=(struct timerequest *)
  198.         AllocMem(sizeof(struct timerequest),MEMF_CLEAR);
  199.     if ( (!t_dev) || (!t_req) ) fatal("Insufficient memory",21);
  200. /* open the timer.device */
  201.     t_dev->REPLYPORT=TimerPort;
  202.     if (OpenDevice("timer.device",UNIT_VBLANK,t_dev,0L))
  203.         fatal("timer.device not available",22);
  204.     timeropen=1;    /* flag to tell clean_exit to close the device */
  205. /* open our window */
  206.     W=(struct Window *)OpenWindow((struct NewWindow *)&NW);
  207.     if (!W) fatal("Can't open window",23);
  208. /* calculate signal bit masks for both message ports and store the results
  209.         so we don't have to repeatedly calculate them later */
  210.     timer_sig=(1<<TimerPort->mp_SigBit);
  211.     window_sig=(1<<W->UserPort->mp_SigBit);
  212. /* initialize display and first timer io request */
  213.     update_time();
  214. /* main loop */
  215.     for(;;)
  216.         {
  217.         /* wait for a message signal from either Intuition or timer.device */
  218.             signal=Wait(timer_sig | window_sig);
  219.         /* check for Intuition message */
  220.             if (signal&window_sig)
  221.                 {
  222.                     Imsg=(struct IntuiMessage *)GetMsg(W->UserPort);
  223.                     while(Imsg)    /* process all messages in the window's queue */
  224.                         {
  225.                         /* save the class and reply */
  226.                             class=Imsg->Class;
  227.                             ReplyMsg(Imsg);
  228.                         /* process the message */
  229.                             if (class==CLOSEWINDOW)
  230.                                 {
  231.                             /* user clicked close gadget. cancel last timer.device io request */
  232.                                     AbortIO(t_req);
  233.                                     WaitIO(t_req);
  234.                             /* exit back to system */
  235.                                     clean_exit(0);
  236.                                 }
  237.                             else    /* refresh display */
  238.                                 PrintIText(W->RPort,&TimeIText,0,0);
  239.                             Imsg=(struct IntuiMessage *)GetMsg(W->UserPort);
  240.                         }
  241.                 /* clear the signal bit */
  242.                     SetSignal(0L,window_sig);
  243.                 }
  244.         /* check for timer.device message */
  245.             if (signal&timer_sig)
  246.                 {
  247.                 /* clear message port */
  248.                     WaitIO(t_req);
  249.                 /* update the display and send new io request */
  250.                     update_time();
  251.                 }
  252.         }
  253. }
  254.  
  255.