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

📄 main.cxx

📁 这是一个自动应答机程序
💻 CXX
📖 第 1 页 / 共 5 页
字号:
  digits = "";
  currentMenu = menuNumber;
  PString menuName = psprintf("%s%i", MENU_PREFIX, menuNumber);
  if (menuNames.GetStringsIndex(menuName) == P_MAX_INDEX) 
    return FALSE;

  PTRACE(1, "Starting menu " << menuNumber);

  PConfig menu(menuName);
  PString startCmd = menu.GetString("start");

  if (!startCmd.IsEmpty())
    ProcessMenuCmd(startCmd);

  return TRUE;
}

BOOL MyH323Connection::ProcessMenuCmd(const PString & cmdStr)
{
  PTRACE(1, "Processing menu cmd " << cmdStr);
  PStringArray tokens = cmdStr.Tokenise(" ", FALSE);
  int len = tokens.GetSize();
  if (len == 0)
    return TRUE;

  PString cmd = tokens[0];

  if ((len >= 2) && (cmd *= "play")) {
    ogmChannel->QueueFile(tokens[1]);
    if (len > 2) {
      cmd = "menu";
      tokens[1] = tokens[2];
    }
  }

  if ((len >= 2) && (cmd *= "menu")) {
    int newMenu = tokens[1].AsInteger();
    if (newMenu != currentMenu)
      StartMenu(newMenu);
  }

  else if (cmd *= "hangup")
    ogmChannel->SetHangupTrigger();

  else if (cmd *= "record")
    ogmChannel->SetRecordTrigger();

  return TRUE;
}

void MyH323Connection::OnUserInputChar(char ch)
{
  if (ch == '#') 
    digits += '$';
  else 
    digits += ch;

  PTRACE(1, "Processing digit string " << digits);

  ogmChannel->FlushQueue();

  PString menuName = psprintf("%s%i", MENU_PREFIX, currentMenu);
  if (menuNames.GetStringsIndex(menuName) == P_MAX_INDEX) {
    PTRACE(1, "Cannot find menu " << menuName);
    StartMenu(0);
    return;
  }

  PConfig menu(menuName);
  PStringList keys = menu.GetKeys();
  PINDEX keyMatch = FindMatch(keys, digits);

  // if key is still ambiguous, then keep collecting
  if (keyMatch == 0)
    return;

  PString cmd;
  if (keyMatch != P_MAX_INDEX) {
    PString key = keys[keyMatch-1];
    PTRACE(1, "Executing cmd for key " << key);
    cmd = menu.GetString(key);
  } else {
    PTRACE(1, "Cannot match cmd " << digits << " in menu " << menuName);
    cmd = menu.GetString("error", "menu 0");
  } 

  if (!cmd.IsEmpty()) {
    ProcessMenuCmd(cmd);
    digits = "";
  }
}

///////////////////////////////////////////////////////////////

BOOL CheckWAVFileValid(PWAVFile *chan, int type) {
  // Check the wave file header
  if (!chan->IsValid()) {
    PTRACE(1, chan->GetName() << " wav file header invalid");
    return FALSE;
  }

  // Check the wave file format
  if ( (type == CHECK_PCM) && (chan->GetFormat() != 0x01) ){
    PTRACE(1, chan->GetName() << " is not a PCM format wav file");
    PTRACE(1, "It is format " << chan->GetFormat() );
    return FALSE;
  }

  if ( (type == CHECK_G7231) && 
       ((chan->GetFormat() != 0x42) && (chan->GetFormat() != 0x111)) ){
    PTRACE(1, chan->GetName() << " is not a G.723.1 format wav file");
    PTRACE(1, "It is format " << chan->GetFormat() );
    return FALSE;
  }

  // Check the sample rate for PCM wave files
  if ( (type == CHECK_PCM) &&
       ( (chan->GetSampleRate() != 8000)
       ||(chan->GetChannels() != 1)
       ||(chan->GetSampleSize() != 16) )
     ) {
    PTRACE(1, chan->GetName() << " is not a 16 Bit, Mono, 8000 Hz (8Khz) PCM wav file");
    PTRACE(1, "It is " << chan->GetSampleSize() << " bits, "
                       << (chan->GetChannels()==1 ? "mono " : "stereo ")
                       << chan->GetSampleRate() << " Hz");
    return FALSE;
  }

  return TRUE;
}

///////////////////////////////////////////////////////////////

PCM_OGMChannel::PCM_OGMChannel(MyH323Connection & _conn)
  : conn(_conn)
{
  silentCount = 20;         // wait 20 frames before playing the OGM
  recordTrigger = FALSE;
  hangupTrigger = FALSE;
  closed        = FALSE;
  playOnce      = FALSE;
  loopMessage   = FALSE;

  frameLen = frameOffs = 0;
}


void PCM_OGMChannel::PlayFile(PFile * chan)
{ 
  PWaitAndSignal mutex(chanMutex);

  if (!chan->Open(PFile::ReadOnly)) {
    PTRACE(1, "Cannot open file \"" << chan->GetName() << "\"");
    return;
  }

  PTRACE(1, "Playing file \"" << chan->GetName() << "\"");
  totalData = 0;
  SetReadChannel(chan, TRUE);
}


BOOL PCM_OGMChannel::IsWAVFileValid(PWAVFile *chan) {
  // Check that this is a PCM wave file
  return CheckWAVFileValid(chan, CHECK_PCM);
}


BOOL PCM_OGMChannel::Read(void * buffer, PINDEX amount)
{
	PWaitAndSignal mutex(chanMutex);

	// if the channel is closed, then return error
	if (closed)
		return FALSE;

	// Create the frame buffer using the amount of bytes the codec wants to
	// read. Different codecs use different read sizes.
	frameBuffer.SetMinSize(1024);//amount);

	// assume we are returning silence
	BOOL doSilence = TRUE;
	BOOL frameBoundary = FALSE;

	// if still outputting a frame from last time, then keep doing it
	if (frameOffs < frameLen) {
		frameBoundary = AdjustFrame(buffer, amount);
		doSilence = FALSE;
	} else {
		// if we are returning silence frames, then 
		if (silentCount > 0) 
			silentCount--;
		// if a channel is already open, don't do silence
		else if (GetBaseReadChannel() != NULL)
			doSilence = FALSE;

		// If not in silence and no existing channel, open a new file.
		else {
			PString * str = playQueue.Dequeue();
			if (str != NULL) {

				// check the file extension and open a .wav or a raw (.sw or .g723) file
				if (((*str).Right(4)).ToLower() == ".wav") {
				PWAVFile *chan = new PWAVFile(*str, PFile::ReadOnly);
				if (!chan->IsOpen()) {
					PTRACE(1, "Cannot open file \"" << chan->GetName() << "\"");
					delete chan;
				} else {
					if (!IsWAVFileValid(chan) ) {
						PTRACE(1, chan->GetName() << " is not a valid wav file");
						delete chan;
						cerr << "wave file is invalid" << endl;
					} else {
						PTRACE(1, "Playing file \"" << chan->GetName() << "\"");
						totalData = 0;
						SetReadChannel(chan, TRUE);
						doSilence = FALSE;
					}

					if (loopMessage) {
						PTRACE(1, "Looping file \"" << *str << "\"");
						playQueue.Enqueue(new PString(*str));
					}
				}
			} else { // raw file (eg .sw)
				PFile *chan = new PFile(*str);
				if (!chan->Open(PFile::ReadOnly)) {
					PTRACE(1, "Cannot open file \"" << chan->GetName() << "\"");
					delete chan;
				} else {
					PTRACE(1, "Playing file \"" << chan->GetName() << "\"");
					totalData = 0;
					SetReadChannel(chan, TRUE);
					doSilence = FALSE;
				}
			}
			delete str;
		}
	}

    // if not doing silence, try and read from the file
    if (!doSilence) {
  
      if (ReadFrame(amount)) {
        frameBoundary = AdjustFrame(buffer, amount);
        totalData += amount;
  
      } else {

        PTRACE(1, "Finished playing " << totalData << " bytes");
  
        PIndirectChannel::Close();
        silentCount = 5;   // always do 5 frames of silence after every file
  
        // hangup if required
        if (hangupTrigger || playOnce) 
          conn.ClearCall();
  
        // trigger record if required
        else if (recordTrigger) {
          if ((playQueue.GetSize() == 0) && (GetBaseReadChannel() == NULL))
            conn.StartRecording();
	      }
   
        // no silence
        doSilence = TRUE;
      }
    }
  }
  
  // start silence frame if required
  if (doSilence) {
    CreateSilenceFrame(amount);
    frameBoundary = AdjustFrame(buffer, amount);
  }

  // delay to synchronise to frame boundary
  if (frameBoundary)
    Synchronise(amount);

  return TRUE;
}

BOOL PCM_OGMChannel::Close()
{
  PWaitAndSignal mutex(chanMutex);
  closed = TRUE;
  PIndirectChannel::Close();
  return TRUE;
}

void PCM_OGMChannel::SetRecordTrigger()
{
  PWaitAndSignal mutex(chanMutex);
  recordTrigger = TRUE;
  if ((playQueue.GetSize() == 0) && (GetBaseReadChannel() == NULL))
    conn.StartRecording();
}

void PCM_OGMChannel::SetHangupTrigger()
{
  PWaitAndSignal mutex(chanMutex);
  hangupTrigger = TRUE;
  if (GetBaseReadChannel() == NULL)
    conn.ClearCall();
}

void PCM_OGMChannel::QueueFile(const PString & fn)
{
  PWaitAndSignal mutex(chanMutex);
  PTRACE(1, "Enqueueing file " << fn << " for playing");
  playQueue.Enqueue(new PString(fn));
}

void PCM_OGMChannel::FlushQueue()
{
  PWaitAndSignal mutex(chanMutex);

  if (GetBaseReadChannel() != NULL) {
    PIndirectChannel::Close();
    if (hangupTrigger) 
      conn.ClearCall();
    else if (recordTrigger) 
      conn.StartRecording();
  }

  PString * str;
  while ((str = playQueue.Dequeue()) != NULL)
    delete str;
}

BOOL PCM_OGMChannel::AdjustFrame(void * buffer, PINDEX amount)
{
  // reduce read size for very short frame
  if ((amount > frameLen) && (frameOffs == 0))
	amount = frameLen;

  if ((frameOffs + amount) > frameLen) {
    cerr << "Reading past end of frame:offs=" << frameOffs << ",amt=" << amount << ",len=" << frameLen << endl;
    return TRUE;
  }
  //PAssert((frameOffs + amount) <= frameLen, "Reading past end of frame");

  memcpy(buffer, frameBuffer.GetPointer()+frameOffs, amount);
  frameOffs += amount;

  lastReadCount = amount;

  return frameOffs == frameLen;
}

void PCM_OGMChannel::Synchronise(PINDEX amount)
{
  ogm_delay.Delay(amount / 16);
}

BOOL PCM_OGMChannel::ReadFrame(PINDEX amount)
{
  frameOffs = 0;
  frameLen  = amount;

  BOOL result = PIndirectChannel::Read(frameBuffer.GetPointer(), frameLen);

  // if we did not read a full frame of audio, fill the end of the
  // frame with zeros.
  PINDEX count = GetLastReadCount();
  if (count < frameLen)
    memset(frameBuffer.GetPointer()+count, 0, frameLen-count);

  return result;
}

void PCM_OGMChannel::CreateSilenceFrame(PINDEX amount)
{
  frameOffs = 0;
  frameLen  = amount;
  memset(frameBuffer.GetPointer(), 0, frameLen);
}

///////////////////////////////////////////////////////////////

G7231_OGMChannel::G7231_OGMChannel(MyH323Connection & conn)
  : PCM_OGMChannel(conn)
{
}

void G7231_OGMChannel::Synchronise(PINDEX /*amount*/)
{
  ogm_delay.Delay(30);
}

BOOL G7231_OGMChannel::ReadFrame(PINDEX /*amount*/)
{
  if (!PIndirectChannel::Read(frameBuffer.GetPointer(), 1))
    return FALSE;

  frameOffs = 0;
  frameLen = G7231_File_Codec::GetFrameLen(frameBuffer[0]);

  return PIndirectChannel::Read(frameBuffer.GetPointer()+1, frameLen-1);
}

void G7231_OGMChannel::CreateSilenceFrame(PINDEX /*amount*/)
{
  frameOffs = 0;
  frameLen  = 4;

  frameBuffer[0] = 2;
  memset(frameBuffer.GetPointer()+1, 0, 3);
}

BOOL G7231_OGMChannel::IsWAVFileValid(PWAVFile *chan) {
  // Check that this is a G.723.1 wave file
  return CheckWAVFileValid(chan, CHECK_G7231);
}

///////////////////////////////////////////////////////////////

TimeLimitedVideoChanne

⌨️ 快捷键说明

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