--- qsampler/trunk/src/qsamplerMainForm.ui.h 2004/06/05 11:37:06 109 +++ qsampler/trunk/src/qsamplerMainForm.ui.h 2004/09/29 13:12:45 264 @@ -36,6 +36,7 @@ #include "qsamplerAbout.h" #include "qsamplerOptions.h" +#include "qsamplerChannel.h" #include "qsamplerMessages.h" #include "qsamplerChannelStrip.h" @@ -43,9 +44,6 @@ #include "config.h" -#if !defined(WIN32) -#include -#endif // Timer constant stuff. #define QSAMPLER_TIMER_MSECS 200 @@ -57,10 +55,42 @@ #define QSAMPLER_STATUS_SESSION 3 // Current session modification state. +// All winsock apps needs this. #if defined(WIN32) static WSADATA _wsaData; #endif + +//------------------------------------------------------------------------- +// qsamplerCustomEvent -- specialty for callback comunication. + +#define QSAMPLER_CUSTOM_EVENT 1000 + +class qsamplerCustomEvent : public QCustomEvent +{ +public: + + // Constructor. + qsamplerCustomEvent(lscp_event_t event, const char *pchData, int cchData) + : QCustomEvent(QSAMPLER_CUSTOM_EVENT) + { + m_event = event; + m_data.setLatin1(pchData, cchData); + } + + // Accessors. + lscp_event_t event() { return m_event; } + QString& data() { return m_data; } + +private: + + // The proper event type. + lscp_event_t m_event; + // The event data as a string. + QString m_data; +}; + + //------------------------------------------------------------------------- // qsamplerMainForm -- Main window form implementation. @@ -255,6 +285,7 @@ } +// Window drag-n-drop event handlers. void qsamplerMainForm::dragEnterEvent ( QDragEnterEvent* pDragEnterEvent ) { bool bAccept = false; @@ -279,6 +310,28 @@ } +// Custome event handler. +void qsamplerMainForm::customEvent ( QCustomEvent *pCustomEvent ) +{ + // For the time being, just pump it to messages. + if (pCustomEvent->type() == QSAMPLER_CUSTOM_EVENT) { + qsamplerCustomEvent *pEvent = (qsamplerCustomEvent *) pCustomEvent; + appendMessagesColor(tr("Notify event: %1 data: %2") + .arg(::lscp_event_to_text(pEvent->event())) + .arg(pEvent->data()), "#996699"); + } +} + + +// Context menu event handler. +void qsamplerMainForm::contextMenuEvent( QContextMenuEvent *pEvent ) +{ + stabilizeForm(); + + editMenu->exec(pEvent->globalPos()); +} + + //------------------------------------------------------------------------- // qsamplerMainForm -- Brainless public property accessors. @@ -431,10 +484,13 @@ m_pWorkspace->setUpdatesEnabled(false); QWidgetList wlist = m_pWorkspace->windowList(); for (int iChannel = 0; iChannel < (int) wlist.count(); iChannel++) { - qsamplerChannelStrip *pChannel = (qsamplerChannelStrip *) wlist.at(iChannel); - if (bForce && ::lscp_remove_channel(m_pClient, pChannel->channelID()) != LSCP_OK) - appendMessagesClient("lscp_remove_channel"); - delete pChannel; + qsamplerChannelStrip *pChannelStrip = (qsamplerChannelStrip *) wlist.at(iChannel); + if (pChannelStrip) { + qsamplerChannel *pChannel = pChannelStrip->channel(); + if (bForce && pChannel && ::lscp_remove_channel(m_pClient, pChannel->channelID()) != LSCP_OK) + appendMessagesClient("lscp_remove_channel"); + delete pChannelStrip; + } } m_pWorkspace->setUpdatesEnabled(true); // We're now clean, for sure. @@ -543,18 +599,28 @@ ts << endl; QWidgetList wlist = m_pWorkspace->windowList(); for (int iChannel = 0; iChannel < (int) wlist.count(); iChannel++) { - qsamplerChannelStrip *pChannel = (qsamplerChannelStrip *) wlist.at(iChannel); - int iChannelID = pChannel->channelID(); - ts << "# " << pChannel->caption() << endl; - ts << "ADD CHANNEL" << endl; - ts << "LOAD ENGINE " << pChannel->engineName() << " " << iChannelID << endl; - ts << "SET CHANNEL MIDI_INPUT_TYPE " << iChannelID << " " << pChannel->midiDriver() << endl; - ts << "SET CHANNEL MIDI_INPUT_PORT " << iChannelID << " " << pChannel->midiPort() << endl; - ts << "SET CHANNEL MIDI_INPUT_CHANNEL " << iChannelID << " " << pChannel->midiChannel() << endl; - ts << "SET CHANNEL AUDIO_OUTPUT_TYPE " << iChannelID << " " << pChannel->audioDriver() << endl; - ts << "SET CHANNEL VOLUME " << iChannelID << " " << pChannel->volume() << endl; - ts << "LOAD INSTRUMENT " << pChannel->instrumentFile() << " " << pChannel->instrumentNr() << " " << iChannelID << endl; - ts << endl; + qsamplerChannelStrip *pChannelStrip = (qsamplerChannelStrip *) wlist.at(iChannel); + if (pChannelStrip) { + qsamplerChannel *pChannel = pChannelStrip->channel(); + if (pChannel) { + int iChannelID = pChannel->channelID(); + ts << "# " << pChannelStrip->caption() << endl; + ts << "ADD CHANNEL" << endl; + ts << "SET CHANNEL AUDIO_OUTPUT_TYPE " << iChannelID << " " << pChannel->audioDriver() << endl; + ts << "SET CHANNEL MIDI_INPUT_TYPE " << iChannelID << " " << pChannel->midiDriver() << endl; + ts << "SET CHANNEL MIDI_INPUT_PORT " << iChannelID << " " << pChannel->midiPort() << endl; + ts << "SET CHANNEL MIDI_INPUT_CHANNEL " << iChannelID << " "; + if (pChannel->midiChannel() > 0) + ts << pChannel->midiChannel(); + else + ts << "ALL"; + ts << endl; + ts << "LOAD ENGINE " << pChannel->engineName() << " " << iChannelID << endl; + ts << "LOAD INSTRUMENT NON_MODAL '" << pChannel->instrumentFile() << "' " << pChannel->instrumentNr() << " " << iChannelID << endl; + ts << "SET CHANNEL VOLUME " << iChannelID << " " << pChannel->volume() << endl; + ts << endl; + } + } // Try to keep it snappy :) QApplication::eventLoop()->processEvents(QEventLoop::ExcludeUserInput); } @@ -626,6 +692,34 @@ } +// Reset the sampler instance. +void qsamplerMainForm::fileReset (void) +{ + if (m_pClient == NULL) + return; + + // Ask user whether he/she want's an internal sampler reset... + if (QMessageBox::warning(this, tr("Warning"), + tr("Resetting the sampler instance will close\n" + "all device and channel configurations.\n\n" + "Please note that this operation may cause\n" + "temporary MIDI and Audio disruption\n\n" + "Do you want to reset the sampler engine now?"), + tr("Reset"), tr("Cancel")) > 0) + return; + + // Just do the reset, after closing down current session... + if (closeSession(true) && ::lscp_reset_sampler(m_pClient) != LSCP_OK) { + appendMessagesClient("lscp_reset_sampler"); + appendMessagesError(tr("Could not reset sampler instance.\n\nSorry.")); + return; + } + + // Log this. + appendMessages(tr("Sampler reset.")); +} + + // Restart the client/server instance. void qsamplerMainForm::fileRestart (void) { @@ -700,7 +794,11 @@ if (m_pClient == NULL) return; - qsamplerChannelStrip *pChannel = activeChannel(); + qsamplerChannelStrip *pChannelStrip = activeChannelStrip(); + if (pChannelStrip == NULL) + return; + + qsamplerChannel *pChannel = pChannelStrip->channel(); if (pChannel == NULL) return; @@ -710,7 +808,7 @@ tr("About to remove channel:\n\n" "%1\n\n" "Are you sure?") - .arg(pChannel->caption()), + .arg(pChannelStrip->caption()), tr("OK"), tr("Cancel")) > 0) return; } @@ -743,12 +841,12 @@ if (m_pClient == NULL) return; - qsamplerChannelStrip *pChannel = activeChannel(); - if (pChannel == NULL) + qsamplerChannelStrip *pChannelStrip = activeChannelStrip(); + if (pChannelStrip == NULL) return; // Just invoque the channel strip procedure. - pChannel->channelSetup(); + pChannelStrip->showChannelSetup(false); } @@ -758,7 +856,11 @@ if (m_pClient == NULL) return; - qsamplerChannelStrip *pChannel = activeChannel(); + qsamplerChannelStrip *pChannelStrip = activeChannelStrip(); + if (pChannelStrip == NULL) + return; + + qsamplerChannel *pChannel = pChannelStrip->channel(); if (pChannel == NULL) return; @@ -773,7 +875,7 @@ appendMessages(tr("Channel %1 reset.").arg(pChannel->channelID())); // Refresh channel strip info. - pChannel->updateChannelInfo(); + pChannelStrip->updateChannelInfo(); } @@ -834,9 +936,9 @@ qsamplerOptionsForm *pOptionsForm = new qsamplerOptionsForm(this); if (pOptionsForm) { // Check out some initial nullities(tm)... - qsamplerChannelStrip *pChannel = activeChannel(); - if (m_pOptions->sDisplayFont.isEmpty() && pChannel) - m_pOptions->sDisplayFont = pChannel->displayFont().toString(); + qsamplerChannelStrip *pChannelStrip = activeChannelStrip(); + if (m_pOptions->sDisplayFont.isEmpty() && pChannelStrip) + m_pOptions->sDisplayFont = pChannelStrip->displayFont().toString(); if (m_pOptions->sMessagesFont.isEmpty() && m_pMessages) m_pOptions->sMessagesFont = m_pMessages->messagesFont().toString(); // To track down deferred or immediate changes. @@ -846,6 +948,7 @@ bool bOldServerStart = m_pOptions->bServerStart; QString sOldServerCmdLine = m_pOptions->sServerCmdLine; QString sOldDisplayFont = m_pOptions->sDisplayFont; + int iOldMaxVolume = m_pOptions->iMaxVolume; QString sOldMessagesFont = m_pOptions->sMessagesFont; bool bOldStdoutCapture = m_pOptions->bStdoutCapture; int bOldMessagesLimit = m_pOptions->bMessagesLimit; @@ -871,6 +974,8 @@ updateRecentFilesMenu(); if (sOldDisplayFont != m_pOptions->sDisplayFont) updateDisplayFont(); + if (iOldMaxVolume != m_pOptions->iMaxVolume) + updateMaxVolume(); if (sOldMessagesFont != m_pOptions->sMessagesFont) updateMessagesFont(); if (( bOldMessagesLimit && !m_pOptions->bMessagesLimit) || @@ -909,19 +1014,19 @@ m_pWorkspace->setUpdatesEnabled(false); int y = 0; for (int iChannel = 0; iChannel < (int) wlist.count(); iChannel++) { - qsamplerChannelStrip *pChannel = (qsamplerChannelStrip *) wlist.at(iChannel); - /* if (pChannel->testWState(WState_Maximized | WState_Minimized)) { + qsamplerChannelStrip *pChannelStrip = (qsamplerChannelStrip *) wlist.at(iChannel); + /* if (pChannelStrip->testWState(WState_Maximized | WState_Minimized)) { // Prevent flicker... - pChannel->hide(); - pChannel->showNormal(); + pChannelStrip->hide(); + pChannelStrip->showNormal(); } */ - pChannel->adjustSize(); + pChannelStrip->adjustSize(); int iWidth = m_pWorkspace->width(); - if (iWidth < pChannel->width()) - iWidth = pChannel->width(); - // int iHeight = pChannel->height() + pChannel->parentWidget()->baseSize().height(); - int iHeight = pChannel->parentWidget()->frameGeometry().height(); - pChannel->parentWidget()->setGeometry(0, y, iWidth, iHeight); + if (iWidth < pChannelStrip->width()) + iWidth = pChannelStrip->width(); + // int iHeight = pChannelStrip->height() + pChannelStrip->parentWidget()->baseSize().height(); + int iHeight = pChannelStrip->parentWidget()->frameGeometry().height(); + pChannelStrip->parentWidget()->setGeometry(0, y, iWidth, iHeight); y += iHeight; } m_pWorkspace->setUpdatesEnabled(true); @@ -969,6 +1074,11 @@ sText += tr("Debugging option enabled."); sText += "
"; #endif +#ifndef CONFIG_LIBGIG + sText += ""; + sText += tr("GIG (libgig) file support disabled."); + sText += "
"; +#endif sText += "
\n"; sText += tr("Using") + ": "; sText += ::lscp_client_package(); @@ -1002,13 +1112,14 @@ setCaption(tr(QSAMPLER_TITLE " - [%1]").arg(sSessioName)); // Update the main menu state... - qsamplerChannelStrip *pChannel = activeChannel(); + qsamplerChannelStrip *pChannelStrip = activeChannelStrip(); bool bHasClient = (m_pOptions != NULL && m_pClient != NULL); - bool bHasChannel = (bHasClient && pChannel != NULL); + bool bHasChannel = (bHasClient && pChannelStrip != NULL); fileNewAction->setEnabled(bHasClient); fileOpenAction->setEnabled(bHasClient); fileSaveAction->setEnabled(bHasClient && m_iDirtyCount > 0); fileSaveAsAction->setEnabled(bHasClient); + fileResetAction->setEnabled(bHasClient); fileRestartAction->setEnabled(bHasClient || m_pServer == NULL); editAddChannelAction->setEnabled(bHasClient); editRemoveChannelAction->setEnabled(bHasChannel); @@ -1027,7 +1138,7 @@ } // Channel status... if (bHasChannel) - m_status[QSAMPLER_STATUS_CHANNEL]->setText(pChannel->caption()); + m_status[QSAMPLER_STATUS_CHANNEL]->setText(pChannelStrip->caption()); else m_status[QSAMPLER_STATUS_CHANNEL]->clear(); // Session status... @@ -1046,7 +1157,7 @@ // Channel change receiver slot. -void qsamplerMainForm::channelChanged( qsamplerChannelStrip * ) +void qsamplerMainForm::channelStripChanged( qsamplerChannelStrip * ) { // Just mark the dirty form. m_iDirtyCount++; @@ -1120,8 +1231,30 @@ m_pWorkspace->setUpdatesEnabled(false); for (int iChannel = 0; iChannel < (int) wlist.count(); iChannel++) { - qsamplerChannelStrip *pChannel = (qsamplerChannelStrip *) wlist.at(iChannel); - pChannel->setDisplayFont(font); + qsamplerChannelStrip *pChannelStrip = (qsamplerChannelStrip *) wlist.at(iChannel); + if (pChannelStrip) + pChannelStrip->setDisplayFont(font); + } + m_pWorkspace->setUpdatesEnabled(true); +} + + +// Force update of the channels maximum volume setting. +void qsamplerMainForm::updateMaxVolume (void) +{ + if (m_pOptions == NULL) + return; + + // Full channel list update... + QWidgetList wlist = m_pWorkspace->windowList(); + if (wlist.isEmpty()) + return; + + m_pWorkspace->setUpdatesEnabled(false); + for (int iChannel = 0; iChannel < (int) wlist.count(); iChannel++) { + qsamplerChannelStrip *pChannelStrip = (qsamplerChannelStrip *) wlist.at(iChannel); + if (pChannelStrip) + pChannelStrip->setMaxVolume(m_pOptions->iMaxVolume); } m_pWorkspace->setUpdatesEnabled(true); } @@ -1226,52 +1359,53 @@ return; // Prepare for auto-arrange? - qsamplerChannelStrip *pChannel = NULL; + qsamplerChannelStrip *pChannelStrip = NULL; int y = 0; if (m_pOptions && m_pOptions->bAutoArrange) { QWidgetList wlist = m_pWorkspace->windowList(); for (int iChannel = 0; iChannel < (int) wlist.count(); iChannel++) { - pChannel = (qsamplerChannelStrip *) wlist.at(iChannel); - // y += pChannel->height() + pChannel->parentWidget()->baseSize().height(); - y += pChannel->parentWidget()->frameGeometry().height(); + pChannelStrip = (qsamplerChannelStrip *) wlist.at(iChannel); + // y += pChannelStrip->height() + pChannelStrip->parentWidget()->baseSize().height(); + y += pChannelStrip->parentWidget()->frameGeometry().height(); } } // Add a new channel itema... WFlags wflags = Qt::WStyle_Customize | Qt::WStyle_Tool | Qt::WStyle_Title | Qt::WStyle_NoBorder; - pChannel = new qsamplerChannelStrip(m_pWorkspace, 0, wflags); - pChannel->setup(this, iChannelID); + pChannelStrip = new qsamplerChannelStrip(m_pWorkspace, 0, wflags); + pChannelStrip->setMaxVolume(m_pOptions->iMaxVolume); + pChannelStrip->setup(this, iChannelID); // We'll need a display font. QFont font; if (m_pOptions && font.fromString(m_pOptions->sDisplayFont)) - pChannel->setDisplayFont(font); + pChannelStrip->setDisplayFont(font); // Track channel setup changes. - QObject::connect(pChannel, SIGNAL(channelChanged(qsamplerChannelStrip *)), this, SLOT(channelChanged(qsamplerChannelStrip *))); + QObject::connect(pChannelStrip, SIGNAL(channelChanged(qsamplerChannelStrip *)), this, SLOT(channelStripChanged(qsamplerChannelStrip *))); // Before we show it up, may be we'll // better ask for some initial values? if (bPrompt) - pChannel->channelSetup(); + pChannelStrip->showChannelSetup(true); // Now we show up us to the world. - pChannel->show(); + pChannelStrip->show(); // Only then, we'll auto-arrange... if (m_pOptions && m_pOptions->bAutoArrange) { int iWidth = m_pWorkspace->width(); // int iHeight = pChannel->height() + pChannel->parentWidget()->baseSize().height(); - int iHeight = pChannel->parentWidget()->frameGeometry().height(); - pChannel->parentWidget()->setGeometry(0, y, iWidth, iHeight); + int iHeight = pChannelStrip->parentWidget()->frameGeometry().height(); + pChannelStrip->parentWidget()->setGeometry(0, y, iWidth, iHeight); } } // Retrieve the active channel strip. -qsamplerChannelStrip *qsamplerMainForm::activeChannel (void) +qsamplerChannelStrip *qsamplerMainForm::activeChannelStrip (void) { return (qsamplerChannelStrip *) m_pWorkspace->activeWindow(); } // Retrieve a channel strip by index. -qsamplerChannelStrip *qsamplerMainForm::channelAt ( int iChannel ) +qsamplerChannelStrip *qsamplerMainForm::channelStripAt ( int iChannel ) { QWidgetList wlist = m_pWorkspace->windowList(); if (wlist.isEmpty()) @@ -1292,10 +1426,12 @@ if (!wlist.isEmpty()) { channelsMenu->insertSeparator(); for (int iChannel = 0; iChannel < (int) wlist.count(); iChannel++) { - qsamplerChannelStrip *pChannel = (qsamplerChannelStrip *) wlist.at(iChannel); - int iItemID = channelsMenu->insertItem(pChannel->caption(), this, SLOT(channelsMenuActivated(int))); - channelsMenu->setItemParameter(iItemID, iChannel); - channelsMenu->setItemChecked(iItemID, activeChannel() == pChannel); + qsamplerChannelStrip *pChannelStrip = (qsamplerChannelStrip *) wlist.at(iChannel); + if (pChannelStrip) { + int iItemID = channelsMenu->insertItem(pChannelStrip->caption(), this, SLOT(channelsMenuActivated(int))); + channelsMenu->setItemParameter(iItemID, iChannel); + channelsMenu->setItemChecked(iItemID, activeChannelStrip() == pChannelStrip); + } } } } @@ -1304,10 +1440,10 @@ // Windows menu activation slot void qsamplerMainForm::channelsMenuActivated ( int iChannel ) { - qsamplerChannelStrip *pChannel = channelAt(iChannel); - if (pChannel) - pChannel->showNormal(); - pChannel->setFocus(); + qsamplerChannelStrip *pChannelStrip = channelStripAt(iChannel); + if (pChannelStrip) + pChannelStrip->showNormal(); + pChannelStrip->setFocus(); } @@ -1353,9 +1489,9 @@ m_iTimerSlot = 0; QWidgetList wlist = m_pWorkspace->windowList(); for (int iChannel = 0; iChannel < (int) wlist.count(); iChannel++) { - qsamplerChannelStrip *pChannel = (qsamplerChannelStrip *) wlist.at(iChannel); - if (pChannel->isVisible()) - pChannel->updateChannelUsage(); + qsamplerChannelStrip *pChannelStrip = (qsamplerChannelStrip *) wlist.at(iChannel); + if (pChannelStrip && pChannelStrip->isVisible()) + pChannelStrip->updateChannelUsage(); } } } @@ -1441,12 +1577,16 @@ // And try to stop server. if (m_pServer) { appendMessages(tr("Server is stopping...")); - if (m_pServer->isRunning()) { + if (m_pServer->isRunning()) m_pServer->tryTerminate(); - return; - } } + // Give it some time to terminate gracefully and stabilize... + QTime t; + t.start(); + while (t.elapsed() < QSAMPLER_TIMER_MSECS) + QApplication::eventLoop()->processEvents(QEventLoop::ExcludeUserInput); + // Do final processing anyway. processServerExit(); } @@ -1488,22 +1628,17 @@ //------------------------------------------------------------------------- // qsamplerMainForm -- Client stuff. - // The LSCP client callback procedure. -lscp_status_t qsampler_client_callback ( lscp_client_t *pClient, const char *pchBuffer, int cchBuffer, void *pvData ) +lscp_status_t qsampler_client_callback ( lscp_client_t */*pClient*/, lscp_event_t event, const char *pchData, int cchData, void *pvData ) { qsamplerMainForm *pMainForm = (qsamplerMainForm *) pvData; if (pMainForm == NULL) return LSCP_FAILED; - char *pszBuffer = (char *) malloc(cchBuffer + 1); - if (pszBuffer == NULL) - return LSCP_FAILED; - - memcpy(pszBuffer, pchBuffer, cchBuffer); - pszBuffer[cchBuffer] = (char) 0; - pMainForm->appendMessagesColor(pszBuffer, "#996699"); - free(pszBuffer); + // ATTN: DO NOT EVER call any GUI code here, + // as this is run under some other thread context. + // A custom event must be posted here... + QApplication::postEvent(pMainForm, new qsamplerCustomEvent(event, pchData, cchData)); return LSCP_OK; }