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#if defined(WEBRTC_ANDROID)
12#include "webrtc/modules/audio_device/android/audio_device_template.h"
13#include "webrtc/modules/audio_device/android/audio_record_jni.h"
14#include "webrtc/modules/audio_device/android/audio_track_jni.h"
15#include "webrtc/modules/utility/include/jvm_android.h"
16#endif
17
18#include "webrtc/base/checks.h"
19#include "webrtc/modules/audio_coding/include/audio_coding_module.h"
20#include "webrtc/system_wrappers/include/critical_section_wrapper.h"
21#include "webrtc/system_wrappers/include/trace.h"
22#include "webrtc/voice_engine/channel_proxy.h"
23#include "webrtc/voice_engine/voice_engine_impl.h"
24
25namespace webrtc {
26
27// Counter to be ensure that we can add a correct ID in all static trace
28// methods. It is not the nicest solution, especially not since we already
29// have a counter in VoEBaseImpl. In other words, there is room for
30// improvement here.
31static int32_t gVoiceEngineInstanceCounter = 0;
32
33VoiceEngine* GetVoiceEngine(const Config* config, bool owns_config) {
34  VoiceEngineImpl* self = new VoiceEngineImpl(config, owns_config);
35  if (self != NULL) {
36    self->AddRef();  // First reference.  Released in VoiceEngine::Delete.
37    gVoiceEngineInstanceCounter++;
38  }
39  return self;
40}
41
42int VoiceEngineImpl::AddRef() {
43  return ++_ref_count;
44}
45
46// This implements the Release() method for all the inherited interfaces.
47int VoiceEngineImpl::Release() {
48  int new_ref = --_ref_count;
49  assert(new_ref >= 0);
50  if (new_ref == 0) {
51    WEBRTC_TRACE(kTraceApiCall, kTraceVoice, -1,
52                 "VoiceEngineImpl self deleting (voiceEngine=0x%p)", this);
53
54    // Clear any pointers before starting destruction. Otherwise worker-
55    // threads will still have pointers to a partially destructed object.
56    // Example: AudioDeviceBuffer::RequestPlayoutData() can access a
57    // partially deconstructed |_ptrCbAudioTransport| during destruction
58    // if we don't call Terminate here.
59    Terminate();
60    delete this;
61  }
62
63  return new_ref;
64}
65
66rtc::scoped_ptr<voe::ChannelProxy> VoiceEngineImpl::GetChannelProxy(
67    int channel_id) {
68  RTC_DCHECK(channel_id >= 0);
69  CriticalSectionScoped cs(crit_sec());
70  RTC_DCHECK(statistics().Initialized());
71  return rtc::scoped_ptr<voe::ChannelProxy>(
72      new voe::ChannelProxy(channel_manager().GetChannel(channel_id)));
73}
74
75VoiceEngine* VoiceEngine::Create() {
76  Config* config = new Config();
77  return GetVoiceEngine(config, true);
78}
79
80VoiceEngine* VoiceEngine::Create(const Config& config) {
81  return GetVoiceEngine(&config, false);
82}
83
84int VoiceEngine::SetTraceFilter(unsigned int filter) {
85  WEBRTC_TRACE(kTraceApiCall, kTraceVoice,
86               VoEId(gVoiceEngineInstanceCounter, -1),
87               "SetTraceFilter(filter=0x%x)", filter);
88
89  // Remember old filter
90  uint32_t oldFilter = Trace::level_filter();
91  Trace::set_level_filter(filter);
92
93  // If previous log was ignored, log again after changing filter
94  if (kTraceNone == oldFilter) {
95    WEBRTC_TRACE(kTraceApiCall, kTraceVoice, -1, "SetTraceFilter(filter=0x%x)",
96                 filter);
97  }
98
99  return 0;
100}
101
102int VoiceEngine::SetTraceFile(const char* fileNameUTF8, bool addFileCounter) {
103  int ret = Trace::SetTraceFile(fileNameUTF8, addFileCounter);
104  WEBRTC_TRACE(kTraceApiCall, kTraceVoice,
105               VoEId(gVoiceEngineInstanceCounter, -1),
106               "SetTraceFile(fileNameUTF8=%s, addFileCounter=%d)", fileNameUTF8,
107               addFileCounter);
108  return (ret);
109}
110
111int VoiceEngine::SetTraceCallback(TraceCallback* callback) {
112  WEBRTC_TRACE(kTraceApiCall, kTraceVoice,
113               VoEId(gVoiceEngineInstanceCounter, -1),
114               "SetTraceCallback(callback=0x%x)", callback);
115  return (Trace::SetTraceCallback(callback));
116}
117
118bool VoiceEngine::Delete(VoiceEngine*& voiceEngine) {
119  if (voiceEngine == NULL)
120    return false;
121
122  VoiceEngineImpl* s = static_cast<VoiceEngineImpl*>(voiceEngine);
123  // Release the reference that was added in GetVoiceEngine.
124  int ref = s->Release();
125  voiceEngine = NULL;
126
127  if (ref != 0) {
128    WEBRTC_TRACE(
129        kTraceWarning, kTraceVoice, -1,
130        "VoiceEngine::Delete did not release the very last reference.  "
131        "%d references remain.",
132        ref);
133  }
134
135  return true;
136}
137
138#if !defined(WEBRTC_CHROMIUM_BUILD)
139// TODO(henrika): change types to JavaVM* and jobject instead of void*.
140int VoiceEngine::SetAndroidObjects(void* javaVM, void* context) {
141#ifdef WEBRTC_ANDROID
142  webrtc::JVM::Initialize(reinterpret_cast<JavaVM*>(javaVM),
143                          reinterpret_cast<jobject>(context));
144  return 0;
145#else
146  return -1;
147#endif
148}
149#endif
150
151std::string VoiceEngine::GetVersionString() {
152  std::string version = "VoiceEngine 4.1.0";
153#ifdef WEBRTC_EXTERNAL_TRANSPORT
154  version += " (External transport build)";
155#endif
156  return version;
157}
158
159}  // namespace webrtc
160