diff --git a/aegisub/src/main.cpp b/aegisub/src/main.cpp index 4e6b9f5c5..bc74920fb 100644 --- a/aegisub/src/main.cpp +++ b/aegisub/src/main.cpp @@ -285,6 +285,7 @@ bool AegisubApp::OnInit() { /// int AegisubApp::OnExit() { SubtitleFormat::DestroyFormats(); + VideoContext::OnExit(); delete plugins; delete config::opt; delete config::mru; diff --git a/aegisub/src/threaded_frame_source.cpp b/aegisub/src/threaded_frame_source.cpp index 0c0a3ab9c..17368e713 100644 --- a/aegisub/src/threaded_frame_source.cpp +++ b/aegisub/src/threaded_frame_source.cpp @@ -150,7 +150,7 @@ void *ThreadedFrameSource::Entry() { } ThreadedFrameSource::ThreadedFrameSource(wxString videoFileName, wxEvtHandler *parent) -: wxThread() +: wxThread(wxTHREAD_JOINABLE) , provider(SubtitlesProviderFactory::GetProvider()) , videoProvider(VideoProviderFactory::GetProvider(videoFileName)) , parent(parent) @@ -162,6 +162,13 @@ ThreadedFrameSource::ThreadedFrameSource(wxString videoFileName, wxEvtHandler *p Create(); Run(); } +ThreadedFrameSource::~ThreadedFrameSource() { + run = false; + jobReady.Signal(); + Wait(); + frameBuffer[0].Clear(); + frameBuffer[1].Clear(); +} void ThreadedFrameSource::LoadSubtitles(AssFile *subs) throw() { AssExporter exporter(subs); @@ -185,16 +192,6 @@ AegiVideoFrame const& ThreadedFrameSource::GetFrame(int frame, double time, bool return ProcFrame(frame, time, raw); } -void ThreadedFrameSource::End() { - run = false; - jobReady.Signal(); -} - -ThreadedFrameSource::~ThreadedFrameSource() { - frameBuffer[0].Clear(); - frameBuffer[1].Clear(); -} - wxDEFINE_EVENT(EVT_FRAME_READY, FrameReadyEvent); wxDEFINE_EVENT(EVT_VIDEO_ERROR, VideoProviderErrorEvent); wxDEFINE_EVENT(EVT_SUBTITLES_ERROR, SubtitlesProviderErrorEvent); diff --git a/aegisub/src/threaded_frame_source.h b/aegisub/src/threaded_frame_source.h index 85870e1ef..2697be01b 100644 --- a/aegisub/src/threaded_frame_source.h +++ b/aegisub/src/threaded_frame_source.h @@ -109,13 +109,6 @@ public: /// @brief raw Get raw frame without subtitles AegiVideoFrame const& GetFrame(int frame, double time, bool raw = false); - /// @brief Non-blocking Delete - /// - /// Needed due to that calling Delete while the thread is waiting on - /// jobReady results in a deadlock; as such this is the only safe way to - /// destroy a ThreadedFrameSource - void End(); - std::tr1::shared_ptr GetVideoProvider() const { return videoProvider; } /// @brief Constructor diff --git a/aegisub/src/video_context.cpp b/aegisub/src/video_context.cpp index 17b914dac..29d67ff82 100644 --- a/aegisub/src/video_context.cpp +++ b/aegisub/src/video_context.cpp @@ -172,7 +172,7 @@ void VideoContext::SetVideo(const wxString &filename) { try { grid->CommitChanges(true); - provider.reset(new ThreadedFrameSource(filename, this), std::mem_fun(&ThreadedFrameSource::End)); + provider.reset(new ThreadedFrameSource(filename, this)); videoProvider = provider->GetVideoProvider(); videoFile = filename; @@ -581,3 +581,10 @@ void VideoContext::OnSubtitlesError(SubtitlesProviderErrorEvent const& err) { L"Failed rendering subtitles. Error message reported: %s", lagi_wxString(err.GetMessage()).c_str()); } + +void VideoContext::OnExit() { + // On unix wxThreadModule will shut down any still-running threads (and + // display a warning that it's doing so) before the destructor for + // VideoContext runs, so manually kill the thread + Get()->provider.reset(); +} diff --git a/aegisub/src/video_context.h b/aegisub/src/video_context.h index ba9ac70eb..55a04f4ec 100644 --- a/aegisub/src/video_context.h +++ b/aegisub/src/video_context.h @@ -84,7 +84,7 @@ private: std::tr1::shared_ptr videoProvider; /// DOCME - std::tr1::shared_ptr provider; + std::auto_ptr provider; /// Filename of currently open video wxString videoFile; @@ -279,6 +279,7 @@ public: int FrameAtTime(int time, agi::vfr::Time type = agi::vfr::EXACT) const; static VideoContext *Get(); + static void OnExit(); DECLARE_EVENT_TABLE() };