Make VideoContext use events for some of its communication with other objects

Originally committed to SVN as r4900.
This commit is contained in:
Thomas Goyne 2010-12-07 19:09:21 +00:00
parent 13f052317e
commit d9006b0eb4
12 changed files with 132 additions and 184 deletions

View file

@ -58,7 +58,6 @@
#include "fft.h" #include "fft.h"
#include "hotkeys.h" #include "hotkeys.h"
#include "include/aegisub/audio_player.h" #include "include/aegisub/audio_player.h"
#include "include/aegisub/audio_provider.h"
#include "main.h" #include "main.h"
#include "standard_paths.h" #include "standard_paths.h"
#include "subs_edit_box.h" #include "subs_edit_box.h"
@ -123,6 +122,11 @@ AudioDisplay::AudioDisplay(wxWindow *parent)
h -= OPT_GET("Audio/Display/Draw/Timeline")->GetBool() ? 20 : 0; h -= OPT_GET("Audio/Display/Draw/Timeline")->GetBool() ? 20 : 0;
SetSamplesPercent(50,false); SetSamplesPercent(50,false);
VideoContext *vc = VideoContext::Get();
vc->AddKeyframesOpenListener(&AudioDisplay::Update, this);
if (OPT_GET("Audio/Display/Draw/Video Position")->GetBool())
vc->AddSeekListener(&AudioDisplay::UpdateImage, this, false);
// Set cursor // Set cursor
//wxCursor cursor(wxCURSOR_BLANK); //wxCursor cursor(wxCURSOR_BLANK);
//SetCursor(cursor); //SetCursor(cursor);
@ -2221,4 +2225,3 @@ void AudioDisplay::UpdateTimeEditCtrls() {
grid->editBox->EndTime->SetTime(curEndMS); grid->editBox->EndTime->SetTime(curEndMS);
grid->editBox->Duration->SetTime(curEndMS-curStartMS); grid->editBox->Duration->SetTime(curEndMS-curStartMS);
} }

View file

@ -852,7 +852,6 @@ void FrameMain::SetDisplayMode(int video, int audio) {
MainSizer->RecalcSizes(); MainSizer->RecalcSizes();
MainSizer->Layout(); MainSizer->Layout();
Layout(); Layout();
if (showVideo) VideoContext::Get()->UpdateDisplays(true);
if (didFreeze) Thaw(); if (didFreeze) Thaw();
} }
@ -1012,7 +1011,7 @@ void FrameMain::SynchronizeProject(bool fromSubs) {
wxString ar = _T("0"); wxString ar = _T("0");
wxString zoom = _T("6"); wxString zoom = _T("6");
if (VideoContext::Get()->IsLoaded()) { if (VideoContext::Get()->IsLoaded()) {
seekpos = wxString::Format(_T("%i"),videoBox->videoDisplay->GetFrame()); seekpos = wxString::Format(_T("%i"),VideoContext::Get()->GetFrameN());
zoom = wxString::Format(_T("%f"),videoBox->videoDisplay->GetZoom()); zoom = wxString::Format(_T("%f"),videoBox->videoDisplay->GetZoom());
int arType = VideoContext::Get()->GetAspectRatioType(); int arType = VideoContext::Get()->GetAspectRatioType();
@ -1176,7 +1175,6 @@ void FrameMain::DetachVideo(bool detach) {
if (!detachedVideo) { if (!detachedVideo) {
detachedVideo = new DialogDetachedVideo(this, videoBox->videoDisplay->GetClientSize()); detachedVideo = new DialogDetachedVideo(this, videoBox->videoDisplay->GetClientSize());
detachedVideo->Show(); detachedVideo->Show();
VideoContext::Get()->UpdateDisplays(true);
} }
} }
else if (detachedVideo) { else if (detachedVideo) {

View file

@ -535,18 +535,13 @@ void FrameMain::OnOpenRecentTimecodes(wxCommandEvent &event) {
/// @brief Open recent Keyframes entry /// @brief Open recent Keyframes entry
/// @param event /// @param event
void FrameMain::OnOpenRecentKeyframes(wxCommandEvent &event) { void FrameMain::OnOpenRecentKeyframes(wxCommandEvent &event) {
int number = event.GetId()-Menu_Keyframes_Recent; VideoContext::Get()->LoadKeyframes(lagi_wxString(config::mru->GetEntry("Keyframes", event.GetId()-Menu_Keyframes_Recent)));
VideoContext::Get()->LoadKeyframes(lagi_wxString(config::mru->GetEntry("Keyframes", number)));
videoBox->videoSlider->Refresh();
audioBox->audioDisplay->Update();
Refresh();
} }
/// @brief Open recent audio menu entry /// @brief Open recent audio menu entry
/// @param event /// @param event
void FrameMain::OnOpenRecentAudio(wxCommandEvent &event) { void FrameMain::OnOpenRecentAudio(wxCommandEvent &event) {
int number = event.GetId()-Menu_Audio_Recent; LoadAudio(lagi_wxString(config::mru->GetEntry("Audio", event.GetId()-Menu_Audio_Recent)));
LoadAudio(lagi_wxString(config::mru->GetEntry("Audio", number)));
} }
/// @brief Open new Window /// @brief Open new Window
@ -813,17 +808,11 @@ void FrameMain::OnOpenKeyframes (wxCommandEvent &) {
// Load // Load
VideoContext::Get()->LoadKeyframes(filename); VideoContext::Get()->LoadKeyframes(filename);
videoBox->videoSlider->Refresh();
audioBox->audioDisplay->Update();
Refresh();
} }
/// @brief Close keyframes /// @brief Close keyframes
void FrameMain::OnCloseKeyframes (wxCommandEvent &) { void FrameMain::OnCloseKeyframes (wxCommandEvent &) {
VideoContext::Get()->CloseKeyframes(); VideoContext::Get()->CloseKeyframes();
videoBox->videoSlider->Refresh();
audioBox->audioDisplay->Update();
Refresh();
} }
/// @brief Save keyframes /// @brief Save keyframes

View file

@ -62,7 +62,6 @@
#include "subs_grid.h" #include "subs_grid.h"
#include "utils.h" #include "utils.h"
#include "video_context.h" #include "video_context.h"
#include "video_display.h"
BEGIN_EVENT_TABLE(SubtitlesGrid, BaseGrid) BEGIN_EVENT_TABLE(SubtitlesGrid, BaseGrid)
EVT_KEY_DOWN(SubtitlesGrid::OnKeyDown) EVT_KEY_DOWN(SubtitlesGrid::OnKeyDown)
@ -107,6 +106,11 @@ SubtitlesGrid::SubtitlesGrid(FrameMain* parentFr, wxWindow *parent, wxWindowID i
byFrame = false; byFrame = false;
editBox = NULL; editBox = NULL;
parentFrame = parentFr; parentFrame = parentFr;
seekListener = VideoContext::Get()->AddSeekListener(&SubtitlesGrid::Refresh, this, false, (const wxRect *)NULL);
OnHighlightVisibleChange(*OPT_GET("Subtitle/Grid/Highlight Subtitles in Frame"));
OPT_SUB("Subtitle/Grid/Highlight Subtitles in Frame", &SubtitlesGrid::OnHighlightVisibleChange, this);
} }
/// @brief Destructor /// @brief Destructor
@ -665,7 +669,7 @@ void SubtitlesGrid::OnAudioClip(wxCommandEvent &) {
if (!filename.empty()) { if (!filename.empty()) {
std::ofstream outfile(filename.mb_str(csConvLocal),std::ios::binary); std::ofstream outfile(filename.mb_str(csConvLocal),std::ios::binary);
size_t bufsize=(end-start)*provider->GetChannels()*provider->GetBytesPerSample(); size_t bufsize=(end-start)*provider->GetChannels()*provider->GetBytesPerSample();
int intval; int intval;
short shortval; short shortval;
@ -1273,3 +1277,12 @@ void SubtitlesGrid::SetSelectionFromAbsolute(std::vector<int> &selection) {
SetSelectedSet(newsel); SetSelectedSet(newsel);
} }
void SubtitlesGrid::OnHighlightVisibleChange(agi::OptionValue const& opt) {
if (opt.GetBool()) {
seekListener.Unblock();
}
else {
seekListener.Block();
}
}

View file

@ -46,6 +46,10 @@
#include "base_grid.h" #include "base_grid.h"
#include <libaegisub/signals.h>
namespace agi { class OptionValue; }
class AssFile; class AssFile;
class AssEntry; class AssEntry;
class AssDialogue; class AssDialogue;
@ -61,6 +65,8 @@ typedef std::list<AssEntry*>::iterator entryIter;
/// DOCME /// DOCME
class SubtitlesGrid: public BaseGrid { class SubtitlesGrid: public BaseGrid {
private: private:
agi::signal::Connection seekListener;
void OnPopupMenu(bool alternate=false); void OnPopupMenu(bool alternate=false);
void OnKeyDown(wxKeyEvent &event); void OnKeyDown(wxKeyEvent &event);
@ -89,6 +95,8 @@ private:
void OnAudioClip(wxCommandEvent &event); void OnAudioClip(wxCommandEvent &event);
void OnShowColMenu(wxCommandEvent &event); void OnShowColMenu(wxCommandEvent &event);
void OnHighlightVisibleChange(agi::OptionValue const& opt);
public: public:
/// Currently open file /// Currently open file
AssFile *ass; AssFile *ass;

View file

@ -113,7 +113,6 @@ VideoBox::VideoBox(wxWindow *parent, bool isDetached, wxComboBox *zoomBox)
// Display // Display
videoDisplay = new VideoDisplay(this,videoSlider,VideoPosition,VideoSubsPos,zoomBox,videoPage,-1,wxDefaultPosition,wxDefaultSize,wxSUNKEN_BORDER); videoDisplay = new VideoDisplay(this,videoSlider,VideoPosition,VideoSubsPos,zoomBox,videoPage,-1,wxDefaultPosition,wxDefaultSize,wxSUNKEN_BORDER);
VideoContext::Get()->AddDisplay(videoDisplay);
// Set display // Set display
videoSlider->Display = videoDisplay; videoSlider->Display = videoDisplay;

View file

@ -207,7 +207,8 @@ void VideoContext::SetVideo(const wxString &filename) {
} }
provider->LoadSubtitles(grid->ass); provider->LoadSubtitles(grid->ass);
UpdateDisplays(true); VideoOpen();
KeyframesOpen(keyFrames);
} }
catch (agi::UserCancelException const&) { } catch (agi::UserCancelException const&) { }
catch (agi::FileNotAccessibleError const& err) { catch (agi::FileNotAccessibleError const& err) {
@ -227,47 +228,11 @@ void VideoContext::Reload() {
} }
} }
void VideoContext::AddDisplay(VideoDisplay *display) {
if (std::find(displayList.begin(), displayList.end(), display) == displayList.end())
displayList.push_back(display);
}
void VideoContext::RemoveDisplay(VideoDisplay *display) {
displayList.remove(display);
}
void VideoContext::UpdateDisplays(bool full, bool seek) {
if (!IsLoaded()) return;
for (std::list<VideoDisplay*>::iterator cur=displayList.begin();cur!=displayList.end();cur++) {
VideoDisplay *display = *cur;
if (!seek) {
display->Refresh();
}
if (full) {
display->UpdateSize();
display->SetFrameRange(0,GetLength()-1);
}
if (seek || full) {
display->SetFrame(GetFrameN());
}
}
// Update audio display
if (audio && audio->loaded && audio->IsShownOnScreen()) {
static const agi::OptionValue* opt = OPT_GET("Audio/Display/Draw/Video Position");
if (opt->GetBool()) {
audio->UpdateImage(false);
}
}
}
void VideoContext::Refresh() { void VideoContext::Refresh() {
if (!IsLoaded()) return; if (!IsLoaded()) return;
provider->LoadSubtitles(grid->ass); provider->LoadSubtitles(grid->ass);
UpdateDisplays(false); SubtitlesChange();
} }
void VideoContext::JumpToFrame(int n) { void VideoContext::JumpToFrame(int n) {
@ -278,10 +243,7 @@ void VideoContext::JumpToFrame(int n) {
frame_n = n; frame_n = n;
UpdateDisplays(false, true); Seek(n);
static const agi::OptionValue* highlight = OPT_GET("Subtitle/Grid/Highlight Subtitles in Frame");
if (!isPlaying && highlight->GetBool()) grid->Refresh(false);
} }
void VideoContext::JumpToTime(int ms, agi::vfr::Time end) { void VideoContext::JumpToTime(int ms, agi::vfr::Time end) {
@ -481,12 +443,9 @@ double VideoContext::GetARFromType(int type) const {
void VideoContext::SetAspectRatio(int type, double value) { void VideoContext::SetAspectRatio(int type, double value) {
if (type != 4) value = GetARFromType(type); if (type != 4) value = GetARFromType(type);
if (value < 0.5) value = 0.5;
if (value > 5.0) value = 5.0;
arType = type; arType = type;
arValue = value; arValue = MID(.5, value, 5.);
UpdateDisplays(true);
} }
void VideoContext::LoadKeyframes(wxString filename) { void VideoContext::LoadKeyframes(wxString filename) {
@ -494,7 +453,7 @@ void VideoContext::LoadKeyframes(wxString filename) {
try { try {
keyFrames = KeyFrameFile::Load(filename); keyFrames = KeyFrameFile::Load(filename);
keyFramesFilename = filename; keyFramesFilename = filename;
Refresh(); KeyframesOpen(keyFrames);
} }
catch (const wchar_t *error) { catch (const wchar_t *error) {
wxMessageBox(error, _T("Error opening keyframes file"), wxOK | wxICON_ERROR, NULL); wxMessageBox(error, _T("Error opening keyframes file"), wxOK | wxICON_ERROR, NULL);
@ -520,7 +479,7 @@ void VideoContext::CloseKeyframes() {
else { else {
keyFrames.clear(); keyFrames.clear();
} }
Refresh(); KeyframesOpen(keyFrames);
} }
void VideoContext::LoadTimecodes(wxString filename) { void VideoContext::LoadTimecodes(wxString filename) {

View file

@ -49,6 +49,7 @@
#error "Aegisub requires wxWidgets to be compiled with OpenGL support." #error "Aegisub requires wxWidgets to be compiled with OpenGL support."
#endif #endif
#include <libaegisub/signals.h>
#include <libaegisub/vfr.h> #include <libaegisub/vfr.h>
class AegiVideoFrame; class AegiVideoFrame;
@ -76,6 +77,17 @@ class VideoContext : public wxEvtHandler {
friend class AudioProvider; friend class AudioProvider;
friend class KeyFrameFile; friend class KeyFrameFile;
/// Current frame number changed
agi::signal::Signal<int> Seek;
/// A new video was opened
agi::signal::Signal<> VideoOpen;
/// Subtitles file changed
/// @todo Move this to AssFile
agi::signal::Signal<> SubtitlesChange;
/// New keyframes opened
agi::signal::Signal<std::vector<int> const&> KeyframesOpen;
private:
/// DOCME /// DOCME
std::list<VideoDisplay*> displayList; std::list<VideoDisplay*> displayList;
@ -165,10 +177,6 @@ public:
VideoContext(); VideoContext();
~VideoContext(); ~VideoContext();
void AddDisplay(VideoDisplay *display);
void RemoveDisplay(VideoDisplay *display);
/// @brief Get the video provider used for the currently open video /// @brief Get the video provider used for the currently open video
VideoProvider *GetProvider() const { return videoProvider.get(); } VideoProvider *GetProvider() const { return videoProvider.get(); }
std::tr1::shared_ptr<AegiVideoFrame> GetFrame(int n, bool raw = false); std::tr1::shared_ptr<AegiVideoFrame> GetFrame(int n, bool raw = false);
@ -234,11 +242,6 @@ public:
/// @brief Refresh the subtitle provider /// @brief Refresh the subtitle provider
void Refresh(); void Refresh();
/// @brief Update the video display
/// @param full Recalculate size and slider lengths
/// @param seek Update is just a seek and file has not changed
void UpdateDisplays(bool full, bool seek = false);
/// @brief Get the height and width of the current script /// @brief Get the height and width of the current script
/// @param[out] w Width /// @param[out] w Width
/// @param[out] h Height /// @param[out] h Height
@ -257,6 +260,11 @@ public:
/// Stop playing /// Stop playing
void Stop(); void Stop();
DEFINE_SIGNAL_ADDERS(Seek, AddSeekListener)
DEFINE_SIGNAL_ADDERS(VideoOpen, AddVideoOpenListener)
DEFINE_SIGNAL_ADDERS(KeyframesOpen, AddKeyframesOpenListener)
DEFINE_SIGNAL_ADDERS(SubtitlesChange, AddSubtitlesChangeListener)
const std::vector<int>& GetKeyFrames() const { return keyFrames; }; const std::vector<int>& GetKeyFrames() const { return keyFrames; };
wxString GetKeyFramesName() const { return keyFramesFilename; } wxString GetKeyFramesName() const { return keyFramesFilename; }
void LoadKeyframes(wxString filename); void LoadKeyframes(wxString filename);

View file

@ -97,6 +97,7 @@ BEGIN_EVENT_TABLE(VideoDisplay, wxGLCanvas)
EVT_PAINT(VideoDisplay::OnPaint) EVT_PAINT(VideoDisplay::OnPaint)
EVT_SIZE(VideoDisplay::OnSizeEvent) EVT_SIZE(VideoDisplay::OnSizeEvent)
EVT_ERASE_BACKGROUND(VideoDisplay::OnEraseBackground) EVT_ERASE_BACKGROUND(VideoDisplay::OnEraseBackground)
EVT_SHOW(VideoDisplay::OnShow)
EVT_MENU(VIDEO_MENU_COPY_COORDS,VideoDisplay::OnCopyCoords) EVT_MENU(VIDEO_MENU_COPY_COORDS,VideoDisplay::OnCopyCoords)
EVT_MENU(VIDEO_MENU_COPY_TO_CLIPBOARD,VideoDisplay::OnCopyToClipboard) EVT_MENU(VIDEO_MENU_COPY_TO_CLIPBOARD,VideoDisplay::OnCopyToClipboard)
@ -110,7 +111,7 @@ int attribList[] = { WX_GL_RGBA , WX_GL_DOUBLEBUFFER, WX_GL_STENCIL_SIZE, 8, 0 }
/// @class VideoOutRenderException /// @class VideoOutRenderException
/// @extends VideoOutException /// @extends VideoOutException
/// @brief An OpenGL error occured while uploading or displaying a frame /// @brief An OpenGL error occurred while uploading or displaying a frame
class OpenGlException : public agi::Exception { class OpenGlException : public agi::Exception {
public: public:
OpenGlException(const wxChar *func, int err) OpenGlException(const wxChar *func, int err)
@ -155,13 +156,18 @@ VideoDisplay::VideoDisplay(
{ {
if (zoomBox) zoomBox->SetValue(wxString::Format("%g%%", zoomValue * 100.)); if (zoomBox) zoomBox->SetValue(wxString::Format("%g%%", zoomValue * 100.));
box->Bind(wxEVT_COMMAND_TOOL_CLICKED, &VideoDisplay::OnMode, this, Video_Mode_Standard, Video_Mode_Vector_Clip); box->Bind(wxEVT_COMMAND_TOOL_CLICKED, &VideoDisplay::OnMode, this, Video_Mode_Standard, Video_Mode_Vector_Clip);
VideoContext::Get()->Bind(EVT_FRAME_READY, &VideoDisplay::UploadFrameData, this);
VideoContext *vc = VideoContext::Get();
vc->Bind(EVT_FRAME_READY, &VideoDisplay::UploadFrameData, this);
slots.push_back(vc->AddSeekListener(&VideoDisplay::SetFrame, this));
slots.push_back(vc->AddVideoOpenListener(&VideoDisplay::OnVideoOpen, this));
slots.push_back(vc->AddSubtitlesChangeListener(&VideoDisplay::Refresh, this));
SetCursor(wxNullCursor); SetCursor(wxNullCursor);
} }
VideoDisplay::~VideoDisplay () { VideoDisplay::~VideoDisplay () {
VideoContext::Get()->Unbind(EVT_FRAME_READY, &VideoDisplay::UploadFrameData, this); VideoContext::Get()->Unbind(EVT_FRAME_READY, &VideoDisplay::UploadFrameData, this);
VideoContext::Get()->RemoveDisplay(this);
} }
bool VideoDisplay::InitContext() { bool VideoDisplay::InitContext() {
@ -205,7 +211,6 @@ void VideoDisplay::UpdateRelativeTimes(int time) {
void VideoDisplay::SetFrame(int frameNumber) { void VideoDisplay::SetFrame(int frameNumber) {
VideoContext *context = VideoContext::Get(); VideoContext *context = VideoContext::Get();
ControlSlider->SetValue(frameNumber);
currentFrame = frameNumber; currentFrame = frameNumber;
@ -270,8 +275,9 @@ void VideoDisplay::Refresh() {
UpdateRelativeTimes(VideoContext::Get()->TimeAtFrame(currentFrame, agi::vfr::EXACT)); UpdateRelativeTimes(VideoContext::Get()->TimeAtFrame(currentFrame, agi::vfr::EXACT));
} }
void VideoDisplay::SetFrameRange(int from, int to) { void VideoDisplay::OnVideoOpen() {
ControlSlider->SetRange(from, to); UpdateSize();
Refresh();
} }
void VideoDisplay::Render() try { void VideoDisplay::Render() try {
@ -548,6 +554,10 @@ double VideoDisplay::GetZoom() const {
return zoomValue; return zoomValue;
} }
void VideoDisplay::OnShow(wxShowEvent&) {
OnVideoOpen();
}
template<class T> template<class T>
void VideoDisplay::SetTool() { void VideoDisplay::SetTool() {
tool.reset(); tool.reset();

View file

@ -42,6 +42,8 @@
#include <memory> #include <memory>
#endif #endif
#include <libaegisub/signals.h>
// Prototypes // Prototypes
class FrameReadyEvent; class FrameReadyEvent;
class VideoSlider; class VideoSlider;
@ -64,6 +66,9 @@ struct VideoState {
/// @class VideoDisplay /// @class VideoDisplay
/// @brief DOCME /// @brief DOCME
class VideoDisplay : public wxGLCanvas { class VideoDisplay : public wxGLCanvas {
/// Signals the display is connected to
std::list<agi::signal::Connection> slots;
const agi::OptionValue* alwaysShowTools; const agi::OptionValue* alwaysShowTools;
/// The unscaled size of the displayed video /// The unscaled size of the displayed video
wxSize origSize; wxSize origSize;
@ -159,6 +164,15 @@ class VideoDisplay : public wxGLCanvas {
/// @param time Currently displayed frame's time /// @param time Currently displayed frame's time
void UpdateRelativeTimes(int time); void UpdateRelativeTimes(int time);
/// @brief Set this video display to the given frame
/// @frameNumber The desired frame number
void SetFrame(int frameNumber);
/// @brief Signal that the file has changed
void Refresh();
void OnVideoOpen();
void OnShow(wxShowEvent &event);
void OnMode(const wxCommandEvent &event); void OnMode(const wxCommandEvent &event);
void SetMode(int mode); void SetMode(int mode);
@ -206,18 +220,6 @@ public:
/// @brief Reset the size of the display to the video size /// @brief Reset the size of the display to the video size
void Reset(); void Reset();
/// @brief Set this video display to the given frame
/// @frameNumber The desired frame number
void SetFrame(int frameNumber);
/// @brief Get the number of the currently displayed framed
int GetFrame() const { return currentFrame; }
/// @brief Set the range of valid frame numbers for the slider
/// @from Minimum frame number
/// @to Maximum frame number; must be >= from or strange things may happen
void SetFrameRange(int from, int to);
/// @brief Signal that the file has changed
void Refresh();
/// @brief Render the currently visible frame /// @brief Render the currently visible frame
void Render(); void Render();

View file

@ -34,9 +34,6 @@
/// @ingroup custom_control /// @ingroup custom_control
/// ///
////////////
// Includes
#include "config.h" #include "config.h"
#ifndef AGI_PRE #ifndef AGI_PRE
@ -66,17 +63,22 @@ VideoSlider::VideoSlider (wxWindow* parent, wxWindowID id)
: wxWindow (parent,id,wxDefaultPosition,wxDefaultSize,wxWANTS_CHARS | wxFULL_REPAINT_ON_RESIZE) : wxWindow (parent,id,wxDefaultPosition,wxDefaultSize,wxWANTS_CHARS | wxFULL_REPAINT_ON_RESIZE)
{ {
val = 0; val = 0;
min = 0;
max = 1; max = 1;
Display = NULL; Display = NULL;
SetClientSize(20,25); SetClientSize(20,25);
SetMinSize(wxSize(20, 25)); SetMinSize(wxSize(20, 25));
locked = false; locked = false;
SetRange(0,1);
OPT_SUB("Video/Slider/Show Keyframes", &wxWindow::Refresh, this, false, (wxRect*)NULL); OPT_SUB("Video/Slider/Show Keyframes", &wxWindow::Refresh, this, false, (wxRect*)NULL);
VideoContext *vc = VideoContext::Get();
assert(vc);
vc->AddSeekListener(&VideoSlider::SetValue, this);
vc->AddVideoOpenListener(&VideoSlider::VideoOpened, this);
vc->AddKeyframesOpenListener(&VideoSlider::KeyframesChanged, this);
} }
VideoSlider::~VideoSlider() { VideoSlider::~VideoSlider() {
VideoContext *vc = VideoContext::Get();
assert(vc);
} }
/// @brief Set value /// @brief Set value
@ -84,29 +86,22 @@ VideoSlider::~VideoSlider() {
/// @return /// @return
/// ///
void VideoSlider::SetValue(int value) { void VideoSlider::SetValue(int value) {
if (locked) return; if (val == value) return;
val = value; val = MID(0, value, max);
if (val < min) val = min;
if (val > max) val = max;
Refresh(false); Refresh(false);
} }
void VideoSlider::VideoOpened() {
VideoContext *vc = VideoContext::Get();
/// @brief Set range max = vc->GetLength() - 1;
/// @param from keyframes = vc->GetKeyFrames();
/// @param to Refresh(false);
///
void VideoSlider::SetRange(int from,int to) {
if (from > to) from = to;
locked = false;
min = from;
max = to;
if (val < from) val = from;
if (val > to) val = to;
} }
void VideoSlider::KeyframesChanged(std::vector<int> const& newKeyframes) {
keyframes = newKeyframes;
Refresh(false);
}
/// @brief Get value at X /// @brief Get value at X
/// @param x /// @param x
@ -121,7 +116,7 @@ int VideoSlider::GetValueAtX(int x) {
if (w <= 10) return 0; if (w <= 10) return 0;
// Calculate // Calculate
return (int64_t)(x-5)*(int64_t)(max-min)/(int64_t)(w-10)+min; return (int64_t)(x-5)*(int64_t)max/(int64_t)(w-10);
} }
@ -136,10 +131,10 @@ int VideoSlider::GetXAtValue(int value) {
GetClientSize(&w,&h); GetClientSize(&w,&h);
// Special case // Special case
if (max-min <= 0) return 0; if (max <= 0) return 0;
// Calculate // Calculate
return (int64_t)(value-min)*(int64_t)(w-10)/(int64_t)(max-min)+5; return (int64_t)value*(int64_t)(w-10)/(int64_t)max+5;
} }
@ -151,7 +146,7 @@ void VideoSlider::NextFrame() {
if (VideoContext::Get()->IsPlaying()) return; if (VideoContext::Get()->IsPlaying()) return;
//don't request out of range frames //don't request out of range frames
if (GetValue() < max) VideoContext::Get()->PlayNextFrame(); if (val < max) VideoContext::Get()->PlayNextFrame();
Refresh(false); Refresh(false);
Update(); Update();
} }
@ -165,14 +160,11 @@ void VideoSlider::PrevFrame() {
if (VideoContext::Get()->IsPlaying()) return; if (VideoContext::Get()->IsPlaying()) return;
//don't request out of range frames //don't request out of range frames
if (GetValue() > min) VideoContext::Get()->PlayPrevFrame(); if (val > 0) VideoContext::Get()->PlayPrevFrame();
Refresh(false); Refresh(false);
Update(); Update();
} }
///////////////
// Event table
BEGIN_EVENT_TABLE(VideoSlider, wxWindow) BEGIN_EVENT_TABLE(VideoSlider, wxWindow)
EVT_MOUSE_EVENTS(VideoSlider::OnMouse) EVT_MOUSE_EVENTS(VideoSlider::OnMouse)
EVT_KEY_DOWN(VideoSlider::OnKeyDown) EVT_KEY_DOWN(VideoSlider::OnKeyDown)
@ -182,22 +174,6 @@ BEGIN_EVENT_TABLE(VideoSlider, wxWindow)
EVT_ERASE_BACKGROUND(VideoSlider::OnEraseBackground) EVT_ERASE_BACKGROUND(VideoSlider::OnEraseBackground)
END_EVENT_TABLE() END_EVENT_TABLE()
/// @brief Change position
/// @return
///
void VideoSlider::UpdateVideo() {
if (Display) {
if (VideoContext::Get()->IsPlaying()) return;
locked = true;
VideoContext::Get()->JumpToFrame(GetValue());
locked = false;
}
}
/// @brief Mouse events /// @brief Mouse events
/// @param event /// @param event
/// @return /// @return
@ -214,7 +190,7 @@ void VideoSlider::OnMouse(wxMouseEvent &event) {
bool canDrag = wxWindow::FindFocus() == this; bool canDrag = wxWindow::FindFocus() == this;
if (!canDrag) { if (!canDrag) {
int tolerance = 4; int tolerance = 4;
int curX = GetXAtValue(GetValue()); int curX = GetXAtValue(val);
if (x-curX < -tolerance || x-curX > tolerance) canDrag = true; if (x-curX < -tolerance || x-curX > tolerance) canDrag = true;
} }
@ -237,14 +213,14 @@ void VideoSlider::OnMouse(wxMouseEvent &event) {
} }
// Jump to frame // Jump to frame
if (closest == GetValue()) return; if (closest == val) return;
SetValue(closest); SetValue(closest);
} }
// Normal click // Normal click
else { else {
int go = GetValueAtX(x); int go = GetValueAtX(x);
if (go == GetValue()) return; if (go == val) return;
SetValue(go); SetValue(go);
} }
Refresh(false); Refresh(false);
@ -252,10 +228,10 @@ void VideoSlider::OnMouse(wxMouseEvent &event) {
// Playing? // Playing?
if (VideoContext::Get()->IsPlaying()) { if (VideoContext::Get()->IsPlaying()) {
VideoContext::Get()->Stop(); VideoContext::Get()->Stop();
UpdateVideo(); VideoContext::Get()->JumpToFrame(val);
VideoContext::Get()->Play(); VideoContext::Get()->Play();
} }
else UpdateVideo(); else VideoContext::Get()->JumpToFrame(val);
} }
// Get focus // Get focus
@ -307,8 +283,8 @@ void VideoSlider::OnKeyDown(wxKeyEvent &event) {
// Fast move // Fast move
if (!ctrl && !shift && alt) { if (!ctrl && !shift && alt) {
if (VideoContext::Get()->IsPlaying()) return; if (VideoContext::Get()->IsPlaying()) return;
int target = MID(min,GetValue() + direction * OPT_GET("Video/Slider/Fast Jump Step")->GetInt(),max); int target = MID(0,val + direction * OPT_GET("Video/Slider/Fast Jump Step")->GetInt(),max);
if (target != GetValue()) VideoContext::Get()->JumpToFrame(target); if (target != val) VideoContext::Get()->JumpToFrame(target);
return; return;
} }
@ -371,24 +347,20 @@ void VideoSlider::OnKeyDown(wxKeyEvent &event) {
if (direction != 0) { if (direction != 0) {
// Prepare // Prepare
int prevKey = 0; int prevKey = 0;
int nextKey = VideoContext::Get()->GetLength()-1; int nextKey = max;
std::vector<int> KeyFrames = VideoContext::Get()->GetKeyFrames(); int keys = keyframes.size();
int keys = KeyFrames.size();
int cur = VideoContext::Get()->GetFrameN();
int i;
int temp;
// Find previous keyframe // Find previous keyframe
// This algorithm does unnecessary loops, but it ensures it works even if keyframes are out of order. // This algorithm does unnecessary loops, but it ensures it works even if keyframes are out of order.
for (i=0;i<keys;i++) { for (int i=0;i<keys;i++) {
temp = KeyFrames[i]; int temp = keyframes[i];
if (temp < cur && temp > prevKey) prevKey = temp; if (temp < val && temp > prevKey) prevKey = temp;
} }
// Find next keyframe // Find next keyframe
for (i=0;i<keys;i++) { for (int i=0;i<keys;i++) {
temp = KeyFrames[i]; int temp = keyframes[i];
if (temp > cur && temp < nextKey) nextKey = KeyFrames[i]; if (temp > val && temp < nextKey) nextKey = temp;
} }
if (direction == -1) VideoContext::Get()->JumpToFrame(prevKey); if (direction == -1) VideoContext::Get()->JumpToFrame(prevKey);
@ -477,16 +449,14 @@ void VideoSlider::DrawImage(wxDC &destdc) {
int curX; int curX;
if (Display && OPT_GET("Video/Slider/Show Keyframes")->GetBool()) { if (Display && OPT_GET("Video/Slider/Show Keyframes")->GetBool()) {
dc.SetPen(wxPen(shad)); dc.SetPen(wxPen(shad));
std::vector<int> KeyFrames = VideoContext::Get()->GetKeyFrames(); for (size_t i=0;i<keyframes.size();i++) {
int keys = KeyFrames.size(); curX = GetXAtValue(keyframes[i]);
for (int i=0;i<keys;i++) {
curX = GetXAtValue(KeyFrames[i]);
dc.DrawLine(curX,2,curX,8); dc.DrawLine(curX,2,curX,8);
} }
} }
// Draw cursor // Draw cursor
curX = GetXAtValue(GetValue()); curX = GetXAtValue(val);
// Fill bg // Fill bg
dc.SetBrush(wxBrush(face)); dc.SetBrush(wxBrush(face));
@ -529,8 +499,6 @@ void VideoSlider::DrawImage(wxDC &destdc) {
/// @brief Update image /// @brief Update image
/// ///
void VideoSlider::UpdateImage () { void VideoSlider::UpdateImage () {
//wxClientDC dc(this);
//DrawImage(dc);
Refresh(false); Refresh(false);
} }
@ -542,5 +510,3 @@ void VideoSlider::UpdateImage () {
void VideoSlider::OnFocus(wxFocusEvent &event) { void VideoSlider::OnFocus(wxFocusEvent &event) {
Refresh(false); Refresh(false);
} }

View file

@ -47,11 +47,10 @@ class SubtitlesGrid;
/// ///
/// DOCME /// DOCME
class VideoSlider: public wxWindow { class VideoSlider: public wxWindow {
/// DOCME std::vector<int> keyframes;
int val;
/// DOCME /// DOCME
int min; int val;
/// DOCME /// DOCME
int max; int max;
@ -61,22 +60,20 @@ class VideoSlider: public wxWindow {
int GetValueAtX(int x); int GetValueAtX(int x);
int GetXAtValue(int value); int GetXAtValue(int value);
void UpdateVideo();
void DrawImage(wxDC &dc); void DrawImage(wxDC &dc);
void UpdateImage(); void UpdateImage();
void SetValue(int value);
void VideoOpened();
void KeyframesChanged(std::vector<int> const& newKeyframes);
void OnMouse(wxMouseEvent &event); void OnMouse(wxMouseEvent &event);
void OnKeyDown(wxKeyEvent &event); void OnKeyDown(wxKeyEvent &event);
void OnPaint(wxPaintEvent &event); void OnPaint(wxPaintEvent &event);
void OnFocus(wxFocusEvent &event); void OnFocus(wxFocusEvent &event);
/// @brief DOCME
/// @param event
///
void OnEraseBackground(wxEraseEvent &event) {} void OnEraseBackground(wxEraseEvent &event) {}
public: public:
/// DOCME /// DOCME
VideoDisplay *Display; VideoDisplay *Display;
@ -89,9 +86,5 @@ public:
void NextFrame(); void NextFrame();
void PrevFrame(); void PrevFrame();
void SetRange(int start,int end);
int GetValue() const { return val; };
void SetValue(int value);
DECLARE_EVENT_TABLE() DECLARE_EVENT_TABLE()
}; };