⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ixjwin32.cxx

📁 sloedgy open sip stack source code
💻 CXX
📖 第 1 页 / 共 5 页
字号:
  if (!IoControl(IOCTL_Device_Read, NULL, 0,
                 reblockG729 ? temp_frame_buffer         : buffer,
                 reblockG729 ? sizeof(temp_frame_buffer) : readFrameSize,
                 &dwBytesReturned, &overlap))
    return FALSE;

  if (reblockG729) {
    switch (temp_frame_buffer[0]) {
      case 1 :
        memcpy(buffer, &temp_frame_buffer[1], 10);
        count = 10;
        break;
      case 2 :
        if (CodecInfo[readCodecType].vad) {
          *(WORD *)buffer = temp_frame_buffer[1];
          count = 2;
        }
        else {
          memset(buffer, 0, 10);
          count = 10;
        }
        break;
      default : // Must be old driver
        memcpy(buffer, temp_frame_buffer, 10);
        count = 10;
    }
  }
  else if (CodecInfo[readCodecType].isG7231) {
    // Pick out special cases for G.723.1 based codecs (variable length frames)
    static const PINDEX g723count[4] = { 24, 20, 4, 1 };
    count = g723count[(*(BYTE *)buffer)&3];
  }
  else
    count = (PINDEX)dwBytesReturned;

  return TRUE;
}


BOOL OpalIxJDevice::WriteFrame(unsigned, const void * buffer, PINDEX count, PINDEX & written)
{
  PWaitAndSignal mutex(writeMutex);
  if (writeStopped)
    return FALSE;

  DWORD dwResult = 0;
  DWORD dwBytesReturned = 0;

  if (inRawMode) {
    for (written = 0; written < count; written += dwResult) {
      if (WaitForSingleObjectEx(hWriteEvent, 1000, TRUE) != WAIT_OBJECT_0) {
        osError = EAGAIN;
        PTRACE(1, "xJack\tWrite Timeout!");
        return FALSE;
      }
      IoControl(IOCTL_Fax_Write, ((BYTE *)buffer)+written, count-written,
                &dwResult, sizeof(dwResult), &dwBytesReturned);
    }
    return TRUE;
  }

  WORD temp_frame_buffer[12];
  PINDEX bytesToWrite;

  if (CodecInfo[writeCodecType].isG7231) {
    // Pick out special cases for G.723.1 based codecs (variable length frames)
    switch ((*(BYTE *)buffer)&3) {
      case 0 : // 6.3kbps rate frame
        written = 24;
        break;
      case 1 : // 5.3kbps rate frame
        written = 20;
        break;
      case 2 : // a Silence Insertion Descriptor
        memset(temp_frame_buffer, 0, sizeof(temp_frame_buffer));
        *(DWORD *)(temp_frame_buffer) = *(const DWORD *)buffer;
        buffer = temp_frame_buffer;
        written = 4;
        break;
      case 3 : // repeat last CNG frame
        // Check for frame erasure command
        if (memcmp(buffer, "\xff\xff\xff\xff", 4) == 0)
          written = 24;
        else {
          memset(temp_frame_buffer, 0, sizeof(temp_frame_buffer));
          temp_frame_buffer[0] = 3;
          buffer = temp_frame_buffer;
          written = 1;
        }
        break;
    }
    bytesToWrite = 24;
  }
  else if (CodecInfo[writeCodecType].isG729) {
    if (count == 2) {
      PTRACE_IF(2, !CodecInfo[readCodecType].vad,
                "xJack\tG.729B frame received, but not selected.");
      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) {
#if 0
        memset(temp_frame_buffer, 0, 12);
#else
        // We really should be sending a full frame of zeros here, but the codec
        // makes a clicking sound if you do so send annex B CNG frames instead.
        temp_frame_buffer[0] = 2;
        memset(&temp_frame_buffer[1], 0, 10);
#endif
      }
      else {
        temp_frame_buffer[0] = 1;
        memcpy(&temp_frame_buffer[1], buffer, 10);
      }
      written = 10;
    }
    buffer = temp_frame_buffer;
    bytesToWrite = 12;
  }
  else {
    bytesToWrite = writeFrameSize;
    written = bytesToWrite;
  }

  if (count < written) {
    osError = EINVAL;
    PTRACE(1, "xJack\tWrite of too small a buffer");
    return FALSE;
  }

  PWin32Overlapped overlap;
  return IoControl(IOCTL_Device_Write, (void *)buffer, bytesToWrite,
                   &dwResult, sizeof(dwResult), &dwBytesReturned, &overlap);
}


unsigned OpalIxJDevice::GetAverageSignalLevel(unsigned, BOOL playback)
{
  DWORD dwLevel;
  if (!IoControl(playback ? IOCTL_Playback_GetAvgPlaybackLevel
                          : IOCTL_Record_GetAvgRecordLevel,
                 0, &dwLevel))
    return UINT_MAX;

  return dwLevel;
}


BOOL OpalIxJDevice::EnableAudio(unsigned line, BOOL enable)
{
  if (line >= GetLineCount())
    return FALSE;

  DWORD dwSource = ANALOG_SOURCE_SPEAKERPHONE;

  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;
    }
    dwSource = line == POTSLine ? ANALOG_SOURCE_POTSPHONE : ANALOG_SOURCE_PSTNLINE;
  }
  else
    enabledAudioLine = UINT_MAX;

  if (!IsLineJACK())
    return IoControl(IOCTL_DevCtrl_SetAnalogSource, dwSource);

  BOOL connected = IsLineToLineDirect(POTSLine, PSTNLine);
  IoControl(IOCTL_DevCtrl_SetLineJackMode,
                 dwSource == ANALOG_SOURCE_PSTNLINE ? LINEJACK_MODE_LINEJACK
                                                    : LINEJACK_MODE_PHONEJACK);
  SetLineToLineDirect(POTSLine, PSTNLine, connected);

  if (dwSource != ANALOG_SOURCE_PSTNLINE) {
    if (!IoControl(IOCTL_DevCtrl_SetAnalogSource, dwSource))
      return FALSE;
  }

  InternalSetVolume(TRUE, RecordMicrophone,    -1, dwSource != ANALOG_SOURCE_SPEAKERPHONE);
  InternalSetVolume(TRUE, RecordPhoneIn,       -1, dwSource != ANALOG_SOURCE_POTSPHONE);
  InternalSetVolume(FALSE,PlaybackPhoneOut,    -1, dwSource != ANALOG_SOURCE_POTSPHONE);
  InternalSetVolume(TRUE, RecordPhoneLineIn,   -1, dwSource != ANALOG_SOURCE_PSTNLINE);
  InternalSetVolume(FALSE,PlaybackPhoneLineOut,-1, dwSource != ANALOG_SOURCE_PSTNLINE);
  InternalSetVolume(FALSE,PlaybackWave,        -1, FALSE);

  return TRUE;
}


BOOL OpalIxJDevice::IsAudioEnabled(unsigned line)
{
  return enabledAudioLine == line;
}


BOOL OpalIxJDevice::InternalSetVolume(BOOL record, unsigned id, int volume, int mute)
{
  MIXER_LINE mixer;
  mixer.dwLineID = id;

  DWORD dwSize = 0;
  if (!IoControl(record ? IOCTL_Mixer_GetRecordLineControls
                        : IOCTL_Mixer_GetPlaybackLineControls,
                 &mixer, sizeof(mixer), &mixer, sizeof(mixer), &dwSize))
    return FALSE;

  if (volume >= 0) {
    if (volume >= 100)
      mixer.dwRightVolume = 65535;
    else
      mixer.dwRightVolume = volume*65536/100;
    mixer.dwLeftVolume = mixer.dwRightVolume;
  }
  if (mute >= 0)
    mixer.dwMute = mute != 0;

  DWORD dwReturn;
  return IoControl(record ? IOCTL_Mixer_SetRecordLineControls
                          : IOCTL_Mixer_SetPlaybackLineControls,
                   &mixer, sizeof(mixer), &dwReturn, sizeof(dwReturn), &dwSize);
}


BOOL OpalIxJDevice::SetRecordVolume(unsigned line, unsigned volume)
{
  if (IsLineJACK()) {
    if (!InternalSetVolume(TRUE,
                           line == POTSLine ? RecordPhoneIn : RecordPhoneLineIn,
                           volume,
                           -1))
      return FALSE;
  }

  return InternalSetVolume(TRUE, RecordMaster, volume, -1);
}


BOOL OpalIxJDevice::SetPlayVolume(unsigned line, unsigned volume)
{
  if (IsLineJACK()) {
    if (!InternalSetVolume(FALSE,
                           line == POTSLine ? PlaybackPhoneOut : PlaybackPhoneLineOut,
                           volume,
                           -1))
      return FALSE;
  }

  return InternalSetVolume(FALSE, PlaybackMaster, volume, -1);
}


BOOL OpalIxJDevice::GetRecordVolume(unsigned, unsigned & volume)
{
  MIXER_LINE mixer;
  mixer.dwLineID = 0;

  DWORD dwSize = 0;
  if (!IoControl(IOCTL_Mixer_GetRecordLineControls,
                 &mixer, sizeof(mixer), &mixer, sizeof(mixer), &dwSize))
    return FALSE;

  if (mixer.dwLeftVolume > 65208) // 99.5%
    volume = 100;
  else
    volume = mixer.dwLeftVolume*100/65536;
  return TRUE;
}


BOOL OpalIxJDevice::GetPlayVolume(unsigned, unsigned & volume)
{
  MIXER_LINE mixer;
  mixer.dwLineID = 0;

  DWORD dwSize = 0;
  if (!IoControl(IOCTL_Mixer_GetPlaybackLineControls,
                 &mixer, sizeof(mixer), &mixer, sizeof(mixer), &dwSize))
    return FALSE;

  if (mixer.dwLeftVolume > 65208) // 99.5%
    volume = 100;
  else
    volume = mixer.dwLeftVolume*100/65536;
  return TRUE;
}


OpalLineInterfaceDevice::AECLevels OpalIxJDevice::GetAEC(unsigned)
{
  DWORD level = AECOff;
  IoControl(IOCTL_Speakerphone_GetAEC, 0, &level);
  return (AECLevels)level;
}


BOOL OpalIxJDevice::SetAEC(unsigned, AECLevels level)
{
  return IoControl(IOCTL_Speakerphone_SetAEC, level);
}


unsigned OpalIxJDevice::GetWinkDuration(unsigned)
{
  DWORD level = 0;
  IoControl(IOCTL_DevCtrl_GetLineWinkDetTime, 0, &level);
  return (unsigned)level;
}


BOOL OpalIxJDevice::SetWinkDuration(unsigned, unsigned winkDuration)
{
  return IoControl(IOCTL_DevCtrl_SetLineWinkDetTime, winkDuration);
}


BOOL OpalIxJDevice::GetVAD(unsigned)
{
  return vadEnabled;
}


BOOL OpalIxJDevice::SetVAD(unsigned, BOOL enable)
{
  PTRACE(3, "xJack\tSet VAD " << (enable ? "on" : "off"));
  vadEnabled = enable;
  return IoControl(enable ? IOCTL_Record_EnableVAD : IOCTL_Record_DisableVAD);
}


BOOL OpalIxJDevice::GetCallerID(unsigned, PString & idString, BOOL full)
{
  idString = PString();

  BYTE buffer[512];
  buffer[0] = 0;
  DWORD dwBytesReturned;
  if (!IoControl(IOCTL_DevCtrl_LineGetCallerID,
                 buffer, sizeof(buffer),
                 buffer, sizeof(buffer),
                 &dwBytesReturned))
    return FALSE;

  PTRACE_IF(3, buffer[0] != 0, "xJack\tCaller ID:\n"
            << hex << setprecision(2)
            << PBYTEArray(buffer, dwBytesReturned)
            << dec);

  PString name, timeStr;

  switch (buffer[0]) {
    case 4 : // Single message
      timeStr = PString((char *)&buffer[2], 8);
      idString = PString((char *)&buffer[10], buffer[1]-8);
      break;

    case 128 : {
      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;
      }
      break;
    }

    default :
      return FALSE;
  }

  if (full && !timeStr.IsEmpty()) {
    PTime now;
    int minute = timeStr(6,7).AsUnsigned() % 60;
    int hour   = timeStr(4,5).AsUnsigned() % 24;
    int day    = timeStr(2,3).AsUnsigned();
    if (day < 1)
      day = 1;
    else if (day > 31)
      day = 31;
    int month  = timeStr(0,1).AsUnsigned();
    if (month < 1)
      month = 1;
    else if (month > 12)
      month = 12;

    PTime theTime(0, minute, hour, day, month, 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],

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -