From 3b093cfacdb0d31b0cbbddf52e73e63aa7338d9f Mon Sep 17 00:00:00 2001 From: Hamzah Al-washali <32926868+mez0ru@users.noreply.github.com> Date: Sun, 19 Mar 2023 12:53:02 +0800 Subject: [PATCH 01/12] Asynchronous call to CFileList. The original behavior of the program is to check all files synchronously upon startup, which in my opinion is a bad practice. It should however check asynchronously while it's viewing the startup image for quicker startup. Rationale: I have thousands of images in one folder, and opening each image individually takes about 1-3 seconds to load. My own solution is immature, but it works. --- src/JPEGView/JPEGProvider.cpp | 79 +++++++++ src/JPEGView/JPEGProvider.h | 3 + src/JPEGView/JPEGView.vcxproj | 16 +- src/JPEGView/MainDlg.cpp | 135 ++++++++++++++-- src/JPEGView/MainDlg.h | 9 ++ src/UpgradeLog.htm | 275 ++++++++++++++++++++++++++++++++ src/WICLoader/WICLoader.vcxproj | 8 +- 7 files changed, 497 insertions(+), 28 deletions(-) create mode 100644 src/UpgradeLog.htm diff --git a/src/JPEGView/JPEGProvider.cpp b/src/JPEGView/JPEGProvider.cpp index 7ea45801..b541c26f 100644 --- a/src/JPEGView/JPEGProvider.cpp +++ b/src/JPEGView/JPEGProvider.cpp @@ -123,6 +123,85 @@ void CJPEGProvider::NotifyNotUsed(CJPEGImage* pImage) { if (pImage != NULL) delete pImage; } +CJPEGImage* CJPEGProvider::RequestImage(EReadAheadDirection eDirection, + LPCTSTR strFileName, int nFrameIndex, const CProcessParams& processParams, + bool& bOutOfMemory, bool& bExceptionError) { + if (strFileName == NULL) { + bOutOfMemory = false; + bExceptionError = false; + return NULL; + } + + // Search if we have the requested image already present or in progress + CImageRequest* pRequest = FindRequest(strFileName, nFrameIndex); + bool bDirectionChanged = eDirection != m_eOldDirection || eDirection == TOGGLE; + bool bRemoveAlsoActiveRequests = bDirectionChanged; // if direction changed, all read-ahead requests are wrongly guessed + bool bWasOutOfMemory = false; + m_eOldDirection = eDirection; + + if (pRequest == NULL) { + // no request pending for this file, add to request queue and start async + pRequest = StartNewRequest(strFileName, nFrameIndex, processParams); + // wait with read ahead when direction changed - maybe user just wants to re-see last image + //if (!bDirectionChanged && eDirection != NONE) { + // // start parallel if more than one thread + // StartNewRequestBundle(pFileList, eDirection, processParams, m_nNumThread - 1, NULL); + //} + } + + // wait for request if not yet ready + if (!pRequest->Ready) { +#ifdef DEBUG + ::OutputDebugString(_T("Waiting for request: ")); ::OutputDebugString(pRequest->FileName); ::OutputDebugString(_T("\n")); +#endif + ::WaitForSingleObject(pRequest->EventFinished, INFINITE); + GetLoadedImageFromWorkThread(pRequest); + } + else { + CJPEGImage* pImage = pRequest->Image; + if (pImage != NULL) { + // make sure the initial parameters are reset as when keep params was on before they are wrong + EProcessingFlags procFlags = processParams.ProcFlags; + pImage->RestoreInitialParameters(strFileName, processParams.ImageProcParams, procFlags, + processParams.RotationParams.Rotation, processParams.Zoom, processParams.Offsets, + CSize(processParams.TargetWidth, processParams.TargetHeight), processParams.MonitorSize); + } +#ifdef DEBUG + ::OutputDebugString(_T("Found in cache: ")); ::OutputDebugString(pRequest->FileName); ::OutputDebugString(_T("\n")); +#endif + } + + // set before removing unused images! + pRequest->InUse = true; + pRequest->AccessTimeStamp = m_nCurrentTimeStamp++; + + if (pRequest->OutOfMemory) { + // The request could not be satisfied because the system is out of memory. + // Clear all memory and try again - maybe some readahead requests can be deleted +#ifdef DEBUG + ::OutputDebugString(_T("Retrying request because out of memory: ")); ::OutputDebugString(pRequest->FileName); ::OutputDebugString(_T("\n")); +#endif + bWasOutOfMemory = true; + if (FreeAllPossibleMemory()) { + DeleteElement(pRequest); + pRequest = StartRequestAndWaitUntilReady(strFileName, nFrameIndex, processParams); + } + } + + // cleanup stuff no longer used + RemoveUnusedImages(bRemoveAlsoActiveRequests); + ClearOldestInactiveRequest(); + + // check if we shall start new requests (don't start another request if we are short of memory!) + //if (m_requestList.size() < (unsigned int)m_nNumBuffers && !bDirectionChanged && !bWasOutOfMemory && eDirection != NONE) { + // StartNewRequestBundle(pFileList, eDirection, processParams, m_nNumThread, pRequest); + //} + + bOutOfMemory = pRequest->OutOfMemory; + bExceptionError = pRequest->ExceptionError; + return pRequest->Image; +} + void CJPEGProvider::ClearAllRequests() { std::list::iterator iter; for (iter = m_requestList.begin( ); iter != m_requestList.end( ); iter++ ) { diff --git a/src/JPEGView/JPEGProvider.h b/src/JPEGView/JPEGProvider.h index 23f4d1cd..e8436476 100644 --- a/src/JPEGView/JPEGProvider.h +++ b/src/JPEGView/JPEGProvider.h @@ -41,6 +41,9 @@ class CJPEGProvider // created automatically so that the next image will be ready immediately when requested in the future. CJPEGImage* RequestImage(CFileList* pFileList, EReadAheadDirection eDirection, LPCTSTR strFileName, int nFrameIndex, const CProcessParams & processParams, bool& bOutOfMemory, bool& bExceptionError); + CJPEGImage* CJPEGProvider::RequestImage(EReadAheadDirection eDirection, + LPCTSTR strFileName, int nFrameIndex, const CProcessParams& processParams, + bool& bOutOfMemory, bool& bExceptionError); // Notifies that the specified image is no longer used and its memory can be freed. // The CJPEGProvider class may decide to keep the image cached. diff --git a/src/JPEGView/JPEGView.vcxproj b/src/JPEGView/JPEGView.vcxproj index 1eb3d471..16d50cac 100644 --- a/src/JPEGView/JPEGView.vcxproj +++ b/src/JPEGView/JPEGView.vcxproj @@ -26,22 +26,22 @@ Application Unicode - v142 + v143 Application Unicode - v142 + v143 Application Unicode - v142 + v143 Application Unicode - v142 + v143 @@ -152,7 +152,7 @@ Disabled - %(AdditionalIncludeDirectories) + C:\Users\lazyhorse\Documents\github\wtl10\Include;%(AdditionalIncludeDirectories) WIN32;_WINDOWS;STRICT;_DEBUG;%(PreprocessorDefinitions) Async EnableFastChecks @@ -167,7 +167,7 @@ _DEBUG;%(PreprocessorDefinitions) 0x0409 - $(IntDir);%(AdditionalIncludeDirectories) + $(IntDir);C:\Users\lazyhorse\Documents\github\wtl10\Include;%(AdditionalIncludeDirectories) legacy_stdio_definitions.lib;legacy_stdio_wide_specifiers.lib;Dbghelp.lib;gdiplus.lib;WICLoader.lib;turbojpeg-static.lib;libpng16.lib;zlib.lib;jxl_dec.lib;jxl_threads.lib;heif.lib;libwebp.lib;libwebpdemux.lib;avif.lib;lcms2.lib;%(AdditionalDependencies) @@ -256,7 +256,7 @@ MaxSpeed - %(AdditionalIncludeDirectories) + C:\Users\lazyhorse\Documents\github\wtl10\Include;%(AdditionalIncludeDirectories) WIN32;_WINDOWS;STRICT;NDEBUG;%(PreprocessorDefinitions) false Async @@ -276,7 +276,7 @@ NDEBUG;%(PreprocessorDefinitions) 0x0409 - $(IntDir);%(AdditionalIncludeDirectories) + $(IntDir);C:\Users\lazyhorse\Documents\github\wtl10\Include;%(AdditionalIncludeDirectories) legacy_stdio_definitions.lib;legacy_stdio_wide_specifiers.lib;gdiplus.lib;WICLoader.lib;turbojpeg-static.lib;libpng16.lib;zlib.lib;jxl_dec.lib;jxl_threads.lib;heif.lib;libwebp.lib;libwebpdemux.lib;avif.lib;lcms2.lib;%(AdditionalDependencies) diff --git a/src/JPEGView/MainDlg.cpp b/src/JPEGView/MainDlg.cpp index c16bc951..768d940b 100644 --- a/src/JPEGView/MainDlg.cpp +++ b/src/JPEGView/MainDlg.cpp @@ -52,6 +52,7 @@ #include "DirectoryWatcher.h" #include "DesktopWallpaper.h" #include "PrintImage.h" +#include ////////////////////////////////////////////////////////////////////////////////////////////// // Constants @@ -371,24 +372,39 @@ LRESULT CMainDlg::OnInitDialog(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam ::ShowCursor(m_bMouseOn); // intitialize list of files to show with startup file (and folder) - m_pFileList = new CFileList(m_sStartupFile, *m_pDirectoryWatcher, - (m_eForcedSorting == Helpers::FS_Undefined) ? sp.Sorting() : m_eForcedSorting, sp.IsSortedAscending(), sp.WrapAroundFolder(), - 0, m_eForcedSorting != Helpers::FS_Undefined); - m_pFileList->SetNavigationMode(sp.Navigation()); - + //m_pFileList = new CFileList(m_sStartupFile, *m_pDirectoryWatcher, + // (m_eForcedSorting == Helpers::FS_Undefined) ? sp.Sorting() : m_eForcedSorting, sp.IsSortedAscending(), sp.WrapAroundFolder(), + // 0, m_eForcedSorting != Helpers::FS_Undefined); + //std::thread([&, this]() { + // m_pFileList = new CFileList(m_sStartupFile, *m_pDirectoryWatcher, + // (m_eForcedSorting == Helpers::FS_Undefined) ? sp.Sorting() : m_eForcedSorting, sp.IsSortedAscending(), sp.WrapAroundFolder(), + // 0, m_eForcedSorting != Helpers::FS_Undefined); + // m_pFileList->SetNavigationMode(sp.Navigation()); + // }).detach(); + + isDone_future_m_pFileList = false; + future_m_pFileList = std::async(std::launch::async, [this, &sp]() { + m_pFileList = new CFileList(m_sStartupFile, *m_pDirectoryWatcher, + (m_eForcedSorting == Helpers::FS_Undefined) ? sp.Sorting() : m_eForcedSorting, sp.IsSortedAscending(), sp.WrapAroundFolder(), + 0, m_eForcedSorting != Helpers::FS_Undefined); + m_pFileList->SetNavigationMode(sp.Navigation()); + isDone_future_m_pFileList = true; + }); + // create thread pool for processing requests on multiple CPU cores CProcessingThreadPool::This().CreateThreadPoolThreads(); // create JPEG provider and request first image - do no processing yet if not in fullscreen mode (as we do not know the size yet) - m_pJPEGProvider = new CJPEGProvider(m_hWnd, NUM_THREADS, READ_AHEAD_BUFFERS); - m_pCurrentImage = m_pJPEGProvider->RequestImage(m_pFileList, CJPEGProvider::FORWARD, - m_pFileList->Current(), 0, CreateProcessParams(!m_bFullScreenMode), m_bOutOfMemoryLastImage, m_bExceptionErrorLastImage); + m_pJPEGProvider = new CJPEGProvider(m_hWnd, NUM_THREADS, READ_AHEAD_BUFFERS); + if (!m_sStartupFile.IsEmpty()) + m_pCurrentImage = m_pJPEGProvider->RequestImage(CJPEGProvider::FORWARD, + m_sStartupFile, 0, CreateProcessParams(!m_bFullScreenMode), m_bOutOfMemoryLastImage, m_bExceptionErrorLastImage); if (m_pCurrentImage != NULL && m_pCurrentImage->IsAnimation()) { StartAnimation(); } m_nLastLoadError = GetLoadErrorAfterOpenFile(); CheckIfApplyAutoFitWndToImage(true); - AfterNewImageLoaded(true, true, false); // synchronize to per image parameters + AfterNewImageLoaded(true, true, false, m_sStartupFile); // synchronize to per image parameters if (!m_bFullScreenMode) { // Window mode, set correct window size @@ -955,6 +971,8 @@ LRESULT CMainDlg::OnKeyDown(UINT /*uMsg*/, WPARAM wParam, LPARAM /*lParam*/, BOO m_pCropCtl->AbortCropping(); } else if (!bCtrl && wParam != VK_ESCAPE && m_nLastLoadError == HelpersGUI::FileLoad_NoFilesInDirectory && !m_sStartupFile.IsEmpty()) { // search in subfolders if initial directory has no images + if (!isDone_future_m_pFileList) + future_m_pFileList.wait(); // Check if m_pFileList is available first before using. bHandled = true; m_pFileList->SetNavigationMode(Helpers::NM_LoopSubDirectories); GotoImage(POS_Next); @@ -2143,17 +2161,23 @@ void CMainDlg::OpenFile(LPCTSTR sFileName, bool bAfterStartup) { bool oOldAscending = m_pFileList->IsSortedAscending(); delete m_pFileList; m_sStartupFile = sFileName; - m_pFileList = new CFileList(m_sStartupFile, *m_pDirectoryWatcher, eOldSorting, oOldAscending, CSettingsProvider::This().WrapAroundFolder()); + //m_pFileList = new CFileList(m_sStartupFile, *m_pDirectoryWatcher, eOldSorting, oOldAscending, CSettingsProvider::This().WrapAroundFolder()); + isDone_future_m_pFileList = false; + future_m_pFileList = std::async(std::launch::async, [this, eOldSorting, oOldAscending]() { + m_pFileList = new CFileList(m_sStartupFile, *m_pDirectoryWatcher, eOldSorting, oOldAscending, CSettingsProvider::This().WrapAroundFolder()); + isDone_future_m_pFileList = true; + }); + // free current image and all read ahead images InitParametersForNewImage(); m_pJPEGProvider->NotifyNotUsed(m_pCurrentImage); m_pJPEGProvider->ClearAllRequests(); - m_pCurrentImage = m_pJPEGProvider->RequestImage(m_pFileList, CJPEGProvider::FORWARD, - m_pFileList->Current(), 0, CreateProcessParams(!m_bFullScreenMode && (bAfterStartup || IsAdjustWindowToImage())), + m_pCurrentImage = m_pJPEGProvider->RequestImage(CJPEGProvider::FORWARD, + m_sStartupFile, 0, CreateProcessParams(!m_bFullScreenMode && (bAfterStartup || IsAdjustWindowToImage())), m_bOutOfMemoryLastImage, m_bExceptionErrorLastImage); m_nLastLoadError = GetLoadErrorAfterOpenFile(); if (bAfterStartup) CheckIfApplyAutoFitWndToImage(false); - AfterNewImageLoaded(true, false, false); + AfterNewImageLoaded(true, false, false, m_sStartupFile); if (m_pCurrentImage != NULL && m_pCurrentImage->IsAnimation()) { StartAnimation(); } @@ -2161,6 +2185,9 @@ void CMainDlg::OpenFile(LPCTSTR sFileName, bool bAfterStartup) { m_sSaveDirectory = _T(""); MouseOff(); this->Invalidate(FALSE); + //std::thread([&, this]() { + // m_pFileList = new CFileList(m_sStartupFile, *m_pDirectoryWatcher, eOldSorting, oOldAscending, CSettingsProvider::This().WrapAroundFolder()); + // }).detach(); } bool CMainDlg::SaveImage(bool bFullSize) { @@ -2398,6 +2425,9 @@ void CMainDlg::GotoImage(EImagePosition ePos) { } void CMainDlg::GotoImage(EImagePosition ePos, int nFlags) { + if (!isDone_future_m_pFileList) + future_m_pFileList.wait(); // Check if m_pFileList is available first before using. + // Timer handling for slideshows if (ePos == POS_Next || ePos == POS_NextSlideShow) { if (m_nCurrentTimeout > 0) { @@ -3028,6 +3058,59 @@ void CMainDlg::AfterNewImageLoaded(bool bSynchronize, bool bAfterStartup, bool n } } +void CMainDlg::AfterNewImageLoaded(bool bSynchronize, bool bAfterStartup, bool noAdjustWindow, LPCTSTR fileName) { + UpdateWindowTitle(fileName); + InvalidateHelpDlg(); + m_pDirectoryWatcher->SetCurrentFile(fileName); + if (!m_bIsAnimationPlaying) m_pNavPanelCtl->HideNavPanelTemporary(); + //m_pPanelMgr->AfterNewImageLoaded(); + m_pCropCtl->AbortCropping(); + if (m_pCurrentImage != NULL) m_pCropCtl->SetImageSize(m_pCurrentImage->OrigSize()); // inform CropCtl of the image size for CropImageAR + m_pPrintImage->ClearOffsets(); + if (bSynchronize) { + // after loading an image, the per image processing parameters must be synchronized with + // the current processing parameters + bool bLastWasSpecialProcessing = m_bCurrentImageIsSpecialProcessing; + bool bLastWasInParamDB = m_bCurrentImageInParamDB; + m_bCurrentImageInParamDB = false; + m_bCurrentImageIsSpecialProcessing = false; + if (m_pCurrentImage != NULL) { + m_dCurrentInitialLightenShadows = m_pCurrentImage->GetInitialProcessParams().LightenShadows; + m_bCurrentImageInParamDB = m_pCurrentImage->IsInParamDB(); + m_bCurrentImageIsSpecialProcessing = m_pCurrentImage->GetLightenShadowFactor() != 1.0f; + if (!m_bKeepParams) { + m_bHQResampling = GetProcessingFlag(m_pCurrentImage->GetInitialProcessFlags(), PFLAG_HighQualityResampling); + m_bAutoContrast = GetProcessingFlag(m_pCurrentImage->GetInitialProcessFlags(), PFLAG_AutoContrast); + m_bLDC = GetProcessingFlag(m_pCurrentImage->GetInitialProcessFlags(), PFLAG_LDC); + + m_nRotation = m_pCurrentImage->GetInitialRotation(); + m_dZoom = m_pCurrentImage->GetInititialZoom(); + m_offsets = m_pCurrentImage->GetInitialOffsets(); + + if (m_pCurrentImage->HasZoomStoredInParamDB()) { + m_bUserZoom = m_bUserPan = true; + } + + *m_pImageProcParams = m_pCurrentImage->GetInitialProcessParams(); + } + else if (m_bCurrentImageIsSpecialProcessing && m_bKeepParams) { + // set this factor, no matter if we keep parameters + m_pImageProcParams->LightenShadows = m_pCurrentImage->GetInitialProcessParams().LightenShadows; + } + else if (bLastWasSpecialProcessing && m_bKeepParams) { + // take kept value when last was special processing as the special processing value is not usable + m_pImageProcParams->LightenShadows = m_pImageProcParamsKept->LightenShadows; + } + if (m_bKeepParams) { + m_nRotation = m_pCurrentImage->GetInitialRotation() + m_nUserRotation; + } + } + if (!bAfterStartup && !m_bIsAnimationPlaying && !noAdjustWindow) { + AdjustWindowToImage(false); + } + } +} + bool CMainDlg::IsAdjustWindowToImage() { return !m_bFullScreenMode && !::IsZoomed(m_hWnd) && m_bAutoFitWndToImage; } @@ -3240,6 +3323,26 @@ void CMainDlg::UpdateWindowTitle() { } } +void CMainDlg::UpdateWindowTitle(LPCTSTR sCurrentFileName) { + bool bShowFullPathInTitle = CSettingsProvider::This().ShowFullPathInTitle(); + + if (sCurrentFileName == NULL || m_pCurrentImage == NULL) { + this->SetWindowText(_T(JPEGVIEW_TITLE)); + } + else { + CString sWindowText = sCurrentFileName; + sWindowText += Helpers::GetMultiframeIndex(m_pCurrentImage); + if (CSettingsProvider::This().ShowEXIFDateInTitle()) { + CEXIFReader* pEXIF = m_pCurrentImage->GetEXIFReader(); + if (pEXIF != NULL && pEXIF->GetAcquisitionTime().wYear > 1600) { + sWindowText += " - " + Helpers::SystemTimeToString(pEXIF->GetAcquisitionTime()); + } + } + sWindowText += " - " + CString(JPEGVIEW_TITLE); + this->SetWindowText(sWindowText); + } +} + bool CMainDlg::PrepareForModalPanel() { m_pImageProcPanelCtl->SetVisible(false); bool bOldShowNavPanel = m_pNavPanelCtl->IsActive(); @@ -3261,9 +3364,9 @@ int CMainDlg::TrackPopupMenu(CPoint pos, HMENU hMenu) { int CMainDlg::GetLoadErrorAfterOpenFile() { if (m_pCurrentImage == NULL) { if (CurrentFileName(false) == NULL) { - if (m_pFileList->IsSlideShowList()) { - return HelpersGUI::FileLoad_SlideShowListInvalid; - } + //if (m_pFileList->IsSlideShowList()) { + // return HelpersGUI::FileLoad_SlideShowListInvalid; + //} return HelpersGUI::FileLoad_NoFilesInDirectory; } return HelpersGUI::FileLoad_LoadError; diff --git a/src/JPEGView/MainDlg.h b/src/JPEGView/MainDlg.h index 0332ecb4..7022a77f 100644 --- a/src/JPEGView/MainDlg.h +++ b/src/JPEGView/MainDlg.h @@ -7,6 +7,7 @@ #include "ProcessParams.h" #include "Helpers.h" #include "CropCtl.h" +#include class CFileList; class CJPEGProvider; @@ -194,6 +195,7 @@ class CMainDlg : public CDialogImpl void BlendBlackRect(CDC & targetDC, CPanel& panel, float fBlendFactor); void UpdateWindowTitle(); + void UpdateWindowTitle(LPCTSTR fileName); void MouseOff(); void MouseOn(); void GotoImage(EImagePosition ePos); @@ -228,7 +230,11 @@ class CMainDlg : public CDialogImpl int m_nAutoStartSlideShow; // if positive: Auto start slide show with given interval in seconds, passed on command line bool m_bAutoExit; Helpers::ESorting m_eForcedSorting; // forced sorting mode on command line + CFileList* m_pFileList; // used for navigation + std::future future_m_pFileList; // check if m_pFileList loaded successfully before accessing the original variable. + std::atomic isDone_future_m_pFileList = true; + CDirectoryWatcher* m_pDirectoryWatcher; // notifies the main window when the current file changed or a file in the current directory was added or deleted CJPEGProvider * m_pJPEGProvider; // reads image (of any format, not only JPEGs) files, using read ahead CJPEGImage * m_pCurrentImage; // currently displayed image @@ -360,6 +366,7 @@ class CMainDlg : public CDialogImpl void ExchangeProcessingParams(); void SaveParameters(); void AfterNewImageLoaded(bool bSynchronize, bool bAfterStartup, bool noAdjustWindow); + void AfterNewImageLoaded(bool bSynchronize, bool bAfterStartup, bool noAdjustWindow, LPCTSTR fileName); CRect ScreenToDIB(const CSize& sizeDIB, const CRect& rect); void ToggleMonitor(); CRect GetZoomTextRect(CRect imageProcessingArea); @@ -379,4 +386,6 @@ class CMainDlg : public CDialogImpl void StartAnimation(); void AdjustAnimationFrameTime(); void StopAnimation(); + + // Wait for future to finish function }; diff --git a/src/UpgradeLog.htm b/src/UpgradeLog.htm new file mode 100644 index 00000000..a5bd6c4c --- /dev/null +++ b/src/UpgradeLog.htm @@ -0,0 +1,275 @@ + + + + Migration Report +

+ Migration Report -

\ No newline at end of file diff --git a/src/WICLoader/WICLoader.vcxproj b/src/WICLoader/WICLoader.vcxproj index 0a2ad09b..ac488318 100644 --- a/src/WICLoader/WICLoader.vcxproj +++ b/src/WICLoader/WICLoader.vcxproj @@ -29,27 +29,27 @@ DynamicLibrary true Unicode - v142 + v143 DynamicLibrary true Unicode - v142 + v143 DynamicLibrary false true Unicode - v142 + v143 DynamicLibrary false true Unicode - v142 + v143 From 5df9e3b084aef43b8d8b24f3c22988dbde1eab05 Mon Sep 17 00:00:00 2001 From: Hamzah Al-washali <32926868+mez0ru@users.noreply.github.com> Date: Sun, 19 Mar 2023 13:36:01 +0800 Subject: [PATCH 02/12] More error checking --- src/JPEGView/MainDlg.cpp | 46 ++++++++++++++++++++++++++++++++++++---- src/JPEGView/MainDlg.h | 2 +- 2 files changed, 43 insertions(+), 5 deletions(-) diff --git a/src/JPEGView/MainDlg.cpp b/src/JPEGView/MainDlg.cpp index 768d940b..58945647 100644 --- a/src/JPEGView/MainDlg.cpp +++ b/src/JPEGView/MainDlg.cpp @@ -285,7 +285,8 @@ CMainDlg::CMainDlg(bool bForceFullScreen) { CMainDlg::~CMainDlg() { delete m_pDirectoryWatcher; - delete m_pFileList; + if (isDone_future_m_pFileList) + delete m_pFileList; if (m_pJPEGProvider != NULL) delete m_pJPEGProvider; delete m_pImageProcParams; delete m_pImageProcParamsKept; @@ -1001,6 +1002,8 @@ LRESULT CMainDlg::OnKeyDown(UINT /*uMsg*/, WPARAM wParam, LPARAM /*lParam*/, BOO if (!bHandled) { // look if any of the user commands wants to handle this key + if (!isDone_future_m_pFileList) + future_m_pFileList.wait(); // Check if m_pFileList is available first before using. if (m_pFileList->Current() != NULL) { HandleUserCommands(CKeyMap::GetCombinedKeyCode((int)wParam, bAlt, bCtrl, bShift)); } @@ -1352,11 +1355,15 @@ void CMainDlg::ExecuteCommand(int nCommand) { MouseOn(); break; case IDM_TOGGLE: + if (!isDone_future_m_pFileList) + future_m_pFileList.wait(); if (m_pFileList->FileMarkedForToggle()) { GotoImage(POS_Toggle); } break; case IDM_MARK_FOR_TOGGLE: + if (!isDone_future_m_pFileList) + future_m_pFileList.wait(); if (m_pFileList->Current() != NULL && m_pCurrentImage != NULL && !m_pCurrentImage->IsClipboardImage()) { m_pFileList->MarkCurrentFile(); } @@ -1392,6 +1399,8 @@ void CMainDlg::ExecuteCommand(int nCommand) { case IDM_PRINT: if (m_pCurrentImage != NULL) { StopAnimation(); // stop any running animation + if (!isDone_future_m_pFileList) + future_m_pFileList.wait(); if (m_pPrintImage->Print(this->m_hWnd, m_pCurrentImage, *m_pImageProcParams, CreateDefaultProcessingFlags(), m_pFileList->Current())) { this->Invalidate(FALSE); } @@ -1399,17 +1408,23 @@ void CMainDlg::ExecuteCommand(int nCommand) { break; case IDM_COPY: if (m_pCurrentImage != NULL) { + if (!isDone_future_m_pFileList) + future_m_pFileList.wait(); CClipboard::CopyImageToClipboard(this->m_hWnd, m_pCurrentImage, m_pFileList->Current()); } break; case IDM_COPY_FULL: if (m_pCurrentImage != NULL) { + if (!isDone_future_m_pFileList) + future_m_pFileList.wait(); CClipboard::CopyFullImageToClipboard(this->m_hWnd, m_pCurrentImage, *m_pImageProcParams, CreateDefaultProcessingFlags(), m_pFileList->Current()); this->Invalidate(FALSE); } break; case IDM_COPY_PATH: if (m_pCurrentImage != NULL && !m_pCurrentImage->IsClipboardImage()) { + if (!isDone_future_m_pFileList) + future_m_pFileList.wait(); CClipboard::CopyPathToClipboard(this->m_hWnd, m_pCurrentImage, m_pFileList->Current()); } break; @@ -1430,6 +1445,8 @@ void CMainDlg::ExecuteCommand(int nCommand) { case IDM_MOVE_TO_RECYCLE_BIN_CONFIRM: case IDM_MOVE_TO_RECYCLE_BIN_CONFIRM_PERMANENT_DELETE: MouseOn(); + if (!isDone_future_m_pFileList) + future_m_pFileList.wait(); if (m_pCurrentImage != NULL && m_pFileList != NULL && !m_pCurrentImage->IsClipboardImage() && sp.AllowFileDeletion()) { LPCTSTR currentFileName = CurrentFileName(false); bool noConfirmation = nCommand == IDM_MOVE_TO_RECYCLE_BIN || @@ -1463,20 +1480,30 @@ void CMainDlg::ExecuteCommand(int nCommand) { m_pNavPanelCtl->SetActive(!m_pNavPanelCtl->IsActive()); break; case IDM_NEXT: + if (!isDone_future_m_pFileList) + future_m_pFileList.wait(); // Check if m_pFileList is available first before using. GotoImage(POS_Next); break; case IDM_PREV: + if (!isDone_future_m_pFileList) + future_m_pFileList.wait(); // Check if m_pFileList is available first before using. GotoImage(POS_Previous); break; case IDM_FIRST: + if (!isDone_future_m_pFileList) + future_m_pFileList.wait(); // Check if m_pFileList is available first before using. GotoImage(POS_First); break; case IDM_LAST: + if (!isDone_future_m_pFileList) + future_m_pFileList.wait(); // Check if m_pFileList is available first before using. GotoImage(POS_Last); break; case IDM_LOOP_FOLDER: case IDM_LOOP_RECURSIVELY: case IDM_LOOP_SIBLINGS: + if (!isDone_future_m_pFileList) + future_m_pFileList.wait(); m_pFileList->SetNavigationMode( (nCommand == IDM_LOOP_FOLDER) ? Helpers::NM_LoopDirectory : (nCommand == IDM_LOOP_RECURSIVELY) ? Helpers::NM_LoopSubDirectories : @@ -1487,6 +1514,8 @@ void CMainDlg::ExecuteCommand(int nCommand) { case IDM_SORT_NAME: case IDM_SORT_RANDOM: case IDM_SORT_SIZE: + if (!isDone_future_m_pFileList) + future_m_pFileList.wait(); m_pFileList->SetSorting( (nCommand == IDM_SORT_CREATION_DATE) ? Helpers::FS_CreationTime : (nCommand == IDM_SORT_MOD_DATE) ? Helpers::FS_LastModTime : @@ -1498,6 +1527,8 @@ void CMainDlg::ExecuteCommand(int nCommand) { break; case IDM_SORT_ASCENDING: case IDM_SORT_DESCENDING: + if (!isDone_future_m_pFileList) + future_m_pFileList.wait(); m_pFileList->SetSorting(m_pFileList->GetSorting(), nCommand == IDM_SORT_ASCENDING); if (m_pEXIFDisplayCtl->IsActive() || m_bShowFileName) { this->Invalidate(FALSE); @@ -1573,6 +1604,8 @@ void CMainDlg::ExecuteCommand(int nCommand) { if (CParameterDB::This().DeleteEntry(m_pCurrentImage->GetPixelHash())) { // restore initial parameters and realize the parameters EProcessingFlags procFlags = GetDefaultProcessingFlags(m_bLandscapeMode); + if (!isDone_future_m_pFileList) + future_m_pFileList.wait(); m_pCurrentImage->RestoreInitialParameters(m_pFileList->Current(), GetDefaultProcessingParams(), procFlags, 0, -1, CPoint(0, 0), CSize(0, 0), CSize(0, 0)); *m_pImageProcParams = GetDefaultProcessingParams(); @@ -1663,6 +1696,8 @@ void CMainDlg::ExecuteCommand(int nCommand) { sConfirmMsg, CNLS::GetString(_T("Confirm")), MB_YESNOCANCEL | MB_ICONWARNING); } if (bPerformTransformation) { + if (!isDone_future_m_pFileList) + future_m_pFileList.wait(); CJPEGLosslessTransform::EResult eResult = CJPEGLosslessTransform::PerformTransformation(m_pFileList->Current(), m_pFileList->Current(), HelpersGUI::CommandIdToLosslessTransformation(nCommand), bCrop || sp.CropWithoutPromptLosslessJPEG()); if (eResult != CJPEGLosslessTransform::Success) { @@ -1704,6 +1739,8 @@ void CMainDlg::ExecuteCommand(int nCommand) { EProcessingFlags eProcFlags = GetDefaultProcessingFlags(false); CImageProcessingParams ipa = GetDefaultProcessingParams(); if (m_pCurrentImage != NULL) { + if (!isDone_future_m_pFileList) + future_m_pFileList.wait(); m_pCurrentImage->GetFileParams(m_pFileList->Current(), eProcFlags, ipa); } m_bLDC = GetProcessingFlag(eProcFlags, PFLAG_LDC); @@ -2021,6 +2058,8 @@ void CMainDlg::ExecuteCommand(int nCommand) { bOk = EXIFHelpers::SetModificationDate(strFileName, st); } if (bOk) { + if (!isDone_future_m_pFileList) + future_m_pFileList.wait(); m_pFileList->ModificationTimeChanged(); if (m_pEXIFDisplayCtl->IsActive()) { this->Invalidate(FALSE); @@ -2157,6 +2196,8 @@ void CMainDlg::OpenFile(LPCTSTR sFileName, bool bAfterStartup) { StopMovieMode(); StopAnimation(); // recreate file list based on image opened + if (!isDone_future_m_pFileList) + future_m_pFileList.wait(); Helpers::ESorting eOldSorting = m_pFileList->GetSorting(); bool oOldAscending = m_pFileList->IsSortedAscending(); delete m_pFileList; @@ -2425,9 +2466,6 @@ void CMainDlg::GotoImage(EImagePosition ePos) { } void CMainDlg::GotoImage(EImagePosition ePos, int nFlags) { - if (!isDone_future_m_pFileList) - future_m_pFileList.wait(); // Check if m_pFileList is available first before using. - // Timer handling for slideshows if (ePos == POS_Next || ePos == POS_NextSlideShow) { if (m_nCurrentTimeout > 0) { diff --git a/src/JPEGView/MainDlg.h b/src/JPEGView/MainDlg.h index 7022a77f..47475e1c 100644 --- a/src/JPEGView/MainDlg.h +++ b/src/JPEGView/MainDlg.h @@ -233,7 +233,7 @@ class CMainDlg : public CDialogImpl CFileList* m_pFileList; // used for navigation std::future future_m_pFileList; // check if m_pFileList loaded successfully before accessing the original variable. - std::atomic isDone_future_m_pFileList = true; + bool isDone_future_m_pFileList = true; CDirectoryWatcher* m_pDirectoryWatcher; // notifies the main window when the current file changed or a file in the current directory was added or deleted CJPEGProvider * m_pJPEGProvider; // reads image (of any format, not only JPEGs) files, using read ahead From 8db31ef188fce8d665e9d7df47427c6d05af681d Mon Sep 17 00:00:00 2001 From: Hamzah Al-washali <32926868+mez0ru@users.noreply.github.com> Date: Sun, 19 Mar 2023 15:40:48 +0800 Subject: [PATCH 03/12] Removed files/used from the original --- src/JPEGView/JPEGView.vcxproj | 16 +- src/UpgradeLog.htm | 275 -------------------------------- src/WICLoader/WICLoader.vcxproj | 8 +- 3 files changed, 12 insertions(+), 287 deletions(-) delete mode 100644 src/UpgradeLog.htm diff --git a/src/JPEGView/JPEGView.vcxproj b/src/JPEGView/JPEGView.vcxproj index 16d50cac..1eb3d471 100644 --- a/src/JPEGView/JPEGView.vcxproj +++ b/src/JPEGView/JPEGView.vcxproj @@ -26,22 +26,22 @@ Application Unicode - v143 + v142 Application Unicode - v143 + v142 Application Unicode - v143 + v142 Application Unicode - v143 + v142 @@ -152,7 +152,7 @@ Disabled - C:\Users\lazyhorse\Documents\github\wtl10\Include;%(AdditionalIncludeDirectories) + %(AdditionalIncludeDirectories) WIN32;_WINDOWS;STRICT;_DEBUG;%(PreprocessorDefinitions) Async EnableFastChecks @@ -167,7 +167,7 @@ _DEBUG;%(PreprocessorDefinitions) 0x0409 - $(IntDir);C:\Users\lazyhorse\Documents\github\wtl10\Include;%(AdditionalIncludeDirectories) + $(IntDir);%(AdditionalIncludeDirectories) legacy_stdio_definitions.lib;legacy_stdio_wide_specifiers.lib;Dbghelp.lib;gdiplus.lib;WICLoader.lib;turbojpeg-static.lib;libpng16.lib;zlib.lib;jxl_dec.lib;jxl_threads.lib;heif.lib;libwebp.lib;libwebpdemux.lib;avif.lib;lcms2.lib;%(AdditionalDependencies) @@ -256,7 +256,7 @@ MaxSpeed - C:\Users\lazyhorse\Documents\github\wtl10\Include;%(AdditionalIncludeDirectories) + %(AdditionalIncludeDirectories) WIN32;_WINDOWS;STRICT;NDEBUG;%(PreprocessorDefinitions) false Async @@ -276,7 +276,7 @@ NDEBUG;%(PreprocessorDefinitions) 0x0409 - $(IntDir);C:\Users\lazyhorse\Documents\github\wtl10\Include;%(AdditionalIncludeDirectories) + $(IntDir);%(AdditionalIncludeDirectories) legacy_stdio_definitions.lib;legacy_stdio_wide_specifiers.lib;gdiplus.lib;WICLoader.lib;turbojpeg-static.lib;libpng16.lib;zlib.lib;jxl_dec.lib;jxl_threads.lib;heif.lib;libwebp.lib;libwebpdemux.lib;avif.lib;lcms2.lib;%(AdditionalDependencies) diff --git a/src/UpgradeLog.htm b/src/UpgradeLog.htm deleted file mode 100644 index a5bd6c4c..00000000 --- a/src/UpgradeLog.htm +++ /dev/null @@ -1,275 +0,0 @@ - - - - Migration Report -

- Migration Report -

\ No newline at end of file diff --git a/src/WICLoader/WICLoader.vcxproj b/src/WICLoader/WICLoader.vcxproj index ac488318..0a2ad09b 100644 --- a/src/WICLoader/WICLoader.vcxproj +++ b/src/WICLoader/WICLoader.vcxproj @@ -29,27 +29,27 @@ DynamicLibrary true Unicode - v143 + v142 DynamicLibrary true Unicode - v143 + v142 DynamicLibrary false true Unicode - v143 + v142 DynamicLibrary false true Unicode - v143 + v142 From 0048c206a466bd8af192f2a05c51beef92d0df57 Mon Sep 17 00:00:00 2001 From: Hamzah Al-washali <32926868+mez0ru@users.noreply.github.com> Date: Sun, 19 Mar 2023 18:51:08 +0800 Subject: [PATCH 04/12] Added one more check if image is corrupt. --- src/JPEGView/MainDlg.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/JPEGView/MainDlg.cpp b/src/JPEGView/MainDlg.cpp index 58945647..bbad7b02 100644 --- a/src/JPEGView/MainDlg.cpp +++ b/src/JPEGView/MainDlg.cpp @@ -667,6 +667,10 @@ void CMainDlg::DisplayErrors(CJPEGImage* pCurrentImage, const CRect& clientRect, CNLS::GetString(_T("Press ESC to exit...")), -1, &rectText, DT_CENTER | DT_WORDBREAK | DT_NOPREFIX); } } else if (pCurrentImage == NULL) { + // Access to m_pFileList is needed in this case, wait until initialized: + if (!isDone_future_m_pFileList) + future_m_pFileList.wait(); + HelpersGUI::DrawImageLoadErrorText(dc, clientRect, (m_nLastLoadError == HelpersGUI::FileLoad_SlideShowListInvalid) ? m_sStartupFile : (m_nLastLoadError == HelpersGUI::FileLoad_NoFilesInDirectory) ? m_pFileList->CurrentDirectory() : CurrentFileName(false), From 062e6b66ce5886e23057a5f6b7c535d7c51ea7f3 Mon Sep 17 00:00:00 2001 From: Hamzah Al-washali <32926868+mez0ru@users.noreply.github.com> Date: Mon, 20 Mar 2023 00:17:49 +0800 Subject: [PATCH 05/12] CFileList with async. Removed all instances of async inside MainDlg. It's now only implemented inside CFileList. Some methods needed to be overloaded like RequestImage inside JPEGProvider, so that it does not rely on fileList (during startup & Open Dialog only). --- src/JPEGView/FileList.cpp | 40 +++++++++-- src/JPEGView/FileList.h | 12 +++- src/JPEGView/JPEGProvider.cpp | 6 +- src/JPEGView/MainDlg.cpp | 125 ++-------------------------------- src/JPEGView/MainDlg.h | 4 -- 5 files changed, 54 insertions(+), 133 deletions(-) diff --git a/src/JPEGView/FileList.cpp b/src/JPEGView/FileList.cpp index 79787a0f..96162092 100644 --- a/src/JPEGView/FileList.cpp +++ b/src/JPEGView/FileList.cpp @@ -190,7 +190,7 @@ static LPCTSTR* GetSupportedFileEndingList() { CFileList::CFileList(const CString & sInitialFile, CDirectoryWatcher & directoryWatcher, Helpers::ESorting eInitialSorting, bool isSortedAscending, bool bWrapAroundFolder, int nLevel, bool forceSorting) : m_directoryWatcher(directoryWatcher) { - + m_isProcessing = true; CFileDesc::SetSorting(eInitialSorting, isSortedAscending); m_bDeleteHistory = true; m_bWrapAroundFolder = bWrapAroundFolder; @@ -217,9 +217,13 @@ CFileList::CFileList(const CString & sInitialFile, CDirectoryWatcher & directory if (!m_bIsSlideShowList) { if (bImageFile || bIsDirectory) { - FindFiles(); - m_iter = FindFile(sInitialFile); - m_iterStart = bWrapAroundFolder ? m_iter : m_fileList.begin(); + // Expensive operation, it will be run asynchronously to avoid blocking the main thread. + m_future_fileList = std::async(std::launch::async, [this, &sInitialFile, &bWrapAroundFolder]() { + FindFiles(); + m_iter = FindFile(sInitialFile); + m_iterStart = bWrapAroundFolder ? m_iter : m_fileList.begin(); + m_isProcessing = false; + }); } else { // neither image file nor directory nor list of file names - try to read anyway but normally will fail CFindFile fileFind; @@ -256,6 +260,7 @@ CString CFileList::GetSupportedFileEndings() { void CFileList::Reload(LPCTSTR sFileName, bool clearForwardHistory) { LPCTSTR sCurrent = sFileName; if (sCurrent == NULL) { + WaitIfNotReady(); // If async is still processing, then wait. sCurrent = Current(); if (sCurrent == NULL) { m_fileList.clear(); @@ -339,6 +344,9 @@ void CFileList::FileHasRenamed(LPCTSTR sOldFileName, LPCTSTR sNewFileName) { m_sInitialFile = sNewFileName; } std::list::iterator iter; + + WaitIfNotReady(); // If async is still processing, then wait. + for (iter = m_fileList.begin( ); iter != m_fileList.end( ); iter++ ) { if (_tcsicmp(sOldFileName, iter->GetName()) == 0) { iter->SetName(sNewFileName); @@ -347,6 +355,8 @@ void CFileList::FileHasRenamed(LPCTSTR sOldFileName, LPCTSTR sNewFileName) { } void CFileList::ModificationTimeChanged() { + WaitIfNotReady(); // If async is still processing, then wait. + if (m_iter != m_fileList.end()) { LPCTSTR sName = m_iter->GetName(); HANDLE hFile = ::CreateFile(sName, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL); @@ -362,6 +372,8 @@ void CFileList::ModificationTimeChanged() { CFileList* CFileList::Next() { m_nMarkedIndexShow = -1; + WaitIfNotReady(); // If async is still processing, then wait. + if (m_fileList.size() > 0) { std::list::iterator iterTemp = m_iter; if (iterTemp == m_fileList.end()) @@ -402,6 +414,8 @@ CFileList* CFileList::Next() { CFileList* CFileList::Prev() { m_nMarkedIndexShow = -1; + WaitIfNotReady(); // If async is still processing, then wait. + if (m_iter == m_iterStart) { if (sm_eMode == Helpers::NM_LoopDirectory) { if (!m_bWrapAroundFolder) { @@ -429,17 +443,23 @@ CFileList* CFileList::Prev() { } void CFileList::First() { + WaitIfNotReady(); // If async is still processing, then wait. + m_nMarkedIndexShow = -1; m_iter = m_iterStart = m_fileList.begin(); } void CFileList::Last() { + WaitIfNotReady(); // If async is still processing, then wait. + m_nMarkedIndexShow = -1; MoveIterToLast(); m_iterStart = m_fileList.begin(); } CFileList* CFileList::AwayFromCurrent() { + WaitIfNotReady(); // If async is still processing, then wait. + LPCTSTR sCurrentFile = Current(); LPCTSTR sNextFile = PeekNextPrev(1, true, false); if (sCurrentFile == NULL || sNextFile == NULL || _tcscmp(sCurrentFile, sNextFile) == 0) { @@ -455,7 +475,10 @@ CFileList* CFileList::AwayFromCurrent() { } LPCTSTR CFileList::Current() const { - if (m_iter != m_fileList.end()) { + if (m_isProcessing) { // Most likely CFileList is being inialized, thus it's probably the initial file being requested. + return m_sInitialFile; + } + else if (m_iter != m_fileList.end()) { return m_iter->GetName(); } else { return NULL; @@ -505,6 +528,8 @@ LPCTSTR CFileList::PeekNextPrev(int nIndex, bool bForward, bool bToggle) { if (bToggle) { return (m_nMarkedIndexShow == 0) ? m_sMarkedFile : m_sMarkedFileCurrent; } else { + WaitIfNotReady(); // If async is still processing, then wait. + std::list::iterator thisIter = m_iter; LPCTSTR sFileName; if (nIndex != 0) { @@ -998,3 +1023,8 @@ bool CFileList::TryReadingSlideShowList(const CString & sSlideShowFile) { delete[] fileBuffOrig; return true; } + +void CFileList::WaitIfNotReady() { + if (m_isProcessing) + m_future_fileList.wait(); +} \ No newline at end of file diff --git a/src/JPEGView/FileList.h b/src/JPEGView/FileList.h index 50f8e6cf..f05efde9 100644 --- a/src/JPEGView/FileList.h +++ b/src/JPEGView/FileList.h @@ -1,6 +1,7 @@ #pragma once #include "Helpers.h" +#include class CDirectoryWatcher; @@ -120,7 +121,10 @@ class CFileList void ToggleBetweenMarkedAndCurrentFile(); // Sets a checkpoint on the current image - void SetCheckpoint() { m_iterCheckPoint = m_iter; } + void SetCheckpoint() { + WaitIfNotReady(); + m_iterCheckPoint = m_iter; + } // Check if we are now on another image since the last checkpoint was set bool ChangedSinceCheckpoint() { return m_iterCheckPoint != m_iter; } @@ -145,6 +149,8 @@ class CFileList // delete the chain of CFileLists forward and backward and only leave the current node alive void DeleteHistory(bool onlyForward = false); + void WaitIfNotReady(); + private: static Helpers::ENavigationMode sm_eMode; @@ -162,6 +168,10 @@ class CFileList std::list::iterator m_iterStart; // start of iteration in m_fileList std::list::iterator m_iterCheckPoint; + // Async + std::future m_future_fileList; + bool m_isProcessing; + CString m_sMarkedFile; CString m_sMarkedFileCurrent; int m_nMarkedIndexShow; diff --git a/src/JPEGView/JPEGProvider.cpp b/src/JPEGView/JPEGProvider.cpp index b541c26f..6b9fecda 100644 --- a/src/JPEGView/JPEGProvider.cpp +++ b/src/JPEGView/JPEGProvider.cpp @@ -123,6 +123,7 @@ void CJPEGProvider::NotifyNotUsed(CJPEGImage* pImage) { if (pImage != NULL) delete pImage; } +// Only used for startup, to avoid accessing m_fileList. CJPEGImage* CJPEGProvider::RequestImage(EReadAheadDirection eDirection, LPCTSTR strFileName, int nFrameIndex, const CProcessParams& processParams, bool& bOutOfMemory, bool& bExceptionError) { @@ -142,11 +143,6 @@ CJPEGImage* CJPEGProvider::RequestImage(EReadAheadDirection eDirection, if (pRequest == NULL) { // no request pending for this file, add to request queue and start async pRequest = StartNewRequest(strFileName, nFrameIndex, processParams); - // wait with read ahead when direction changed - maybe user just wants to re-see last image - //if (!bDirectionChanged && eDirection != NONE) { - // // start parallel if more than one thread - // StartNewRequestBundle(pFileList, eDirection, processParams, m_nNumThread - 1, NULL); - //} } // wait for request if not yet ready diff --git a/src/JPEGView/MainDlg.cpp b/src/JPEGView/MainDlg.cpp index bbad7b02..e0e27819 100644 --- a/src/JPEGView/MainDlg.cpp +++ b/src/JPEGView/MainDlg.cpp @@ -52,7 +52,6 @@ #include "DirectoryWatcher.h" #include "DesktopWallpaper.h" #include "PrintImage.h" -#include ////////////////////////////////////////////////////////////////////////////////////////////// // Constants @@ -285,8 +284,6 @@ CMainDlg::CMainDlg(bool bForceFullScreen) { CMainDlg::~CMainDlg() { delete m_pDirectoryWatcher; - if (isDone_future_m_pFileList) - delete m_pFileList; if (m_pJPEGProvider != NULL) delete m_pJPEGProvider; delete m_pImageProcParams; delete m_pImageProcParamsKept; @@ -383,14 +380,10 @@ LRESULT CMainDlg::OnInitDialog(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam // m_pFileList->SetNavigationMode(sp.Navigation()); // }).detach(); - isDone_future_m_pFileList = false; - future_m_pFileList = std::async(std::launch::async, [this, &sp]() { - m_pFileList = new CFileList(m_sStartupFile, *m_pDirectoryWatcher, - (m_eForcedSorting == Helpers::FS_Undefined) ? sp.Sorting() : m_eForcedSorting, sp.IsSortedAscending(), sp.WrapAroundFolder(), - 0, m_eForcedSorting != Helpers::FS_Undefined); - m_pFileList->SetNavigationMode(sp.Navigation()); - isDone_future_m_pFileList = true; - }); + m_pFileList = new CFileList(m_sStartupFile, *m_pDirectoryWatcher, + (m_eForcedSorting == Helpers::FS_Undefined) ? sp.Sorting() : m_eForcedSorting, sp.IsSortedAscending(), sp.WrapAroundFolder(), + 0, m_eForcedSorting != Helpers::FS_Undefined); + m_pFileList->SetNavigationMode(sp.Navigation()); // create thread pool for processing requests on multiple CPU cores CProcessingThreadPool::This().CreateThreadPoolThreads(); @@ -405,7 +398,7 @@ LRESULT CMainDlg::OnInitDialog(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam } m_nLastLoadError = GetLoadErrorAfterOpenFile(); CheckIfApplyAutoFitWndToImage(true); - AfterNewImageLoaded(true, true, false, m_sStartupFile); // synchronize to per image parameters + AfterNewImageLoaded(true, true, false); // synchronize to per image parameters if (!m_bFullScreenMode) { // Window mode, set correct window size @@ -667,10 +660,6 @@ void CMainDlg::DisplayErrors(CJPEGImage* pCurrentImage, const CRect& clientRect, CNLS::GetString(_T("Press ESC to exit...")), -1, &rectText, DT_CENTER | DT_WORDBREAK | DT_NOPREFIX); } } else if (pCurrentImage == NULL) { - // Access to m_pFileList is needed in this case, wait until initialized: - if (!isDone_future_m_pFileList) - future_m_pFileList.wait(); - HelpersGUI::DrawImageLoadErrorText(dc, clientRect, (m_nLastLoadError == HelpersGUI::FileLoad_SlideShowListInvalid) ? m_sStartupFile : (m_nLastLoadError == HelpersGUI::FileLoad_NoFilesInDirectory) ? m_pFileList->CurrentDirectory() : CurrentFileName(false), @@ -976,8 +965,6 @@ LRESULT CMainDlg::OnKeyDown(UINT /*uMsg*/, WPARAM wParam, LPARAM /*lParam*/, BOO m_pCropCtl->AbortCropping(); } else if (!bCtrl && wParam != VK_ESCAPE && m_nLastLoadError == HelpersGUI::FileLoad_NoFilesInDirectory && !m_sStartupFile.IsEmpty()) { // search in subfolders if initial directory has no images - if (!isDone_future_m_pFileList) - future_m_pFileList.wait(); // Check if m_pFileList is available first before using. bHandled = true; m_pFileList->SetNavigationMode(Helpers::NM_LoopSubDirectories); GotoImage(POS_Next); @@ -1006,8 +993,6 @@ LRESULT CMainDlg::OnKeyDown(UINT /*uMsg*/, WPARAM wParam, LPARAM /*lParam*/, BOO if (!bHandled) { // look if any of the user commands wants to handle this key - if (!isDone_future_m_pFileList) - future_m_pFileList.wait(); // Check if m_pFileList is available first before using. if (m_pFileList->Current() != NULL) { HandleUserCommands(CKeyMap::GetCombinedKeyCode((int)wParam, bAlt, bCtrl, bShift)); } @@ -1359,15 +1344,11 @@ void CMainDlg::ExecuteCommand(int nCommand) { MouseOn(); break; case IDM_TOGGLE: - if (!isDone_future_m_pFileList) - future_m_pFileList.wait(); if (m_pFileList->FileMarkedForToggle()) { GotoImage(POS_Toggle); } break; case IDM_MARK_FOR_TOGGLE: - if (!isDone_future_m_pFileList) - future_m_pFileList.wait(); if (m_pFileList->Current() != NULL && m_pCurrentImage != NULL && !m_pCurrentImage->IsClipboardImage()) { m_pFileList->MarkCurrentFile(); } @@ -1403,8 +1384,6 @@ void CMainDlg::ExecuteCommand(int nCommand) { case IDM_PRINT: if (m_pCurrentImage != NULL) { StopAnimation(); // stop any running animation - if (!isDone_future_m_pFileList) - future_m_pFileList.wait(); if (m_pPrintImage->Print(this->m_hWnd, m_pCurrentImage, *m_pImageProcParams, CreateDefaultProcessingFlags(), m_pFileList->Current())) { this->Invalidate(FALSE); } @@ -1412,23 +1391,17 @@ void CMainDlg::ExecuteCommand(int nCommand) { break; case IDM_COPY: if (m_pCurrentImage != NULL) { - if (!isDone_future_m_pFileList) - future_m_pFileList.wait(); CClipboard::CopyImageToClipboard(this->m_hWnd, m_pCurrentImage, m_pFileList->Current()); } break; case IDM_COPY_FULL: if (m_pCurrentImage != NULL) { - if (!isDone_future_m_pFileList) - future_m_pFileList.wait(); CClipboard::CopyFullImageToClipboard(this->m_hWnd, m_pCurrentImage, *m_pImageProcParams, CreateDefaultProcessingFlags(), m_pFileList->Current()); this->Invalidate(FALSE); } break; case IDM_COPY_PATH: if (m_pCurrentImage != NULL && !m_pCurrentImage->IsClipboardImage()) { - if (!isDone_future_m_pFileList) - future_m_pFileList.wait(); CClipboard::CopyPathToClipboard(this->m_hWnd, m_pCurrentImage, m_pFileList->Current()); } break; @@ -1449,8 +1422,6 @@ void CMainDlg::ExecuteCommand(int nCommand) { case IDM_MOVE_TO_RECYCLE_BIN_CONFIRM: case IDM_MOVE_TO_RECYCLE_BIN_CONFIRM_PERMANENT_DELETE: MouseOn(); - if (!isDone_future_m_pFileList) - future_m_pFileList.wait(); if (m_pCurrentImage != NULL && m_pFileList != NULL && !m_pCurrentImage->IsClipboardImage() && sp.AllowFileDeletion()) { LPCTSTR currentFileName = CurrentFileName(false); bool noConfirmation = nCommand == IDM_MOVE_TO_RECYCLE_BIN || @@ -1484,30 +1455,20 @@ void CMainDlg::ExecuteCommand(int nCommand) { m_pNavPanelCtl->SetActive(!m_pNavPanelCtl->IsActive()); break; case IDM_NEXT: - if (!isDone_future_m_pFileList) - future_m_pFileList.wait(); // Check if m_pFileList is available first before using. GotoImage(POS_Next); break; case IDM_PREV: - if (!isDone_future_m_pFileList) - future_m_pFileList.wait(); // Check if m_pFileList is available first before using. GotoImage(POS_Previous); break; case IDM_FIRST: - if (!isDone_future_m_pFileList) - future_m_pFileList.wait(); // Check if m_pFileList is available first before using. GotoImage(POS_First); break; case IDM_LAST: - if (!isDone_future_m_pFileList) - future_m_pFileList.wait(); // Check if m_pFileList is available first before using. GotoImage(POS_Last); break; case IDM_LOOP_FOLDER: case IDM_LOOP_RECURSIVELY: case IDM_LOOP_SIBLINGS: - if (!isDone_future_m_pFileList) - future_m_pFileList.wait(); m_pFileList->SetNavigationMode( (nCommand == IDM_LOOP_FOLDER) ? Helpers::NM_LoopDirectory : (nCommand == IDM_LOOP_RECURSIVELY) ? Helpers::NM_LoopSubDirectories : @@ -1518,8 +1479,6 @@ void CMainDlg::ExecuteCommand(int nCommand) { case IDM_SORT_NAME: case IDM_SORT_RANDOM: case IDM_SORT_SIZE: - if (!isDone_future_m_pFileList) - future_m_pFileList.wait(); m_pFileList->SetSorting( (nCommand == IDM_SORT_CREATION_DATE) ? Helpers::FS_CreationTime : (nCommand == IDM_SORT_MOD_DATE) ? Helpers::FS_LastModTime : @@ -1531,8 +1490,6 @@ void CMainDlg::ExecuteCommand(int nCommand) { break; case IDM_SORT_ASCENDING: case IDM_SORT_DESCENDING: - if (!isDone_future_m_pFileList) - future_m_pFileList.wait(); m_pFileList->SetSorting(m_pFileList->GetSorting(), nCommand == IDM_SORT_ASCENDING); if (m_pEXIFDisplayCtl->IsActive() || m_bShowFileName) { this->Invalidate(FALSE); @@ -1608,8 +1565,6 @@ void CMainDlg::ExecuteCommand(int nCommand) { if (CParameterDB::This().DeleteEntry(m_pCurrentImage->GetPixelHash())) { // restore initial parameters and realize the parameters EProcessingFlags procFlags = GetDefaultProcessingFlags(m_bLandscapeMode); - if (!isDone_future_m_pFileList) - future_m_pFileList.wait(); m_pCurrentImage->RestoreInitialParameters(m_pFileList->Current(), GetDefaultProcessingParams(), procFlags, 0, -1, CPoint(0, 0), CSize(0, 0), CSize(0, 0)); *m_pImageProcParams = GetDefaultProcessingParams(); @@ -1700,8 +1655,6 @@ void CMainDlg::ExecuteCommand(int nCommand) { sConfirmMsg, CNLS::GetString(_T("Confirm")), MB_YESNOCANCEL | MB_ICONWARNING); } if (bPerformTransformation) { - if (!isDone_future_m_pFileList) - future_m_pFileList.wait(); CJPEGLosslessTransform::EResult eResult = CJPEGLosslessTransform::PerformTransformation(m_pFileList->Current(), m_pFileList->Current(), HelpersGUI::CommandIdToLosslessTransformation(nCommand), bCrop || sp.CropWithoutPromptLosslessJPEG()); if (eResult != CJPEGLosslessTransform::Success) { @@ -1743,8 +1696,6 @@ void CMainDlg::ExecuteCommand(int nCommand) { EProcessingFlags eProcFlags = GetDefaultProcessingFlags(false); CImageProcessingParams ipa = GetDefaultProcessingParams(); if (m_pCurrentImage != NULL) { - if (!isDone_future_m_pFileList) - future_m_pFileList.wait(); m_pCurrentImage->GetFileParams(m_pFileList->Current(), eProcFlags, ipa); } m_bLDC = GetProcessingFlag(eProcFlags, PFLAG_LDC); @@ -2062,8 +2013,6 @@ void CMainDlg::ExecuteCommand(int nCommand) { bOk = EXIFHelpers::SetModificationDate(strFileName, st); } if (bOk) { - if (!isDone_future_m_pFileList) - future_m_pFileList.wait(); m_pFileList->ModificationTimeChanged(); if (m_pEXIFDisplayCtl->IsActive()) { this->Invalidate(FALSE); @@ -2200,18 +2149,11 @@ void CMainDlg::OpenFile(LPCTSTR sFileName, bool bAfterStartup) { StopMovieMode(); StopAnimation(); // recreate file list based on image opened - if (!isDone_future_m_pFileList) - future_m_pFileList.wait(); Helpers::ESorting eOldSorting = m_pFileList->GetSorting(); bool oOldAscending = m_pFileList->IsSortedAscending(); delete m_pFileList; m_sStartupFile = sFileName; - //m_pFileList = new CFileList(m_sStartupFile, *m_pDirectoryWatcher, eOldSorting, oOldAscending, CSettingsProvider::This().WrapAroundFolder()); - isDone_future_m_pFileList = false; - future_m_pFileList = std::async(std::launch::async, [this, eOldSorting, oOldAscending]() { - m_pFileList = new CFileList(m_sStartupFile, *m_pDirectoryWatcher, eOldSorting, oOldAscending, CSettingsProvider::This().WrapAroundFolder()); - isDone_future_m_pFileList = true; - }); + m_pFileList = new CFileList(m_sStartupFile, *m_pDirectoryWatcher, eOldSorting, oOldAscending, CSettingsProvider::This().WrapAroundFolder()); // free current image and all read ahead images InitParametersForNewImage(); @@ -2222,7 +2164,7 @@ void CMainDlg::OpenFile(LPCTSTR sFileName, bool bAfterStartup) { m_bOutOfMemoryLastImage, m_bExceptionErrorLastImage); m_nLastLoadError = GetLoadErrorAfterOpenFile(); if (bAfterStartup) CheckIfApplyAutoFitWndToImage(false); - AfterNewImageLoaded(true, false, false, m_sStartupFile); + AfterNewImageLoaded(true, false, false); if (m_pCurrentImage != NULL && m_pCurrentImage->IsAnimation()) { StartAnimation(); } @@ -3100,59 +3042,6 @@ void CMainDlg::AfterNewImageLoaded(bool bSynchronize, bool bAfterStartup, bool n } } -void CMainDlg::AfterNewImageLoaded(bool bSynchronize, bool bAfterStartup, bool noAdjustWindow, LPCTSTR fileName) { - UpdateWindowTitle(fileName); - InvalidateHelpDlg(); - m_pDirectoryWatcher->SetCurrentFile(fileName); - if (!m_bIsAnimationPlaying) m_pNavPanelCtl->HideNavPanelTemporary(); - //m_pPanelMgr->AfterNewImageLoaded(); - m_pCropCtl->AbortCropping(); - if (m_pCurrentImage != NULL) m_pCropCtl->SetImageSize(m_pCurrentImage->OrigSize()); // inform CropCtl of the image size for CropImageAR - m_pPrintImage->ClearOffsets(); - if (bSynchronize) { - // after loading an image, the per image processing parameters must be synchronized with - // the current processing parameters - bool bLastWasSpecialProcessing = m_bCurrentImageIsSpecialProcessing; - bool bLastWasInParamDB = m_bCurrentImageInParamDB; - m_bCurrentImageInParamDB = false; - m_bCurrentImageIsSpecialProcessing = false; - if (m_pCurrentImage != NULL) { - m_dCurrentInitialLightenShadows = m_pCurrentImage->GetInitialProcessParams().LightenShadows; - m_bCurrentImageInParamDB = m_pCurrentImage->IsInParamDB(); - m_bCurrentImageIsSpecialProcessing = m_pCurrentImage->GetLightenShadowFactor() != 1.0f; - if (!m_bKeepParams) { - m_bHQResampling = GetProcessingFlag(m_pCurrentImage->GetInitialProcessFlags(), PFLAG_HighQualityResampling); - m_bAutoContrast = GetProcessingFlag(m_pCurrentImage->GetInitialProcessFlags(), PFLAG_AutoContrast); - m_bLDC = GetProcessingFlag(m_pCurrentImage->GetInitialProcessFlags(), PFLAG_LDC); - - m_nRotation = m_pCurrentImage->GetInitialRotation(); - m_dZoom = m_pCurrentImage->GetInititialZoom(); - m_offsets = m_pCurrentImage->GetInitialOffsets(); - - if (m_pCurrentImage->HasZoomStoredInParamDB()) { - m_bUserZoom = m_bUserPan = true; - } - - *m_pImageProcParams = m_pCurrentImage->GetInitialProcessParams(); - } - else if (m_bCurrentImageIsSpecialProcessing && m_bKeepParams) { - // set this factor, no matter if we keep parameters - m_pImageProcParams->LightenShadows = m_pCurrentImage->GetInitialProcessParams().LightenShadows; - } - else if (bLastWasSpecialProcessing && m_bKeepParams) { - // take kept value when last was special processing as the special processing value is not usable - m_pImageProcParams->LightenShadows = m_pImageProcParamsKept->LightenShadows; - } - if (m_bKeepParams) { - m_nRotation = m_pCurrentImage->GetInitialRotation() + m_nUserRotation; - } - } - if (!bAfterStartup && !m_bIsAnimationPlaying && !noAdjustWindow) { - AdjustWindowToImage(false); - } - } -} - bool CMainDlg::IsAdjustWindowToImage() { return !m_bFullScreenMode && !::IsZoomed(m_hWnd) && m_bAutoFitWndToImage; } diff --git a/src/JPEGView/MainDlg.h b/src/JPEGView/MainDlg.h index 47475e1c..5a9061bb 100644 --- a/src/JPEGView/MainDlg.h +++ b/src/JPEGView/MainDlg.h @@ -7,7 +7,6 @@ #include "ProcessParams.h" #include "Helpers.h" #include "CropCtl.h" -#include class CFileList; class CJPEGProvider; @@ -232,8 +231,6 @@ class CMainDlg : public CDialogImpl Helpers::ESorting m_eForcedSorting; // forced sorting mode on command line CFileList* m_pFileList; // used for navigation - std::future future_m_pFileList; // check if m_pFileList loaded successfully before accessing the original variable. - bool isDone_future_m_pFileList = true; CDirectoryWatcher* m_pDirectoryWatcher; // notifies the main window when the current file changed or a file in the current directory was added or deleted CJPEGProvider * m_pJPEGProvider; // reads image (of any format, not only JPEGs) files, using read ahead @@ -366,7 +363,6 @@ class CMainDlg : public CDialogImpl void ExchangeProcessingParams(); void SaveParameters(); void AfterNewImageLoaded(bool bSynchronize, bool bAfterStartup, bool noAdjustWindow); - void AfterNewImageLoaded(bool bSynchronize, bool bAfterStartup, bool noAdjustWindow, LPCTSTR fileName); CRect ScreenToDIB(const CSize& sizeDIB, const CRect& rect); void ToggleMonitor(); CRect GetZoomTextRect(CRect imageProcessingArea); From a4e25b418bbd9d0179df1cb738cc400cbd93b1c2 Mon Sep 17 00:00:00 2001 From: Hamzah Al-washali <32926868+mez0ru@users.noreply.github.com> Date: Mon, 20 Mar 2023 00:51:02 +0800 Subject: [PATCH 06/12] Removed dead code. --- src/JPEGView/MainDlg.cpp | 33 +-------------------------------- src/JPEGView/MainDlg.h | 5 ----- 2 files changed, 1 insertion(+), 37 deletions(-) diff --git a/src/JPEGView/MainDlg.cpp b/src/JPEGView/MainDlg.cpp index e0e27819..16d08b0f 100644 --- a/src/JPEGView/MainDlg.cpp +++ b/src/JPEGView/MainDlg.cpp @@ -369,17 +369,6 @@ LRESULT CMainDlg::OnInitDialog(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam m_bMouseOn = !m_bFullScreenMode; ::ShowCursor(m_bMouseOn); - // intitialize list of files to show with startup file (and folder) - //m_pFileList = new CFileList(m_sStartupFile, *m_pDirectoryWatcher, - // (m_eForcedSorting == Helpers::FS_Undefined) ? sp.Sorting() : m_eForcedSorting, sp.IsSortedAscending(), sp.WrapAroundFolder(), - // 0, m_eForcedSorting != Helpers::FS_Undefined); - //std::thread([&, this]() { - // m_pFileList = new CFileList(m_sStartupFile, *m_pDirectoryWatcher, - // (m_eForcedSorting == Helpers::FS_Undefined) ? sp.Sorting() : m_eForcedSorting, sp.IsSortedAscending(), sp.WrapAroundFolder(), - // 0, m_eForcedSorting != Helpers::FS_Undefined); - // m_pFileList->SetNavigationMode(sp.Navigation()); - // }).detach(); - m_pFileList = new CFileList(m_sStartupFile, *m_pDirectoryWatcher, (m_eForcedSorting == Helpers::FS_Undefined) ? sp.Sorting() : m_eForcedSorting, sp.IsSortedAscending(), sp.WrapAroundFolder(), 0, m_eForcedSorting != Helpers::FS_Undefined); @@ -392,7 +381,7 @@ LRESULT CMainDlg::OnInitDialog(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam m_pJPEGProvider = new CJPEGProvider(m_hWnd, NUM_THREADS, READ_AHEAD_BUFFERS); if (!m_sStartupFile.IsEmpty()) m_pCurrentImage = m_pJPEGProvider->RequestImage(CJPEGProvider::FORWARD, - m_sStartupFile, 0, CreateProcessParams(!m_bFullScreenMode), m_bOutOfMemoryLastImage, m_bExceptionErrorLastImage); + m_pFileList->Current(), 0, CreateProcessParams(!m_bFullScreenMode), m_bOutOfMemoryLastImage, m_bExceptionErrorLastImage); if (m_pCurrentImage != NULL && m_pCurrentImage->IsAnimation()) { StartAnimation(); } @@ -3254,26 +3243,6 @@ void CMainDlg::UpdateWindowTitle() { } } -void CMainDlg::UpdateWindowTitle(LPCTSTR sCurrentFileName) { - bool bShowFullPathInTitle = CSettingsProvider::This().ShowFullPathInTitle(); - - if (sCurrentFileName == NULL || m_pCurrentImage == NULL) { - this->SetWindowText(_T(JPEGVIEW_TITLE)); - } - else { - CString sWindowText = sCurrentFileName; - sWindowText += Helpers::GetMultiframeIndex(m_pCurrentImage); - if (CSettingsProvider::This().ShowEXIFDateInTitle()) { - CEXIFReader* pEXIF = m_pCurrentImage->GetEXIFReader(); - if (pEXIF != NULL && pEXIF->GetAcquisitionTime().wYear > 1600) { - sWindowText += " - " + Helpers::SystemTimeToString(pEXIF->GetAcquisitionTime()); - } - } - sWindowText += " - " + CString(JPEGVIEW_TITLE); - this->SetWindowText(sWindowText); - } -} - bool CMainDlg::PrepareForModalPanel() { m_pImageProcPanelCtl->SetVisible(false); bool bOldShowNavPanel = m_pNavPanelCtl->IsActive(); diff --git a/src/JPEGView/MainDlg.h b/src/JPEGView/MainDlg.h index 5a9061bb..0332ecb4 100644 --- a/src/JPEGView/MainDlg.h +++ b/src/JPEGView/MainDlg.h @@ -194,7 +194,6 @@ class CMainDlg : public CDialogImpl void BlendBlackRect(CDC & targetDC, CPanel& panel, float fBlendFactor); void UpdateWindowTitle(); - void UpdateWindowTitle(LPCTSTR fileName); void MouseOff(); void MouseOn(); void GotoImage(EImagePosition ePos); @@ -229,9 +228,7 @@ class CMainDlg : public CDialogImpl int m_nAutoStartSlideShow; // if positive: Auto start slide show with given interval in seconds, passed on command line bool m_bAutoExit; Helpers::ESorting m_eForcedSorting; // forced sorting mode on command line - CFileList* m_pFileList; // used for navigation - CDirectoryWatcher* m_pDirectoryWatcher; // notifies the main window when the current file changed or a file in the current directory was added or deleted CJPEGProvider * m_pJPEGProvider; // reads image (of any format, not only JPEGs) files, using read ahead CJPEGImage * m_pCurrentImage; // currently displayed image @@ -382,6 +379,4 @@ class CMainDlg : public CDialogImpl void StartAnimation(); void AdjustAnimationFrameTime(); void StopAnimation(); - - // Wait for future to finish function }; From 0128c51f75bb70d342b8153f0930ebda559a0697 Mon Sep 17 00:00:00 2001 From: Hamzah Al-washali <32926868+mez0ru@users.noreply.github.com> Date: Mon, 20 Mar 2023 00:57:21 +0800 Subject: [PATCH 07/12] Corrections --- src/JPEGView/MainDlg.cpp | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/src/JPEGView/MainDlg.cpp b/src/JPEGView/MainDlg.cpp index 16d08b0f..d1620462 100644 --- a/src/JPEGView/MainDlg.cpp +++ b/src/JPEGView/MainDlg.cpp @@ -284,6 +284,7 @@ CMainDlg::CMainDlg(bool bForceFullScreen) { CMainDlg::~CMainDlg() { delete m_pDirectoryWatcher; + delete m_pFileList; if (m_pJPEGProvider != NULL) delete m_pJPEGProvider; delete m_pImageProcParams; delete m_pImageProcParamsKept; @@ -370,8 +371,8 @@ LRESULT CMainDlg::OnInitDialog(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam ::ShowCursor(m_bMouseOn); m_pFileList = new CFileList(m_sStartupFile, *m_pDirectoryWatcher, - (m_eForcedSorting == Helpers::FS_Undefined) ? sp.Sorting() : m_eForcedSorting, sp.IsSortedAscending(), sp.WrapAroundFolder(), - 0, m_eForcedSorting != Helpers::FS_Undefined); + (m_eForcedSorting == Helpers::FS_Undefined) ? sp.Sorting() : m_eForcedSorting, sp.IsSortedAscending(), sp.WrapAroundFolder(), + 0, m_eForcedSorting != Helpers::FS_Undefined); m_pFileList->SetNavigationMode(sp.Navigation()); // create thread pool for processing requests on multiple CPU cores @@ -2161,9 +2162,6 @@ void CMainDlg::OpenFile(LPCTSTR sFileName, bool bAfterStartup) { m_sSaveDirectory = _T(""); MouseOff(); this->Invalidate(FALSE); - //std::thread([&, this]() { - // m_pFileList = new CFileList(m_sStartupFile, *m_pDirectoryWatcher, eOldSorting, oOldAscending, CSettingsProvider::This().WrapAroundFolder()); - // }).detach(); } bool CMainDlg::SaveImage(bool bFullSize) { @@ -3264,9 +3262,9 @@ int CMainDlg::TrackPopupMenu(CPoint pos, HMENU hMenu) { int CMainDlg::GetLoadErrorAfterOpenFile() { if (m_pCurrentImage == NULL) { if (CurrentFileName(false) == NULL) { - //if (m_pFileList->IsSlideShowList()) { - // return HelpersGUI::FileLoad_SlideShowListInvalid; - //} + if (m_pFileList->IsSlideShowList()) { + return HelpersGUI::FileLoad_SlideShowListInvalid; + } return HelpersGUI::FileLoad_NoFilesInDirectory; } return HelpersGUI::FileLoad_LoadError; From 7bff3d7db7b0c9b126af903afcfdcd1ca6c07356 Mon Sep 17 00:00:00 2001 From: Hamzah Al-washali <32926868+mez0ru@users.noreply.github.com> Date: Mon, 20 Mar 2023 16:49:47 +0800 Subject: [PATCH 08/12] Using inline --- src/JPEGView/FileList.cpp | 5 ----- src/JPEGView/FileList.h | 5 ++++- src/JPEGView/MainDlg.cpp | 11 ++++++----- 3 files changed, 10 insertions(+), 11 deletions(-) diff --git a/src/JPEGView/FileList.cpp b/src/JPEGView/FileList.cpp index 96162092..b756133c 100644 --- a/src/JPEGView/FileList.cpp +++ b/src/JPEGView/FileList.cpp @@ -1022,9 +1022,4 @@ bool CFileList::TryReadingSlideShowList(const CString & sSlideShowFile) { fclose(fptr); delete[] fileBuffOrig; return true; -} - -void CFileList::WaitIfNotReady() { - if (m_isProcessing) - m_future_fileList.wait(); } \ No newline at end of file diff --git a/src/JPEGView/FileList.h b/src/JPEGView/FileList.h index f05efde9..7b9c3aa2 100644 --- a/src/JPEGView/FileList.h +++ b/src/JPEGView/FileList.h @@ -149,7 +149,10 @@ class CFileList // delete the chain of CFileLists forward and backward and only leave the current node alive void DeleteHistory(bool onlyForward = false); - void WaitIfNotReady(); + inline void CFileList::WaitIfNotReady() { + if (m_isProcessing) + m_future_fileList.wait(); + } private: static Helpers::ENavigationMode sm_eMode; diff --git a/src/JPEGView/MainDlg.cpp b/src/JPEGView/MainDlg.cpp index d1620462..0e3adbe8 100644 --- a/src/JPEGView/MainDlg.cpp +++ b/src/JPEGView/MainDlg.cpp @@ -370,19 +370,20 @@ LRESULT CMainDlg::OnInitDialog(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam m_bMouseOn = !m_bFullScreenMode; ::ShowCursor(m_bMouseOn); + // intitialize list of files to show with startup file (and folder) m_pFileList = new CFileList(m_sStartupFile, *m_pDirectoryWatcher, - (m_eForcedSorting == Helpers::FS_Undefined) ? sp.Sorting() : m_eForcedSorting, sp.IsSortedAscending(), sp.WrapAroundFolder(), - 0, m_eForcedSorting != Helpers::FS_Undefined); + (m_eForcedSorting == Helpers::FS_Undefined) ? sp.Sorting() : m_eForcedSorting, sp.IsSortedAscending(), sp.WrapAroundFolder(), + 0, m_eForcedSorting != Helpers::FS_Undefined); m_pFileList->SetNavigationMode(sp.Navigation()); - + // create thread pool for processing requests on multiple CPU cores CProcessingThreadPool::This().CreateThreadPoolThreads(); // create JPEG provider and request first image - do no processing yet if not in fullscreen mode (as we do not know the size yet) m_pJPEGProvider = new CJPEGProvider(m_hWnd, NUM_THREADS, READ_AHEAD_BUFFERS); if (!m_sStartupFile.IsEmpty()) - m_pCurrentImage = m_pJPEGProvider->RequestImage(CJPEGProvider::FORWARD, - m_pFileList->Current(), 0, CreateProcessParams(!m_bFullScreenMode), m_bOutOfMemoryLastImage, m_bExceptionErrorLastImage); + m_pCurrentImage = m_pJPEGProvider->RequestImage(CJPEGProvider::FORWARD, + m_pFileList->Current(), 0, CreateProcessParams(!m_bFullScreenMode), m_bOutOfMemoryLastImage, m_bExceptionErrorLastImage); if (m_pCurrentImage != NULL && m_pCurrentImage->IsAnimation()) { StartAnimation(); } From aac36ed9736b2689e7c6643226d4a872b4aced9b Mon Sep 17 00:00:00 2001 From: Hamzah Al-washali <32926868+mez0ru@users.noreply.github.com> Date: Mon, 20 Mar 2023 21:07:49 +0800 Subject: [PATCH 09/12] Bug fix m_isProcessing is true only when it's inside the same scope as the async function. --- src/JPEGView/FileList.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/JPEGView/FileList.cpp b/src/JPEGView/FileList.cpp index b756133c..9b480085 100644 --- a/src/JPEGView/FileList.cpp +++ b/src/JPEGView/FileList.cpp @@ -190,7 +190,7 @@ static LPCTSTR* GetSupportedFileEndingList() { CFileList::CFileList(const CString & sInitialFile, CDirectoryWatcher & directoryWatcher, Helpers::ESorting eInitialSorting, bool isSortedAscending, bool bWrapAroundFolder, int nLevel, bool forceSorting) : m_directoryWatcher(directoryWatcher) { - m_isProcessing = true; + m_isProcessing = false; CFileDesc::SetSorting(eInitialSorting, isSortedAscending); m_bDeleteHistory = true; m_bWrapAroundFolder = bWrapAroundFolder; @@ -218,6 +218,7 @@ CFileList::CFileList(const CString & sInitialFile, CDirectoryWatcher & directory if (!m_bIsSlideShowList) { if (bImageFile || bIsDirectory) { // Expensive operation, it will be run asynchronously to avoid blocking the main thread. + m_isProcessing = true; m_future_fileList = std::async(std::launch::async, [this, &sInitialFile, &bWrapAroundFolder]() { FindFiles(); m_iter = FindFile(sInitialFile); From b83a9a07f155eec12ca9b0f41228cec1dd876738 Mon Sep 17 00:00:00 2001 From: Hamzah Al-washali <32926868+mez0ru@users.noreply.github.com> Date: Mon, 20 Mar 2023 22:36:48 +0800 Subject: [PATCH 10/12] Reduced unnecessary async checks. --- src/JPEGView/FileList.cpp | 9 --------- 1 file changed, 9 deletions(-) diff --git a/src/JPEGView/FileList.cpp b/src/JPEGView/FileList.cpp index 9b480085..46f9bda2 100644 --- a/src/JPEGView/FileList.cpp +++ b/src/JPEGView/FileList.cpp @@ -373,8 +373,6 @@ void CFileList::ModificationTimeChanged() { CFileList* CFileList::Next() { m_nMarkedIndexShow = -1; - WaitIfNotReady(); // If async is still processing, then wait. - if (m_fileList.size() > 0) { std::list::iterator iterTemp = m_iter; if (iterTemp == m_fileList.end()) @@ -415,8 +413,6 @@ CFileList* CFileList::Next() { CFileList* CFileList::Prev() { m_nMarkedIndexShow = -1; - WaitIfNotReady(); // If async is still processing, then wait. - if (m_iter == m_iterStart) { if (sm_eMode == Helpers::NM_LoopDirectory) { if (!m_bWrapAroundFolder) { @@ -444,15 +440,11 @@ CFileList* CFileList::Prev() { } void CFileList::First() { - WaitIfNotReady(); // If async is still processing, then wait. - m_nMarkedIndexShow = -1; m_iter = m_iterStart = m_fileList.begin(); } void CFileList::Last() { - WaitIfNotReady(); // If async is still processing, then wait. - m_nMarkedIndexShow = -1; MoveIterToLast(); m_iterStart = m_fileList.begin(); @@ -529,7 +521,6 @@ LPCTSTR CFileList::PeekNextPrev(int nIndex, bool bForward, bool bToggle) { if (bToggle) { return (m_nMarkedIndexShow == 0) ? m_sMarkedFile : m_sMarkedFileCurrent; } else { - WaitIfNotReady(); // If async is still processing, then wait. std::list::iterator thisIter = m_iter; LPCTSTR sFileName; From 6379ba1958d4b471bb2387a7bf701c79e5323e1d Mon Sep 17 00:00:00 2001 From: Hamzah Al-washali <32926868+mez0ru@users.noreply.github.com> Date: Tue, 21 Mar 2023 11:38:31 +0800 Subject: [PATCH 11/12] Removed if isEmpty. --- src/JPEGView/MainDlg.cpp | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/JPEGView/MainDlg.cpp b/src/JPEGView/MainDlg.cpp index 0e3adbe8..8e26decb 100644 --- a/src/JPEGView/MainDlg.cpp +++ b/src/JPEGView/MainDlg.cpp @@ -381,9 +381,8 @@ LRESULT CMainDlg::OnInitDialog(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam // create JPEG provider and request first image - do no processing yet if not in fullscreen mode (as we do not know the size yet) m_pJPEGProvider = new CJPEGProvider(m_hWnd, NUM_THREADS, READ_AHEAD_BUFFERS); - if (!m_sStartupFile.IsEmpty()) - m_pCurrentImage = m_pJPEGProvider->RequestImage(CJPEGProvider::FORWARD, - m_pFileList->Current(), 0, CreateProcessParams(!m_bFullScreenMode), m_bOutOfMemoryLastImage, m_bExceptionErrorLastImage); + m_pCurrentImage = m_pJPEGProvider->RequestImage(CJPEGProvider::FORWARD, + m_pFileList->Current(), 0, CreateProcessParams(!m_bFullScreenMode), m_bOutOfMemoryLastImage, m_bExceptionErrorLastImage); if (m_pCurrentImage != NULL && m_pCurrentImage->IsAnimation()) { StartAnimation(); } From 773240dd92a4d55ab0c8d8f16944ff93d3bd8ec6 Mon Sep 17 00:00:00 2001 From: Hamzah Al-washali <32926868+mez0ru@users.noreply.github.com> Date: Tue, 21 Mar 2023 11:50:16 +0800 Subject: [PATCH 12/12] using m_pFileList->Current() for consistency --- src/JPEGView/MainDlg.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/JPEGView/MainDlg.cpp b/src/JPEGView/MainDlg.cpp index 8e26decb..75bb0bac 100644 --- a/src/JPEGView/MainDlg.cpp +++ b/src/JPEGView/MainDlg.cpp @@ -2150,7 +2150,7 @@ void CMainDlg::OpenFile(LPCTSTR sFileName, bool bAfterStartup) { m_pJPEGProvider->NotifyNotUsed(m_pCurrentImage); m_pJPEGProvider->ClearAllRequests(); m_pCurrentImage = m_pJPEGProvider->RequestImage(CJPEGProvider::FORWARD, - m_sStartupFile, 0, CreateProcessParams(!m_bFullScreenMode && (bAfterStartup || IsAdjustWindowToImage())), + m_pFileList->Current(), 0, CreateProcessParams(!m_bFullScreenMode && (bAfterStartup || IsAdjustWindowToImage())), m_bOutOfMemoryLastImage, m_bExceptionErrorLastImage); m_nLastLoadError = GetLoadErrorAfterOpenFile(); if (bAfterStartup) CheckIfApplyAutoFitWndToImage(false);