diff --git a/aegisub/src/command/video.cpp b/aegisub/src/command/video.cpp index 2979f001e..8c0cda8fa 100644 --- a/aegisub/src/command/video.cpp +++ b/aegisub/src/command/video.cpp @@ -601,10 +601,9 @@ struct video_open_dummy : public Command { STR_HELP("Opens a video clip with solid color") void operator()(agi::Context *c) { - wxString fn; - if (DialogDummyVideo::CreateDummyVideo(c->parent, fn)) { + wxString fn = DialogDummyVideo::CreateDummyVideo(c->parent); + if (!fn.empty()) c->videoController->SetVideo(fn); - } } }; diff --git a/aegisub/src/dialog_dummy_video.cpp b/aegisub/src/dialog_dummy_video.cpp index b44a366a5..a1fe8dfcb 100644 --- a/aegisub/src/dialog_dummy_video.cpp +++ b/aegisub/src/dialog_dummy_video.cpp @@ -1,29 +1,16 @@ -// Copyright (c) 2007, Niels Martin Hansen -// All rights reserved. +// Copyright (c) 2012, Thomas Goyne // -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are met: +// Permission to use, copy, modify, and distribute this software for any +// purpose with or without fee is hereby granted, provided that the above +// copyright notice and this permission notice appear in all copies. // -// * 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. +// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. // // Aegisub Project http://www.aegisub.org/ @@ -32,37 +19,29 @@ /// @ingroup secondary_ui /// - #include "config.h" #include "dialog_dummy_video.h" -#include - #include #include -#include -#include #include #include #include #include #include #include +#include +#include +#include "ass_time.h" #include "colour_button.h" -#include "compat.h" #include "help_button.h" #include "libresrc/libresrc.h" #include "main.h" -#include "utils.h" #include "video_provider_dummy.h" -enum { - Dummy_Video_Resolution_Shortcut = 1700, - Dummy_Video_FPS, - Dummy_Video_Length -}; +namespace { struct ResolutionShortcut { const char *name; @@ -79,187 +58,120 @@ static ResolutionShortcut resolutions[] = { {"704x400 (SD widescreen MOD16)", 704, 400}, {"1280x720 (HD 720p)", 1280, 720}, {"1920x1080 (HD 1080p)", 1920, 1080}, - {"1024x576 (SuperPAL widescreen)", 1024, 576}, - {0, 0, 0} + {"1024x576 (SuperPAL widescreen)", 1024, 576} }; -bool DialogDummyVideo::CreateDummyVideo(wxWindow *parent, wxString &out_filename) -{ - DialogDummyVideo dlg(parent); - if (dlg.ShowModal() != wxID_OK) - return false; +wxSpinCtrl *spin_ctrl(wxWindow *parent, int min, int max, int *value) { + auto ctrl = new wxSpinCtrl(parent, -1, "", wxDefaultPosition, wxSize(50, -1), wxSP_ARROW_KEYS, min, max, *value); + ctrl->SetValidator(wxGenericValidator(value)); + return ctrl; +} - double fps; - long width, height, length; - agi::Color colour; - bool pattern; +wxControl *spin_ctrl(wxWindow *parent, double min, double max, double *value) { + wxFloatingPointValidator val(4, value); + val.SetRange(min, max); + return new wxTextCtrl(parent, -1, "", wxDefaultPosition, wxSize(50, -1), 0, val); +} - // Read back values and check sensibility - if (!dlg.fps->GetValue().ToDouble(&fps) || fps <= 0) { - wxLogWarning("Invalid framerate specified, assuming 23.976"); - fps = 24/1.001; - } - if (!dlg.width->GetValue().ToLong(&width) || width <= 0) { - wxLogWarning("Invalid width specified"); - width = 0; - } - if (!dlg.height->GetValue().ToLong(&height) || height <= 0) { - wxLogWarning("Invalid height specified"); - height = 0; - } - if (width == 0 && height == 0) { - wxLogWarning("Assuming 640x480"); - width = 640; height = 480; - } else if (width == 0) { - width = height * 4 / 3; - wxLogWarning("Assuming 4:3 fullscreen, %dx%d", width, height); - } else if (height == 0) { - height = width * 3 / 4; - wxLogWarning("Assuming 4:3 fullscreen, %dx%d", width, height); - } - if ((length = dlg.length->GetValue()) <= 0) { - wxLogWarning("Invalid duration, assuming 2 frames"); - length = 2; - } - colour = dlg.colour->GetColor(); - pattern = dlg.pattern->GetValue(); +wxComboBox *resolution_shortcuts(wxWindow *parent, int width, int height) { + wxComboBox *ctrl = new wxComboBox(parent, -1, "", wxDefaultPosition, wxDefaultSize, 0, 0, wxCB_READONLY); - // Write to options - OPT_SET("Video/Dummy/FPS")->SetDouble(fps); - OPT_SET("Video/Dummy/Last/Width")->SetInt(width); - OPT_SET("Video/Dummy/Last/Height")->SetInt(height); - OPT_SET("Video/Dummy/Last/Length")->SetInt(length); - OPT_SET("Colour/Video Dummy/Last Colour")->SetColor(colour); - OPT_SET("Video/Dummy/Pattern")->SetBool(pattern); + for (auto const& res : resolutions) { + ctrl->Append(res.name); + if (res.width == width && res.height == height) + ctrl->SetSelection(ctrl->GetCount() - 1); + } + + return ctrl; +} - out_filename = DummyVideoProvider::MakeFilename(fps, length, width, height, colour, pattern); - return true; } DialogDummyVideo::DialogDummyVideo(wxWindow *parent) -: wxDialog(parent, -1, _("Dummy video options"),wxDefaultPosition,wxDefaultSize) +: wxDialog(parent, -1, _("Dummy video options")) +, fps(OPT_GET("Video/Dummy/FPS")->GetDouble()) +, width(OPT_GET("Video/Dummy/Last/Width")->GetInt()) +, height(OPT_GET("Video/Dummy/Last/Height")->GetInt()) +, length(OPT_GET("Video/Dummy/Last/Length")->GetInt()) +, color(OPT_GET("Colour/Video Dummy/Last Colour")->GetColor()) +, pattern(OPT_GET("Video/Dummy/Pattern")->GetBool()) { SetIcon(GETICON(use_dummy_video_menu_16)); - // Main controls - length_display = 0; - resolution_shortcuts = new wxComboBox(this, Dummy_Video_Resolution_Shortcut, "", wxDefaultPosition, wxDefaultSize, 0, 0, wxCB_READONLY); - width = new wxTextCtrl(this, -1); - height = new wxTextCtrl(this, -1); - colour = new ColourButton(this, -1, wxSize(30, 17), OPT_GET("Colour/Video Dummy/Last Colour")->GetColor()); - pattern = new wxCheckBox(this, -1, _("Checkerboard &pattern")); - fps = new wxTextCtrl(this, Dummy_Video_FPS, wxString::Format("%f", OPT_GET("Video/Dummy/FPS")->GetDouble())); - length = new wxSpinCtrl(this, Dummy_Video_Length, "", wxDefaultPosition, wxDefaultSize, 4096|wxALIGN_LEFT); - length_display = new wxStaticText(this, -1, ""); - - // Support controls and layout - wxFlexGridSizer *fg = new wxFlexGridSizer(2, 5, 5); - fg->Add(new wxStaticText(this, -1, _("Video resolution:")), 0, wxALIGN_CENTRE_VERTICAL); - fg->Add(resolution_shortcuts, 0, wxEXPAND); - fg->AddStretchSpacer(); wxBoxSizer *res_sizer = new wxBoxSizer(wxHORIZONTAL); - res_sizer->Add(width, 0, wxEXPAND); - res_sizer->Add(new wxStaticText(this, -1, " x "), 0, wxALIGN_CENTRE_VERTICAL|wxFIXED_MINSIZE); - res_sizer->Add(height, 0, wxEXPAND); - fg->Add(res_sizer, 0, wxEXPAND); - fg->Add(new wxStaticText(this, -1, _("Color:")), 0, wxALIGN_CENTRE_VERTICAL); - fg->Add(colour, 0, wxALIGN_LEFT|wxALIGN_CENTRE_VERTICAL); - fg->AddStretchSpacer(); - fg->Add(pattern, 0, wxALIGN_LEFT|wxALIGN_CENTRE_VERTICAL); - fg->Add(new wxStaticText(this, -1, _("Frame rate (fps):")), 0, wxALIGN_CENTRE_VERTICAL); - fg->Add(fps, 0, wxEXPAND); - fg->Add(new wxStaticText(this, -1, _("Duration (frames):")), 0, wxALIGN_CENTRE_VERTICAL); - fg->Add(length, 0, wxEXPAND); - fg->AddStretchSpacer(); - fg->Add(length_display, 0, wxEXPAND|wxALIGN_CENTRE_VERTICAL|wxALIGN_LEFT); + res_sizer->Add(spin_ctrl(this, 1, 10000, &width), wxSizerFlags(1).Expand()); + res_sizer->Add(new wxStaticText(this, -1, " x "), wxSizerFlags().Center()); + res_sizer->Add(spin_ctrl(this, 1, 10000, &height), wxSizerFlags(1).Expand()); + + wxBoxSizer *color_sizer = new wxBoxSizer(wxHORIZONTAL); + ColourButton *color_btn = new ColourButton(this, -1, wxSize(30, 17), color); + color_sizer->Add(color_btn, wxSizerFlags().DoubleBorder(wxRIGHT)); + color_sizer->Add(new wxCheckBox(this, -1, _("Checkerboard &pattern"), wxDefaultPosition, wxDefaultSize, 0, wxGenericValidator(&pattern)), wxSizerFlags(1).Center()); + + sizer = new wxFlexGridSizer(2, 5, 5); + AddCtrl(_("Video resolution:"), resolution_shortcuts(this, width, height)); + AddCtrl("", res_sizer); + AddCtrl(_("Color:"), color_sizer); + AddCtrl(_("Frame rate (fps):"), spin_ctrl(this, .1, 1000.0, &fps)); + AddCtrl(_("Duration (frames):"), spin_ctrl(this, 2, 36000000, &length)); // Ten hours of 1k FPS + AddCtrl("", length_display = new wxStaticText(this, -1, "")); + + wxStdDialogButtonSizer *btn_sizer = CreateStdDialogButtonSizer(wxOK | wxCANCEL | wxHELP); + btn_sizer->GetHelpButton()->Bind(wxEVT_COMMAND_BUTTON_CLICKED, std::bind(&HelpButton::OpenPage, "Dummy Video")); + wxBoxSizer *main_sizer = new wxBoxSizer(wxVERTICAL); - main_sizer->Add(fg, 1, wxALL|wxEXPAND, 5); + main_sizer->Add(sizer, wxSizerFlags(1).Border().Expand()); + main_sizer->Add(new wxStaticLine(this, wxHORIZONTAL), wxSizerFlags().HorzBorder().Expand()); + main_sizer->Add(btn_sizer, wxSizerFlags().Expand().Border()); - wxStdDialogButtonSizer *btnSizer = CreateStdDialogButtonSizer(wxOK | wxCANCEL | wxHELP); - ok_button = btnSizer->GetAffirmativeButton(); - btnSizer->GetHelpButton()->Bind(wxEVT_COMMAND_BUTTON_CLICKED, std::bind(&HelpButton::OpenPage, "Dummy Video")); - - main_sizer->Add(new wxStaticLine(this,wxHORIZONTAL),0,wxALL|wxEXPAND,5); - main_sizer->Add(btnSizer,0,wxLEFT|wxRIGHT|wxBOTTOM|wxEXPAND,5); - - // Initialise controls - int lastwidth, lastheight, lastres = 0; - lastwidth = OPT_GET("Video/Dummy/Last/Width")->GetInt(); - lastheight = OPT_GET("Video/Dummy/Last/Height")->GetInt(); - for (ResolutionShortcut *res = resolutions; res->name; ++res) { - resolution_shortcuts->Append(res->name); - if (res->width == lastwidth && res->height == lastheight) - resolution_shortcuts->SetSelection(lastres); - lastres++; - } - pattern->SetValue(OPT_GET("Video/Dummy/Pattern")->GetBool()); - width->ChangeValue(AegiIntegerToString(OPT_GET("Video/Dummy/Last/Width")->GetInt())); - height->ChangeValue(AegiIntegerToString(OPT_GET("Video/Dummy/Last/Height")->GetInt())); - length->SetRange(0, 0x10000000); - length->SetValue(OPT_GET("Video/Dummy/Last/Length")->GetInt()); UpdateLengthDisplay(); - // Layout SetSizerAndFit(main_sizer); CenterOnParent(); + + Bind(wxEVT_COMMAND_COMBOBOX_SELECTED, &DialogDummyVideo::OnResolutionShortcut, this); + color_btn->Bind(wxEVT_COMMAND_BUTTON_CLICKED, [=](wxCommandEvent& e) { + color = color_btn->GetColor(); + e.Skip(); + }); + Bind(wxEVT_COMMAND_SPINCTRL_UPDATED, [=](wxCommandEvent&) { + TransferDataFromWindow(); + UpdateLengthDisplay(); + }); } -DialogDummyVideo::~DialogDummyVideo() -{ +template +void DialogDummyVideo::AddCtrl(wxString const& label, T *ctrl) { + if (!label) + sizer->AddStretchSpacer(); + else + sizer->Add(new wxStaticText(this, -1, label), wxSizerFlags().Center().Left()); + sizer->Add(ctrl, wxSizerFlags().Expand().Center().Left()); } -BEGIN_EVENT_TABLE(DialogDummyVideo,wxDialog) - EVT_COMBOBOX(Dummy_Video_Resolution_Shortcut, DialogDummyVideo::OnResolutionShortcut) - EVT_TEXT(Dummy_Video_FPS, DialogDummyVideo::OnFpsChange) - EVT_SPINCTRL(Dummy_Video_Length, DialogDummyVideo::OnLengthSpin) - EVT_TEXT(Dummy_Video_Length, DialogDummyVideo::OnLengthChange) -END_EVENT_TABLE() - -void DialogDummyVideo::OnResolutionShortcut(wxCommandEvent &) -{ - int rs = resolution_shortcuts->GetSelection(); - width->ChangeValue(wxString::Format("%d", resolutions[rs].width)); - height->ChangeValue(wxString::Format("%d", resolutions[rs].height)); +void DialogDummyVideo::OnResolutionShortcut(wxCommandEvent &e) { + TransferDataFromWindow(); + int rs = e.GetSelection(); + width = resolutions[rs].width; + height = resolutions[rs].height; + TransferDataToWindow(); } -void DialogDummyVideo::OnFpsChange(wxCommandEvent &) -{ - UpdateLengthDisplay(); +void DialogDummyVideo::UpdateLengthDisplay() { + length_display->SetLabel(wxString::Format(_("Resulting duration: %s"), AssTime(length / fps * 1000).GetAssFormated(true))); } -void DialogDummyVideo::OnLengthSpin(wxSpinEvent &) -{ - UpdateLengthDisplay(); -} +wxString DialogDummyVideo::CreateDummyVideo(wxWindow *parent) { + DialogDummyVideo dlg(parent); + if (dlg.ShowModal() != wxID_OK) + return ""; -void DialogDummyVideo::OnLengthChange(wxCommandEvent &) -{ - UpdateLengthDisplay(); -} + OPT_SET("Video/Dummy/FPS")->SetDouble(dlg.fps); + OPT_SET("Video/Dummy/Last/Width")->SetInt(dlg.width); + OPT_SET("Video/Dummy/Last/Height")->SetInt(dlg.height); + OPT_SET("Video/Dummy/Last/Length")->SetInt(dlg.length); + OPT_SET("Colour/Video Dummy/Last Colour")->SetColor(dlg.color); + OPT_SET("Video/Dummy/Pattern")->SetBool(dlg.pattern); -void DialogDummyVideo::UpdateLengthDisplay() -{ - double fpsval; - if (!length_display) return; - bool valid = false; - if (fps->GetValue().ToDouble(&fpsval)) { - int lengthval = length->GetValue(); - if (lengthval && fpsval > 0 && lengthval > 0) { - valid = true; - int tt = int(lengthval / fpsval * 1000); // frames / (frames/seconds) * 1000 = milliseconds - // 32 bit signed int can hold almost 600 positive hours when counting milliseconds, ASS allows at most just below 10 hours, so we're safe - int ms, s, m, h; - ms = tt % 1000; tt /= 1000; - s = tt % 60; tt /= 60; - m = tt % 60; tt /= 60; - h = tt; - length_display->SetLabel(wxString::Format(_("Resulting duration: %d:%02d:%02d.%03d"), h, m, s, ms)); - ok_button->Enable(); - } - } - - if (!valid) { - length_display->SetLabel(_("Invalid fps or length value")); - ok_button->Disable(); - } + return DummyVideoProvider::MakeFilename(dlg.fps, dlg.length, dlg.width, dlg.height, dlg.color, dlg.pattern); } diff --git a/aegisub/src/dialog_dummy_video.h b/aegisub/src/dialog_dummy_video.h index 2b8b05066..4a06d1bd4 100644 --- a/aegisub/src/dialog_dummy_video.h +++ b/aegisub/src/dialog_dummy_video.h @@ -1,29 +1,16 @@ -// Copyright (c) 2007, Niels Martin Hansen -// All rights reserved. +// Copyright (c) 2012, Thomas Goyne // -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are met: +// Permission to use, copy, modify, and distribute this software for any +// purpose with or without fee is hereby granted, provided that the above +// copyright notice and this permission notice appear in all copies. // -// * 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. +// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. // // Aegisub Project http://www.aegisub.org/ @@ -34,37 +21,30 @@ #include -class ColourButton; -class wxButton; -class wxCheckBox; -class wxComboBox; -class wxSpinCtrl; +#include + +class wxFlexGridSizer; class wxStaticText; -class wxTextCtrl; class DialogDummyVideo : public wxDialog { DialogDummyVideo(wxWindow *parent); - ~DialogDummyVideo(); - wxComboBox *resolution_shortcuts; - wxTextCtrl *width; - wxTextCtrl *height; - ColourButton *colour; - wxCheckBox *pattern; - wxTextCtrl *fps; - wxSpinCtrl *length; + double fps; + int width; + int height; + int length; + agi::Color color; + bool pattern; + wxStaticText *length_display; - wxButton *ok_button; + wxFlexGridSizer *sizer; + + template + void AddCtrl(wxString const& label, T *ctrl); void OnResolutionShortcut(wxCommandEvent &evt); - void OnFpsChange(wxCommandEvent &evt); - void OnLengthSpin(wxSpinEvent &evt); - void OnLengthChange(wxCommandEvent &evt); - void UpdateLengthDisplay(); public: - static bool CreateDummyVideo(wxWindow *parent, wxString &out_filename); - - DECLARE_EVENT_TABLE() + static wxString CreateDummyVideo(wxWindow *parent); };