/*
 * Copyright (C) 2011, Google Inc. All rights reserved.
 * Copyright (C) 2020-2021, Apple 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.
 */

#include "config.h"

#if ENABLE(WEB_AUDIO)

#include "DefaultAudioDestinationNode.h"

#include "AudioContext.h"
#include "AudioDestination.h"
#include "AudioWorklet.h"
#include "AudioWorkletMessagingProxy.h"
#include "Logging.h"
#include "MediaStrategy.h"
#include "PlatformStrategies.h"
#include "ScriptExecutionContext.h"
#include "WorkerRunLoop.h"
#include <wtf/IsoMallocInlines.h>
#include <wtf/MainThread.h>

constexpr unsigned EnabledInputChannels = 2;

namespace WebCore {

WTF_MAKE_ISO_ALLOCATED_IMPL(DefaultAudioDestinationNode);

DefaultAudioDestinationNode::DefaultAudioDestinationNode(AudioContext& context, std::optional<float> sampleRate)
    : AudioDestinationNode(context, sampleRate.value_or(AudioDestination::hardwareSampleRate()))
{
    ASSERT(BaseAudioContext::isSupportedSampleRate(AudioDestination::hardwareSampleRate()));
    initializeDefaultNodeOptions(2, ChannelCountMode::Explicit, ChannelInterpretation::Speakers);
}

DefaultAudioDestinationNode::~DefaultAudioDestinationNode()
{
    uninitialize();
}

AudioContext& DefaultAudioDestinationNode::context()
{
    return downcast<AudioContext>(AudioDestinationNode::context());
}

const AudioContext& DefaultAudioDestinationNode::context() const
{
    return downcast<AudioContext>(AudioDestinationNode::context());
}

void DefaultAudioDestinationNode::initialize()
{
    ASSERT(isMainThread()); 
    if (isInitialized())
        return;
    ALWAYS_LOG(LOGIDENTIFIER);

    createDestination();
    AudioNode::initialize();
}

void DefaultAudioDestinationNode::uninitialize()
{
    ASSERT(isMainThread()); 
    if (!isInitialized())
        return;

    ALWAYS_LOG(LOGIDENTIFIER);
    clearDestination();
    m_numberOfInputChannels = 0;

    AudioNode::uninitialize();
}

void DefaultAudioDestinationNode::clearDestination()
{
    ASSERT(m_destination);
    if (m_wasDestinationStarted) {
        m_destination->stop();
        m_wasDestinationStarted = false;
    }
    m_destination->clearCallback();
    m_destination = nullptr;
}

void DefaultAudioDestinationNode::createDestination()
{
    ALWAYS_LOG(LOGIDENTIFIER, "contextSampleRate = ", sampleRate(), ", hardwareSampleRate = ", AudioDestination::hardwareSampleRate());
    ASSERT(!m_destination);
    m_destination = platformStrategies()->mediaStrategy().createAudioDestination(*this, m_inputDeviceId, m_numberOfInputChannels, channelCount(), sampleRate());
}

void DefaultAudioDestinationNode::recreateDestination()
{
    bool wasDestinationStarted = m_wasDestinationStarted;
    clearDestination();
    createDestination();
    if (wasDestinationStarted) {
        m_wasDestinationStarted = true;
        m_destination->start(dispatchToRenderThreadFunction());
    }
}

void DefaultAudioDestinationNode::enableInput(const String& inputDeviceId)
{
    ALWAYS_LOG(LOGIDENTIFIER);

    ASSERT(isMainThread());
    if (m_numberOfInputChannels != EnabledInputChannels) {
        m_numberOfInputChannels = EnabledInputChannels;
        m_inputDeviceId = inputDeviceId;

        if (isInitialized())
            recreateDestination();
    }
}

Function<void(Function<void()>&&)> DefaultAudioDestinationNode::dispatchToRenderThreadFunction()
{
    if (auto* workletProxy = context().audioWorklet().proxy()) {
        return [workletProxy = Ref { *workletProxy }](Function<void()>&& function) {
            workletProxy->postTaskForModeToWorkletGlobalScope([function = WTFMove(function)](ScriptExecutionContext&) mutable {
                function();
            }, WorkerRunLoop::defaultMode());
        };
    }
    return nullptr;
}

void DefaultAudioDestinationNode::startRendering(CompletionHandler<void(std::optional<Exception>&&)>&& completionHandler)
{
    ASSERT(isInitialized());
    if (!isInitialized())
        return completionHandler(Exception { InvalidStateError, "AudioDestinationNode is not initialized"_s });

    auto innerCompletionHandler = [completionHandler = WTFMove(completionHandler)](bool success) mutable {
        completionHandler(success ? std::nullopt : std::make_optional(Exception { InvalidStateError, "Failed to start the audio device"_s }));
    };

    m_wasDestinationStarted = true;
    m_destination->start(dispatchToRenderThreadFunction(), WTFMove(innerCompletionHandler));
}

void DefaultAudioDestinationNode::resume(CompletionHandler<void(std::optional<Exception>&&)>&& completionHandler)
{
    ASSERT(isInitialized());
    if (!isInitialized()) {
        context().postTask([completionHandler = WTFMove(completionHandler)]() mutable {
            completionHandler(Exception { InvalidStateError, "AudioDestinationNode is not initialized"_s });
        });
        return;
    }
    m_wasDestinationStarted = true;
    m_destination->start(dispatchToRenderThreadFunction(), [completionHandler = WTFMove(completionHandler)](bool success) mutable {
        completionHandler(success ? std::nullopt : std::make_optional(Exception { InvalidStateError, "Failed to start the audio device"_s }));
    });
}

void DefaultAudioDestinationNode::suspend(CompletionHandler<void(std::optional<Exception>&&)>&& completionHandler)
{
    ASSERT(isInitialized());
    if (!isInitialized()) {
        context().postTask([completionHandler = WTFMove(completionHandler)]() mutable {
            completionHandler(Exception { InvalidStateError, "AudioDestinationNode is not initialized"_s });
        });
        return;
    }

    m_wasDestinationStarted = false;
    m_destination->stop([completionHandler = WTFMove(completionHandler)](bool success) mutable {
        completionHandler(success ? std::nullopt : std::make_optional(Exception { InvalidStateError, "Failed to stop the audio device"_s }));
    });
}

void DefaultAudioDestinationNode::restartRendering()
{
    if (!m_wasDestinationStarted)
        return;

    m_destination->stop();
    m_destination->start(dispatchToRenderThreadFunction());
}

void DefaultAudioDestinationNode::close(CompletionHandler<void()>&& completionHandler)
{
    ASSERT(isInitialized());
    uninitialize();
    context().postTask(WTFMove(completionHandler));
}

unsigned DefaultAudioDestinationNode::maxChannelCount() const
{
    return AudioDestination::maxChannelCount();
}

ExceptionOr<void> DefaultAudioDestinationNode::setChannelCount(unsigned channelCount)
{
    // The channelCount for the input to this node controls the actual number of channels we
    // send to the audio hardware. It can only be set depending on the maximum number of
    // channels supported by the hardware.

    ASSERT(isMainThread());
    ALWAYS_LOG(LOGIDENTIFIER, channelCount);

    if (channelCount > maxChannelCount())
        return Exception { IndexSizeError, "Channel count exceeds maximum limit"_s };

    auto oldChannelCount = this->channelCount();
    auto result = AudioNode::setChannelCount(channelCount);
    if (result.hasException())
        return result;

    if (this->channelCount() != oldChannelCount && isInitialized())
        recreateDestination();

    return { };
}

unsigned DefaultAudioDestinationNode::framesPerBuffer() const
{
    return m_destination ? m_destination->framesPerBuffer() : 0;
}

void DefaultAudioDestinationNode::render(AudioBus*, AudioBus* destinationBus, size_t numberOfFrames, const AudioIOPosition& outputPosition)
{
    renderQuantum(destinationBus, numberOfFrames, outputPosition);

    setIsSilent(destinationBus->isSilent());

    // The reason we are handling mute after the call to setIsSilent() is because the muted state does
    // not affect the audio destination node's effective playing state.
    if (m_muted)
        destinationBus->zero();
}

void DefaultAudioDestinationNode::setIsSilent(bool isSilent)
{
    if (m_isSilent == isSilent)
        return;

    m_isSilent = isSilent;
    updateIsEffectivelyPlayingAudio();
}

void DefaultAudioDestinationNode::isPlayingDidChange()
{
    updateIsEffectivelyPlayingAudio();
}

void DefaultAudioDestinationNode::updateIsEffectivelyPlayingAudio()
{
    bool isEffectivelyPlayingAudio = m_destination && m_destination->isPlaying() && !m_isSilent;
    if (m_isEffectivelyPlayingAudio == isEffectivelyPlayingAudio)
        return;

    m_isEffectivelyPlayingAudio = isEffectivelyPlayingAudio;
    context().isPlayingAudioDidChange();
}

} // namespace WebCore

#endif // ENABLE(WEB_AUDIO)
