From: <rel...@us...> - 2011-07-28 20:52:05
|
Revision: 932 http://modplug.svn.sourceforge.net/modplug/?rev=932&view=rev Author: relabsoluness Date: 2011-07-28 20:51:57 +0000 (Thu, 28 Jul 2011) Log Message: ----------- [New] General: Template modules. Can be accessed from file-menu. [New] General: Example modules are now accessible through help menu. [Ref] Minor tweaks here and there. Modified Paths: -------------- trunk/OpenMPT/mptrack/AbstractVstEditor.cpp trunk/OpenMPT/mptrack/Ctrl_pat.h trunk/OpenMPT/mptrack/InputHandler.cpp trunk/OpenMPT/mptrack/MainFrm.cpp trunk/OpenMPT/mptrack/Mainfrm.h trunk/OpenMPT/mptrack/Moddoc.cpp trunk/OpenMPT/mptrack/Moddoc.h trunk/OpenMPT/mptrack/Mptrack.cpp trunk/OpenMPT/mptrack/Mptrack.h trunk/OpenMPT/mptrack/PerformanceCounter.h trunk/OpenMPT/mptrack/TrackerSettings.cpp trunk/OpenMPT/mptrack/TrackerSettings.h trunk/OpenMPT/mptrack/TuningDialog.h trunk/OpenMPT/mptrack/misc_util.h trunk/OpenMPT/mptrack/mptrack.rc trunk/OpenMPT/mptrack/resource.h trunk/OpenMPT/mptrack/test/test.cpp trunk/OpenMPT/mptrack/tuningRatioMapWnd.h trunk/OpenMPT/soundlib/SNDDEVX.H trunk/OpenMPT/soundlib/mod_specifications.cpp trunk/OpenMPT/soundlib/mod_specifications.h Modified: trunk/OpenMPT/mptrack/AbstractVstEditor.cpp =================================================================== --- trunk/OpenMPT/mptrack/AbstractVstEditor.cpp 2011-07-28 14:59:55 UTC (rev 931) +++ trunk/OpenMPT/mptrack/AbstractVstEditor.cpp 2011-07-28 20:51:57 UTC (rev 932) @@ -202,7 +202,7 @@ } } SetNullTerminator(rawname); - CreateVerifiedProgramName(rawname, sizeof(rawname), name, sizeof(name), index); + CreateVerifiedProgramName(rawname, CountOf(rawname), name, CountOf(name), index); m_pMenu->ModifyMenu(8, MF_BYPOSITION, 0, name); } Modified: trunk/OpenMPT/mptrack/Ctrl_pat.h =================================================================== --- trunk/OpenMPT/mptrack/Ctrl_pat.h 2011-07-28 14:59:55 UTC (rev 931) +++ trunk/OpenMPT/mptrack/Ctrl_pat.h 2011-07-28 20:51:57 UTC (rev 932) @@ -66,7 +66,7 @@ BYTE GetMargins() {return GetMargins(GetMarginsMax());} // Returns the effective margin value. - BYTE GetMargins(const BYTE nMaxMargins) {return min(nMaxMargins, m_nOrderlistMargins);} + BYTE GetMargins(const BYTE nMaxMargins) {return Util::Min(nMaxMargins, static_cast<BYTE>(m_nOrderlistMargins));} // Returns maximum margin value given current window width. BYTE GetMarginsMax() {return GetMarginsMax(GetLength());} Modified: trunk/OpenMPT/mptrack/InputHandler.cpp =================================================================== --- trunk/OpenMPT/mptrack/InputHandler.cpp 2011-07-28 14:59:55 UTC (rev 931) +++ trunk/OpenMPT/mptrack/InputHandler.cpp 2011-07-28 20:51:57 UTC (rev 932) @@ -416,9 +416,11 @@ { case FILENEW: s="&New\t"; c=kcFileNew; break; case ID_FILE_OPEN: s="&Open...\t"; c=kcFileOpen; break; + case ID_FILE_OPENTEMPLATE: return "Open Template\t"; case ID_FILE_CLOSE: s="&Close\t"; c=kcFileClose; break; case ID_FILE_SAVE: s="&Save\t"; c=kcFileSave; break; case ID_FILE_SAVE_AS: s="Save &As...\t"; c=kcFileSaveAs; break; + case ID_FILE_SAVEASTEMPLATE:s="Save as Template\t"; break; case ID_FILE_SAVEASWAVE: s="Export as &Wave...\t"; c=kcFileSaveAsWave; break; case ID_FILE_SAVEASMP3: s="Export as M&P3...\t"; c=kcFileSaveAsMP3; break; case ID_FILE_SAVEMIDI: s="Export as M&IDI...\t"; c=kcFileSaveMidi; break; @@ -465,6 +467,8 @@ case ID_VIEW_SONGPROPERTIES:s="Song P&roperties...\t"; c=kcViewSongProperties; break; //rewbs.graph case ID_VIEW_MIDIMAPPING: s="&MIDI Mapping...\t"; c = kcViewMIDImapping; break; case ID_VIEW_EDITHISTORY: s="Edit &History...\t"; c = kcViewEditHistory; break; + // Help submenu: + case ID_EXAMPLE_MODULES: return "&Example Modules\t"; /* case ID_WINDOW_NEW: s="&New Window\t"; c=kcWindowNew; break; Modified: trunk/OpenMPT/mptrack/MainFrm.cpp =================================================================== --- trunk/OpenMPT/mptrack/MainFrm.cpp 2011-07-28 14:59:55 UTC (rev 931) +++ trunk/OpenMPT/mptrack/MainFrm.cpp 2011-07-28 20:51:57 UTC (rev 932) @@ -79,11 +79,13 @@ ON_COMMAND(ID_DEFAULT_HELP, CMDIFrameWnd::OnHelpFinder) ON_COMMAND(ID_NEXTOCTAVE, OnNextOctave) ON_COMMAND(ID_PREVOCTAVE, OnPrevOctave) + ON_COMMAND_RANGE(ID_FILE_OPENTEMPLATE, ID_FILE_OPENTEMPLATE_LASTINRANGE, OnOpenTemplateModule) ON_COMMAND(ID_ADD_SOUNDBANK, OnAddDlsBank) ON_COMMAND(ID_IMPORT_MIDILIB, OnImportMidiLib) ON_COMMAND(ID_MIDI_RECORD, OnMidiRecord) ON_COMMAND(ID_PANIC, OnPanic) ON_COMMAND(ID_PLAYER_PAUSE, OnPlayerPause) + ON_COMMAND_RANGE(ID_EXAMPLE_MODULES, ID_EXAMPLE_MODULES_LASTINRANGE, OnExampleSong) ON_COMMAND_EX(IDD_TREEVIEW, OnBarCheck) ON_COMMAND_EX(ID_NETLINK_MODPLUG, OnInternetLink) ON_COMMAND_EX(ID_NETLINK_TOP_PICKS, OnInternetLink) @@ -120,6 +122,9 @@ UINT CMainFrame::m_nLastOptionsPage = 0; HHOOK CMainFrame::ghKbdHook = NULL; +std::vector<CString> CMainFrame::s_ExampleModulePaths; +std::vector<CString> CMainFrame::s_TemplateModulePaths; + CRITICAL_SECTION CMainFrame::m_csAudio; HANDLE CMainFrame::m_hPlayThread = NULL; DWORD CMainFrame::m_dwPlayThreadId = 0; @@ -183,7 +188,7 @@ CInputHandler *CMainFrame::m_InputHandler = nullptr; //rewbs.customKeys CAutoSaver *CMainFrame::m_pAutoSaver = nullptr; //rewbs.autosave -CPerformanceCounter *CMainFrame::m_pPerfCounter = nullptr; +//CPerformanceCounter *CMainFrame::m_pPerfCounter = nullptr; static UINT indicators[] = { @@ -231,7 +236,7 @@ m_Settings.LoadSettings(); m_InputHandler = new CInputHandler(this); //rewbs.customKeys - m_pPerfCounter= new CPerformanceCounter(); + //m_pPerfCounter= new CPerformanceCounter(); //Loading static tunings here - probably not the best place to do that but anyway. CSoundFile::LoadStaticTunings(); @@ -288,6 +293,9 @@ UpdateAudioParameters(TRUE); // Update the tree m_wndTree.Init(); + + CreateExampleModulesMenu(); + CreateTemplateModulesMenu(); } @@ -297,7 +305,7 @@ DeleteCriticalSection(&m_csAudio); delete m_InputHandler; //rewbs.customKeys delete m_pAutoSaver; //rewbs.autosaver - delete m_pPerfCounter; + //delete m_pPerfCounter; CChannelManagerDlg::DestroySharedInstance(); CSoundFile::DeleteStaticdata(); @@ -2160,6 +2168,61 @@ } +void CMainFrame::OpenMenuItemFile(const UINT nId, const bool bTemplateFile) +{ + const UINT nIdBegin = (bTemplateFile) ? ID_FILE_OPENTEMPLATE : ID_EXAMPLE_MODULES; + const std::vector<CString>& vecFilePaths = (bTemplateFile) ? s_TemplateModulePaths : s_ExampleModulePaths; + + const UINT nIndex = nId - nIdBegin; + if (nIndex < vecFilePaths.size()) + { + const CString& sPath = vecFilePaths[nIndex]; + const bool bAvailable = Util::sdOs::IsPathFileAvailable(sPath, Util::sdOs::FileModeRead); + if (bAvailable) + { + CDocument* pDoc = theApp.OpenDocumentFile(sPath); + if (pDoc != nullptr) + { + ASSERT(pDoc->IsKindOf(RUNTIME_CLASS(CModDoc)) == TRUE); + CModDoc* pModDoc = static_cast<CModDoc*>(pDoc); + pModDoc->ClearFilePath(); // Clear path so that saving will not take place in templates/examples folder. + if (bTemplateFile) + { + theApp.RemoveMruItem(0); + } + } + } + else + { + const bool bExists = Util::sdOs::IsPathFileAvailable(sPath, Util::sdOs::FileModeExists); + CString str; + if (bExists) + AfxFormatString1(str, IDS_FILE_EXISTS_BUT_IS_NOT_READABLE, (LPCTSTR)sPath); + else + AfxFormatString1(str, IDS_FILE_DOES_NOT_EXIST, (LPCTSTR)sPath); + AfxMessageBox(str); + } + } + else + ASSERT(false); +} + + +void CMainFrame::OnOpenTemplateModule(UINT nId) +//--------------------------------------------- +{ + OpenMenuItemFile(nId, true/*open template menu file*/); +} + + +void CMainFrame::OnExampleSong(UINT nId) +//-------------------------------------- +{ + OpenMenuItemFile(nId, false/*open example menu file*/); + +} + + LRESULT CMainFrame::OnInvalidatePatterns(WPARAM wParam, LPARAM) //------------------------------------------------------------- { @@ -2520,6 +2583,87 @@ } +HMENU CMainFrame::CreateFileMenu(const size_t nMaxCount, std::vector<CString>& vPaths, const LPCTSTR pszFolderName, const uint16 nIdRangeBegin) +//--------------------------------------------------------------------------------------------------------------------------------------------- +{ + vPaths.clear(); + HMENU hMenu = ::CreatePopupMenu(); + ASSERT(hMenu != NULL); + if (hMenu != NULL) + { + UINT_PTR nAddCounter = 0; + for(size_t i = 0; i < 2; i++) // 0: app items, 1: user items + { + // To avoid duplicates, check whether app path and config path are the same. + if (i == 1 && _tcsicmp(CTrackApp::GetAppDirPath(), theApp.GetConfigPath()) == 0) + break; + CFileFind fileFind; + CFixedStringT<CString, MAX_PATH> sPath; + sPath = (i == 0) ? CTrackApp::GetAppDirPath() : theApp.GetConfigPath(); + sPath += pszFolderName; + if (Util::sdOs::IsPathFileAvailable(sPath, Util::sdOs::FileModeExists) == false) + continue; + sPath += _T("*"); + + BOOL bWorking = fileFind.FindFile(sPath); + // Note: The order in which the example files appears in the menu is unspecified. + while (bWorking && nAddCounter < nMaxCount) + { + bWorking = fileFind.FindNextFile(); + const CString fn = fileFind.GetFileName(); + if (fileFind.IsDirectory() == FALSE) + { + vPaths.push_back(fileFind.GetFilePath()); + AppendMenu(hMenu, MF_STRING, nIdRangeBegin + nAddCounter, fileFind.GetFileName()); + ++nAddCounter; + } + } + fileFind.Close(); + } + + if (nAddCounter == 0) + AppendMenu(hMenu, MF_STRING | MF_GRAYED | MF_DISABLED, 0, _T("No items found")); + } + + return hMenu; +} + + +void CMainFrame::CreateExampleModulesMenu() +//----------------------------------------- +{ + static_assert(nMaxItemsInExampleModulesMenu == ID_EXAMPLE_MODULES_LASTINRANGE - ID_EXAMPLE_MODULES + 1, + "Make sure that there's a proper range for menu commands in resources."); + HMENU hMenu = CreateFileMenu(nMaxItemsInExampleModulesMenu, s_ExampleModulePaths, _T("ExampleSongs\\"), ID_EXAMPLE_MODULES); + CMenu* const pMainMenu = GetMenu(); + if (hMenu && pMainMenu && m_InputHandler) + VERIFY(pMainMenu->ModifyMenu(ID_EXAMPLE_MODULES, MF_BYCOMMAND | MF_POPUP, (UINT_PTR)hMenu, m_InputHandler->GetMenuText(ID_EXAMPLE_MODULES))); + else + ASSERT(false); +} + + +void CMainFrame::CreateTemplateModulesMenu() +//------------------------------------------ +{ + static_assert(nMaxItemsInTemplateModulesMenu == ID_FILE_OPENTEMPLATE_LASTINRANGE - ID_FILE_OPENTEMPLATE + 1, + "Make sure that there's a proper range for menu commands in resources."); + HMENU hMenu = CreateFileMenu(nMaxItemsInTemplateModulesMenu, s_TemplateModulePaths, _T("TemplateModules\\"), ID_FILE_OPENTEMPLATE); + CMenu* const pMainMenu = GetMenu(); + CMenu* pFileMenu = (pMainMenu) ? pMainMenu->GetSubMenu(0) : nullptr; + if (hMenu && pFileMenu && m_InputHandler) + { + if (pFileMenu->GetMenuItemID(1) != ID_FILE_OPEN) + pFileMenu = pMainMenu->GetSubMenu(1); + ASSERT(pFileMenu->GetMenuItemID(1) == ID_FILE_OPEN); + VERIFY(pFileMenu->RemoveMenu(2, MF_BYPOSITION)); + VERIFY(pFileMenu->InsertMenu(2, MF_BYPOSITION | MF_POPUP, (UINT_PTR)hMenu, m_InputHandler->GetMenuText(ID_FILE_OPENTEMPLATE))); + } + else + ASSERT(false); +} + + ///////////////////////////////////////////// //Misc helper functions ///////////////////////////////////////////// @@ -2533,10 +2677,10 @@ PSNDMIXPLUGIN p = &plugarray[iPlug]; CString str; str.Preallocate(80); - str.Format("FX%d: ", iPlug+1); + str.Format(_T("FX%d: "), iPlug+1); const int size0 = str.GetLength(); str += (librarynames) ? p->GetLibraryName() : p->GetName(); - if(str.GetLength() <= size0) str += "undefined"; + if(str.GetLength() <= size0) str += _T("undefined"); CBox.SetItemData(CBox.AddString(str), iPlug + 1); } Modified: trunk/OpenMPT/mptrack/Mainfrm.h =================================================================== --- trunk/OpenMPT/mptrack/Mainfrm.h 2011-07-28 14:59:55 UTC (rev 931) +++ trunk/OpenMPT/mptrack/Mainfrm.h 2011-07-28 20:51:57 UTC (rev 932) @@ -502,7 +502,7 @@ static VOID GetKeyName(LONG lParam, LPSTR pszName, UINT cbSize); static CInputHandler *m_InputHandler; //rewbs.customKeys static CAutoSaver *m_pAutoSaver; //rewbs.customKeys - static CPerformanceCounter *m_pPerfCounter; + //static CPerformanceCounter *m_pPerfCounter; static bool WritePrivateProfileLong(const CString section, const CString key, const long value, const CString iniFile); static long GetPrivateProfileLong(const CString section, const CString key, const long defaultValue, const CString iniFile); @@ -535,6 +535,19 @@ double GetApproxBPM(); //rewbs.VSTTimeInfo void ThreadSafeSetModified(CModDoc* modified) {m_pJustModifiedDoc=modified;} + void CreateExampleModulesMenu(); + void CreateTemplateModulesMenu(); + + /// Creates submenu whose items are filenames of files in both + /// AppDirectory\pszFolderName\ (usually C:\program files\OpenMPT\pszFolderName\) + /// and + /// ConfigDirectory\pszFolderName (usually %appdata%\OpenMPT\pszFolderName\) + /// [in] nMaxCount: Maximum number of items allowed in the menu + /// [out] vPaths: Receives the full paths of the files added to the menu. + /// [in] pszFolderName: Name of the folder (should end with \) + /// [in] nIdRangeBegin: First ID for the menu item. + static HMENU CreateFileMenu(const size_t nMaxCount, std::vector<CString>& vPaths, const LPCTSTR pszFolderName, const uint16 nIdRangeBegin); + // Player functions public: BOOL PlayMod(CModDoc *, HWND hPat=NULL, DWORD dwNotifyType=0); @@ -576,6 +589,9 @@ virtual void OnUpdateFrameTitle(BOOL bAddToTitle); //}}AFX_VIRTUAL + /// Opens either template or example menu item. + void OpenMenuItemFile(const UINT nId, const bool bTemplateFile); + // Implementation public: virtual ~CMainFrame(); @@ -625,6 +641,8 @@ afx_msg void OnReportBug(); //rewbs.customKeys afx_msg BOOL OnInternetLink(UINT nID); afx_msg LRESULT OnUpdatePosition(WPARAM, LPARAM lParam); + afx_msg void OnExampleSong(UINT nId); + afx_msg void OnOpenTemplateModule(UINT nId); afx_msg LRESULT OnInvalidatePatterns(WPARAM, LPARAM); afx_msg LRESULT OnSpecialKey(WPARAM, LPARAM); afx_msg LRESULT OnCustomKeyMsg(WPARAM, LPARAM); @@ -639,6 +657,14 @@ afx_msg void OnKillFocus(CWnd* pNewWnd); afx_msg void OnShowWindow(BOOL bShow, UINT nStatus); + // Defines maximum number of items in example modules menu. + static const size_t nMaxItemsInExampleModulesMenu = 50; + static const size_t nMaxItemsInTemplateModulesMenu = 50; + + /// Array of paths of example modules that are available from help menu. + static std::vector<CString> s_ExampleModulePaths; + /// Array of paths of template modules that are available from file menu. + static std::vector<CString> s_TemplateModulePaths; }; const CHAR gszBuildDate[] = __DATE__ " " __TIME__; Modified: trunk/OpenMPT/mptrack/Moddoc.cpp =================================================================== --- trunk/OpenMPT/mptrack/Moddoc.cpp 2011-07-28 14:59:55 UTC (rev 931) +++ trunk/OpenMPT/mptrack/Moddoc.cpp 2011-07-28 20:51:57 UTC (rev 932) @@ -15,6 +15,7 @@ #include "version.h" #include "modsmp_ctrl.h" #include "CleanupSong.h" +#include <shlwapi.h> extern WORD S3MFineTuneTable[16]; @@ -30,7 +31,22 @@ const TCHAR FileFilterIT[] = _T("Impulse Tracker Modules (*.it)|*.it||"); const TCHAR FileFilterITP[] = _T("Impulse Tracker Projects (*.itp)|*.itp||"); const TCHAR FileFilterMPT[] = _T("OpenMPT Modules (*.mptm)|*.mptm||"); +const TCHAR FileFilterNone[] = _T(""); +const TCHAR* ModTypeToFilter(const CSoundFile& sndFile) +{ + const MODTYPE modtype = sndFile.GetType(); + switch(modtype) + { + case MOD_TYPE_MOD: return FileFilterMOD; + case MOD_TYPE_XM: return FileFilterXM; + case MOD_TYPE_S3M: return FileFilterS3M; + case MOD_TYPE_IT: return (sndFile.m_dwSongFlags & SONG_ITPROJECT) ? FileFilterITP : FileFilterIT; + case MOD_TYPE_MPT: return FileFilterMPT; + default: return FileFilterNone; + } +} + ///////////////////////////////////////////////////////////////////////////// // CModDoc @@ -38,6 +54,7 @@ BEGIN_MESSAGE_MAP(CModDoc, CDocument) //{{AFX_MSG_MAP(CModDoc) + ON_COMMAND(ID_FILE_SAVEASTEMPLATE, OnSaveTemplateModule) ON_COMMAND(ID_FILE_SAVEASWAVE, OnFileWaveConvert) ON_COMMAND(ID_FILE_SAVEASMP3, OnFileMP3Convert) ON_COMMAND(ID_FILE_SAVEMIDI, OnFileMidiConvert) @@ -414,26 +431,32 @@ } -BOOL CModDoc::OnSaveDocument(LPCTSTR lpszPathName) +BOOL CModDoc::OnSaveDocument(LPCTSTR lpszPathName, const bool bTemplateFile) //------------------------------------------------ { static int greccount = 0; - TCHAR fext[_MAX_EXT]=""; - UINT nType = m_SndFile.m_nType, dwPacking = 0; + TCHAR fext[_MAX_EXT] = _T(""); + UINT dwPacking = 0; BOOL bOk = FALSE; m_SndFile.m_dwLastSavedWithVersion = MptVersion::num; - if (!lpszPathName) return FALSE; + if (!lpszPathName) + return FALSE; _tsplitpath(lpszPathName, NULL, NULL, NULL, fext); - if (!lstrcmpi(fext, ".mod")) nType = MOD_TYPE_MOD; else - if (!lstrcmpi(fext, ".s3m")) nType = MOD_TYPE_S3M; else - if (!lstrcmpi(fext, ".xm")) nType = MOD_TYPE_XM; else + MODTYPE type = CModSpecifications::ExtensionToType(fext); + + /* + if (!lstrcmpi(fext, ".mod")) type = MOD_TYPE_MOD; else + if (!lstrcmpi(fext, ".s3m")) type = MOD_TYPE_S3M; else + if (!lstrcmpi(fext, ".xm")) type = MOD_TYPE_XM; else // -> CODE#0023 // -> DESC="IT project files (.itp)" // if (!lstrcmpi(fext, ".it")) nType = MOD_TYPE_IT; else - if (!lstrcmpi(fext, ".it") || !lstrcmpi(fext, ".itp")) nType = MOD_TYPE_IT; else - if (!lstrcmpi(fext, ".mptm")) nType = MOD_TYPE_MPT; else + if (!lstrcmpi(fext, ".it") || !lstrcmpi(fext, ".itp")) type = MOD_TYPE_IT; else + if (!lstrcmpi(fext, ".mptm")) type = MOD_TYPE_MPT; else // -! NEW_FEATURE#0023 - if (!greccount) +*/ + + if (type == MOD_TYPE_NONE && !greccount) { greccount++; bOk = DoSave(NULL, TRUE); @@ -443,23 +466,32 @@ BeginWaitCursor(); ClearLog(); FixNullStrings(); - switch(nType) + switch(type) { case MOD_TYPE_MOD: bOk = m_SndFile.SaveMod(lpszPathName, dwPacking); break; case MOD_TYPE_S3M: bOk = m_SndFile.SaveS3M(lpszPathName, dwPacking); break; case MOD_TYPE_XM: bOk = m_SndFile.SaveXM(lpszPathName, dwPacking); break; - case MOD_TYPE_IT: bOk = (m_SndFile.m_dwSongFlags & SONG_ITPROJECT || !lstrcmpi(fext, ".itp")) ? m_SndFile.SaveITProject(lpszPathName) : m_SndFile.SaveIT(lpszPathName, dwPacking); break; + case MOD_TYPE_IT: bOk = (m_SndFile.m_dwSongFlags & SONG_ITPROJECT || !lstrcmpi(fext, _T(".itp"))) ? m_SndFile.SaveITProject(lpszPathName) : m_SndFile.SaveIT(lpszPathName, dwPacking); break; case MOD_TYPE_MPT: bOk = m_SndFile.SaveIT(lpszPathName, dwPacking); break; } EndWaitCursor(); if (bOk) { - if (nType == m_SndFile.m_nType) SetPathName(lpszPathName); + if (type == m_SndFile.GetType() && !bTemplateFile) + SetPathName(lpszPathName); ShowLog(); + if (bTemplateFile) + { + CMainFrame* const pMainFrame = CMainFrame::GetMainFrame(); + if (pMainFrame) + pMainFrame->CreateTemplateModulesMenu(); + } } else { - if(nType == MOD_TYPE_IT && m_SndFile.m_dwSongFlags & SONG_ITPROJECT) ::MessageBox(NULL,"ITP projects need to have a path set for each instrument...",NULL,MB_ICONERROR | MB_OK); - else ErrorBox(IDS_ERR_SAVESONG, CMainFrame::GetMainFrame()); + if(type == MOD_TYPE_IT && m_SndFile.m_dwSongFlags & SONG_ITPROJECT) + AfxMessageBox(_T("ITP projects need to have a path set for each instrument..."), MB_ICONERROR | MB_OK); + else + ErrorBox(IDS_ERR_SAVESONG, CMainFrame::GetMainFrame()); } return bOk; } @@ -3898,3 +3930,40 @@ // Sequence names. // Not needed? } + +void CModDoc::OnSaveTemplateModule() +{ + // Create template folder if doesn't exist already. + const LPCTSTR pszTemplateFolder = CMainFrame::GetSettings().GetDefaultDirectory(DIR_TEMPLATE_FILES_USER); + if (!PathIsDirectory(pszTemplateFolder)) + { + if (!CreateDirectory(pszTemplateFolder, nullptr)) + { + CString sErrMsg; + AfxFormatString1(sErrMsg, IDS_UNABLE_TO_CREATE_USER_TEMPLATE_FOLDER, pszTemplateFolder); + AfxMessageBox(sErrMsg); + return; + } + } + + // Generate file name candidate. + CString sName; + for(size_t i = 0; i<1000; ++i) + { + sName.Format(_T("newTemplate%u."), i); + sName += m_SndFile.GetModSpecifications().fileExtension; + if (!Util::sdOs::IsPathFileAvailable(pszTemplateFolder + sName, Util::sdOs::FileModeExists)) + break; + } + + // Ask file name from user. + FileDlgResult fdr = CTrackApp::ShowOpenSaveFileDialog(false, m_SndFile.GetModSpecifications().fileExtension, (LPCTSTR)sName, + ModTypeToFilter(m_SndFile), pszTemplateFolder); + + if (fdr.abort) + return; + + const CString sOldPath = m_strPathName; + OnSaveDocument(fdr.first_file.c_str(), true/*template file*/); + m_strPathName = sOldPath; +} Modified: trunk/OpenMPT/mptrack/Moddoc.h =================================================================== --- trunk/OpenMPT/mptrack/Moddoc.h 2011-07-28 14:59:55 UTC (rev 931) +++ trunk/OpenMPT/mptrack/Moddoc.h 2011-07-28 20:51:57 UTC (rev 932) @@ -223,6 +223,7 @@ LPCSTR GetLog() const { return m_lpszLog; } BOOL ClearLog(); UINT ShowLog(LPCSTR lpszTitle=NULL, CWnd *parent=NULL); + void ClearFilePath() {m_strPathName.Empty();} // Logging for general progress and error events. void AddLogEvent(LogEventType eventType, LPCTSTR pszFuncName, LPCTSTR pszFormat, ...); @@ -383,9 +384,10 @@ public: virtual BOOL OnNewDocument(); virtual BOOL OnOpenDocument(LPCTSTR lpszPathName); - virtual BOOL OnSaveDocument(LPCTSTR lpszPathName); + virtual BOOL OnSaveDocument(LPCTSTR lpszPathName) {return OnSaveDocument(lpszPathName, false);} virtual void OnCloseDocument(); void SafeFileClose(); + BOOL OnSaveDocument(LPCTSTR lpszPathName, const bool bTemplateFile); // -> CODE#0023 // -> DESC="IT project files (.itp)" @@ -439,6 +441,7 @@ afx_msg void OnPatternPlayNoLoop(); //rewbs.customKeys afx_msg void OnViewEditHistory(); afx_msg void OnViewMPTHacks(); + afx_msg void OnSaveTemplateModule(); //}}AFX_MSG DECLARE_MESSAGE_MAP() private: Modified: trunk/OpenMPT/mptrack/Mptrack.cpp =================================================================== --- trunk/OpenMPT/mptrack/Mptrack.cpp 2011-07-28 14:59:55 UTC (rev 931) +++ trunk/OpenMPT/mptrack/Mptrack.cpp 2011-07-28 20:51:57 UTC (rev 932) @@ -17,6 +17,7 @@ #include "version.h" #include "test/test.h" #include <shlwapi.h> +#include <afxadv.h> #include "UpdateCheck.h" // rewbs.memLeak @@ -768,6 +769,11 @@ strcpy(m_szPluginCacheFileName, m_szConfigDirectory); // plugin cache strcat(m_szPluginCacheFileName, "plugin.cache"); + TCHAR szTemplatePath[MAX_PATH]; + _tcscpy(szTemplatePath, m_szConfigDirectory); + _tcscat(szTemplatePath, _T("TemplateModules\\")); + CMainFrame::GetSettings().SetDefaultDirectory(szTemplatePath, DIR_TEMPLATE_FILES_USER); + m_bPortableMode = bIsAppDir; } @@ -3138,3 +3144,9 @@ } SetNullTerminator(szPath); } + +void CTrackApp::RemoveMruItem(const int nItem) +{ + if (m_pRecentFileList && nItem >= 0 && nItem < m_pRecentFileList->GetSize()) + m_pRecentFileList->Remove(nItem); +} Modified: trunk/OpenMPT/mptrack/Mptrack.h =================================================================== --- trunk/OpenMPT/mptrack/Mptrack.h 2011-07-28 14:59:55 UTC (rev 931) +++ trunk/OpenMPT/mptrack/Mptrack.h 2011-07-28 20:51:57 UTC (rev 932) @@ -178,10 +178,12 @@ BOOL CanEncodeLayer3() const { return m_bLayer3Present; } BOOL IsWaveExEnabled() const { return m_bExWaveSupport; } BOOL IsDebug() const { return m_bDebugMode; } - LPCSTR GetConfigFileName() const { return m_szConfigFileName; } + LPCTSTR GetConfigFileName() const { return m_szConfigFileName; } static bool IsPortableMode() { return m_bPortableMode; } - LPCSTR GetPluginCacheFileName() const { return m_szPluginCacheFileName; } - LPCSTR GetConfigPath() const { return m_szConfigDirectory; } + LPCTSTR GetPluginCacheFileName() const { return m_szPluginCacheFileName; } + + /// Returns path to config folder including trailing '\'. + LPCTSTR GetConfigPath() const { return m_szConfigDirectory; } void SetupPaths(bool overridePortable); // Relative / absolute paths conversion template <size_t nLength> @@ -189,6 +191,9 @@ template <size_t nLength> void RelativePathToAbsolute(TCHAR (&szPath)[nLength]); + /// Removes item from MRU-list; most recent item has index zero. + void RemoveMruItem(const int nItem); + // Splash Screen protected: VOID StartSplashScreen(); Modified: trunk/OpenMPT/mptrack/PerformanceCounter.h =================================================================== --- trunk/OpenMPT/mptrack/PerformanceCounter.h 2011-07-28 14:59:55 UTC (rev 931) +++ trunk/OpenMPT/mptrack/PerformanceCounter.h 2011-07-28 20:51:57 UTC (rev 932) @@ -1,5 +1,6 @@ #pragma once +#if 0 class CPerformanceCounter { protected: @@ -59,3 +60,4 @@ } }; +#endif Modified: trunk/OpenMPT/mptrack/TrackerSettings.cpp =================================================================== --- trunk/OpenMPT/mptrack/TrackerSettings.cpp 2011-07-28 14:59:55 UTC (rev 931) +++ trunk/OpenMPT/mptrack/TrackerSettings.cpp 2011-07-28 20:51:57 UTC (rev 932) @@ -22,7 +22,7 @@ #include "TrackerSettings.h" -const TCHAR *TrackerSettings::m_szDirectoryToSettingsName[NUM_DIRS] = { _T("Songs_Directory"), _T("Samples_Directory"), _T("Instruments_Directory"), _T("Plugins_Directory"), _T("Plugin_Presets_Directory"), _T("Export_Directory"), _T("") }; +const TCHAR *TrackerSettings::m_szDirectoryToSettingsName[NUM_DIRS] = { _T("Songs_Directory"), _T("Samples_Directory"), _T("Instruments_Directory"), _T("Plugins_Directory"), _T("Plugin_Presets_Directory"), _T("Export_Directory"), _T(""), _T("") }; TrackerSettings::TrackerSettings() Modified: trunk/OpenMPT/mptrack/TrackerSettings.h =================================================================== --- trunk/OpenMPT/mptrack/TrackerSettings.h 2011-07-28 14:59:55 UTC (rev 931) +++ trunk/OpenMPT/mptrack/TrackerSettings.h 2011-07-28 20:51:57 UTC (rev 932) @@ -24,6 +24,7 @@ DIR_PLUGINPRESETS, DIR_EXPORT, DIR_TUNING, + DIR_TEMPLATE_FILES_USER, NUM_DIRS }; Modified: trunk/OpenMPT/mptrack/TuningDialog.h =================================================================== --- trunk/OpenMPT/mptrack/TuningDialog.h 2011-07-28 14:59:55 UTC (rev 931) +++ trunk/OpenMPT/mptrack/TuningDialog.h 2011-07-28 20:51:57 UTC (rev 932) @@ -7,6 +7,7 @@ #include <string> #include "afxcmn.h" #include "afxwin.h" +#include "resource.h" using std::vector; using std::string; Modified: trunk/OpenMPT/mptrack/misc_util.h =================================================================== --- trunk/OpenMPT/mptrack/misc_util.h 2011-07-28 14:59:55 UTC (rev 931) +++ trunk/OpenMPT/mptrack/misc_util.h 2011-07-28 20:51:57 UTC (rev 932) @@ -4,9 +4,11 @@ #include <sstream> #include <string> #include <limits> +#include "typedefs.h" #if _HAS_TR1 #include <type_traits> #endif +#include <io.h> // for _taccess //Convert object(typically number) to string template<class T> @@ -245,6 +247,9 @@ // Like std::max, but avoids conflict with max-macro. template <class T> inline const T& Max(const T& a, const T& b) {return (std::max)(a, b);} + // Like std::min, but avoids conflict with min-macro. + template <class T> inline const T& Min(const T& a, const T& b) {return (std::min)(a, b);} + // Returns maximum value of given integer type. template <class T> inline T MaxValueOfType(const T&) {static_assert(std::numeric_limits<T>::is_integer == true, "Only interger types are allowed."); return (std::numeric_limits<T>::max)();} @@ -260,5 +265,12 @@ }}; // namespace Util::sdTime +namespace Util { namespace sdOs +{ + /// Checks whether file or folder exists and whether it has the given mode. + enum FileMode {FileModeExists = 0, FileModeRead = 4, FileModeWrite = 2, FileModeReadWrite = 6}; + inline bool IsPathFileAvailable(LPCTSTR pszFilePath, FileMode fm) {return (_taccess(pszFilePath, fm) == 0);} +} } // namespace Util::sdOs + #endif Modified: trunk/OpenMPT/mptrack/mptrack.rc =================================================================== --- trunk/OpenMPT/mptrack/mptrack.rc 2011-07-28 14:59:55 UTC (rev 931) +++ trunk/OpenMPT/mptrack/mptrack.rc 2011-07-28 20:51:57 UTC (rev 932) @@ -13,7 +13,7 @@ #undef APSTUDIO_READONLY_SYMBOLS ///////////////////////////////////////////////////////////////////////////// -// Deutsch (Deutschland) resources +// German (Germany) resources #if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_DEU) #ifdef _WIN32 @@ -148,7 +148,6 @@ PUSHBUTTON "Add",IDC_BUTTON_ADD,174,78,50,14 END - IDD_EDITHISTORY DIALOGEX 0, 0, 316, 185 STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | WS_POPUP | WS_CAPTION | WS_SYSMENU CAPTION "Module edit history" @@ -300,12 +299,12 @@ END #endif // APSTUDIO_INVOKED -#endif // Deutsch (Deutschland) resources +#endif // German (Germany) resources ///////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////// -// Englisch (USA) resources +// English (U.S.) resources #if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU) #ifdef _WIN32 @@ -1982,10 +1981,12 @@ MENUITEM "IT &Project", ID_NEW_ITPROJECT MENUITEM "Open&MPT Module", ID_NEW_MPT END - MENUITEM "&Open...\tCtrl+O", 57601 + MENUITEM "&Open...\tCtrl+O", ID_FILE_OPEN + MENUITEM "Open template", 65535 MENUITEM "&Close", ID_FILE_CLOSE MENUITEM "&Save\tCtrl+S", ID_FILE_SAVE MENUITEM "Save &As...", ID_FILE_SAVE_AS + MENUITEM "Save as Template...", ID_FILE_SAVEASTEMPLATE MENUITEM "Export &unraped...", ID_FILE_SAVECOMPAT MENUITEM "Export as &Wave...", ID_FILE_SAVEASWAVE MENUITEM "Export as M&P3...", ID_FILE_SAVEASMP3 @@ -2070,6 +2071,8 @@ MENUITEM "&Search...", ID_HELP_SEARCH MENUITEM "&Report a bug", ID_REPORT_BUG MENUITEM SEPARATOR + MENUITEM "&Example modules", ID_EXAMPLE_MODULES + MENUITEM SEPARATOR MENUITEM "&OpenMPT Website", ID_NETLINK_MODPLUG MENUITEM "&Web Resources", ID_NETLINK_TOP_PICKS MENUITEM SEPARATOR @@ -2481,16 +2484,27 @@ IDS_TUNING_IMPORT_UNRECOGNIZED_FILE "-Unable to import file ""%1%2"": unrecognized file.\n" IDS_SOUNDTOUCH_LOADFAILURE "Unable to load OpenMPT_soundtouch_i16.dll." + IDS_UNABLE_TO_CREATE_USER_TEMPLATE_FOLDER + """Error: Unable to create template folder '%1'""" + IDS_FILE_DOES_NOT_EXIST "The file '%1' does not exist" + IDS_FILE_EXISTS_BUT_IS_NOT_READABLE + "The file '%1' exists but can't be read" END STRINGTABLE BEGIN ID_PANIC "Kill all VSTi and sample voices\nStop all hanging VSTi and sample voices" ID_VIEW_EDITHISTORY "View the edit history of this module" + ID_FILE_SAVEASTEMPLATE "Save the active document as template module\nSave as Template" END STRINGTABLE BEGIN + ID_FILE_OPENTEMPLATE "Open a template document\nOpen template document" +END + +STRINGTABLE +BEGIN ID_VIEW_MIDIMAPPING "Configure the MIDI Mapping" END @@ -2510,12 +2524,12 @@ IDC_SAMPLE_XFADE "Crossfade Loop Points\nCrossfade between loop start and loop end to create seamless sample loops." END -#endif // Englisch (USA) resources +#endif // English (U.S.) resources ///////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////// -// Englisch (GB) resources +// English (U.K.) resources #if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENG) #ifdef _WIN32 @@ -2888,7 +2902,7 @@ // IDR_BUILTIN_TUNINGS TUNING "res\\built-inTunings.tc" -#endif // Englisch (GB) resources +#endif // English (U.K.) resources ///////////////////////////////////////////////////////////////////////////// Modified: trunk/OpenMPT/mptrack/resource.h =================================================================== --- trunk/OpenMPT/mptrack/resource.h 2011-07-28 14:59:55 UTC (rev 931) +++ trunk/OpenMPT/mptrack/resource.h 2011-07-28 20:51:57 UTC (rev 932) @@ -67,6 +67,9 @@ #define IDS_TUNING_IMPORT_SCL_FAILURE 228 #define IDS_TUNING_IMPORT_UNRECOGNIZED_FILE 229 #define IDS_SOUNDTOUCH_LOADFAILURE 230 +#define IDS_UNABLE_TO_CREATE_USER_TEMPLATE_FOLDER 231 +#define IDS_FILE_DOES_NOT_EXIST 232 +#define IDS_FILE_EXISTS_BUT_IS_NOT_READABLE 233 #define IDB_MAINBAR 300 #define IDB_IMAGELIST 301 #define IDB_PATTERNS 302 @@ -1124,6 +1127,10 @@ #define ID_GROW_SELECTION 40001 #define ID_SHRINK_SELECTION 40002 #define ID_RUN_SCRIPT 40003 +#define ID_EXAMPLE_MODULES 40004 +#define ID_EXAMPLE_MODULES_LASTINRANGE 40053 +#define ID_FILE_OPENTEMPLATE 40054 +#define ID_FILE_OPENTEMPLATE_LASTINRANGE 40103 #define IDS_ERR_FILEOPEN 55001 #define IDS_ERR_FILETYPE 55002 #define IDS_ERR_SAVEINS 55003 @@ -1189,6 +1196,8 @@ #define ID_VIEW_MPTHACKS 60456 #define ID_PLUGINTOINSTRUMENT 60457 #define ID_INTERNETUPDATE 60458 +#define ID_HELP_EXAMPLEMODULES 60459 +#define ID_FILE_SAVEASTEMPLATE 60460 // Next default values for new objects // @@ -1196,7 +1205,7 @@ #ifndef APSTUDIO_READONLY_SYMBOLS #define _APS_3D_CONTROLS 1 #define _APS_NEXT_RESOURCE_VALUE 530 -#define _APS_NEXT_COMMAND_VALUE 60459 +#define _APS_NEXT_COMMAND_VALUE 60461 #define _APS_NEXT_CONTROL_VALUE 2436 #define _APS_NEXT_SYMED_VALUE 901 #endif Modified: trunk/OpenMPT/mptrack/test/test.cpp =================================================================== --- trunk/OpenMPT/mptrack/test/test.cpp 2011-07-28 14:59:55 UTC (rev 931) +++ trunk/OpenMPT/mptrack/test/test.cpp 2011-07-28 20:51:57 UTC (rev 932) @@ -203,6 +203,23 @@ VERIFY_EQUAL(MODCOMMAND::IsPcNote(NOTE_MAX), false); VERIFY_EQUAL(MODCOMMAND::IsPcNote(NOTE_PC), true); VERIFY_EQUAL(MODCOMMAND::IsPcNote(NOTE_PCS), true); + + VERIFY_EQUAL(CModSpecifications::ExtensionToType(_T(".mod")), MOD_TYPE_MOD); + VERIFY_EQUAL(CModSpecifications::ExtensionToType(_T("mod")), MOD_TYPE_MOD); + VERIFY_EQUAL(CModSpecifications::ExtensionToType(_T(".s3m")), MOD_TYPE_S3M); + VERIFY_EQUAL(CModSpecifications::ExtensionToType(_T("s3m")), MOD_TYPE_S3M); + VERIFY_EQUAL(CModSpecifications::ExtensionToType(_T(".xm")), MOD_TYPE_XM); + VERIFY_EQUAL(CModSpecifications::ExtensionToType(_T("xm")), MOD_TYPE_XM); + VERIFY_EQUAL(CModSpecifications::ExtensionToType(_T(".it")), MOD_TYPE_IT); + VERIFY_EQUAL(CModSpecifications::ExtensionToType(_T("it")), MOD_TYPE_IT); + VERIFY_EQUAL(CModSpecifications::ExtensionToType(_T(".itp")), MOD_TYPE_IT); + VERIFY_EQUAL(CModSpecifications::ExtensionToType(_T("itp")), MOD_TYPE_IT); + VERIFY_EQUAL(CModSpecifications::ExtensionToType(_T("mptm")), MOD_TYPE_MPT); + VERIFY_EQUAL(CModSpecifications::ExtensionToType(_T("invalidExtension")), MOD_TYPE_NONE); + VERIFY_EQUAL(CModSpecifications::ExtensionToType(_T("ita")), MOD_TYPE_NONE); + VERIFY_EQUAL(CModSpecifications::ExtensionToType(_T("s2m")), MOD_TYPE_NONE); + VERIFY_EQUAL(CModSpecifications::ExtensionToType(_T("")), MOD_TYPE_NONE); + VERIFY_EQUAL(CModSpecifications::ExtensionToType(LPCTSTR(nullptr)), MOD_TYPE_NONE); } Modified: trunk/OpenMPT/mptrack/tuningRatioMapWnd.h =================================================================== --- trunk/OpenMPT/mptrack/tuningRatioMapWnd.h 2011-07-28 14:59:55 UTC (rev 931) +++ trunk/OpenMPT/mptrack/tuningRatioMapWnd.h 2011-07-28 20:51:57 UTC (rev 932) @@ -1,7 +1,7 @@ #ifndef TUNINGRATIOMAPWND_H #define TUNINGRATIOMAPWND_H -#include "../soundlib/tuningbase.h" +#include "../soundlib/tuning.h" class CTuningDialog; Modified: trunk/OpenMPT/soundlib/SNDDEVX.H =================================================================== --- trunk/OpenMPT/soundlib/SNDDEVX.H 2011-07-28 14:59:55 UTC (rev 931) +++ trunk/OpenMPT/soundlib/SNDDEVX.H 2011-07-28 20:51:57 UTC (rev 932) @@ -2,6 +2,7 @@ #define _SNDDEVX_H_ #include <mmsystem.h> +#include "snddev.h" #ifndef NO_DSOUND #include <dsound.h> Modified: trunk/OpenMPT/soundlib/mod_specifications.cpp =================================================================== --- trunk/OpenMPT/soundlib/mod_specifications.cpp 2011-07-28 14:59:55 UTC (rev 931) +++ trunk/OpenMPT/soundlib/mod_specifications.cpp 2011-07-28 20:51:57 UTC (rev 932) @@ -1,6 +1,34 @@ #include <stdafx.h> #include "mod_specifications.h" +MODTYPE CModSpecifications::ExtensionToType(LPCTSTR pszExt) +{ + if (pszExt == nullptr) + return MOD_TYPE_NONE; + if (pszExt[0] == '.') + pszExt++; + char szExtA[CountOf(ModSpecs::mod.fileExtension)]; + MemsetZero(szExtA); + size_t i = 0; + const size_t nLength = _tcslen(pszExt); + if (nLength >= CountOf(szExtA)) + return MOD_TYPE_NONE; + for(i = 0; i<nLength; ++i) + szExtA[i] = static_cast<char>(pszExt[i]); + if (!lstrcmpiA(szExtA, ModSpecs::mod.fileExtension) || !lstrcmpiA(szExtA, ModSpecs::modEx.fileExtension)) + return MOD_TYPE_MOD; + else if (!lstrcmpiA(szExtA, ModSpecs::s3m.fileExtension) || !lstrcmpiA(szExtA, ModSpecs::s3mEx.fileExtension)) + return MOD_TYPE_S3M; + else if (!lstrcmpiA(szExtA, ModSpecs::xm.fileExtension) || !lstrcmpiA(szExtA, ModSpecs::xmEx.fileExtension)) + return MOD_TYPE_XM; + else if (!lstrcmpiA(szExtA, ModSpecs::it.fileExtension) || !lstrcmpiA(szExtA, ModSpecs::itEx.fileExtension) + || !lstrcmpi(szExtA, _T("itp"))) + return MOD_TYPE_IT; + else if (!lstrcmpiA(szExtA, ModSpecs::mptm.fileExtension)) + return MOD_TYPE_MPT; + else + return MOD_TYPE_NONE; +} bool CModSpecifications::HasNote(MODCOMMAND::NOTE note) const //------------------------------------------------------------ Modified: trunk/OpenMPT/soundlib/mod_specifications.h =================================================================== --- trunk/OpenMPT/soundlib/mod_specifications.h 2011-07-28 14:59:55 UTC (rev 931) +++ trunk/OpenMPT/soundlib/mod_specifications.h 2011-07-28 20:51:57 UTC (rev 932) @@ -10,6 +10,10 @@ struct CModSpecifications //======================= { + /// Returns modtype corresponding to given file extension. The extension string + /// may begin with or without dot, e.g. both ".it" and "it" will be handled correctly. + static MODTYPE ExtensionToType(LPCTSTR pszExt); + // Return true if format supports given note. bool HasNote(MODCOMMAND::NOTE note) const; bool HasVolCommand(MODCOMMAND::VOLCMD volcmd) const; This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |