root/branches/jackMidi/libs/hydrogen/src/pattern.cpp @ 400

Revision 400, 6.0 KB (checked in by gabriel, 5 years ago)

Merge rev 354:373 from trunk.

Conflicts:

libs/hydrogen/src/hydrogen.cpp

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 lenght )
34                : Object( "Pattern" )
35{
36//      INFOLOG( "INIT: " + m_sName );
37        set_name( name );
38        set_category( category );
39        set_lenght( lenght );
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("Pattern::purge_instrument");
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
104
105/// Returns an empty Pattern
106Pattern* Pattern::get_empty_pattern()
107{
108        Pattern *pat = new Pattern( "Pattern", "not_categorized" );
109        return pat;
110}
111
112
113
114Pattern* Pattern::copy()
115{
116//      ERRORLOG( "not implemented yet!!!" );
117
118        Pattern *newPat = new Pattern( __name, __category );
119        newPat->set_lenght( get_lenght() );
120
121        std::multimap <int, Note*>::iterator pos;
122        for ( pos = note_map.begin(); pos != note_map.end(); ++pos ) {
123                Note *pNote = new Note( pos->second );
124                newPat->note_map.insert( std::make_pair( pos->first, pNote ) );
125        }
126
127        return newPat;
128}
129
130
131
132void Pattern::dump()
133{
134        INFOLOG( "Pattern dump" );
135        INFOLOG( "Pattern name: " + __name );
136        INFOLOG( "Pattern category: " + __category );
137        INFOLOG( "Pattern lenght: " + to_string( get_lenght() ) );
138}
139
140
141
142// ::::::::::::::::::::::::
143
144
145
146PatternList::PatternList()
147                : Object( "PatternList" )
148{
149//      infoLog("Init");
150}
151
152
153
154PatternList::~PatternList()
155{
156//      infoLog("destroy");
157
158        // find single patterns. (skip duplicates)
159        std::vector<Pattern*> temp;
160        for ( unsigned int i = 0; i < list.size(); ++i ) {
161                Pattern *pat = list[i];
162
163                // pat exists in temp?
164                bool exists = false;
165                for ( unsigned int j = 0; j < temp.size(); ++j ) {
166                        if ( pat == temp[j] ) {
167                                exists = true;
168                                break;
169                        }
170                }
171                if ( !exists ) {
172                        temp.push_back( pat );
173                }
174        }
175
176        // delete patterns
177        for ( unsigned int i = 0; i < temp.size(); ++i ) {
178                Pattern *pat = temp[i];
179                if ( pat != NULL ) {
180                        delete pat;
181                        pat = NULL;
182                }
183        }
184}
185
186
187
188void PatternList::add( Pattern* newPattern )
189{
190        list.push_back( newPattern );
191}
192
193
194
195Pattern* PatternList::get( int nPos )
196{
197        if ( nPos >= ( int )list.size() ) {
198                ERRORLOG( "Pattern index out of bounds. nPos > list.size() - " + to_string( nPos ) + " > " + to_string( list.size() ) );
199                return NULL;
200        }
201//      assert( nPos < (int)list.size() );
202        return list[ nPos ];
203}
204
205
206
207unsigned PatternList::get_size()
208{
209        return list.size();
210}
211
212
213
214void PatternList::clear()
215{
216        list.clear();
217}
218
219
220
221/// Replace an existent pattern with another one
222void PatternList::replace( Pattern* newPattern, unsigned int pos )
223{
224        if ( pos >= ( unsigned )list.size() ) {
225                ERRORLOG( "Pattern index out of bounds in PatternList::replace. pos >= list.size() - " + to_string( pos ) + " > " + to_string( list.size() ) );
226                return;
227        }
228        list.insert( list.begin() + pos, newPattern );  // insert the new pattern
229        // remove the old pattern
230        list.erase( list.begin() + pos + 1 );
231}
232
233
234
235int PatternList::index_of( Pattern* pattern )
236{
237        int r = 0;
238        if ( get_size() < 1 ) return -1;
239
240        std::vector<Pattern*>::iterator i;
241
242        for ( i = list.begin(); i != list.end(); ++i ) {
243                if ( *i == pattern ) return r;
244                r++;
245        }
246        return -1;
247}
248
249
250
251/// Remove a pattern from the list (every instance in the list), the pattern is not deleted!!!
252Pattern * PatternList::del( Pattern * p )
253{
254        bool did_delete = false;
255        if ( get_size() < 1 ) return NULL;
256
257        std::vector<Pattern*>::iterator i;
258
259        for ( i = list.begin(); i != list.end(); i++ ) {
260                if ( *i == p ) {
261                        i = list.erase( i );
262                        did_delete = true;
263                        break; // 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...
264                        // ... or roll back the iterator after deleting :
265//                      i--;
266                }
267        }
268        if ( did_delete ) return p;
269        return NULL;
270}
271
272
273
274/// Remove one pattern from the list, the pattern is not deleted!!!
275void PatternList::del( unsigned pos )
276{
277        if ( pos >= ( unsigned )list.size() ) {
278                ERRORLOG( "Pattern index out of bounds in PatternList::del. pos >= list.size() - " + to_string( pos ) + " > " + to_string( list.size() ) );
279                return;
280        }
281        list.erase( list.begin()+pos );
282}
283
284
285};
Note: See TracBrowser for help on using the browser.