1/*
2 * libjingle
3 * Copyright 2004 Google Inc.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 *
8 *  1. Redistributions of source code must retain the above copyright notice,
9 *     this list of conditions and the following disclaimer.
10 *  2. Redistributions in binary form must reproduce the above copyright notice,
11 *     this list of conditions and the following disclaimer in the documentation
12 *     and/or other materials provided with the distribution.
13 *  3. The name of the author may not be used to endorse or promote products
14 *     derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
17 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
18 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
19 * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
20 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
21 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
22 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
23 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
24 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
25 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28#include <assert.h>
29#include "talk/session/media/audiomonitor.h"
30#include "talk/session/media/voicechannel.h"
31
32namespace cricket {
33
34const uint32 MSG_MONITOR_POLL = 1;
35const uint32 MSG_MONITOR_START = 2;
36const uint32 MSG_MONITOR_STOP = 3;
37const uint32 MSG_MONITOR_SIGNAL = 4;
38
39AudioMonitor::AudioMonitor(VoiceChannel *voice_channel,
40                           rtc::Thread *monitor_thread) {
41  voice_channel_ = voice_channel;
42  monitoring_thread_ = monitor_thread;
43  monitoring_ = false;
44}
45
46AudioMonitor::~AudioMonitor() {
47  voice_channel_->worker_thread()->Clear(this);
48  monitoring_thread_->Clear(this);
49}
50
51void AudioMonitor::Start(int milliseconds) {
52  rate_ = milliseconds;
53  if (rate_ < 100)
54    rate_ = 100;
55  voice_channel_->worker_thread()->Post(this, MSG_MONITOR_START);
56}
57
58void AudioMonitor::Stop() {
59  voice_channel_->worker_thread()->Post(this, MSG_MONITOR_STOP);
60}
61
62void AudioMonitor::OnMessage(rtc::Message *message) {
63  rtc::CritScope cs(&crit_);
64
65  switch (message->message_id) {
66  case MSG_MONITOR_START:
67    assert(rtc::Thread::Current() == voice_channel_->worker_thread());
68    if (!monitoring_) {
69      monitoring_ = true;
70      PollVoiceChannel();
71    }
72    break;
73
74  case MSG_MONITOR_STOP:
75    assert(rtc::Thread::Current() == voice_channel_->worker_thread());
76    if (monitoring_) {
77      monitoring_ = false;
78      voice_channel_->worker_thread()->Clear(this);
79    }
80    break;
81
82  case MSG_MONITOR_POLL:
83    assert(rtc::Thread::Current() == voice_channel_->worker_thread());
84    PollVoiceChannel();
85    break;
86
87  case MSG_MONITOR_SIGNAL:
88    {
89      assert(rtc::Thread::Current() == monitoring_thread_);
90      AudioInfo info = audio_info_;
91      crit_.Leave();
92      SignalUpdate(this, info);
93      crit_.Enter();
94    }
95    break;
96  }
97}
98
99void AudioMonitor::PollVoiceChannel() {
100  rtc::CritScope cs(&crit_);
101  assert(rtc::Thread::Current() == voice_channel_->worker_thread());
102
103  // Gather connection infos
104  audio_info_.input_level = voice_channel_->GetInputLevel_w();
105  audio_info_.output_level = voice_channel_->GetOutputLevel_w();
106  voice_channel_->GetActiveStreams_w(&audio_info_.active_streams);
107
108  // Signal the monitoring thread, start another poll timer
109  monitoring_thread_->Post(this, MSG_MONITOR_SIGNAL);
110  voice_channel_->worker_thread()->PostDelayed(rate_, this, MSG_MONITOR_POLL);
111}
112
113VoiceChannel *AudioMonitor::voice_channel() {
114  return voice_channel_;
115}
116
117rtc::Thread *AudioMonitor::monitor_thread() {
118  return monitoring_thread_;
119}
120
121}
122