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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1511 - (show annotations) (download)
Thu Nov 22 21:22:34 2007 UTC (12 years, 6 months ago) by schoenebeck
File size: 34030 byte(s)
* fixed another minor but important bug in device management dialog

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 ( DeviceType 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 ( DeviceType 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::DeviceType 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 DeviceType 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 DeviceType 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::DeviceType 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::DeviceType 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* pParent )
957 : QAbstractTableModel(pParent), m_bEditable(false)
958 {
959 m_pParams = NULL;
960 }
961
962
963 int AbstractDeviceParamModel::rowCount ( const QModelIndex& /*parent*/) const
964 {
965 //std::cout << "model size=" << params.size() << "\n" << std::flush;
966 return (m_pParams ? m_pParams->size() : 0);
967 }
968
969
970 int AbstractDeviceParamModel::columnCount ( const QModelIndex& /*parent*/) const
971 {
972 return 3;
973 }
974
975
976 Qt::ItemFlags AbstractDeviceParamModel::flags ( const QModelIndex& /*index*/) const
977 {
978 return Qt::ItemIsSelectable | Qt::ItemIsEditable | Qt::ItemIsEnabled;
979 }
980
981
982 QVariant AbstractDeviceParamModel::headerData (
983 int section, Qt::Orientation orientation, int role) const
984 {
985 if (role != Qt::DisplayRole)
986 return QVariant();
987
988 if (orientation == Qt::Horizontal) {
989 switch (section) {
990 case 0: return tr("Parameter");
991 case 1: return tr("Value");
992 case 2: return tr("Description");
993 default: return QVariant();
994 }
995 }
996
997 return QVariant();
998 }
999
1000
1001 void AbstractDeviceParamModel::refresh (
1002 const qsamplerDeviceParamMap* pParams, bool bEditable )
1003 {
1004 m_pParams = pParams;
1005 m_bEditable = bEditable;
1006 // inform the outer world (QTableView) that our data changed
1007 QAbstractTableModel::reset();
1008 }
1009
1010
1011 void AbstractDeviceParamModel::clear (void)
1012 {
1013 m_pParams = NULL;
1014 // inform the outer world (QTableView) that our data changed
1015 QAbstractTableModel::reset();
1016 }
1017
1018
1019 //-------------------------------------------------------------------------
1020 // DeviceParamModel - data model for device parameters (used for QTableView)
1021 //
1022
1023 DeviceParamModel::DeviceParamModel ( QObject *pParent )
1024 : AbstractDeviceParamModel(pParent)
1025 {
1026 m_pDevice = NULL;
1027 }
1028
1029 QVariant DeviceParamModel::data (
1030 const QModelIndex &index, int role) const
1031 {
1032 if (!index.isValid())
1033 return QVariant();
1034
1035 if (role != Qt::DisplayRole)
1036 return QVariant();
1037
1038 DeviceParameterRow item;
1039 item.name = m_pParams->keys()[index.row()];
1040 item.param = (*m_pParams)[item.name];
1041 item.alive = (m_pDevice && m_pDevice->deviceID() >= 0);
1042
1043 return QVariant::fromValue(item);
1044 }
1045
1046
1047 bool DeviceParamModel::setData (
1048 const QModelIndex& index, const QVariant& value, int /*role*/)
1049 {
1050 if (!index.isValid())
1051 return false;
1052
1053 QString key = m_pParams->keys()[index.row()];
1054 //m_pParams[key].value = value.toString();
1055 m_pDevice->setParam(key, value.toString());
1056 emit dataChanged(index, index);
1057 return true;
1058 }
1059
1060
1061 void DeviceParamModel::refresh ( qsamplerDevice* pDevice, bool bEditable )
1062 {
1063 m_pDevice = pDevice;
1064 AbstractDeviceParamModel::refresh(&pDevice->params(), bEditable);
1065 }
1066
1067
1068 void DeviceParamModel::clear (void)
1069 {
1070 AbstractDeviceParamModel::clear();
1071 m_pDevice = NULL;
1072 }
1073
1074
1075 //-------------------------------------------------------------------------
1076 // PortParamModel - data model for port parameters (used for QTableView)
1077 //
1078
1079 PortParamModel::PortParamModel ( QObject *pParent)
1080 : AbstractDeviceParamModel(pParent)
1081 {
1082 m_pPort = NULL;
1083 }
1084
1085 QVariant PortParamModel::data ( const QModelIndex &index, int role ) const
1086 {
1087 if (!index.isValid())
1088 return QVariant();
1089
1090 if (role != Qt::DisplayRole)
1091 return QVariant();
1092
1093 DeviceParameterRow item;
1094 item.name = m_pParams->keys()[index.row()];
1095 item.param = (*m_pParams)[item.name];
1096 item.alive = (m_pPort && m_pPort->portID() >= 0);
1097
1098 return QVariant::fromValue(item);
1099 }
1100
1101
1102 bool PortParamModel::setData (
1103 const QModelIndex& index, const QVariant& value, int /*role*/)
1104 {
1105 if (!index.isValid())
1106 return false;
1107
1108 QString key = m_pParams->keys()[index.row()];
1109 //params[key].value = value.toString();
1110 m_pPort->setParam(key, value.toString());
1111 emit dataChanged(index, index);
1112 return true;
1113 }
1114
1115
1116 void PortParamModel::refresh ( qsamplerDevicePort* pPort, bool bEditable )
1117 {
1118 m_pPort = pPort;
1119 AbstractDeviceParamModel::refresh(&pPort->params(), bEditable);
1120 }
1121
1122
1123 void PortParamModel::clear (void)
1124 {
1125 AbstractDeviceParamModel::clear();
1126 m_pPort = NULL;
1127 }
1128
1129
1130 //-------------------------------------------------------------------------
1131 // DeviceParamDelegate - table cell renderer for device/port parameters
1132 //
1133
1134 DeviceParamDelegate::DeviceParamDelegate ( QObject *pParent)
1135 : QItemDelegate(pParent)
1136 {
1137 }
1138
1139
1140 QWidget* DeviceParamDelegate::createEditor ( QWidget *pParent,
1141 const QStyleOptionViewItem& /* option */, const QModelIndex& index ) const
1142 {
1143 if (!index.isValid())
1144 return NULL;
1145
1146 DeviceParameterRow r = index.model()->data(index,
1147 Qt::DisplayRole).value<DeviceParameterRow>();
1148
1149 const bool bEnabled = (r.alive) ? !r.param.fix : true;
1150
1151 QString val = (r.alive) ? r.param.value : r.param.defaultv;
1152
1153 switch (index.column()) {
1154 case 0:
1155 return new QLabel(r.name, pParent);
1156 case 1: {
1157 if (r.param.type == LSCP_TYPE_BOOL) {
1158 QCheckBox *pCheckBox = new QCheckBox(pParent);
1159 if (val != QString::null)
1160 pCheckBox->setChecked(val.toLower() == "true");
1161 pCheckBox->setEnabled(bEnabled);
1162 return pCheckBox;
1163 } else if (r.param.possibilities.count() > 0) {
1164 QStringList opts = r.param.possibilities;
1165 if (r.param.multiplicity)
1166 opts.prepend(tr("(none)"));
1167 QComboBox *pComboBox = new QComboBox(pParent);
1168 pComboBox->addItems(opts);
1169 if (r.param.value.isEmpty())
1170 pComboBox->setCurrentIndex(0);
1171 else
1172 pComboBox->setCurrentIndex(pComboBox->findText(val));
1173 pComboBox->setEnabled(bEnabled);
1174 return pComboBox;
1175 } else if (r.param.type == LSCP_TYPE_INT && bEnabled) {
1176 QSpinBox *pSpinBox = new QSpinBox(pParent);
1177 pSpinBox->setMinimum(
1178 (!r.param.range_min.isEmpty()) ?
1179 r.param.range_min.toInt() : 0 // or better a negative default min value ?
1180 );
1181 pSpinBox->setMaximum(
1182 (!r.param.range_max.isEmpty()) ?
1183 r.param.range_max.toInt() : (1 << 16) // or better a nigher default max value ?
1184 );
1185 pSpinBox->setValue(val.toInt());
1186 return pSpinBox;
1187 } else if (bEnabled) {
1188 QLineEdit *pLineEdit = new QLineEdit(val, pParent);
1189 return pLineEdit;
1190 } else {
1191 QLabel *pLabel = new QLabel(val, pParent);
1192 return pLabel;
1193 }
1194 }
1195 case 2:
1196 return new QLabel(r.param.description, pParent);
1197 default:
1198 return NULL;
1199 }
1200 }
1201
1202
1203 void DeviceParamDelegate::setEditorData (
1204 QWidget* /*pEditor*/, const QModelIndex& /*index*/) const
1205 {
1206 // Unused, since we set the editor data already in createEditor()
1207 }
1208
1209
1210 void DeviceParamDelegate::setModelData ( QWidget *pEditor,
1211 QAbstractItemModel *pModel, const QModelIndex& index ) const
1212 {
1213 if (index.column() == 1) {
1214 DeviceParameterRow r = index.model()->data(index,
1215 Qt::DisplayRole).value<DeviceParameterRow> ();
1216 if (pEditor->metaObject()->className() == QString("QCheckBox")) {
1217 QCheckBox* pCheckBox = static_cast<QCheckBox*> (pEditor);
1218 pModel->setData(index, QVariant(pCheckBox->checkState() == Qt::Checked));
1219 } else if (pEditor->metaObject()->className() == QString("QComboBox")) {
1220 QComboBox* pComboBox = static_cast<QComboBox*> (pEditor);
1221 pModel->setData(index, pComboBox->currentText());
1222 } else if (pEditor->metaObject()->className() == QString("QSpinBox")) {
1223 QSpinBox* pSpinBox = static_cast<QSpinBox*> (pEditor);
1224 pModel->setData(index, pSpinBox->value());
1225 } else if (pEditor->metaObject()->className() == QString("QLineEdit")) {
1226 QLineEdit* pLineEdit = static_cast<QLineEdit*> (pEditor);
1227 pModel->setData(index, pLineEdit->text());
1228 } else if (pEditor->metaObject()->className() == QString("QLabel")) {
1229 QLabel* pLabel = static_cast<QLabel*> (pEditor);
1230 pModel->setData(index, pLabel->text());
1231 }
1232 }
1233 }
1234
1235 void DeviceParamDelegate::updateEditorGeometry ( QWidget *pEditor,
1236 const QStyleOptionViewItem &option, const QModelIndex &/* index */) const
1237 {
1238 if (pEditor)
1239 pEditor->setGeometry(option.rect);
1240 }
1241
1242 // end of qsamplerDevice.cpp

  ViewVC Help
Powered by ViewVC