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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1507 - (show annotations) (download)
Wed Nov 21 23:22:18 2007 UTC (16 years, 5 months ago) by capela
File size: 12675 byte(s)
- Qt4 migration: more tiny-fixes, specially on the sampler channel
strip appearence and channels menu content.

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

  ViewVC Help
Powered by ViewVC