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. Get last error code \n", option_index++);
437      printf("%i. Toggle typing detection \n",
438             option_index++);
439      printf("%i. Record a PCM file \n", option_index++);
440      printf("%i. Play a previously recorded PCM file locally \n",
441             option_index++);
442      printf("%i. Play a previously recorded PCM file as microphone \n",
443             option_index++);
444      printf("%i. Add an additional file-playing channel \n", option_index++);
445      printf("%i. Remove a file-playing channel \n", option_index++);
446      printf("%i. Toggle Opus stereo (Opus must be selected again to apply "
447             "the setting) \n", option_index++);
448      printf("%i. Set Opus maximum playback rate \n", option_index++);
449      printf("%i. Set bit rate (only take effect on codecs that allow the "
450             "change) \n", option_index++);
451
452      printf("Select action or %i to stop the call: ", option_index);
453      int option_selection;
454      ASSERT_EQ(1, scanf("%i", &option_selection));
455
456      option_index = num_codecs;
457      if (option_selection < option_index) {
458        res = codec->GetCodec(option_selection, cinst);
459        VALIDATE;
460        SetStereoIfOpus(opus_stereo, &cinst);
461        printf("Set primary codec\n");
462        res = codec->SetSendCodec(chan, cinst);
463        VALIDATE;
464      } else if (option_selection == option_index++) {
465        enable_cng = !enable_cng;
466        res = codec->SetVADStatus(0, enable_cng);
467        VALIDATE;
468        if (enable_cng)
469          printf("\n CNG is now on! \n");
470        else
471          printf("\n CNG is now off! \n");
472      } else if (option_selection == option_index++) {
473        enable_agc = !enable_agc;
474        res = apm->SetAgcStatus(enable_agc);
475        VALIDATE;
476        if (enable_agc)
477          printf("\n AGC is now on! \n");
478        else
479          printf("\n AGC is now off! \n");
480      } else if (option_selection == option_index++) {
481        enable_ns = !enable_ns;
482        res = apm->SetNsStatus(enable_ns);
483        VALIDATE;
484        if (enable_ns)
485          printf("\n NS is now on! \n");
486        else
487          printf("\n NS is now off! \n");
488      } else if (option_selection == option_index++) {
489        experimental_ns_enabled = !experimental_ns_enabled;
490        Config config;
491        config.Set<ExperimentalNs>(new ExperimentalNs(experimental_ns_enabled));
492        base1->audio_processing()->SetExtraOptions(config);
493        if (experimental_ns_enabled) {
494          printf("\n Experimental NS is now on!\n");
495        } else {
496          printf("\n Experimental NS is now off!\n");
497        }
498      } else if (option_selection == option_index++) {
499        enable_aec = !enable_aec;
500        res = apm->SetEcStatus(enable_aec, kEcUnchanged);
501        VALIDATE;
502        if (enable_aec)
503          printf("\n Echo control is now on! \n");
504        else
505          printf("\n Echo control is now off! \n");
506      } else if (option_selection == option_index++) {
507        res = apm->SetEcStatus(enable_aec, kEcAec);
508        VALIDATE;
509        printf("\n AEC selected! \n");
510        if (enable_aec)
511          printf(" (Echo control is on)\n");
512        else
513          printf(" (Echo control is off)\n");
514      } else if (option_selection == option_index++) {
515        res = apm->SetEcStatus(enable_aec, kEcAecm);
516        VALIDATE;
517        printf("\n AECM selected! \n");
518        if (enable_aec)
519          printf(" (Echo control is on)\n");
520        else
521          printf(" (Echo control is off)\n");
522      } else if (option_selection == option_index++) {
523        unsigned vol(0);
524        res = volume->GetSpeakerVolume(vol);
525        VALIDATE;
526        printf("\n Speaker Volume is %d \n", vol);
527      } else if (option_selection == option_index++) {
528        printf("Level: ");
529        int level;
530        ASSERT_EQ(1, scanf("%i", &level));
531        res = volume->SetSpeakerVolume(level);
532        VALIDATE;
533      } else if (option_selection == option_index++) {
534        unsigned vol(0);
535        res = volume->GetMicVolume(vol);
536        VALIDATE;
537        printf("\n Microphone Volume is %d \n", vol);
538      } else if (option_selection == option_index++) {
539        printf("Level: ");
540        int level;
541        ASSERT_EQ(1, scanf("%i", &level));
542        res = volume->SetMicVolume(level);
543        VALIDATE;
544      } else if (option_selection == option_index++) {
545        res = file->StartPlayingFileLocally(0, audio_filename.c_str());
546        VALIDATE;
547      } else if (option_selection == option_index++) {
548        // change the playout device with current call
549        int num_pd(-1);
550        res = hardware->GetNumOfPlayoutDevices(num_pd);
551        VALIDATE;
552
553        char dn[128] = { 0 };
554        char guid[128] = { 0 };
555
556        printf("\nPlayout devices (%d): \n", num_pd);
557        for (int i = 0; i < num_pd; ++i) {
558          res = hardware->GetPlayoutDeviceName(i, dn, guid);
559          VALIDATE;
560          printf("  %d: %s \n", i, dn);
561        }
562        printf("Select playout device: ");
563        ASSERT_EQ(1, scanf("%d", &num_pd));
564        // Will use plughw for hardware devices
565        res = hardware->SetPlayoutDevice(num_pd);
566        VALIDATE;
567      } else if (option_selection == option_index++) {
568        // change the recording device with current call
569        int num_rd(-1);
570
571        res = hardware->GetNumOfRecordingDevices(num_rd);
572        VALIDATE;
573
574        char dn[128] = { 0 };
575        char guid[128] = { 0 };
576
577        printf("Recording devices (%d): \n", num_rd);
578        for (int i = 0; i < num_rd; ++i) {
579          res = hardware->GetRecordingDeviceName(i, dn, guid);
580          VALIDATE;
581          printf("  %d: %s \n", i, dn);
582        }
583
584        printf("Select recording device: ");
585        ASSERT_EQ(1, scanf("%d", &num_rd));
586        printf("Setting sound devices \n");
587        // Will use plughw for hardware devices
588        res = hardware->SetRecordingDevice(num_rd);
589        VALIDATE;
590      } else if (option_selection == option_index++) {
591        // Remote AGC
592        enable_rx_agc = !enable_rx_agc;
593        res = apm->SetRxAgcStatus(chan, enable_rx_agc);
594        VALIDATE;
595        if (enable_rx_agc)
596          printf("\n Receive-side AGC is now on! \n");
597        else
598          printf("\n Receive-side AGC is now off! \n");
599      } else if (option_selection == option_index++) {
600        // Remote NS
601        enable_rx_ns = !enable_rx_ns;
602        res = apm->SetRxNsStatus(chan, enable_rx_ns);
603        VALIDATE;
604        if (enable_rx_ns)
605          printf("\n Receive-side NS is now on! \n");
606        else
607          printf("\n Receive-side NS is now off! \n");
608      } else if (option_selection == option_index++) {
609        AgcModes agcmode;
610        bool enable;
611        res = apm->GetAgcStatus(enable, agcmode);
612        VALIDATE
613            printf("\n AGC enable is %d, mode is %d \n", enable, agcmode);
614      } else if (option_selection == option_index++) {
615        // Toggle Mute on Microphone
616        res = volume->GetInputMute(chan, muted);
617        VALIDATE;
618        muted = !muted;
619        res = volume->SetInputMute(chan, muted);
620        VALIDATE;
621        if (muted)
622          printf("\n Microphone is now on mute! \n");
623        else
624          printf("\n Microphone is no longer on mute! \n");
625      } else if (option_selection == option_index++) {
626        // Get the last error code and print to screen
627        int err_code = 0;
628        err_code = base1->LastError();
629        if (err_code != -1)
630          printf("\n The last error code was %i.\n", err_code);
631      } else if (option_selection == option_index++) {
632        typing_detection= !typing_detection;
633        res = apm->SetTypingDetectionStatus(typing_detection);
634        VALIDATE;
635        if (typing_detection)
636          printf("\n Typing detection is now on!\n");
637        else
638          printf("\n Typing detection is now off!\n");
639      } else if (option_selection == option_index++) {
640        int stop_record = 1;
641        int file_source = 1;
642        printf("\n Select source of recorded file. ");
643        printf("\n 1. Record from microphone to file ");
644        printf("\n 2. Record from playout to file ");
645        printf("\n Enter your selection: \n");
646        ASSERT_EQ(1, scanf("%i", &file_source));
647        if (file_source == 1) {
648          printf("\n Start recording microphone as %s \n",
649                 mic_filename.c_str());
650          res = file->StartRecordingMicrophone(mic_filename.c_str());
651          VALIDATE;
652        } else {
653          printf("\n Start recording playout as %s \n", play_filename.c_str());
654          res = file->StartRecordingPlayout(chan, play_filename.c_str());
655          VALIDATE;
656        }
657        while (stop_record != 0) {
658          printf("\n Type 0 to stop recording file \n");
659          ASSERT_EQ(1, scanf("%i", &stop_record));
660        }
661        if (file_source == 1) {
662          res = file->StopRecordingMicrophone();
663          VALIDATE;
664        } else {
665          res = file->StopRecordingPlayout(chan);
666          VALIDATE;
667        }
668        printf("\n File finished recording \n");
669      } else if (option_selection == option_index++) {
670        int file_type = 1;
671        int stop_play = 1;
672        printf("\n Select a file to play locally in a loop.");
673        printf("\n 1. Play %s", mic_filename.c_str());
674        printf("\n 2. Play %s", play_filename.c_str());
675        printf("\n Enter your selection\n");
676        ASSERT_EQ(1, scanf("%i", &file_type));
677        if (file_type == 1)  {
678          printf("\n Start playing %s locally in a loop\n",
679                 mic_filename.c_str());
680          res = file->StartPlayingFileLocally(chan, mic_filename.c_str(), true);
681          VALIDATE;
682        } else {
683          printf("\n Start playing %s locally in a loop\n",
684                 play_filename.c_str());
685          res = file->StartPlayingFileLocally(chan, play_filename.c_str(),
686                                              true);
687          VALIDATE;
688        }
689        while (stop_play != 0) {
690          printf("\n Type 0 to stop playing file\n");
691          ASSERT_EQ(1, scanf("%i", &stop_play));
692        }
693        res = file->StopPlayingFileLocally(chan);
694        VALIDATE;
695      } else if (option_selection == option_index++) {
696        int file_type = 1;
697        int stop_play = 1;
698        printf("\n Select a file to play as microphone in a loop.");
699        printf("\n 1. Play %s", mic_filename.c_str());
700        printf("\n 2. Play %s", play_filename.c_str());
701        printf("\n Enter your selection\n");
702        ASSERT_EQ(1, scanf("%i", &file_type));
703        if (file_type == 1)  {
704          printf("\n Start playing %s as mic in a loop\n",
705                 mic_filename.c_str());
706          res = file->StartPlayingFileAsMicrophone(chan, mic_filename.c_str(),
707                                                   true);
708          VALIDATE;
709        } else {
710          printf("\n Start playing %s as mic in a loop\n",
711                 play_filename.c_str());
712          res = file->StartPlayingFileAsMicrophone(chan, play_filename.c_str(),
713                                                   true);
714          VALIDATE;
715        }
716        while (stop_play != 0) {
717          printf("\n Type 0 to stop playing file\n");
718          ASSERT_EQ(1, scanf("%i", &stop_play));
719        }
720        res = file->StopPlayingFileAsMicrophone(chan);
721        VALIDATE;
722      } else if (option_selection == option_index++) {
723        if (channel_index < kMaxNumChannels) {
724          res = base1->StartReceive(channels[channel_index]);
725          VALIDATE;
726          res = base1->StartPlayout(channels[channel_index]);
727          VALIDATE;
728          res = base1->StartSend(channels[channel_index]);
729          VALIDATE;
730          res = file->StartPlayingFileAsMicrophone(channels[channel_index],
731                                                   audio_filename.c_str(),
732                                                   true,
733                                                   false);
734          VALIDATE;
735          channel_index++;
736          printf("Using %d additional channels\n", channel_index);
737        } else {
738          printf("Max number of channels reached\n");
739        }
740      } else if (option_selection == option_index++) {
741        if (channel_index > 0) {
742          channel_index--;
743          res = file->StopPlayingFileAsMicrophone(channels[channel_index]);
744          VALIDATE;
745          res = base1->StopSend(channels[channel_index]);
746          VALIDATE;
747          res = base1->StopPlayout(channels[channel_index]);
748          VALIDATE;
749          res = base1->StopReceive(channels[channel_index]);
750          VALIDATE;
751          printf("Using %d additional channels\n", channel_index);
752        } else {
753          printf("All additional channels stopped\n");
754        }
755      } else if (option_selection == option_index++) {
756        opus_stereo = !opus_stereo;
757        if (opus_stereo)
758          printf("\n Opus stereo enabled (select Opus again to apply the "
759                 "setting). \n");
760        else
761          printf("\n Opus mono enabled (select Opus again to apply the "
762                 "setting). \n");
763      } else if (option_selection == option_index++) {
764        printf("\n Input maxium playback rate in Hz: ");
765        int max_playback_rate;
766        ASSERT_EQ(1, scanf("%i", &max_playback_rate));
767        res = codec->SetOpusMaxPlaybackRate(chan, max_playback_rate);
768        VALIDATE;
769      } else if (option_selection == option_index++) {
770        res = codec->GetSendCodec(chan, cinst);
771        VALIDATE;
772        printf("Current bit rate is %i bps, set to: ", cinst.rate);
773        ASSERT_EQ(1, scanf("%i", &cinst.rate));
774        res = codec->SetSendCodec(chan, cinst);
775        VALIDATE;
776      } else {
777        break;
778      }
779    }
780
781    if (send) {
782      printf("Stop Send \n");
783      res = base1->StopSend(chan);
784      VALIDATE;
785    }
786
787    if (receive) {
788      printf("Stop Playout \n");
789      res = base1->StopPlayout(chan);
790      VALIDATE;
791
792#ifndef EXTERNAL_TRANSPORT
793      printf("Stop Listen \n");
794      res = base1->StopReceive(chan);
795      VALIDATE;
796#endif
797    }
798
799    while (channel_index > 0) {
800      --channel_index;
801      res = file->StopPlayingFileAsMicrophone(channels[channel_index]);
802      VALIDATE;
803      res = base1->StopSend(channels[channel_index]);
804      VALIDATE;
805      res = base1->StopPlayout(channels[channel_index]);
806      VALIDATE;
807      res = base1->StopReceive(channels[channel_index]);
808      VALIDATE;
809    }
810
811    printf("\n1. New call \n");
812    printf("2. Quit \n");
813    printf("Select action: ");
814    int end_option;
815    ASSERT_EQ(1, scanf("%i", &end_option));
816    newcall = (end_option == 1);
817    // Call loop
818  }
819  for (int i = 0; i < kMaxNumChannels; ++i) {
820    delete voice_channel_transports[i];
821    voice_channel_transports[i] = NULL;
822  }
823
824  printf("Delete channels \n");
825  res = base1->DeleteChannel(chan);
826  VALIDATE;
827
828  for (int i = 0; i < kMaxNumChannels; ++i) {
829    channels[i] = base1->DeleteChannel(channels[i]);
830    VALIDATE;
831  }
832}
833