home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Digispeech DS201A Drivers
/
dsapi_v120.zip
/
SOURCE
/
CALLIDLE.C
< prev
next >
Wrap
C/C++ Source or Header
|
1993-08-13
|
9KB
|
319 lines
/* CALLIDLE.C */
/****************************************************************************/
/* */
/* Abstract: DIGIAPI SDK Illustration of Driver Callback techniques. */
/* */
/* Language: Microsoft C, v6.00a Model: LARGE Machine type: IBM PC */
/* */
/****************************************************************************/
/*
REV DATE AUTHOR DESCRIPTION
1.0 04-20-92 Lee Mulcahy Initial version.
--- 07-19-93 Lee Mulcahy Latest change.
*/
#include <stdio.h>
#include <signal.h>
#include <io.h>
#include <dos.h>
/****************************************************************************/
/* */
/* Literals, etc. */
/* */
/****************************************************************************/
#include "digi.h"
#define ESC_KEY 0x1B
#define BUFFER_CNT 4 // Number of audio buffers
#define BUFFER_LEN 7400
typedef struct _buffer
{
BYTE buf[ BUFFER_LEN];
} BUFFER;
static BUFFER buffer [BUFFER_CNT];
static int error; // Audio restart error code.
static int playSegment;
static DWORD dataLen;
/** KeyPressed **************************************************************/
/* */
/* If a key was pressed, return the key, else return FALSE. */
/* */
/****************************************************************************/
int KeyPressed ( void )
{
int key;
/* Check for ESC key. */
key = 0;
if ( kbhit())
{
key = getch();
/* If NULL, get another key and */
/* discard it (IBM PC oddity). */
if ( key == 0)
getch();
}
return( key );
}
/** OurCallIdle *************************************************************/
/* */
/* The foreground application's Driver Idle callback routine. */
/* */
/****************************************************************************/
#pragma check_stack( off ) // No stack checking in callback function.
void far OurCallIdle ( void )
{
int status;
_asm
{
; Establish local DS by using the segment
; of a known local variable. Since this
; is SMALL model, this should work without
; any problems.
mov ax, seg playSegment
mov ds, ax
}
/* Start the next chunk of data playing. */
if ( playSegment == 0 )
{
status = DSReset();
if (status)
{
error = status;
return;
}
/* Must restore the IDLE callback. */
DSSetCallIdle( &OurCallIdle );
/* Specify buffers 2 and 3 as the active buffers. */
status = DSSetBuffer( 0, BUFFER_LEN, (char far *)buffer[ 2].buf );
if (status)
{
error = status;
return;
}
/* Send address of buffer #1 to the driver. */
status = DSSetBuffer( 1, BUFFER_LEN, (char far *)buffer[ 3].buf );
if (status)
{
error = status;
return;
}
error = StartPlay( DF_PCM8, 11025, 1, BUFFER_LEN * 2 );
playSegment++;
}
}
#pragma check_stack // Allow stack checking outside callback function
/** main ********************************************************************/
/* */
/* The foreground application. */
/* */
/****************************************************************************/
int main ( int argc, char *argv[] )
{
FILE *fin, *fin1;
int status, count, i, stopPlay, fillIndex;
DWORD remaining, audioPosition, support;
if ( argc < 2 )
{
printf( "Usage: CALLIDLE <file name>\n");
exit(1);
}
if ( !DriverInstalled() )
{
printf( "Cannot find Audio driver\n" );
exit( 1 );
}
/* Check for CALLIDLE functionality. */
DSQuery( NULL, NULL, &support );
if (( support & CAPS_CALLIDLE ) == 0 )
{
printf( "IDLE Callback not available\n" );
exit( 1 );
}
/* Open input file. */
if (( fin = fopen( argv[1], "rb")) == NULL )
{
printf( "Error: cannot open %s\n", argv[1]);
exit(1);
}
dataLen = filelength( fileno( fin ));
dataLen--; // Ignore header byte.
dataLen &= 0xFFFFFFFE; // length must be even.
/* IGNORE ^C */
signal( SIGINT, SIG_IGN );
status = DSReset();
/* Send address of callback function to the driver. */
printf( "SetCallIdle: %04X\n", DSSetCallIdle( &OurCallIdle ));
remaining = dataLen;
/* Fill buffers pool with audio data. */
memset( buffer, 0, sizeof( buffer) );
for ( i = 0; i < 4; i++)
{
count = fread(
buffer[ i].buf,
1,
(WORD)((remaining > BUFFER_LEN) ? BUFFER_LEN : remaining),
fin
);
remaining -= count;
}
/* Init stuff. */
fillIndex = 0;
error = FALSE;
/* Send address of buffer #0 to the driver. */
status = DSSetBuffer( 0, BUFFER_LEN, (char far *)buffer[ 0].buf );
if (status)
{
printf( "SetBuffer 0 failed: %04X\n", status );
exit(1);
}
/* Send address of buffer #1 to the driver. */
status = DSSetBuffer( 1, BUFFER_LEN, (char far *)buffer[ 1].buf );
if (status)
{
printf( "SetBuffer 1 failed: %04X\n", status );
exit(1);
}
/* Start the first half of the file. */
status = StartPlay( DF_PCM8, 8000, 1, BUFFER_LEN * 2 );
if ( status )
{
printf( "StartPlay failed: %04x\n", status );
DSReset();
fcloseall();
exit(1);
}
remaining = dataLen;
/* Buffering and foreground process. */
playSegment = 0;
stopPlay = FALSE;
for ( ;; )
{
/* Check for user intervention. */
switch ( KeyPressed() )
{
case 'p':
case 'P':
status = DSPause();
printf( "-- Pause ('R' resumes play) : " );
break;
case 'r':
case 'R':
status = DSResume();
printf( "-- Resume\n" );
break;
case ESC_KEY:
stopPlay = TRUE;
break;
default:
break;
}
/* Wait till next buffer is ready. */
status = DSGetStatus();
if ( stopPlay )
break;
/* Skip rest if paused or all buffers full. */
if (status == E_PAUSE)
continue;
/* Exit if error or end of action. */
if (( status != E_BUF0) && ( status != E_BUF1))
break;
/* Display current file position. */
DSGetByteCount( &audioPosition );
printf( "Total bytes = %lu\r", audioPosition );
}
/* Display final stats. */
DSGetByteCount( &audioPosition );
printf( "Total bytes = %lu\n", audioPosition );
/* Display second StartPlay() error, if detected. */
if ( error )
{
printf( "*** Error starting second segment\n" );
status = error;
}
DSReset();
printf( "Last status: %04X\n", status );
fcloseall();
exit( status );
}