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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1474 - (show annotations) (download)
Mon Nov 5 20:47:38 2007 UTC (16 years, 4 months ago) by schoenebeck
File size: 12576 byte(s)
* Qt4 migration: fixed another bunch of ghost connections, fixed engine
  combo box in channel form, fixed stdout ouptut in message window (a lot
  of white lines were shown), show channel strip on the work space (and not
  in the nirvana of the desktop universe)

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

  ViewVC Help
Powered by ViewVC