From: <sag...@us...> - 2014-12-14 23:50:26
|
Revision: 4650 http://sourceforge.net/p/modplug/code/4650 Author: saga-games Date: 2014-12-14 23:50:14 +0000 (Sun, 14 Dec 2014) Log Message: ----------- [New] Remember window positions for each tune individually when it is being saved (http://forum.openmpt.org/index.php?topic=3280.0). [Mod] VST editor positions are now stored alongside other song window settings in SongSettings.ini Modified Paths: -------------- trunk/OpenMPT/common/misc_util.cpp trunk/OpenMPT/common/mptString.cpp trunk/OpenMPT/installer/install.iss trunk/OpenMPT/mptrack/Childfrm.cpp trunk/OpenMPT/mptrack/Childfrm.h trunk/OpenMPT/mptrack/Ctrl_ins.cpp trunk/OpenMPT/mptrack/Ctrl_pat.cpp trunk/OpenMPT/mptrack/Ctrl_smp.cpp trunk/OpenMPT/mptrack/Globals.cpp trunk/OpenMPT/mptrack/Globals.h trunk/OpenMPT/mptrack/Moddoc.cpp trunk/OpenMPT/mptrack/Moddoc.h trunk/OpenMPT/mptrack/Mptrack.cpp trunk/OpenMPT/mptrack/Mptrack.h trunk/OpenMPT/mptrack/View_gen.cpp trunk/OpenMPT/mptrack/view_com.cpp trunk/OpenMPT/soundlib/Load_it.cpp Modified: trunk/OpenMPT/common/misc_util.cpp =================================================================== --- trunk/OpenMPT/common/misc_util.cpp 2014-12-13 23:30:29 UTC (rev 4649) +++ trunk/OpenMPT/common/misc_util.cpp 2014-12-14 23:50:14 UTC (rev 4650) @@ -559,7 +559,7 @@ namespace Util { - + static const MPT_UCHAR_TYPE EncodeNibble[16] = { MPT_UCHAR('0'), MPT_UCHAR('1'), MPT_UCHAR('2'), MPT_UCHAR('3'), MPT_UCHAR('4'), MPT_UCHAR('5'), MPT_UCHAR('6'), MPT_UCHAR('7'), @@ -613,10 +613,10 @@ std::vector<char> HexToBin(const mpt::ustring &src) { std::vector<char> result; - for(std::size_t i = 0; i+1 < src.size(); i += 2) + for(std::size_t i = 0; (i + 1) < src.size(); i += 2) { uint8 byte = 0; - if(!DecodeByte(byte, src[i*2+0], src[i*2+1])) + if(!DecodeByte(byte, src[i], src[i + 1])) { return result; } @@ -643,7 +643,7 @@ #if defined(MODPLUG_TRACKER) - + static bool SystemIsNT = true; // Initialize to used SDK version @@ -840,7 +840,7 @@ break; #if 0 // Using restricted search paths applies to potential DLL dependencies - // recursively. + // recursively. // This fails loading for e.g. Codec or Plugin DLLs in application // directory if they depend on the MSVC C or C++ runtime (which is // located in the system directory). @@ -946,7 +946,7 @@ inited = false; } } - + public: bool IsValid() const Modified: trunk/OpenMPT/common/mptString.cpp =================================================================== --- trunk/OpenMPT/common/mptString.cpp 2014-12-13 23:30:29 UTC (rev 4649) +++ trunk/OpenMPT/common/mptString.cpp 2014-12-14 23:50:14 UTC (rev 4650) @@ -1454,6 +1454,7 @@ { Tstring result; const std::size_t len = format.length(); + result.reserve(len); for(std::size_t pos = 0; pos != len; ++pos) { typename Tstring::value_type c = format[pos]; Modified: trunk/OpenMPT/installer/install.iss =================================================================== --- trunk/OpenMPT/installer/install.iss 2014-12-13 23:30:29 UTC (rev 4649) +++ trunk/OpenMPT/installer/install.iss 2014-12-14 23:50:14 UTC (rev 4650) @@ -93,6 +93,7 @@ ; kind of auto-backup - handy! Source: {userappdata}\OpenMPT\Keybindings.mkb; DestDir: {userappdata}\OpenMPT; DestName: Keybindings.mkb.old; Flags: external skipifsourcedoesntexist; Tasks: not portable Source: {userappdata}\OpenMPT\mptrack.ini; DestDir: {userappdata}\OpenMPT; DestName: mptrack.ini.old; Flags: external skipifsourcedoesntexist; Tasks: not portable +Source: {userappdata}\OpenMPT\SongSettings.ini; DestDir: {userappdata}\OpenMPT; DestName: SongSettings.ini.old; Flags: external skipifsourcedoesntexist; Tasks: not portable Source: {userappdata}\OpenMPT\plugin.cache; DestDir: {userappdata}\OpenMPT; DestName: plugin.cache.old; Flags: external skipifsourcedoesntexist; Tasks: not portable [Dirs] @@ -105,8 +106,6 @@ [Icons] ; start menu Name: {group}\OpenMPT; Filename: {app}\mptrack.exe -Name: {group}\{cm:UninstallProgram,OpenMPT}; Filename: {uninstallexe} -Name: {group}\ModPlug Central; Filename: {app}\ModPlug Central.url ; app's directory and keymaps directory (for ease of use) Name: {app}\Configuration files; Filename: {userappdata}\OpenMPT\; Tasks: not portable @@ -214,7 +213,7 @@ case CurUninstallStep of usUninstall: begin - if MsgBox('Do you want to keep your OpenMPT settings files (mptrack.ini, Keybindings.mkb, plugin.cache and local_tunings.tc)?', mbConfirmation, MB_YESNO or MB_DEFBUTTON2) = IDNO then + if MsgBox('Do you want to keep your OpenMPT settings files (mptrack.ini, SongSettings.ini, Keybindings.mkb, plugin.cache and local_tunings.tc)?', mbConfirmation, MB_YESNO or MB_DEFBUTTON2) = IDNO then begin if(GetIniInt('Paths', 'UseAppDataDirectory', 1, 0, 0, ExpandConstant('{app}\mptrack.ini')) = 1) then begin @@ -224,6 +223,7 @@ begin end; DeleteFile(filepath + 'mptrack.ini'); + DeleteFile(filepath + 'SongSettings.ini'); DeleteFile(filepath + 'Keybindings.mkb'); DeleteFile(filepath + 'plugin.cache'); DeleteFile(filepath + 'tunings\local_tunings.tc'); Modified: trunk/OpenMPT/mptrack/Childfrm.cpp =================================================================== --- trunk/OpenMPT/mptrack/Childfrm.cpp 2014-12-13 23:30:29 UTC (rev 4649) +++ trunk/OpenMPT/mptrack/Childfrm.cpp 2014-12-14 23:50:14 UTC (rev 4650) @@ -10,14 +10,25 @@ #include "stdafx.h" #include <afxpriv.h> -#include "mptrack.h" -#include "mainfrm.h" +#include "Mptrack.h" +#include "Mainfrm.h" #include "ChildFrm.h" -#include "moddoc.h" -#include "globals.h" -#include "view_gen.h" -#include ".\childfrm.h" +#include "Moddoc.h" +#include "Globals.h" +#include "View_gen.h" +#include "Ctrl_pat.h" +#include "View_pat.h" +#include "Ctrl_smp.h" +#include "View_smp.h" +#include "Ctrl_ins.h" +#include "View_ins.h" +#include "View_com.h" +#include "Childfrm.h" +#include "../common/FileReader.h" +#include "../common/mptIO.h" +#include <sstream> + #ifdef _DEBUG #define new DEBUG_NEW #undef THIS_FILE @@ -29,7 +40,7 @@ ///////////////////////////////////////////////////////////////////////////// -// +// IMPLEMENT_DYNAMIC(CViewExSplitWnd, CSplitterWnd) @@ -69,7 +80,7 @@ ON_WM_SETFOCUS() //rewbs.customKeysAutoEffects END_MESSAGE_MAP() -LONG CChildFrame::glMdiOpenCount = 0; +int CChildFrame::glMdiOpenCount = 0; ///////////////////////////////////////////////////////////////////////////// // CChildFrame construction/destruction @@ -87,6 +98,7 @@ RtlZeroMemory(&m_ViewSamples, sizeof(m_ViewSamples)); RtlZeroMemory(&m_ViewInstruments, sizeof(m_ViewInstruments)); RtlZeroMemory(&m_ViewComments, sizeof(m_ViewComments)); + m_ViewPatterns.initialOrder = ORDERINDEX_INVALID; } @@ -110,10 +122,10 @@ int cy = TrackerSettings::Instance().glGeneralWindowHeight; //rewbs.varWindowSize - default to general tab. if (cy <= 1) cy = (lpcs->cy*2) / 3; if (!m_wndSplitter.CreateView(0, 0, pContext->m_pNewViewClass, CSize(0, cy), pContext)) return FALSE; - + // Get 2nd window handle CModControlView *pModView; - if ((pModView = (CModControlView *)m_wndSplitter.GetPane(0, 0)) != NULL) + if ((pModView = GetModControlView()) != NULL) { m_hWndCtrl = pModView->m_hWnd; pModView->SetMDIParentFrame(m_hWnd); @@ -235,7 +247,7 @@ //------------------------------ { CModControlView *pModView; - if ((pModView = (CModControlView *)m_wndSplitter.GetPane(0, 0)) != NULL) + if ((pModView = GetModControlView()) != nullptr) { pModView->ForceRefresh(); } @@ -249,7 +261,7 @@ if (m_hWnd) { CRect rect; - + m_bMaxWhenClosed = IsZoomed(); if (bForce) TrackerSettings::Instance().gbMdiMaximize = (m_bMaxWhenClosed != 0); if (!IsIconic()) @@ -260,15 +272,15 @@ pWnd->GetWindowRect(&rect); LONG l = rect.Height(); //rewbs.varWindowSize - not the nicest piece of code, but we need to distinguish btw the views: - if (strcmp("CViewGlobals",m_szCurrentViewClassName) == 0) + if (strcmp(CViewGlobals::classCViewGlobals.m_lpszClassName, m_szCurrentViewClassName) == 0) TrackerSettings::Instance().glGeneralWindowHeight = l; - else if (strcmp("CViewPattern", m_szCurrentViewClassName) == 0) + else if (strcmp(CViewPattern::classCViewPattern.m_lpszClassName, m_szCurrentViewClassName) == 0) TrackerSettings::Instance().glPatternWindowHeight = l; - else if (strcmp("CViewSample", m_szCurrentViewClassName) == 0) + else if (strcmp(CViewSample::classCViewSample.m_lpszClassName, m_szCurrentViewClassName) == 0) TrackerSettings::Instance().glSampleWindowHeight = l; - else if (strcmp("CViewInstrument", m_szCurrentViewClassName) == 0) + else if (strcmp(CViewInstrument::classCViewInstrument.m_lpszClassName, m_szCurrentViewClassName) == 0) TrackerSettings::Instance().glInstrumentWindowHeight = l; - else if (strcmp("CViewComments", m_szCurrentViewClassName) == 0) + else if (strcmp(CViewComments::classCViewComments.m_lpszClassName, m_szCurrentViewClassName) == 0) TrackerSettings::Instance().glCommentsWindowHeight = l; //rewbs.graph else if (strcmp("CViewGraph", m_szCurrentViewClassName) == 0) @@ -293,7 +305,7 @@ { pWnd->GetWindowRect(&rect); return rect.Height(); - } + } } return 15; // tidy default }; @@ -456,4 +468,62 @@ //end rewbs.customKeysAutoEffects +std::ostringstream CChildFrame::SerializeView() const +//--------------------------------------------------- +{ + std::ostringstream f(std::ios::out | std::ios::binary); + // Version + mpt::IO::WriteVarInt(f, 0u); + // Current page + mpt::IO::WriteVarInt(f, static_cast<uint8_t>(GetModControlView()->GetActivePage())); + + CModControlView *view = GetModControlView(); + if (strcmp(CViewPattern::classCViewPattern.m_lpszClassName, m_szCurrentViewClassName) == 0) + { + mpt::IO::WriteVarInt(f, (uint32_t)view->SendMessage(WM_MOD_CTRLMSG, CTRLMSG_GETCURRENTORDER)); // Order number + } else if (strcmp(CViewSample::classCViewSample.m_lpszClassName, m_szCurrentViewClassName) == 0) + { + mpt::IO::WriteVarInt(f, (uint32_t)view->SendMessage(WM_MOD_CTRLMSG, CTRLMSG_GETCURRENTINSTRUMENT)); // Sample number + } else if (strcmp(CViewInstrument::classCViewInstrument.m_lpszClassName, m_szCurrentViewClassName) == 0) + { + mpt::IO::WriteVarInt(f, (uint32_t)view->SendMessage(WM_MOD_CTRLMSG, CTRLMSG_GETCURRENTINSTRUMENT)); // Instrument number + } + return f; +} + + +void CChildFrame::DeserializeView(FileReader &file) +//------------------------------------------------- +{ + uint32_t version, page; + if(file.ReadVarInt(version) && version == 0 && + file.ReadVarInt(page) && page >= 0 && page < CModControlView::MAX_PAGES) + { + UINT pageDlg = 0; + switch(page) + { + case CModControlView::VIEW_GLOBALS: + pageDlg = IDD_CONTROL_GLOBALS; + break; + case CModControlView::VIEW_PATTERNS: + pageDlg = IDD_CONTROL_PATTERNS; + file.ReadVarInt(m_ViewPatterns.initialOrder); + break; + case CModControlView::VIEW_SAMPLES: + pageDlg = IDD_CONTROL_SAMPLES; + file.ReadVarInt(m_ViewSamples.initialSample); + break; + case CModControlView::VIEW_INSTRUMENTS: + pageDlg = IDD_CONTROL_INSTRUMENTS; + file.ReadVarInt(m_ViewInstruments.initialInstrument); + break; + case CModControlView::VIEW_COMMENTS: + pageDlg = IDD_CONTROL_COMMENTS; + break; + } + GetModControlView()->PostMessage(WM_MOD_ACTIVATEVIEW, pageDlg); + } + +} + OPENMPT_NAMESPACE_END Modified: trunk/OpenMPT/mptrack/Childfrm.h =================================================================== --- trunk/OpenMPT/mptrack/Childfrm.h 2014-12-13 23:30:29 UTC (rev 4649) +++ trunk/OpenMPT/mptrack/Childfrm.h 2014-12-14 23:50:14 UTC (rev 4650) @@ -14,7 +14,9 @@ OPENMPT_NAMESPACE_BEGIN +class CModControlView; class CModControlDlg; +class FileReader; class CChildFrame; typedef struct _GENERALVIEWSTATE @@ -34,6 +36,7 @@ PatternRect selection; PatternCursor::Columns nDetailLevel; ORDERINDEX nOrder; //rewbs.playSongFromCursor + ORDERINDEX initialOrder; } PATTERNVIEWSTATE; typedef struct SAMPLEVIEWSTATE @@ -42,6 +45,7 @@ SmpLength dwBeginSel; SmpLength dwEndSel; SAMPLEINDEX nSample; + SAMPLEINDEX initialSample; } SAMPLEVIEWSTATE; @@ -49,6 +53,7 @@ { DWORD cbStruct; enmEnvelopeTypes nEnv; + INSTRUMENTINDEX initialInstrument; bool bGrid; } INSTRUMENTVIEWSTATE; @@ -84,7 +89,7 @@ CChildFrame(); protected: - static LONG glMdiOpenCount; + static int glMdiOpenCount; // Attributes protected: @@ -101,6 +106,7 @@ // Operations public: + CModControlView *GetModControlView() const { return (CModControlView *)m_wndSplitter.GetPane(0, 0); } BOOL ChangeViewClass(CRuntimeClass* pNewViewClass, CCreateContext* pContext=NULL); void ForceRefresh(); void SavePosition(BOOL bExit=FALSE); @@ -109,15 +115,18 @@ LRESULT ActivateView(UINT nId, LPARAM lParam) { return ::SendMessage(m_hWndCtrl, WM_MOD_ACTIVATEVIEW, nId, lParam); } HWND GetHwndCtrl() const { return m_hWndCtrl; } HWND GetHwndView() const { return m_hWndView; } - GENERALVIEWSTATE *GetGeneralViewState() { return &m_ViewGeneral; } - PATTERNVIEWSTATE *GetPatternViewState() { return &m_ViewPatterns; } - SAMPLEVIEWSTATE *GetSampleViewState() { return &m_ViewSamples; } - INSTRUMENTVIEWSTATE *GetInstrumentViewState() { return &m_ViewInstruments; } - COMMENTVIEWSTATE *GetCommentViewState() { return &m_ViewComments; } + GENERALVIEWSTATE &GetGeneralViewState() { return m_ViewGeneral; } + PATTERNVIEWSTATE &GetPatternViewState() { return m_ViewPatterns; } + SAMPLEVIEWSTATE &GetSampleViewState() { return m_ViewSamples; } + INSTRUMENTVIEWSTATE &GetInstrumentViewState() { return m_ViewInstruments; } + COMMENTVIEWSTATE &GetCommentViewState() { return m_ViewComments; } - void SetSplitterHeight(int x); //rewbs.varWindowSize - int GetSplitterHeight(); //rewbs.varWindowSize + void SetSplitterHeight(int x); + int GetSplitterHeight(); + std::ostringstream SerializeView() const; + void DeserializeView(FileReader &file); + // Overrides // ClassWizard generated virtual function overrides //{{AFX_VIRTUAL(CChildFrame) Modified: trunk/OpenMPT/mptrack/Ctrl_ins.cpp =================================================================== --- trunk/OpenMPT/mptrack/Ctrl_ins.cpp 2014-12-13 23:30:29 UTC (rev 4649) +++ trunk/OpenMPT/mptrack/Ctrl_ins.cpp 2014-12-14 23:50:14 UTC (rev 4650) @@ -68,18 +68,18 @@ if (pMsg) { //We handle keypresses before Windows has a chance to handle them (for alt etc..) - if ((pMsg->message == WM_SYSKEYUP) || (pMsg->message == WM_KEYUP) || + if ((pMsg->message == WM_SYSKEYUP) || (pMsg->message == WM_KEYUP) || (pMsg->message == WM_SYSKEYDOWN) || (pMsg->message == WM_KEYDOWN)) { CInputHandler* ih = (CMainFrame::GetMainFrame())->GetInputHandler(); - + //Translate message manually UINT nChar = pMsg->wParam; UINT nRepCnt = LOWORD(pMsg->lParam); UINT nFlags = HIWORD(pMsg->lParam); KeyEventType kT = ih->GetKeyEventType(nFlags); InputTargetContext ctx = (InputTargetContext)(kCtxInsNoteMap); - + if (ih->KeyEvent(ctx, nChar, nRepCnt, nFlags, kT) != kcNull) return true; // Mapped to a command, no need to pass message on. @@ -90,7 +90,7 @@ return true; // Mapped to a command, no need to pass message on. } } - + //The key was not handled by a command, but it might still be useful if (pMsg->message == WM_CHAR) //key is a character { @@ -100,7 +100,7 @@ if (kT == kKeyEventDown) if (HandleChar(wParam)) return true; - } + } else if (pMsg->message == WM_KEYDOWN) //key is not a character { if (HandleNav(wParam)) @@ -255,7 +255,7 @@ DrawButtonRect(hdc, &rect, "", FALSE, FALSE); if (ypaint < rcClient.bottom) { - rect.SetRect(rcClient.left, ypaint, rcClient.right, rcClient.bottom); + rect.SetRect(rcClient.left, ypaint, rcClient.right, rcClient.bottom); FillRect(hdc, &rect, CMainFrame::brushGray); } } @@ -322,7 +322,7 @@ { CHAR s[64]; CInputHandler* ih = CMainFrame::GetInputHandler(); - + CSoundFile &sndFile = m_modDoc.GetrSoundFile(); ModInstrument *pIns = sndFile.Instruments[m_nInstrument]; if (pIns) @@ -519,7 +519,7 @@ { if (wParam == kcNull) return NULL; - + CMainFrame *pMainFrm = CMainFrame::GetMainFrame(); ModInstrument *pIns = m_modDoc.GetrSoundFile().Instruments[m_nInstrument]; @@ -532,10 +532,10 @@ HandleChar(lParam); else EnterNote(wParam-kcInsNoteMapStartNotes+1+pMainFrm->GetBaseOctave()*12); - + return wParam; } - + if (wParam>=kcInsNoteMapStartNoteStops && wParam<=kcInsNoteMapEndNoteStops) { StopNote(m_nPlayingNote); @@ -563,7 +563,7 @@ case kcNextInstrument: m_pParent.PostMessage(WM_COMMAND, ID_NEXTINSTRUMENT); return wParam; case kcPrevInstrument: m_pParent.PostMessage(WM_COMMAND, ID_PREVINSTRUMENT); return wParam; } - + return NULL; } @@ -579,22 +579,22 @@ UINT n = pIns->NoteMap[m_nNote]; bool bOk = false; if ((note >= sndFile.GetModSpecifications().noteMin) && (note <= sndFile.GetModSpecifications().noteMax)) - { + { n = note; bOk = true; - } + } if (n != pIns->NoteMap[m_nNote]) { pIns->NoteMap[m_nNote] = n; m_pParent.SetModified(InstrumentHint().Info(), false); InvalidateRect(NULL, FALSE); } - if (bOk) + if (bOk) { PlayNote(m_nNote + 1); //SetCurrentNote(m_nNote+1); } - + } } } @@ -656,7 +656,7 @@ m_pParent.SetModified(InstrumentHint().Info(), false); InvalidateRect(NULL, FALSE); } - + if (c == ' ') { SetCurrentNote(m_nNote+1); @@ -720,7 +720,7 @@ default: return false; } - if (bRedraw) + if (bRedraw) { InvalidateRect(NULL, FALSE); } @@ -966,7 +966,7 @@ GetDlgItem(IDC_PITCHWHEELDEPTH)->EnableWindow(FALSE); BuildTuningComboBox(); - + CheckDlgButton(IDC_CHECK_PITCHTEMPOLOCK, MF_UNCHECKED); m_EditPitchTempoLock.SetLimitText(4); @@ -1043,13 +1043,20 @@ UpdatePluginList(); + CChildFrame *pFrame = (CChildFrame *)GetParentFrame(); + INSTRUMENTVIEWSTATE &instrumentState = pFrame->GetInstrumentViewState(); + if(instrumentState.initialInstrument != 0) + { + m_nInstrument = instrumentState.initialInstrument; + instrumentState.initialInstrument = 0; + } + SetCurrentInstrument((lParam > 0) ? lParam : m_nInstrument); // Initial Update if (!m_bInitialized) UpdateView(InstrumentHint(m_nInstrument).Info().Envelope().ModType(), NULL); - CChildFrame *pFrame = (CChildFrame *)GetParentFrame(); - if (pFrame) PostViewMessage(VIEWMSG_LOADSTATE, (LPARAM)pFrame->GetInstrumentViewState()); + if (pFrame) PostViewMessage(VIEWMSG_LOADSTATE, (LPARAM)&instrumentState); SwitchToView(); // Combo boxes randomly disappear without this... why? @@ -1062,7 +1069,7 @@ { m_modDoc.NoteOff(0, true); CChildFrame *pFrame = (CChildFrame *)GetParentFrame(); - if ((pFrame) && (m_hWndView)) SendViewMessage(VIEWMSG_SAVESTATE, (LPARAM)pFrame->GetInstrumentViewState()); + if ((pFrame) && (m_hWndView)) SendViewMessage(VIEWMSG_SAVESTATE, (LPARAM)&pFrame->GetInstrumentViewState()); } @@ -1071,6 +1078,10 @@ { switch(wParam) { + case CTRLMSG_GETCURRENTINSTRUMENT: + return m_nInstrument; + break; + case CTRLMSG_INS_PREVINSTRUMENT: OnPrevInstrument(); break; @@ -1195,7 +1206,7 @@ m_NoteMap.EnableWindow(bITandXM); m_CbnResampling.EnableWindow(bITandXM); - + m_ComboNNA.EnableWindow(bITandMPT); m_SliderVolSwing.EnableWindow(bITandMPT); m_SliderPanSwing.EnableWindow(bITandMPT); @@ -1264,7 +1275,7 @@ if (pIns->nMidiChannel < 18) { - m_CbnMidiCh.SetCurSel(pIns->nMidiChannel); + m_CbnMidiCh.SetCurSel(pIns->nMidiChannel); } else { m_CbnMidiCh.SetCurSel(0); @@ -1404,7 +1415,7 @@ { strcpy(s, "No Change"); } - + SetDlgItemText(IDC_FILTERTEXT, s); } } @@ -1415,7 +1426,7 @@ //-------------------------------------------------------------------- { BOOL bFirst, bOk; - + BeginWaitCursor(); InputFile f(fileName); if(!f.IsValid()) @@ -1453,7 +1464,7 @@ { mpt::PathString name, ext; fileName.SplitPath(nullptr, nullptr, &name, &ext); - + if (!pIns->name[0] && m_sndFile.GetModSpecifications().instrNameLengthMax > 0) { mpt::String::CopyN(pIns->name, name.ToLocale().c_str(), m_sndFile.GetModSpecifications().instrNameLengthMax); @@ -1526,7 +1537,7 @@ //------------------------------------------------------------ { //Note: pszText seems to point to char array of length 256 (Noverber 2006). - //Note2: If there's problems in getting tooltips showing for certain tools, + //Note2: If there's problems in getting tooltips showing for certain tools, // setting the tab order may have effect. ModInstrument *pIns = m_sndFile.Instruments[m_nInstrument]; @@ -1716,7 +1727,7 @@ { //If loading multiple instruments, advancing to next instrument and creating //new instrument if necessary. - if(counter > 0) + if(counter > 0) { if(m_nInstrument >= MAX_INSTRUMENTS - 1) break; @@ -1741,7 +1752,7 @@ { TCHAR szFileName[_MAX_PATH] = ""; ModInstrument *pIns = m_sndFile.Instruments[m_nInstrument]; - + if (!pIns) return; if (pIns->filename[0]) { @@ -1767,7 +1778,7 @@ .WorkingDirectory(TrackerDirectories::Instance().GetWorkingDirectory(DIR_INSTRUMENTS)) .FilterIndex(&index); if(!dlg.Show(this)) return; - + BeginWaitCursor(); bool ok = false; @@ -1845,7 +1856,7 @@ m_SpinFadeOut.GetRange(minval, maxval); int nVol = GetDlgItemInt(IDC_EDIT7); Limit(nVol, minval, maxval); - + if(nVol != (int)pIns->nFadeOut) { pIns->nFadeOut = nVol; @@ -2001,7 +2012,7 @@ } //rewbs.MidiBank: we will not set the midi bank/program if it is 0 if (n==0) - { + { LockControls(); SetDlgItemText(IDC_EDIT10, "---"); UnlockControls(); @@ -2025,7 +2036,7 @@ } //rewbs.MidiBank: we will not set the midi bank/program if it is 0 if(w == 0) - { + { LockControls(); SetDlgItemText(IDC_EDIT11, "---"); UnlockControls(); @@ -2050,7 +2061,7 @@ } } -void CCtrlInstruments::OnResamplingChanged() +void CCtrlInstruments::OnResamplingChanged() //------------------------------------------ { ModInstrument *pIns = m_sndFile.Instruments[m_nInstrument]; @@ -2085,7 +2096,7 @@ if(nPlug >= 0 && nPlug <= MAX_MIXPLUGINS) { if ((!IsLocked()) && pIns->nMixPlug != nPlug) - { + { pIns->nMixPlug = nPlug; SetModified(InstrumentHint().Info(), false); } @@ -2120,7 +2131,7 @@ if(plugin.pMixPlugin != nullptr) { GetDlgItem(IDC_INSVIEWPLG)->EnableWindow(true); - + if(active && plugin.pMixPlugin->isInstrument()) { if(pIns->nMidiChannel == MidiNoChannel) @@ -2157,7 +2168,7 @@ } } } - + } ::EnableWindow(::GetDlgItem(m_hWnd, IDC_INSVIEWPLG), false); } @@ -2285,7 +2296,7 @@ SwitchToView(); } -void CCtrlInstruments::OnFilterModeChanged() +void CCtrlInstruments::OnFilterModeChanged() //------------------------------------------ { ModInstrument *pIns = m_sndFile.Instruments[m_nInstrument]; @@ -2350,9 +2361,9 @@ SetModified(InstrumentHint().Info(), false); } // -! NEW_FEATURE#0027 - } + } // Volume Swing - else if (pSlider == &m_SliderVolSwing) + else if (pSlider == &m_SliderVolSwing) { n = m_SliderVolSwing.GetPos(); if ((n >= 0) && (n <= 100) && (n != (int)pIns->nVolSwing)) @@ -2362,7 +2373,7 @@ } } // Pan Swing - else if (pSlider == &m_SliderPanSwing) + else if (pSlider == &m_SliderPanSwing) { n = m_SliderPanSwing.GetPos(); if ((n >= 0) && (n <= 64) && (n != (int)pIns->nPanSwing)) @@ -2372,7 +2383,7 @@ } } //Cutoff swing - else if (pSlider == &m_SliderCutSwing) + else if (pSlider == &m_SliderCutSwing) { n = m_SliderCutSwing.GetPos(); if ((n >= 0) && (n <= 64) && (n != (int)pIns->nCutSwing)) @@ -2382,7 +2393,7 @@ } } //Resonance swing - else if (pSlider == &m_SliderResSwing) + else if (pSlider == &m_SliderResSwing) { n = m_SliderResSwing.GetPos(); if ((n >= 0) && (n <= 64) && (n != (int)pIns->nResSwing)) @@ -2415,7 +2426,7 @@ filterChanger = true; } } - + // Update channels if (filterChanger) { @@ -2434,7 +2445,7 @@ { SwitchToView(); } - + } @@ -2474,24 +2485,24 @@ if (pMsg) { //We handle keypresses before Windows has a chance to handle them (for alt etc..) - if ((pMsg->message == WM_SYSKEYUP) || (pMsg->message == WM_KEYUP) || + if ((pMsg->message == WM_SYSKEYUP) || (pMsg->message == WM_KEYUP) || (pMsg->message == WM_SYSKEYDOWN) || (pMsg->message == WM_KEYDOWN)) { CInputHandler* ih = (CMainFrame::GetMainFrame())->GetInputHandler(); - + //Translate message manually UINT nChar = pMsg->wParam; UINT nRepCnt = LOWORD(pMsg->lParam); UINT nFlags = HIWORD(pMsg->lParam); KeyEventType kT = ih->GetKeyEventType(nFlags); InputTargetContext ctx = (InputTargetContext)(kCtxCtrlInstruments); - + if (ih->KeyEvent(ctx, nChar, nRepCnt, nFlags, kT) != kcNull) return true; // Mapped to a command, no need to pass message on. } } - + return CModControlDlg::PreTranslateMessage(pMsg); } @@ -2500,7 +2511,7 @@ { if (wParam == kcNull) return NULL; - + switch(wParam) { case kcInstrumentCtrlLoad: OnInstrumentOpen(); return wParam; @@ -2509,7 +2520,7 @@ case kcInstrumentCtrlDuplicate: OnInstrumentDuplicate(); return wParam; } - + return 0; } @@ -2538,7 +2549,7 @@ sel -= 1; CTuningCollection* tc = 0; - + if(sel < CSoundFile::GetBuiltInTunings().GetNumTunings()) tc = &CSoundFile::GetBuiltInTunings(); else @@ -2586,7 +2597,7 @@ //Recreating tuning combobox so that possible //new tuning(s) come visible. BuildTuningComboBox(); - + UpdateView(InstrumentHint(m_nInstrument).Info()); } @@ -2849,10 +2860,10 @@ CHAR s[64]; for (PLUGINDEX nPlug = 0; nPlug <= MAX_MIXPLUGINS; nPlug++) { - if(!nPlug) - { + if(!nPlug) + { strcpy(s, "No plugin"); - } + } else { const SNDMIXPLUGIN &plugin = m_sndFile.m_MixPlugins[nPlug - 1]; Modified: trunk/OpenMPT/mptrack/Ctrl_pat.cpp =================================================================== --- trunk/OpenMPT/mptrack/Ctrl_pat.cpp 2014-12-13 23:30:29 UTC (rev 4649) +++ trunk/OpenMPT/mptrack/Ctrl_pat.cpp 2014-12-14 23:50:14 UTC (rev 4650) @@ -108,7 +108,7 @@ //--------------------------------------------------------------------------------------------------------------------------------------- { m_nInstrument = 0; - + m_bVUMeters = TrackerSettings::Instance().gbPatternVUMeters; m_bPluginNames = TrackerSettings::Instance().gbPatternPluginNames; //rewbs.patPlugNames m_bRecord = TrackerSettings::Instance().gbPatternRecord; @@ -198,7 +198,7 @@ m_SpinSequence.SetPos(m_sndFile.Order.GetCurrentSequenceIndex()); SetDlgItemText(IDC_EDIT_SEQUENCE_NAME, m_sndFile.Order.GetName().c_str()); - m_OrderList.SetFocus(); + m_OrderList.SetFocus(); UpdateView(PatternHint().Names().ModType(), NULL); RecalcLayout(); @@ -467,7 +467,7 @@ case CTRLMSG_PREVORDER: m_OrderList.SetCurSel(m_OrderList.GetCurSel(true).firstOrd - 1, true); break; - + case CTRLMSG_NEXTORDER: m_OrderList.SetCurSel(m_OrderList.GetCurSel(true).firstOrd + 1, true); break; @@ -497,7 +497,7 @@ { setLoop = (lParam != 0); } - + if (setLoop) { m_sndFile.m_SongFlags.set(SONG_PATTERNLOOP); @@ -505,7 +505,7 @@ } else { m_sndFile.m_SongFlags.reset(SONG_PATTERNLOOP); - CheckDlgButton(IDC_PATTERN_LOOP, BST_UNCHECKED); + CheckDlgButton(IDC_PATTERN_LOOP, BST_UNCHECKED); } break; @@ -595,7 +595,7 @@ } } SetCurrentPattern(nPat); - } + } else if ((lParam & 0x80000000)) { // Order item @@ -616,12 +616,18 @@ OnSpacingChanged(); if (m_bRecord) SendViewMessage(VIEWMSG_SETRECORD, m_bRecord); CChildFrame *pFrame = (CChildFrame *)GetParentFrame(); - + //Restore all save pattern state, except pattern number which we might have just set. - PATTERNVIEWSTATE* patternViewState = pFrame->GetPatternViewState(); - patternViewState->nPattern = static_cast<PATTERNINDEX>(SendViewMessage(VIEWMSG_GETCURRENTPATTERN)); - if (pFrame) SendViewMessage(VIEWMSG_LOADSTATE, (LPARAM)patternViewState); - + PATTERNVIEWSTATE &patternViewState = pFrame->GetPatternViewState(); + if(patternViewState.initialOrder != ORDERINDEX_INVALID) + { + m_OrderList.SetCurSel(patternViewState.initialOrder); + patternViewState.initialOrder = ORDERINDEX_INVALID; + } + + patternViewState.nPattern = static_cast<PATTERNINDEX>(SendViewMessage(VIEWMSG_GETCURRENTPATTERN)); + if (pFrame) SendViewMessage(VIEWMSG_LOADSTATE, (LPARAM)&patternViewState); + SwitchToView(); } @@ -634,7 +640,7 @@ //------------------------------------ { CChildFrame *pFrame = (CChildFrame *)GetParentFrame(); - if ((pFrame) && (m_hWndView)) SendViewMessage(VIEWMSG_SAVESTATE, (LPARAM)pFrame->GetPatternViewState()); + if ((pFrame) && (m_hWndView)) SendViewMessage(VIEWMSG_SAVESTATE, (LPARAM)&pFrame->GetPatternViewState()); } @@ -723,7 +729,7 @@ if ((m_EditSpacing.m_hWnd) && (m_EditSpacing.GetWindowTextLength() > 0)) { TrackerSettings::Instance().gnPatternSpacing = GetDlgItemInt(IDC_EDIT_SPACING); - if (TrackerSettings::Instance().gnPatternSpacing > MAX_SPACING) + if (TrackerSettings::Instance().gnPatternSpacing > MAX_SPACING) { TrackerSettings::Instance().gnPatternSpacing = MAX_SPACING; SetDlgItemInt(IDC_EDIT_SPACING, TrackerSettings::Instance().gnPatternSpacing, FALSE); @@ -1089,7 +1095,7 @@ CHAR s[MAX_PATTERNNAME]; m_EditPatName.GetWindowText(s, CountOf(s)); mpt::String::SetNullTerminator(s); - + if(m_sndFile.Patterns[nPat].GetName() != s) { if(m_sndFile.Patterns[nPat].SetName(s)) @@ -1140,7 +1146,7 @@ m_sndFile.m_SongFlags.set(SONG_EMBEDMIDICFG); m_modDoc.SetModified(); } - } + } } } } @@ -1238,7 +1244,7 @@ return CModControlDlg::OnMouseWheel(nFlags, zDelta, pt); } -BOOL CCtrlPatterns::OnToolTip(UINT /*id*/, NMHDR *pNMHDR, LRESULT* /*pResult*/) +BOOL CCtrlPatterns::OnToolTip(UINT /*id*/, NMHDR *pNMHDR, LRESULT* /*pResult*/) //--------------------------------------------------------------------- { TOOLTIPTEXT *pTTT = (TOOLTIPTEXT *)pNMHDR; @@ -1268,7 +1274,7 @@ // avoid reloading the order list and thus setting the document modified if(newSeq == m_sndFile.Order.GetCurrentSequenceIndex()) return; - + if (newSeq >= MAX_SEQUENCES) { newSeq = MAX_SEQUENCES - 1; @@ -1278,5 +1284,4 @@ } } - OPENMPT_NAMESPACE_END Modified: trunk/OpenMPT/mptrack/Ctrl_smp.cpp =================================================================== --- trunk/OpenMPT/mptrack/Ctrl_smp.cpp 2014-12-13 23:30:29 UTC (rev 4649) +++ trunk/OpenMPT/mptrack/Ctrl_smp.cpp 2014-12-14 23:50:14 UTC (rev 4650) @@ -257,13 +257,13 @@ GetDlgItem(IDC_BUTTON1)->ShowWindow(SW_SHOW); // PitchShiftTimeStretch GetDlgItem(IDC_BUTTON2)->ShowWindow(SW_SHOW); // EstimateSampleSize GetDlgItem(IDC_CHECK3)->ShowWindow(SW_SHOW); // EnableStretchToSize - GetDlgItem(IDC_EDIT6)->ShowWindow(SW_SHOW); // + GetDlgItem(IDC_EDIT6)->ShowWindow(SW_SHOW); // GetDlgItem(IDC_GROUPBOX_PITCH_TIME)->ShowWindow(SW_SHOW); // GetDlgItem(IDC_TEXT_PITCH)->ShowWindow(SW_SHOW); // GetDlgItem(IDC_TEXT_QUALITY)->ShowWindow(SW_SHOW); // GetDlgItem(IDC_TEXT_FFT)->ShowWindow(SW_SHOW); // GetDlgItem(IDC_GROUPBOX_PITCH_TIME)->ShowWindow(SW_SHOW); // - + CHAR str[16]; // Pitch selection @@ -400,12 +400,20 @@ m_parent.InstrumentChanged(lParam); } } + + CChildFrame *pFrame = (CChildFrame *)GetParentFrame(); + SAMPLEVIEWSTATE &sampleState = pFrame->GetSampleViewState(); + if(sampleState.initialSample != 0) + { + m_nSample = sampleState.initialSample; + sampleState.initialSample = 0; + } + SetCurrentSample((lParam > 0) ? ((SAMPLEINDEX)lParam) : m_nSample); // Initial Update if (!m_bInitialized) UpdateView(SampleHint(m_nSample).Info().ModType(), NULL); - CChildFrame *pFrame = (CChildFrame *)GetParentFrame(); - if ((pFrame) && (m_hWndView)) PostViewMessage(VIEWMSG_LOADSTATE, (LPARAM)pFrame->GetSampleViewState()); + if ((pFrame) && (m_hWndView)) PostViewMessage(VIEWMSG_LOADSTATE, (LPARAM)&sampleState); SwitchToView(); // Combo boxes randomly disappear without this... why? @@ -417,7 +425,7 @@ //----------------------------------- { CChildFrame *pFrame = (CChildFrame *)GetParentFrame(); - if ((pFrame) && (m_hWndView)) SendViewMessage(VIEWMSG_SAVESTATE, (LPARAM)pFrame->GetSampleViewState()); + if ((pFrame) && (m_hWndView)) SendViewMessage(VIEWMSG_SAVESTATE, (LPARAM)&pFrame->GetSampleViewState()); m_modDoc.NoteOff(0, true); } @@ -427,6 +435,10 @@ { switch(wParam) { + case CTRLMSG_GETCURRENTINSTRUMENT: + return m_nSample; + break; + case CTRLMSG_SMP_PREVINSTRUMENT: OnPrevInstrument(); break; @@ -505,7 +517,7 @@ case IDC_SAMPLE_SAVEAS: OnSampleSave(); break; - + case IDC_SAMPLE_NEW: OnSampleNew(); break; @@ -814,7 +826,7 @@ EndWaitCursor(); return false; } - + m_modDoc.GetSampleUndo().PrepareUndo(m_nSample, sundo_replace, "Replace"); bool bOk = m_sndFile.ReadSampleFromFile(m_nSample, file, TrackerSettings::Instance().m_MayNormalizeSamplesOnLoad); ModSample &sample = m_sndFile.GetSample(m_nSample); @@ -834,7 +846,7 @@ rememberRawFormat = dlg.GetRemeberFormat(); BeginWaitCursor(); - + m_sndFile.DestroySampleThreadsafe(m_nSample); sample.nLength = file.GetLength(); @@ -1235,7 +1247,7 @@ { bool bOk = false; ModSample &sample = m_sndFile.GetSample(iSmp); - + if(minSample != maxSample) { //if more than one sample is selected, always amplify the whole sample. @@ -1589,7 +1601,7 @@ SmpLength procCount = resampler.process(&convBuffer[0], smpCount, outBuffer); const SmpLength procLatency = std::min(outLatency, procCount); procCount = std::min(procCount- procLatency, writeCount); - + switch(sample.GetElementarySampleSize()) { case 1: @@ -1699,7 +1711,7 @@ //Open dialog CPSRatioCalc dlg(m_sndFile, m_nSample, m_dTimeStretchRatio, this); if (dlg.DoModal() != IDOK) return; - + //Update ratio value&textbox m_dTimeStretchRatio = dlg.m_dRatio; UpdateData(FALSE); @@ -1740,7 +1752,7 @@ sample.uFlags[CHN_PINGPONGSUSTAIN], m_sndFile); } - + } // Pitch shifting else @@ -1855,7 +1867,7 @@ } // Initialize soundtouch object. - { + { soundtouch_setSampleRate(handleSt, nSampleRate); soundtouch_setChannels(handleSt, nChn); @@ -2376,7 +2388,7 @@ //------------------------------------ { TCHAR s[MAX_SAMPLEFILENAME] = _T(""); - + if(IsLocked()) return; m_EditFileName.GetWindowText(s, CountOf(s)); @@ -2775,7 +2787,7 @@ const uint8 *pSample = static_cast<const uint8 *>(sample.pSample); int pos; bool redraw = false; - + LockControls(); if ((!sample.nLength) || (!pSample)) goto NoSample; if (sample.uFlags[CHN_16BIT]) @@ -3013,24 +3025,24 @@ if (pMsg) { //We handle keypresses before Windows has a chance to handle them (for alt etc..) - if ((pMsg->message == WM_SYSKEYUP) || (pMsg->message == WM_KEYUP) || + if ((pMsg->message == WM_SYSKEYUP) || (pMsg->message == WM_KEYUP) || (pMsg->message == WM_SYSKEYDOWN) || (pMsg->message == WM_KEYDOWN)) { CInputHandler* ih = (CMainFrame::GetMainFrame())->GetInputHandler(); - + //Translate message manually UINT nChar = (UINT)pMsg->wParam; UINT nRepCnt = LOWORD(pMsg->lParam); UINT nFlags = HIWORD(pMsg->lParam); KeyEventType kT = ih->GetKeyEventType(nFlags); InputTargetContext ctx = (InputTargetContext)(kCtxViewSamples); - + if (ih->KeyEvent(ctx, nChar, nRepCnt, nFlags, kT) != kcNull) return true; // Mapped to a command, no need to pass message on. } } - + return CModControlDlg::PreTranslateMessage(pMsg); } @@ -3039,7 +3051,7 @@ { if (wParam == kcNull) return NULL; - + int transpose = 0; switch(wParam) { @@ -3077,7 +3089,7 @@ } return wParam; } - + return 0; } //end rewbs.customKeys @@ -3251,5 +3263,4 @@ } } - OPENMPT_NAMESPACE_END Modified: trunk/OpenMPT/mptrack/Globals.cpp =================================================================== --- trunk/OpenMPT/mptrack/Globals.cpp 2014-12-13 23:30:29 UTC (rev 4649) +++ trunk/OpenMPT/mptrack/Globals.cpp 2014-12-14 23:50:14 UTC (rev 4650) @@ -272,32 +272,27 @@ } -void CModControlView::OnUpdate(CView*, LPARAM lHint, CObject*pHint) -//----------------------------------------------------------------- +void CModControlView::OnUpdate(CView *, LPARAM lHint, CObject *pHint) +//------------------------------------------------------------------- { UpdateView(UpdateHint::FromLPARAM(lHint), pHint); } -void CModControlView::ForceRefresh() +void CModControlView::ForceRefresh() //--------------------------------- { SetActivePage(GetActivePage()); } -int CModControlView::GetActivePage() -//----------------------------------- -{ - return m_nActiveDlg; -} BOOL CModControlView::SetActivePage(int nIndex, LPARAM lParam) //------------------------------------------------------------ { CMainFrame *pMainFrm = CMainFrame::GetMainFrame(); CModControlDlg *pDlg = NULL; - - + + if (nIndex == -1) nIndex = m_TabCtrl.GetCurSel(); const UINT nID = m_TabCtrl.GetItemData(nIndex); @@ -398,7 +393,7 @@ pMainFrm->SetInfoText(""); pMainFrm->SetXInfoText(""); //rewbs.xinfo pDlg->ShowWindow(SW_SHOW); - ((CChildFrame *)GetParentFrame())->SetSplitterHeight(*(pDlg->GetSplitPosRef())); //rewbs.varWindowSize + ((CChildFrame *)GetParentFrame())->SetSplitterHeight(*(pDlg->GetSplitPosRef())); //rewbs.varWindowSize if (m_hWndMDI) ::PostMessage(m_hWndMDI, WM_MOD_CHANGEVIEWCLASS, (WPARAM)lParam, (LPARAM)pDlg); return TRUE; } @@ -761,8 +756,8 @@ btn.iString = 0; return AddButtons(1, &btn); } - + void CModControlBar::UpdateStyle() //-------------------------------- { @@ -796,5 +791,4 @@ return 0; } - OPENMPT_NAMESPACE_END Modified: trunk/OpenMPT/mptrack/Globals.h =================================================================== --- trunk/OpenMPT/mptrack/Globals.h 2014-12-13 23:30:29 UTC (rev 4649) +++ trunk/OpenMPT/mptrack/Globals.h 2014-12-14 23:50:14 UTC (rev 4650) @@ -116,8 +116,18 @@ class CModControlView: public CView //================================= { -protected: - enum { MAX_PAGES=6 }; //rewbs.graph: 5 to 6 +public: + enum Views + { + VIEW_UNKNOWN = -1, + VIEW_GLOBALS = 0, + VIEW_PATTERNS, + VIEW_SAMPLES, + VIEW_INSTRUMENTS, + VIEW_COMMENTS, + VIEW_PLUGINS, + MAX_PAGES + }; protected: CModTabCtrl m_TabCtrl; @@ -141,9 +151,11 @@ protected: void RecalcLayout(); void UpdateView(UpdateHint hint, CObject *pHint = nullptr); - BOOL SetActivePage(int nIndex=-1, LPARAM lParam=-1); - int GetActivePage(); + BOOL SetActivePage(int nIndex = -1, LPARAM lParam=-1); +public: + int GetActivePage() const { return m_nActiveDlg; } +protected: //{{AFX_VIRTUAL(CModControlView) public: virtual BOOL PreCreateWindow(CREATESTRUCT& cs); Modified: trunk/OpenMPT/mptrack/Moddoc.cpp =================================================================== --- trunk/OpenMPT/mptrack/Moddoc.cpp 2014-12-13 23:30:29 UTC (rev 4649) +++ trunk/OpenMPT/mptrack/Moddoc.cpp 2014-12-14 23:50:14 UTC (rev 4650) @@ -34,6 +34,8 @@ #include <shlwapi.h> #include "FileDialog.h" #include "ExternalSamples.h" +#include "Globals.h" +#include <sstream> #ifdef _DEBUG #define new DEBUG_NEW @@ -287,7 +289,7 @@ if (CDLSBank::IsDLSBank(pszMidiMapName)) { CDLSBank *pDLSBank = NULL; - + if ((pCachedBank) && (!mpt::PathString::CompareNoCase(szCachedBankFile, pszMidiMapName))) { pDLSBank = pCachedBank; @@ -375,11 +377,13 @@ ReinitRecordState(); // -! NEW_FEATURE#0015 + DeserializeViews(); + // Show warning if file was made with more recent version of OpenMPT except if(MptVersion::RemoveBuildNumber(m_SndFile.m_dwLastSavedWithVersion) > MptVersion::num) { char s[256]; - wsprintf(s, "Warning: this song was last saved with a more recent version of OpenMPT.\r\nSong saved with: v%s. Current version: v%s.\r\n", + wsprintf(s, "Warning: this song was last saved with a more recent version of OpenMPT.\r\nSong saved with: v%s. Current version: v%s.\r\n", MptVersion::ToStr(m_SndFile.m_dwLastSavedWithVersion).c_str(), MptVersion::str); Reporting::Notification(s); @@ -410,7 +414,7 @@ static int greccount = 0; BOOL bOk = FALSE; m_SndFile.m_dwLastSavedWithVersion = MptVersion::num; - if(filename.empty()) + if(filename.empty()) return FALSE; MODTYPE type = m_SndFile.GetType(); // CModSpecifications::ExtensionToType(fext); @@ -447,6 +451,7 @@ if (pMainFrame) pMainFrame->CreateTemplateModulesMenu(); } + SerializeViews(); } else { ErrorBox(IDS_ERR_SAVESONG, CMainFrame::GetMainFrame()); @@ -579,7 +584,7 @@ { const mpt::PathString docFileName = GetPathNameMpt(); const std::string defaultExtension = m_SndFile.GetModSpecifications().fileExtension; - + switch(m_SndFile.GetBestSaveFormat()) { case MOD_TYPE_MOD: @@ -595,7 +600,7 @@ break; case MOD_TYPE_MPT: break; - default: + default: ErrorBox(IDS_ERR_SAVESONG, CMainFrame::GetMainFrame()); return FALSE; } @@ -614,7 +619,7 @@ fileName = mpt::PathString::FromCStringSilent(GetTitle()).SanitizeComponent(); } mpt::PathString defaultSaveName = drive + dir + fileName + ext; - + FileDialog dlg = SaveFileDialog() .DefaultExtension(defaultExtension) .DefaultFilename(defaultSaveName) @@ -634,10 +639,10 @@ if((TrackerSettings::Instance().m_dwPatternSetup & PATTERN_CREATEBACKUP) && (IsModified()) && (!mpt::PathString::CompareNoCase(saveFileName, docFileName))) { - if(PathFileExistsW(saveFileName.AsNative().c_str())) + if(saveFileName.IsFile()) { mpt::PathString backupFileName = saveFileName.ReplaceExt(MPT_PATHSTRING(".bak")); - if(PathFileExistsW(backupFileName.AsNative().c_str())) + if(backupFileName.IsFile()) { DeleteFileW(backupFileName.AsNative().c_str()); } @@ -785,7 +790,7 @@ { CView* pView = GetNextView(pos); if (pView) pView->PostMessage(uMsg, wParam, lParam); - } + } } @@ -1052,7 +1057,7 @@ { CMainFrame *pMainFrm = CMainFrame::GetMainFrame(); CHANNELINDEX nChn = GetNumChannels(); - + if (pMainFrm == nullptr || note == NOTE_NONE) return FALSE; if (nVol > 256) nVol = 256; if (ModCommand::IsNote(ModCommand::NOTE(note))) @@ -1060,7 +1065,7 @@ //kill notes if required. if ( (pause) || (m_SndFile.IsPaused()) || pMainFrm->GetModPlaying() != this) - { + { CriticalSection cs; //OnPlayerPause(); // pause song - pausing VSTis is too slow @@ -1087,7 +1092,7 @@ // Find a channel to play on nChn = FindAvailableChannel(); ModChannel &chn = m_SndFile.m_PlayState.Chn[nChn]; - + // reset channel properties; in theory the chan is completely unused anyway. chn.Reset(ModChannel::resetTotal, m_SndFile, CHANNELINDEX_INVALID); chn.nMasterChn = 0; // remove NNA association @@ -1117,7 +1122,7 @@ m_SndFile.NoteChange(&chn, note, false, true, true); if (nVol >= 0) chn.nVolume = nVol; - + // Handle sample looping. // Changed line to fix http://forum.openmpt.org/index.php?topic=1700.0 //if ((loopstart + 16 < loopend) && (loopstart >= 0) && (loopend <= (LONG)pchn.nLength)) @@ -1137,7 +1142,7 @@ if(sampleOffset > 0 && chn.pModSample) { chn.nPos = sampleOffset; - // If start position is after loop end, set loop end to sample end so that the sample starts + // If start position is after loop end, set loop end to sample end so that the sample starts // playing. if(chn.nLoopEnd < sampleOffset) chn.nLength = chn.nLoopEnd = chn.pModSample->nLength; @@ -1150,13 +1155,13 @@ if (pIns && pIns->HasValidMIDIChannel()) // instro sends to a midi chan { // UINT nPlugin = m_SndFile.GetBestPlugin(nChn, PRIORITISE_INSTRUMENT, EVEN_IF_MUTED); - + PLUGINDEX nPlugin = 0; - if (chn.pModInstrument) + if (chn.pModInstrument) nPlugin = chn.pModInstrument->nMixPlug; // First try instrument plugin if ((!nPlugin || nPlugin > MAX_MIXPLUGINS) && nCurrentChn != CHANNELINDEX_INVALID) nPlugin = m_SndFile.ChnSettings[nCurrentChn].nMixPlugin; // Then try channel plugin - + if ((nPlugin) && (nPlugin <= MAX_MIXPLUGINS)) { IMixPlugin *pPlugin = m_SndFile.m_MixPlugins[nPlugin - 1].pMixPlugin; @@ -1199,7 +1204,7 @@ { plug = m_SndFile.ChnSettings[currentChn].nMixPlugin;// Then try Channel VST } - + if(plug && plug <= MAX_MIXPLUGINS) { IMixPlugin *pPlugin = m_SndFile.m_MixPlugins[plug - 1].pMixPlugin; @@ -1314,7 +1319,7 @@ if (m_SndFile.m_PlayState.Chn[i].nMasterChn == nChn + 1u) { if (doMute) - { + { m_SndFile.m_PlayState.Chn[i].dwFlags.set(muteType); } else { @@ -1636,7 +1641,7 @@ void CModDoc::ActivateWindow() //---------------------------- { - + CChildFrame *pChildFrm = GetChildFrame(); if(pChildFrm) pChildFrm->MDIActivate(); } @@ -1812,7 +1817,7 @@ MuteInstrument((INSTRUMENTINDEX)(i + 1), false); } } - + if(strcmp(fileNameAdd, "")) { SanitizeFilename(fileNameAdd); @@ -2104,7 +2109,7 @@ //User has sent play song command: set loop pattern checkbox to false. pChildFrm->SendViewMessage(VIEWMSG_PATTERNLOOP, 0); } - + pMainFrm->PauseMod(); CriticalSection cs; m_SndFile.m_SongFlags.reset(SONG_STEP | SONG_PATTERNLOOP); @@ -2270,7 +2275,7 @@ { s.AppendFormat(_T("\n\nTotal length:\t%.0fmn%02.0fs"), std::floor(totalLength / 60.0), std::fmod(totalLength, 60.0)); } - + Reporting::Information(s); } @@ -2339,7 +2344,7 @@ followSonghWnd = pChildFrm->GetHwndView(); PATTERNVIEWSTATE patternViewState; pChildFrm->SendViewMessage(VIEWMSG_SAVESTATE, (LPARAM)(&patternViewState)); - + pat = patternViewState.nPattern; row = patternViewState.cursor.GetRow(); ord = patternViewState.nOrder; @@ -2347,11 +2352,11 @@ { //patern editor object does not exist (i.e. is not active) - use saved state. followSonghWnd = NULL; - PATTERNVIEWSTATE *patternViewState = pChildFrm->GetPatternViewState(); + PATTERNVIEWSTATE &patternViewState = pChildFrm->GetPatternViewState(); - pat = patternViewState->nPattern; - row = patternViewState->cursor.GetRow(); - ord = patternViewState->nOrder; + pat = patternViewState.nPattern; + row = patternViewState.cursor.GetRow(); + ord = patternViewState.nOrder; } if(ord >= m_SndFile.Order.size()) @@ -2409,7 +2414,7 @@ followSonghWnd = GetEditPosition(nRow, nPat, nOrd); CModDoc *pModPlaying = pMainFrm->GetModPlaying(); - + CriticalSection cs; // Cut instruments/samples @@ -2437,7 +2442,7 @@ } cs.Leave(); - + if(pModPlaying != this) { SetNotifications(m_notifyType|Notification::Position|Notification::VUMeters, m_notifyItem); @@ -2470,7 +2475,7 @@ followSonghWnd = GetEditPosition(nRow,nPat,nOrd); CModDoc *pModPlaying = pMainFrm->GetModPlaying(); - + CriticalSection cs; // Cut instruments/samples @@ -2482,7 +2487,7 @@ m_SndFile.m_SongFlags.reset(SONG_PAUSED | SONG_STEP); m_SndFile.LoopPattern(nPat); m_SndFile.m_PlayState.m_nNextRow = nRow; - + // set playback timer in the status bar (and update channel status) SetElapsedTime(nOrd, nRow, true); @@ -2618,8 +2623,8 @@ case kcStopSong: OnPlayerStop(); break; case kcPanic: OnPanic(); break; // case kcPauseSong: OnPlayerPause(); break; - + } return wParam; @@ -2714,7 +2719,7 @@ for (int checkMacro = 0; checkMacro < NUM_MACROS; checkMacro++) { int macroType = m_SndFile.m_MidiCfg.GetParameteredMacroType(checkMacro); - + if (macroType == sfx_plug && m_SndFile.m_MidiCfg.MacroToPlugParam(checkMacro) == paramToUse) { CString message; @@ -2739,7 +2744,7 @@ CString message; message.Format("Parameter %02d can now be controlled with macro %X.", paramToUse, macroToSet); Reporting::Information(message, "Macro assigned for this parameter"); - + return; } @@ -2749,7 +2754,7 @@ { CModTypeDlg dlg(m_SndFile, CMainFrame::GetMainFrame()); if (dlg.DoModal() == IDOK) - { + { ScopedLogCapturer logcapturer(*this, "Conversion Status"); bool bShowLog = false; if(dlg.m_nType) @@ -2757,7 +2762,7 @@ if (!ChangeModType(dlg.m_nType)) return; bShowLog = true; } - + CHANNELINDEX nNewChannels = Clamp(dlg.m_nChannels, m_SndFile.GetModSpecifications().channelsMin, m_SndFile.GetModSpecifications().channelsMax); if (nNewChannels != GetNumChannels()) @@ -2799,7 +2804,7 @@ return TEXT(""); CString displayName, instrumentName, pluginName; - + // Get instrument name. instrumentName = m_SndFile.GetInstrumentName(nInstr); @@ -2892,7 +2897,7 @@ // Pattern names // std::string, doesn't need to be fixed. - + // Sequence names. // std::string, doesn't need to be fixed. } @@ -2960,4 +2965,162 @@ } +// Store all view positions t settings file +void CModDoc::SerializeViews() const +//---------------------------------- +{ + const mpt::PathString pathName = GetPathNameMpt(); + if(pathName.empty()) + { + return; + } + std::ostringstream f(std::ios::out | std::ios::binary); + + CRect mdiRect; + ::GetClientRect(CMainFrame::GetMainFrame()->m_hWndMDIClient, &mdiRect); + const int width = mdiRect.Width(); + const int height = mdiRect.Height(); + + // Document view positions and sizes + POSITION pos = GetFirstViewPosition(); + while(pos != nullptr) + { + CModControlView *pView = dynamic_cast<CModControlView *>(GetNextView(pos)); + if(pView) + { + CChildFrame *pChildFrm = (CChildFrame *)pView->GetParentFrame(); + WINDOWPLACEMENT wnd; + wnd.length = sizeof(WINDOWPLACEMENT); + pChildFrm->GetWindowPlacement(&wnd); + const CRect rect = wnd.rcNormalPosition; + + // Write size information + uint8_t windowState = 0; + if(wnd.showCmd == SW_SHOWMAXIMIZED) windowState = 1; + else if(wnd.showCmd == SW_SHOWMINIMIZED) windowState = 2; + mpt::IO::WriteIntLE<uint8_t>(f, 0); // Window type + mpt::IO::WriteIntLE<uint8_t>(f, windowState); + mpt::IO::WriteIntLE<int32_t>(f, Util::muldivr(rect.left, 1 << 30, width)); + mpt::IO::WriteIntLE<int32_t>(f, Util::muldivr(rect.top, 1 << 30, height)); + mpt::IO::WriteIntLE<int32_t>(f, Util::muldivr(rect.Width(), 1 << 30, width)); + mpt::IO::WriteIntLE<int32_t>(f, Util::muldivr(rect.Height(), 1 << 30, height)); + + std::string s = pChildFrm->SerializeView().str(); + mpt::IO::WriteVarInt(f, s.size()); + f << s; + } + } + // Plugin window positions + for(PLUGINDEX i = 0; i < MAX_MIXPLUGINS; i++) + { + if(m_SndFile.m_MixPlugins[i].IsValidPlugin() && m_SndFile.m_MixPlugins[i].editorX != int32_min) + { + mpt::IO::WriteIntLE<uint8_t>(f, 1); // Window type + mpt::IO::WriteIntLE<uint8_t>(f, 0); // Version + mpt::IO::WriteVarInt(f, i); + mpt::IO::WriteIntLE<int32_t>(f, m_SndFile.m_MixPlugins[i].editorX); + mpt::IO::WriteIntLE<int32_t>(f, m_SndFile.m_MixPlugins[i].editorY); + } + } + + SettingsContainer &settings = theApp.GetSongSettings(); + const std::string s = f.str(); + const std::vector<char> data(s.begin(), s.end()); + settings.Write("WindowSettings", pathName.GetFullFileName().ToWide(), pathName); + settings.Write("WindowSettings", pathName.ToWide(), Util::BinToHex(data)); +} + + +// Restore all view positions from settings file +void CModDoc::DeserializeViews() +//------------------------------ +{ + const mpt::PathString pathName = GetPathNameMpt(); + if(pathName.empty()) return; + + SettingsContainer &settings = theApp.GetSongSettings(); + mpt::ustring s = settings.Read<mpt::ustring>("WindowSettings", pathName.ToWide()); + if(s.size() < 2) + { + // Try searching for filename instead of full path name + const std::wstring altName = settings.Read<std::wstring>("WindowSettings", pathName.GetFullFileName().ToWide()); + s = settings.Read<mpt::ustring>("WindowSettings", altName); + if(s.size() < 2) return; + } + std::vector<char> data = Util::HexToBin(s); + + FileReader file(&data[0], data.size()); + + CRect mdiRect; + ::GetWindowRect(CMainFrame::GetMainFrame()->m_hWndMDIClient, &mdiRect); + const int width = mdiRect.Width(); + const int height = mdiRect.Height(); + + POSITION pos = GetFirstViewPosition(); + CChildFrame *pChildFrm = nullptr; + if(pos != nullptr) pChildFrm = dynamic_cast<CChildFrame *>(GetNextView(pos)->GetParentFrame()); + + bool anyMaximized = false; + while(file.AreBytesLeft()) + { + const uint8 windowType = file.ReadUint8(); + if(windowType == 0) + { + // Document view positions and sizes + const uint8 windowState = file.ReadUint8(); + CRect rect; + rect.left = Util::muldivr(file.ReadInt32LE(), width, 1 << 30); + rect.top = Util::muldivr(file.ReadInt32LE(), height, 1 << 30); + rect.right = rect.left + Util::muldivr(file.ReadInt32LE(), width, 1 << 30); + rect.bottom = rect.top + Util::muldivr(file.ReadInt32LE(), height, 1 << 30); + size_t dataSize; + file.ReadVarInt(dataSize); + FileReader data = file.ReadChunk(dataSize); + + if(pChildFrm == nullptr) + { + CModDocTemplate *pTemplate = static_cast<CModDocTemplate *>(GetDocTemplate()); + ASSERT_VALID(pTemplate); + pChildFrm = static_cast<CChildFrame *>(pTemplate->CreateNewFrame(this, nullptr)); + if(pChildFrm != nullptr) + { + pTemplate->InitialUpdateFrame(pChildFrm, this); + } + } + if(pChildFrm != nullptr) + { + WINDOWPLACEMENT wnd; + wnd.length = sizeof(wnd); + pChildFrm->GetWindowPlacement(&wnd); + wnd.showCmd = SW_SHOWNOACTIVATE; + if(windowState == 1 || anyMaximized) + { + // Once a window has been maximized, all following windows have to be marked as maximized as well. + wnd.showCmd = SW_MAXIMIZE; + anyMaximized = true; + } else if(windowState == 2) + { + wnd.showCmd = SW_MINIMIZE; + } + if(rect.left < width && rect.right > 0 && rect.top < height && rect.bottom > 0) + { + wnd.rcNormalPosition = CRect(rect.left, rect.top, rect.right, rect.bottom); + } + pChildFrm->SetWindowPlacement(&wnd); + pChildFrm->DeserializeView(data); + pChildFrm = nullptr; + } + } else if(windowType == 1 && file.ReadUint8() == 0) + { + // Plugin window positions + PLUGINDEX plug = 0; + if(file.ReadVarInt(plug) && plug < MAX_MIXPLUGINS) + { + m_SndFile.m_MixPlugins[plug].editorX = file.ReadInt32LE(); + m_SndFile.m_MixPlugins[plug].editorY = file.ReadInt32LE(); + } + } + } +} + OPENMPT_NAMESPACE_END Modified: trunk/OpenMPT/mptrack/Moddoc.h =================================================================== --- trunk/OpenMPT/mptrack/Moddoc.h 2014-12-13 23:30:29 UTC (rev 4649) +++ trunk/OpenMPT/mptrack/Moddoc.h 2014-12-14 23:50:14 UTC (rev 4650) @@ -177,7 +177,7 @@ SplitKeyboardSettings &GetSplitKeyboardSettings() { return m_SplitKeyboardSettings; } time_t GetCreationTime() const { return m_creationTime; } - + // operations public: bool ChangeModType(MODTYPE wType); @@ -226,7 +226,7 @@ bool IsChannelMuted(CHANNELINDEX nChn) const; bool IsSampleMuted(SAMPLEINDEX nSample) const; bool IsInstrumentMuted(INSTRUMENTINDEX nInstr) const; - + bool NoFxChannel(CHANNELINDEX nChn, bool bNoFx, bool updateMix = true); bool IsChannelNoFx(CHANNELINDEX nChn) const; bool IsChannelRecord1(CHANNELINDEX channel) const; @@ -274,7 +274,7 @@ void OnFileWaveConvert(ORDERINDEX nMinOrder, ORDERINDEX nMaxOrder, const std::vector<EncoderFactoryBase*> &encFactories); // Returns formatted ModInstrument name. - // [in] bEmptyInsteadOfNoName: In case of unnamed instrument string, "(no name)" is returned unless this + // [in] bEmptyInsteadOfNoName: In case of unnamed instrument string, "(no name)" is returned unless this // parameter is true is case which an empty name is returned. // [in] bIncludeIndex: True to include instrument index in front of the instrument name, false otherwise. CString GetPatternViewInstrumentName(INSTRUMENTINDEX nInstr, bool bEmptyInsteadOfNoName = false, bool bIncludeIndex = true) const; @@ -357,6 +357,8 @@ uint8 GetPlaybackMidiChannel(const ModInstrument *pIns, CHANNELINDEX nChn) const; + void SerializeViews() const; + void DeserializeViews(); // Implementation public: Modified: trunk/OpenMPT/mptrack/Mptrack.cpp =================================================================== --- trunk/OpenMPT/mptrack/Mptrack.cpp 2014-12-13 23:30:29 UTC (rev 4649) +++ trunk/OpenMPT/mptrack/Mptrack.cpp 2014-12-14 23:50:14 UTC (rev 4650) @@ -58,8 +58,8 @@ const char *szSpecialNoteShortDesc[] = {TEXT("Param Control (Smooth)"), TEXT("Param Control"), TEXT("Note Fade"), TEXT("Note Cut"), TEXT("Note Off")}; // Make sure that special note arrays include string for every note. -STATIC_ASSERT(NOTE_MAX_SPECIAL - NOTE_MIN_SPECIAL + 1 == CountOf(szSpecialNoteNamesMPT)); -STATIC_ASSERT(CountOf(szSpecialNoteShortDesc) == CountOf(szSpecialNoteNamesMPT)); +STATIC_ASSERT(NOTE_MAX_SPECIAL - NOTE_MIN_SPECIAL + 1 == CountOf(szSpecialNoteNamesMPT)); +STATIC_ASSERT(CountOf(szSpecialNoteShortDesc) == CountOf(szSpecialNoteNamesMPT)); const char *szHexChar = "0123456789ABCDEF"; @@ -642,6 +642,7 @@ : m_GuiThreadId(0) , m_pTrackerDirectories(nullptr) , m_pSettingsIniFile(nullptr) + , m_pSongSettings(nullptr) , m_pSettings(nullptr) , m_pTrackerSettings(nullptr) , m_pComponentManagerSettings(nullptr) @@ -653,7 +654,7 @@ m_GuiThreadId = GetCurrentThreadId(); mpt::log::Trace::SetThreadId(mpt::log::Trace::ThreadKindGUI, m_GuiThreadId); - + ExceptionHandler::Register(); m_bPortableMode = false; @@ -926,11 +927,12 @@ CMainFrame::m_pAutoSaver = new CAutoSaver(); m_pSettingsIniFile = new IniFileSettingsBackend(m_szConfigFileName); - m_pSettings = new SettingsContainer(m_pSettingsIniFile); - m_pTrackerSettings = new TrackerSettings(*m_pSettings); + m_pSongSettingsIniFile = new IniFileSettingsBackend(m_szConfigDirectory + MPT_PATHSTRING("SongSettings.ini")); + m_pSongSettings = new SettingsContainer(m_pSongSettingsIniFile); + // enable debug features (as early as possible after reading the settings) if(TrackerSettings::Instance().DebugTraceEnable) { @@ -1068,7 +1070,7 @@ UninitializeDXPlugins(); ComponentManager::Release(); - + delete m_pPluginCache; m_pPluginCache = nullptr; delete m_pComponentManagerSettings; @@ -1079,6 +1081,10 @@ m_pSettings = nullptr; delete m_pSettingsIniFile; m_pSettingsIniFile = nullptr; + delete m_pSongSettings; + m_pSongSettings = nullptr; + delete m_pSongSettingsIniFile; + m_pSongSettingsIniFile = nullptr; delete m_pTrackerDirectories; m_pTrackerDirectories = nullptr; @@ -1300,7 +1306,7 @@ //--------------------------- { CPaintDC dc(this); - + CDC hdcMem; hdcMem.CreateCompatibleDC(&dc); CBitmap *oldBitmap = hdcMem.SelectObject(&m_Bitmap); @@ -1843,5 +1849,4 @@ return false; } - OPENMPT_NAMESPACE_END Modified: trunk/OpenMPT/mptrack/Mptrack.h =================================================================== --- trunk/OpenMPT/mptrack/Mptrack.h 2014-12-13 23:30:29 UTC (rev 4649) +++ trunk/OpenMPT/mptrack/Mptrack.h 2014-12-14 23:50:14 UTC (rev 4650) @@ -176,7 +176,7 @@ { CDocument* pDoc = CWinApp::OpenDocumentFile(filename.empty() ? NULL : mpt::PathString::TunnelIntoCString(filename).GetString()); if (pDoc && bAddToMRU != TRUE) - RemoveMruItem(0); // This doesn't result to the same behaviour as not adding to MRU + RemoveMruItem(0); // This doesn't result to the same behaviour as not adding to MRU // (if the new item got added, it might have already dropped the last item out) return pDoc; } @@ -205,6 +205,8 @@ IniFileSettingsBackend *m_pSettingsIniFile; SettingsContainer *m_pSettings; TrackerSettings *m_pTrackerSettings; + IniFileSettingsBackend *m_pSongSettingsIniFile; + SettingsContainer *m_pSongSettings; ComponentManagerSettings *m_pComponentManagerSettings; IniFileSettingsContainer *m_pPluginCache; CModDocTemplate *m_pModTemplate; @@ -278,6 +280,12 @@ return *m_pPluginCache; } + SettingsContainer & GetSongSettings() + { + ASSERT(m_pSongSettings); + return *m_pSongSettings; + } + /// Returns path to config fold... [truncated message content] |