1/*
2 *  Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
3 *
4 *  Use of this source code is governed by a BSD-style license
5 *  that can be found in the LICENSE file in the root of the source
6 *  tree. An additional intellectual property rights grant can be found
7 *  in the file PATENTS.  All contributing project authors may
8 *  be found in the AUTHORS file in the root of the source tree.
9 */
10
11#include <stdio.h>
12#include <stdlib.h>
13#include <string.h>
14#ifndef _WIN32
15#include <unistd.h>
16#endif
17
18#include <vector>
19
20#include "gflags/gflags.h"
21#include "testing/gtest/include/gtest/gtest.h"
22#include "webrtc/engine_configurations.h"
23#include "webrtc/modules/audio_processing/include/audio_processing.h"
24#include "webrtc/system_wrappers/interface/scoped_ptr.h"
25#include "webrtc/test/channel_transport/include/channel_transport.h"
26#include "webrtc/test/testsupport/fileutils.h"
27#include "webrtc/test/testsupport/trace_to_stderr.h"
28#include "webrtc/voice_engine/include/voe_audio_processing.h"
29#include "webrtc/voice_engine/include/voe_base.h"
30#include "webrtc/voice_engine/include/voe_codec.h"
31#include "webrtc/voice_engine/include/voe_dtmf.h"
32#include "webrtc/voice_engine/include/voe_errors.h"
33#include "webrtc/voice_engine/include/voe_external_media.h"
34#include "webrtc/voice_engine/include/voe_file.h"
35#include "webrtc/voice_engine/include/voe_hardware.h"
36#include "webrtc/voice_engine/include/voe_neteq_stats.h"
37#include "webrtc/voice_engine/include/voe_network.h"
38#include "webrtc/voice_engine/include/voe_rtp_rtcp.h"
39#include "webrtc/voice_engine/include/voe_video_sync.h"
40#include "webrtc/voice_engine/include/voe_volume_control.h"
41
42DEFINE_bool(use_log_file, false,
43    "Output logs to a file; by default they will be printed to stderr.");
44
45using namespace webrtc;
46using namespace test;
47
48#define VALIDATE                                           \
49  if (res != 0) {                                          \
50    printf("*** Error at line %i \n", __LINE__);           \
51    printf("*** Error code = %i \n", base1->LastError());  \
52  }
53
54VoiceEngine* m_voe = NULL;
55VoEBase* base1 = NULL;
56VoECodec* codec = NULL;
57VoEVolumeControl* volume = NULL;
58VoEDtmf* dtmf = NULL;
59VoERTP_RTCP* rtp_rtcp = NULL;
60VoEAudioProcessing* apm = NULL;
61VoENetwork* netw = NULL;
62VoEFile* file = NULL;
63VoEVideoSync* vsync = NULL;
64VoEHardware* hardware = NULL;
65VoEExternalMedia* xmedia = NULL;
66VoENetEqStats* neteqst = NULL;
67
68void RunTest(std::string out_path);
69
70class MyObserver : public VoiceEngineObserver {
71 public:
72   virtual void CallbackOnError(int channel, int err_code);
73};
74
75void MyObserver::CallbackOnError(int channel, int err_code) {
76  // Add printf for other error codes here
77  if (err_code == VE_TYPING_NOISE_WARNING) {
78    printf("  TYPING NOISE DETECTED \n");
79  } else if (err_code == VE_TYPING_NOISE_OFF_WARNING) {
80    printf("  TYPING NOISE OFF DETECTED \n");
81  } else if (err_code == VE_RECEIVE_PACKET_TIMEOUT) {
82    printf("  RECEIVE PACKET TIMEOUT \n");
83  } else if (err_code == VE_PACKET_RECEIPT_RESTARTED) {
84    printf("  PACKET RECEIPT RESTARTED \n");
85  } else if (err_code == VE_RUNTIME_PLAY_WARNING) {
86    printf("  RUNTIME PLAY WARNING \n");
87  } else if (err_code == VE_RUNTIME_REC_WARNING) {
88    printf("  RUNTIME RECORD WARNING \n");
89  } else if (err_code == VE_SATURATION_WARNING) {
90    printf("  SATURATION WARNING \n");
91  } else if (err_code == VE_RUNTIME_PLAY_ERROR) {
92    printf("  RUNTIME PLAY ERROR \n");
93  } else if (err_code == VE_RUNTIME_REC_ERROR) {
94    printf("  RUNTIME RECORD ERROR \n");
95  } else if (err_code == VE_REC_DEVICE_REMOVED) {
96    printf("  RECORD DEVICE REMOVED \n");
97  }
98}
99
100void SetStereoIfOpus(bool use_stereo, CodecInst* codec_params) {
101  if (strncmp(codec_params->plname, "opus", 4) == 0) {
102    if (use_stereo)
103      codec_params->channels = 2;
104    else
105      codec_params->channels = 1;
106  }
107}
108
109void PrintCodecs(bool opus_stereo) {
110  CodecInst codec_params;
111  for (int i = 0; i < codec->NumOfCodecs(); ++i) {
112    int res = codec->GetCodec(i, codec_params);
113    VALIDATE;
114    SetStereoIfOpus(opus_stereo, &codec_params);
115    printf("%2d. %3d  %s/%d/%d \n", i, codec_params.pltype, codec_params.plname,
116           codec_params.plfreq, codec_params.channels);
117  }
118}
119
120int main(int argc, char** argv) {
121  google::ParseCommandLineFlags(&argc, &argv, true);
122
123  int res = 0;
124
125  printf("Test started \n");
126
127  m_voe = VoiceEngine::Create();
128  base1 = VoEBase::GetInterface(m_voe);
129  codec = VoECodec::GetInterface(m_voe);
130  apm = VoEAudioProcessing::GetInterface(m_voe);
131  volume = VoEVolumeControl::GetInterface(m_voe);
132  dtmf = VoEDtmf::GetInterface(m_voe);
133  rtp_rtcp = VoERTP_RTCP::GetInterface(m_voe);
134  netw = VoENetwork::GetInterface(m_voe);
135  file = VoEFile::GetInterface(m_voe);
136  vsync = VoEVideoSync::GetInterface(m_voe);
137  hardware = VoEHardware::GetInterface(m_voe);
138  xmedia = VoEExternalMedia::GetInterface(m_voe);
139  neteqst = VoENetEqStats::GetInterface(m_voe);
140
141  MyObserver my_observer;
142
143  scoped_ptr<test::TraceToStderr> trace_to_stderr;
144  if (!FLAGS_use_log_file) {
145    trace_to_stderr.reset(new test::TraceToStderr);
146  } else {
147    const std::string trace_filename = test::OutputPath() + "webrtc_trace.txt";
148    VoiceEngine::SetTraceFilter(kTraceAll);
149    res = VoiceEngine::SetTraceFile(trace_filename.c_str());
150    VALIDATE;
151    res = VoiceEngine::SetTraceCallback(NULL);
152    VALIDATE;
153    printf("Outputting logs to file: %s\n", trace_filename.c_str());
154  }
155
156  printf("Init\n");
157  res = base1->Init();
158  if (res != 0) {
159    printf("\nError calling Init: %d\n", base1->LastError());
160    fflush(NULL);
161    exit(1);
162  }
163
164  res = base1->RegisterVoiceEngineObserver(my_observer);
165  VALIDATE;
166
167  printf("Version\n");
168  char tmp[1024];
169  res = base1->GetVersion(tmp);
170  VALIDATE;
171  printf("%s\n", tmp);
172
173  RunTest(test::OutputPath());
174
175  printf("Terminate \n");
176
177  base1->DeRegisterVoiceEngineObserver();
178
179  res = base1->Terminate();
180  VALIDATE;
181
182  if (base1)
183    base1->Release();
184
185  if (codec)
186    codec->Release();
187
188  if (volume)
189    volume->Release();
190
191  if (dtmf)
192    dtmf->Release();
193
194  if (rtp_rtcp)
195    rtp_rtcp->Release();
196
197  if (apm)
198    apm->Release();
199
200  if (netw)
201    netw->Release();
202
203  if (file)
204    file->Release();
205
206  if (vsync)
207    vsync->Release();
208
209  if (hardware)
210    hardware->Release();
211
212  if (xmedia)
213    xmedia->Release();
214
215  if (neteqst)
216    neteqst->Release();
217
218  VoiceEngine::Delete(m_voe);
219
220  return 0;
221}
222
223void RunTest(std::string out_path) {
224  int chan, res;
225  CodecInst cinst;
226  bool enable_aec = false;
227  bool enable_agc = false;
228  bool enable_rx_agc = false;
229  bool enable_cng = false;
230  bool enable_ns = false;
231  bool enable_rx_ns = false;
232  bool typing_detection = false;
233  bool muted = false;
234  bool opus_stereo = false;
235  bool experimental_ns_enabled = false;
236
237#if defined(WEBRTC_ANDROID)
238  std::string resource_path = "/sdcard/";
239#else
240  std::string resource_path = webrtc::test::ProjectRootPath();
241  if (resource_path == webrtc::test::kCannotFindProjectRootDir) {
242    printf("*** Unable to get project root directory. "
243           "File playing may fail. ***\n");
244    // Fall back to the current directory.
245    resource_path = "./";
246  } else {
247    resource_path += "data/voice_engine/";
248  }
249#endif
250  const std::string audio_filename = resource_path + "audio_long16.pcm";
251
252  const std::string play_filename = out_path + "recorded_playout.pcm";
253  const std::string mic_filename = out_path + "recorded_mic.pcm";
254
255  chan = base1->CreateChannel();
256  if (chan < 0) {
257    printf("************ Error code = %i\n", base1->LastError());
258    fflush(NULL);
259  }
260
261  scoped_ptr<VoiceChannelTransport> voice_channel_transport(
262      new VoiceChannelTransport(netw, chan));
263
264  char ip[64];
265  printf("1. 127.0.0.1 \n");
266  printf("2. Specify IP \n");
267  int ip_selection;
268  ASSERT_EQ(1, scanf("%i", &ip_selection));
269
270  if (ip_selection == 1) {
271    strcpy(ip, "127.0.0.1");
272  } else {
273    printf("Specify remote IP: ");
274    ASSERT_EQ(1, scanf("%s", ip));
275  }
276
277  int rPort;
278  printf("Specify remote port (1=1234): ");
279  ASSERT_EQ(1, scanf("%i", &rPort));
280  if (1 == rPort)
281    rPort = 1234;
282  printf("Set Send port \n");
283
284  printf("Set Send IP \n");
285  res = voice_channel_transport->SetSendDestination(ip, rPort);
286  VALIDATE;
287
288  int lPort;
289  printf("Specify local port (1=1234): ");
290  ASSERT_EQ(1, scanf("%i", &lPort));
291  if (1 == lPort)
292    lPort = 1234;
293  printf("Set Rec Port \n");
294
295  res = voice_channel_transport->SetLocalReceiver(lPort);
296  VALIDATE;
297
298  printf("\n");
299  PrintCodecs(opus_stereo);
300  printf("Select send codec: ");
301  int codec_selection;
302  ASSERT_EQ(1, scanf("%i", &codec_selection));
303  codec->GetCodec(codec_selection, cinst);
304
305  printf("Set primary codec\n");
306  SetStereoIfOpus(opus_stereo, &cinst);
307  res = codec->SetSendCodec(chan, cinst);
308  VALIDATE;
309
310  const int kMaxNumChannels = 8;
311  int channel_index = 0;
312  std::vector<int> channels(kMaxNumChannels);
313  std::vector<VoiceChannelTransport*> voice_channel_transports(kMaxNumChannels);
314
315  for (int i = 0; i < kMaxNumChannels; ++i) {
316    channels[i] = base1->CreateChannel();
317    int port = rPort + (i + 1) * 2;
318
319    voice_channel_transports[i] = new VoiceChannelTransport(netw, channels[i]);
320
321    res = voice_channel_transports[i]->SetSendDestination(ip, port);
322    VALIDATE;
323    res = voice_channel_transports[i]->SetLocalReceiver(port);
324    VALIDATE;
325    res = codec->SetSendCodec(channels[i], cinst);
326    VALIDATE;
327  }
328
329  // Call loop
330  bool newcall = true;
331  while (newcall) {
332    int rd(-1), pd(-1);
333    res = hardware->GetNumOfRecordingDevices(rd);
334    VALIDATE;
335    res = hardware->GetNumOfPlayoutDevices(pd);
336    VALIDATE;
337
338    char dn[128] = { 0 };
339    char guid[128] = { 0 };
340    printf("\nPlayout devices (%d): \n", pd);
341    for (int j = 0; j < pd; ++j) {
342      res = hardware->GetPlayoutDeviceName(j, dn, guid);
343      VALIDATE;
344      printf("  %d: %s \n", j, dn);
345    }
346
347    printf("Recording devices (%d): \n", rd);
348    for (int j = 0; j < rd; ++j) {
349      res = hardware->GetRecordingDeviceName(j, dn, guid);
350      VALIDATE;
351      printf("  %d: %s \n", j, dn);
352    }
353
354    printf("Select playout device: ");
355    ASSERT_EQ(1, scanf("%d", &pd));
356    res = hardware->SetPlayoutDevice(pd);
357    VALIDATE;
358    printf("Select recording device: ");
359    ASSERT_EQ(1, scanf("%d", &rd));
360    printf("Setting sound devices \n");
361    res = hardware->SetRecordingDevice(rd);
362    VALIDATE;
363
364    res = codec->SetVADStatus(0, enable_cng);
365    VALIDATE;
366
367    res = apm->SetAgcStatus(enable_agc);
368    VALIDATE;
369
370    res = apm->SetEcStatus(enable_aec);
371    VALIDATE;
372
373    res = apm->SetNsStatus(enable_ns);
374    VALIDATE;
375
376    printf("\n1. Send, listen and playout \n");
377    printf("2. Send only \n");
378    printf("3. Listen and playout only \n");
379    printf("Select transfer mode: ");
380    int call_selection;
381    ASSERT_EQ(1, scanf("%i", &call_selection));
382    const bool send = !(call_selection == 3);
383    const bool receive = !(call_selection == 2);
384
385    if (receive) {
386#ifndef EXTERNAL_TRANSPORT
387      printf("Start Listen \n");
388      res = base1->StartReceive(chan);
389      VALIDATE;
390#endif
391
392      printf("Start Playout \n");
393      res = base1->StartPlayout(chan);
394      VALIDATE;
395    }
396
397    if (send) {
398      printf("Start Send \n");
399      res = base1->StartSend(chan);
400      VALIDATE;
401    }
402
403    printf("Getting mic volume \n");
404    unsigned int vol = 999;
405    res = volume->GetMicVolume(vol);
406    VALIDATE;
407    if ((vol > 255) || (vol < 1)) {
408      printf("\n****ERROR in GetMicVolume");
409    }
410
411    int forever = 1;
412    while (forever) {
413      printf("\nSelect codec\n");
414      PrintCodecs(opus_stereo);
415      printf("\nOther actions\n");
416      const int num_codecs = codec->NumOfCodecs();
417      int option_index = num_codecs;
418      printf("%i. Toggle CNG\n", option_index++);
419      printf("%i. Toggle AGC\n", option_index++);
420      printf("%i. Toggle NS\n", option_index++);
421      printf("%i. Toggle experimental NS\n", option_index++);
422      printf("%i. Toggle EC\n", option_index++);
423      printf("%i. Select AEC\n", option_index++);
424      printf("%i. Select AECM\n", option_index++);
425      printf("%i. Get speaker volume\n", option_index++);
426      printf("%i. Set speaker volume\n", option_index++);
427      printf("%i. Get microphone volume\n", option_index++);
428      printf("%i. Set microphone volume\n", option_index++);
429      printf("%i. Play local file (audio_long16.pcm) \n", option_index++);
430      printf("%i. Change playout device \n", option_index++);
431      printf("%i. Change recording device \n", option_index++);
432      printf("%i. Toggle receive-side AGC \n", option_index++);
433      printf("%i. Toggle receive-side NS \n", option_index++);
434      printf("%i. AGC status \n", option_index++);
435      printf("%i. Toggle microphone mute \n", option_index++);
436      printf("%i. Toggle on hold status \n", option_index++);
437      printf("%i. Get last error code \n", option_index++);
438      printf("%i. Toggle typing detection \n",
439             option_index++);
440      printf("%i. Record a PCM file \n", option_index++);
441      printf("%i. Play a previously recorded PCM file locally \n",
442             option_index++);
443      printf("%i. Play a previously recorded PCM file as microphone \n",
444             option_index++);
445      printf("%i. Add an additional file-playing channel \n", option_index++);
446      printf("%i. Remove a file-playing channel \n", option_index++);
447      printf("%i. Toggle Opus stereo (Opus must be selected again to apply "
448             "the setting) \n", option_index++);
449
450      printf("Select action or %i to stop the call: ", option_index);
451      int option_selection;
452      ASSERT_EQ(1, scanf("%i", &option_selection));
453
454      option_index = num_codecs;
455      if (option_selection < option_index) {
456        res = codec->GetCodec(option_selection, cinst);
457        VALIDATE;
458        SetStereoIfOpus(opus_stereo, &cinst);
459        printf("Set primary codec\n");
460        res = codec->SetSendCodec(chan, cinst);
461        VALIDATE;
462      } else if (option_selection == option_index++) {
463        enable_cng = !enable_cng;
464        res = codec->SetVADStatus(0, enable_cng);
465        VALIDATE;
466        if (enable_cng)
467          printf("\n CNG is now on! \n");
468        else
469          printf("\n CNG is now off! \n");
470      } else if (option_selection == option_index++) {
471        enable_agc = !enable_agc;
472        res = apm->SetAgcStatus(enable_agc);
473        VALIDATE;
474        if (enable_agc)
475          printf("\n AGC is now on! \n");
476        else
477          printf("\n AGC is now off! \n");
478      } else if (option_selection == option_index++) {
479        enable_ns = !enable_ns;
480        res = apm->SetNsStatus(enable_ns);
481        VALIDATE;
482        if (enable_ns)
483          printf("\n NS is now on! \n");
484        else
485          printf("\n NS is now off! \n");
486      } else if (option_selection == option_index++) {
487        experimental_ns_enabled = !experimental_ns_enabled;
488        res = base1->audio_processing()->EnableExperimentalNs(
489            experimental_ns_enabled);
490        VALIDATE;
491        if (experimental_ns_enabled) {
492          printf("\n Experimental NS is now on!\n");
493        } else {
494          printf("\n Experimental NS is now off!\n");
495        }
496      } else if (option_selection == option_index++) {
497        enable_aec = !enable_aec;
498        res = apm->SetEcStatus(enable_aec, kEcUnchanged);
499        VALIDATE;
500        if (enable_aec)
501          printf("\n Echo control is now on! \n");
502        else
503          printf("\n Echo control is now off! \n");
504      } else if (option_selection == option_index++) {
505        res = apm->SetEcStatus(enable_aec, kEcAec);
506        VALIDATE;
507        printf("\n AEC selected! \n");
508        if (enable_aec)
509          printf(" (Echo control is on)\n");
510        else
511          printf(" (Echo control is off)\n");
512      } else if (option_selection == option_index++) {
513        res = apm->SetEcStatus(enable_aec, kEcAecm);
514        VALIDATE;
515        printf("\n AECM selected! \n");
516        if (enable_aec)
517          printf(" (Echo control is on)\n");
518        else
519          printf(" (Echo control is off)\n");
520      } else if (option_selection == option_index++) {
521        unsigned vol(0);
522        res = volume->GetSpeakerVolume(vol);
523        VALIDATE;
524        printf("\n Speaker Volume is %d \n", vol);
525      } else if (option_selection == option_index++) {
526        printf("Level: ");
527        int level;
528        ASSERT_EQ(1, scanf("%i", &level));
529        res = volume->SetSpeakerVolume(level);
530        VALIDATE;
531      } else if (option_selection == option_index++) {
532        unsigned vol(0);
533        res = volume->GetMicVolume(vol);
534        VALIDATE;
535        printf("\n Microphone Volume is %d \n", vol);
536      } else if (option_selection == option_index++) {
537        printf("Level: ");
538        int level;
539        ASSERT_EQ(1, scanf("%i", &level));
540        res = volume->SetMicVolume(level);
541        VALIDATE;
542      } else if (option_selection == option_index++) {
543        res = file->StartPlayingFileLocally(0, audio_filename.c_str());
544        VALIDATE;
545      } else if (option_selection == option_index++) {
546        // change the playout device with current call
547        int num_pd(-1);
548        res = hardware->GetNumOfPlayoutDevices(num_pd);
549        VALIDATE;
550
551        char dn[128] = { 0 };
552        char guid[128] = { 0 };
553
554        printf("\nPlayout devices (%d): \n", num_pd);
555        for (int i = 0; i < num_pd; ++i) {
556          res = hardware->GetPlayoutDeviceName(i, dn, guid);
557          VALIDATE;
558          printf("  %d: %s \n", i, dn);
559        }
560        printf("Select playout device: ");
561        ASSERT_EQ(1, scanf("%d", &num_pd));
562        // Will use plughw for hardware devices
563        res = hardware->SetPlayoutDevice(num_pd);
564        VALIDATE;
565      } else if (option_selection == option_index++) {
566        // change the recording device with current call
567        int num_rd(-1);
568
569        res = hardware->GetNumOfRecordingDevices(num_rd);
570        VALIDATE;
571
572        char dn[128] = { 0 };
573        char guid[128] = { 0 };
574
575        printf("Recording devices (%d): \n", num_rd);
576        for (int i = 0; i < num_rd; ++i) {
577          res = hardware->GetRecordingDeviceName(i, dn, guid);
578          VALIDATE;
579          printf("  %d: %s \n", i, dn);
580        }
581
582        printf("Select recording device: ");
583        ASSERT_EQ(1, scanf("%d", &num_rd));
584        printf("Setting sound devices \n");
585        // Will use plughw for hardware devices
586        res = hardware->SetRecordingDevice(num_rd);
587        VALIDATE;
588      } else if (option_selection == option_index++) {
589        // Remote AGC
590        enable_rx_agc = !enable_rx_agc;
591        res = apm->SetRxAgcStatus(chan, enable_rx_agc);
592        VALIDATE;
593        if (enable_rx_agc)
594          printf("\n Receive-side AGC is now on! \n");
595        else
596          printf("\n Receive-side AGC is now off! \n");
597      } else if (option_selection == option_index++) {
598        // Remote NS
599        enable_rx_ns = !enable_rx_ns;
600        res = apm->SetRxNsStatus(chan, enable_rx_ns);
601        VALIDATE;
602        if (enable_rx_ns)
603          printf("\n Receive-side NS is now on! \n");
604        else
605          printf("\n Receive-side NS is now off! \n");
606      } else if (option_selection == option_index++) {
607        AgcModes agcmode;
608        bool enable;
609        res = apm->GetAgcStatus(enable, agcmode);
610        VALIDATE
611            printf("\n AGC enable is %d, mode is %d \n", enable, agcmode);
612      } else if (option_selection == option_index++) {
613        // Toggle Mute on Microphone
614        res = volume->GetInputMute(chan, muted);
615        VALIDATE;
616        muted = !muted;
617        res = volume->SetInputMute(chan, muted);
618        VALIDATE;
619        if (muted)
620          printf("\n Microphone is now on mute! \n");
621        else
622          printf("\n Microphone is no longer on mute! \n");
623      } else if (option_selection == option_index++) {
624        // Get the last error code and print to screen
625        int err_code = 0;
626        err_code = base1->LastError();
627        if (err_code != -1)
628          printf("\n The last error code was %i.\n", err_code);
629      } else if (option_selection == option_index++) {
630        typing_detection= !typing_detection;
631        res = apm->SetTypingDetectionStatus(typing_detection);
632        VALIDATE;
633        if (typing_detection)
634          printf("\n Typing detection is now on!\n");
635        else
636          printf("\n Typing detection is now off!\n");
637      } else if (option_selection == option_index++) {
638        int stop_record = 1;
639        int file_source = 1;
640        printf("\n Select source of recorded file. ");
641        printf("\n 1. Record from microphone to file ");
642        printf("\n 2. Record from playout to file ");
643        printf("\n Enter your selection: \n");
644        ASSERT_EQ(1, scanf("%i", &file_source));
645        if (file_source == 1) {
646          printf("\n Start recording microphone as %s \n",
647                 mic_filename.c_str());
648          res = file->StartRecordingMicrophone(mic_filename.c_str());
649          VALIDATE;
650        } else {
651          printf("\n Start recording playout as %s \n", play_filename.c_str());
652          res = file->StartRecordingPlayout(chan, play_filename.c_str());
653          VALIDATE;
654        }
655        while (stop_record != 0) {
656          printf("\n Type 0 to stop recording file \n");
657          ASSERT_EQ(1, scanf("%i", &stop_record));
658        }
659        if (file_source == 1) {
660          res = file->StopRecordingMicrophone();
661          VALIDATE;
662        } else {
663          res = file->StopRecordingPlayout(chan);
664          VALIDATE;
665        }
666        printf("\n File finished recording \n");
667      } else if (option_selection == option_index++) {
668        int file_type = 1;
669        int stop_play = 1;
670        printf("\n Select a file to play locally in a loop.");
671        printf("\n 1. Play %s", mic_filename.c_str());
672        printf("\n 2. Play %s", play_filename.c_str());
673        printf("\n Enter your selection\n");
674        ASSERT_EQ(1, scanf("%i", &file_type));
675        if (file_type == 1)  {
676          printf("\n Start playing %s locally in a loop\n",
677                 mic_filename.c_str());
678          res = file->StartPlayingFileLocally(chan, mic_filename.c_str(), true);
679          VALIDATE;
680        } else {
681          printf("\n Start playing %s locally in a loop\n",
682                 play_filename.c_str());
683          res = file->StartPlayingFileLocally(chan, play_filename.c_str(),
684                                              true);
685          VALIDATE;
686        }
687        while (stop_play != 0) {
688          printf("\n Type 0 to stop playing file\n");
689          ASSERT_EQ(1, scanf("%i", &stop_play));
690        }
691        res = file->StopPlayingFileLocally(chan);
692        VALIDATE;
693      } else if (option_selection == option_index++) {
694        int file_type = 1;
695        int stop_play = 1;
696        printf("\n Select a file to play as microphone in a loop.");
697        printf("\n 1. Play %s", mic_filename.c_str());
698        printf("\n 2. Play %s", play_filename.c_str());
699        printf("\n Enter your selection\n");
700        ASSERT_EQ(1, scanf("%i", &file_type));
701        if (file_type == 1)  {
702          printf("\n Start playing %s as mic in a loop\n",
703                 mic_filename.c_str());
704          res = file->StartPlayingFileAsMicrophone(chan, mic_filename.c_str(),
705                                                   true);
706          VALIDATE;
707        } else {
708          printf("\n Start playing %s as mic in a loop\n",
709                 play_filename.c_str());
710          res = file->StartPlayingFileAsMicrophone(chan, play_filename.c_str(),
711                                                   true);
712          VALIDATE;
713        }
714        while (stop_play != 0) {
715          printf("\n Type 0 to stop playing file\n");
716          ASSERT_EQ(1, scanf("%i", &stop_play));
717        }
718        res = file->StopPlayingFileAsMicrophone(chan);
719        VALIDATE;
720      } else if (option_selection == option_index++) {
721        if (channel_index < kMaxNumChannels) {
722          res = base1->StartReceive(channels[channel_index]);
723          VALIDATE;
724          res = base1->StartPlayout(channels[channel_index]);
725          VALIDATE;
726          res = base1->StartSend(channels[channel_index]);
727          VALIDATE;
728          res = file->StartPlayingFileAsMicrophone(channels[channel_index],
729                                                   audio_filename.c_str(),
730                                                   true,
731                                                   false);
732          VALIDATE;
733          channel_index++;
734          printf("Using %d additional channels\n", channel_index);
735        } else {
736          printf("Max number of channels reached\n");
737        }
738      } else if (option_selection == option_index++) {
739        if (channel_index > 0) {
740          channel_index--;
741          res = file->StopPlayingFileAsMicrophone(channels[channel_index]);
742          VALIDATE;
743          res = base1->StopSend(channels[channel_index]);
744          VALIDATE;
745          res = base1->StopPlayout(channels[channel_index]);
746          VALIDATE;
747          res = base1->StopReceive(channels[channel_index]);
748          VALIDATE;
749          printf("Using %d additional channels\n", channel_index);
750        } else {
751          printf("All additional channels stopped\n");
752        }
753      } else if (option_selection == option_index++) {
754        opus_stereo = !opus_stereo;
755        if (opus_stereo)
756          printf("\n Opus stereo enabled (select Opus again to apply the "
757                 "setting). \n");
758        else
759          printf("\n Opus mono enabled (select Opus again to apply the "
760                 "setting). \n");
761      } else {
762        break;
763      }
764    }
765
766    if (send) {
767      printf("Stop Send \n");
768      res = base1->StopSend(chan);
769      VALIDATE;
770    }
771
772    if (receive) {
773      printf("Stop Playout \n");
774      res = base1->StopPlayout(chan);
775      VALIDATE;
776
777#ifndef EXTERNAL_TRANSPORT
778      printf("Stop Listen \n");
779      res = base1->StopReceive(chan);
780      VALIDATE;
781#endif
782    }
783
784    while (channel_index > 0) {
785      --channel_index;
786      res = file->StopPlayingFileAsMicrophone(channels[channel_index]);
787      VALIDATE;
788      res = base1->StopSend(channels[channel_index]);
789      VALIDATE;
790      res = base1->StopPlayout(channels[channel_index]);
791      VALIDATE;
792      res = base1->StopReceive(channels[channel_index]);
793      VALIDATE;
794    }
795
796    printf("\n1. New call \n");
797    printf("2. Quit \n");
798    printf("Select action: ");
799    int end_option;
800    ASSERT_EQ(1, scanf("%i", &end_option));
801    newcall = (end_option == 1);
802    // Call loop
803  }
804  for (int i = 0; i < kMaxNumChannels; ++i) {
805    delete voice_channel_transports[i];
806    voice_channel_transports[i] = NULL;
807  }
808
809  printf("Delete channels \n");
810  res = base1->DeleteChannel(chan);
811  VALIDATE;
812
813  for (int i = 0; i < kMaxNumChannels; ++i) {
814    channels[i] = base1->DeleteChannel(channels[i]);
815    VALIDATE;
816  }
817}
818