/* -*-c++-*- */
/**
 * OsgAL - OpenSceneGraph Audio Library
 * Copyright (C) 2004 VRlab, Ume University
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library 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
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA.
 */

#ifndef AUDIOBASE_H_INCLUDED_C41996D8
#define AUDIOBASE_H_INCLUDED_C41996D8

#include "openalpp/Export"
#include <cstdlib>

extern "C" {
#ifdef _WIN32
#include <al.h>
#include <alut.h>
#include <alc.h>
#else // _WIN32
#include <AL/al.h>
#include <AL/alut.h>
#include <AL/alc.h>
#endif // _WIN32
}

#include "openalpp/windowsstuff"
#include "openalpp/Error"
#include <osg/Referenced>
#include <osg/ref_ptr>


/**
 * Namespace for OpenAL++.
 */
/// C++ wrapper for OpenAL with additional functionality of handling ogg-vorbis as streams.
namespace openalpp {

/**
 * Format for sound data. Mono/Stereo, 8 or 16 bits.
 */
typedef enum SampleFormat {Mono8,Stereo8,Mono16,Stereo16};

/** 
 * Base class for enviroment, listener and source classes.
 * Takes care of initialisation/shutdown of anything necessary (e.g. ALut)
 */
class OPENALPP_API AudioBase : public osg::Referenced {
  /**
   * Counter for #instances for enviroment, listener and source classes.
   * Used to determine when init and shutdown functions should be called
   */
  static int instances_;

  /**
   * Pointer to device.
   */
  static ALCdevice *device_;

  /**
   * Pointer to context.
   */
#ifndef WIN32
#if OPENAL_VERSION < 2007
  static void *context_;
#else // OPENAL_VERSION < 2007
  static ALCcontext *context_;
#endif // OPENAL_VERSION < 2007
#else
  static struct ALCcontext_struct *context_;
#endif
 protected:
  /**
   * Constructor.
   * @param frequency is the output frequency, in Hz.
   * @param refresh is the refresh rate, in Hz.
   * @param is a flag for syncronous context. Values <0 indicates that the
   * default should be used.
   */
   AudioBase(int frequency=-1,int refresh=-1,int synchronous=-1)
    throw (InitError);

  /**
   * Destructor.
   */
  virtual  ~AudioBase();

  /**
   * Flag for whether reverb has been initiated.
   * Reverb can be initiated with AudioEnviroment::InitiateReverb()
   */
  static bool reverbinitiated_;

  /**
   * Set reverb scale.
   * This pointer will be set by AudioEnviroment::InitiateReverb()
   * @param sid is the OpenAL name for the source
   * @param param is the reverb scale. Range [0.0,1.0].
   */
  static void (*alReverbScale)(ALuint sid, ALfloat param);

  /**
   * Set reverb delay.
   * This pointer will be set by AudioEnviroment::InitiateReverb()
   * @param sid is the OpenAL name for the source
   * @param param is the reverb delay. Range [0.0,2.0].
   */
  static void (*alReverbDelay)(ALuint sid, ALfloat param);
};

  const char *alGetErrorString(ALenum error);

#include <iostream>
  #define ALCHECKERROR() \
  { \
    ALenum e; \
    if ((e=alGetError()) != AL_NO_ERROR){ \
      const char *msg = openalpp::alGetErrorString(e); \
      std::cerr << "alError: (" << e << ") " << __FILE__ << " at Line: " << __LINE__  << ": " << msg << std::endl; \
    } \
  }

}

#endif /* AUDIOBASE_H_INCLUDED_C41996D8 */
