/*  SoundRenderer.h

    flatzebra - SDL-based sound renderer
    Copyright (C) 2011 Pierre Sarrazin <http://sarrazip.com/>

    This program is free software; you can redistribute it and/or
    modify it under the terms of the GNU General Public License
    as published by the Free Software Foundation; either version 2
    of the License, or (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public
    License along with this program; if not, write to the Free
    Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
    Boston, MA  02110-1301, USA.
*/

#pragma once

#include <flatzebra/roundbeetle/AutoLocker.h>
#include <flatzebra/roundbeetle/FrameSourceAdder.h>


namespace roundbeetle {


class SoundRenderer
{
protected:

    static SoundRenderer *inst;

    SoundRenderer(float _rendererFreqInHz);

public:

    // waitForEnd() must have been called successfully.
    //
    virtual ~SoundRenderer();

    static bool hasInstance();

    static SoundRenderer &instance();

    static SDL_mutex *getMutex();

    int start();

    virtual float getRendererFreq() const;

    // Returns frequency of the unique instance of this class.
    //
    static float freq();

    FrameSourceAdder &getTopFrameSourceAdder();

    // Can be used in a derived class to ask a thread to terminate.
    //
    virtual void requestStop();

    // Can be used in a derived class to reclaim a thread's resources
    // (e.g., pthread_join()).
    //
    virtual void waitForEnd();

    void startRecording();

    bool isRecording() const;

    // Returns true if renderer was recording.
    // Returns false if it was not.
    // It is harmless to call this when not recording, although it
    // involves locking a mutex.
    //
    bool stopRecording();

    bool isBusy() const;

protected:

    // Must return error code <= -100 on error, on 0 for success.
    //
    virtual int initAudio() = 0;

    void getFramesFromTopSource(Frame *frameBuffer, size_t numFramesToFill);

    // Called with every framebuffer obtained from the top frame source.
    //
    virtual void record(Frame *frameBuffer, size_t numFramesToFill);

private:

    SoundRenderer(const SoundRenderer &);
    SoundRenderer & operator = (const SoundRenderer &);

protected:

    SDL_mutex *mutex;  // owned by this object
    float rendererFreqInHz;
    FrameSourceAdder topFrameSource;
    bool recording;

};


}  // namespace roundbeetle
