📄 ixjunix.cxx
字号:
int stat = IOCTL2(os_handle, PHONE_PLAY_CODEC, CodecInfo[writeCodecType].mode);
if (stat != 0) {
PTRACE(1, "IXJ\tSecond try on set play codec");
stat = IOCTL2(os_handle, PHONE_PLAY_CODEC, CodecInfo[writeCodecType].mode);
if (stat != 0)
return FALSE;
}
// PHONE_PLAY_DEPTH does not set return value
IOCTL2(os_handle, PHONE_PLAY_DEPTH, 1);
// start the codec
stat = IOCTL(os_handle, PHONE_PLAY_START);
if (stat != 0) {
PTRACE(1, "IXJ\tSecond try on start play codec");
stat = IOCTL(os_handle, PHONE_PLAY_START);
if (stat != 0)
return FALSE;
}
// wait for codec to become writable. If it doesn't happen after 100ms, give error
fd_set wfds;
struct timeval ts;
for (;;) {
FD_ZERO(&wfds);
FD_SET(os_handle, &wfds);
ts.tv_sec = 0;
ts.tv_usec = 100*1000;
stat = ::select(os_handle+1, NULL, &wfds, NULL, &ts);
if (stat > 0)
break;
else if (stat == 0) {
PTRACE(1, "IXJ\tWrite timeout on startup");
return FALSE;
}
if (errno != EINTR) {
PTRACE(1, "IXJ\tWrite error on startup");
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 line)
{
if (inRawMode)
return FALSE;
PTRACE(2, "IXJ\tSetting raw codec mode");
// save the current volumes
savedPlayVol = userPlayVol;
savedRecVol = userRecVol;
savedAEC = aecLevel;
if (!SetReadFormat (line, CodecInfo[0].mediaFormat) ||
!SetWriteFormat(line, CodecInfo[0].mediaFormat)) {
PTRACE(1, "IXJ\t Failed to set raw codec");
StopReadCodec(line);
StopWriteCodec(line);
return FALSE;
}
// set the new (maximum) volumes
SetAEC (line, AECOff);
SetRecordVolume(line, 100);
SetPlayVolume (line, 100);
// stop values from changing
inRawMode = TRUE;
return TRUE;
}
BOOL OpalIxJDevice::StopReadCodec(unsigned line)
{
PTRACE(3, "xJack\tStopping read codec");
PWaitAndSignal mutex(readMutex);
if (!readStopped) {
IOCTL(os_handle, PHONE_REC_STOP);
readStopped = TRUE;
}
return OpalLineInterfaceDevice::StopReadCodec(line);
}
BOOL OpalIxJDevice::StopWriteCodec(unsigned line)
{
PTRACE(3, "xJack\tStopping write codec");
PWaitAndSignal mutex(readMutex);
if (!writeStopped) {
IOCTL(os_handle, PHONE_PLAY_STOP);
writeStopped = TRUE;
}
return OpalLineInterfaceDevice::StopWriteCodec(line);
}
BOOL OpalIxJDevice::StopRawCodec(unsigned line)
{
if (!inRawMode)
return FALSE;
StopReadCodec(line);
StopWriteCodec(line);
// allow values to change again
inRawMode = FALSE;
SetPlayVolume (line, savedPlayVol);
SetRecordVolume(line, savedRecVol);
SetAEC (line, savedAEC);
OpalLineInterfaceDevice::StopReadCodec(line);
OpalLineInterfaceDevice::StopWriteCodec(line);
return TRUE;
}
PINDEX OpalIxJDevice::GetReadFrameSize(unsigned)
{
return readFrameSize;
}
BOOL OpalIxJDevice::SetReadFrameSize(unsigned, PINDEX)
{
return FALSE;
}
static void G728_Pack(const unsigned short * unpacked, BYTE * packed)
{
packed[0] = ((unpacked[0] & 0x3fc) >> 2);
packed[1] = ((unpacked[0] & 0x003) << 6) | ((unpacked[1] & 0x3f0) >> 4);
packed[2] = ((unpacked[1] & 0x00f) << 4) | ((unpacked[2] & 0x3c0) >> 6);
packed[3] = ((unpacked[2] & 0x03f) << 2) | ((unpacked[3] & 0x300) >> 8);
packed[4] = (unpacked[3] & 0x0ff);
}
static const PINDEX G723count[4] = { 24, 20, 4, 1 };
BOOL OpalIxJDevice::ReadFrame(unsigned, void * buffer, PINDEX & count)
{
{
PWaitAndSignal rmutex(readMutex);
count = 0;
if (readStopped) {
PTRACE(1, "IXJ\tRead stopped, so ReadFrame returns false");
return FALSE;
}
if (writeStopped) {
PThread::Sleep(30);
memset(buffer, 0, readFrameSize);
switch (CodecInfo[readCodecType].mode) {
case G723_63:
case G723_53:
*((DWORD *)buffer) = 0x02;
count = 4;
break;
case G729B:
*((WORD *)buffer) = 0;
count = 2;
break;
default:
memset(buffer, 0, readFrameSize);
count = readFrameSize;
break;
}
return TRUE;
}
WORD temp_frame_buffer[48]; // 30ms = 12 frames = 48 vectors = 48 WORDS for unpacked vectors
void * readBuf;
int readLen;
switch (CodecInfo[readCodecType].mode) {
case G728 :
readBuf = temp_frame_buffer;
readLen = sizeof(temp_frame_buffer);
break;
case G729B :
readBuf = temp_frame_buffer;
readLen = 12;
break;
default :
readBuf = buffer;
readLen = readFrameSize;
}
for (;;) {
fd_set rfds;
FD_ZERO(&rfds);
FD_SET(os_handle, &rfds);
struct timeval ts;
ts.tv_sec = 30;
ts.tv_usec = 0;
#if PTRACING
PTime then;
#endif
int stat = ::select(os_handle+1, &rfds, NULL, NULL, &ts);
if (stat == 0) {
PTRACE(1, "IXJ\tRead timeout:" << (PTime() - then));
return FALSE;
}
if (stat > 0) {
stat = ::read(os_handle, readBuf, readLen);
if (stat == (int)readLen)
break;
}
if ((stat >= 0) || (errno != EINTR)) {
PTRACE(1, "IXJ\tRead error = " << errno);
return FALSE;
}
PTRACE(1, "IXJ\tRead EINTR");
}
switch (CodecInfo[readCodecType].mode) {
case G723_63:
case G723_53:
count = G723count[(*(BYTE *)readBuf)&3];
break;
case G728 :
// for G728, pack four x 4 vectors
PINDEX i;
for (i = 0; i < 12; i++)
G728_Pack(temp_frame_buffer+i*4, ((BYTE *)buffer)+i*5);
count = readFrameSize;
break;
case G729B :
switch (temp_frame_buffer[0]) {
case 0 : // Silence
memset(buffer, 0, 10);
count = 10;
break;
case 1 : // Signal
memcpy(buffer, &temp_frame_buffer[1], 10);
count = 10;
break;
case 2 : // VAD
memcpy(buffer, &temp_frame_buffer[1], 2);
count = 2;
break;
default : // error
PTRACE(1, "IXJ\tIllegal value from codec in G729");
return FALSE;
}
break;
default :
count = readFrameSize;
}
}
PThread::Yield();
return TRUE;
}
PINDEX OpalIxJDevice::GetWriteFrameSize(unsigned)
{
return writeFrameSize;
}
BOOL OpalIxJDevice::SetWriteFrameSize(unsigned, PINDEX)
{
return FALSE;
}
static void G728_Unpack(const BYTE * packed, unsigned short * unpacked)
{
unpacked[0] = ( packed[0] << 2) | ((packed[1] & 0xc0) >> 6);
unpacked[1] = ((packed[1] & 0x3f) << 4) | ((packed[2] & 0xf0) >> 4);
unpacked[2] = ((packed[2] & 0x0f) << 6) | ((packed[3] & 0xfc) >> 2);
unpacked[3] = ((packed[3] & 0x03) << 8) | packed[4];
}
BOOL OpalIxJDevice::WriteFrame(unsigned, const void * buffer, PINDEX count, PINDEX & written)
{
{
PWaitAndSignal rmutex(readMutex);
written = 0;
if (writeStopped)
return FALSE;
if (readStopped) {
PThread::Sleep(30);
written = writeFrameSize;
return TRUE;
}
WORD temp_frame_buffer[48];
const void * writeBuf;
int writeLen;
switch (CodecInfo[writeCodecType].mode) {
case G723_63:
case G723_53:
writeBuf = buffer;
writeLen = 24;
written = G723count[(*(BYTE *)buffer)&3];
break;
case G728 :
writeBuf = temp_frame_buffer;
writeLen = sizeof(temp_frame_buffer);
// for G728, unpack twelve x 4 vectors
PINDEX i;
for (i = 0; i < 12; i++)
G728_Unpack(((const BYTE *)buffer)+i*5, temp_frame_buffer+i*4);
written = 60;
break;
case G729B :
writeBuf = temp_frame_buffer;
writeLen = 12;
if (count == 2) {
temp_frame_buffer[0] = 2;
temp_frame_buffer[1] = *(const WORD *)buffer;
memset(&temp_frame_buffer[2], 0, 8);
written = 2;
}
else {
if (memcmp(buffer, "\0\0\0\0\0\0\0\0\0", 10) != 0)
temp_frame_buffer[0] = 1;
else
temp_frame_buffer[0] = 0;
memcpy(&temp_frame_buffer[1], buffer, 10);
written = 10;
}
break;
default :
writeBuf = buffer;
writeLen = writeFrameSize;
written = writeFrameSize;
}
if (count < written) {
osError = EINVAL;
PTRACE(1, "xJack\tWrite of too small a buffer : " << count << " vs " << written);
return FALSE;
}
for (;;) {
fd_set wfds;
FD_ZERO(&wfds);
FD_SET(os_handle, &wfds);
struct timeval ts;
ts.tv_sec = 5;
ts.tv_usec = 0;
int stat = ::select(os_handle+1, NULL, &wfds, NULL, &ts);
if (stat == 0) {
PTRACE(1, "IXJ\tWrite timeout");
return FALSE;
}
if (stat > 0) {
stat = ::write(os_handle, writeBuf, writeLen);
if (stat == (int)writeLen)
break;
}
if ((stat >= 0) || (errno != EINTR)) {
PTRACE(1, "IXJ\tWrite error = " << errno);
return FALSE;
}
PTRACE(1, "IXJ\tWrite EINTR");
}
}
// PTRACE(4, "IXJ\tWrote " << writeLen << " bytes to codec");
PThread::Yield();
return TRUE;
}
unsigned OpalIxJDevice::GetAverageSignalLevel(unsigned, BOOL playback)
{
return IOCTL(os_handle, playback ? PHONE_PLAY_LEVEL : PHONE_REC_LEVEL);
}
BOOL OpalIxJDevice::EnableAudio(unsigned line, BOOL enable)
{
if (line >= GetLineCount())
return FALSE;
int port = PORT_SPEAKER;
if (enable) {
if (enabledAudioLine != line) {
if (enabledAudioLine != UINT_MAX && exclusiveAudioMode) {
PTRACE(3, "xJack\tEnableAudio on port when already enabled other port.");
return FALSE;
}
enabledAudioLine = line;
}
port = (line == POTSLine) ? PORT_POTS : PORT_PSTN;
}
else
enabledAudioLine = UINT_MAX;
return ConvertOSError(IOCTL2(os_handle, IXJCTL_PORT, port));
}
BOOL OpalIxJDevice::IsAudioEnabled(unsigned line)
{
return enabledAudioLine == line;
}
PINDEX OpalIxJDevice::LogScaleVolume(unsigned line, PINDEX volume, BOOL isPlay)
{
PINDEX dspMax = isPlay ? 0x100 : 0x200;
switch (dwCardType) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -