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