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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 404 - (show annotations) (download)
Wed Feb 23 13:47:47 2005 UTC (19 years, 1 month ago) by capela
File size: 17196 byte(s)
* Added new menu and toolbar option: Reset All Channels.

* Channel setup changes are now properly filtered, as for
  only those settings that are actually changed gets applied;
  change information are now also posted to messages window.

1 // qsamplerChannel.cpp
2 //
3 /****************************************************************************
4 Copyright (C) 2003-2005, rncbc aka Rui Nuno Capela. All rights reserved.
5
6 This program is free software; you can redistribute it and/or
7 modify it under the terms of the GNU General Public License
8 as published by the Free Software Foundation; either version 2
9 of the License, or (at your option) any later version.
10
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
19
20 *****************************************************************************/
21
22 #include "qsamplerChannel.h"
23
24 #include "qsamplerMainForm.h"
25 #include "qsamplerChannelForm.h"
26
27 #include "config.h"
28
29 #include <qfileinfo.h>
30
31 #ifdef CONFIG_LIBGIG
32 #include "gig.h"
33 #endif
34
35 #define QSAMPLER_INSTRUMENT_MAX 8
36
37
38 //-------------------------------------------------------------------------
39 // qsamplerChannel - Sampler channel structure.
40 //
41
42 // Constructor.
43 qsamplerChannel::qsamplerChannel ( qsamplerMainForm *pMainForm, int iChannelID )
44 {
45 m_pMainForm = pMainForm;
46 m_iChannelID = iChannelID;
47
48 // m_sEngineName = noEngineName();
49 // m_sInstrumentName = noInstrumentName();
50 // m_sInstrumentFile = m_sInstrumentName;
51 m_iInstrumentNr = -1;
52 m_iInstrumentStatus = -1;
53 m_sMidiDriver = "Alsa"; // DEPRECATED.
54 m_iMidiDevice = -1;
55 m_iMidiPort = -1;
56 m_iMidiChannel = -1;
57 m_sAudioDriver = "Alsa"; // DEPRECATED.
58 m_iAudioDevice = -1;
59 m_fVolume = 0.0;
60
61 }
62
63 // Default destructor.
64 qsamplerChannel::~qsamplerChannel (void)
65 {
66 }
67
68
69 // The global options settings delegated property.
70 qsamplerOptions *qsamplerChannel::options (void)
71 {
72 if (m_pMainForm == NULL)
73 return NULL;
74
75 return m_pMainForm->options();
76 }
77
78
79 // The client descriptor delegated property.
80 lscp_client_t *qsamplerChannel::client (void)
81 {
82 if (m_pMainForm == NULL)
83 return NULL;
84
85 return m_pMainForm->client();
86 }
87
88
89 // Create a new sampler channel, if not already.
90 bool qsamplerChannel::addChannel (void)
91 {
92 if (client() == NULL)
93 return false;
94
95 // Are we a new channel?
96 if (m_iChannelID < 0) {
97 m_iChannelID = ::lscp_add_channel(client());
98 if (m_iChannelID < 0) {
99 appendMessagesClient("lscp_add_channel");
100 appendMessagesError(QObject::tr("Could not add channel.\n\nSorry."));
101 } // Otherwise it's created...
102 else appendMessages(QObject::tr("added."));
103 }
104
105 // Return whether we're a valid channel...
106 return (m_iChannelID >= 0);
107 }
108
109
110 // Remove sampler channel.
111 bool qsamplerChannel::removeChannel (void)
112 {
113 if (client() == NULL)
114 return false;
115
116 // Are we an existing channel?
117 if (m_iChannelID >= 0) {
118 if (::lscp_remove_channel(client(), m_iChannelID) != LSCP_OK) {
119 appendMessagesClient("lscp_remove_channel");
120 appendMessagesError(QObject::tr("Could not remove channel.\n\nSorry."));
121 } else {
122 // Otherwise it's removed.
123 appendMessages(QObject::tr("removed."));
124 m_iChannelID = -1;
125 }
126 }
127
128 // Return whether we've removed the channel...
129 return (m_iChannelID < 0);
130 }
131
132
133 // Channel-ID (aka Sammpler-Channel) accessors.
134 int qsamplerChannel::channelID (void)
135 {
136 return m_iChannelID;
137 }
138
139 void qsamplerChannel::setChannelID ( int iChannelID )
140 {
141 m_iChannelID = iChannelID;
142 }
143
144
145 // Readable channel name.
146 QString qsamplerChannel::channelName (void)
147 {
148 return (m_iChannelID < 0 ? QObject::tr("New Channel") : QObject::tr("Channel %1").arg(m_iChannelID));
149 }
150
151
152 // Engine name accessors.
153 QString& qsamplerChannel::engineName (void)
154 {
155 return m_sEngineName;
156 }
157
158 bool qsamplerChannel::loadEngine ( const QString& sEngineName )
159 {
160 if (client() == NULL || m_iChannelID < 0)
161 return false;
162 if (m_iInstrumentStatus == 100 && m_sEngineName == sEngineName)
163 return true;
164
165 if (::lscp_load_engine(client(), sEngineName.latin1(), m_iChannelID) != LSCP_OK) {
166 appendMessagesClient("lscp_load_engine");
167 return false;
168 }
169 appendMessages(QObject::tr("Engine: %1.").arg(sEngineName));
170
171 m_sEngineName = sEngineName;
172 return true;
173 }
174
175
176 // Instrument filename accessor.
177 QString& qsamplerChannel::instrumentFile (void)
178 {
179 return m_sInstrumentFile;
180 }
181
182 // Instrument index accessor.
183 int qsamplerChannel::instrumentNr (void)
184 {
185 return m_iInstrumentNr;
186 }
187
188 // Instrument name accessor.
189 QString& qsamplerChannel::instrumentName (void)
190 {
191 return m_sInstrumentName;
192 }
193
194 // Instrument status accessor.
195 int qsamplerChannel::instrumentStatus (void)
196 {
197 return m_iInstrumentStatus;
198 }
199
200 // Instrument file loader.
201 bool qsamplerChannel::loadInstrument ( const QString& sInstrumentFile, int iInstrumentNr )
202 {
203 if (client() == NULL || m_iChannelID < 0)
204 return false;
205 if (!isInstrumentFile(sInstrumentFile))
206 return false;
207 if (m_iInstrumentStatus == 100 && m_sInstrumentFile == sInstrumentFile && m_iInstrumentNr == iInstrumentNr)
208 return true;
209
210 if (::lscp_load_instrument_non_modal(client(), sInstrumentFile.latin1(), iInstrumentNr, m_iChannelID) != LSCP_OK) {
211 appendMessagesClient("lscp_load_instrument");
212 return false;
213 }
214
215 appendMessages(QObject::tr("Instrument: \"%1\" (%2).")
216 .arg(sInstrumentFile).arg(iInstrumentNr));
217
218 return setInstrument(sInstrumentFile, iInstrumentNr);
219 }
220
221
222 // Special instrument file/name/number settler.
223 bool qsamplerChannel::setInstrument ( const QString& sInstrumentFile, int iInstrumentNr )
224 {
225 m_sInstrumentFile = sInstrumentFile;
226 m_iInstrumentNr = iInstrumentNr;
227 #ifdef CONFIG_INSTRUMENT_NAME
228 m_sInstrumentName = QString::null; // We'll get it, maybe later, on channel_info...
229 #else
230 m_sInstrumentName = getInstrumentName(sInstrumentFile, iInstrumentNr, true);
231 #endif
232 m_iInstrumentStatus = 0;
233
234 return true;
235 }
236
237
238 // MIDI driver type accessors (DEPRECATED).
239 QString& qsamplerChannel::midiDriver (void)
240 {
241 return m_sMidiDriver;
242 }
243
244 bool qsamplerChannel::setMidiDriver ( const QString& sMidiDriver )
245 {
246 if (client() == NULL || m_iChannelID < 0)
247 return false;
248 if (m_iInstrumentStatus == 100 && m_sMidiDriver == sMidiDriver)
249 return true;
250
251 if (::lscp_set_channel_midi_type(client(), m_iChannelID, sMidiDriver.latin1()) != LSCP_OK) {
252 appendMessagesClient("lscp_set_channel_midi_type");
253 return false;
254 }
255
256 appendMessages(QObject::tr("MIDI driver: %1.").arg(sMidiDriver));
257
258 m_sMidiDriver = sMidiDriver;
259 return true;
260 }
261
262
263 // MIDI device accessors.
264 int qsamplerChannel::midiDevice (void)
265 {
266 return m_iMidiDevice;
267 }
268
269 bool qsamplerChannel::setMidiDevice ( int iMidiDevice )
270 {
271 if (client() == NULL || m_iChannelID < 0)
272 return false;
273 if (m_iInstrumentStatus == 100 && m_iMidiDevice == iMidiDevice)
274 return true;
275
276 if (::lscp_set_channel_midi_device(client(), m_iChannelID, iMidiDevice) != LSCP_OK) {
277 appendMessagesClient("lscp_set_channel_midi_device");
278 return false;
279 }
280
281 appendMessages(QObject::tr("MIDI device: %1.").arg(iMidiDevice));
282
283 m_iMidiDevice = iMidiDevice;
284 return true;
285 }
286
287
288 // MIDI port number accessor.
289 int qsamplerChannel::midiPort (void)
290 {
291 return m_iMidiPort;
292 }
293
294 bool qsamplerChannel::setMidiPort ( int iMidiPort )
295 {
296 if (client() == NULL || m_iChannelID < 0)
297 return false;
298 if (m_iInstrumentStatus == 100 && m_iMidiPort == iMidiPort)
299 return true;
300
301 if (::lscp_set_channel_midi_port(client(), m_iChannelID, iMidiPort) != LSCP_OK) {
302 appendMessagesClient("lscp_set_channel_midi_port");
303 return false;
304 }
305
306 appendMessages(QObject::tr("MIDI port: %1.").arg(iMidiPort));
307
308 m_iMidiPort = iMidiPort;
309 return true;
310 }
311
312
313 // MIDI channel accessor.
314 int qsamplerChannel::midiChannel (void)
315 {
316 return m_iMidiChannel;
317 }
318
319 bool qsamplerChannel::setMidiChannel ( int iMidiChannel )
320 {
321 if (client() == NULL || m_iChannelID < 0)
322 return false;
323 if (m_iInstrumentStatus == 100 && m_iMidiChannel == iMidiChannel)
324 return true;
325
326 if (::lscp_set_channel_midi_channel(client(), m_iChannelID, iMidiChannel) != LSCP_OK) {
327 appendMessagesClient("lscp_set_channel_midi_channel");
328 return false;
329 }
330
331 appendMessages(QObject::tr("MIDI channel: %1.").arg(iMidiChannel));
332
333 m_iMidiChannel = iMidiChannel;
334 return true;
335 }
336
337
338 // Audio device accessor.
339 int qsamplerChannel::audioDevice (void)
340 {
341 return m_iAudioDevice;
342 }
343
344 bool qsamplerChannel::setAudioDevice ( int iAudioDevice )
345 {
346 if (client() == NULL || m_iChannelID < 0)
347 return false;
348 if (m_iInstrumentStatus == 100 && m_iAudioDevice == iAudioDevice)
349 return true;
350
351 if (::lscp_set_channel_audio_device(client(), m_iChannelID, iAudioDevice) != LSCP_OK) {
352 appendMessagesClient("lscp_set_channel_audio_device");
353 return false;
354 }
355
356 appendMessages(QObject::tr("Audio device: %1.").arg(iAudioDevice));
357
358 m_iAudioDevice = iAudioDevice;
359 return true;
360 }
361
362
363 // Audio driver type accessors (DEPRECATED).
364 QString& qsamplerChannel::audioDriver (void)
365 {
366 return m_sAudioDriver;
367 }
368
369 bool qsamplerChannel::setAudioDriver ( const QString& sAudioDriver )
370 {
371 if (client() == NULL || m_iChannelID < 0)
372 return false;
373 if (m_iInstrumentStatus == 100 && m_sAudioDriver == sAudioDriver)
374 return true;
375
376 if (::lscp_set_channel_audio_type(client(), m_iChannelID, sAudioDriver.latin1()) != LSCP_OK) {
377 appendMessagesClient("lscp_set_channel_audio_type");
378 return false;
379 }
380
381 appendMessages(QObject::tr("Audio driver: %1.").arg(sAudioDriver));
382
383 m_sAudioDriver = sAudioDriver;
384 return true;
385 }
386
387
388 // Channel volume accessors.
389 float qsamplerChannel::volume (void)
390 {
391 return m_fVolume;
392 }
393
394 bool qsamplerChannel::setVolume ( float fVolume )
395 {
396 if (client() == NULL || m_iChannelID < 0)
397 return false;
398 if (m_iInstrumentStatus == 100 && m_fVolume == fVolume)
399 return true;
400
401 if (::lscp_set_channel_volume(client(), m_iChannelID, fVolume) != LSCP_OK) {
402 appendMessagesClient("lscp_set_channel_volume");
403 return false;
404 }
405
406 appendMessages(QObject::tr("Volume: %1.").arg(fVolume));
407
408 m_fVolume = fVolume;
409 return true;
410 }
411
412
413 // Istrument name remapper.
414 void qsamplerChannel::updateInstrumentName (void)
415 {
416 #ifndef CONFIG_INSTRUMENT_NAME
417 m_sInstrumentName = getInstrumentName(m_sInstrumentFile,
418 m_iInstrumentNr, (options() && options()->bInstrumentNames));
419 #endif
420 }
421
422
423 // Update whole channel info state.
424 bool qsamplerChannel::updateChannelInfo (void)
425 {
426 if (client() == NULL || m_iChannelID < 0)
427 return false;
428
429 // Read channel information.
430 lscp_channel_info_t *pChannelInfo = ::lscp_get_channel_info(client(), m_iChannelID);
431 if (pChannelInfo == NULL) {
432 appendMessagesClient("lscp_get_channel_info");
433 appendMessagesError(QObject::tr("Could not get channel information.\n\nSorry."));
434 return false;
435 }
436
437 #ifdef CONFIG_INSTRUMENT_NAME
438 // We got all actual instrument datum...
439 m_sInstrumentFile = pChannelInfo->instrument_file;
440 m_iInstrumentNr = pChannelInfo->instrument_nr;
441 m_sInstrumentName = pChannelInfo->instrument_name;
442 #else
443 // First, check if intrument name has changed,
444 // taking care that instrument name lookup might be expensive,
445 // so we better make it only once and when really needed...
446 if ((m_sInstrumentFile != pChannelInfo->instrument_file) ||
447 (m_iInstrumentNr != pChannelInfo->instrument_nr)) {
448 m_sInstrumentFile = pChannelInfo->instrument_file;
449 m_iInstrumentNr = pChannelInfo->instrument_nr;
450 updateInstrumentName();
451 }
452 #endif
453 // Cache in other channel information.
454 m_sEngineName = pChannelInfo->engine_name;
455 m_iInstrumentStatus = pChannelInfo->instrument_status;
456 m_iMidiDevice = pChannelInfo->midi_device;
457 m_iMidiPort = pChannelInfo->midi_port;
458 m_iMidiChannel = pChannelInfo->midi_channel;
459 m_iAudioDevice = pChannelInfo->audio_device;
460 m_fVolume = pChannelInfo->volume;
461 // Some sanity checks.
462 if (m_sEngineName == "NONE")
463 m_sEngineName = QString::null;
464 if (m_sInstrumentFile == "NONE") {
465 m_sInstrumentFile = QString::null;
466 m_sInstrumentName = QString::null;
467 }
468
469 return true;
470 }
471
472
473 // Reset channel method.
474 bool qsamplerChannel::channelReset (void)
475 {
476 if (client() == NULL || m_iChannelID < 0)
477 return false;
478
479 if (::lscp_reset_channel(client(), m_iChannelID) != LSCP_OK) {
480 appendMessagesClient("lscp_reset_channel");
481 return false;
482 }
483
484 appendMessages(QObject::tr("reset."));
485
486 return true;
487 }
488
489
490 // Channel setup dialog form.
491 bool qsamplerChannel::channelSetup ( QWidget *pParent )
492 {
493 bool bResult = false;
494
495 appendMessages(QObject::tr("setup..."));
496
497 qsamplerChannelForm *pChannelForm = new qsamplerChannelForm(pParent);
498 if (pChannelForm) {
499 pChannelForm->setup(this);
500 bResult = pChannelForm->exec();
501 delete pChannelForm;
502 }
503
504 return bResult;
505 }
506
507
508 // Redirected messages output methods.
509 void qsamplerChannel::appendMessages( const QString& s )
510 {
511 if (m_pMainForm)
512 m_pMainForm->appendMessages(channelName() + ' ' + s);
513 }
514
515 void qsamplerChannel::appendMessagesColor( const QString& s, const QString& c )
516 {
517 if (m_pMainForm)
518 m_pMainForm->appendMessagesColor(channelName() + ' ' + s, c);
519 }
520
521 void qsamplerChannel::appendMessagesText( const QString& s )
522 {
523 if (m_pMainForm)
524 m_pMainForm->appendMessagesText(channelName() + ' ' + s);
525 }
526
527 void qsamplerChannel::appendMessagesError( const QString& s )
528 {
529 if (m_pMainForm)
530 m_pMainForm->appendMessagesError(channelName() + "\n\n" + s);
531 }
532
533 void qsamplerChannel::appendMessagesClient( const QString& s )
534 {
535 if (m_pMainForm)
536 m_pMainForm->appendMessagesClient(channelName() + ' ' + s);
537 }
538
539
540 // Context menu event handler.
541 void qsamplerChannel::contextMenuEvent( QContextMenuEvent *pEvent )
542 {
543 if (m_pMainForm)
544 m_pMainForm->contextMenuEvent(pEvent);
545 }
546
547
548 // FIXME: Check whether a given file is an instrument file.
549 bool qsamplerChannel::isInstrumentFile ( const QString& sInstrumentFile )
550 {
551 bool bResult = false;
552
553 QFile file(sInstrumentFile);
554 if (file.open(IO_ReadOnly)) {
555 char achHeader[4];
556 if (file.readBlock(achHeader, 4)) {
557 bResult = (achHeader[0] == 'R'
558 && achHeader[1] == 'I'
559 && achHeader[2] == 'F'
560 && achHeader[3] == 'F');
561 }
562 file.close();
563 }
564
565 return bResult;
566 }
567
568
569 // Retrieve the instrument list of a instrument file (.gig).
570 QStringList qsamplerChannel::getInstrumentList( const QString& sInstrumentFile,
571 bool bInstrumentNames )
572 {
573 QString sInstrumentName = QFileInfo(sInstrumentFile).fileName();
574 QStringList instlist;
575
576 if (isInstrumentFile(sInstrumentFile)) {
577 #ifdef CONFIG_LIBGIG
578 if (bInstrumentNames) {
579 RIFF::File *pRiff = new RIFF::File(sInstrumentFile);
580 gig::File *pGig = new gig::File(pRiff);
581 gig::Instrument *pInstrument = pGig->GetFirstInstrument();
582 while (pInstrument) {
583 instlist.append((pInstrument->pInfo)->Name.c_str());
584 pInstrument = pGig->GetNextInstrument();
585 }
586 delete pGig;
587 delete pRiff;
588 }
589 else
590 #endif
591 for (int iInstrumentNr = 0; iInstrumentNr < QSAMPLER_INSTRUMENT_MAX; iInstrumentNr++)
592 instlist.append(sInstrumentName + " [" + QString::number(iInstrumentNr) + "]");
593 }
594 else instlist.append(noInstrumentName());
595
596 return instlist;
597 }
598
599
600 // Retrieve the spacific instrument name of a instrument file (.gig), given its index.
601 QString qsamplerChannel::getInstrumentName( const QString& sInstrumentFile,
602 int iInstrumentNr, bool bInstrumentNames )
603 {
604 QString sInstrumentName;
605
606 if (isInstrumentFile(sInstrumentFile)) {
607 sInstrumentName = QFileInfo(sInstrumentFile).fileName();
608 #ifdef CONFIG_LIBGIG
609 if (bInstrumentNames) {
610 RIFF::File *pRiff = new RIFF::File(sInstrumentFile);
611 gig::File *pGig = new gig::File(pRiff);
612 int iIndex = 0;
613 gig::Instrument *pInstrument = pGig->GetFirstInstrument();
614 while (pInstrument) {
615 if (iIndex == iInstrumentNr) {
616 sInstrumentName = (pInstrument->pInfo)->Name.c_str();
617 break;
618 }
619 iIndex++;
620 pInstrument = pGig->GetNextInstrument();
621 }
622 delete pGig;
623 delete pRiff;
624 }
625 else
626 #endif
627 sInstrumentName += " [" + QString::number(iInstrumentNr) + "]";
628 }
629 else sInstrumentName = noInstrumentName();
630
631 return sInstrumentName;
632 }
633
634
635 // Common invalid name-helpers.
636 QString qsamplerChannel::noEngineName (void)
637 {
638 return QObject::tr("(No engine)");
639 }
640
641 QString qsamplerChannel::noInstrumentName (void)
642 {
643 return QObject::tr("(No instrument)");
644 }
645
646
647 // end of qsamplerChannel.cpp

  ViewVC Help
Powered by ViewVC