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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1704 - (hide annotations) (download)
Tue Feb 19 09:18:45 2008 UTC (16 years, 2 months ago) by capela
File size: 14904 byte(s)
- Update for the lowling win32 project build.

1 capela 1464 // qsamplerChannelStrip.cpp
2     //
3     /****************************************************************************
4     Copyright (C) 2004-2007, rncbc aka Rui Nuno Capela. All rights reserved.
5 schoenebeck 1667 Copyright (C) 2007, 2008 Christian Schoenebeck
6 capela 1464
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 capela 1499 #include "qsamplerAbout.h"
24 schoenebeck 1461 #include "qsamplerChannelStrip.h"
25    
26     #include "qsamplerMainForm.h"
27    
28 schoenebeck 1667 #include "qsamplerChannelFxForm.h"
29    
30     #include <QMessageBox>
31 capela 1499 #include <QDragEnterEvent>
32 schoenebeck 1461 #include <QUrl>
33    
34 schoenebeck 1691 #define MIDI_OFF_COLOR Qt::darkGreen
35     #define MIDI_ON_COLOR Qt::green
36    
37 schoenebeck 1461 // Channel status/usage usage limit control.
38     #define QSAMPLER_ERROR_LIMIT 3
39    
40 capela 1510 // Needed for lroundf()
41     #include <math.h>
42    
43     #ifndef CONFIG_ROUND
44     static inline long lroundf ( float x )
45     {
46     if (x >= 0.0f)
47     return long(x + 0.5f);
48     else
49     return long(x - 0.5f);
50     }
51     #endif
52    
53 capela 1514
54     namespace QSampler {
55    
56 capela 1558 //-------------------------------------------------------------------------
57     // QSampler::ChannelStrip -- Channel strip form implementation.
58     //
59    
60 capela 1514 // Channel strip activation/selection.
61     ChannelStrip *ChannelStrip::g_pSelectedStrip = NULL;
62    
63 capela 1509 ChannelStrip::ChannelStrip ( QWidget* pParent, Qt::WindowFlags wflags )
64     : QWidget(pParent, wflags)
65     {
66 capela 1510 m_ui.setupUi(this);
67 schoenebeck 1461
68 capela 1510 // Initialize locals.
69     m_pChannel = NULL;
70     m_iDirtyChange = 0;
71     m_iErrorCount = 0;
72 schoenebeck 1461
73 capela 1510 // Try to restore normal window positioning.
74     adjustSize();
75 capela 1466
76 capela 1509 QObject::connect(m_ui.ChannelSetupPushButton,
77 capela 1466 SIGNAL(clicked()),
78     SLOT(channelSetup()));
79 capela 1509 QObject::connect(m_ui.ChannelMutePushButton,
80 capela 1466 SIGNAL(toggled(bool)),
81     SLOT(channelMute(bool)));
82 capela 1509 QObject::connect(m_ui.ChannelSoloPushButton,
83 capela 1466 SIGNAL(toggled(bool)),
84     SLOT(channelSolo(bool)));
85 capela 1509 QObject::connect(m_ui.VolumeSlider,
86 capela 1466 SIGNAL(valueChanged(int)),
87     SLOT(volumeChanged(int)));
88 capela 1509 QObject::connect(m_ui.VolumeSpinBox,
89 capela 1466 SIGNAL(valueChanged(int)),
90     SLOT(volumeChanged(int)));
91 capela 1509 QObject::connect(m_ui.ChannelEditPushButton,
92 capela 1466 SIGNAL(clicked()),
93     SLOT(channelEdit()));
94 schoenebeck 1667 QObject::connect(m_ui.FxPushButton,
95     SIGNAL(clicked()),
96     SLOT(channelFxEdit()));
97 capela 1515
98 schoenebeck 1691 pMidiActivityTimer = new QTimer(this);
99     pMidiActivityTimer->setSingleShot(true);
100     QObject::connect(
101     pMidiActivityTimer, SIGNAL(timeout()),
102     this, SLOT(midiDataCeased())
103     );
104    
105 capela 1704 #if CONFIG_EVENT_CHANNEL_MIDI
106 schoenebeck 1691 m_ui.MidiActivityLabel->setPalette(MIDI_OFF_COLOR);
107     m_ui.MidiActivityLabel->setAutoFillBackground(true);
108     #else
109     m_ui.MidiActivityLabel->setText("X");
110 capela 1703 m_ui.MidiActivityLabel->setToolTip("MIDI Activity Disabled");
111 schoenebeck 1691 #endif
112    
113 capela 1515 setSelected(false);
114 schoenebeck 1461 }
115    
116 capela 1513
117     ChannelStrip::~ChannelStrip (void)
118     {
119 capela 1515 setSelected(false);
120    
121 capela 1510 // Destroy existing channel descriptor.
122     if (m_pChannel)
123     delete m_pChannel;
124     m_pChannel = NULL;
125 schoenebeck 1461 }
126    
127    
128 capela 1499 // Window drag-n-drop event handlers.
129     void ChannelStrip::dragEnterEvent ( QDragEnterEvent* pDragEnterEvent )
130 schoenebeck 1461 {
131     if (m_pChannel == NULL)
132 capela 1499 return;
133    
134     bool bAccept = false;
135    
136     if (pDragEnterEvent->source() == NULL) {
137     const QMimeData *pMimeData = pDragEnterEvent->mimeData();
138     if (pMimeData && pMimeData->hasUrls()) {
139     QListIterator<QUrl> iter(pMimeData->urls());
140     while (iter.hasNext()) {
141     const QString& sFilename = iter.next().toLocalFile();
142     if (!sFilename.isEmpty()) {
143 capela 1558 bAccept = Channel::isInstrumentFile(sFilename);
144 capela 1499 break;
145 schoenebeck 1461 }
146     }
147     }
148     }
149    
150 capela 1499 if (bAccept)
151     pDragEnterEvent->accept();
152     else
153     pDragEnterEvent->ignore();
154 schoenebeck 1461 }
155    
156    
157     void ChannelStrip::dropEvent ( QDropEvent* pDropEvent )
158     {
159 capela 1499 if (m_pChannel == NULL)
160     return;
161 schoenebeck 1461
162 capela 1499 if (pDropEvent->source())
163     return;
164    
165     const QMimeData *pMimeData = pDropEvent->mimeData();
166     if (pMimeData && pMimeData->hasUrls()) {
167     QStringList files;
168     QListIterator<QUrl> iter(pMimeData->urls());
169     while (iter.hasNext()) {
170     const QString& sFilename = iter.next().toLocalFile();
171     if (!sFilename.isEmpty()) {
172     // Go and set the dropped instrument filename...
173     m_pChannel->setInstrument(sFilename, 0);
174     // Open up the channel dialog.
175     channelSetup();
176     break;
177     }
178     }
179 schoenebeck 1461 }
180     }
181    
182    
183     // Channel strip setup formal initializer.
184 capela 1558 void ChannelStrip::setup ( Channel *pChannel )
185 schoenebeck 1461 {
186 capela 1510 // Destroy any previous channel descriptor;
187     // (remember that once setup we own it!)
188     if (m_pChannel)
189     delete m_pChannel;
190 schoenebeck 1461
191 capela 1510 // Set the new one...
192     m_pChannel = pChannel;
193 schoenebeck 1461
194 capela 1510 // Stabilize this around.
195     updateChannelInfo();
196 schoenebeck 1461
197     // We'll accept drops from now on...
198     if (m_pChannel)
199     setAcceptDrops(true);
200     }
201    
202 capela 1513
203 schoenebeck 1461 // Channel secriptor accessor.
204 capela 1558 Channel *ChannelStrip::channel (void) const
205 schoenebeck 1461 {
206 capela 1510 return m_pChannel;
207 schoenebeck 1461 }
208    
209    
210     // Messages view font accessors.
211 capela 1509 QFont ChannelStrip::displayFont (void) const
212 schoenebeck 1461 {
213 capela 1510 return m_ui.EngineNameTextLabel->font();
214 schoenebeck 1461 }
215    
216     void ChannelStrip::setDisplayFont ( const QFont & font )
217     {
218 capela 1510 m_ui.EngineNameTextLabel->setFont(font);
219     m_ui.MidiPortChannelTextLabel->setFont(font);
220     m_ui.InstrumentNameTextLabel->setFont(font);
221     m_ui.InstrumentStatusTextLabel->setFont(font);
222 schoenebeck 1461 }
223    
224    
225     // Channel display background effect.
226     void ChannelStrip::setDisplayEffect ( bool bDisplayEffect )
227     {
228 capela 1499 QPalette pal;
229 capela 1507 pal.setColor(QPalette::Foreground, Qt::yellow);
230 capela 1509 m_ui.EngineNameTextLabel->setPalette(pal);
231     m_ui.MidiPortChannelTextLabel->setPalette(pal);
232 capela 1499 pal.setColor(QPalette::Foreground, Qt::green);
233     if (bDisplayEffect) {
234     QPixmap pm(":/icons/displaybg1.png");
235     pal.setBrush(QPalette::Background, QBrush(pm));
236     } else {
237     pal.setColor(QPalette::Background, Qt::black);
238     }
239 capela 1509 m_ui.ChannelInfoFrame->setPalette(pal);
240 capela 1637 m_ui.InstrumentNameTextLabel->setPalette(pal);
241 capela 1509 m_ui.StreamVoiceCountTextLabel->setPalette(pal);
242 schoenebeck 1461 }
243    
244    
245     // Maximum volume slider accessors.
246     void ChannelStrip::setMaxVolume ( int iMaxVolume )
247     {
248 capela 1510 m_iDirtyChange++;
249     m_ui.VolumeSlider->setRange(0, iMaxVolume);
250     m_ui.VolumeSpinBox->setRange(0, iMaxVolume);
251     m_iDirtyChange--;
252 schoenebeck 1461 }
253    
254    
255     // Channel setup dialog slot.
256     bool ChannelStrip::channelSetup (void)
257     {
258     if (m_pChannel == NULL)
259     return false;
260    
261     // Invoke the channel setup dialog.
262     bool bResult = m_pChannel->channelSetup(this);
263     // Notify that this channel has changed.
264     if (bResult)
265     emit channelChanged(this);
266    
267     return bResult;
268     }
269    
270    
271     // Channel mute slot.
272     bool ChannelStrip::channelMute ( bool bMute )
273     {
274     if (m_pChannel == NULL)
275     return false;
276    
277     // Invoke the channel mute method.
278     bool bResult = m_pChannel->setChannelMute(bMute);
279     // Notify that this channel has changed.
280     if (bResult)
281     emit channelChanged(this);
282    
283     return bResult;
284     }
285    
286    
287     // Channel solo slot.
288     bool ChannelStrip::channelSolo ( bool bSolo )
289     {
290     if (m_pChannel == NULL)
291     return false;
292    
293     // Invoke the channel solo method.
294     bool bResult = m_pChannel->setChannelSolo(bSolo);
295     // Notify that this channel has changed.
296     if (bResult)
297     emit channelChanged(this);
298    
299     return bResult;
300     }
301    
302    
303     // Channel edit slot.
304     void ChannelStrip::channelEdit (void)
305     {
306     if (m_pChannel == NULL)
307     return;
308    
309     m_pChannel->editChannel();
310     }
311    
312 schoenebeck 1667 bool ChannelStrip::channelFxEdit (void)
313     {
314     MainForm *pMainForm = MainForm::getInstance();
315     if (!pMainForm || !channel())
316     return false;
317 schoenebeck 1461
318 schoenebeck 1667 pMainForm->appendMessages(QObject::tr("channel fx sends..."));
319    
320     bool bResult = false;
321    
322     #if CONFIG_FXSEND
323     ChannelFxForm *pChannelFxForm =
324 schoenebeck 1668 new ChannelFxForm(channel(), parentWidget());
325 schoenebeck 1667 if (pChannelFxForm) {
326     //pChannelForm->setup(this);
327     bResult = pChannelFxForm->exec();
328     delete pChannelFxForm;
329     }
330     #else // CONFIG_FXSEND
331     QMessageBox::critical(this,
332     QSAMPLER_TITLE ": " + tr("Unavailable"),
333     tr("Sorry, QSampler was built without FX send support!\n\n"
334     "(Make sure you have a recent liblscp when recompiling QSampler)"));
335     #endif // CONFIG_FXSEND
336    
337     return bResult;
338     }
339    
340 schoenebeck 1461 // Channel reset slot.
341     bool ChannelStrip::channelReset (void)
342     {
343     if (m_pChannel == NULL)
344     return false;
345    
346     // Invoke the channel reset method.
347     bool bResult = m_pChannel->channelReset();
348     // Notify that this channel has changed.
349     if (bResult)
350     emit channelChanged(this);
351    
352     return bResult;
353     }
354    
355    
356     // Update the channel instrument name.
357     bool ChannelStrip::updateInstrumentName ( bool bForce )
358     {
359     if (m_pChannel == NULL)
360     return false;
361    
362     // Do we refresh the actual name?
363     if (bForce)
364     m_pChannel->updateInstrumentName();
365    
366     // Instrument name...
367     if (m_pChannel->instrumentName().isEmpty()) {
368 capela 1513 if (m_pChannel->instrumentStatus() >= 0) {
369     m_ui.InstrumentNameTextLabel->setText(
370 capela 1558 ' ' + Channel::loadingInstrument());
371 capela 1513 } else {
372     m_ui.InstrumentNameTextLabel->setText(
373 capela 1558 ' ' + Channel::noInstrumentName());
374 capela 1513 }
375     } else {
376     m_ui.InstrumentNameTextLabel->setText(
377     ' ' + m_pChannel->instrumentName());
378     }
379 schoenebeck 1461
380     return true;
381     }
382    
383    
384     // Do the dirty volume change.
385     bool ChannelStrip::updateChannelVolume (void)
386     {
387 capela 1510 if (m_pChannel == NULL)
388     return false;
389 schoenebeck 1461
390 capela 1510 // Convert...
391     int iVolume = ::lroundf(100.0f * m_pChannel->volume());
392     // And clip...
393     if (iVolume < 0)
394     iVolume = 0;
395 schoenebeck 1461
396 capela 1510 // Flag it here, to avoid infinite recursion.
397     m_iDirtyChange++;
398     m_ui.VolumeSlider->setValue(iVolume);
399     m_ui.VolumeSpinBox->setValue(iVolume);
400     m_iDirtyChange--;
401 schoenebeck 1461
402 capela 1510 return true;
403 schoenebeck 1461 }
404    
405    
406     // Update whole channel info state.
407     bool ChannelStrip::updateChannelInfo (void)
408     {
409 capela 1510 if (m_pChannel == NULL)
410     return false;
411 schoenebeck 1461
412     // Check for error limit/recycle...
413     if (m_iErrorCount > QSAMPLER_ERROR_LIMIT)
414     return true;
415    
416 capela 1510 // Update strip caption.
417     QString sText = m_pChannel->channelName();
418     setWindowTitle(sText);
419 capela 1513 m_ui.ChannelSetupPushButton->setText('&' + sText);
420 schoenebeck 1461
421 capela 1510 // Check if we're up and connected.
422 schoenebeck 1461 MainForm* pMainForm = MainForm::getInstance();
423     if (pMainForm->client() == NULL)
424     return false;
425    
426 capela 1510 // Read actual channel information.
427     m_pChannel->updateChannelInfo();
428 schoenebeck 1461
429 capela 1510 // Engine name...
430 capela 1513 if (m_pChannel->engineName().isEmpty()) {
431     m_ui.EngineNameTextLabel->setText(
432 capela 1558 ' ' + Channel::noEngineName());
433 capela 1513 } else {
434     m_ui.EngineNameTextLabel->setText(
435     ' ' + m_pChannel->engineName());
436     }
437 schoenebeck 1461
438     // Instrument name...
439     updateInstrumentName(false);
440    
441 capela 1510 // MIDI Port/Channel...
442 schoenebeck 1461 QString sMidiPortChannel = QString::number(m_pChannel->midiPort()) + " / ";
443     if (m_pChannel->midiChannel() == LSCP_MIDI_CHANNEL_ALL)
444     sMidiPortChannel += tr("All");
445     else
446     sMidiPortChannel += QString::number(m_pChannel->midiChannel() + 1);
447 capela 1509 m_ui.MidiPortChannelTextLabel->setText(sMidiPortChannel);
448 schoenebeck 1461
449 capela 1499 // Common palette...
450     QPalette pal;
451     const QColor& rgbFore = pal.color(QPalette::Foreground);
452    
453 capela 1510 // Instrument status...
454     int iInstrumentStatus = m_pChannel->instrumentStatus();
455     if (iInstrumentStatus < 0) {
456 capela 1499 pal.setColor(QPalette::Foreground, Qt::red);
457 capela 1509 m_ui.InstrumentStatusTextLabel->setPalette(pal);
458 capela 1513 m_ui.InstrumentStatusTextLabel->setText(
459     tr("ERR%1").arg(iInstrumentStatus));
460 capela 1510 m_iErrorCount++;
461     return false;
462     }
463     // All seems normal...
464 capela 1499 pal.setColor(QPalette::Foreground,
465     iInstrumentStatus < 100 ? Qt::yellow : Qt::green);
466 capela 1510 m_ui.InstrumentStatusTextLabel->setPalette(pal);
467 capela 1513 m_ui.InstrumentStatusTextLabel->setText(
468     QString::number(iInstrumentStatus) + '%');
469 capela 1510 m_iErrorCount = 0;
470 schoenebeck 1461
471     #ifdef CONFIG_MUTE_SOLO
472 capela 1510 // Mute/Solo button state coloring...
473     bool bMute = m_pChannel->channelMute();
474 capela 1499 const QColor& rgbButton = pal.color(QPalette::Button);
475     pal.setColor(QPalette::Foreground, rgbFore);
476     pal.setColor(QPalette::Button, bMute ? Qt::yellow : rgbButton);
477 capela 1509 m_ui.ChannelMutePushButton->setPalette(pal);
478     m_ui.ChannelMutePushButton->setDown(bMute);
479 capela 1510 bool bSolo = m_pChannel->channelSolo();
480 capela 1499 pal.setColor(QPalette::Button, bSolo ? Qt::cyan : rgbButton);
481 capela 1509 m_ui.ChannelSoloPushButton->setPalette(pal);
482     m_ui.ChannelSoloPushButton->setDown(bSolo);
483 schoenebeck 1461 #else
484 capela 1509 m_ui.ChannelMutePushButton->setEnabled(false);
485     m_ui.ChannelSoloPushButton->setEnabled(false);
486 schoenebeck 1461 #endif
487    
488 capela 1510 // And update the both GUI volume elements;
489     // return success if, and only if, intrument is fully loaded...
490     return updateChannelVolume() && (iInstrumentStatus == 100);
491 schoenebeck 1461 }
492    
493    
494     // Update whole channel usage state.
495     bool ChannelStrip::updateChannelUsage (void)
496     {
497 capela 1510 if (m_pChannel == NULL)
498     return false;
499 schoenebeck 1461
500     MainForm *pMainForm = MainForm::getInstance();
501     if (pMainForm->client() == NULL)
502     return false;
503    
504     // This only makes sense on fully loaded channels...
505     if (m_pChannel->instrumentStatus() < 100)
506 capela 1510 return false;
507 schoenebeck 1461
508 capela 1510 // Get current channel voice count.
509 capela 1513 int iVoiceCount = ::lscp_get_channel_voice_count(
510     pMainForm->client(), m_pChannel->channelID());
511 capela 1510 // Get current stream count.
512 capela 1513 int iStreamCount = ::lscp_get_channel_stream_count(
513     pMainForm->client(), m_pChannel->channelID());
514 capela 1510 // Get current channel buffer fill usage.
515     // As benno has suggested this is the percentage usage
516     // of the least filled buffer stream...
517 capela 1513 int iStreamUsage = ::lscp_get_channel_stream_usage(
518     pMainForm->client(), m_pChannel->channelID());;
519 schoenebeck 1461
520 capela 1510 // Update the GUI elements...
521     m_ui.StreamUsageProgressBar->setValue(iStreamUsage);
522 capela 1513 m_ui.StreamVoiceCountTextLabel->setText(
523     QString("%1 / %2").arg(iStreamCount).arg(iVoiceCount));
524 schoenebeck 1461
525 capela 1510 // We're clean.
526     return true;
527 schoenebeck 1461 }
528    
529    
530     // Volume change slot.
531     void ChannelStrip::volumeChanged ( int iVolume )
532     {
533 capela 1510 if (m_pChannel == NULL)
534     return;
535 schoenebeck 1461
536 capela 1510 // Avoid recursion.
537     if (m_iDirtyChange > 0)
538     return;
539 schoenebeck 1461
540 capela 1510 // Convert and clip.
541     float fVolume = (float) iVolume / 100.0f;
542     if (fVolume < 0.001f)
543     fVolume = 0.0f;
544 schoenebeck 1461
545 capela 1510 // Update the GUI elements.
546     if (m_pChannel->setVolume(fVolume)) {
547     updateChannelVolume();
548     emit channelChanged(this);
549     }
550 schoenebeck 1461 }
551    
552 schoenebeck 1691 void ChannelStrip::midiArrived() {
553     m_ui.MidiActivityLabel->setPalette(MIDI_ON_COLOR);
554     pMidiActivityTimer->start(50);
555     }
556 schoenebeck 1461
557     // Context menu event handler.
558     void ChannelStrip::contextMenuEvent( QContextMenuEvent *pEvent )
559     {
560 capela 1510 if (m_pChannel == NULL)
561     return;
562 schoenebeck 1461
563 capela 1510 // We'll just show up the main form's edit menu (thru qsamplerChannel).
564     m_pChannel->contextMenuEvent(pEvent);
565 schoenebeck 1461 }
566    
567 schoenebeck 1691 void ChannelStrip::midiDataCeased() {
568     m_ui.MidiActivityLabel->setPalette(MIDI_OFF_COLOR);
569     }
570 schoenebeck 1461
571     // Error count hackish accessors.
572     void ChannelStrip::resetErrorCount (void)
573     {
574     m_iErrorCount = 0;
575     }
576    
577 capela 1514
578     // Channel strip activation/selection.
579     void ChannelStrip::setSelected ( bool bSelected )
580     {
581     if (bSelected) {
582     if (g_pSelectedStrip == this)
583     return;
584     if (g_pSelectedStrip)
585     g_pSelectedStrip->setSelected(false);
586     g_pSelectedStrip = this;
587     } else {
588     if (g_pSelectedStrip == this)
589     g_pSelectedStrip = NULL;
590     }
591    
592     QPalette pal;
593     if (bSelected) {
594     const QColor& color = pal.midlight().color();
595     pal.setColor(QPalette::Background, color.dark(150));
596     pal.setColor(QPalette::Foreground, color.light(150));
597     }
598     QWidget::setPalette(pal);
599     }
600    
601    
602     bool ChannelStrip::isSelected (void) const
603     {
604     return (this == g_pSelectedStrip);
605     }
606    
607    
608 schoenebeck 1461 } // namespace QSampler
609 capela 1464
610    
611     // end of qsamplerChannelStrip.cpp

  ViewVC Help
Powered by ViewVC