home *** CD-ROM | disk | FTP | other *** search
/ Carousel / CAROUSEL.cdr / mactosh / code / c_macula.sit < prev    next >
Text File  |  1988-06-20  |  10KB  |  496 lines

  1. 18-Jun-88 14:51:15-MDT,10295;000000000000
  2. Return-Path: <u-lchoqu%sunset@cs.utah.edu>
  3. Received: from cs.utah.edu by SIMTEL20.ARPA with TCP; Sat, 18 Jun 88 14:51:02 MDT
  4. Received: by cs.utah.edu (5.54/utah-2.0-cs)
  5.     id AA22805; Sat, 18 Jun 88 14:51:02 MDT
  6. Received: by sunset.utah.edu (5.54/utah-2.0-leaf)
  7.     id AA24880; Sat, 18 Jun 88 14:50:59 MDT
  8. Date: Sat, 18 Jun 88 14:50:59 MDT
  9. From: u-lchoqu%sunset@cs.utah.edu (Lee Choquette)
  10. Message-Id: <8806182050.AA24880@sunset.utah.edu>
  11. To: rthum@simtel20.arpa
  12. Subject: macula.c
  13.  
  14. /*
  15.  * Macula:
  16.  *
  17.  *  A Megamax C (we used version 2.1) program to read and speak a
  18.  *   file of TEXT messages.  For a good time, make up a file of
  19.  *   phrases, attach a speaker to your Macintosh, and hide it outside
  20.  *   your door on Halloween night.  (Hide the speaker, not the Mac!)
  21.  *
  22.  *  The system-file "Macintalk" will need to be present; if in doubt,
  23.  *   put it into the same folder as Macula.
  24.  *  Upon startup, pick a TEXT file of phrases.
  25.  *  Change the pitch, rate, etc. by menu choices.
  26.  *  The robotic/natural speech choice is non-functional because the
  27.  *   Macintalk documentation didn't tell us what values to plug in
  28.  *   to effect the change.
  29.  *
  30.  *  By Neil Groundwater and Mike O'Dell
  31.  */
  32.  
  33. #include <event.h>
  34. #include <pack.h>
  35. #include <menu.h>
  36. #include <win.h>
  37. #include <mem.h>
  38. #include <qdvars.h>
  39. #include <misc.h>
  40. #include <stdio.h>
  41.  
  42. #define MAXPHRASES    500
  43. #define MAXPHLENGTH    2048
  44.  
  45. #define ABOUT        1
  46. #define REREAD        1
  47. #define QUIT        3
  48.     
  49. MenuHandle            menus[5];
  50. #define APPLE_ID    200
  51. #define FILE_ID        201
  52. #define DELAY_ID    202
  53. #define PITCH_ID    203
  54. #define RATE_ID        204
  55.  
  56. short repeat_rate;
  57. short doneFlag = 0;
  58. short duration = 1;
  59.  
  60. Handle thespeech = NULL;        /* Handle to speech subsystem */
  61. Handle phonemes = NULL;         /* output Handle used for the Reader() */
  62.  
  63. char *phrases[MAXPHRASES];
  64. int phrasecount = 0;
  65.  
  66. SFReply infile;
  67. FILE *input;
  68.  
  69. #define TICKS    6L    /* 1/10 second */
  70.  
  71.  
  72. main()
  73. {
  74.     int i, previous = -1;
  75.     long now;
  76.     extern char *slurpline();
  77.     extern int rand();
  78.  
  79.     InitSys();
  80.  
  81.     _autowin("Son of Macula");
  82.     fflush(stdout);
  83.  
  84.     srand(now);                    /* randomize the seed */
  85.  
  86.     if (speakinit() == -1) {
  87.         printf("speechinit() failed; exiting\n");
  88.         ExitToShell();
  89.     }
  90.  
  91.     loadtext();
  92.  
  93.     while (!doneFlag) {
  94.         i = pickone();
  95.         /* don't repeat immediately */
  96.         if (i == previous)
  97.             continue;
  98.         previous = i;
  99.  
  100.         output(i);
  101.  
  102.         if (repeat_rate)
  103.             duration = repeat_rate * TICKS;
  104.         else
  105.             duration = randrange(5*TICKS, 20*TICKS);
  106.  
  107.         for (i = 0; i < duration; i++) {
  108.             Delay(10L, &now);
  109.             SystemTask();
  110.             EventTask();
  111.         }
  112.     }
  113.  
  114.     speakuninit();
  115.     ExitToShell();
  116. }
  117.  
  118. InitSys()
  119. {
  120.     char s1[5];
  121.  
  122.     InitGraf(&thePort);
  123.     InitFonts();
  124.     InitWindows();
  125.     InitDialogs(NULL);
  126.     InitCursor();
  127.     InitMenus();
  128.  
  129.     s1[0] = 20;
  130.     s1[1] = 0;
  131.     menus[0] = NewMenu(APPLE_ID, s1);
  132.     AppendMenu(menus[0],"About Macula...");
  133.     /* AddResMenu(menus[0], "DRVR"); */
  134.     InsertMenu(menus[0], APPLE_ID);
  135.  
  136.     menus[1] = NewMenu(FILE_ID, "File");
  137.     AppendMenu(menus[1], "Reread Phrases/R;(-;Quit/Q");
  138.     InsertMenu(menus[1],FILE_ID);
  139.  
  140.     repeat_rate = 3;
  141.     menus[2] = NewMenu(DELAY_ID, "Delay");
  142.     AppendMenu(menus[2], "Random;(-;1 sec;5 secs;10 secs;15 secs");
  143.     InsertMenu(menus[2],DELAY_ID);
  144.     CheckItem(menus[2],3,TRUE);
  145.  
  146.     menus[3] = NewMenu(PITCH_ID, "Pitch");
  147.     AppendMenu(menus[3],
  148.         "Natural;Robotic;(-;Very High;High;Medium;Low");
  149.     InsertMenu(menus[3],PITCH_ID);
  150.     CheckItem(menus[3],1,TRUE);
  151.     CheckItem(menus[3],6,TRUE);
  152.  
  153.     menus[4] = NewMenu(RATE_ID, "Rate");
  154.     AppendMenu(menus[4], "Very Fast;Fast;Medium;Slow;Very Slow");
  155.     InsertMenu(menus[4],RATE_ID);
  156.     CheckItem(menus[4],4,TRUE);
  157.  
  158.     DrawMenuBar();
  159.     FlushEvents(everyEvent, 0);
  160. }
  161.  
  162. EventTask()
  163. {
  164.     EventRecord event;
  165.     char c;
  166.     short windowcode;
  167.     WindowPtr mouseWindow;
  168.     
  169.     if (GetNextEvent(everyEvent, &event))
  170.         switch (event.what) {
  171.         case autoKey:
  172.         case keyDown:
  173.             c = (char) event.message;
  174.             if ((event.modifiers & cmdKey))
  175.                 HandleMenu(MenuKey(c));
  176.             break;
  177.  
  178.         case mouseDown:
  179.             windowcode = FindWindow(&event.where, &mouseWindow);
  180.  
  181.             switch (windowcode) {
  182.             case inMenuBar:
  183.                 HandleMenu(MenuSelect(&event.where));
  184.                 break;
  185.             case inSysWindow:
  186.                 SystemClick(&event, mouseWindow);
  187.                 break;
  188.             }
  189.         }      
  190. }
  191.  
  192. HandleMenu(menuID, itemNumber)
  193.     int menuID, itemNumber;
  194. {
  195.     char result;
  196.     extern Handle thespeech;
  197.     short i;
  198.  
  199.     switch (menuID) {
  200.     case APPLE_ID:
  201.         if (itemNumber == ABOUT)
  202.             DoAbout();
  203.         else {
  204.             struct P_Str AccessoryName;
  205.             GetItem(menus[0], itemNumber, &AccessoryName);
  206.             OpenDeskAcc(&AccessoryName);
  207.             DrawMenuBar();
  208.         }
  209.         break;
  210.     case FILE_ID:
  211.         switch (itemNumber) {
  212.         case REREAD:    
  213.             rereadtext();
  214.             break;
  215.         case QUIT:    
  216.             doneFlag = 1;
  217.         }
  218.         break;
  219.     case DELAY_ID:
  220.         for (i=1; i<=6; i++)
  221.             CheckItem(menus[2],i,FALSE);
  222.         switch (itemNumber) {
  223.         case 1: repeat_rate = 0;  CheckItem(menus[2],1,TRUE);  break;
  224.         case 2: break;
  225.         case 3: repeat_rate = 1;  CheckItem(menus[2],3,TRUE);  break;
  226.         case 4: repeat_rate = 5;  CheckItem(menus[2],4,TRUE);  break;
  227.         case 5: repeat_rate = 10; CheckItem(menus[2],5,TRUE);  break;
  228.         case 6: repeat_rate = 15; CheckItem(menus[2],6,TRUE);  break;
  229.  
  230.         }
  231.         break;
  232.     case PITCH_ID:
  233.         if (itemNumber > 3)
  234.             for (i=4; i<=7; i++)
  235.                 CheckItem(menus[3],i,FALSE);
  236.         switch (itemNumber) {
  237.         case 1:
  238.             /* I can't figure out the values for natural/robotic mode */
  239.             SpeechPitch(thespeech, 0, 1);
  240.             CheckItem(menus[3],1,TRUE);   CheckItem(menus[3],2,FALSE);
  241.             break;
  242.         case 2:    
  243.             SpeechPitch(thespeech, 0, 0);
  244.             CheckItem(menus[3],1,FALSE);  CheckItem(menus[3],2,TRUE);
  245.             break;
  246.         case 3:
  247.             break;
  248.         case 4:
  249.             SpeechPitch(thespeech, 300, 0); CheckItem(menus[3],4,TRUE); break;
  250.         case 5:
  251.             SpeechPitch(thespeech, 180, 0); CheckItem(menus[3],5,TRUE); break;
  252.         case 6:
  253.             SpeechPitch(thespeech, 95, 0);  CheckItem(menus[3],6,TRUE); break;
  254.         case 7:
  255.             SpeechPitch(thespeech, 70, 0);  CheckItem(menus[3],7,TRUE); break;
  256.         }
  257.         duration = 0; /* break out of delay loop */
  258.         break;
  259.     case RATE_ID:
  260.         for (i=1; i<=5; i++)
  261.             CheckItem(menus[4],i,FALSE);
  262.         switch (itemNumber) {
  263.         case 1: SpeechRate(thespeech, 240); CheckItem(menus[4],1,TRUE); break;
  264.         case 2: SpeechRate(thespeech, 180); CheckItem(menus[4],2,TRUE); break;
  265.         case 3: SpeechRate(thespeech, 150); CheckItem(menus[4],3,TRUE); break;
  266.         case 4: SpeechRate(thespeech, 120); CheckItem(menus[4],4,TRUE); break;
  267.         case 5: SpeechRate(thespeech, 88);  CheckItem(menus[4],5,TRUE); break;
  268.         }
  269.     }
  270.  
  271.     if ((menuID >= APPLE_ID) && (menuID <= RATE_ID))
  272.         duration = 0; /* break out of delay loop */
  273.  
  274.     HiliteMenu(0);
  275. }
  276.  
  277. DoAbout()
  278. {
  279.     WindowPtr aboutWindow;
  280.     Rect rectAbout;
  281.  
  282.     SetRect(&rectAbout,80,100,430,160);
  283.     aboutWindow = NewWindow(0L,&rectAbout,"",TRUE,DBoxProc,0L,0L);
  284.     SetPort(aboutWindow);
  285.     TextFont(systemFont);
  286.     MoveTo(20,20);
  287.     DrawString("Macula - by Neil Groundwater and Mike O'Dell");
  288.     MoveTo(120,44);
  289.     DrawString("Happy Halloween!");
  290.     while(!Button());
  291.     while(Button());
  292.     DisposeWindow(aboutWindow);
  293. }
  294.  
  295.  
  296. /*
  297.  * loadtext(file) char *file;
  298.  * Load the text 
  299.  * and construct the headers
  300.  */
  301.  
  302. loadtext(file)
  303. char *file;
  304. {
  305.     Point wh;
  306.  
  307.     wh.a.v = 70;
  308.     wh.a.h = 70;
  309.  
  310.     do {
  311.         SFGetFile (&wh, NULL, NULL, 1, "TEXT", NULL, &infile);
  312.         if (infile.good == FALSE)
  313.             exit();
  314.     } while (!(input = fopen(&infile.fName, "r")));
  315.  
  316.     readtext();
  317. }
  318.  
  319. readtext()
  320. {
  321.     char *slurpline();
  322.  
  323.     for (phrasecount = 0; phrasecount < MAXPHRASES; phrasecount++)
  324.         if ((phrases[phrasecount] = slurpline(input)) == NULL)
  325.             break;
  326.     fclose(input);
  327. /*
  328.     printf("Read %d phrases from the sayings file\n", phrasecount);
  329.     fflush(stdout);
  330.  */
  331.     if (phrasecount <= 0) {
  332.         printf("loadtext() failed\n");
  333.         fflush(stdout);
  334.         ExitToShell();
  335.     }
  336. }
  337.  
  338. rereadtext()
  339. {
  340.     int i;
  341.  
  342.     for (i = 0; i < phrasecount; i++)
  343.         free(phrases[i]);
  344.     input = fopen(&infile.fName, "r");
  345.     readtext();
  346. }
  347.  
  348. char *slurpline(in)
  349. FILE *in;
  350. {
  351.     char *p;
  352.     int c, i;
  353.     char buf[MAXPHLENGTH+2];
  354.     char *malloc();
  355.     
  356.     for (i = 0, p = buf; i < MAXPHLENGTH; i++, p++) {
  357.         if ((c = fgetc(in)) == EOF) {
  358.             return(NULL);
  359.         }
  360.         if (c == '\n')
  361.             break;
  362.         else
  363.             *p = c;
  364.     }
  365.     *p = '\0';
  366.     i++;
  367.  
  368.     if ((p = malloc(i)) == NULL) {
  369.         printf("slurpline: malloc failed for i = %d\n", i);
  370.         return(NULL);
  371.     }
  372.  
  373.     strcpy(p, buf);
  374.     return(p);
  375. }
  376.  
  377. output(which)
  378. int which;
  379. {
  380. /*
  381.     printf("[%d] %s\n", which, phrases[which]);
  382.     fflush(stdout);
  383.  */
  384.     
  385.     speakit(phrases[which]);
  386. }
  387.  
  388. int posrand()
  389. {
  390.     int rand();
  391.     int foo;
  392.  
  393.     if ((foo = (rand() * rand())) < 0) {
  394.         return (-foo);
  395.     } else {
  396.         return(foo);
  397.     }
  398. }
  399.  
  400. /*
  401.  * pick a number from [0..linecount]
  402.  */
  403.  
  404. int pickone()
  405. {
  406.     return (randrange(0, phrasecount));
  407. }
  408.  
  409. /*
  410.  * return positive random int from [lo..hi]
  411.  */
  412.  
  413. randrange(lo, hi)
  414. int lo;
  415. int hi;
  416. {
  417.     int val;
  418.     
  419.     for (val = posrand() % (hi+1);
  420.         val < lo || val > hi;
  421.         val = posrand() % (hi+1));
  422.     
  423.     return(val);
  424. }
  425.  
  426.  
  427. /*
  428.  * say in (english) char *english;
  429.  * output the english string via the MacInTalk Reader()
  430.  */
  431.  
  432. speakit(english)
  433. char *english;
  434. {
  435.     int i;
  436.     
  437.     i = Reader(thespeech, english, (long)(strlen(english)), phonemes);
  438.     if (i != 0) {
  439.         printf("reader error %d processing\n\"%s\"\n", i, english);
  440.         fflush(stdout);
  441.         return(-1);
  442.     }
  443.  
  444.     i = MacinTalk(thespeech, phonemes);
  445.     if (i != 0) {
  446.         printf("macintalk error %d.  English was\n\"%s\"\n", i, english);
  447.         return(-1);
  448.     }
  449.     
  450.     SetHandleSize(phonemes, 0L);        /* scrap old phoneme data */
  451.     CompactMem(20000L);                    /* force a compaction */
  452.     
  453.     return(0);
  454.     
  455. }
  456.  
  457. /*
  458.  * speakinit()
  459.  * Initialize the MacInTalk speech subsystem
  460.  *
  461.  * Returns -1 if initialization fails
  462.  */
  463.  
  464. speakinit()
  465. {
  466.     int i;
  467.     
  468.     i = SpeechOn("", &thespeech);    /* initialize the speach system */
  469.     if (i != 0) {
  470.         printf("Initializing MacInTalk got %d\n", i);
  471.         return(-1);
  472.     }
  473.  
  474.     SpeechRate(thespeech, 120);
  475.  
  476.     phonemes = NewHandle(0L);            /* an empty Handle */
  477.     
  478.     return(0);
  479. }
  480.  
  481. /*
  482.  * speakuninit()
  483.  * Shut down the speech subsystem, release resources, dispose handles...
  484.  */
  485.  
  486. speakuninit()
  487. {
  488.     if (thespeech != NULL) {
  489.         SpeechOff(thespeech);
  490.     }
  491.     
  492.     if (phonemes != NULL) {
  493.         DisposHandle(phonemes);
  494.     }
  495. }
  496.