⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 tapiwave.c

📁 一个tapi开发的很好的语音通信程序
💻 C
📖 第 1 页 / 共 3 页
字号:
/*----------------------------------------------------------*\
TapiWave

This sample console application is designed to demonstrate
how to use TAPI to play and record wave files using a voice modem.

\*----------------------------------------------------------*/

#define TAPI_CURRENT_VERSION 0x00010004

#include <windows.h>
#include <tapi.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "TapiInfo.h"
#include <mmsystem.h>

char szAppName[] = "TapiWave";
char szAppFileName[] = "TapiWave.exe";

// TAPI constants; command line settable
DWORD dwDeviceID = 0;
DWORD dwAddressID = 0;

// TAPI global variables.
HINSTANCE hInstance;
HLINEAPP hLineApp = 0;
LINEEXTENSIONID LineExtensionID;
DWORD dwNumDevs;
DWORD dwAPIVersion;
HLINE hLine;
HCALL hCall = 0;
long lRet;
char szPhoneNumber[1024] = "45776";

LPVARSTRING      lpVarString;
LPLINEDEVSTATUS  lpLineDevStatus;
LPLINECALLINFO   lpLineCallInfo;
LPLINECALLPARAMS lpLineCallParams;

// State machine information.
DWORD dwMakeCallAsyncID=0;
DWORD dwLineDropAsyncID=0;
BOOL bDropped = FALSE;
BOOL bConnected = FALSE;
BOOL bAnswered  = FALSE;
BOOL bReadyToEnd = FALSE;
BOOL bPrintedEnd = FALSE;

// Constants in how the state machine behaves.
BOOL bDontClose = FALSE;
BOOL bCommandLineError = FALSE;
BOOL bLogExtraInfo = FALSE;
BOOL bAnswer = TRUE;

// Variables so we can ^C to shutdown and clean up properly.
DWORD dwThreadID;
HANDLE hSleep;

// Used to format data into.
char szBuff[4096];


// /// Waveaudio content ///

UINT WaveInID = 0;
UINT WaveOutID = 0;
BOOL bWaveLocal = FALSE;
char szFileName[1024] = "greeting.wav";
DWORD dwWaveBuffers = 10;
DWORD dwWaveBuffSize = 1024;

DWORD dwWaveMapped = WAVE_MAPPED;

HWAVEIN hWaveIn = NULL;
HWAVEOUT hWaveOut = NULL;
LPWAVEHDR   lpWaveHdr  = NULL;
LPSTR    lpData      = NULL;     // waveform data block
LPSTR    lpstrLoadStrBuf   = NULL;
HMMIO          hmmio;
MMCKINFO       mmckinfoParent;
MMCKINFO       mmckinfoSubchunk;
DWORD          dwFmtSize;
WAVEFORMATEX   *pFormat;
DWORD          dwDataSize;
LPSTR          hpch1, hpch2;
WORD           wBlockSize;

// Prototypes
void CALLBACK lineCallbackFunc(
    DWORD dwDevice, DWORD dwMsg, DWORD dwCallbackInstance, 
    DWORD dwParam1, DWORD dwParam2, DWORD dwParam3);
BOOL SetupEnvironment (int argc, char * argv[]);
void PrintHelp();
BOOL BreakHandlerRoutine(DWORD dwCtrlType);
BOOL GetCallInfo();
void StopEverything();
BOOL PumpMessages(BOOL bWaitForMessage);
BOOL DoConnectedStuff();
void StopConnectedStuff();
void PlayFromMemory (LPSTR szWavData);
DWORD WINAPI ThreadRecorded (LPVOID lpvThreadParam);
void RecordToMemory (LPSTR szWavData);
void BuildWavData (LPSTR szFilename, LPSTR szWavData, DWORD dwMaxBufferSize);


// Console app starting place.
int main (int argc, char * argv[], char * envp[])
{
   MSG msg;

   // Setup basic stuff.
   hInstance = GetModuleHandle(NULL);
   hSleep = CreateEvent(NULL, TRUE, FALSE, NULL);
   dwThreadID = GetCurrentThreadId();
   SetConsoleCtrlHandler((PHANDLER_ROUTINE) BreakHandlerRoutine, TRUE);	

   if (!SetupEnvironment(argc, argv))
      goto end;

   if (bWaveLocal)
   {
      DoConnectedStuff();
      goto end;
   }


   // Prime the message queue.  TAPI callback is called as a result
   // of messages being dispatched.  By default, console apps don't have 
   // a message queue to hold these messages.  PeekMessage will create it.
   PeekMessage(&msg, NULL, 0, 0, PM_REMOVE);

   lpVarString      = LocalAlloc(LPTR, 1024);
   lpLineDevStatus  = LocalAlloc(LPTR, 4096);
   lpLineCallInfo   = LocalAlloc(LPTR, 4096);
   lpLineCallParams = LocalAlloc(LPTR, 4096);

   lpVarString      -> dwTotalSize = 1024;
   lpLineDevStatus  -> dwTotalSize = 4096;
   lpLineCallInfo   -> dwTotalSize = 4096;

   lpLineCallParams -> dwTotalSize = 4096;
   lpLineCallParams -> dwBearerMode       = LINEBEARERMODE_VOICE;
   lpLineCallParams -> dwMinRate          = 300;
   lpLineCallParams -> dwMaxRate          = 64000;
   lpLineCallParams -> dwMediaMode        = LINEMEDIAMODE_AUTOMATEDVOICE,
   lpLineCallParams -> dwCallParamFlags   = 0;
   lpLineCallParams -> dwAddressMode      = LINEADDRESSMODE_ADDRESSID;
   lpLineCallParams -> dwAddressID        = dwAddressID;

   if (lRet = lineInitialize(&hLineApp, hInstance, lineCallbackFunc, 
      szAppName, &dwNumDevs))
   {
      printf("lineInitialize failed: %s.\n", FormatTapiError(lRet, szBuff));
      goto end;
   }


   if (lRet = lineNegotiateAPIVersion(hLineApp, dwDeviceID, 
      0x00010004, 0x00010004, &dwAPIVersion, &LineExtensionID))
   {
      if (lRet = LINEERR_INCOMPATIBLEAPIVERSION)
      {
         if (lRet = lineNegotiateAPIVersion(hLineApp, dwDeviceID, 
            0x00010003, 0x0FFF0FFF, &dwAPIVersion, &LineExtensionID))
         {
            printf("lineNegotiateAPIVersion failed: %s.\n", FormatTapiError(lRet, szBuff));
            goto end;
         }

         if (bLogExtraInfo)
            printf("lineNegotiateAPIVersion succeeded for API Version 0x%lx.\n"
               "%s is designed for API Version 1.4, but 1.3 and 2.0 should be ok\n",
               dwAPIVersion);
      }
      else
      {
         printf("lineNegotiateAPIVersion failed: %s.\n", FormatTapiError(lRet, szBuff));
         goto end;
      }
   }



   if (lRet = lineOpen(hLineApp, dwDeviceID, &hLine, dwAPIVersion, 0, 0,
            LINECALLPRIVILEGE_NONE, 0, NULL))
   {
      printf("lineOpen failed: %s.\n", FormatTapiError(lRet, szBuff));
      goto end;
   }
   
   while (TRUE)
   {
      if (lRet = lineGetLineDevStatus(hLine, lpLineDevStatus))
      {
         printf("lineGetLineDevStatus failed: %s.\n", FormatTapiError(lRet, szBuff));
         goto end;
      }

      if (lpLineDevStatus->dwNeededSize > lpLineDevStatus->dwTotalSize)
      {
         LocalReAlloc(lpLineDevStatus, lpLineDevStatus->dwNeededSize, LMEM_MOVEABLE);
         lpLineDevStatus->dwTotalSize = lpLineDevStatus->dwNeededSize;
         continue;
      }
      break;
   }

   if (lpLineDevStatus -> dwOpenMediaModes)
      printf("!!!WARNING!!!  Another application is already waiting for calls.\n\n");

   if (!((lpLineDevStatus -> dwLineFeatures) & LINEFEATURE_MAKECALL))
      printf("!!!WARNING!!!  No call appearances available at this time.\n\n");

   if (bAnswer)
   {
      lineClose(hLine);

      if (lRet = lineOpen(hLineApp, dwDeviceID, &hLine, dwAPIVersion, 0, 0,
            LINECALLPRIVILEGE_OWNER, LINEMEDIAMODE_AUTOMATEDVOICE, NULL))
      {
         printf("lineOpen failed: %s.\n", FormatTapiError(lRet, szBuff));
         goto end;
      }

      printf("Waiting for a call on TAPI Line Device %lu\n", dwDeviceID);
   }
   else
   {
      lRet = lineMakeCall(hLine, &hCall, szPhoneNumber, 0, lpLineCallParams);
      if (lRet < 0)
      {
         printf("lineMakeCall failed: %s.\n", FormatTapiError(lRet, szBuff));
         goto end;
      }
      else
      {
         dwMakeCallAsyncID = lRet;
      }
   }

   // TAPI callback is called only when messages are dispatched!
   while (!bReadyToEnd || hCall)
   {
      PumpMessages(TRUE);
   }

  end:

   lineShutdown(hLineApp);
   hLineApp = 0;

   LocalFree(lpLineDevStatus);
   LocalFree(lpLineCallInfo);
   LocalFree(lpLineCallParams);
   LocalFree(lpVarString);

   if (bDontClose)
      WaitForSingleObject(hSleep, INFINITE);

   CloseHandle(hSleep);
   return 1;
}



// Here's the TAPI callback.  Mondo switch statement!
void CALLBACK lineCallbackFunc(
    DWORD dwDevice, DWORD dwMsg, DWORD dwCallbackInstance, 
    DWORD dwParam1, DWORD dwParam2, DWORD dwParam3)
{
   if (bLogExtraInfo)
      printf("LCBF: %s\n",    // LCBF stands for lineCallBackFunc
         FormatLineCallback(
               dwDevice, dwMsg, dwCallbackInstance, 
               dwParam1, dwParam2, dwParam3,
               szBuff));

   switch(dwMsg)
   {
      case LINE_LINEDEVSTATE:
         if (dwParam1 == LINEDEVSTATE_REINIT)
         {
            printf("LINEDEVSTATE_REINIT\n");
            StopEverything();
         }
         break;

      case LINE_REPLY:
         if (dwParam2 == dwLineDropAsyncID)
         {
            if (dwParam2 != 0)
            {
               printf("lineDrop LINE_REPLY with failure: %s.  Stopping.\r\n", 
                  FormatTapiError((long) dwParam2, szBuff));
               StopEverything();
            }
         }
         else if (dwParam2 == dwMakeCallAsyncID)
         {
            if (dwParam2 != 0)
            {
               printf("lineMakeCall LINE_REPLY with failure: %s.  Stopping.\r\n", 
                  FormatTapiError((long) dwParam2, szBuff));
               StopEverything();
            }
         }


         // else ignore it.
         break;

      case LINE_CALLSTATE:
      {
         // Is this a new call?
         if (dwParam3 == LINECALLPRIVILEGE_OWNER)
         {
            // Do we already have a call?
            if (hCall && (hCall != (HCALL) dwDevice))
            {
               if (dwMsg == LINECALLSTATE_IDLE)
                  lineDeallocateCall((HCALL) dwDevice);
               else
               {
                  printf("New call; %lu, but already managing one.  Dropping it.\r\n",
                        dwDevice);
                  lineDrop((HCALL) dwDevice, NULL, 0);
               }
               break;
            }

            if (hCall)
               printf("Given OWNER privs to a call already owned?\n"
                      " - Should only happen if handed a call already owned.\n");
            else
            {
               hCall = (HCALL) dwDevice;
               printf("New incoming hCall 0x%lx on TAPI Line Device.\r\n",
                  hCall, dwDeviceID);
            }
         }

         if (hCall != (HCALL) dwDevice)
         {
            if (dwMsg == LINECALLSTATE_IDLE)
               lineDeallocateCall((HCALL) dwDevice);
            else
            {
               lineDrop((HCALL) dwDevice, NULL, 0);
               printf("LINE_CALLSTATE 0x%lx for non-main hCall: 0x%lx.  Dropping.\n", 
                  dwParam1, dwDevice);
            }
            break;
         }

         switch (dwParam1)
         {
            case LINECALLSTATE_IDLE:
            {
               printf("IDLE.\n\n");
               lRet = lineDeallocateCall(hCall);

               // Should make sure lineDeallocateCall succeeded

               hCall = 0;
               StopEverything();
               break;
            }

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -