📄 ixjwin32.cxx
字号:
PTRACE(3, "xJack\tDetected dial or busy tone, line disconnected.");
return TRUE;
}
return FALSE;
}
BOOL OpalIxJDevice::SetLineToLineDirect(unsigned line1, unsigned line2, BOOL connect)
{
if (line1 >= GetLineCount() || line2 >= GetLineCount())
return FALSE;
if (line1 == line2)
return FALSE;
DWORD dwResult = 0;
return IoControl(IOCTL_DevCtrl_SetPotsToSlic, connect ? 0 : 1, &dwResult) && dwResult != 0;
}
BOOL OpalIxJDevice::IsLineToLineDirect(unsigned line1, unsigned line2)
{
if (line1 >= GetLineCount() || line2 >= GetLineCount())
return FALSE;
if (line1 == line2)
return FALSE;
// The IOCTL_DevCtrl_GetPotsToSlic is broken unless the line test has been
// performed and there is a PSTN line present.
if (!IsLinePresent(PSTNLine))
return FALSE;
DWORD dwResult = 1;
if (!IoControl(IOCTL_DevCtrl_GetPotsToSlic, 0, &dwResult))
return FALSE;
return dwResult == 0;
}
static const struct {
const char * mediaFormat;
unsigned dspBitMask:3; // bit0=8020,bit1=8021,bit2=8022
unsigned isG729:1;
unsigned isG7231:1;
unsigned vad:1;
PINDEX frameSize;
DWORD recordMode;
DWORD recordRate;
DWORD playbackMode;
DWORD playbackRate;
} CodecInfo[] = {
{ OPAL_PCM16, 7, 0, 0, 0, 0, RECORD_MODE_16LINEAR, 0, PLAYBACK_MODE_16LINEAR, 0 },
{ OPAL_G711_ULAW_64K, 7, 0, 0, 0, 0, RECORD_MODE_ULAW, 0, PLAYBACK_MODE_ULAW, 0 },
{ OPAL_G711_ALAW_64K, 7, 0, 0, 0, 0, RECORD_MODE_ALAW, 0, PLAYBACK_MODE_ALAW, 0 },
{ OPAL_G728, 2, 0, 0, 0, 20, RECORD_MODE_TRUESPEECH, RECORD_RATE_G728, PLAYBACK_MODE_TRUESPEECH, PLAYBACK_RATE_G728 },
{ OPAL_G729, 6, 1, 0, 0, 10, RECORD_MODE_TRUESPEECH, RECORD_RATE_G729, PLAYBACK_MODE_TRUESPEECH, PLAYBACK_RATE_G729 },
{ OPAL_G729AB, 6, 1, 0, 1, 10, RECORD_MODE_TRUESPEECH, RECORD_RATE_G729, PLAYBACK_MODE_TRUESPEECH, PLAYBACK_RATE_G729 },
// these two lines should be for the 5k3 codec, but this does not work properly in the driver so we lie
{ OPAL_G7231_5k3, 7, 0, 1, 0, 24, RECORD_MODE_TRUESPEECH, RECORD_RATE_G723_63, PLAYBACK_MODE_TRUESPEECH, PLAYBACK_RATE_G723_63 },
{ OPAL_G7231A_5k3, 7, 0, 1, 1, 24, RECORD_MODE_TRUESPEECH, RECORD_RATE_G723_63, PLAYBACK_MODE_TRUESPEECH, PLAYBACK_RATE_G723_63 },
{ OPAL_G7231_6k3, 7, 0, 1, 0, 24, RECORD_MODE_TRUESPEECH, RECORD_RATE_G723_63, PLAYBACK_MODE_TRUESPEECH, PLAYBACK_RATE_G723_63 },
{ OPAL_G7231A_6k3, 7, 0, 1, 1, 24, RECORD_MODE_TRUESPEECH, RECORD_RATE_G723_63, PLAYBACK_MODE_TRUESPEECH, PLAYBACK_RATE_G723_63 },
};
OpalMediaFormatList OpalIxJDevice::GetMediaFormats() const
{
OpalMediaFormatList codecs;
OpalIxJDevice * unconstThis = (OpalIxJDevice *)this;
DWORD dwIdCode = 0;
if (unconstThis->IoControl(IOCTL_DevCtrl_GetIdCode, 0, &dwIdCode)) {
unsigned dspBit = 1 << (dwIdCode&3);
PINDEX codec = PARRAYSIZE(CodecInfo);
while (codec-- > 0) {
BOOL add = (CodecInfo[codec].dspBitMask&dspBit) != 0;
if (add && CodecInfo[codec].isG729) {
DWORD hasG729 = 1;
add = unconstThis->IoControl(IOCTL_Device_GetG729Enable, 0, &hasG729) && hasG729;
}
if (add)
codecs += CodecInfo[codec].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)
{
StopReadCodec(line);
PWaitAndSignal mutex(readMutex);
IoControl(IOCTL_Record_Stop);
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\tAsymmetric codecs requested: "
"read=" << CodecInfo[readCodecType].mediaFormat
<< " write=" << CodecInfo[writeCodecType].mediaFormat);
return FALSE;
}
PTRACE(3, "xJack\tSetReadFormat(" << CodecInfo[readCodecType].mediaFormat << ')');
if (!IoControl(IOCTL_Codec_SetKHz, 8000))
return FALSE;
if (!IoControl(IOCTL_Record_SetBufferChannelLimit, 1))
return FALSE;
DWORD mode;
do {
if (!IoControl(IOCTL_Record_SetRECMODE, CodecInfo[readCodecType].recordMode))
return FALSE;
if (!IoControl(IOCTL_Record_GetRECMODE, 0, &mode))
return FALSE;
PTRACE_IF(3, mode != CodecInfo[readCodecType].recordMode,
"xJack\tSetRECMODE failed (" << mode << " -> " <<
CodecInfo[readCodecType].recordMode << "), retrying");
} while (mode != CodecInfo[readCodecType].recordMode);
DWORD rate;
do {
if (!IoControl(IOCTL_Record_SetRate, CodecInfo[readCodecType].recordRate))
return FALSE;
if (!IoControl(IOCTL_Record_GetRate, 0, &rate))
return FALSE;
PTRACE_IF(3, rate != CodecInfo[readCodecType].recordRate,
"xJack\tRecord_SetRate failed (" << rate << " -> " <<
CodecInfo[readCodecType].recordRate << "), retrying");
} while (rate != CodecInfo[readCodecType].recordRate);
readFrameSize = CodecInfo[readCodecType].frameSize;
if (readFrameSize == 0) {
DWORD frameWords;
if (IoControl(IOCTL_Record_GetFrameSize, 0, &frameWords))
readFrameSize = frameWords*2;
else {
PTRACE(1, "xJack\tCould not get record frame size.");
return FALSE;
}
}
SetVAD(line, CodecInfo[readCodecType].vad);
if (!IoControl(driverVersion >= NEW_DRIVER_VERSION ? IOCTL_Record_Start
: IOCTL_Record_Start_Old))
return FALSE;
readStopped = FALSE;
return TRUE;
}
BOOL OpalIxJDevice::SetWriteFormat(unsigned line, const OpalMediaFormat & mediaFormat)
{
StopWriteCodec(line);
PWaitAndSignal mutex(writeMutex);
IoControl(IOCTL_Playback_Stop);
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\tAsymmetric codecs requested: "
"read=" << CodecInfo[readCodecType].mediaFormat
<< " write=" << CodecInfo[writeCodecType].mediaFormat);
return FALSE;
}
PTRACE(3, "xJack\tSetWriteFormat(" << CodecInfo[writeCodecType].mediaFormat << ')');
if (!IoControl(IOCTL_Codec_SetKHz, 8000))
return FALSE;
if (!IoControl(IOCTL_Playback_SetBufferChannelLimit, 1))
return FALSE;
DWORD mode;
do {
if (!IoControl(IOCTL_Playback_SetPLAYMODE, CodecInfo[writeCodecType].playbackMode))
return FALSE;
if (!IoControl(IOCTL_Playback_GetPLAYMODE, 0, &mode))
return FALSE;
PTRACE_IF(2, mode != CodecInfo[writeCodecType].playbackMode,
"xJack\tSetPLAYMODE failed (" << mode << " -> " <<
CodecInfo[writeCodecType].playbackMode << "), retrying");
} while (mode != CodecInfo[writeCodecType].playbackMode);
DWORD rate;
do {
if (!IoControl(IOCTL_Playback_SetRate, CodecInfo[writeCodecType].playbackRate))
return FALSE;
if (!IoControl(IOCTL_Playback_GetRate, 0, &rate))
return FALSE;
PTRACE_IF(2, rate != CodecInfo[writeCodecType].playbackRate,
"xJack\tPlayback_SetRate failed (" << rate << " -> " <<
CodecInfo[writeCodecType].playbackRate << "), retrying");
} while (rate != CodecInfo[writeCodecType].playbackRate);
writeFrameSize = CodecInfo[writeCodecType].frameSize;
if (writeFrameSize == 0) {
DWORD frameWords;
if (IoControl(IOCTL_Playback_GetFrameSize, 0, &frameWords))
writeFrameSize = frameWords*2;
else {
PTRACE(1, "xJack\tCould not get playback frame size.");
return FALSE;
}
}
SetVAD(line, CodecInfo[writeCodecType].vad);
if (!IoControl(driverVersion >= NEW_DRIVER_VERSION ? IOCTL_Playback_Start
: IOCTL_Playback_Start_Old))
return FALSE;
writeStopped = FALSE;
return TRUE;
}
OpalMediaFormat OpalIxJDevice::GetReadFormat(unsigned)
{
if (readCodecType == P_MAX_INDEX)
return "";
return CodecInfo[readCodecType].mediaFormat;
}
OpalMediaFormat OpalIxJDevice::GetWriteFormat(unsigned)
{
if (writeCodecType == P_MAX_INDEX)
return "";
return CodecInfo[writeCodecType].mediaFormat;
}
BOOL OpalIxJDevice::SetRawCodec(unsigned)
{
if (inRawMode)
return FALSE;
PTRACE(3, "xJack\tSetRawCodec()");
// Default to 30ms frames of 16 bit PCM data
readFrameSize = 480;
writeFrameSize = 480;
if (hReadEvent == NULL)
hReadEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
if (hWriteEvent == NULL)
hWriteEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
HANDLE hEventArr[2];
if (GetOperatingSystem() == IsWindows9x) {
CHAR K32Path[MAX_PATH];
HINSTANCE hK32;
HANDLE (WINAPI *OpenVxDHandle)(HANDLE);
GetSystemDirectory(K32Path, MAX_PATH);
strcat(K32Path, "\\kernel32.dll");
hK32 = LoadLibrary(K32Path);
OpenVxDHandle = (HANDLE(WINAPI *)(HANDLE))GetProcAddress(hK32, "OpenVxDHandle");
hEventArr[0] = OpenVxDHandle(hReadEvent);
hEventArr[1] = OpenVxDHandle(hWriteEvent);
FreeLibrary(hK32);
}
else
{
hEventArr[0] = hReadEvent;
hEventArr[1] = hWriteEvent;
}
readMutex.Wait();
writeMutex.Wait();
DWORD dwReturn, dwBytesReturned;
inRawMode = IoControl(IOCTL_Fax_Start,
hEventArr, sizeof(hEventArr),
&dwReturn, sizeof(dwReturn), &dwBytesReturned);
readCodecType = writeCodecType = 0;
readStopped = writeStopped = !inRawMode;
readMutex.Signal();
writeMutex.Signal();
return inRawMode;
}
BOOL OpalIxJDevice::StopReadCodec(unsigned line)
{
if (inRawMode)
return StopRawCodec(line);
PTRACE(3, "xJack\tStopping read codec");
readMutex.Wait();
if (!readStopped) {
readStopped = TRUE;
IoControl(IOCTL_Record_Stop);
}
readMutex.Signal();
return OpalLineInterfaceDevice::StopReadCodec(line);
}
BOOL OpalIxJDevice::StopWriteCodec(unsigned line)
{
if (inRawMode)
return StopRawCodec(line);
PTRACE(3, "xJack\tStopping write codec");
writeMutex.Wait();
if (!writeStopped) {
writeStopped = TRUE;
IoControl(IOCTL_Playback_Stop);
}
writeMutex.Signal();
return OpalLineInterfaceDevice::StopWriteCodec(line);
}
BOOL OpalIxJDevice::StopRawCodec(unsigned line)
{
if (!inRawMode) {
BOOL ok = StopReadCodec(line);
return StopWriteCodec(line) && ok;
}
PTRACE(3, "xJack\tStopping raw codec");
readMutex.Wait();
writeMutex.Wait();
readStopped = TRUE;
writeStopped = TRUE;
BOOL ok = IoControl(IOCTL_Fax_Stop);
readMutex.Signal();
writeMutex.Signal();
inRawMode = FALSE;
OpalLineInterfaceDevice::StopReadCodec(line);
OpalLineInterfaceDevice::StopWriteCodec(line);
return ok;
}
PINDEX OpalIxJDevice::GetReadFrameSize(unsigned)
{
return readFrameSize;
}
BOOL OpalIxJDevice::SetReadFrameSize(unsigned, PINDEX size)
{
if (!inRawMode)
return FALSE;
readFrameSize = size;
return TRUE;
}
PINDEX OpalIxJDevice::GetWriteFrameSize(unsigned)
{
return writeFrameSize;
}
BOOL OpalIxJDevice::SetWriteFrameSize(unsigned, PINDEX size)
{
if (!inRawMode)
return FALSE;
writeFrameSize = size;
return TRUE;
}
BOOL OpalIxJDevice::ReadFrame(unsigned, void * buffer, PINDEX & count)
{
count = 0;
PWaitAndSignal mutex(readMutex);
if (readStopped)
return FALSE;
DWORD dwBytesReturned = 0;
if (inRawMode) {
if (WaitForSingleObjectEx(hReadEvent, 1000, TRUE) != WAIT_OBJECT_0) {
osError = EAGAIN;
PTRACE(1, "xJack\tRead Timeout!");
return FALSE;
}
IoControl(IOCTL_Fax_Read, NULL, 0, buffer, readFrameSize, &dwBytesReturned);
count = (PINDEX)dwBytesReturned;
return TRUE;
}
BOOL reblockG729 = CodecInfo[readCodecType].isG729;
WORD temp_frame_buffer[6];
PWin32Overlapped overlap;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -