home *** CD-ROM | disk | FTP | other *** search
/ Digispeech DS201A Drivers / dsapi_v120.zip / SOURCE / CALLIDLE.C < prev    next >
C/C++ Source or Header  |  1993-08-13  |  9KB  |  319 lines

  1. /* CALLIDLE.C */
  2. /****************************************************************************/
  3. /*                                                                          */
  4. /*  Abstract: DIGIAPI SDK Illustration of Driver Callback techniques.       */
  5. /*                                                                          */
  6. /*  Language: Microsoft C, v6.00a  Model: LARGE    Machine type: IBM PC     */
  7. /*                                                                          */
  8. /****************************************************************************/
  9. /*
  10.  
  11.  REV  DATE       AUTHOR          DESCRIPTION
  12.  1.0  04-20-92   Lee Mulcahy     Initial version.
  13.  ---  07-19-93   Lee Mulcahy     Latest change.
  14.  
  15. */
  16.  
  17. #include <stdio.h>
  18. #include <signal.h>
  19. #include <io.h>
  20. #include <dos.h>
  21.  
  22.  
  23. /****************************************************************************/
  24. /*                                                                          */
  25. /*  Literals, etc.                                                          */
  26. /*                                                                          */
  27. /****************************************************************************/
  28.  
  29. #include "digi.h"
  30.  
  31. #define ESC_KEY     0x1B
  32.  
  33. #define BUFFER_CNT  4               // Number of audio buffers
  34. #define BUFFER_LEN  7400
  35.  
  36. typedef struct _buffer
  37.     {
  38.     BYTE    buf[ BUFFER_LEN];
  39.     } BUFFER;
  40.  
  41. static BUFFER buffer [BUFFER_CNT];
  42.  
  43. static int      error;              // Audio restart error code.
  44. static int      playSegment;
  45. static DWORD    dataLen;
  46.  
  47.  
  48.  
  49. /** KeyPressed **************************************************************/
  50. /*                                                                          */
  51. /*  If a key was pressed, return the key, else return FALSE.                */
  52. /*                                                                          */
  53. /****************************************************************************/
  54.  
  55. int KeyPressed ( void )
  56.     {
  57.     int key;
  58.  
  59.         /* Check for ESC key.   */
  60.  
  61.     key = 0;
  62.     if ( kbhit())
  63.         {
  64.         key = getch();
  65.  
  66.             /* If NULL, get another key and */
  67.             /* discard it (IBM PC oddity).  */
  68.  
  69.         if ( key == 0)
  70.             getch();
  71.         }
  72.  
  73.     return( key );
  74.     }
  75.  
  76.  
  77. /** OurCallIdle *************************************************************/
  78. /*                                                                          */
  79. /*  The foreground application's Driver Idle callback routine.              */
  80. /*                                                                          */
  81. /****************************************************************************/
  82.  
  83. #pragma check_stack( off )      // No stack checking in callback function.
  84.  
  85. void far OurCallIdle ( void )
  86.     {
  87.     int status;
  88.  
  89.     _asm
  90.         {
  91.             ; Establish local DS by using the segment
  92.             ; of a known local variable.  Since this
  93.             ; is SMALL model, this should work without
  94.             ; any problems.
  95.  
  96.         mov        ax, seg playSegment
  97.         mov     ds, ax
  98.         }
  99.  
  100.         /* Start the next chunk of data playing.    */
  101.  
  102.     if ( playSegment == 0 )
  103.         {
  104.  
  105.         status = DSReset();
  106.         if (status)
  107.             {
  108.             error = status;
  109.             return;
  110.             }
  111.  
  112.             /* Must restore the IDLE callback.  */
  113.  
  114.         DSSetCallIdle( &OurCallIdle );
  115.  
  116.             /* Specify buffers 2 and 3 as the active buffers.   */
  117.  
  118.         status = DSSetBuffer( 0, BUFFER_LEN, (char far *)buffer[ 2].buf );
  119.         if (status)
  120.             {
  121.             error = status;
  122.             return;
  123.             }
  124.  
  125.           /* Send address of buffer #1 to the driver. */
  126.  
  127.         status = DSSetBuffer( 1, BUFFER_LEN, (char far *)buffer[ 3].buf );
  128.         if (status)
  129.             {
  130.             error = status;
  131.             return;
  132.             }
  133.  
  134.         error = StartPlay( DF_PCM8, 11025, 1, BUFFER_LEN * 2 );
  135.         playSegment++;
  136.         }
  137.  
  138.     }
  139. #pragma check_stack     // Allow stack checking outside callback function
  140.  
  141.  
  142. /** main ********************************************************************/
  143. /*                                                                          */
  144. /*  The foreground application.                                             */
  145. /*                                                                          */
  146. /****************************************************************************/
  147.  
  148. int main ( int argc, char *argv[] )
  149.     {
  150.     FILE    *fin, *fin1;
  151.     int     status, count, i, stopPlay, fillIndex;
  152.     DWORD   remaining, audioPosition, support;
  153.  
  154.     if ( argc < 2 )
  155.         {
  156.         printf( "Usage: CALLIDLE <file name>\n");
  157.         exit(1);
  158.         }
  159.  
  160.     if ( !DriverInstalled() )
  161.         {
  162.         printf( "Cannot find Audio driver\n" );
  163.         exit( 1 );
  164.         }
  165.  
  166.         /* Check for CALLIDLE functionality.    */
  167.  
  168.     DSQuery( NULL, NULL, &support );
  169.     if (( support & CAPS_CALLIDLE ) == 0 )
  170.         {
  171.         printf( "IDLE Callback not available\n" );
  172.         exit( 1 );
  173.         }
  174.  
  175.         /* Open input file. */
  176.  
  177.     if (( fin = fopen( argv[1], "rb")) == NULL )
  178.         {
  179.         printf( "Error: cannot open %s\n", argv[1]);
  180.         exit(1);
  181.         }
  182.     dataLen = filelength( fileno( fin ));
  183.     dataLen--;                              // Ignore header byte.
  184.     dataLen &= 0xFFFFFFFE;                  // length must be even.
  185.  
  186.         /* IGNORE ^C */
  187.  
  188.     signal( SIGINT, SIG_IGN );
  189.  
  190.     status = DSReset();
  191.  
  192.         /* Send address of callback function to the driver. */
  193.  
  194.     printf( "SetCallIdle: %04X\n", DSSetCallIdle( &OurCallIdle ));
  195.  
  196.     remaining = dataLen;
  197.  
  198.         /* Fill buffers pool with audio data.   */
  199.  
  200.     memset( buffer, 0, sizeof( buffer) );
  201.     for ( i = 0; i < 4; i++) 
  202.         {
  203.         count = fread(
  204.             buffer[ i].buf,
  205.             1,
  206.             (WORD)((remaining > BUFFER_LEN) ? BUFFER_LEN : remaining),
  207.             fin
  208.             );
  209.         remaining -= count;
  210.         }
  211.  
  212.         /* Init stuff.  */
  213.  
  214.     fillIndex = 0;
  215.     error = FALSE;
  216.  
  217.         /* Send address of buffer #0 to the driver. */
  218.  
  219.     status = DSSetBuffer( 0, BUFFER_LEN, (char far *)buffer[ 0].buf );
  220.     if (status)
  221.         {
  222.         printf( "SetBuffer 0 failed: %04X\n", status );
  223.         exit(1);
  224.         }
  225.  
  226.         /* Send address of buffer #1 to the driver. */
  227.  
  228.     status = DSSetBuffer( 1, BUFFER_LEN, (char far *)buffer[ 1].buf );
  229.     if (status)
  230.         {
  231.         printf( "SetBuffer 1 failed: %04X\n", status );
  232.         exit(1);
  233.         }
  234.  
  235.         /* Start the first half of the file.    */
  236.  
  237.     status = StartPlay( DF_PCM8, 8000, 1, BUFFER_LEN * 2 );
  238.     if ( status )
  239.         {
  240.         printf( "StartPlay failed: %04x\n", status );
  241.         DSReset();
  242.         fcloseall();
  243.         exit(1);
  244.         }
  245.     remaining = dataLen;
  246.  
  247.         /* Buffering and foreground process.    */
  248.  
  249.     playSegment = 0;
  250.     stopPlay = FALSE;
  251.     for ( ;; )
  252.         {
  253.             /* Check for user intervention. */
  254.  
  255.         switch ( KeyPressed() )
  256.             {
  257.             case 'p':
  258.             case 'P':
  259.                 status = DSPause();
  260.                 printf( "-- Pause ('R' resumes play) : " );
  261.                 break;
  262.  
  263.             case 'r':
  264.             case 'R':
  265.                 status = DSResume();
  266.                 printf( "-- Resume\n" );
  267.                 break;
  268.  
  269.             case ESC_KEY:
  270.                 stopPlay = TRUE;
  271.                 break;
  272.  
  273.             default:
  274.                 break;
  275.             }
  276.  
  277.             /* Wait till next buffer is ready.  */
  278.  
  279.         status = DSGetStatus();
  280.         if ( stopPlay )
  281.             break;
  282.  
  283.             /* Skip rest if paused or all buffers full. */
  284.  
  285.         if (status == E_PAUSE)
  286.             continue;
  287.  
  288.             /* Exit if error or end of action.  */
  289.  
  290.         if (( status != E_BUF0) && ( status != E_BUF1))
  291.             break;
  292.  
  293.             /* Display current file position.   */
  294.  
  295.         DSGetByteCount( &audioPosition );
  296.         printf( "Total bytes = %lu\r", audioPosition );
  297.         }
  298.  
  299.         /* Display final stats. */
  300.  
  301.     DSGetByteCount( &audioPosition );
  302.     printf( "Total bytes = %lu\n", audioPosition );
  303.  
  304.         /* Display second StartPlay() error, if detected.   */
  305.  
  306.  
  307.     if ( error )
  308.         {
  309.         printf( "*** Error starting second segment\n" );
  310.         status = error;
  311.         }
  312.  
  313.     DSReset();
  314.     printf( "Last status: %04X\n", status );
  315.     fcloseall();
  316.     exit( status );
  317.     }
  318.  
  319.