--- qsampler/trunk/src/qsamplerDeviceForm.ui.h 2005/03/08 20:12:08 431 +++ qsampler/trunk/src/qsamplerDeviceForm.ui.h 2005/03/15 15:32:29 463 @@ -24,6 +24,8 @@ #include #include #include +#include +#include #include "qsamplerMainForm.h" @@ -37,9 +39,16 @@ m_pMainForm = (qsamplerMainForm *) QWidget::parentWidget(); m_pClient = NULL; m_iDirtySetup = 0; - m_iDirtyCount = 0; - m_iUntitled = 1; m_bNewDevice = false; + m_deviceType = qsamplerDevice::None; + m_pAudioItems = NULL; + m_pMidiItems = NULL; + + // This an outsider (from designer), but rather important. + QObject::connect(DeviceParamTable, SIGNAL(valueChanged(int,int)), + this, SLOT(changeDeviceParam(int,int))); + QObject::connect(DevicePortParamTable, SIGNAL(valueChanged(int,int)), + this, SLOT(changeDevicePortParam(int,int))); // Try to restore normal window positioning. adjustSize(); @@ -89,169 +98,117 @@ } -// Format the displayable device configuration filename. -QString qsamplerDeviceForm::devicesName ( const QString& sFilename ) -{ - QString sDevicesName = sFilename; - qsamplerOptions *pOptions = m_pMainForm->options(); - if (pOptions) { - bool bCompletePath = (pOptions && pOptions->bCompletePath); - if (sDevicesName.isEmpty()) - sDevicesName = tr("Untitled") + QString::number(m_iUntitled); - else if (!bCompletePath) - sDevicesName = QFileInfo(sDevicesName).fileName(); - } - return sDevicesName; -} - - -// Window close event handlers. -bool qsamplerDeviceForm::queryClose (void) -{ - bool bQueryClose = true; - - if (m_iDirtyCount > 0) { - switch (QMessageBox::warning(this, tr("Warning"), - tr("The device configuration has been changed.\n\n" - "\"%1\"\n\n" - "Do you want to save the changes?") - .arg(devicesName(m_sFilename)), - tr("Save"), tr("Discard"), tr("Cancel"))) { - case 0: // Save... - saveDevices(); - // Fall thru.... - case 1: // Discard - break; - default: // Cancel. - bQueryClose = false; - } - } - - return bQueryClose; -} - - - -// Dirty up settings. -void qsamplerDeviceForm::contentsChanged (void) +// Create a new device from current table view. +void qsamplerDeviceForm::createDevice (void) { - if (m_iDirtySetup > 0) + QListViewItem *pItem = DeviceListView->selectedItem(); + if (pItem == NULL || pItem->rtti() != QSAMPLER_DEVICE_ITEM) return; - m_iDirtyCount++; - stabilizeForm(); -} - - -// Load device configuration slot. -void qsamplerDeviceForm::loadDevices (void) -{ - QString sFilename = QFileDialog::getOpenFileName( - m_sFilename, // Start here. - tr("Device Configuration files") + " (*.lscp)", // Filter (XML files) - this, 0, // Parent and name (none) - tr("Load Device Configuration") // Caption. - ); + const qsamplerDevice& device = ((qsamplerDeviceItem *) pItem)->device(); - if (sFilename.isEmpty()) - return; + // Build the parameter list... + const qsamplerDeviceParamMap& params = device.params(); + lscp_param_t *pParams = new lscp_param_t [params.count() + 1]; + int iParam = 0; + qsamplerDeviceParamMap::ConstIterator iter; + for (iter = params.begin(); iter != params.end(); ++iter) { + pParams[iParam].key = (char *) iter.key().latin1(); + pParams[iParam].value = (char *) iter.data().value.latin1(); + ++iParam; + } + // Null terminated. + pParams[iParam].key = NULL; + pParams[iParam].value = NULL; + + // Now it depends on the device type... + qsamplerDeviceItem *pRootItem = NULL; + int iDeviceID = -1; + switch (device.deviceType()) { + case qsamplerDevice::Audio: + pRootItem = m_pAudioItems; + if ((iDeviceID = ::lscp_create_audio_device(m_pClient, + device.driverName().latin1(), pParams)) < 0) + m_pMainForm->appendMessagesClient("lscp_create_audio_device"); + break; + case qsamplerDevice::Midi: + pRootItem = m_pMidiItems; + if ((iDeviceID = ::lscp_create_midi_device(m_pClient, + device.driverName().latin1(), pParams)) < 0) + m_pMainForm->appendMessagesClient("lscp_create_midi_device"); + break; + case qsamplerDevice::None: + break; + } - // Check if we're going to discard safely the current one... - if (!queryClose()) - return; + // Free used parameter array. + delete pParams; - // Load it right away... - loadDevicesFile(sFilename); + // We're on to create the new device item. + if (iDeviceID >= 0) { + // Append the new device item. + qsamplerDeviceItem *pDeviceItem = new qsamplerDeviceItem(pRootItem, + m_pClient, device.deviceType(), iDeviceID); + // Just make it the new selection... + DeviceListView->setSelected(pDeviceItem, true); + // Done. + m_pMainForm->appendMessages(pDeviceItem->device().deviceName() + ' ' + + tr("created.")); + // Main session should be marked dirty. + m_pMainForm->sessionDirty(); + } } -// Save device configuration slot. -void qsamplerDeviceForm::saveDevices (void) +// Delete current device in table view. +void qsamplerDeviceForm::deleteDevice (void) { - QString sFilename = QFileDialog::getSaveFileName( - m_sFilename, // Start here. - tr("Device Configuration files") + " (*.lscp)", // Filter (XML files) - this, 0, // Parent and name (none) - tr("Save Device Configuration") // Caption. - ); - - if (sFilename.isEmpty()) + QListViewItem *pItem = DeviceListView->selectedItem(); + if (pItem == NULL || pItem->rtti() != QSAMPLER_DEVICE_ITEM) return; - // Enforce .xml extension... - if (QFileInfo(sFilename).extension().isEmpty()) - sFilename += ".lscp"; - - // Save it right away... - saveDevicesFile(sFilename); -} - - -// Load device configuration from file. -void qsamplerDeviceForm::loadDevicesFile ( const QString& sFilename ) -{ - // - // TODO: Load device configuration from file... - // - m_pMainForm->appendMessages("qsamplerDeviceForm::loadDevicesFile(\"" + sFilename + "\")..."); - - m_sFilename = sFilename; - m_iDirtyCount = 0; - - refreshDevices(); -} - - -// Save device configuration into file. -void qsamplerDeviceForm::saveDevicesFile ( const QString& sFilename ) -{ - // - // TODO: Save device configuration into file... - // - m_pMainForm->appendMessages("qsamplerDeviceForm::saveDevicesFile(\"" + sFilename + "\")..."); - - m_sFilename = sFilename; - m_iDirtyCount = 0; - stabilizeForm(); -} - - -// Create a new device from current table view. -void qsamplerDeviceForm::createDevice (void) -{ - // - // TODO: Create a new device from current table view... - // - m_pMainForm->appendMessages("qsamplerDeviceForm::createDevice()..."); - - m_iDirtyCount++; - stabilizeForm(); -} - - -// Update current device in table view. -void qsamplerDeviceForm::updateDevice (void) -{ - // - // TODO: Update current device in table view... - // - m_pMainForm->appendMessages("qsamplerDeviceForm::updateDevice()..."); - - m_iDirtyCount++; - stabilizeForm(); -} + const qsamplerDevice& device = ((qsamplerDeviceItem *) pItem)->device(); + // Prompt user if this is for real... + qsamplerOptions *pOptions = m_pMainForm->options(); + if (pOptions && pOptions->bConfirmRemove) { + if (QMessageBox::warning(this, tr("Warning"), + tr("Delete %1 device:\n\n" + "%2\n\n" + "Are you sure?") + .arg(device.deviceTypeName()) + .arg(device.deviceName()), + tr("OK"), tr("Cancel")) > 0) + return; + } -// Delete current device in table view. -void qsamplerDeviceForm::deleteDevice (void) -{ - // - // TODO: Delete current device in table view... - // - m_pMainForm->appendMessages("qsamplerDeviceForm::deleteDevice()..."); + // Now it depends on the device type... + lscp_status_t ret = LSCP_FAILED; + switch (device.deviceType()) { + case qsamplerDevice::Audio: + if ((ret = ::lscp_destroy_audio_device(m_pClient, + device.deviceID())) != LSCP_OK) + m_pMainForm->appendMessagesClient("lscp_destroy_audio_device"); + break; + case qsamplerDevice::Midi: + if ((ret = ::lscp_destroy_midi_device(m_pClient, + device.deviceID())) != LSCP_OK) + m_pMainForm->appendMessagesClient("lscp_destroy_midi_device"); + break; + case qsamplerDevice::None: + break; + } - m_iDirtyCount++; - stabilizeForm(); + // Show result. + if (ret == LSCP_OK) { + // Show log message before loosing it. + m_pMainForm->appendMessages(device.deviceName() + ' ' + + tr("deleted.")); + // Done. + delete pItem; + // Main session should be marked dirty. + m_pMainForm->sessionDirty(); + } } @@ -262,137 +219,374 @@ m_iDirtySetup++; // - // TODO: Load device configuration data ... + // (Re)Load complete device configuration data ... // - m_pMainForm->appendMessages("qsamplerDeviceForm::refreshDevices()"); - + m_pAudioItems = NULL; + m_pMidiItems = NULL; DeviceListView->clear(); if (m_pClient) { - qsamplerDeviceItem *pItem; int *piDeviceIDs; // Grab and pop Audio devices... - pItem = new qsamplerDeviceItem(DeviceListView, m_pClient, + m_pAudioItems = new qsamplerDeviceItem(DeviceListView, m_pClient, qsamplerDevice::Audio); - if (pItem) { - pItem->setText(0, tr("Audio")); + if (m_pAudioItems) { + m_pAudioItems->setText(0, tr("Audio")); piDeviceIDs = qsamplerDevice::getDevices(m_pClient, qsamplerDevice::Audio); for (int i = 0; piDeviceIDs && piDeviceIDs[i] >= 0; i++) { - new qsamplerDeviceItem(pItem, m_pClient, + new qsamplerDeviceItem(m_pAudioItems, m_pClient, qsamplerDevice::Audio, piDeviceIDs[i]); } - pItem->setOpen(true); + m_pAudioItems->setOpen(true); } // Grab and pop MIDI devices... - pItem = new qsamplerDeviceItem(DeviceListView, m_pClient, + m_pMidiItems = new qsamplerDeviceItem(DeviceListView, m_pClient, qsamplerDevice::Midi); - if (pItem) { - pItem->setText(0, tr("MIDI")); + if (m_pMidiItems) { + m_pMidiItems->setText(0, tr("MIDI")); piDeviceIDs = qsamplerDevice::getDevices(m_pClient, qsamplerDevice::Midi); for (int i = 0; piDeviceIDs && piDeviceIDs[i] >= 0; i++) { - new qsamplerDeviceItem(pItem, m_pClient, + new qsamplerDeviceItem(m_pMidiItems, m_pClient, qsamplerDevice::Midi, piDeviceIDs[i]); } - pItem->setOpen(true); + m_pMidiItems->setOpen(true); } } // Done. - selectDevice(); m_iDirtySetup--; + + // Show something. + selectDevice(); } // Driver selection slot. void qsamplerDeviceForm::selectDriver ( const QString& sDriverName ) { + if (m_iDirtySetup > 0) + return; + // - // TODO: Driver name has changed for a new device... + // Driver name has changed for a new device... // - m_pMainForm->appendMessages("qsamplerDeviceForm::selectDriver(\"" + sDriverName + "\")"); QListViewItem *pItem = DeviceListView->selectedItem(); if (pItem == NULL || pItem->rtti() != QSAMPLER_DEVICE_ITEM) return; qsamplerDevice& device = ((qsamplerDeviceItem *) pItem)->device(); + + // Driver change is only valid for scratch devices... if (m_bNewDevice) { + m_iDirtySetup++; device.setDriver(m_pClient, sDriverName); - m_iDirtyCount++; + DeviceParamTable->refresh(device.params(), m_bNewDevice); + m_iDirtySetup--; + // Done. + stabilizeForm(); } - - // Done. - stabilizeForm(); } // Device selection slot. void qsamplerDeviceForm::selectDevice (void) { + if (m_iDirtySetup > 0) + return; + // - // TODO: Device selection has changed... + // Device selection has changed... // - m_pMainForm->appendMessages("qsamplerDeviceForm::selectDevice()"); QListViewItem *pItem = DeviceListView->selectedItem(); if (pItem == NULL || pItem->rtti() != QSAMPLER_DEVICE_ITEM) { + m_deviceType = qsamplerDevice::None; + DeviceNameTextLabel->setText(QString::null); + DeviceParamTable->setNumRows(0); + DevicePortComboBox->setEnabled(false); + DevicePortParamTable->setEnabled(false); stabilizeForm(); return; } qsamplerDevice& device = ((qsamplerDeviceItem *) pItem)->device(); + + m_iDirtySetup++; + // Flag whether this is a new device. m_bNewDevice = (device.deviceID() < 0); - // Fill the device heading... - DeviceNameTextLabel->setText(' ' + device.deviceName()); - DriverNameComboBox->clear(); - DriverNameComboBox->insertStringList( - qsamplerDevice::getDrivers(m_pClient, device.deviceType())); - const QString& sDriverName = device.driverName(); - if (m_bNewDevice || sDriverName.isEmpty()) { - device.setDriver(m_pClient, DriverNameComboBox->currentText()); - } else { - if (DriverNameComboBox->listBox()->findItem(sDriverName, Qt::ExactMatch) == NULL) - DriverNameComboBox->insertItem(sDriverName); - DriverNameComboBox->setCurrentText(sDriverName); + // Fill the device/driver heading... + QString sPrefix; + if (!m_bNewDevice) + sPrefix += device.deviceTypeName() + ' '; + DeviceNameTextLabel->setText(sPrefix + device.deviceName()); + // The driver combobox is only rebuilt if device type has changed... + if (device.deviceType() != m_deviceType) { + DriverNameComboBox->clear(); + DriverNameComboBox->insertStringList( + qsamplerDevice::getDrivers(m_pClient, device.deviceType())); + m_deviceType = device.deviceType(); } + // Do we need a driver name? + if (m_bNewDevice || device.driverName().isEmpty()) + device.setDriver(m_pClient, DriverNameComboBox->currentText()); + const QString& sDriverName = device.driverName(); + if (DriverNameComboBox->listBox()->findItem(sDriverName, Qt::ExactMatch) == NULL) + DriverNameComboBox->insertItem(sDriverName); + DriverNameComboBox->setCurrentText(sDriverName); DriverNameTextLabel->setEnabled(m_bNewDevice); DriverNameComboBox->setEnabled(m_bNewDevice); - // Fill the device parameter table... - DeviceParamTable->refresh(device); + DeviceParamTable->refresh(device.params(), m_bNewDevice); + // And now the device port/channel parameter table... + DevicePortComboBox->clear(); + DevicePortParamTable->setNumRows(0); + if (m_bNewDevice) { + DevicePortComboBox->setEnabled(false); + DevicePortParamTable->setEnabled(false); + } else { + QPixmap pixmap; + switch (device.deviceType()) { + case qsamplerDevice::Audio: + pixmap = QPixmap::fromMimeSource("audio2.png"); + break; + case qsamplerDevice::Midi: + pixmap = QPixmap::fromMimeSource("midi2.png"); + break; + case qsamplerDevice::None: + break; + } + qsamplerDevicePortList& ports = device.ports(); + qsamplerDevicePort *pPort; + for (pPort = ports.first(); pPort; pPort = ports.next()) { + DevicePortComboBox->insertItem(pixmap, + device.deviceTypeName() + ' ' + pPort->portName()); + } + bool bEnabled = (ports.count() > 0); + DevicePortComboBox->setEnabled(bEnabled); + DevicePortParamTable->setEnabled(bEnabled); + } + // Done. + m_iDirtySetup--; + + // Make the device port/channel selection effective. + selectDevicePort(DevicePortComboBox->currentItem()); +} + + +// Device port/channel selection slot. +void qsamplerDeviceForm::selectDevicePort ( int iPort ) +{ + if (m_iDirtySetup > 0) + return; + + // + // Device port/channel selection has changed... + // + QListViewItem *pItem = DeviceListView->selectedItem(); + if (pItem == NULL || pItem->rtti() != QSAMPLER_DEVICE_ITEM) + return; + + qsamplerDevice& device = ((qsamplerDeviceItem *) pItem)->device(); + qsamplerDevicePort *pPort = device.ports().at(iPort); + if (pPort) { + m_iDirtySetup++; + DevicePortParamTable->refresh(pPort->params(), true); + m_iDirtySetup--; + } // Done. stabilizeForm(); } -// Stabilize current form state. -void qsamplerDeviceForm::stabilizeForm (void) +// Device parameter value change slot. +void qsamplerDeviceForm::changeDeviceParam ( int iRow, int iCol ) { - // Update the main caption... - QString sDevicesName = devicesName(m_sFilename); - if (m_iDirtyCount > 0) - sDevicesName += '*'; - setCaption(tr("Devices - [%1]").arg(sDevicesName)); + if (m_iDirtySetup > 0) + return; + if (iRow < 0 || iCol < 0) + return; + + // + // Device parameter change... + // + + QListViewItem *pItem = DeviceListView->selectedItem(); + if (pItem == NULL || pItem->rtti() != QSAMPLER_DEVICE_ITEM) + return; + + qsamplerDevice& device = ((qsamplerDeviceItem *) pItem)->device(); + + m_iDirtySetup++; + // Table 1st column has the parameter name; + const qsamplerDeviceParamMap& params = device.params(); + const QString sParam = DeviceParamTable->text(iRow, 0); + const QString sValue = DeviceParamTable->text(iRow, iCol); + + // Set the local device parameter value. + device.setParam(sParam, sValue); + + // Set proper device parameter, on existing device ... + if (device.deviceID() >= 0) { + // Prepare parameter struct. + lscp_param_t param; + param.key = (char *) sParam.latin1(); + param.value = (char *) sValue.latin1(); + // Now it depends on the device type... + bool bRefresh = false; + lscp_status_t ret = LSCP_FAILED; + switch (device.deviceType()) { + case qsamplerDevice::Audio: + bRefresh = (sParam == "CHANNELS"); + if ((ret = ::lscp_set_audio_device_param(m_pClient, + device.deviceID(), ¶m)) != LSCP_OK) + m_pMainForm->appendMessagesClient("lscp_set_audio_device_param"); + break; + case qsamplerDevice::Midi: + bRefresh = (sParam == "PORTS"); + if ((ret = ::lscp_set_midi_device_param(m_pClient, + device.deviceID(), ¶m)) != LSCP_OK) + m_pMainForm->appendMessagesClient("lscp_set_midi_device_param"); + break; + case qsamplerDevice::None: + break; + } + // Show result. + if (ret == LSCP_OK) { + m_pMainForm->appendMessages(device.deviceName() + ' ' + + QString("%1: %2.").arg(sParam).arg(sValue)); + // Special care for specific parameter changes... + if (bRefresh) + device.refresh(m_pClient); + } + } + + // Done. + m_iDirtySetup--; + stabilizeForm(); + // Main session should be dirtier... + m_pMainForm->sessionDirty(); +} + + +// Device port/channel parameter value change slot. +void qsamplerDeviceForm::changeDevicePortParam ( int iRow, int iCol ) +{ + if (m_iDirtySetup > 0) + return; + if (iRow < 0 || iCol < 0) + return; // - // TODO: Enable/disable available command buttons. + // Device port/channel parameter change... // - m_pMainForm->appendMessages("qsamplerDeviceForm::stabilizeForm()"); - SaveDevicesPushButton->setEnabled(m_iDirtyCount > 0); + QListViewItem *pItem = DeviceListView->selectedItem(); + if (pItem == NULL || pItem->rtti() != QSAMPLER_DEVICE_ITEM) + return; + + qsamplerDevice& device = ((qsamplerDeviceItem *) pItem)->device(); + + int iPort = DevicePortComboBox->currentItem(); + qsamplerDevicePort *pPort = device.ports().at(iPort); + if (pPort == NULL) + return; + + m_iDirtySetup++; + // Table 1st column has the parameter name; + const qsamplerDeviceParamMap& params = pPort->params(); + const QString sParam = DevicePortParamTable->text(iRow, 0); + const QString sValue = DevicePortParamTable->text(iRow, iCol); + + // Set the local device port/channel parameter value. + pPort->setParam(sParam, sValue); + + // Set proper device port/channel parameter, if any... + if (device.deviceID() >= 0 && pPort->portID() >= 0) { + // Prepare parameter struct. + lscp_param_t param; + param.key = (char *) sParam.latin1(); + param.value = (char *) sValue.latin1(); + // Now it depends on the device type... + lscp_status_t ret = LSCP_FAILED; + switch (device.deviceType()) { + case qsamplerDevice::Audio: + if ((ret = ::lscp_set_audio_channel_param(m_pClient, + device.deviceID(), pPort->portID(), ¶m)) != LSCP_OK) + m_pMainForm->appendMessagesClient("lscp_set_audio_channel_param"); + break; + case qsamplerDevice::Midi: + if ((ret = ::lscp_set_midi_port_param(m_pClient, + device.deviceID(), pPort->portID(), ¶m)) != LSCP_OK) + m_pMainForm->appendMessagesClient("lscp_set_midi_port_param"); + break; + case qsamplerDevice::None: + break; + } + // Show result. + if (ret == LSCP_OK) { + m_pMainForm->appendMessages(device.deviceName() + ' ' + + pPort->portName() + ' ' + + QString("%1: %2.").arg(sParam).arg(sValue)); + } + } + + // Done. + m_iDirtySetup--; + stabilizeForm(); + // Main session should be dirtier... + m_pMainForm->sessionDirty(); +} + + +// Device list view context menu handler. +void qsamplerDeviceForm::contextMenu ( QListViewItem *pItem, const QPoint& pos, int ) +{ + int iItemID; + + // Build the device context menu... + QPopupMenu* pContextMenu = new QPopupMenu(this); + + bool bClient = (m_pClient != NULL); + bool bEnabled = (pItem != NULL); + iItemID = pContextMenu->insertItem( + QIconSet(QPixmap::fromMimeSource("deviceCreate.png")), + tr("&Create device"), this, SLOT(createDevice())); + pContextMenu->setItemEnabled(iItemID, bEnabled || (bClient && m_bNewDevice)); + iItemID = pContextMenu->insertItem( + QIconSet(QPixmap::fromMimeSource("deviceDelete.png")), + tr("&Delete device"), this, SLOT(deleteDevice())); + pContextMenu->setItemEnabled(iItemID, bEnabled && !m_bNewDevice); + pContextMenu->insertSeparator(); + iItemID = pContextMenu->insertItem( + QIconSet(QPixmap::fromMimeSource("formRefresh.png")), + tr("&Refresh"), this, SLOT(refreshDevices())); + pContextMenu->setItemEnabled(iItemID, bClient); + + pContextMenu->exec(pos); + + delete pContextMenu; +} + +// Stabilize current form state. +void qsamplerDeviceForm::stabilizeForm (void) +{ QListViewItem *pItem = DeviceListView->selectedItem(); + bool bClient = (m_pClient != NULL); bool bEnabled = (pItem != NULL); - DeviceNameTextLabel->setEnabled(bEnabled); - DriverNameTextLabel->setEnabled(bEnabled && m_bNewDevice); + DeviceNameTextLabel->setEnabled(bEnabled && !m_bNewDevice); + DriverNameTextLabel->setEnabled(bEnabled && m_bNewDevice); DriverNameComboBox->setEnabled(bEnabled && m_bNewDevice); DeviceParamTable->setEnabled(bEnabled); - CreateDevicePushButton->setEnabled(bEnabled && (m_iDirtyCount > 0 || m_bNewDevice)); - UpdateDevicePushButton->setEnabled(bEnabled && (m_iDirtyCount > 0 && !m_bNewDevice)); - DeleteDevicePushButton->setEnabled(bEnabled && (m_iDirtyCount > 0 && !m_bNewDevice)); + RefreshDevicesPushButton->setEnabled(bClient); + CreateDevicePushButton->setEnabled(bEnabled || (bClient && m_bNewDevice)); + DeleteDevicePushButton->setEnabled(bEnabled && !m_bNewDevice); } // end of qsamplerDeviceForm.ui.h + +