From: <rel...@us...> - 2010-04-18 14:46:51
|
Revision: 570 http://modplug.svn.sourceforge.net/modplug/?rev=570&view=rev Author: relabsoluness Date: 2010-04-18 14:46:44 +0000 (Sun, 18 Apr 2010) Log Message: ----------- [Fix] Mod conversion: Merging multiple sequences didn't properly convert '---'/'+++' orders. [Fix] Mod cleanup: Merging sequences could truncate the result sequence to length 256 even for MPTM files (bug introduced in r568). [Ref] Some refactoring and minor fixing(e.g. moved some mod conversion code that modifies sequences to ModSequence classes). Modified Paths: -------------- trunk/OpenMPT/mptrack/CleanupSong.cpp trunk/OpenMPT/mptrack/Ctrl_seq.cpp trunk/OpenMPT/mptrack/Moddoc.h trunk/OpenMPT/mptrack/Modedit.cpp trunk/OpenMPT/mptrack/View_tre.cpp trunk/OpenMPT/soundlib/ModSequence.cpp trunk/OpenMPT/soundlib/ModSequence.h trunk/OpenMPT/soundlib/Sndfile.cpp Modified: trunk/OpenMPT/mptrack/CleanupSong.cpp =================================================================== --- trunk/OpenMPT/mptrack/CleanupSong.cpp 2010-04-17 13:14:48 UTC (rev 569) +++ trunk/OpenMPT/mptrack/CleanupSong.cpp 2010-04-18 14:46:44 UTC (rev 570) @@ -1044,9 +1044,9 @@ return true; } -// Remove all plugins + bool CModCleanupDlg::MergeSequences() //----------------------------------- { - return m_pModDoc->MergeSequences(); + return m_pModDoc->GetSoundFile()->Order.MergeSequences(); } Modified: trunk/OpenMPT/mptrack/Ctrl_seq.cpp =================================================================== --- trunk/OpenMPT/mptrack/Ctrl_seq.cpp 2010-04-17 13:14:48 UTC (rev 569) +++ trunk/OpenMPT/mptrack/Ctrl_seq.cpp 2010-04-18 14:46:44 UTC (rev 570) @@ -1374,7 +1374,7 @@ CSoundFile& rSf = *m_pModDoc->GetSoundFile(); if (nSeq == MAX_SEQUENCES + 2) { - CString strParam; strParam.Format(TEXT("%u: %s"), rSf.Order.GetCurrentSequenceIndex(), rSf.Order.m_sName); + CString strParam; strParam.Format(TEXT("%u: %s"), rSf.Order.GetCurrentSequenceIndex(), (LPCTSTR)rSf.Order.m_sName); CString str; AfxFormatString1(str, IDS_CONFIRM_SEQUENCE_DELETE, strParam); if (AfxMessageBox(str, MB_YESNO | MB_ICONQUESTION) == IDYES) Modified: trunk/OpenMPT/mptrack/Moddoc.h =================================================================== --- trunk/OpenMPT/mptrack/Moddoc.h 2010-04-17 13:14:48 UTC (rev 569) +++ trunk/OpenMPT/mptrack/Moddoc.h 2010-04-18 14:46:44 UTC (rev 570) @@ -289,9 +289,6 @@ BOOL RemoveChannels(BOOL bChnMask[MAX_CHANNELS]); - bool MergeSequences(); - bool ConvertSubsongsToMultipleSequences(); - bool HasMPTHacks(bool autofix = false); bool m_bHasValidPath; //becomes true if document is loaded or saved. Modified: trunk/OpenMPT/mptrack/Modedit.cpp =================================================================== --- trunk/OpenMPT/mptrack/Modedit.cpp 2010-04-17 13:14:48 UTC (rev 569) +++ trunk/OpenMPT/mptrack/Modedit.cpp 2010-04-18 14:46:44 UTC (rev 570) @@ -324,38 +324,6 @@ } } - // Order list too long? -> remove unnecessary order items first. - if(m_SndFile.Order.GetLengthTailTrimmed() > specs.ordersMax) - { - for(ORDERINDEX nOrd = m_SndFile.Order.GetLengthTailTrimmed() - 1; nOrd > 0; nOrd--) - { - if(m_SndFile.Patterns.IsValidPat(m_SndFile.Order[nOrd]) == false) - { - for(ORDERINDEX nMoveOrd = nOrd; nMoveOrd < m_SndFile.Order.GetLengthTailTrimmed() - 1; nMoveOrd++) - { - m_SndFile.Order[nMoveOrd] = m_SndFile.Order[nMoveOrd + 1]; - } - m_SndFile.Order[m_SndFile.Order.GetLengthTailTrimmed() - 1] = m_SndFile.Order.GetInvalidPatIndex(); - } - } - if(m_SndFile.Order.GetLengthTailTrimmed() > specs.ordersMax) - { - AddToLog("WARNING: Order list has been trimmed!\n"); - } - } - - // If not supported, remove "+++" separator order items. - if(CSoundFile::GetModSpecifications(nNewType).hasIgnoreIndex == false) - { - for(ORDERINDEX nOrd = m_SndFile.Order.GetLengthTailTrimmed() - 1; nOrd > 0; nOrd--) - { - if(m_SndFile.Order[nOrd] == m_SndFile.Order.GetIgnoreIndex()) - { - m_SndFile.Order.Remove(nOrd, nOrd); - } - } - } - // Is the "restart position" value allowed in this format? if(m_SndFile.m_nRestartPos > 0 && !CSoundFile::GetModSpecifications(nNewType).hasRestartPos) { @@ -391,29 +359,6 @@ END_CRITICAL(); ChangeFileExtension(nNewType); - // Multisequences not suppported by other formats - if(m_SndFile.GetType() != MOD_TYPE_MPT) MergeSequences(); - // Convert sequence with separator patterns into multiple sequences? - if(m_SndFile.GetType() == MOD_TYPE_MPT && m_SndFile.Order.GetNumSequences() == 1) - { - bool hasSepPatterns = false; - for(ORDERINDEX nOrd = 0; nOrd < m_SndFile.Order.GetLengthTailTrimmed(); nOrd++) - { - if(!m_SndFile.Patterns.IsValidIndex(m_SndFile.Order[nOrd])) - { - hasSepPatterns = true; - break; - } - } - if(hasSepPatterns && - ::MessageBox(NULL, - "The order list contains separator items.\nThe new format supports multiple sequences, do you want to convert those separate tracks into multiple song sequences?", - "Order list conversion", MB_YESNO | MB_ICONQUESTION) == IDYES) - { - ConvertSubsongsToMultipleSequences(); - } - } - //rewbs.cutomKeys: update effect key commands CInputHandler *ih = CMainFrame::GetMainFrame()->GetInputHandler(); if (newTypeIsMOD_XM) { @@ -1680,149 +1625,4 @@ } } -// Merge multiple sequences into one sequence -bool CModDoc::MergeSequences() -//---------------------------- -{ - if(m_SndFile.Order.GetNumSequences() <= 1) return false; - CHAR s[256]; - m_SndFile.Order.SetSequence(0); - m_SndFile.Order.resize(m_SndFile.Order.GetLengthTailTrimmed()); - SEQUENCEINDEX removedSequences = 0; // sequence count - vector <SEQUENCEINDEX> patternsFixed; // pattern fixed by other sequence already? - patternsFixed.resize(m_SndFile.Patterns.Size(), SEQUENCEINDEX_INVALID); - // Set up vector - for(ORDERINDEX nOrd = 0; nOrd < m_SndFile.Order.GetLengthTailTrimmed(); nOrd++) - { - PATTERNINDEX nPat = m_SndFile.Order[nOrd]; - if(!m_SndFile.Patterns.IsValidPat(nPat)) continue; - patternsFixed[nPat] = 0; - } - - while(m_SndFile.Order.GetNumSequences() > 1) - { - removedSequences++; - const ORDERINDEX nFirstOrder = m_SndFile.Order.GetLengthTailTrimmed() + 1; // +1 for separator item - if(nFirstOrder + m_SndFile.Order.GetSequence(1).GetLengthTailTrimmed() > m_SndFile.GetModSpecifications().ordersMax) - { - wsprintf(s, "WARNING: Cannot merge Sequence %d (too long!)\n", removedSequences); - AddToLog(s); - m_SndFile.Order.RemoveSequence(1); - continue; - } - m_SndFile.Order.Append(m_SndFile.Order.GetInvalidPatIndex()); // Separator item - for(ORDERINDEX nOrd = 0; nOrd < m_SndFile.Order.GetSequence(1).GetLengthTailTrimmed(); nOrd++) - { - PATTERNINDEX nPat = m_SndFile.Order.GetSequence(1)[nOrd]; - m_SndFile.Order.Append(nPat); - - // Try to fix patterns (Bxx commands) - if(!m_SndFile.Patterns.IsValidPat(nPat)) continue; - - MODCOMMAND *m = m_SndFile.Patterns[nPat]; - for (UINT len = 0; len < m_SndFile.PatternSize[nPat] * m_SndFile.m_nChannels; m++, len++) - { - if(m->command == CMD_POSITIONJUMP) - { - if(patternsFixed[nPat] != SEQUENCEINDEX_INVALID && patternsFixed[nPat] != removedSequences) - { - // Oops, some other sequence uses this pattern already. - const PATTERNINDEX nNewPat = m_SndFile.Patterns.Insert(m_SndFile.PatternSize[nPat]); - if(nNewPat != SEQUENCEINDEX_INVALID) - { - // could create new pattern - copy data over and continue from here. - m_SndFile.Order[nFirstOrder + nOrd] = nNewPat; - MODCOMMAND *pSrc = m_SndFile.Patterns[nPat]; - MODCOMMAND *pDest = m_SndFile.Patterns[nNewPat]; - memcpy(pDest, pSrc, m_SndFile.PatternSize[nPat] * m_SndFile.m_nChannels * sizeof(MODCOMMAND)); - m = pDest + len; - patternsFixed.resize(max(nNewPat + 1, (PATTERNINDEX)patternsFixed.size()), SEQUENCEINDEX_INVALID); - nPat = nNewPat; - } else - { - // cannot create new pattern: notify the user - wsprintf(s, "CONFLICT: Pattern break commands in Pattern %d might be broken since it has been used in several sequences!", nPat); - AddToLog(s); - } - } - m->param += nFirstOrder; - patternsFixed[nPat] = removedSequences; - } - } - - } - m_SndFile.Order.RemoveSequence(1); - } - // Remove order name + fill up with empty patterns. - m_SndFile.Order.m_sName = ""; - m_SndFile.Order.resize(min(MAX_ORDERS, m_SndFile.GetModSpecifications().ordersMax)); - return true; -} - - -// Split subsongs (separated by "---" or "+++" patterns) into sequences -bool CModDoc::ConvertSubsongsToMultipleSequences() -//------------------------------------------------ -{ - if(m_SndFile.GetType() != MOD_TYPE_MPT || m_SndFile.Order.GetNumSequences() != 1) return false; - bool modified = false; - - m_SndFile.Order.SetSequence(0); - for(ORDERINDEX nOrd = 0; nOrd < m_SndFile.Order.GetLengthTailTrimmed(); nOrd++) - { - // end of subsong? - if(!m_SndFile.Patterns.IsValidIndex(m_SndFile.Order[nOrd])) - { - ORDERINDEX oldLength = m_SndFile.Order.GetLengthTailTrimmed(); - // remove all separator patterns between current and next subsong first - while(nOrd < oldLength && (!m_SndFile.Patterns.IsValidIndex(m_SndFile.Order[nOrd]))) - { - m_SndFile.Order[nOrd] = m_SndFile.Order.GetInvalidPatIndex(); - nOrd++; - modified = true; - } - if(nOrd >= oldLength) break; - ORDERINDEX startOrd = nOrd; - modified = true; - - SEQUENCEINDEX newSeq = m_SndFile.Order.AddSequence(false); - m_SndFile.Order.SetSequence(newSeq); - - // resize new seqeuence if necessary - if(m_SndFile.Order.GetLength() < oldLength - startOrd) - { - m_SndFile.Order.resize(oldLength - startOrd); - } - - // now, move all following orders to the new sequence - while(nOrd < oldLength) - { - PATTERNINDEX copyPat = m_SndFile.Order.GetSequence(newSeq - 1)[nOrd]; - m_SndFile.Order[nOrd - startOrd] = copyPat; - nOrd++; - - // is this a valid pattern? adjust pattern jump commands, if necessary. - if(m_SndFile.Patterns.IsValidPat(copyPat)) - { - MODCOMMAND *m = m_SndFile.Patterns[copyPat]; - for (UINT len = m_SndFile.PatternSize[copyPat] * m_SndFile.m_nChannels; len; m++, len--) - { - if(m->command == CMD_POSITIONJUMP && m->param >= startOrd) - { - m->param -= startOrd; - } - } - } - } - m_SndFile.Order.SetSequence(newSeq - 1); - m_SndFile.Order.Remove(startOrd, oldLength - 1); - m_SndFile.Order.SetSequence(newSeq); - // start from beginning... - nOrd = 0; - if(m_SndFile.Order.GetLengthTailTrimmed() == 0 || !m_SndFile.Patterns.IsValidIndex(m_SndFile.Order[nOrd])) break; - } - } - m_SndFile.Order.SetSequence(0); - return modified; -} Modified: trunk/OpenMPT/mptrack/View_tre.cpp =================================================================== --- trunk/OpenMPT/mptrack/View_tre.cpp 2010-04-17 13:14:48 UTC (rev 569) +++ trunk/OpenMPT/mptrack/View_tre.cpp 2010-04-18 14:46:44 UTC (rev 570) @@ -761,7 +761,7 @@ { // more than one sequence -> add folder CString sSeqName; - sSeqName.Format("%d: %s", nSeq, pSndFile->Order.GetSequence(nSeq).m_sName); + sSeqName.Format("%d: %s", nSeq, (LPCTSTR)pSndFile->Order.GetSequence(nSeq).m_sName); if(sSeqName.IsEmpty()) sSeqName.Format("Sequence %d", nSeq); UINT state = (nSeq == pSndFile->Order.GetCurrentSequenceIndex()) ? TVIS_BOLD : 0; Modified: trunk/OpenMPT/soundlib/ModSequence.cpp =================================================================== --- trunk/OpenMPT/soundlib/ModSequence.cpp 2010-04-17 13:14:48 UTC (rev 569) +++ trunk/OpenMPT/soundlib/ModSequence.cpp 2010-04-18 14:46:44 UTC (rev 570) @@ -1,15 +1,17 @@ #include "stdafx.h" #include "sndfile.h" #include "ModSequence.h" +#include "../mptrack/moddoc.h" #include "../mptrack/version.h" #include "../mptrack/serialization_utils.h" +#include <functional> #define str_SequenceTruncationNote (GetStrI18N((_TEXT("Module has sequence of length %u; it will be truncated to maximum supported length, %u.")))) #define new DEBUG_NEW -ModSequence::ModSequence(const CSoundFile& rSf, +ModSequence::ModSequence(CSoundFile& rSf, PATTERNINDEX* pArray, ORDERINDEX nSize, ORDERINDEX nCapacity, @@ -25,7 +27,7 @@ {} -ModSequence::ModSequence(const CSoundFile& rSf, ORDERINDEX nSize) : +ModSequence::ModSequence(CSoundFile& rSf, ORDERINDEX nSize) : m_pSndFile(&rSf), m_bDeletableArray(true), m_nInvalidIndex(GetInvalidPatIndex(MOD_TYPE_MPT)), @@ -62,26 +64,58 @@ return false; } +namespace +{ + // Functor for detecting non-valid patterns from sequence. + struct IsNotValidPat + { + IsNotValidPat(CSoundFile& sndFile) : rSndFile(sndFile) {} + bool operator()(PATTERNINDEX i) {return !rSndFile.Patterns.IsValidPat(i);} + CSoundFile& rSndFile; + }; +} -void ModSequence::OnModTypeChanged(const MODTYPE oldtype) -//------------------------------------------------------- + +void ModSequence::AdjustToNewModType(const MODTYPE oldtype) +//--------------------------------------------------------- { const CModSpecifications specs = m_pSndFile->GetModSpecifications(); + const MODTYPE newtype = m_pSndFile->GetType(); - m_nInvalidIndex = GetInvalidPatIndex(m_pSndFile->GetType()); - m_nIgnoreIndex = GetIgnoreIndex(m_pSndFile->GetType()); + m_nInvalidIndex = GetInvalidPatIndex(newtype); + m_nIgnoreIndex = GetIgnoreIndex(newtype); + // If not supported, remove "+++" separator order items. + if (specs.hasIgnoreIndex == false) + { + if (oldtype != MOD_TYPE_NONE) + { + iterator i = std::remove_if(begin(), end(), std::bind2nd(std::equal_to<PATTERNINDEX>(), GetIgnoreIndex(oldtype))); + std::fill(i, end(), GetInvalidPatIndex()); + } + } + else + Replace(GetIgnoreIndex(oldtype), GetIgnoreIndex()); + //Resize orderlist if needed. - if (specs.ordersMax < GetLength()) + if (specs.ordersMax < GetLength()) { + // Order list too long? -> remove unnecessary order items first. + if (oldtype != MOD_TYPE_NONE && specs.ordersMax < GetLengthTailTrimmed()) + { + iterator iter = std::remove_if(begin(), end(), IsNotValidPat(*m_pSndFile)); + std::fill(iter, end(), GetInvalidPatIndex()); + if(GetLengthTailTrimmed() > specs.ordersMax) + { + if (m_pSndFile->GetpModDoc()) + m_pSndFile->GetpModDoc()->AddToLog("WARNING: Order list has been trimmed!\n"); + } + } resize(specs.ordersMax); - /*resize(max(MAX_ORDERS, specs.ordersMax)); - std::fill(begin() + specs.ordersMax, end(), GetInvalidPatIndex());*/ } - - //Replace items used to denote end of song/skip order. - Replace(GetInvalidPatIndex(oldtype), GetInvalidPatIndex()); - Replace(GetIgnoreIndex(oldtype), GetIgnoreIndex()); + + // Replace items used to denote end of song order. + Replace(GetInvalidPatIndex(oldtype), GetInvalidPatIndex()); } @@ -235,7 +269,7 @@ ///////////////////////////////////// -ModSequenceSet::ModSequenceSet(const CSoundFile& sndFile) +ModSequenceSet::ModSequenceSet(CSoundFile& sndFile) : ModSequence(sndFile, m_Cache, s_nCacheSize, s_nCacheSize, NoArrayDelete), m_nCurrentSeq(0) //------------------------------------------------------------------- @@ -244,8 +278,8 @@ } -const ModSequence& ModSequenceSet::GetSequence(SEQUENCEINDEX nSeq) -//---------------------------------------------------------------- +const ModSequence& ModSequenceSet::GetSequence(SEQUENCEINDEX nSeq) const +//---------------------------------------------------------------------- { if (nSeq == GetCurrentSequenceIndex()) return *this; @@ -254,6 +288,16 @@ } +ModSequence& ModSequenceSet::GetSequence(SEQUENCEINDEX nSeq) +//---------------------------------------------------------- +{ + if (nSeq == GetCurrentSequenceIndex()) + return *this; + else + return m_Sequences[nSeq]; +} + + void ModSequenceSet::CopyCacheToStorage() //--------------------------------------- { @@ -322,6 +366,195 @@ } +void ModSequenceSet::OnModTypeChanged(const MODTYPE oldtype) +//---------------------------------------------------------- +{ + const MODTYPE newtype = m_pSndFile->GetType(); + const SEQUENCEINDEX nSeqs = GetNumSequences(); + for(SEQUENCEINDEX n = 0; n < nSeqs; n++) + { + GetSequence(n).AdjustToNewModType(oldtype); + } + // Multisequences not suppported by other formats + if (oldtype != MOD_TYPE_NONE && newtype != MOD_TYPE_MPT) + MergeSequences(); + + // Convert sequence with separator patterns into multiple sequences? + if (oldtype != MOD_TYPE_NONE && newtype == MOD_TYPE_MPT && GetNumSequences() == 1) + ConvertSubsongsToMultipleSequences(); +} + + +bool ModSequenceSet::ConvertSubsongsToMultipleSequences() +//------------------------------------------------------- +{ + // Allow conversion only if there's only one sequence. + if (GetNumSequences() != 1 || m_pSndFile->GetType() != MOD_TYPE_MPT) + return false; + + bool hasSepPatterns = false; + const ORDERINDEX nLengthTt = GetLengthTailTrimmed(); + for(ORDERINDEX nOrd = 0; nOrd < nLengthTt; nOrd++) + { + if(!m_pSndFile->Patterns.IsValidIndex(At(nOrd))) + { + hasSepPatterns = true; + break; + } + } + bool modified = false; + + if(hasSepPatterns && + ::MessageBox(NULL, + "The order list contains separator items.\nThe new format supports multiple sequences, do you want to convert those separate tracks into multiple song sequences?", + "Order list conversion", MB_YESNO | MB_ICONQUESTION) == IDYES) + { + + SetSequence(0); + for(ORDERINDEX nOrd = 0; nOrd < GetLengthTailTrimmed(); nOrd++) + { + // end of subsong? + if(!m_pSndFile->Patterns.IsValidIndex(At(nOrd))) + { + ORDERINDEX oldLength = GetLengthTailTrimmed(); + // remove all separator patterns between current and next subsong first + while(nOrd < oldLength && (!m_pSndFile->Patterns.IsValidIndex(At(nOrd)))) + { + At(nOrd) = GetInvalidPatIndex(); + nOrd++; + modified = true; + } + if(nOrd >= oldLength) break; + ORDERINDEX startOrd = nOrd; + modified = true; + + SEQUENCEINDEX newSeq = AddSequence(false); + SetSequence(newSeq); + + // resize new seqeuence if necessary + if(GetLength() < oldLength - startOrd) + { + resize(oldLength - startOrd); + } + + // now, move all following orders to the new sequence + while(nOrd < oldLength) + { + PATTERNINDEX copyPat = GetSequence(newSeq - 1)[nOrd]; + At(nOrd - startOrd) = copyPat; + nOrd++; + + // is this a valid pattern? adjust pattern jump commands, if necessary. + if(m_pSndFile->Patterns.IsValidPat(copyPat)) + { + MODCOMMAND *m = m_pSndFile->Patterns[copyPat]; + for (UINT len = m_pSndFile->PatternSize[copyPat] * m_pSndFile->m_nChannels; len; m++, len--) + { + if(m->command == CMD_POSITIONJUMP && m->param >= startOrd) + { + m->param = static_cast<BYTE>(m->param - startOrd); + } + } + } + } + SetSequence(newSeq - 1); + Remove(startOrd, oldLength - 1); + SetSequence(newSeq); + // start from beginning... + nOrd = 0; + if(GetLengthTailTrimmed() == 0 || !m_pSndFile->Patterns.IsValidIndex(At(nOrd))) break; + } + } + SetSequence(0); + } + return modified; +} + +bool ModSequenceSet::MergeSequences() +//----------------------------------- +{ + if(GetNumSequences() <= 1) + return false; + + CHAR s[256]; + SetSequence(0); + resize(GetLengthTailTrimmed()); + SEQUENCEINDEX removedSequences = 0; // sequence count + vector <SEQUENCEINDEX> patternsFixed; // pattern fixed by other sequence already? + patternsFixed.resize(m_pSndFile->Patterns.Size(), SEQUENCEINDEX_INVALID); + // Set up vector + for(ORDERINDEX nOrd = 0; nOrd < GetLengthTailTrimmed(); nOrd++) + { + PATTERNINDEX nPat = At(nOrd); + if(!m_pSndFile->Patterns.IsValidPat(nPat)) continue; + patternsFixed[nPat] = 0; + } + + while(GetNumSequences() > 1) + { + removedSequences++; + const ORDERINDEX nFirstOrder = GetLengthTailTrimmed() + 1; // +1 for separator item + if(nFirstOrder + GetSequence(1).GetLengthTailTrimmed() > m_pSndFile->GetModSpecifications().ordersMax) + { + wsprintf(s, "WARNING: Cannot merge Sequence %d (too long!)\n", removedSequences); + if (m_pSndFile->GetpModDoc()) + m_pSndFile->GetpModDoc()->AddToLog(s); + RemoveSequence(1); + continue; + } + Append(GetInvalidPatIndex()); // Separator item + for(ORDERINDEX nOrd = 0; nOrd < GetSequence(1).GetLengthTailTrimmed(); nOrd++) + { + PATTERNINDEX nPat = GetSequence(1)[nOrd]; + Append(nPat); + + // Try to fix patterns (Bxx commands) + if(!m_pSndFile->Patterns.IsValidPat(nPat)) continue; + + MODCOMMAND *m = m_pSndFile->Patterns[nPat]; + for (UINT len = 0; len < m_pSndFile->PatternSize[nPat] * m_pSndFile->m_nChannels; m++, len++) + { + if(m->command == CMD_POSITIONJUMP) + { + if(patternsFixed[nPat] != SEQUENCEINDEX_INVALID && patternsFixed[nPat] != removedSequences) + { + // Oops, some other sequence uses this pattern already. + const PATTERNINDEX nNewPat = m_pSndFile->Patterns.Insert(m_pSndFile->PatternSize[nPat]); + if(nNewPat != SEQUENCEINDEX_INVALID) + { + // could create new pattern - copy data over and continue from here. + At(nFirstOrder + nOrd) = nNewPat; + MODCOMMAND *pSrc = m_pSndFile->Patterns[nPat]; + MODCOMMAND *pDest = m_pSndFile->Patterns[nNewPat]; + memcpy(pDest, pSrc, m_pSndFile->PatternSize[nPat] * m_pSndFile->m_nChannels * sizeof(MODCOMMAND)); + m = pDest + len; + patternsFixed.resize(max(nNewPat + 1, (PATTERNINDEX)patternsFixed.size()), SEQUENCEINDEX_INVALID); + nPat = nNewPat; + } else + { + // cannot create new pattern: notify the user + wsprintf(s, "CONFLICT: Pattern break commands in Pattern %d might be broken since it has been used in several sequences!", nPat); + if (m_pSndFile->GetpModDoc()) + m_pSndFile->GetpModDoc()->AddToLog(s); + } + } + m->param = static_cast<BYTE>(m->param + nFirstOrder); + patternsFixed[nPat] = removedSequences; + } + } + + } + RemoveSequence(1); + } + // Remove order name + fill up with empty patterns. + m_sName = ""; + const ORDERINDEX nMinLength = (std::min)(ModSequenceSet::s_nCacheSize, m_pSndFile->GetModSpecifications().ordersMax); + if (GetLength() < nMinLength) + resize(nMinLength); + return true; +} + + ///////////////////////////////////// // Read/Write ///////////////////////////////////// Modified: trunk/OpenMPT/soundlib/ModSequence.h =================================================================== --- trunk/OpenMPT/soundlib/ModSequence.h 2010-04-17 13:14:48 UTC (rev 569) +++ trunk/OpenMPT/soundlib/ModSequence.h 2010-04-18 14:46:44 UTC (rev 570) @@ -19,14 +19,16 @@ virtual ~ModSequence() {if (m_bDeletableArray) delete[] m_pArray;} ModSequence(const ModSequence&); - ModSequence(const CSoundFile& rSf, ORDERINDEX nSize); - ModSequence(const CSoundFile& rSf, PATTERNINDEX* pArray, ORDERINDEX nSize, ORDERINDEX nCapacity, bool bDeletableArray); + ModSequence(CSoundFile& rSf, ORDERINDEX nSize); + ModSequence(CSoundFile& rSf, PATTERNINDEX* pArray, ORDERINDEX nSize, ORDERINDEX nCapacity, bool bDeletableArray); // Initialize default sized sequence. void Init(); PATTERNINDEX& operator[](const size_t i) {ASSERT(i < m_nSize); return m_pArray[i];} const PATTERNINDEX& operator[](const size_t i) const {ASSERT(i < m_nSize); return m_pArray[i];} + PATTERNINDEX& At(const size_t i) {return (*this)[i];} + const PATTERNINDEX& At(const size_t i) const {return (*this)[i];} PATTERNINDEX& Last() {ASSERT(m_nSize > 0); return m_pArray[m_nSize-1];} const PATTERNINDEX& Last() const {ASSERT(m_nSize > 0); return m_pArray[m_nSize-1];} @@ -52,9 +54,9 @@ void resize(ORDERINDEX nNewSize, PATTERNINDEX nFill); // Replaces all occurences of nOld with nNew. - void Replace(PATTERNINDEX nOld, PATTERNINDEX nNew) {std::replace(begin(), end(), nOld, nNew);} + void Replace(PATTERNINDEX nOld, PATTERNINDEX nNew) {if (nOld != nNew) std::replace(begin(), end(), nOld, nNew);} - void OnModTypeChanged(const MODTYPE oldtype); + void AdjustToNewModType(const MODTYPE oldtype); ORDERINDEX size() const {return GetLength();} ORDERINDEX GetLength() const {return m_nSize;} @@ -106,7 +108,7 @@ PATTERNINDEX m_nInvalidIndex; // Invalid pat index. PATTERNINDEX m_nIgnoreIndex; // Ignore pat index. bool m_bDeletableArray; // True if m_pArray points the deletable(with delete[]) array. - const CSoundFile* m_pSndFile; // Pointer to associated CSoundFile. + CSoundFile* m_pSndFile; // Pointer to associated CSoundFile. static const bool NoArrayDelete = false; }; @@ -127,10 +129,11 @@ friend void ReadModSequence(std::istream& iStrm, ModSequence& seq, const size_t); public: - ModSequenceSet(const CSoundFile& sndFile); + ModSequenceSet(CSoundFile& sndFile); const ModSequence& GetSequence() {return GetSequence(GetCurrentSequenceIndex());} - const ModSequence& GetSequence(SEQUENCEINDEX nSeq); + const ModSequence& GetSequence(SEQUENCEINDEX nSeq) const; + ModSequence& GetSequence(SEQUENCEINDEX nSeq); SEQUENCEINDEX GetNumSequences() const {return static_cast<SEQUENCEINDEX>(m_Sequences.size());} void SetSequence(SEQUENCEINDEX); // Sets working sequence. SEQUENCEINDEX AddSequence(bool bDuplicate = true); // Adds new sequence. If bDuplicate is true, new sequence is a duplicate of the old one. Returns the ID of the new sequence. @@ -138,8 +141,20 @@ void RemoveSequence(SEQUENCEINDEX); // Removes given sequence SEQUENCEINDEX GetCurrentSequenceIndex() const {return m_nCurrentSeq;} + void OnModTypeChanged(const MODTYPE oldtype); + ModSequenceSet& operator=(const ModSequence& seq) {ModSequence::operator=(seq); return *this;} + // Merges multiple sequences into one and destroys all other sequences. + // Returns false if there were no sequences to merge, true otherwise. + bool MergeSequences(); + + // If there are subsongs (separated by "---" or "+++" patterns) in the module, + // asks user whether to convert these into multiple sequences (given that the + // modformat supports multiple sequences). + // Returns true if sequences were modified, false otherwise. + bool ConvertSubsongsToMultipleSequences(); + static const ORDERINDEX s_nCacheSize = MAX_ORDERS; private: Modified: trunk/OpenMPT/soundlib/Sndfile.cpp =================================================================== --- trunk/OpenMPT/soundlib/Sndfile.cpp 2010-04-17 13:14:48 UTC (rev 569) +++ trunk/OpenMPT/soundlib/Sndfile.cpp 2010-04-18 14:46:44 UTC (rev 570) @@ -3027,9 +3027,11 @@ } void CSoundFile::ChangeModTypeTo(const MODTYPE& newType) -//--------------------------------------------------- +//------------------------------------------------------ { const MODTYPE oldtype = m_nType; + if (oldtype == newType) + return; m_nType = newType; SetModSpecsPointer(m_pModSpecs, m_nType); SetupMODPanning(); // Setup LRRL panning scheme if needed This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |