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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1508 - (show annotations) (download)
Thu Nov 22 02:48:41 2007 UTC (16 years, 4 months ago) by schoenebeck
File size: 35115 byte(s)
* fixed device manager dialog's amok run: the Qt4 QString::toLower(),
  QString::toUtf8() methods and Co only return temporary objects which can
  of course NOT directly be used as char* pointers for the liblscp C API
  (fixed this issue in qsamplerDevice.cpp only yet, expect all other source
  files to still have the same problem)

1 // qsamplerDevice.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 "qsamplerDevice.h"
25
26 #include "qsamplerMainForm.h"
27 #include "qsamplerDeviceForm.h"
28
29 #include <QCheckBox>
30 #include <QSpinBox>
31 #include <QLineEdit>
32
33
34 using namespace QSampler;
35
36 //-------------------------------------------------------------------------
37 // qsamplerDeviceParam - MIDI/Audio Device parameter structure.
38 //
39
40 // Constructors.
41 qsamplerDeviceParam::qsamplerDeviceParam ( lscp_param_info_t *pParamInfo,
42 const char *pszValue )
43 {
44 setParam(pParamInfo, pszValue);
45 }
46
47
48 // Default destructor.
49 qsamplerDeviceParam::~qsamplerDeviceParam (void)
50 {
51 }
52
53
54 // Initializer.
55 void qsamplerDeviceParam::setParam ( lscp_param_info_t *pParamInfo,
56 const char *pszValue )
57 {
58 if (pParamInfo == NULL)
59 return;
60
61 // Info structure field members.
62
63 type = pParamInfo->type;
64
65 if (pParamInfo->description)
66 description = pParamInfo->description;
67 else
68 description = QString::null;
69
70 mandatory = (bool) pParamInfo->mandatory;
71 fix = (bool) pParamInfo->fix;
72 multiplicity = (bool) pParamInfo->multiplicity;
73
74 depends.clear();
75 for (int i = 0; pParamInfo->depends && pParamInfo->depends[i]; i++)
76 depends.append(pParamInfo->depends[i]);
77
78 if (pParamInfo->defaultv)
79 defaultv = pParamInfo->defaultv;
80 else
81 defaultv = QString::null;
82
83 if (pParamInfo->range_min)
84 range_min = pParamInfo->range_min;
85 else
86 range_min = QString::null;
87
88 if (pParamInfo->range_max)
89 range_max = pParamInfo->range_max;
90 else
91 range_max = QString::null;
92
93 possibilities.clear();
94 for (int i = 0; pParamInfo->possibilities && pParamInfo->possibilities[i]; i++)
95 possibilities.append(pParamInfo->possibilities[i]);
96
97 // The current parameter value.
98 if (pszValue)
99 value = pszValue;
100 else
101 value = QString::null;
102 }
103
104
105 //-------------------------------------------------------------------------
106 // qsamplerDevice - MIDI/Audio Device structure.
107 //
108
109 // Constructor.
110 qsamplerDevice::qsamplerDevice ( qsamplerDeviceType deviceType, int iDeviceID )
111 {
112 // m_ports.setAutoDelete(true);
113
114 setDevice(deviceType, iDeviceID);
115 }
116
117 // Default destructor.
118 qsamplerDevice::~qsamplerDevice (void)
119 {
120 qDeleteAll(m_ports);
121 m_ports.clear();
122 }
123
124 // Copy constructor.
125 qsamplerDevice::qsamplerDevice ( const qsamplerDevice& device )
126 : m_params(device.m_params), m_ports(device.m_ports)
127 {
128 m_iDeviceID = device.m_iDeviceID;
129 m_deviceType = device.m_deviceType;
130 m_sDeviceType = device.m_sDeviceType;
131 m_sDriverName = device.m_sDriverName;
132 m_sDeviceName = device.m_sDeviceName;
133 }
134
135
136 // Initializer.
137 void qsamplerDevice::setDevice ( qsamplerDeviceType deviceType, int iDeviceID )
138 {
139 MainForm *pMainForm = MainForm::getInstance();
140 if (pMainForm == NULL)
141 return;
142 if (pMainForm->client() == NULL)
143 return;
144
145 // Device id and type should be always set.
146 m_iDeviceID = iDeviceID;
147 m_deviceType = deviceType;
148
149 // Reset device parameters and ports anyway.
150 m_params.clear();
151 qDeleteAll(m_ports);
152 m_ports.clear();
153
154 // Retrieve device info, if any.
155 lscp_device_info_t *pDeviceInfo = NULL;
156 switch (deviceType) {
157 case qsamplerDevice::Audio:
158 m_sDeviceType = QObject::tr("Audio");
159 if (m_iDeviceID >= 0 && (pDeviceInfo = ::lscp_get_audio_device_info(
160 pMainForm->client(), m_iDeviceID)) == NULL)
161 appendMessagesClient("lscp_get_audio_device_info");
162 break;
163 case qsamplerDevice::Midi:
164 m_sDeviceType = QObject::tr("MIDI");
165 if (m_iDeviceID >= 0 && (pDeviceInfo = ::lscp_get_midi_device_info(
166 pMainForm->client(), m_iDeviceID)) == NULL)
167 appendMessagesClient("lscp_get_midi_device_info");
168 break;
169 case qsamplerDevice::None:
170 m_sDeviceType = QString::null;
171 break;
172 }
173 // If we're bogus, bail out...
174 if (pDeviceInfo == NULL) {
175 m_sDriverName = QString::null;
176 m_sDeviceName = QObject::tr("New %1 device").arg(m_sDeviceType);
177 return;
178 }
179
180 // Other device properties...
181 m_sDriverName = pDeviceInfo->driver;
182 m_sDeviceName = m_sDriverName + ' '
183 + QObject::tr("Device %1").arg(m_iDeviceID);
184
185 // Grab device parameters...
186 for (int i = 0; pDeviceInfo->params && pDeviceInfo->params[i].key; i++) {
187 const QString sParam = pDeviceInfo->params[i].key;
188 lscp_param_info_t *pParamInfo = NULL;
189 switch (deviceType) {
190 case qsamplerDevice::Audio:
191 if ((pParamInfo = ::lscp_get_audio_driver_param_info(
192 pMainForm->client(), m_sDriverName.toUtf8().constData(),
193 sParam.toUtf8().constData(), NULL)) == NULL)
194 appendMessagesClient("lscp_get_audio_driver_param_info");
195 break;
196 case qsamplerDevice::Midi:
197 if ((pParamInfo = ::lscp_get_midi_driver_param_info(
198 pMainForm->client(), m_sDriverName.toUtf8().constData(),
199 sParam.toUtf8().constData(), NULL)) == NULL)
200 appendMessagesClient("lscp_get_midi_driver_param_info");
201 break;
202 case qsamplerDevice::None:
203 break;
204 }
205 if (pParamInfo) {
206 m_params[sParam.toUpper()] = qsamplerDeviceParam(pParamInfo,
207 pDeviceInfo->params[i].value);
208 }
209 }
210
211 // Refresh parameter dependencies...
212 refreshParams();
213 // Set port/channel list...
214 refreshPorts();
215 }
216
217
218 // Driver name initializer/settler.
219 void qsamplerDevice::setDriver ( const QString& sDriverName )
220 {
221 MainForm *pMainForm = MainForm::getInstance();
222 if (pMainForm == NULL)
223 return;
224 if (pMainForm->client() == NULL)
225 return;
226
227 // Valid only for scratch devices.
228 if (m_sDriverName == sDriverName)
229 return;
230
231 // Reset device parameters and ports anyway.
232 m_params.clear();
233 qDeleteAll(m_ports);
234 m_ports.clear();
235
236 // Retrieve driver info, if any.
237 lscp_driver_info_t *pDriverInfo = NULL;
238 switch (m_deviceType) {
239 case qsamplerDevice::Audio:
240 if ((pDriverInfo = ::lscp_get_audio_driver_info(pMainForm->client(),
241 sDriverName.toUtf8().constData())) == NULL)
242 appendMessagesClient("lscp_get_audio_driver_info");
243 break;
244 case qsamplerDevice::Midi:
245 if ((pDriverInfo = ::lscp_get_midi_driver_info(pMainForm->client(),
246 sDriverName.toUtf8().constData())) == NULL)
247 appendMessagesClient("lscp_get_midi_driver_info");
248 break;
249 case qsamplerDevice::None:
250 break;
251 }
252
253 // If we're bogus, bail out...
254 if (pDriverInfo == NULL)
255 return;
256
257 // Remember device parameters...
258 m_sDriverName = sDriverName;
259
260 // Grab driver parameters...
261 for (int i = 0; pDriverInfo->parameters && pDriverInfo->parameters[i]; i++) {
262 const QString sParam = pDriverInfo->parameters[i];
263 lscp_param_info_t *pParamInfo = NULL;
264 switch (m_deviceType) {
265 case qsamplerDevice::Audio:
266 if ((pParamInfo = ::lscp_get_audio_driver_param_info(
267 pMainForm->client(), sDriverName.toUtf8().constData(),
268 sParam.toUtf8().constData(), NULL)) == NULL)
269 appendMessagesClient("lscp_get_audio_driver_param_info");
270 break;
271 case qsamplerDevice::Midi:
272 if ((pParamInfo = ::lscp_get_midi_driver_param_info(
273 pMainForm->client(), sDriverName.toUtf8().constData(),
274 sParam.toUtf8().constData(), NULL)) == NULL)
275 appendMessagesClient("lscp_get_midi_driver_param_info");
276 break;
277 case qsamplerDevice::None:
278 break;
279 }
280 if (pParamInfo) {
281 m_params[sParam.toUpper()] = qsamplerDeviceParam(pParamInfo,
282 pParamInfo->defaultv);
283 }
284 }
285
286 // Refresh parameter dependencies...
287 refreshParams();
288 // Set port/channel list...
289 refreshPorts();
290 }
291
292
293 // Device property accessors.
294 int qsamplerDevice::deviceID (void) const
295 {
296 return m_iDeviceID;
297 }
298
299 qsamplerDevice::qsamplerDeviceType qsamplerDevice::deviceType (void) const
300 {
301 return m_deviceType;
302 }
303
304 const QString& qsamplerDevice::deviceTypeName (void) const
305 {
306 return m_sDeviceType;
307 }
308
309 const QString& qsamplerDevice::driverName (void) const
310 {
311 return m_sDriverName;
312 }
313
314 // Special device name formatter.
315 QString qsamplerDevice::deviceName (void) const
316 {
317 QString sPrefix;
318 if (m_iDeviceID >= 0)
319 sPrefix += m_sDeviceType + ' ';
320 return sPrefix + m_sDeviceName;
321 }
322
323
324 // Set the proper device parameter value.
325 bool qsamplerDevice::setParam ( const QString& sParam,
326 const QString& sValue )
327 {
328 MainForm *pMainForm = MainForm::getInstance();
329 if (pMainForm == NULL)
330 return false;
331 if (pMainForm->client() == NULL)
332 return false;
333
334 // Set proper device parameter.
335 m_params[sParam.toUpper()].value = sValue;
336
337 // If the device already exists, things get immediate...
338 int iRefresh = 0;
339 if (m_iDeviceID >= 0 && sValue != QString::null) {
340
341 // we need temporary byte arrrays with the final strings, because
342 // i.e. QString::toUtf8() only returns a temporary object and the
343 // C-style char* pointers for liblscp would immediately be invalidated
344 QByteArray finalParamKey = sParam.toUtf8();
345 QByteArray finalParamVal = sValue.toUtf8();
346
347 // Prepare parameter struct.
348 lscp_param_t param;
349 param.key = (char *) finalParamKey.constData();
350 param.value = (char *) finalParamVal.constData();
351 // Now it depends on the device type...
352 lscp_status_t ret = LSCP_FAILED;
353 switch (m_deviceType) {
354 case qsamplerDevice::Audio:
355 if (sParam == "CHANNELS") iRefresh++;
356 if ((ret = ::lscp_set_audio_device_param(pMainForm->client(),
357 m_iDeviceID, &param)) != LSCP_OK)
358 appendMessagesClient("lscp_set_audio_device_param");
359 break;
360 case qsamplerDevice::Midi:
361 if (sParam == "PORTS") iRefresh++;
362 if ((ret = ::lscp_set_midi_device_param(pMainForm->client(),
363 m_iDeviceID, &param)) != LSCP_OK)
364 appendMessagesClient("lscp_set_midi_device_param");
365 break;
366 case qsamplerDevice::None:
367 break;
368 }
369 // Show result.
370 if (ret == LSCP_OK) {
371 appendMessages(QString("%1: %2.").arg(sParam).arg(sValue));
372 // Special care for specific parameter changes...
373 if (iRefresh > 0)
374 iRefresh += refreshPorts();
375 iRefresh += refreshDepends(sParam);
376 } else {
377 // Oops...
378 appendMessagesError(
379 QObject::tr("Could not set device parameter value.\n\nSorry."));
380 }
381 }
382
383 // Return whether we're need a view refresh.
384 return (iRefresh > 0);
385 }
386
387
388 // Device parameter accessor.
389 const qsamplerDeviceParamMap& qsamplerDevice::params (void) const
390 {
391 return m_params;
392 }
393
394
395 // Device port/channel list accessor.
396 qsamplerDevicePortList& qsamplerDevice::ports (void)
397 {
398 return m_ports;
399 }
400
401
402 // Create a new device, as a copy of this current one.
403 bool qsamplerDevice::createDevice (void)
404 {
405 MainForm *pMainForm = MainForm::getInstance();
406 if (pMainForm == NULL)
407 return false;
408 if (pMainForm->client() == NULL)
409 return false;
410
411 // we need temporary lists with the final strings, because i.e.
412 // QString::toUtf8() only returns a temporary object and the
413 // C-style char* pointers for liblscp would immediately be invalidated
414 QList<QByteArray> finalKeys;
415 QList<QByteArray> finalVals;
416
417 qsamplerDeviceParamMap::ConstIterator iter;
418 for (iter = m_params.begin(); iter != m_params.end(); ++iter) {
419 if (iter.value().value == QString::null) continue;
420 finalKeys.push_back(iter.key().toUtf8());
421 finalVals.push_back(iter.value().value.toUtf8());
422 }
423
424 // yeah, we DO HAVE to do the two loops separately !
425
426 // Build the parameter list...
427 lscp_param_t *pParams = new lscp_param_t [finalKeys.count() + 1];
428 int iParam;
429 for (iParam = 0; iParam < finalKeys.count(); iParam++) {
430 pParams[iParam].key = (char *) finalKeys[iParam].constData();
431 pParams[iParam].value = (char *) finalVals[iParam].constData();
432 }
433 // Null terminated.
434 pParams[iParam].key = NULL;
435 pParams[iParam].value = NULL;
436
437 // Now it depends on the device type...
438 switch (m_deviceType) {
439 case qsamplerDevice::Audio:
440 if ((m_iDeviceID = ::lscp_create_audio_device(pMainForm->client(),
441 m_sDriverName.toUtf8().constData(), pParams)) < 0)
442 appendMessagesClient("lscp_create_audio_device");
443 break;
444 case qsamplerDevice::Midi:
445 if ((m_iDeviceID = ::lscp_create_midi_device(pMainForm->client(),
446 m_sDriverName.toUtf8().constData(), pParams)) < 0)
447 appendMessagesClient("lscp_create_midi_device");
448 break;
449 case qsamplerDevice::None:
450 break;
451 }
452
453 // Free used parameter array.
454 delete pParams;
455
456 // Show result.
457 if (m_iDeviceID >= 0) {
458 // Refresh our own stuff...
459 setDevice(m_deviceType, m_iDeviceID);
460 appendMessages(QObject::tr("created."));
461 } else {
462 appendMessagesError(QObject::tr("Could not create device.\n\nSorry."));
463 }
464
465 // Return whether we're a valid device...
466 return (m_iDeviceID >= 0);
467 }
468
469
470 // Destroy existing device.
471 bool qsamplerDevice::deleteDevice (void)
472 {
473 MainForm *pMainForm = MainForm::getInstance();
474 if (pMainForm == NULL)
475 return false;
476 if (pMainForm->client() == NULL)
477 return false;
478
479 // Now it depends on the device type...
480 lscp_status_t ret = LSCP_FAILED;
481 switch (m_deviceType) {
482 case qsamplerDevice::Audio:
483 if ((ret = ::lscp_destroy_audio_device(pMainForm->client(),
484 m_iDeviceID)) != LSCP_OK)
485 appendMessagesClient("lscp_destroy_audio_device");
486 break;
487 case qsamplerDevice::Midi:
488 if ((ret = ::lscp_destroy_midi_device(pMainForm->client(),
489 m_iDeviceID)) != LSCP_OK)
490 appendMessagesClient("lscp_destroy_midi_device");
491 break;
492 case qsamplerDevice::None:
493 break;
494 }
495
496 // Show result.
497 if (ret == LSCP_OK) {
498 appendMessages(QObject::tr("deleted."));
499 m_iDeviceID = -1;
500 } else {
501 appendMessagesError(QObject::tr("Could not delete device.\n\nSorry."));
502 }
503
504 // Return whether we've done it..
505 return (ret == LSCP_OK);
506 }
507
508
509 // Device parameter dependencies refreshner.
510 int qsamplerDevice::refreshParams (void)
511 {
512 // This should only make sense for scratch devices...
513 if (m_iDeviceID >= 0)
514 return 0;
515 // Refresh all parameters that have dependencies...
516 int iParams = 0;
517 qsamplerDeviceParamMap::ConstIterator iter;
518 for (iter = m_params.begin(); iter != m_params.end(); ++iter)
519 iParams += refreshParam(iter.key());
520 // Return how many parameters have been refreshed...
521 return iParams;
522 }
523
524
525 // Device port/channel list refreshner.
526 int qsamplerDevice::refreshPorts (void)
527 {
528 // This should only make sense for actual devices...
529 if (m_iDeviceID < 0)
530 return 0;
531 // Port/channel count determination...
532 int iPorts = 0;
533 switch (m_deviceType) {
534 case qsamplerDevice::Audio:
535 iPorts = m_params["CHANNELS"].value.toInt();
536 break;
537 case qsamplerDevice::Midi:
538 iPorts = m_params["PORTS"].value.toInt();
539 break;
540 case qsamplerDevice::None:
541 break;
542 }
543 // Retrieve port/channel information...
544 qDeleteAll(m_ports);
545 m_ports.clear();
546 for (int iPort = 0; iPort < iPorts; iPort++)
547 m_ports.append(new qsamplerDevicePort(*this, iPort));
548 // Return how many ports have been refreshed...
549 return iPorts;
550 }
551
552
553 // Refresh/set dependencies given that some parameter has changed.
554 int qsamplerDevice::refreshDepends ( const QString& sParam )
555 {
556 // This should only make sense for scratch devices...
557 if (m_iDeviceID >= 0)
558 return 0;
559 // Refresh all parameters that depend on this one...
560 int iDepends = 0;
561 qsamplerDeviceParamMap::ConstIterator iter;
562 for (iter = m_params.begin(); iter != m_params.end(); ++iter) {
563 const QStringList& depends = iter.value().depends;
564 if (depends.indexOf(sParam) >= 0)
565 iDepends += refreshParam(iter.key());
566 }
567 // Return how many dependencies have been refreshed...
568 return iDepends;
569 }
570
571
572 // Refresh/set given parameter based on driver supplied dependencies.
573 int qsamplerDevice::refreshParam ( const QString& sParam )
574 {
575 MainForm *pMainForm = MainForm::getInstance();
576 if (pMainForm == NULL)
577 return 0;
578 if (pMainForm->client() == NULL)
579 return 0;
580
581 // Check if we have dependencies...
582 qsamplerDeviceParam& param = m_params[sParam.toUpper()];
583 if (param.depends.isEmpty())
584 return 0;
585
586 int iRefresh = 0;
587
588 // Build dependency list...
589 lscp_param_t *pDepends = new lscp_param_t [param.depends.count() + 1];
590 int iDepend = 0;
591
592 // we need temporary lists with the final strings, because i.e.
593 // QString::toUtf8() only returns a temporary object and the
594 // C-style char* pointers for liblscp would immediately be invalidated
595 QList<QByteArray> finalKeys;
596 QList<QByteArray> finalVals;
597 for (int i = 0; i < param.depends.count(); i++) {
598 const QString& sDepend = param.depends[i];
599 finalKeys.push_back(sDepend.toUtf8());
600 finalVals.push_back(m_params[sDepend.toUpper()].value.toUtf8());
601 }
602 // yeah, we DO HAVE to do those two loops separately !
603 for (int i = 0; i < param.depends.count(); i++) {
604 pDepends[iDepend].key = (char *) finalKeys[i].constData();
605 pDepends[iDepend].value = (char *) finalVals[i].constData();
606 ++iDepend;
607 }
608 // Null terminated.
609 pDepends[iDepend].key = NULL;
610 pDepends[iDepend].value = NULL;
611
612 // FIXME: Some parameter dependencies (e.g.ALSA CARD)
613 // are blocking for no reason, causing potential timeout-crashes.
614 // hopefully this gets mitigated if this dependency hell is only
615 // carried out for scratch devices...
616
617 // Retrieve some modern parameters...
618 lscp_param_info_t *pParamInfo = NULL;
619 switch (m_deviceType) {
620 case qsamplerDevice::Audio:
621 if ((pParamInfo = ::lscp_get_audio_driver_param_info(
622 pMainForm->client(), m_sDriverName.toUtf8().constData(),
623 sParam.toUtf8().constData(), pDepends)) == NULL)
624 appendMessagesClient("lscp_get_audio_driver_param_info");
625 break;
626 case qsamplerDevice::Midi:
627 if ((pParamInfo = ::lscp_get_midi_driver_param_info(
628 pMainForm->client(), m_sDriverName.toUtf8().constData(),
629 sParam.toUtf8().constData(), pDepends)) == NULL)
630 appendMessagesClient("lscp_get_midi_driver_param_info");
631 break;
632 case qsamplerDevice::None:
633 break;
634 }
635 if (pParamInfo) {
636 param = qsamplerDeviceParam(pParamInfo,
637 param.value.isEmpty() ? NULL : param.value.toUtf8().constData());
638 iRefresh++;
639 }
640
641 // Free used parameter array.
642 delete pDepends;
643
644 // Return whether the parameters has been changed...
645 return iRefresh;
646 }
647
648
649 // Redirected messages output methods.
650 void qsamplerDevice::appendMessages( const QString& s ) const
651 {
652 MainForm *pMainForm = MainForm::getInstance();
653 if (pMainForm)
654 pMainForm->appendMessages(deviceName() + ' ' + s);
655 }
656
657 void qsamplerDevice::appendMessagesColor( const QString& s,
658 const QString& c ) const
659 {
660 MainForm *pMainForm = MainForm::getInstance();
661 if (pMainForm)
662 pMainForm->appendMessagesColor(deviceName() + ' ' + s, c);
663 }
664
665 void qsamplerDevice::appendMessagesText( const QString& s ) const
666 {
667 MainForm *pMainForm = MainForm::getInstance();
668 if (pMainForm)
669 pMainForm->appendMessagesText(deviceName() + ' ' + s);
670 }
671
672 void qsamplerDevice::appendMessagesError( const QString& s ) const
673 {
674 MainForm *pMainForm = MainForm::getInstance();
675 if (pMainForm)
676 pMainForm->appendMessagesError(deviceName() + "\n\n" + s);
677 }
678
679 void qsamplerDevice::appendMessagesClient( const QString& s ) const
680 {
681 MainForm *pMainForm = MainForm::getInstance();
682 if (pMainForm)
683 pMainForm->appendMessagesClient(deviceName() + ' ' + s);
684 }
685
686
687 // Device ids enumerator.
688 int *qsamplerDevice::getDevices ( lscp_client_t *pClient,
689 qsamplerDeviceType deviceType )
690 {
691 int *piDeviceIDs = NULL;
692 switch (deviceType) {
693 case qsamplerDevice::Audio:
694 piDeviceIDs = ::lscp_list_audio_devices(pClient);
695 break;
696 case qsamplerDevice::Midi:
697 piDeviceIDs = ::lscp_list_midi_devices(pClient);
698 break;
699 case qsamplerDevice::None:
700 break;
701 }
702 return piDeviceIDs;
703 }
704
705
706 // Driver names enumerator.
707 QStringList qsamplerDevice::getDrivers ( lscp_client_t *pClient,
708 qsamplerDeviceType deviceType )
709 {
710 QStringList drivers;
711
712 const char **ppszDrivers = NULL;
713 switch (deviceType) {
714 case qsamplerDevice::Audio:
715 ppszDrivers = ::lscp_list_available_audio_drivers(pClient);
716 break;
717 case qsamplerDevice::Midi:
718 ppszDrivers = ::lscp_list_available_midi_drivers(pClient);
719 break;
720 case qsamplerDevice::None:
721 break;
722 }
723
724 for (int iDriver = 0; ppszDrivers && ppszDrivers[iDriver]; iDriver++)
725 drivers.append(ppszDrivers[iDriver]);
726
727 return drivers;
728 }
729
730
731 //-------------------------------------------------------------------------
732 // qsamplerDevicePort - MIDI/Audio Device port/channel structure.
733 //
734
735 // Constructor.
736 qsamplerDevicePort::qsamplerDevicePort ( qsamplerDevice& device,
737 int iPortID ) : m_device(device)
738 {
739 setDevicePort(iPortID);
740 }
741
742 // Default destructor.
743 qsamplerDevicePort::~qsamplerDevicePort (void)
744 {
745 }
746
747
748 // Initializer.
749 void qsamplerDevicePort::setDevicePort ( int iPortID )
750 {
751 MainForm *pMainForm = MainForm::getInstance();
752 if (pMainForm == NULL)
753 return;
754 if (pMainForm->client() == NULL)
755 return;
756
757 // Device port id should be always set.
758 m_iPortID = iPortID;
759
760 // Reset port parameters anyway.
761 m_params.clear();
762
763 // Retrieve device port/channel info, if any.
764 lscp_device_port_info_t *pPortInfo = NULL;
765 switch (m_device.deviceType()) {
766 case qsamplerDevice::Audio:
767 if ((pPortInfo = ::lscp_get_audio_channel_info(pMainForm->client(),
768 m_device.deviceID(), m_iPortID)) == NULL)
769 m_device.appendMessagesClient("lscp_get_audio_channel_info");
770 break;
771 case qsamplerDevice::Midi:
772 if ((pPortInfo = ::lscp_get_midi_port_info(pMainForm->client(),
773 m_device.deviceID(), m_iPortID)) == NULL)
774 m_device.appendMessagesClient("lscp_get_midi_port_info");
775 break;
776 case qsamplerDevice::None:
777 break;
778 }
779
780 // If we're bogus, bail out...
781 if (pPortInfo == NULL) {
782 m_sPortName = QString::null;
783 return;
784 }
785
786 // Set device port/channel properties...
787 m_sPortName = pPortInfo->name;
788
789 // Grab device port/channel parameters...
790 m_params.clear();
791 for (int i = 0; pPortInfo->params && pPortInfo->params[i].key; i++) {
792 const QString sParam = pPortInfo->params[i].key;
793 lscp_param_info_t *pParamInfo = NULL;
794 switch (m_device.deviceType()) {
795 case qsamplerDevice::Audio:
796 if ((pParamInfo = ::lscp_get_audio_channel_param_info(
797 pMainForm->client(), m_device.deviceID(),
798 m_iPortID, sParam.toUtf8().constData())) == NULL)
799 m_device.appendMessagesClient("lscp_get_audio_channel_param_info");
800 break;
801 case qsamplerDevice::Midi:
802 if ((pParamInfo = ::lscp_get_midi_port_param_info(
803 pMainForm->client(), m_device.deviceID(),
804 m_iPortID, sParam.toUtf8().constData())) == NULL)
805 m_device.appendMessagesClient("lscp_get_midi_port_param_info");
806 break;
807 case qsamplerDevice::None:
808 break;
809 }
810 if (pParamInfo) {
811 m_params[sParam.toUpper()] = qsamplerDeviceParam(pParamInfo,
812 pPortInfo->params[i].value);
813 }
814 }
815 }
816
817
818 // Device port/channel property accessors.
819 int qsamplerDevicePort::portID (void) const
820 {
821 return m_iPortID;
822 }
823
824 const QString& qsamplerDevicePort::portName (void) const
825 {
826 return m_sPortName;
827 }
828
829 // Device port/channel parameter accessor.
830 const qsamplerDeviceParamMap& qsamplerDevicePort::params (void) const
831 {
832 return m_params;
833 }
834
835
836 // Set the proper device port/channel parameter value.
837 bool qsamplerDevicePort::setParam ( const QString& sParam,
838 const QString& sValue )
839 {
840 MainForm *pMainForm = MainForm::getInstance();
841 if (pMainForm == NULL)
842 return false;
843 if (pMainForm->client() == NULL)
844 return false;
845
846 // Set proper port/channel parameter.
847 m_params[sParam.toUpper()].value = sValue;
848
849 // If the device already exists, things get immediate...
850 int iRefresh = 0;
851 if (m_device.deviceID() >= 0 && m_iPortID >= 0) {
852
853 // we need temporary byte arrrays with the final strings, because
854 // i.e. QString::toUtf8() only returns a temporary object and the
855 // C-style char* pointers for liblscp would immediately be invalidated
856 QByteArray finalParamKey = sParam.toUtf8();
857 QByteArray finalParamVal = sValue.toUtf8();
858
859 // Prepare parameter struct.
860 lscp_param_t param;
861 param.key = (char *) finalParamKey.constData();
862 param.value = (char *) finalParamVal.constData();
863 // Now it depends on the device type...
864 lscp_status_t ret = LSCP_FAILED;
865 switch (m_device.deviceType()) {
866 case qsamplerDevice::Audio:
867 if ((ret = ::lscp_set_audio_channel_param(pMainForm->client(),
868 m_device.deviceID(), m_iPortID, &param)) != LSCP_OK)
869 m_device.appendMessagesClient("lscp_set_audio_channel_param");
870 break;
871 case qsamplerDevice::Midi:
872 if ((ret = ::lscp_set_midi_port_param(pMainForm->client(),
873 m_device.deviceID(), m_iPortID, &param)) != LSCP_OK)
874 m_device.appendMessagesClient("lscp_set_midi_port_param");
875 break;
876 case qsamplerDevice::None:
877 break;
878 }
879 // Show result.
880 if (ret == LSCP_OK) {
881 m_device.appendMessages(m_sPortName
882 + ' ' + QString("%1: %2.").arg(sParam).arg(sValue));
883 iRefresh++;
884 } else {
885 m_device.appendMessagesError(
886 QObject::tr("Could not set %1 parameter value.\n\n"
887 "Sorry.").arg(m_sPortName));
888 }
889 }
890
891 // Return whether we're need a view refresh.
892 return (iRefresh > 0);
893 }
894
895
896 //-------------------------------------------------------------------------
897 // qsamplerDeviceItem - QTreeWidget device item.
898 //
899
900 // Constructors.
901 qsamplerDeviceItem::qsamplerDeviceItem ( QTreeWidget* pTreeWidget,
902 qsamplerDevice::qsamplerDeviceType deviceType )
903 : QTreeWidgetItem(pTreeWidget, QSAMPLER_DEVICE_ITEM),
904 m_device(deviceType)
905 {
906 switch(m_device.deviceType()) {
907 case qsamplerDevice::Audio:
908 setIcon(0, QPixmap(":/icons/audio1.png"));
909 setText(0, QObject::tr("Audio Devices"));
910 break;
911 case qsamplerDevice::Midi:
912 setIcon(0, QPixmap(":/icons/midi1.png"));
913 setText(0, QObject::tr("MIDI Devices"));
914 break;
915 case qsamplerDevice::None:
916 break;
917 }
918 }
919
920 qsamplerDeviceItem::qsamplerDeviceItem ( QTreeWidgetItem* pItem,
921 qsamplerDevice::qsamplerDeviceType deviceType,
922 int iDeviceID )
923 : QTreeWidgetItem(pItem, QSAMPLER_DEVICE_ITEM),
924 m_device(deviceType, iDeviceID)
925 {
926 switch(m_device.deviceType()) {
927 case qsamplerDevice::Audio:
928 setIcon(0, QPixmap(":/icons/audio2.png"));
929 break;
930 case qsamplerDevice::Midi:
931 setIcon(0, QPixmap(":/icons/midi2.png"));
932 break;
933 case qsamplerDevice::None:
934 break;
935 }
936
937 setText(0, m_device.deviceName());
938 }
939
940 // Default destructor.
941 qsamplerDeviceItem::~qsamplerDeviceItem ()
942 {
943 }
944
945 // Instance accessors.
946 qsamplerDevice& qsamplerDeviceItem::device ()
947 {
948 return m_device;
949 }
950
951
952 //-------------------------------------------------------------------------
953 // AbstractDeviceParamModel - data model base class for device parameters
954 //
955
956 AbstractDeviceParamModel::AbstractDeviceParamModel(QObject* parent) : QAbstractTableModel(parent), bEditable(false) {
957 params = NULL;
958 }
959
960 int AbstractDeviceParamModel::rowCount(const QModelIndex& /*parent*/) const {
961 //std::cout << "model size=" << params.size() << "\n" << std::flush;
962 return (params) ? params->size() : 0;
963 }
964
965 int AbstractDeviceParamModel::columnCount(const QModelIndex& /*parent*/) const {
966 return 3;
967 }
968
969 Qt::ItemFlags AbstractDeviceParamModel::flags(const QModelIndex& /*index*/) const {
970 return Qt::ItemIsSelectable | Qt::ItemIsEditable | Qt::ItemIsEnabled;
971 }
972
973 QVariant AbstractDeviceParamModel::headerData(int section, Qt::Orientation orientation, int role) const {
974 if (role != Qt::DisplayRole) return QVariant();
975
976 if (orientation == Qt::Horizontal) {
977 switch (section) {
978 case 0: return tr("Parameter");
979 case 1: return tr("Value");
980 case 2: return tr("Description");
981 default: return QVariant();
982 }
983 }
984
985 return QVariant();
986 }
987
988 void AbstractDeviceParamModel::refresh(const qsamplerDeviceParamMap* params, bool bEditable) {
989 this->params = params;
990 this->bEditable = bEditable;
991 // inform the outer world (QTableView) that our data changed
992 QAbstractTableModel::reset();
993 }
994
995 void AbstractDeviceParamModel::clear() {
996 params = NULL;
997 // inform the outer world (QTableView) that our data changed
998 QAbstractTableModel::reset();
999 }
1000
1001
1002 //-------------------------------------------------------------------------
1003 // DeviceParamModel - data model for device parameters (used for QTableView)
1004 //
1005
1006 DeviceParamModel::DeviceParamModel(QObject* parent) : AbstractDeviceParamModel(parent) {
1007 device = NULL;
1008 }
1009
1010 QVariant DeviceParamModel::data(const QModelIndex &index, int role) const {
1011 if (!index.isValid()) {
1012 //std::cout << "inavlid device model index\n" << std::flush;
1013 return QVariant();
1014 }
1015 if (role != Qt::DisplayRole) {
1016 //std::cout << "inavlid display role\n" << std::flush;
1017 return QVariant();
1018 }
1019
1020 DeviceParameterRow item;
1021 item.name = params->keys()[index.row()];
1022 item.param = (*params)[item.name];
1023 item.alive = device != NULL && device->deviceID() >= 0;
1024
1025 return QVariant::fromValue(item);
1026 }
1027
1028 bool DeviceParamModel::setData(const QModelIndex& index, const QVariant& value, int /*role*/) {
1029 if (!index.isValid()) {
1030 return false;
1031 }
1032 QString key = params->keys()[index.row()];
1033 //params[key].value = value.toString();
1034 device->setParam(key, value.toString());
1035 emit dataChanged(index, index);
1036 return true;
1037 }
1038
1039 void DeviceParamModel::refresh(qsamplerDevice* pDevice, bool bEditable) {
1040 device = pDevice;
1041 AbstractDeviceParamModel::refresh(&pDevice->params(), bEditable);
1042 }
1043
1044 void DeviceParamModel::clear() {
1045 AbstractDeviceParamModel::clear();
1046 device = NULL;
1047 }
1048
1049
1050 //-------------------------------------------------------------------------
1051 // PortParamModel - data model for port parameters (used for QTableView)
1052 //
1053
1054 PortParamModel::PortParamModel(QObject* parent) : AbstractDeviceParamModel(parent) {
1055 port = NULL;
1056 }
1057
1058 QVariant PortParamModel::data(const QModelIndex &index, int role) const {
1059 if (!index.isValid()) {
1060 //std::cout << "inavlid device model index\n" << std::flush;
1061 return QVariant();
1062 }
1063 if (role != Qt::DisplayRole) {
1064 //std::cout << "inavlid display role\n" << std::flush;
1065 return QVariant();
1066 }
1067
1068 DeviceParameterRow item;
1069 item.name = params->keys()[index.row()];
1070 item.param = (*params)[item.name];
1071 item.alive = port != NULL && port->portID() >= 0;
1072
1073 return QVariant::fromValue(item);
1074 }
1075
1076 bool PortParamModel::setData(const QModelIndex& index, const QVariant& value, int /*role*/) {
1077 if (!index.isValid()) {
1078 return false;
1079 }
1080 QString key = params->keys()[index.row()];
1081 //params[key].value = value.toString();
1082 port->setParam(key, value.toString());
1083 emit dataChanged(index, index);
1084 return true;
1085 }
1086
1087 void PortParamModel::refresh(qsamplerDevicePort* pPort, bool bEditable) {
1088 port = pPort;
1089 AbstractDeviceParamModel::refresh(&pPort->params(), bEditable);
1090 }
1091
1092 void PortParamModel::clear() {
1093 AbstractDeviceParamModel::clear();
1094 port = NULL;
1095 }
1096
1097
1098 //-------------------------------------------------------------------------
1099 // DeviceParamDelegate - table cell renderer for device/port parameters
1100 //
1101
1102 DeviceParamDelegate::DeviceParamDelegate(QObject *parent) : QItemDelegate(parent) {
1103 }
1104
1105 QWidget* DeviceParamDelegate::createEditor(QWidget *parent,
1106 const QStyleOptionViewItem &/* option */,
1107 const QModelIndex& index) const
1108 {
1109 if (!index.isValid()) {
1110 return NULL;
1111 }
1112
1113 DeviceParameterRow r = index.model()->data(index, Qt::DisplayRole).value<DeviceParameterRow>();
1114
1115 const bool bEnabled = (r.alive) ? !r.param.fix : true;
1116
1117 QString val = (r.alive) ? r.param.value : r.param.defaultv;
1118
1119 switch (index.column()) {
1120 case 0:
1121 return new QLabel(r.name, parent);
1122 case 1: {
1123 if (r.param.type == LSCP_TYPE_BOOL) {
1124 QCheckBox* pCheckBox = new QCheckBox(parent);
1125 if (val != QString::null)
1126 pCheckBox->setChecked(val.toLower() == "true");
1127 pCheckBox->setEnabled(bEnabled);
1128 return pCheckBox;
1129 } else if (r.param.possibilities.count() > 0) {
1130 QStringList opts = r.param.possibilities;
1131 if (r.param.multiplicity)
1132 opts.prepend(tr("(none)"));
1133 QComboBox* pComboBox = new QComboBox(parent);
1134 pComboBox->addItems(opts);
1135 if (r.param.value.isEmpty())
1136 pComboBox->setCurrentIndex(0);
1137 else
1138 pComboBox->setCurrentIndex(pComboBox->findText(val));
1139 pComboBox->setEnabled(bEnabled);
1140 return pComboBox;
1141 } else if (r.param.type == LSCP_TYPE_INT && bEnabled) {
1142 QSpinBox* pSpinBox = new QSpinBox(parent);
1143 pSpinBox->setMinimum(
1144 (!r.param.range_min.isEmpty()) ?
1145 r.param.range_min.toInt() : 0 // or better a negative default min value ?
1146 );
1147 pSpinBox->setMaximum(
1148 (!r.param.range_max.isEmpty()) ?
1149 r.param.range_max.toInt() : (1 << 16) // or better a nigher default max value ?
1150 );
1151 pSpinBox->setValue(val.toInt());
1152 return pSpinBox;
1153 } else if (bEnabled) {
1154 QLineEdit* pLineEdit = new QLineEdit(val, parent);
1155 return pLineEdit;
1156 } else {
1157 QLabel* pLabel = new QLabel(val, parent);
1158 return pLabel;
1159 }
1160 }
1161 case 2:
1162 return new QLabel(r.param.description, parent);
1163 default:
1164 return NULL;
1165 }
1166 }
1167
1168 void DeviceParamDelegate::setEditorData(QWidget* /*editor*/, const QModelIndex& /*index*/) const {
1169 // unused, since we set the editor data already in createEditor()
1170 }
1171
1172 void DeviceParamDelegate::setModelData(QWidget* editor, QAbstractItemModel* model, const QModelIndex& index) const {
1173 if (index.column() == 1) {
1174 DeviceParameterRow r = index.model()->data(index, Qt::DisplayRole).value<DeviceParameterRow>();
1175 if (editor->metaObject()->className() == "QCheckBox") {
1176 QCheckBox* pCheckBox = static_cast<QCheckBox*>(editor);
1177 model->setData(index, QVariant(pCheckBox->checkState() == Qt::Checked));
1178 } else if (editor->metaObject()->className() == "QComboBox") {
1179 QComboBox* pComboBox = static_cast<QComboBox*>(editor);
1180 model->setData(index, pComboBox->currentText());
1181 } else if (editor->metaObject()->className() == "QSpinBox") {
1182 QSpinBox* pSpinBox = static_cast<QSpinBox*>(editor);
1183 model->setData(index, pSpinBox->value());
1184 } else if (editor->metaObject()->className() == "QLineEdit") {
1185 QLineEdit* pLineEdit = static_cast<QLineEdit*>(editor);
1186 model->setData(index, pLineEdit->text());
1187 } else if (editor->metaObject()->className() == "QLabel") {
1188 QLabel* pLabel = static_cast<QLabel*>(editor);
1189 model->setData(index, pLabel->text());
1190 }
1191 }
1192 }
1193
1194 void DeviceParamDelegate::updateEditorGeometry(QWidget* editor,
1195 const QStyleOptionViewItem &option, const QModelIndex &/* index */) const
1196 {
1197 if (editor) editor->setGeometry(option.rect);
1198 }
1199
1200 // end of qsamplerDevice.cpp

  ViewVC Help
Powered by ViewVC