/[svn]/qsampler/trunk/src/qsamplerChannel.cpp
ViewVC logotype

Annotation of /qsampler/trunk/src/qsamplerChannel.cpp

Parent Directory Parent Directory | Revision Log Revision Log


Revision 4062 - (hide annotations) (download)
Sat Sep 9 09:55:05 2023 UTC (6 months, 1 week ago) by capela
File size: 29508 byte(s)
* An End-of-Summer'23 Release (v0.9.11)
1 capela 264 // qsamplerChannel.cpp
2     //
3     /****************************************************************************
4 capela 4062 Copyright (C) 2004-2023, rncbc aka Rui Nuno Capela. All rights reserved.
5 schoenebeck 1668 Copyright (C) 2007, 2008 Christian Schoenebeck
6 capela 264
7     This program is free software; you can redistribute it and/or
8     modify it under the terms of the GNU General Public License
9     as published by the Free Software Foundation; either version 2
10     of the License, or (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 capela 920 You should have received a copy of the GNU General Public License along
18     with this program; if not, write to the Free Software Foundation, Inc.,
19     51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
20 capela 264
21     *****************************************************************************/
22    
23 capela 758 #include "qsamplerAbout.h"
24 capela 264 #include "qsamplerChannel.h"
25 capela 1499 #include "qsamplerUtilities.h"
26 capela 264
27     #include "qsamplerMainForm.h"
28 capela 303 #include "qsamplerChannelForm.h"
29 capela 264
30 capela 1499 #include <QFileInfo>
31     #include <QComboBox>
32 capela 264
33 capela 299 #ifdef CONFIG_LIBGIG
34 capela 3855 #if defined(Q_CC_GNU) || defined(Q_CC_MINGW)
35 capela 3849 #pragma GCC diagnostic push
36     #pragma GCC diagnostic ignored "-Wunused-parameter"
37 capela 3855 #endif
38 capela 299 #include "gig.h"
39 capela 2647 #ifdef CONFIG_LIBGIG_SF2
40 capela 3849 #pragma GCC diagnostic ignored "-Wunused-variable"
41 capela 2563 #include "SF.h"
42 capela 299 #endif
43 capela 3855 #if defined(Q_CC_GNU) || defined(Q_CC_MINGW)
44 capela 3849 #pragma GCC diagnostic pop
45 capela 2646 #endif
46 capela 3855 #endif
47 capela 299
48 capela 1558 namespace QSampler {
49    
50 capela 2563 #define QSAMPLER_INSTRUMENT_MAX 128
51 capela 299
52 schoenebeck 1490 #define UNICODE_RIGHT_ARROW QChar(char(0x92), char(0x21))
53    
54 capela 1499
55 capela 264 //-------------------------------------------------------------------------
56 capela 1558 // QSampler::Channel - Sampler channel structure.
57 capela 264 //
58    
59     // Constructor.
60 capela 1558 Channel::Channel ( int iChannelID )
61 capela 264 {
62 capela 467 m_iChannelID = iChannelID;
63 capela 264
64 capela 388 // m_sEngineName = noEngineName();
65     // m_sInstrumentName = noInstrumentName();
66 capela 344 // m_sInstrumentFile = m_sInstrumentName;
67 capela 467 m_iInstrumentNr = -1;
68     m_iInstrumentStatus = -1;
69 capela 490 m_sMidiDriver = "ALSA";
70 capela 467 m_iMidiDevice = -1;
71     m_iMidiPort = -1;
72     m_iMidiChannel = -1;
73 capela 980 m_iMidiMap = -1;
74 capela 490 m_sAudioDriver = "ALSA";
75 capela 467 m_iAudioDevice = -1;
76 capela 1510 m_fVolume = 0.0f;
77 capela 751 m_bMute = false;
78     m_bSolo = false;
79 capela 264 }
80    
81     // Default destructor.
82 capela 1558 Channel::~Channel (void)
83 capela 264 {
84     }
85    
86    
87 capela 295 // Create a new sampler channel, if not already.
88 capela 1558 bool Channel::addChannel (void)
89 capela 295 {
90 schoenebeck 1461 MainForm* pMainForm = MainForm::getInstance();
91 capela 3555 if (pMainForm == nullptr)
92 capela 467 return false;
93 capela 3555 if (pMainForm->client() == nullptr)
94 capela 961 return false;
95 capela 295
96 capela 467 // Are we a new channel?
97     if (m_iChannelID < 0) {
98 capela 961 m_iChannelID = ::lscp_add_channel(pMainForm->client());
99 capela 467 if (m_iChannelID < 0) {
100     appendMessagesClient("lscp_add_channel");
101 capela 961 appendMessagesError(
102     QObject::tr("Could not add channel.\n\nSorry."));
103 capela 467 } // Otherwise it's created...
104     else appendMessages(QObject::tr("added."));
105     }
106 capela 295
107 capela 467 // Return whether we're a valid channel...
108     return (m_iChannelID >= 0);
109 capela 295 }
110    
111    
112     // Remove sampler channel.
113 capela 1558 bool Channel::removeChannel (void)
114 capela 295 {
115 schoenebeck 1461 MainForm *pMainForm = MainForm::getInstance();
116 capela 3555 if (pMainForm == nullptr)
117 capela 467 return false;
118 capela 3555 if (pMainForm->client() == nullptr)
119 capela 961 return false;
120 capela 295
121 capela 467 // Are we an existing channel?
122     if (m_iChannelID >= 0) {
123 capela 961 if (::lscp_remove_channel(pMainForm->client(), m_iChannelID) != LSCP_OK) {
124 capela 467 appendMessagesClient("lscp_remove_channel");
125     appendMessagesError(QObject::tr("Could not remove channel.\n\nSorry."));
126     } else {
127     // Otherwise it's removed.
128     appendMessages(QObject::tr("removed."));
129     m_iChannelID = -1;
130     }
131     }
132 capela 490
133 capela 467 // Return whether we've removed the channel...
134     return (m_iChannelID < 0);
135 capela 295 }
136    
137    
138 capela 264 // Channel-ID (aka Sammpler-Channel) accessors.
139 capela 1558 int Channel::channelID (void) const
140 capela 264 {
141 capela 467 return m_iChannelID;
142 capela 264 }
143    
144 capela 1558 void Channel::setChannelID ( int iChannelID )
145 capela 264 {
146 capela 467 m_iChannelID = iChannelID;
147 capela 264 }
148    
149    
150 capela 295 // Readable channel name.
151 capela 1558 QString Channel::channelName (void) const
152 capela 295 {
153 capela 467 return (m_iChannelID < 0 ? QObject::tr("New Channel") : QObject::tr("Channel %1").arg(m_iChannelID));
154 capela 295 }
155    
156    
157 capela 264 // Engine name accessors.
158 capela 1558 const QString& Channel::engineName (void) const
159 capela 264 {
160 capela 467 return m_sEngineName;
161 capela 264 }
162    
163 capela 1558 bool Channel::loadEngine ( const QString& sEngineName )
164 capela 264 {
165 schoenebeck 1461 MainForm *pMainForm = MainForm::getInstance();
166 capela 3555 if (pMainForm == nullptr)
167 capela 467 return false;
168 capela 3555 if (pMainForm->client() == nullptr || m_iChannelID < 0)
169 capela 961 return false;
170 capela 400 if (m_iInstrumentStatus == 100 && m_sEngineName == sEngineName)
171 capela 467 return true;
172 capela 490
173 capela 1499 if (::lscp_load_engine(pMainForm->client(),
174     sEngineName.toUtf8().constData(), m_iChannelID) != LSCP_OK) {
175 capela 467 appendMessagesClient("lscp_load_engine");
176     return false;
177     }
178 capela 961
179 capela 467 appendMessages(QObject::tr("Engine: %1.").arg(sEngineName));
180 capela 264
181 capela 467 m_sEngineName = sEngineName;
182     return true;
183 capela 264 }
184    
185    
186     // Instrument filename accessor.
187 capela 1558 const QString& Channel::instrumentFile (void) const
188 capela 264 {
189 capela 467 return m_sInstrumentFile;
190 capela 264 }
191    
192     // Instrument index accessor.
193 capela 1558 int Channel::instrumentNr (void) const
194 capela 264 {
195 capela 467 return m_iInstrumentNr;
196 capela 264 }
197    
198 capela 382 // Instrument name accessor.
199 capela 1558 const QString& Channel::instrumentName (void) const
200 capela 382 {
201 capela 467 return m_sInstrumentName;
202 capela 382 }
203    
204 capela 264 // Instrument status accessor.
205 capela 1558 int Channel::instrumentStatus (void) const
206 capela 264 {
207 capela 467 return m_iInstrumentStatus;
208 capela 264 }
209    
210     // Instrument file loader.
211 capela 1558 bool Channel::loadInstrument ( const QString& sInstrumentFile, int iInstrumentNr )
212 capela 264 {
213 schoenebeck 1461 MainForm *pMainForm = MainForm::getInstance();
214 capela 3555 if (pMainForm == nullptr)
215 capela 467 return false;
216 capela 3555 if (pMainForm->client() == nullptr || m_iChannelID < 0)
217 capela 961 return false;
218 capela 2108 if (!QFileInfo(sInstrumentFile).exists())
219 capela 467 return false;
220 capela 2108 if (m_iInstrumentStatus == 100
221     && m_sInstrumentFile == sInstrumentFile
222     && m_iInstrumentNr == iInstrumentNr)
223 capela 467 return true;
224 capela 264
225 capela 2108 if (::lscp_load_instrument_non_modal(
226 schoenebeck 1386 pMainForm->client(),
227 capela 1499 qsamplerUtilities::lscpEscapePath(
228 capela 3914 sInstrumentFile).constData(),
229 schoenebeck 1386 iInstrumentNr, m_iChannelID
230 capela 2108 ) != LSCP_OK) {
231 capela 467 appendMessagesClient("lscp_load_instrument");
232     return false;
233     }
234 capela 264
235 capela 467 appendMessages(QObject::tr("Instrument: \"%1\" (%2).")
236 capela 404 .arg(sInstrumentFile).arg(iInstrumentNr));
237 capela 490
238 capela 467 return setInstrument(sInstrumentFile, iInstrumentNr);
239 capela 388 }
240    
241    
242     // Special instrument file/name/number settler.
243 capela 1558 bool Channel::setInstrument ( const QString& sInstrumentFile, int iInstrumentNr )
244 capela 388 {
245 capela 467 m_sInstrumentFile = sInstrumentFile;
246     m_iInstrumentNr = iInstrumentNr;
247 capela 382 #ifdef CONFIG_INSTRUMENT_NAME
248 capela 3518 m_sInstrumentName.clear(); // We'll get it, maybe later, on channel_info...
249 capela 382 #else
250 capela 467 m_sInstrumentName = getInstrumentName(sInstrumentFile, iInstrumentNr, true);
251 capela 382 #endif
252 capela 467 m_iInstrumentStatus = 0;
253 capela 264
254 capela 388 return true;
255 capela 264 }
256    
257    
258     // MIDI driver type accessors (DEPRECATED).
259 capela 1558 const QString& Channel::midiDriver (void) const
260 capela 264 {
261 capela 467 return m_sMidiDriver;
262 capela 264 }
263    
264 capela 1558 bool Channel::setMidiDriver ( const QString& sMidiDriver )
265 capela 264 {
266 schoenebeck 1461 MainForm *pMainForm = MainForm::getInstance();
267 capela 3555 if (pMainForm == nullptr)
268 capela 467 return false;
269 capela 3555 if (pMainForm->client() == nullptr || m_iChannelID < 0)
270 capela 961 return false;
271 capela 400 if (m_iInstrumentStatus == 100 && m_sMidiDriver == sMidiDriver)
272 capela 467 return true;
273 capela 264
274 capela 1499 if (::lscp_set_channel_midi_type(pMainForm->client(),
275     m_iChannelID, sMidiDriver.toUtf8().constData()) != LSCP_OK) {
276 capela 467 appendMessagesClient("lscp_set_channel_midi_type");
277     return false;
278     }
279 capela 264
280 capela 467 appendMessages(QObject::tr("MIDI driver: %1.").arg(sMidiDriver));
281 capela 404
282 capela 467 m_sMidiDriver = sMidiDriver;
283     return true;
284 capela 264 }
285    
286    
287     // MIDI device accessors.
288 capela 1558 int Channel::midiDevice (void) const
289 capela 264 {
290 capela 467 return m_iMidiDevice;
291 capela 264 }
292    
293 capela 1558 bool Channel::setMidiDevice ( int iMidiDevice )
294 capela 264 {
295 schoenebeck 1461 MainForm *pMainForm = MainForm::getInstance();
296 capela 3555 if (pMainForm == nullptr)
297 capela 467 return false;
298 capela 3555 if (pMainForm->client() == nullptr || m_iChannelID < 0)
299 capela 961 return false;
300 capela 400 if (m_iInstrumentStatus == 100 && m_iMidiDevice == iMidiDevice)
301 capela 467 return true;
302 capela 264
303 capela 961 if (::lscp_set_channel_midi_device(pMainForm->client(), m_iChannelID, iMidiDevice) != LSCP_OK) {
304 capela 467 appendMessagesClient("lscp_set_channel_midi_device");
305     return false;
306     }
307 capela 264
308 capela 467 appendMessages(QObject::tr("MIDI device: %1.").arg(iMidiDevice));
309 capela 404
310 capela 467 m_iMidiDevice = iMidiDevice;
311     return true;
312 capela 264 }
313    
314    
315     // MIDI port number accessor.
316 capela 1558 int Channel::midiPort (void) const
317 capela 264 {
318 capela 467 return m_iMidiPort;
319 capela 264 }
320    
321 capela 1558 bool Channel::setMidiPort ( int iMidiPort )
322 capela 264 {
323 schoenebeck 1461 MainForm *pMainForm = MainForm::getInstance();
324 capela 3555 if (pMainForm == nullptr)
325 capela 467 return false;
326 capela 3555 if (pMainForm->client() == nullptr || m_iChannelID < 0)
327 capela 961 return false;
328 capela 400 if (m_iInstrumentStatus == 100 && m_iMidiPort == iMidiPort)
329 capela 467 return true;
330 capela 264
331 capela 961 if (::lscp_set_channel_midi_port(pMainForm->client(), m_iChannelID, iMidiPort) != LSCP_OK) {
332 capela 467 appendMessagesClient("lscp_set_channel_midi_port");
333     return false;
334     }
335 capela 264
336 capela 467 appendMessages(QObject::tr("MIDI port: %1.").arg(iMidiPort));
337 capela 404
338 capela 467 m_iMidiPort = iMidiPort;
339     return true;
340 capela 264 }
341    
342    
343     // MIDI channel accessor.
344 capela 1558 int Channel::midiChannel (void) const
345 capela 264 {
346 capela 467 return m_iMidiChannel;
347 capela 264 }
348    
349 capela 1558 bool Channel::setMidiChannel ( int iMidiChannel )
350 capela 264 {
351 schoenebeck 1461 MainForm *pMainForm = MainForm::getInstance();
352 capela 3555 if (pMainForm == nullptr)
353 capela 467 return false;
354 capela 3555 if (pMainForm->client() == nullptr || m_iChannelID < 0)
355 capela 961 return false;
356 capela 400 if (m_iInstrumentStatus == 100 && m_iMidiChannel == iMidiChannel)
357 capela 467 return true;
358 capela 264
359 capela 961 if (::lscp_set_channel_midi_channel(pMainForm->client(), m_iChannelID, iMidiChannel) != LSCP_OK) {
360 capela 467 appendMessagesClient("lscp_set_channel_midi_channel");
361     return false;
362     }
363 capela 264
364 capela 467 appendMessages(QObject::tr("MIDI channel: %1.").arg(iMidiChannel));
365 capela 404
366 capela 467 m_iMidiChannel = iMidiChannel;
367     return true;
368 capela 264 }
369    
370    
371 capela 980 // MIDI instrument map accessor.
372 capela 1558 int Channel::midiMap (void) const
373 capela 980 {
374     return m_iMidiMap;
375     }
376    
377 capela 1558 bool Channel::setMidiMap ( int iMidiMap )
378 capela 980 {
379 schoenebeck 1461 MainForm *pMainForm = MainForm::getInstance();
380 capela 3555 if (pMainForm == nullptr)
381 capela 980 return false;
382 capela 3555 if (pMainForm->client() == nullptr || m_iChannelID < 0)
383 capela 980 return false;
384     if (m_iInstrumentStatus == 100 && m_iMidiMap == iMidiMap)
385     return true;
386     #ifdef CONFIG_MIDI_INSTRUMENT
387     if (::lscp_set_channel_midi_map(pMainForm->client(), m_iChannelID, iMidiMap) != LSCP_OK) {
388     appendMessagesClient("lscp_set_channel_midi_map");
389     return false;
390     }
391     #endif
392     appendMessages(QObject::tr("MIDI map: %1.").arg(iMidiMap));
393    
394     m_iMidiMap = iMidiMap;
395     return true;
396     }
397    
398    
399 capela 264 // Audio device accessor.
400 capela 1558 int Channel::audioDevice (void) const
401 capela 264 {
402 capela 467 return m_iAudioDevice;
403 capela 264 }
404    
405 capela 1558 bool Channel::setAudioDevice ( int iAudioDevice )
406 capela 264 {
407 schoenebeck 1461 MainForm *pMainForm = MainForm::getInstance();
408 capela 3555 if (pMainForm == nullptr)
409 capela 467 return false;
410 capela 3555 if (pMainForm->client() == nullptr || m_iChannelID < 0)
411 capela 961 return false;
412 capela 400 if (m_iInstrumentStatus == 100 && m_iAudioDevice == iAudioDevice)
413 capela 467 return true;
414 capela 264
415 capela 961 if (::lscp_set_channel_audio_device(pMainForm->client(), m_iChannelID, iAudioDevice) != LSCP_OK) {
416 capela 467 appendMessagesClient("lscp_set_channel_audio_device");
417     return false;
418     }
419 capela 264
420 capela 467 appendMessages(QObject::tr("Audio device: %1.").arg(iAudioDevice));
421 capela 404
422 capela 467 m_iAudioDevice = iAudioDevice;
423     return true;
424 capela 264 }
425    
426    
427     // Audio driver type accessors (DEPRECATED).
428 capela 1558 const QString& Channel::audioDriver (void) const
429 capela 264 {
430 capela 467 return m_sAudioDriver;
431 capela 264 }
432    
433 capela 1558 bool Channel::setAudioDriver ( const QString& sAudioDriver )
434 capela 264 {
435 schoenebeck 1461 MainForm *pMainForm = MainForm::getInstance();
436 capela 3555 if (pMainForm == nullptr)
437 capela 467 return false;
438 capela 3555 if (pMainForm->client() == nullptr || m_iChannelID < 0)
439 capela 961 return false;
440 capela 400 if (m_iInstrumentStatus == 100 && m_sAudioDriver == sAudioDriver)
441 capela 467 return true;
442 capela 264
443 capela 1499 if (::lscp_set_channel_audio_type(pMainForm->client(),
444     m_iChannelID, sAudioDriver.toUtf8().constData()) != LSCP_OK) {
445 capela 467 appendMessagesClient("lscp_set_channel_audio_type");
446     return false;
447     }
448 capela 264
449 capela 467 appendMessages(QObject::tr("Audio driver: %1.").arg(sAudioDriver));
450 capela 404
451 capela 467 m_sAudioDriver = sAudioDriver;
452     return true;
453 capela 264 }
454    
455    
456     // Channel volume accessors.
457 capela 1558 float Channel::volume (void) const
458 capela 264 {
459 capela 467 return m_fVolume;
460 capela 264 }
461    
462 capela 1558 bool Channel::setVolume ( float fVolume )
463 capela 264 {
464 schoenebeck 1461 MainForm *pMainForm = MainForm::getInstance();
465 capela 3555 if (pMainForm == nullptr)
466 capela 467 return false;
467 capela 3555 if (pMainForm->client() == nullptr || m_iChannelID < 0)
468 capela 961 return false;
469 capela 400 if (m_iInstrumentStatus == 100 && m_fVolume == fVolume)
470 capela 467 return true;
471 capela 264
472 capela 961 if (::lscp_set_channel_volume(pMainForm->client(), m_iChannelID, fVolume) != LSCP_OK) {
473 capela 467 appendMessagesClient("lscp_set_channel_volume");
474     return false;
475     }
476 capela 264
477 capela 467 appendMessages(QObject::tr("Volume: %1.").arg(fVolume));
478 capela 404
479 capela 467 m_fVolume = fVolume;
480     return true;
481 capela 264 }
482    
483    
484 capela 751 // Sampler channel mute state.
485 capela 1558 bool Channel::channelMute (void) const
486 capela 751 {
487     return m_bMute;
488     }
489    
490 capela 1558 bool Channel::setChannelMute ( bool bMute )
491 capela 751 {
492 schoenebeck 1461 MainForm *pMainForm = MainForm::getInstance();
493 capela 3555 if (pMainForm == nullptr)
494 capela 751 return false;
495 capela 3555 if (pMainForm->client() == nullptr || m_iChannelID < 0)
496 capela 961 return false;
497 capela 751 if (m_iInstrumentStatus == 100 && ((m_bMute && bMute) || (!m_bMute && !bMute)))
498     return true;
499    
500     #ifdef CONFIG_MUTE_SOLO
501 capela 961 if (::lscp_set_channel_mute(pMainForm->client(), m_iChannelID, bMute) != LSCP_OK) {
502 capela 751 appendMessagesClient("lscp_set_channel_mute");
503     return false;
504     }
505     appendMessages(QObject::tr("Mute: %1.").arg((int) bMute));
506     m_bMute = bMute;
507     return true;
508     #else
509     return false;
510     #endif
511     }
512    
513    
514     // Sampler channel solo state.
515 capela 1558 bool Channel::channelSolo (void) const
516 capela 751 {
517     return m_bSolo;
518     }
519    
520 capela 1558 bool Channel::setChannelSolo ( bool bSolo )
521 capela 751 {
522 schoenebeck 1461 MainForm *pMainForm = MainForm::getInstance();
523 capela 3555 if (pMainForm == nullptr)
524 capela 751 return false;
525 capela 3555 if (pMainForm->client() == nullptr || m_iChannelID < 0)
526 capela 961 return false;
527 capela 751 if (m_iInstrumentStatus == 100 && ((m_bSolo && bSolo) || (!m_bSolo && !bSolo)))
528     return true;
529    
530     #ifdef CONFIG_MUTE_SOLO
531 capela 961 if (::lscp_set_channel_solo(pMainForm->client(), m_iChannelID, bSolo) != LSCP_OK) {
532 capela 751 appendMessagesClient("lscp_set_channel_solo");
533     return false;
534     }
535     appendMessages(QObject::tr("Solo: %1.").arg((int) bSolo));
536     m_bSolo = bSolo;
537     return true;
538     #else
539     return false;
540     #endif
541     }
542    
543    
544 capela 758 // Audio routing accessors.
545 capela 1558 int Channel::audioChannel ( int iAudioOut ) const
546 capela 758 {
547     return m_audioRouting[iAudioOut];
548     }
549    
550 capela 1558 bool Channel::setAudioChannel ( int iAudioOut, int iAudioIn )
551 capela 758 {
552 schoenebeck 1461 MainForm *pMainForm = MainForm::getInstance();
553 capela 3555 if (pMainForm == nullptr)
554 capela 758 return false;
555 capela 3555 if (pMainForm->client() == nullptr || m_iChannelID < 0)
556 capela 961 return false;
557 capela 758 if (m_iInstrumentStatus == 100 &&
558     m_audioRouting[iAudioOut] == iAudioIn)
559     return true;
560    
561 capela 961 if (::lscp_set_channel_audio_channel(pMainForm->client(),
562 capela 758 m_iChannelID, iAudioOut, iAudioIn) != LSCP_OK) {
563     appendMessagesClient("lscp_set_channel_audio_channel");
564     return false;
565     }
566    
567     appendMessages(QObject::tr("Audio Channel: %1 -> %2.")
568     .arg(iAudioOut).arg(iAudioIn));
569    
570     m_audioRouting[iAudioOut] = iAudioIn;
571     return true;
572     }
573    
574     // The audio routing map itself.
575 capela 1558 const ChannelRoutingMap& Channel::audioRouting (void) const
576 capela 758 {
577     return m_audioRouting;
578     }
579    
580    
581 capela 371 // Istrument name remapper.
582 capela 1558 void Channel::updateInstrumentName (void)
583 capela 371 {
584 capela 382 #ifndef CONFIG_INSTRUMENT_NAME
585 capela 3898 Options *pOptions = nullptr;
586     MainForm *pMainForm = MainForm::getInstance();
587     if (pMainForm)
588     pOptions = pMainForm->options();
589 capela 371 m_sInstrumentName = getInstrumentName(m_sInstrumentFile,
590 capela 3898 m_iInstrumentNr, (pOptions && pOptions->bInstrumentNames));
591 capela 382 #endif
592 capela 371 }
593    
594    
595 capela 264 // Update whole channel info state.
596 capela 1558 bool Channel::updateChannelInfo (void)
597 capela 264 {
598 schoenebeck 1461 MainForm *pMainForm = MainForm::getInstance();
599 capela 3555 if (pMainForm == nullptr)
600 capela 467 return false;
601 capela 3555 if (pMainForm->client() == nullptr || m_iChannelID < 0)
602 capela 961 return false;
603 capela 264
604 capela 467 // Read channel information.
605 capela 961 lscp_channel_info_t *pChannelInfo = ::lscp_get_channel_info(pMainForm->client(), m_iChannelID);
606 capela 3555 if (pChannelInfo == nullptr) {
607 capela 467 appendMessagesClient("lscp_get_channel_info");
608     appendMessagesError(QObject::tr("Could not get channel information.\n\nSorry."));
609     return false;
610     }
611 capela 295
612 capela 382 #ifdef CONFIG_INSTRUMENT_NAME
613     // We got all actual instrument datum...
614 schoenebeck 1402 m_sInstrumentFile =
615     qsamplerUtilities::lscpEscapedPathToPosix(pChannelInfo->instrument_file);
616 capela 382 m_iInstrumentNr = pChannelInfo->instrument_nr;
617 schoenebeck 1402 m_sInstrumentName =
618     qsamplerUtilities::lscpEscapedTextToRaw(pChannelInfo->instrument_name);
619 capela 382 #else
620 capela 371 // First, check if intrument name has changed,
621     // taking care that instrument name lookup might be expensive,
622     // so we better make it only once and when really needed...
623     if ((m_sInstrumentFile != pChannelInfo->instrument_file) ||
624     (m_iInstrumentNr != pChannelInfo->instrument_nr)) {
625     m_sInstrumentFile = pChannelInfo->instrument_file;
626     m_iInstrumentNr = pChannelInfo->instrument_nr;
627     updateInstrumentName();
628 capela 344 }
629 capela 382 #endif
630 capela 467 // Cache in other channel information.
631     m_sEngineName = pChannelInfo->engine_name;
632     m_iInstrumentStatus = pChannelInfo->instrument_status;
633     m_iMidiDevice = pChannelInfo->midi_device;
634     m_iMidiPort = pChannelInfo->midi_port;
635     m_iMidiChannel = pChannelInfo->midi_channel;
636 capela 980 #ifdef CONFIG_MIDI_INSTRUMENT
637     m_iMidiMap = pChannelInfo->midi_map;
638     #endif
639 capela 467 m_iAudioDevice = pChannelInfo->audio_device;
640     m_fVolume = pChannelInfo->volume;
641 capela 751 #ifdef CONFIG_MUTE_SOLO
642     m_bMute = pChannelInfo->mute;
643     m_bSolo = pChannelInfo->solo;
644     #endif
645 capela 467 // Some sanity checks.
646     if (m_sEngineName == "NONE" || m_sEngineName.isEmpty())
647 capela 3518 m_sEngineName.clear();
648 capela 467 if (m_sInstrumentFile == "NONE" || m_sInstrumentFile.isEmpty()) {
649 capela 3518 m_sInstrumentFile.clear();
650     m_sInstrumentName.clear();
651 capela 344 }
652 capela 490
653     // Time for device info grabbing...
654 capela 414 lscp_device_info_t *pDeviceInfo;
655     const QString sNone = QObject::tr("(none)");
656     // Audio device driver type.
657 capela 961 pDeviceInfo = ::lscp_get_audio_device_info(pMainForm->client(), m_iAudioDevice);
658 capela 3555 if (pDeviceInfo == nullptr) {
659 capela 467 appendMessagesClient("lscp_get_audio_device_info");
660 capela 414 m_sAudioDriver = sNone;
661     } else {
662     m_sAudioDriver = pDeviceInfo->driver;
663     }
664     // MIDI device driver type.
665 capela 961 pDeviceInfo = ::lscp_get_midi_device_info(pMainForm->client(), m_iMidiDevice);
666 capela 3555 if (pDeviceInfo == nullptr) {
667 capela 467 appendMessagesClient("lscp_get_midi_device_info");
668 capela 414 m_sMidiDriver = sNone;
669     } else {
670     m_sMidiDriver = pDeviceInfo->driver;
671     }
672 capela 295
673 capela 758 // Set the audio routing map.
674     m_audioRouting.clear();
675 capela 1022 #ifdef CONFIG_AUDIO_ROUTING
676     int *piAudioRouting = pChannelInfo->audio_routing;
677     for (int i = 0; piAudioRouting && piAudioRouting[i] >= 0; i++)
678     m_audioRouting[i] = piAudioRouting[i];
679     #else
680     char **ppszAudioRouting = pChannelInfo->audio_routing;
681     for (int i = 0; ppszAudioRouting && ppszAudioRouting[i]; i++)
682     m_audioRouting[i] = ::atoi(ppszAudioRouting[i]);
683     #endif
684 capela 758
685 capela 467 return true;
686 capela 264 }
687    
688    
689     // Reset channel method.
690 capela 1558 bool Channel::channelReset (void)
691 capela 264 {
692 schoenebeck 1461 MainForm *pMainForm = MainForm::getInstance();
693 capela 3555 if (pMainForm == nullptr)
694 capela 467 return false;
695 capela 3555 if (pMainForm->client() == nullptr || m_iChannelID < 0)
696 capela 961 return false;
697 capela 264
698 capela 961 if (::lscp_reset_channel(pMainForm->client(), m_iChannelID) != LSCP_OK) {
699 capela 467 appendMessagesClient("lscp_reset_channel");
700     return false;
701     }
702 capela 295
703 capela 467 appendMessages(QObject::tr("reset."));
704 capela 404
705 capela 467 return true;
706 capela 264 }
707    
708    
709 schoenebeck 1366 // Spawn instrument editor method.
710 capela 1558 bool Channel::editChannel (void)
711 schoenebeck 1366 {
712     #ifdef CONFIG_EDIT_INSTRUMENT
713 capela 1372
714 schoenebeck 1461 MainForm *pMainForm = MainForm::getInstance();
715 capela 3555 if (pMainForm == nullptr)
716 schoenebeck 1366 return false;
717 capela 3555 if (pMainForm->client() == nullptr || m_iChannelID < 0)
718 schoenebeck 1366 return false;
719    
720 capela 1414 if (::lscp_edit_channel_instrument(pMainForm->client(), m_iChannelID)
721     != LSCP_OK) {
722     appendMessagesClient("lscp_edit_channel_instrument");
723 capela 1367 appendMessagesError(QObject::tr(
724     "Could not launch an appropriate instrument editor "
725 capela 1528 "for the given instrument!\n\n"
726 capela 1372 "Make sure you have an appropriate "
727 capela 1528 "instrument editor like 'gigedit' installed "
728 capela 1372 "and that it placed its mandatory DLL file "
729     "into the sampler's plugin directory.")
730 schoenebeck 1366 );
731     return false;
732     }
733    
734     appendMessages(QObject::tr("edit instrument."));
735    
736     return true;
737 capela 1372
738 schoenebeck 1366 #else
739 capela 1372
740 capela 1367 appendMessagesError(QObject::tr(
741     "Sorry, QSampler was compiled for a version of liblscp "
742 capela 1528 "which lacks this feature.\n\n"
743 capela 1367 "You may want to update liblscp and recompile QSampler afterwards.")
744 schoenebeck 1366 );
745 capela 1372
746 schoenebeck 1366 return false;
747 capela 1372
748 schoenebeck 1366 #endif
749     }
750    
751    
752 capela 303 // Channel setup dialog form.
753 capela 1558 bool Channel::channelSetup ( QWidget *pParent )
754 capela 303 {
755 schoenebeck 1461 MainForm *pMainForm = MainForm::getInstance();
756 capela 3555 if (pMainForm == nullptr)
757 capela 961 return false;
758    
759 capela 467 bool bResult = false;
760 capela 303
761 capela 467 appendMessages(QObject::tr("setup..."));
762 capela 490
763 schoenebeck 1461 ChannelForm *pChannelForm = new ChannelForm(pParent);
764 capela 467 if (pChannelForm) {
765     pChannelForm->setup(this);
766     bResult = pChannelForm->exec();
767     delete pChannelForm;
768     }
769 capela 303
770 capela 467 return bResult;
771 capela 303 }
772    
773    
774 capela 264 // Redirected messages output methods.
775 capela 2722 void Channel::appendMessages ( const QString& sText ) const
776 capela 264 {
777 schoenebeck 1461 MainForm *pMainForm = MainForm::getInstance();
778 capela 961 if (pMainForm)
779 capela 2722 pMainForm->appendMessages(channelName() + ' ' + sText);
780 capela 264 }
781    
782 capela 2722 void Channel::appendMessagesColor (
783 capela 3788 const QString& sText, const QColor& rgb ) const
784 capela 264 {
785 schoenebeck 1461 MainForm *pMainForm = MainForm::getInstance();
786 capela 961 if (pMainForm)
787 capela 3788 pMainForm->appendMessagesColor(channelName() + ' ' + sText, rgb);
788 capela 264 }
789    
790 capela 2722 void Channel::appendMessagesText ( const QString& sText ) const
791 capela 264 {
792 schoenebeck 1461 MainForm *pMainForm = MainForm::getInstance();
793 capela 961 if (pMainForm)
794 capela 2722 pMainForm->appendMessagesText(channelName() + ' ' + sText);
795 capela 264 }
796    
797 capela 2722 void Channel::appendMessagesError ( const QString& sText ) const
798 capela 264 {
799 schoenebeck 1461 MainForm *pMainForm = MainForm::getInstance();
800 capela 961 if (pMainForm)
801 capela 2722 pMainForm->appendMessagesError(channelName() + "\n\n" + sText);
802 capela 264 }
803    
804 capela 2722 void Channel::appendMessagesClient ( const QString& sText ) const
805 capela 264 {
806 schoenebeck 1461 MainForm *pMainForm = MainForm::getInstance();
807 capela 961 if (pMainForm)
808 capela 2722 pMainForm->appendMessagesClient(channelName() + ' ' + sText);
809 capela 264 }
810    
811    
812 capela 303 // Context menu event handler.
813 capela 2722 void Channel::contextMenuEvent ( QContextMenuEvent *pEvent )
814 capela 303 {
815 schoenebeck 1461 MainForm *pMainForm = MainForm::getInstance();
816 capela 961 if (pMainForm)
817     pMainForm->contextMenuEvent(pEvent);
818 capela 303 }
819    
820    
821 capela 2108 // FIXME: Check whether a given file is an instrument file (DLS only).
822     bool Channel::isDlsInstrumentFile ( const QString& sInstrumentFile )
823 capela 388 {
824     bool bResult = false;
825    
826     QFile file(sInstrumentFile);
827 capela 1499 if (file.open(QIODevice::ReadOnly)) {
828 capela 409 char achHeader[16];
829 capela 1499 if (file.read(achHeader, 16) > 0) {
830 capela 409 bResult = (::memcmp(&achHeader[0], "RIFF", 4) == 0
831     && ::memcmp(&achHeader[8], "DLS LIST", 8) == 0);
832 capela 388 }
833     file.close();
834     }
835    
836     return bResult;
837     }
838    
839    
840 capela 2563 // FIXME: Check whether a given file is an instrument file (SF2 only).
841     bool Channel::isSf2InstrumentFile ( const QString& sInstrumentFile )
842     {
843     bool bResult = false;
844    
845     QFile file(sInstrumentFile);
846     if (file.open(QIODevice::ReadOnly)) {
847 capela 2567 char achHeader[12];
848     if (file.read(achHeader, 12) > 0) {
849 capela 2563 bResult = (::memcmp(&achHeader[0], "RIFF", 4) == 0
850 capela 2567 && ::memcmp(&achHeader[8], "sfbk", 4) == 0);
851 capela 2563 }
852     file.close();
853     }
854    
855     return bResult;
856     }
857    
858    
859 capela 299 // Retrieve the instrument list of a instrument file (.gig).
860 capela 2567 QStringList Channel::getInstrumentList (
861 capela 2563 const QString& sInstrumentFile, bool bInstrumentNames )
862 capela 299 {
863 capela 467 QStringList instlist;
864 capela 299
865 capela 2563 const QFileInfo fi(sInstrumentFile);
866     if (!fi.exists()) {
867     instlist.append(noInstrumentName());
868     return instlist;
869     }
870    
871     #ifdef CONFIG_LIBGIG
872     if (bInstrumentNames) {
873     if (isDlsInstrumentFile(sInstrumentFile)) {
874 capela 1499 RIFF::File *pRiff
875     = new RIFF::File(sInstrumentFile.toUtf8().constData());
876 capela 2567 gig::File *pGig = new gig::File(pRiff);
877 capela 2646 #ifdef CONFIG_LIBGIG_SETAUTOLOAD
878 schoenebeck 1527 // prevent sleepy response time on large .gig files
879     pGig->SetAutoLoad(false);
880 capela 2108 #endif
881 capela 4062 int iIndex = 0;
882     gig::Instrument *pInstrument = pGig->GetInstrument(iIndex);
883 capela 467 while (pInstrument) {
884     instlist.append((pInstrument->pInfo)->Name.c_str());
885 capela 4062 pInstrument = pGig->GetInstrument(++iIndex);
886 capela 467 }
887     delete pGig;
888     delete pRiff;
889 capela 341 }
890 capela 2646 #ifdef CONFIG_LIBGIG_SF2
891 capela 2563 else
892     if (isSf2InstrumentFile(sInstrumentFile)) {
893     RIFF::File *pRiff
894     = new RIFF::File(sInstrumentFile.toUtf8().constData());
895     sf2::File *pSf2 = new sf2::File(pRiff);
896     const int iPresetCount = pSf2->GetPresetCount();
897     for (int iIndex = 0; iIndex < iPresetCount; ++iIndex) {
898     sf2::Preset *pPreset = pSf2->GetPreset(iIndex);
899     if (pPreset) {
900     instlist.append(pPreset->Name.c_str());
901     } else {
902     instlist.append(fi.fileName()
903     + " [" + QString::number(iIndex) + "]");
904     }
905     }
906     delete pSf2;
907     delete pRiff;
908     }
909 capela 2646 #endif
910 capela 467 }
911 capela 2563 #endif
912 capela 306
913 capela 2108 if (instlist.isEmpty()) {
914 capela 2563 for (int iIndex = 0; iIndex < QSAMPLER_INSTRUMENT_MAX; ++iIndex) {
915     instlist.append(fi.fileName()
916     + " [" + QString::number(iIndex) + "]");
917 capela 2108 }
918     }
919    
920 capela 467 return instlist;
921 capela 299 }
922    
923    
924     // Retrieve the spacific instrument name of a instrument file (.gig), given its index.
925 capela 2563 QString Channel::getInstrumentName (
926     const QString& sInstrumentFile, int iInstrumentNr, bool bInstrumentNames )
927 capela 299 {
928 capela 2563 const QFileInfo fi(sInstrumentFile);
929     if (!fi.exists())
930     return noInstrumentName();
931    
932 capela 467 QString sInstrumentName;
933 capela 299
934 capela 2563 #ifdef CONFIG_LIBGIG
935     if (bInstrumentNames) {
936     if (isDlsInstrumentFile(sInstrumentFile)) {
937 capela 1499 RIFF::File *pRiff
938     = new RIFF::File(sInstrumentFile.toUtf8().constData());
939     gig::File *pGig = new gig::File(pRiff);
940 capela 2646 #ifdef CONFIG_LIBGIG_SETAUTOLOAD
941 schoenebeck 1527 // prevent sleepy response time on large .gig files
942     pGig->SetAutoLoad(false);
943 capela 2108 #endif
944 capela 467 int iIndex = 0;
945 capela 4062 gig::Instrument *pInstrument = pGig->GetInstrument(iIndex);
946 capela 467 while (pInstrument) {
947     if (iIndex == iInstrumentNr) {
948     sInstrumentName = (pInstrument->pInfo)->Name.c_str();
949     break;
950     }
951 capela 4062 pInstrument = pGig->GetInstrument(++iIndex);
952 capela 467 }
953     delete pGig;
954     delete pRiff;
955 capela 341 }
956 capela 2646 #ifdef CONFIG_LIBGIG_SF2
957 capela 2563 else
958     if (isSf2InstrumentFile(sInstrumentFile)) {
959     RIFF::File *pRiff
960     = new RIFF::File(sInstrumentFile.toUtf8().constData());
961     sf2::File *pSf2 = new sf2::File(pRiff);
962     sf2::Preset *pPreset = pSf2->GetPreset(iInstrumentNr);
963     if (pPreset)
964     sInstrumentName = pPreset->Name.c_str();
965     delete pSf2;
966     delete pRiff;
967     }
968 capela 2646 #endif
969 capela 467 }
970 capela 2563 #endif
971 capela 299
972 capela 2108 if (sInstrumentName.isEmpty()) {
973 capela 2563 sInstrumentName = fi.fileName();
974     sInstrumentName += " [" + QString::number(iInstrumentNr) + "]";
975 capela 2108 }
976    
977 capela 467 return sInstrumentName;
978 capela 299 }
979    
980    
981 capela 388 // Common invalid name-helpers.
982 capela 1558 QString Channel::noEngineName (void)
983 capela 388 {
984     return QObject::tr("(No engine)");
985     }
986    
987 capela 1558 QString Channel::noInstrumentName (void)
988 capela 388 {
989     return QObject::tr("(No instrument)");
990     }
991    
992 capela 1558 QString Channel::loadingInstrument (void) {
993 schoenebeck 519 return QObject::tr("(Loading instrument...)");
994     }
995 capela 388
996 schoenebeck 519
997 capela 758 //-------------------------------------------------------------------------
998 capela 1558 // QSampler::ChannelRoutingModel - data model for audio routing
999     // (used for QTableView)
1000 capela 758
1001 capela 1510 ChannelRoutingModel::ChannelRoutingModel ( QObject *pParent )
1002 capela 3555 : QAbstractTableModel(pParent), m_pDevice(nullptr)
1003 capela 1510 {
1004 schoenebeck 1461 }
1005 capela 767
1006 capela 1510
1007     int ChannelRoutingModel::rowCount ( const QModelIndex& /*parent*/) const
1008     {
1009 schoenebeck 1668 return (m_pDevice) ? m_routing.size() : 0;
1010 schoenebeck 1461 }
1011    
1012 capela 1510
1013     int ChannelRoutingModel::columnCount ( const QModelIndex& /*parent*/) const
1014     {
1015     return 1;
1016 schoenebeck 1461 }
1017    
1018 capela 1510
1019     Qt::ItemFlags ChannelRoutingModel::flags ( const QModelIndex& /*index*/) const
1020     {
1021     return Qt::ItemIsSelectable | Qt::ItemIsEditable | Qt::ItemIsEnabled;
1022 schoenebeck 1489 }
1023    
1024    
1025 capela 1510 bool ChannelRoutingModel::setData ( const QModelIndex& index,
1026     const QVariant& value, int /*role*/)
1027     {
1028     if (!index.isValid())
1029     return false;
1030 schoenebeck 1489
1031 capela 1510 m_routing[index.row()] = value.toInt();
1032    
1033     emit dataChanged(index, index);
1034     return true;
1035 schoenebeck 1489 }
1036    
1037 schoenebeck 1461
1038 capela 1510 QVariant ChannelRoutingModel::data ( const QModelIndex &index, int role ) const
1039     {
1040     if (!index.isValid())
1041     return QVariant();
1042     if (role != Qt::DisplayRole)
1043     return QVariant();
1044     if (index.column() != 0)
1045     return QVariant();
1046 schoenebeck 1461
1047 capela 1510 ChannelRoutingItem item;
1048    
1049     // The common device port item list.
1050 capela 1558 DevicePortList& ports = m_pDevice->ports();
1051     QListIterator<DevicePort *> iter(ports);
1052 capela 1499 while (iter.hasNext()) {
1053 capela 1558 DevicePort *pPort = iter.next();
1054 capela 1510 item.options.append(
1055     m_pDevice->deviceTypeName()
1056     + ' ' + m_pDevice->driverName()
1057     + ' ' + pPort->portName()
1058     );
1059     }
1060 schoenebeck 1461
1061 capela 1510 item.selection = m_routing[index.row()];
1062 schoenebeck 1461
1063 capela 1510 return QVariant::fromValue(item);
1064 schoenebeck 1461 }
1065    
1066    
1067 capela 1510 QVariant ChannelRoutingModel::headerData ( int section,
1068     Qt::Orientation orientation, int role) const
1069     {
1070     if (role != Qt::DisplayRole)
1071     return QVariant();
1072    
1073     switch (orientation) {
1074     case Qt::Horizontal:
1075     return UNICODE_RIGHT_ARROW + QObject::tr(" Device Channel");
1076     case Qt::Vertical:
1077 schoenebeck 1668 return QObject::tr("Audio Channel ") +
1078 capela 1510 QString::number(section) + " " + UNICODE_RIGHT_ARROW;
1079     default:
1080     return QVariant();
1081     }
1082 schoenebeck 1461 }
1083    
1084 capela 1510
1085 capela 1558 void ChannelRoutingModel::refresh ( Device *pDevice,
1086     const ChannelRoutingMap& routing )
1087 schoenebeck 1461 {
1088 capela 1510 m_pDevice = pDevice;
1089     m_routing = routing;
1090     // inform the outer world (QTableView) that our data changed
1091 capela 3520 #if QT_VERSION < QT_VERSION_CHECK(5, 0, 0)
1092 capela 1510 QAbstractTableModel::reset();
1093 capela 2387 #else
1094     QAbstractTableModel::beginResetModel();
1095     QAbstractTableModel::endResetModel();
1096     #endif
1097 schoenebeck 1461 }
1098    
1099    
1100 schoenebeck 1489 //-------------------------------------------------------------------------
1101 capela 1558 // QSampler::ChannelRoutingDelegate - table cell renderer for audio routing
1102 schoenebeck 1489 //
1103 schoenebeck 1461
1104 capela 1510 ChannelRoutingDelegate::ChannelRoutingDelegate ( QObject *pParent )
1105     : QItemDelegate(pParent)
1106     {
1107 schoenebeck 1461 }
1108    
1109 capela 1510
1110     QWidget* ChannelRoutingDelegate::createEditor ( QWidget *pParent,
1111     const QStyleOptionViewItem & option, const QModelIndex& index ) const
1112 schoenebeck 1461 {
1113 capela 1510 if (!index.isValid())
1114 capela 3555 return nullptr;
1115 schoenebeck 1489
1116 capela 1510 if (index.column() != 0)
1117 capela 3555 return nullptr;
1118 schoenebeck 1489
1119 capela 1510 ChannelRoutingItem item = index.model()->data(index, Qt::DisplayRole).value<ChannelRoutingItem>();
1120 schoenebeck 1461
1121 capela 1510 QComboBox* pComboBox = new QComboBox(pParent);
1122     pComboBox->addItems(item.options);
1123     pComboBox->setCurrentIndex(item.selection);
1124     pComboBox->setEnabled(true);
1125 capela 3405 pComboBox->setEditable(true);
1126 capela 1510 pComboBox->setGeometry(option.rect);
1127     return pComboBox;
1128 schoenebeck 1461 }
1129    
1130 capela 1510
1131     void ChannelRoutingDelegate::setEditorData ( QWidget *pEditor,
1132     const QModelIndex &index) const
1133     {
1134     ChannelRoutingItem item = index.model()->data(index,
1135     Qt::DisplayRole).value<ChannelRoutingItem> ();
1136     QComboBox* pComboBox = static_cast<QComboBox*> (pEditor);
1137     pComboBox->setCurrentIndex(item.selection);
1138 schoenebeck 1461 }
1139    
1140 capela 1510
1141     void ChannelRoutingDelegate::setModelData ( QWidget* pEditor,
1142     QAbstractItemModel *pModel, const QModelIndex& index ) const
1143     {
1144     QComboBox *pComboBox = static_cast<QComboBox*> (pEditor);
1145     pModel->setData(index, pComboBox->currentIndex());
1146 schoenebeck 1461 }
1147    
1148 capela 1510
1149     void ChannelRoutingDelegate::updateEditorGeometry ( QWidget *pEditor,
1150     const QStyleOptionViewItem& option, const QModelIndex &/* index */) const
1151 schoenebeck 1461 {
1152 capela 1510 pEditor->setGeometry(option.rect);
1153 schoenebeck 1461 }
1154    
1155 capela 1558 } // namespace QSampler
1156 capela 1510
1157 capela 1558
1158 capela 1465 // end of qsamplerChannel.cpp

  ViewVC Help
Powered by ViewVC