root/branches/undo/libs/hydrogen/src/pattern.cpp @ 1608

Revision 1608, 6.2 KB (checked in by wolke, 3 years ago)

merge rev 1603:1607 from trunk

Line 
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#include <hydrogen/Pattern.h>
24#include <hydrogen/Song.h>
25#include <hydrogen/note.h>
26#include <hydrogen/audio_engine.h>
27
28#include <vector>
29#include <cassert>
30namespace H2Core
31{
32
33Pattern::Pattern( const QString& name, const QString& category, unsigned length )
34                : Object( "Pattern" )
35{
36//      INFOLOG( "INIT: " + m_sName );
37        set_name( name );
38        set_category( category );
39        set_length( length );
40}
41
42
43
44Pattern::~Pattern()
45{
46//      INFOLOG( "DESTROY: " + m_sName );
47
48        // delete all Notes
49        std::multimap <int, Note*>::iterator pos;
50        for ( pos = note_map.begin(); pos != note_map.end(); ++pos ) {
51                Note *pNote = pos->second;
52                delete pNote;
53        }
54}
55
56
57void Pattern::purge_instrument( Instrument * I )
58{
59        bool locked = false;
60        std::list< Note* > slate;
61       
62        std::multimap <int, Note*>::iterator pos = note_map.begin();
63        while ( pos != note_map.end() ) {
64                Note *pNote = pos->second;
65                assert( pNote );
66               
67                if ( pNote->get_instrument() == I ) {
68                        if ( !locked ) {
69                                H2Core::AudioEngine::get_instance()->lock( RIGHT_HERE );
70                                locked = true;
71                        }
72                        slate.push_back( pNote );
73                       
74                        note_map.erase( pos++ );
75                } else {
76                        ++pos;
77                }
78        }
79       
80        if ( locked ) {
81                H2Core::AudioEngine::get_instance()->unlock();
82                while ( slate.size() ) {
83                        delete slate.front();
84                        slate.pop_front();
85                }
86        }
87}
88
89
90bool Pattern::references_instrument( Instrument * I )
91{
92        std::multimap <int, Note*>::const_iterator pos;
93        for ( pos = note_map.begin(); pos != note_map.end(); ++pos ) {
94                Note *pNote = pos->second;
95                assert( pNote );
96                if ( pNote->get_instrument() == I ) {
97                        return true;
98                }
99        }
100        return false;
101}
102
103
104void Pattern::set_to_old()
105{
106        std::multimap <int, Note*>::const_iterator pos;
107        for ( pos = note_map.begin(); pos != note_map.end(); ++pos ) {
108                Note *pNote = pos->second;
109                assert( pNote );
110                pNote->m_bJustRecorded = false ;
111        }
112}
113
114
115/// Returns an empty Pattern
116Pattern* Pattern::get_empty_pattern()
117{
118        Pattern *pat = new Pattern( "Pattern", "not_categorized" );
119        return pat;
120}
121
122
123
124Pattern* Pattern::copy()
125{
126//      ERRORLOG( "not implemented yet!!!" );
127
128        Pattern *newPat = new Pattern( __name, __category );
129        newPat->set_length( get_length() );
130
131        std::multimap <int, Note*>::iterator pos;
132        for ( pos = note_map.begin(); pos != note_map.end(); ++pos ) {
133                Note *pNote = new Note( pos->second );
134                newPat->note_map.insert( std::make_pair( pos->first, pNote ) );
135        }
136
137        return newPat;
138}
139
140
141
142void Pattern::debug_dump()
143{
144        INFOLOG( "Pattern dump" );
145        INFOLOG( "Pattern name: " + __name );
146        INFOLOG( "Pattern category: " + __category );
147        INFOLOG( QString("Pattern length: %1").arg( get_length() ) );
148}
149
150
151
152// ::::::::::::::::::::::::
153
154
155
156PatternList::PatternList()
157                : Object( "PatternList" )
158{
159//      infoLog("Init");
160}
161
162
163
164PatternList::~PatternList()
165{
166//      infoLog("destroy");
167
168        // find single patterns. (skip duplicates)
169        std::vector<Pattern*> temp;
170        for ( unsigned int i = 0; i < list.size(); ++i ) {
171                Pattern *pat = list[i];
172
173                // pat exists in temp?
174                bool exists = false;
175                for ( unsigned int j = 0; j < temp.size(); ++j ) {
176                        if ( pat == temp[j] ) {
177                                exists = true;
178                                break;
179                        }
180                }
181                if ( !exists ) {
182                        temp.push_back( pat );
183                }
184        }
185
186        // delete patterns
187        for ( unsigned int i = 0; i < temp.size(); ++i ) {
188                Pattern *pat = temp[i];
189                if ( pat != NULL ) {
190                        delete pat;
191                        pat = NULL;
192                }
193        }
194}
195
196
197
198void PatternList::add( Pattern* newPattern )
199{
200        list.push_back( newPattern );
201}
202
203
204
205Pattern* PatternList::get( int nPos )
206{
207        if ( nPos >= ( int )list.size() ) {
208                ERRORLOG( QString("Pattern index out of bounds. nPos > list.size() - %1 > %2")
209                          .arg( nPos )
210                          .arg( list.size() )
211                        );
212                return NULL;
213        }
214//      assert( nPos < (int)list.size() );
215        return list[ nPos ];
216}
217
218
219
220unsigned PatternList::get_size()
221{
222        return list.size();
223}
224
225
226
227void PatternList::clear()
228{
229        list.clear();
230}
231
232
233
234/// Replace an existent pattern with another one
235void PatternList::replace( Pattern* newPattern, unsigned int pos )
236{
237        if ( pos >= ( unsigned )list.size() ) {
238                ERRORLOG( QString("Pattern index out of bounds in PatternList::replace. pos >= list.size() - %1 > %2")
239                          .arg( pos )
240                          .arg( list.size() )
241                        );
242                return;
243        }
244        list.insert( list.begin() + pos, newPattern );  // insert the new pattern
245        // remove the old pattern
246        list.erase( list.begin() + pos + 1 );
247}
248
249
250
251int PatternList::index_of( Pattern* pattern )
252{
253        if ( get_size() < 1 ) return -1;
254
255        std::vector<Pattern*>::iterator i;
256
257        int r = 0;
258        for ( i = list.begin(); i != list.end(); ++i ) {
259                if ( !*i  ) return -1;
260                if ( *i == pattern ) return r;
261                ++r;
262        }
263        return -1;
264}
265
266
267
268Pattern * PatternList::del( Pattern * p )
269{
270        bool did_delete = false;
271        if ( get_size() < 1 ) return NULL;
272
273        std::vector<Pattern*>::iterator i;
274
275        for ( i = list.begin(); i != list.end(); i++ ) {
276                if ( *i == p ) {
277                        i = list.erase( i );
278                        did_delete = true;
279                        break;
280                        // NOTE: Do we need to delete EVERY instance of p in the list? Better to avoid adding more than one copy of a pattern in the first place! Using the iterator i after modifying the list is dangerous, so either just delete one OR...
281                        // ... or roll back the iterator after deleting :
282//                      i--;
283                }
284        }
285        if ( did_delete ) return p;
286        return NULL;
287}
288
289
290void PatternList::set_to_old()
291{
292        for ( int nPattern = 0 ; nPattern < (int) get_size() ; ++nPattern ) {
293                get( nPattern )->set_to_old();
294        }
295}
296
297
298void PatternList::del( unsigned pos )
299{
300        if ( pos >= ( unsigned )list.size() ) {
301                ERRORLOG( QString("Pattern index out of bounds in PatternList::del. pos >= list.size() - %1 > %2")
302                          .arg( pos )
303                          .arg( list.size() )
304                        );
305                return;
306        }
307        list.erase( list.begin()+pos );
308}
309
310
311};
Note: See TracBrowser for help on using the browser.