📄 ixjwin32.cxx
字号:
DWORD dwBytesReturned; if (!IoControl(IOCTL_DevCtrl_LineGetCallerID, buffer, sizeof(buffer), &dwReturn, sizeof(dwReturn), &dwBytesReturned, FALSE)) return FALSE; PTRACE(3, "IxJ\tCaller ID:\n" << hex << setprecision(2) << PBYTEArray(buffer, sizeof(buffer)) << dec); if (buffer[0] != 128) return FALSE; PString name, timeStr; PINDEX totalLength = buffer[1]; PINDEX pos = 2; while (pos < totalLength) { switch (buffer[pos]) { case 1 : timeStr = PString((char *)&buffer[pos+2], buffer[pos+1]); break; case 2 : idString = PString((char *)&buffer[pos+2], buffer[pos+1]); break; case 7 : name = PString((char *)&buffer[pos+2], buffer[pos+1]); break; } pos += buffer[pos+1]+2; } if (full) { PTime now; PTime theTime(0, timeStr(6,7).AsUnsigned(), timeStr(4,5).AsUnsigned(), timeStr(2,3).AsUnsigned(), timeStr(0,1).AsUnsigned(), now.GetYear()); idString += '\t' + theTime.AsString(PTime::ShortDateTime) + '\t' + name; } return TRUE;}BOOL OpalIxJDevice::SetCallerID(unsigned line, const PString & idString){ if (line != POTSLine) return FALSE; if (idString.IsEmpty()) return TRUE; PString name, number; PTime theTime; PStringArray fields = idString.Tokenise('\t', TRUE); switch (fields.GetSize()) { case 3 : name = fields[2]; case 2 : theTime = PTime(fields[1]); case 1 : number = fields[0]; break; default : return FALSE; } PINDEX numberLength = number.GetLength(); PINDEX nameLength = name.GetLength(); char buffer[256]; buffer[0] = 1; buffer[1] = '\x80'; buffer[2] = (char)(14+numberLength+nameLength); buffer[3] = 1; buffer[4] = 8; sprintf(&buffer[5], "%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);#ifdef IOCTL_FSK_SetMsgData DWORD dwReturn = 0; DWORD dwBytesReturned; return IoControl(IOCTL_FSK_SetMsgData, buffer, 17+numberLength+nameLength, &dwReturn, sizeof(dwReturn), &dwBytesReturned, FALSE);#else return FALSE;#endif}BOOL OpalIxJDevice::PlayDTMF(unsigned line, const char * digits, DWORD onTime, DWORD offTime){ while (*digits != '\0') { DWORD dwToneIndex; switch (*digits++) { 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 : 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, "IxJ\tDetected DTMF tone: " << dtmf[dwNewDigit&0xf]); return dtmf[dwNewDigit&0xf];}BOOL OpalIxJDevice::GetRemoveDTMF(unsigned){ return FALSE;}BOOL OpalIxJDevice::SetRemoveDTMF(unsigned, BOOL /*state*/){ return FALSE;}OpalLineInterfaceDevice::CallProgressTones OpalIxJDevice::IsToneDetected(unsigned line){ if (line >= GetLineCount()) return NumTones; if (!EnableAudio(line, TRUE)) return NumTones; DWORD dwResult; if (!IoControl(IOCTL_Filter_LineMonitor, 0, &dwResult)) return NumTones; dwResult &= 0x0f00; if (dwResult == 0x300) return DialTone; if (dwResult == 0x600) return RingTone; if (dwResult == 0xc00) return BusyTone;#if PTRACING if (dwResult != 0) PTRACE(1, "xJack\tUnkown tone detected: " << hex << dwResult << dec);#endif return NumTones;}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); 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"); PWaitAndSignal mutexr(readMutex); PWaitAndSignal mutexw(writeMutex); if (!IoControl(IOCTL_Idle_StopTone)) return FALSE; // If doing a tone stop, need to restart read and write codec data if (!readStopped) IoControl(IOCTL_Record_Start); if (!writeStopped) IoControl(IOCTL_Playback_Start); return TRUE;}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, FALSE) || 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); return TRUE;}PStringArray OpalIxJDevice::GetDeviceNames(){ PStringArray array; PINDEX i; if (IsWindows95()) { PStringArray devices = PSoundChannel::GetDeviceNames(PSoundChannel::Player); for (i = 0; i < devices.GetSize(); i++) { if (devices[i].Find("Internet") != P_MAX_INDEX && (devices[i].Find("JACK") != P_MAX_INDEX || devices[i].Find("PhoneCARD") != P_MAX_INDEX)) { PINDEX pos = devices[i].Find('('); array[array.GetSize()] = devices[i](pos+1, devices[i].Find(')')-1); } } } else { const char qtKey[] = "HKEY_LOCAL_MACHINE\\SYSTEM\\CurrentControlSet\\Services" "\\QTJACK\\Parameters\\"; PString devbase; RegistryKey qtJack(qtKey, RegistryKey::ReadOnly); for (i = 0; qtJack.EnumKey(i, devbase); i++) { if (strncmp(devbase, "Device", 6) == 0) { RegistryKey device(qtKey + devbase, RegistryKey::ReadOnly); PString pnpdev; if (device.QueryValue("PnP Device", pnpdev)) { PString devpath = "\\\\.\\QTJack" + devbase; HANDLE hDriver = CreateFile(devpath, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED, NULL); if (hDriver != INVALID_HANDLE_VALUE) { if (strncmp(pnpdev, "ISAPNP", 6) == 0) array.SetAt(array.GetSize(), new PCaselessString(devpath + " (" + pnpdev.Mid(pnpdev.FindLast('\\')+1) + ')')); else if (strncmp(pnpdev, "PCI", 3) == 0) { DWORD devId = 0, bytesReturned; if (DeviceIoControl(hDriver, IOCTL_Device_GetSerialNumber, NULL, 0, &devId, sizeof(devId), &bytesReturned, NULL) && bytesReturned == sizeof(devId) && devId != 0) array.SetAt(array.GetSize(), new PCaselessString(devpath + psprintf(" (%08X)", devId))); } CloseHandle(hDriver); } } } } } return array;}BOOL OpalIxJDevice::IoControl(DWORD dwIoControlCode, DWORD inParam, DWORD * outParam){ DWORD dwDummy; if (outParam == NULL) outParam = &dwDummy; DWORD dwBytesReturned = 0; return IoControl(dwIoControlCode, &inParam, sizeof(DWORD), outParam, sizeof(DWORD), &dwBytesReturned, FALSE) && dwBytesReturned == sizeof(DWORD);}BOOL OpalIxJDevice::IoControl(DWORD dwIoControlCode, LPVOID lpInBuffer, DWORD nInBufferSize, LPVOID lpOutBuffer, DWORD nOutBufferSize, LPDWORD lpdwBytesReturned, BOOL wait){ if (hDriver == INVALID_HANDLE_VALUE) return FALSE; OVERLAPPED overlap; memset(&overlap, 0, sizeof(overlap)); if (wait) overlap.hEvent = CreateEvent(0, TRUE, 0, NULL); DWORD newError = ERROR_SUCCESS; if (!DeviceIoControl(hDriver, dwIoControlCode, lpInBuffer, nInBufferSize, lpOutBuffer, nOutBufferSize, lpdwBytesReturned, wait ? &overlap : NULL)) { newError = ::GetLastError(); while (newError == ERROR_IO_PENDING) { if (GetOverlappedResult(hDriver, &overlap, lpdwBytesReturned, TRUE)) newError = ERROR_SUCCESS; else newError = ::GetLastError(); } } if (wait) CloseHandle(overlap.hEvent); osError = newError; return newError == ERROR_SUCCESS;}/////////////////////////////////////////////////////////////////////////////
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -