From: <sag...@us...> - 2013-11-12 21:18:08
|
Revision: 3199 http://sourceforge.net/p/modplug/code/3199 Author: saga-games Date: 2013-11-12 21:17:57 +0000 (Tue, 12 Nov 2013) Log Message: ----------- [New] Instrument library is now refreshed automatically when there are changes in the folder (e.g. adding new files) [Ref] Added mpt::thread to unify thread creation code. [Fix] DMO plugins broke in previous revision. Modified Paths: -------------- trunk/OpenMPT/common/versionNumber.h trunk/OpenMPT/mptrack/MainFrm.cpp trunk/OpenMPT/mptrack/Mptrack.cpp trunk/OpenMPT/mptrack/UpdateCheck.cpp trunk/OpenMPT/mptrack/UpdateCheck.h trunk/OpenMPT/mptrack/View_tre.cpp trunk/OpenMPT/mptrack/View_tre.h trunk/OpenMPT/mptrack/mptrack_08.vcproj trunk/OpenMPT/mptrack/mptrack_10.vcxproj trunk/OpenMPT/mptrack/mptrack_10.vcxproj.filters trunk/OpenMPT/soundlib/plugins/PluginManager.cpp Added Paths: ----------- trunk/OpenMPT/common/thread.h Added: trunk/OpenMPT/common/thread.h =================================================================== --- trunk/OpenMPT/common/thread.h (rev 0) +++ trunk/OpenMPT/common/thread.h 2013-11-12 21:17:57 UTC (rev 3199) @@ -0,0 +1,61 @@ +/* + * thread.h + * -------- + * Purpose: Helper class for running threads, with a more or less platform-independent interface. + * Notes : (currently none) + * Authors: OpenMPT Devs + * The OpenMPT source code is released under the BSD license. Read LICENSE for more details. + */ + +#pragma once + +namespace mpt +{ + +// Default WinAPI thread +class thread +{ +protected: + HANDLE threadHandle; + +public: + + enum Priority + { + lowest = THREAD_PRIORITY_LOWEST, + lower = THREAD_PRIORITY_BELOW_NORMAL, + normal = THREAD_PRIORITY_NORMAL, + high = THREAD_PRIORITY_ABOVE_NORMAL, + highest = THREAD_PRIORITY_HIGHEST + }; + + operator HANDLE& () { return threadHandle; } + operator bool () { return threadHandle != nullptr; } + + thread() : threadHandle(nullptr) { } + thread(LPTHREAD_START_ROUTINE function, void *userData = nullptr, Priority priority = normal) + { + DWORD dummy; // For Win9x + threadHandle = CreateThread(NULL, 0, function, userData, 0, &dummy); + SetThreadPriority(threadHandle, priority); + } +}; + + +// Thread that operates on a member function +template<typename T, void (T::*Fun)()> +class thread_member : public thread +{ +protected: + static DWORD WINAPI wrapperFunc(LPVOID param) + { + (static_cast<T *>(param)->*Fun)(); + return 0; + } + +public: + + thread_member(T *instance, Priority priority = normal) : thread(wrapperFunc, instance, priority) { } +}; + +} // namespace mpt Modified: trunk/OpenMPT/common/versionNumber.h =================================================================== --- trunk/OpenMPT/common/versionNumber.h 2013-11-12 20:54:13 UTC (rev 3198) +++ trunk/OpenMPT/common/versionNumber.h 2013-11-12 21:17:57 UTC (rev 3199) @@ -17,7 +17,7 @@ #define VER_MAJORMAJOR 1 #define VER_MAJOR 22 #define VER_MINOR 06 -#define VER_MINORMINOR 01 +#define VER_MINORMINOR 02 //Version string. For example "1.17.02.28" #define MPT_VERSION_STR VER_STRINGIZE(VER_MAJORMAJOR) "." VER_STRINGIZE(VER_MAJOR) "." VER_STRINGIZE(VER_MINOR) "." VER_STRINGIZE(VER_MINORMINOR) Modified: trunk/OpenMPT/mptrack/MainFrm.cpp =================================================================== --- trunk/OpenMPT/mptrack/MainFrm.cpp 2013-11-12 20:54:13 UTC (rev 3198) +++ trunk/OpenMPT/mptrack/MainFrm.cpp 2013-11-12 21:17:57 UTC (rev 3199) @@ -2504,8 +2504,7 @@ void CMainFrame::OnInternetUpdate() //--------------------------------- { - CUpdateCheck *updateCheck = CUpdateCheck::Create(false); - updateCheck->DoUpdateCheck(); + CUpdateCheck::DoUpdateCheck(false); } Modified: trunk/OpenMPT/mptrack/Mptrack.cpp =================================================================== --- trunk/OpenMPT/mptrack/Mptrack.cpp 2013-11-12 20:54:13 UTC (rev 3198) +++ trunk/OpenMPT/mptrack/Mptrack.cpp 2013-11-12 21:17:57 UTC (rev 3199) @@ -898,10 +898,9 @@ m_dwTimeStarted = timeGetTime(); m_bInitialized = TRUE; - if (CUpdateCheck::GetUpdateCheckPeriod() != 0) + if(CUpdateCheck::GetUpdateCheckPeriod() != 0) { - CUpdateCheck *updateCheck = CUpdateCheck::Create(true); - updateCheck->DoUpdateCheck(); + CUpdateCheck::DoUpdateCheck(true); } // Open settings if the previous execution was with an earlier version. Modified: trunk/OpenMPT/mptrack/UpdateCheck.cpp =================================================================== --- trunk/OpenMPT/mptrack/UpdateCheck.cpp 2013-11-12 20:54:13 UTC (rev 3198) +++ trunk/OpenMPT/mptrack/UpdateCheck.cpp 2013-11-12 21:17:57 UTC (rev 3199) @@ -18,11 +18,7 @@ #include "Mainfrm.h" #include "Moptions.h" -#ifdef _DEBUG -#define new DEBUG_NEW -#endif - const CString CUpdateCheck::defaultUpdateURL = "http://update.openmpt.org/check/$VERSION/$GUID"; // Static configuration variables @@ -33,55 +29,31 @@ bool CUpdateCheck::showUpdateHint = true; -CUpdateCheck::CUpdateCheck(const bool autoUpdate) +// Start update check +void CUpdateCheck::DoUpdateCheck(bool autoUpdate) //----------------------------------------------- { - isAutoUpdate = autoUpdate; - threadHandle = NULL; -} - - -CUpdateCheck::~CUpdateCheck() -//--------------------------- -{ - if(threadHandle != NULL) + CUpdateCheck *that = new (std::nothrow) CUpdateCheck(autoUpdate); + if(that != nullptr) { - CloseHandle(threadHandle); + that->threadHandle = mpt::thread_member<CUpdateCheck, &CUpdateCheck::UpdateThread>(that, autoUpdate ? mpt::thread::lower : mpt::thread::normal); } } -// Start update check -void CUpdateCheck::DoUpdateCheck() -//-------------------------------- -{ - internetHandle = NULL; - connectionHandle = NULL; - - DWORD dummy; // For Win9x - threadHandle = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)&CUpdateCheck::UpdateThread, (LPVOID)this, 0, &dummy); - if(isAutoUpdate) - { - SetThreadPriority(threadHandle, THREAD_PRIORITY_BELOW_NORMAL); - } -} - - // Run update check (independent thread) -DWORD WINAPI CUpdateCheck::UpdateThread(LPVOID param) -//--------------------------------------------------- +void CUpdateCheck::UpdateThread() +//------------------------------- { - CUpdateCheck *caller = (CUpdateCheck *)param; - const time_t now = time(nullptr); - if(caller->isAutoUpdate) + if(isAutoUpdate) { // Do we actually need to run the update check right now? if(CUpdateCheck::updateCheckPeriod == 0 || difftime(now, CUpdateCheck::lastUpdateCheck) < (double)(CUpdateCheck::updateCheckPeriod * 86400)) { - caller->Terminate(); - return 0; + Terminate(); + return; } // Never ran update checks before, so we notify the user of automatic update checks. @@ -93,8 +65,8 @@ if(Reporting::Confirm(msg, "OpenMPT Internet Update") == cnfNo) { CUpdateCheck::lastUpdateCheck = now; - caller->Terminate(); - return 0; + Terminate(); + return; } } @@ -108,57 +80,57 @@ updateURL.Replace("$GUID", GetSendGUID() ? TrackerSettings::Instance().gcsInstallGUID.Get() : "anonymous"); // Establish a connection. - caller->internetHandle = InternetOpen(userAgent, INTERNET_OPEN_TYPE_PRECONFIG, NULL, NULL, 0); - if(caller->internetHandle == NULL) + internetHandle = InternetOpen(userAgent, INTERNET_OPEN_TYPE_PRECONFIG, NULL, NULL, 0); + if(internetHandle == NULL) { - caller->Die("Could not start update check:\n", GetLastError()); - return 0; + Die("Could not start update check:\n", GetLastError()); + return; } - caller->connectionHandle = InternetOpenUrl(caller->internetHandle, updateURL, NULL, 0, INTERNET_FLAG_RELOAD | INTERNET_FLAG_PRAGMA_NOCACHE | INTERNET_FLAG_NO_CACHE_WRITE | INTERNET_FLAG_NO_UI, 0); - if(caller->connectionHandle == NULL) + connectionHandle = InternetOpenUrl(internetHandle, updateURL, NULL, 0, INTERNET_FLAG_RELOAD | INTERNET_FLAG_PRAGMA_NOCACHE | INTERNET_FLAG_NO_CACHE_WRITE | INTERNET_FLAG_NO_UI, 0); + if(connectionHandle == NULL) { - caller->Die("Could not establish connection:\n", GetLastError()); - return 0; + Die("Could not establish connection:\n", GetLastError()); + return; } // Retrieve HTTP status code. DWORD statusCodeHTTP = 0; DWORD length = sizeof(statusCodeHTTP); - if(HttpQueryInfo(caller->connectionHandle, HTTP_QUERY_STATUS_CODE | HTTP_QUERY_FLAG_NUMBER, (LPVOID)&statusCodeHTTP, &length, NULL) == FALSE) + if(HttpQueryInfo(connectionHandle, HTTP_QUERY_STATUS_CODE | HTTP_QUERY_FLAG_NUMBER, (LPVOID)&statusCodeHTTP, &length, NULL) == FALSE) { - caller->Die("Could not retrieve HTTP header information:\n", GetLastError()); - return 0; + Die("Could not retrieve HTTP header information:\n", GetLastError()); + return; } if(statusCodeHTTP >= 400) { CString error; error.Format("Version information could not be found on the server (HTTP status code %d). Maybe your version of OpenMPT is too old!", statusCodeHTTP); - caller->Die(error); - return 0; + Die(error); + return; } // Download data. CString resultData = ""; char *downloadBuffer = new char[DOWNLOAD_BUFFER_SIZE]; - DWORD availableSize, bytesRead; + DWORD availableSize, bytesRead; do { // Query number of available bytes to download - if(InternetQueryDataAvailable(caller->connectionHandle, &availableSize, 0, NULL) == FALSE) + if(InternetQueryDataAvailable(connectionHandle, &availableSize, 0, NULL) == FALSE) { delete[] downloadBuffer; - caller->Die("Error while downloading update information data:\n", GetLastError()); - return 0; + Die("Error while downloading update information data:\n", GetLastError()); + return; } LimitMax(availableSize, (DWORD)DOWNLOAD_BUFFER_SIZE); // Put downloaded bytes into our buffer - if(InternetReadFile(caller->connectionHandle, downloadBuffer, availableSize, &bytesRead) == FALSE) + if(InternetReadFile(connectionHandle, downloadBuffer, availableSize, &bytesRead) == FALSE) { delete[] downloadBuffer; - caller->Die("Error while downloading update information data:\n", GetLastError()); - return 0; + Die("Error while downloading update information data:\n", GetLastError()); + return; } resultData.Append(downloadBuffer, availableSize); @@ -170,7 +142,7 @@ // Now, evaluate the downloaded data. if(!resultData.CompareNoCase("noupdate")) { - if(!caller->isAutoUpdate) + if(!isAutoUpdate) { Reporting::Information("You already have the latest version of OpenMPT installed.", "OpenMPT Internet Update"); } @@ -187,8 +159,8 @@ case 0: if(token.CompareNoCase("update") != 0) { - caller->Die("Could not understand server response. Maybe your version of OpenMPT is too old!"); - return 0; + Die("Could not understand server response. Maybe your version of OpenMPT is too old!"); + return; } break; case 1: @@ -211,15 +183,14 @@ } } else { - caller->Die("Could not understand server response. Maybe your version of OpenMPT is too old!"); - return 0; + Die("Could not understand server response. Maybe your version of OpenMPT is too old!"); + return; } } CUpdateCheck::lastUpdateCheck = now; - caller->Terminate(); - return 0; + Terminate(); } @@ -241,7 +212,7 @@ { if(!isAutoUpdate) { - LPVOID lpMsgBuf; + void *lpMsgBuf; FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_HMODULE | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, GetModuleHandle(TEXT("wininet.dll")), errorCode, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPTSTR)&lpMsgBuf, 0, NULL); @@ -256,17 +227,16 @@ void CUpdateCheck::Terminate() //---------------------------- { - if(connectionHandle != NULL) + if(connectionHandle != nullptr) { InternetCloseHandle(connectionHandle); - connectionHandle = NULL; + connectionHandle = nullptr; } - if(internetHandle != NULL) + if(internetHandle != nullptr) { InternetCloseHandle(internetHandle); - internetHandle = NULL; + internetHandle = nullptr; } - threadHandle = NULL; // If we got here, the thread asked for termination, so don't use CloseHandle() delete this; } Modified: trunk/OpenMPT/mptrack/UpdateCheck.h =================================================================== --- trunk/OpenMPT/mptrack/UpdateCheck.h 2013-11-12 20:54:13 UTC (rev 3198) +++ trunk/OpenMPT/mptrack/UpdateCheck.h 2013-11-12 21:17:57 UTC (rev 3199) @@ -14,8 +14,8 @@ #include <time.h> #include "resource.h" +#include "../common/thread.h" - #define DOWNLOAD_BUFFER_SIZE 256 //================ @@ -26,9 +26,7 @@ static const CString defaultUpdateURL; - // Force creation via "new" as we're using "delete this". - static CUpdateCheck *Create(bool autoUpdate) { return new CUpdateCheck(autoUpdate); }; - void DoUpdateCheck(); + static void DoUpdateCheck(bool autoUpdate); static time_t GetLastUpdateCheck() { return lastUpdateCheck; }; static int GetUpdateCheckPeriod() { return updateCheckPeriod; }; @@ -50,13 +48,13 @@ bool isAutoUpdate; // Are we running an automatic update check? // Runtime resource handles - HANDLE threadHandle; + mpt::thread threadHandle; HINTERNET internetHandle, connectionHandle; - CUpdateCheck(const bool showErrors); - ~CUpdateCheck(); + // Force creation via "new" as we're using "delete this". Use CUpdateCheck::DoUpdateCheck to create an object. + CUpdateCheck::CUpdateCheck(bool autoUpdate) : internetHandle(nullptr), connectionHandle(nullptr), isAutoUpdate(autoUpdate) { } - static DWORD WINAPI UpdateThread(LPVOID param); + void UpdateThread(); void Die(CString errorMessage); void Die(CString errorMessage, DWORD errorCode); void Terminate(); Modified: trunk/OpenMPT/mptrack/View_tre.cpp =================================================================== --- trunk/OpenMPT/mptrack/View_tre.cpp 2013-11-12 20:54:13 UTC (rev 3198) +++ trunk/OpenMPT/mptrack/View_tre.cpp 2013-11-12 21:17:57 UTC (rev 3199) @@ -116,13 +116,20 @@ CModTree::CModTree(CModTree *pDataTree) : m_pDataTree(pDataTree), m_hDropWnd(nullptr), + m_hWatchDir(nullptr), m_dwStatus(0), m_nDocNdx(0), m_nDragDocNdx(0), m_hItemDrag(nullptr), m_hItemDrop(nullptr), m_hInsLib(nullptr), m_hMidiLib(nullptr), m_bShowAllFiles(false), doLabelEdit(false) -//------------------------------------- +//-------------------------------------------- { + if(m_pDataTree != nullptr) + { + // Set up instrument library monitoring thread + m_hWatchDirKillThread = CreateEvent(NULL, FALSE, FALSE, NULL); + watchDirThread = mpt::thread_member<CModTree, &CModTree::MonitorInstrumentLibrary>(this, mpt::thread::lowest); + } MemsetZero(m_tiMidi); MemsetZero(m_tiPerc); } @@ -143,6 +150,12 @@ delete m_SongFile; m_SongFile = nullptr; } + + if(m_pDataTree != nullptr) + { + SetEvent(m_hWatchDirKillThread); + WaitForSingleObject(watchDirThread, INFINITE); + } } @@ -423,7 +436,7 @@ for(UINT iMidi = 0; iMidi < 128; iMidi++) { DWORD dwImage = IMAGE_NOINSTRUMENT; - s = StringifyW(iMidi) + L": " + mpt::String::Decode(szMidiProgramNames[iMidi], mpt::CharsetUTF8); + s = StringifyW(iMidi) + L": " + mpt::String::Decode(szMidiProgramNames[iMidi], mpt::CharsetUS_ASCII); const LPARAM param = (MODITEM_MIDIINSTRUMENT << MIDILIB_SHIFT) | iMidi; if(!midiLib.MidiMap[iMidi].empty()) { @@ -457,7 +470,7 @@ for (UINT iPerc=24; iPerc<=84; iPerc++) { DWORD dwImage = IMAGE_NOSAMPLE; - s = mpt::String::Decode(szDefaultNoteNames[iPerc], mpt::CharsetUTF8) + L": " + mpt::String::Decode(szMidiPercussionNames[iPerc - 24], mpt::CharsetUTF8); + s = mpt::String::Decode(szDefaultNoteNames[iPerc], mpt::CharsetUS_ASCII) + L": " + mpt::String::Decode(szMidiPercussionNames[iPerc - 24], mpt::CharsetUS_ASCII); const LPARAM param = (MODITEM_MIDIPERCUSSION << MIDILIB_SHIFT) | iPerc; if(!midiLib.MidiMap[iPerc | 0x80].empty()) { @@ -650,7 +663,7 @@ void CModTree::UpdateView(ModTreeDocInfo *pInfo, DWORD lHint) //---------------------------------------------------------- { - CHAR s[256], stmp[256]; + TCHAR s[256], stmp[256]; TV_ITEM tvi; const DWORD hintFlagPart = HintFlagPart(lHint); if ((pInfo == nullptr) || (pInfo->pModDoc == nullptr) || IsSampleBrowser()) return; @@ -670,9 +683,9 @@ if (!pInfo->hSong) { pInfo->hSong = InsertItem(s, TVI_ROOT, TVI_FIRST); - pInfo->hOrders = InsertItem("Sequence", IMAGE_FOLDER, IMAGE_FOLDER, pInfo->hSong, TVI_LAST); - pInfo->hPatterns = InsertItem("Patterns", IMAGE_FOLDER, IMAGE_FOLDER, pInfo->hSong, TVI_LAST); - pInfo->hSamples = InsertItem("Samples", IMAGE_FOLDER, IMAGE_FOLDER, pInfo->hSong, TVI_LAST); + pInfo->hOrders = InsertItem(_T("Sequence"), IMAGE_FOLDER, IMAGE_FOLDER, pInfo->hSong, TVI_LAST); + pInfo->hPatterns = InsertItem(_T("Patterns"), IMAGE_FOLDER, IMAGE_FOLDER, pInfo->hSong, TVI_LAST); + pInfo->hSamples = InsertItem(_T("Samples"), IMAGE_FOLDER, IMAGE_FOLDER, pInfo->hSong, TVI_LAST); } if (hintFlagPart & (HINT_MODGENERAL|HINT_MODTYPE)) { @@ -682,7 +695,7 @@ tvi.cchTextMax = CountOf(stmp); tvi.iImage = tvi.iSelectedImage = IMAGE_FOLDER; GetItem(&tvi); - if ((strcmp(s, stmp)) || (tvi.iImage != IMAGE_FOLDER)) + if(tvi.iImage != IMAGE_FOLDER || strcmp(s, stmp)) { tvi.mask |= TVIF_TEXT | TVIF_HANDLE | TVIF_IMAGE | TVIF_SELECTEDIMAGE | TVIF_PARAM; tvi.hItem = pInfo->hSong; @@ -694,7 +707,7 @@ } if (sndFile.GetModSpecifications().instrumentsMax > 0) { - if (!pInfo->hInstruments) pInfo->hInstruments = InsertItem("Instruments", IMAGE_FOLDER, IMAGE_FOLDER, pInfo->hSong, TVI_LAST); + if (!pInfo->hInstruments) pInfo->hInstruments = InsertItem(_T("Instruments"), IMAGE_FOLDER, IMAGE_FOLDER, pInfo->hSong, TVI_LAST); } else { if (pInfo->hInstruments) @@ -704,7 +717,7 @@ pInfo->hInstruments = NULL; } } - if (!pInfo->hComments) pInfo->hComments = InsertItem("Comments", IMAGE_COMMENTS, IMAGE_COMMENTS, pInfo->hSong, TVI_LAST); + if (!pInfo->hComments) pInfo->hComments = InsertItem(_T("Comments"), IMAGE_COMMENTS, IMAGE_COMMENTS, pInfo->hSong, TVI_LAST); // Add effects if (hintFlagPart & (HINT_MODGENERAL|HINT_MODTYPE|HINT_MODCHANNELS|HINT_MIXPLUGINS)) { @@ -717,7 +730,7 @@ { if (!pInfo->hEffects) { - pInfo->hEffects = InsertItem("Plugins", IMAGE_FOLDER, IMAGE_FOLDER, pInfo->hSong, TVI_LAST); + pInfo->hEffects = InsertItem(_T("Plugins"), IMAGE_FOLDER, IMAGE_FOLDER, pInfo->hSong, TVI_LAST); } wsprintf(s, "FX%u: %s", iFx + 1, plugin.GetName()); int nImage = IMAGE_NOPLUGIN; @@ -781,12 +794,12 @@ // Adjust caption of the "Sequence" node (if only one sequence exists, it should be labeled with the sequence name) if(((hintFlagPart & HINT_SEQNAMES) && sndFile.Order.GetNumSequences() == 1) || adjustParentNode) { - CString sSeqName = sndFile.Order.GetSequence(0).m_sName; - if(sSeqName.IsEmpty() || sndFile.Order.GetNumSequences() > 1) - sSeqName = "Sequence"; + CString seqName = sndFile.Order.GetSequence(0).m_sName; + if(seqName.IsEmpty() || sndFile.Order.GetNumSequences() > 1) + seqName = _T("Sequence"); else - sSeqName = "Sequence: " + sSeqName; - SetItem(pInfo->hOrders, TVIF_TEXT, sSeqName, 0, 0, 0, 0, 0); + seqName = _T("Sequence: ") + seqName; + SetItem(pInfo->hOrders, TVIF_TEXT, seqName, 0, 0, 0, 0, 0); } // go through all sequences @@ -874,7 +887,7 @@ tvi.pszText = stmp; tvi.cchTextMax = CountOf(stmp); GetItem(&tvi); - if ((strcmp(s, stmp)) || (tvi.state != state)) + if(tvi.state != state || strcmp(s, stmp)) SetItem(pInfo->tiOrders[nSeq][iOrd], TVIF_TEXT | TVIF_STATE | TVIF_PARAM, s, 0, 0, state, TVIS_BOLD, param); } else { @@ -967,7 +980,7 @@ tvi.cchTextMax = CountOf(stmp); tvi.iImage = tvi.iSelectedImage = nImage; GetItem(&tvi); - if ((strcmp(s, stmp)) || (tvi.iImage != nImage)) + if(tvi.iImage != nImage || strcmp(s, stmp)) { SetItem(hChild, TVIF_TEXT|TVIF_IMAGE|TVIF_SELECTEDIMAGE, s, nImage, nImage, 0, 0, 0); } @@ -1024,7 +1037,7 @@ tvi.cchTextMax = CountOf(stmp); tvi.iImage = tvi.iSelectedImage = nImage; GetItem(&tvi); - if ((strcmp(s, stmp)) || (tvi.iImage != nImage)) + if(tvi.iImage != nImage || strcmp(s, stmp)) SetItem(hChild, TVIF_TEXT|TVIF_IMAGE|TVIF_SELECTEDIMAGE, s, nImage, nImage, 0, 0, 0); } SetItemData(hChild, nIns); @@ -1383,7 +1396,7 @@ } -BOOL CModTree::DeleteTreeItem(HTREEITEM hItem) +void CModTree::DeleteTreeItem(HTREEITEM hItem) //-------------------------------------------- { const ModItem modItem = GetModItem(hItem); @@ -1392,21 +1405,23 @@ ModTreeDocInfo *pInfo = (m_nDocNdx < DocInfo.size() ? DocInfo[m_nDocNdx] : nullptr); CModDoc *pModDoc = (pInfo) ? pInfo->pModDoc : nullptr; + if(modItem.IsSongItem() && pModDoc == nullptr) + { + return; + } + switch(modItem.type) { case MODITEM_SEQUENCE: - if (pModDoc) - { - wsprintf(s, _T("Remove sequence %u?"), modItemID); - if(Reporting::Confirm(s, false, true) == cnfNo) break; - pModDoc->GetrSoundFile().Order.RemoveSequence((SEQUENCEINDEX)(modItemID)); - pModDoc->UpdateAllViews(NULL, HINT_MODSEQUENCE, NULL); - } + wsprintf(s, _T("Remove sequence %u?"), modItemID); + if(Reporting::Confirm(s, false, true) == cnfNo) break; + pModDoc->GetrSoundFile().Order.RemoveSequence((SEQUENCEINDEX)(modItemID)); + pModDoc->UpdateAllViews(NULL, HINT_MODSEQUENCE, NULL); break; case MODITEM_ORDER: // might be slightly annoying to ask for confirmation here, and it's rather easy to restore the orderlist anyway. - if ((pModDoc) && (pModDoc->RemoveOrder((SEQUENCEINDEX)(modItem.val2), (ORDERINDEX)(modItem.val1)))) + if(pModDoc->RemoveOrder((SEQUENCEINDEX)(modItem.val2), (ORDERINDEX)(modItem.val1))) { pModDoc->UpdateAllViews(NULL, HINT_MODSEQUENCE, NULL); } @@ -1414,8 +1429,7 @@ case MODITEM_PATTERN: wsprintf(s, _T("Remove pattern %u?"), modItemID); - if (pModDoc == nullptr || Reporting::Confirm(s, false, true) == cnfNo) break; - if (pModDoc->RemovePattern((PATTERNINDEX)modItemID)) + if(Reporting::Confirm(s, false, true) == cnfYes && pModDoc->RemovePattern((PATTERNINDEX)modItemID)) { pModDoc->UpdateAllViews(NULL, (UINT(modItemID) << HINT_SHIFT_PAT) | HINT_PATTERNDATA|HINT_PATNAMES); } @@ -1423,7 +1437,7 @@ case MODITEM_SAMPLE: wsprintf(s, _T("Remove sample %u?"), modItemID); - if (pModDoc == nullptr || Reporting::Confirm(s, false, true) == cnfNo) break; + if(Reporting::Confirm(s, false, true) == cnfNo) break; pModDoc->GetSampleUndo().PrepareUndo((SAMPLEINDEX)modItemID, sundo_replace); if (pModDoc->RemoveSample((SAMPLEINDEX)modItemID)) { @@ -1433,8 +1447,7 @@ case MODITEM_INSTRUMENT: wsprintf(s, _T("Remove instrument %u?"), modItemID); - if (pModDoc == nullptr || Reporting::Confirm(s, false, true) == cnfNo) break; - if (pModDoc->RemoveInstrument((INSTRUMENTINDEX)modItemID)) + if(Reporting::Confirm(s, false, true) == cnfYes && pModDoc->RemoveInstrument((INSTRUMENTINDEX)modItemID)) { pModDoc->UpdateAllViews(NULL, (UINT(modItemID) << HINT_SHIFT_INS) | HINT_MODTYPE|HINT_ENVELOPE|HINT_INSTRUMENT); } @@ -1470,7 +1483,6 @@ } break; } - return TRUE; } @@ -1558,6 +1570,7 @@ //------------------------------------ { if (!m_hInsLib) return; + SetRedraw(FALSE); if(!m_szSongName.empty() && IsSampleBrowser() && m_SongFile) { @@ -1729,6 +1742,7 @@ FindClose(hFind); } } + // Sort items TV_SORTCB tvs; tvs.hParent = (!IsSampleBrowser()) ? m_hInsLib : TVI_ROOT; @@ -1737,9 +1751,35 @@ SortChildren(tvs.hParent); SortChildrenCB(&tvs); SetRedraw(TRUE); + + if(m_hWatchDir == nullptr) + { + m_hWatchDir = FindFirstChangeNotificationW(m_szInstrLibPath.AsNative().c_str(), FALSE, FILE_NOTIFY_CHANGE_FILE_NAME | FILE_NOTIFY_CHANGE_DIR_NAME); + } } +// Monitor changes in the instrument library folder. +void CModTree::MonitorInstrumentLibrary() +//--------------------------------------- +{ + DWORD result; + do + { + const HANDLE waitHandles[] = { m_hWatchDirKillThread, m_hWatchDir }; + result = WaitForMultipleObjects(m_hWatchDir != nullptr ? 2 : 1, waitHandles, FALSE, 1000); + if(result == WAIT_OBJECT_0 + 1 && m_hWatchDir == waitHandles[1]) + { + FindNextChangeNotification(m_hWatchDir); + RefreshInstrumentLibrary(); + } else if(result == WAIT_FAILED) + { + Sleep(100); + } + } while(result != WAIT_OBJECT_0); +} + + // Insert sample browser item. void CModTree::ModTreeInsert(const WCHAR *name, int image) //-------------------------------------------------------- @@ -1859,7 +1899,12 @@ if(!ok) { std::wstring s = L"Unable to browse to \"" + dir.AsNative() + L"\""; - Reporting::Error(s); + Reporting::Error(s, L"Instrument Library"); + } else + { + HANDLE watchDir = m_hWatchDir; + m_hWatchDir = nullptr; + FindCloseChangeNotification(watchDir); } } @@ -3023,7 +3068,7 @@ if(pSndFile && modItem.val1) { - FileDialog dlg = OpenFileDialog() + FileDialog dlg = SaveFileDialog() .ExtensionFilter("All files(*.*)|*.*||"); if(!dlg.Show()) return; Modified: trunk/OpenMPT/mptrack/View_tre.h =================================================================== --- trunk/OpenMPT/mptrack/View_tre.h 2013-11-12 20:54:13 UTC (rev 3198) +++ trunk/OpenMPT/mptrack/View_tre.h 2013-11-12 21:17:57 UTC (rev 3199) @@ -71,6 +71,7 @@ #include "CTreeCtrl.h" +#include "../common/thread.h" //=============================== class CModTree: public CTreeCtrlW @@ -163,6 +164,9 @@ CModTreeDropTarget m_DropTarget; CModTree *m_pDataTree; // Pointer to instrument browser (lower part of tree view) - if it's a nullptr, this object is the instrument browser itself. HWND m_hDropWnd; + volatile HANDLE m_hWatchDir; + HANDLE m_hWatchDirKillThread; + mpt::thread watchDirThread; ModItem m_itemDrag; DWORD m_dwStatus; UINT m_nDocNdx, m_nDragDocNdx; @@ -191,11 +195,12 @@ void RefreshInstrumentLibrary(); void EmptyInstrumentLibrary(); void FillInstrumentLibrary(); + void MonitorInstrumentLibrary(); ModItem GetModItem(HTREEITEM hItem); BOOL SetMidiInstrument(UINT nIns, const mpt::PathString &fileName); BOOL SetMidiPercussion(UINT nPerc, const mpt::PathString &fileName); BOOL ExecuteItem(HTREEITEM hItem); - BOOL DeleteTreeItem(HTREEITEM hItem); + void DeleteTreeItem(HTREEITEM hItem); BOOL PlayItem(HTREEITEM hItem, ModCommand::NOTE nParam); BOOL OpenTreeItem(HTREEITEM hItem); BOOL OpenMidiInstrument(DWORD dwItem); Modified: trunk/OpenMPT/mptrack/mptrack_08.vcproj =================================================================== --- trunk/OpenMPT/mptrack/mptrack_08.vcproj 2013-11-12 20:54:13 UTC (rev 3198) +++ trunk/OpenMPT/mptrack/mptrack_08.vcproj 2013-11-12 21:17:57 UTC (rev 3199) @@ -1257,6 +1257,10 @@ > </File> <File + RelativePath="..\common\thread.h" + > + </File> + <File RelativePath="..\common\typedefs.h" > </File> Modified: trunk/OpenMPT/mptrack/mptrack_10.vcxproj =================================================================== --- trunk/OpenMPT/mptrack/mptrack_10.vcxproj 2013-11-12 20:54:13 UTC (rev 3198) +++ trunk/OpenMPT/mptrack/mptrack_10.vcxproj 2013-11-12 21:17:57 UTC (rev 3199) @@ -634,6 +634,7 @@ <ClInclude Include="..\common\serialization_utils.h" /> <ClInclude Include="..\common\StringFixer.h" /> <ClInclude Include="..\common\svn_version_default\svn_version.h" /> + <ClInclude Include="..\common\thread.h" /> <ClInclude Include="..\common\typedefs.h" /> <ClInclude Include="..\common\version.h" /> <ClInclude Include="..\common\versionNumber.h" /> Modified: trunk/OpenMPT/mptrack/mptrack_10.vcxproj.filters =================================================================== --- trunk/OpenMPT/mptrack/mptrack_10.vcxproj.filters 2013-11-12 20:54:13 UTC (rev 3198) +++ trunk/OpenMPT/mptrack/mptrack_10.vcxproj.filters 2013-11-12 21:17:57 UTC (rev 3199) @@ -960,6 +960,9 @@ <ClInclude Include="CTreeCtrl.h"> <Filter>Header Files</Filter> </ClInclude> + <ClInclude Include="..\common\thread.h"> + <Filter>Header Files\common</Filter> + </ClInclude> </ItemGroup> <ItemGroup> <None Include="res\bitmap1.bmp"> Modified: trunk/OpenMPT/soundlib/plugins/PluginManager.cpp =================================================================== --- trunk/OpenMPT/soundlib/plugins/PluginManager.cpp 2013-11-12 20:54:13 UTC (rev 3198) +++ trunk/OpenMPT/soundlib/plugins/PluginManager.cpp 2013-11-12 21:17:57 UTC (rev 3199) @@ -118,18 +118,16 @@ { HKEY hkEnum; WCHAR keyname[128]; - LONG cr; - DWORD index; - cr = RegOpenKey(HKEY_LOCAL_MACHINE, "software\\classes\\DirectShow\\MediaObjects\\Categories\\f3602b3f-0592-48df-a4cd-674721e7ebeb", &hkEnum); - index = 0; + LONG cr = RegOpenKey(HKEY_LOCAL_MACHINE, "software\\classes\\DirectShow\\MediaObjects\\Categories\\f3602b3f-0592-48df-a4cd-674721e7ebeb", &hkEnum); + DWORD index = 0; while (cr == ERROR_SUCCESS) { if ((cr = RegEnumKeyW(hkEnum, index, keyname, CountOf(keyname))) == ERROR_SUCCESS) { CLSID clsid; std::wstring formattedKey = std::wstring(L"{") + std::wstring(keyname) + std::wstring(L"}"); - if(Util::StringToCLSID(formattedKey, clsid) == S_OK) + if(Util::StringToCLSID(formattedKey, clsid)) { HKEY hksub; formattedKey = std::wstring(L"software\\classes\\DirectShow\\MediaObjects\\") + std::wstring(keyname); This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |