1/*
2 * Copyright (C) 2011 Google Inc. All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are
6 * met:
7 *
8 *     * Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 *     * Redistributions in binary form must reproduce the above
11 * copyright notice, this list of conditions and the following disclaimer
12 * in the documentation and/or other materials provided with the
13 * distribution.
14 *     * Neither the name of Google Inc. nor the names of its
15 * contributors may be used to endorse or promote products derived from
16 * this software without specific prior written permission.
17 *
18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
21 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
22 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
24 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 */
30
31#include "config.h"
32
33#include "public/platform/WebMediaStreamSource.h"
34
35#include "platform/audio/AudioBus.h"
36#include "platform/mediastream/MediaStreamSource.h"
37#include "public/platform/WebAudioDestinationConsumer.h"
38#include "public/platform/WebMediaConstraints.h"
39#include "public/platform/WebString.h"
40#include "wtf/MainThread.h"
41#include "wtf/PassOwnPtr.h"
42#include "wtf/Vector.h"
43
44namespace blink {
45
46namespace {
47
48class ExtraDataContainer : public MediaStreamSource::ExtraData {
49public:
50    ExtraDataContainer(PassOwnPtr<WebMediaStreamSource::ExtraData> extraData) : m_extraData(extraData) { }
51
52    WebMediaStreamSource::ExtraData* extraData() { return m_extraData.get(); }
53
54private:
55    OwnPtr<WebMediaStreamSource::ExtraData> m_extraData;
56};
57
58} // namespace
59
60WebMediaStreamSource WebMediaStreamSource::ExtraData::owner()
61{
62    ASSERT(m_owner);
63    return WebMediaStreamSource(m_owner);
64}
65
66void WebMediaStreamSource::ExtraData::setOwner(MediaStreamSource* owner)
67{
68    ASSERT(!m_owner);
69    m_owner = owner;
70}
71
72WebMediaStreamSource::WebMediaStreamSource(const PassRefPtr<MediaStreamSource>& mediaStreamSource)
73    : m_private(mediaStreamSource)
74{
75}
76
77WebMediaStreamSource& WebMediaStreamSource::operator=(MediaStreamSource* mediaStreamSource)
78{
79    m_private = mediaStreamSource;
80    return *this;
81}
82
83void WebMediaStreamSource::assign(const WebMediaStreamSource& other)
84{
85    m_private = other.m_private;
86}
87
88void WebMediaStreamSource::reset()
89{
90    m_private.reset();
91}
92
93WebMediaStreamSource::operator PassRefPtr<MediaStreamSource>() const
94{
95    return m_private.get();
96}
97
98WebMediaStreamSource::operator MediaStreamSource*() const
99{
100    return m_private.get();
101}
102
103void WebMediaStreamSource::initialize(const WebString& id, Type type, const WebString& name)
104{
105    m_private = MediaStreamSource::create(id, static_cast<MediaStreamSource::Type>(type), name);
106}
107
108WebString WebMediaStreamSource::id() const
109{
110    ASSERT(!m_private.isNull());
111    return m_private.get()->id();
112}
113
114WebMediaStreamSource::Type WebMediaStreamSource::type() const
115{
116    ASSERT(!m_private.isNull());
117    return static_cast<Type>(m_private.get()->type());
118}
119
120WebString WebMediaStreamSource::name() const
121{
122    ASSERT(!m_private.isNull());
123    return m_private.get()->name();
124}
125
126void WebMediaStreamSource::setReadyState(ReadyState state)
127{
128    ASSERT(!m_private.isNull());
129    m_private->setReadyState(static_cast<MediaStreamSource::ReadyState>(state));
130}
131
132WebMediaStreamSource::ReadyState WebMediaStreamSource::readyState() const
133{
134    ASSERT(!m_private.isNull());
135    return static_cast<ReadyState>(m_private->readyState());
136}
137
138WebMediaStreamSource::ExtraData* WebMediaStreamSource::extraData() const
139{
140    ASSERT(!m_private.isNull());
141    MediaStreamSource::ExtraData* data = m_private->extraData();
142    if (!data)
143        return 0;
144    return static_cast<ExtraDataContainer*>(data)->extraData();
145}
146
147void WebMediaStreamSource::setExtraData(ExtraData* extraData)
148{
149    ASSERT(!m_private.isNull());
150
151    if (extraData)
152        extraData->setOwner(m_private.get());
153
154    m_private->setExtraData(adoptPtr(new ExtraDataContainer(adoptPtr(extraData))));
155}
156
157WebMediaConstraints WebMediaStreamSource::constraints()
158{
159    ASSERT(!m_private.isNull());
160    return m_private->constraints();
161}
162
163bool WebMediaStreamSource::requiresAudioConsumer() const
164{
165    ASSERT(!m_private.isNull());
166    return m_private->requiresAudioConsumer();
167}
168
169class ConsumerWrapper FINAL : public AudioDestinationConsumer {
170public:
171    static ConsumerWrapper* create(WebAudioDestinationConsumer* consumer)
172    {
173        return new ConsumerWrapper(consumer);
174    }
175
176    virtual void setFormat(size_t numberOfChannels, float sampleRate) OVERRIDE;
177    virtual void consumeAudio(AudioBus*, size_t numberOfFrames) OVERRIDE;
178
179    WebAudioDestinationConsumer* consumer() { return m_consumer; }
180
181private:
182    explicit ConsumerWrapper(WebAudioDestinationConsumer* consumer) : m_consumer(consumer) { }
183
184    // m_consumer is not owned by this class.
185    WebAudioDestinationConsumer* m_consumer;
186};
187
188void ConsumerWrapper::setFormat(size_t numberOfChannels, float sampleRate)
189{
190    m_consumer->setFormat(numberOfChannels, sampleRate);
191}
192
193void ConsumerWrapper::consumeAudio(AudioBus* bus, size_t numberOfFrames)
194{
195    if (!bus)
196        return;
197
198    // Wrap AudioBus.
199    size_t numberOfChannels = bus->numberOfChannels();
200    WebVector<const float*> busVector(numberOfChannels);
201    for (size_t i = 0; i < numberOfChannels; ++i)
202        busVector[i] = bus->channel(i)->data();
203
204    m_consumer->consumeAudio(busVector, numberOfFrames);
205}
206
207void WebMediaStreamSource::addAudioConsumer(WebAudioDestinationConsumer* consumer)
208{
209    ASSERT(isMainThread());
210    ASSERT(!m_private.isNull() && consumer);
211
212    m_private->addAudioConsumer(ConsumerWrapper::create(consumer));
213}
214
215bool WebMediaStreamSource::removeAudioConsumer(WebAudioDestinationConsumer* consumer)
216{
217    ASSERT(isMainThread());
218    ASSERT(!m_private.isNull() && consumer);
219
220    const HeapHashSet<Member<AudioDestinationConsumer> >& consumers = m_private->audioConsumers();
221    for (HeapHashSet<Member<AudioDestinationConsumer> >::const_iterator it = consumers.begin(); it != consumers.end(); ++it) {
222        ConsumerWrapper* wrapper = static_cast<ConsumerWrapper*>(it->get());
223        if (wrapper->consumer() == consumer) {
224            m_private->removeAudioConsumer(wrapper);
225            return true;
226        }
227    }
228    return false;
229}
230
231} // namespace blink
232