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/basics/instrument_list.h>
24
25 #include <hydrogen/helpers/xml.h>
26 #include <hydrogen/basics/instrument.h>
27
28 #include <set>
29
30 namespace H2Core
31 {
32
33 const char* InstrumentList::__class_name = "InstrumentList";
34
InstrumentList()35 InstrumentList::InstrumentList() : Object( __class_name )
36 {
37 }
38
InstrumentList(InstrumentList * other)39 InstrumentList::InstrumentList( InstrumentList* other ) : Object( __class_name )
40 {
41 assert( __instruments.size() == 0 );
42 for ( int i=0; i<other->size(); i++ ) {
43 ( *this ) << ( new Instrument( ( *other )[i] ) );
44 }
45 }
46
~InstrumentList()47 InstrumentList::~InstrumentList()
48 {
49 for ( int i = 0; i < __instruments.size(); ++i ) {
50 delete __instruments[i];
51 }
52 }
53
load_samples()54 void InstrumentList::load_samples()
55 {
56 for( int i=0; i<__instruments.size(); i++ ) {
57 __instruments[i]->load_samples();
58 }
59 }
60
unload_samples()61 void InstrumentList::unload_samples()
62 {
63 for( int i=0; i<__instruments.size(); i++ ) {
64 __instruments[i]->unload_samples();
65 }
66 }
67
load_from(XMLNode * node,const QString & dk_path,const QString & dk_name)68 InstrumentList* InstrumentList::load_from( XMLNode* node, const QString& dk_path, const QString& dk_name )
69 {
70 InstrumentList* instruments = new InstrumentList();
71 XMLNode instrument_node = node->firstChildElement( "instrument" );
72 int count = 0;
73 while ( !instrument_node.isNull() ) {
74 count++;
75 if ( count > MAX_INSTRUMENTS ) {
76 ERRORLOG( QString( "instrument count >= %2, stop reading instruments" ).arg( MAX_INSTRUMENTS ) );
77 break;
78 }
79 Instrument* instrument = Instrument::load_from( &instrument_node, dk_path, dk_name );
80 if( instrument ) {
81 ( *instruments ) << instrument;
82 } else {
83 ERRORLOG( QString( "Empty ID for instrument %1. The drumkit is corrupted. Skipping instrument" ).arg( count ) );
84 count--;
85 }
86 instrument_node = instrument_node.nextSiblingElement( "instrument" );
87 }
88 return instruments;
89 }
90
save_to(XMLNode * node,int component_id)91 void InstrumentList::save_to( XMLNode* node, int component_id )
92 {
93 XMLNode instruments_node = node->createNode( "instrumentList" );
94 for ( int i = 0; i < size(); i++ ) {
95 ( *this )[i]->save_to( &instruments_node, component_id );
96 }
97 }
98
operator <<(Instrument * instrument)99 void InstrumentList::operator<<( Instrument* instrument )
100 {
101 // do nothing if already in __instruments
102 for( int i=0; i<__instruments.size(); i++ ) {
103 if( __instruments[i]==instrument ) return;
104 }
105 __instruments.push_back( instrument );
106 }
107
add(Instrument * instrument)108 void InstrumentList::add( Instrument* instrument )
109 {
110 // do nothing if already in __instruments
111 for( int i=0; i<__instruments.size(); i++ ) {
112 if( __instruments[i]==instrument ) return;
113 }
114 __instruments.push_back( instrument );
115 }
116
insert(int idx,Instrument * instrument)117 void InstrumentList::insert( int idx, Instrument* instrument )
118 {
119 // do nothing if already in __instruments
120 for( int i=0; i<__instruments.size(); i++ ) {
121 if( __instruments[i]==instrument ) return;
122 }
123 __instruments.insert( __instruments.begin() + idx, instrument );
124 }
125
operator [](int idx)126 Instrument* InstrumentList::operator[]( int idx )
127 {
128 if ( idx < 0 || idx >= __instruments.size() ) {
129 ERRORLOG( QString( "idx %1 out of [0;%2]" ).arg( idx ).arg( size() ) );
130 return nullptr;
131 }
132 assert( idx >= 0 && idx < __instruments.size() );
133 return __instruments[idx];
134 }
135
is_valid_index(int idx) const136 bool InstrumentList::is_valid_index( int idx ) const
137 {
138 bool is_valid_index = true;
139
140 if ( idx < 0 || idx >= __instruments.size() ) {
141 is_valid_index = false;
142 }
143
144 return is_valid_index;
145 }
146
get(int idx)147 Instrument* InstrumentList::get( int idx )
148 {
149 if ( !is_valid_index( idx ) ) {
150 ERRORLOG( QString( "idx %1 out of [0;%2]" ).arg( idx ).arg( size() ) );
151 return nullptr;
152 }
153 assert( idx >= 0 && idx < __instruments.size() );
154 return __instruments[idx];
155 }
156
index(Instrument * instr)157 int InstrumentList::index( Instrument* instr )
158 {
159 for( int i=0; i<__instruments.size(); i++ ) {
160 if ( __instruments[i]==instr ) return i;
161 }
162 return -1;
163 }
164
find(const int id)165 Instrument* InstrumentList::find( const int id )
166 {
167 for( int i=0; i<__instruments.size(); i++ ) {
168 if ( __instruments[i]->get_id()==id ) return __instruments[i];
169 }
170 return nullptr;
171 }
172
find(const QString & name)173 Instrument* InstrumentList::find( const QString& name )
174 {
175 for( int i=0; i<__instruments.size(); i++ ) {
176 if ( __instruments[i]->get_name()==name ) return __instruments[i];
177 }
178 return nullptr;
179 }
180
findMidiNote(const int note)181 Instrument* InstrumentList::findMidiNote( const int note )
182 {
183 for( int i=0; i<__instruments.size(); i++ ) {
184 if ( __instruments[i]->get_midi_out_note()==note ) return __instruments[i];
185 }
186 return nullptr;
187 }
188
del(int idx)189 Instrument* InstrumentList::del( int idx )
190 {
191 assert( idx >= 0 && idx < __instruments.size() );
192 Instrument* instrument = __instruments[idx];
193 __instruments.erase( __instruments.begin() + idx );
194 return instrument;
195 }
196
del(Instrument * instrument)197 Instrument* InstrumentList::del( Instrument* instrument )
198 {
199 for( int i=0; i<__instruments.size(); i++ ) {
200 if( __instruments[i]==instrument ) {
201 __instruments.erase( __instruments.begin() + i );
202 return instrument;
203 }
204 }
205 return nullptr;
206 }
207
swap(int idx_a,int idx_b)208 void InstrumentList::swap( int idx_a, int idx_b )
209 {
210 assert( idx_a >= 0 && idx_a < __instruments.size() );
211 assert( idx_b >= 0 && idx_b < __instruments.size() );
212 if( idx_a == idx_b ) return;
213 //DEBUGLOG(QString("===>> SWAP %1 %2").arg(idx_a).arg(idx_b) );
214 Instrument* tmp = __instruments[idx_a];
215 __instruments[idx_a] = __instruments[idx_b];
216 __instruments[idx_b] = tmp;
217 }
218
move(int idx_a,int idx_b)219 void InstrumentList::move( int idx_a, int idx_b )
220 {
221 assert( idx_a >= 0 && idx_a < __instruments.size() );
222 assert( idx_b >= 0 && idx_b < __instruments.size() );
223 if( idx_a == idx_b ) return;
224 //DEBUGLOG(QString("===>> MOVE %1 %2").arg(idx_a).arg(idx_b) );
225 Instrument* tmp = __instruments[idx_a];
226 __instruments.erase( __instruments.begin() + idx_a );
227 __instruments.insert( __instruments.begin() + idx_b, tmp );
228 }
229
fix_issue_307()230 void InstrumentList::fix_issue_307()
231 {
232 if ( has_all_midi_notes_same() ) {
233 WARNINGLOG( "Same MIDI note assigned to every instrument. Assigning default values." );
234 set_default_midi_out_notes();
235 }
236 }
237
has_all_midi_notes_same() const238 bool InstrumentList::has_all_midi_notes_same() const
239 {
240 if (__instruments.size() < 2) {
241 return false;
242 }
243
244 std::set<int> notes;
245 for( int i=0; i<__instruments.size(); i++ ) {
246 auto instr = __instruments[i];
247 notes.insert( instr->get_midi_out_note() );
248 }
249 return notes.size() == 1;
250 }
251
set_default_midi_out_notes()252 void InstrumentList::set_default_midi_out_notes()
253 {
254 for( int i=0; i<__instruments.size(); i++ ) {
255 __instruments[i]->set_midi_out_note( i + 36 );
256 }
257 }
258
259 };
260
261 /* vim: set softtabstop=4 noexpandtab: */
262