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

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

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 426 by capela, Mon Mar 7 11:09:32 2005 UTC revision 2059 by capela, Wed Feb 17 19:50:04 2010 UTC
# Line 1  Line 1 
1  // qsamplerDevice.cpp  // qsamplerDevice.cpp
2  //  //
3  /****************************************************************************  /****************************************************************************
4     Copyright (C) 2003-2005, rncbc aka Rui Nuno Capela. All rights reserved.     Copyright (C) 2004-2010, rncbc aka Rui Nuno Capela. All rights reserved.
5       Copyright (C) 2007, 2008 Christian Schoenebeck
6    
7     This program is free software; you can redistribute it and/or     This program is free software; you can redistribute it and/or
8     modify it under the terms of the GNU General Public License     modify it under the terms of the GNU General Public License
# Line 13  Line 14 
14     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15     GNU General Public License for more details.     GNU General Public License for more details.
16    
17     You should have received a copy of the GNU General Public License     You should have received a copy of the GNU General Public License along
18     along with this program; if not, write to the Free Software     with this program; if not, write to the Free Software Foundation, Inc.,
19     Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.     51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
20    
21  *****************************************************************************/  *****************************************************************************/
22    
23    #include "qsamplerAbout.h"
24  #include "qsamplerDevice.h"  #include "qsamplerDevice.h"
25    
26  #include "qsamplerMainForm.h"  #include "qsamplerMainForm.h"
27  #include "qsamplerDeviceForm.h"  #include "qsamplerDeviceForm.h"
28    
29  #include "config.h"  #include <QCheckBox>
30    #include <QSpinBox>
31    #include <QLineEdit>
32    
33    
34    namespace QSampler {
35    
36    //-------------------------------------------------------------------------
37    // QSampler::DeviceParam - MIDI/Audio Device parameter structure.
38    //
39    
40    // Constructors.
41    DeviceParam::DeviceParam ( lscp_param_info_t *pParamInfo,
42            const char *pszValue )
43    {
44            setParam(pParamInfo, pszValue);
45    }
46    
47    
48    // Default destructor.
49    DeviceParam::~DeviceParam (void)
50    {
51    }
52    
53    
54    // Initializer.
55    void DeviceParam::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    // QSampler::Device - MIDI/Audio Device structure.
107    //
108    
109    // Constructor.
110    Device::Device ( DeviceType deviceType, int iDeviceID )
111    {
112    //      m_ports.setAutoDelete(true);
113    
114            setDevice(deviceType, iDeviceID);
115    }
116    
117    // Default destructor.
118    Device::~Device (void)
119    {
120            qDeleteAll(m_ports);
121            m_ports.clear();
122    }
123    
124    // Copy constructor.
125    Device::Device ( const Device& 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 Device::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 Device::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 Device::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 Device::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 Device::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 Device::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 Device::None:
203                            break;
204                    }
205                    if (pParamInfo) {
206                            m_params[sParam.toUpper()] = DeviceParam(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 Device::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 Device::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 Device::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 Device::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 Device::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 Device::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 Device::None:
278                            break;
279                    }
280                    if (pParamInfo) {
281                            m_params[sParam.toUpper()] = DeviceParam(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 Device::deviceID (void) const
295    {
296            return m_iDeviceID;
297    }
298    
299    Device::DeviceType Device::deviceType (void) const
300    {
301            return m_deviceType;
302    }
303    
304    const QString& Device::deviceTypeName (void) const
305    {
306            return m_sDeviceType;
307    }
308    
309    const QString& Device::driverName (void) const
310    {
311            return m_sDriverName;
312    }
313    
314    // Special device name formatter.
315    QString Device::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 Device::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 Device::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 Device::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 Device::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 DeviceParamMap& Device::params (void) const
390    {
391            return m_params;
392    }
393    
394    
395    // Device port/channel list accessor.
396    DevicePortList& Device::ports (void)
397    {
398            return m_ports;
399    }
400    
401    
402    // Create a new device, as a copy of this current one.
403    bool Device::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            DeviceParamMap::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 Device::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 Device::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 Device::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 Device::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 Device::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 Device::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 Device::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 Device::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            DeviceParamMap::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 Device::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 Device::Audio:
535                    iPorts = m_params["CHANNELS"].value.toInt();
536                    break;
537            case Device::Midi:
538                    iPorts = m_params["PORTS"].value.toInt();
539                    break;
540            case Device::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 DevicePort(*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 Device::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            DeviceParamMap::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 Device::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            DeviceParam& 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 Device::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 Device::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 Device::None:
633                    break;
634            }
635            if (pParamInfo) {
636                    param = DeviceParam(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 Device::appendMessages( const QString& s ) const
651    {
652            MainForm *pMainForm = MainForm::getInstance();
653            if (pMainForm)
654                    pMainForm->appendMessages(deviceName() + ' ' + s);
655    }
656    
657    void Device::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 Device::appendMessagesText( const QString& s ) const
666    {
667            MainForm *pMainForm = MainForm::getInstance();
668            if (pMainForm)
669                    pMainForm->appendMessagesText(deviceName() + ' ' + s);
670    }
671    
672    void Device::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 Device::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 *Device::getDevices ( lscp_client_t *pClient,
689            DeviceType deviceType )
690    {
691            int *piDeviceIDs = NULL;
692            switch (deviceType) {
693            case Device::Audio:
694                    piDeviceIDs = ::lscp_list_audio_devices(pClient);
695                    break;
696            case Device::Midi:
697                    piDeviceIDs = ::lscp_list_midi_devices(pClient);
698                    break;
699            case Device::None:
700                    break;
701            }
702            return piDeviceIDs;
703    }
704    
705    std::set<int> Device::getDeviceIDs(lscp_client_t *pClient,
706            DeviceType deviceType)
707    {
708            std::set<int> result;
709            int* piDeviceIDs = getDevices(pClient, deviceType);
710            if (!piDeviceIDs) return result;
711            for (int i = 0; piDeviceIDs[i] != -1; ++i)
712                    result.insert(piDeviceIDs[i]);
713            return result;
714    }
715    
716    
717    // Driver names enumerator.
718    QStringList Device::getDrivers ( lscp_client_t *pClient,
719            DeviceType deviceType )
720    {
721            QStringList drivers;
722    
723            const char **ppszDrivers = NULL;
724            switch (deviceType) {
725            case Device::Audio:
726                    ppszDrivers = ::lscp_list_available_audio_drivers(pClient);
727                    break;
728            case Device::Midi:
729                    ppszDrivers = ::lscp_list_available_midi_drivers(pClient);
730                    break;
731            case Device::None:
732                    break;
733            }
734    
735            for (int iDriver = 0; ppszDrivers && ppszDrivers[iDriver]; iDriver++)
736                    drivers.append(ppszDrivers[iDriver]);
737    
738            return drivers;
739    }
740    
741    
742  //-------------------------------------------------------------------------  //-------------------------------------------------------------------------
743  // qsamplerDeviceParameterTable - Device parameter view table.  // QSampler::DevicePort - MIDI/Audio Device port/channel structure.
744  //  //
745    
746  // Constructor.  // Constructor.
747  qsamplerDeviceParameterTable::qsamplerDeviceParameterTable ( QWidget *pParent, const char *pszName )  DevicePort::DevicePort ( Device& device,
748          : QTable(pParent, pszName)          int iPortID ) : m_device(device)
749    {
750            setDevicePort(iPortID);
751    }
752    
753    // Default destructor.
754    DevicePort::~DevicePort (void)
755    {
756    }
757    
758    
759    // Initializer.
760    void DevicePort::setDevicePort ( int iPortID )
761    {
762            MainForm *pMainForm = MainForm::getInstance();
763            if (pMainForm == NULL)
764                    return;
765            if (pMainForm->client() == NULL)
766                    return;
767    
768            // Device port id should be always set.
769            m_iPortID = iPortID;
770    
771            // Reset port parameters anyway.
772            m_params.clear();
773    
774            // Retrieve device port/channel info, if any.
775            lscp_device_port_info_t *pPortInfo = NULL;
776            switch (m_device.deviceType()) {
777            case Device::Audio:
778                    if ((pPortInfo = ::lscp_get_audio_channel_info(pMainForm->client(),
779                                    m_device.deviceID(), m_iPortID)) == NULL)
780                            m_device.appendMessagesClient("lscp_get_audio_channel_info");
781                    break;
782            case Device::Midi:
783                    if ((pPortInfo = ::lscp_get_midi_port_info(pMainForm->client(),
784                                    m_device.deviceID(), m_iPortID)) == NULL)
785                            m_device.appendMessagesClient("lscp_get_midi_port_info");
786                    break;
787            case Device::None:
788                    break;
789            }
790    
791            // If we're bogus, bail out...
792            if (pPortInfo == NULL) {
793                    m_sPortName = QString::null;
794                    return;
795            }
796    
797            // Set device port/channel properties...
798            m_sPortName = pPortInfo->name;
799    
800            // Grab device port/channel parameters...
801            m_params.clear();
802            for (int i = 0; pPortInfo->params && pPortInfo->params[i].key; i++) {
803                    const QString sParam = pPortInfo->params[i].key;
804                    lscp_param_info_t *pParamInfo = NULL;
805                    switch (m_device.deviceType()) {
806                    case Device::Audio:
807                            if ((pParamInfo = ::lscp_get_audio_channel_param_info(
808                                            pMainForm->client(), m_device.deviceID(),
809                                            m_iPortID, sParam.toUtf8().constData())) == NULL)
810                                    m_device.appendMessagesClient("lscp_get_audio_channel_param_info");
811                            break;
812                    case Device::Midi:
813                            if ((pParamInfo = ::lscp_get_midi_port_param_info(
814                                            pMainForm->client(), m_device.deviceID(),
815                                            m_iPortID, sParam.toUtf8().constData())) == NULL)
816                                    m_device.appendMessagesClient("lscp_get_midi_port_param_info");
817                            break;
818                    case Device::None:
819                            break;
820                    }
821                    if (pParamInfo) {
822                            m_params[sParam.toUpper()] = DeviceParam(pParamInfo,
823                                    pPortInfo->params[i].value);
824                    }
825            }
826    }
827    
828    
829    // Device port/channel property accessors.
830    int DevicePort::portID (void) const
831    {
832            return m_iPortID;
833    }
834    
835    const QString& DevicePort::portName (void) const
836    {
837            return m_sPortName;
838    }
839    
840    // Device port/channel parameter accessor.
841    const DeviceParamMap& DevicePort::params (void) const
842    {
843            return m_params;
844    }
845    
846    
847    // Set the proper device port/channel parameter value.
848    bool DevicePort::setParam ( const QString& sParam,
849            const QString& sValue )
850    {
851            MainForm *pMainForm = MainForm::getInstance();
852            if (pMainForm == NULL)
853                    return false;
854            if (pMainForm->client() == NULL)
855                    return false;
856    
857            // Set proper port/channel parameter.
858            m_params[sParam.toUpper()].value = sValue;
859    
860            // If the device already exists, things get immediate...
861            int iRefresh = 0;
862            if (m_device.deviceID() >= 0 && m_iPortID >= 0) {
863    
864                    // we need temporary byte arrrays with the final strings, because
865                    // i.e. QString::toUtf8() only returns a temporary object and the
866                    // C-style char* pointers for liblscp would immediately be invalidated
867                    QByteArray finalParamKey = sParam.toUtf8();
868                    QByteArray finalParamVal = sValue.toUtf8();
869    
870                    // Prepare parameter struct.
871                    lscp_param_t param;
872                    param.key   = (char *) finalParamKey.constData();
873                    param.value = (char *) finalParamVal.constData();
874                    // Now it depends on the device type...
875                    lscp_status_t ret = LSCP_FAILED;
876                    switch (m_device.deviceType()) {
877                    case Device::Audio:
878                            if ((ret = ::lscp_set_audio_channel_param(pMainForm->client(),
879                                            m_device.deviceID(), m_iPortID, &param)) != LSCP_OK)
880                                    m_device.appendMessagesClient("lscp_set_audio_channel_param");
881                            break;
882                    case Device::Midi:
883                            if ((ret = ::lscp_set_midi_port_param(pMainForm->client(),
884                                            m_device.deviceID(), m_iPortID, &param)) != LSCP_OK)
885                                    m_device.appendMessagesClient("lscp_set_midi_port_param");
886                            break;
887                    case Device::None:
888                            break;
889                    }
890                    // Show result.
891                    if (ret == LSCP_OK) {
892                            m_device.appendMessages(m_sPortName
893                                    + ' ' + QString("%1: %2.").arg(sParam).arg(sValue));
894                            iRefresh++;
895                    } else {
896                            m_device.appendMessagesError(
897                                    QObject::tr("Could not set %1 parameter value.\n\n"
898                                            "Sorry.").arg(m_sPortName));
899                    }
900            }
901    
902            // Return whether we're need a view refresh.
903            return (iRefresh > 0);
904    }
905    
906    
907    //-------------------------------------------------------------------------
908    // QSampler::DeviceItem - QTreeWidget device item.
909    //
910    
911    // Constructors.
912    DeviceItem::DeviceItem ( QTreeWidget* pTreeWidget,
913            Device::DeviceType deviceType )
914            : QTreeWidgetItem(pTreeWidget, QSAMPLER_DEVICE_ITEM),
915                    m_device(deviceType)
916  {  {
917          m_pClient = NULL;          switch(m_device.deviceType()) {
918            case Device::Audio:
919                    setIcon(0, QPixmap(":/icons/audio1.png"));
920                    setText(0, QObject::tr("Audio Devices"));
921                    break;
922            case Device::Midi:
923                    setIcon(0, QPixmap(":/icons/midi1.png"));
924                    setText(0, QObject::tr("MIDI Devices"));
925                    break;
926            case Device::None:
927                    break;
928            }
929    
930            // Root items are not selectable...
931            setFlags(flags() & ~Qt::ItemIsSelectable);
932    }
933    
934    DeviceItem::DeviceItem ( QTreeWidgetItem* pItem,
935            Device::DeviceType deviceType,
936            int iDeviceID )
937            : QTreeWidgetItem(pItem, QSAMPLER_DEVICE_ITEM),
938                    m_device(deviceType, iDeviceID)
939    {
940            switch(m_device.deviceType()) {
941            case Device::Audio:
942                    setIcon(0, QPixmap(":/icons/audio2.png"));
943                    break;
944            case Device::Midi:
945                    setIcon(0, QPixmap(":/icons/midi2.png"));
946                    break;
947            case Device::None:
948                    break;
949            }
950    
951            setText(0, m_device.deviceName());
952  }  }
953    
954  // Default destructor.  // Default destructor.
955  qsamplerDeviceParameterTable::~qsamplerDeviceParameterTable (void)  DeviceItem::~DeviceItem ()
956    {
957    }
958    
959    // Instance accessors.
960    Device& DeviceItem::device ()
961    {
962            return m_device;
963    }
964    
965    
966    //-------------------------------------------------------------------------
967    // QSampler::AbstractDeviceParamModel - data model base class for device parameters
968    //
969    
970    AbstractDeviceParamModel::AbstractDeviceParamModel ( QObject* pParent )
971            : QAbstractTableModel(pParent), m_bEditable(false)
972    {
973            m_pParams = NULL;
974    }
975    
976    
977    int AbstractDeviceParamModel::rowCount ( const QModelIndex& /*parent*/) const
978    {
979            //std::cout << "model size=" << params.size() << "\n" << std::flush;
980            return (m_pParams ? m_pParams->size() : 0);
981    }
982    
983    
984    int AbstractDeviceParamModel::columnCount ( const QModelIndex& /*parent*/) const
985    {
986            return 3;
987    }
988    
989    
990    Qt::ItemFlags AbstractDeviceParamModel::flags ( const QModelIndex& /*index*/) const
991    {
992            return Qt::ItemIsEditable | Qt::ItemIsEnabled;
993    }
994    
995    
996    QVariant AbstractDeviceParamModel::headerData (
997            int section, Qt::Orientation orientation, int role) const
998    {
999            if (role != Qt::DisplayRole)
1000                    return QVariant();
1001    
1002            if (orientation == Qt::Horizontal) {
1003                    switch (section) {
1004                            case 0:  return tr("Parameter");
1005                            case 1:  return tr("Value");
1006                            case 2:  return tr("Description");
1007                            default: return QVariant();
1008                    }
1009            }
1010    
1011            return QVariant();
1012    }
1013    
1014    
1015    void AbstractDeviceParamModel::refresh (
1016            const DeviceParamMap* pParams, bool bEditable )
1017    {
1018            m_pParams   = pParams;
1019            m_bEditable = bEditable;
1020            // inform the outer world (QTableView) that our data changed
1021            QAbstractTableModel::reset();
1022    }
1023    
1024    
1025    void AbstractDeviceParamModel::clear (void)
1026    {
1027            m_pParams = NULL;
1028            // inform the outer world (QTableView) that our data changed
1029            QAbstractTableModel::reset();
1030    }
1031    
1032    
1033    //-------------------------------------------------------------------------
1034    // QSampler::DeviceParamModel - data model for device parameters
1035    //                              (used for QTableView)
1036    
1037    DeviceParamModel::DeviceParamModel ( QObject *pParent )
1038            : AbstractDeviceParamModel(pParent)
1039    {
1040            m_pDevice = NULL;
1041    }
1042    
1043    QVariant DeviceParamModel::data (
1044            const QModelIndex &index, int role) const
1045    {
1046            if (!index.isValid())
1047                    return QVariant();
1048    
1049            if (role != Qt::DisplayRole)
1050                    return QVariant();
1051    
1052            DeviceParameterRow item;
1053            item.name  = m_pParams->keys()[index.row()];
1054            item.param = (*m_pParams)[item.name];
1055            item.alive = (m_pDevice && m_pDevice->deviceID() >= 0);
1056    
1057            return QVariant::fromValue(item);
1058    }
1059    
1060    
1061    bool DeviceParamModel::setData (
1062            const QModelIndex& index, const QVariant& value, int /*role*/)
1063    {
1064            if (!index.isValid())
1065                    return false;
1066    
1067            QString key = m_pParams->keys()[index.row()];
1068            //m_pParams[key].value = value.toString();
1069            m_pDevice->setParam(key, value.toString());
1070            emit dataChanged(index, index);
1071            return true;
1072    }
1073    
1074    
1075    void DeviceParamModel::refresh ( Device* pDevice, bool bEditable )
1076    {
1077            m_pDevice = pDevice;
1078            AbstractDeviceParamModel::refresh(&pDevice->params(), bEditable);
1079    }
1080    
1081    
1082    void DeviceParamModel::clear (void)
1083    {
1084            AbstractDeviceParamModel::clear();
1085            m_pDevice = NULL;
1086    }
1087    
1088    
1089    //-------------------------------------------------------------------------
1090    // QSampler::PortParamModel - data model for port parameters
1091    //                            (used for QTableView)
1092    
1093    PortParamModel::PortParamModel ( QObject *pParent)
1094            : AbstractDeviceParamModel(pParent)
1095    {
1096            m_pPort = NULL;
1097    }
1098    
1099    QVariant PortParamModel::data ( const QModelIndex &index, int role ) const
1100    {
1101            if (!index.isValid())
1102                    return QVariant();
1103    
1104            if (role != Qt::DisplayRole)
1105                    return QVariant();
1106    
1107            DeviceParameterRow item;
1108            item.name  = m_pParams->keys()[index.row()];
1109            item.param = (*m_pParams)[item.name];
1110            item.alive = (m_pPort && m_pPort->portID() >= 0);
1111    
1112            return QVariant::fromValue(item);
1113    }
1114    
1115    
1116    bool PortParamModel::setData (
1117            const QModelIndex& index, const QVariant& value, int /*role*/)
1118    {
1119            if (!index.isValid())
1120                    return false;
1121    
1122            QString key = m_pParams->keys()[index.row()];
1123            //params[key].value = value.toString();
1124            m_pPort->setParam(key, value.toString());
1125            emit dataChanged(index, index);
1126            return true;
1127    }
1128    
1129    
1130    void PortParamModel::refresh ( DevicePort* pPort, bool bEditable )
1131    {
1132            m_pPort = pPort;
1133            AbstractDeviceParamModel::refresh(&pPort->params(), bEditable);
1134    }
1135    
1136    
1137    void PortParamModel::clear (void)
1138    {
1139            AbstractDeviceParamModel::clear();
1140            m_pPort = NULL;
1141    }
1142    
1143    
1144    //-------------------------------------------------------------------------
1145    // QSampler::DeviceParamDelegate - table cell renderer for device/port parameters
1146    //
1147    
1148    DeviceParamDelegate::DeviceParamDelegate ( QObject *pParent)
1149            : QItemDelegate(pParent)
1150    {
1151    }
1152    
1153    
1154    QWidget* DeviceParamDelegate::createEditor ( QWidget *pParent,
1155            const QStyleOptionViewItem& /* option */, const QModelIndex& index ) const
1156    {
1157            if (!index.isValid())
1158                    return NULL;
1159    
1160            DeviceParameterRow r = index.model()->data(index,
1161                    Qt::DisplayRole).value<DeviceParameterRow>();
1162    
1163            const bool bEnabled = (r.alive) ? !r.param.fix : true;
1164    
1165            QString val = (r.alive) ? r.param.value : r.param.defaultv;
1166    
1167            switch (index.column()) {
1168                    case 0:
1169                            return new QLabel(r.name, pParent);
1170                    case 1: {
1171                            if (r.param.type == LSCP_TYPE_BOOL) {
1172                                    QCheckBox *pCheckBox = new QCheckBox(pParent);
1173                                    if (val != QString::null)
1174                                            pCheckBox->setChecked(val.toLower() == "true");
1175                                    pCheckBox->setEnabled(bEnabled);
1176                                    return pCheckBox;
1177                            } else if (r.param.possibilities.count() > 0) {
1178                                    QStringList opts = r.param.possibilities;
1179                                    if (r.param.multiplicity)
1180                                            opts.prepend(tr("(none)"));
1181                                    QComboBox *pComboBox = new QComboBox(pParent);
1182                                    pComboBox->addItems(opts);
1183                                    if (r.param.value.isEmpty())
1184                                            pComboBox->setCurrentIndex(0);
1185                                    else
1186                                            pComboBox->setCurrentIndex(pComboBox->findText(val));
1187                                    pComboBox->setEnabled(bEnabled);
1188                                    return pComboBox;
1189                            } else if (r.param.type == LSCP_TYPE_INT && bEnabled) {
1190                                    QSpinBox *pSpinBox = new QSpinBox(pParent);
1191                                    pSpinBox->setMinimum(
1192                                            (!r.param.range_min.isEmpty()) ?
1193                                                    r.param.range_min.toInt() : 0 // or better a negative default min value ?
1194                                    );
1195                                    pSpinBox->setMaximum(
1196                                            (!r.param.range_max.isEmpty()) ?
1197                                                    r.param.range_max.toInt() : (1 << 24) // or better a higher default max value ?
1198                                    );
1199                                    pSpinBox->setValue(val.toInt());
1200                                    return pSpinBox;
1201                            } else if (bEnabled) {
1202                                    QLineEdit *pLineEdit = new QLineEdit(val, pParent);
1203                                    return pLineEdit;
1204                            } else {
1205                                    QLabel *pLabel = new QLabel(val, pParent);
1206                                    return pLabel;
1207                            }
1208                    }
1209                    case 2:
1210                            return new QLabel(r.param.description, pParent);
1211                    default:
1212                            return NULL;
1213            }
1214    }
1215    
1216    
1217    void DeviceParamDelegate::setEditorData (
1218            QWidget* /*pEditor*/, const QModelIndex& /*index*/) const
1219  {  {
1220            // Unused, since we set the editor data already in createEditor()
1221  }  }
1222    
1223    
1224  // The client descriptor property accessors.  void DeviceParamDelegate::setModelData ( QWidget *pEditor,
1225  void qsamplerDeviceParameterTable::setClient ( lscp_client_t *pClient )          QAbstractItemModel *pModel, const QModelIndex& index ) const
1226  {  {
1227      m_pClient = pClient;          if (index.column() == 1) {
1228                    DeviceParameterRow r = index.model()->data(index,
1229                            Qt::DisplayRole).value<DeviceParameterRow> ();
1230                    if (pEditor->metaObject()->className() == QString("QCheckBox")) {
1231                            QCheckBox *pCheckBox = static_cast<QCheckBox *> (pEditor);
1232                            pModel->setData(index, QVariant(pCheckBox->checkState() == Qt::Checked));
1233                    } else if (pEditor->metaObject()->className() == QString("QComboBox")) {
1234                            QComboBox *pComboBox = static_cast<QComboBox *> (pEditor);
1235                            pModel->setData(index, pComboBox->currentText());
1236                    } else if (pEditor->metaObject()->className() == QString("QSpinBox")) {
1237                            QSpinBox *pSpinBox = static_cast<QSpinBox *> (pEditor);
1238                            pModel->setData(index, pSpinBox->value());
1239                    } else if (pEditor->metaObject()->className() == QString("QLineEdit")) {
1240                            QLineEdit *pLineEdit = static_cast<QLineEdit *> (pEditor);
1241                            pModel->setData(index, pLineEdit->text());
1242                    } else if (pEditor->metaObject()->className() == QString("QLabel")) {
1243                            QLabel *pLabel = static_cast<QLabel *> (pEditor);
1244                            pModel->setData(index, pLabel->text());
1245                    }
1246            }
1247  }  }
1248    
1249  lscp_client_t *qsamplerDeviceParameterTable::client (void)  void DeviceParamDelegate::updateEditorGeometry ( QWidget *pEditor,
1250            const QStyleOptionViewItem &option, const QModelIndex &/* index */) const
1251  {  {
1252      return m_pClient;          if (pEditor)
1253                    pEditor->setGeometry(option.rect);
1254  }  }
1255    
1256    } // namespace QSampler
1257    
1258  // end of qsamplerDevice.cpp  // end of qsamplerDevice.cpp

Legend:
Removed from v.426  
changed lines
  Added in v.2059

  ViewVC Help
Powered by ViewVC