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

模拟服务器

开发平台:

Visual C++

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