diff --git a/aegisub/audio_provider_ffmpegsource.cpp b/aegisub/audio_provider_ffmpegsource.cpp index 3e57bc7a2..5ff946db6 100644 --- a/aegisub/audio_provider_ffmpegsource.cpp +++ b/aegisub/audio_provider_ffmpegsource.cpp @@ -69,8 +69,7 @@ void FFmpegSourceAudioProvider::LoadAudio(Aegisub::String filename) { wxString FileNameWX(filename.c_str(), wxConvFile); // generate a default name for the cache file - wxString CacheName(filename.c_str(), wxConvFile); - CacheName.append(_T(".ffindex")); + wxString CacheName = GetCacheFilename(filename); FrameIndex *Index; Index = FFMS_ReadIndex(CacheName.char_str(), FFMSErrMsg, MsgSize); diff --git a/aegisub/dialog_progress.cpp b/aegisub/dialog_progress.cpp index 2b836e624..00ddcdeef 100644 --- a/aegisub/dialog_progress.cpp +++ b/aegisub/dialog_progress.cpp @@ -41,6 +41,9 @@ #include "dialog_progress.h" +DEFINE_EVENT_TYPE(wxEVT_PROGRESS_UPDATE) + + /////////////// // Constructor DialogProgress::DialogProgress(wxWindow *parent,wxString title,volatile bool *cancel,wxString message,int cur,int max) @@ -49,9 +52,10 @@ DialogProgress::DialogProgress(wxWindow *parent,wxString title,volatile bool *ca // Variables canceled = cancel; if (cancel) *canceled = false; + virtualMax = max; // Gauge - gauge = new wxGauge(this, -1, max, wxDefaultPosition, wxSize(300,20), wxGA_HORIZONTAL); + gauge = new wxGauge(this, -1, 100, wxDefaultPosition, wxSize(300,20), wxGA_HORIZONTAL); wxButton *cancelButton = NULL; if (cancel) cancelButton = new wxButton(this,wxID_CANCEL); text = new wxStaticText(this, -1, message, wxDefaultPosition, wxDefaultSize, wxALIGN_CENTRE | wxST_NO_AUTORESIZE); @@ -64,23 +68,46 @@ DialogProgress::DialogProgress(wxWindow *parent,wxString title,volatile bool *ca MainSizer->SetSizeHints(this); SetSizer(MainSizer); CenterOnParent(); + Connect(0,wxEVT_PROGRESS_UPDATE,wxCommandEventHandler(DialogProgress::OnUpdateProgress)); } //////////////// // Set progress void DialogProgress::SetProgress(int cur,int max) { - // Lock - bool isMain = wxIsMainThread(); - if (!isMain) wxMutexGuiEnter(); + // Return if there's nothing to do + int value = cur*100/virtualMax; + if (gauge->GetValue() == value && virtualMax == max) return; + virtualMax = max; - // Update - gauge->SetRange(max); - gauge->SetValue(cur); - wxSafeYield(this); + // Check if it's the main thread, if so, just process it now + if (wxIsMainThread()) { + gauge->SetValue(value); + wxYield(); + return; + } - // Unlock - if (!isMain) wxMutexGuiLeave(); + // Otherwise, go on + { + wxMutexLocker locker(mutex); + if (count >= 2) return; + else count++; + } + + wxCommandEvent* evt = new wxCommandEvent(wxEVT_PROGRESS_UPDATE,0); + evt->SetInt(value); + AddPendingEvent(*evt); +} + + +/////////////////// +// Update progress +void DialogProgress::OnUpdateProgress(wxCommandEvent &event) +{ + int value = event.GetInt(); + if (gauge->GetValue() != value) gauge->SetValue(value); + wxMutexLocker locker(mutex); + count--; } @@ -117,7 +144,6 @@ void DialogProgress::OnCancel(wxCommandEvent &event) { if (!isMain) wxMutexGuiLeave(); } - ////////////////////// // Thread constructor DialogProgressThread::DialogProgressThread(wxWindow *parent,wxString title,volatile bool *canceled,wxString message,int cur,int max) diff --git a/aegisub/dialog_progress.h b/aegisub/dialog_progress.h index 4d7cc9c14..de0eac560 100644 --- a/aegisub/dialog_progress.h +++ b/aegisub/dialog_progress.h @@ -50,9 +50,14 @@ // Progress dialog class class DialogProgress : public wxDialog { private: + volatile int count; + int virtualMax; + wxMutex mutex; + wxGauge *gauge; wxStaticText *text; void OnCancel(wxCommandEvent &event); + void OnUpdateProgress(wxCommandEvent &event); public: volatile bool *canceled; diff --git a/aegisub/ffmpegsource_common.cpp b/aegisub/ffmpegsource_common.cpp index 16554fe82..60beb7afa 100644 --- a/aegisub/ffmpegsource_common.cpp +++ b/aegisub/ffmpegsource_common.cpp @@ -38,6 +38,10 @@ /////////// // Headers #include "ffmpegsource_common.h" +#include "md5.h" +#include "standard_paths.h" +#include "main.h" +#include "frame_main.h" /////////////// // Update indexing progress @@ -64,7 +68,7 @@ FrameIndex *FFmpegSourceProvider::DoIndexing(FrameIndex *Index, wxString FileNam // set up progress dialog callback IndexingProgressDialog Progress; Progress.IndexingCanceled = false; - Progress.ProgressDialog = new DialogProgress(NULL, _("Indexing"), &Progress.IndexingCanceled, _("Reading timecodes and frame/sample data"), 0, 1); + Progress.ProgressDialog = new DialogProgress(AegisubApp::Get()->frame, _("Indexing"), &Progress.IndexingCanceled, _("Reading timecodes and frame/sample data"), 0, 1); Progress.ProgressDialog->Show(); Progress.ProgressDialog->SetProgress(0,1); @@ -90,4 +94,42 @@ FrameIndex *FFmpegSourceProvider::DoIndexing(FrameIndex *Index, wxString FileNam return Index; } +///////////////////// +// Creates a name for the ffmpegsource2 index and prepares the folder if it doesn't exist +// method by amz +wxString FFmpegSourceProvider::GetCacheFilename(const wxString& filename) +{ + // Get the size of the file to be hashed + wxFileOffset len = 0; + { + wxFile file(filename,wxFile::read); + if (file.IsOpened()) len = file.Length(); + } + + // Generate string to be hashed + wxString toHash = filename + wxString::Format(_T(":%i"),len); + + // Get the MD5 digest of the string + md5_state_t state; + md5_byte_t digest[16]; + md5_init(&state); + md5_append(&state,(md5_byte_t*)toHash.c_str(),toHash.Length()*sizeof(wxChar)); + md5_finish(&state,digest); + + // Generate the filename + unsigned int *md5 = (unsigned int*) digest; + wxString result = wxString::Format(_T("?user/ffms2cache/%08X%08X%08X%08X.ffindex"),md5[0],md5[1],md5[2],md5[3]); + result = StandardPaths::DecodePath(result); + + // Ensure that folder exists + wxFileName fn(result); + wxString dir = fn.GetPath(); + if (!wxFileName::DirExists(dir)) { + wxFileName::Mkdir(dir); + } + + wxFileName dirfn(dir); + return dirfn.GetShortPath() + _T("/") + fn.GetFullName(); +} + #endif WITH_FFMPEGSOURCE \ No newline at end of file diff --git a/aegisub/ffmpegsource_common.h b/aegisub/ffmpegsource_common.h index 1ad0757e0..72d950a47 100644 --- a/aegisub/ffmpegsource_common.h +++ b/aegisub/ffmpegsource_common.h @@ -55,6 +55,7 @@ public: static int FFMS_CC UpdateIndexingProgress(int State, int64_t Current, int64_t Total, void *Private); FrameIndex *DoIndexing(FrameIndex *Index, wxString Filename, wxString Cachename, int Trackmask, bool IgnoreDecodeErrors); + wxString GetCacheFilename(const wxString& filename); }; #endif /* WITH_FFMPEGSOURCE */ \ No newline at end of file diff --git a/aegisub/video_provider_ffmpegsource.cpp b/aegisub/video_provider_ffmpegsource.cpp index b64ff0202..d09ae3a7b 100644 --- a/aegisub/video_provider_ffmpegsource.cpp +++ b/aegisub/video_provider_ffmpegsource.cpp @@ -63,7 +63,7 @@ FFmpegSourceVideoProvider::FFmpegSourceVideoProvider(Aegisub::String filename, d LoadVideo(filename, fps); } catch (...) { Close(); - throw; + //throw; } } @@ -82,8 +82,7 @@ void FFmpegSourceVideoProvider::LoadVideo(Aegisub::String filename, double fps) wxString FileNameWX(filename.c_str(), wxConvFile); // generate a name for the cache file - wxString CacheName(filename.c_str(), wxConvFile); - CacheName.append(_T(".ffindex")); + wxString CacheName = GetCacheFilename(filename); // try to read index Index = FFMS_ReadIndex(CacheName.char_str(), FFMSErrorMessage, MessageSize);