home *** CD-ROM | disk | FTP | other *** search
/ Club Amiga de Montreal - CAM / CAM_CD_1.iso / files / 148.lha / SpudClock / spudclock.c < prev    next >
C/C++ Source or Header  |  1988-04-26  |  34KB  |  834 lines

  1. /*************************************************************************
  2.  *
  3.  *  SPUDclock - This program does a nice little talking alarm clock
  4.  *  
  5.  *  This was written by Robert E. Beaty and H. Bret Young and
  6.  *  are Copyright (C) 1987 by R.E.Beaty and H. Bret Young and
  7.  *  The Man From S.P.U.D.
  8.  *
  9.  *  v1.2
  10.  *************************************************************************/
  11. /* Get the necessary include files for this program */
  12. #include <exec/types.h>
  13. #include <exec/exec.h>
  14. #include <devices/narrator.h>
  15. #include <devices/timer.h>
  16. #include <libraries/translator.h>
  17. #include <libraries/dos.h>
  18. #include <intuition/intuition.h>
  19. #include <string.h>
  20. /*
  21.  * Here are some necessary defines for processing needs
  22.  */
  23. #define REVISION        1
  24. #define TASK_PRIORITY   0
  25. /*
  26.  * Here are some necessary return codes for various routines
  27.  */
  28. #define NORMAL_EXIT             0
  29. #define NORMAL_START            0
  30. #define QUICK_EXIT              -10
  31. #define QUICK_START             -20
  32. #define CANT_OPEN_INTUITION     -100
  33. #define CANT_OPEN_TRANSLATOR    -200
  34. #define CANT_OPEN_NARRATOR      -300
  35. #define CANT_OPEN_TIMER         -400
  36. #define CREATE_PORT_PROBLEMS    -500
  37. #define CREATE_IO_PROBLEMS      -600
  38. #define TRANSLATOR_NOT_WORKING  -700
  39. /* 
  40.  * Here are the variable values that come in handy
  41.  */
  42. #define QUARTER_HOUR            1
  43. #define HALF_HOUR               2
  44. #define HOUR                    4
  45. #define LITTLE                  1
  46. #define BIG                     2
  47.  
  48. #define AM_BIT                  (1<<0)
  49. #define PS_BIT                  (1<<1)
  50. #define SA_BIT                  (1<<2)
  51. #define EA_BIT                  (1<<3)
  52. #define AV_BIT                  (1<<4)
  53. #define S_BIT                   (1<<5)
  54. /* 
  55.  * Here are the global structures
  56.  */
  57. struct timerequest timeReq;     /* this is my conduit to the timer */
  58. struct MsgPort *clockPort = NULL, *writePort = NULL, 
  59.                *replyPort = NULL, *timerPort = NULL;
  60. struct narrator_rb *writeNarrator = NULL;
  61. struct IntuitionBase *IntuitionBase = NULL;
  62. struct Library *TranslatorBase = NULL;
  63. struct DateStamp now;
  64. struct PacketMessage {
  65.         struct Message packet_message;          /* this is for DOS */
  66.         int alarm_mode,         /* this will tell us how often to alarm */
  67.             prestart,           /* this will tell if we prestart the speakers */            start_alarm,        /* this is the starting time */
  68.             end_alarm,          /* this is the ending time */
  69.             alarm_volume,       /* this is how loud to make it */
  70.             quit_flag;          /* this will tell when to quit */
  71.         char salutation[80];    /* this is a little saying before the time */
  72.         int change_flags,
  73.             changing,
  74.             listing;
  75.         };
  76. /* 
  77.  * Here are the global variables
  78.  */
  79. UBYTE *sampleInput, outputString[500];  /* these are for the translator */
  80. SHORT rtnCode, error;
  81. BYTE audChanMasks[4] = { 3, 5, 10, 12 };        /* which channels to use */
  82. int signal, timer_signal, port_signal;  /* where the message came from */
  83. int alarm_mode, quit_flag, prestart, alarm_volume;
  84. int start_alarm, end_alarm, alarm_time;
  85. int hours_24, hours_12, minutes;
  86. char *cp, salutation[80], alarm[120];
  87. struct PacketMessage *incoming, *outgoing;
  88.  
  89. /************************************************************************
  90.  *
  91.  *  cprintf( why ) - This routine does simple string printing to
  92.  *                   the console, and so saves us loading the printf
  93.  *                   routines.
  94.  *
  95.  *  This code section was written by Robert E. Beaty and
  96.  *  are Copyright (C) 1987 by R.E.Beaty and The Man From S.P.U.D.
  97.  *
  98.  ************************************************************************/
  99. cprintf( arg )
  100. char *arg;
  101. {
  102.     int length;
  103.     length = Write( Output(), arg, strlen(arg) );
  104.     return( length );
  105. }   /* end of cprintf(); */
  106. /************************************************************************
  107.  *
  108.  *  itoa( string, value ) - This routine does simple integer to ascii
  109.  *                          conversion. NOTE: value < 9999 !!
  110.  *
  111.  *  This code section was written by Robert E. Beaty and
  112.  *  are Copyright (C) 1987 by R.E.Beaty and The Man From S.P.U.D.
  113.  *
  114.  ************************************************************************/
  115. void itoa( carg, varg )
  116. char *carg;
  117. int varg;
  118. {
  119.     int place;
  120.     /* reset where I am putting this stuff */
  121.     place = 0;
  122.     if ( varg > 999 ) {
  123.         /* do the most thousands digit */
  124.         carg[place++] = '0' + (varg/1000);
  125.         varg = varg - (1000*(varg/1000));
  126.     }
  127.     if ( (varg > 99) || (place != 0) ) {
  128.         /* do the hundreds digit */
  129.         carg[place++] = '0' + (varg/100);
  130.         varg = varg - (100*(varg/100));
  131.     }
  132.     if ( (varg > 9) || (place != 0) ) {
  133.         /* do the tens digit */
  134.         carg[place++] = '0' + (varg/10);
  135.         varg = varg - (10*(varg/10));
  136.     }
  137.     /* always do the ones digit */
  138.     carg[place++] = '0' + varg;
  139.     /* null terminate this string */
  140.     carg[place] = '\0';
  141. }   /* end of itoa(); */
  142. /************************************************************************
  143.  *
  144.  *  CloseNarrator( why ) - This routine closes up the narrator and
  145.  *                         translator devices nicely.
  146.  *
  147.  *  This code section was written by Robert E. Beaty and
  148.  *  are Copyright (C) 1987 by R.E.Beaty and The Man From S.P.U.D.
  149.  *
  150.  ************************************************************************/
  151. void CloseNarrator( why )
  152. int why;
  153. {
  154.     /* Check to see if this was called by OpenNarrator() */
  155.     if ( why != CANT_OPEN_NARRATOR ) {
  156.         if ( writeNarrator != NULL )
  157.             CloseDevice( writeNarrator );
  158.     }
  159.     /* Just start deleting things if they exist */
  160.     if ( writeNarrator != NULL )
  161.         DeleteExtIO( writeNarrator, sizeof(struct narrator_rb) );
  162.     if ( writePort != NULL )
  163.         DeletePort( writePort );
  164.     if ( TranslatorBase != NULL )
  165.         CloseLibrary( TranslatorBase );
  166. }   /* end of CloseNarrator(); */
  167. /************************************************************************
  168.  *
  169.  *  OpenNarrator() - This routine opens up the narrator and translator
  170.  *                   devices nicely. It will return non-FALSE if an error
  171.  *                   occured.
  172.  *
  173.  *  This code section was written by Robert E. Beaty and
  174.  *  are Copyright (C) 1987 by R.E.Beaty and The Man From S.P.U.D.
  175.  *
  176.  ************************************************************************/
  177. OpenNarrator( )
  178. {
  179.     int error;
  180.     /* Open up the translator first */
  181.     TranslatorBase = (struct Library *) OpenLibrary( "translator.library", REVISION );
  182.     if ( TranslatorBase == NULL )
  183.         return( CANT_OPEN_TRANSLATOR );
  184.         
  185.     /* test it */
  186.     sampleInput = "this is a test.";
  187.     rtnCode = Translate( sampleInput, strlen(sampleInput), outputString, 500 );
  188.     if ( rtnCode != 0 ) {
  189.         CloseLibrary( TranslatorBase );         /* this is open, so close */
  190.         return( TRANSLATOR_NOT_WORKING );
  191.     }   /* end of error checking the translator */
  192.     /* Create the port to the Narrator */
  193.     writePort = (struct MsgPort *) CreatePort( "SPUDclock.narrator", TASK_PRIORITY );
  194.     if ( writePort == NULL ) {
  195.         CloseLibrary( TranslatorBase );         /* this is open, so close */
  196.         return( CREATE_PORT_PROBLEMS );
  197.     }   /* end of error checking the port creation */
  198.     /* Open an I/O channel to the Narrator */
  199.     writeNarrator = (struct narrator_rb *) CreateExtIO( writePort, sizeof(struct narrator_rb) );
  200.     if ( writeNarrator == NULL ) {
  201.         DeletePort( writePort );                /* this port is open */
  202.         CloseLibrary( TranslatorBase );         /* this is open, so close */
  203.         return( CREATE_IO_PROBLEMS );
  204.     }   /* end of error checking I/O creation */
  205.     /* Now set up the defaults for the narrator port */
  206.     writeNarrator->ch_masks = audChanMasks;     /* ... the channel masks */
  207.     writeNarrator->nm_masks = sizeof(audChanMasks);     /* ... the size */
  208.     writeNarrator->message.io_Data = (APTR)outputString;        /* data */
  209.     writeNarrator->mouths = 0;          /* we don't want shapes computed */
  210.     writeNarrator->message.io_Command = CMD_WRITE;      /* output command */
  211.     /* Finally, open the narrator device */
  212.     error = OpenDevice( "narrator.device", 0, writeNarrator, TASK_PRIORITY );
  213.     if ( error != 0 ) {
  214.         CloseNarrator( CANT_OPEN_NARRATOR );    /* close it all up */
  215.         return( CANT_OPEN_NARRATOR );
  216.     }   /* end of checking narrator device opening */
  217.     
  218.     /* no errors so return FALSE */
  219.     return( FALSE );
  220. }   /* end of OpenNarrator(); */
  221. /************************************************************************
  222.  *
  223.  *  init( how ) - This routine opens everything up and returns non-FALSE
  224.  *                if something went wrong.
  225.  *
  226.  *  This code section was written by Robert E. Beaty and
  227.  *  are Copyright (C) 1987 by R.E.Beaty and The Man From S.P.U.D.
  228.  *
  229.  ************************************************************************/
  230. init( how )
  231. int how;
  232. {
  233.     int error;
  234.     /* Open up Intuition first */
  235.     if ( IntuitionBase == NULL ) {
  236.         IntuitionBase = (struct IntuitionBase *) OpenLibrary( "intuition.library", REVISION );
  237.         if ( IntuitionBase == NULL )
  238.             return( CANT_OPEN_INTUITION );
  239.     }   /* end of opening intuition if needed */
  240.     /* if this is a quick start, then only open up intuition */
  241.     if ( how == QUICK_START ) return( FALSE );
  242.     /* Open the communication port to other copies of SPUDclock */
  243.     clockPort = (struct MsgPort *) CreatePort( "SPUDclock", TASK_PRIORITY );
  244.     if ( clockPort == NULL ) {
  245.         CloseLibrary( IntuitionBase );          /* this is open, so close */
  246.         return( CREATE_PORT_PROBLEMS );
  247.     }   /* end of error checking the port creation */
  248.     /* Now open the narrator */
  249.     error = OpenNarrator();
  250.     if ( error ) {
  251.         DeletePort( clockPort );
  252.         CloseLibrary( IntuitionBase );
  253.         return( error );
  254.     }   /* end of error checking the narrator opening */
  255.     
  256.     /* Now create the timer */
  257.     timerPort = (struct MsgPort *) CreatePort( "SPUDclock.timer", TASK_PRIORITY );
  258.     if ( timerPort == NULL ) {
  259.         CloseNarrator( CANT_OPEN_TIMER );
  260.         DeletePort( clockPort );
  261.         CloseLibrary( IntuitionBase );          /* this is open, so close */
  262.         return( CREATE_PORT_PROBLEMS );
  263.     }   /* end of error checking the port creation */
  264.     error = OpenDevice( TIMERNAME, UNIT_VBLANK, (char *) &timeReq, TASK_PRIORITY );    
  265.     if ( error != 0 ) {
  266.         DeletePort( timerPort );
  267.         CloseNarrator( CANT_OPEN_TIMER );
  268.         DeletePort( clockPort );
  269.         CloseLibrary( IntuitionBase );          /* this is open, so close */
  270.         return( CANT_OPEN_TIMER );
  271.     }
  272.     /* Everything is open O.K., so get the signal bits */
  273.     timer_signal = 1 << timerPort->mp_SigBit;
  274.     port_signal = 1 << clockPort->mp_SigBit;
  275.     
  276.     /* ... and set up the timer request structure */
  277.     timeReq.tr_node.io_Message.mn_ReplyPort = timerPort;
  278.     timeReq.tr_node.io_Command = TR_ADDREQUEST;
  279.     timeReq.tr_node.io_Flags = 0;
  280.     timeReq.tr_node.io_Error = 0;
  281.     /* no errors, so return FALSE */
  282.     return( FALSE );
  283. }   /* end of init(); */
  284.  
  285. /************************************************************************
  286.  *
  287.  *  clean( why ) - This routine cleans everything up.
  288.  *
  289.  *  This code section was written by Robert E. Beaty and
  290.  *  are Copyright (C) 1987 by R.E.Beaty and The Man From S.P.U.D.
  291.  *
  292.  ************************************************************************/
  293. void clean( why )
  294. int why;
  295. {
  296.     /* Abort the timer request pending */
  297.     if ( timeReq.tr_node.io_Message.mn_ReplyPort != NULL )
  298.         AbortIO( (char *) &timeReq.tr_node );
  299.     /* if we want a quick exit then skip this stuff */
  300.     if ( why == QUICK_EXIT ) goto quick;
  301.     /* just call the clean up routines */
  302.     if ( timerPort != NULL ) DeletePort( timerPort );
  303.     CloseNarrator( why );
  304.     if ( clockPort != NULL ) DeletePort( clockPort );
  305.     quick:
  306.     if ( IntuitionBase != NULL ) CloseLibrary( IntuitionBase );
  307. }   /* end of clean(); */
  308. /************************************************************************
  309.  *
  310.  *  bed_bye( how_much ) - This routine submits a timer event for us
  311.  *
  312.  *  This code section was written by Robert E. Beaty and
  313.  *  are Copyright (C) 1987 by R.E.Beaty and The Man From S.P.U.D.
  314.  *
  315.  ************************************************************************/
  316. void bed_bye( how_much )
  317. int how_much;
  318. {
  319.     /* See how long the sleep is for */
  320.     if ( how_much == LITTLE ) {
  321.         timeReq.tr_time.tv_secs = 5;            /* little is 5 sec. */
  322.         timeReq.tr_time.tv_micro = 0;
  323.     }
  324.     else {
  325.         timeReq.tr_time.tv_secs = 885;          /* big is 14 min 45 sec. */
  326.         timeReq.tr_time.tv_micro = 0;
  327.     }
  328.     /* ... and send it out to be done */
  329.     SendIO( (char *) &timeReq.tr_node ); 
  330. }   /* end of bed_bye(); */
  331. /************************************************************************
  332.  *
  333.  *  speak_time( hrs, mins ) - This routine formats and speaks the time.
  334.  *
  335.  *  This code section was written by Robert E. Beaty and
  336.  *  are Copyright (C) 1987 by R.E.Beaty and The Man From S.P.U.D.
  337.  *
  338.  ************************************************************************/
  339. void speak_time( hrs, mins )
  340. int hrs, mins;
  341. {
  342.     /* 
  343.      * First, see if we need to prestart the speakers 
  344.      */
  345.     if ( prestart )
  346.         cp = stpcpy( alarm, "t,," );
  347.     else
  348.         cp = alarm;
  349.     /*
  350.      * Build up the string to speak
  351.      */
  352.     /* start with the salutation */
  353.     cp = stpcpy( cp, salutation );
  354.     /* ... add the time is stuff */
  355.     cp = stpcpy( cp, ", It is now " );
  356.     /* check for quarter till */
  357.     if ( (alarm_mode == QUARTER_HOUR) && (mins == 45) ) {
  358.         cp = stpcpy( cp, "quarter till " );
  359.         /* check to see that it makes sense */
  360.         if ( (++hrs) == 13 ) hrs = 1;
  361.     }
  362.     /*
  363.      * always add the hour
  364.      */
  365.     switch( hrs ) {
  366.         case 1 : cp = stpcpy( cp, "1 " );  break;
  367.         case 2 : cp = stpcpy( cp, "2 " );  break;
  368.         case 3 : cp = stpcpy( cp, "3 " );  break;
  369.         case 4 : cp = stpcpy( cp, "4 " );  break;
  370.         case 5 : cp = stpcpy( cp, "5 " );  break;
  371.         case 6 : cp = stpcpy( cp, "6 " );  break;
  372.         case 7 : cp = stpcpy( cp, "7 " );  break;
  373.         case 8 : cp = stpcpy( cp, "8 " );  break;
  374.         case 9 : cp = stpcpy( cp, "9 " );  break;
  375.         case 10 : cp = stpcpy( cp, "ten " );  break;
  376.         /* the number 11 sounds better spelled 'eelaven' */
  377.         case 11 : cp = stpcpy( cp, "eelaven " );  break;
  378.         case 12 : cp = stpcpy( cp, "twelve " );  break;
  379.     }   /* end of decoding the hours */
  380.     /*
  381.      * decode the different modes
  382.      */
  383.     switch( alarm_mode ) {
  384.         case QUARTER_HOUR :
  385.             switch( mins ) {
  386.                 case 0 : cp = stpcpy( cp, "o'clock." );  break;
  387.                 case 15 : cp = stpcpy( cp, "fifteen." );  break;
  388.                 case 30 : cp = stpcpy( cp, "thirty." );  break;
  389.                 case 45 : cp = stpcpy( cp, "." );  break;
  390.                 /* if we aren't where we are supposed to be, NULL it out */
  391.                 default : cp = NULL;  break;
  392.             }
  393.             break;
  394.         case HALF_HOUR :
  395.             switch( mins ) {
  396.                 case 0 : cp = stpcpy( cp, "o'clock." );  break;
  397.                 case 30 : cp = stpcpy( cp, "thirty." );  break;
  398.                 /* if we aren't where we are supposed to be, NULL it out */
  399.                 default : cp = NULL;  break;
  400.             }
  401.             break;
  402.         case HOUR :
  403.             if ( mins == 0 )
  404.                 cp = stpcpy( cp, "o'clock." );
  405.             else
  406.                 /* if we aren't where we are supposed to be, NULL it out */
  407.                 cp = NULL;
  408.             break;
  409.     }   /* end of alarm_mode selection */
  410.     /*
  411.      * If the time section is not NULL, do the rest
  412.      */
  413.     if ( cp != NULL ) {
  414.         /*
  415.          * ... add the "Good morning..." or "Good night..."
  416.          */
  417.         if ( start_alarm != end_alarm ) {
  418.             if ( alarm_time == start_alarm )
  419.                 cp = stpcpy( cp, ",, Good Morning!" );
  420.             if ( alarm_time == end_alarm )
  421.                 cp = stpcpy( cp, ",, Good Night." );
  422.         }   /* end of special salutation */
  423.         /*
  424.          * translate it and speak it
  425.          */
  426.         rtnCode = Translate( alarm, strlen(alarm), outputString, 500 );
  427.         writeNarrator->sex = MALE;
  428.         writeNarrator->pitch = DEFPITCH;
  429.         writeNarrator->mode = ROBOTICF0;
  430.         writeNarrator->volume = alarm_volume;
  431.         writeNarrator->message.io_Data = (APTR)outputString;
  432.         writeNarrator->message.io_Length = strlen( outputString );
  433.         DoIO( writeNarrator );
  434.     }   /* end of finishing it up and speaking it */
  435. }   /* end of speak_time(); */
  436. /************************************************************************
  437.  *
  438.  *  usage() - This routine helps the user.
  439.  *
  440.  *  This code section was written by Robert E. Beaty and
  441.  *  are Copyright (C) 1987 by R.E.Beaty and The Man From S.P.U.D.
  442.  *  
  443.  *  minimal additions by H. Bret Young 
  444.  *
  445.  ************************************************************************/
  446. usage( how_much )
  447. int how_much;
  448. {
  449.     cprintf( "Usage:\n" );
  450.     cprintf( "  run SPUDclock [-m greeting message] [-f] [-t] [-h] [-q] [-p] [-s ####] [-e ####] [-v ##]\n" );
  451.     if ( how_much == LITTLE ) return( FALSE );
  452.     cprintf( "Where:\n" );
  453.     cprintf( "  -m greeting message  - this will be spoken before the time\n" );    cprintf( "  -f  - this will cause the alarm to sound every quarter hour\n" );
  454.     cprintf( "  -t  - this will cause the alarm to sound every half hour\n" );
  455.     cprintf( "  -h  - this will cause the alarm to sound every hour\n" );
  456.     cprintf( "  -p  - this will make the alarm contain a 't' to start speakers\n" );
  457.     cprintf( "  -s #### - this will set the starting time to this time (2400 hr.)\n" );
  458.     cprintf( "  -e #### - this will set the ending time to this time (2400 hr.)\n" );
  459.     cprintf( "  -v ## - this will set the alarm volume to this (>0 and <=64)\n" );
  460.     cprintf( "  -q  - this will remove all copies of SPUDclock from memory\n" );    cprintf( "  -l  - this will list the current SPUDclock settings\n");
  461.     cprintf( "  -d  - this will cause the parameters not specified on the\n");
  462.     cprintf( "        command line to revert to their defaults\n");
  463.     return( FALSE );
  464. }   /* end of usage(); */
  465. /************************************************************************
  466.  *
  467.  *  print_settings() - This routine prints the current SPUDclock settings
  468.  *
  469.  *  This section was written by H. Bret Young
  470.  *  are Copyright (C) 1987 by H. Bret Young and The Man From S.P.U.D.
  471.  *
  472.  ************************************************************************/
  473. void print_settings()
  474. {
  475.     char out[5];
  476.     
  477.     cprintf("SPUDclock settings \n\n");
  478.     cprintf("  The alarm will sound  ");
  479.     switch (alarm_mode) {
  480.         case QUARTER_HOUR :
  481.             cprintf("every QUARTER HOUR\n");
  482.             break;
  483.         case HALF_HOUR :
  484.             cprintf("every HALF HOUR\n");
  485.             break;
  486.         case HOUR :
  487.             cprintf("every HOUR\n");
  488.             break;
  489.     }
  490.     if (prestart)
  491.         cprintf("  The speakers WILL be prestarted\n");
  492.     else
  493.         cprintf("  The speakers WILL NOT be prestarted\n");
  494.     cprintf("  The clock will begin at ");      
  495.     itoa(out,start_alarm);
  496.     cprintf(out); cprintf("\n");
  497.     cprintf("  The clock will stop at ");    
  498.     itoa(out,end_alarm);
  499.     cprintf(out); cprintf("\n");
  500.     cprintf("  The alarm volume is ");
  501.     itoa(out,alarm_volume);
  502.     cprintf(out); cprintf("\n");
  503.     cprintf("  The alarm salutation is :\n");
  504.     cprintf("   ");
  505.     cprintf(salutation); cprintf("\n");
  506. }
  507.  
  508. /************************************************************************
  509.  *
  510.  *  Main section of SPUDclock...
  511.  *
  512.  *  This and all code sections were written by Robert E. Beaty and
  513.  *  H. Bret Young are Copyright (C) 1987 by H. Bret Young and R.E.Beaty
  514.  *  and The Man From S.P.U.D.
  515.  *
  516.  ************************************************************************/
  517. main( argc, argv )
  518. int argc;
  519. char *argv[];
  520. {
  521.     int i;
  522.     int change_flags,
  523.         changing,
  524.         listing;
  525.     /*
  526.      *
  527.      *  Set the defaults
  528.      *
  529.      */
  530.     alarm_mode = HALF_HOUR;             /* do it every 30 minutes */
  531.     prestart = FALSE;                   /* don't prestart the speakers */
  532.     start_alarm = 830;                  /* start at 8:30 am */
  533.     end_alarm = 2300;                   /* end at 11:00 pm */
  534.     alarm_volume = 50;                  /* not too loud */
  535.     stpcpy( salutation, " " );          /* no salutation to start off */
  536.     cp = salutation;                    /* this is for the argument processing */
  537.     quit_flag = FALSE;                  /* we aren't stopping yet */
  538.     change_flags = 0;
  539.     changing = FALSE;
  540.     listing = FALSE;
  541.     /*
  542.      *
  543.      *  Decode the arguments
  544.      *
  545.      */
  546.     for ( i=1; i < argc; i++ ) {
  547.         /* check the options */
  548.         if ( argv[i][0] == '-' ) {
  549.             /* decode the options */
  550.             switch( argv[i][1] ) {
  551.                 case 'f' :
  552.                     change_flags |= AM_BIT;
  553.                     alarm_mode = QUARTER_HOUR;
  554.                     break;
  555.                 case 't' :
  556.                     change_flags |= AM_BIT;
  557.                     alarm_mode = HALF_HOUR;
  558.                     break;
  559.                 case 'h' :
  560.                     change_flags |= AM_BIT;
  561.                     alarm_mode = HOUR;
  562.                     break;
  563.                 case 'q' :
  564.                     quit_flag = TRUE;
  565.                     break;
  566.                 case 'p' :
  567.                     change_flags |= PS_BIT;
  568.                     prestart = TRUE;
  569.                     break;
  570.                 case 's' :
  571.                     change_flags |= SA_BIT;
  572.                     i++;        /* move to the next argument, the time */
  573.                     start_alarm = 0;
  574.                     while((*argv[i] >= '0') && (*argv[i] <= '9'))
  575.                         start_alarm = (start_alarm * 10) + *argv[i]++ - '0';
  576.                     break;
  577.                 case 'e' :
  578.                     change_flags |= EA_BIT;
  579.                     i++;        /* move to the next argument, the time */
  580.                     end_alarm = 0;
  581.                     while((*argv[i] >= '0') && (*argv[i] <= '9'))
  582.                         end_alarm = (end_alarm * 10) + *argv[i]++ - '0';
  583.                     break;
  584.                 case 'v' :
  585.                     change_flags |= AV_BIT;
  586.                     i++;        /* move to the next argument, the volume */
  587.                     alarm_volume = 0;
  588.                     while((*argv[i] >= '0') && (*argv[i] <= '9'))
  589.                         alarm_volume = (alarm_volume * 10) + *argv[i]++ - '0';
  590.                     break;
  591.                 case 'm' :
  592.                     change_flags |= S_BIT;
  593.                     /* read in the salutation a word at a time */
  594.                     for ( i=i; (argv[i+1][0] != '-') && (i < argc); i++ ) {
  595.                         cp = stpcpy( cp, argv[i+1] );
  596.                         cp = stpcpy( cp, " ");
  597.                     }    
  598.                     break;
  599.                 case 'l' :
  600.                     listing = TRUE;
  601.                     break;
  602.                 case 'd' :
  603.                     changing = TRUE;
  604.                     break;
  605.                 default :
  606.                     usage( LITTLE );    /* show him the small usage */
  607.                     exit( TRUE );
  608.                     break;
  609.             }   /* end of decoding the options */
  610.         }   /* end of checking the options */
  611.         else {
  612.             usage( BIG );       /* he needs lots of help */
  613.             exit( TRUE );
  614.         }
  615.     }   /* end of decoding the arguments */
  616.     /*
  617.      * 
  618.      *  O.K. all arguments are decoded, so let's see if one copy of
  619.      *  SPUDclock already exists 
  620.      *
  621.      */
  622.     /* Assume one does and do just a quick start */
  623.     if ( (error=init( QUICK_START )) != FALSE ) {
  624.         if ( error == CANT_OPEN_INTUITION ) {
  625.             cprintf( "Sorry, but I cannot open a copy of Intuition!\n" );
  626.             cprintf( "Please check your DEVS: directory or reboot.\n" );
  627.         }    /* end of printing the error message */
  628.         exit( error );
  629.     }   /* end of error checking for the initial start */
  630.     clockPort = (struct MsgPort *) FindPort( "SPUDclock" );
  631.     if ( clockPort != NULL ) {
  632.         /* Allocate the memory for the message to the other SPUDclock */
  633.         outgoing = (struct PacketMessage *) AllocMem( sizeof(struct PacketMessage), MEMF_PUBLIC );
  634.         if ( outgoing == NULL ) {
  635.             cprintf( "Sorry, There is not enough memory to send the message\n" );
  636.             cprintf( "to the running copy of SPUDclock. You will probably\n" );
  637.             cprintf( "have to re-boot the machine to change the running copy\n" );
  638.             cprintf( "of SPUDclock.\n" );
  639.             clean( QUICK_EXIT );
  640.             exit( TRUE );
  641.         }   /* end of error checking the message allocation */
  642.         /* Allocate the reply port for this message */
  643.         replyPort = (struct MsgPort *) CreatePort( "SPUDclock.reply.port", TASK_PRIORITY );
  644.         if ( replyPort == NULL ) {
  645.             cprintf( "Sorry, There are not enough free resources to send the\n" );
  646.             cprintf( "message to the running copy of SPUDclock. You will probably\n" );
  647.             cprintf( "have to re-boot the machine to change the running copy\n" );
  648.             cprintf( "of SPUDclock.\n" );
  649.             /* free everything up */
  650.             FreeMem( outgoing, sizeof(struct PacketMessage) );
  651.             clean( QUICK_EXIT );
  652.             exit( TRUE );
  653.         }   /* end of error checking for port creation */
  654.         /*
  655.          * Now set this message packet so that it will do the job
  656.          */
  657.         outgoing->packet_message.mn_Node.ln_Type = NT_MESSAGE;
  658.         outgoing->packet_message.mn_ReplyPort = replyPort;
  659.         outgoing->packet_message.mn_Length = sizeof( struct PacketMessage );
  660.         /* Get the status from the packet */
  661.         outgoing->alarm_mode = alarm_mode;
  662.         outgoing->prestart = prestart;
  663.         outgoing->start_alarm = start_alarm;
  664.         outgoing->end_alarm = end_alarm;
  665.         outgoing->alarm_volume = alarm_volume;
  666.         stpcpy( outgoing->salutation, salutation );
  667.         outgoing->quit_flag = quit_flag;
  668.         outgoing->change_flags = change_flags;
  669.         outgoing->changing = changing;
  670.         outgoing->listing = listing;
  671.         
  672.         /*
  673.          * Send it, wait for a reply, and then dispose of all of it
  674.          */
  675.         PutMsg( clockPort, outgoing );
  676.         WaitPort( replyPort );
  677.         /* free everything up */
  678.         DeletePort( replyPort );
  679.         FreeMem( outgoing, sizeof(struct PacketMessage) );
  680.         clean( QUICK_EXIT );
  681.         exit( TRUE );
  682.     }   /* end of passing arguments to the running SPUDclock */
  683.     /* Print a copyright notice */
  684.     cprintf( "SPUDclock v1.2 - Copyright 1987 by The Man From S.P.U.D.\n" );
  685.     
  686.     if (listing) print_settings();
  687.     /* If quitting was our only motive, then quit */
  688.     if ( quit_flag ) {
  689.         clean( QUICK_EXIT );
  690.         exit( FALSE );
  691.     }   /* end of quick quit */
  692.     /* We need to do a normal start */
  693.     if ( (error=init( NORMAL_START )) != FALSE ) {
  694.         /* decode the error */
  695.         switch ( error ) {
  696.             case CANT_OPEN_INTUITION :
  697.                 cprintf( "Sorry, but I cannot open a copy of Intuition!\n" );
  698.                 cprintf( "Please check your DEVS: directory or reboot.\n" );
  699.                 break;
  700.             case CANT_OPEN_TRANSLATOR :
  701.                 cprintf( "Sorry, but I cannot open a copy of the\n" );
  702.                 cprintf( "Translator device! Please check your DEVS:\n" );
  703.                 cprintf( "directory for the narrator.device file\n" );
  704.                 cprintf( "and/or reboot.\n" );
  705.                 break;
  706.             case CANT_OPEN_NARRATOR :
  707.                 cprintf( "Sorry, but I cannot open a copy of the\n" );
  708.                 cprintf( "Narrator device! Please check your DEVS:\n" );
  709.                 cprintf( "directory for the narrator.device file\n" );
  710.                 cprintf( "and/or reboot.\n" );
  711.                 break;
  712.             case CANT_OPEN_TIMER :
  713.                 cprintf( "Sorry, but I cannot open a copy of the\n" );
  714.                 cprintf( "Timer device! Please check your DEVS:\n" );
  715.                 cprintf( "directory and/or reboot.\n" );
  716.                 break;
  717.             case CREATE_PORT_PROBLEMS :
  718.                 cprintf( "Sorry, There are not enough free resources to open the\n" );
  719.                 cprintf( "message ports required. You will probably have to re-boot\n" );
  720.                 cprintf( "the machine to run SPUDclock.\n" );
  721.                 break;
  722.             case CREATE_IO_PROBLEMS :
  723.                 cprintf( "Sorry, There are not enough free resources to open the\n" );
  724.                 cprintf( "I/O ports required. You will probably have to re-boot\n" );
  725.                 cprintf( "the machine to run SPUDclock.\n" );
  726.                 break;
  727.             case TRANSLATOR_NOT_WORKING :
  728.                 cprintf( "Sorry, but the Translator device does not seem to be working\n" );
  729.                 cprintf( "at this time. The only suggestion is to re-boot the machine\n" );
  730.                 cprintf( "and/or get a fresh copy of narrator.device into DEVS:.\n" );
  731.                 break;
  732.             default :
  733.                 cprintf( "Sorry, but SPUDclock has returned an error.\n" );
  734.                 cprintf( "Please try running it again.\n" );
  735.                 break;
  736.         }   /* end of decoding the error and printing the error message */
  737.         exit( error );
  738.     }   /* end of error checking the start-up of the original copy */
  739.     /* Submit a little sleep */
  740.     bed_bye( LITTLE );
  741.     while( TRUE ) {
  742.         /*
  743.          *  Now wait until something wakes us up
  744.          */
  745.         signal = Wait( timer_signal | port_signal );
  746.         /*
  747.          *
  748.          * ... check the timer
  749.          *
  750.          */
  751.         if ( signal & timer_signal ) {
  752.             /* get the message out of the way */
  753.             (void) GetMsg( timerPort );
  754.             /* Get the time now */
  755.             DateStamp( &now );
  756.             /* Get the time into hours and minutes */
  757.             hours_24 = now.ds_Minute / 60;
  758.             hours_12 = ( now.ds_Minute / 60 ) % 12;
  759.             if ( hours_12 == 0 ) hours_12 = 12;         /* make it simple 12 hour */
  760.             minutes = now.ds_Minute % 60;
  761.             /*
  762.              *  See if we are synced up yet
  763.              */
  764.             if ( (minutes == 0) || (minutes == 15) || (minutes == 30) || (minutes == 45) ) {
  765.                 /* submit a nice long wake up call */
  766.                 bed_bye( BIG );
  767.                 /*
  768.                  *  Now see if we need to output this to the speakers
  769.                  */
  770.                 alarm_time = hours_24 * 100 + minutes;
  771.                 if ( (alarm_time >= start_alarm) && (alarm_time <= end_alarm) )
  772.                     speak_time( hours_12, minutes );
  773.             }   /* end of processing for synced up */
  774.             else {
  775.                 /* submit another wake up call soon */
  776.                 bed_bye( LITTLE );
  777.             }   /* end of processing for not synced up */
  778.         }   /* end of processing the timer signal */
  779.  
  780.         /*
  781.          *
  782.          * ... check the clock port 
  783.          *
  784.          */
  785.         if ( signal & port_signal ) {
  786.             /* Get the message */
  787.             incoming = (struct PacketMessage *) GetMsg( clockPort );
  788.             /* Get the status from the packet */
  789.             
  790.             changing = incoming->changing;
  791.             change_flags = incoming->change_flags;
  792.             listing = incoming->listing;
  793.             quit_flag = incoming->quit_flag;
  794.             switch (changing) {
  795.                 case FALSE :
  796.                     if (change_flags & AM_BIT)
  797.                         alarm_mode = incoming->alarm_mode;
  798.                     if (change_flags & PS_BIT)
  799.                         prestart = incoming->prestart;
  800.                     if (change_flags & SA_BIT)
  801.                         start_alarm = incoming->start_alarm;
  802.                     if (change_flags & EA_BIT)
  803.                         end_alarm = incoming->end_alarm;
  804.                     if (change_flags & AV_BIT)
  805.                         alarm_volume = incoming->alarm_volume;
  806.                     if (change_flags & S_BIT)
  807.                         stpcpy( salutation, incoming->salutation );
  808.                     break;
  809.                 case TRUE :
  810.                     alarm_mode = incoming->alarm_mode;
  811.                     prestart = incoming->prestart;
  812.                     start_alarm = incoming->start_alarm;
  813.                     end_alarm = incoming->end_alarm;
  814.                     alarm_volume = incoming->alarm_volume;
  815.                     stpcpy( salutation, incoming->salutation );
  816.                     break;
  817.             }
  818.             if (listing) print_settings();
  819.             /* since we didn't allocate this message, we must reply */
  820.             ReplyMsg( incoming );
  821.             
  822.             /*
  823.              * If the quit flag is set then we need to leave
  824.              */
  825.             if ( quit_flag ) {
  826.                 clean( NORMAL_EXIT );   /* clean all this up */
  827.                 exit( FALSE );
  828.             }   /* end of quitting */
  829.         }   /* end of processing the port signal */
  830.     }   /* end of main loop */    
  831.     /* we need this to keep the compiler happy */
  832.     return( FALSE );
  833. }   /* end of SPUDclock(); */
  834.