home *** CD-ROM | disk | FTP | other *** search
/ Gold Fish 2 / goldfish_vol2_cd1.bin / files / util / cdity / speaktimecx / speaktime_cx.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-04-19  |  13.0 KB  |  441 lines

  1. /*
  2.  * SpeakTime_Cx.c - Commodity version 1.2 of SpeakTime.c
  3.  *
  4.  * Copyright (c) 1994  Gary Walker.
  5.  *
  6.  * This program sends a string of phonetic text to the narrator
  7.  * device to tell the local system time.
  8.  *
  9.  * Requires Kickstart V37 or greater.
  10.  */
  11.  
  12. #include <exec/types.h>
  13. #include <exec/exec.h>
  14. #include <exec/libraries.h>
  15. #include <dos/dos.h>
  16. #include <devices/narrator.h>
  17. #include <libraries/commodities.h>
  18. #include "clib/translator_protos.h"
  19. #include <clib/exec_protos.h>
  20. #include <clib/alib_protos.h>
  21. #include <clib/dos_protos.h>
  22. #include <clib/alib_stdio_protos.h>
  23. #include <clib/commodities_protos.h>
  24. #include <string.h>
  25. #include "stdlib.h"
  26. #include <time.h>
  27. #include "SpeakTime_Cx_protos.h"
  28.  
  29. #ifdef LATTICE
  30. int CXBRK(void) { return(0); }    /* Disable SAS CTRL/C handling */
  31. int chkabort(void) { return(0); } /* really */
  32. #endif
  33.  
  34. extern struct Library *SysBase;   /* Used to check the OS version number */
  35.  
  36. #define EVT_HOTKEY 1L
  37. #define BUFLEN 500
  38. UBYTE PhonBuffer[BUFLEN];
  39. STRPTR hourmin;
  40. char sentence[100];
  41. char numbers[7];
  42.  
  43. void main(int, char **);
  44. void ProcessMsg(void);
  45.  
  46. struct Library *CxBase, *IconBase, *TranslatorBase;
  47. struct MsgPort *broker_mp;
  48. CxObj *broker, *filter, *sender, *translate;
  49.  
  50. struct NewBroker newbroker = {
  51.     NB_VERSION,
  52.     "SpeakTime HotKey",           /* string to identify this broker */
  53.     "A Simple HotKey",
  54.     "A simple hot key commodity",
  55.     NBU_UNIQUE | NBU_NOTIFY,    /* Don't want any new commodities starting with this name. */
  56.     0, 0, 0, 0                  /* If someone tries it, let me know */
  57. };
  58.  
  59. ULONG cxsigflag;
  60.  
  61. void main(int argc, char **argv)
  62. {
  63.     UBYTE *hotkey, **ttypes;
  64.     CxMsg *msg;
  65.  
  66.    /* Check the version number of the operating system */
  67. if(SysBase->lib_Version>=36)
  68.    {
  69.     if (CxBase = OpenLibrary("commodities.library", 37L))
  70.     {
  71.         /* open the icon.library for the support library */
  72.         /* functions, ArgArrayInit() and ArgArrayDone()  */
  73.         if (IconBase = OpenLibrary("icon.library", 36L))
  74.         {
  75.             if (broker_mp = CreateMsgPort())
  76.             {
  77.                 newbroker.nb_Port = broker_mp;
  78.                 cxsigflag = 1L << broker_mp->mp_SigBit;
  79.  
  80.                 /* ArgArrayInit() is a support library function (from the 2.0 version
  81.                  * of amiga.lib) that makes it easy to read arguments from either a
  82.                  * CLI or from Workbench's ToolTypes.  Because it uses icon.library,
  83.                  * the library has to be open before calling this function.
  84.                  * ArgArrayDone() cleans up after this function.
  85.                  */
  86.                 ttypes = ArgArrayInit(argc, argv);
  87.  
  88.                 /* ArgInt() (also from amiga.lib) searches through the array set up
  89.                  * by ArgArrayInit() for a specific ToolType.  If it finds one, it
  90.                  * returns the numeric value of the number that followed the
  91.                  * ToolType (i.e., CX_PRIORITY=7). If it doesn't find the ToolType,
  92.                  * it returns the default value (the third argument)
  93.                  */
  94.                 newbroker.nb_Pri = (BYTE)ArgInt(ttypes, "CX_PRIORITY", 0);
  95.  
  96.                 /* ArgString() works just like ArgInt(), except it returns a pointer to a string
  97.                  * rather than an integer. In the example below, if there is no ToolType
  98.                  * "HOTKEY", the function returns a pointer to "rawkey control esc".
  99.                  */
  100.                 hotkey = ArgString(ttypes, "HOTKEY", "rawkey alt z");
  101.  
  102.                 if (broker = CxBroker(&newbroker, NULL))
  103.                 {
  104.                     /* CxFilter() is a macro that creates a filter CxObject.  This filter
  105.                      * passes input events that match the string pointed to by hotkey.
  106.                      */
  107.                     if (filter = CxFilter(hotkey))
  108.                     {
  109.                         /* Add a CxObject to another's personal list */
  110.                         AttachCxObj(broker, filter);
  111.  
  112.                         /* CxSender() creates a sender CxObject.  Every time a sender gets
  113.                          * a CxMessage, it sends a new CxMessage to the port pointed to in
  114.                          * the first argument. CxSender()'s second argument will be the ID
  115.                          * of any CxMessages the sender sends to the port.  The data pointer
  116.                          * associated with the CxMessage will point to a *COPY* of the
  117.                          * InputEvent structure associated with the orginal CxMessage.
  118.                          */
  119.                         if (sender = CxSender(broker_mp, EVT_HOTKEY))
  120.                         {
  121.                             AttachCxObj(filter, sender);
  122.  
  123.                             /* CxTranslate() creates a translate CxObject. When a translate
  124.                              * CxObject gets a CxMessage, it deletes the original CxMessage
  125.                              * and adds a new input event to the input.device's input stream
  126.                              * after the Commodities input handler. CxTranslate's argument
  127.                              * points to an InputEvent structure from which to create the new
  128.                              * input event.  In this example, the pointer is NULL, meaning no
  129.                              * new event should be introduced, which causes any event that
  130.                              * reaches this object to disappear from the input stream.
  131.                              */
  132.                             if (translate = (CxTranslate(NULL)))
  133.                             {
  134.                                 AttachCxObj(filter, translate);
  135.  
  136.                                 /* CxObjError() is a commodities.library function that returns
  137.                                  * the internal accumulated error code of a CxObject.
  138.                                  */
  139.                                 if (! CxObjError(filter))
  140.                                 {
  141.                                     ActivateCxObj(broker, 1L);
  142.                                     ProcessMsg();
  143.                                 }
  144.                             }
  145.                         }
  146.                     }
  147.  
  148.     }
  149.  
  150.                     /* DeleteCxObjAll() is a commodities.library function that not only
  151.                      * deletes the CxObject pointed to in its argument, but it deletes
  152.                      * all of the CxObjects that are attached to it.
  153.                      */
  154.                     DeleteCxObjAll(broker);
  155.  
  156.                     /* Empty the port of all CxMsgs */
  157.                     while(msg = (CxMsg *)GetMsg(broker_mp))
  158.                         ReplyMsg((struct Message *)msg);
  159.                 }
  160.                 DeletePort(broker_mp);
  161.             }
  162.             /* this amiga.lib function cleans up after ArgArrayInit() */
  163.             ArgArrayDone();
  164.             CloseLibrary(IconBase);
  165.         }
  166.         CloseLibrary(CxBase);
  167.    }
  168. else
  169.    printf("Error: Release 2 (V36) or a later version of the OS required.\n");
  170. }
  171.  
  172. void Sayit()
  173. {
  174.     struct  MsgPort     *VoiceMP;
  175.     struct  narrator_rb *VoiceIO;
  176.     BYTE    audio_chan[4]   = {3, 5, 10, 12};
  177.  
  178.     ThisTime();
  179.     Phoneme();
  180.  
  181.       /* Create the message port */
  182.    if (VoiceMP=CreateMsgPort())
  183.       {
  184.          /* Create the IORequest */
  185.       if (VoiceIO = CreateIORequest(VoiceMP,sizeof(struct narrator_rb)))
  186.          {
  187.          /*   Set the NEWIORB bit in the flags field to use the new fields */
  188.          VoiceIO->flags = NDF_NEWIORB;
  189.  
  190.             /* Open the narrator device */
  191.          if (OpenDevice("narrator.device",0,(struct IORequest *)VoiceIO,0L))
  192.  
  193.             /* Inform user that it could not be opened */
  194.             printf("Error: narrator.device did not open\n");
  195.  
  196.          else
  197.             {
  198.              /* Speak the string using the default parameters */
  199.              VoiceIO->ch_masks = &audio_chan[0];
  200.              VoiceIO->nm_masks = sizeof(audio_chan);
  201.              VoiceIO->message.io_Command = CMD_WRITE;
  202.              VoiceIO->message.io_Data = PhonBuffer;
  203.              VoiceIO->message.io_Length = strlen(PhonBuffer);
  204.              DoIO((struct IORequest *)VoiceIO);
  205.  
  206.  
  207.             /* Close the narrator device */
  208.             CloseDevice((struct IORequest *)VoiceIO);
  209.             }
  210.          /* Delete the IORequest */
  211.          DeleteIORequest(VoiceIO);
  212.          }
  213.       else
  214.          /* Inform user that the IORequest could be created */
  215.          printf("Error: Could not create IORequest\n");
  216.  
  217.       /* Delete the message port */
  218.       DeleteMsgPort(VoiceMP);
  219.       }
  220.    else
  221.       /* Inform user that the message port could not be created */
  222.       printf("Error: Could not create message port\n");
  223. }
  224.  
  225. void ProcessMsg(void)
  226. {
  227.     extern struct MsgPort *broker_mp;
  228.     extern CxObj *broker;
  229.     extern ULONG cxsigflag;
  230.     CxMsg *msg;
  231.     ULONG sigrcvd, msgid, msgtype;
  232.     LONG returnvalue = 1L;
  233.  
  234.     while(returnvalue)
  235.     {
  236.         sigrcvd = Wait(cxsigflag);
  237.  
  238.         while(msg = (CxMsg *)GetMsg(broker_mp))
  239.         {
  240.             msgid = CxMsgID(msg);
  241.             msgtype = CxMsgType(msg);
  242.             ReplyMsg((struct Message *)msg);
  243.  
  244.             switch(msgtype)
  245.             {
  246.                 case CXM_IEVENT:
  247.                     switch(msgid)
  248.                     {
  249.                         case EVT_HOTKEY: /* We got the message from the sender CxObject */
  250.                 Sayit();
  251.                             break;
  252.                         default:
  253.                             break;
  254.                     }
  255.                     break;
  256.                 case CXM_COMMAND:
  257.                     switch(msgid)
  258.                     {
  259.                         case CXCMD_UNIQUE:
  260.                         /* Commodities Exchange can be told not only to refuse to launch a
  261.                          * commodity with a name already in use but also can notify the
  262.                          * already running commodity that it happened. It does this by
  263.                          * sending a CXM_COMMAND with the ID set to CXMCMD_UNIQUE.  If the
  264.                          * user tries to run a windowless commodity that is already running,
  265.                          * the user wants the commodity to shut down. */
  266.                             returnvalue = 0L;
  267.                             break;
  268.                         default:
  269.                             break;
  270.                     }
  271.                     break;
  272.                 default:
  273.                     break;
  274.             }
  275.         }
  276.     }
  277. }
  278.  
  279. Phoneme()
  280. {
  281.     LONG EnglLen;
  282.     LONG rtnCode;
  283.  
  284.     TranslatorBase = OpenLibrary("translator.library",37);
  285.     if (TranslatorBase == NULL)
  286.         {
  287.         printf("No Translator Library available.\n");
  288.         exit(0);
  289.         }
  290.     Makeword();
  291.     EnglLen = strlen(sentence);
  292.     rtnCode = Translate(sentence, EnglLen, (STRPTR)&PhonBuffer[0], BUFLEN);
  293.  
  294.     CloseLibrary(TranslatorBase);
  295.     return(rtnCode);
  296. }
  297. STRPTR ThisTime()
  298. {
  299.     struct tm *p;
  300.     long t;
  301.  
  302.     time(&t);
  303.     p = localtime(&t);
  304.     hourmin = asctime(p);
  305.     return(hourmin);
  306. }
  307. void Makeword()
  308. {
  309.     int i,m,n,hourflag,ampm, pmdigits;
  310.  
  311.     for(i=0;i<=6;++i)
  312.         { numbers[i] = hourmin[i+11];
  313.         }
  314.     numbers[6] = NULL;
  315.     strcpy(sentence, "Local time is ");
  316.     m = numbers[0]-48;
  317.     n = numbers[1]-48;
  318.     hourflag = 1;
  319.     ampm = 0;
  320.     pmdigits = (m*10)+n;
  321.     if (pmdigits>11) 
  322.             { ampm = 1;
  323.             pmdigits=pmdigits-12;
  324.             if (pmdigits==0) pmdigits=12;
  325.             if (pmdigits>9)
  326.                 {
  327.                 n=pmdigits % 10;
  328.                 m=1;
  329.                 }
  330.             else {
  331.                 m=0;
  332.                 n=pmdigits;
  333.                  }
  334.             }
  335.     testdigit(m,n,ampm,hourflag);
  336.     m = numbers[3]-48;
  337.     n = numbers[4]-48;
  338.     hourflag = 0;
  339.     testdigit(m,n,ampm,hourflag);
  340. }
  341. void testdigit(m,n,ampm,hourflag)
  342. {
  343.     char *texts[]=
  344.     {
  345.     "ten", "alevehn", "twelve", "thir", "fif", "teeen", "twenty", "thirty", "forty", "fifty", "ayh m", "p m,"
  346.     };
  347.     char *nums[]= { "o", "1", "2", "3", "4", "5", "6", "7", "8", "9", ":", "00" };
  348.  
  349.     switch (m)
  350.         {
  351.     case 0:
  352.         switch (n)
  353.         {
  354.         case 0:
  355.             if (!hourflag) 
  356.                 {
  357.                 strcat(sentence, nums[11]);
  358.                 break;
  359.                 }
  360.             if (ampm) break;
  361.             strcat(sentence, texts[2]);
  362.             break;
  363.         default:
  364.             if (!hourflag) strcat(sentence, nums[0]);
  365.             strcat(sentence, nums[n]);
  366.             break;
  367.         }
  368.         break;
  369.     case 1:
  370.         switch (n)
  371.         {
  372.         case 0:
  373.             strcat(sentence, texts[0]);
  374.             break;
  375.         case 1:
  376.             strcat(sentence, texts[1]);
  377.             break;
  378.         case 2:
  379.             strcat(sentence, texts[2]);
  380.             break;
  381.         case 3:
  382.             strcat(sentence, texts[3]);
  383.             strcat(sentence, texts[5]);
  384.             break;
  385.         case 4:
  386.             strcat(sentence, nums[4]);
  387.             strcat(sentence, texts[5]);
  388.             break;
  389.         case 5:
  390.             strcat(sentence, texts[4]);
  391.             strcat(sentence, texts[5]);
  392.             break;
  393.         case 6:
  394.             strcat(sentence, nums[6]);
  395.             strcat(sentence, texts[5]);
  396.             break;
  397.         case 7:
  398.             strcat(sentence, nums[7]);
  399.             strcat(sentence, texts[5]);
  400.             break;
  401.         case 8:
  402.             strcat(sentence, nums[8]);
  403.             strcat(sentence, texts[5]);
  404.             break;
  405.         case 9:
  406.             strcat(sentence, nums[9]);
  407.             strcat(sentence, texts[5]);
  408.             break;
  409.         }
  410.         break;
  411.     case 2:
  412.         strcat(sentence, texts[6]);
  413.         if (n) strcat(sentence, nums[n]);
  414.         break;
  415.     case 3:
  416.         strcat(sentence, texts[7]);
  417.         if (n) strcat(sentence, nums[n]);
  418.         break;
  419.     case 4:
  420.         strcat(sentence, texts[8]);
  421.         if (n) strcat(sentence, nums[n]);
  422.         break;
  423.     case 5:
  424.         strcat(sentence, texts[9]);
  425.         if (n) strcat(sentence, nums[n]);
  426.         break;
  427.         }
  428.     strcat(sentence, nums[10]);
  429.     if (!ampm && !hourflag)  
  430.         {
  431.         strcat(sentence, texts[10]);
  432.         strcat(sentence, nums[10]);
  433.         }
  434.     else if (!hourflag)
  435.         {
  436.         strcat(sentence, texts[11]);
  437.         strcat(sentence, nums[10]);
  438.         }
  439.  
  440. }
  441.