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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1558 - (show annotations) (download)
Thu Dec 6 09:35:33 2007 UTC (16 years, 3 months ago) by capela
File size: 13268 byte(s)
* Qt4 migration: complete QSampler namespace overhaul.

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.StreamVoiceCountTextLabel->setPalette(pal);
217 }
218
219
220 // Maximum volume slider accessors.
221 void ChannelStrip::setMaxVolume ( int iMaxVolume )
222 {
223 m_iDirtyChange++;
224 m_ui.VolumeSlider->setRange(0, iMaxVolume);
225 m_ui.VolumeSpinBox->setRange(0, iMaxVolume);
226 m_iDirtyChange--;
227 }
228
229
230 // Channel setup dialog slot.
231 bool ChannelStrip::channelSetup (void)
232 {
233 if (m_pChannel == NULL)
234 return false;
235
236 // Invoke the channel setup dialog.
237 bool bResult = m_pChannel->channelSetup(this);
238 // Notify that this channel has changed.
239 if (bResult)
240 emit channelChanged(this);
241
242 return bResult;
243 }
244
245
246 // Channel mute slot.
247 bool ChannelStrip::channelMute ( bool bMute )
248 {
249 if (m_pChannel == NULL)
250 return false;
251
252 // Invoke the channel mute method.
253 bool bResult = m_pChannel->setChannelMute(bMute);
254 // Notify that this channel has changed.
255 if (bResult)
256 emit channelChanged(this);
257
258 return bResult;
259 }
260
261
262 // Channel solo slot.
263 bool ChannelStrip::channelSolo ( bool bSolo )
264 {
265 if (m_pChannel == NULL)
266 return false;
267
268 // Invoke the channel solo method.
269 bool bResult = m_pChannel->setChannelSolo(bSolo);
270 // Notify that this channel has changed.
271 if (bResult)
272 emit channelChanged(this);
273
274 return bResult;
275 }
276
277
278 // Channel edit slot.
279 void ChannelStrip::channelEdit (void)
280 {
281 if (m_pChannel == NULL)
282 return;
283
284 m_pChannel->editChannel();
285 }
286
287
288 // Channel reset slot.
289 bool ChannelStrip::channelReset (void)
290 {
291 if (m_pChannel == NULL)
292 return false;
293
294 // Invoke the channel reset method.
295 bool bResult = m_pChannel->channelReset();
296 // Notify that this channel has changed.
297 if (bResult)
298 emit channelChanged(this);
299
300 return bResult;
301 }
302
303
304 // Update the channel instrument name.
305 bool ChannelStrip::updateInstrumentName ( bool bForce )
306 {
307 if (m_pChannel == NULL)
308 return false;
309
310 // Do we refresh the actual name?
311 if (bForce)
312 m_pChannel->updateInstrumentName();
313
314 // Instrument name...
315 if (m_pChannel->instrumentName().isEmpty()) {
316 if (m_pChannel->instrumentStatus() >= 0) {
317 m_ui.InstrumentNameTextLabel->setText(
318 ' ' + Channel::loadingInstrument());
319 } else {
320 m_ui.InstrumentNameTextLabel->setText(
321 ' ' + Channel::noInstrumentName());
322 }
323 } else {
324 m_ui.InstrumentNameTextLabel->setText(
325 ' ' + m_pChannel->instrumentName());
326 }
327
328 return true;
329 }
330
331
332 // Do the dirty volume change.
333 bool ChannelStrip::updateChannelVolume (void)
334 {
335 if (m_pChannel == NULL)
336 return false;
337
338 // Convert...
339 int iVolume = ::lroundf(100.0f * m_pChannel->volume());
340 // And clip...
341 if (iVolume < 0)
342 iVolume = 0;
343
344 // Flag it here, to avoid infinite recursion.
345 m_iDirtyChange++;
346 m_ui.VolumeSlider->setValue(iVolume);
347 m_ui.VolumeSpinBox->setValue(iVolume);
348 m_iDirtyChange--;
349
350 return true;
351 }
352
353
354 // Update whole channel info state.
355 bool ChannelStrip::updateChannelInfo (void)
356 {
357 if (m_pChannel == NULL)
358 return false;
359
360 // Check for error limit/recycle...
361 if (m_iErrorCount > QSAMPLER_ERROR_LIMIT)
362 return true;
363
364 // Update strip caption.
365 QString sText = m_pChannel->channelName();
366 setWindowTitle(sText);
367 m_ui.ChannelSetupPushButton->setText('&' + sText);
368
369 // Check if we're up and connected.
370 MainForm* pMainForm = MainForm::getInstance();
371 if (pMainForm->client() == NULL)
372 return false;
373
374 // Read actual channel information.
375 m_pChannel->updateChannelInfo();
376
377 // Engine name...
378 if (m_pChannel->engineName().isEmpty()) {
379 m_ui.EngineNameTextLabel->setText(
380 ' ' + Channel::noEngineName());
381 } else {
382 m_ui.EngineNameTextLabel->setText(
383 ' ' + m_pChannel->engineName());
384 }
385
386 // Instrument name...
387 updateInstrumentName(false);
388
389 // MIDI Port/Channel...
390 QString sMidiPortChannel = QString::number(m_pChannel->midiPort()) + " / ";
391 if (m_pChannel->midiChannel() == LSCP_MIDI_CHANNEL_ALL)
392 sMidiPortChannel += tr("All");
393 else
394 sMidiPortChannel += QString::number(m_pChannel->midiChannel() + 1);
395 m_ui.MidiPortChannelTextLabel->setText(sMidiPortChannel);
396
397 // Common palette...
398 QPalette pal;
399 const QColor& rgbFore = pal.color(QPalette::Foreground);
400
401 // Instrument status...
402 int iInstrumentStatus = m_pChannel->instrumentStatus();
403 if (iInstrumentStatus < 0) {
404 pal.setColor(QPalette::Foreground, Qt::red);
405 m_ui.InstrumentStatusTextLabel->setPalette(pal);
406 m_ui.InstrumentStatusTextLabel->setText(
407 tr("ERR%1").arg(iInstrumentStatus));
408 m_iErrorCount++;
409 return false;
410 }
411 // All seems normal...
412 pal.setColor(QPalette::Foreground,
413 iInstrumentStatus < 100 ? Qt::yellow : Qt::green);
414 m_ui.InstrumentStatusTextLabel->setPalette(pal);
415 m_ui.InstrumentStatusTextLabel->setText(
416 QString::number(iInstrumentStatus) + '%');
417 m_iErrorCount = 0;
418
419 #ifdef CONFIG_MUTE_SOLO
420 // Mute/Solo button state coloring...
421 bool bMute = m_pChannel->channelMute();
422 const QColor& rgbButton = pal.color(QPalette::Button);
423 pal.setColor(QPalette::Foreground, rgbFore);
424 pal.setColor(QPalette::Button, bMute ? Qt::yellow : rgbButton);
425 m_ui.ChannelMutePushButton->setPalette(pal);
426 m_ui.ChannelMutePushButton->setDown(bMute);
427 bool bSolo = m_pChannel->channelSolo();
428 pal.setColor(QPalette::Button, bSolo ? Qt::cyan : rgbButton);
429 m_ui.ChannelSoloPushButton->setPalette(pal);
430 m_ui.ChannelSoloPushButton->setDown(bSolo);
431 #else
432 m_ui.ChannelMutePushButton->setEnabled(false);
433 m_ui.ChannelSoloPushButton->setEnabled(false);
434 #endif
435
436 // And update the both GUI volume elements;
437 // return success if, and only if, intrument is fully loaded...
438 return updateChannelVolume() && (iInstrumentStatus == 100);
439 }
440
441
442 // Update whole channel usage state.
443 bool ChannelStrip::updateChannelUsage (void)
444 {
445 if (m_pChannel == NULL)
446 return false;
447
448 MainForm *pMainForm = MainForm::getInstance();
449 if (pMainForm->client() == NULL)
450 return false;
451
452 // This only makes sense on fully loaded channels...
453 if (m_pChannel->instrumentStatus() < 100)
454 return false;
455
456 // Get current channel voice count.
457 int iVoiceCount = ::lscp_get_channel_voice_count(
458 pMainForm->client(), m_pChannel->channelID());
459 // Get current stream count.
460 int iStreamCount = ::lscp_get_channel_stream_count(
461 pMainForm->client(), m_pChannel->channelID());
462 // Get current channel buffer fill usage.
463 // As benno has suggested this is the percentage usage
464 // of the least filled buffer stream...
465 int iStreamUsage = ::lscp_get_channel_stream_usage(
466 pMainForm->client(), m_pChannel->channelID());;
467
468 // Update the GUI elements...
469 m_ui.StreamUsageProgressBar->setValue(iStreamUsage);
470 m_ui.StreamVoiceCountTextLabel->setText(
471 QString("%1 / %2").arg(iStreamCount).arg(iVoiceCount));
472
473 // We're clean.
474 return true;
475 }
476
477
478 // Volume change slot.
479 void ChannelStrip::volumeChanged ( int iVolume )
480 {
481 if (m_pChannel == NULL)
482 return;
483
484 // Avoid recursion.
485 if (m_iDirtyChange > 0)
486 return;
487
488 // Convert and clip.
489 float fVolume = (float) iVolume / 100.0f;
490 if (fVolume < 0.001f)
491 fVolume = 0.0f;
492
493 // Update the GUI elements.
494 if (m_pChannel->setVolume(fVolume)) {
495 updateChannelVolume();
496 emit channelChanged(this);
497 }
498 }
499
500
501 // Context menu event handler.
502 void ChannelStrip::contextMenuEvent( QContextMenuEvent *pEvent )
503 {
504 if (m_pChannel == NULL)
505 return;
506
507 // We'll just show up the main form's edit menu (thru qsamplerChannel).
508 m_pChannel->contextMenuEvent(pEvent);
509 }
510
511
512 // Error count hackish accessors.
513 void ChannelStrip::resetErrorCount (void)
514 {
515 m_iErrorCount = 0;
516 }
517
518
519 // Channel strip activation/selection.
520 void ChannelStrip::setSelected ( bool bSelected )
521 {
522 if (bSelected) {
523 if (g_pSelectedStrip == this)
524 return;
525 if (g_pSelectedStrip)
526 g_pSelectedStrip->setSelected(false);
527 g_pSelectedStrip = this;
528 } else {
529 if (g_pSelectedStrip == this)
530 g_pSelectedStrip = NULL;
531 }
532
533 QPalette pal;
534 if (bSelected) {
535 const QColor& color = pal.midlight().color();
536 pal.setColor(QPalette::Background, color.dark(150));
537 pal.setColor(QPalette::Foreground, color.light(150));
538 }
539 QWidget::setPalette(pal);
540 }
541
542
543 bool ChannelStrip::isSelected (void) const
544 {
545 return (this == g_pSelectedStrip);
546 }
547
548
549 } // namespace QSampler
550
551
552 // end of qsamplerChannelStrip.cpp

  ViewVC Help
Powered by ViewVC