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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1515 - (hide annotations) (download)
Fri Nov 23 18:15:33 2007 UTC (16 years, 5 months ago) by capela
File size: 13173 byte(s)
* Fixed sure crash when removing channel strips.
* Force auto-arrange when adding channel strips,
  among other incremental fixes.

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

  ViewVC Help
Powered by ViewVC