#include "common.h"
#include "device.h"
#include "player.h"
#include "setup.h"

#include <fmp.h>

#include "device.h"
#include "setup.h"


/*if (mState == psDVDMenu) break;
	               mZoomStep = (mZoomStep + 1) % ZoomStepCount; 
				   Dprintf("zoomstep: %d\n", mZoomStep);
			  if(mZoomStep == 0)
				;//FMPSet(FMPI_OVERLAY_FLAGS,0x0002);
			 else
				;//FMPSet(FMPI_OVERLAY_FLAGS,0x0001);
	               FMPSetVisibleSource(ZoomSteps[mZoomStep].x1, ZoomSteps[mZoomStep].y1, 
                                   ZoomSteps[mZoomStep].x2, ZoomSteps[mZoomStep].y2);

     case kYellow:
       FMPSetVisibleSource(0,0,360,288);
     break;

     default:
       return osUnknown;
     break;
  }

  return osContinue;
}*/

//Defines for the domains 
#define STOP_STATE	0x01
#define VMGM_DOM	0x03
#define VTSM_DOM	0x04
#define VTSTT_DOM       0x05

class cPlayerEm84xx: public cPlayer {
	friend DWORD PlayerCallback(DWORD dwContext, DWORD dwMsg, DWORD dwValue);
public:
	enum em84PlayState {
		psNone,
		psDVDMenu,
		psDVDTitle,
		psDiscStopped
	};

private:
	enum ePlayModes { pmPlay, pmPause, pmSlow, pmFast, pmStill };
	enum ePlayDirs { pdForward, pdBackward };

	cControlEm84xx*	mEm84Control;
	cDeviceEm84xx*	mEm84Device;
	bool          mActive;
	em84PlayState mState;
	
	bool		mDiscLoaded;
	BYTE		mDiscType;

	DWORD mLastAudioCDCurrent;

	ePlayModes mPlayMode;
	ePlayDirs mPlayDir;
	int mTrickSpeed;
	static int Speeds[];

protected:
	virtual void Activate(bool On);

	DWORD GetTimeCode(unsigned int iSeconds);

	void TrickSpeed(int Increment);
	void PlayerTrickSpeed();
	void PlayerResetTrickSpeed();
	
public:
	cPlayerEm84xx(cControlEm84xx* Em84Control, cDeviceEm84xx* Em84Device);
	virtual ~cPlayerEm84xx();

	void TimeJump(int iSeconds, bool iPaused, bool iAbsolute=false);
	void NextTrack();
	void PrevTrack();
	void NextChapter();
	void PrevChapter();

	void Play(void);
	void Pause(void);
	void Forward(void);
	void Backward(void);

	void DvdMenu(unsigned int iMenuType);
	void NextAudioStream();
	void NextSubpictureStream();
	void NextAngle();

	void DvdResumeBookmark();
	void DvdStoreBookmark();
  
	virtual bool GetIndex(int &Current, int &Total, bool SnapToIFrame = false);
	virtual bool GetReplayMode(bool &Play, bool &Forward, int &Speed);

	bool GetTrackInfo(int& Current, int& Total);
	BYTE GetDiscType();
	int GetPlayState();
	bool DiscLoaded();
};

static DWORD sBookMarkRes = 0;
static BYTE sBookMark[1024*10];


#define MAX_VIDEO_SLOWMOTION 63 // max. arg to pass to VIDEO_SLOWMOTION // TODO is this value correct?
#define NORMAL_SPEED  4 // the index of the '1' entry in the following array (must be '1'!! ;) )
#define MAX_SPEEDS    3 // the offset of the maximum speed from normal speed in either direction
#define SPEED_MULT   12 // the speed multiplier
#define CDDA_MULT	  3 // multiplier for audiocds

int cPlayerEm84xx::Speeds[] = { 0, 1, 1, 1, 1, 2, 4, 8, 0 };

DWORD PlayerCallback(DWORD dwContext, DWORD dwMsg, DWORD dwValue)
{
	cPlayerEm84xx *This = (cPlayerEm84xx*)dwContext;

	switch (dwMsg)
	{
		case FMPM_DVD_DOMAIN_CHANGE:
			/*printf("Domain change - current domain is: %d, value: %d\n",FMPGet(FMPI_CURRENT_DOMAIN),dwValue);

			if (dwValue == 0x01)
				printf("Domain: StopState\n");
			if (dwValue == 0x03)
				printf("Domain: VMGM\n");
			if (dwValue == 0x04)
				printf("Domain: VTSM\n");
			if (dwValue == 0x05)
				printf("Domain: VTSTT\n");*/

			// on dvd-menu enter
			if (((dwValue == VMGM_DOM) || (dwValue  == VTSM_DOM)) && (This->mEm84Control))
			{
				This->mEm84Control->Hide();
				This->mState = cPlayerEm84xx::psDVDMenu;
			}
		break;

		case FMPM_DVD_CURRENT_TIME:
			//Dprintf("change to title\n");
			This->mState = cPlayerEm84xx::psDVDTitle;
		break;

		case FMPM_DVD_END_PLAYBACK:
		case FMPM_DVD_PLAYBACK_STOPPED:
			This->mState = cPlayerEm84xx::psNone;
		break;

		case FMPM_SVCD_PSD_END:
		case FMPM_CDDA_PSD_END:
			This->mState = cPlayerEm84xx::psDiscStopped;
		break;

		default:
		break;
	}

	return FMPE_OK;
}

cPlayerEm84xx::cPlayerEm84xx(cControlEm84xx* Em84Control, cDeviceEm84xx* Em84Device):
		cPlayer(pmExtern_THIS_SHOULD_BE_AVOIDED),
		mEm84Control(Em84Control),
		mEm84Device(Em84Device),
		mActive(false),
		mState(psNone),
		mDiscLoaded(false),
		mDiscType(FMPC_UNKNOWN),
		mLastAudioCDCurrent(0),
		mPlayMode(pmPlay),
		mPlayDir(pdForward),
		mTrickSpeed(NORMAL_SPEED)
{
}

cPlayerEm84xx::~cPlayerEm84xx() 
{
	Detach();
}

void cPlayerEm84xx::Activate(bool On)
{
	if (On)
	{
		// this is a fallback call - if speedcontrol is enabled, we call it redundantly her
		// doesn't harm anyway :)
		if (SetupEm84xx.ControlDvdSpeed)
			cDeviceEm84xx::SpeedControl(1);

		cDeviceEm84xx::Configure();

#ifdef EM_MPLAYER_SUPPORT
		DWORD res = MPEGDriverEntry(PRIMARY_MASTER);
		
		if (res != 0)
		{
			esyslog("ERROR: failed to open em84 MPEG driver");
			return;
		}

		FMPOpen(FMPF_PROGRAM, KILOBYTE(8), 10, NULL, 0);
#endif

		FMPLoadDisc();
		DWORD discLoaded = FMPIsDiscLoaded();

#ifdef EM_MPLAYER_SUPPORT
		FMPClose();
#endif
		
		if (discLoaded) 
		{
			// we have to reenable osd, because we switched it off in device.c on pmExtern
			if (mEm84Device)
				mEm84Device->EnableOsd(true);

			FMP_OPENSTRUCT os;
			os.dwStructSize = sizeof(FMP_OPENSTRUCT);
			os.dwFlags = FMPF_DISCPLAYBACK;
			os.dwSize = KILOBYTE(32);
			os.dwCount = 10;
			os.pCallback = PlayerCallback;
			os.dwContext = (DWORD)this;
			os.bDriverNumber = 0;
			os.sFileName = NULL;
			os.bFileSystem = DONTCARE_ACCESS;
			
			FMPOpenDiscPlayback(&os);
			cDeviceEm84xx::InitEm84();

			mDiscType = os.bDiscContent;

			cDeviceEm84xx::Configure();
			cDevice::PrimaryDevice()->SetVolume(cDevice::CurrentVolume(), true);

			FMPPlay();
			mActive = true;

			if ((mDiscType == FMPC_DVD_VIDEO) && (SetupEm84xx.DvdMenuOnStart))
				MenuCall(DVD_ROOT_ID);

			mDiscLoaded = true;
		}
	}
	else
	{
		FMPStop();
		FMPClose();
#ifdef EM_MPLAYER_SUPPORT
		MPEGDriverUnload();
#endif
		mActive = false;

		// since we turned it on, it's good style to turn it off
		if (mEm84Device)
			mEm84Device->EnableOsd(false);
	}
}

bool cPlayerEm84xx::DiscLoaded()
{
	return mDiscLoaded;
}

void cPlayerEm84xx::TrickSpeed(int Increment)
{
	int nts = mTrickSpeed + Increment;
	if (Speeds[nts] == 1)
	{
		mTrickSpeed = nts;
		if (mPlayMode == pmFast)
			Play();
		else
			Pause();
	}
	else if (Speeds[nts])
	{
		mTrickSpeed = nts;

		PlayerTrickSpeed();
		/*int Mult = (mPlayMode == pmSlow && mPlayDir == pdForward) ? 1 : SPEED_MULT;
		int sp = (Speeds[nts] > 0) ? Mult / Speeds[nts] : -Speeds[nts] * Mult;
		if (sp > MAX_VIDEO_SLOWMOTION)
			sp = MAX_VIDEO_SLOWMOTION;
		DeviceTrickSpeed(sp);*/
	}
}

void cPlayerEm84xx::PlayerTrickSpeed()
{
	if ((mPlayMode != pmSlow) && (mPlayMode != pmFast))
		return;

	if (mDiscType == FMPC_DVD_VIDEO)
	{
		if (mPlayDir == pdForward)
			ForwardScan(abs(Speeds[mTrickSpeed]),(mPlayMode==pmFast)?TRUE:FALSE);
		else
			BackwardScan(abs(Speeds[mTrickSpeed]),(mPlayMode==pmFast)?TRUE:FALSE);
	}
	else if (((mDiscType == FMPC_VCD) || (mDiscType == FMPC_SVCD)) && (mPlayMode == pmFast))
	{
		if (mPlayDir == pdForward)
			::FastForward(abs(Speeds[mTrickSpeed]));
		else
			::Rewind(abs(Speeds[mTrickSpeed]));
	}
	else if ((mDiscType == FMPC_CDDA) && (mPlayMode == pmFast))
	{
		if (mPlayDir == pdForward)
			CDDAFastForward(CDDA_MULT*abs(Speeds[mTrickSpeed]));
		else
			CDDARewind(CDDA_MULT*abs(Speeds[mTrickSpeed]));
	}
}

void cPlayerEm84xx::PlayerResetTrickSpeed()
{
	if ((mPlayMode == pmFast) || (mPlayMode == pmSlow))
	{
		if (mDiscType == FMPC_DVD_VIDEO)
		{
			if (mPlayDir == pdForward)
				::ForwardScan(0, (mPlayMode == pmFast)?TRUE:FALSE);
			else
				::BackwardScan(0, (mPlayMode == pmFast)?TRUE:FALSE);
		}
		else if (((mDiscType == FMPC_VCD) || (mDiscType == FMPC_SVCD)) && (mPlayMode == pmFast))
		{
			if (mPlayDir == pdForward)
				::FastForward(0);
			else
				::Rewind(0);

		}
		else if ((mDiscType == FMPC_CDDA) && (mPlayMode == pmFast))
		{
			if (mPlayDir == pdForward)
				CDDAFastForward(0);
			else
				CDDARewind(0);
		}
	}
}

DWORD cPlayerEm84xx::GetTimeCode(unsigned int iSeconds)
{
	DWORD wTimeCode;
	unsigned int wSeconds = iSeconds % 60;
	iSeconds -= wSeconds;
	iSeconds /= 60;
	unsigned int wMinutes = iSeconds % 60;
	iSeconds -= wMinutes;
	iSeconds /= 60;
	unsigned int wHours = iSeconds;

	wTimeCode = 	((wHours/10)<<4) | ((wHours%10)<<0) | 
			((wMinutes/10)<<12) | ((wMinutes%10)<<8) |
			((wSeconds/10)<<20) | ((wSeconds/10)<<16);

	return wTimeCode;
}

void cPlayerEm84xx::TimeJump(int iSeconds, bool iPaused, bool iAbsolute/*=false*/)
{
	int wSeconds = (int)FMPGet(FMPI_CURRENT_TIME);
	if (iAbsolute)
		wSeconds = 0;
	wSeconds += iSeconds;
	if (wSeconds < 0)
		wSeconds = 0;

	if ((mDiscType == FMPC_DVD_VIDEO) || (mDiscType == FMPC_SVCD))
	{
		DWORD wTimeCode = GetTimeCode((unsigned int)wSeconds);
		TimeSearch((TCHAR*)wTimeCode);
	}
	else if (mDiscType == FMPC_CDDA)
	{
		unsigned int wJumpMinutes = (unsigned int)(wSeconds/60);
		wSeconds -= (wJumpMinutes*60);
		unsigned int wJumpSeconds = (unsigned int)wSeconds;

		DWORD wTrackCur;
		DWORD wPlayMode;
		BYTE wTrackNo;
		CDDAGetStatus(&wPlayMode,&wTrackNo,&wTrackCur);

		// if blubb TODO .....
		PlayerResetTrickSpeed();
		CDDAPlayTrack( wTrackNo, wJumpMinutes, wJumpSeconds);
	}
	else
		return;

	if ((!iPaused) && (mPlayMode != pmPlay))
		Play();
	if (iPaused && ((mPlayMode != pmStill) && (mPlayMode != pmPause)))
		Pause();

	// always call explic. FMPPause() for iPaused, cause every 2nd TimeSearch the sigma-lib starts replay (looks at least like ...)
	if (iPaused && ((mDiscType == FMPC_DVD_VIDEO) || (mDiscType == FMPC_SVCD)))
		FMPPause();
}

void cPlayerEm84xx::NextChapter()
{
	if (mDiscType == FMPC_DVD_VIDEO)
	{
		ChapterSearch(FMPGet(FMPI_CURRENT_CHAPTER) + 1);
	}
}

void cPlayerEm84xx::PrevChapter()
{
	if (mDiscType == FMPC_DVD_VIDEO)
	{
		ChapterSearch(FMPGet(FMPI_CURRENT_CHAPTER) -1);
	}
}

void cPlayerEm84xx::NextTrack()
{
	if ((mDiscType == FMPC_DVD_VIDEO) || (mDiscType == FMPC_SVCD) || (mDiscType == FMPC_VCD))
	{
		TitlePlay(FMPGet(FMPI_CURRENT_TITLE) +1);
	}
	else if (mDiscType == FMPC_CDDA)
	{
		CDDANextTrack();
	}
}

void cPlayerEm84xx::PrevTrack()
{
	if ((mDiscType == FMPC_DVD_VIDEO) || (mDiscType == FMPC_SVCD) || (mDiscType == FMPC_VCD))
	{
		TitlePlay(FMPGet(FMPI_CURRENT_TITLE) -1);
	}
	else if (mDiscType == FMPC_CDDA)
	{
		CDDAPrevTrack();
	}
}

void cPlayerEm84xx::NextAudioStream()
{
	if (mDiscType == FMPC_DVD_VIDEO)
	{
		BYTE wNextStream = (BYTE)FMPGet(FMPI_CURRENT_AUDIO_STREAM) + 1;
		if (wNextStream >= FMPGet(FMPI_AUDIO_STREAMS_AVAILABLE))
			wNextStream = 0;

		if (AudioStreamChange(wNextStream) != FMPE_OK)
			AudioStreamChange(0);
	}
	else if ((mDiscType == FMPC_VCD) || (mDiscType == FMPC_SVCD)) 
	{
		AudioStreamChange(FMPGet(FMPI_CURRENT_AUDIO_STREAM)?0:1);
	}
}

void cPlayerEm84xx::NextSubpictureStream()
{
	if (mDiscType != FMPC_DVD_VIDEO)
		return;

	if (!FMPGet(FMPI_SUBPICTURE_ON))
		SubPictureStreamChange((BYTE)FMPGet(FMPI_CURRENT_SUBPICT_STREAM), 1);
	else
	{
		BYTE wNextSub = FMPGet(FMPI_CURRENT_SUBPICT_STREAM) + 1;
	
		if (wNextSub >= FMPGet(FMPI_SUBPICTURE_STREAM_AVAILABLE))
		{
			SubPictureStreamChange((BYTE)FMPGet(FMPI_CURRENT_SUBPICT_STREAM), 0);
			return;
		}

		SubPictureStreamChange(wNextSub, 1);
	}
}

void cPlayerEm84xx::NextAngle()
{
	if (mDiscType != FMPC_DVD_VIDEO)
		return;

	BYTE wNextAngle = (BYTE)FMPGet(FMPI_CURRENT_ANGLE) + 1;
	if (wNextAngle > FMPGet(FMPI_ANGLES_AVAILABLE))
	    wNextAngle = 1;
	AngleChange(wNextAngle);
}

void cPlayerEm84xx::DvdMenu(unsigned int iMenuType)
{
	MenuCall(iMenuType);
}

void cPlayerEm84xx::DvdStoreBookmark()
{
	if (mDiscType == FMPC_DVD_VIDEO)
	{
		if (StoreBookmark(sBookMark) == 0)
			sBookMarkRes = 1;
		else
			sBookMarkRes = 0;
	}
}

void cPlayerEm84xx::DvdResumeBookmark()
{
	if ((mDiscType == FMPC_DVD_VIDEO) && (sBookMarkRes == 1))
	{
		::ResumeBookmark(sBookMark);
	}
}

bool cPlayerEm84xx::GetIndex(int &Current, int &Total, bool SnapToIFrame) 
{
	if (mDiscType == FMPC_CDDA)
	{
		DWORD wTrackDur;
		DWORD wTrackCur;
		DWORD wPlayMode;
		BYTE wTrackNo;
		CDDAGetStatus(&wPlayMode,&wTrackNo,&wTrackCur);
		CDDAGetTrackDuration(wTrackNo,&wTrackDur);

		Current = wTrackCur * FRAMESPERSEC;
		Total = wTrackDur * FRAMESPERSEC;

		if (((mPlayMode == pmPause) || (mPlayMode == pmStill)) && (Current == 0))
			Current = mLastAudioCDCurrent;
		else
			mLastAudioCDCurrent = Current;
	}
	else if (mDiscType == FMPC_DVD_VIDEO)
	{
		Current = FMPGet(FMPI_CURRENT_TIME) * FRAMESPERSEC;
		Total = FMPGet(FMPI_TOTAL_TITLE_TIME) * FRAMESPERSEC;
	}
	else if ((mDiscType == FMPC_SVCD) || (mDiscType == FMPC_VCD))
	{
		Current = FMPGet(FMPI_CURRENT_TIME) * FRAMESPERSEC;
		Total = FMPGet(FMPI_TOTAL_TITLE_TIME) * FRAMESPERSEC;
	}
	else
		return false;

	return true;
}

bool cPlayerEm84xx::GetReplayMode(bool &Play, bool &Forward, int &Speed)
{
	Play = (mPlayMode == pmPlay || mPlayMode == pmFast);
	Forward = (mPlayDir == pdForward);
	if (mPlayMode == pmFast || mPlayMode == pmSlow)
		Speed = Setup.MultiSpeedMode ? abs(mTrickSpeed - NORMAL_SPEED) : 0;
	else
		Speed = -1;
	return true;
}

bool cPlayerEm84xx::GetTrackInfo(int& Current, int& Total)
{
	Current = -1;
	Total = -1;

	if (mDiscType == FMPC_DVD_VIDEO)
	{
		Current = (int)FMPGet(FMPI_CURRENT_TITLE);
		Total = (int)FMPGet(FMPI_TITLES_AVAILABLE);
		return true;
	}
	else if ((mDiscType == FMPC_VCD) || (mDiscType == FMPC_SVCD) || (mDiscType == FMPC_CDDA))
	{
		Current = (int)FMPGet(FMPI_CURRENT_TRACK);
		Total = (int)FMPGet(FMPI_TITLES_AVAILABLE);
		return true;
	}
	else
		return false;
}

int cPlayerEm84xx::GetPlayState()
{
	return mState;
}

BYTE cPlayerEm84xx::GetDiscType()
{
	return mDiscType;
}

void cPlayerEm84xx::Play(void)
{
	if (mPlayMode != pmPlay)
	{
		PlayerResetTrickSpeed();

		FMPPlay();
	
		//DevicePlay();
		mPlayMode = pmPlay;
		mPlayDir = pdForward;
	}
}

void cPlayerEm84xx::Pause(void)
{
	if (mPlayMode == pmPause || mPlayMode == pmStill)	
		Play();
	else
	{
		PlayerResetTrickSpeed();

		FMPPause();
		mPlayMode = pmPause;
	}
}

void cPlayerEm84xx::Forward(void)
{
	switch (mPlayMode)
	{
		case pmFast:
			if (Setup.MultiSpeedMode)
			{
				TrickSpeed(mPlayDir == pdForward ? 1 : -1);
		       	break;
			}
			else if (mPlayDir == pdForward)
			{
				Play();
				break;
			}
			// run into pmPlay

		case pmPlay:
		{
			mPlayMode = pmFast;
			mPlayDir = pdForward;
			mTrickSpeed = NORMAL_SPEED;
			TrickSpeed(Setup.MultiSpeedMode ? 1 : MAX_SPEEDS);	
		}
		break;

		case pmSlow:
			if (Setup.MultiSpeedMode)
			{
				TrickSpeed(mPlayDir == pdForward ? -1 : 1);
				break;
			}
			else if (mPlayDir == pdForward)
			{
				Pause();
				break;
			}
			// run into pmPause

		case pmStill:
		case pmPause:
			mPlayMode = pmSlow;
			mPlayDir = pdForward;
			mTrickSpeed = NORMAL_SPEED;
			TrickSpeed(Setup.MultiSpeedMode ? -1 : -MAX_SPEEDS);
		break;
	}
}

void cPlayerEm84xx::Backward(void)
{
	switch (mPlayMode)
	{
		case pmFast:
			if (Setup.MultiSpeedMode)
			{
				TrickSpeed(mPlayDir == pdBackward ? 1 : -1);
				break;
			}
			else if (mPlayDir == pdBackward)
			{
				Play();
				break;
			}
			// run into pmPlay

		case pmPlay:
		{
			mPlayMode = pmFast;
			mPlayDir = pdBackward;
			mTrickSpeed = NORMAL_SPEED;
			TrickSpeed(Setup.MultiSpeedMode ? 1 : MAX_SPEEDS);
		}
		break;

		case pmSlow:
			if (Setup.MultiSpeedMode)
			{
				TrickSpeed(mPlayDir == pdBackward ? -1 : 1);
				break;
			}
			else if (mPlayDir == pdBackward)
			{
				Pause();
				break;
			}
			// run into pmPause

		case pmStill:
		case pmPause:
		{
			mPlayMode = pmSlow;
			mPlayDir = pdBackward;
			mTrickSpeed = NORMAL_SPEED;
			TrickSpeed(Setup.MultiSpeedMode ? -1 : -MAX_SPEEDS);
		}
		break;
	}
}

cControlEm84xx::cControlEm84xx(cDeviceEm84xx* Em84Device):
		cControl(mPlayer = new cPlayerEm84xx(this,Em84Device)),
		mEm84Device(Em84Device),
		mDisplay(NULL),
		mTimeSearchActive(false),
		mTimeSearchHide(false),
		mTimeSearchTime(0),
		mTimeSearchPos(0)
{
}

cControlEm84xx::~cControlEm84xx()
{
	Hide();
	delete mPlayer;
}

void cControlEm84xx::Hide(void)
{
	DELETENULL(mDisplay);
}

void cControlEm84xx::ShowProgress(bool Open)
{
	if (mDisplay == NULL && Open) {
		mDisplay = Skins.Current()->DisplayReplay(false);
		if (mDisplay == NULL)
			return;
		//mDisplay->SetTitle("DVD");
	}

	if (mDisplay != NULL) {
		bool play, forward;
		int speed, current, total;
		if (mPlayer->GetReplayMode(play, forward, speed))
			mDisplay->SetMode(play, forward, speed);
		if (mPlayer->GetIndex(current, total)) {
			mDisplay->SetProgress(current, total);
			mDisplay->SetCurrent((const char*)IndexToHMSF(current));
			mDisplay->SetTotal((const char*)IndexToHMSF(total));
		}

		char wTitle[128],wType[64],wTrackInfo[64];
		int wCurrTrack,wTotalTrack;
		BYTE wDiscType = mPlayer->GetDiscType();
		mPlayer->GetTrackInfo(wCurrTrack, wTotalTrack);

		sprintf(wTrackInfo,"(%d/%d)",wCurrTrack,wTotalTrack);

		switch (wDiscType)
		{
			case FMPC_DVD_VIDEO:
				strcpy(wType,"DVD");
			break;

			case FMPC_VCD:
				strcpy(wType,"VCD");
			break;

			case FMPC_SVCD:
				strcpy(wType,"SVCD");
			break;
	
			case FMPC_CDDA:
				strcpy(wType,"AudioCD");
			break;

			case FMPC_UNSUPPORTED:
			case FMPC_UNKNOWN:
			default:
				strcpy(wType,"Unknown");
			break;
		}

		sprintf(wTitle,"%s %s",wType,wTrackInfo);

		mDisplay->SetTitle(wTitle);
	}
}

void cControlEm84xx::TimeSearchDisplay(void)
{
	char buf[64];
	strcpy(buf, tr("Jump: "));
	int len = strlen(buf);
	char h10 = '0' + (mTimeSearchTime >> 24);
	char h1  = '0' + ((mTimeSearchTime & 0x00FF0000) >> 16);
	char m10 = '0' + ((mTimeSearchTime & 0x0000FF00) >> 8);
	char m1  = '0' + (mTimeSearchTime & 0x000000FF);
	char ch10 = mTimeSearchPos > 3 ? h10 : '-';
	char ch1  = mTimeSearchPos > 2 ? h1  : '-';
	char cm10 = mTimeSearchPos > 1 ? m10 : '-';
	char cm1  = mTimeSearchPos > 0 ? m1  : '-';
	sprintf(buf + len, "%c%c:%c%c", ch10, ch1, cm10, cm1);
	if (mDisplay)
		mDisplay->SetJump(buf);
}

void cControlEm84xx::TimeSearchProcess(eKeys Key)
{
#define STAY_SECONDS_OFF_END 10

	int Seconds = (mTimeSearchTime >> 24) * 36000 + ((mTimeSearchTime & 0x00FF0000) >> 16) * 3600 + ((mTimeSearchTime & 0x0000FF00) >> 8) * 600 + (mTimeSearchTime & 0x000000FF) * 60;
	int Current;// = (lastCurrent / FRAMESPERSEC);
	int Total;// = (lastTotal / FRAMESPERSEC);

	GetIndex(Current, Total);

	switch (Key)
	{
		case k0 ... k9:
			if (mTimeSearchPos < 4)
			{
				mTimeSearchTime <<= 8;
				mTimeSearchTime |= Key - k0;
				mTimeSearchPos++;
				TimeSearchDisplay();
			}
		break;

		case kFastRew:
		case kLeft:
		case kFastFwd:
		case kRight:
		{
			int dir = ((Key == kRight || Key == kFastFwd) ? 1 : -1);
			if (dir > 0)
				Seconds = min(Total - Current - STAY_SECONDS_OFF_END, Seconds);
			mPlayer->TimeJump(Seconds * dir,false);//SkipSeconds(Seconds * dir);
			mTimeSearchActive = false;
		}
		break;

		case kPlay:
		case kUp:
		case kPause:
		case kDown:
		case kOk:
			Seconds = min(Total - STAY_SECONDS_OFF_END, Seconds);
			mPlayer->TimeJump(Seconds, (Key == kDown || Key == kPause || Key == kOk), true); // Goto(Seconds * FRAMESPERSEC, Key == kDown || Key == kPause || Key == kOk);
			mTimeSearchActive = false;
		break;

		default:
			mTimeSearchActive = false;
		break;
	}

	if (!mTimeSearchActive)
	{
		if (mTimeSearchHide)
			Hide();
		else
		{
			if (mDisplay)
				mDisplay->SetJump(NULL);
		}
		//ShowMode();
	}
}

void cControlEm84xx::TimeSearch(void)
{
	mTimeSearchTime = mTimeSearchPos = 0;
	mTimeSearchHide = false;
	//if (modeOnly)
	//   Hide();
	if (!mDisplay) //(!visible)
	{
		ShowProgress(true);//Show();
		if (mDisplay) //(visible)
			mTimeSearchHide = true;
		else
			return;
	}

	//timeoutShow = 0;
	TimeSearchDisplay();
	mTimeSearchActive = true;
}

eOSState cControlEm84xx::ProcessKeyDvdNavigation(eKeys Key)
{
	switch (Key)
	{
		case kUp:
			UpperButtonSelect(); 
			return osContinue;
		
		case kDown:
			LowerButtonSelect();
			return osContinue;

		case kLeft:
			LeftButtonSelect();
			return osContinue;

		case kRight:
			RightButtonSelect();
			return osContinue;

		case kOk:
			ButtonActivate();
			return osContinue;

		default:
		break;
	}

	return osUnknown;
}

eOSState cControlEm84xx::ProcessKeyDefaultButtons(eKeys Key)
{
	switch (Key)
	{
		case kUp:
			mPlayer->Play();
			return osContinue;
		
		case kDown:
			mPlayer->Pause();
			return osContinue;

		case kLeft:
			mPlayer->Backward();
			return osContinue;

		case kRight:
			mPlayer->Forward();
			return osContinue;

		case kBack:
			return osEnd;

		default:
		break;
	}

	return osUnknown;
}

eOSState cControlEm84xx::ProcessKeyDiscAction(eKeys Key)
{
	for (int i=0; i < NOOFPLAYERKEYS; i++)
	{
		if (discPlayerKeyTable[i].key == Key)
		{
			if (SetupEm84xx.PlayerKeys[i] == discActionNone)
				return osUnknown;

			switch (SetupEm84xx.PlayerKeys[i])
			{
				case discExit:
					return osEnd;

				case discTimeJump:
					TimeSearch();
					return osContinue;

				case discPrevMinute:
					mPlayer->TimeJump(-60,false);
					return osContinue;
					
				case discNextMinute:
					mPlayer->TimeJump(+60,false);
					return osContinue;

				case discPrevTrack:
					mPlayer->PrevTrack();
					return osContinue;

				case discNextTrack:
					mPlayer->NextTrack();
					return osContinue;

				case discPrevChapter:
					mPlayer->PrevChapter();
					return osContinue;

				case discNextChapter:
					mPlayer->NextChapter();
					return osContinue;

				case discPlay:
					mPlayer->Play();
					return osContinue;

				case discPause:
					mPlayer->Pause();
					return osContinue;

				case discForward:
					mPlayer->Forward();
					return osContinue;

				case discRewind:
					mPlayer->Backward();
					return osContinue;

				case discNextAudiostream:
					mPlayer->NextAudioStream();
					return osContinue;

				case discNextSubpicture:
					mPlayer->NextSubpictureStream();
					return osContinue;

				case discNextAngle:
					mPlayer->NextAngle();
					return osContinue;

				case discDvdRootMenu:
					mPlayer->DvdMenu(DVD_ROOT_ID);
					return osContinue;

				case discDvdTitleMenu:
					mPlayer->DvdMenu(DVD_TITLE_ID);
					return osContinue;

				case discDvdSubpictureMenu:
					mPlayer->DvdMenu(DVD_SUBPICTURE_ID);
					return osContinue;

				case discDvdAudioMenu:
					mPlayer->DvdMenu(DVD_AUDIO_ID);
					return osContinue;

				case discDvdAngleMenu:
					mPlayer->DvdMenu(DVD_ANGLE_ID);
					return osContinue;

				case discDvdChapterMenu:
					mPlayer->DvdMenu(DVD_PTT_ID);
					return osContinue;

				case discDvdResumeBookmark:
					mPlayer->DvdResumeBookmark();
					return osContinue;

				default:
					return osUnknown;
			}
		}
	}

	return osUnknown;
}

eOSState cControlEm84xx::ProcessKey(eKeys Key)
{
	if ((!mPlayer->DiscLoaded()) || (mPlayer->GetPlayState() == cPlayerEm84xx::psDiscStopped))
	{
		Hide();
		return osEnd;
	}

	if (mTimeSearchActive && (Key != kNone))
	{
		TimeSearchProcess(Key);
		return osContinue;
	}

	eOSState state = osUnknown;
	if (mPlayer->GetPlayState() == cPlayerEm84xx::psDVDMenu)
		state = ProcessKeyDvdNavigation(Key);

	if (state == osUnknown)
		state = ProcessKeyDefaultButtons(Key);

	if (state == osUnknown)
		state = ProcessKeyDiscAction(Key);

	switch (state)
	{
		case osEnd:     
			Hide();
			mPlayer->DvdStoreBookmark();
			return osEnd;

		case osUnknown:
			switch (Key)
			{
				case kOk:
					if (mDisplay == NULL)
						ShowProgress(true);
					else
						Hide();
					return osContinue;

				default:
				break;
			}
		break;

		default:
		break;
	}

	ShowProgress();
	return state;
}
