# HG changeset patch # User Chris Cannam # Date 1163180726 0 # Node ID e269ae6ed008c6bb3654ce7da412acff37639674 # Parent 76cc2c42426889f907d6263bcc75a1d9b621d77a * When adding a layer, make it the selected layer on that pane * More OSC support, including transforms diff -r 76cc2c424268 -r e269ae6ed008 main/MainWindow.cpp --- a/main/MainWindow.cpp Fri Nov 10 13:27:57 2006 +0000 +++ b/main/MainWindow.cpp Fri Nov 10 17:45:26 2006 +0000 @@ -96,7 +96,7 @@ using std::set; -MainWindow::MainWindow(bool withAudioOutput) : +MainWindow::MainWindow(bool withAudioOutput, bool withOSCSupport) : m_document(0), m_paneStack(0), m_viewManager(0), @@ -105,7 +105,7 @@ m_audioOutput(withAudioOutput), m_playSource(0), m_playTarget(0), - m_oscQueue(new OSCQueue()), + m_oscQueue(withOSCSupport ? new OSCQueue() : 0), m_recentFiles("RecentFiles"), m_recentTransforms("RecentTransforms", 20), m_mainMenusCreated(false), @@ -119,6 +119,8 @@ m_rightButtonLayerMenu(0), m_rightButtonTransformsMenu(0), m_documentModified(false), + m_openingAudioFile(false), + m_abandoning(false), m_preferencesDialog(0) { setWindowTitle(tr("Sonic Visualiser")); @@ -231,7 +233,7 @@ this, SLOT(preferenceChanged(PropertyContainer::PropertyName))); - if (m_oscQueue->isOK()) { + if (m_oscQueue && m_oscQueue->isOK()) { connect(m_oscQueue, SIGNAL(messagesAvailable()), this, SLOT(pollOSC())); QTimer *oscTimer = new QTimer(this); connect(oscTimer, SIGNAL(timeout()), this, SLOT(pollOSC())); @@ -248,7 +250,9 @@ MainWindow::~MainWindow() { - closeSession(); + if (!m_abandoning) { + closeSession(); + } delete m_playTarget; delete m_playSource; delete m_viewManager; @@ -2042,10 +2046,13 @@ return false; } + m_openingAudioFile = true; + WaveFileModel *newModel = new WaveFileModel(path); if (!newModel->isOK()) { delete newModel; + m_openingAudioFile = false; return false; } @@ -2068,6 +2075,7 @@ if (!ok || item.isEmpty()) { delete newModel; + m_openingAudioFile = false; return false; } @@ -2138,6 +2146,7 @@ updateMenuStates(); m_recentFiles.addFile(path); + m_openingAudioFile = false; return true; } @@ -2453,7 +2462,7 @@ void MainWindow::closeEvent(QCloseEvent *e) { - if (!checkSaveModified()) { + if (!m_abandoning && !checkSaveModified()) { e->ignore(); return; } @@ -2935,6 +2944,7 @@ m_document->addLayerToView(pane, newLayer); m_paneStack->setCurrentPane(pane); + m_paneStack->setCurrentLayer(pane, newLayer); CommandHistory::getInstance()->endCompoundOperation(); @@ -3129,6 +3139,7 @@ m_document->addLayerToView(pane, newLayer); m_document->setChannel(newLayer, context.channel); m_recentTransforms.add(transform); + m_paneStack->setCurrentLayer(pane, newLayer); } updateMenuStates(); @@ -3412,9 +3423,11 @@ void MainWindow::pollOSC() { - if (m_oscQueue->isEmpty()) return; + if (!m_oscQueue || m_oscQueue->isEmpty()) return; std::cerr << "MainWindow::pollOSC: have " << m_oscQueue->getMessagesAvailable() << " messages" << std::endl; + if (m_openingAudioFile) return; + OSCMessage message = m_oscQueue->readMessage(); if (message.getTarget() != 0) { @@ -3427,6 +3440,9 @@ void MainWindow::handleOSCMessage(const OSCMessage &message) { + std::cerr << "MainWindow::handleOSCMessage: thread id = " + << QThread::currentThreadId() << std::endl; + // This large function should really be abstracted out. if (message.getMethod() == "open") { @@ -3668,7 +3684,7 @@ } else if (message.getMethod() == "set") { - if (message.getArgCount() >= 2 && + if (message.getArgCount() == 2 && message.getArg(0).canConvert(QVariant::String) && message.getArg(1).canConvert(QVariant::Double)) { @@ -3689,6 +3705,28 @@ } else { m_viewManager->setOverlayMode(ViewManager::AllOverlays); } + } else if (property == "zoomwheels") { + m_viewManager->setZoomWheelsEnabled(value > 0.5); + } + + } else { + PropertyContainer *container = 0; + Pane *pane = m_paneStack->getCurrentPane(); + if (pane && + message.getArgCount() == 3 && + message.getArg(0).canConvert(QVariant::String) && + message.getArg(1).canConvert(QVariant::String) && + message.getArg(2).canConvert(QVariant::String)) { + if (message.getArg(0).toString() == "pane") { + container = pane->getPropertyContainer(0); + } else if (message.getArg(0).toString() == "layer") { + container = pane->getSelectedLayer(); + } + } + if (container) { + QString nameString = message.getArg(1).toString(); + QString valueString = message.getArg(2).toString(); + container->setPropertyWithCommand(nameString, valueString); } } @@ -3711,13 +3749,12 @@ if (paneIndex >= 0 && paneIndex < m_paneStack->getPaneCount()) { Pane *pane = m_paneStack->getPane(paneIndex); + m_paneStack->setCurrentPane(pane); if (layerIndex >= 0 && layerIndex < pane->getLayerCount()) { Layer *layer = pane->getLayer(layerIndex); m_paneStack->setCurrentLayer(pane, layer); } else if (wantLayer && layerIndex == -1) { m_paneStack->setCurrentLayer(pane, 0); - } else { - m_paneStack->setCurrentPane(pane); } } @@ -3762,6 +3799,59 @@ } } + } else if (message.getMethod() == "quit") { + + m_abandoning = true; + close(); + + } else if (message.getMethod() == "resize") { + + if (message.getArgCount() == 2) { + + int width = 0, height = 0; + + if (message.getArg(1).canConvert(QVariant::Int)) { + + height = message.getArg(1).toInt(); + + if (message.getArg(0).canConvert(QVariant::String) && + message.getArg(0).toString() == "pane") { + + Pane *pane = m_paneStack->getCurrentPane(); + if (pane) pane->resize(pane->width(), height); + + } else if (message.getArg(0).canConvert(QVariant::Int)) { + + width = message.getArg(0).toInt(); + resize(width, height); + } + } + } + + } else if (message.getMethod() == "transform") { + + Pane *pane = m_paneStack->getCurrentPane(); + + if (getMainModel() && + pane && + message.getArgCount() == 1 && + message.getArg(0).canConvert(QVariant::String)) { + + TransformName transform = message.getArg(0).toString(); + + Layer *newLayer = m_document->createDerivedLayer + (transform, + getMainModel(), + PluginTransform::ExecutionContext(), + ""); + + if (newLayer) { + m_document->addLayerToView(pane, newLayer); + m_recentTransforms.add(transform); + m_paneStack->setCurrentLayer(pane, newLayer); + } + } + } else { std::cerr << "WARNING: MainWindow::handleOSCMessage: Unknown or unsupported " << "method \"" << message.getMethod().toStdString() @@ -3919,7 +4009,7 @@ aboutText += tr("
With DSSI plugin support (API v%1) © Chris Cannam, Steve Harris, Sean Bolton").arg(DSSI_VERSION); #ifdef HAVE_LIBLO aboutText += tr("
With liblo Lite OSC library (v%1) © Steve Harris").arg(LIBLO_VERSION); - if (m_oscQueue->isOK()) { + if (m_oscQueue && m_oscQueue->isOK()) { aboutText += tr("

The OSC URL for this instance is: \"%1\"").arg(m_oscQueue->getOSCURL()); } #endif diff -r 76cc2c424268 -r e269ae6ed008 main/MainWindow.h --- a/main/MainWindow.h Fri Nov 10 13:27:57 2006 +0000 +++ b/main/MainWindow.h Fri Nov 10 17:45:26 2006 +0000 @@ -57,7 +57,8 @@ Q_OBJECT public: - MainWindow(bool withAudioOutput = true); + MainWindow(bool withAudioOutput = true, + bool withOSCSupport = true); virtual ~MainWindow(); enum AudioFileOpenMode { @@ -241,6 +242,8 @@ QMenu *m_rightButtonTransformsMenu; bool m_documentModified; + bool m_openingAudioFile; + bool m_abandoning; QPointer m_preferencesDialog; diff -r 76cc2c424268 -r e269ae6ed008 main/main.cpp --- a/main/main.cpp Fri Nov 10 13:27:57 2006 +0000 +++ b/main/main.cpp Fri Nov 10 17:45:26 2006 +0000 @@ -91,7 +91,16 @@ svSystemSpecificInitialisation(); bool audioOutput = true; + bool oscSupport = true; + + if (args.contains("--help")) { + std::cerr << QApplication::tr( + "\nSonic Visualiser is a program for viewing and exploring audio data\nfor semantic music analysis and annotation.\n\nUsage:\n\n %1 [--no-audio] [--no-osc] [ ...]\n\n --no-audio: Do not attempt to open an audio output device\n --no-osc: Do not provide an Open Sound Control port for remote control\n : One or more Sonic Visualiser (.sv) and audio files may be provided.\n").arg(argv[0]).toStdString() << std::endl; + exit(2); + } + if (args.contains("--no-audio")) audioOutput = false; + if (args.contains("--no-osc")) oscSupport = false; QApplication::setOrganizationName("sonic-visualiser"); QApplication::setOrganizationDomain("sonicvisualiser.org"); @@ -117,7 +126,7 @@ qRegisterMetaType("size_t"); qRegisterMetaType("PropertyContainer::PropertyName"); - MainWindow gui(audioOutput); + MainWindow gui(audioOutput, oscSupport); application.setMainWindow(&gui); QDesktopWidget *desktop = QApplication::desktop(); diff -r 76cc2c424268 -r e269ae6ed008 osc/sv-command --- a/osc/sv-command Fri Nov 10 13:27:57 2006 +0000 +++ b/osc/sv-command Fri Nov 10 17:45:26 2006 +0000 @@ -1,17 +1,54 @@ #!/bin/sh -port=`lsof -c sonic- | grep UDP | sed -e 's/^.*[^0-9]\([0-9][0-9]*\) *$/\1/' | grep -v ' ' | head -1` +# +# A very simple command shell for Sonic Visualiser. +# +# This provides a wrapper for the sv-osc-send program, which is a +# generic OSC sending program (not specific to SV, despite its name). +# This script attempts to guess the OSC port number for an SV +# process running on the local host, and then composes a method name +# and arguments into a complete OSC call. +# +# You can either run this with the method and its arguments on the +# command line, e.g. "sv-command set layer Frequency-Scale Log", or +# you can provide a series of method + argument commands on stdin. +# +# Unless you use the -q option, this script will echo the OSC URL +# and arguments that it is sending for each command. +# +# Note that the method and arguments may not contain spaces. +# +# Chris Cannam, Nov 2006 + +quiet= +if [ "$1" = "-q" ]; then + quiet=true; shift; +fi + +# The yucky bit + +port=`lsof -c sonic- | \ + grep UDP | \ + sed -e 's/^.*[^0-9]\([0-9][0-9]*\) *$/\1/' | \ + grep -v ' ' | \ + head -1 ` + +host=127.0.0.1 +scheme=osc.udp + if [ -z "$port" ]; then echo "Sonic Visualiser OSC port not found" exit 1 fi + if [ -n "$1" ]; then command=$1; shift - echo "osc.udp://127.0.0.1:$port/$command" "$@" - sv-osc-send "osc.udp://127.0.0.1:$port/$command" "$@" + [ -z "$quiet" ] && echo "$scheme://$host:$port/$command" "$@" + sv-osc-send "$scheme://$host:$port/$command" "$@" else - while read command arg1 arg2 arg3 arg4 arg5; do - echo "osc.udp://127.0.0.1:$port/$command" $arg1 $arg2 $arg3 $arg4 $arg5 - sv-osc-send "osc.udp://127.0.0.1:$port/$command" $arg1 $arg2 $arg3 $arg4 $arg5 + while read command a1 a2 a3 a4 a5; do + [ -z "$command" ] && continue + [ -z "$quiet" ] && echo "$scheme://$host:$port/$command" $a1 $a2 $a3 $a4 $a5 + sv-osc-send "$scheme://$host:$port/$command" $a1 $a2 $a3 $a4 $a5 done fi