/**************************************************************************
                   fmplayer.h  -  all the FMPlayer-API
                            -------------------
    begin                : September 20th 2002
    copyright            : (C) 2002 by Daniel Gruen
    email                : daniel_gruen@web.de
 ***************************************************************************/

/***************************************************************************
 *                                                                         *
 *   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 is a slim and special fms version for qliss3d
// please use the original version from http://sourceforge.net/projects/fmsynth
// if you want to do anything on it

#ifndef _FMVALUE_
#define _FMVALUE_

#include "../config.h"

float  ggt(float a, float b);

float  kgv(float a, float b);

#ifdef HAVE_SYS_SOUNDCARD_H
#ifdef HAVE_FCNTL_H
#ifdef HAVE_SYS_IOCTL_H
#ifdef HAVE_UNISTD_H

#define FMS_WORKS

#endif
#endif
#endif
#endif

#ifdef FMS_WORKS

#include "fmifstream.h"

#define D_SAMPRATE 22050

// error messages
#define DSP_OPEN_ERR   0
#define DSP_CHAN_ERR   1
#define DSP_SFMT_ERR   2
#define DSP_RATE_ERR   3
#define DSP_SYNC_ERR   4

#define WAV_OPEN_ERR 100
#define WAV_WRIT_ERR 101

#define PLY_MODE_ERR 200

#define MID_NDEF_ERR 300

#define FIF_NFNM_ERR 400

// internal signals
#define ATIME_RETURN  -1

// default values
#define DEFAULT_FREQ 440

/* forward declarations */

class FMChannel;
class FMPackage;
class FMSoundfile;

enum PlayMode {
	DSP,
	WAV,
	NONE
};

class FMPlayer {
	public:
		FMPlayer();
		~FMPlayer();

		FMChannel   *first;
		FMChannel   *channel;
		FMPackage   *package;
		FMSoundfile *sound;

		void nextSound();
		void setRate(int drate);
		int  getRate() const;
		void openFiles();
		void compute();
		void play();
		void playInit();
		void playVal();
		void playCleanup();

	private:
		void syncPointer();
		int   rate;
		PlayMode mode;
};

class FMChannel {
	public:
		FMChannel(FMPlayer *parentPlayer);
		~FMChannel();

		FMPlayer    *player;
		FMPackage   *package;
		FMPackage   *first;
		FMSoundfile *sound;

		float       *ptr;

		void  nextSound();
		void  openFiles();
		void  compute();
		void  ptrInc();
		void  pointerReset();

	private:
		void  syncPointer();

		int   i;
		int   dr;
		int repeat;
};

class FMPackage {
	public:
		FMPackage(FMChannel *parentChannel);
		~FMPackage();

		FMChannel   *channel;
		FMSoundfile *  sound;

		float *values;

		void   nextSound();
		float  getTime() const;
		void   setTime(float dtime);
		float  getVolume() const;
		void   setVolume(float dvol);
		float  getTVol() const;
		void   setTVol(float dtvol);
		float  getRepeat() const;
		void   setRepeat(float drepeat);
		int    getRval() const;
		void   volumeChanged(float oldv, float newv);
		void   openFiles();
		void   compute();
		void   compLockAll();

	private:
		FMSoundfile *first;

		float time;
		float vol;
		float tvol;
		int   rval;
		float repeat;
		float *ptr;
		bool  comp_lock;
};

class FMFile : public FMData {
	public:
		FMFile(FMPackage *parentPackage);
		~FMFile();

		FMPackage *package;

		bool  openLock();
		bool  compLock();
		void  compute();
		void  setFreq(float dfreq);
		void  setVolume(float dvolume, bool setptvol=1);
		float getVolume() const;
		void  setAtime(float datime);
		void  incAtime();
		void  openFile();
		int   rval();

	protected:
		float value(bool count_on=1);
		float freq;
		float volume;
		float atime;
		bool  open_lock;
};

class FMSoundfile : public FMFile {
	public:
		FMSoundfile(FMPackage *parentPackage);
		~FMSoundfile();

		FMSoundfile * next;

		float value(bool count_on=1);
};

#endif

#endif
