/*
 * audio_player.h: The audio player and control interface
 *
 * See the README file for copyright information and how to reach the author.
 *
 * $Id: audio_player.h,v 1.1.1.1 2005/12/20 14:11:45 cm Exp $
 */

#ifndef __AUDIOPLAYER_H
#define __AUDIOPLAYER_H

#include <stdint.h>
#include <vdr/player.h>
#include <vdr/plugin.h>
#include "audio_playlist.h"
#include "audio_decoder.h"

#define PLAYERBUFSIZE	         MEGABYTE(1)
#define MAX_FRAME_PAYLOAD      2000

#define SPAN_PROVIDER_CHECK_ID 	"Span-ProviderCheck-v1.0"
#define SPAN_CLIENT_CHECK_ID 	"Span-ClientCheck-v1.0"
#define SPAN_SET_PCM_DATA_ID 	"Span-SetPcmData-v1.0"
#define SPAN_GET_BAR_HEIGHTS_ID "Span-GetBarHeights-v1.0"

//Span requests to collect possible providers / clients
struct Span_Provider_Check_1_0 {
	bool *isActive;
	bool *isRunning;
};

struct Span_Client_Check_1_0 {
	bool *isActive;
	bool *isRunning;
};
// Span data
struct Span_SetPcmData_1_0 {
	unsigned int length; 	// the length of the PCM-data
	int *data;		// the PCM-Data as 32-bit int, however only the lower 16-bit are used
				// and you have to take care to hand in such data!
};
struct Span_GetBarHeights_v1_0 {
	unsigned int bands;			// number of bands to compute
	unsigned int *barHeights;		// the heights of the bars of the two channels combined
	unsigned int *barHeightsLeftChannel;	// the heights of the bars of the left channel
	unsigned int *barHeightsRightChannel;	// the heights of the bars of the right channel
	unsigned int *volumeLeftChannel;	// the volume of the left channels
	unsigned int *volumeRightChannel;	// the volume of the right channels
	unsigned int *volumeBothChannels;	// the combined volume of the two channels
	const char *name;			// name of the plugin that wants to get the data
						// (must be unique for each client!)
	unsigned int falloff;                   // bar falloff value
	unsigned int *barPeaksBothChannels;	// bar peaks of the two channels combined
	unsigned int *barPeaksLeftChannel;	// bar peaks of the left channel
	unsigned int *barPeaksRightChannel;	// bar peaks of the right channel
};


inline unsigned long MSecondsToFrames(unsigned long n) {
  return n / 40;
}

inline unsigned long FramesToSeconds(unsigned long n) {
  return n / 25;
}

class cAudioPlayer : public cPlayer, public cThread {
  private:
    bool m_indexTrack;
    int m_curFrame;
    int m_maxFrames;
    enum ePlayMode { pmPlay=0, pmPaused, pmStopped, pmBuffered, pmNone };
    ePlayMode m_playMode;
    cFrame *mpo_readFrame, *mpo_playFrame;
    cRingBufferFrame *mpo_ringBufferFrame;
    cCondVar mo_playerCond;
    cMutex mo_playerMutex;
    cAudioDecoder *mpo_decoder;
#ifndef WITHOUT_PRELOADER
    cAudioTunePreloader mo_preloader;
#endif
    cAudioPlaylist *mpo_playlist;
    void Clear(void);
    void Reset(void);
    void SetPlayMode(ePlayMode mode);
    void WaitPlayMode(ePlayMode test, bool negate, ePlayMode wait);
  protected:
    void Action();
    void Activate(bool On);
  public:
    cAudioPlayer(cAudioPlaylist *playlist);
    ~cAudioPlayer();                                     
    void Play(void);
    void Pause(void);
    void Stop(void);
    void Jump(int number);
    void SkipTrack(int offset);
    void SkipSeconds(int seconds);
    bool GetIndex(int &Current, int &Total, bool SnapToIFrame = false);;
    bool GetReplayMode(bool &Play, bool &Forward, int &Speed);
    void ToggleIndex(void);
};

class cAudioControl : public cControl {
  private:
    char *mp_replayDescription;
    int m_curSongId;
    cAudioPlayer *player;
    cAudioPlaylist *mpo_playlist;
    cSkinDisplayReplay *mpo_mnuReplay;
    cSkinDisplayMenu *mpo_mnuPlaylist;
    void RefreshProgress(int number);
    void ShowReplay(void);
    void ShowPlaylist(bool message = false);
  public:
    cAudioControl(cAudioPlaylist *playlist);
    ~cAudioControl();
    void Hide(void);
    eOSState ProcessKey(eKeys Key);
};

#endif
