forked from mia/Aegisub
Make VideoContext use events for some of its communication with other objects
Originally committed to SVN as r4900.
This commit is contained in:
parent
13f052317e
commit
d9006b0eb4
12 changed files with 132 additions and 184 deletions
|
@ -58,7 +58,6 @@
|
|||
#include "fft.h"
|
||||
#include "hotkeys.h"
|
||||
#include "include/aegisub/audio_player.h"
|
||||
#include "include/aegisub/audio_provider.h"
|
||||
#include "main.h"
|
||||
#include "standard_paths.h"
|
||||
#include "subs_edit_box.h"
|
||||
|
@ -123,6 +122,11 @@ AudioDisplay::AudioDisplay(wxWindow *parent)
|
|||
h -= OPT_GET("Audio/Display/Draw/Timeline")->GetBool() ? 20 : 0;
|
||||
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
|
||||
//wxCursor cursor(wxCURSOR_BLANK);
|
||||
//SetCursor(cursor);
|
||||
|
@ -2221,4 +2225,3 @@ void AudioDisplay::UpdateTimeEditCtrls() {
|
|||
grid->editBox->EndTime->SetTime(curEndMS);
|
||||
grid->editBox->Duration->SetTime(curEndMS-curStartMS);
|
||||
}
|
||||
|
||||
|
|
|
@ -852,7 +852,6 @@ void FrameMain::SetDisplayMode(int video, int audio) {
|
|||
MainSizer->RecalcSizes();
|
||||
MainSizer->Layout();
|
||||
Layout();
|
||||
if (showVideo) VideoContext::Get()->UpdateDisplays(true);
|
||||
|
||||
if (didFreeze) Thaw();
|
||||
}
|
||||
|
@ -1012,7 +1011,7 @@ void FrameMain::SynchronizeProject(bool fromSubs) {
|
|||
wxString ar = _T("0");
|
||||
wxString zoom = _T("6");
|
||||
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());
|
||||
|
||||
int arType = VideoContext::Get()->GetAspectRatioType();
|
||||
|
@ -1176,7 +1175,6 @@ void FrameMain::DetachVideo(bool detach) {
|
|||
if (!detachedVideo) {
|
||||
detachedVideo = new DialogDetachedVideo(this, videoBox->videoDisplay->GetClientSize());
|
||||
detachedVideo->Show();
|
||||
VideoContext::Get()->UpdateDisplays(true);
|
||||
}
|
||||
}
|
||||
else if (detachedVideo) {
|
||||
|
|
|
@ -535,18 +535,13 @@ void FrameMain::OnOpenRecentTimecodes(wxCommandEvent &event) {
|
|||
/// @brief Open recent Keyframes entry
|
||||
/// @param event
|
||||
void FrameMain::OnOpenRecentKeyframes(wxCommandEvent &event) {
|
||||
int number = event.GetId()-Menu_Keyframes_Recent;
|
||||
VideoContext::Get()->LoadKeyframes(lagi_wxString(config::mru->GetEntry("Keyframes", number)));
|
||||
videoBox->videoSlider->Refresh();
|
||||
audioBox->audioDisplay->Update();
|
||||
Refresh();
|
||||
VideoContext::Get()->LoadKeyframes(lagi_wxString(config::mru->GetEntry("Keyframes", event.GetId()-Menu_Keyframes_Recent)));
|
||||
}
|
||||
|
||||
/// @brief Open recent audio menu entry
|
||||
/// @param event
|
||||
void FrameMain::OnOpenRecentAudio(wxCommandEvent &event) {
|
||||
int number = event.GetId()-Menu_Audio_Recent;
|
||||
LoadAudio(lagi_wxString(config::mru->GetEntry("Audio", number)));
|
||||
LoadAudio(lagi_wxString(config::mru->GetEntry("Audio", event.GetId()-Menu_Audio_Recent)));
|
||||
}
|
||||
|
||||
/// @brief Open new Window
|
||||
|
@ -813,17 +808,11 @@ void FrameMain::OnOpenKeyframes (wxCommandEvent &) {
|
|||
|
||||
// Load
|
||||
VideoContext::Get()->LoadKeyframes(filename);
|
||||
videoBox->videoSlider->Refresh();
|
||||
audioBox->audioDisplay->Update();
|
||||
Refresh();
|
||||
}
|
||||
|
||||
/// @brief Close keyframes
|
||||
void FrameMain::OnCloseKeyframes (wxCommandEvent &) {
|
||||
VideoContext::Get()->CloseKeyframes();
|
||||
videoBox->videoSlider->Refresh();
|
||||
audioBox->audioDisplay->Update();
|
||||
Refresh();
|
||||
}
|
||||
|
||||
/// @brief Save keyframes
|
||||
|
|
|
@ -62,7 +62,6 @@
|
|||
#include "subs_grid.h"
|
||||
#include "utils.h"
|
||||
#include "video_context.h"
|
||||
#include "video_display.h"
|
||||
|
||||
BEGIN_EVENT_TABLE(SubtitlesGrid, BaseGrid)
|
||||
EVT_KEY_DOWN(SubtitlesGrid::OnKeyDown)
|
||||
|
@ -107,6 +106,11 @@ SubtitlesGrid::SubtitlesGrid(FrameMain* parentFr, wxWindow *parent, wxWindowID i
|
|||
byFrame = false;
|
||||
editBox = NULL;
|
||||
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
|
||||
|
@ -665,7 +669,7 @@ void SubtitlesGrid::OnAudioClip(wxCommandEvent &) {
|
|||
|
||||
if (!filename.empty()) {
|
||||
std::ofstream outfile(filename.mb_str(csConvLocal),std::ios::binary);
|
||||
|
||||
|
||||
size_t bufsize=(end-start)*provider->GetChannels()*provider->GetBytesPerSample();
|
||||
int intval;
|
||||
short shortval;
|
||||
|
@ -1273,3 +1277,12 @@ void SubtitlesGrid::SetSelectionFromAbsolute(std::vector<int> &selection) {
|
|||
|
||||
SetSelectedSet(newsel);
|
||||
}
|
||||
|
||||
void SubtitlesGrid::OnHighlightVisibleChange(agi::OptionValue const& opt) {
|
||||
if (opt.GetBool()) {
|
||||
seekListener.Unblock();
|
||||
}
|
||||
else {
|
||||
seekListener.Block();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -46,6 +46,10 @@
|
|||
|
||||
#include "base_grid.h"
|
||||
|
||||
#include <libaegisub/signals.h>
|
||||
|
||||
namespace agi { class OptionValue; }
|
||||
|
||||
class AssFile;
|
||||
class AssEntry;
|
||||
class AssDialogue;
|
||||
|
@ -61,6 +65,8 @@ typedef std::list<AssEntry*>::iterator entryIter;
|
|||
/// DOCME
|
||||
class SubtitlesGrid: public BaseGrid {
|
||||
private:
|
||||
agi::signal::Connection seekListener;
|
||||
|
||||
void OnPopupMenu(bool alternate=false);
|
||||
void OnKeyDown(wxKeyEvent &event);
|
||||
|
||||
|
@ -89,6 +95,8 @@ private:
|
|||
void OnAudioClip(wxCommandEvent &event);
|
||||
void OnShowColMenu(wxCommandEvent &event);
|
||||
|
||||
void OnHighlightVisibleChange(agi::OptionValue const& opt);
|
||||
|
||||
public:
|
||||
/// Currently open file
|
||||
AssFile *ass;
|
||||
|
|
|
@ -113,7 +113,6 @@ VideoBox::VideoBox(wxWindow *parent, bool isDetached, wxComboBox *zoomBox)
|
|||
|
||||
// Display
|
||||
videoDisplay = new VideoDisplay(this,videoSlider,VideoPosition,VideoSubsPos,zoomBox,videoPage,-1,wxDefaultPosition,wxDefaultSize,wxSUNKEN_BORDER);
|
||||
VideoContext::Get()->AddDisplay(videoDisplay);
|
||||
|
||||
// Set display
|
||||
videoSlider->Display = videoDisplay;
|
||||
|
|
|
@ -207,7 +207,8 @@ void VideoContext::SetVideo(const wxString &filename) {
|
|||
}
|
||||
|
||||
provider->LoadSubtitles(grid->ass);
|
||||
UpdateDisplays(true);
|
||||
VideoOpen();
|
||||
KeyframesOpen(keyFrames);
|
||||
}
|
||||
catch (agi::UserCancelException const&) { }
|
||||
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() {
|
||||
if (!IsLoaded()) return;
|
||||
|
||||
provider->LoadSubtitles(grid->ass);
|
||||
UpdateDisplays(false);
|
||||
SubtitlesChange();
|
||||
}
|
||||
|
||||
void VideoContext::JumpToFrame(int n) {
|
||||
|
@ -278,10 +243,7 @@ void VideoContext::JumpToFrame(int n) {
|
|||
|
||||
frame_n = n;
|
||||
|
||||
UpdateDisplays(false, true);
|
||||
|
||||
static const agi::OptionValue* highlight = OPT_GET("Subtitle/Grid/Highlight Subtitles in Frame");
|
||||
if (!isPlaying && highlight->GetBool()) grid->Refresh(false);
|
||||
Seek(n);
|
||||
}
|
||||
|
||||
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) {
|
||||
if (type != 4) value = GetARFromType(type);
|
||||
if (value < 0.5) value = 0.5;
|
||||
if (value > 5.0) value = 5.0;
|
||||
|
||||
arType = type;
|
||||
arValue = value;
|
||||
UpdateDisplays(true);
|
||||
arValue = MID(.5, value, 5.);
|
||||
}
|
||||
|
||||
void VideoContext::LoadKeyframes(wxString filename) {
|
||||
|
@ -494,7 +453,7 @@ void VideoContext::LoadKeyframes(wxString filename) {
|
|||
try {
|
||||
keyFrames = KeyFrameFile::Load(filename);
|
||||
keyFramesFilename = filename;
|
||||
Refresh();
|
||||
KeyframesOpen(keyFrames);
|
||||
}
|
||||
catch (const wchar_t *error) {
|
||||
wxMessageBox(error, _T("Error opening keyframes file"), wxOK | wxICON_ERROR, NULL);
|
||||
|
@ -520,7 +479,7 @@ void VideoContext::CloseKeyframes() {
|
|||
else {
|
||||
keyFrames.clear();
|
||||
}
|
||||
Refresh();
|
||||
KeyframesOpen(keyFrames);
|
||||
}
|
||||
|
||||
void VideoContext::LoadTimecodes(wxString filename) {
|
||||
|
|
|
@ -49,6 +49,7 @@
|
|||
#error "Aegisub requires wxWidgets to be compiled with OpenGL support."
|
||||
#endif
|
||||
|
||||
#include <libaegisub/signals.h>
|
||||
#include <libaegisub/vfr.h>
|
||||
|
||||
class AegiVideoFrame;
|
||||
|
@ -76,6 +77,17 @@ class VideoContext : public wxEvtHandler {
|
|||
friend class AudioProvider;
|
||||
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
|
||||
std::list<VideoDisplay*> displayList;
|
||||
|
||||
|
@ -165,10 +177,6 @@ public:
|
|||
VideoContext();
|
||||
~VideoContext();
|
||||
|
||||
void AddDisplay(VideoDisplay *display);
|
||||
void RemoveDisplay(VideoDisplay *display);
|
||||
|
||||
|
||||
/// @brief Get the video provider used for the currently open video
|
||||
VideoProvider *GetProvider() const { return videoProvider.get(); }
|
||||
std::tr1::shared_ptr<AegiVideoFrame> GetFrame(int n, bool raw = false);
|
||||
|
@ -234,11 +242,6 @@ public:
|
|||
/// @brief Refresh the subtitle provider
|
||||
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
|
||||
/// @param[out] w Width
|
||||
/// @param[out] h Height
|
||||
|
@ -257,6 +260,11 @@ public:
|
|||
/// Stop playing
|
||||
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; };
|
||||
wxString GetKeyFramesName() const { return keyFramesFilename; }
|
||||
void LoadKeyframes(wxString filename);
|
||||
|
|
|
@ -97,6 +97,7 @@ BEGIN_EVENT_TABLE(VideoDisplay, wxGLCanvas)
|
|||
EVT_PAINT(VideoDisplay::OnPaint)
|
||||
EVT_SIZE(VideoDisplay::OnSizeEvent)
|
||||
EVT_ERASE_BACKGROUND(VideoDisplay::OnEraseBackground)
|
||||
EVT_SHOW(VideoDisplay::OnShow)
|
||||
|
||||
EVT_MENU(VIDEO_MENU_COPY_COORDS,VideoDisplay::OnCopyCoords)
|
||||
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
|
||||
/// @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 {
|
||||
public:
|
||||
OpenGlException(const wxChar *func, int err)
|
||||
|
@ -155,13 +156,18 @@ VideoDisplay::VideoDisplay(
|
|||
{
|
||||
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);
|
||||
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);
|
||||
}
|
||||
|
||||
VideoDisplay::~VideoDisplay () {
|
||||
VideoContext::Get()->Unbind(EVT_FRAME_READY, &VideoDisplay::UploadFrameData, this);
|
||||
VideoContext::Get()->RemoveDisplay(this);
|
||||
}
|
||||
|
||||
bool VideoDisplay::InitContext() {
|
||||
|
@ -205,7 +211,6 @@ void VideoDisplay::UpdateRelativeTimes(int time) {
|
|||
|
||||
void VideoDisplay::SetFrame(int frameNumber) {
|
||||
VideoContext *context = VideoContext::Get();
|
||||
ControlSlider->SetValue(frameNumber);
|
||||
|
||||
currentFrame = frameNumber;
|
||||
|
||||
|
@ -270,8 +275,9 @@ void VideoDisplay::Refresh() {
|
|||
UpdateRelativeTimes(VideoContext::Get()->TimeAtFrame(currentFrame, agi::vfr::EXACT));
|
||||
}
|
||||
|
||||
void VideoDisplay::SetFrameRange(int from, int to) {
|
||||
ControlSlider->SetRange(from, to);
|
||||
void VideoDisplay::OnVideoOpen() {
|
||||
UpdateSize();
|
||||
Refresh();
|
||||
}
|
||||
|
||||
void VideoDisplay::Render() try {
|
||||
|
@ -548,6 +554,10 @@ double VideoDisplay::GetZoom() const {
|
|||
return zoomValue;
|
||||
}
|
||||
|
||||
void VideoDisplay::OnShow(wxShowEvent&) {
|
||||
OnVideoOpen();
|
||||
}
|
||||
|
||||
template<class T>
|
||||
void VideoDisplay::SetTool() {
|
||||
tool.reset();
|
||||
|
|
|
@ -42,6 +42,8 @@
|
|||
#include <memory>
|
||||
#endif
|
||||
|
||||
#include <libaegisub/signals.h>
|
||||
|
||||
// Prototypes
|
||||
class FrameReadyEvent;
|
||||
class VideoSlider;
|
||||
|
@ -64,6 +66,9 @@ struct VideoState {
|
|||
/// @class VideoDisplay
|
||||
/// @brief DOCME
|
||||
class VideoDisplay : public wxGLCanvas {
|
||||
/// Signals the display is connected to
|
||||
std::list<agi::signal::Connection> slots;
|
||||
|
||||
const agi::OptionValue* alwaysShowTools;
|
||||
/// The unscaled size of the displayed video
|
||||
wxSize origSize;
|
||||
|
@ -159,6 +164,15 @@ class VideoDisplay : public wxGLCanvas {
|
|||
/// @param time Currently displayed frame's 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 SetMode(int mode);
|
||||
|
@ -206,18 +220,6 @@ public:
|
|||
/// @brief Reset the size of the display to the video size
|
||||
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
|
||||
void Render();
|
||||
|
||||
|
|
|
@ -34,9 +34,6 @@
|
|||
/// @ingroup custom_control
|
||||
///
|
||||
|
||||
|
||||
////////////
|
||||
// Includes
|
||||
#include "config.h"
|
||||
|
||||
#ifndef AGI_PRE
|
||||
|
@ -66,17 +63,22 @@ VideoSlider::VideoSlider (wxWindow* parent, wxWindowID id)
|
|||
: wxWindow (parent,id,wxDefaultPosition,wxDefaultSize,wxWANTS_CHARS | wxFULL_REPAINT_ON_RESIZE)
|
||||
{
|
||||
val = 0;
|
||||
min = 0;
|
||||
max = 1;
|
||||
Display = NULL;
|
||||
SetClientSize(20,25);
|
||||
SetMinSize(wxSize(20, 25));
|
||||
locked = false;
|
||||
SetRange(0,1);
|
||||
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() {
|
||||
VideoContext *vc = VideoContext::Get();
|
||||
assert(vc);
|
||||
}
|
||||
|
||||
/// @brief Set value
|
||||
|
@ -84,29 +86,22 @@ VideoSlider::~VideoSlider() {
|
|||
/// @return
|
||||
///
|
||||
void VideoSlider::SetValue(int value) {
|
||||
if (locked) return;
|
||||
val = value;
|
||||
if (val < min) val = min;
|
||||
if (val > max) val = max;
|
||||
if (val == value) return;
|
||||
val = MID(0, value, max);
|
||||
Refresh(false);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/// @brief Set range
|
||||
/// @param from
|
||||
/// @param to
|
||||
///
|
||||
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::VideoOpened() {
|
||||
VideoContext *vc = VideoContext::Get();
|
||||
max = vc->GetLength() - 1;
|
||||
keyframes = vc->GetKeyFrames();
|
||||
Refresh(false);
|
||||
}
|
||||
|
||||
|
||||
void VideoSlider::KeyframesChanged(std::vector<int> const& newKeyframes) {
|
||||
keyframes = newKeyframes;
|
||||
Refresh(false);
|
||||
}
|
||||
|
||||
/// @brief Get value at X
|
||||
/// @param x
|
||||
|
@ -121,7 +116,7 @@ int VideoSlider::GetValueAtX(int x) {
|
|||
if (w <= 10) return 0;
|
||||
|
||||
// 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);
|
||||
|
||||
// Special case
|
||||
if (max-min <= 0) return 0;
|
||||
if (max <= 0) return 0;
|
||||
|
||||
// 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;
|
||||
|
||||
//don't request out of range frames
|
||||
if (GetValue() < max) VideoContext::Get()->PlayNextFrame();
|
||||
if (val < max) VideoContext::Get()->PlayNextFrame();
|
||||
Refresh(false);
|
||||
Update();
|
||||
}
|
||||
|
@ -165,14 +160,11 @@ void VideoSlider::PrevFrame() {
|
|||
if (VideoContext::Get()->IsPlaying()) return;
|
||||
|
||||
//don't request out of range frames
|
||||
if (GetValue() > min) VideoContext::Get()->PlayPrevFrame();
|
||||
if (val > 0) VideoContext::Get()->PlayPrevFrame();
|
||||
Refresh(false);
|
||||
Update();
|
||||
}
|
||||
|
||||
|
||||
///////////////
|
||||
// Event table
|
||||
BEGIN_EVENT_TABLE(VideoSlider, wxWindow)
|
||||
EVT_MOUSE_EVENTS(VideoSlider::OnMouse)
|
||||
EVT_KEY_DOWN(VideoSlider::OnKeyDown)
|
||||
|
@ -182,22 +174,6 @@ BEGIN_EVENT_TABLE(VideoSlider, wxWindow)
|
|||
EVT_ERASE_BACKGROUND(VideoSlider::OnEraseBackground)
|
||||
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
|
||||
/// @param event
|
||||
/// @return
|
||||
|
@ -214,7 +190,7 @@ void VideoSlider::OnMouse(wxMouseEvent &event) {
|
|||
bool canDrag = wxWindow::FindFocus() == this;
|
||||
if (!canDrag) {
|
||||
int tolerance = 4;
|
||||
int curX = GetXAtValue(GetValue());
|
||||
int curX = GetXAtValue(val);
|
||||
if (x-curX < -tolerance || x-curX > tolerance) canDrag = true;
|
||||
}
|
||||
|
||||
|
@ -237,14 +213,14 @@ void VideoSlider::OnMouse(wxMouseEvent &event) {
|
|||
}
|
||||
|
||||
// Jump to frame
|
||||
if (closest == GetValue()) return;
|
||||
if (closest == val) return;
|
||||
SetValue(closest);
|
||||
}
|
||||
|
||||
// Normal click
|
||||
else {
|
||||
int go = GetValueAtX(x);
|
||||
if (go == GetValue()) return;
|
||||
if (go == val) return;
|
||||
SetValue(go);
|
||||
}
|
||||
Refresh(false);
|
||||
|
@ -252,10 +228,10 @@ void VideoSlider::OnMouse(wxMouseEvent &event) {
|
|||
// Playing?
|
||||
if (VideoContext::Get()->IsPlaying()) {
|
||||
VideoContext::Get()->Stop();
|
||||
UpdateVideo();
|
||||
VideoContext::Get()->JumpToFrame(val);
|
||||
VideoContext::Get()->Play();
|
||||
}
|
||||
else UpdateVideo();
|
||||
else VideoContext::Get()->JumpToFrame(val);
|
||||
}
|
||||
|
||||
// Get focus
|
||||
|
@ -307,8 +283,8 @@ void VideoSlider::OnKeyDown(wxKeyEvent &event) {
|
|||
// Fast move
|
||||
if (!ctrl && !shift && alt) {
|
||||
if (VideoContext::Get()->IsPlaying()) return;
|
||||
int target = MID(min,GetValue() + direction * OPT_GET("Video/Slider/Fast Jump Step")->GetInt(),max);
|
||||
if (target != GetValue()) VideoContext::Get()->JumpToFrame(target);
|
||||
int target = MID(0,val + direction * OPT_GET("Video/Slider/Fast Jump Step")->GetInt(),max);
|
||||
if (target != val) VideoContext::Get()->JumpToFrame(target);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -371,24 +347,20 @@ void VideoSlider::OnKeyDown(wxKeyEvent &event) {
|
|||
if (direction != 0) {
|
||||
// Prepare
|
||||
int prevKey = 0;
|
||||
int nextKey = VideoContext::Get()->GetLength()-1;
|
||||
std::vector<int> KeyFrames = VideoContext::Get()->GetKeyFrames();
|
||||
int keys = KeyFrames.size();
|
||||
int cur = VideoContext::Get()->GetFrameN();
|
||||
int i;
|
||||
int temp;
|
||||
int nextKey = max;
|
||||
int keys = keyframes.size();
|
||||
|
||||
// Find previous keyframe
|
||||
// This algorithm does unnecessary loops, but it ensures it works even if keyframes are out of order.
|
||||
for (i=0;i<keys;i++) {
|
||||
temp = KeyFrames[i];
|
||||
if (temp < cur && temp > prevKey) prevKey = temp;
|
||||
for (int i=0;i<keys;i++) {
|
||||
int temp = keyframes[i];
|
||||
if (temp < val && temp > prevKey) prevKey = temp;
|
||||
}
|
||||
|
||||
// Find next keyframe
|
||||
for (i=0;i<keys;i++) {
|
||||
temp = KeyFrames[i];
|
||||
if (temp > cur && temp < nextKey) nextKey = KeyFrames[i];
|
||||
for (int i=0;i<keys;i++) {
|
||||
int temp = keyframes[i];
|
||||
if (temp > val && temp < nextKey) nextKey = temp;
|
||||
}
|
||||
|
||||
if (direction == -1) VideoContext::Get()->JumpToFrame(prevKey);
|
||||
|
@ -477,16 +449,14 @@ void VideoSlider::DrawImage(wxDC &destdc) {
|
|||
int curX;
|
||||
if (Display && OPT_GET("Video/Slider/Show Keyframes")->GetBool()) {
|
||||
dc.SetPen(wxPen(shad));
|
||||
std::vector<int> KeyFrames = VideoContext::Get()->GetKeyFrames();
|
||||
int keys = KeyFrames.size();
|
||||
for (int i=0;i<keys;i++) {
|
||||
curX = GetXAtValue(KeyFrames[i]);
|
||||
for (size_t i=0;i<keyframes.size();i++) {
|
||||
curX = GetXAtValue(keyframes[i]);
|
||||
dc.DrawLine(curX,2,curX,8);
|
||||
}
|
||||
}
|
||||
|
||||
// Draw cursor
|
||||
curX = GetXAtValue(GetValue());
|
||||
curX = GetXAtValue(val);
|
||||
|
||||
// Fill bg
|
||||
dc.SetBrush(wxBrush(face));
|
||||
|
@ -529,8 +499,6 @@ void VideoSlider::DrawImage(wxDC &destdc) {
|
|||
/// @brief Update image
|
||||
///
|
||||
void VideoSlider::UpdateImage () {
|
||||
//wxClientDC dc(this);
|
||||
//DrawImage(dc);
|
||||
Refresh(false);
|
||||
}
|
||||
|
||||
|
@ -542,5 +510,3 @@ void VideoSlider::UpdateImage () {
|
|||
void VideoSlider::OnFocus(wxFocusEvent &event) {
|
||||
Refresh(false);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -47,11 +47,10 @@ class SubtitlesGrid;
|
|||
///
|
||||
/// DOCME
|
||||
class VideoSlider: public wxWindow {
|
||||
/// DOCME
|
||||
int val;
|
||||
std::vector<int> keyframes;
|
||||
|
||||
/// DOCME
|
||||
int min;
|
||||
int val;
|
||||
|
||||
/// DOCME
|
||||
int max;
|
||||
|
@ -61,22 +60,20 @@ class VideoSlider: public wxWindow {
|
|||
|
||||
int GetValueAtX(int x);
|
||||
int GetXAtValue(int value);
|
||||
void UpdateVideo();
|
||||
void DrawImage(wxDC &dc);
|
||||
void UpdateImage();
|
||||
void SetValue(int value);
|
||||
|
||||
void VideoOpened();
|
||||
void KeyframesChanged(std::vector<int> const& newKeyframes);
|
||||
|
||||
void OnMouse(wxMouseEvent &event);
|
||||
void OnKeyDown(wxKeyEvent &event);
|
||||
void OnPaint(wxPaintEvent &event);
|
||||
void OnFocus(wxFocusEvent &event);
|
||||
|
||||
/// @brief DOCME
|
||||
/// @param event
|
||||
///
|
||||
void OnEraseBackground(wxEraseEvent &event) {}
|
||||
|
||||
public:
|
||||
|
||||
/// DOCME
|
||||
VideoDisplay *Display;
|
||||
|
||||
|
@ -89,9 +86,5 @@ public:
|
|||
void NextFrame();
|
||||
void PrevFrame();
|
||||
|
||||
void SetRange(int start,int end);
|
||||
int GetValue() const { return val; };
|
||||
void SetValue(int value);
|
||||
|
||||
DECLARE_EVENT_TABLE()
|
||||
};
|
||||
|
|
Loading…
Reference in a new issue