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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1509 - (hide annotations) (download)
Thu Nov 22 11:10:44 2007 UTC (16 years, 4 months ago) by capela
File size: 12786 byte(s)
* Audio routing table is initially hidden in the dialog, when
  creating a new sampler channel.

* README requirements and configuration notes update.

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

  ViewVC Help
Powered by ViewVC