Aegisub/aegisub/src/command/video.cpp

500 lines
12 KiB
C++

// Copyright (c) 2005-2010, Niels Martin Hansen
// Copyright (c) 2005-2010, Rodrigo Braz Monteiro
// Copyright (c) 2010, Amar Takhar
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// * Redistributions of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
// * Neither the name of the Aegisub Group nor the names of its contributors
// may be used to endorse or promote products derived from this software
// without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.
//
// Aegisub Project http://www.aegisub.org/
//
// $Id$
/// @file video.cpp
/// @brief video/ commands.
/// @ingroup command
///
#include "config.h"
#ifndef AGI_PRE
#endif
#include "command.h"
#include "aegisub/context.h"
#include "video_context.h"
#include "main.h"
#include "utils.h"
#include "frame_main.h"
#include "video_display.h"
#include "dialog_detached_video.h"
#include "dialog_video_details.h"
#include "video_slider.h"
#include "dialog_dummy_video.h"
#include "compat.h"
#include "dialog_jumpto.h"
namespace cmd {
/// @defgroup cmd-video Video commands.
/// @{
/// Forces video to 2.35 aspect ratio.
class video_aspect_cinematic: public Command {
public:
CMD_NAME("video/aspect/cinematic")
STR_MENU("&Cinematic (2.35)")
STR_DISP("Cinematic (235)")
STR_HELP("Forces video to 2.35 aspect ratio.")
void operator()(agi::Context *c) {
VideoContext::Get()->Stop();
VideoContext::Get()->SetAspectRatio(3);
wxGetApp().frame->SetDisplayMode(1,-1);
}
};
/// Forces video to a custom aspect ratio.
class video_aspect_custom: public Command {
public:
CMD_NAME("video/aspect/custom")
STR_MENU("Custom..")
STR_DISP("Custom")
STR_HELP("Forces video to a custom aspect ratio.")
void operator()(agi::Context *c) {
VideoContext::Get()->Stop();
wxString value = wxGetTextFromUser(_("Enter aspect ratio in either:\n decimal (e.g. 2.35)\n fractional (e.g. 16:9)\n specific resolution (e.g. 853x480)"),_("Enter aspect ratio"),AegiFloatToString(VideoContext::Get()->GetAspectRatioValue()));
if (value.IsEmpty()) return;
value.MakeLower();
// Process text
double numval;
if (value.ToDouble(&numval)) {
//Nothing to see here, move along
}
else {
double a,b;
int pos=0;
bool scale=false;
//Why bloat using Contains when we can just check the output of Find?
pos = value.Find(':');
if (pos==wxNOT_FOUND) pos = value.Find('/');
if (pos==wxNOT_FOUND&&value.Contains(_T('x'))) {
pos = value.Find('x');
scale=true;
}
if (pos>0) {
wxString num = value.Left(pos);
wxString denum = value.Mid(pos+1);
if (num.ToDouble(&a) && denum.ToDouble(&b) && b!=0) {
numval = a/b;
if (scale) c->videoBox->videoDisplay->SetZoom(b / VideoContext::Get()->GetHeight());
}
}
else numval = 0.0;
}
// Sanity check
if (numval < 0.5 || numval > 5.0) wxMessageBox(_("Invalid value! Aspect ratio must be between 0.5 and 5.0."),_("Invalid Aspect Ratio"),wxICON_ERROR|wxOK);
// Set value
else {
VideoContext::Get()->SetAspectRatio(4,numval);
wxGetApp().frame->SetDisplayMode(1,-1);
}
}
};
/// Leave video on original aspect ratio.
class video_aspect_default: public Command {
public:
CMD_NAME("video/aspect/default")
STR_MENU("&Default")
STR_DISP("Default")
STR_HELP("Leave video on original aspect ratio.")
void operator()(agi::Context *c) {
VideoContext::Get()->Stop();
VideoContext::Get()->SetAspectRatio(0);
wxGetApp().frame->SetDisplayMode(1,-1);
}
};
/// Forces video to 4:3 aspect ratio.
class video_aspect_full: public Command {
public:
CMD_NAME("video/aspect/full")
STR_MENU("&Fullscreen (4:3)")
STR_DISP("Fullscreen (4:3)")
STR_HELP("Forces video to 4:3 aspect ratio.")
void operator()(agi::Context *c) {
VideoContext::Get()->Stop();
VideoContext::Get()->SetAspectRatio(1);
wxGetApp().frame->SetDisplayMode(1,-1);
}
};
/// Forces video to 16:9 aspect ratio.
class video_aspect_wide: public Command {
public:
CMD_NAME("video/aspect/wide")
STR_MENU("&Widescreen (16:9)")
STR_DISP("Widescreen (16:9)")
STR_HELP("Forces video to 16:9 aspect ratio.")
void operator()(agi::Context *c) {
VideoContext::Get()->Stop();
VideoContext::Get()->SetAspectRatio(2);
wxGetApp().frame->SetDisplayMode(1,-1);
}
};
/// Closes the currently open video file.
class video_close: public Command {
public:
CMD_NAME("video/close")
STR_MENU("&Close Video")
STR_DISP("Close Video")
STR_HELP("Closes the currently open video file.")
void operator()(agi::Context *c) {
wxGetApp().frame->LoadVideo(_T(""));
}
};
/// Detach video, displaying it in a separate Window.
class video_detach: public Command {
public:
CMD_NAME("video/detach")
STR_MENU("Detach Video")
STR_DISP("Detach Video")
STR_HELP("Detach video, displaying it in a separate Window.")
void operator()(agi::Context *c) {
wxGetApp().frame->DetachVideo(!c->detachedVideo);
}
};
/// Shows video details.
class video_details: public Command {
public:
CMD_NAME("video/details")
STR_MENU("Show Video Details..")
STR_DISP("Show Video Details")
STR_HELP("Shows video details.")
void operator()(agi::Context *c) {
VideoContext::Get()->Stop();
DialogVideoDetails videodetails(c->parent);
videodetails.ShowModal();
}
};
///
class video_focus_seek: public Command {
public:
CMD_NAME("video/focus_seek")
STR_MENU("XXX: no idea")
STR_DISP("XXX: no idea")
STR_HELP("XXX: no idea")
void operator()(agi::Context *c) {
wxWindow *curFocus = wxWindow::FindFocus();
if (curFocus == c->videoBox->videoSlider) {
if (c->PreviousFocus) c->PreviousFocus->SetFocus();
}
else {
c->PreviousFocus = curFocus;
c->videoBox->videoSlider->SetFocus();
}
}
};
/// Seek to the next frame.
class video_frame_next: public Command {
public:
CMD_NAME("video/frame/next")
STR_MENU("Next Frame")
STR_DISP("Next Frame")
STR_HELP("Seek to the next frame.")
void operator()(agi::Context *c) {
c->videoBox->videoSlider->NextFrame();
}
};
/// Play video.
class video_frame_play: public Command {
public:
CMD_NAME("video/frame/play")
STR_MENU("Play")
STR_DISP("Play")
STR_HELP("Play video.")
void operator()(agi::Context *c) {
VideoContext::Get()->Play();
}
};
/// Seek to the previous frame.
class video_frame_prev: public Command {
public:
CMD_NAME("video/frame/prev")
STR_MENU("Previous Frame")
STR_DISP("Previous Frame")
STR_HELP("Seek to the previous frame.")
void operator()(agi::Context *c) {
c->videoBox->videoSlider->PrevFrame();
}
};
/// Jump to frame or time.
class video_jump: public Command {
public:
CMD_NAME("video/jump")
STR_MENU("&Jump to..")
STR_DISP("Jump to")
STR_HELP("Jump to frame or time.")
void operator()(agi::Context *c) {
VideoContext::Get()->Stop();
if (VideoContext::Get()->IsLoaded()) {
DialogJumpTo JumpTo(c->parent);
JumpTo.ShowModal();
c->videoBox->videoSlider->SetFocus();
}
}
};
/// Jumps the video to the end frame of current subtitle.
class video_jump_end: public Command {
public:
CMD_NAME("video/jump/end")
STR_MENU("Jump Video to End")
STR_DISP("Jump Video to End")
STR_HELP("Jumps the video to the end frame of current subtitle.")
void operator()(agi::Context *c) {
c->SubsGrid->SetVideoToSubs(false);
}
};
/// Jumps the video to the start frame of current subtitle.
class video_jump_start: public Command {
public:
CMD_NAME("video/jump/start")
STR_MENU("Jump Video to Start")
STR_DISP("Jump Video to Start")
STR_HELP("Jumps the video to the start frame of current subtitle.")
void operator()(agi::Context *c) {
c->SubsGrid->SetVideoToSubs(true);
}
};
/// Opens a video file.
class video_open: public Command {
public:
CMD_NAME("video/open")
STR_MENU("&Open Video..")
STR_DISP("Open Video")
STR_HELP("Opens a video file.")
void operator()(agi::Context *c) {
wxString path = lagi_wxString(OPT_GET("Path/Last/Video")->GetString());
wxString str = wxString(_("Video Formats")) + _T(" (*.avi,*.mkv,*.mp4,*.avs,*.d2v,*.ogm,*.mpeg,*.mpg,*.vob,*.mov)|*.avi;*.avs;*.d2v;*.mkv;*.ogm;*.mp4;*.mpeg;*.mpg;*.vob;*.mov|")
+ _("All Files") + _T(" (*.*)|*.*");
wxString filename = wxFileSelector(_("Open video file"),path,_T(""),_T(""),str,wxFD_OPEN | wxFD_FILE_MUST_EXIST);
if (!filename.empty()) {
wxGetApp().frame->LoadVideo(filename);
OPT_SET("Path/Last/Video")->SetString(STD_STR(filename));
}
}
};
/// Opens a video clip with solid colour.
class video_open_dummy: public Command {
public:
CMD_NAME("video/open/dummy")
STR_MENU("Use Dummy Video..")
STR_DISP("Use Dummy Video")
STR_HELP("Opens a video clip with solid colour.")
void operator()(agi::Context *c) {
wxString fn;
if (DialogDummyVideo::CreateDummyVideo(c->parent, fn)) {
wxGetApp().frame->LoadVideo(fn);
}
}
};
/// Show a mask over the video.
class video_show_overscan: public Command {
public:
CMD_NAME("video/show_overscan")
STR_MENU("Show Overscan Mask")
STR_DISP("Show Overscan Mask")
STR_HELP("Show a mask over the video, indicating areas that might get cropped off by overscan on televisions.")
void operator()(agi::Context *c) {
//XXX: Fix to not require using an event. (maybe)
// OPT_SET("Video/Overscan Mask")->SetBool(event.IsChecked());
VideoContext::Get()->Stop();
c->videoBox->videoDisplay->Render();
}
};
/// Set zoom to 100%.
class video_zoom_100: public Command {
public:
CMD_NAME("video/zoom/100")
STR_MENU("&100%")
STR_DISP("100%")
STR_HELP("Set zoom to 100%.")
void operator()(agi::Context *c) {
VideoContext::Get()->Stop();
c->videoBox->videoDisplay->SetZoom(1.);
}
};
/// Set zoom to 200%.
class video_zoom_200: public Command {
public:
CMD_NAME("video/zoom/200")
STR_MENU("&200%")
STR_DISP("200%")
STR_HELP("Set zoom to 200%.")
void operator()(agi::Context *c) {
VideoContext::Get()->Stop();
c->videoBox->videoDisplay->SetZoom(2.);
}
};
/// Set zoom to 50%.
class video_zoom_50: public Command {
public:
CMD_NAME("video/zoom/50")
STR_MENU("&50%")
STR_DISP("50%")
STR_HELP("Set zoom to 50%.")
void operator()(agi::Context *c) {
VideoContext::Get()->Stop();
c->videoBox->videoDisplay->SetZoom(.5);
}
};
/// Zoom video in.
class video_zoom_in: public Command {
public:
CMD_NAME("video/zoom/in")
STR_MENU("Zoom In")
STR_DISP("Zoom In")
STR_HELP("Zoom video in.")
void operator()(agi::Context *c) {
c->videoBox->videoDisplay->SetZoom(c->videoBox->videoDisplay->GetZoom() + .125);
}
};
/// Zoom video out.
class video_zoom_out: public Command {
public:
CMD_NAME("video/zoom/out")
STR_MENU("Zoom Out")
STR_DISP("Zoom Out")
STR_HELP("Zoom video out.")
void operator()(agi::Context *c) {
c->videoBox->videoDisplay->SetZoom(c->videoBox->videoDisplay->GetZoom() - .125);
}
};
/// @}
/// Init video/ commands.
void init_video(CommandManager *cm) {
cm->reg(new video_aspect_cinematic());
cm->reg(new video_aspect_custom());
cm->reg(new video_aspect_default());
cm->reg(new video_aspect_full());
cm->reg(new video_aspect_wide());
cm->reg(new video_close());
cm->reg(new video_detach());
cm->reg(new video_details());
cm->reg(new video_focus_seek());
cm->reg(new video_frame_next());
cm->reg(new video_frame_play());
cm->reg(new video_frame_prev());
cm->reg(new video_jump());
cm->reg(new video_jump_end());
cm->reg(new video_jump_start());
cm->reg(new video_open());
cm->reg(new video_open_dummy());
cm->reg(new video_show_overscan());
cm->reg(new video_zoom_100());
cm->reg(new video_zoom_200());
cm->reg(new video_zoom_50());
cm->reg(new video_zoom_in());
cm->reg(new video_zoom_out());
}
} // namespace cmd