--- qsampler/trunk/src/qsamplerMainForm.cpp 2009/04/28 09:06:43 1890 +++ qsampler/trunk/src/qsamplerMainForm.cpp 2010/10/06 18:49:54 2144 @@ -1,7 +1,7 @@ // qsamplerMainForm.cpp // /**************************************************************************** - Copyright (C) 2004-2009, rncbc aka Rui Nuno Capela. All rights reserved. + Copyright (C) 2004-2010, rncbc aka Rui Nuno Capela. All rights reserved. Copyright (C) 2007, 2008 Christian Schoenebeck This program is free software; you can redistribute it and/or @@ -56,6 +56,14 @@ #include #include +#if QT_VERSION < 0x040500 +namespace Qt { +const WindowFlags WindowCloseButtonHint = WindowFlags(0x08000000); +#if QT_VERSION < 0x040200 +const WindowFlags CustomizeWindowHint = WindowFlags(0x02000000); +#endif +} +#endif #ifdef HAVE_SIGNAL_H #include @@ -85,6 +93,36 @@ #endif +//------------------------------------------------------------------------- +// LADISH Level 1 support stuff. + +#if defined(HAVE_SIGNAL_H) && defined(HAVE_SYS_SOCKET_H) + +#include + +#include +#include + +#include + +// File descriptor for SIGUSR1 notifier. +static int g_fdUsr1[2]; + +// Unix SIGUSR1 signal handler. +static void qsampler_sigusr1_handler ( int /* signo */ ) +{ + char c = 1; + + (::write(g_fdUsr1[0], &c, sizeof(c)) > 0); +} + +#endif // HAVE_SIGNAL_H + + +//------------------------------------------------------------------------- +// qsampler -- namespace + + namespace QSampler { // Timer constant stuff. @@ -97,18 +135,21 @@ #define QSAMPLER_STATUS_SESSION 3 // Current session modification state. +// Specialties for thread-callback comunication. +#define QSAMPLER_LSCP_EVENT QEvent::Type(QEvent::User + 1) + + //------------------------------------------------------------------------- -// CustomEvent -- specialty for callback comunication. +// LscpEvent -- specialty for LSCP callback comunication. -#define QSAMPLER_CUSTOM_EVENT QEvent::Type(QEvent::User + 0) -class CustomEvent : public QEvent +class LscpEvent : public QEvent { public: // Constructor. - CustomEvent(lscp_event_t event, const char *pchData, int cchData) - : QEvent(QSAMPLER_CUSTOM_EVENT) + LscpEvent(lscp_event_t event, const char *pchData, int cchData) + : QEvent(QSAMPLER_LSCP_EVENT) { m_event = event; m_data = QString::fromUtf8(pchData, cchData); @@ -161,10 +202,35 @@ m_iTimerSlot = 0; -#ifdef HAVE_SIGNAL_H +#if defined(HAVE_SIGNAL_H) && defined(HAVE_SYS_SOCKET_H) + // Set to ignore any fatal "Broken pipe" signals. ::signal(SIGPIPE, SIG_IGN); -#endif + + // LADISH Level 1 suport. + + // Initialize file descriptors for SIGUSR1 socket notifier. + ::socketpair(AF_UNIX, SOCK_STREAM, 0, g_fdUsr1); + m_pUsr1Notifier + = new QSocketNotifier(g_fdUsr1[1], QSocketNotifier::Read, this); + + QObject::connect(m_pUsr1Notifier, + SIGNAL(activated(int)), + SLOT(handle_sigusr1())); + + // Install SIGUSR1 signal handler. + struct sigaction usr1; + usr1.sa_handler = qsampler_sigusr1_handler; + ::sigemptyset(&usr1.sa_mask); + usr1.sa_flags = 0; + usr1.sa_flags |= SA_RESTART; + ::sigaction(SIGUSR1, &usr1, NULL); + +#else // HAVE_SIGNAL_H + + m_pUsr1Notifier = NULL; + +#endif // !HAVE_SIGNAL_H #ifdef CONFIG_VOLUME // Make some extras into the toolbar... @@ -337,6 +403,11 @@ WSACleanup(); #endif +#if defined(HAVE_SIGNAL_H) && defined(HAVE_SYS_SOCKET_H) + if (m_pUsr1Notifier) + delete m_pUsr1Notifier; +#endif + // Finally drop any widgets around... if (m_pDeviceForm) delete m_pDeviceForm; @@ -375,26 +446,28 @@ // What style do we create these forms? Qt::WindowFlags wflags = Qt::Window -#if QT_VERSION >= 0x040200 | Qt::CustomizeWindowHint -#endif | Qt::WindowTitleHint | Qt::WindowSystemMenuHint - | Qt::WindowMinMaxButtonsHint; + | Qt::WindowMinMaxButtonsHint + | Qt::WindowCloseButtonHint; if (m_pOptions->bKeepOnTop) wflags |= Qt::Tool; + // Some child forms are to be created right now. m_pMessages = new Messages(this); m_pDeviceForm = new DeviceForm(this, wflags); #ifdef CONFIG_MIDI_INSTRUMENT m_pInstrumentListForm = new InstrumentListForm(this, wflags); #else - viewInstrumentsAction->setEnabled(false); + m_ui.viewInstrumentsAction->setEnabled(false); #endif + // Setup messages logging appropriately... m_pMessages->setLogging( m_pOptions->bMessagesLog, m_pOptions->sMessagesLogPath); + // Set message defaults... updateMessagesFont(); updateMessagesLimit(); @@ -425,7 +498,7 @@ } // Try to restore old window positioning and initial visibility. - m_pOptions->loadWidgetGeometry(this); + m_pOptions->loadWidgetGeometry(this, true); m_pOptions->loadWidgetGeometry(m_pInstrumentListForm); m_pOptions->loadWidgetGeometry(m_pDeviceForm); @@ -469,7 +542,7 @@ // And the children, and the main windows state,. m_pOptions->saveWidgetGeometry(m_pDeviceForm); m_pOptions->saveWidgetGeometry(m_pInstrumentListForm); - m_pOptions->saveWidgetGeometry(this); + m_pOptions->saveWidgetGeometry(this, true); // Close popup widgets. if (m_pInstrumentListForm) m_pInstrumentListForm->close(); @@ -518,7 +591,8 @@ QListIterator iter(pMimeData->urls()); while (iter.hasNext()) { const QString& sPath = iter.next().toLocalFile(); - if (Channel::isInstrumentFile(sPath)) { + // if (Channel::isDlsInstrumentFile(sPath)) { + if (QFileInfo(sPath).exists()) { // Try to create a new channel from instrument file... Channel *pChannel = new Channel(); if (pChannel == NULL) @@ -552,17 +626,17 @@ // Custome event handler. -void MainForm::customEvent(QEvent* pCustomEvent) +void MainForm::customEvent ( QEvent* pEvent ) { // For the time being, just pump it to messages. - if (pCustomEvent->type() == QSAMPLER_CUSTOM_EVENT) { - CustomEvent *pEvent = static_cast (pCustomEvent); - switch (pEvent->event()) { + if (pEvent->type() == QSAMPLER_LSCP_EVENT) { + LscpEvent *pLscpEvent = static_cast (pEvent); + switch (pLscpEvent->event()) { case LSCP_EVENT_CHANNEL_COUNT: updateAllChannelStrips(true); break; case LSCP_EVENT_CHANNEL_INFO: { - int iChannelID = pEvent->data().toInt(); + int iChannelID = pLscpEvent->data().toInt(); ChannelStrip *pChannelStrip = channelStrip(iChannelID); if (pChannelStrip) channelStripChanged(pChannelStrip); @@ -575,7 +649,7 @@ break; case LSCP_EVENT_MIDI_INPUT_DEVICE_INFO: { if (m_pDeviceForm) m_pDeviceForm->refreshDevices(); - const int iDeviceID = pEvent->data().section(' ', 0, 0).toInt(); + const int iDeviceID = pLscpEvent->data().section(' ', 0, 0).toInt(); DeviceStatusForm::onDeviceChanged(iDeviceID); break; } @@ -585,49 +659,64 @@ case LSCP_EVENT_AUDIO_OUTPUT_DEVICE_INFO: if (m_pDeviceForm) m_pDeviceForm->refreshDevices(); break; -#if CONFIG_EVENT_CHANNEL_MIDI + #if CONFIG_EVENT_CHANNEL_MIDI case LSCP_EVENT_CHANNEL_MIDI: { - const int iChannelID = pEvent->data().section(' ', 0, 0).toInt(); + const int iChannelID = pLscpEvent->data().section(' ', 0, 0).toInt(); ChannelStrip *pChannelStrip = channelStrip(iChannelID); if (pChannelStrip) - pChannelStrip->midiArrived(); + pChannelStrip->midiActivityLedOn(); break; } -#endif -#if CONFIG_EVENT_DEVICE_MIDI + #endif + #if CONFIG_EVENT_DEVICE_MIDI case LSCP_EVENT_DEVICE_MIDI: { - const int iDeviceID = pEvent->data().section(' ', 0, 0).toInt(); - const int iPortID = pEvent->data().section(' ', 1, 1).toInt(); - DeviceStatusForm* pDeviceStatusForm = - DeviceStatusForm::getInstance(iDeviceID); + const int iDeviceID = pLscpEvent->data().section(' ', 0, 0).toInt(); + const int iPortID = pLscpEvent->data().section(' ', 1, 1).toInt(); + DeviceStatusForm *pDeviceStatusForm + = DeviceStatusForm::getInstance(iDeviceID); if (pDeviceStatusForm) pDeviceStatusForm->midiArrived(iPortID); break; } -#endif + #endif default: - appendMessagesColor(tr("Notify event: %1 data: %2") - .arg(::lscp_event_to_text(pEvent->event())) - .arg(pEvent->data()), "#996699"); + appendMessagesColor(tr("LSCP Event: %1 data: %2") + .arg(::lscp_event_to_text(pLscpEvent->event())) + .arg(pLscpEvent->data()), "#996699"); } } } -void MainForm::updateViewMidiDeviceStatusMenu() { + +// LADISH Level 1 -- SIGUSR1 signal handler. +void MainForm::handle_sigusr1 (void) +{ +#if defined(HAVE_SIGNAL_H) && defined(HAVE_SYS_SOCKET_H) + + char c; + + if (::read(g_fdUsr1[1], &c, sizeof(c)) > 0) + saveSession(false); + +#endif +} + + +void MainForm::updateViewMidiDeviceStatusMenu (void) +{ m_ui.viewMidiDeviceStatusMenu->clear(); - const std::map statusForms = - DeviceStatusForm::getInstances(); - for ( - std::map::const_iterator iter = statusForms.begin(); - iter != statusForms.end(); ++iter - ) { - DeviceStatusForm* pForm = iter->second; + const std::map statusForms + = DeviceStatusForm::getInstances(); + std::map::const_iterator iter + = statusForms.begin(); + for ( ; iter != statusForms.end(); ++iter) { + DeviceStatusForm *pStatusForm = iter->second; m_ui.viewMidiDeviceStatusMenu->addAction( - pForm->visibleAction() - ); + pStatusForm->visibleAction()); } } + // Context menu event handler. void MainForm::contextMenuEvent( QContextMenuEvent *pEvent ) { @@ -1870,9 +1959,10 @@ setWindowTitle(tr(QSAMPLER_TITLE " - [%1]").arg(sSessionName)); // Update the main menu state... - ChannelStrip* pChannelStrip = activeChannelStrip(); - bool bHasClient = (m_pOptions != NULL && m_pClient != NULL); + ChannelStrip *pChannelStrip = activeChannelStrip(); + bool bHasClient = (m_pOptions != NULL && m_pClient != NULL); bool bHasChannel = (bHasClient && pChannelStrip != NULL); + bool bHasChannels = (bHasClient && m_pWorkspace->windowList().count() > 0); m_ui.fileNewAction->setEnabled(bHasClient); m_ui.fileOpenAction->setEnabled(bHasClient); m_ui.fileSaveAction->setEnabled(bHasClient && m_iDirtyCount > 0); @@ -1888,7 +1978,7 @@ m_ui.editEditChannelAction->setEnabled(false); #endif m_ui.editResetChannelAction->setEnabled(bHasChannel); - m_ui.editResetAllChannelsAction->setEnabled(bHasChannel); + m_ui.editResetAllChannelsAction->setEnabled(bHasChannels); m_ui.viewMessagesAction->setChecked(m_pMessages && m_pMessages->isVisible()); #ifdef CONFIG_MIDI_INSTRUMENT m_ui.viewInstrumentsAction->setChecked(m_pInstrumentListForm @@ -1900,7 +1990,9 @@ m_ui.viewDevicesAction->setChecked(m_pDeviceForm && m_pDeviceForm->isVisible()); m_ui.viewDevicesAction->setEnabled(bHasClient); - m_ui.channelsArrangeAction->setEnabled(bHasChannel); + m_ui.viewMidiDeviceStatusMenu->setEnabled( + DeviceStatusForm::getInstances().size() > 0); + m_ui.channelsArrangeAction->setEnabled(bHasChannels); #ifdef CONFIG_VOLUME // Toolbar widgets are also affected... @@ -2688,7 +2780,7 @@ // as this is run under some other thread context. // A custom event must be posted here... QApplication::postEvent(pMainForm, - new CustomEvent(event, pchData, cchData)); + new LscpEvent(event, pchData, cchData)); return LSCP_OK; }