mirror of
https://github.com/Gericom/FastVideoDSPlayer.git
synced 2025-06-18 18:45:34 -04:00
227 lines
6.1 KiB
C++
227 lines
6.1 KiB
C++
#include <nds.h>
|
|
#include "PlayerController.h"
|
|
|
|
#define DIM_WAIT_SEC 5
|
|
#define DIM_FADE_SEC 3
|
|
|
|
PlayerController::PlayerController(fv_player_t* player)
|
|
: _subScreenState(SUB_SCREEN_STATE_ACTIVE), _subScreenStateCounter(0), _subBacklightOff(false), _player(player),
|
|
_playing(true), _lastTime(-1), _seekPenDown(false), _playPausePenDown(false), _seekLastFrame(-1),
|
|
_inputRepeater(KEY_LEFT | KEY_RIGHT, 12, 3)
|
|
{
|
|
}
|
|
|
|
void PlayerController::Initialize()
|
|
{
|
|
_view.Initialize();
|
|
|
|
_dimWaitFrames = DIM_WAIT_SEC * _player->fvHeader->fpsNum / _player->fvHeader->fpsDen;
|
|
_dimFadeFrames = DIM_FADE_SEC * _player->fvHeader->fpsNum / _player->fvHeader->fpsDen;
|
|
_invDimFadeFrames = 0x800000 / _dimFadeFrames;
|
|
|
|
u32 totalSeconds = ((u64)_player->fvHeader->nrFrames * _player->fvHeader->fpsDen) / _player->fvHeader->fpsNum;
|
|
_view.SetTotalTime(totalSeconds);
|
|
_view.SetCurrentTime(0);
|
|
}
|
|
|
|
void PlayerController::TogglePlayPause()
|
|
{
|
|
if (_playing)
|
|
{
|
|
fv_pausePlayer(_player);
|
|
_playing = false;
|
|
}
|
|
else
|
|
{
|
|
fv_resumePlayer(_player);
|
|
_playing = true;
|
|
}
|
|
}
|
|
|
|
void PlayerController::UpdateTouch()
|
|
{
|
|
if (_subScreenState != SUB_SCREEN_STATE_ACTIVE)
|
|
return;
|
|
|
|
touchPosition touch;
|
|
touchRead(&touch);
|
|
|
|
if (_inputProvider.Triggered(KEY_TOUCH))
|
|
{
|
|
if (touch.px >= 16 && touch.px < 240 && touch.py >= /*117*/ 113 && touch.py < /*121*/ 125)
|
|
{
|
|
_seekPenDown = true;
|
|
_seekLastFrame = -1;
|
|
}
|
|
else if (touch.px >= 110 && touch.px < 110 + 36 && touch.py >= 140 && touch.py < 140 + 36)
|
|
{
|
|
_playPausePenDown = true;
|
|
}
|
|
}
|
|
|
|
if (_inputProvider.Released(KEY_TOUCH))
|
|
{
|
|
_seekPenDown = false;
|
|
|
|
if (_playPausePenDown)
|
|
{
|
|
TogglePlayPause();
|
|
_playPausePenDown = false;
|
|
}
|
|
}
|
|
|
|
if (_inputProvider.Current(KEY_TOUCH) && _playPausePenDown)
|
|
{
|
|
if (!(touch.px >= 110 && touch.px < 110 + 36 && touch.py >= 140 && touch.py < 140 + 36))
|
|
{
|
|
_playPausePenDown = false;
|
|
}
|
|
}
|
|
|
|
if (_inputProvider.Current(KEY_TOUCH) && _seekPenDown)
|
|
{
|
|
int frame = ((int)touch.px - 16) * (int)_player->fvHeader->nrFrames / 224;
|
|
if (frame < 0)
|
|
frame = 0;
|
|
else if ((u32)frame >= _player->fvHeader->nrFrames)
|
|
frame = _player->fvHeader->nrFrames - 1;
|
|
if (frame != _seekLastFrame)
|
|
{
|
|
_seekLastFrame = frame;
|
|
fv_gotoNearestKeyFrame(_player, frame);
|
|
fv_startPlayer(_player);
|
|
_playing = true;
|
|
}
|
|
}
|
|
}
|
|
|
|
void PlayerController::UpdateKeys()
|
|
{
|
|
if (_inputProvider.Current(KEY_LID))
|
|
{
|
|
// pause when lid is closed
|
|
if (_playing)
|
|
{
|
|
fv_pausePlayer(_player);
|
|
_playing = false;
|
|
}
|
|
}
|
|
else if (_inputProvider.Triggered(KEY_A))
|
|
{
|
|
TogglePlayPause();
|
|
}
|
|
else if (_inputProvider.Triggered(KEY_LEFT))
|
|
{
|
|
_seekKeyFrame = fv_gotoPreviousKeyFrame(_player);
|
|
fv_startPlayer(_player);
|
|
_playing = true;
|
|
}
|
|
else if (_inputRepeater.Triggered(KEY_LEFT))
|
|
{
|
|
if (_seekKeyFrame > 0)
|
|
_seekKeyFrame--;
|
|
fv_gotoKeyFrame(_player, _seekKeyFrame);
|
|
fv_startPlayer(_player);
|
|
_playing = true;
|
|
}
|
|
else if (_inputProvider.Triggered(KEY_RIGHT))
|
|
{
|
|
_seekKeyFrame = fv_gotoNextKeyFrame(_player);
|
|
fv_startPlayer(_player);
|
|
_playing = true;
|
|
}
|
|
else if (_inputRepeater.Triggered(KEY_RIGHT))
|
|
{
|
|
fv_gotoKeyFrame(_player, ++_seekKeyFrame);
|
|
fv_startPlayer(_player);
|
|
_playing = true;
|
|
}
|
|
}
|
|
|
|
void PlayerController::UpdateDim()
|
|
{
|
|
if (!_playing || (_inputProvider.GetCurrentKeys() & ~KEY_LID) || (_inputProvider.GetReleasedKeys() & KEY_LID))
|
|
{
|
|
_subScreenState = SUB_SCREEN_STATE_ACTIVE;
|
|
_subScreenStateCounter = 0;
|
|
}
|
|
|
|
if (_subBacklightOff && _subScreenState != SUB_SCREEN_STATE_OFF)
|
|
{
|
|
powerOn(PM_BACKLIGHT_BOTTOM);
|
|
_subBacklightOff = false;
|
|
}
|
|
else if (!_subBacklightOff && _subScreenState == SUB_SCREEN_STATE_OFF)
|
|
{
|
|
powerOff(PM_BACKLIGHT_BOTTOM);
|
|
_subBacklightOff = true;
|
|
}
|
|
|
|
switch (_subScreenState)
|
|
{
|
|
case SUB_SCREEN_STATE_ACTIVE:
|
|
REG_MASTER_BRIGHT_SUB = 0;
|
|
if (++_subScreenStateCounter >= _dimWaitFrames)
|
|
{
|
|
_subScreenStateCounter = 0;
|
|
_subScreenState = SUB_SCREEN_STATE_DIMMING;
|
|
}
|
|
break;
|
|
|
|
case SUB_SCREEN_STATE_DIMMING:
|
|
{
|
|
int dimFrame = (_subScreenStateCounter * 16 * _invDimFadeFrames + 0x400000) >> 23;
|
|
if (dimFrame < 0)
|
|
dimFrame = 0;
|
|
else if (dimFrame > 16)
|
|
dimFrame = 16;
|
|
REG_MASTER_BRIGHT_SUB = dimFrame | (2 << 14);
|
|
if (dimFrame < 16)
|
|
_subScreenStateCounter++;
|
|
else
|
|
_subScreenState = SUB_SCREEN_STATE_OFF;
|
|
break;
|
|
}
|
|
|
|
case SUB_SCREEN_STATE_OFF:
|
|
break;
|
|
}
|
|
}
|
|
|
|
void PlayerController::Update()
|
|
{
|
|
_view.SetPlaying(_playing);
|
|
if (_playing)
|
|
{
|
|
REG_DIVCNT = DIV_64_32;
|
|
REG_DIV_NUMER = (u64)_player->curFrame * (u64)_player->fvHeader->fpsDen;
|
|
REG_DIV_DENOM_L = _player->fvHeader->fpsNum;
|
|
|
|
fv_updatePlayer(_player);
|
|
|
|
while (REG_DIVCNT & DIV_BUSY)
|
|
;
|
|
u32 time = REG_DIV_RESULT_L;
|
|
if (time != _lastTime)
|
|
{
|
|
_lastTime = time;
|
|
_view.SetCurrentTime(time);
|
|
_view.Update();
|
|
_view.VBlank();
|
|
}
|
|
}
|
|
else
|
|
{
|
|
_view.Update();
|
|
swiWaitForVBlank();
|
|
_view.VBlank();
|
|
_lastTime = -1;
|
|
}
|
|
|
|
_inputProvider.Sample(); // todo: sample more frequently
|
|
_inputProvider.Update();
|
|
_inputRepeater.Update(&_inputProvider);
|
|
UpdateTouch();
|
|
UpdateKeys();
|
|
UpdateDim();
|
|
} |