| /* | 
 |  * Copyright (C) 2010, Google Inc. All rights reserved. | 
 |  * | 
 |  * Redistribution and use in source and binary forms, with or without | 
 |  * modification, are permitted provided that the following conditions | 
 |  * are met: | 
 |  * 1.  Redistributions of source code must retain the above copyright | 
 |  *    notice, this list of conditions and the following disclaimer. | 
 |  * 2.  Redistributions in binary form must reproduce the above copyright | 
 |  *    notice, this list of conditions and the following disclaimer in the | 
 |  *    documentation and/or other materials provided with the distribution. | 
 |  * | 
 |  * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' AND | 
 |  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | 
 |  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | 
 |  * ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS BE LIABLE | 
 |  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | 
 |  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR | 
 |  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER | 
 |  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT | 
 |  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY | 
 |  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH | 
 |  * DAMAGE. | 
 |  */ | 
 |  | 
 | #ifndef AudioNodeOutput_h | 
 | #define AudioNodeOutput_h | 
 |  | 
 | #include "modules/webaudio/AudioNode.h" | 
 | #include "modules/webaudio/AudioParam.h" | 
 | #include "platform/audio/AudioBus.h" | 
 | #include "wtf/HashSet.h" | 
 | #include "wtf/RefPtr.h" | 
 | #include <memory> | 
 |  | 
 | namespace blink { | 
 |  | 
 | class AudioNodeInput; | 
 |  | 
 | // AudioNodeOutput represents a single output for an AudioNode. | 
 | // It may be connected to one or more AudioNodeInputs. | 
 | class AudioNodeOutput final { | 
 |   USING_FAST_MALLOC(AudioNodeOutput); | 
 |  | 
 |  public: | 
 |   // It's OK to pass 0 for numberOfChannels in which case | 
 |   // setNumberOfChannels() must be called later on. | 
 |   static std::unique_ptr<AudioNodeOutput> create(AudioHandler*, | 
 |                                                  unsigned numberOfChannels); | 
 |   void dispose(); | 
 |  | 
 |   // Causes our AudioNode to process if it hasn't already for this render | 
 |   // quantum.  It returns the bus containing the processed audio for this | 
 |   // output, returning inPlaceBus if in-place processing was possible.  Called | 
 |   // from context's audio thread. | 
 |   AudioBus* pull(AudioBus* inPlaceBus, size_t framesToProcess); | 
 |  | 
 |   // bus() will contain the rendered audio after pull() is called for each | 
 |   // rendering time quantum. | 
 |   // Called from context's audio thread. | 
 |   AudioBus* bus() const; | 
 |  | 
 |   // renderingFanOutCount() is the number of AudioNodeInputs that we're | 
 |   // connected to during rendering.  Unlike fanOutCount() it will not change | 
 |   // during the course of a render quantum. | 
 |   unsigned renderingFanOutCount() const; | 
 |  | 
 |   // Must be called with the context's graph lock. | 
 |   void disconnectAll(); | 
 |  | 
 |   // Disconnect a specific input or AudioParam. | 
 |   void disconnectInput(AudioNodeInput&); | 
 |   void disconnectAudioParam(AudioParamHandler&); | 
 |  | 
 |   void setNumberOfChannels(unsigned); | 
 |   unsigned numberOfChannels() const { return m_numberOfChannels; } | 
 |   bool isChannelCountKnown() const { return numberOfChannels() > 0; } | 
 |  | 
 |   bool isConnected() { return fanOutCount() > 0 || paramFanOutCount() > 0; } | 
 |  | 
 |   // Probe if the output node is connected with a certain input or AudioParam | 
 |   bool isConnectedToInput(AudioNodeInput&); | 
 |   bool isConnectedToAudioParam(AudioParamHandler&); | 
 |  | 
 |   // Disable/Enable happens when there are still JavaScript references to a | 
 |   // node, but it has otherwise "finished" its work.  For example, when a note | 
 |   // has finished playing.  It is kept around, because it may be played again at | 
 |   // a later time.  They must be called with the context's graph lock. | 
 |   void disable(); | 
 |   void enable(); | 
 |  | 
 |   // updateRenderingState() is called in the audio thread at the start or end of | 
 |   // the render quantum to handle any recent changes to the graph state. | 
 |   // It must be called with the context's graph lock. | 
 |   void updateRenderingState(); | 
 |  | 
 |  private: | 
 |   AudioNodeOutput(AudioHandler*, unsigned numberOfChannels); | 
 |   // Can be called from any thread. | 
 |   AudioHandler& handler() const { return m_handler; } | 
 |   DeferredTaskHandler& deferredTaskHandler() const { | 
 |     return m_handler.context()->deferredTaskHandler(); | 
 |   } | 
 |  | 
 |   // This reference is safe because the AudioHandler owns this AudioNodeOutput | 
 |   // object. | 
 |   AudioHandler& m_handler; | 
 |  | 
 |   friend class AudioNodeInput; | 
 |   friend class AudioParamHandler; | 
 |  | 
 |   // These are called from AudioNodeInput. | 
 |   // They must be called with the context's graph lock. | 
 |   void addInput(AudioNodeInput&); | 
 |   void removeInput(AudioNodeInput&); | 
 |   void addParam(AudioParamHandler&); | 
 |   void removeParam(AudioParamHandler&); | 
 |  | 
 |   // fanOutCount() is the number of AudioNodeInputs that we're connected to. | 
 |   // This method should not be called in audio thread rendering code, instead | 
 |   // renderingFanOutCount() should be used. | 
 |   // It must be called with the context's graph lock. | 
 |   unsigned fanOutCount(); | 
 |  | 
 |   // Similar to fanOutCount(), paramFanOutCount() is the number of AudioParams | 
 |   // that we're connected to.  This method should not be called in audio thread | 
 |   // rendering code, instead renderingParamFanOutCount() should be used. | 
 |   // It must be called with the context's graph lock. | 
 |   unsigned paramFanOutCount(); | 
 |  | 
 |   // Must be called with the context's graph lock. | 
 |   void disconnectAllInputs(); | 
 |   void disconnectAllParams(); | 
 |  | 
 |   // updateInternalBus() updates m_internalBus appropriately for the number of | 
 |   // channels.  It is called in the constructor or in the audio thread with the | 
 |   // context's graph lock. | 
 |   void updateInternalBus(); | 
 |  | 
 |   // Announce to any nodes we're connected to that we changed our channel count | 
 |   // for its input. | 
 |   // It must be called in the audio thread with the context's graph lock. | 
 |   void propagateChannelCount(); | 
 |  | 
 |   // updateNumberOfChannels() is called in the audio thread at the start or end | 
 |   // of the render quantum to pick up channel changes. | 
 |   // It must be called with the context's graph lock. | 
 |   void updateNumberOfChannels(); | 
 |  | 
 |   // m_numberOfChannels will only be changed in the audio thread. | 
 |   // The main thread sets m_desiredNumberOfChannels which will later get picked | 
 |   // up in the audio thread in updateNumberOfChannels(). | 
 |   unsigned m_numberOfChannels; | 
 |   unsigned m_desiredNumberOfChannels; | 
 |  | 
 |   // m_internalBus and m_inPlaceBus must only be changed in the audio thread | 
 |   // with the context's graph lock (or constructor). | 
 |   RefPtr<AudioBus> m_internalBus; | 
 |   RefPtr<AudioBus> m_inPlaceBus; | 
 |   // If m_isInPlace is true, use m_inPlaceBus as the valid AudioBus; If false, | 
 |   // use the default m_internalBus. | 
 |   bool m_isInPlace; | 
 |  | 
 |   // This HashSet holds connection references. We must call | 
 |   // AudioNode::makeConnection when we add an AudioNodeInput to this, and must | 
 |   // call AudioNode::breakConnection() when we remove an AudioNodeInput from | 
 |   // this. | 
 |   HashSet<AudioNodeInput*> m_inputs; | 
 |   bool m_isEnabled; | 
 |  | 
 |   bool m_didCallDispose; | 
 |  | 
 |   // For the purposes of rendering, keeps track of the number of inputs and | 
 |   // AudioParams we're connected to.  These value should only be changed at the | 
 |   // very start or end of the rendering quantum. | 
 |   unsigned m_renderingFanOutCount; | 
 |   unsigned m_renderingParamFanOutCount; | 
 |  | 
 |   // This collection of raw pointers is safe because they are retained by | 
 |   // AudioParam objects retained by m_connectedParams of the owner AudioNode. | 
 |   HashSet<AudioParamHandler*> m_params; | 
 | }; | 
 |  | 
 | }  // namespace blink | 
 |  | 
 | #endif  // AudioNodeOutput_h |