In
August 1996 Charles Mirho authored the article "To
Learn About the Voice Modem Extensions for Windows 95, Press 1 Now!"
for Microsoft Systems Journal.
Since then time has eroded it a bit, so
I have made a few corrections, documented them here
and re-archived the sample. I found
the sample pretty valuable in learning TAPI but even with the fixes it
is still just a sample, not a robust application.
In total there are 21 changes from the original
source, though not all changes were needed to get the sample working
properly again. Until the release of Windows 2000 it compiled
and ran, though not well. With the inclusion of TAPI 3.0 and
H.323 in Windows 2000 that pretty much broke it all together.
The new media types offered confused the application enough that it
shut down almost immediately in telephonyInitialize.
To fix it I first applied the two changes
mentioned in Bruce
Pennypacker's Unofficial TAPI FAQ. The first in Comdial.c in the TTYWndProc
the two lines:
mytapi.dwWaveInID =
mylineGetWaveID(LINECALLSELECT_LINE, "wave/in");
recordMessage
(mytapi.dwWaveInID);
were
commented out. The second in mytapi_.c -> LineCallBackProc two
debugging lines needed to be commented out.
mytapi.dwWaveOutID =
0;
mytapi.dwWaveInID = 0;
In comdial.h the function prototype playSound was changed to match the function
in sound.c
as
follows:
From:
HWAVE playSound(DWORD, char *, HWND);
To:
HWAVEOUT playSound(DWORD, char *, HWND);
With the
above changes, and deleting the Tapi32.lib that was included in the
original archive it would now compile.
The
following are the changes I made to mytapi_.c.
In Windows 2000 it
exited almost immediately in telephonyInitialize.The dwLine member of
the mytapi structure was not getting
set properly so I set it just before the call to mylineGetDevCaps since it is used in that
function. Now it would at least show the main window.
However if your TAPI device was after the H.323 or IPCONF TAPI lines,
the sample would attempt to use those lines instead of a voice
card. I am unsure of the proper way to get around that so I
hacked in another check of the pLineDevCaps
structure:
mytapi.pLinedevcaps->dwMonitorToneMaxNumFreq
With my voice cards this value is always greater
than 0, with the H.323 stuff it was always 0. This will probably
fail in time, but it works for now.
In mylineGetWaveID
and LineCallBackProc I changed
two NULL's to 0 to avoid type conversion warnings, so now the sample
should compile with MSVC at warning level 3 and produce no
warnings.
Also changed in the LineCallBackProc:
Modified the handling of the LINECALLSTATE_CONNECTED message so that
lineMonitorDigits was called before
playSound. The order change was
neccassary for my Dialogic 160/SC as the other way produced an
error from lineMonitorDigits stating
that the device was unavailable. It worked without the
re-ordering with my Creative Labs Modem Blaster (DI5630).
Added the LINECALLSTATE_DISCONNECTED case and the
following code to make sure the call was dropped and the wave devices
freed.
waveOutClose(mytapi.h_waveout) ;
waveInReset(mytapi.h_wavein) ;
waveInClose(mytapi.h_wavein) ;
lineDrop
(mytapi.hCall, NULL, 0) ;
lineDeallocateCall(mytapi.hCall) ;
mytapi.hCall = 0 ;
In LINEDEVSTATE_RINGING
I changed the ring count check from == to >=
since it is possible to miss a ring.
In this
sample you press '2' to record a message. After pressing two
Record.wav is played then the sample is supposed to record your
message, however the call to record the message came before the prompt
was finished and so it would fail to open the device if you weren't
using a Full-Duplex TSP and voice card. Since Unimodem/V and
Unimodem 5 are both Half-Duplex this would always fail with standard
voice cards. This was fixed by moving the recordMessage
call to the COMDIAL.C MM_WOM_DONE message.
This sample also provides for getting your
messages over the phone by pressing '1' then the entering the password
'6727'. This also failed since in the case PLAYSUBSTATE_PASSWORD3 the mytapi.nPlayCnt was set
to start at zero instead of one. That is the final change to
mytapi_.c
.
In comdial.c the following changes were
made:
In TTYWndProc for
the MM_WOM_DONE message a check was
added to see if mytapi.iPlayState ==
PLAYSTATE_RECORD and if so to call the recordMessage function. Also the mytapi.h_wavein member was set so that the
wave in device could be closed properly in the MM_WIM_DATA message.
No
matter which operating system I ran under the application used 100% of
the C.P.U. and failed to show error dialogs. This was caused by
improperly handling the WM_PAINT
message so I added code to the PaintTTY
function as
follows:
PAINTSTRUCT ps;
HDC hdc;
hdc =
BeginPaint(hWnd, &ps);
EndPaint(hWnd, &ps);
That is
all the fixes for comdial.c
.
For sound.c the
only functional change made was in the saveMessage function. The CreateFile function would fail if the file
didn't already exist so the dwCreationDisposition flag was changed from
OPEN_EXISTING to CREATE_ALWAYS. Other than that I
simply added WAVE_MAPPED flags to the
appropriate wavein/out calls and changed the CODEC from PCM 16bit to
u-Law 8bit since that is the only format that works on all my voice
cards, and it is the recommended format for TAPI compatibility as per
Microsoft Knowledge Base Article ID: Q142745.
That's
it! I have included the four wave files required to run the
application in this archive (only added 8k to the size) to get you
started until you record your own. Thanks to http://www.elantts.com/ for
providing the wave files. Maybe the sample will be good for
another couple of years now... With TAPI 3.0 it is surely on
borrowed time.