412196cb3c1fb9d936c07426c65416cff320fa13
[platform/framework/web/crosswalk.git] / src / content / renderer / media / audio_input_message_filter.cc
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "content/renderer/media/audio_input_message_filter.h"
6
7 #include "base/bind.h"
8 #include "base/message_loop/message_loop_proxy.h"
9 #include "base/strings/stringprintf.h"
10 #include "content/common/media/audio_messages.h"
11 #include "content/renderer/media/webrtc_logging.h"
12 #include "ipc/ipc_logging.h"
13 #include "ipc/ipc_sender.h"
14
15 namespace content {
16
17 namespace {
18 const int kStreamIDNotSet = -1;
19 }
20
21 class AudioInputMessageFilter::AudioInputIPCImpl
22     : public NON_EXPORTED_BASE(media::AudioInputIPC) {
23  public:
24   AudioInputIPCImpl(const scoped_refptr<AudioInputMessageFilter>& filter,
25                     int render_view_id);
26   virtual ~AudioInputIPCImpl();
27
28   // media::AudioInputIPC implementation.
29   virtual void CreateStream(media::AudioInputIPCDelegate* delegate,
30                             int session_id,
31                             const media::AudioParameters& params,
32                             bool automatic_gain_control,
33                             uint32 total_segments) OVERRIDE;
34   virtual void RecordStream() OVERRIDE;
35   virtual void SetVolume(double volume) OVERRIDE;
36   virtual void CloseStream() OVERRIDE;
37
38  private:
39   const scoped_refptr<AudioInputMessageFilter> filter_;
40   const int render_view_id_;
41   int stream_id_;
42 };
43
44 AudioInputMessageFilter* AudioInputMessageFilter::g_filter = NULL;
45
46 AudioInputMessageFilter::AudioInputMessageFilter(
47     const scoped_refptr<base::MessageLoopProxy>& io_message_loop)
48     : sender_(NULL),
49       io_message_loop_(io_message_loop) {
50   DCHECK(!g_filter);
51   g_filter = this;
52 }
53
54 AudioInputMessageFilter::~AudioInputMessageFilter() {
55   DCHECK_EQ(g_filter, this);
56   g_filter = NULL;
57 }
58
59 // static
60 AudioInputMessageFilter* AudioInputMessageFilter::Get() {
61   return g_filter;
62 }
63
64 void AudioInputMessageFilter::Send(IPC::Message* message) {
65   DCHECK(io_message_loop_->BelongsToCurrentThread());
66   if (!sender_) {
67     delete message;
68   } else {
69     sender_->Send(message);
70   }
71 }
72
73 bool AudioInputMessageFilter::OnMessageReceived(const IPC::Message& message) {
74   DCHECK(io_message_loop_->BelongsToCurrentThread());
75   bool handled = true;
76   IPC_BEGIN_MESSAGE_MAP(AudioInputMessageFilter, message)
77     IPC_MESSAGE_HANDLER(AudioInputMsg_NotifyStreamCreated,
78                         OnStreamCreated)
79     IPC_MESSAGE_HANDLER(AudioInputMsg_NotifyStreamVolume, OnStreamVolume)
80     IPC_MESSAGE_HANDLER(AudioInputMsg_NotifyStreamStateChanged,
81                         OnStreamStateChanged)
82     IPC_MESSAGE_UNHANDLED(handled = false)
83   IPC_END_MESSAGE_MAP()
84   return handled;
85 }
86
87 void AudioInputMessageFilter::OnFilterAdded(IPC::Sender* sender) {
88   DCHECK(io_message_loop_->BelongsToCurrentThread());
89
90   // Captures the sender for IPC.
91   sender_ = sender;
92 }
93
94 void AudioInputMessageFilter::OnFilterRemoved() {
95   DCHECK(io_message_loop_->BelongsToCurrentThread());
96
97   // Once removed, a filter will not be used again.  At this time all
98   // delegates must be notified so they release their reference.
99   OnChannelClosing();
100 }
101
102 void AudioInputMessageFilter::OnChannelClosing() {
103   DCHECK(io_message_loop_->BelongsToCurrentThread());
104   sender_ = NULL;
105
106   DLOG_IF(WARNING, !delegates_.IsEmpty())
107       << "Not all audio devices have been closed.";
108
109   IDMap<media::AudioInputIPCDelegate>::iterator it(&delegates_);
110   while (!it.IsAtEnd()) {
111     it.GetCurrentValue()->OnIPCClosed();
112     delegates_.Remove(it.GetCurrentKey());
113     it.Advance();
114   }
115 }
116
117 void AudioInputMessageFilter::OnStreamCreated(
118     int stream_id,
119     base::SharedMemoryHandle handle,
120 #if defined(OS_WIN)
121     base::SyncSocket::Handle socket_handle,
122 #else
123     base::FileDescriptor socket_descriptor,
124 #endif
125     uint32 length,
126     uint32 total_segments) {
127   DCHECK(io_message_loop_->BelongsToCurrentThread());
128
129   WebRtcLogMessage(base::StringPrintf(
130       "AIMF::OnStreamCreated. stream_id=%d",
131       stream_id));
132
133 #if !defined(OS_WIN)
134   base::SyncSocket::Handle socket_handle = socket_descriptor.fd;
135 #endif
136   media::AudioInputIPCDelegate* delegate = delegates_.Lookup(stream_id);
137   if (!delegate) {
138     DLOG(WARNING) << "Got audio stream event for a non-existent or removed"
139                   << " audio capturer (stream_id=" << stream_id << ").";
140     base::SharedMemory::CloseHandle(handle);
141     base::SyncSocket socket(socket_handle);
142     return;
143   }
144   // Forward message to the stream delegate.
145   delegate->OnStreamCreated(handle, socket_handle, length, total_segments);
146 }
147
148 void AudioInputMessageFilter::OnStreamVolume(int stream_id, double volume) {
149   DCHECK(io_message_loop_->BelongsToCurrentThread());
150   media::AudioInputIPCDelegate* delegate = delegates_.Lookup(stream_id);
151   if (!delegate) {
152     DLOG(WARNING) << "Got audio stream event for a non-existent or removed"
153                   << " audio capturer.";
154     return;
155   }
156   delegate->OnVolume(volume);
157 }
158
159 void AudioInputMessageFilter::OnStreamStateChanged(
160     int stream_id, media::AudioInputIPCDelegate::State state) {
161   DCHECK(io_message_loop_->BelongsToCurrentThread());
162   media::AudioInputIPCDelegate* delegate = delegates_.Lookup(stream_id);
163   if (!delegate) {
164     DLOG(WARNING) << "Got audio stream event for a non-existent or removed"
165                   << " audio renderer.";
166     return;
167   }
168   delegate->OnStateChanged(state);
169 }
170
171 AudioInputMessageFilter::AudioInputIPCImpl::AudioInputIPCImpl(
172     const scoped_refptr<AudioInputMessageFilter>& filter, int render_view_id)
173     : filter_(filter),
174       render_view_id_(render_view_id),
175       stream_id_(kStreamIDNotSet) {}
176
177 AudioInputMessageFilter::AudioInputIPCImpl::~AudioInputIPCImpl() {}
178
179 scoped_ptr<media::AudioInputIPC> AudioInputMessageFilter::CreateAudioInputIPC(
180     int render_view_id) {
181   DCHECK_GT(render_view_id, 0);
182   return scoped_ptr<media::AudioInputIPC>(
183       new AudioInputIPCImpl(this, render_view_id));
184 }
185
186 void AudioInputMessageFilter::AudioInputIPCImpl::CreateStream(
187     media::AudioInputIPCDelegate* delegate,
188     int session_id,
189     const media::AudioParameters& params,
190     bool automatic_gain_control,
191     uint32 total_segments) {
192   DCHECK(filter_->io_message_loop_->BelongsToCurrentThread());
193   DCHECK(delegate);
194
195   stream_id_ = filter_->delegates_.Add(delegate);
196
197   AudioInputHostMsg_CreateStream_Config config;
198   config.params = params;
199   config.automatic_gain_control = automatic_gain_control;
200   config.shared_memory_count = total_segments;
201   filter_->Send(new AudioInputHostMsg_CreateStream(
202       stream_id_, render_view_id_, session_id, config));
203 }
204
205 void AudioInputMessageFilter::AudioInputIPCImpl::RecordStream() {
206   DCHECK_NE(stream_id_, kStreamIDNotSet);
207   filter_->Send(new AudioInputHostMsg_RecordStream(stream_id_));
208 }
209
210 void AudioInputMessageFilter::AudioInputIPCImpl::SetVolume(double volume) {
211   DCHECK_NE(stream_id_, kStreamIDNotSet);
212   filter_->Send(new AudioInputHostMsg_SetVolume(stream_id_, volume));
213 }
214
215 void AudioInputMessageFilter::AudioInputIPCImpl::CloseStream() {
216   DCHECK(filter_->io_message_loop_->BelongsToCurrentThread());
217   DCHECK_NE(stream_id_, kStreamIDNotSet);
218   filter_->Send(new AudioInputHostMsg_CloseStream(stream_id_));
219   filter_->delegates_.Remove(stream_id_);
220   stream_id_ = kStreamIDNotSet;
221 }
222
223 }  // namespace content