diff --git a/Source/Project64/UserInterface/RomBrowser.h b/Source/Project64/UserInterface/RomBrowser.h index b804b6505..cc11d5160 100644 --- a/Source/Project64/UserInterface/RomBrowser.h +++ b/Source/Project64/UserInterface/RomBrowser.h @@ -139,13 +139,23 @@ private: void RomList_PopupMenu(uint32_t pnmh); void RomList_SortList(void); + bool RomDirNeedsRefresh(void); // Called from watch thread void RomDirChanged(void); + bool GetRomFileNames(strlist & FileList, const CPath & BaseDirectory, const std::string & Directory, bool InWatchThread); + void WatchThreadStart(void); + void WatchThreadStop(void); + static void WatchRomDirChanged(CRomBrowser * _this); + static void AddField(ROMBROWSER_FIELDS_LIST & Fields, const char * Name, int32_t Pos, int32_t ID, int32_t Width, LanguageStringID LangID, bool UseDefault); //Callback static int CALLBACK SelectRomDirCallBack(HWND hwnd, uint32_t uMsg, uint32_t lp, uint32_t lpData); static int CALLBACK RomList_CompareItems(uint32_t lParam1, uint32_t lParam2, uint32_t lParamSort); + + //Watch Directory Changed function + HANDLE m_WatchThread, m_WatchStopEvent; + DWORD m_WatchThreadID; HWND & m_MainWindow; HWND & m_StatusWindow; @@ -159,4 +169,5 @@ private: static std::wstring m_UnknownGoodName; HBRUSH_MAP m_Brushes; std::string m_LastRom; + stdstr m_WatchRomDir; }; diff --git a/Source/Project64/UserInterface/RomBrowserClass.cpp b/Source/Project64/UserInterface/RomBrowserClass.cpp index 434be7d92..d60b9630a 100644 --- a/Source/Project64/UserInterface/RomBrowserClass.cpp +++ b/Source/Project64/UserInterface/RomBrowserClass.cpp @@ -20,7 +20,10 @@ CRomBrowser::CRomBrowser(HWND & MainWindow, HWND & StatusWindow) : m_MainWindow(MainWindow), m_StatusWindow(StatusWindow), m_ShowingRomBrowser(false), - m_AllowSelectionLastRom(true) + m_AllowSelectionLastRom(true), + m_WatchThreadID(0), + m_WatchThread(NULL), + m_WatchStopEvent(NULL) { m_hRomList = 0; m_Visible = false; @@ -31,6 +34,7 @@ CRomBrowser::CRomBrowser(HWND & MainWindow, HWND & StatusWindow) : CRomBrowser::~CRomBrowser(void) { + WatchThreadStop(); DeallocateBrushs(); } @@ -285,6 +289,15 @@ void CRomBrowser::RomListReset(void) Sleep(100); WriteTrace(TraceUserInterface, TraceDebug, "3"); m_LastRom = UISettingsLoadStringIndex(File_RecentGameFileIndex, 0); + + if (m_WatchRomDir != g_Settings->LoadStringVal(RomList_GameDir)) + { + WriteTrace(TraceUserInterface, TraceDebug, "4"); + WatchThreadStop(); + WriteTrace(TraceUserInterface, TraceDebug, "5"); + WatchThreadStart(); + WriteTrace(TraceUserInterface, TraceDebug, "6"); + } } void CRomBrowser::CreateRomListControl(void) @@ -1084,3 +1097,171 @@ void CRomBrowser::HideRomList(void) PostMessage(m_MainWindow, WM_MAKE_FOCUS, 0, 0); } +bool CRomBrowser::RomDirNeedsRefresh(void) +{ + bool InWatchThread = (m_WatchThreadID == GetCurrentThreadId()); + + //Get Old MD5 of file names + stdstr FileName = g_Settings->LoadStringVal(RomList_RomListCache); + HANDLE hFile = CreateFile(FileName.c_str(), GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_RANDOM_ACCESS, NULL); + if (hFile == INVALID_HANDLE_VALUE) + { + //if file does not exist then refresh the data + return true; + } + + DWORD dwRead; + unsigned char CurrentFileMD5[16]; + ReadFile(hFile, &CurrentFileMD5, sizeof(CurrentFileMD5), &dwRead, NULL); + CloseHandle(hFile); + + //Get Current MD5 of file names + strlist FileNames; + if (!GetRomFileNames(FileNames, CPath(g_Settings->LoadStringVal(RomList_GameDir)), stdstr(""), InWatchThread)) + { + return false; + } + FileNames.sort(); + + MD5 NewMd5 = RomListHash(FileNames); + if (memcmp(NewMd5.raw_digest(), CurrentFileMD5, sizeof(CurrentFileMD5)) != 0) + { + return true; + } + return false; +} + +void CRomBrowser::WatchRomDirChanged(CRomBrowser * _this) +{ + try + { + WriteTrace(TraceUserInterface, TraceDebug, "1"); + _this->m_WatchRomDir = g_Settings->LoadStringVal(RomList_GameDir); + WriteTrace(TraceUserInterface, TraceDebug, "2"); + if (_this->RomDirNeedsRefresh()) + { + WriteTrace(TraceUserInterface, TraceDebug, "2a"); + _this->RomDirChanged(); + } + WriteTrace(TraceUserInterface, TraceDebug, "3"); + HANDLE hChange[] = + { + _this->m_WatchStopEvent, + FindFirstChangeNotification(_this->m_WatchRomDir.c_str(), g_Settings->LoadBool(RomList_GameDirRecursive), FILE_NOTIFY_CHANGE_FILE_NAME | FILE_NOTIFY_CHANGE_SIZE), + }; + WriteTrace(TraceUserInterface, TraceDebug, "4"); + for (;;) + { + WriteTrace(TraceUserInterface, TraceDebug, "5"); + if (WaitForMultipleObjects(sizeof(hChange) / sizeof(hChange[0]), hChange, false, INFINITE) == WAIT_OBJECT_0) + { + WriteTrace(TraceUserInterface, TraceDebug, "5a"); + FindCloseChangeNotification(hChange[1]); + return; + } + WriteTrace(TraceUserInterface, TraceDebug, "5b"); + if (_this->RomDirNeedsRefresh()) + { + _this->RomDirChanged(); + } + WriteTrace(TraceUserInterface, TraceDebug, "5c"); + if (!FindNextChangeNotification(hChange[1])) + { + FindCloseChangeNotification(hChange[1]); + return; + } + WriteTrace(TraceUserInterface, TraceDebug, "5d"); + } + } + catch (...) + { + WriteTrace(TraceUserInterface, TraceError, __FUNCTION__ ": Unhandled Exception"); + } +} + +void CRomBrowser::WatchThreadStart(void) +{ + WriteTrace(TraceUserInterface, TraceDebug, "1"); + WatchThreadStop(); + WriteTrace(TraceUserInterface, TraceDebug, "2"); + if (m_WatchStopEvent == NULL) + { + m_WatchStopEvent = CreateEvent(NULL, true, false, NULL); + } + WriteTrace(TraceUserInterface, TraceDebug, "3"); + m_WatchThread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)WatchRomDirChanged, this, 0, &m_WatchThreadID); + WriteTrace(TraceUserInterface, TraceDebug, "4"); +} + +void CRomBrowser::WatchThreadStop(void) +{ + if (m_WatchThread == NULL) + { + return; + } + WriteTrace(TraceUserInterface, TraceDebug, "1"); + SetEvent(m_WatchStopEvent); + DWORD ExitCode = 0; + for (int32_t count = 0; count < 20; count++) + { + WriteTrace(TraceUserInterface, TraceDebug, "2"); + GetExitCodeThread(m_WatchThread, &ExitCode); + if (ExitCode != STILL_ACTIVE) + { + break; + } + Sleep(200); + } + WriteTrace(TraceUserInterface, TraceDebug, "3"); + if (ExitCode == STILL_ACTIVE) + { + WriteTrace(TraceUserInterface, TraceDebug, "3a"); + TerminateThread(m_WatchThread, 0); + } + WriteTrace(TraceUserInterface, TraceDebug, "4"); + + CloseHandle(m_WatchThread); + CloseHandle(m_WatchStopEvent); + m_WatchStopEvent = NULL; + m_WatchThread = NULL; + m_WatchThreadID = 0; + WriteTrace(TraceUserInterface, TraceDebug, "5"); +} + +bool CRomBrowser::GetRomFileNames(strlist & FileList, const CPath & BaseDirectory, const std::string & Directory, bool InWatchThread) +{ + if (!BaseDirectory.DirectoryExists()) + { + return false; + } + CPath SearchPath(BaseDirectory, "*.*"); + SearchPath.AppendDirectory(Directory.c_str()); + + if (!SearchPath.FindFirst(CPath::FIND_ATTRIBUTE_ALLFILES)) + { + return false; + } + + do + { + if (InWatchThread && WaitForSingleObject(m_WatchStopEvent, 0) != WAIT_TIMEOUT) + { + return false; + } + + if (SearchPath.IsDirectory()) + { + if (g_Settings->LoadBool(RomList_GameDirRecursive)) + { + CPath CurrentDir(Directory); + CurrentDir.AppendDirectory(SearchPath.GetLastDirectory().c_str()); + GetRomFileNames(FileList, BaseDirectory, CurrentDir, InWatchThread); + } + } + else + { + AddFileNameToList(FileList, Directory, SearchPath); + } + } while (SearchPath.FindNext()); + return true; +} \ No newline at end of file diff --git a/Source/Project64/UserInterface/RomList.cpp b/Source/Project64/UserInterface/RomList.cpp index 13686f865..9c6ac5ead 100644 --- a/Source/Project64/UserInterface/RomList.cpp +++ b/Source/Project64/UserInterface/RomList.cpp @@ -34,10 +34,7 @@ CRomList::CRomList() : #ifdef _WIN32 m_ZipIniFile(NULL), #endif - m_RomIniFile(NULL), - m_WatchThreadID(0), - m_WatchThread(NULL), - m_WatchStopEvent(NULL) + m_RomIniFile(NULL) { if (g_Settings) { @@ -52,7 +49,6 @@ CRomList::CRomList() : CRomList::~CRomList() { - WatchThreadStop(); m_StopRefresh = true; if (m_NotesIniFile) { @@ -101,15 +97,6 @@ void CRomList::RefreshRomListThread(void) RomListReset(); m_RomInfo.clear(); - if (m_WatchRomDir != g_Settings->LoadStringVal(RomList_GameDir)) - { - WriteTrace(TraceUserInterface, TraceDebug, "4"); - WatchThreadStop(); - WriteTrace(TraceUserInterface, TraceDebug, "5"); - WatchThreadStart(); - WriteTrace(TraceUserInterface, TraceDebug, "6"); - } - WriteTrace(TraceUserInterface, TraceDebug, "7"); stdstr RomDir = g_Settings->LoadStringVal(RomList_GameDir); stdstr LastRom = UISettingsLoadStringIndex(File_RecentGameFileIndex, 0); @@ -182,12 +169,6 @@ void CRomList::FillRomList(strlist & FileList, const CPath & BaseDirectory, cons continue; } WriteTrace(TraceRomList, TraceVerbose, "File has matching extension: \"%s\"", ROM_extensions[i]); - if (FileList.size() <= 3000) - { - stdstr file = stdstr(Directory + SearchPath.GetNameExtension()).ToLower(); - WriteTrace(TraceRomList, TraceVerbose, "Adding: \"%s\" to FileList", file.c_str()); - FileList.push_back(file); - } if (Extension != "7z") { AddRomToList(SearchPath); @@ -637,137 +618,6 @@ void CRomList::SaveRomList(strlist & FileList) file.Close(); } -void CRomList::WatchRomDirChanged(CRomList * _this) -{ - try - { - WriteTrace(TraceUserInterface, TraceDebug, "1"); - _this->m_WatchRomDir = g_Settings->LoadStringVal(RomList_GameDir); - WriteTrace(TraceUserInterface, TraceDebug, "2"); - if (_this->RomDirNeedsRefresh()) - { - WriteTrace(TraceUserInterface, TraceDebug, "2a"); - _this->RomDirChanged(); - } - WriteTrace(TraceUserInterface, TraceDebug, "3"); - HANDLE hChange[] = - { - _this->m_WatchStopEvent, - FindFirstChangeNotification(_this->m_WatchRomDir.c_str(), g_Settings->LoadBool(RomList_GameDirRecursive), FILE_NOTIFY_CHANGE_FILE_NAME | FILE_NOTIFY_CHANGE_SIZE), - }; - WriteTrace(TraceUserInterface, TraceDebug, "4"); - for (;;) - { - WriteTrace(TraceUserInterface, TraceDebug, "5"); - if (WaitForMultipleObjects(sizeof(hChange) / sizeof(hChange[0]), hChange, false, INFINITE) == WAIT_OBJECT_0) - { - WriteTrace(TraceUserInterface, TraceDebug, "5a"); - FindCloseChangeNotification(hChange[1]); - return; - } - WriteTrace(TraceUserInterface, TraceDebug, "5b"); - if (_this->RomDirNeedsRefresh()) - { - _this->RomDirChanged(); - } - WriteTrace(TraceUserInterface, TraceDebug, "5c"); - if (!FindNextChangeNotification(hChange[1])) - { - FindCloseChangeNotification(hChange[1]); - return; - } - WriteTrace(TraceUserInterface, TraceDebug, "5d"); - } - } - catch (...) - { - WriteTrace(TraceUserInterface, TraceError, __FUNCTION__ ": Unhandled Exception"); - } -} - -bool CRomList::RomDirNeedsRefresh(void) -{ - bool InWatchThread = (m_WatchThreadID == GetCurrentThreadId()); - - //Get Old MD5 of file names - stdstr FileName = g_Settings->LoadStringVal(RomList_RomListCache); - HANDLE hFile = CreateFile(FileName.c_str(), GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_RANDOM_ACCESS, NULL); - if (hFile == INVALID_HANDLE_VALUE) - { - //if file does not exist then refresh the data - return true; - } - - DWORD dwRead; - unsigned char CurrentFileMD5[16]; - ReadFile(hFile, &CurrentFileMD5, sizeof(CurrentFileMD5), &dwRead, NULL); - CloseHandle(hFile); - - //Get Current MD5 of file names - strlist FileNames; - if (!GetRomFileNames(FileNames, CPath(g_Settings->LoadStringVal(RomList_GameDir)), stdstr(""), InWatchThread)) - { - return false; - } - FileNames.sort(); - - MD5 NewMd5 = RomListHash(FileNames); - if (memcmp(NewMd5.raw_digest(), CurrentFileMD5, sizeof(CurrentFileMD5)) != 0) - { - return true; - } - return false; -} - -void CRomList::WatchThreadStart(void) -{ - WriteTrace(TraceUserInterface, TraceDebug, "1"); - WatchThreadStop(); - WriteTrace(TraceUserInterface, TraceDebug, "2"); - if (m_WatchStopEvent == NULL) - { - m_WatchStopEvent = CreateEvent(NULL, true, false, NULL); - } - WriteTrace(TraceUserInterface, TraceDebug, "3"); - m_WatchThread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)WatchRomDirChanged, this, 0, &m_WatchThreadID); - WriteTrace(TraceUserInterface, TraceDebug, "4"); -} - -void CRomList::WatchThreadStop(void) -{ - if (m_WatchThread == NULL) - { - return; - } - WriteTrace(TraceUserInterface, TraceDebug, "1"); - SetEvent(m_WatchStopEvent); - DWORD ExitCode = 0; - for (int32_t count = 0; count < 20; count++) - { - WriteTrace(TraceUserInterface, TraceDebug, "2"); - GetExitCodeThread(m_WatchThread, &ExitCode); - if (ExitCode != STILL_ACTIVE) - { - break; - } - Sleep(200); - } - WriteTrace(TraceUserInterface, TraceDebug, "3"); - if (ExitCode == STILL_ACTIVE) - { - WriteTrace(TraceUserInterface, TraceDebug, "3a"); - TerminateThread(m_WatchThread, 0); - } - WriteTrace(TraceUserInterface, TraceDebug, "4"); - - CloseHandle(m_WatchThread); - CloseHandle(m_WatchStopEvent); - m_WatchStopEvent = NULL; - m_WatchThread = NULL; - m_WatchThreadID = 0; - WriteTrace(TraceUserInterface, TraceDebug, "5"); -} - MD5 CRomList::RomListHash(strlist & FileList) { stdstr NewFileNames; @@ -798,7 +648,7 @@ void CRomList::AddFileNameToList(strlist & FileList, const stdstr & Directory, C { if (Extension == ROM_extensions[i]) { - stdstr FileName = Directory + Name + Extension; + stdstr FileName = Directory + Name + "." + Extension; FileName.ToLower(); FileList.push_back(FileName); break; @@ -806,40 +656,3 @@ void CRomList::AddFileNameToList(strlist & FileList, const stdstr & Directory, C } } -bool CRomList::GetRomFileNames(strlist & FileList, const CPath & BaseDirectory, const std::string & Directory, bool InWatchThread) -{ - if (!BaseDirectory.DirectoryExists()) - { - return false; - } - CPath SearchPath(BaseDirectory, "*.*"); - SearchPath.AppendDirectory(Directory.c_str()); - - if (!SearchPath.FindFirst(CPath::FIND_ATTRIBUTE_ALLFILES)) - { - return false; - } - - do - { - if (InWatchThread && WaitForSingleObject(m_WatchStopEvent, 0) != WAIT_TIMEOUT) - { - return false; - } - - if (SearchPath.IsDirectory()) - { - if (g_Settings->LoadBool(RomList_GameDirRecursive)) - { - CPath CurrentDir(Directory); - CurrentDir.AppendDirectory(SearchPath.GetLastDirectory().c_str()); - GetRomFileNames(FileList, BaseDirectory, CurrentDir, InWatchThread); - } - } - else - { - AddFileNameToList(FileList, Directory, SearchPath); - } - } while (SearchPath.FindNext()); - return true; -} diff --git a/Source/Project64/UserInterface/RomList.h b/Source/Project64/UserInterface/RomList.h index 3fa12218f..ef60cee2b 100644 --- a/Source/Project64/UserInterface/RomList.h +++ b/Source/Project64/UserInterface/RomList.h @@ -61,9 +61,8 @@ protected: virtual void RomListLoaded(void) {} virtual void RomDirChanged(void) {} - void WatchThreadStart(void); - void WatchThreadStop(void); - + MD5 RomListHash(strlist & FileList); + void AddFileNameToList(strlist & FileList, const stdstr & Directory, CPath & File); ROMINFO_LIST m_RomInfo; bool m_StopRefresh; @@ -73,19 +72,10 @@ private: bool FillRomInfo(ROM_INFO * pRomInfo); void FillRomExtensionInfo(ROM_INFO * pRomInfo); bool LoadDataFromRomFile(const char * FileName, uint8_t * Data, int32_t DataLen, int32_t * RomSize, FILE_FORMAT & FileFormat); - void AddFileNameToList(strlist & FileList, const stdstr & Directory, CPath & File); void SaveRomList(strlist & FileList); void RefreshRomListThread(void); - bool GetRomFileNames(strlist & FileList, const CPath & BaseDirectory, const std::string & Directory, bool InWatchThread); - MD5 RomListHash(strlist & FileList); - - //Watch Directory Changed function - HANDLE m_WatchThread, m_WatchStopEvent; - DWORD m_WatchThreadID; - bool RomDirNeedsRefresh(void); // Called from watch thread static void NotificationCB(const char * Status, CRomList * _this); - static void WatchRomDirChanged(CRomList * _this); static void RefreshRomListStatic(CRomList * _this); static void ByteSwapRomData(uint8_t * Data, int DataLen); @@ -96,6 +86,4 @@ private: CIniFile * m_ZipIniFile; #endif HANDLE m_RefreshThread; - stdstr m_WatchRomDir; - };