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

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

Parent Directory Parent Directory | Revision Log Revision Log


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

  ViewVC Help
Powered by ViewVC