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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1513 - (show annotations) (download)
Fri Nov 23 09:32:06 2007 UTC (16 years, 4 months ago) by capela
File size: 12404 byte(s)
* Qt4 migration: more cleanups and channel strip visual fixes.

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 namespace QSampler {
38
39 #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 ChannelStrip::ChannelStrip ( QWidget* pParent, Qt::WindowFlags wflags )
50 : QWidget(pParent, wflags)
51 {
52 m_ui.setupUi(this);
53
54 // Initialize locals.
55 m_pChannel = NULL;
56 m_iDirtyChange = 0;
57 m_iErrorCount = 0;
58
59 // Try to restore normal window positioning.
60 adjustSize();
61
62 QObject::connect(m_ui.ChannelSetupPushButton,
63 SIGNAL(clicked()),
64 SLOT(channelSetup()));
65 QObject::connect(m_ui.ChannelMutePushButton,
66 SIGNAL(toggled(bool)),
67 SLOT(channelMute(bool)));
68 QObject::connect(m_ui.ChannelSoloPushButton,
69 SIGNAL(toggled(bool)),
70 SLOT(channelSolo(bool)));
71 QObject::connect(m_ui.VolumeSlider,
72 SIGNAL(valueChanged(int)),
73 SLOT(volumeChanged(int)));
74 QObject::connect(m_ui.VolumeSpinBox,
75 SIGNAL(valueChanged(int)),
76 SLOT(volumeChanged(int)));
77 QObject::connect(m_ui.ChannelEditPushButton,
78 SIGNAL(clicked()),
79 SLOT(channelEdit()));
80 }
81
82
83 ChannelStrip::~ChannelStrip (void)
84 {
85 // Destroy existing channel descriptor.
86 if (m_pChannel)
87 delete m_pChannel;
88 m_pChannel = NULL;
89 }
90
91
92 // Window drag-n-drop event handlers.
93 void ChannelStrip::dragEnterEvent ( QDragEnterEvent* pDragEnterEvent )
94 {
95 if (m_pChannel == NULL)
96 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 }
110 }
111 }
112 }
113
114 if (bAccept)
115 pDragEnterEvent->accept();
116 else
117 pDragEnterEvent->ignore();
118 }
119
120
121 void ChannelStrip::dropEvent ( QDropEvent* pDropEvent )
122 {
123 if (m_pChannel == NULL)
124 return;
125
126 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 }
144 }
145
146
147 // Channel strip setup formal initializer.
148 void ChannelStrip::setup ( qsamplerChannel *pChannel )
149 {
150 // Destroy any previous channel descriptor;
151 // (remember that once setup we own it!)
152 if (m_pChannel)
153 delete m_pChannel;
154
155 // Set the new one...
156 m_pChannel = pChannel;
157
158 // Stabilize this around.
159 updateChannelInfo();
160
161 // We'll accept drops from now on...
162 if (m_pChannel)
163 setAcceptDrops(true);
164 }
165
166
167 // Channel secriptor accessor.
168 qsamplerChannel *ChannelStrip::channel (void) const
169 {
170 return m_pChannel;
171 }
172
173
174 // Messages view font accessors.
175 QFont ChannelStrip::displayFont (void) const
176 {
177 return m_ui.EngineNameTextLabel->font();
178 }
179
180 void ChannelStrip::setDisplayFont ( const QFont & font )
181 {
182 m_ui.EngineNameTextLabel->setFont(font);
183 m_ui.MidiPortChannelTextLabel->setFont(font);
184 m_ui.InstrumentNameTextLabel->setFont(font);
185 m_ui.InstrumentStatusTextLabel->setFont(font);
186 }
187
188
189 // Channel display background effect.
190 void ChannelStrip::setDisplayEffect ( bool bDisplayEffect )
191 {
192 QPalette pal;
193 pal.setColor(QPalette::Foreground, Qt::yellow);
194 m_ui.EngineNameTextLabel->setPalette(pal);
195 m_ui.MidiPortChannelTextLabel->setPalette(pal);
196 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 m_ui.ChannelInfoFrame->setPalette(pal);
204 m_ui.StreamVoiceCountTextLabel->setPalette(pal);
205 }
206
207
208 // Maximum volume slider accessors.
209 void ChannelStrip::setMaxVolume ( int iMaxVolume )
210 {
211 m_iDirtyChange++;
212 m_ui.VolumeSlider->setRange(0, iMaxVolume);
213 m_ui.VolumeSpinBox->setRange(0, iMaxVolume);
214 m_iDirtyChange--;
215 }
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 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
316 return true;
317 }
318
319
320 // Do the dirty volume change.
321 bool ChannelStrip::updateChannelVolume (void)
322 {
323 if (m_pChannel == NULL)
324 return false;
325
326 // Convert...
327 int iVolume = ::lroundf(100.0f * m_pChannel->volume());
328 // And clip...
329 if (iVolume < 0)
330 iVolume = 0;
331
332 // 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
338 return true;
339 }
340
341
342 // Update whole channel info state.
343 bool ChannelStrip::updateChannelInfo (void)
344 {
345 if (m_pChannel == NULL)
346 return false;
347
348 // Check for error limit/recycle...
349 if (m_iErrorCount > QSAMPLER_ERROR_LIMIT)
350 return true;
351
352 // Update strip caption.
353 QString sText = m_pChannel->channelName();
354 setWindowTitle(sText);
355 m_ui.ChannelSetupPushButton->setText('&' + sText);
356
357 // Check if we're up and connected.
358 MainForm* pMainForm = MainForm::getInstance();
359 if (pMainForm->client() == NULL)
360 return false;
361
362 // Read actual channel information.
363 m_pChannel->updateChannelInfo();
364
365 // Engine name...
366 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
374 // Instrument name...
375 updateInstrumentName(false);
376
377 // MIDI Port/Channel...
378 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 m_ui.MidiPortChannelTextLabel->setText(sMidiPortChannel);
384
385 // Common palette...
386 QPalette pal;
387 const QColor& rgbFore = pal.color(QPalette::Foreground);
388
389 // Instrument status...
390 int iInstrumentStatus = m_pChannel->instrumentStatus();
391 if (iInstrumentStatus < 0) {
392 pal.setColor(QPalette::Foreground, Qt::red);
393 m_ui.InstrumentStatusTextLabel->setPalette(pal);
394 m_ui.InstrumentStatusTextLabel->setText(
395 tr("ERR%1").arg(iInstrumentStatus));
396 m_iErrorCount++;
397 return false;
398 }
399 // All seems normal...
400 pal.setColor(QPalette::Foreground,
401 iInstrumentStatus < 100 ? Qt::yellow : Qt::green);
402 m_ui.InstrumentStatusTextLabel->setPalette(pal);
403 m_ui.InstrumentStatusTextLabel->setText(
404 QString::number(iInstrumentStatus) + '%');
405 m_iErrorCount = 0;
406
407 #ifdef CONFIG_MUTE_SOLO
408 // Mute/Solo button state coloring...
409 bool bMute = m_pChannel->channelMute();
410 const QColor& rgbButton = pal.color(QPalette::Button);
411 pal.setColor(QPalette::Foreground, rgbFore);
412 pal.setColor(QPalette::Button, bMute ? Qt::yellow : rgbButton);
413 m_ui.ChannelMutePushButton->setPalette(pal);
414 m_ui.ChannelMutePushButton->setDown(bMute);
415 bool bSolo = m_pChannel->channelSolo();
416 pal.setColor(QPalette::Button, bSolo ? Qt::cyan : rgbButton);
417 m_ui.ChannelSoloPushButton->setPalette(pal);
418 m_ui.ChannelSoloPushButton->setDown(bSolo);
419 #else
420 m_ui.ChannelMutePushButton->setEnabled(false);
421 m_ui.ChannelSoloPushButton->setEnabled(false);
422 #endif
423
424 // And update the both GUI volume elements;
425 // return success if, and only if, intrument is fully loaded...
426 return updateChannelVolume() && (iInstrumentStatus == 100);
427 }
428
429
430 // Update whole channel usage state.
431 bool ChannelStrip::updateChannelUsage (void)
432 {
433 if (m_pChannel == NULL)
434 return false;
435
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 return false;
443
444 // Get current channel voice count.
445 int iVoiceCount = ::lscp_get_channel_voice_count(
446 pMainForm->client(), m_pChannel->channelID());
447 // Get current stream count.
448 int iStreamCount = ::lscp_get_channel_stream_count(
449 pMainForm->client(), m_pChannel->channelID());
450 // Get current channel buffer fill usage.
451 // As benno has suggested this is the percentage usage
452 // of the least filled buffer stream...
453 int iStreamUsage = ::lscp_get_channel_stream_usage(
454 pMainForm->client(), m_pChannel->channelID());;
455
456 // Update the GUI elements...
457 m_ui.StreamUsageProgressBar->setValue(iStreamUsage);
458 m_ui.StreamVoiceCountTextLabel->setText(
459 QString("%1 / %2").arg(iStreamCount).arg(iVoiceCount));
460
461 // We're clean.
462 return true;
463 }
464
465
466 // Volume change slot.
467 void ChannelStrip::volumeChanged ( int iVolume )
468 {
469 if (m_pChannel == NULL)
470 return;
471
472 // Avoid recursion.
473 if (m_iDirtyChange > 0)
474 return;
475
476 // Convert and clip.
477 float fVolume = (float) iVolume / 100.0f;
478 if (fVolume < 0.001f)
479 fVolume = 0.0f;
480
481 // Update the GUI elements.
482 if (m_pChannel->setVolume(fVolume)) {
483 updateChannelVolume();
484 emit channelChanged(this);
485 }
486 }
487
488
489 // Context menu event handler.
490 void ChannelStrip::contextMenuEvent( QContextMenuEvent *pEvent )
491 {
492 if (m_pChannel == NULL)
493 return;
494
495 // We'll just show up the main form's edit menu (thru qsamplerChannel).
496 m_pChannel->contextMenuEvent(pEvent);
497 }
498
499
500 // Error count hackish accessors.
501 void ChannelStrip::resetErrorCount (void)
502 {
503 m_iErrorCount = 0;
504 }
505
506 } // namespace QSampler
507
508
509 // end of qsamplerChannelStrip.cpp

  ViewVC Help
Powered by ViewVC