Pull some of the context (de)init out of FrameMain

And actually do deinitialize more of the stuff in the context.
This commit is contained in:
Thomas Goyne 2014-03-25 14:49:26 -07:00
parent 821f54a372
commit aa46c49403
23 changed files with 139 additions and 101 deletions

View File

@ -329,6 +329,7 @@
<ClCompile Include="$(SrcDir)command\video.cpp" />
<ClCompile Include="$(SrcDir)command\vis_tool.cpp" />
<ClCompile Include="$(SrcDir)compat.cpp" />
<ClCompile Include="$(SrcDir)context.cpp" />
<ClCompile Include="$(SrcDir)crash_writer.cpp">
<ExcludedFromBuild>true</ExcludedFromBuild>
</ClCompile>

View File

@ -1184,6 +1184,9 @@
<ClCompile Include="$(SrcDir)crash_writer_minidump.cpp">
<Filter>Utilities\Logging</Filter>
</ClCompile>
<ClCompile Include="$(SrcDir)context.cpp">
<Filter>Main UI</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ResourceCompile Include="$(SrcDir)res/res.rc">

View File

@ -154,6 +154,7 @@ SRC += \
colorspace.cpp \
colour_button.cpp \
compat.cpp \
context.cpp \
crash_writer.cpp \
dialog_about.cpp \
dialog_attachments.cpp \

View File

@ -75,11 +75,11 @@ enum {
AudioBox::AudioBox(wxWindow *parent, agi::Context *context)
: wxSashWindow(parent, -1, wxDefaultPosition, wxDefaultSize, wxSW_3D | wxCLIP_CHILDREN)
, controller(context->audioController)
, controller(context->audioController.get())
, context(context)
, audio_open_connection(controller->AddAudioOpenListener(&AudioBox::OnAudioOpen, this))
, panel(new wxPanel(this, -1, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL | wxBORDER_RAISED))
, audioDisplay(new AudioDisplay(panel, context->audioController, context))
, audioDisplay(new AudioDisplay(panel, context->audioController.get(), context))
, HorizontalZoom(new wxSlider(panel, Audio_Horizontal_Zoom, -OPT_GET("Audio/Zoom/Horizontal")->GetInt(), -50, 30, wxDefaultPosition, wxSize(-1, 20), wxSL_VERTICAL|wxSL_BOTH))
, VerticalZoom(new wxSlider(panel, Audio_Vertical_Zoom, OPT_GET("Audio/Zoom/Vertical")->GetInt(), 0, 100, wxDefaultPosition, wxSize(-1, 20), wxSL_VERTICAL|wxSL_BOTH|wxSL_INVERSE))
, VolumeBar(new wxSlider(panel, Audio_Volume, OPT_GET("Audio/Volume")->GetInt(), 0, 100, wxDefaultPosition, wxSize(-1, 20), wxSL_VERTICAL|wxSL_BOTH|wxSL_INVERSE))

View File

@ -45,7 +45,7 @@ public:
};
AudioMarkerProviderKeyframes::AudioMarkerProviderKeyframes(agi::Context *c, const char *opt_name)
: vc(c->videoController)
: vc(c->videoController.get())
, keyframe_slot(vc->AddKeyframesListener(&AudioMarkerProviderKeyframes::Update, this))
, timecode_slot(vc->AddTimecodesListener(&AudioMarkerProviderKeyframes::Update, this))
, enabled_slot(OPT_SUB(opt_name, &AudioMarkerProviderKeyframes::Update, this))
@ -107,7 +107,7 @@ public:
};
VideoPositionMarkerProvider::VideoPositionMarkerProvider(agi::Context *c)
: vc(c->videoController)
: vc(c->videoController.get())
, video_seek_slot(vc->AddSeekListener(&VideoPositionMarkerProvider::Update, this))
, enable_opt_changed_slot(OPT_SUB("Audio/Display/Draw/Video Position", &VideoPositionMarkerProvider::OptChanged, this))
{

View File

@ -861,7 +861,7 @@ namespace Automation4 {
set_context(L, c);
GetFeatureFunction("validate");
auto subsobj = new LuaAssFile(L, c->ass);
auto subsobj = new LuaAssFile(L, c->ass.get());
push_value(L, transform_selection(L, c));
int err = lua_pcall(L, 3, 2, 0);
@ -894,7 +894,7 @@ namespace Automation4 {
stackcheck.check_stack(0);
GetFeatureFunction("run");
auto subsobj = new LuaAssFile(L, c->ass, true, true);
auto subsobj = new LuaAssFile(L, c->ass.get(), true, true);
push_value(L, transform_selection(L, c));
try {
@ -966,7 +966,7 @@ namespace Automation4 {
stackcheck.check_stack(0);
GetFeatureFunction("isactive");
auto subsobj = new LuaAssFile(L, c->ass);
auto subsobj = new LuaAssFile(L, c->ass.get());
push_value(L, transform_selection(L, c));
int err = lua_pcall(L, 3, 1, 0);
@ -1071,7 +1071,7 @@ namespace Automation4 {
GetFeatureFunction("config");
// prepare function call
auto subsobj = new LuaAssFile(L, c->ass);
auto subsobj = new LuaAssFile(L, c->ass.get());
// stored options
lua_newtable(L); // TODO, nothing for now

View File

@ -87,7 +87,7 @@ struct subtitle_attachment final : public Command {
void operator()(agi::Context *c) override {
c->videoController->Stop();
DialogAttachments(c->parent, c->ass).ShowModal();
DialogAttachments(c->parent, c->ass.get()).ShowModal();
}
};

View File

@ -205,7 +205,7 @@ struct time_snap_scene final : public validate_video_loaded {
STR_HELP("Set start and end of subtitles to the keyframes around current video frame")
void operator()(agi::Context *c) override {
VideoContext *con = c->videoController;
VideoContext *con = c->videoController.get();
if (!con->IsLoaded() || !con->KeyFramesLoaded()) return;
int curFrame = con->GetFrameN();

View File

@ -120,7 +120,7 @@ struct tool_resampleres final : public Command {
c->videoController->Stop();
ResampleSettings settings;
if (DialogResample(c, settings).ShowModal() == wxID_OK)
ResampleResolution(c->ass, settings);
ResampleResolution(c->ass.get(), settings);
}
};

49
src/context.cpp Normal file
View File

@ -0,0 +1,49 @@
// Copyright (c) 2014, Thomas Goyne <plorkyeran@aegisub.org>
//
// 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.
//
// 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/
#include "config.h"
#include "include/aegisub/context.h"
#include "ass_file.h"
#include "audio_controller.h"
#include "auto4_base.h"
#include "dialog_manager.h"
#include "initial_line_state.h"
#include "search_replace_engine.h"
#include "selection_controller.h"
#include "subs_controller.h"
#include "video_context.h"
#include <libaegisub/util.h>
namespace agi {
Context::Context()
: ass(util::make_unique<AssFile>())
, subsController(util::make_unique<SubsController>(this))
, local_scripts(util::make_unique<Automation4::LocalScriptManager>(this))
, videoController(util::make_unique<VideoContext>(this))
, audioController(util::make_unique<AudioController>(this))
, selectionController(util::make_unique<SelectionController>(this))
, initialLineState(util::make_unique<InitialLineState>(this))
, search(util::make_unique<SearchReplaceEngine>(this))
, dialog(util::make_unique<DialogManager>())
{
subsController->SetSelectionController(selectionController.get());
}
Context::~Context() {}
}

View File

@ -61,7 +61,7 @@ using std::placeholders::_1;
DialogAutomation::DialogAutomation(agi::Context *c)
: wxDialog(c->parent, -1, _("Automation Manager"), wxDefaultPosition, wxDefaultSize, wxDEFAULT_DIALOG_STYLE | wxRESIZE_BORDER)
, context(c)
, local_manager(c->local_scripts)
, local_manager(c->local_scripts.get())
, local_scripts_changed(local_manager->AddScriptChangeListener(&DialogAutomation::RebuildList, this))
, global_manager(wxGetApp().global_scripts)
, global_scripts_changed(global_manager->AddScriptChangeListener(&DialogAutomation::RebuildList, this))

View File

@ -183,7 +183,7 @@ void FontsCollectorThread(AssFile *subs, agi::fs::path const& destination, FcMod
DialogFontsCollector::DialogFontsCollector(agi::Context *c)
: wxDialog(c->parent, -1, _("Fonts Collector"))
, subs(c->ass)
, subs(c->ass.get())
{
SetIcon(GETICON(font_collector_button_16));

View File

@ -450,7 +450,7 @@ bool KaraokeLineMatchDisplay::UndoMatch()
DialogKanjiTimer::DialogKanjiTimer(agi::Context *c)
: wxDialog(c->parent, -1, _("Kanji timing"))
, subs(c->ass)
, subs(c->ass.get())
{
SetIcon(GETICON(kara_timing_copier_16));

View File

@ -136,7 +136,7 @@ void DialogSearchReplace::FindReplace(bool (SearchReplaceEngine::*func)()) {
c->search->Configure(*settings);
try {
(c->search->*func)();
((*c->search).*func)();
}
catch (std::exception const& e) {
wxMessageBox(to_wx(e.what()), "Error", wxOK | wxICON_ERROR | wxCENTER, this);

View File

@ -178,7 +178,7 @@ void DialogSelection::Process(wxCommandEvent&) {
from_wx(match_text->GetValue()), case_sensitive->IsChecked(),
static_cast<Mode>(match_mode->GetSelection()), select_unmatching_lines->GetValue(),
apply_to_comments->IsChecked(), apply_to_dialogue->IsChecked(),
dialogue_field->GetSelection(), con->ass);
dialogue_field->GetSelection(), con->ass.get());
}
catch (agi::Exception const&) {
Close();

View File

@ -477,7 +477,7 @@ void DialogStyleManager::CopyToClipboard(wxListBox *list, T const& v) {
void DialogStyleManager::PasteToCurrent() {
add_styles(
std::bind(&AssFile::GetStyle, c->ass, _1),
[=](std::string const& str) { return c->ass->GetStyle(str); },
[=](AssStyle *s) { c->ass->Styles.push_back(*s); });
c->ass->Commit(_("style paste"), AssFile::COMMIT_STYLES);
@ -554,8 +554,9 @@ void DialogStyleManager::OnCurrentCopy() {
int sel = get_single_sel(CurrentList);
if (sel == -1) return;
ShowCurrentEditor(styleMap[sel],
unique_name(std::bind(&AssFile::GetStyle, c->ass, _1), styleMap[sel]->name));
ShowCurrentEditor(styleMap[sel], unique_name(
[=](std::string const& str) { return c->ass->GetStyle(str); },
styleMap[sel]->name));
}
void DialogStyleManager::OnCurrentDelete() {

View File

@ -44,7 +44,6 @@
#include "ass_file.h"
#include "audio_controller.h"
#include "audio_box.h"
#include "auto4_base.h"
#include "base_grid.h"
#include "compat.h"
#include "command/command.h"
@ -52,12 +51,9 @@
#include "dialog_manager.h"
#include "dialog_version_check.h"
#include "help_button.h"
#include "initial_line_state.h"
#include "libresrc/libresrc.h"
#include "main.h"
#include "options.h"
#include "selection_controller.h"
#include "search_replace_engine.h"
#include "subs_controller.h"
#include "subs_edit_box.h"
#include "subs_edit_ctrl.h"
@ -205,32 +201,17 @@ FrameMain::FrameMain()
LOG_D("locale") << setlocale(LC_ALL, nullptr);
#endif
StartupLog("Initializing context models");
memset(context.get(), 0, sizeof(*context));
context->ass = new AssFile;
StartupLog("Initializing context controls");
context->subsController = new SubsController(context.get());
context->ass->AddCommitListener(&FrameMain::UpdateTitle, this);
context->subsController->AddFileOpenListener(&FrameMain::OnSubtitlesOpen, this);
context->subsController->AddFileSaveListener(&FrameMain::UpdateTitle, this);
context->audioController = new AudioController(context.get());
context->audioController->AddAudioOpenListener(&FrameMain::OnAudioOpen, this);
context->audioController->AddAudioCloseListener(&FrameMain::OnAudioClose, this);
context->local_scripts = new Automation4::LocalScriptManager(context.get());
context->selectionController = new SelectionController(context.get());
context->subsController->SetSelectionController(context->selectionController);
context->videoController = VideoContext::Get(); // derp
context->videoController->AddVideoOpenListener(&FrameMain::OnVideoOpen, this);
StartupLog("Initializing context frames");
context->parent = this;
context->frame = this;
context->previousFocus = nullptr;
StartupLog("Install PNG handler");
wxImage::AddHandler(new wxPNGHandler);
@ -257,13 +238,9 @@ FrameMain::FrameMain()
#endif
StartupLog("Create views and inner main window controls");
context->dialog = new DialogManager;
InitContents();
OPT_SUB("Video/Detached/Enabled", &FrameMain::OnVideoDetach, this, agi::signal::_1);
StartupLog("Complete context initialization");
context->videoController->SetContext(context.get());
StartupLog("Set up drag/drop target");
SetDropTarget(new AegisubFileDropTarget(this));
@ -307,10 +284,6 @@ FrameMain::~FrameMain () {
context->audioController->CloseAudio();
DestroyChildren();
delete context->ass;
delete context->audioController;
delete context->local_scripts;
}
void FrameMain::InitToolbar() {
@ -339,8 +312,6 @@ void FrameMain::InitContents() {
StartupLog("Create subtitles grid");
context->subsGrid = new BaseGrid(Panel, context.get());
context->search = new SearchReplaceEngine(context.get());
context->initialLineState = new InitialLineState(context.get());
StartupLog("Create video box");
videoBox = new VideoBox(Panel, false, context.get());
@ -530,8 +501,7 @@ void FrameMain::OnCloseWindow(wxCloseEvent &event) {
return;
}
delete context->dialog;
context->dialog = nullptr;
context->dialog.reset();
// Store maximization state
OPT_SET("App/Maximized")->SetBool(IsMaximized());
@ -553,7 +523,7 @@ void FrameMain::OnAudioClose() {
void FrameMain::OnSubtitlesOpen() {
UpdateTitle();
auto vc = context->videoController;
auto vc = context->videoController.get();
/// @todo figure out how to move this to the relevant controllers without
/// prompting for each file loaded/unloaded

View File

@ -1,3 +1,21 @@
// Copyright (c) 2014, Thomas Goyne <plorkyeran@aegisub.org>
//
// 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.
//
// 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/
#include <memory>
class AssFile;
class AudioBox;
class AudioController;
@ -9,7 +27,6 @@ class SearchReplaceEngine;
class InitialLineState;
class SelectionController;
class SubsController;
class SubsTextEditCtrl;
class BaseGrid;
class TextSelectionController;
class VideoContext;
@ -20,32 +37,33 @@ namespace Automation4 { class ScriptManager; }
namespace agi {
struct Context {
// Models
AssFile *ass;
Automation4::ScriptManager *local_scripts;
InitialLineState *initialLineState;
// Controllers
AudioController *audioController;
SelectionController *selectionController;
SubsController *subsController;
// Note: order here matters quite a bit, as things need to be set up and
// torn down in the correct order
std::unique_ptr<AssFile> ass;
std::unique_ptr<SubsController> subsController;
std::unique_ptr<Automation4::ScriptManager> local_scripts;
std::unique_ptr<VideoContext> videoController;
std::unique_ptr<AudioController> audioController;
std::unique_ptr<SelectionController> selectionController;
std::unique_ptr<InitialLineState> initialLineState;
TextSelectionController *textSelectionController;
VideoContext *videoController;
SearchReplaceEngine *search;
std::unique_ptr<SearchReplaceEngine> search;
// Things that should probably be in some sort of UI-context-model
wxWindow *parent;
wxWindow *previousFocus;
wxWindow *videoSlider;
wxWindow *parent = nullptr;
wxWindow *previousFocus = nullptr;
wxWindow *videoSlider = nullptr;
// Views (i.e. things that should eventually not be here at all)
AudioBox *audioBox;
AudioKaraoke *karaoke;
BaseGrid *subsGrid;
DialogManager *dialog;
FrameMain *frame;
VideoDisplay *videoDisplay;
AudioBox *audioBox = nullptr;
AudioKaraoke *karaoke = nullptr;
BaseGrid *subsGrid = nullptr;
std::unique_ptr<DialogManager> dialog;
FrameMain *frame = nullptr;
VideoDisplay *videoDisplay = nullptr;
Context();
~Context();
};
}

View File

@ -150,6 +150,8 @@ SubsController::SubsController(agi::Context *context)
});
}
SubsController::~SubsController() { }
void SubsController::SetSelectionController(SelectionController *selection_controller) {
active_line_connection = context->selectionController->AddActiveLineListener(&SubsController::OnActiveLineChanged, this);
selection_connection = context->selectionController->AddSelectionListener(&SubsController::OnSelectionChanged, this);
@ -254,7 +256,7 @@ void SubsController::Save(agi::fs::path const& filename, std::string const& enco
FileSave();
writer->WriteFile(context->ass, filename, encoding);
writer->WriteFile(context->ass.get(), filename, encoding);
}
catch (...) {
autosaved_commit_id = old_autosaved_commit_id;
@ -309,7 +311,7 @@ agi::fs::path SubsController::AutoSave() {
path /= str(boost::format("%s.%s.AUTOSAVE.ass") % name.string() % agi::util::strftime("%Y-%m-%d-%H-%M-%S"));
SubtitleFormat::GetWriter(path)->WriteFile(context->ass, path);
SubtitleFormat::GetWriter(path)->WriteFile(context->ass.get(), path);
autosaved_commit_id = commit_id;
return path;
@ -317,7 +319,7 @@ agi::fs::path SubsController::AutoSave() {
bool SubsController::CanSave() const {
try {
return SubtitleFormat::GetWriter(filename)->CanSave(context->ass);
return SubtitleFormat::GetWriter(filename)->CanSave(context->ass.get());
}
catch (...) {
return false;

View File

@ -69,6 +69,7 @@ class SubsController {
public:
SubsController(agi::Context *context);
~SubsController();
/// Set the selection controller to use
///

View File

@ -60,10 +60,17 @@
#include <wx/msgdlg.h>
VideoContext::VideoContext()
: playback(this)
static VideoContext *instance;
VideoContext::VideoContext(agi::Context *c)
: context(c)
, playback(this)
, playAudioOnStep(OPT_GET("Audio/Plays When Stepping Video"))
{
instance = this;
context->ass->AddCommitListener(&VideoContext::OnSubtitlesCommit, this);
context->subsController->AddFileSaveListener(&VideoContext::OnSubtitlesSave, this);
Bind(EVT_VIDEO_ERROR, &VideoContext::OnVideoError, this);
Bind(EVT_SUBTITLES_ERROR, &VideoContext::OnSubtitlesError, this);
Bind(wxEVT_TIMER, &VideoContext::OnPlayTimer, this);
@ -80,12 +87,10 @@ VideoContext::VideoContext()
OPT_SUB("Video/Force BT.601", &VideoContext::Reload, this);
}
VideoContext::~VideoContext () {
}
VideoContext::~VideoContext () { }
VideoContext *VideoContext::Get() {
static VideoContext instance;
return &instance;
return instance;
}
void VideoContext::Reset() {
@ -109,12 +114,6 @@ void VideoContext::Reset() {
if (!ovr_fps.IsLoaded()) TimecodesOpen(video_fps);
}
void VideoContext::SetContext(agi::Context *context) {
this->context = context;
context->ass->AddCommitListener(&VideoContext::OnSubtitlesCommit, this);
context->subsController->AddFileSaveListener(&VideoContext::OnSubtitlesSave, this);
}
void VideoContext::SetVideo(const agi::fs::path &filename) {
Reset();
if (filename.empty()) {
@ -208,7 +207,7 @@ void VideoContext::SetVideo(const agi::fs::path &filename) {
if (agi::fs::HasExtension(filename, "mkv"))
has_subtitles = MatroskaWrapper::HasSubtitles(filename);
provider->LoadSubtitles(context->ass);
provider->LoadSubtitles(context->ass.get());
VideoOpen();
KeyframesOpen(keyframes);
TimecodesOpen(FPS());
@ -240,9 +239,9 @@ void VideoContext::OnSubtitlesCommit(int type, std::set<const AssDialogue *> con
if (!IsLoaded()) return;
if (changed.empty() || no_amend)
provider->LoadSubtitles(context->ass);
provider->LoadSubtitles(context->ass.get());
else
provider->UpdateSubtitles(context->ass, changed);
provider->UpdateSubtitles(context->ass.get(), changed);
if (!IsPlaying())
GetFrameAsync(frame_n);

View File

@ -90,7 +90,7 @@ class VideoContext final : public wxEvtHandler {
/// The video provider owned by the threaded frame source, or nullptr if no
/// video is open
VideoProvider *video_provider;
VideoProvider *video_provider = nullptr;
/// Asynchronous provider of video frames
std::unique_ptr<ThreadedFrameSource> provider;
@ -162,16 +162,9 @@ class VideoContext final : public wxEvtHandler {
void Reset();
public:
VideoContext();
VideoContext(agi::Context *context);
~VideoContext();
/// @brief Set the context that this is the video controller for
/// @param context Initialized project context
///
/// Once this is no longer a singleton this can probably be moved into
/// the constructor
void SetContext(agi::Context *context);
/// @brief Get the video provider used for the currently open video
VideoProvider *GetProvider() const { return video_provider; }

View File

@ -81,7 +81,7 @@ void VisualToolDrag::UpdateToggleButtons() {
void VisualToolDrag::OnSubTool(wxCommandEvent &) {
// Toggle \move <-> \pos
VideoContext *vc = c->videoController;
VideoContext *vc = c->videoController.get();
for (auto line : selection) {
Vector2D p1, p2;
int t1, t2;