1 /*
2 * PatternContainer.h
3 * ------------------
4 * Purpose: Container class for managing patterns.
5 * Notes : (currently none)
6 * Authors: OpenMPT Devs
7 * The OpenMPT source code is released under the BSD license. Read LICENSE for more details.
8 */
9
10
11 #pragma once
12
13 #include "openmpt/all/BuildSettings.hpp"
14
15 #include "pattern.h"
16
17 #include <algorithm>
18
19 OPENMPT_NAMESPACE_BEGIN
20
21 class CSoundFile;
22
23 class CPatternContainer
24 {
25 public:
26 CPattern& operator[](const int pat) { return m_Patterns[pat]; }
27 const CPattern& operator[](const int pat) const { return m_Patterns[pat]; }
28
29 public:
CPatternContainer(CSoundFile & sndFile)30 CPatternContainer(CSoundFile& sndFile) : m_rSndFile(sndFile) { }
31
32 // Empty and initialize all patterns.
33 void ClearPatterns();
34 // Delete all patterns.
35 void DestroyPatterns();
36
37 // Insert (default)pattern to given position. If pattern already exists at that position,
38 // ignoring request. Returns true on success, false otherwise.
39 bool Insert(const PATTERNINDEX index, const ROWINDEX rows);
40
41 // Insert pattern to position with the lowest index, and return that index, PATTERNINDEX_INVALID on failure.
42 // If respectQtyLimits is true, inserting patterns will fail if the resulting pattern index would exceed the current format's pattern quantity limits.
43 PATTERNINDEX InsertAny(const ROWINDEX rows, bool respectQtyLimits = false);
44
45 // Duplicate an existing pattern. Returns new pattern index on success, or PATTERNINDEX_INVALID on failure.
46 // If respectQtyLimits is true, inserting patterns will fail if the resulting pattern index would exceed the current format's pattern quantity limits.
47 PATTERNINDEX Duplicate(PATTERNINDEX from, bool respectQtyLimits = false);
48
49 //Remove pattern from given position. Currently it actually makes the pattern
50 //'invisible' - the pattern data is cleared but the actual pattern object won't get removed.
51 void Remove(const PATTERNINDEX index);
52
53 // Applies function object for modcommands in patterns in given range.
54 // Return: Copy of the function object.
55 template <class Func>
56 Func ForEachModCommand(PATTERNINDEX nStartPat, PATTERNINDEX nLastPat, Func func);
57 template <class Func>
ForEachModCommand(Func func)58 Func ForEachModCommand(Func func) { return ForEachModCommand(0, Size() - 1, func); }
59
begin()60 std::vector<CPattern>::iterator begin() { return m_Patterns.begin(); }
begin()61 std::vector<CPattern>::const_iterator begin() const { return m_Patterns.begin(); }
cbegin()62 std::vector<CPattern>::const_iterator cbegin() const { return m_Patterns.cbegin(); }
end()63 std::vector<CPattern>::iterator end() { return m_Patterns.end(); }
end()64 std::vector<CPattern>::const_iterator end() const { return m_Patterns.end(); }
cend()65 std::vector<CPattern>::const_iterator cend() const { return m_Patterns.cend(); }
66
Size()67 PATTERNINDEX Size() const { return static_cast<PATTERNINDEX>(m_Patterns.size()); }
68
GetSoundFile()69 CSoundFile& GetSoundFile() { return m_rSndFile; }
GetSoundFile()70 const CSoundFile& GetSoundFile() const { return m_rSndFile; }
71
72 // Return true if pattern can be accessed with operator[](iPat), false otherwise.
IsValidIndex(const PATTERNINDEX iPat)73 bool IsValidIndex(const PATTERNINDEX iPat) const { return (iPat < Size()); }
74
75 // Return true if IsValidIndex() is true and the corresponding pattern has allocated modcommand array, false otherwise.
IsValidPat(const PATTERNINDEX iPat)76 bool IsValidPat(const PATTERNINDEX iPat) const { return IsValidIndex(iPat) && m_Patterns[iPat].IsValid(); }
77
78 // Returns true if the pattern is empty, i.e. there are no notes/effects in this pattern
79 bool IsPatternEmpty(const PATTERNINDEX nPat) const;
80
81 void ResizeArray(const PATTERNINDEX newSize);
82
83 void OnModTypeChanged(const MODTYPE oldtype);
84
85 // Returns index of last valid pattern + 1, zero if no such pattern exists.
86 PATTERNINDEX GetNumPatterns() const;
87
88 // Returns index of highest pattern with pattern named + 1.
89 PATTERNINDEX GetNumNamedPatterns() const;
90
91
92 private:
93 std::vector<CPattern> m_Patterns;
94 CSoundFile &m_rSndFile;
95 };
96
97
98 template <class Func>
ForEachModCommand(PATTERNINDEX nStartPat,PATTERNINDEX nLastPat,Func func)99 Func CPatternContainer::ForEachModCommand(PATTERNINDEX nStartPat, PATTERNINDEX nLastPat, Func func)
100 {
101 if (nStartPat > nLastPat || nLastPat >= Size())
102 return func;
103 for (PATTERNINDEX nPat = nStartPat; nPat <= nLastPat; nPat++) if (m_Patterns[nPat].IsValid())
104 std::for_each(m_Patterns[nPat].begin(), m_Patterns[nPat].end(), func);
105 return func;
106 }
107
108
109 const char FileIdPatterns[] = "mptPc";
110
111 void ReadModPatterns(std::istream& iStrm, CPatternContainer& patc, const size_t nSize = 0);
112 void WriteModPatterns(std::ostream& oStrm, const CPatternContainer& patc);
113
114
115 OPENMPT_NAMESPACE_END
116