home *** CD-ROM | disk | FTP | other *** search
- /***********************************************************/
- /* */
- /* Amiga C Encyclopedia (ACE) V3.0 Amiga C Club (ACC) */
- /* ------------------------------- ------------------ */
- /* */
- /* Book: ACM Devices Amiga C Club */
- /* Chapter: Narrator Device Tulevagen 22 */
- /* File: Example6.c 181 41 LIDINGO */
- /* Author: Anders Bjerin SWEDEN */
- /* Date: 92-04-26 */
- /* Version: 1.00 */
- /* */
- /* Copyright 1992, Anders Bjerin - Amiga C Club (ACC) */
- /* */
- /* Registered members may use this program freely in their */
- /* own commercial/noncommercial programs/articles. */
- /* */
- /***********************************************************/
-
- /* This example demonstrates how to use the mouth */
- /* request block to draw a talking mouth. */
-
-
-
- /* We are using Intuition: */
- #include <intuition/intuition.h>
-
- /* We are also using the narrator device: */
- #include <devices/narrator.h>
-
-
-
- /* Size of the phonetic string buffer. */
- #define PHONETIC_BUFFER_SIZE 200
-
- /* The size of the window: */
- #define WIDTH 320
- #define HEIGHT 200
-
- /* Mouth position: */
- #define MOUTH_X (WIDTH>>1)
- #define MOUTH_Y (HEIGHT>>1)
-
- /* The mouth's size: */
- #define SCALE 5
-
- /* The audio channels: */
-
- /* Values: */
- #define LEFT0B 0
- #define RIGHT0B 1
- #define RIGHT1B 2
- #define LEFT1B 3
-
- /* Bit fields: */
- #define LEFT0F (1<<LEFT0B)
- #define RIGHT0F (1<<RIGHT0B)
- #define RIGHT1F (1<<RIGHT1B)
- #define LEFT1F (1<<LEFT1B)
-
-
-
- /* Pointer to the Intuition Library: */
- struct IntuitionBase *IntuitionBase;
-
- /* Pointer to the Graphics Library: */
- struct GfxBase *GfxBase;
-
- /* Pointer to the translator library: */
- struct Library *TranslatorBase;
-
-
-
- /* Declare a pointer to our reply port: */
- struct MsgPort *replymp = NULL;
-
- /* Declare a pointer to our narrator request block: */
- struct narrator_rb *narrator_req = NULL;
-
- /* Declare a pointer to our mouth request block: */
- struct mouth_rb *mouth_req = NULL;
-
-
-
- /* The text should be read in stereo: */
- UBYTE allocation_array[]=
- {
- LEFT0F|RIGHT0F, /* First left and first right channel. */
- LEFT0F|RIGHT1F, /* First left and second right channel. */
- LEFT1F|RIGHT0F, /* Second left and first right channel. */
- LEFT1F|RIGHT1F /* Second left and second right channel. */
- };
-
-
-
- /* Declare a pointer to a Window structure: */
- struct Window *my_window;
-
- /* Declare and initialize your NewWindow structure: */
- struct NewWindow my_new_window=
- {
- 50, /* LeftEdge x position of the window. */
- 50, /* TopEdge y positio of the window. */
- WIDTH, /* Width The width of the window. */
- HEIGHT, /* Height The height of the window. */
- 0, /* DetailPen Text should be drawn with colour reg. 0 */
- 1, /* BlockPen Blocks should be drawn with colour reg. 1 */
- NULL, /* IDCMPFlags No IDCMP flags. */
- SMART_REFRESH| /* Flags Intuition should refresh the window. */
- WINDOWCLOSE| /* Close Gadget. */
- WINDOWDRAG| /* Drag gadget. */
- WINDOWDEPTH| /* Depth arrange Gadgets. */
- ACTIVATE, /* The window should be Active when opened. */
- NULL, /* FirstGadget No Custom Gadgets. */
- NULL, /* CheckMark Use Intuition's default CheckMark (v). */
- "The talking window!", /* Title Title of the window. */
- NULL, /* Screen Connected to the Workbench Screen. */
- NULL, /* BitMap No Custom BitMap. */
- 0, /* MinWidth We do not need to care about these */
- 0, /* MinHeight since we havent supplied the window with */
- 0, /* MaxWidth a Sizing Gadget. */
- 0, /* MaxHeight */
- WBENCHSCREEN /* Type Connected to the Workbench Screen. */
- };
-
-
-
- /* Declare our functions: */
- void main();
- void clean_up( STRPTR text );
- void draw_mouth
- (
- struct RastPort *rp,
- UBYTE width,
- UBYTE height,
- UBYTE colour
- );
-
-
-
- void main()
- {
- /* Number of translated characters, or zero */
- /* if all characters were translated: */
- int char_translated;
-
- /* The original string: */
- char *original_string = "This is a talking picture! Only the Amiga makes it possible!";
-
- /* The phonetic string: */
- char phonetic_string[ PHONETIC_BUFFER_SIZE ];
-
- /* Store error values here: */
- BYTE error;
-
- /* TRUE as long the Amiga is reading text: */
- BOOL still_talking;
-
- /* Pointer to the window's RastPort: */
- struct RastPort *rast_port;
-
- /* Previous mouth size: */
- UBYTE old_mouth_height;
- UBYTE old_mouth_width;
-
-
-
- /* Since this program uses a window we have to */
- /* open the Intuition library, and since we use */
- /* the low level graphical functions Move(), */
- /* Draw() etc, we have to open the Graphical */
- /* library. */
-
- /* Open the Intuition Library: */
- IntuitionBase = (struct IntuitionBase *)
- OpenLibrary( "intuition.library", 0 );
- /* Have we successfully opened the library? */
- if( !IntuitionBase )
- clean_up( "Could not open the Intuition Library!" );
-
- /* Open the Graphics library: */
- GfxBase = (struct GfxBase *)
- OpenLibrary( "graphics.library", 0 );
- /* Have we successfully opened the library? */
- if( !GfxBase )
- clean_up( "Could not open the Graphics library!" );
-
- /* Open the translator library: */
- TranslatorBase = (struct Library *)
- OpenLibrary( "translator.library", 0 );
- /* Have we successfully opened the library? */
- if( !TranslatorBase )
- clean_up( "Could not open the translator library!" );
-
-
-
- /* We will now try to open the window: */
- my_window = (struct Window *)
- OpenWindow( &my_new_window );
-
- /* Have we successfully opened the window? */
- if( !my_window )
- clean_up( "Could not open the Window!" );
-
- /* Get the address of the window's RastPort: */
- rast_port = my_window->RPort;
-
- printf( "A picture can say more than thousand words,\n" );
- printf( "but this is ridiculous!\n" );
-
-
-
- /* Translate our string into phonetics: (The Translate() */
- /* functipon can sadly only translate English text, but */
- /* with small modifications of the phonetic string it */
- /* can be used with most languages.) */
- char_translated =
- Translate( original_string, strlen( original_string ),
- phonetic_string, PHONETIC_BUFFER_SIZE );
-
- /* If all characters could successfully be translated */
- /* and stored in the phonetic string Translate() */
- /* returns zero, else a negativa value is returned */
- /* which tells us how many characters were actually */
- /* translated: (Note that we put a minus sign infront */
- /* of the variable to make it positive.) */
- if( char_translated )
- printf( "Translated only %d characters!\n", -char_translated );
-
-
-
- /* Get a reply port: (No name, priority 0) */
- replymp = (struct MsgPort *)
- CreatePort( NULL, 0 );
- if( !replymp )
- clean_up( "Could not create the reply port!" );
-
-
-
- /* Allocate and preinitialize a narrator request block: */
- narrator_req = (struct narrator_rb *)
- CreateExtIO( replymp, sizeof( struct narrator_rb ) );
- if( !narrator_req )
- clean_up( "Not enough memory for the narrator request!" );
-
-
-
- /* Open the Narrator Device: */
- error = OpenDevice( "narrator.device", 0, narrator_req, 0 );
- if( error )
- {
- /* Clear the "io_Device" flag since */
- /* we have not opened the device: */
- narrator_req->message.io_Device = NULL;
-
- /* Quit: */
- clean_up( "Could not open the Narrator Device!" );
- }
-
-
-
- /* Allocate and preinitialize the mouth request block: */
- mouth_req = (struct mouth_rb *)
- CreateExtIO( replymp, sizeof( struct mouth_rb ) );
- if( !mouth_req )
- clean_up( "Not enough memory for the mouth request!" );
-
-
-
- /* Initialize the mouth request: */
-
- /* Set the mouth width and heigh to zero: */
- mouth_req->width = 0;
- mouth_req->height = 0;
-
- /* Copy the mouth values: */
- old_mouth_height = mouth_req->width;
- old_mouth_width = mouth_req->height;
-
- /* Give the mouth request a pointer to the narrator device: */
- mouth_req->voice.message.io_Device = narrator_req->message.io_Device;
-
- /* Give the mouth request the current unit number: */
- mouth_req->voice.message.io_Unit = narrator_req->message.io_Unit;
-
- /* No error number (so far): */
- mouth_req->voice.message.io_Error = 0;
-
- /* The mouth request shuld look at (read) the request */
- /* which is currently talking: */
- mouth_req->voice.message.io_Command = CMD_READ;
-
-
-
-
-
- /* Set our requirements: */
-
- /* Set the length of the phonetic string: */
- narrator_req->message.io_Length = strlen( phonetic_string );
-
- /* Give it a pointer to the phonetic string: */
- narrator_req->message.io_Data = (APTR) phonetic_string;
-
- /* Send (write) the text to the device: */
- narrator_req->message.io_Command = CMD_WRITE;
-
- /* Desired channel combinations: */
- narrator_req->ch_masks = allocation_array;
-
- /* Size of the allocation array: */
- narrator_req->nm_masks = sizeof( allocation_array );
-
- /* Generate mouth values: */
- narrator_req->mouths = TRUE;
-
-
-
- /* Normal (one colour) draw mode: */
- SetDrMd( rast_port, JAM1 );
-
- /* Start to read: */
- SendIO( narrator_req );
-
-
-
- /* The Amiga is still reading the text: */
- still_talking = TRUE;
-
- /* As long as the Amiga is reading the text */
- /* we stay in the while loop: */
- while( still_talking )
- {
- /* Send the mouth request to the narrator device. The request */
- /* will be returned when the mouth width and/or heigh have */
- /* changed, or the device has stopped reading the text: */
- DoIO( mouth_req );
-
- /* Has the device stopped reading thel text: */
- if( mouth_req->voice.message.io_Error == ND_NoWrite )
- still_talking = FALSE;
- else
- {
- /* No, the device is still reading. The mouth must have */
- /* changed, so we better redraw it: */
-
- /* Remove the old mouth: */
- draw_mouth
- (
- rast_port,
- old_mouth_width,
- old_mouth_height,
- 0
- );
-
- /* Draw the new mouth: */
- draw_mouth
- (
- rast_port,
- mouth_req->width,
- mouth_req->height,
- 1
- );
-
- /* Save the mouth values: */
- old_mouth_width = mouth_req->width;
- old_mouth_height = mouth_req->height;
- }
- }
-
- /* We know that the Amiga has stopped speaking, */
- /* and hence we do not have to wait for the */
- /* narrator to finish reading. We should however */
- /* check if we have successfully read the text: */
-
- if( narrator_req->message.io_Error )
- {
- printf( "Error code: %d\n", narrator_req->message.io_Error );
- clean_up( "Error while reading!" );
- }
-
-
-
- /* Clean up and quit: */
- clean_up( "The End!" );
- }
-
-
-
- /* Close and return everything that has been */
- /* opened and allocated before we quit: */
-
- void clean_up( STRPTR text )
- {
- /* If we have a request block and the "io_Device" field */
- /* is not zero, we know that the device has successfully */
- /* been opened and must now be closed: */
- if( narrator_req && narrator_req->message.io_Device )
- CloseDevice( narrator_req );
-
- /* Empty the reply port: */
- while( GetMsg( replymp ) )
- printf( "Collected a message at the reply port.\n" );
-
- /* Remove the replyport: */
- if( replymp )
- DeletePort( replymp);
-
- /* Dealocate the narrator request block: */
- if( narrator_req )
- DeleteExtIO( narrator_req, sizeof( struct narrator_rb ) );
-
- /* Close the window: */
- if( my_window )
- CloseWindow( my_window );
-
- /* Close the translator library: */
- if( TranslatorBase )
- CloseLibrary( TranslatorBase );
-
- /* Close the Graphics library: */
- if( GfxBase )
- CloseLibrary( GfxBase );
-
- /* Close the Intuition Library: */
- if( IntuitionBase )
- CloseLibrary( IntuitionBase );
-
-
-
- /* Print the last message: */
- printf( "%s\n", text );
-
- /* Quit: */
- exit( 0 );
- }
-
-
-
- /* This simple function will draw the mouth: */
-
- void draw_mouth
- (
- struct RastPort *rp,
- UBYTE width,
- UBYTE height,
- UBYTE colour
- )
- {
- /* Set colour: */
- SetAPen( rp, colour );
-
- /* Start position: */
- Move( rp, MOUTH_X - width * SCALE, MOUTH_Y );
-
- /* Draw the mouth: */
- Draw( rp, MOUTH_X, MOUTH_Y - height * SCALE );
- Draw( rp, MOUTH_X + width * SCALE, MOUTH_Y );
- Draw( rp, MOUTH_X, MOUTH_Y + height * SCALE );
- Draw( rp, MOUTH_X - width * SCALE, MOUTH_Y );
- }
-