    /*

    Copyright (C) 2000 Hans Meine
	                   <hans_meine@gmx.net>

    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.

    */

#ifndef ARTS_TOOLS_LEVELMETERS_H
#define ARTS_TOOLS_LEVELMETERS_H

#include <tqobject.h>
#include <tqframe.h>
#include <tqdatetime.h>
#include <tqptrlist.h>
#include <math.h>

// helper functions
const float LEVEL_MIN= 1.f/(1<<20); // minimal positive sample for 20 bit resolution
inline float levelToDB(float level) {
	if (level<LEVEL_MIN) level=LEVEL_MIN; // prevent from div by 0
	return (6.f/log(2.f))*log(level);
}

inline float DBToLevel(float db) {
	return exp(db/(log(2.f)/6.f));
}

/**
 * Base class for a single volume / value bar.
 */
class ACLevelMeter : public TQFrame {
	TQ_OBJECT
  
public:
	ACLevelMeter(TQWidget *parent): TQFrame(parent) {}
public slots:
	virtual void setValue(float f) = 0;
};

/**
 * Base class for a pair of volume / value bars.
 */
class StereoLevelMeter : public TQFrame {
	TQ_OBJECT
  
public:
	StereoLevelMeter(TQWidget *parent): TQFrame(parent) {}
public slots:
	virtual void setValues(float left, float right) = 0;
};

/**
 * Special LevelMeter which remembers min and max of the last [peakMillis]
 * milliseconds and displays a full bar with optional max/min markers.
 */
class PeakBar : public ACLevelMeter {
	TQ_OBJECT
  
	bool clipped;

protected:
	static const int peakMillis; // how long do the peaks stay at their max?
	
	class Observation {
	public:
		TQTime time;
		float value;
		Observation(float aValue): value(aValue) { time.start(); }
	};
	TQPtrList<Observation> lastValues;
	
	float currentValue, maxValue, minValue;
	void checkMinMax();

	bool displayMinPeak;
	bool horizontalMode;

	void frameChanged();
	
public:
	PeakBar(TQWidget *parent);
	
	TQSize sizeHint() const;

	void drawContents(TQPainter *p);
	virtual void setValue(float f);
};

/**
 * Special class which draws the Db scale with ticks, numbers and so on.
 */
class ScaleView : public TQFrame {
	TQ_OBJECT
  
protected:
	TQFont font;
	int dbRange;
	int upperMargin, lowerMargin;
public:
	ScaleView(TQWidget *parent);
	void setDbRange(int db);
	void setScaleMargins(int margins) { upperMargin= margins; lowerMargin=margins; }
	TQSize sizeHint() const;
	void drawContents(TQPainter *p);
};

/**
 * Reusable class which displays two volume bars (left/right) with a Db scale
 * and clip indicators. Supports / will have a context menu with some display
 * options like Db range, whether minimal values are also shown and others.
 */
class PeakLevelMeters : public StereoLevelMeter {
	TQ_OBJECT
  
protected:
	int dbRange;
	PeakBar left, right;
	ScaleView scaleView;

public:
	PeakLevelMeters(TQWidget *parent);

public slots:
	void setValues(float leftVal, float rightVal);
	void setDbRange(int db);
};

class KLed;

/**
 * Simple LevelMeter implementation with 12 KLeds.
 * Shows them in green/yellow/red combi if not blueState set, in which
 * case it's all blue. (Original artscontrol widget by stw.)
 */
class LedMeter : public ACLevelMeter {
	TQ_OBJECT
  
protected:
	KLed *leds[12];

public:
	LedMeter(TQWidget *parent, bool blueState = false);
	void setValue(float f);
};

/**
 * A simple pair of LedMeters.
 */
class StereoLedMeters : public StereoLevelMeter {
	TQ_OBJECT
  
protected:
	LedMeter left, right;
	
public:
	StereoLedMeters(TQWidget *parent);
public slots:
	void setValues(float left, float right);
};

#endif /* ARTS_TOOLS_LEVELMETERS_H */
