1 /*
2 * Hydrogen
3 * Copyright(c) 2002-2008 by Alex >Comix< Cominu [comix@users.sourceforge.net]
4 *
5 * http://www.hydrogen-music.org
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY, without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 *
21 */
22
23 #ifndef H2C_PATTERN_H
24 #define H2C_PATTERN_H
25
26 #include <set>
27
28 #include <hydrogen/object.h>
29 #include <hydrogen/basics/note.h>
30
31 namespace H2Core
32 {
33
34 class XMLNode;
35 class Instrument;
36 class InstrumentList;
37 class PatternList;
38
39 /**
40 Pattern class is a Note container
41 */
42 class Pattern : public H2Core::Object
43 {
44 H2_OBJECT
45 public:
46 ///< multimap note type
47 typedef std::multimap <int, Note*> notes_t;
48 ///< multimap note iterator type
49 typedef notes_t::iterator notes_it_t;
50 ///< multimap note const iterator type
51 typedef notes_t::const_iterator notes_cst_it_t;
52 ///< note set type;
53 typedef std::set <Pattern*> virtual_patterns_t;
54 ///< note set iterator type;
55 typedef virtual_patterns_t::iterator virtual_patterns_it_t;
56 ///< note set const iterator type;
57 typedef virtual_patterns_t::const_iterator virtual_patterns_cst_it_t;
58 /**
59 * constructor
60 * \param name the name of the pattern
61 * \param info Initialized with an empty string.
62 * \param category the name of the pattern
63 * \param length the length of the pattern
64 */
65 Pattern( const QString& name="Pattern", const QString& info="", const QString& category="not_categorized", int length=MAX_NOTES );
66 /** copy constructor */
67 Pattern( Pattern* other );
68 /** destructor */
69 ~Pattern();
70
71 /**
72 * load a pattern from a file
73 * \param pattern_path the path to the file to load the pattern from
74 * \param instruments the current instrument list to search instrument into
75 */
76 static Pattern* load_file( const QString& pattern_path, InstrumentList* instruments );
77 /**
78 * save a pattern into an xml file
79 * \param drumkit_name the name of the drumkit it is supposed to play with
80 * \param author the name of the author
81 * \param license the license that applies to it
82 * \param pattern_path the path to save the pattern into
83 * \param overwrite allows to write over existing pattern file
84 * \return true on success
85 */
86 bool save_file( const QString& drumkit_name, const QString& author, const QString& license, const QString& pattern_path, bool overwrite=false ) const;
87
88 ///< set the name of the pattern
89 void set_name( const QString& name );
90 ///< get the name of the pattern
91 const QString& get_name() const;
92 ///< set the category of the pattern
93 void set_category( const QString& category );
94 ///< set the info of the pattern
95 void set_info( const QString& info );
96 ///< get the info of the pattern
97 const QString& get_info() const;
98 ///< get the category of the pattern
99 const QString& get_category() const;
100 ///< set the length of the pattern
101 void set_length( int length );
102 ///< get the length of the pattern
103 int get_length() const;
104 ///< get the note multimap
105 const notes_t* get_notes() const;
106 ///< get the virtual pattern set
107 const virtual_patterns_t* get_virtual_patterns() const;
108 ///< get the flattened virtual pattern set
109 const virtual_patterns_t* get_flattened_virtual_patterns() const;
110
111 /**
112 * insert a new note within __notes
113 * \param note the note to be inserted
114 * \param position if not -1 will be used as std::pair first element, otherwise note position will be used
115 */
116 void insert_note( Note* note, int position=-1 );
117 /**
118 * search for a note at a given index within __notes which correspond to the given arguments
119 * \param idx_a the first __notes index to search in
120 * \param idx_b the second __notes index to search in, will be omitted if is -1
121 * \param instrument the instrument the note should be playing
122 * \param strict if set to false, will search for a note around the given idx
123 * \return the note if found, 0 otherwise
124 */
125 Note* find_note( int idx_a, int idx_b, Instrument* instrument, bool strict=true ) const;
126 /**
127 * search for a note at a given index within __notes which correspond to the given arguments
128 * \param idx_a the first __notes index to search in
129 * \param idx_b the second __notes index to search in, will be omitted if is -1
130 * \param instrument the instrument the note should be playing
131 * \param key the key that should be set to the note
132 * \param octave the octave that should be set to the note
133 * \param strict if set to false, will search for a note around the given idx
134 * \return the note if found, 0 otherwise
135 */
136 Note* find_note( int idx_a, int idx_b, Instrument* instrument, Note::Key key, Note::Octave octave, bool strict=true) const;
137 /**
138 * removes a given note from __notes, it's not deleted
139 * \param note the note to be removed
140 */
141 void remove_note( Note* note );
142
143 /**
144 * check if this pattern contains a note referencing the given instrument
145 * \param instr the instrument
146 */
147 bool references( Instrument* instr );
148 /**
149 * delete the notes referencing the given instrument
150 * The function is thread safe (it locks the audio data while deleting notes)
151 * \param instr the instrument
152 */
153 void purge_instrument( Instrument* instr );
154 /**
155 * mark all notes as old
156 */
157 void set_to_old();
158
159 ///< return true if __virtual_patterns is empty
160 bool virtual_patterns_empty() const;
161 ///< clear __virtual_patterns
162 void virtual_patterns_clear();
163 /**
164 * add a pattern to __virtual_patterns
165 * \param pattern the pattern to add
166 */
167 void virtual_patterns_add( Pattern* pattern );
168 /**
169 * remove a pattern from virtual_pattern set, flattened virtual patterns have to be rebuilt
170 * */
171 void virtual_patterns_del( Pattern* pattern );
172 ///< clear flattened_virtual_patterns
173 void flattened_virtual_patterns_clear();
174 /**
175 * compute virtual_pattern_transitive_closure_set based on virtual_pattern_transitive_closure_set
176 * virtual_pattern_transitive_closure_set must have been cleared before which is the case is called
177 * from PatternList::compute_flattened_virtual_patterns
178 */
179 void flattened_virtual_patterns_compute();
180 /**
181 * add content of __flatteened_virtual_patterns into patterns
182 * \param patterns the pattern list to feed
183 */
184 void extand_with_flattened_virtual_patterns( PatternList* patterns );
185
186 /**
187 * save the pattern within the given XMLNode
188 * \param node the XMLNode to feed
189 * \param instrumentOnly export only the notes of that instrument if given
190 */
191 void save_to( XMLNode* node, const Instrument* instrumentOnly = nullptr ) const;
192
193 private:
194 int __length; ///< the length of the pattern
195 QString __name; ///< the name of thepattern
196 QString __category; ///< the category of the pattern
197 QString __info; ///< a description of the pattern
198 notes_t __notes; ///< a multimap (hash with possible multiple values for one key) of note
199 virtual_patterns_t __virtual_patterns; ///< a list of patterns directly referenced by this one
200 virtual_patterns_t __flattened_virtual_patterns; ///< the complete list of virtual patterns
201 /**
202 * load a pattern from an XMLNode
203 * \param node the XMLDode to read from
204 * \param instruments the current instrument list to search instrument into
205 * \return a new Pattern instance
206 */
207 static Pattern* load_from( XMLNode* node, InstrumentList* instruments );
208 };
209
210 #define FOREACH_NOTE_CST_IT_BEGIN_END(_notes,_it) \
211 for( Pattern::notes_cst_it_t (_it)=(_notes)->begin(); (_it)!=(_notes)->end(); (_it)++ )
212
213 #define FOREACH_NOTE_CST_IT_BOUND(_notes,_it,_bound) \
214 for( Pattern::notes_cst_it_t (_it)=(_notes)->lower_bound((_bound)); (_it)!=(_notes)->upper_bound((_bound)); (_it)++ )
215
216 #define FOREACH_NOTE_IT_BEGIN_END(_notes,_it) \
217 for( Pattern::notes_it_t (_it)=(_notes)->begin(); (_it)!=(_notes)->end(); (_it)++ )
218
219 #define FOREACH_NOTE_IT_BOUND(_notes,_it,_bound) \
220 for( Pattern::notes_it_t (_it)=(_notes)->lower_bound((_bound)); (_it)!=(_notes)->upper_bound((_bound)); (_it)++ )
221
222 // DEFINITIONS
223
set_name(const QString & name)224 inline void Pattern::set_name( const QString& name )
225 {
226 __name = name;
227 }
228
get_name()229 inline const QString& Pattern::get_name() const
230 {
231 return __name;
232 }
233
set_info(const QString & info)234 inline void Pattern::set_info( const QString& info )
235 {
236 __info = info;
237 }
238
get_info()239 inline const QString& Pattern::get_info() const
240 {
241 return __info;
242 }
243
set_category(const QString & category)244 inline void Pattern::set_category( const QString& category )
245 {
246 __category = category;
247 }
248
get_category()249 inline const QString& Pattern::get_category() const
250 {
251 return __category;
252 }
253
set_length(int length)254 inline void Pattern::set_length( int length )
255 {
256 __length = length;
257 }
258
get_length()259 inline int Pattern::get_length() const
260 {
261 return __length;
262 }
263
get_notes()264 inline const Pattern::notes_t* Pattern::get_notes() const
265 {
266 return &__notes;
267 }
268
get_virtual_patterns()269 inline const Pattern::virtual_patterns_t* Pattern::get_virtual_patterns() const
270 {
271 return &__virtual_patterns;
272 }
273
get_flattened_virtual_patterns()274 inline const Pattern::virtual_patterns_t* Pattern::get_flattened_virtual_patterns() const
275 {
276 return &__flattened_virtual_patterns;
277 }
278
insert_note(Note * note,int position)279 inline void Pattern::insert_note( Note* note, int position )
280 {
281 __notes.insert( std::make_pair( ( position==-1 ? note->get_position() : position ), note ) );
282 }
283
virtual_patterns_empty()284 inline bool Pattern::virtual_patterns_empty() const
285 {
286 return __virtual_patterns.empty();
287 }
288
virtual_patterns_clear()289 inline void Pattern::virtual_patterns_clear()
290 {
291 __virtual_patterns.clear();
292 }
293
virtual_patterns_add(Pattern * pattern)294 inline void Pattern::virtual_patterns_add( Pattern* pattern )
295 {
296 __virtual_patterns.insert( pattern );
297 }
298
virtual_patterns_del(Pattern * pattern)299 inline void Pattern::virtual_patterns_del( Pattern* pattern )
300 {
301 virtual_patterns_cst_it_t it = __virtual_patterns.find( pattern );
302 if ( it!=__virtual_patterns.end() ) __virtual_patterns.erase( it );
303 }
304
flattened_virtual_patterns_clear()305 inline void Pattern::flattened_virtual_patterns_clear()
306 {
307 __flattened_virtual_patterns.clear();
308 }
309
310 };
311
312 #endif // H2C_PATTERN_H
313
314 /* vim: set softtabstop=4 noexpandtab: */
315