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

📄 ixjwin32.cxx

📁 sloedgy open sip stack source code
💻 CXX
📖 第 1 页 / 共 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);

  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 + -