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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1514 - (show annotations) (download)
Fri Nov 23 10:51:37 2007 UTC (16 years, 4 months ago) by capela
File size: 13150 byte(s)
* The current selected/activated channel-strip is now visually
  evident while in the application workspace (highlighting).

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

  ViewVC Help
Powered by ViewVC