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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1637 - (show annotations) (download)
Mon Jan 7 20:00:13 2008 UTC (16 years, 2 months ago) by capela
File size: 13316 byte(s)
* Color pallete fix for the instrument name display in channel strip,
  particularly notorious on Mac OS X builds.

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

  ViewVC Help
Powered by ViewVC