📄 ixjwin32.cxx
字号:
"%02u%02u%02u%02u",
theTime.GetMonth(),
theTime.GetDay(),
theTime.GetHour(),
theTime.GetMinute());
buffer[13] = 2;
buffer[14] = (char)numberLength;
strcpy(&buffer[15], number);
buffer[15+numberLength] = 7;
buffer[16+numberLength] = (char)nameLength;
strcpy(&buffer[17+numberLength], name);
DWORD dwReturn = 0;
DWORD dwBytesReturned;
return IoControl(IOCTL_FSK_SetMsgData,
buffer, 17+numberLength+nameLength,
&dwReturn, sizeof(dwReturn), &dwBytesReturned);
}
BOOL OpalIxJDevice::SendCallerIDOnCallWaiting(unsigned, const PString & /*idString*/)
{
return FALSE;
}
BOOL OpalIxJDevice::SendVisualMessageWaitingIndicator(unsigned line, BOOL isOn)
{
if (IsLineOffHook(line))
return FALSE;
BYTE buffer[] = { 0, 130, 3, 11, 1, 0 };
if (isOn)
buffer[5] = 255;
DWORD dwReturn = 0;
DWORD dwBytesReturned;
return IoControl(IOCTL_FSK_SetMsgData,
buffer, sizeof(buffer),
&dwReturn, sizeof(dwReturn), &dwBytesReturned);
}
BOOL OpalIxJDevice::PlayDTMF(unsigned line,
const char * digits,
DWORD onTime, DWORD offTime)
{
while (*digits != '\0') {
DWORD dwToneIndex;
int digit = toupper(*digits++);
switch (digit) {
case '0' :
dwToneIndex = IDLE_TONE_0;
break;
case '1' :
dwToneIndex = IDLE_TONE_1;
break;
case '2' :
dwToneIndex = IDLE_TONE_2;
break;
case '3' :
dwToneIndex = IDLE_TONE_3;
break;
case '4' :
dwToneIndex = IDLE_TONE_4;
break;
case '5' :
dwToneIndex = IDLE_TONE_5;
break;
case '6' :
dwToneIndex = IDLE_TONE_6;
break;
case '7' :
dwToneIndex = IDLE_TONE_7;
break;
case '8' :
dwToneIndex = IDLE_TONE_8;
break;
case '9' :
dwToneIndex = IDLE_TONE_9;
break;
case '*' :
dwToneIndex = IDLE_TONE_STAR;
break;
case '#' :
dwToneIndex = IDLE_TONE_POUND;
break;
case 'A' :
dwToneIndex = IDLE_TONE_A;
break;
case 'B' :
dwToneIndex = IDLE_TONE_B;
break;
case 'C' :
dwToneIndex = IDLE_TONE_C;
break;
case 'D' :
dwToneIndex = IDLE_TONE_D;
break;
case ',' :
dwToneIndex = IDLE_TONE_NOTONE;
Sleep(2000);
break;
default :
if ('E' <= digit && digit <= ('E' + 11))
dwToneIndex = (digit - 'E') + 13;
else {
dwToneIndex = IDLE_TONE_NOTONE;
Sleep(onTime+offTime);
}
break;
}
if (dwToneIndex != IDLE_TONE_NOTONE)
if (!InternalPlayTone(line, dwToneIndex, onTime, offTime, TRUE))
return FALSE;
}
return TRUE;
}
char OpalIxJDevice::ReadDTMF(unsigned)
{
DWORD dwNewDigit;
if (!IoControl(IOCTL_Filter_GetDTMFDigit, lastDTMFDigit, &dwNewDigit))
return '\0';
if (dwNewDigit == 0 || dwNewDigit == lastDTMFDigit)
return '\0';
lastDTMFDigit = dwNewDigit;
static char const dtmf[16] = {
'D','1','2','3','4','5','6','7','8','9','*','0','#','A','B','C'
};
PTRACE(3, "xJack\tDetected DTMF tone: " << dtmf[dwNewDigit&0xf]);
return dtmf[dwNewDigit&0xf];
}
BOOL OpalIxJDevice::GetRemoveDTMF(unsigned)
{
DWORD result = FALSE;
if (!IoControl(IOCTL_Record_GetDisableOnDTMFDetect, 0, &result))
return FALSE;
return result != 0;
}
BOOL OpalIxJDevice::SetRemoveDTMF(unsigned, BOOL state)
{
return IoControl(IOCTL_Record_SetDisableOnDTMFDetect, state);
}
unsigned OpalIxJDevice::IsToneDetected(unsigned line)
{
if (line >= GetLineCount())
return NoTone;
if (!EnableAudio(line, TRUE))
return NoTone;
int tones = NoTone;
DWORD dwReturn = 0;
if (IoControl(IOCTL_Filter_IsToneCadenceValid, 0, &dwReturn) && dwReturn != 0)
tones |= DialTone;
dwReturn = 0;
if (IoControl(IOCTL_Filter_IsToneCadenceValid, 1, &dwReturn) && dwReturn != 0)
tones |= RingTone;
dwReturn = 0;
if (IoControl(IOCTL_Filter_IsToneCadenceValid, 2, &dwReturn) && dwReturn != 0)
tones |= BusyTone;
dwReturn = 0;
if (IoControl(IOCTL_Filter_IsToneCadenceValid, 3, &dwReturn) && dwReturn != 0)
tones |= CNGTone;
return tones;
}
BOOL OpalIxJDevice::SetToneFilterParameters(unsigned /*line*/,
CallProgressTones tone,
unsigned lowFrequency,
unsigned highFrequency,
PINDEX numCadences,
const unsigned * onTimes,
const unsigned * offTimes)
{
DWORD toneIndex;
switch (tone) {
case DialTone :
toneIndex = 0;
break;
case RingTone :
toneIndex = 1;
break;
case BusyTone :
toneIndex = 2;
break;
case CNGTone :
toneIndex = 3;
break;
default :
PTRACE(1, "xJack\tCannot set filter for tone: " << tone);
return FALSE;
}
if (numCadences > 0) {
qthDetectToneCadence dtc;
if (numCadences > PARRAYSIZE(dtc.element)) {
PTRACE(1, "xJack\tToo many cadence elements: " << numCadences);
return FALSE;
}
dtc.ulFilter = toneIndex;
dtc.ulNumElements = numCadences;
dtc.type = QTH_DETECT_TONE_TYPE_ADD;
dtc.term = QTH_DETECT_TONE_REPEAT_ALL;
dtc.ulTolerance = 10; // in %
dtc.ulMinDetectLoops = 1;
memset(dtc.element, 0, sizeof(dtc.element));
for (PINDEX i = 0; i < numCadences; i++) {
dtc.element[i].ulOnTime = onTimes[i];
dtc.element[i].ulOffTime = offTimes[i];
}
PTRACE(2, "xJack\tSetting cadence for tone index " << toneIndex
<< ", num=" << numCadences
<< ' ' << dtc.element[0].ulOnTime
<< '-' << dtc.element[0].ulOffTime);
DWORD dwReturn = 0;
DWORD dwBytesReturned;
IoControl(IOCTL_Filter_DetectToneCadence, &dtc, sizeof(dtc),
&dwReturn, sizeof(dwReturn), &dwBytesReturned, FALSE);
}
static struct FilterTableEntry {
unsigned lowFrequency;
unsigned highFrequency;
unsigned predefinedFilterSet; // 0 = custom
short coefficients[19];
} const FilterTable[] = {
{ 300, 640, 4 },
{ 300, 500, 5 },
{ 1100,1100, 6 },
{ 350, 350, 7 },
{ 400, 400, 8 },
{ 480, 480, 9 },
{ 440, 440, 10},
{ 620, 620, 11},
{ 425, 425, 0, 30850,-32534,-504,0,504,30831,-32669,24303,-22080,24303,30994,-32673, 1905, -1811, 1905,5,129,17,0xff5 },
{ 350, 440, 0, 30634,-31533,-680,0,680,30571,-32277,12894,-11945,12894,31367,-32379,23820,-23104,23820,7,159,21,0x0FF5 },
{ 400, 450, 0, 30613,-32031,-618,0,618,30577,-32491, 9612, -8935, 9612,31071,-32524,21596,-20667,21596,7,159,21,0x0FF5 },
};
FilterTableEntry match = { 0, 0, UINT_MAX };
PINDEX i;
// Look for exact match
for (i = 0; i < PARRAYSIZE(FilterTable); i++) {
if (lowFrequency == FilterTable[i].lowFrequency &&
highFrequency == FilterTable[i].highFrequency) {
match = FilterTable[i];
break;
}
}
if (match.predefinedFilterSet == UINT_MAX) {
// If single frequency, make a band out of it, +/- 5%
if (lowFrequency == highFrequency) {
lowFrequency -= lowFrequency/20;
highFrequency += highFrequency/20;
}
// Try again looking for a band that is just a bit larger than required, no
// more than twice the size required.
for (i = 0; i < PARRAYSIZE(FilterTable); i++) {
if (lowFrequency > FilterTable[i].lowFrequency &&
highFrequency < FilterTable[i].highFrequency &&
2*(highFrequency - lowFrequency) >
(FilterTable[i].highFrequency - FilterTable[i].lowFrequency)) {
match = FilterTable[i];
break;
}
}
}
if (match.predefinedFilterSet == UINT_MAX) {
PTRACE(1, "xJack\tInvalid frequency for fixed filter sets: "
<< lowFrequency << '-' << highFrequency);
return FALSE;
}
struct {
DWORD dwFilterNum;
union {
DWORD predefinedFilterSet;
short coefficients[19];
};
} filterSet;
PINDEX sizeOfFilterSet;
if (match.predefinedFilterSet != 0) {
filterSet.predefinedFilterSet = match.predefinedFilterSet;
sizeOfFilterSet = sizeof(filterSet.dwFilterNum) + sizeof(filterSet.predefinedFilterSet);
}
else {
memcpy(filterSet.coefficients, match.coefficients, sizeof(filterSet.coefficients));
sizeOfFilterSet = sizeof(filterSet);
}
filterSet.dwFilterNum = toneIndex;
PTRACE(2, "xJack\tSetting filter for tone index " << toneIndex
<< " freq: " << match.lowFrequency << '-' << match.highFrequency);
DWORD dwReturn = 0;
DWORD dwBytesReturned;
return IoControl(IOCTL_Filter_ProgramFilter, &filterSet, sizeOfFilterSet,
&dwReturn, sizeof(dwReturn), &dwBytesReturned, FALSE);
}
BOOL OpalIxJDevice::PlayTone(unsigned line, CallProgressTones tone)
{
switch (tone) {
case DialTone :
return InternalPlayTone(line, IDLE_TONE_DIAL, 0, 0, FALSE);
case RingTone :
return InternalPlayTone(line, IDLE_TONE_RING, 0, 0, FALSE);
case BusyTone :
return InternalPlayTone(line, IDLE_TONE_BUSY, 0, 0, FALSE);
case ClearTone :
return InternalPlayTone(line, IDLE_TONE_BUSY, 0, 0, FALSE);
default :
return InternalPlayTone(line, IDLE_TONE_NOTONE, 0, 0, FALSE);
}
}
BOOL OpalIxJDevice::IsTonePlaying(unsigned)
{
return PTimer::Tick() < toneSendCompletionTime;
}
BOOL OpalIxJDevice::StopTone(unsigned)
{
PTRACE(3, "xJack\tStopping tones");
return IoControl(IOCTL_Idle_StopTone);
}
BOOL OpalIxJDevice::InternalPlayTone(unsigned line,
DWORD toneIndex,
DWORD onTime, DWORD offTime,
BOOL synchronous)
{
StopTone(line);
PTRACE(3, "xJack\tPlaying tone: "
<< toneIndex << ' ' << onTime << ' ' << offTime << ' ' << synchronous);
IDLE_TONE tone;
tone.dwToneIndex = toneIndex;
tone.dwToneOnPeriod = onTime;
tone.dwToneOffPeriod = offTime;
tone.dwDuration = tone.dwToneOnPeriod+tone.dwToneOffPeriod;
tone.dwMasterGain = 15;
DWORD dwReturn = 0;
DWORD dwBytesReturned;
if (!IoControl(IOCTL_Idle_PlayTone,
&tone, sizeof(tone),
&dwReturn, sizeof(dwReturn), &dwBytesReturned) ||
dwBytesReturned != sizeof(dwReturn) ||
dwReturn == 0)
return FALSE;
toneSendCompletionTime = PTimer::Tick() + (int)tone.dwDuration - 1;
if (synchronous)
Sleep(tone.dwDuration);
return TRUE;
}
BOOL OpalIxJDevice::SetCountryCode(T35CountryCodes country)
{
OpalLineInterfaceDevice::SetCountryCode(country);
// if a LineJack, the set the DAA coeffiecients
if (!IsLineJACK())
return FALSE;
if (country == UnknownCountry)
return TRUE;
static struct {
T35CountryCodes t35Code;
DWORD ixjCode;
} ixjCountry[] = {
{ UnitedStates, COEFF_US },
{ Australia, COEFF_AUSTRALIA },
{ Czechoslovakia,COEFF_CZECH },
{ France, COEFF_FRANCE },
{ Germany, COEFF_GERMANY },
{ Italy, COEFF_ITALY },
{ Japan, COEFF_JAPAN },
{ KoreaRepublic, COEFF_SOUTH_KOREA },
{ NewZealand, COEFF_NEW_ZEALAND },
{ Norway, COEFF_NORWAY },
{ Philippines, COEFF_PHILIPPINES },
{ Poland, COEFF_POLAND },
{ SouthAfrica, COEFF_SOUTH_AFRICA },
{ Sweden, COEFF_SWEDEN },
{ UnitedKingdom, COEFF_UK }
};
PINDEX i;
for (i = PARRAYSIZE(ixjCountry)-1; i > 0; i--) {
if (ixjCountry[i].t35Code == countryCode)
break;
}
PTRACE(2, "xJack\tSetting coefficient
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -