home *** CD-ROM | disk | FTP | other *** search
- /*
- Ticker - Written by Ray Lambert - This source was an exercise in
- learning to work with devices. In this program the timer.device
- is used to maintain an on-screen clock. timer.device will be
- programmed to send a message to a port that Ticker creates
- every time the 'minute' advances in the system clock. timer.device
- will also be polled for the time every sixty seconds or so when
- the time display is updated. I've put many comments in here to
- make it easy to learn from this piece of code. This program
- is PUBLIC DOMAIN. Enjoy! Ray
-
-
- Compilering: Ticker was written with Lattice C then converted to Manx.
- It should still compile under Lattice with little or no modification.
-
- Manx produces a smaller executable code size. Use the make file
- (Ticker.make) with Manx ( eg. MAKE -f Ticker.make ).
-
- With Lattice use: LC -v -L Ticker
-
-
- Running Ticker: Using the supplied icon Ticker can be easily run from
- Workbench. From the CLI however you will have to use the AmigaDOS
- RUN command ( eg. RUN Ticker ). If you need to close the CLI that
- Ticker is RUN from however, you will have to use RUNBACK (PD) or
- the ARP replacement for RUN called ARUN. If you use ARUN you must
- specify the NOIO option ( eg. ARUN Ticker NOIO ).
- */
-
- #include <intuition/intuition.h>
- #include <devices/timer.h>
- #include <exec/ports.h>
- #include <exec/memory.h>
- #include <functions.h> /* remove this for Lattice! */
-
- struct IntuitionBase *IntuitionBase;
- struct Window *W=0L;
- struct IntuiMessage *Imsg;
- int timeropen=0; /* flag to let clean_exit() know if the timer.device
- was succesfully opened... 'Should we CloseDevice(timer.device)??' */
-
- struct NewWindow NW = {0,0,149,10,0,1,CLOSEWINDOW+ACTIVEWINDOW+
- REFRESHWINDOW+INACTIVEWINDOW,WINDOWDRAG+WINDOWDEPTH+WINDOWCLOSE+
- SIMPLE_REFRESH,0L,0L,0L,0L,0L,149,10,149,10,WBENCHSCREEN};
-
- struct timerequest *t_req=0L;
- struct timerequest *t_dev=0L;
-
- /* defines to work with the timerequest structs less painful :) */
- #define TIMEVAL tr_time
- #define SECS TIMEVAL.tv_secs
- #define MICROS TIMEVAL.tv_micro
- #define IOCOMMAND tr_node.io_Command
- #define IOFLAGS tr_node.io_Flags
- #define IOERROR tr_node.io_Error
- #define REPLYPORT tr_node.io_Message.mn_ReplyPort
- #define DEVICE tr_node.io_Device
- #define UNIT tr_node.io_Unit
-
- struct MsgPort *TimerPort=0L;
-
- void clean_exit(xcode)
- int xcode;
- {
- /* close our window */
- if (W) CloseWindow(W);
- /* close timer.device */
- if (timeropen) CloseDevice(t_dev);
- /* remove our message port from the system */
- if (TimerPort)
- {
- /* remove the port */
- RemPort(TimerPort);
- /* free it's signal bits */
- FreeSignal(TimerPort->mp_SigBit);
- /* free the memory it occupied */
- FreeMem(TimerPort,sizeof(struct MsgPort));
- }
- /* free the memory allocated to the timerequest structs */
- if (t_req) FreeMem(t_req,sizeof(struct timerequest));
- if (t_dev) FreeMem(t_dev,sizeof(struct timerequest));
- /* close intuition.library */
- if (IntuitionBase) CloseLibrary((struct Library *)IntuitionBase);
- /* exit to system */
- exit(xcode);
- }
-
- struct IntuiText fatal_mess = {0,1,JAM2,124,15,0L,
- (UBYTE *)"Ticker Fatal Error!",0L};
- struct IntuiText fatal_body = {0,1,JAM2,70,35,0L,0L,&fatal_mess};
- struct IntuiText fatal_ack = {0,1,JAM2,6,3,0L,(UBYTE *)"Acknowledged",0L};
-
- void fatal(message, ecode)
- UBYTE *message;
- int ecode;
- { /* a fatal error has occured, put up requester and clean_exit() */
- fatal_body.IText=message;
- fatal_body.LeftEdge=((400-IntuiTextLength(&fatal_body))>>1);
- AutoRequest(0L,&fatal_body,&fatal_ack,&fatal_ack,0L,0L,400,90);
- clean_exit(ecode);
- }
-
- int create_port() /* create and add our message port to the system */
- {
- /* allocate a signal bit */
- int sigbit=AllocSignal(-1);
- if (sigbit==-1) return(0);
- /* allocate memory for the port struct */
- TimerPort=(struct MsgPort *)AllocMem(sizeof(struct MsgPort),
- MEMF_CLEAR+MEMF_PUBLIC);
- if (!TimerPort)
- {
- FreeSignal(sigbit);
- return(0);
- }
- /* initialize the port struct */
- TimerPort->mp_Node.ln_Name="TickerPort";
- TimerPort->mp_Node.ln_Pri=0;
- TimerPort->mp_Node.ln_Type=NT_MSGPORT;
- TimerPort->mp_Flags=PA_SIGNAL;
- TimerPort->mp_SigBit=sigbit;
- TimerPort->mp_SigTask=(struct Task *)FindTask(0L);
- /* add the port to the system list */
- AddPort(TimerPort);
- return(1);
- }
-
- UBYTE TimeStr[10];
-
- struct IntuiText TimeIText = {1,0,JAM2,30,1,0L,TimeStr,0L};
-
- ULONG timer_sig;
- ULONG window_sig;
-
- void update_time()
- {
- int hour;
- int minute;
- int seconds;
- char ampm;
-
- /* send request to timer.device to get current system time */
- t_req->REPLYPORT=t_dev->REPLYPORT;
- t_req->DEVICE=t_dev->DEVICE;
- t_req->UNIT=t_dev->UNIT;
- t_req->IOCOMMAND=TR_GETSYSTIME;
- t_req->IOFLAGS=IOF_QUICK;
- t_req->SECS=0L;
- t_req->MICROS=0L;
- if (DoIO(t_req)) return;
- /* clear message port */
- WaitIO(t_req);
- /* calculate hour */
- hour=((t_req->SECS%86400L)/3600L);
- /* decide if it's am or pm */
- if (hour<12)
- ampm='a';
- else
- ampm='p';
- /* convert hour to 12 hour format */
- if (hour==0) hour=12;
- if (hour>12) hour-=12;
- /* calculate minute */
- minute=((t_req->SECS%3600L)/60L);
- /* display hours:minutes */
- sprintf(TimeStr," %02d:%02d%c ",hour,minute,ampm);
- PrintIText(W->RPort,&TimeIText,0,0);
- /* initialize a timer.device request to signal the next display update */
- t_req->REPLYPORT=t_dev->REPLYPORT;
- t_req->DEVICE=t_dev->DEVICE;
- t_req->UNIT=t_dev->UNIT;
- t_req->IOCOMMAND=TR_ADDREQUEST;
- t_req->IOFLAGS=0L;
- t_req->MICROS=0L;
- /* calculate amount of seconds until system clock advances it's 'minutes' */
- seconds=(t_req->SECS%60L);
- t_req->SECS=(60L-(long)seconds);
- /* send the request */
- SendIO(t_req);
- /* clear the signal bit for the TimerPort */
- SetSignal(0L,timer_sig);
- }
-
- void _main()
- {
- LONG class=0L;
- ULONG signal;
-
- /* open intuition.library */
- IntuitionBase=(struct IntuitionBase *)OpenLibrary("intuition.library",0L);
- if (!IntuitionBase) clean_exit(500);
- /* create new message port for communication with timer.device */
- if (!create_port()) fatal("Can't allocate message port",20);
- /* allocate memory for two timerequest structs */
- t_req=(struct timerequest *)
- AllocMem(sizeof(struct timerequest),MEMF_CLEAR);
- t_dev=(struct timerequest *)
- AllocMem(sizeof(struct timerequest),MEMF_CLEAR);
- if ( (!t_dev) || (!t_req) ) fatal("Insufficient memory",21);
- /* open the timer.device */
- t_dev->REPLYPORT=TimerPort;
- if (OpenDevice("timer.device",UNIT_VBLANK,t_dev,0L))
- fatal("timer.device not available",22);
- timeropen=1; /* flag to tell clean_exit to close the device */
- /* open our window */
- W=(struct Window *)OpenWindow((struct NewWindow *)&NW);
- if (!W) fatal("Can't open window",23);
- /* calculate signal bit masks for both message ports and store the results
- so we don't have to repeatedly calculate them later */
- timer_sig=(1<<TimerPort->mp_SigBit);
- window_sig=(1<<W->UserPort->mp_SigBit);
- /* initialize display and first timer io request */
- update_time();
- /* main loop */
- for(;;)
- {
- /* wait for a message signal from either Intuition or timer.device */
- signal=Wait(timer_sig | window_sig);
- /* check for Intuition message */
- if (signal&window_sig)
- {
- Imsg=(struct IntuiMessage *)GetMsg(W->UserPort);
- while(Imsg) /* process all messages in the window's queue */
- {
- /* save the class and reply */
- class=Imsg->Class;
- ReplyMsg(Imsg);
- /* process the message */
- if (class==CLOSEWINDOW)
- {
- /* user clicked close gadget. cancel last timer.device io request */
- AbortIO(t_req);
- WaitIO(t_req);
- /* exit back to system */
- clean_exit(0);
- }
- else /* refresh display */
- PrintIText(W->RPort,&TimeIText,0,0);
- Imsg=(struct IntuiMessage *)GetMsg(W->UserPort);
- }
- /* clear the signal bit */
- SetSignal(0L,window_sig);
- }
- /* check for timer.device message */
- if (signal&timer_sig)
- {
- /* clear message port */
- WaitIO(t_req);
- /* update the display and send new io request */
- update_time();
- }
- }
- }
-
-