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

#ifndef SOUND_SOUND_BASE_HH
#define SOUND_SOUND_BASE_HH 1

#include <map>
#include "sound/defs.hh"
#include "sound/sound_sample.hh"

namespace sound {

////////////////////////////////////////////////////////////////////////////////
/// @brief Base Sound class.
///
/// SoundBase:
/// ----------
/// SoundBase provides generic functionality.
/// SoundBase controls sound samples in terms of the base Sample class.
/// A derivative of Sound is specific to a sound system.
/// If no sound system is available, SoundNOP will be compiled.
///
/// Sound keeps tracking of samples being played:
/// ---------------------------------------------
/// Play() will become a NOP if redundantly passed the same args while it is still playing.
/// So clients can rely on Sound to keep track of which samples are playing.
///
/// Class design:
/// -------------
/// A derivative of SoundBase initializes the sound system and controls the master volume.
/// A derivative of Sample plays sound files.
/// SoundBase provides caching of Samples.
/// SoundBase is able to define the Sample-related methods,
/// but defers other functionality to a SoundBase derivative.
///
class SoundBase
{
PREVENT_COPYING(SoundBase)
protected:
                    SoundBase( void );
    virtual         ~SoundBase();

public:
    virtual bool    Enable( const bool enable = true ) = 0;
    virtual bool    IfEnabled( void ) = 0;
    bool            IfPlaying( const Sample::Name& sampleName );
    bool            Play( const Sample::Name& sampleName,
                          const defs::ePlayLoop playLoop,
                          const fp volume = defs::DEFAULT_VOLUME );
    bool            Stop( void );
    bool            Stop( const Sample::Name& sampleName );
    virtual fp      GetVolume( void ) = 0;             // master volume
    virtual bool    SetVolume( const fp volume ) = 0;  // master volume
    fp              GetVolume( const Sample::Name& sampleName );
    bool            SetVolume( const Sample::Name& sampleName, const fp volume );

// Internal to sound module:
public:
    CLASS_METHOD const string ComputePathnameSoundFile( const string& soundFilename );

protected:
    // Almost all of the Sample-related methods are generic, so they're defined in SoundBase.
    // But SoundBase has to use CreateSample() to create a concrete Sample derivative.
    virtual shptr<Sample> CreateSample( const Sample::Name& sampleName ) = 0;

private:
    typedef std::map< Sample::Name, shptr<Sample> > SampleMap;
    SampleMap       mSampleMap;         ///< cache of sound samples
};

} // namespace sound

#endif // SOUND_SOUND_BASE_HH
