--- qsampler/trunk/src/qsamplerMainForm.ui.h 2005/03/02 16:23:10 418 +++ qsampler/trunk/src/qsamplerMainForm.ui.h 2005/03/14 14:02:30 456 @@ -41,6 +41,8 @@ #include "qsamplerMessages.h" #include "qsamplerChannelStrip.h" + +#include "qsamplerDeviceForm.h" #include "qsamplerOptionsForm.h" #include "config.h" @@ -105,7 +107,8 @@ m_pOptions = NULL; // All child forms are to be created later, not earlier than setup. - m_pMessages = NULL; + m_pMessages = NULL; + m_pDeviceForm = NULL; // We'll start clean. m_iUntitled = 0; @@ -138,23 +141,23 @@ pLabel = new QLabel(tr("Connected"), this); pLabel->setAlignment(Qt::AlignLeft); pLabel->setMinimumSize(pLabel->sizeHint()); - m_status[QSAMPLER_STATUS_CLIENT] = pLabel; + m_statusItem[QSAMPLER_STATUS_CLIENT] = pLabel; statusBar()->addWidget(pLabel); // Server address. pLabel = new QLabel(this); pLabel->setAlignment(Qt::AlignLeft); - m_status[QSAMPLER_STATUS_SERVER] = pLabel; + m_statusItem[QSAMPLER_STATUS_SERVER] = pLabel; statusBar()->addWidget(pLabel, 1); // Channel title. pLabel = new QLabel(this); pLabel->setAlignment(Qt::AlignLeft); - m_status[QSAMPLER_STATUS_CHANNEL] = pLabel; + m_statusItem[QSAMPLER_STATUS_CHANNEL] = pLabel; statusBar()->addWidget(pLabel, 2); // Session modification status. pLabel = new QLabel(tr("MOD"), this); pLabel->setAlignment(Qt::AlignHCenter); pLabel->setMinimumSize(pLabel->sizeHint()); - m_status[QSAMPLER_STATUS_SESSION] = pLabel; + m_statusItem[QSAMPLER_STATUS_SESSION] = pLabel; statusBar()->addWidget(pLabel); // Create the recent files sub-menu. @@ -179,20 +182,22 @@ #endif // Finally drop any widgets around... + if (m_pDeviceForm) + delete m_pDeviceForm; if (m_pMessages) delete m_pMessages; if (m_pWorkspace) delete m_pWorkspace; // Delete status item labels one by one. - if (m_status[QSAMPLER_STATUS_CLIENT]) - delete m_status[QSAMPLER_STATUS_CLIENT]; - if (m_status[QSAMPLER_STATUS_SERVER]) - delete m_status[QSAMPLER_STATUS_SERVER]; - if (m_status[QSAMPLER_STATUS_CHANNEL]) - delete m_status[QSAMPLER_STATUS_CHANNEL]; - if (m_status[QSAMPLER_STATUS_SESSION]) - delete m_status[QSAMPLER_STATUS_SESSION]; + if (m_statusItem[QSAMPLER_STATUS_CLIENT]) + delete m_statusItem[QSAMPLER_STATUS_CLIENT]; + if (m_statusItem[QSAMPLER_STATUS_SERVER]) + delete m_statusItem[QSAMPLER_STATUS_SERVER]; + if (m_statusItem[QSAMPLER_STATUS_CHANNEL]) + delete m_statusItem[QSAMPLER_STATUS_CHANNEL]; + if (m_statusItem[QSAMPLER_STATUS_SESSION]) + delete m_statusItem[QSAMPLER_STATUS_SESSION]; // Delete recentfiles menu. if (m_pRecentFilesMenu) @@ -206,8 +211,13 @@ // We got options? m_pOptions = pOptions; + // What style do we create these forms? + WFlags wflags = Qt::WType_TopLevel; + if (m_pOptions->bKeepOnTop) + wflags |= Qt::WStyle_Tool; // Some child forms are to be created right now. m_pMessages = new qsamplerMessages(this); + m_pDeviceForm = new qsamplerDeviceForm(this, 0, wflags); // Set message defaults... updateMessagesFont(); updateMessagesLimit(); @@ -236,8 +246,9 @@ QTextIStream istr(&sDockables); istr >> *this; } - // Try to restore old window positioning. + // Try to restore old window positioning and initial visibility. m_pOptions->loadWidgetGeometry(this); + m_pOptions->loadWidgetGeometry(m_pDeviceForm); // Final startup stabilization... updateRecentFilesMenu(); @@ -275,8 +286,12 @@ QTextOStream ostr(&sDockables); ostr << *this; m_pOptions->settings().writeEntry("/Layout/DockWindows", sDockables); - // And the main windows state. + // And the children, and the main windows state,. + m_pOptions->saveWidgetGeometry(m_pDeviceForm); m_pOptions->saveWidgetGeometry(this); + // Close popup widgets. + if (m_pDeviceForm) + m_pDeviceForm->close(); // Stop client and/or server, gracefully. stopServer(); } @@ -627,7 +642,7 @@ } // Write the file. - int iErrors = 0; + int iErrors = 0; QTextStream ts(&file); ts << "# " << QSAMPLER_TITLE " - " << tr(QSAMPLER_SUBTITLE) << endl; ts << "# " << tr("Version") @@ -638,21 +653,77 @@ ts << "# " << tr("File") << ": " << QFileInfo(sFilename).fileName() << endl; ts << "# " << tr("Date") - << ": " << QDate::currentDate().toString("MMMM dd yyyy") + << ": " << QDate::currentDate().toString("MMM dd yyyy") << " " << QTime::currentTime().toString("hh:mm:ss") << endl; ts << "#" << endl; ts << endl; + // It is assumed that this new kind of device+session file + // will be loaded from a complete + int *piDeviceIDs; + int iDevice; + ts << "RESET" << endl; + // Audio device mapping. + QMap audioDeviceMap; + piDeviceIDs = qsamplerDevice::getDevices(m_pClient, qsamplerDevice::Audio); + for (iDevice = 0; piDeviceIDs && piDeviceIDs[iDevice] >= 0; iDevice++) { + qsamplerDevice device(m_pClient, qsamplerDevice::Audio, piDeviceIDs[iDevice]); + ts << endl; + ts << "# " << device.deviceTypeName() << " " << device.driverName() + << " " << tr("Device") << " " << iDevice << endl; + ts << "CREATE AUDIO_OUTPUT_DEVICE " << device.driverName(); + qsamplerDeviceParamMap& params = device.params(); + qsamplerDeviceParamMap::ConstIterator iter; + for (iter = params.begin(); iter != params.end(); ++iter) + ts << " " << iter.key() << "='" << iter.data().value << "'"; + ts << endl; + audioDeviceMap[device.deviceID()] = iDevice; + // Try to keep it snappy :) + QApplication::eventLoop()->processEvents(QEventLoop::ExcludeUserInput); + } + // MIDI device mapping. + QMap midiDeviceMap; + piDeviceIDs = qsamplerDevice::getDevices(m_pClient, qsamplerDevice::Midi); + for (iDevice = 0; piDeviceIDs && piDeviceIDs[iDevice] >= 0; iDevice++) { + qsamplerDevice device(m_pClient, qsamplerDevice::Midi, piDeviceIDs[iDevice]); + ts << endl; + ts << "# " << device.deviceTypeName() << " " << device.driverName() + << " " << tr("Device") << " " << iDevice << endl; + ts << "CREATE MIDI_INPUT_DEVICE " << device.driverName(); + qsamplerDeviceParamMap& params = device.params(); + qsamplerDeviceParamMap::ConstIterator iter; + for (iter = params.begin(); iter != params.end(); ++iter) + ts << " " << iter.key() << "='" << iter.data().value << "'"; + ts << endl; + midiDeviceMap[device.deviceID()] = iDevice; + // Try to keep it snappy :) + QApplication::eventLoop()->processEvents(QEventLoop::ExcludeUserInput); + } + ts << endl; + // Sampler channel mapping. QWidgetList wlist = m_pWorkspace->windowList(); for (int iChannel = 0; iChannel < (int) wlist.count(); iChannel++) { qsamplerChannelStrip *pChannelStrip = (qsamplerChannelStrip *) wlist.at(iChannel); if (pChannelStrip) { qsamplerChannel *pChannel = pChannelStrip->channel(); if (pChannel) { - ts << "# Channel " << iChannel << endl; + ts << "# " << tr("Channel") << " " << iChannel << endl; ts << "ADD CHANNEL" << endl; - ts << "SET CHANNEL AUDIO_OUTPUT_TYPE " << iChannel << " " << pChannel->audioDriver() << endl; - ts << "SET CHANNEL MIDI_INPUT_TYPE " << iChannel << " " << pChannel->midiDriver() << endl; - // ts << "SET CHANNEL MIDI_INPUT_PORT " << iChannel << " " << pChannel->midiPort() << endl; + if (audioDeviceMap.isEmpty()) { + ts << "SET CHANNEL AUDIO_OUTPUT_TYPE " << iChannel + << " " << pChannel->audioDriver() << endl; + } else { + ts << "SET CHANNEL AUDIO_OUTPUT_DEVICE " << iChannel + << " " << audioDeviceMap[pChannel->audioDevice()] << endl; + } + if (midiDeviceMap.isEmpty()) { + ts << "SET CHANNEL MIDI_INPUT_TYPE " << iChannel + << " " << pChannel->midiDriver() << endl; + } else { + ts << "SET CHANNEL MIDI_INPUT_DEVICE " << iChannel + << " " << midiDeviceMap[pChannel->midiDevice()] << endl; + } + ts << "SET CHANNEL MIDI_INPUT_PORT " << iChannel + << " " << pChannel->midiPort() << endl; ts << "SET CHANNEL MIDI_INPUT_CHANNEL " << iChannel << " "; if (pChannel->midiChannel() == LSCP_MIDI_CHANNEL_ALL) ts << "ALL"; @@ -690,6 +761,16 @@ } +// Session change receiver slot. +void qsamplerMainForm::sessionDirty (void) +{ + // Just mark the dirty form. + m_iDirtyCount++; + // and update the form status... + stabilizeForm(); +} + + //------------------------------------------------------------------------- // qsamplerMainForm -- File Action slots. @@ -977,6 +1058,26 @@ } +// Show/hide the device configurator form. +void qsamplerMainForm::viewDevices (void) +{ + if (m_pOptions == NULL) + return; + + if (m_pDeviceForm) { + m_pOptions->saveWidgetGeometry(m_pDeviceForm); + m_pDeviceForm->setClient(m_pClient); + if (m_pDeviceForm->isVisible()) { + m_pDeviceForm->hide(); + } else { + m_pDeviceForm->show(); + m_pDeviceForm->raise(); + m_pDeviceForm->setActiveWindow(); + } + } +} + + // Show options dialog. void qsamplerMainForm::viewOptions (void) { @@ -1001,6 +1102,7 @@ bool bOldDisplayEffect = m_pOptions->bDisplayEffect; int iOldMaxVolume = m_pOptions->iMaxVolume; QString sOldMessagesFont = m_pOptions->sMessagesFont; + bool bOldKeepOnTop = m_pOptions->bKeepOnTop; bool bOldStdoutCapture = m_pOptions->bStdoutCapture; int bOldMessagesLimit = m_pOptions->bMessagesLimit; int iOldMessagesLimitLines = m_pOptions->iMessagesLimitLines; @@ -1013,7 +1115,9 @@ if (pOptionsForm->exec()) { // Warn if something will be only effective on next run. if (( bOldStdoutCapture && !m_pOptions->bStdoutCapture) || - (!bOldStdoutCapture && m_pOptions->bStdoutCapture)) { + (!bOldStdoutCapture && m_pOptions->bStdoutCapture) || + ( bOldKeepOnTop && !m_pOptions->bKeepOnTop) || + (!bOldKeepOnTop && m_pOptions->bKeepOnTop)) { QMessageBox::information(this, tr("Information"), tr("Some settings may be only effective\n" "next time you start this program."), tr("OK")); @@ -1189,27 +1293,29 @@ editSetupChannelAction->setEnabled(bHasChannel); editResetChannelAction->setEnabled(bHasChannel); editResetAllChannelsAction->setEnabled(bHasChannel); - channelsArrangeAction->setEnabled(bHasChannel); viewMessagesAction->setOn(m_pMessages && m_pMessages->isVisible()); + viewDevicesAction->setOn(m_pDeviceForm && m_pDeviceForm->isVisible()); + viewDevicesAction->setEnabled(bHasClient); + channelsArrangeAction->setEnabled(bHasChannel); // Client/Server status... if (bHasClient) { - m_status[QSAMPLER_STATUS_CLIENT]->setText(tr("Connected")); - m_status[QSAMPLER_STATUS_SERVER]->setText(m_pOptions->sServerHost + ":" + QString::number(m_pOptions->iServerPort)); + m_statusItem[QSAMPLER_STATUS_CLIENT]->setText(tr("Connected")); + m_statusItem[QSAMPLER_STATUS_SERVER]->setText(m_pOptions->sServerHost + ":" + QString::number(m_pOptions->iServerPort)); } else { - m_status[QSAMPLER_STATUS_CLIENT]->clear(); - m_status[QSAMPLER_STATUS_SERVER]->clear(); + m_statusItem[QSAMPLER_STATUS_CLIENT]->clear(); + m_statusItem[QSAMPLER_STATUS_SERVER]->clear(); } // Channel status... if (bHasChannel) - m_status[QSAMPLER_STATUS_CHANNEL]->setText(pChannelStrip->caption()); + m_statusItem[QSAMPLER_STATUS_CHANNEL]->setText(pChannelStrip->caption()); else - m_status[QSAMPLER_STATUS_CHANNEL]->clear(); + m_statusItem[QSAMPLER_STATUS_CHANNEL]->clear(); // Session status... if (m_iDirtyCount > 0) - m_status[QSAMPLER_STATUS_SESSION]->setText(tr("MOD")); + m_statusItem[QSAMPLER_STATUS_SESSION]->setText(tr("MOD")); else - m_status[QSAMPLER_STATUS_SESSION]->clear(); + m_statusItem[QSAMPLER_STATUS_SESSION]->clear(); // Recent files menu. m_pRecentFilesMenu->setEnabled(bHasClient && m_pOptions->recentFiles.count() > 0); @@ -1862,6 +1968,11 @@ // Log success here. appendMessages(tr("Client connected.")); + // Hard-notify device configuration form, + // if visible, that we're ready... + if (m_pDeviceForm && m_pDeviceForm->isVisible()) + m_pDeviceForm->setClient(m_pClient); + // Is any session pending to be loaded? if (!m_pOptions->sSessionFile.isEmpty()) { // Just load the prabably startup session... @@ -1882,6 +1993,11 @@ if (m_pClient == NULL) return; + // Hard-notify device configuration form, + // if visible, that we're running out... + if (m_pDeviceForm && m_pDeviceForm->isVisible()) + m_pDeviceForm->setClient(NULL); + // Log prepare here. appendMessages(tr("Client disconnecting..."));