Repository: LadybirdBrowser/ladybird
File: Libraries/LibWeb/WebAudio/BaseAudioContext.h (C/C++)

Code before:
    WebIDL::ExceptionOr<GC::Ref<GainNode>> create_gain();
    WebIDL::ExceptionOr<GC::Ref<PannerNode>> create_panner();
    WebIDL::ExceptionOr<GC::Ref<PeriodicWave>> create_periodic_wave(Vector<float> const& real, Vector<float> const& imag, Optional<PeriodicWaveConstraints> const& constraints = {});
    WebIDL::ExceptionOr<GC::Ref<ScriptProcessorNode>> create_script_processor(WebIDL::UnsignedLong buffer_size,
        WebIDL::UnsignedLong number_of_input_channels, WebIDL::UnsignedLong number_of_output_channels);
    WebIDL::ExceptionOr<GC::Ref<StereoPannerNode>> create_stereo_panner();

    GC::Ref<WebIDL::Promise> decode_audio_data(GC::Root<WebIDL::BufferSource>, GC::Ptr<WebIDL::CallbackType>, GC::Ptr<WebIDL::CallbackType>);

    void queue_control_message(ControlMessage);

protected:
    explicit BaseAudioContext(JS::Realm&, float m_sample_rate = 0);

    void queue_a_media_element_task(GC::Ref<GC::Function<void()>>);

    NodeID next_node_id() { return ++m_next_node_id; }

    virtual void initialize(JS::Realm&) override;
    virtual void visit_edges(Cell::Visitor&) override;

    GC::Ptr<AudioDestinationNode> m_destination;
    Vector<GC::Ref<WebIDL::Promise>> m_pending_promises;

private:
    friend class AudioNode;

    // https://webaudio.github.io/web-audio-api/#render-quantum-size
    static constexpr WebIDL::UnsignedLong s_render_quantum_size { 128 };

    void queue_a_decoding_operation(GC::Ref<JS::PromiseCapability>, GC::Root<WebIDL::BufferSource>, GC::Ptr<WebIDL::CallbackType>, GC::Ptr<WebIDL::CallbackType>);

    u64 m_next_node_id { 0 };

    float m_sample_rate { 0 };
    double m_current_time { 0 };

    GC::Ref<AudioListener> m_listener;

    Bindings::AudioContextState m_control_thread_state = Bindings::AudioContextState::Suspended;
    Bindings::AudioContextState m_rendering_thread_state = Bindings::AudioContextState::Suspended;

    HTML::UniqueTaskSource m_media_element_event_task_source {};

    NonnullOwnPtr<ControlMessageQueue> m_control_message_queue;
};

}


Review comment (suggestion):
Nit; you don't have to add a friend class just for this one new method. Make this public:

```cpp
NodeID next_node_id(Badge<AudioNode>) { return ++m_next_node_id; }
```

And in AudioNode's constructor, do this:

```cpp
    , m_node_id(context->next_node_id({}))
```

Code after:
    WebIDL::ExceptionOr<GC::Ref<GainNode>> create_gain();
    WebIDL::ExceptionOr<GC::Ref<PannerNode>> create_panner();
    WebIDL::ExceptionOr<GC::Ref<PeriodicWave>> create_periodic_wave(Vector<float> const& real, Vector<float> const& imag, Optional<PeriodicWaveConstraints> const& constraints = {});
    WebIDL::ExceptionOr<GC::Ref<ScriptProcessorNode>> create_script_processor(WebIDL::UnsignedLong buffer_size,
        WebIDL::UnsignedLong number_of_input_channels, WebIDL::UnsignedLong number_of_output_channels);
    WebIDL::ExceptionOr<GC::Ref<StereoPannerNode>> create_stereo_panner();

    GC::Ref<WebIDL::Promise> decode_audio_data(GC::Root<WebIDL::BufferSource>, GC::Ptr<WebIDL::CallbackType>, GC::Ptr<WebIDL::CallbackType>);

    void queue_control_message(ControlMessage);

    NodeID next_node_id(Badge<AudioNode>) { return ++m_next_node_id; }

protected:
    explicit BaseAudioContext(JS::Realm&, float m_sample_rate = 0);

    void queue_a_media_element_task(GC::Ref<GC::Function<void()>>);

    virtual void initialize(JS::Realm&) override;
    virtual void visit_edges(Cell::Visitor&) override;

    GC::Ptr<AudioDestinationNode> m_destination;
    Vector<GC::Ref<WebIDL::Promise>> m_pending_promises;

private:
    // https://webaudio.github.io/web-audio-api/#render-quantum-size
    static constexpr WebIDL::UnsignedLong s_render_quantum_size { 128 };

    void queue_a_decoding_operation(GC::Ref<JS::PromiseCapability>, GC::Root<WebIDL::BufferSource>, GC::Ptr<WebIDL::CallbackType>, GC::Ptr<WebIDL::CallbackType>);

    u64 m_next_node_id { 0 };

    float m_sample_rate { 0 };
    double m_current_time { 0 };

    GC::Ref<AudioListener> m_listener;

    Bindings::AudioContextState m_control_thread_state = Bindings::AudioContextState::Suspended;
    Bindings::AudioContextState m_rendering_thread_state = Bindings::AudioContextState::Suspended;

    HTML::UniqueTaskSource m_media_element_event_task_source {};

    NonnullOwnPtr<ControlMessageQueue> m_control_message_queue;
};

}