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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 4062 - (show 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 // qsamplerChannel.cpp
2 //
3 /****************************************************************************
4 Copyright (C) 2004-2023, 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).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 Options *pOptions = nullptr;
586 MainForm *pMainForm = MainForm::getInstance();
587 if (pMainForm)
588 pOptions = pMainForm->options();
589 m_sInstrumentName = getInstrumentName(m_sInstrumentFile,
590 m_iInstrumentNr, (pOptions && pOptions->bInstrumentNames));
591 #endif
592 }
593
594
595 // Update whole channel info state.
596 bool Channel::updateChannelInfo (void)
597 {
598 MainForm *pMainForm = MainForm::getInstance();
599 if (pMainForm == nullptr)
600 return false;
601 if (pMainForm->client() == nullptr || m_iChannelID < 0)
602 return false;
603
604 // Read channel information.
605 lscp_channel_info_t *pChannelInfo = ::lscp_get_channel_info(pMainForm->client(), m_iChannelID);
606 if (pChannelInfo == nullptr) {
607 appendMessagesClient("lscp_get_channel_info");
608 appendMessagesError(QObject::tr("Could not get channel information.\n\nSorry."));
609 return false;
610 }
611
612 #ifdef CONFIG_INSTRUMENT_NAME
613 // We got all actual instrument datum...
614 m_sInstrumentFile =
615 qsamplerUtilities::lscpEscapedPathToPosix(pChannelInfo->instrument_file);
616 m_iInstrumentNr = pChannelInfo->instrument_nr;
617 m_sInstrumentName =
618 qsamplerUtilities::lscpEscapedTextToRaw(pChannelInfo->instrument_name);
619 #else
620 // 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 }
629 #endif
630 // 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 #ifdef CONFIG_MIDI_INSTRUMENT
637 m_iMidiMap = pChannelInfo->midi_map;
638 #endif
639 m_iAudioDevice = pChannelInfo->audio_device;
640 m_fVolume = pChannelInfo->volume;
641 #ifdef CONFIG_MUTE_SOLO
642 m_bMute = pChannelInfo->mute;
643 m_bSolo = pChannelInfo->solo;
644 #endif
645 // Some sanity checks.
646 if (m_sEngineName == "NONE" || m_sEngineName.isEmpty())
647 m_sEngineName.clear();
648 if (m_sInstrumentFile == "NONE" || m_sInstrumentFile.isEmpty()) {
649 m_sInstrumentFile.clear();
650 m_sInstrumentName.clear();
651 }
652
653 // Time for device info grabbing...
654 lscp_device_info_t *pDeviceInfo;
655 const QString sNone = QObject::tr("(none)");
656 // Audio device driver type.
657 pDeviceInfo = ::lscp_get_audio_device_info(pMainForm->client(), m_iAudioDevice);
658 if (pDeviceInfo == nullptr) {
659 appendMessagesClient("lscp_get_audio_device_info");
660 m_sAudioDriver = sNone;
661 } else {
662 m_sAudioDriver = pDeviceInfo->driver;
663 }
664 // MIDI device driver type.
665 pDeviceInfo = ::lscp_get_midi_device_info(pMainForm->client(), m_iMidiDevice);
666 if (pDeviceInfo == nullptr) {
667 appendMessagesClient("lscp_get_midi_device_info");
668 m_sMidiDriver = sNone;
669 } else {
670 m_sMidiDriver = pDeviceInfo->driver;
671 }
672
673 // Set the audio routing map.
674 m_audioRouting.clear();
675 #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
685 return true;
686 }
687
688
689 // Reset channel method.
690 bool Channel::channelReset (void)
691 {
692 MainForm *pMainForm = MainForm::getInstance();
693 if (pMainForm == nullptr)
694 return false;
695 if (pMainForm->client() == nullptr || m_iChannelID < 0)
696 return false;
697
698 if (::lscp_reset_channel(pMainForm->client(), m_iChannelID) != LSCP_OK) {
699 appendMessagesClient("lscp_reset_channel");
700 return false;
701 }
702
703 appendMessages(QObject::tr("reset."));
704
705 return true;
706 }
707
708
709 // Spawn instrument editor method.
710 bool Channel::editChannel (void)
711 {
712 #ifdef CONFIG_EDIT_INSTRUMENT
713
714 MainForm *pMainForm = MainForm::getInstance();
715 if (pMainForm == nullptr)
716 return false;
717 if (pMainForm->client() == nullptr || m_iChannelID < 0)
718 return false;
719
720 if (::lscp_edit_channel_instrument(pMainForm->client(), m_iChannelID)
721 != LSCP_OK) {
722 appendMessagesClient("lscp_edit_channel_instrument");
723 appendMessagesError(QObject::tr(
724 "Could not launch an appropriate instrument editor "
725 "for the given instrument!\n\n"
726 "Make sure you have an appropriate "
727 "instrument editor like 'gigedit' installed "
728 "and that it placed its mandatory DLL file "
729 "into the sampler's plugin directory.")
730 );
731 return false;
732 }
733
734 appendMessages(QObject::tr("edit instrument."));
735
736 return true;
737
738 #else
739
740 appendMessagesError(QObject::tr(
741 "Sorry, QSampler was compiled for a version of liblscp "
742 "which lacks this feature.\n\n"
743 "You may want to update liblscp and recompile QSampler afterwards.")
744 );
745
746 return false;
747
748 #endif
749 }
750
751
752 // Channel setup dialog form.
753 bool Channel::channelSetup ( QWidget *pParent )
754 {
755 MainForm *pMainForm = MainForm::getInstance();
756 if (pMainForm == nullptr)
757 return false;
758
759 bool bResult = false;
760
761 appendMessages(QObject::tr("setup..."));
762
763 ChannelForm *pChannelForm = new ChannelForm(pParent);
764 if (pChannelForm) {
765 pChannelForm->setup(this);
766 bResult = pChannelForm->exec();
767 delete pChannelForm;
768 }
769
770 return bResult;
771 }
772
773
774 // Redirected messages output methods.
775 void Channel::appendMessages ( const QString& sText ) const
776 {
777 MainForm *pMainForm = MainForm::getInstance();
778 if (pMainForm)
779 pMainForm->appendMessages(channelName() + ' ' + sText);
780 }
781
782 void Channel::appendMessagesColor (
783 const QString& sText, const QColor& rgb ) const
784 {
785 MainForm *pMainForm = MainForm::getInstance();
786 if (pMainForm)
787 pMainForm->appendMessagesColor(channelName() + ' ' + sText, rgb);
788 }
789
790 void Channel::appendMessagesText ( const QString& sText ) const
791 {
792 MainForm *pMainForm = MainForm::getInstance();
793 if (pMainForm)
794 pMainForm->appendMessagesText(channelName() + ' ' + sText);
795 }
796
797 void Channel::appendMessagesError ( const QString& sText ) const
798 {
799 MainForm *pMainForm = MainForm::getInstance();
800 if (pMainForm)
801 pMainForm->appendMessagesError(channelName() + "\n\n" + sText);
802 }
803
804 void Channel::appendMessagesClient ( const QString& sText ) const
805 {
806 MainForm *pMainForm = MainForm::getInstance();
807 if (pMainForm)
808 pMainForm->appendMessagesClient(channelName() + ' ' + sText);
809 }
810
811
812 // Context menu event handler.
813 void Channel::contextMenuEvent ( QContextMenuEvent *pEvent )
814 {
815 MainForm *pMainForm = MainForm::getInstance();
816 if (pMainForm)
817 pMainForm->contextMenuEvent(pEvent);
818 }
819
820
821 // FIXME: Check whether a given file is an instrument file (DLS only).
822 bool Channel::isDlsInstrumentFile ( const QString& sInstrumentFile )
823 {
824 bool bResult = false;
825
826 QFile file(sInstrumentFile);
827 if (file.open(QIODevice::ReadOnly)) {
828 char achHeader[16];
829 if (file.read(achHeader, 16) > 0) {
830 bResult = (::memcmp(&achHeader[0], "RIFF", 4) == 0
831 && ::memcmp(&achHeader[8], "DLS LIST", 8) == 0);
832 }
833 file.close();
834 }
835
836 return bResult;
837 }
838
839
840 // 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 char achHeader[12];
848 if (file.read(achHeader, 12) > 0) {
849 bResult = (::memcmp(&achHeader[0], "RIFF", 4) == 0
850 && ::memcmp(&achHeader[8], "sfbk", 4) == 0);
851 }
852 file.close();
853 }
854
855 return bResult;
856 }
857
858
859 // Retrieve the instrument list of a instrument file (.gig).
860 QStringList Channel::getInstrumentList (
861 const QString& sInstrumentFile, bool bInstrumentNames )
862 {
863 QStringList instlist;
864
865 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 RIFF::File *pRiff
875 = new RIFF::File(sInstrumentFile.toUtf8().constData());
876 gig::File *pGig = new gig::File(pRiff);
877 #ifdef CONFIG_LIBGIG_SETAUTOLOAD
878 // prevent sleepy response time on large .gig files
879 pGig->SetAutoLoad(false);
880 #endif
881 int iIndex = 0;
882 gig::Instrument *pInstrument = pGig->GetInstrument(iIndex);
883 while (pInstrument) {
884 instlist.append((pInstrument->pInfo)->Name.c_str());
885 pInstrument = pGig->GetInstrument(++iIndex);
886 }
887 delete pGig;
888 delete pRiff;
889 }
890 #ifdef CONFIG_LIBGIG_SF2
891 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 #endif
910 }
911 #endif
912
913 if (instlist.isEmpty()) {
914 for (int iIndex = 0; iIndex < QSAMPLER_INSTRUMENT_MAX; ++iIndex) {
915 instlist.append(fi.fileName()
916 + " [" + QString::number(iIndex) + "]");
917 }
918 }
919
920 return instlist;
921 }
922
923
924 // Retrieve the spacific instrument name of a instrument file (.gig), given its index.
925 QString Channel::getInstrumentName (
926 const QString& sInstrumentFile, int iInstrumentNr, bool bInstrumentNames )
927 {
928 const QFileInfo fi(sInstrumentFile);
929 if (!fi.exists())
930 return noInstrumentName();
931
932 QString sInstrumentName;
933
934 #ifdef CONFIG_LIBGIG
935 if (bInstrumentNames) {
936 if (isDlsInstrumentFile(sInstrumentFile)) {
937 RIFF::File *pRiff
938 = new RIFF::File(sInstrumentFile.toUtf8().constData());
939 gig::File *pGig = new gig::File(pRiff);
940 #ifdef CONFIG_LIBGIG_SETAUTOLOAD
941 // prevent sleepy response time on large .gig files
942 pGig->SetAutoLoad(false);
943 #endif
944 int iIndex = 0;
945 gig::Instrument *pInstrument = pGig->GetInstrument(iIndex);
946 while (pInstrument) {
947 if (iIndex == iInstrumentNr) {
948 sInstrumentName = (pInstrument->pInfo)->Name.c_str();
949 break;
950 }
951 pInstrument = pGig->GetInstrument(++iIndex);
952 }
953 delete pGig;
954 delete pRiff;
955 }
956 #ifdef CONFIG_LIBGIG_SF2
957 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 #endif
969 }
970 #endif
971
972 if (sInstrumentName.isEmpty()) {
973 sInstrumentName = fi.fileName();
974 sInstrumentName += " [" + QString::number(iInstrumentNr) + "]";
975 }
976
977 return sInstrumentName;
978 }
979
980
981 // Common invalid name-helpers.
982 QString Channel::noEngineName (void)
983 {
984 return QObject::tr("(No engine)");
985 }
986
987 QString Channel::noInstrumentName (void)
988 {
989 return QObject::tr("(No instrument)");
990 }
991
992 QString Channel::loadingInstrument (void) {
993 return QObject::tr("(Loading instrument...)");
994 }
995
996
997 //-------------------------------------------------------------------------
998 // QSampler::ChannelRoutingModel - data model for audio routing
999 // (used for QTableView)
1000
1001 ChannelRoutingModel::ChannelRoutingModel ( QObject *pParent )
1002 : QAbstractTableModel(pParent), m_pDevice(nullptr)
1003 {
1004 }
1005
1006
1007 int ChannelRoutingModel::rowCount ( const QModelIndex& /*parent*/) const
1008 {
1009 return (m_pDevice) ? m_routing.size() : 0;
1010 }
1011
1012
1013 int ChannelRoutingModel::columnCount ( const QModelIndex& /*parent*/) const
1014 {
1015 return 1;
1016 }
1017
1018
1019 Qt::ItemFlags ChannelRoutingModel::flags ( const QModelIndex& /*index*/) const
1020 {
1021 return Qt::ItemIsSelectable | Qt::ItemIsEditable | Qt::ItemIsEnabled;
1022 }
1023
1024
1025 bool ChannelRoutingModel::setData ( const QModelIndex& index,
1026 const QVariant& value, int /*role*/)
1027 {
1028 if (!index.isValid())
1029 return false;
1030
1031 m_routing[index.row()] = value.toInt();
1032
1033 emit dataChanged(index, index);
1034 return true;
1035 }
1036
1037
1038 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
1047 ChannelRoutingItem item;
1048
1049 // The common device port item list.
1050 DevicePortList& ports = m_pDevice->ports();
1051 QListIterator<DevicePort *> iter(ports);
1052 while (iter.hasNext()) {
1053 DevicePort *pPort = iter.next();
1054 item.options.append(
1055 m_pDevice->deviceTypeName()
1056 + ' ' + m_pDevice->driverName()
1057 + ' ' + pPort->portName()
1058 );
1059 }
1060
1061 item.selection = m_routing[index.row()];
1062
1063 return QVariant::fromValue(item);
1064 }
1065
1066
1067 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 return QObject::tr("Audio Channel ") +
1078 QString::number(section) + " " + UNICODE_RIGHT_ARROW;
1079 default:
1080 return QVariant();
1081 }
1082 }
1083
1084
1085 void ChannelRoutingModel::refresh ( Device *pDevice,
1086 const ChannelRoutingMap& routing )
1087 {
1088 m_pDevice = pDevice;
1089 m_routing = routing;
1090 // inform the outer world (QTableView) that our data changed
1091 #if QT_VERSION < QT_VERSION_CHECK(5, 0, 0)
1092 QAbstractTableModel::reset();
1093 #else
1094 QAbstractTableModel::beginResetModel();
1095 QAbstractTableModel::endResetModel();
1096 #endif
1097 }
1098
1099
1100 //-------------------------------------------------------------------------
1101 // QSampler::ChannelRoutingDelegate - table cell renderer for audio routing
1102 //
1103
1104 ChannelRoutingDelegate::ChannelRoutingDelegate ( QObject *pParent )
1105 : QItemDelegate(pParent)
1106 {
1107 }
1108
1109
1110 QWidget* ChannelRoutingDelegate::createEditor ( QWidget *pParent,
1111 const QStyleOptionViewItem & option, const QModelIndex& index ) const
1112 {
1113 if (!index.isValid())
1114 return nullptr;
1115
1116 if (index.column() != 0)
1117 return nullptr;
1118
1119 ChannelRoutingItem item = index.model()->data(index, Qt::DisplayRole).value<ChannelRoutingItem>();
1120
1121 QComboBox* pComboBox = new QComboBox(pParent);
1122 pComboBox->addItems(item.options);
1123 pComboBox->setCurrentIndex(item.selection);
1124 pComboBox->setEnabled(true);
1125 pComboBox->setEditable(true);
1126 pComboBox->setGeometry(option.rect);
1127 return pComboBox;
1128 }
1129
1130
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 }
1139
1140
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 }
1147
1148
1149 void ChannelRoutingDelegate::updateEditorGeometry ( QWidget *pEditor,
1150 const QStyleOptionViewItem& option, const QModelIndex &/* index */) const
1151 {
1152 pEditor->setGeometry(option.rect);
1153 }
1154
1155 } // namespace QSampler
1156
1157
1158 // end of qsamplerChannel.cpp

  ViewVC Help
Powered by ViewVC