📄 ixjunix.cxx
字号:
}
char * str = ::getenv("IXJ_COUNTRY");
if (str != NULL) {
if (isdigit(*str))
SetCountryCode((T35CountryCodes)atoi(str));
else
SetCountryCodeName(PString(str));
}
// make sure the PSTN line is on-hook
pstnIsOffHook = FALSE;
gotWink = FALSE;
IOCTL2(os_handle, PHONE_PSTN_SET_STATE, PSTN_ON_HOOK);
inRawMode = FALSE;
SetAEC (0, AECOff);
SetRecordVolume(0, 100);
SetPlayVolume (0, 100);
return TRUE;
}
BOOL OpalIxJDevice::Close()
{
if (!IsOpen())
return FALSE;
StopReadCodec(0);
StopWriteCodec(0);
RingLine(0, 0);
SetLineToLineDirect(0, 1, TRUE);
deviceName = PString();
// close the device
int stat = ::close(os_handle);
// remove the device from the exception information
{
PWaitAndSignal m(exceptionMutex);
ExceptionInfo * info = GetException();
info->fd = -1;
}
os_handle = -1;
return ConvertOSError(stat);
}
PString OpalIxJDevice::GetDeviceType() const
{
return OPAL_IXJ_TYPE_NAME;
}
PString OpalIxJDevice::GetDeviceName() const
{
return deviceName;
}
PString OpalIxJDevice::GetDescription() const
{
PStringStream name;
name << "Internet ";
switch (dwCardType) {
case 0 :
case 1 :
name << "PhoneJACK";
break;
case 3 :
name << "LineJACK";
break;
case 4 :
name << "PhoneJACK-Lite";
break;
case 5 :
name << "PhoneJACK-PCI";
break;
case 6 :
name << "PhoneCARD";
break;
default :
name << "xJACK";
}
name << " (" << deviceName << ')';
return name;
}
PStringArray OpalIxJDevice::GetAllNames() const
{
return GetDeviceNames();
}
unsigned OpalIxJDevice::GetLineCount()
{
return 1;
/*Each card has just one line that can be active.
Consequently, return (IsLineJACK() ? NumLines : 1); is wrong.*/
}
BOOL OpalIxJDevice::IsLinePresent(unsigned line, BOOL /* force */)
{
if (line != PSTNLine)
return FALSE;
BOOL stat = IOCTL(os_handle, IXJCTL_PSTN_LINETEST) == 1;
PThread::Sleep(2000);
// clear ring signal status
IsLineRinging(line);
return stat;
}
BOOL OpalIxJDevice::IsLineOffHook(unsigned line)
{
if (line == PSTNLine)
return pstnIsOffHook;
PWaitAndSignal m(exceptionMutex);
ExceptionInfo * info = GetException();
#ifdef MANUAL_FLASH
if (info->hookState != lastHookState) {
lastHookState = info->hookState;
if (lastHookState) {
currentHookState = lastHookState;
} else {
hookTimeout = FLASH_TIME;
}
} else if (!hookTimeout.IsRunning() && (currentHookState != info->hookState))
currentHookState = info->hookState;
return currentHookState;
#else
return info->hookState;
#endif
}
BOOL OpalIxJDevice::HasHookFlash(unsigned line)
{
if (line != POTSLine)
return FALSE;
PWaitAndSignal m(exceptionMutex);
ExceptionInfo * info = GetException();
BOOL flash = info->hasFlash;
info->hasFlash = FALSE;
return flash;
}
BOOL OpalIxJDevice::SetLineOffHook(unsigned line, BOOL newState)
{
if (line == POTSLine) {
#ifdef PHONE_WINK
IOCTL(os_handle, PHONE_WINK);
return TRUE;
#else
return FALSE;
#endif
}
pstnIsOffHook = newState;
if (!pstnIsOffHook) {
StopReadCodec(line);
StopWriteCodec(line);
}
// reset wink detected state going on or off hook
gotWink = FALSE;
IOCTL2(os_handle, PHONE_PSTN_SET_STATE, pstnIsOffHook ? PSTN_OFF_HOOK : PSTN_ON_HOOK);
return TRUE;
}
OpalIxJDevice::ExceptionInfo * OpalIxJDevice::GetException()
{
PINDEX i;
for (i = 0; i < MaxIxjDevices; i++)
if (exceptionInfo[i].fd == os_handle)
return &exceptionInfo[i];
PAssertAlways("Cannot find open device in exception list");
return NULL;
}
BOOL OpalIxJDevice::IsLineRinging(unsigned line, DWORD * /*cadence*/)
{
if (line != PSTNLine)
return FALSE;
PWaitAndSignal m(exceptionMutex);
ExceptionInfo * info = GetException();
BOOL ring = info->hasRing;
info->hasRing = FALSE;
return ring;
}
BOOL OpalIxJDevice::RingLine(unsigned line, DWORD cadence)
{
if (line != POTSLine)
return FALSE;
if (cadence == 0)
return ConvertOSError(IOCTL(os_handle, PHONE_RING_STOP));
//if (!ConvertOSError(IOCTL2(os_handle, PHONE_RING_CADENCE, cadence)))
// return FALSE;
int stat;
// Need to add something to set caller ID here
#if TELEPHONY_VERSION >= 3000
if (callerIdInfo.name[0] != '\0') {
stat = IOCTLP(os_handle, PHONE_RING_START, &callerIdInfo);
SetCallerID(line, "");
} else
#endif
stat = IOCTL2(os_handle, PHONE_RING_START, 0);
return ConvertOSError(stat);
}
BOOL OpalIxJDevice::RingLine(unsigned line, PINDEX nCadence, unsigned * pattern)
{
if (line >= GetLineCount())
return FALSE;
if (line != POTSLine)
return FALSE;
return RingLine(line, nCadence != 0 ? 0xaaa : 0);
}
BOOL OpalIxJDevice::IsLineDisconnected(unsigned line, BOOL checkForWink)
{
if (line >= GetLineCount())
return FALSE;
if (line != PSTNLine)
return !IsLineOffHook(line);
if (checkForWink) {
// if we got a wink previously, hangup
if (gotWink)
return TRUE;
// if we have not got a wink, then check for one
PWaitAndSignal m(exceptionMutex);
ExceptionInfo * info = GetException();
gotWink = info->hasWink;
info->hasWink = FALSE;
if (gotWink) {
PTRACE(3, "xJack\tDetected wink");
return TRUE;
}
}
if (IsToneDetected(line) & (BusyTone)) {
PTRACE(3, "xJack\tDetected end of call tone");
return TRUE;
}
return FALSE;
}
BOOL OpalIxJDevice::SetLineToLineDirect(unsigned line1, unsigned line2, BOOL connect)
{
if (connect && (line1 != line2))
IOCTL2(os_handle, IXJCTL_POTS_PSTN, 1);
else
IOCTL2(os_handle, IXJCTL_POTS_PSTN, 0);
return TRUE;
}
BOOL OpalIxJDevice::IsLineToLineDirect(unsigned line1, unsigned line2)
{
return FALSE;
}
BOOL OpalIxJDevice::ConvertOSError(int err)
{
PChannel::Errors normalisedError;
return PChannel::ConvertOSError(err, normalisedError, osError);
}
static const struct {
const char * mediaFormat;
PINDEX writeFrameSize;
PINDEX readFrameSize;
int mode;
int frameTime;
BOOL vad;
} CodecInfo[] = {
/* NOTE: These are enumerated in reverse order. */
{ OPAL_PCM16, 480, 480, LINEAR16, 30, FALSE }, // 480 bytes = 240 samples = 30ms
{ OPAL_G711_ULAW_64K, 240, 240, ULAW, 30, FALSE }, // 240 bytes = 240 samples = 30ms
{ OPAL_G711_ALAW_64K, 240, 240, ALAW, 30, FALSE }, // 240 bytes = 240 samples = 30ms
{ OPAL_G728, 60, 60, G728, 30, FALSE }, // 60 bytes = 12 frames = 30ms
{ OPAL_G729A, 10, 10, G729, 10, FALSE }, // 10 bytes = 1 frame = 10 ms
{ OPAL_G729AB, 10, 10, G729B, 10, TRUE }, // 10 bytes = 1 frame = 10 ms
{ OPAL_G7231_5k3 , 24, 20, G723_53, 30, FALSE }, // 20 bytes = 1 frame = 30 ms
{ OPAL_G7231_6k3, 24, 24, G723_63, 30, FALSE }, // 24 bytes = 1 frame = 30 ms
{ OPAL_G7231A_5k3 , 24, 20, G723_53, 30, TRUE }, // 20 bytes = 1 frame = 30 ms
{ OPAL_G7231A_6k3, 24, 24, G723_63, 30, TRUE } // 24 bytes = 1 frame = 30 ms
};
OpalMediaFormatList OpalIxJDevice::GetMediaFormats() const
{
OpalMediaFormatList codecs;
PINDEX idx = PARRAYSIZE(CodecInfo);
while (idx-- > 0) {
phone_capability cap;
cap.captype = codec;
cap.cap = CodecInfo[idx].mode;
if (IOCTLP(os_handle, PHONE_CAPABILITIES_CHECK, &cap))
codecs += CodecInfo[idx].mediaFormat;
}
return codecs;
}
static PINDEX FindCodec(const OpalMediaFormat & mediaFormat)
{
for (PINDEX codecType = 0; codecType < PARRAYSIZE(CodecInfo); codecType++) {
if (mediaFormat == CodecInfo[codecType].mediaFormat)
return codecType;
}
return P_MAX_INDEX;
}
BOOL OpalIxJDevice::SetReadFormat(unsigned line, const OpalMediaFormat & mediaFormat)
{
{
PWaitAndSignal mutex(toneMutex);
if (tonePlaying) {
tonePlaying = FALSE;
IOCTL(os_handle, PHONE_CPT_STOP);
}
}
PWaitAndSignal mutex(readMutex);
if (!readStopped) {
IOCTL(os_handle, PHONE_REC_STOP);
readStopped = TRUE;
OpalLineInterfaceDevice::StopReadCodec(line);
}
readCodecType = FindCodec(mediaFormat);
if (readCodecType == P_MAX_INDEX) {
PTRACE(1, "xJack\tUnsupported read codec requested: " << mediaFormat);
return FALSE;
}
if (!writeStopped && readCodecType != writeCodecType) {
PTRACE(1, "xJack\tAsymmectric codecs requested: "
"read=" << CodecInfo[readCodecType].mediaFormat <<
" write=" << CodecInfo[writeCodecType].mediaFormat);
return FALSE;
}
PTRACE(2, "IXJ\tSetting read codec to "
<< CodecInfo[readCodecType].mediaFormat
<< " code=" << CodecInfo[readCodecType].mode);
readFrameSize = CodecInfo[readCodecType].readFrameSize;
// set frame time
if (writeStopped)
IOCTL2(os_handle, PHONE_FRAME, CodecInfo[readCodecType].frameTime);
int stat = IOCTL2(os_handle, PHONE_REC_CODEC, CodecInfo[readCodecType].mode);
if (stat != 0) {
PTRACE(1, "IXJ\tSecond try on set record codec");
stat = IOCTL2(os_handle, PHONE_REC_CODEC, CodecInfo[readCodecType].mode);
if (stat != 0) {
PTRACE(1, "IXJ\tFailed second try on set record codec");
return FALSE;
}
}
// PHONE_REC_DEPTH does not set return value
IOCTL2(os_handle, PHONE_REC_DEPTH, 1);
// PHONE_REC_START does not set return value
stat = IOCTL(os_handle, PHONE_REC_START);
if (stat != 0) {
return FALSE;
}
readStopped = FALSE;
return TRUE;
}
BOOL OpalIxJDevice::SetWriteFormat(unsigned line, const OpalMediaFormat & mediaFormat)
{
{
PWaitAndSignal mutex(toneMutex);
if (tonePlaying) {
tonePlaying = FALSE;
IOCTL(os_handle, PHONE_CPT_STOP);
}
}
PWaitAndSignal mutex(readMutex);
if (!writeStopped) {
IOCTL(os_handle, PHONE_PLAY_STOP);
writeStopped = TRUE;
OpalLineInterfaceDevice::StopWriteCodec(line);
}
writeCodecType = FindCodec(mediaFormat);
if (writeCodecType == P_MAX_INDEX) {
PTRACE(1, "xJack\tUnsupported write codec requested: " << mediaFormat);
return FALSE;
}
if (!readStopped && writeCodecType != readCodecType) {
PTRACE(1, "xJack\tAsymmectric codecs requested: "
"read=" << CodecInfo[readCodecType].mediaFormat <<
" write=" << CodecInfo[writeCodecType].mediaFormat);
return FALSE;
}
PTRACE(2, "IXJ\tSetting write codec to "
<< CodecInfo[writeCodecType].mediaFormat
<< " code=" << CodecInfo[writeCodecType].mode);
writeFrameSize = CodecInfo[writeCodecType].writeFrameSize;
// set frame time
if (readStopped)
IOCTL2(os_handle, PHONE_FRAME, CodecInfo[writeCodecType].frameTime);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -