/*****************************************************************************
 * $LastChangedDate: 2011-04-23 21:07:07 -0400 (Sat, 23 Apr 2011) $
 * @file
 * @author  Jim E. Brooks  http://www.palomino3d.org
 * @brief   Sound class.
 *//*
 * LEGAL:   COPYRIGHT (C) 2007 JIM E. BROOKS
 *          THIS SOURCE CODE IS RELEASED UNDER THE TERMS
 *          OF THE GNU GENERAL PUBLIC LICENSE VERSION 2 (GPL 2).
 *****************************************************************************/

#if COMPILE_PLIB
#ifndef SOUND_SOUND_PLIB_HH
#define SOUND_SOUND_PLIB_HH 1

#include "base/singleton.hh"
#include "base/timer.hh"

//------------------------------------------------------------------------------
namespace sound {
namespace defs {

const uint         SOUND_PLIB_SAMPLE_RATE = 8000;
const string       SOUND_PLIB_MIXER_DEVICE ="/dev/mixer";
const uint         SOUND_PLIB_VOLUME = 50;
const Milliseconds SOUND_PLIB_TICK_FREQ( 20 );

} // namespace defs
} // namespace sound
//------------------------------------------------------------------------------

#include "sound/sound_base.hh"
#include "sound/sound_sample.hh"

class slScheduler;  // alternative to including plib headers here
class smMixer;
class slSample;

namespace sound {

class SamplePLIB;

////////////////////////////////////////////////////////////////////////////////
/// @brief Sound class based on PLIB.
///
/// Changing the volume of a PLIB sample should be considered a slow operation.
///
/// Gory details of PLIB code is better structured by making Sample
/// mostly private to Sound, but letting Sample have full access to Sound.
///
class SoundPLIB : public SoundBase
{
PREVENT_COPYING(SoundPLIB)
friend class SamplePLIB;
private:
                            SoundPLIB( void );
    virtual                 ~SoundPLIB();

public:
                            DEFINE_GetInstance( SoundPLIB )  // Singleton
    virtual bool            Enable( const bool enable = true );
    virtual bool            IfEnabled( void ) { return mEnabled; }
    virtual fp              GetVolume( void );
    virtual bool            SetVolume( const fp volume );  // master volume
    // [SoundBase defines the other methods]

private:
    virtual shptr<Sample>   CreateSample( const Sample::Name& sampleName );

// PLIB-specific:
private:
    void                    Pulse( void );
    void                    EnqueueZombieSample( slSample* zombie );

private:
    /// @brief Timer-tick.
    CLASS_TICK_FUNCTOR_BASIC

private:
    CLASS_VAR SoundPLIB*    msInstance;
    bool                    mEnabled;
    bool                    mWasEnabled;
    fp                      mVolume;            ///< master volume
    shptr<TickFunctor>      mTickFunctor;       ///< to pulse PLIB
    slScheduler*            mSched;             ///< PLIB
    smMixer*                mMixer;             ///< PLIB
    std::set<slSample*>     mZombieSamples;     ///< samples that were discarded after changing volume (yuck)
};

} // namespace sound

#endif // SOUND_SOUND_PLIB_HH
#endif // COMPILE_PLIB
