From: <sag...@us...> - 2011-04-13 13:45:01
|
Revision: 851 http://modplug.svn.sourceforge.net/modplug/?rev=851&view=rev Author: saga-games Date: 2011-04-13 13:44:49 +0000 (Wed, 13 Apr 2011) Log Message: ----------- A whole ton of refacting! - ReArrangeChannels and MoveChannel have been moved to CModDoc - Many channel adding/removing functions have been rewritten to use ReArrangeChannels, to avoid all this mess of copypasta - Related changes to code and semantics (ReArrangeChannels returns CHANNELINDEX_INVALID on failure, changed CheckUnusedChannels() to CheckUsedChannels(), replaced big arrays with vectors, etc...) Modified Paths: -------------- trunk/OpenMPT/mptrack/ChannelManagerDlg.cpp trunk/OpenMPT/mptrack/Moddoc.cpp trunk/OpenMPT/mptrack/Moddoc.h trunk/OpenMPT/mptrack/Modedit.cpp trunk/OpenMPT/mptrack/View_pat.cpp trunk/OpenMPT/mptrack/View_pat.h trunk/OpenMPT/mptrack/dlg_misc.cpp trunk/OpenMPT/mptrack/dlg_misc.h trunk/OpenMPT/mptrack/test/test.cpp trunk/OpenMPT/soundlib/Sndfile.cpp trunk/OpenMPT/soundlib/Sndfile.h Modified: trunk/OpenMPT/mptrack/ChannelManagerDlg.cpp =================================================================== --- trunk/OpenMPT/mptrack/ChannelManagerDlg.cpp 2011-04-13 00:44:30 UTC (rev 850) +++ trunk/OpenMPT/mptrack/ChannelManagerDlg.cpp 2011-04-13 13:44:49 UTC (rev 851) @@ -200,11 +200,11 @@ { newChnOrder.push_back(newpat[nChn]); } - if(m_pSndFile->ReArrangeChannels(newChnOrder) != nChannels) + if(pModDoc->ReArrangeChannels(newChnOrder) != nChannels) { - MessageBox("Rearranging channels failed"); END_CRITICAL(); EndWaitCursor(); + MessageBox("Rearranging channels failed"); ResetState(true, true, true, true, true); LeaveCriticalSection(&applying); Modified: trunk/OpenMPT/mptrack/Moddoc.cpp =================================================================== --- trunk/OpenMPT/mptrack/Moddoc.cpp 2011-04-13 00:44:30 UTC (rev 850) +++ trunk/OpenMPT/mptrack/Moddoc.cpp 2011-04-13 13:44:49 UTC (rev 851) @@ -1491,7 +1491,7 @@ int nRenderPasses = 1; // Channel mode - bool unusedChannels[MAX_BASECHANNELS]; + vector<bool> usedChannels; vector<DWORD> channelFlags; // Instrument mode vector<bool> instrMuteState; @@ -1500,8 +1500,7 @@ if(wsdlg.m_bChannelMode) { // Don't save empty channels - memset(unusedChannels, false, sizeof(unusedChannels)); - CheckUnusedChannels(unusedChannels); + CheckUsedChannels(usedChannels); nRenderPasses = m_SndFile.GetNumChannels(); channelFlags.resize(nRenderPasses, 0); @@ -1510,7 +1509,7 @@ // Save channels' flags channelFlags[i] = m_SndFile.ChnSettings[i].dwFlags; // Ignore muted channels - if(channelFlags[i] & CHN_MUTE) unusedChannels[i] = true; + if(channelFlags[i] & CHN_MUTE) usedChannels[i] = false; // Mute each channel m_SndFile.ChnSettings[i].dwFlags |= CHN_MUTE; } @@ -1559,7 +1558,7 @@ if(i > 0) m_SndFile.ChnSettings[i - 1].dwFlags |= CHN_MUTE; // Was this channel actually muted? Don't process it then. - if(unusedChannels[i] == true) + if(usedChannels[i] == false) continue; // Add channel number & name (if available) to path string if(strlen(m_SndFile.ChnSettings[i].szName) > 0) Modified: trunk/OpenMPT/mptrack/Moddoc.h =================================================================== --- trunk/OpenMPT/mptrack/Moddoc.h 2011-04-13 00:44:30 UTC (rev 850) +++ trunk/OpenMPT/mptrack/Moddoc.h 2011-04-13 13:44:49 UTC (rev 851) @@ -274,8 +274,13 @@ // operations public: bool ChangeModType(MODTYPE wType); - bool ChangeNumChannels(UINT nNewChannels, const bool showCancelInRemoveDlg = true); + bool ChangeNumChannels(CHANNELINDEX nNewChannels, const bool showCancelInRemoveDlg = true); + CHANNELINDEX ReArrangeChannels(const vector<CHANNELINDEX> &fromToArray); + bool MoveChannel(CHANNELINDEX chn_from, CHANNELINDEX chn_to); + bool RemoveChannels(const vector<bool> &keepMask); + void CheckUsedChannels(vector<bool> &usedMask, CHANNELINDEX maxRemoveCount = MAX_BASECHANNELS) const; + bool ConvertInstrumentsToSamples(); UINT RemovePlugs(const bool (&keepMask)[MAX_MIXPLUGINS]); @@ -342,8 +347,6 @@ void LearnMacro(int macro, long param); void SetElapsedTime(ORDERINDEX nOrd, ROWINDEX nRow); - bool RemoveChannels(bool bChnMask[MAX_BASECHANNELS]); - bool RestartPosToPattern(); bool HasMPTHacks(const bool autofix = false); @@ -373,8 +376,6 @@ BOOL InitializeMod(); void* GetChildFrame(); //rewbs.customKeys - void CheckUnusedChannels(bool mask[MAX_BASECHANNELS], CHANNELINDEX maxRemoveCount = MAX_BASECHANNELS) const; - // Overrides // ClassWizard generated virtual function overrides //{{AFX_VIRTUAL(CModDoc) Modified: trunk/OpenMPT/mptrack/Modedit.cpp =================================================================== --- trunk/OpenMPT/mptrack/Modedit.cpp 2011-04-13 00:44:30 UTC (rev 850) +++ trunk/OpenMPT/mptrack/Modedit.cpp 2011-04-13 13:44:49 UTC (rev 851) @@ -32,156 +32,267 @@ } -// Change the number of channels -bool CModDoc::ChangeNumChannels(UINT nNewChannels, const bool showCancelInRemoveDlg) -//---------------------------------------------------------------------------------- +// Change the number of channels. +// Return true on success. +bool CModDoc::ChangeNumChannels(CHANNELINDEX nNewChannels, const bool showCancelInRemoveDlg) +//------------------------------------------------------------------------------------------ { const CHANNELINDEX maxChans = m_SndFile.GetModSpecifications().channelsMax; - if (nNewChannels > maxChans) { + if (nNewChannels > maxChans) + { CString error; error.Format("Error: Max number of channels for this file type is %d", maxChans); ::AfxMessageBox(error, MB_OK|MB_ICONEXCLAMATION); return false; } - if (nNewChannels == m_SndFile.m_nChannels) return false; - if (nNewChannels < m_SndFile.m_nChannels) + if (nNewChannels == GetNumChannels()) return false; + + if (nNewChannels < GetNumChannels()) { + // Remove channels UINT nChnToRemove = 0; CHANNELINDEX nFound = 0; //nNewChannels = 0 means user can choose how many channels to remove - if(nNewChannels > 0) { - nChnToRemove = m_SndFile.m_nChannels - nNewChannels; + if(nNewChannels > 0) + { + nChnToRemove = GetNumChannels() - nNewChannels; nFound = nChnToRemove; - } else { + } else + { nChnToRemove = 0; - nFound = m_SndFile.m_nChannels; + nFound = GetNumChannels(); } CRemoveChannelsDlg rem(&m_SndFile, nChnToRemove, showCancelInRemoveDlg); - CheckUnusedChannels(rem.m_bChnMask, nFound); + CheckUsedChannels(rem.m_bKeepMask, nFound); if (rem.DoModal() != IDOK) return false; // Removing selected channels - RemoveChannels(rem.m_bChnMask); + return RemoveChannels(rem.m_bKeepMask); } else { + // Increasing number of channels BeginWaitCursor(); - // Increasing number of channels - BEGIN_CRITICAL(); - for (UINT i=0; i<m_SndFile.Patterns.Size(); i++) if (m_SndFile.Patterns[i]) + vector<CHANNELINDEX> channels(nNewChannels, CHANNELINDEX_INVALID); + for(CHANNELINDEX nChn = 0; nChn < GetNumChannels(); nChn++) { - MODCOMMAND *p = m_SndFile.Patterns[i]; - MODCOMMAND *newp = CPattern::AllocatePattern(m_SndFile.Patterns[i].GetNumRows(), nNewChannels); - if (!newp) - { - END_CRITICAL(); - AddToLog("ERROR: Not enough memory to create new channels!\nPattern Data is corrupted!\n"); - return false; - } - for (UINT j=0; j<m_SndFile.Patterns[i].GetNumRows(); j++) - { - memcpy(&newp[j*nNewChannels], &p[j*m_SndFile.m_nChannels], m_SndFile.m_nChannels*sizeof(MODCOMMAND)); - } - m_SndFile.Patterns[i] = newp; - CPattern::FreePattern(p); + channels[nChn] = nChn; } - //if channel was removed before and is added again, mute status has to be unset! (bug 1814) - for (UINT i=m_SndFile.m_nChannels; i<nNewChannels; i++) + const bool success = (ReArrangeChannels(channels) == nNewChannels); + if(success) { - m_SndFile.InitChannel(i); + SetModified(); + UpdateAllViews(NULL, HINT_MODTYPE); } - - m_SndFile.m_nChannels = nNewChannels; - m_SndFile.SetupMODPanning(); - END_CRITICAL(); - EndWaitCursor(); + return success; } - SetModified(); - GetPatternUndo()->ClearUndo(); - UpdateAllViews(NULL, HINT_MODTYPE); - return true; } -bool CModDoc::RemoveChannels(bool m_bChnMask[MAX_BASECHANNELS]) -//--------------------------------------------------------- -//To remove all channels whose index corresponds to true value at m_bChnMask[] array. Code is almost non-modified copy of -//the code which was in CModDoc::ChangeNumChannels(UINT nNewChannels) - the only differences are the lines before -//BeginWaitCursor(), few lines in the end and that nNewChannels is renamed to nRemaningChannels. +// To remove all channels whose index corresponds to false in the keepMask vector. +// Return true on success. +bool CModDoc::RemoveChannels(const vector<bool> &keepMask) +//-------------------------------------------------------- { - UINT nRemainingChannels = 0; - //First calculating how many channels are to be left - UINT i = 0; - for(i = 0; i<m_SndFile.m_nChannels; i++) + UINT nRemainingChannels = 0; + //First calculating how many channels are to be left + for(CHANNELINDEX nChn = 0; nChn < GetNumChannels(); nChn++) + { + if(keepMask[nChn]) nRemainingChannels++; + } + if(nRemainingChannels == GetNumChannels() || nRemainingChannels < m_SndFile.GetModSpecifications().channelsMin) + { + CString str; + if(nRemainingChannels == GetNumChannels()) str.Format("No channels chosen to be removed."); + else str.Format("No removal done - channel number is already at minimum."); + CMainFrame::GetMainFrame()->MessageBox(str, "Remove channel", MB_OK | MB_ICONINFORMATION); + return false; + } + + BeginWaitCursor(); + // Create new channel order, with only channels from m_bChnMask left. + vector<CHANNELINDEX> channels(nRemainingChannels, 0); + CHANNELINDEX i = 0; + for(CHANNELINDEX nChn = 0; nChn < GetNumChannels(); nChn++) + { + if(keepMask[nChn]) { - if(!m_bChnMask[i]) nRemainingChannels++; + channels[i++] = nChn; } - if(nRemainingChannels == m_SndFile.m_nChannels || nRemainingChannels < m_SndFile.GetModSpecifications().channelsMin) - { - CString str; - if(nRemainingChannels == m_SndFile.m_nChannels) str.Format("No channels chosen to be removed."); - else str.Format("No removal done - channel number is already at minimum."); - CMainFrame::GetMainFrame()->MessageBox(str , "Remove channel", MB_OK | MB_ICONINFORMATION); - return false; - } + } + const bool success = (ReArrangeChannels(channels) == nRemainingChannels); + if(success) + { + SetModified(); + UpdateAllViews(NULL, HINT_MODTYPE); + } + EndWaitCursor(); + return success; - BeginWaitCursor(); - BEGIN_CRITICAL(); - for (i=0; i<m_SndFile.Patterns.Size(); i++) if (m_SndFile.Patterns[i]) +} + + +// Base code for adding, removing, moving and duplicating channels. Returns new number of channels on success, CHANNELINDEX_INVALID otherwise. +// The new channel vector can contain CHANNELINDEX_INVALID for adding new (empty) channels. +CHANNELINDEX CModDoc::ReArrangeChannels(const vector<CHANNELINDEX> &newOrder) +//--------------------------------------------------------------------------- +{ + //newOrder[i] tells which current channel should be placed to i:th position in + //the new order, or if i is not an index of current channels, then new channel is + //added to position i. If index of some current channel is missing from the + //newOrder-vector, then the channel gets removed. + + const CHANNELINDEX nRemainingChannels = static_cast<CHANNELINDEX>(newOrder.size()); + + if(nRemainingChannels > m_SndFile.GetModSpecifications().channelsMax || nRemainingChannels < m_SndFile.GetModSpecifications().channelsMin) + { + CString str; + str.Format(GetStrI18N(_TEXT("Can't apply change: Number of channels should be within [%u,%u]")), m_SndFile.GetModSpecifications().channelsMin, m_SndFile.GetModSpecifications().channelsMax); + CMainFrame::GetMainFrame()->MessageBox(str , "ReArrangeChannels", MB_OK | MB_ICONINFORMATION); + return CHANNELINDEX_INVALID; + } + + bool first = true; + if(nRemainingChannels != GetNumChannels()) + { + // For now, changing number of channels can't be undone + GetPatternUndo()->ClearUndo(); + } + + BEGIN_CRITICAL(); + for(PATTERNINDEX nPat = 0; nPat < m_SndFile.Patterns.Size(); nPat++) + { + if(m_SndFile.Patterns[nPat]) { - MODCOMMAND *p = m_SndFile.Patterns[i]; - MODCOMMAND *newp = CPattern::AllocatePattern(m_SndFile.Patterns[i].GetNumRows(), nRemainingChannels); - if (!newp) + if(nRemainingChannels == GetNumChannels()) { + GetPatternUndo()->PrepareUndo(nPat, 0, 0, GetNumChannels(), m_SndFile.Patterns[nPat].GetNumRows(), !first); + first = false; + } + + MODCOMMAND *p = m_SndFile.Patterns[nPat]; + MODCOMMAND *newp = CPattern::AllocatePattern(m_SndFile.Patterns[nPat].GetNumRows(), nRemainingChannels); + if(!newp) + { END_CRITICAL(); - AddToLog("ERROR: Not enough memory to resize patterns!\nPattern Data is corrupted!"); - return true; + CMainFrame::GetMainFrame()->MessageBox("ERROR: Pattern allocation failed in ReArrangechannels(...)" , "ReArrangeChannels", MB_OK | MB_ICONINFORMATION); + return CHANNELINDEX_INVALID; } MODCOMMAND *tmpsrc = p, *tmpdest = newp; - for (UINT j=0; j<m_SndFile.Patterns[i].GetNumRows(); j++) + for(ROWINDEX nRow = 0; nRow < m_SndFile.Patterns[nPat].GetNumRows(); nRow++) //Scrolling rows { - for (UINT k=0; k<m_SndFile.m_nChannels; k++, tmpsrc++) + for(CHANNELINDEX nChn = 0; nChn < nRemainingChannels; nChn++, tmpdest++) //Scrolling channels. { - if (!m_bChnMask[k]) *tmpdest++ = *tmpsrc; + if(newOrder[nChn] < GetNumChannels()) //Case: getting old channel to the new channel order. + *tmpdest = tmpsrc[nRow * GetNumChannels() + newOrder[nChn]]; + else //Case: figure newOrder[k] is not the index of any current channel, so adding a new channel. + *tmpdest = MODCOMMAND::Empty(); + } } - m_SndFile.Patterns[i] = newp; + m_SndFile.Patterns[nPat] = newp; CPattern::FreePattern(p); } - UINT tmpchn = 0; - for (i=0; i<m_SndFile.m_nChannels; i++) + } + + MODCHANNEL chns[MAX_BASECHANNELS]; + MODCHANNELSETTINGS settings[MAX_BASECHANNELS]; + vector<UINT> recordStates(GetNumChannels(), 0); + vector<bool> chnMutePendings(GetNumChannels(), false); + + for(CHANNELINDEX nChn = 0; nChn < GetNumChannels(); nChn++) + { + settings[nChn] = m_SndFile.ChnSettings[nChn]; + chns[nChn] = m_SndFile.Chn[nChn]; + recordStates[nChn] = IsChannelRecord(nChn); + chnMutePendings[nChn] = m_SndFile.m_bChannelMuteTogglePending[nChn]; + } + + ReinitRecordState(); + + for(CHANNELINDEX nChn = 0; nChn < nRemainingChannels; nChn++) + { + if(newOrder[nChn] < GetNumChannels()) { - if (!m_bChnMask[i]) - { - if (tmpchn != i) - { - m_SndFile.ChnSettings[tmpchn] = m_SndFile.ChnSettings[i]; - m_SndFile.Chn[tmpchn] = m_SndFile.Chn[i]; - } - tmpchn++; - } else - { - if (i >= nRemainingChannels) - { - m_SndFile.InitChannel(i); - m_SndFile.Chn[i].dwFlags |= CHN_MUTE; - } - } + m_SndFile.ChnSettings[nChn] = settings[newOrder[nChn]]; + m_SndFile.Chn[nChn] = chns[newOrder[nChn]]; + if(recordStates[newOrder[nChn]] == 1) Record1Channel(nChn, true); + if(recordStates[newOrder[nChn]] == 2) Record2Channel(nChn, true); + m_SndFile.m_bChannelMuteTogglePending[nChn] = chnMutePendings[newOrder[nChn]]; } - m_SndFile.m_nChannels = nRemainingChannels; - END_CRITICAL(); - EndWaitCursor(); - SetModified(); - GetPatternUndo()->ClearUndo(); - UpdateAllViews(NULL, HINT_MODTYPE); - return false; + else + { + m_SndFile.InitChannel(nChn); + } + } + // Reset MOD panning (won't affect other module formats) + m_SndFile.SetupMODPanning(); + + m_SndFile.m_nChannels = nRemainingChannels; + + // Reset removed channels. Most notably, clear the channel name. + for(CHANNELINDEX nChn = GetNumChannels(); nChn < MAX_BASECHANNELS; nChn++) + { + m_SndFile.InitChannel(nChn); + m_SndFile.Chn[nChn].dwFlags |= CHN_MUTE; + } + + END_CRITICAL(); + + return GetNumChannels(); } +bool CModDoc::MoveChannel(CHANNELINDEX chnFrom, CHANNELINDEX chnTo) +//----------------------------------------------------------------- +{ + //Implementation of move channel using ReArrangeChannels(...). So this function + //only creates correct newOrder-vector used in the ReArrangeChannels(...). + if(chnFrom == chnTo) return false; + if(chnFrom >= GetNumChannels() || chnTo >= GetNumChannels()) + { + CString str = "Error: Bad move indexes in CSoundFile::MoveChannel(...)"; + CMainFrame::GetMainFrame()->MessageBox(str , "MoveChannel(...)", MB_OK | MB_ICONINFORMATION); + return true; + } + vector<CHANNELINDEX> newOrder; + //First creating new order identical to current order... + for(CHANNELINDEX i = 0; i < GetNumChannels(); i++) + { + newOrder.push_back(i); + } + //...and then add the move channel effect. + if(chnFrom < chnTo) + { + CHANNELINDEX temp = newOrder[chnFrom]; + for(UINT i = chnFrom; i < chnTo; i++) + { + newOrder[i] = newOrder[i + 1]; + } + newOrder[chnTo] = temp; + } + else //case chnFrom > chnTo(can't be equal, since it has been examined earlier.) + { + CHANNELINDEX temp = newOrder[chnFrom]; + for(UINT i = chnFrom; i >= chnTo + 1; i--) + { + newOrder[i] = newOrder[i - 1]; + } + newOrder[chnTo] = temp; + } + + if(newOrder.size() != ReArrangeChannels(newOrder)) + { + CMainFrame::GetMainFrame()->MessageBox("BUG: Channel number changed in MoveChannel()" , "", MB_OK | MB_ICONINFORMATION); + } + return false; +} + + // Functor for converting instrument numbers to sample numbers in the patterns struct ConvertInstrumentsToSamplesInPatterns //========================================== @@ -1230,15 +1341,16 @@ // Check which channels contain note data. maxRemoveCount specified how many empty channels are reported at max. -void CModDoc::CheckUnusedChannels(bool mask[MAX_BASECHANNELS], CHANNELINDEX maxRemoveCount) const -//----------------------------------------------------------------------------------------------- +void CModDoc::CheckUsedChannels(vector<bool> &usedMask, CHANNELINDEX maxRemoveCount) const +//---------------------------------------------------------------------------------------- { // Checking for unused channels - const int nChannels = m_SndFile.GetNumChannels(); + const int nChannels = GetNumChannels(); + usedMask.resize(nChannels); for(int iRst = nChannels - 1; iRst >= 0; iRst--) { - mask[iRst] = IsChannelUnused(iRst); - if(mask[iRst]) + usedMask[iRst] = !IsChannelUnused(iRst); + if(!usedMask[iRst]) { // Found enough empty channels yet? if((--maxRemoveCount) == 0) break; @@ -1251,7 +1363,7 @@ bool CModDoc::IsChannelUnused(CHANNELINDEX nChn) const //---------------------------------------------------- { - const CHANNELINDEX nChannels = m_SndFile.GetNumChannels(); + const CHANNELINDEX nChannels = GetNumChannels(); if(nChn >= nChannels) { return true; Modified: trunk/OpenMPT/mptrack/View_pat.cpp =================================================================== --- trunk/OpenMPT/mptrack/View_pat.cpp 2011-04-13 00:44:30 UTC (rev 850) +++ trunk/OpenMPT/mptrack/View_pat.cpp 2011-04-13 13:44:49 UTC (rev 851) @@ -1127,8 +1127,6 @@ const bool bItemSelected = m_bInItemRect || ((m_nDragItem & DRAGITEM_MASK) == DRAGITEM_CHNHEADER); if (/*(!m_bDragging) ||*/ (!pModDoc)) return; - CSoundFile *pSndFile = pModDoc->GetSoundFile(); - m_bDragging = false; m_bInItemRect = false; ReleaseCapture(); @@ -1187,18 +1185,18 @@ pModDoc->MuteChannel(nItemNo, !pModDoc->IsChannelMuted(nItemNo)); pModDoc->UpdateAllViews(this, HINT_MODCHANNELS | ((nItemNo / CHANNELS_IN_TAB) << HINT_SHIFT_CHNTAB)); } - } else if(nTargetNo < pSndFile->GetNumChannels()) + } else if(nTargetNo < pModDoc->GetNumChannels()) { // Dragged to other channel header => move or copy channel InvalidateRect(&m_rcDropItem, FALSE); const bool duplicate = (nFlags & MK_SHIFT) ? true : false; - vector<CHANNELINDEX> channels(pSndFile->GetNumChannels() + (duplicate ? 1 : 0), 0); + vector<CHANNELINDEX> channels(pModDoc->GetNumChannels() + (duplicate ? 1 : 0), 0); CHANNELINDEX i = 0; bool modified = duplicate; - for(CHANNELINDEX nChn = 0; nChn < pSndFile->GetNumChannels(); nChn++) + for(CHANNELINDEX nChn = 0; nChn < pModDoc->GetNumChannels(); nChn++) { if(nChn == nTargetNo) { @@ -1217,7 +1215,7 @@ modified = true; } } - if(modified && pSndFile->ReArrangeChannels(channels) != 0) + if(modified && pModDoc->ReArrangeChannels(channels) != CHANNELINDEX_INVALID) { if(duplicate) { @@ -2671,15 +2669,17 @@ SetSelectionInstrument(GetCurrentInstrument()); } + void CViewPattern::OnRemoveChannelDialog() //---------------------------------------- { CModDoc *pModDoc = GetDocument(); - if(pModDoc == 0) return; + if(pModDoc == nullptr) return; pModDoc->ChangeNumChannels(0); SetCurrentPattern(m_nPattern); //Updating the screen. } + void CViewPattern::OnRemoveChannel() //---------------------------------- { @@ -2700,33 +2700,35 @@ str.Format("Remove channel %d? This channel still contains note data!\nNote: Operation affects all patterns and has no undo", nChn + 1); if(isEmpty || CMainFrame::GetMainFrame()->MessageBox(str , "Remove channel", MB_YESNO | MB_ICONQUESTION) == IDYES) { - bool chnMask[MAX_BASECHANNELS]; - for(CHANNELINDEX i = 0; i < MAX_BASECHANNELS; i++) {chnMask[i] = false;} - chnMask[nChn] = TRUE; - pModDoc->RemoveChannels(chnMask); + vector<bool> keepMask(pModDoc->GetNumChannels(), true); + keepMask[nChn] = false; + pModDoc->RemoveChannels(keepMask); SetCurrentPattern(m_nPattern); //Updating the screen. } } -void CViewPattern::OnAddChannelFront() -//------------------------------------ +void CViewPattern::AddChannelBefore(CHANNELINDEX nBefore) +//------------------------------------------------------- { - UINT nChn = GetChanFromCursor(m_nMenuParam); CModDoc *pModDoc = GetDocument(); - CSoundFile* pSndFile; - if (pModDoc == 0 || (pSndFile = pModDoc->GetSoundFile()) == 0) return; + if(pModDoc == nullptr) return; BeginWaitCursor(); - //First adding channel as the last channel... - if (pModDoc->ChangeNumChannels(pSndFile->m_nChannels + 1)) + // Create new channel order, with channel nBefore being an invalid (and thus empty) channel. + vector<CHANNELINDEX> channels(pModDoc->GetNumChannels() + 1, CHANNELINDEX_INVALID); + CHANNELINDEX i = 0; + for(CHANNELINDEX nChn = 0; nChn < pModDoc->GetNumChannels() + 1; nChn++) { - pSndFile->InitChannel(pSndFile->m_nChannels-1); - //...and then moving it to right position. - pSndFile->MoveChannel(pSndFile->m_nChannels-1, nChn); + if(nChn != nBefore) + { + channels[nChn] = i++; + } + } + if (pModDoc->ReArrangeChannels(channels) != CHANNELINDEX_INVALID) + { pModDoc->SetModified(); - pModDoc->GetPatternUndo()->ClearUndo(); pModDoc->UpdateAllViews(NULL, HINT_MODCHANNELS); //refresh channel headers pModDoc->UpdateAllViews(NULL, HINT_MODTYPE); //updates(?) the channel number to general tab display SetCurrentPattern(m_nPattern); @@ -2735,70 +2737,45 @@ } -void CViewPattern::OnAddChannelAfter() -//------------------------------------ -{ - UINT nChn = ((m_nMenuParam&0xFFFF)>>3)+1; - CModDoc *pModDoc = GetDocument(); - CSoundFile* pSndFile; - if (pModDoc == 0 || (pSndFile = pModDoc->GetSoundFile()) == 0) return; - - BeginWaitCursor(); - if (pModDoc->ChangeNumChannels(pSndFile->m_nChannels + 1)) - { - pSndFile->InitChannel(pSndFile->m_nChannels-1); - pSndFile->MoveChannel(pSndFile->m_nChannels-1, nChn); - - pModDoc->SetModified(); - pModDoc->GetPatternUndo()->ClearUndo(); - pModDoc->UpdateAllViews(NULL, HINT_MODCHANNELS); - pModDoc->UpdateAllViews(NULL, HINT_MODTYPE); - SetCurrentPattern(m_nPattern); - } - EndWaitCursor(); -} - void CViewPattern::OnDuplicateChannel() //------------------------------------ { CModDoc *pModDoc = GetDocument(); - CSoundFile* pSndFile; - if (pModDoc == 0 || (pSndFile = pModDoc->GetSoundFile()) == 0) - return; + if (pModDoc == nullptr) return; if(AfxMessageBox(GetStrI18N(_TEXT("This affects all patterns, proceed?")), MB_YESNO) != IDYES) return; const CHANNELINDEX nDupChn = GetChanFromCursor(m_nMenuParam); - if(nDupChn >= pSndFile->GetNumChannels()) + if(nDupChn >= pModDoc->GetNumChannels()) return; - CHANNELINDEX nNumChnNew = pSndFile->GetNumChannels()+1; - // Create vector {0, 1,..., n-1, n, n, n+1, n+2, ..., nNumChnNew-2), where n = nDupChn. - vector<CHANNELINDEX> vecChns(nNumChnNew); + BeginWaitCursor(); + // Create new channel order, with channel nDupChn duplicated. + vector<CHANNELINDEX> channels(pModDoc->GetNumChannels() + 1, 0); CHANNELINDEX i = 0; - for(i = 0; i<nDupChn+1; i++) - vecChns[i] = i; - vecChns[i] = nDupChn; - i++; - for(; i<nNumChnNew; i++) - vecChns[i] = i-1; + for(CHANNELINDEX nChn = 0; nChn < pModDoc->GetNumChannels() + 1; nChn++) + { + channels[nChn] = i; + if(nChn != nDupChn) + { + i++; + } + } - nNumChnNew = pSndFile->ReArrangeChannels(vecChns); - // Check that duplication happened and in that case update. - if(nNumChnNew == vecChns.size()) + if(pModDoc->ReArrangeChannels(channels) != CHANNELINDEX_INVALID) { pModDoc->SetModified(); pModDoc->UpdateAllViews(NULL, HINT_MODCHANNELS); pModDoc->UpdateAllViews(NULL, HINT_MODTYPE); SetCurrentPattern(m_nPattern); } - + EndWaitCursor(); } void CViewPattern::OnRunScript() -//-------------------------------- +//------------------------------ { ; } Modified: trunk/OpenMPT/mptrack/View_pat.h =================================================================== --- trunk/OpenMPT/mptrack/View_pat.h 2011-04-13 00:44:30 UTC (rev 850) +++ trunk/OpenMPT/mptrack/View_pat.h 2011-04-13 13:44:49 UTC (rev 851) @@ -315,8 +315,8 @@ afx_msg void OnTransposeOctUp(); afx_msg void OnTransposeOctDown(); afx_msg void OnSetSelInstrument(); - afx_msg void OnAddChannelFront(); - afx_msg void OnAddChannelAfter(); + afx_msg void OnAddChannelFront() { AddChannelBefore(GetChanFromCursor(m_nMenuParam)); } + afx_msg void OnAddChannelAfter() { AddChannelBefore(GetChanFromCursor(m_nMenuParam) + 1); }; afx_msg void OnDuplicateChannel(); afx_msg void OnRemoveChannel(); afx_msg void OnRemoveChannelDialog(); @@ -406,6 +406,9 @@ // Play one pattern row and stop ("step mode") void PatternStep(bool autoStep); + // Add a channel. + void AddChannelBefore(CHANNELINDEX nBefore); + public: afx_msg void OnRButtonDblClk(UINT nFlags, CPoint point); private: Modified: trunk/OpenMPT/mptrack/dlg_misc.cpp =================================================================== --- trunk/OpenMPT/mptrack/dlg_misc.cpp 2011-04-13 00:44:30 UTC (rev 850) +++ trunk/OpenMPT/mptrack/dlg_misc.cpp 2011-04-13 13:44:49 UTC (rev 851) @@ -570,7 +570,7 @@ wsprintf(label, "Channel %d", n + 1); m_RemChansList.SetItemData(m_RemChansList.AddString(label), n); - if (m_bChnMask[n]) m_RemChansList.SetSel(n); + if (!m_bKeepMask[n]) m_RemChansList.SetSel(n); } if (m_nRemove > 0) { @@ -590,15 +590,15 @@ void CRemoveChannelsDlg::OnOK() //----------------------------- { - memset(m_bChnMask, false, sizeof(m_bChnMask)); int nCount = m_RemChansList.GetSelCount(); CArray<int,int> aryListBoxSel; aryListBoxSel.SetSize(nCount); m_RemChansList.GetSelItems(nCount, aryListBoxSel.GetData()); - for (int n=0; n<nCount; n++) + m_bKeepMask.assign(m_nChannels, true); + for (int n = 0; n < nCount; n++) { - m_bChnMask[aryListBoxSel[n]] = true; + m_bKeepMask[aryListBoxSel[n]] = false; } if ((static_cast<UINT>(nCount) == m_nRemove && nCount > 0) || (m_nRemove == 0 && (m_pSndFile->GetNumChannels() >= nCount + m_pSndFile->GetModSpecifications().channelsMin))) CDialog::OnOK(); Modified: trunk/OpenMPT/mptrack/dlg_misc.h =================================================================== --- trunk/OpenMPT/mptrack/dlg_misc.h 2011-04-13 00:44:30 UTC (rev 850) +++ trunk/OpenMPT/mptrack/dlg_misc.h 2011-04-13 13:44:49 UTC (rev 851) @@ -84,17 +84,17 @@ { public: CSoundFile *m_pSndFile; - bool m_bChnMask[MAX_BASECHANNELS]; - UINT m_nChannels, m_nRemove; + vector<bool> m_bKeepMask; + CHANNELINDEX m_nChannels, m_nRemove; CListBox m_RemChansList; //rewbs.removeChansDlgCleanup bool m_ShowCancel; public: - CRemoveChannelsDlg(CSoundFile *pSndFile, UINT nChns, bool showCancel = true, CWnd *parent=NULL):CDialog(IDD_REMOVECHANNELS, parent) + CRemoveChannelsDlg(CSoundFile *pSndFile, CHANNELINDEX nChns, bool showCancel = true, CWnd *parent=NULL):CDialog(IDD_REMOVECHANNELS, parent) { m_pSndFile = pSndFile; - m_nChannels = m_pSndFile->m_nChannels; - m_nRemove = nChns; - memset(m_bChnMask, false, sizeof(m_bChnMask)); + m_nChannels = m_pSndFile->GetNumChannels(); + m_nRemove = nChns; + m_bKeepMask.assign(m_nChannels, true); m_ShowCancel = showCancel; } Modified: trunk/OpenMPT/mptrack/test/test.cpp =================================================================== --- trunk/OpenMPT/mptrack/test/test.cpp 2011-04-13 00:44:30 UTC (rev 850) +++ trunk/OpenMPT/mptrack/test/test.cpp 2011-04-13 13:44:49 UTC (rev 851) @@ -239,16 +239,16 @@ CMainFrame* pMainFrm = CMainFrame::GetMainFrame(); if(pMainFrm == nullptr) throw(std::runtime_error("pMainFrm is nullptr")); - CModDoc* pModdoc = pMainFrm->GetActiveDoc(); - if(pModdoc == nullptr) + CModDoc* pModDoc = pMainFrm->GetActiveDoc(); + if(pModDoc == nullptr) throw(std::runtime_error("pModdoc is nullptr")); - CSoundFile* pSndFile = pModdoc->GetSoundFile(); + CSoundFile* pSndFile = pModDoc->GetSoundFile(); if(pSndFile == nullptr) throw(std::runtime_error("pSndFile is nullptr")); // Set maximum number of channels. - pSndFile->ReArrangeChannels(std::vector<CHANNELINDEX>(ModSpecs::mptm.channelsMax , 0)); + pModDoc->ReArrangeChannels(std::vector<CHANNELINDEX>(ModSpecs::mptm.channelsMax , 0)); pSndFile->Patterns.Remove(0); pSndFile->Patterns.Insert(0, ModSpecs::mptm.patternRowsMin); @@ -305,7 +305,7 @@ VERIFY_EQUAL( bPatternDataMatch, true); } - pModdoc->OnCloseDocument(); + pModDoc->OnCloseDocument(); } Modified: trunk/OpenMPT/soundlib/Sndfile.cpp =================================================================== --- trunk/OpenMPT/soundlib/Sndfile.cpp 2011-04-13 00:44:30 UTC (rev 850) +++ trunk/OpenMPT/soundlib/Sndfile.cpp 2011-04-13 13:44:49 UTC (rev 851) @@ -1505,166 +1505,6 @@ } -CHANNELINDEX CSoundFile::ReArrangeChannels(const vector<CHANNELINDEX>& newOrder) -//------------------------------------------------------------------------------ -{ - //newOrder[i] tells which current channel should be placed to i:th position in - //the new order, or if i is not an index of current channels, then new channel is - //added to position i. If index of some current channel is missing from the - //newOrder-vector, then the channel gets removed. - - const CHANNELINDEX nRemainingChannels = static_cast<CHANNELINDEX>(newOrder.size()); - - if(nRemainingChannels > GetModSpecifications().channelsMax || nRemainingChannels < GetModSpecifications().channelsMin) - { - CString str; - str.Format(GetStrI18N(_TEXT("Can't apply change: Number of channels should be within [%u,%u]")), GetModSpecifications().channelsMin, GetModSpecifications().channelsMax); - CMainFrame::GetMainFrame()->MessageBox(str , "ReArrangeChannels", MB_OK | MB_ICONINFORMATION); - return 0; - } - - CModDoc *pModDoc = GetpModDoc(); - bool first = true; - if(pModDoc != nullptr && nRemainingChannels != GetNumChannels()) - { - // For now, changing number of channels can't be undone - pModDoc->GetPatternUndo()->ClearUndo(); - } - - BEGIN_CRITICAL(); - for (PATTERNINDEX nPat = 0; nPat < Patterns.Size(); nPat++) - { - if (Patterns[nPat]) - { - if(pModDoc != nullptr && nRemainingChannels == GetNumChannels()) - { - pModDoc->GetPatternUndo()->PrepareUndo(nPat, 0, 0, GetNumChannels(), Patterns[nPat].GetNumRows(), !first); - first = false; - } - - MODCOMMAND *p = Patterns[nPat]; - MODCOMMAND *newp = CPattern::AllocatePattern(Patterns[nPat].GetNumRows(), nRemainingChannels); - if (!newp) - { - END_CRITICAL(); - CMainFrame::GetMainFrame()->MessageBox("ERROR: Pattern allocation failed in ReArrangechannels(...)" , "ReArrangeChannels", MB_OK | MB_ICONINFORMATION); - return 0; - } - MODCOMMAND *tmpsrc = p, *tmpdest = newp; - for (ROWINDEX nRow = 0; nRow<Patterns[nPat].GetNumRows(); nRow++) //Scrolling rows - { - for (CHANNELINDEX nChn = 0; nChn < nRemainingChannels; nChn++, tmpdest++) //Scrolling channels. - { - if(newOrder[nChn] < m_nChannels) //Case: getting old channel to the new channel order. - *tmpdest = tmpsrc[nRow*m_nChannels+newOrder[nChn]]; - else //Case: figure newOrder[k] is not the index of any current channel, so adding a new channel. - *tmpdest = MODCOMMAND::Empty(); - - } - } - Patterns[nPat] = newp; - CPattern::FreePattern(p); - } - } - - MODCHANNELSETTINGS settings[MAX_BASECHANNELS]; - MODCHANNEL chns[MAX_BASECHANNELS]; - UINT recordStates[MAX_BASECHANNELS]; - bool chnMutePendings[MAX_BASECHANNELS]; - - for(CHANNELINDEX nChn = 0; nChn < m_nChannels; nChn++) - { - settings[nChn] = ChnSettings[nChn]; - chns[nChn] = Chn[nChn]; - if(m_pModDoc) - recordStates[nChn] = m_pModDoc->IsChannelRecord(nChn); - chnMutePendings[nChn] = m_bChannelMuteTogglePending[nChn]; - } - - if(m_pModDoc) - m_pModDoc->ReinitRecordState(); - - for (CHANNELINDEX nChn = 0; nChn < nRemainingChannels; nChn++) - { - if(newOrder[nChn] < m_nChannels) - { - ChnSettings[nChn] = settings[newOrder[nChn]]; - Chn[nChn] = chns[newOrder[nChn]]; - if(m_pModDoc) - { - if(recordStates[newOrder[nChn]] == 1) m_pModDoc->Record1Channel(nChn, true); - if(recordStates[newOrder[nChn]] == 2) m_pModDoc->Record2Channel(nChn, true); - } - m_bChannelMuteTogglePending[nChn] = chnMutePendings[newOrder[nChn]]; - } - else - { - InitChannel(nChn); - } - } - // Reset MOD panning (won't affect other module formats) - SetupMODPanning(); - - m_nChannels = nRemainingChannels; - - // Reset removed channels. Most notably, clear the channel name. - for(CHANNELINDEX nChn = m_nChannels; nChn < MAX_BASECHANNELS; nChn++) - { - InitChannel(nChn); - Chn[nChn].dwFlags |= CHN_MUTE; - } - - END_CRITICAL(); - - return static_cast<CHANNELINDEX>(m_nChannels); -} - -bool CSoundFile::MoveChannel(UINT chnFrom, UINT chnTo) -//---------------------------------------------------- -{ - //Implementation of move channel using ReArrangeChannels(...). So this function - //only creates correct newOrder-vector used in the ReArrangeChannels(...). - if(chnFrom == chnTo) return false; - if(chnFrom >= m_nChannels || chnTo >= m_nChannels) - { - CString str = "Error: Bad move indexes in CSoundFile::MoveChannel(...)"; - CMainFrame::GetMainFrame()->MessageBox(str , "MoveChannel(...)", MB_OK | MB_ICONINFORMATION); - return true; - } - vector<CHANNELINDEX> newOrder; - //First creating new order identical to current order... - for(CHANNELINDEX i = 0; i<GetNumChannels(); i++) - { - newOrder.push_back(i); - } - //...and then add the move channel effect. - if(chnFrom < chnTo) - { - CHANNELINDEX temp = newOrder[chnFrom]; - for(UINT i = chnFrom; i<chnTo; i++) - { - newOrder[i] = newOrder[i+1]; - } - newOrder[chnTo] = temp; - } - else //case chnFrom > chnTo(can't be equal, since it has been examined earlier.) - { - CHANNELINDEX temp = newOrder[chnFrom]; - for(UINT i = chnFrom; i>=chnTo+1; i--) - { - newOrder[i] = newOrder[i-1]; - } - newOrder[chnTo] = temp; - } - - if(newOrder.size() != ReArrangeChannels(newOrder)) - { - CMainFrame::GetMainFrame()->MessageBox("BUG: Channel number changed in MoveChannel()" , "", MB_OK | MB_ICONINFORMATION); - } - return false; -} - - #ifndef NO_PACKING UINT CSoundFile::PackSample(int &sample, int next) //------------------------------------------------ Modified: trunk/OpenMPT/soundlib/Sndfile.h =================================================================== --- trunk/OpenMPT/soundlib/Sndfile.h 2011-04-13 00:44:30 UTC (rev 850) +++ trunk/OpenMPT/soundlib/Sndfile.h 2011-04-13 13:44:49 UTC (rev 851) @@ -740,8 +740,6 @@ void CheckCPUUsage(UINT nCPU); BOOL SetPatternName(PATTERNINDEX nPat, LPCSTR lpszName); BOOL GetPatternName(PATTERNINDEX nPat, LPSTR lpszName, UINT cbSize=MAX_PATTERNNAME) const; - CHANNELINDEX ReArrangeChannels(const vector<CHANNELINDEX>& fromToArray); - bool MoveChannel(UINT chn_from, UINT chn_to); void SetupITBidiMode(); This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |