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