From c9ce15bb016b3f718b6be4f1252786948815f04a Mon Sep 17 00:00:00 2001 From: Niels Martin Hansen Date: Mon, 2 Apr 2007 18:28:09 +0000 Subject: [PATCH] GUI for dummy video provider Originally committed to SVN as r977. --- aegisub/Makefile.am | 1 + aegisub/dialog_dummy_video.cpp | 240 +++++++++++++++++++++++++++++++ aegisub/dialog_dummy_video.h | 83 +++++++++++ aegisub/dialog_options.cpp | 10 +- aegisub/frame_main.cpp | 1 + aegisub/frame_main.h | 2 + aegisub/frame_main_events.cpp | 12 ++ aegisub/main.cpp | 2 + aegisub/options.cpp | 7 + aegisub/video_provider.cpp | 6 + aegisub/video_provider_dummy.cpp | 124 +++++++++++----- aegisub/video_provider_dummy.h | 79 ++++++++++ 12 files changed, 528 insertions(+), 39 deletions(-) create mode 100644 aegisub/dialog_dummy_video.cpp create mode 100644 aegisub/dialog_dummy_video.h create mode 100644 aegisub/video_provider_dummy.h diff --git a/aegisub/Makefile.am b/aegisub/Makefile.am index 4ef794c2a..04d0ed893 100644 --- a/aegisub/Makefile.am +++ b/aegisub/Makefile.am @@ -54,6 +54,7 @@ aegisub_SOURCES = \ dialog_automation.cpp \ dialog_colorpicker.cpp \ dialog_detached_video.cpp \ + dialog_dummy_video.cpp \ dialog_export.cpp \ dialog_fextracker.cpp \ dialog_fonts_collector.cpp \ diff --git a/aegisub/dialog_dummy_video.cpp b/aegisub/dialog_dummy_video.cpp new file mode 100644 index 000000000..a83da64d7 --- /dev/null +++ b/aegisub/dialog_dummy_video.cpp @@ -0,0 +1,240 @@ +// Copyright (c) 2007, Niels Martin Hansen +// 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 +// +// Website: http://aegisub.cellosoft.com +// Contact: mailto:jiifurusu@gmail.com +// + + +#include "dialog_dummy_video.h" +#include +#include +#include "options.h" + + +struct ResolutionShortcut { + const wxChar *name; + int width; + int height; +}; +static ResolutionShortcut resolutions[] = { + {_T("640x480 (SD fullscreen)"), 640, 480}, + {_T("704x480 (SD anamorphic)"), 704, 480}, + {_T("640x360 (SD widescreen)"), 640, 360}, + {_T("704x396 (SD widescreen)"), 640, 396}, + {_T("640x352 (SD widescreen MOD16)"), 640, 352}, + {_T("704x400 (SD widescreen MOD16)"), 704, 400}, + {_T("1280x720 (HD 720p)"), 1280, 720}, + {_T("1920x1080 (HD 1080p)"), 1920, 1080}, + {_T("1024x576 (SuperPAL widescreen)"), 1024, 576}, + {0, 0, 0} +}; + + +bool DialogDummyVideo::CreateDummyVideo(wxWindow *parent, wxString &out_filename) +{ + DialogDummyVideo dlg(parent); + if (dlg.ShowModal() == wxID_OK) { + double fps; + long width, height, length; + wxColour colour; + + // Read back values and check sensibility + if (!dlg.fps->GetValue().ToDouble(&fps) || fps <= 0) { + wxLogWarning(_T("Invalid framerate specified, assuming 23.976")); + fps = 24/1.001; + } + if (!dlg.width->GetValue().ToLong(&width) || width <= 0) { + wxLogWarning(_T("Invalid width specified")); + width = 0; + } + if (!dlg.height->GetValue().ToLong(&height) || height <= 0) { + wxLogWarning(_T("Invalid height specified")); + height = 0; + } + if (width == 0 && height == 0) { + wxLogWarning(_T("Assuming 640x480")); + width = 640; height = 480; + } else if (width == 0) { + width = height * 4 / 3; + wxLogWarning(_T("Assuming 4:3 fullscreen, %dx%d"), width, height); + } else if (height == 0) { + height = width * 3 / 4; + wxLogWarning(_T("Assuming 4:3 fullscreen, %dx%d"), width, height); + } + if ((length = dlg.length->GetValue()) <= 0) { + wxLogWarning(_T("Invalid duration, assuming 2 frames")); + length = 2; + } + colour = dlg.colour->GetColour(); + + // Write to options + Options.SetFloat(_T("Video Dummy Last FPS"), fps); + Options.SetInt(_T("Video Dummy Last Width"), width); + Options.SetInt(_T("Video Dummy Last Height"), height); + Options.SetInt(_T("Video Dummy Last Length"), length); + Options.SetColour(_T("Video Dummy Last Colour"), colour); + + out_filename = DummyVideoProvider::MakeFilename(fps, length, width, height, colour); + return true; + } else { + return false; + } +} + + +DialogDummyVideo::DialogDummyVideo(wxWindow *parent) +: wxDialog(parent, -1, _("Dummy video options")) +{ + // Main controls + length_display = 0; + resolution_shortcuts = new wxComboBox(this, Dummy_Video_Resolution_Shortcut, _T(""), wxDefaultPosition, wxDefaultSize, 0, 0, wxCB_READONLY); + width = new wxTextCtrl(this, -1); + height = new wxTextCtrl(this, -1); + colour = new ColourButton(this, -1, wxSize(30, 17), Options.AsColour(_T("Video Dummy Last Colour"))); + //fps = new wxComboBox(this, Dummy_Video_FPS, Options.AsText(_T("Video Dummy Last FPS")), wxDefaultPosition, wxDefaultSize, 0, 0, wxCB_DROPDOWN); + fps = new wxTextCtrl(this, Dummy_Video_FPS, Options.AsText(_T("Video Dummy Last FPS"))); + length = new wxSpinCtrl(this, Dummy_Video_Length); + length_display = new wxStaticText(this, -1, _T("")); + + // 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, 1, wxEXPAND); + fg->AddStretchSpacer(); + wxBoxSizer *res_sizer = new wxBoxSizer(wxHORIZONTAL); + res_sizer->Add(width, 1, wxEXPAND); + res_sizer->Add(new wxStaticText(this, -1, _T(" x ")), 0, wxALIGN_CENTRE_VERTICAL|wxFIXED_MINSIZE); + res_sizer->Add(height, 1, wxEXPAND); + fg->Add(res_sizer, 1, wxEXPAND); + fg->Add(new wxStaticText(this, -1, _("Colour:")), 0, wxALIGN_CENTRE_VERTICAL); + fg->Add(colour, 1, wxFIXED_MINSIZE|wxALIGN_LEFT|wxALIGN_CENTRE_VERTICAL); + fg->Add(new wxStaticText(this, -1, _("Frame rate (fps):")), 0, wxALIGN_CENTRE_VERTICAL); + fg->Add(fps, 1, wxEXPAND); + fg->Add(new wxStaticText(this, -1, _("Duration (frames):")), 0, wxALIGN_CENTRE_VERTICAL); + fg->Add(length, 1, wxEXPAND); + fg->AddStretchSpacer(); + fg->Add(length_display, 1, wxEXPAND|wxALIGN_CENTRE_VERTICAL|wxALIGN_LEFT); + wxStdDialogButtonSizer *buttons = new wxStdDialogButtonSizer(); + buttons->Add(ok_button = new wxButton(this, wxID_OK)); + buttons->Add(cancel_button = new wxButton(this, wxID_CANCEL)); + buttons->Realize(); + wxBoxSizer *main_sizer = new wxBoxSizer(wxVERTICAL); + main_sizer->Add(fg, 1, wxALL, 5); + main_sizer->Add(buttons, 0, wxLEFT|wxRIGHT|wxBOTTOM, 5); + + // Layout + main_sizer->SetSizeHints(this); + SetSizer(main_sizer); + CenterOnParent(); + + // Initialise controls + int lastwidth, lastheight, lastres = 0; + lastwidth = Options.AsInt(_T("Video Dummy Last Width")); + lastheight = Options.AsInt(_T("Video Dummy Last Height")); + for (ResolutionShortcut *res = resolutions; res->name; ++res) { + resolution_shortcuts->Append(res->name); + if (res->width == lastwidth && res->height == lastheight) + resolution_shortcuts->SetSelection(lastres); + lastres++; + } + /*fps->Append(_T("23.976")); + fps->Append(_T("29.97")); + fps->Append(_T("24")); + fps->Append(_T("25")); + fps->Append(_T("30"));*/ + width->ChangeValue(Options.AsText(_T("Video Dummy Last Width"))); + height->ChangeValue(Options.AsText(_T("Video Dummy Last Height"))); + length->SetRange(0, 0x10000000); + length->SetValue(Options.AsInt(_T("Video Dummy Last Length"))); + UpdateLengthDisplay(); +} + + +DialogDummyVideo::~DialogDummyVideo() +{ +} + + +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 &evt) +{ + int rs = resolution_shortcuts->GetSelection(); + width->ChangeValue(wxString::Format(_T("%d"), resolutions[rs].width)); + height->ChangeValue(wxString::Format(_T("%d"), resolutions[rs].height)); +} + + +void DialogDummyVideo::OnFpsChange(wxCommandEvent &evt) +{ + UpdateLengthDisplay(); +} + + +void DialogDummyVideo::OnLengthSpin(wxSpinEvent &evt) +{ + UpdateLengthDisplay(); +} + + +void DialogDummyVideo::OnLengthChange(wxCommandEvent &evt) +{ + UpdateLengthDisplay(); +} + + +void DialogDummyVideo::UpdateLengthDisplay() +{ + double fpsval; + int lengthval; + if (!length_display) return; + if ((fps->GetValue().ToDouble(&fpsval)) && (lengthval = length->GetValue()) && fpsval > 0 && lengthval > 0) { + int tt = 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(); + } else { + length_display->SetLabel(_("Invalid fps or length value")); + ok_button->Disable(); + } +} diff --git a/aegisub/dialog_dummy_video.h b/aegisub/dialog_dummy_video.h new file mode 100644 index 000000000..7de87de0d --- /dev/null +++ b/aegisub/dialog_dummy_video.h @@ -0,0 +1,83 @@ +// Copyright (c) 2007, Niels Martin Hansen +// 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 +// +// Website: http://aegisub.cellosoft.com +// Contact: mailto:jiifurusu@gmail.com +// + +#ifndef _DIALOG_DUMMY_VIDEO_H +#define _DIALOG_DUMMY_VIDEO_H + +#include +#include +#include +#include +#include +#include "video_provider_dummy.h" +#include "colour_button.h" + +class DialogDummyVideo : public wxDialog { +private: + DialogDummyVideo(wxWindow *parent); + virtual ~DialogDummyVideo(); + + wxComboBox *resolution_shortcuts; + wxTextCtrl *width; + wxTextCtrl *height; + ColourButton *colour; + //wxComboBox *fps; + wxTextCtrl *fps; + wxSpinCtrl *length; + wxStaticText *length_display; + wxButton *ok_button; + wxButton *cancel_button; + + 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() +}; + +enum { + Dummy_Video_Resolution_Shortcut = 1700, + Dummy_Video_FPS, + Dummy_Video_Length, +}; + + +#endif \ No newline at end of file diff --git a/aegisub/dialog_options.cpp b/aegisub/dialog_options.cpp index d7fe367b2..bbdcfb575 100644 --- a/aegisub/dialog_options.cpp +++ b/aegisub/dialog_options.cpp @@ -579,11 +579,11 @@ DialogOptions::DialogOptions(wxWindow *parent) #endif // Buttons Sizer - wxSizer *buttonSizer = new wxBoxSizer(wxHORIZONTAL); - buttonSizer->AddStretchSpacer(1); - buttonSizer->Add(new wxButton(this,wxID_OK),0,wxRIGHT,5); - buttonSizer->Add(new wxButton(this,wxID_CANCEL),0,wxRIGHT,5); - buttonSizer->Add(new wxButton(this,wxID_APPLY),0,wxRIGHT,5); + wxStdDialogButtonSizer *buttonSizer = new wxStdDialogButtonSizer(); + buttonSizer->Add(new wxButton(this,wxID_OK)); + buttonSizer->Add(new wxButton(this,wxID_CANCEL)); + buttonSizer->Add(new wxButton(this,wxID_APPLY)); + buttonSizer->Realize(); // Main Sizer wxSizer *mainSizer = new wxBoxSizer(wxVERTICAL); diff --git a/aegisub/frame_main.cpp b/aegisub/frame_main.cpp index 6de86022d..21e33db58 100644 --- a/aegisub/frame_main.cpp +++ b/aegisub/frame_main.cpp @@ -353,6 +353,7 @@ void FrameMain::InitMenu() { videoMenu->Append(Menu_File_Close_Video, _("&Close Video"), _("Closes the currently open video file")); wxMenuItem *RecentVidParent = new wxMenuItem(videoMenu, Menu_File_Recent_Vids_Parent, _("Recent"), _T(""), wxITEM_NORMAL, RecentVids); videoMenu->Append(RecentVidParent); + videoMenu->Append(Menu_Video_Dummy, _("Use dummy video..."), _("Opens a video clip with solid colour")); videoMenu->AppendSeparator(); videoMenu->Append(Menu_File_Open_VFR, _("Open timecodes file..."), _("Opens a VFR timecodes v1 or v2 file")); videoMenu->Append(Menu_File_Close_VFR, _("Close timecodes file"), _("Closes the currently open timecodes file"))->Enable(false); diff --git a/aegisub/frame_main.h b/aegisub/frame_main.h index 0929871d7..bfb99e843 100644 --- a/aegisub/frame_main.h +++ b/aegisub/frame_main.h @@ -159,6 +159,7 @@ private: void OnSetAR235 (wxCommandEvent &event); void OnSetARCustom (wxCommandEvent &event); void OnDetachVideo (wxCommandEvent &event); + void OnDummyVideo (wxCommandEvent &event); void OnOpenAudio (wxCommandEvent &event); void OnOpenAudioFromVideo (wxCommandEvent &event); @@ -317,6 +318,7 @@ enum { Menu_Video_Select_Visible, Menu_Video_Play, Menu_Video_Detach, + Menu_Video_Dummy, Menu_Audio_Open_File, Menu_Audio_Open_From_Video, diff --git a/aegisub/frame_main_events.cpp b/aegisub/frame_main_events.cpp index 70595a636..161f7b2c3 100644 --- a/aegisub/frame_main_events.cpp +++ b/aegisub/frame_main_events.cpp @@ -86,6 +86,7 @@ #include "dialog_automation.h" #include "dialog_version_check.h" #include "dialog_detached_video.h" +#include "dialog_dummy_video.h" //////////////////// @@ -138,6 +139,7 @@ BEGIN_EVENT_TABLE(FrameMain, wxFrame) EVT_MENU(Menu_Video_JumpTo, FrameMain::OnJumpTo) EVT_MENU(Menu_Video_Select_Visible, FrameMain::OnSelectVisible) EVT_MENU(Menu_Video_Detach, FrameMain::OnDetachVideo) + EVT_MENU(Menu_Video_Dummy, FrameMain::OnDummyVideo) EVT_MENU(Menu_Audio_Open_File, FrameMain::OnOpenAudio) EVT_MENU(Menu_Audio_Open_From_Video, FrameMain::OnOpenAudioFromVideo) @@ -867,6 +869,16 @@ void FrameMain::OnDetachVideo(wxCommandEvent &event) { } +/////////////////// +// Use dummy video +void FrameMain::OnDummyVideo (wxCommandEvent &event) { + wxString fn; + if (DialogDummyVideo::CreateDummyVideo(this, fn)) { + LoadVideo(fn); + } +} + + /////////////////////// // Open jump to dialog void FrameMain::OnJumpTo(wxCommandEvent& WXUNUSED(event)) { diff --git a/aegisub/main.cpp b/aegisub/main.cpp index a422b3970..8e87ec04e 100644 --- a/aegisub/main.cpp +++ b/aegisub/main.cpp @@ -110,7 +110,9 @@ bool AegisubApp::OnInit() { AssExportFilterChain::PrepareFilters(); // Set association +#ifndef DEBUG RegistryAssociate(); +#endif // Get parameter subs wxArrayString subs; diff --git a/aegisub/options.cpp b/aegisub/options.cpp index 2d26ce405..47212c2cd 100644 --- a/aegisub/options.cpp +++ b/aegisub/options.cpp @@ -139,6 +139,13 @@ void OptionsManager::LoadDefaults() { SetModificationType(MOD_VIDEO); SetBool(_T("Show keyframes on video slider"),true); + // Dummy video defaults + SetInt(_T("Video Dummy Last Width"), 640); + SetInt(_T("Video Dummy Last Height"), 480); + SetColour(_T("Video Dummy Last Colour"), wxColour(47, 163, 254)); + SetFloat(_T("Video Dummy Last FPS"), 23.976); + SetInt(_T("Video Dummy Last Length"), 40000); + // Video Provider (Advanced) SetModificationType(MOD_RESTART); SetBool(_T("Threaded Video"),false); diff --git a/aegisub/video_provider.cpp b/aegisub/video_provider.cpp index c834d7c94..3a7d8fc6c 100644 --- a/aegisub/video_provider.cpp +++ b/aegisub/video_provider.cpp @@ -37,6 +37,7 @@ /////////// // Headers #include "video_provider.h" +#include "video_provider_dummy.h" #include "options.h" #include "setup.h" #include "vfr.h" @@ -129,6 +130,11 @@ void VideoProvider::ClearCache() { //////////////// // Get provider VideoProvider *VideoProviderFactory::GetProvider(wxString video,double fps) { + // First check special case of dummy video + if (video.StartsWith(_T("?dummy:"))) { + return new DummyVideoProvider(video, fps); + } + // List of providers wxArrayString list = GetFactoryList(Options.AsText(_T("Video provider"))); diff --git a/aegisub/video_provider_dummy.cpp b/aegisub/video_provider_dummy.cpp index d841d9c68..9dd755dc8 100644 --- a/aegisub/video_provider_dummy.cpp +++ b/aegisub/video_provider_dummy.cpp @@ -36,63 +36,119 @@ /////////// // Headers -#include "video_provider.h" - - -//////////////////////// -// Dummy video provider -class DummyVideoProvider : public VideoProvider { -private: - int lastFrame; - AegiVideoFrame frame; - -protected: - const AegiVideoFrame DoGetFrame(int n); - -public: - DummyVideoProvider(wxString filename, double fps); - ~DummyVideoProvider(); - - int GetPosition(); - int GetFrameCount(); - - int GetWidth(); - int GetHeight(); - double GetFPS(); -}; +#include "video_provider_dummy.h" +#include /////////// // Factory -class DummyVideoProviderFactory : public VideoProviderFactory { +// Shouldn't be needed +/*class DummyVideoProviderFactory : public VideoProviderFactory { public: VideoProvider *CreateProvider(wxString video,double fps=0.0) { return new DummyVideoProvider(video,fps); } DummyVideoProviderFactory() : VideoProviderFactory(_T("dummy")) {} -} registerDummyVideo; +} registerDummyVideo; */ /////////////// // Constructor -DummyVideoProvider::DummyVideoProvider(wxString filename, double fps) { +void DummyVideoProvider::Create(double _fps, int frames, int _width, int _height, const wxColour &colour) { lastFrame = -1; + framecount = frames; + fps = _fps; + width = _width; + height = _height; frame = AegiVideoFrame(640,480,FORMAT_RGB32); unsigned char *dst = frame.data[0]; + unsigned char r = colour.Red(), g = colour.Green(), b = colour.Blue(); for (int i=frame.pitch[0]*frame.h/frame.GetBpp();--i>=0;) { - *dst++ = 254; - *dst++ = 163; - *dst++ = 47; + *dst++ = b; + *dst++ = g; + *dst++ = r; *dst++ = 0; } } +/////////////////////// +// Parsing constructor +DummyVideoProvider::DummyVideoProvider(wxString filename, double _fps) +{ + wxString params; + if (!filename.StartsWith(_T("?dummy:"), ¶ms)) { + throw _T("Attempted creating dummy video provider with non-dummy filename"); + } + + wxStringTokenizer t(params, _T(":")); + if (t.CountTokens() < 7) { + throw _T("Too few fields in dummy video parameter list"); + } + + double parsedfps; + long _frames, _width, _height, red, green, blue; + + wxString field = t.GetNextToken(); + if (!field.ToDouble(&parsedfps)) { + throw _T("Unable to parse fps field in dummy video parameter list"); + } + if (_fps == 0.0) + _fps = parsedfps; + + field = t.GetNextToken(); + if (!field.ToLong(&_frames)) { + throw _T("Unable to parse framecount field in dummy video parameter list"); + } + + field = t.GetNextToken(); + if (!field.ToLong(&_width)) { + throw _T("Unable to parse width field in dummy video parameter list"); + } + + field = t.GetNextToken(); + if (!field.ToLong(&_height)) { + throw _T("Unable to parse height field in dummy video parameter list"); + } + + field = t.GetNextToken(); + if (!field.ToLong(&red)) { + throw _T("Unable to parse red colour field in dummy video parameter list"); + } + + field = t.GetNextToken(); + if (!field.ToLong(&green)) { + throw _T("Unable to parse green colour field in dummy video parameter list"); + } + + field = t.GetNextToken(); + if (!field.ToLong(&blue)) { + throw _T("Unable to parse bluecolour field in dummy video parameter list"); + } + + Create(_fps, _frames, _width, _height, wxColour(red, green, blue)); +} + + +////////////////////// +// Direct constructor +DummyVideoProvider::DummyVideoProvider(double _fps, int frames, int _width, int _height, const wxColour &colour) { + Create(_fps, frames, _width, _height, colour); +} + + ////////////// // Destructor DummyVideoProvider::~DummyVideoProvider() { } +////////////////////////////////////////////////// +// Construct a fake filename describing the video +wxString DummyVideoProvider::MakeFilename(double fps, int frames, int _width, int _height, const wxColour &colour) { + return wxString::Format(_T("?dummy:%f:%d:%d:%d:%d:%d:%d"), fps, frames, _width, _height, colour.Red(), colour.Green(), colour.Blue()); +} + + ///////////// // Get frame const AegiVideoFrame DummyVideoProvider::DoGetFrame(int n) { @@ -111,26 +167,26 @@ int DummyVideoProvider::GetPosition() { /////////////////// // Get frame count int DummyVideoProvider::GetFrameCount() { - return 40000; + return framecount; } ///////////// // Get width int DummyVideoProvider::GetWidth() { - return 640; + return width; } ////////////// // Get height int DummyVideoProvider::GetHeight() { - return 480; + return height; } /////////// // Get FPS double DummyVideoProvider::GetFPS() { - return 24.0/1.001; + return fps; } diff --git a/aegisub/video_provider_dummy.h b/aegisub/video_provider_dummy.h new file mode 100644 index 000000000..7e7e4c041 --- /dev/null +++ b/aegisub/video_provider_dummy.h @@ -0,0 +1,79 @@ +// Copyright (c) 2007, Niels Martin Hansen +// 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 +// +// Website: http://aegisub.cellosoft.com +// Contact: mailto:jiifurusu@gmail.com +// + +// The dummy video provider needs a header, since it needs to be created directly as a special case + +#ifndef _VIDEO_PROVIDER_DUMMY_H +#define _VIDEO_PROVIDER_DUMMY_H + + +/////////// +// Headers +#include "video_provider.h" +#include + + +//////////////////////// +// Dummy video provider +class DummyVideoProvider : public VideoProvider { +private: + int lastFrame; + int framecount; + double fps; + int width; + int height; + AegiVideoFrame frame; + + void Create(double fps, int frames, int _width, int _height, const wxColour &colour); + +protected: + const AegiVideoFrame DoGetFrame(int n); + +public: + DummyVideoProvider(wxString filename, double fps); + DummyVideoProvider(double fps, int frames, int _width, int _height, const wxColour &colour); + ~DummyVideoProvider(); + + static wxString MakeFilename(double fps, int frames, int _width, int _height, const wxColour &colour); + + int GetPosition(); + int GetFrameCount(); + + int GetWidth(); + int GetHeight(); + double GetFPS(); +}; + +#endif