callercmds.cxx
上传用户:wzkunzhan
上传日期:2022-04-23
资源大小:2618k
文件大小:12k
源码类别:

模拟服务器

开发平台:

Visual C++

  1. /*
  2.  * cmds.cxx
  3.  *
  4.  * Auxiliary commands for Caller
  5.  *
  6.  * Copyright (c) 1993-2001 Equivalence Pty. Ltd.
  7.  *
  8.  * The contents of this file are subject to the Mozilla Public License
  9.  * Version 1.0 (the "License"); you may not use this file except in
  10.  * compliance with the License. You may obtain a copy of the License at
  11.  * http://www.mozilla.org/MPL/
  12.  *
  13.  * Software distributed under the License is distributed on an "AS IS"
  14.  * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
  15.  * the License for the specific language governing rights and limitations
  16.  * under the License.
  17.  *
  18.  * The Original Code is Portable Windows Library.
  19.  *
  20.  * The Initial Developer of the Original Code is Equivalence Pty. Ltd.
  21.  *
  22.  *
  23.  */
  24. #include <ptlib.h>
  25. #include <ixjlid.h>
  26. #include "version.h"
  27. #include "callermain.h"
  28. class ConsoleThread : public PThread {
  29.   PCLASSINFO(ConsoleThread, PThread);
  30.   public:
  31.     ConsoleThread(PMutex *_enter, BOOL *_enter_pressed) : PThread(1000,AutoDeleteThread)
  32.     {
  33.       enter = _enter;
  34.       enter_pressed = _enter_pressed;
  35.       
  36.       Resume(); // start running this thread as soon as the thread is created.
  37.     }
  38.     void Main() {
  39.       PConsoleChannel console(PConsoleChannel::StandardInput);
  40.       // wait for Enter to be pressed
  41.       console.peek();
  42.       enter->Wait();
  43.       *enter_pressed = TRUE;
  44.       enter->Signal();
  45.     }
  46.   private:
  47.     PMutex *enter;
  48.     BOOL   *enter_pressed;
  49. };
  50. #define new PNEW
  51. #if HAS_IXJ
  52. #define G7231_BUFFER_SIZE 24
  53. #define PCM_BUFFER_SIZE 480
  54. extern PString G7231Ext;
  55. extern PString WAVExt;
  56. extern PString PCMExt;
  57. extern BOOL CheckWAVFileValid(PWAVFile *chan, int type);
  58. #define CHECK_PCM   1
  59. #define CHECK_G7231 2
  60. static BOOL DetermineType(PArgList & args, const PFilePath & fn, BOOL & isPCM, BOOL & isWAV, BOOL openExisting)
  61. {
  62.   BOOL knowType = FALSE;
  63.   // Handle .WAV file types
  64.   if ((fn.GetType() *= WAVExt) && (openExisting)) {
  65.     // determine the file type by peeking into the existing file
  66.     PWAVFile *wavfile = new PWAVFile(fn, PFile::ReadOnly);
  67.     if (!wavfile->IsOpen()) {
  68.       PError << "error: cannot open file "" << fn << """ << endl;
  69.       delete wavfile;
  70.       return FALSE;
  71.     }
  72.     if (CheckWAVFileValid(wavfile,CHECK_G7231))    isPCM = FALSE;
  73.     else if (CheckWAVFileValid(wavfile,CHECK_PCM)) isPCM = TRUE;
  74.     else {
  75.       PError << "error: invalid wav file format for file "" << fn << """ << endl;
  76.       delete wavfile;
  77.       return FALSE;
  78.     }
  79.     wavfile->Close();
  80.     delete wavfile;
  81.     isWAV    = TRUE;
  82.     knowType = TRUE;
  83.   }
  84.   if ((fn.GetType() *= WAVExt) && (!openExisting)) {
  85.     // determine the file type from the command line options
  86.     if (args.HasOption("pcm")) {
  87.       isPCM    = TRUE;
  88.       isWAV    = TRUE;
  89.       knowType = TRUE;
  90.     } else if (args.HasOption("g7231")) {
  91.       isPCM    = FALSE;
  92.       isWAV    = TRUE;
  93.       knowType = TRUE;
  94.     } else {
  95.       PError << "usage: recording a .wav file requires either --g7231 or --pcm,"
  96.              << endl;
  97.       return FALSE;
  98.     }
  99.   }
  100.   // For non .WAV files determine file type from filename extension
  101.   if (fn.GetType() *= G7231Ext) {
  102.     isPCM    = FALSE;
  103.     isWAV    = FALSE;
  104.     knowType = TRUE;
  105.   }
  106.   if (fn.GetType() *= PCMExt) {
  107.     isPCM    = TRUE;
  108.     isWAV    = FALSE;
  109.     knowType = TRUE;
  110.   }
  111.   // if we still do not know the file type, use the command line options
  112.   if (!knowType) {
  113.     if (args.HasOption("pcm")) {
  114.       isPCM    = TRUE;
  115.       isWAV    = FALSE;
  116.       knowType = TRUE;
  117.     } else if (args.HasOption("g7231")) {
  118.       isPCM    = FALSE;
  119.       isWAV    = FALSE;
  120.       knowType = TRUE;
  121.     }
  122.   }
  123.   // error if we could not determine the file type
  124.   if (!knowType) {
  125.     PError << "usage: command requires either --g7231 or --pcm,"
  126.            << "       or filename with " << WAVExt << " or " << G7231Ext
  127.            << " or " << PCMExt << " extension" << endl;
  128.     return FALSE;
  129.   }
  130.   return TRUE;
  131. }
  132. static BOOL OpenDevice(OpalIxJDevice & xJack, const PString & ixjDevice, int port)
  133. {
  134.   if (!xJack.Open(ixjDevice)) {
  135.     PError << "error: cannot open device "" << ixjDevice << """ << endl;
  136.     return FALSE;
  137.   }
  138.   xJack.SetLineToLineDirect(0, 1, FALSE);
  139.   if (port == 3) xJack.EnableAudio(0, FALSE);
  140.   if (port == 2) xJack.EnableAudio(OpalIxJDevice::PSTNLine, TRUE);
  141.   if (port == 1) xJack.EnableAudio(OpalIxJDevice::POTSLine, TRUE);
  142.   return TRUE;
  143. }
  144. void Caller::RecordFile(PArgList & args)
  145. {
  146.   if (args.GetCount() < 2) {
  147.     PError << "usage: openam record [--port n] [--pcm|--g7231] -q N  fn" << endl;
  148.     PError << "usage: port 1=POTS 3=MIC+SPEAKER" << endl;
  149.     PError << "usage: -q N   quicknet device. Eg -q 0" << endl;
  150.     PError << "usage: -fn    filename" << endl;
  151.     return;
  152.   }
  153.   PFilePath fn  = args[1];
  154.   BOOL isPCM = FALSE;
  155.   BOOL isWAV = FALSE;
  156.   int port;
  157.   // Determine the type of file
  158.   if (!DetermineType(args, fn, isPCM, isWAV, FALSE)) return;
  159.   PFile *recordFile;
  160.   if (isWAV) {
  161.     if (isPCM) recordFile = new PWAVFile(PWAVFile::PCM_WavFile);
  162.     else       recordFile = new PWAVFile(PWAVFile::G7231_WavFile);
  163.   }
  164.   else       recordFile = new PFile();
  165.   if (recordFile == NULL)
  166.     return;
  167.   // open the file
  168.   if (!recordFile->Open(fn, PFile::WriteOnly)) {
  169.     PError << "error: cannot open file "" << fn << """ << endl;
  170.     return;
  171.   }
  172.   // open the device
  173.   if (!args.HasOption('q')) {
  174.     PError << "error: record command requires -q option for Quicknet device" << endl;
  175.     return;
  176.   }
  177.   cout << "ok" << endl
  178.        << "Recording " << (isPCM ? "PCM" : "G.723.1")
  179.        << (isWAV ? " wav message" : " message") << endl;
  180.   if (args.HasOption("port")) {
  181.     port = args.GetOptionString("port").AsInteger();
  182.   } else {
  183.     port = OpalIxJDevice::POTSLine; // default to a real telephone
  184.   }
  185.   OpalIxJDevice xJack;
  186.   if (!OpenDevice(xJack, args.GetOptionString('q'),port)) 
  187.     return;
  188.   // ring handset
  189.   if (port == OpalIxJDevice::POTSLine) {
  190.     xJack.RingLine(OpalIxJDevice::POTSLine, 0x33);
  191.     // wait for answer
  192.     cout << "Waiting for phone to go offhook...";
  193.     cout.flush();
  194.     while (!xJack.IsLineOffHook(OpalIxJDevice::POTSLine))
  195.       Sleep(100);
  196.     cout << endl;
  197.   }
  198.   // start codecs
  199.   if (!xJack.SetReadCodec (OpalIxJDevice::POTSLine,
  200.                            isPCM ? RTP_DataFrame::L16_Mono : RTP_DataFrame::G7231)) {
  201.     PError << "error: error during SetReadCodec" << endl;
  202.     return;
  203.   }
  204.   if (!xJack.SetWriteCodec(OpalIxJDevice::POTSLine,
  205.                            isPCM ? RTP_DataFrame::L16_Mono : RTP_DataFrame::G7231)) {
  206.     PError << "error: error during SetWriteCodec" << endl;
  207.     return;
  208.   }
  209.   // determine the read buffer size
  210.   PINDEX bufferSize;
  211.   if (isPCM)
  212.     bufferSize = xJack.GetReadFrameSize(OpalIxJDevice::POTSLine);
  213.   else
  214.     bufferSize = G7231_BUFFER_SIZE;
  215.   // allocate a buffer
  216.   PBYTEArray buffer;
  217.   buffer.SetSize(bufferSize);
  218.   // Create the console thread.
  219.   PMutex enter;
  220.   BOOL enter_pressed = FALSE;
  221.   PThread * consolethread;
  222.   consolethread = new ConsoleThread( &enter, &enter_pressed);
  223.   cout << "Recording Started." << endl << "To stop recording " ;
  224.   if (port == OpalIxJDevice::POTSLine)
  225.     cout << "put the phone back onhook or ";
  226.   cout << "press Enter" << endl;
  227.   // start recording
  228.   for (;;) {
  229.     // stop if we are using POTS and the telephone handset it put down
  230.     if ((port == OpalIxJDevice::POTSLine) && (!xJack.IsLineOffHook(OpalIxJDevice::POTSLine)))
  231.       break;
  232.     // stop if the user pressed Enter on the console
  233.     enter.Wait();
  234.     if (enter_pressed == TRUE) {
  235.       enter.Signal();
  236.       break;
  237.     }
  238.     enter.Signal();
  239.     PINDEX count;
  240.     if (!xJack.ReadFrame(OpalIxJDevice::POTSLine, buffer.GetPointer(), count)) {
  241.       PError << "error: error during ReadFrame" << endl;
  242.       return;
  243.     }
  244.     recordFile->Write(buffer, count);
  245.   }
  246.   cout << "Recording Finished" << endl;
  247.   // stop recording;
  248.   xJack.StopReadCodec (OpalIxJDevice::POTSLine);
  249.   xJack.StopWriteCodec(OpalIxJDevice::POTSLine);
  250.   // close the file
  251.   recordFile->Close();
  252.   delete recordFile;
  253. }
  254. void Caller::PlayFile(PArgList & args)
  255. {
  256.   if (args.GetCount() < 2) {
  257.     PError << "usage: openam play [--port n] [--pcm|--g7231] -q N  fn" << endl;
  258.     PError << "usage: port 1=POTS 2=PSTN 3=MIC+SPEAKER" << endl;
  259.     PError << "usage: -q N   quicknet device. Eg -q 0" << endl;
  260.     PError << "usage: -fn    filename" << endl;
  261.     return;
  262.   }
  263.   PFilePath fn  = args[1];
  264.   BOOL isPCM = FALSE;
  265.   BOOL isWAV = FALSE;
  266.   int port;
  267.   // Determine the type of file
  268.   if (!DetermineType(args, fn, isPCM, isWAV, TRUE)) return;
  269.   PFile *playFile;
  270.   if (isWAV) playFile = new PWAVFile();
  271.   else       playFile = new PFile();
  272.   if (playFile == NULL)
  273.     return;
  274.   // open the file
  275.   if (!playFile->Open(fn, PFile::ReadOnly)) {
  276.     PError << "error: cannot open file "" << fn << """ << endl;
  277.     return;
  278.   }
  279.   // open the device
  280.   if (!args.HasOption('q')) {
  281.     PError << "error: play command requires -q option for Quicknet device" << endl;
  282.     return;
  283.   }
  284.   cout << "Playing " << (isPCM ? "PCM" : "G.723.1")
  285.        << (isWAV ? " wav message" : " message") << endl;
  286.   if (args.HasOption("port")) {
  287.     port = args.GetOptionString("port").AsInteger();
  288.   } else {
  289.     port = 1; // default to a real telephone
  290.   }
  291.   OpalIxJDevice xJack;
  292.   if (!OpenDevice(xJack, args.GetOptionString('q'),port))
  293.     return;
  294.   // ring handset
  295.   if (port == 1) {
  296.     xJack.RingLine(OpalIxJDevice::POTSLine, 0x33);
  297.     // wait for answer
  298.     cout << "Waiting for phone to go offhook...";
  299.     cout.flush();
  300.     while (!xJack.IsLineOffHook(OpalIxJDevice::POTSLine))
  301.       Sleep(100);
  302.     cout << endl;
  303.   }
  304.   // start codecs
  305.   if (!xJack.SetReadCodec (OpalIxJDevice::POTSLine,
  306.                            isPCM ? RTP_DataFrame::L16_Mono : RTP_DataFrame::G7231)) {
  307.     PError << "error: error during SetReadCodec" << endl;
  308.     return;
  309.   }
  310.   if (!xJack.SetWriteCodec(OpalIxJDevice::POTSLine,
  311.                            isPCM ? RTP_DataFrame::L16_Mono : RTP_DataFrame::G7231)) {
  312.     PError << "error: error during SetWriteCodec" << endl;
  313.     return;
  314.   }
  315.   // determine the write buffer size
  316.   PINDEX bufferSize;
  317.   if (isPCM)
  318.     bufferSize = xJack.GetReadFrameSize(OpalIxJDevice::POTSLine);
  319.   else
  320.     bufferSize = G7231_BUFFER_SIZE;
  321.   // allocate a buffer
  322.   PBYTEArray buffer;
  323.   buffer.SetSize(bufferSize);
  324.   // Create the console thread.
  325.   PMutex enter;
  326.   BOOL enter_pressed = FALSE;
  327.   PThread * consolethread;
  328.   consolethread = new ConsoleThread( &enter, &enter_pressed);
  329.   cout << "Playback Started." << endl << "To stop playback " ;
  330.   if (port == 1)
  331.     cout << "put the phone back onhook or ";
  332.   cout << "press Enter" << endl;
  333.   // start playing
  334.   for (;;) {
  335.     // stop if we are using POTS and the telephone handset it put down
  336.     if ((port == 1) && (!xJack.IsLineOffHook(OpalIxJDevice::POTSLine))) {
  337.       break;
  338.     }
  339.     // stop if the user pressed Enter on the console
  340.     enter.Wait();
  341.     if (enter_pressed == TRUE) {
  342.       enter.Signal();
  343.       break;
  344.     }
  345.     enter.Signal();
  346.     PINDEX count = 0;
  347.     if (isPCM) {
  348.       if (!playFile->Read(buffer.GetPointer(), bufferSize))
  349.         break;
  350.     } else {
  351.       if (!playFile->Read(buffer.GetPointer(), 1)) 
  352.         break;
  353.       count++;
  354.       static const int frameLen[] = { 24, 20, 4, 1 };
  355.       if (!playFile->Read(buffer.GetPointer()+1, frameLen[buffer[0]&3] - 1))
  356.         break;
  357.     }
  358.     count += playFile->GetLastReadCount();
  359.     PINDEX written;
  360.     if (!xJack.WriteFrame(OpalIxJDevice::POTSLine, buffer.GetPointer(), count, written)) {
  361.       PError << "error: error during WriteFrame" << endl;
  362.       return;
  363.     }
  364.   }
  365.   // stop recording;
  366.   xJack.StopReadCodec (OpalIxJDevice::POTSLine);
  367.   xJack.StopWriteCodec(OpalIxJDevice::POTSLine);
  368.   // close the file
  369.   playFile->Close();
  370.   delete playFile;
  371. }
  372. #endif