home *** CD-ROM | disk | FTP | other *** search
/ World of A1200 / World_Of_A1200.iso / datafiles / text / c_manual / devices / narratordevice / example6.c < prev    next >
C/C++ Source or Header  |  1995-02-27  |  13KB  |  462 lines

  1. /***********************************************************/
  2. /*                                                         */
  3. /* Amiga C Encyclopedia (ACE) V3.0      Amiga C Club (ACC) */
  4. /* -------------------------------      ------------------ */
  5. /*                                                         */
  6. /* Book:    ACM Devices                 Amiga C Club       */
  7. /* Chapter: Narrator Device             Tulevagen 22       */
  8. /* File:    Example6.c                  181 41  LIDINGO    */
  9. /* Author:  Anders Bjerin               SWEDEN             */
  10. /* Date:    92-04-26                                       */
  11. /* Version: 1.00                                           */
  12. /*                                                         */
  13. /*   Copyright 1992, Anders Bjerin - Amiga C Club (ACC)    */
  14. /*                                                         */
  15. /* Registered members may use this program freely in their */
  16. /*     own commercial/noncommercial programs/articles.     */
  17. /*                                                         */
  18. /***********************************************************/
  19.  
  20. /* This example demonstrates how to use the mouth */
  21. /* request block to draw a talking mouth.         */
  22.  
  23.  
  24.  
  25. /* We are using Intuition: */
  26. #include <intuition/intuition.h>
  27.  
  28. /* We are also using the narrator device: */
  29. #include <devices/narrator.h>
  30.  
  31.  
  32.  
  33. /* Size of the phonetic string buffer. */
  34. #define PHONETIC_BUFFER_SIZE 200
  35.  
  36. /* The size of the window: */
  37. #define WIDTH  320
  38. #define HEIGHT 200
  39.  
  40. /* Mouth position: */
  41. #define MOUTH_X (WIDTH>>1)
  42. #define MOUTH_Y (HEIGHT>>1)
  43.  
  44. /* The mouth's size: */
  45. #define SCALE 5
  46.  
  47. /* The audio channels: */
  48.  
  49. /* Values: */
  50. #define LEFT0B   0
  51. #define RIGHT0B  1
  52. #define RIGHT1B  2
  53. #define LEFT1B   3
  54.  
  55. /* Bit fields: */
  56. #define LEFT0F   (1<<LEFT0B)
  57. #define RIGHT0F  (1<<RIGHT0B)
  58. #define RIGHT1F  (1<<RIGHT1B)
  59. #define LEFT1F   (1<<LEFT1B)
  60.  
  61.  
  62.  
  63. /* Pointer to the Intuition Library: */
  64. struct IntuitionBase *IntuitionBase;
  65.  
  66. /* Pointer to the Graphics Library: */
  67. struct GfxBase *GfxBase;
  68.  
  69. /* Pointer to the translator library: */
  70. struct Library *TranslatorBase;
  71.  
  72.  
  73.  
  74. /* Declare a pointer to our reply port: */
  75. struct MsgPort *replymp = NULL;
  76.  
  77. /* Declare a pointer to our narrator request block: */
  78. struct narrator_rb *narrator_req = NULL;
  79.  
  80. /* Declare a pointer to our mouth request block: */
  81. struct mouth_rb *mouth_req = NULL;
  82.  
  83.  
  84.  
  85. /* The text should be read in stereo: */
  86. UBYTE allocation_array[]=
  87. {
  88.   LEFT0F|RIGHT0F, /* First left and first right channel.   */
  89.   LEFT0F|RIGHT1F, /* First left and second right channel.  */
  90.   LEFT1F|RIGHT0F, /* Second left and first right channel.  */
  91.   LEFT1F|RIGHT1F  /* Second left and second right channel. */
  92. };
  93.  
  94.  
  95.  
  96. /* Declare a pointer to a Window structure: */ 
  97. struct Window *my_window;
  98.  
  99. /* Declare and initialize your NewWindow structure: */
  100. struct NewWindow my_new_window=
  101. {
  102.   50,            /* LeftEdge    x position of the window. */
  103.   50,            /* TopEdge     y positio of the window. */
  104.   WIDTH,         /* Width       The width of the window. */
  105.   HEIGHT,        /* Height      The height of the window. */
  106.   0,             /* DetailPen   Text should be drawn with colour reg. 0 */
  107.   1,             /* BlockPen    Blocks should be drawn with colour reg. 1 */
  108.   NULL,          /* IDCMPFlags  No IDCMP flags. */
  109.   SMART_REFRESH| /* Flags       Intuition should refresh the window. */
  110.   WINDOWCLOSE|   /*             Close Gadget. */
  111.   WINDOWDRAG|    /*             Drag gadget. */
  112.   WINDOWDEPTH|   /*             Depth arrange Gadgets. */
  113.   ACTIVATE,      /*             The window should be Active when opened. */
  114.   NULL,          /* FirstGadget No Custom Gadgets. */
  115.   NULL,          /* CheckMark   Use Intuition's default CheckMark (v). */
  116.   "The talking window!", /* Title Title of the window. */
  117.   NULL,          /* Screen      Connected to the Workbench Screen. */
  118.   NULL,          /* BitMap      No Custom BitMap. */
  119.   0,             /* MinWidth    We do not need to care about these */
  120.   0,             /* MinHeight   since we havent supplied the window with */
  121.   0,             /* MaxWidth    a Sizing Gadget. */
  122.   0,             /* MaxHeight */
  123.   WBENCHSCREEN   /* Type        Connected to the Workbench Screen. */
  124. };
  125.  
  126.  
  127.  
  128. /* Declare our functions: */
  129. void main();
  130. void clean_up( STRPTR text );
  131. void draw_mouth
  132. (
  133.   struct RastPort *rp,
  134.   UBYTE width,
  135.   UBYTE height,
  136.   UBYTE colour
  137. );
  138.  
  139.  
  140.  
  141. void main()
  142. {
  143.   /* Number of translated characters, or zero */
  144.   /* if all characters were translated:       */
  145.   int char_translated;
  146.   
  147.   /* The original string: */
  148.   char *original_string = "This is a talking picture! Only the Amiga makes it possible!";
  149.   
  150.   /* The phonetic string: */
  151.   char phonetic_string[ PHONETIC_BUFFER_SIZE ];
  152.  
  153.   /* Store error values here: */
  154.   BYTE error;
  155.  
  156.   /* TRUE as long the Amiga is reading text: */
  157.   BOOL still_talking;
  158.  
  159.   /* Pointer to the window's RastPort: */
  160.   struct RastPort *rast_port;
  161.  
  162.   /* Previous mouth size: */
  163.   UBYTE old_mouth_height;
  164.   UBYTE old_mouth_width;
  165.  
  166.  
  167.  
  168.   /* Since this program uses a window we have to  */
  169.   /* open the Intuition library, and since we use */
  170.   /* the low level graphical functions Move(),    */
  171.   /* Draw() etc, we have to open the Graphical    */
  172.   /* library.                                     */
  173.  
  174.   /* Open the Intuition Library: */
  175.   IntuitionBase = (struct IntuitionBase *)
  176.     OpenLibrary( "intuition.library", 0 );
  177.   /* Have we successfully opened the library? */
  178.   if( !IntuitionBase )
  179.     clean_up( "Could not open the Intuition Library!" );
  180.  
  181.   /* Open the Graphics library: */
  182.   GfxBase = (struct GfxBase *)
  183.     OpenLibrary( "graphics.library", 0 );
  184.   /* Have we successfully opened the library? */
  185.   if( !GfxBase )
  186.     clean_up( "Could not open the Graphics library!" );
  187.  
  188.   /* Open the translator library: */
  189.   TranslatorBase = (struct Library *)
  190.     OpenLibrary( "translator.library", 0 );
  191.   /* Have we successfully opened the library? */
  192.   if( !TranslatorBase )
  193.     clean_up( "Could not open the translator library!" );
  194.  
  195.  
  196.  
  197.   /* We will now try to open the window: */
  198.   my_window = (struct Window *)
  199.     OpenWindow( &my_new_window );
  200.  
  201.   /* Have we successfully opened the window? */
  202.   if( !my_window )
  203.     clean_up( "Could not open the Window!" );
  204.  
  205.   /* Get the address of the window's RastPort: */
  206.   rast_port = my_window->RPort;
  207.  
  208.   printf( "A picture can say more than thousand words,\n" );
  209.   printf( "but this is ridiculous!\n" );
  210.  
  211.  
  212.  
  213.   /* Translate our string into phonetics: (The Translate() */
  214.   /* functipon can sadly only translate English text, but  */
  215.   /* with small modifications of the phonetic string it    */
  216.   /* can be used with most languages.)                     */
  217.   char_translated =
  218.     Translate( original_string, strlen( original_string ),
  219.                phonetic_string, PHONETIC_BUFFER_SIZE );
  220.  
  221.   /* If all characters could successfully be translated */
  222.   /* and stored in the phonetic string Translate()      */ 
  223.   /* returns zero, else a negativa value is returned    */
  224.   /* which tells us how many characters were actually   */
  225.   /* translated: (Note that we put a minus sign infront */
  226.   /* of the variable to make it positive.)              */
  227.   if( char_translated )
  228.     printf( "Translated only %d characters!\n", -char_translated );
  229.  
  230.  
  231.  
  232.   /* Get a reply port: (No name, priority 0) */
  233.   replymp = (struct MsgPort *)
  234.     CreatePort( NULL, 0 );
  235.   if( !replymp )
  236.     clean_up( "Could not create the reply port!" );
  237.  
  238.  
  239.  
  240.   /* Allocate and preinitialize a narrator request block: */
  241.   narrator_req = (struct narrator_rb *)
  242.     CreateExtIO( replymp, sizeof( struct narrator_rb ) );
  243.   if( !narrator_req )
  244.     clean_up( "Not enough memory for the narrator request!" );
  245.  
  246.  
  247.  
  248.   /* Open the Narrator Device: */
  249.   error = OpenDevice( "narrator.device", 0, narrator_req, 0 );
  250.   if( error )
  251.   {
  252.     /* Clear the "io_Device" flag since */
  253.     /* we have not opened the device:   */
  254.     narrator_req->message.io_Device = NULL;
  255.   
  256.     /* Quit: */
  257.     clean_up( "Could not open the Narrator Device!" );
  258.   }
  259.  
  260.  
  261.  
  262.   /* Allocate and preinitialize the mouth request block: */
  263.   mouth_req = (struct mouth_rb *)
  264.     CreateExtIO( replymp, sizeof( struct mouth_rb ) );
  265.   if( !mouth_req )
  266.     clean_up( "Not enough memory for the mouth request!" );
  267.  
  268.  
  269.  
  270.   /* Initialize the mouth request: */
  271.  
  272.   /* Set the mouth width and heigh to zero: */
  273.   mouth_req->width = 0;
  274.   mouth_req->height = 0;
  275.  
  276.   /* Copy the mouth values: */
  277.   old_mouth_height = mouth_req->width;
  278.   old_mouth_width = mouth_req->height;
  279.  
  280.   /* Give the mouth request a pointer to the narrator device: */
  281.   mouth_req->voice.message.io_Device = narrator_req->message.io_Device;
  282.  
  283.   /* Give the mouth request the current unit number: */
  284.   mouth_req->voice.message.io_Unit = narrator_req->message.io_Unit;
  285.  
  286.   /* No error number (so far): */
  287.   mouth_req->voice.message.io_Error = 0;
  288.  
  289.   /* The mouth request shuld look at (read) the request */
  290.   /* which is currently talking:                        */
  291.   mouth_req->voice.message.io_Command = CMD_READ;
  292.  
  293.   
  294.  
  295.  
  296.  
  297.   /* Set our requirements: */
  298.  
  299.   /* Set the length of the phonetic string: */
  300.   narrator_req->message.io_Length = strlen( phonetic_string );
  301.  
  302.   /* Give it a pointer to the phonetic string: */
  303.   narrator_req->message.io_Data = (APTR) phonetic_string;
  304.  
  305.   /* Send (write) the text to the device: */
  306.   narrator_req->message.io_Command = CMD_WRITE;
  307.  
  308.   /* Desired channel combinations: */
  309.   narrator_req->ch_masks = allocation_array;
  310.  
  311.   /* Size of the allocation array: */
  312.   narrator_req->nm_masks = sizeof( allocation_array );
  313.  
  314.   /* Generate mouth values: */
  315.   narrator_req->mouths = TRUE;
  316.  
  317.  
  318.  
  319.   /* Normal (one colour) draw mode: */
  320.   SetDrMd( rast_port, JAM1 );
  321.  
  322.   /* Start to read: */
  323.   SendIO( narrator_req );
  324.  
  325.  
  326.  
  327.   /* The Amiga is still reading the text: */
  328.   still_talking = TRUE;
  329.  
  330.   /* As long as the Amiga is reading the text */
  331.   /* we stay in the while loop:               */
  332.   while( still_talking )
  333.   {
  334.     /* Send the mouth request to the narrator device. The request */
  335.     /* will be returned when the mouth width and/or heigh have    */
  336.     /* changed, or the device has stopped reading the text:       */ 
  337.     DoIO( mouth_req );
  338.     
  339.     /* Has the device stopped reading thel text: */
  340.     if( mouth_req->voice.message.io_Error == ND_NoWrite )
  341.       still_talking = FALSE;
  342.     else
  343.     {
  344.       /* No, the device is still reading. The mouth must have */
  345.       /* changed, so we better redraw it:                     */
  346.  
  347.       /* Remove the old mouth: */
  348.       draw_mouth
  349.       (
  350.         rast_port,
  351.         old_mouth_width,
  352.         old_mouth_height,
  353.         0
  354.       );
  355.  
  356.       /* Draw the new mouth: */
  357.       draw_mouth
  358.       (
  359.         rast_port,
  360.         mouth_req->width,
  361.         mouth_req->height,
  362.         1
  363.       );
  364.  
  365.       /* Save the mouth values: */
  366.       old_mouth_width = mouth_req->width;
  367.       old_mouth_height = mouth_req->height;
  368.     }
  369.   }
  370.  
  371.   /* We know that the Amiga has stopped speaking,  */
  372.   /* and hence we do not have to wait for the      */
  373.   /* narrator to finish reading. We should however */
  374.   /* check if we have successfully read the text:  */
  375.  
  376.   if( narrator_req->message.io_Error )
  377.   {
  378.     printf( "Error code: %d\n", narrator_req->message.io_Error );
  379.     clean_up( "Error while reading!" );
  380.   }
  381.  
  382.  
  383.  
  384.   /* Clean up and quit: */
  385.   clean_up( "The End!" );
  386. }
  387.  
  388.  
  389.  
  390. /* Close and return everything that has been */
  391. /* opened and allocated before we quit:      */
  392.  
  393. void clean_up( STRPTR text )
  394. {
  395.   /* If we have a request block and the "io_Device" field  */
  396.   /* is not zero, we know that the device has successfully */
  397.   /* been opened and must now be closed:                   */ 
  398.   if( narrator_req && narrator_req->message.io_Device )
  399.     CloseDevice( narrator_req );
  400.  
  401.   /* Empty the reply port: */
  402.   while( GetMsg( replymp ) )
  403.     printf( "Collected a message at the reply port.\n" );
  404.  
  405.   /* Remove the replyport: */
  406.   if( replymp )
  407.     DeletePort( replymp);
  408.  
  409.   /* Dealocate the narrator request block: */
  410.   if( narrator_req )
  411.     DeleteExtIO( narrator_req, sizeof( struct narrator_rb ) );
  412.  
  413.   /* Close the window: */
  414.   if( my_window )
  415.     CloseWindow( my_window );
  416.   
  417.   /* Close the translator library: */
  418.   if( TranslatorBase )
  419.     CloseLibrary( TranslatorBase );
  420.  
  421.   /* Close the Graphics library: */
  422.   if( GfxBase )
  423.     CloseLibrary( GfxBase );
  424.  
  425.   /* Close the Intuition Library: */
  426.   if( IntuitionBase )
  427.     CloseLibrary( IntuitionBase );
  428.  
  429.  
  430.  
  431.   /* Print the last message: */
  432.   printf( "%s\n", text );
  433.  
  434.   /* Quit: */
  435.   exit( 0 );
  436. }
  437.  
  438.  
  439.  
  440. /* This simple function will draw the mouth: */
  441.  
  442. void draw_mouth
  443. (
  444.   struct RastPort *rp,
  445.   UBYTE width,
  446.   UBYTE height,
  447.   UBYTE colour
  448. )
  449. {
  450.   /* Set colour: */ 
  451.   SetAPen( rp, colour );
  452.  
  453.   /* Start position: */
  454.   Move( rp, MOUTH_X - width * SCALE, MOUTH_Y );
  455.  
  456.   /* Draw the mouth: */
  457.   Draw( rp, MOUTH_X, MOUTH_Y - height * SCALE );
  458.   Draw( rp, MOUTH_X + width * SCALE, MOUTH_Y );
  459.   Draw( rp, MOUTH_X, MOUTH_Y + height * SCALE );
  460.   Draw( rp, MOUTH_X - width * SCALE, MOUTH_Y );
  461. }
  462.