Here's my Openmodem() and Close() and lineEventThread:
int CTapiModem::OpenModem(LPVOID lp)
{
LINEINITIALIZEEXPARAMS stInitParams;
LINEDEVCAPS *lpDevCaps =NULL;
LONG lRet;
DWORD dwMediaMode;
DWORD dwNumDevs =0;
DWORD dwTAPIVer =TAPI_CURRENT_VERSION;
DWORD dwTmpVer =0;
LINEEXTENSIONID stExtID;
unsigned long i;
CWinguardDlg *m_pOwner;
m_pObj = lp;
m_pOwner = (CWinguardDlg *) m_pObj;
m_pOwner->StatusPrint("******* OPENING MODEM*********");
TRACE("******CTapiModem:Open()\n");
m_hEventFromThread = NULL;
m_hLineMsgThread = NULL; // TAPI Event monitoring thread.
m_bStopLineEventThread = FALSE;
m_dwLineMsg= 0;
m_nDevID = 0;
m_hLineApp = NULL;
m_hLine = NULL;
m_hCall = NULL;
SecState = SS_Idle;
m_hSerialHandle = NULL;
dwMediaMode = LINEMEDIAMODE_DATAMODEM; // data/fax this should be
lRet = lineSetNumRings(m_hLine,0,4);
memset(&stInitParams, 0, sizeof(LINEINITIALIZEEXPARAMS));
// set the options...
stInitParams.dwTotalSize = sizeof(LINEINITIALIZEEXPARAMS);
stInitParams.dwOptions = LINEINITIALIZEEXOPTION_USEEVENT;
// Initialize TAPI.
lRet = lineInitializeEx(&m_hLineApp,
AfxGetInstanceHandle(),
NULL,
AfxGetAppName(),
&dwNumDevs,
&dwTAPIVer,
&stInitParams);
if(lRet) //error
{
TRACE(" IN OPEN MODEM AFTER lineInitializeEx, %x\n",
lRet);
return lRet;
}
// Got the event handle...
m_hLineEvent = stInitParams.Handles.hEvent;
m_nDevID = -1;
// go through the device list and select the appropriate device to
transfer voice
for(i=0;i<dwNumDevs;i++) //i=0 == built in modem which
{
lRet = lineNegotiateAPIVersion(m_hLineApp, i, dwTAPIVer,
dwTAPIVer, &dwTmpVer, &stExtID);
if(lRet != 0)
continue;
lpDevCaps = (LINEDEVCAPS
*)malloc(sizeof(LINEDEVCAPS)+1024);// Allocate a little extra memory...
memset(lpDevCaps, 0, sizeof(LINEDEVCAPS)+1024);
lpDevCaps->dwTotalSize = sizeof(LINEDEVCAPS)+1024;
lRet = lineGetDevCaps(m_hLineApp, i, dwTmpVer, 0,
lpDevCaps);
if(lRet) //error
{
free(lpDevCaps);\
lpDevCaps=NULL;
continue;
}
char *szText = ((char*)lpDevCaps) +
lpDevCaps->dwLineNameOffset;// FOR DEBUGGING
// for more refer LINEMEDIAMODE_ Constants in MSDN
if(lpDevCaps->dwMediaModes & dwMediaMode)
{
free(lpDevCaps);
m_nDevID = i;
break;
}
free(lpDevCaps);
}
if(m_nDevID < 0)
{
TRACE("LINEERR_BADDEVICEID: %x\n", LINEERR_BADDEVICEID);
return LINEERR_BADDEVICEID; // no device available
}
// Open the line...
lRet = lineOpen(m_hLineApp, m_nDevID, &m_hLine, dwTAPIVer,
0x00000000, 1,LINECALLPRIVILEGE_OWNER,dwMediaMode,NULL);
if(lRet)
{
TRACE(" IN OPEN MODEM AFTER lineOpen, %x\n", lRet);
lineShutdown(m_hLineApp);
return lRet;
}
// We want to be notified for everything
lRet = lineSetStatusMessages(m_hLine, 0x1ffffff, 0);
if(lRet)
{
TRACE(" IN OPEN MODEM AFTER lineSetStatusMessages, %x\n",
lRet);
lineShutdown(m_hLineApp);
return lRet;
}
m_bStopLineEventThread = FALSE;
DWORD lineEventID;
m_hLineMsgThread =
CreateThread(NULL,NULL,LineEventThread,this,NULL,&lineEventID);
TRACE("After createthread, LineEventThread ID: %x\n", lineEventID);
SetThreadPriority(m_hLineMsgThread, THREAD_PRIORITY_BELOW_NORMAL);
m_hEventFromThread = CreateEvent(NULL,0,0,NULL);
m_pOwner->m_StopGetByte = CreateEvent(0, TRUE, FALSE, 0);
m_pOwner->m_WaitGetByte = CreateEvent(0, TRUE, FALSE, 0);
return 0;
}
int CTapiModem::Close(LPVOID lp)
{
LINECALLSTATUS stLineStatus;
LONG lRet;
CWinguardDlg *m_pOwner;
m_pObj = lp;
m_pOwner = (CWinguardDlg *) m_pObj;
TRACE(" ************CTapiModem::Close()\n");
if(m_hCall) // Call might be in progress...
{
memset(&stLineStatus, 0, sizeof(LINECALLSTATUS));
lRet = lineGetCallStatus(m_hCall, &stLineStatus);
// Technically, lineGetCallStatus returns more info
than
// there is in the structure. Since we don't care
about it,
// We just go on our merry way...
if(!lRet) // If it didn't fail, there's at least a call that
needs to be dropped.
lineDrop(m_hCall, NULL, 0);
// lineDeallocateCall(m_hCall);
m_hCall = NULL;
}
if (m_hSerialHandle)
{
CloseHandle(m_hSerialHandle);
m_hSerialHandle = NULL;
}
if(m_hLine)
lineClose(m_hLine);
m_hLine = NULL;
if(m_hLineMsgThread)
{
m_bStopLineEventThread = TRUE; // stop the event waiting
thread
TRACE("B4 WaitForSingleObject(m_hLineMsgThread, INFINITE)\n");
WaitForSingleObject(m_hLineMsgThread, INFINITE); // Wait for
it to comit suicide..
TRACE("F2 WaitForSingleObject(m_hLineMsgThread, INFINITE)\n");
CloseHandle(m_hLineMsgThread);
CloseHandle(m_hEventFromThread);
}
if(m_hLineApp)
lineShutdown(m_hLineApp);
m_hLineApp = NULL;
m_hLineMsgThread = NULL;
m_hEventFromThread = NULL;
m_dwLineMsg= 0;
m_nDevID = -1;
if (m_pOwner->m_StopGetByte)
{
CloseHandle(m_pOwner->m_StopGetByte);
m_pOwner->m_StopGetByte =NULL;
}
if (m_pOwner->m_WaitGetByte)
{
CloseHandle(m_pOwner->m_WaitGetByte);
m_pOwner->m_WaitGetByte =NULL;
}
//wait for thread to terminate
Sleep(100);
return 0;
}
HANDLE CTapiModem::GetHandle(const char *szClassType, long *lError)
{
HANDLE mHandle;
VARSTRING *pvarStrDevID = (VARSTRING
*)malloc(sizeof(VARSTRING)+255);
memset(pvarStrDevID,0,sizeof(VARSTRING)+255);
pvarStrDevID->dwTotalSize = sizeof(VARSTRING)+255;
long lRet =
lineGetID(m_hLine,0,m_hCall,LINECALLSELECT_LINE,pvarStrDevID,szClassType);
if(lRet)
{
*lError = lRet;
return NULL;
}
*lError = 0;
mHandle = *((LPHANDLE)((char *)pvarStrDevID +
pvarStrDevID->dwStringOffset));
free(pvarStrDevID);
return mHandle;
}
//**************************************************************************
********
DWORD WINAPI CTapiModem::LineEventThread(LPVOID lpVoid)
{
long lRet;
LINEMESSAGE stLineMsg;
char *szError;
CTapiModem *pcTapiModem = (CTapiModem *)lpVoid;
CWinguardDlg *m_pOwner;
m_pOwner = (CWinguardDlg *) pcTapiModem->m_pObj;
modem_task *mtask = m_pOwner->m_p_modem_task;
TRACE("in LineEventTHREAD,m_bStopLineEventThread: %d\n",
pcTapiModem->m_bStopLineEventThread);
while(!pcTapiModem->m_bStopLineEventThread)
{
// Get a TAPI event if available, wait for 10ms just enough
to give up quantum
int iret = WaitForSingleObject(pcTapiModem->m_hLineEvent, 1);
if (iret == WAIT_OBJECT_0)
{
//TAPI's got something
if ((lRet = lineGetMessage(pcTapiModem->m_hLineApp,
&stLineMsg, 0)) != 0)
{
return lRet;
}
TRACE("*in LineEventTHREAD, dwMessageID: %d\n",
stLineMsg.dwMessageID);
// Process the returned msg
switch (stLineMsg.dwMessageID)
{
case LINE_REPLY: // Sent after lineMakeCall or lineDrop
// Get a TAPI event if available, wait for 10ms just enough
to give up quontum
TRACE("LINE_REPLY \n");
pcTapiModem->SecState = SS_StartConnection;
break;
case LINE_CALLSTATE: // Sent after change of call state
TRACE("LINE_CALLSTATE \n");
switch (stLineMsg.dwParam1)
{
case LINECALLSTATE_OFFERING: //Incoming call is
offering. answer and
// connect
// Get the call handle
TRACE("LINECALLSTATE_OFFERING\n");
pcTapiModem->m_hCall = (HCALL)stLineMsg.hDevice;
pcTapiModem->m_dwLineMsg = LINECALLSTATE_OFFERING;
lRet = lineAnswer(pcTapiModem->m_hCall, NULL, 0);
lRet = (lRet>0)?0:lRet;
break;
case LINECALLSTATE_IDLE:
TRACE("-------LINECALLSTATE_IDLE\n");
lineDeallocateCall(pcTapiModem->m_hCall);
pcTapiModem->m_hCall = NULL;
if(pcTapiModem->m_hLine)
lineClose(pcTapiModem->m_hLine);
pcTapiModem->m_hLine = NULL;
if(pcTapiModem->m_hLineApp)
lineShutdown(pcTapiModem->m_hLineApp);
pcTapiModem->m_hLineApp = NULL;
pcTapiModem->m_bStopLineEventThread = TRUE;
pcTapiModem->m_dwLineMsg= 0;
pcTapiModem->m_nDevID = -1;
break;
case LINECALLSTATE_CONNECTED:
if(stLineMsg.dwCallbackInstance == 1)
{
m_pOwner->StatusPrint("+++++
CONNECTED ++++++");
pcTapiModem->SecState =
SS_ConnectInProgress;
TRACE("LINECALLSTATE_CONNECTED\n");
pcTapiModem->m_dwLineMsg =
LINECALLSTATE_CONNECTED;
pcTapiModem->m_hSerialHandle =
pcTapiModem->GetHandle("comm/datamodem",&lRet);
if(lRet)
{
pcTapiModem->m_hSerialHandle = NULL;
pcTapiModem->GetErrorString(lRet,szError);
TRACE("GetHandle returns: %d\n", szError);
return 0;
}
}
break;
case LINECALLSTATE_DISCONNECTED:
m_pOwner->StatusPrint("*** DISCONNECTED
***");
TRACE("-----LINECALLSTATE_DISCONNECTED
***\n");
lineDrop(pcTapiModem->m_hCall, NULL, 0);
CloseHandle(pcTapiModem->m_hSerialHandle);
pcTapiModem->m_hSerialHandle = NULL;
pcTapiModem->SecState = SS_DisConnected;
::SetEvent(m_pOwner->m_StopGetByte);
TRACE("@@@@ IN LINECALLSTATE_DISCONNECTED: b4 waitforsingleobject
m_pOwner->m_WaitGetByte %x\n",
m_pOwner->m_WaitGetByte);
::WaitForSingleObject(m_pOwner->m_WaitGetByte, 5000); //wait
5 seconds
TRACE("@@@@ IN LINECALLSTATE_DISCONNECTED: f2 waitforsingleobject\n");
// Close handles
pcTapiModem->m_hCall = NULL;
break;
default:
TRACE("in LineEventTHREAD, DEFAULT: dwMessageID:
%x\n",
stLineMsg.dwMessageID);
break;
}
break;
default:
break;
}
} //end if
} //endwhile
TRACE("CTapiModem::LineEventThread FINISHED\n");
pcTapiModem->m_hLineMsgThread = NULL;
return 0;
}
//**************************************************************************
*****
Gregory Hartmann
Performance Evaluation
InDyne, WROCI
Vandenberg AFB, CA
Work: (805)605-2056 / DSN 275-2056
Gregory,
what do you do to clear this isuue?
- Restart your app
- Restart TAPISRV (Telephony Service)
- Reboot (external) modem
- Reboot PC
> Is the some way to clear up
> lineInitializEx in my program?
The question is: why does lineInitializEx () fail repeatedly.
I guess due to an issue within the Modem HW / driver or UniModem TSP.
This cannot be cleared from within a TAPI app.
Maybe there is something in your code that may cause this "once in a while",
i.e. a race condition when releasing stuff prior your re-establish attempt.
I noticed a couple of thingschqving a quick look at your code:
- it isn't recommended to lineClose() / lineShutdown after each call. Only
do this when you actually want to exit your app
- usage of LINECALLPRIVILEGE_OWNER | LINECALLPRIVILEGE_MONITOR instead of
solely LINECALLPRIVILEGE_OWNER
> SetThreadPriority(m_hLineMsgThread, THREAD_PRIORITY_BELOW_NORMAL);
- it isn't recommended to handle events with lowered priority
- if you handle COM port data then even higher priority for this thread m,ay
be worth trying
> case LINE_REPLY: // Sent after lineMakeCall or lineDrop
> pcTapiModem->SecState = SS_StartConnection;
- This caues SS_StartConnection on all LINE_REPLY. Is that what you
intended?
> //wait for thread to terminate
> Sleep(100);
- you don't check here whether the thread actually terminated
--
Best Regards
Andreas Marschall
Microsoft MVP for TAPI / Windows SDK / Visual C++ 2003-2008
TAPI / TSP Developer and Tester
My TAPI and TSPI FAQ:
http://www.I-B-A-M.de/Andreas_Marschall's_TAPI_and_TSPI_FAQ.htm
My Toto� Tools (a collection of free, mostly TAPI related tools):
http://www.i-b-a-m.de/Andreas_Marschall's_Toto_Tools.htm
TAPI development around the world (Frappr! map):
http://www.frappr.com/TAPIaroundTheWorld
* Please post all messages and replies to the newsgroup so all may
* benefit from the discussion. Private mail is usually not replied to.
* This posting is provided "AS IS" with no warranties, and confers no
rights.
> .
>
Andreas,
Thanks for the prompt reply. I will look into the issues you brought up
after next week after Christmas. If I stop my application by quitting Debug
(I am running this in Debug mode) then restart using Debug (f5) everything
clears up and runs fine until I make it hang up again.
"Andreas Marschall [exMVP TAPI]" wrote:
> .
>
Also, I am using the internal modem on a Sony Vaio
Gregory, you are welcome.
Are you encountering the issue only with the debug version of your app, or
even only if you run it in the debugger,
or is also occuring with the release version (not runnin in debugger) ?