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

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

Parent Directory Parent Directory | Revision Log Revision Log


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

  ViewVC Help
Powered by ViewVC