From: <sag...@us...> - 2009-10-05 17:02:33
|
Revision: 387 http://modplug.svn.sourceforge.net/modplug/?rev=387&view=rev Author: saga-games Date: 2009-10-05 17:02:19 +0000 (Mon, 05 Oct 2009) Log Message: ----------- [Fix] PSM16 Loader: It was possible to load corrupted modules with > MAX_BASECHANNELS channels (up to 0xFFFF). [Fix] Instrument tab: Update plugin list properly when cleaning up plugins while being on the plugin tab (possibly also improves instrument tab behaviour when working with multiple windows) [Imp] Cleanup: Moved all cleanup functions to a separate sourcecode file, moved cleanup functions from a submenu to an own dialog Modified Paths: -------------- trunk/OpenMPT/mptrack/Ctrl_ins.cpp trunk/OpenMPT/mptrack/Ctrl_ins.h trunk/OpenMPT/mptrack/Moddoc.cpp trunk/OpenMPT/mptrack/Moddoc.h trunk/OpenMPT/mptrack/Modedit.cpp trunk/OpenMPT/mptrack/dlg_misc.cpp trunk/OpenMPT/mptrack/mptrack.rc trunk/OpenMPT/mptrack/mptrack.vcproj trunk/OpenMPT/mptrack/mptrack_08.vcproj trunk/OpenMPT/mptrack/resource.h trunk/OpenMPT/soundlib/Load_psm.cpp Added Paths: ----------- trunk/OpenMPT/mptrack/CleanupSong.cpp trunk/OpenMPT/mptrack/CleanupSong.h Added: trunk/OpenMPT/mptrack/CleanupSong.cpp =================================================================== --- trunk/OpenMPT/mptrack/CleanupSong.cpp (rev 0) +++ trunk/OpenMPT/mptrack/CleanupSong.cpp 2009-10-05 17:02:19 UTC (rev 387) @@ -0,0 +1,813 @@ +/* + * + * CleanupSong.cpp + * --------------- + * Purpose: Interface for cleaning up modules (rearranging, removing unused items) + * + * Authors: Olivier Lapicque + * OpenMPT Devs + * + */ + +#include "stdafx.h" +#include "moddoc.h" +#include "Mainfrm.h" +#include "modsmp_ctrl.h" +#include "CleanupSong.h" + +// Default checkbox state +bool CModCleanupDlg::m_bCheckBoxes[CU_MAX_CLEANUP_OPTIONS] = +{ + true, true, + true, true, + true, false, + true, false, +}; + +// Checkbox -> Control ID LUT +WORD const CModCleanupDlg::m_nCleanupIDtoDlgID[CU_MAX_CLEANUP_OPTIONS] = +{ + IDC_CHK_CLEANUP_PATTERNS, IDC_CHK_REARRANGE_PATTERNS, + IDC_CHK_CLEANUP_SAMPLES, IDC_CHK_REARRANGE_SAMPLES, + IDC_CHK_CLEANUP_INSTRUMENTS, IDC_CHK_REMOVE_INSTRUMENTS, + IDC_CHK_CLEANUP_PLUGINS, IDC_CHK_SAMPLEPACK, +}; + +/////////////////////////////////////////////////////////////////////// +// CModCleanupDlg + +BEGIN_MESSAGE_MAP(CModCleanupDlg, CDialog) + //{{AFX_MSG_MAP(CModTypeDlg) + /*ON_COMMAND(IDC_CHK_CLEANUP_PATTERNS, OnCheckCleanupPatterns) + ON_COMMAND(IDC_CHK_REARRANGE_PATTERNS, OnCheckRearrangePatterns) + ON_COMMAND(IDC_CHK_CLEANUP_SAMPLES, OnCheckCleanupSamples) + ON_COMMAND(IDC_CHK_REARRANGE_SAMPLES, OnCheckRearrangeSamples) + ON_COMMAND(IDC_CHK_CLEANUP_INSTRUMENTS, OnCheckCleanupInstruments) + ON_COMMAND(IDC_CHK_REMOVE_INSTRUMENTS, OnCheckRemoveInstruments) + ON_COMMAND(IDC_CHK_CLEANUP_PLUGINS, OnCheckCleanupPlugins) + ON_COMMAND(IDC_CHK_SAMPLEPACK, OnCheckCreateSamplepack)*/ + + ON_COMMAND(IDC_BTN_CLEANUP_SONG, OnPresetCleanupSong) + ON_COMMAND(IDC_BTN_COMPO_CLEANUP, OnPresetCompoCleanup) + // -! NEW_FEATURE#0023 + //}}AFX_MSG_MAP +END_MESSAGE_MAP() + +BOOL CModCleanupDlg::OnInitDialog() +//--------------------------------- +{ + CDialog::OnInitDialog(); + for(int i = 0; i < CU_MAX_CLEANUP_OPTIONS; i++) + { + CheckDlgButton(m_nCleanupIDtoDlgID[i], (m_bCheckBoxes[i]) ? MF_CHECKED : MF_UNCHECKED); + } + + CSoundFile *pSndFile = m_pModDoc->GetSoundFile(); + if(pSndFile == nullptr) return FALSE; + + GetDlgItem(m_nCleanupIDtoDlgID[CU_CLEANUP_INSTRUMENTS])->EnableWindow((pSndFile->m_nInstruments > 0) ? TRUE :FALSE); + GetDlgItem(m_nCleanupIDtoDlgID[CU_REMOVE_INSTRUMENTS])->EnableWindow((pSndFile->m_nInstruments > 0) ? TRUE :FALSE); + GetDlgItem(m_nCleanupIDtoDlgID[CU_REARRANGE_SAMPLES])->EnableWindow((pSndFile->m_nSamples > 1) ? TRUE :FALSE); + return TRUE; +} + +void CModCleanupDlg::OnOK() +//------------------------- +{ + for(int i = 0; i < CU_MAX_CLEANUP_OPTIONS; i++) + { + m_bCheckBoxes[i] = IsDlgButtonChecked(m_nCleanupIDtoDlgID[i]) ? true : false; + } + + bool bModified = false; + m_pModDoc->ClearLog(); + + // Patterns + if(m_bCheckBoxes[CU_CLEANUP_PATTERNS]) bModified |= RemoveUnusedPatterns(); + if(m_bCheckBoxes[CU_REARRANGE_PATTERNS]) bModified |= RemoveUnusedPatterns(false); + // Instruments + if(m_pModDoc->GetSoundFile()->m_nInstruments > 0) + { + if(m_bCheckBoxes[CU_CLEANUP_INSTRUMENTS]) bModified |= RemoveUnusedInstruments(); + if(m_bCheckBoxes[CU_REMOVE_INSTRUMENTS]) bModified |= RemoveAllInstruments(); + } + // Samples + if(m_bCheckBoxes[CU_CLEANUP_SAMPLES]) bModified |= RemoveUnusedSamples(); + if(m_pModDoc->GetSoundFile()->m_nSamples > 1) + { + if(m_bCheckBoxes[CU_REARRANGE_SAMPLES]) bModified |= RearrangeSamples(); + } + // Plugins + if(m_bCheckBoxes[CU_CLEANUP_PLUGINS]) bModified |= RemoveUnusedPlugins(); + // Create samplepack + if(m_bCheckBoxes[CU_CREATE_SAMPLEPACK]) bModified |= CreateSamplepack(); + + if(bModified) m_pModDoc->SetModified(); + m_pModDoc->UpdateAllViews(NULL, HINT_MODTYPE|HINT_MODSEQUENCE|HINT_MODGENERAL); + m_pModDoc->ShowLog("Cleanup", this); + CDialog::OnOK(); +} + + +void CModCleanupDlg::OnCancel() +//------------------------- +{ + CDialog::OnCancel(); +} + + + +void CModCleanupDlg::OnPresetCleanupSong() +//---------------------------------------- +{ + CheckDlgButton(IDC_CHK_CLEANUP_PATTERNS, MF_CHECKED); + CheckDlgButton(IDC_CHK_REARRANGE_PATTERNS, MF_CHECKED); + CheckDlgButton(IDC_CHK_CLEANUP_SAMPLES, MF_CHECKED); + CheckDlgButton(IDC_CHK_REARRANGE_SAMPLES, MF_CHECKED); + CheckDlgButton(IDC_CHK_CLEANUP_INSTRUMENTS, MF_CHECKED); + CheckDlgButton(IDC_CHK_REMOVE_INSTRUMENTS, MF_UNCHECKED); + CheckDlgButton(IDC_CHK_CLEANUP_PLUGINS, MF_CHECKED); + CheckDlgButton(IDC_CHK_SAMPLEPACK, MF_UNCHECKED); +} + +void CModCleanupDlg::OnPresetCompoCleanup() +//---------------------------------------- +{ + CheckDlgButton(IDC_CHK_CLEANUP_PATTERNS, MF_UNCHECKED); + CheckDlgButton(IDC_CHK_REARRANGE_PATTERNS, MF_UNCHECKED); + CheckDlgButton(IDC_CHK_CLEANUP_SAMPLES, MF_UNCHECKED); + CheckDlgButton(IDC_CHK_REARRANGE_SAMPLES, MF_CHECKED); + CheckDlgButton(IDC_CHK_CLEANUP_INSTRUMENTS, MF_UNCHECKED); + CheckDlgButton(IDC_CHK_REMOVE_INSTRUMENTS, MF_UNCHECKED); + CheckDlgButton(IDC_CHK_CLEANUP_PLUGINS, MF_UNCHECKED); + CheckDlgButton(IDC_CHK_SAMPLEPACK, MF_CHECKED); +} + + +/////////////////////////////////////////////////////////////////////// +// Actual cleanup implementations + +// Remove unused patterns / rearrange patterns +bool CModCleanupDlg::RemoveUnusedPatterns(bool bRemove) +//----------------------------------------------------- +{ + CSoundFile *pSndFile = m_pModDoc->GetSoundFile(); + if(pSndFile == nullptr) return false; + + if(pSndFile->GetType() == MOD_TYPE_MPT && pSndFile->Order.GetNumSequences() > 1) + { // Multiple sequences are not taken into account in the code below. For now just make + // removing unused patterns disabled in this case. + AfxMessageBox(IDS_PATTERN_CLEANUP_UNAVAILABLE, MB_ICONINFORMATION); + return false; + } + const PATTERNINDEX maxPatIndex = pSndFile->Patterns.Size(); + const ORDERINDEX maxOrdIndex = pSndFile->Order.size(); + vector<PATTERNINDEX> nPatMap(maxPatIndex, 0); + vector<ROWINDEX> nPatRows(maxPatIndex, 0); + vector<MODCOMMAND*> pPatterns(maxPatIndex, nullptr); + vector<bool> bPatUsed(maxPatIndex, false); + + bool bSubtunesDetected = false; + // detect subtunes (separated by "---") + for(SEQUENCEINDEX nSeq = 0; nSeq < pSndFile->Order.GetNumSequences(); nSeq++) + { + if(pSndFile->Order.GetSequence(nSeq).GetLengthFirstEmpty() != pSndFile->Order.GetSequence(nSeq).GetLengthTailTrimmed()) + bSubtunesDetected = true; + } + + // Flag to tell whether keeping sequence items which are after the first empty('---') order. + bool bKeepSubSequences = false; + + if(bSubtunesDetected) + { // There are used sequence items after first '---'; ask user whether to remove those. + if (m_wParent->MessageBox( + _TEXT("Do you want to remove sequence items which are after the first '---' item?"), + _TEXT("Sequence Cleanup"), MB_YESNO) != IDYES + ) + bKeepSubSequences = true; + } + + CHAR s[512]; + bool bEnd = false, bReordered = false; + UINT nPatRemoved = 0, nMinToRemove; + PATTERNINDEX nPats; + + BeginWaitCursor(); + PATTERNINDEX maxpat = 0; + for (ORDERINDEX nOrd = 0; nOrd < maxOrdIndex; nOrd++) + { + PATTERNINDEX n = pSndFile->Order[nOrd]; + if (n < maxPatIndex) + { + if (n >= maxpat) maxpat = n + 1; + if (!bEnd || bKeepSubSequences) bPatUsed[n] = true; + } else if (n == pSndFile->Order.GetInvalidPatIndex()) bEnd = true; + } + nMinToRemove = 0; + if (!bRemove) + { + PATTERNINDEX imax = maxPatIndex; + while (imax > 0) + { + imax--; + if ((pSndFile->Patterns[imax]) && (bPatUsed[imax])) break; + } + nMinToRemove = imax + 1; + } + for (PATTERNINDEX nPat = maxpat; nPat < maxPatIndex; nPat++) if ((pSndFile->Patterns[nPat]) && (nPat >= nMinToRemove)) + { + MODCOMMAND *m = pSndFile->Patterns[nPat]; + UINT ncmd = pSndFile->m_nChannels * pSndFile->PatternSize[nPat]; + for (UINT i=0; i<ncmd; i++) + { + if ((m[i].note) || (m[i].instr) || (m[i].volcmd) || (m[i].command)) goto NotEmpty; + } + pSndFile->Patterns.Remove(nPat); + nPatRemoved++; +NotEmpty: + ; + } + UINT bWaste = 0; + for (UINT ichk=0; ichk < maxPatIndex; ichk++) + { + if ((pSndFile->Patterns[ichk]) && (!bPatUsed[ichk])) bWaste++; + } + if ((bRemove) && (bWaste)) + { + EndWaitCursor(); + wsprintf(s, "%d pattern(s) present in file, but not used in the song\nDo you want to reorder the sequence list and remove these patterns?", bWaste); + if (m_wParent->MessageBox(s, "Pattern Cleanup", MB_YESNO) != IDYES) return false; + BeginWaitCursor(); + } + + for (UINT i = 0; i < maxPatIndex; i++) nPatMap[i] = PATTERNINDEX_INVALID; + nPats = 0; + ORDERINDEX imap = 0; + for (imap = 0; imap < maxOrdIndex; imap++) + { + PATTERNINDEX n = pSndFile->Order[imap]; + if (n < maxPatIndex) + { + if (nPatMap[n] > maxPatIndex) nPatMap[n] = nPats++; + pSndFile->Order[imap] = nPatMap[n]; + } else if (n == pSndFile->Order.GetInvalidPatIndex() && (bKeepSubSequences == false)) break; + } + // Add unused patterns at the end + if ((!bRemove) || (!bWaste)) + { + for (UINT iadd=0; iadd<maxPatIndex; iadd++) + { + if ((pSndFile->Patterns[iadd]) && (nPatMap[iadd] >= maxPatIndex)) + { + nPatMap[iadd] = nPats++; + } + } + } + while (imap < maxOrdIndex) + { + pSndFile->Order[imap++] = pSndFile->Order.GetInvalidPatIndex(); + } + // Reorder patterns & Delete unused patterns + BEGIN_CRITICAL(); + { + UINT npatnames = pSndFile->m_nPatternNames; + LPSTR lpszpatnames = pSndFile->m_lpszPatternNames; + pSndFile->m_nPatternNames = 0; + pSndFile->m_lpszPatternNames = NULL; + for (PATTERNINDEX i = 0; i < maxPatIndex; i++) + { + PATTERNINDEX k = nPatMap[i]; + if (k < maxPatIndex) + { + if (i != k) bReordered = true; + // Remap pattern names + if (i < npatnames) + { + UINT noldpatnames = pSndFile->m_nPatternNames; + LPSTR lpszoldpatnames = pSndFile->m_lpszPatternNames; + pSndFile->m_nPatternNames = npatnames; + pSndFile->m_lpszPatternNames = lpszpatnames; + pSndFile->GetPatternName(i, s); + pSndFile->m_nPatternNames = noldpatnames; + pSndFile->m_lpszPatternNames = lpszoldpatnames; + if (s[0]) pSndFile->SetPatternName(k, s); + } + nPatRows[k] = pSndFile->PatternSize[i]; + pPatterns[k] = pSndFile->Patterns[i]; + } else + if (pSndFile->Patterns[i]) + { + pSndFile->Patterns.Remove(i); + nPatRemoved++; + } + } + for (PATTERNINDEX j = 0; j < maxPatIndex;j++) + { + pSndFile->Patterns[j].SetData(pPatterns[j], nPatRows[j]); + } + } + END_CRITICAL(); + EndWaitCursor(); + if ((nPatRemoved) || (bReordered)) + { + m_pModDoc->ClearUndo(); + if (nPatRemoved) + { + wsprintf(s, "%d pattern(s) removed.\n", nPatRemoved); + m_pModDoc->AddToLog(s); + } + return true; + } + return false; +} + + +// Remove unused samples +bool CModCleanupDlg::RemoveUnusedSamples() +//--------------------------------- +{ + CSoundFile *pSndFile = m_pModDoc->GetSoundFile(); + if(pSndFile == nullptr) return false; + + CHAR s[512]; + BOOL bIns[MAX_SAMPLES]; + UINT nExt = 0, nLoopOpt = 0; + UINT nRemoved = 0; + + BeginWaitCursor(); + for (SAMPLEINDEX nSmp = pSndFile->m_nSamples; nSmp >= 1; nSmp--) if (pSndFile->Samples[nSmp].pSample) + { + if (!pSndFile->IsSampleUsed(nSmp)) + { + BEGIN_CRITICAL(); + pSndFile->DestroySample(nSmp); + if ((nSmp == pSndFile->m_nSamples) && (nSmp > 1)) pSndFile->m_nSamples--; + END_CRITICAL(); + nRemoved++; + } + } + if (pSndFile->m_nInstruments) + { + memset(bIns, 0, sizeof(bIns)); + for (UINT ipat=0; ipat<pSndFile->Patterns.Size(); ipat++) + { + MODCOMMAND *p = pSndFile->Patterns[ipat]; + if (p) + { + UINT jmax = pSndFile->PatternSize[ipat] * pSndFile->m_nChannels; + for (UINT j=0; j<jmax; j++, p++) + { + if ((p->note) && (p->note <= NOTE_MAX)) + { + if ((p->instr) && (p->instr < MAX_INSTRUMENTS)) + { + MODINSTRUMENT *pIns = pSndFile->Instruments[p->instr]; + if (pIns) + { + UINT n = pIns->Keyboard[p->note-1]; + if (n < MAX_SAMPLES) bIns[n] = TRUE; + } + } else + { + for (UINT k=1; k<=pSndFile->m_nInstruments; k++) + { + MODINSTRUMENT *pIns = pSndFile->Instruments[k]; + if (pIns) + { + UINT n = pIns->Keyboard[p->note-1]; + if (n < MAX_SAMPLES) bIns[n] = TRUE; + } + } + } + } + } + } + } + for (UINT ichk=1; ichk<MAX_SAMPLES; ichk++) + { + if ((!bIns[ichk]) && (pSndFile->Samples[ichk].pSample)) nExt++; + } + } + EndWaitCursor(); + if (nExt && !((pSndFile->m_nType & MOD_TYPE_IT) && (pSndFile->m_dwSongFlags&SONG_ITPROJECT))) + { //We don't remove an instrument's unused samples in an ITP. + wsprintf(s, "OpenMPT detected %d sample(s) referenced by an instrument,\n" + "but not used in the song. Do you want to remove them ?", nExt); + if (::MessageBox(NULL, s, "Sample Cleanup", MB_YESNO | MB_ICONQUESTION) == IDYES) + { + for (SAMPLEINDEX j = 1; j < MAX_SAMPLES; j++) + { + if ((!bIns[j]) && (pSndFile->Samples[j].pSample)) + { + BEGIN_CRITICAL(); + pSndFile->DestroySample(j); + if ((j == pSndFile->m_nSamples) && (j > 1)) pSndFile->m_nSamples--; + END_CRITICAL(); + nRemoved++; + } + } + } + } + for (SAMPLEINDEX ilo=1; ilo<=pSndFile->m_nSamples; ilo++) if (pSndFile->Samples[ilo].pSample) + { + if ((pSndFile->Samples[ilo].uFlags & CHN_LOOP) + && (pSndFile->Samples[ilo].nLength > pSndFile->Samples[ilo].nLoopEnd + 2)) nLoopOpt++; + } + if (nLoopOpt) + { + wsprintf(s, "OpenMPT detected %d sample(s) with unused data after the loop end point,\n" + "Do you want to optimize it, and remove this unused data ?", nLoopOpt); + if (::MessageBox(NULL, s, "Sample Cleanup", MB_YESNO | MB_ICONQUESTION) == IDYES) + { + for (UINT j=1; j<=pSndFile->m_nSamples; j++) + { + if ((pSndFile->Samples[j].uFlags & CHN_LOOP) + && (pSndFile->Samples[j].nLength > pSndFile->Samples[j].nLoopEnd + 2)) + { + UINT lmax = pSndFile->Samples[j].nLoopEnd + 2; + if ((lmax < pSndFile->Samples[j].nLength) && (lmax >= 16)) pSndFile->Samples[j].nLength = lmax; + } + } + } else nLoopOpt = 0; + } + if ((nRemoved) || (nLoopOpt)) + { + if (nRemoved) + { + wsprintf(s, "%d unused sample(s) removed\n" ,nRemoved); + m_pModDoc->AddToLog(s); + } + if (nLoopOpt) + { + wsprintf(s, "%d sample loop(s) optimized\n" ,nLoopOpt); + m_pModDoc->AddToLog(s); + } + return true; + } + return false; +} + + +// Rearrange sample list +bool CModCleanupDlg::RearrangeSamples() +//------------------------------------- +{ + CSoundFile *pSndFile = m_pModDoc->GetSoundFile(); + if(pSndFile == nullptr) return false; + + if(pSndFile->m_nSamples < 2) + return false; + + SAMPLEINDEX nRemap = 0; // remap count + SAMPLEINDEX nSampleMap[MAX_SAMPLES + 1]; // map old => new + for(SAMPLEINDEX i = 0; i <= MAX_SAMPLES; i++) + nSampleMap[i] = i; + + // First, find out which sample slots are unused and create the new sample map + for(SAMPLEINDEX i = 1 ; i <= pSndFile->m_nSamples; i++) { + if(!pSndFile->Samples[i].pSample) + { + // Move all following samples + nRemap++; + nSampleMap[i] = 0; + for(UINT j = i + 1; j <= pSndFile->m_nSamples; j++) + nSampleMap[j]--; + } + } + + if(!nRemap) + return false; + + BEGIN_CRITICAL(); + + // Now, move everything around + for(SAMPLEINDEX i = 1; i <= pSndFile->m_nSamples; i++) + { + if(nSampleMap[i] != i) + { + // This gotta be moved + pSndFile->MoveSample(i, nSampleMap[i]); + pSndFile->Samples[i].pSample = nullptr; + if(nSampleMap[i] > 0) strcpy(pSndFile->m_szNames[nSampleMap[i]], pSndFile->m_szNames[i]); + memset(pSndFile->m_szNames[i], 0, sizeof(pSndFile->m_szNames[i])); + + // Also update instrument mapping (if module is in instrument mode) + for(INSTRUMENTINDEX iInstr = 1; iInstr <= pSndFile->m_nInstruments; iInstr++){ + if(pSndFile->Instruments[iInstr]){ + MODINSTRUMENT *p = pSndFile->Instruments[iInstr]; + for(WORD iNote = 0; iNote < 128; iNote++) + if(p->Keyboard[iNote] == i) p->Keyboard[iNote] = nSampleMap[i]; + } + } + } + } + + // Go through the patterns and remap samples (if module is in sample mode) + if(!pSndFile->m_nInstruments) + { + for (PATTERNINDEX nPat = 0; nPat < pSndFile->Patterns.Size(); nPat++) if (pSndFile->Patterns[nPat]) + { + MODCOMMAND *m = pSndFile->Patterns[nPat]; + for(UINT len = pSndFile->PatternSize[nPat] * pSndFile->m_nChannels; len; m++, len--) + { + if(m->instr <= pSndFile->m_nSamples) m->instr = (BYTE)nSampleMap[m->instr]; + } + } + } + + pSndFile->m_nSamples -= nRemap; + + END_CRITICAL(); + + return true; + +} + + +// Remove unused instruments +bool CModCleanupDlg::RemoveUnusedInstruments() +//-------------------------------------------- +{ + CSoundFile *pSndFile = m_pModDoc->GetSoundFile(); + if(pSndFile == nullptr) return false; + + INSTRUMENTINDEX usedmap[MAX_INSTRUMENTS]; + INSTRUMENTINDEX swapmap[MAX_INSTRUMENTS]; + INSTRUMENTINDEX swapdest[MAX_INSTRUMENTS]; + CHAR s[512]; + UINT nRemoved = 0; + INSTRUMENTINDEX nSwap, nIndex; + bool bReorg = false; + + if (!pSndFile->m_nInstruments) return false; + + char removeSamples = -1; + if ( !((pSndFile->m_nType & MOD_TYPE_IT) && (pSndFile->m_dwSongFlags&SONG_ITPROJECT))) { //never remove an instrument's samples in ITP. + if(::MessageBox(NULL, "Remove samples associated with an instrument if they are unused?", "Removing unused instruments", MB_YESNO | MB_ICONQUESTION) == IDYES) { + removeSamples = 1; + } + } else { + ::MessageBox(NULL, "This is an IT project file, so no samples associated with a used instrument will be removed.", "Removing unused instruments", MB_OK | MB_ICONINFORMATION); + } + + BeginWaitCursor(); + memset(usedmap, 0, sizeof(usedmap)); + + for(INSTRUMENTINDEX i = pSndFile->m_nInstruments; i >= 1; i--) + { + if (!pSndFile->IsInstrumentUsed(i)) + { + BEGIN_CRITICAL(); + // -> CODE#0003 + // -> DESC="remove instrument's samples" + // pSndFile->DestroyInstrument(i); + pSndFile->DestroyInstrument(i, removeSamples); + // -! BEHAVIOUR_CHANGE#0003 + if ((i == pSndFile->m_nInstruments) && (i>1)) pSndFile->m_nInstruments--; else bReorg = true; + END_CRITICAL(); + nRemoved++; + } else + { + usedmap[i] = 1; + } + } + EndWaitCursor(); + if ((bReorg) && (pSndFile->m_nInstruments > 1) + && (::MessageBox(NULL, "Do you want to reorganize the remaining instruments?", "Removing unused instruments", MB_YESNO | MB_ICONQUESTION) == IDYES)) + { + BeginWaitCursor(); + BEGIN_CRITICAL(); + nSwap = 0; + nIndex = 1; + for (INSTRUMENTINDEX nIns = 1; nIns <= pSndFile->m_nInstruments; nIns++) + { + if (usedmap[nIns]) + { + while (nIndex<nIns) + { + if ((!usedmap[nIndex]) && (!pSndFile->Instruments[nIndex])) + { + swapmap[nSwap] = nIns; + swapdest[nSwap] = nIndex; + pSndFile->Instruments[nIndex] = pSndFile->Instruments[nIns]; + pSndFile->Instruments[nIns] = nullptr; + usedmap[nIndex] = 1; + usedmap[nIns] = 0; + nSwap++; + nIndex++; + break; + } + nIndex++; + } + } + } + while ((pSndFile->m_nInstruments > 1) && (!pSndFile->Instruments[pSndFile->m_nInstruments])) pSndFile->m_nInstruments--; + END_CRITICAL(); + if (nSwap > 0) + { + for (PATTERNINDEX iPat = 0; iPat < pSndFile->Patterns.Size(); iPat++) if (pSndFile->Patterns[iPat]) + { + MODCOMMAND *p = pSndFile->Patterns[iPat]; + UINT nLen = pSndFile->m_nChannels * pSndFile->PatternSize[iPat]; + while (nLen--) + { + if (p->instr) + { + for (UINT k=0; k<nSwap; k++) + { + if (p->instr == swapmap[k]) p->instr = (BYTE)swapdest[k]; + } + } + p++; + } + } + } + EndWaitCursor(); + } + if (nRemoved) + { + wsprintf(s, "%d unused instrument(s) removed\n", nRemoved); + m_pModDoc->AddToLog(s); + return true; + } + return false; +} + + +// Remove all instruments +bool CModCleanupDlg::RemoveAllInstruments(bool bConfirm) +//----------------------------------------------- +{ + CSoundFile *pSndFile = m_pModDoc->GetSoundFile(); + if(pSndFile == nullptr) return false; + + if (!pSndFile->m_nInstruments) + return false; + + char removeSamples = -1; + if(bConfirm) + { + if (CMainFrame::GetMainFrame()->MessageBox("This will remove all the instruments in the song,\n" + "Do you want to continue?", "Removing all instruments", MB_YESNO | MB_ICONQUESTION) != IDYES) return false; + if (CMainFrame::GetMainFrame()->MessageBox("Do you want to convert all instruments to samples ?\n", + "Removing all instruments", MB_YESNO | MB_ICONQUESTION) == IDYES) + { + m_pModDoc->ConvertInstrumentsToSamples(); + } + + if (::MessageBox(NULL, "Remove samples associated with an instrument if they are unused?", "Removing all instruments", MB_YESNO | MB_ICONQUESTION) == IDYES) { + removeSamples = 1; + } + } + + for (INSTRUMENTINDEX i = 1; i <= pSndFile->m_nInstruments; i++) + { + pSndFile->DestroyInstrument(i, removeSamples); + } + + pSndFile->m_nInstruments = 0; + return true; +} + + +// Remove ununsed plugins +bool CModCleanupDlg::RemoveUnusedPlugins() +//-------------------------------------- +{ + CSoundFile *pSndFile = m_pModDoc->GetSoundFile(); + if(pSndFile == nullptr) return false; + + bool usedmap[MAX_MIXPLUGINS]; + memset(usedmap, false, sizeof(usedmap)); + + for (PLUGINDEX nPlug = 0; nPlug < MAX_MIXPLUGINS; nPlug++) { + + //Is the plugin assigned to a channel? + for (CHANNELINDEX nChn = 0; nChn < pSndFile->GetNumChannels(); nChn++) { + if (pSndFile->ChnSettings[nChn].nMixPlugin == nPlug + 1u) { + usedmap[nPlug] = true; + break; + } + } + + //Is the plugin used by an instrument? + for (INSTRUMENTINDEX nIns=1; nIns<=pSndFile->GetNumInstruments(); nIns++) { + if (pSndFile->Instruments[nIns] && (pSndFile->Instruments[nIns]->nMixPlug == nPlug+1)) { + usedmap[nPlug] = true; + break; + } + } + + //Is the plugin assigned to master? + if (pSndFile->m_MixPlugins[nPlug].Info.dwInputRouting & MIXPLUG_INPUTF_MASTEREFFECT) { + usedmap[nPlug] = true; + } + + //all outputs of used plugins count as used + if (usedmap[nPlug]!=0) { + if (pSndFile->m_MixPlugins[nPlug].Info.dwOutputRouting & 0x80) { + int output = pSndFile->m_MixPlugins[nPlug].Info.dwOutputRouting & 0x7f; + usedmap[output] = true; + } + } + + } + + UINT nRemoved = m_pModDoc->RemovePlugs(usedmap); + + return (nRemoved > 0) ? true : false; +} + + +// Turn module into samplepack (convert to IT, remove patterns, etc.) +bool CModCleanupDlg::CreateSamplepack() +//------------------------------------- +{ + CSoundFile *pSndFile = m_pModDoc->GetSoundFile(); + if(pSndFile == nullptr) return false; + + //jojo.compocleanup + if(::MessageBox(NULL, TEXT("WARNING: Turning this module into as samplepack means that OpenMPT will convert the module to IT format, remove all patterns and reset song, sample and instrument attributes to default values. Continue?"), TEXT("Samplepack creation"), MB_YESNO | MB_ICONWARNING) == IDNO) + return false; + + // Stop play. + CMainFrame::GetMainFrame()->StopMod(m_pModDoc); + + BeginWaitCursor(); + BEGIN_CRITICAL(); + + // convert to IT... + m_pModDoc->ChangeModType(MOD_TYPE_IT); + pSndFile->m_nMixLevels = mixLevels_original; + pSndFile->m_nTempoMode = tempo_mode_classic; + pSndFile->m_dwSongFlags = SONG_LINEARSLIDES | SONG_EXFILTERRANGE; + + // clear order list + pSndFile->Order.Init(); + pSndFile->Order[0] = 0; + + // remove all patterns + pSndFile->Patterns.Init(); + pSndFile->Patterns.Insert(0, 64); + pSndFile->SetCurrentOrder(0); + + // Global vars + pSndFile->m_nDefaultTempo = 125; + pSndFile->m_nDefaultSpeed = 6; + pSndFile->m_nDefaultGlobalVolume = 256; + pSndFile->m_nSamplePreAmp = 48; + pSndFile->m_nVSTiVolume = 48; + pSndFile->m_nRestartPos = 0; + + // Set 4 default channels. + pSndFile->ReArrangeChannels(vector<CHANNELINDEX>(4, MAX_BASECHANNELS)); + + // remove plugs + bool keepMask[MAX_MIXPLUGINS]; memset(keepMask, 0, sizeof(keepMask)); + m_pModDoc->RemovePlugs(keepMask); + + // instruments + if(pSndFile->m_nInstruments && ::MessageBox(NULL, "Keep instruments?", TEXT("Samplepack creation"), MB_YESNO | MB_ICONQUESTION) == IDNO) + { + // remove instruments + RemoveAllInstruments(false); + } + else + { + // reset instruments (if there are any) + for(INSTRUMENTINDEX i = 1; i <= pSndFile->m_nInstruments; i++) + { + pSndFile->Instruments[i]->nFadeOut = 256; + pSndFile->Instruments[i]->nGlobalVol = 64; + pSndFile->Instruments[i]->nPan = 128; + pSndFile->Instruments[i]->dwFlags &= ~ENV_SETPANNING; + pSndFile->Instruments[i]->nMixPlug = 0; + + pSndFile->Instruments[i]->nVolSwing = 0; + pSndFile->Instruments[i]->nPanSwing = 0; + pSndFile->Instruments[i]->nCutSwing = 0; + pSndFile->Instruments[i]->nResSwing = 0; + + //might be a good idea to leave those enabled... + /* + pSndFile->Instruments[i]->dwFlags &= ~ENV_VOLUME; + pSndFile->Instruments[i]->dwFlags &= ~ENV_PANNING; + pSndFile->Instruments[i]->dwFlags &= ~ENV_PITCH; + pSndFile->Instruments[i]->dwFlags &= ~ENV_FILTER; + */ + } + } + + // reset samples + ctrlSmp::ResetSamples(*pSndFile, ctrlSmp::SmpResetCompo); + + // Set modflags. + pSndFile->SetModFlag(MSF_MIDICC_BUGEMULATION, false); + pSndFile->SetModFlag(MSF_OLDVOLSWING, false); + pSndFile->SetModFlag(MSF_COMPATIBLE_PLAY, true); + + END_CRITICAL(); + EndWaitCursor(); + + return true; +} Added: trunk/OpenMPT/mptrack/CleanupSong.h =================================================================== --- trunk/OpenMPT/mptrack/CleanupSong.h (rev 0) +++ trunk/OpenMPT/mptrack/CleanupSong.h 2009-10-05 17:02:19 UTC (rev 387) @@ -0,0 +1,67 @@ +/* + * + * CleanupSong.h + * --------------- + * Purpose: Header file for CleanupSong.cpp + * + */ + +#pragma once + +enum ENUM_CLEANUP_OPTIONS +{ + CU_CLEANUP_PATTERNS = 0, + CU_REARRANGE_PATTERNS, + CU_CLEANUP_SAMPLES, + CU_REARRANGE_SAMPLES, + CU_CLEANUP_INSTRUMENTS, + CU_REMOVE_INSTRUMENTS, + CU_CLEANUP_PLUGINS, + CU_CREATE_SAMPLEPACK, + CU_MAX_CLEANUP_OPTIONS +}; + +//================================== +class CModCleanupDlg: public CDialog +//================================== +{ +private: + CModDoc *m_pModDoc; + CWnd *m_wParent; + static bool m_bCheckBoxes[CU_MAX_CLEANUP_OPTIONS]; // Checkbox state + static const WORD m_nCleanupIDtoDlgID[CU_MAX_CLEANUP_OPTIONS]; // Checkbox -> Control ID LUT + + // Actual cleanup implementations + bool RemoveUnusedPatterns(bool bRemove = true); // Remove unused patterns / rearrange patterns + bool RemoveUnusedSamples(); // Remove unused samples + bool RearrangeSamples(); // Rearrange sample list + bool RemoveUnusedInstruments(); // Remove unused instruments + bool RemoveAllInstruments(bool bConfirm = true); // Remove all instruments + bool RemoveUnusedPlugins(); // Remove ununsed plugins + bool CreateSamplepack(); // Turn module into samplepack (convert to IT, remove patterns, etc.) + +public: + CModCleanupDlg(CModDoc *pModDoc, CWnd *parent):CDialog(IDD_CLEANUP_SONG, parent) { m_pModDoc = pModDoc; m_wParent = parent; } + +protected: + //{{AFX_VIRTUAL(CModCleanupDlg) + virtual BOOL OnInitDialog(); + virtual void OnOK(); + virtual void OnCancel(); + //}}AFX_VIRTUAL + + //{{AFX_MSG(CModCleanupDlg) + /*afx_msg void OnCheckCleanupPatterns(); + afx_msg void OnCheckRearrangePatterns(); + afx_msg void OnCheckCleanupSamples(); + afx_msg void OnCheckRearrangeSamples(); + afx_msg void OnCheckCleanupInstruments(); + afx_msg void OnCheckRemoveInstruments(); + afx_msg void OnCheckCleanupPlugins(); + afx_msg void OnCheckCreateSamplepack();*/ + + afx_msg void OnPresetCleanupSong(); + afx_msg void OnPresetCompoCleanup(); + //}}AFX_MSG + DECLARE_MESSAGE_MAP() +}; \ No newline at end of file Modified: trunk/OpenMPT/mptrack/Ctrl_ins.cpp =================================================================== --- trunk/OpenMPT/mptrack/Ctrl_ins.cpp 2009-10-04 18:13:30 UTC (rev 386) +++ trunk/OpenMPT/mptrack/Ctrl_ins.cpp 2009-10-05 17:02:19 UTC (rev 387) @@ -932,34 +932,8 @@ } } - //rewbs.instroVSTi - //Update plugin list - m_CbnMixPlug.Clear(); - m_CbnMixPlug.ResetContent(); - CHAR s[64]; - for (UINT plug=0; plug<=MAX_MIXPLUGINS; plug++) - { - s[0] = 0; - if (!plug) - { - strcpy(s, "No plugin"); - } - else - { - PSNDMIXPLUGIN p = &(m_pSndFile->m_MixPlugins[plug-1]); - p->Info.szLibraryName[63] = 0; - if (p->Info.szLibraryName[0]) - wsprintf(s, "FX%d: %s", plug, p->Info.szName); - else - wsprintf(s, "FX%d: undefined", plug); - } + UpdatePluginList(); - m_CbnMixPlug.SetItemData(m_CbnMixPlug.AddString(s), plug); - } - MODINSTRUMENT *pIns = m_pSndFile->Instruments[m_nInstrument]; - if ((pIns) && (pIns->nMixPlug < MAX_MIXPLUGINS)) m_CbnMixPlug.SetCurSel(pIns->nMixPlug); - //end rewbs.instroVSTi - SetCurrentInstrument((lParam > 0) ? lParam : m_nInstrument); // Initial Update @@ -1236,6 +1210,11 @@ } m_NoteMap.InvalidateRect(NULL, FALSE); } + if(dwHintMask & (HINT_MIXPLUGINS|HINT_MODTYPE)) + { + UpdatePluginList(); + } + if (!m_bInitialized) { // First update @@ -2818,3 +2797,33 @@ m_ComboTuning.AddString("Control tunings..."); m_ComboTuning.SetCurSel(0); } + +void CCtrlInstruments::UpdatePluginList() +//--------------------------------------- +{ + //Update plugin list + m_CbnMixPlug.Clear(); + m_CbnMixPlug.ResetContent(); + CHAR s[64]; + for (PLUGINDEX nPlug = 0; nPlug <= MAX_MIXPLUGINS; nPlug++) + { + s[0] = 0; + if (!nPlug) + { + strcpy(s, "No plugin"); + } + else + { + PSNDMIXPLUGIN p = &(m_pSndFile->m_MixPlugins[nPlug-1]); + p->Info.szLibraryName[63] = 0; + if (p->Info.szLibraryName[0]) + wsprintf(s, "FX%d: %s", nPlug, p->Info.szName); + else + wsprintf(s, "FX%d: undefined", nPlug); + } + + m_CbnMixPlug.SetItemData(m_CbnMixPlug.AddString(s), nPlug); + } + MODINSTRUMENT *pIns = m_pSndFile->Instruments[m_nInstrument]; + if ((pIns) && (pIns->nMixPlug < MAX_MIXPLUGINS)) m_CbnMixPlug.SetCurSel(pIns->nMixPlug); +} Modified: trunk/OpenMPT/mptrack/Ctrl_ins.h =================================================================== --- trunk/OpenMPT/mptrack/Ctrl_ins.h 2009-10-04 18:13:30 UTC (rev 386) +++ trunk/OpenMPT/mptrack/Ctrl_ins.h 2009-10-05 17:02:19 UTC (rev 387) @@ -84,6 +84,8 @@ void UpdateTuningComboBox(); void BuildTuningComboBox(); + void UpdatePluginList(); + //Pitch/Tempo lock CEdit m_EditPitchTempoLock; CButton m_CheckPitchTempoLock; Modified: trunk/OpenMPT/mptrack/Moddoc.cpp =================================================================== --- trunk/OpenMPT/mptrack/Moddoc.cpp 2009-10-04 18:13:30 UTC (rev 386) +++ trunk/OpenMPT/mptrack/Moddoc.cpp 2009-10-05 17:02:19 UTC (rev 387) @@ -14,6 +14,7 @@ #include "vstplug.h" #include "version.h" #include "modsmp_ctrl.h" +#include "CleanupSong.h" #ifdef _DEBUG #define new DEBUG_NEW @@ -52,27 +53,14 @@ ON_COMMAND(ID_INSERT_PATTERN, OnInsertPattern) ON_COMMAND(ID_INSERT_SAMPLE, OnInsertSample) ON_COMMAND(ID_INSERT_INSTRUMENT, OnInsertInstrument) - ON_COMMAND(ID_CLEANUP_SAMPLES, OnCleanupSamples) - ON_COMMAND(ID_CLEANUP_INSTRUMENTS, OnCleanupInstruments) - ON_COMMAND(ID_CLEANUP_PLUGS, OnCleanupPlugs) - ON_COMMAND(ID_CLEANUP_PATTERNS, OnCleanupPatterns) - ON_COMMAND(ID_CLEANUP_SONG, OnCleanupSong) - ON_COMMAND(ID_CLEANUP_REARRANGE, OnRearrangePatterns) - ON_COMMAND(ID_CLEANUP_COMPO, OnCompoCleanup) - ON_COMMAND(ID_INSTRUMENTS_REMOVEALL,OnRemoveAllInstruments) -// -> CODE#0020 -// -> DESC="rearrange sample list" - ON_COMMAND(ID_REARRANGE_SAMPLES, RearrangeSamples) -// -! NEW_FEATURE#0020 + ON_COMMAND(ID_EDIT_CLEANUP, OnShowCleanup) + ON_COMMAND(ID_ESTIMATESONGLENGTH, OnEstimateSongLength) ON_COMMAND(ID_APPROX_BPM, OnApproximateBPM) ON_COMMAND(ID_PATTERN_PLAY, OnPatternPlay) //rewbs.patPlayAllViews ON_COMMAND(ID_PATTERN_PLAYNOLOOP, OnPatternPlayNoLoop) //rewbs.patPlayAllViews ON_COMMAND(ID_PATTERN_RESTART, OnPatternRestart) //rewbs.patPlayAllViews ON_UPDATE_COMMAND_UI(ID_INSERT_INSTRUMENT, OnUpdateXMITMPTOnly) - ON_UPDATE_COMMAND_UI(ID_INSTRUMENTS_REMOVEALL, OnUpdateInstrumentOnly) - ON_UPDATE_COMMAND_UI(ID_CLEANUP_INSTRUMENTS, OnUpdateInstrumentOnly) - ON_UPDATE_COMMAND_UI(ID_REARRANGE_SAMPLES, OnUpdateSampleCount) ON_UPDATE_COMMAND_UI(ID_VIEW_INSTRUMENTS, OnUpdateXMITMPTOnly) ON_UPDATE_COMMAND_UI(ID_VIEW_COMMENTS, OnUpdateXMITMPTOnly) ON_UPDATE_COMMAND_UI(ID_VIEW_MIDIMAPPING, OnUpdateHasMIDIMappings) @@ -1835,89 +1823,14 @@ //end rewbs.graph -void CModDoc::OnCleanupSamples() -//------------------------------ -{ - ClearLog(); - RemoveUnusedSamples(); - UpdateAllViews(NULL, HINT_MODTYPE); - ShowLog("Sample Cleanup", CMainFrame::GetMainFrame()); -} - - -void CModDoc::OnCleanupInstruments() -//---------------------------------- -{ - ClearLog(); - RemoveUnusedInstruments(); - UpdateAllViews(NULL, HINT_MODTYPE); - ShowLog("Instrument Cleanup", CMainFrame::GetMainFrame()); -} - -void CModDoc::OnCleanupPlugs() -//---------------------------------- -{ - ClearLog(); - RemoveUnusedPlugs(); - UpdateAllViews(NULL, HINT_MODTYPE); - ShowLog("Plugin Cleanup", CMainFrame::GetMainFrame()); -} - - - -void CModDoc::OnCleanupPatterns() -//------------------------------- -{ - ClearLog(); - RemoveUnusedPatterns(); - UpdateAllViews(NULL, HINT_MODTYPE|HINT_MODSEQUENCE); - ShowLog("Pattern Cleanup", CMainFrame::GetMainFrame()); -} - - -void CModDoc::OnCleanupSong() +void CModDoc::OnShowCleanup() //--------------------------- { - ClearLog(); - RemoveUnusedPatterns(); - RemoveUnusedInstruments(); - RemoveUnusedSamples(); - RemoveUnusedPlugs(); - UpdateAllViews(NULL, HINT_MODTYPE|HINT_MODSEQUENCE); - ShowLog("Song Cleanup", CMainFrame::GetMainFrame()); + CModCleanupDlg dlg(this, CMainFrame::GetMainFrame()); + dlg.DoModal(); } -void CModDoc::OnRearrangePatterns() -//--------------------------------- -{ - ClearLog(); - RemoveUnusedPatterns(FALSE); - UpdateAllViews(NULL, HINT_MODTYPE|HINT_MODSEQUENCE); - ShowLog("Pattern Rearrange", CMainFrame::GetMainFrame()); -} - -void CModDoc::OnCompoCleanup() -//------------------------------ -{ - CompoCleanup(); - UpdateAllViews(NULL, HINT_MODTYPE); -} - - - -void CModDoc::OnUpdateInstrumentOnly(CCmdUI *p) -//--------------------------------------------- -{ - if (p) p->Enable((m_SndFile.m_nInstruments) ? TRUE : FALSE); -} - -void CModDoc::OnUpdateSampleCount(CCmdUI *p) -//------------------------------------------ -{ - if (p) p->Enable((m_SndFile.m_nSamples > 1) ? TRUE : FALSE); -} - void CModDoc::OnUpdateHasMIDIMappings(CCmdUI *p) //---------------------------------------------- { @@ -1977,13 +1890,7 @@ } -void CModDoc::OnRemoveAllInstruments() -//------------------------------------ -{ - RemoveAllInstruments(); -} - void CModDoc::OnEstimateSongLength() //---------------------------------- { Modified: trunk/OpenMPT/mptrack/Moddoc.h =================================================================== --- trunk/OpenMPT/mptrack/Moddoc.h 2009-10-04 18:13:30 UTC (rev 386) +++ trunk/OpenMPT/mptrack/Moddoc.h 2009-10-05 17:02:19 UTC (rev 387) @@ -189,15 +189,8 @@ BOOL ChangeModType(UINT nNewType); BOOL ChangeNumChannels(UINT nNewChannels, const bool showCancelInRemoveDlg = true); - BOOL ConvertInstrumentsToSamples();; - BOOL RemoveUnusedSamples(); - BOOL RemoveUnusedInstruments(); - void RemoveAllInstruments(bool bConfirm = true); - BOOL RemoveUnusedPlugs(); + BOOL ConvertInstrumentsToSamples(); UINT RemovePlugs(const bool (&keepMask)[MAX_MIXPLUGINS]); - BOOL RemoveUnusedPatterns(BOOL bRemove=TRUE); - void RearrangeSamples(); - BOOL CompoCleanup(); PATTERNINDEX InsertPattern(ORDERINDEX nOrd = -1, ROWINDEX nRows = 64); SAMPLEINDEX InsertSample(bool bLimit = false); @@ -242,7 +235,7 @@ BOOL IsChildSample(UINT nIns, UINT nSmp) const; UINT FindSampleParent(UINT nSmp) const; UINT FindInstrumentChild(UINT nIns) const; - bool MoveOrder(ORDERINDEX nSourceNdx, ORDERINDEX nDestNdx, bool bUpdate = true, bool bCopy = false); + bool MoveOrder(ORDERINDEX nSourceNdx, ORDERINDEX nDestNdx, bool bUpdate = true, bool bCopy = false, SEQUENCEINDEX nSourceSeq = SEQUENCEINDEX_INVALID, SEQUENCEINDEX nDestSeq = SEQUENCEINDEX_INVALID); BOOL ExpandPattern(PATTERNINDEX nPattern); BOOL ShrinkPattern(PATTERNINDEX nPattern); BOOL CopyPattern(PATTERNINDEX nPattern, DWORD dwBeginSel, DWORD dwEndSel); @@ -332,20 +325,11 @@ afx_msg void OnInsertPattern(); afx_msg void OnInsertSample(); afx_msg void OnInsertInstrument(); - afx_msg void OnCleanupSamples(); - afx_msg void OnCleanupInstruments(); - afx_msg void OnCleanupPlugs(); - afx_msg void OnCleanupPatterns(); - afx_msg void OnCleanupSong(); - afx_msg void OnRearrangePatterns(); - afx_msg void OnCompoCleanup(); - afx_msg void OnRemoveAllInstruments(); + afx_msg void OnShowCleanup(); afx_msg void OnEstimateSongLength(); afx_msg void OnApproximateBPM(); afx_msg void OnUpdateXMITMPTOnly(CCmdUI *p); afx_msg void OnUpdateHasMIDIMappings(CCmdUI *p); - afx_msg void OnUpdateInstrumentOnly(CCmdUI *pCmdUI); - afx_msg void OnUpdateSampleCount(CCmdUI *pCmdUI); afx_msg void OnUpdateMP3Encode(CCmdUI *pCmdUI); afx_msg void OnPatternRestart(); //rewbs.customKeys afx_msg void OnPatternPlay(); //rewbs.customKeys Modified: trunk/OpenMPT/mptrack/Modedit.cpp =================================================================== --- trunk/OpenMPT/mptrack/Modedit.cpp 2009-10-04 18:13:30 UTC (rev 386) +++ trunk/OpenMPT/mptrack/Modedit.cpp 2009-10-05 17:02:19 UTC (rev 387) @@ -1007,251 +1007,6 @@ } -BOOL CModDoc::RemoveUnusedPatterns(BOOL bRemove) -//---------------------------------------------- -{ - if (GetSoundFile()->GetType() == MOD_TYPE_MPT && GetSoundFile()->Order.GetNumSequences() > 1) - { // Multiple sequences are not taken into account in the code below. For now just make - // removing unused patterns disabled in this case. - AfxMessageBox(IDS_PATTERN_CLEANUP_UNAVAILABLE, MB_ICONINFORMATION); - return FALSE; - } - const UINT maxPatIndex = m_SndFile.Patterns.Size(); - const UINT maxOrdIndex = m_SndFile.Order.size(); - vector<UINT> nPatMap(maxPatIndex, 0); - vector<UINT> nPatRows(maxPatIndex, 0); - vector<MODCOMMAND*> pPatterns(maxPatIndex, NULL); - vector<BOOL> bPatUsed(maxPatIndex, false); - - bool bSubtunesDetected = false; - // detect subtunes (separated by "---") - for(SEQUENCEINDEX nSeq = 0; nSeq < m_SndFile.Order.GetNumSequences(); nSeq++) - { - if(m_SndFile.Order.GetSequence(nSeq).GetLengthFirstEmpty() != m_SndFile.Order.GetSequence(nSeq).GetLengthTailTrimmed()) - bSubtunesDetected = true; - } - - // Flag to tell whether keeping sequence items which are after the first empty('---') order. - bool bKeepSubSequences = false; - - if(bSubtunesDetected) - { // There are used sequence items after first '---'; ask user whether to remove those. - if (CMainFrame::GetMainFrame()->MessageBox( - _TEXT("Do you want to remove sequence items which are after the first '---' item?"), - _TEXT("Sequence Cleanup"), MB_YESNO) != IDYES - ) - bKeepSubSequences = true; - } - - CHAR s[512]; - BOOL bEnd = FALSE, bReordered = FALSE; - UINT nPatRemoved = 0, nMinToRemove, nPats; - - BeginWaitCursor(); - UINT maxpat = 0; - for (UINT iord=0; iord<maxOrdIndex; iord++) - { - UINT n = m_SndFile.Order[iord]; - if (n < maxPatIndex) - { - if (n >= maxpat) maxpat = n+1; - if (!bEnd || bKeepSubSequences) bPatUsed[n] = TRUE; - } else if (n == m_SndFile.Order.GetInvalidPatIndex()) bEnd = TRUE; - } - nMinToRemove = 0; - if (!bRemove) - { - UINT imax = maxPatIndex; - while (imax > 0) - { - imax--; - if ((m_SndFile.Patterns[imax]) && (bPatUsed[imax])) break; - } - nMinToRemove = imax+1; - } - for (UINT ipat=maxpat; ipat<maxPatIndex; ipat++) if ((m_SndFile.Patterns[ipat]) && (ipat >= nMinToRemove)) - { - MODCOMMAND *m = m_SndFile.Patterns[ipat]; - UINT ncmd = m_SndFile.m_nChannels * m_SndFile.PatternSize[ipat]; - for (UINT i=0; i<ncmd; i++) - { - if ((m[i].note) || (m[i].instr) || (m[i].volcmd) || (m[i].command)) goto NotEmpty; - } - m_SndFile.Patterns.Remove(ipat); - nPatRemoved++; - NotEmpty: - ; - } - UINT bWaste = 0; - for (UINT ichk=0; ichk < maxPatIndex; ichk++) - { - if ((m_SndFile.Patterns[ichk]) && (!bPatUsed[ichk])) bWaste++; - } - if ((bRemove) && (bWaste)) - { - EndWaitCursor(); - wsprintf(s, "%d pattern(s) present in file, but not used in the song\nDo you want to reorder the sequence list and remove these patterns?", bWaste); - if (CMainFrame::GetMainFrame()->MessageBox(s, "Pattern Cleanup", MB_YESNO) != IDYES) return TRUE; - BeginWaitCursor(); - } - for (UINT irst=0; irst<maxPatIndex; irst++) nPatMap[irst] = 0xFFFF; - nPats = 0; - UINT imap = 0; - for (imap=0; imap<maxOrdIndex; imap++) - { - UINT n = m_SndFile.Order[imap]; - if (n < maxPatIndex) - { - if (nPatMap[n] > maxPatIndex) nPatMap[n] = nPats++; - m_SndFile.Order[imap] = nPatMap[n]; - } else if (n == m_SndFile.Order.GetInvalidPatIndex() && (bKeepSubSequences == false)) break; - } - // Add unused patterns at the end - if ((!bRemove) || (!bWaste)) - { - for (UINT iadd=0; iadd<maxPatIndex; iadd++) - { - if ((m_SndFile.Patterns[iadd]) && (nPatMap[iadd] >= maxPatIndex)) - { - nPatMap[iadd] = nPats++; - } - } - } - while (imap < maxOrdIndex) - { - m_SndFile.Order[imap++] = m_SndFile.Order.GetInvalidPatIndex(); - } - BEGIN_CRITICAL(); - // Reorder patterns & Delete unused patterns - { - UINT npatnames = m_SndFile.m_nPatternNames; - LPSTR lpszpatnames = m_SndFile.m_lpszPatternNames; - m_SndFile.m_nPatternNames = 0; - m_SndFile.m_lpszPatternNames = NULL; - for (UINT i=0; i<maxPatIndex; i++) - { - UINT k = nPatMap[i]; - if (k < maxPatIndex) - { - if (i != k) bReordered = TRUE; - // Remap pattern names - if (i < npatnames) - { - UINT noldpatnames = m_SndFile.m_nPatternNames; - LPSTR lpszoldpatnames = m_SndFile.m_lpszPatternNames; - m_SndFile.m_nPatternNames = npatnames; - m_SndFile.m_lpszPatternNames = lpszpatnames; - m_SndFile.GetPatternName(i, s); - m_SndFile.m_nPatternNames = noldpatnames; - m_SndFile.m_lpszPatternNames = lpszoldpatnames; - if (s[0]) m_SndFile.SetPatternName(k, s); - } - nPatRows[k] = m_SndFile.PatternSize[i]; - pPatterns[k] = m_SndFile.Patterns[i]; - } else - if (m_SndFile.Patterns[i]) - { - m_SndFile.Patterns.Remove(i); - nPatRemoved++; - } - } - for (UINT j=0; j<maxPatIndex;j++) - { - m_SndFile.Patterns[j].SetData(pPatterns[j], nPatRows[j]); - } - } - END_CRITICAL(); - EndWaitCursor(); - if ((nPatRemoved) || (bReordered)) - { - ClearUndo(); - SetModified(); - if (nPatRemoved) - { - wsprintf(s, "%d pattern(s) removed.\n", nPatRemoved); - AddToLog(s); - } - return TRUE; - } - return FALSE; -} - - - - -void CModDoc::RearrangeSamples() -//------------------------------ -{ - if(m_SndFile.m_nSamples < 2) - return; - - UINT nRemap = 0; // remap count - UINT nSampleMap[MAX_SAMPLES + 1]; // map old => new - for(UINT i = 0; i <= MAX_SAMPLES; i++) - nSampleMap[i] = i; - - // First, find out which sample slots are unused and create the new sample map - for(SAMPLEINDEX i = 1 ; i <= m_SndFile.m_nSamples; i++) { - if(!m_SndFile.Samples[i].pSample) - { - // Move all following samples - nRemap++; - nSampleMap[i] = 0; - for(UINT j = i + 1; j <= m_SndFile.m_nSamples; j++) - nSampleMap[j]--; - } - } - - if(!nRemap) - return; - - BEGIN_CRITICAL(); - - // Now, move everything around - for(SAMPLEINDEX i = 1; i <= m_SndFile.m_nSamples; i++) - { - if(nSampleMap[i] != i) - { - // This gotta be moved - m_SndFile.MoveSample(i, nSampleMap[i]); - m_SndFile.Samples[i].pSample = nullptr; - if(nSampleMap[i] > 0) strcpy(m_SndFile.m_szNames[nSampleMap[i]], m_SndFile.m_szNames[i]); - memset(m_SndFile.m_szNames[i], 0, sizeof(m_SndFile.m_szNames[i])); - - // Also update instrument mapping (if module is in instrument mode) - for(INSTRUMENTINDEX iInstr = 1; iInstr <= m_SndFile.m_nInstruments; iInstr++){ - if(m_SndFile.Instruments[iInstr]){ - MODINSTRUMENT *p = m_SndFile.Instruments[iInstr]; - for(WORD iNote = 0; iNote < 128; iNote++) - if(p->Keyboard[iNote] == i) p->Keyboard[iNote] = nSampleMap[i]; - } - } - } - } - - // Go through the patterns and remap samples (if module is in sample mode) - if(!m_SndFile.m_nInstruments) - { - for (PATTERNINDEX nPat = 0; nPat < m_SndFile.Patterns.Size(); nPat++) if (m_SndFile.Patterns[nPat]) - { - MODCOMMAND *m = m_SndFile.Patterns[nPat]; - for(UINT len = m_SndFile.PatternSize[nPat] * m_SndFile.m_nChannels; len; m++, len--) - { - if(m->instr <= m_SndFile.m_nSamples) m->instr = nSampleMap[m->instr]; - } - } - } - - m_SndFile.m_nSamples -= nRemap; - - END_CRITICAL(); - - SetModified(); - UpdateAllViews(NULL, HINT_MODTYPE); - -} - - BOOL CModDoc::ConvertInstrumentsToSamples() //----------------------------------------- { @@ -1278,130 +1033,7 @@ } -BOOL CModDoc::RemoveUnusedSamples() -//--------------------------------- -{ - CHAR s[512]; - BOOL bIns[MAX_SAMPLES]; - UINT nExt = 0, nLoopOpt = 0; - UINT nRemoved = 0; - - BeginWaitCursor(); - for (UINT i=m_SndFile.m_nSamples; i>=1; i--) if (m_SndFile.Samples[i].pSample) - { - if (!m_SndFile.IsSampleUsed(i)) - { - BEGIN_CRITICAL(); - m_SndFile.DestroySample(i); - if ((i == m_SndFile.m_nSamples) && (i > 1)) m_SndFile.m_nSamples--; - END_CRITICAL(); - nRemoved++; - } - } - if (m_SndFile.m_nInstruments) - { - memset(bIns, 0, sizeof(bIns)); - for (UINT ipat=0; ipat<m_SndFile.Patterns.Size(); ipat++) - { - MODCOMMAND *p = m_SndFile.Patterns[ipat]; - if (p) - { - UINT jmax = m_SndFile.PatternSize[ipat] * m_SndFile.m_nChannels; - for (UINT j=0; j<jmax; j++, p++) - { - if ((p->note) && (p->note <= NOTE_MAX)) - { - if ((p->instr) && (p->instr < MAX_INSTRUMENTS)) - { - MODINSTRUMENT *pIns = m_SndFile.Instruments[p->instr]; - if (pIns) - { - UINT n = pIns->Keyboard[p->note-1]; - if (n < MAX_SAMPLES) bIns[n] = TRUE; - } - } else - { - for (UINT k=1; k<=m_SndFile.m_nInstruments; k++) - { - MODINSTRUMENT *pIns = m_SndFile.Instruments[k]; - if (pIns) - { - UINT n = pIns->Keyboard[p->note-1]; - if (n < MAX_SAMPLES) bIns[n] = TRUE; - } - } - } - } - } - } - } - for (UINT ichk=1; ichk<MAX_SAMPLES; ichk++) - { - if ((!bIns[ichk]) && (m_SndFile.Samples[ichk].pSample)) nExt++; - } - } - EndWaitCursor(); - if (nExt && !((m_SndFile.m_nType & MOD_TYPE_IT) && (m_SndFile.m_dwSongFlags&SONG_ITPROJECT))) - { //We don't remove an instrument's unused samples in an ITP. - wsprintf(s, "OpenMPT detected %d sample(s) referenced by an instrument,\n" - "but not used in the song. Do you want to remove them ?", nExt); - if (::MessageBox(NULL, s, "Sample Cleanup", MB_YESNO | MB_ICONQUESTION) == IDYES) - { - for (UINT j=1; j<MAX_SAMPLES; j++) - { - if ((!bIns[j]) && (m_SndFile.Samples[j].pSample)) - { - BEGIN_CRITICAL(); - m_SndFile.DestroySample(j); - if ((j == m_SndFile.m_nSamples) && (j > 1)) m_SndFile.m_nSamples--; - END_CRITICAL(); - nRemoved++; - } - } - } - } - for (UINT ilo=1; ilo<=m_SndFile.m_nSamples; ilo++) if (m_SndFile.Samples[ilo].pSample) - { - if ((m_SndFile.Samples[ilo].uFlags & CHN_LOOP) - && (m_SndFile.Samples[ilo].nLength > m_SndFile.Samples[ilo].nLoopEnd + 2)) nLoopOpt++; - } - if (nLoopOpt) - { - wsprintf(s, "OpenMPT detected %d sample(s) with unused data after the loop end point,\n" - "Do you want to optimize it, and remove this unused data ?", nLoopOpt); - if (::MessageBox(NULL, s, "Sample Cleanup", MB_YESNO | MB_ICONQUESTION) == IDYES) - { - for (UINT j=1; j<=m_SndFile.m_nSamples; j++) - { - if ((m_SndFile.Samples[j].uFlags & CHN_LOOP) - && (m_SndFile.Samples[j].nLength > m_SndFile.Samples[j].nLoopEnd + 2)) - { - UINT lmax = m_SndFile.Samples[j].nLoopEnd + 2; - if ((lmax < m_SndFile.Samples[j].nLength) && (lmax >= 16)) m_SndFile.Samples[j].nLength = lmax; - } - } - } else nLoopOpt = 0; - } - if ((nRemoved) || (nLoopOpt)) - { - if (nRemoved) - { - wsprintf(s, "%d unused sample(s) removed\n" ,nRemoved); - AddToLog(s); - } - if (nLoopOpt) - { - wsprintf(s, "%d sample loop(s) optimized\n" ,nLoopOpt); - AddToLog(s); - } - SetModified(); - return TRUE; - } - return FALSE; -} - - UINT CModDoc::RemovePlugs(const bool (&keepMask)[MAX_MIXPLUGINS]) //--------------------------------------------------------------- { @@ -1443,288 +1075,6 @@ } -BOOL CModDoc::RemoveUnusedPlugs() -//------------------------------- -{ - bool usedmap[MAX_MIXPLUGINS]; - memset(usedmap, false, sizeof(usedmap)); - - for (PLUGINDEX nPlug=0; nPlug < MAX_MIXPLUGINS; nPlug++) { - - //Is the plugin assigned to a channel? - for (CHANNELINDEX nChn = 0; nChn < m_SndFile.GetNumChannels(); nChn++) { - if (m_SndFile.ChnSettings[nChn].nMixPlugin == nPlug + 1u) { - usedmap[nPlug]=true; - break; - } - } - - //Is the plugin used by an instrument? - for (INSTRUMENTINDEX nIns=1; nIns<=m_SndFile.GetNumInstruments(); nIns++) { - if (m_SndFile.Instruments[nIns] && (m_SndFile.Instruments[nIns]->nMixPlug == nPlug+1)) { - usedmap[nPlug]=true; - break; - } - } - - //Is the plugin assigned to master? - if (m_SndFile.m_MixPlugins[nPlug].Info.dwInputRouting & MIXPLUG_INPUTF_MASTEREFFECT) { - usedmap[nPlug]=true; - } - - //all outputs of used plugins count as used - if (usedmap[nPlug]!=0) { - if (m_SndFile.m_MixPlugins[nPlug].Info.dwOutputRouting & 0x80) { - int output = m_SndFile.m_MixPlugins[nPlug].Info.dwOutputRouting & 0x7f; - usedmap[output]=true; - } - } - - } - - UINT nRemoved = RemovePlugs(usedmap); - - if (nRemoved) { - SetModified(); - } - - return nRemoved; -} - - -void CModDoc::RemoveAllInstruments(bool bConfirm) -//----------------------------------------------- -{ - if (!m_SndFile.m_nInstruments) - return; - - char removeSamples = -1; - if(bConfirm) - { - if (CMainFrame::GetMainFrame()->MessageBox("This will remove all the instruments in the song,\n" - "Do you want to continue?", "Warning", MB_YESNO | MB_ICONQUESTION) != IDYES) return; - if (CMainFrame::GetMainFrame()->MessageBox("Do you want to convert all instruments to samples ?\n", - NULL, MB_YESNO | MB_ICONQUESTION) == IDYES) - { - ConvertInstrumentsToSamples(); - } - - if (::MessageBox(NULL, "Remove samples associated with an instrument if they are unused?", "Removing instrument", MB_YESNO | MB_ICONQUESTION) == IDYES) { - removeSamples = 1; - } - } - - for (INSTRUMENTINDEX i = 1; i <= m_SndFile.m_nInstruments; i++) - { - m_SndFile.DestroyInstrument(i,removeSamples); - } - - m_SndFile.m_nInstruments = 0; - SetModified(); - UpdateAllViews(NULL, HINT_MODTYPE); -} - - -BOOL CModDoc::RemoveUnusedInstruments() -//------------------------------------- -{ - BYTE usedmap[MAX_INSTRUMENTS]; - BYTE swapmap[MAX_INSTRUMENTS]; - BYTE swapdest[MAX_INSTRUMENTS]; - CHAR s[512]; - UINT nRemoved = 0; - UINT nSwap, nIndex; - bool bReorg = false; - - if (!m_SndFile.m_nInstruments) return FALSE; - - char removeSamples = -1; - if ( !((m_SndFile.m_nType & MOD_TYPE_IT) && (m_SndFile.m_dwSongFlags&SONG_ITPROJECT))) { //never remove an instrument's samples in ITP. - if(::MessageBox(NULL, "Remove samples associated with an instrument if they are unused?", "Removing instrument", MB_YESNO | MB_ICONQUESTION) == IDYES) { - removeSamples = 1; - } - } else { - MessageBox(NULL, "This is an IT project, so no samples associated with a used instrument will be removed.", "Removing Instruments", MB_OK | MB_ICONINFORMATION); - } - - BeginWaitCursor(); - memset(usedmap, 0, sizeof(usedmap)); - - for(INSTRUMENTINDEX i = m_SndFile.m_nInstruments; i >= 1; i--) - { - if (!m_SndFile.IsInstrumentUsed(i)) - { - BEGIN_CRITICAL(); -// -> CODE#0003 -// -> DESC="remove instrument's samples" -// m_SndFile.DestroyInstrument(i); - m_SndFile.DestroyInstrument(i, removeSamples); -// -! BEHAVIOUR_CHANGE#0003 - if ((i == m_SndFile.m_nInstruments) && (i>1)) m_SndFile.m_nInstruments--; else bReorg = true; - END_CRITICAL(); - nRemoved++; - } else - { - usedmap[i] = 1; - } - } - EndWaitCursor(); - if ((bReorg) && (m_SndFile.m_nInstruments > 1) - && (::MessageBox(NULL, "Do you want to reorganize the remaining instruments?", "Instrument Cleanup", MB_YESNO | MB_ICONQUESTION) == IDYES)) - { - BeginWaitCursor(); - BEGIN_CRITICAL(); - nSwap = 0; - nIndex = 1; - for (UINT j=1; j<=m_SndFile.m_nInstruments; j++) - { - if (usedmap[j]) - { - while (nIndex<j) - { - if ((!usedmap[nIndex]) && (!m_SndFile.Instruments[nIndex])) - { - swapmap[nSwap] = j; - swapdest[nSwap] = nIndex; - m_SndFile.Instruments[nIndex] = m_SndFile.Instruments[j]; - m_SndFile.Instruments[j] = NULL; - usedmap[nIndex] = 1; - usedmap[j] = 0; - nSwap++; - nIndex++; - break; - } - nIndex++; - } - } - } - while ((m_SndFile.m_nInstruments > 1) && (!m_SndFile.Instruments[m_SndFile.m_nInstruments])) m_SndFile.m_nInstruments--; - END_CRITICAL(); - if (nSwap > 0) - { - for (UINT iPat=0; iPat<m_SndFile.Patterns.Size(); iPat++) if (m_SndFile.Patterns[iPat]) - { - MODCOMMAND *p = m_SndFile.Patterns[iPat]; - UINT nLen = m_SndFile.m_nChannels * m_SndFile.PatternSize[iPat]; - while (nLen--) - { - if (p->instr) - { - for (UINT k=0; k<nSwap; k++) - { - if (p->instr == swapmap[k]) p->instr = swapdest[k]; - } - } - p++; - } - } - } - EndWaitCursor(); - } - if (nRemoved) - { - wsprintf(s, "%d unused instrument(s) removed\n", nRemoved); - AddToLog(s); - SetModified(); - return TRUE; - } - return FALSE; -} - - -BOOL CModDoc::CompoCleanup() -//-------------------------- -{ - //jojo.compocleanup - if(::MessageBox(NULL, TEXT("WARNING: Compo cleanup will convert module to IT format, remove all patterns and reset song, sample and instrument attributes to default values. Continue?"), TEXT("Compo Cleanup"), MB_YESNO | MB_ICONWARNING) == IDNO) - return FALSE; - - // Stop play. - CMainFrame::GetMainFrame()->StopMod(this); - - BeginWaitCursor(); - BEGIN_CRITICAL(); - - // convert to IT... - ChangeModType(MOD_TYPE_IT); - m_SndFile.m_nMixLevels = mixLevels_original; - m_SndFile.m_nTempoMode = tempo_mode_classic; - m_SndFile.m_dwSongFlags = SONG_LINEARSLIDES | SONG_EXFILTERRANGE; - - // clear order list - m_SndFile.Order.Init(); - m_SndFile.Order[0] = 0; - - // remove all patterns - m_SndFile.Patterns.Init(); - m_SndFile.Patterns.Insert(0, 64); - m_SndFile.SetCurrentOrder(0); - - // Global vars - m_SndFile.m_nDefaultTempo = 125; - m_SndFile.m_nDefaultSpeed = 6; - m_SndFile.m_nDefaultGlobalVolume = 256; - m_SndFile.m_nSamplePreAmp = 48; - m_SndFile.m_nVSTiVolume = 48; - m_SndFile.m_nRestartPos = 0; - - // Set 4 default channels. - m_SndFile.ReArrangeChannels(vector<CHANNELINDEX>(4, MAX_BASECHANNELS)); - - //remove plugs - bool keepMask[MAX_MIXPLUGINS]; memset(keepMask, 0, sizeof(keepMask)); - RemovePlugs(keepMask); - - // instruments - if(m_SndFile.m_nInstruments && ::MessageBox(NULL, "Remove instruments?", "Compo Cleanup", MB_YESNO | MB_ICONQUESTION) == IDYES) - { - // remove instruments - RemoveAllInstruments(false); - } - else - { - // reset instruments - for(UINT i = 1; i <= m_SndFile.m_nInstruments; i++) - { - m_SndFile.Instruments[i]->nFadeOut = 256; - m_SndFile.Instruments[i]->nGlobalVol = 64; - m_SndFile.Instruments[i]->nPan = 128; - m_SndFile.Instruments[i]->dwFlags &= ~ENV_SETPANNING; - m_SndFile.Instruments[i]->nMixPlug = 0; - - m_SndFile.Instruments[i]->nVolSwing = 0; - m_SndFile.Instruments[i]->nPanSwing = 0; - m_SndFile.Instruments[i]->nCutSwing = 0; - m_SndFile.Instruments[i]->nResSwing = 0; - - //might be a good idea to leave those enabled... - /* - m_SndFile.Instruments[i]->dwFlags &= ~ENV_VOLUME; - m_SndFile.Instruments[i]->dwFlags &= ~ENV_PANNING; - m_SndFile.Instruments[i]->dwFlags &= ~ENV_PITCH; - m_SndFile.Instruments[i]->dwFlags &= ~ENV_FILTER; - */ - } - } - - // reset samples - ctrlSmp::ResetSamples(m_SndFile, ctrlSmp::SmpResetCompo); - - // Set modflags. - m_SndFile.SetModFlag(MSF_MIDICC_BUGEMULATION, false); - m_SndFile.SetModFlag(MSF_OLDVOLSWING, false); - m_SndFile.SetModFlag(MSF_COMPATIBLE_PLAY, true); - - END_CRITICAL(); - EndWaitCursor(); - - UpdateAllViews(NULL, HINT_MODGENERAL, this); - - SetModified(); - return TRUE; -} - - BOOL CModDoc::AdjustEndOfSample(UINT nSample) //------------------------------------------- { @@ -2018,8 +1368,8 @@ } -bool CModDoc::MoveOrder(ORDERINDEX nSourceNdx, ORDERINDEX nDestNdx, bool bUpdate, bool bCopy) -//------------------------------------------------------------------------------------------- +bool CModDoc::MoveOrder(ORDERINDEX nSourceNdx, ORDERINDEX nDestNdx, bool bUpdate, bool bCopy, SEQUENCEINDEX nSourceSeq, SEQUENCEINDEX nDestSeq) +//--------------------------------------------------------------------------------------------------------------------------------------------- { if ((nSourceNdx >= m_SndFile.Order.size()) || (nDestNdx >= m_SndFile.Order.size())) return false; if (nDestNdx >= m_SndFile.GetModSpecifications().ordersMax) return false; Modified: trunk/OpenMPT/mptrack/dlg_misc.cpp =================================================================== --- trunk/OpenMPT/mptrack/dlg_misc.cpp 2009-10-04 18:13:30 UTC (rev 386) +++ trunk/OpenMPT/mptrack/dlg_misc.cpp 2009-10-05 17:02:19 UTC (rev 387) @@ -7,7 +7,6 @@ #include "ChildFrm.h" #include "vstplug.h" #include "ChannelManagerDlg.h" -#include ".\dlg_misc.h" #include "midi.h" #include "version.h" Modified: trunk/OpenMPT/mptrack/mptrack.rc =================================================================== --- trunk/OpenMPT/mptrack/mptrack.rc 2009-10-04 18:13:30 UTC (rev 386) +++ trunk/OpenMPT/mptrack/mptrack.rc 2009-10-05 17:02:19 UTC (rev 387) @@ -36,7 +36,30 @@ LTEXT "The following problems have been encountered when loading this module:",IDC_STATIC,6,6,237,8 END +IDD_CLEANUP_SONG DIALOGEX 0, 0, 298, 161 +STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | WS_POPUP | WS_CAPTION | WS_SYSMENU +CAPTION "Cleanup" +FONT 8, "MS Shell Dlg", 400, 0, 0x1 +BEGIN + DEFPUSHBUTTON "OK",IDOK,240,6,50,14 + PUSHBUTTON "Cancel",IDCANCEL,240,24,50,14 + GROUPBOX "Items to be cleaned up",IDC_STATIC,6,6,228,90 + CONTROL "Remove unused patterns",IDC_CHK_CLEANUP_PATTERNS,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,18,24,102,12 + CONTROL "Rearrange patterns",IDC_CHK_REARRANGE_PATTERNS,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,126,24,102,12 + CONTROL "Remove unused samples",IDC_CHK_CLEANUP_SAMPLES,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,18,42,102,12 + CONTROL "Rearrange samples",IDC_CHK_REARRANGE_SAMPLES,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,126,42,102,12 + CONTROL "Remove unused instruments",IDC_CHK_CLEANUP_INSTRUMENTS, + "Button",BS_AUTOCHECKBOX | WS_TABSTOP,18,60,102,12 + CONTROL "Remove all instruments",IDC_CHK_REMOVE_INSTRUMENTS, + "Button",BS_AUTOCHECKBOX | WS_TABSTOP,126,60,102,12 + CONTROL "Remove unused plugins",IDC_CHK_CLEANUP_PLUGINS,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,18,78,102,12 + CONTROL "Turn into samplepack",IDC_CHK_SAMPLEPACK,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,126,78,102,12 + GROUPBOX "Presets",IDC_STATIC,6,102,228,48 + PUSHBUTTON "Remove all unused stuff",IDC_BTN_CLEANUP_SONG,18,120,96,18 + PUSHBUTTON "Compo cleanup",IDC_BTN_COM... [truncated message content] |