Mercurial > hg > sonic-visualiser
changeset 246:ddbde90773b0 spectrogram-cache-rejig
* Merge from trunk
author | Chris Cannam |
---|---|
date | Wed, 27 Feb 2008 11:59:42 +0000 |
parents | 37847fc0b381 |
children | 8492db8cf579 |
files | icons/draw.png icons/erase.png icons/invert-vertical.png icons/normalise-columns.png icons/normalise.png icons/select.png icons/show-peaks.png icons/sv-splash.png icons/sv-splash.svg main/MainWindow.cpp main/MainWindow.h main/OSCHandler.cpp main/PreferencesDialog.cpp main/PreferencesDialog.h main/main.cpp sonic-visualiser.qrc sv.pro |
diffstat | 17 files changed, 1083 insertions(+), 723 deletions(-) [+] |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/icons/sv-splash.svg Wed Feb 27 11:59:42 2008 +0000 @@ -0,0 +1,101 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<!-- Created with Inkscape (http://www.inkscape.org/) --> +<svg + xmlns:dc="http://purl.org/dc/elements/1.1/" + xmlns:cc="http://web.resource.org/cc/" + xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:svg="http://www.w3.org/2000/svg" + xmlns="http://www.w3.org/2000/svg" + xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" + xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" + width="640px" + height="480px" + id="svg1952" + sodipodi:version="0.32" + inkscape:version="0.44.1" + sodipodi:docbase="/home/studio/code/sonic-visualiser/sv/icons" + sodipodi:docname="sv-splash.svg" + inkscape:export-filename="/home/studio/code/sonic-visualiser/sv/icons/sv-splash.png" + inkscape:export-xdpi="90" + inkscape:export-ydpi="90"> + <defs + id="defs1954" /> + <sodipodi:namedview + id="base" + pagecolor="#ffffff" + bordercolor="#666666" + borderopacity="1.0" + inkscape:pageopacity="0.0" + inkscape:pageshadow="2" + inkscape:zoom="1" + inkscape:cx="320" + inkscape:cy="240" + inkscape:current-layer="layer1" + inkscape:document-units="px" + showgrid="true" + inkscape:window-width="1101" + inkscape:window-height="969" + inkscape:window-x="169" + inkscape:window-y="26" /> + <metadata + id="metadata1957"> + <rdf:RDF> + <cc:Work + rdf:about=""> + <dc:format>image/svg+xml</dc:format> + <dc:type + rdf:resource="http://purl.org/dc/dcmitype/StillImage" /> + </cc:Work> + </rdf:RDF> + </metadata> + <g + id="layer1" + inkscape:label="Layer 1" + inkscape:groupmode="layer"> + <rect + style="fill:white;fill-opacity:1;stroke:black;stroke-width:5.70384979;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" + id="rect3849" + width="578.29614" + height="316.29614" + x="28.851925" + y="57.851925" /> + <path + style="fill:none;fill-rule:evenodd;stroke:#d45500;stroke-width:7.58643961px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" + d="M 226.71778,185.52035 C 407.22042,185.52035 407.22042,185.52035 407.22042,185.52035" + id="path4036" /> + <path + style="fill:none;fill-rule:evenodd;stroke:black;stroke-width:10.28721237;stroke-linecap:butt;stroke-linejoin:miter;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:1.39999998;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" + d="M 228.89103,185.52402 C 255.18599,185.52402 258.59857,185.60302 258.59857,185.60302 C 270.76871,133.56701 271.36497,127.54591 274.66485,178.25451 C 279.70514,266.89367 284.18048,220.02667 290.61951,183.64501 C 302.75722,68.043355 303.99332,111.5005 306.56423,135.80647 C 316.45027,256.01216 316.0237,282.95104 321.30811,243.02856 C 325.23523,213.36022 336.92287,88.29917 339.01862,122.7736 C 353.59512,259.79486 354.02613,251.94928 358.50413,216.49781 C 373.27326,77.656444 368.76189,188.69998 377.97144,186.27485 C 404.04172,186.27485 403.59893,185.60302 403.59893,185.60302 L 407.00661,185.60302" + id="path3783" + sodipodi:nodetypes="cccccsccccc" /> + <rect + style="fill:none;stroke:#d45500;stroke-width:15.17287922;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" + id="rect3775" + width="191.29092" + height="187.44695" + x="223.48573" + y="91.460907" /> + <text + xml:space="preserve" + style="font-size:32px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:125%;writing-mode:lr-tb;text-anchor:start;fill:black;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Korataki" + x="59" + y="330" + id="text2049" + sodipodi:linespacing="125%"><tspan + sodipodi:role="line" + id="tspan2051" + x="59" + y="330">SONIC VISUALISER</tspan></text> + <text + xml:space="preserve" + style="font-size:14px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:100%;writing-mode:lr-tb;text-anchor:start;fill:black;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Korataki" + x="84.300003" + y="352" + id="text2053" + sodipodi:linespacing="100%"><tspan + sodipodi:role="line" + id="tspan2055" + x="84.300003" + y="352">QUEEN MARY, UNIVERSITY OF LONDON</tspan></text> + </g> +</svg>
--- a/main/MainWindow.cpp Tue Nov 13 13:51:07 2007 +0000 +++ b/main/MainWindow.cpp Wed Feb 27 11:59:42 2008 +0000 @@ -16,7 +16,6 @@ #include "../version.h" #include "MainWindow.h" -#include "framework/Document.h" #include "PreferencesDialog.h" #include "view/Pane.h" @@ -25,6 +24,8 @@ #include "data/model/SparseOneDimensionalModel.h" #include "data/model/NoteModel.h" #include "data/model/Labeller.h" +#include "data/osc/OSCQueue.h" +#include "framework/Document.h" #include "view/ViewManager.h" #include "base/Preferences.h" #include "layer/WaveformLayer.h" @@ -41,7 +42,7 @@ #include "widgets/PropertyStack.h" #include "widgets/AudioDial.h" #include "widgets/IconLoader.h" -#include "widgets/LayerTree.h" +#include "widgets/LayerTreeDialog.h" #include "widgets/ListInputDialog.h" #include "widgets/SubdividingMenu.h" #include "widgets/NotifyingPushButton.h" @@ -69,7 +70,6 @@ #include "base/Clipboard.h" #include "base/UnitDatabase.h" #include "base/ColourDatabase.h" -#include "data/osc/OSCQueue.h" // For version information #include "vamp/vamp.h" @@ -133,8 +133,10 @@ m_prevSolo(false), m_ffwdAction(0), m_rwdAction(0), + m_playControlsSpacer(0), + m_playControlsWidth(0), m_preferencesDialog(0), - m_layerTreeView(0), + m_layerTreeDialog(0), m_keyReference(new KeyReference()) { setWindowTitle(tr("Sonic Visualiser")); @@ -220,47 +222,33 @@ IconLoader il; - m_playSharpen = new NotifyingPushButton(frame); - m_playSharpen->setToolTip(tr("Sharpen percussive transients")); - m_playSharpen->setFixedSize(20, 20); - m_playSharpen->setEnabled(false); - m_playSharpen->setCheckable(true); - m_playSharpen->setChecked(false); - m_playSharpen->setIcon(il.load("sharpen")); - connect(m_playSharpen, SIGNAL(clicked()), this, SLOT(playSharpenToggled())); - connect(m_playSharpen, SIGNAL(mouseEntered()), this, SLOT(mouseEnteredWidget())); - connect(m_playSharpen, SIGNAL(mouseLeft()), this, SLOT(mouseLeftWidget())); - - m_playMono = new NotifyingPushButton(frame); - m_playMono->setToolTip(tr("Run time stretcher in mono only")); - m_playMono->setFixedSize(20, 20); - m_playMono->setEnabled(false); - m_playMono->setCheckable(true); - m_playMono->setChecked(false); - m_playMono->setIcon(il.load("mono")); - connect(m_playMono, SIGNAL(clicked()), this, SLOT(playMonoToggled())); - connect(m_playMono, SIGNAL(mouseEntered()), this, SLOT(mouseEnteredWidget())); - connect(m_playMono, SIGNAL(mouseLeft()), this, SLOT(mouseLeftWidget())); - QSettings settings; settings.beginGroup("MainWindow"); - m_playSharpen->setChecked(settings.value("playsharpen", true).toBool()); - m_playMono->setChecked(settings.value("playmono", false).toBool()); settings.endGroup(); + m_playControlsSpacer = new QFrame; + layout->setSpacing(4); layout->addWidget(scroll, 0, 0, 1, 5); - layout->addWidget(m_overview, 1, 0); - layout->addWidget(m_fader, 1, 1); - layout->addWidget(m_playSpeed, 1, 2); - layout->addWidget(m_playSharpen, 1, 3); - layout->addWidget(m_playMono, 1, 4); - - m_paneStack->setPropertyStackMinWidth - (m_fader->width() + m_playSpeed->width() + m_playSharpen->width() + - m_playMono->width() + layout->spacing() * 4); - - layout->setColumnStretch(0, 10); + layout->addWidget(m_overview, 1, 1); + layout->addWidget(m_playControlsSpacer, 1, 2); + layout->addWidget(m_playSpeed, 1, 3); + layout->addWidget(m_fader, 1, 4); + + m_playControlsWidth = + m_fader->width() + m_playSpeed->width() + layout->spacing() * 2; + + layout->setColumnMinimumWidth(0, 14); + layout->setColumnStretch(0, 0); + + m_paneStack->setPropertyStackMinWidth(m_playControlsWidth + + 2 + layout->spacing()); + m_playControlsSpacer->setFixedSize(QSize(2, 2)); + + layout->setColumnStretch(1, 10); + + connect(m_paneStack, SIGNAL(propertyStacksResized(int)), + this, SLOT(propertyStacksResized(int))); frame->setLayout(layout); @@ -277,7 +265,7 @@ { delete m_keyReference; delete m_preferencesDialog; - delete m_layerTreeView; + delete m_layerTreeDialog; Profiles::getInstance()->dump(); } @@ -593,6 +581,7 @@ menu->addAction(action); QMenu *numberingMenu = menu->addMenu(tr("Number New Instants with")); + numberingMenu->setTearOffEnabled(true); QActionGroup *numberingGroup = new QActionGroup(this); Labeller::TypeNameMap types = m_labeller->getTypeNames(); @@ -614,7 +603,7 @@ QMenu *cycleMenu = numberingMenu->addMenu(tr("Cycle size")); QActionGroup *cycleGroup = new QActionGroup(this); - int cycles[] = { 2, 3, 4, 5, 6, 7, 8, 10, 12, 16 }; + int cycles[] = { 2, 3, 4, 5, 6, 7, 8, 9, 10, 12, 16 }; for (int i = 0; i < int(sizeof(cycles)/sizeof(cycles[0])); ++i) { action = new QAction(QString("%1").arg(cycles[i]), this); connect(action, SIGNAL(triggered()), this, SLOT(setInstantsCounterCycle())); @@ -623,10 +612,6 @@ cycleGroup->addAction(action); cycleMenu->addAction(action); } - - action = new QAction(tr("Reset Counters..."), this); - connect(action, SIGNAL(triggered()), this, SLOT(resetInstantsCounters())); - numberingMenu->addAction(action); } if (i->first == Labeller::ValueNone || @@ -636,8 +621,13 @@ } } - action = new QAction(tr("Re-Number Selected Instants"), this); - action->setStatusTip(tr("Re-number the selected instants using the current labelling scheme")); + action = new QAction(tr("Set Numbering Counters..."), this); + action->setStatusTip(tr("Set the counters used for counter-based labelling")); + connect(action, SIGNAL(triggered()), this, SLOT(resetInstantsCounters())); + menu->addAction(action); + + action = new QAction(tr("Renumber Selected Instants"), this); + action->setStatusTip(tr("Renumber the selected instants using the current labelling scheme")); connect(action, SIGNAL(triggered()), this, SLOT(renumberInstants())); connect(this, SIGNAL(canRenumberInstants(bool)), action, SLOT(setEnabled(bool))); // m_keyReference->registerShortcut(action); @@ -810,8 +800,8 @@ menu->addSeparator(); - action = new QAction(tr("Show La&yer Hierarchy"), this); - action->setShortcut(tr("H")); + action = new QAction(tr("Show La&yer Summary"), this); + action->setShortcut(tr("Y")); action->setStatusTip(tr("Open a window displaying the hierarchy of panes and layers in this session")); connect(action, SIGNAL(triggered()), this, SLOT(showLayerTree())); m_keyReference->registerShortcut(action); @@ -848,7 +838,7 @@ action->setStatusTip(tr("Add a new pane containing only a time ruler")); connect(action, SIGNAL(triggered()), this, SLOT(addPane())); connect(this, SIGNAL(canAddPane(bool)), action, SLOT(setEnabled(bool))); - m_paneActions[action] = PaneConfiguration(LayerFactory::TimeRuler); + m_paneActions[action] = LayerConfiguration(LayerFactory::TimeRuler); m_keyReference->registerShortcut(action); menu->addAction(action); @@ -884,7 +874,7 @@ connect(action, SIGNAL(triggered()), this, SLOT(addLayer())); connect(this, SIGNAL(canAddLayer(bool)), action, SLOT(setEnabled(bool))); - m_layerActions[action] = type; + m_layerActions[action] = LayerConfiguration(type); menu->addAction(action); m_rightButtonLayerMenu->addAction(action); } @@ -901,7 +891,7 @@ }; std::vector<Model *> models; - if (m_document) models = m_document->getTransformerInputModels(); //!!! not well named for this! + if (m_document) models = m_document->getTransformInputModels(); bool plural = (models.size() > 1); if (models.empty()) { models.push_back(getMainModel()); // probably 0 @@ -910,9 +900,11 @@ for (unsigned int i = 0; i < sizeof(backgroundTypes)/sizeof(backgroundTypes[0]); ++i) { - for (int menuType = 0; menuType <= 1; ++menuType) { // pane, layer - - if (menuType == 0) menu = m_paneMenu; + const int paneMenuType = 0, layerMenuType = 1; + + for (int menuType = paneMenuType; menuType <= layerMenuType; ++menuType) { + + if (menuType == paneMenuType) menu = m_paneMenu; else menu = m_layerMenu; QMenu *submenu = 0; @@ -927,7 +919,7 @@ case LayerFactory::Waveform: icon = il.load("waveform"); mainText = tr("Add &Waveform"); - if (menuType == 0) { + if (menuType == paneMenuType) { shortcutText = tr("W"); tipText = tr("Add a new pane showing a waveform view"); } else { @@ -939,7 +931,7 @@ case LayerFactory::Spectrogram: icon = il.load("spectrogram"); mainText = tr("Add Spectro&gram"); - if (menuType == 0) { + if (menuType == paneMenuType) { shortcutText = tr("G"); tipText = tr("Add a new pane showing a spectrogram"); } else { @@ -950,7 +942,7 @@ case LayerFactory::MelodicRangeSpectrogram: icon = il.load("spectrogram"); mainText = tr("Add &Melodic Range Spectrogram"); - if (menuType == 0) { + if (menuType == paneMenuType) { shortcutText = tr("M"); tipText = tr("Add a new pane showing a spectrogram set up for an overview of note pitches"); } else { @@ -961,7 +953,7 @@ case LayerFactory::PeakFrequencySpectrogram: icon = il.load("spectrogram"); mainText = tr("Add Pea&k Frequency Spectrogram"); - if (menuType == 0) { + if (menuType == paneMenuType) { shortcutText = tr("K"); tipText = tr("Add a new pane showing a spectrogram set up for tracking frequencies"); } else { @@ -972,7 +964,7 @@ case LayerFactory::Spectrum: icon = il.load("spectrum"); mainText = tr("Add Spectr&um"); - if (menuType == 0) { + if (menuType == paneMenuType) { shortcutText = tr("U"); tipText = tr("Add a new pane showing a frequency spectrum"); } else { @@ -984,11 +976,11 @@ } std::vector<Model *> candidateModels; - if (menuType == 0) { +// if (menuType == paneMenuType) { candidateModels = models; - } else { - candidateModels.push_back(0); - } +// } else { +// candidateModels.push_back(0); +// } for (std::vector<Model *>::iterator mi = candidateModels.begin(); @@ -1013,33 +1005,33 @@ bool isDefault = (c == 0); bool isOnly = (isDefault && (channels == 1)); - if (menuType == 1) { - if (isDefault) isOnly = true; - else continue; - } - - if (isOnly && (!plural || menuType == 1)) { - - if (menuType == 1 && type != LayerFactory::Waveform) { - action = new QAction(mainText, this); - } else { +// if (menuType == layerMenuType) { +// if (isDefault) isOnly = true; +// else continue; +// } + + if (isOnly && (!plural /*|| menuType == layerMenuType*/)) { + +// if (menuType == layerMenuType && type != LayerFactory::Waveform) { +// action = new QAction(mainText, this); +// } else { action = new QAction(icon, mainText, this); - } +// } action->setShortcut(shortcutText); action->setStatusTip(tipText); - if (menuType == 0) { + if (menuType == paneMenuType) { connect(action, SIGNAL(triggered()), this, SLOT(addPane())); connect(this, SIGNAL(canAddPane(bool)), action, SLOT(setEnabled(bool))); - m_paneActions[action] = PaneConfiguration(type); + m_paneActions[action] = LayerConfiguration(type); } else { connect(action, SIGNAL(triggered()), this, SLOT(addLayer())); connect(this, SIGNAL(canAddLayer(bool)), action, SLOT(setEnabled(bool))); - m_layerActions[action] = type; + m_layerActions[action] = LayerConfiguration(type); } if (shortcutText != "") { m_keyReference->registerShortcut(action); @@ -1083,19 +1075,20 @@ action->setStatusTip(tipText); - if (menuType == 0) { + if (menuType == paneMenuType) { connect(action, SIGNAL(triggered()), this, SLOT(addPane())); connect(this, SIGNAL(canAddPane(bool)), action, SLOT(setEnabled(bool))); m_paneActions[action] = - PaneConfiguration(type, model, c - 1); + LayerConfiguration(type, model, c - 1); } else { connect(action, SIGNAL(triggered()), this, SLOT(addLayer())); connect(this, SIGNAL(canAddLayer(bool)), action, SLOT(setEnabled(bool))); - m_layerActions[action] = type; + m_layerActions[action] = + LayerConfiguration(type, model, c - 1); } submenu->addAction(action); @@ -1106,6 +1099,23 @@ } menu = m_paneMenu; + menu->addSeparator(); + + action = new QAction(tr("Switch to Previous Pane"), this); + action->setShortcut(tr("[")); + action->setStatusTip(tr("Make the next pane up in the pane stack current")); + connect(action, SIGNAL(triggered()), this, SLOT(previousPane())); + connect(this, SIGNAL(canSelectPreviousPane(bool)), action, SLOT(setEnabled(bool))); + m_keyReference->registerShortcut(action); + menu->addAction(action); + + action = new QAction(tr("Switch to Next Pane"), this); + action->setShortcut(tr("]")); + action->setStatusTip(tr("Make the next pane down in the pane stack current")); + connect(action, SIGNAL(triggered()), this, SLOT(nextPane())); + connect(this, SIGNAL(canSelectNextPane(bool)), action, SLOT(setEnabled(bool))); + m_keyReference->registerShortcut(action); + menu->addAction(action); menu->addSeparator(); @@ -1123,7 +1133,7 @@ action->setStatusTip(tr("Add a new layer showing a time ruler")); connect(action, SIGNAL(triggered()), this, SLOT(addLayer())); connect(this, SIGNAL(canAddLayer(bool)), action, SLOT(setEnabled(bool))); - m_layerActions[action] = LayerFactory::TimeRuler; + m_layerActions[action] = LayerConfiguration(LayerFactory::TimeRuler); menu->addAction(action); menu->addSeparator(); @@ -1138,6 +1148,25 @@ setupExistingLayersMenus(); +/*!!! These don't work correctly -- fix or omit + menu->addSeparator(); + + action = new QAction(tr("Switch to Previous Layer"), this); + action->setShortcut(tr("{")); + action->setStatusTip(tr("Make the previous layer in the pane current")); + connect(action, SIGNAL(triggered()), this, SLOT(previousLayer())); + connect(this, SIGNAL(canSelectPreviousLayer(bool)), action, SLOT(setEnabled(bool))); + m_keyReference->registerShortcut(action); + menu->addAction(action); + + action = new QAction(tr("Switch to Next Layer"), this); + action->setShortcut(tr("}")); + action->setStatusTip(tr("Make the next layer in the pane current")); + connect(action, SIGNAL(triggered()), this, SLOT(nextLayer())); + connect(this, SIGNAL(canSelectNextLayer(bool)), action, SLOT(setEnabled(bool))); + m_keyReference->registerShortcut(action); + menu->addAction(action); +*/ m_rightButtonLayerMenu->addSeparator(); menu->addSeparator(); @@ -1174,7 +1203,7 @@ } TransformList transforms = - TransformFactory::getInstance()->getAllTransforms(); + TransformFactory::getInstance()->getAllTransformDescriptions(); vector<QString> types = TransformFactory::getInstance()->getAllTransformTypes(); @@ -1280,6 +1309,20 @@ } } + // Names should only be duplicated here if they have the same + // plugin name, output name and maker but are in different library + // .so names -- that won't happen often I hope + std::map<QString, QString> idNameSonameMap; + std::set<QString> seenNames, duplicateNames; + for (unsigned int i = 0; i < transforms.size(); ++i) { + QString name = transforms[i].name; + if (seenNames.find(name) != seenNames.end()) { + duplicateNames.insert(name); + } else { + seenNames.insert(name); + } + } + for (unsigned int i = 0; i < transforms.size(); ++i) { QString name = transforms[i].name; @@ -1299,6 +1342,16 @@ QString pluginName = name.section(": ", 0, 0); QString output = name.section(": ", 1); + if (duplicateNames.find(pluginName) != duplicateNames.end()) { + pluginName = QString("%1 <%2>") + .arg(pluginName) + .arg(transforms[i].identifier.section(':', 1, 1)); + if (output == "") name = pluginName; + else name = QString("%1: %2") + .arg(pluginName) + .arg(output); + } + QAction *action = new QAction(tr("%1...").arg(name), this); connect(action, SIGNAL(triggered()), this, SLOT(addLayer())); m_transformActions[action] = transforms[i].identifier; @@ -1439,6 +1492,8 @@ (tr("Repeat Transform"), ti->second->shortcut(), tr("Re-select the most recently run transform")); + } else { + ti->second->setShortcut(QString("")); } m_recentTransformsMenu->addAction(ti->second); } @@ -1737,10 +1792,21 @@ m_keyReference->registerShortcut(action); m_toolActions[ViewManager::DrawMode] = action; + action = toolbar->addAction(il.load("erase"), + tr("Erase")); + action->setCheckable(true); + action->setShortcut(tr("5")); + action->setStatusTip(tr("Erase items from layer")); + connect(action, SIGNAL(triggered()), this, SLOT(toolEraseSelected())); + connect(this, SIGNAL(canEditLayer(bool)), action, SLOT(setEnabled(bool))); + group->addAction(action); + m_keyReference->registerShortcut(action); + m_toolActions[ViewManager::EraseMode] = action; + action = toolbar->addAction(il.load("measure"), tr("Measure")); action->setCheckable(true); - action->setShortcut(tr("5")); + action->setShortcut(tr("6")); action->setStatusTip(tr("Make measurements in layer")); connect(action, SIGNAL(triggered()), this, SLOT(toolMeasureSelected())); connect(this, SIGNAL(canMeasureLayer(bool)), action, SLOT(setEnabled(bool))); @@ -1748,14 +1814,6 @@ m_keyReference->registerShortcut(action); m_toolActions[ViewManager::MeasureMode] = action; -// action = toolbar->addAction(il.load("text"), -// tr("Text")); -// action->setCheckable(true); -// action->setShortcut(tr("5")); -// connect(action, SIGNAL(triggered()), this, SLOT(toolTextSelected())); -// group->addAction(action); -// m_toolActions[ViewManager::TextMode] = action; - toolNavigateSelected(); Pane::registerShortcuts(*m_keyReference); @@ -1898,17 +1956,17 @@ } void +MainWindow::toolEraseSelected() +{ + m_viewManager->setToolMode(ViewManager::EraseMode); +} + +void MainWindow::toolMeasureSelected() { m_viewManager->setToolMode(ViewManager::MeasureMode); } -//void -//MainWindow::toolTextSelected() -//{ -// m_viewManager->setToolMode(ViewManager::TextMode); -//} - void MainWindow::importAudio() { @@ -2508,11 +2566,6 @@ m_preferencesDialog->applicationClosing(false); } - if (m_layerTreeView && - m_layerTreeView->isVisible()) { - delete m_layerTreeView; - } - closeSession(); e->accept(); @@ -2659,6 +2712,20 @@ } void +MainWindow::propertyStacksResized(int width) +{ + std::cerr << "MainWindow::propertyStacksResized(" << width << ")" << std::endl; + + if (!m_playControlsSpacer) return; + + int spacerWidth = width - m_playControlsWidth - 4; + + std::cerr << "resizing spacer from " << m_playControlsSpacer->width() << " to " << spacerWidth << std::endl; + + m_playControlsSpacer->setFixedSize(QSize(spacerWidth, 2)); +} + +void MainWindow::addPane() { QObject *s = sender(); @@ -2682,7 +2749,7 @@ } void -MainWindow::addPane(const PaneConfiguration &configuration, QString text) +MainWindow::addPane(const LayerConfiguration &configuration, QString text) { CommandHistory::getInstance()->startCompoundOperation(text, true); @@ -2719,7 +2786,7 @@ if (suggestedModel) { // check its validity - std::vector<Model *> inputModels = m_document->getTransformerInputModels(); + std::vector<Model *> inputModels = m_document->getTransformInputModels(); for (size_t j = 0; j < inputModels.size(); ++j) { if (inputModels[j] == suggestedModel) { model = suggestedModel; @@ -2813,7 +2880,7 @@ return; } - LayerFactory::LayerType type = i->second; + LayerFactory::LayerType type = i->second.layer; LayerFactory::LayerTypeSet emptyTypes = LayerFactory::getInstance()->getValidEmptyLayerTypes(); @@ -2823,24 +2890,42 @@ if (emptyTypes.find(type) != emptyTypes.end()) { newLayer = m_document->createEmptyLayer(type); - m_toolActions[ViewManager::DrawMode]->trigger(); + if (newLayer) { + m_toolActions[ViewManager::DrawMode]->trigger(); + } } else { - newLayer = m_document->createMainModelLayer(type); - } - - m_document->addLayerToView(pane, newLayer); - m_paneStack->setCurrentLayer(pane, newLayer); + if (!i->second.sourceModel) { + // e.g. time ruler + newLayer = m_document->createMainModelLayer(type); + } else { + newLayer = m_document->createLayer(type); + if (m_document->isKnownModel(i->second.sourceModel)) { + m_document->setChannel(newLayer, i->second.channel); + m_document->setModel(newLayer, i->second.sourceModel); + } else { + std::cerr << "WARNING: MainWindow::addLayer: unknown model " + << i->second.sourceModel + << " (\"" + << (i->second.sourceModel ? i->second.sourceModel->objectName().toStdString() : "") + << "\") in layer action map" + << std::endl; + } + } + } + + if (newLayer) { + m_document->addLayerToView(pane, newLayer); + m_paneStack->setCurrentLayer(pane, newLayer); + } return; } - TransformId transform = i->second; - ModelTransformerFactory *factory = ModelTransformerFactory::getInstance(); - - QString configurationXml; - + //!!! want to do something like this, but it's not supported in + //ModelTransformerFactory yet + /* int channel = -1; // pick up the default channel from any existing layers on the same pane for (int j = 0; j < pane->getLayerCount(); ++j) { @@ -2850,44 +2935,62 @@ break; } } + */ // We always ask for configuration, even if the plugin isn't // supposed to be configurable, because we need to let the user // change the execution context (block size etc). - PluginTransformer::ExecutionContext context(channel); + QString transformId = i->second; + Transform transform = TransformFactory::getInstance()-> + getDefaultTransformFor(transformId); std::vector<Model *> candidateInputModels = - m_document->getTransformerInputModels(); - + m_document->getTransformInputModels(); + + Model *defaultInputModel = 0; + for (int j = 0; j < pane->getLayerCount(); ++j) { + Layer *layer = pane->getLayer(j); + if (!layer) continue; + if (LayerFactory::getInstance()->getLayerType(layer) != + LayerFactory::Waveform && + !layer->isLayerOpaque()) continue; + Model *model = layer->getModel(); + if (!model) continue; + for (size_t k = 0; k < candidateInputModels.size(); ++k) { + if (candidateInputModels[k] == model) { + defaultInputModel = model; + break; + } + } + if (defaultInputModel) break; + } + size_t startFrame = 0, duration = 0; size_t endFrame = 0; m_viewManager->getSelection().getExtents(startFrame, endFrame); if (endFrame > startFrame) duration = endFrame - startFrame; else startFrame = 0; - Model *inputModel = factory->getConfigurationForTransformer + ModelTransformer::Input input = ModelTransformerFactory::getInstance()-> + getConfigurationForTransform (transform, candidateInputModels, - context, - configurationXml, + defaultInputModel, m_playSource, startFrame, duration); - if (!inputModel) return; - -// std::cerr << "MainWindow::addLayer: Input model is " << inputModel << " \"" << inputModel->objectName().toStdString() << "\"" << std::endl; - - Layer *newLayer = m_document->createDerivedLayer(transform, - inputModel, - context, - configurationXml); + if (!input.getModel()) return; + +// std::cerr << "MainWindow::addLayer: Input model is " << input.getModel() << " \"" << input.getModel()->objectName().toStdString() << "\"" << std::endl; + + Layer *newLayer = m_document->createDerivedLayer(transform, input); if (newLayer) { m_document->addLayerToView(pane, newLayer); - m_document->setChannel(newLayer, context.channel); - m_recentTransforms.add(transform); + m_document->setChannel(newLayer, input.getChannel()); + m_recentTransforms.add(transformId); m_paneStack->setCurrentLayer(pane, newLayer); } @@ -2907,7 +3010,7 @@ tr("New name for this layer:"), QLineEdit::Normal, layer->objectName(), &ok); if (ok) { - layer->setObjectName(newName); + layer->setPresentationName(newName); setupExistingLayersMenus(); } } @@ -2986,38 +3089,12 @@ .arg(pc)); } - m_playSharpen->setEnabled(something); - m_playMono->setEnabled(something); - bool sharpen = (something && m_playSharpen->isChecked()); - bool mono = (something && m_playMono->isChecked()); - m_playSource->setTimeStretch(factor, sharpen, mono); + m_playSource->setTimeStretch(factor); updateMenuStates(); } void -MainWindow::playSharpenToggled() -{ - QSettings settings; - settings.beginGroup("MainWindow"); - settings.setValue("playsharpen", m_playSharpen->isChecked()); - settings.endGroup(); - - playSpeedChanged(m_playSpeed->value()); -} - -void -MainWindow::playMonoToggled() -{ - QSettings settings; - settings.beginGroup("MainWindow"); - settings.setValue("playmono", m_playMono->isChecked()); - settings.endGroup(); - - playSpeedChanged(m_playSpeed->value()); -} - -void MainWindow::speedUpPlayback() { int value = m_playSpeed->value(); @@ -3042,6 +3119,27 @@ } void +MainWindow::currentPaneChanged(Pane *pane) +{ + MainWindowBase::currentPaneChanged(pane); + + if (!pane || !m_panLayer) return; + for (int i = pane->getLayerCount(); i > 0; ) { + --i; + Layer *layer = pane->getLayer(i); + if (LayerFactory::getInstance()->getLayerType(layer) == + LayerFactory::Waveform) { + RangeSummarisableTimeValueModel *tvm = + dynamic_cast<RangeSummarisableTimeValueModel *>(layer->getModel()); + if (tvm) { + m_panLayer->setModel(tvm); + return; + } + } + } +} + +void MainWindow::updateVisibleRangeDisplay(Pane *p) const { if (!getMainModel() || !p) { @@ -3194,28 +3292,76 @@ MainWindow::resetInstantsCounters() { LabelCounterInputDialog dialog(m_labeller, this); + dialog.setWindowTitle(tr("Reset Counters")); dialog.exec(); } void -MainWindow::modelGenerationFailed(QString transformName) +MainWindow::modelGenerationFailed(QString transformName, QString message) +{ + if (message != "") { + + QMessageBox::warning + (this, + tr("Failed to generate layer"), + tr("<b>Layer generation failed</b><p>Failed to generate derived layer.<p>The layer transform \"%1\" failed:<p>%2") + .arg(transformName).arg(message), + QMessageBox::Ok); + } else { + QMessageBox::warning + (this, + tr("Failed to generate layer"), + tr("<b>Layer generation failed</b><p>Failed to generate a derived layer.<p>The layer transform \"%1\" failed.<p>No error information is available.") + .arg(transformName), + QMessageBox::Ok); + } +} + +void +MainWindow::modelGenerationWarning(QString transformName, QString message) +{ + QMessageBox::warning + (this, tr("Warning"), message, QMessageBox::Ok); +} + +void +MainWindow::modelRegenerationFailed(QString layerName, + QString transformName, QString message) +{ + if (message != "") { + + QMessageBox::warning + (this, + tr("Failed to regenerate layer"), + tr("<b>Layer generation failed</b><p>Failed to regenerate derived layer \"%1\" using new data model as input.<p>The layer transform \"%2\" failed:<p>%3") + .arg(layerName).arg(transformName).arg(message), + QMessageBox::Ok); + } else { + QMessageBox::warning + (this, + tr("Failed to regenerate layer"), + tr("<b>Layer generation failed</b><p>Failed to regenerate derived layer \"%1\" using new data model as input.<p>The layer transform \"%2\" failed.<p>No error information is available.") + .arg(layerName).arg(transformName), + QMessageBox::Ok); + } +} + +void +MainWindow::modelRegenerationWarning(QString layerName, + QString transformName, QString message) +{ + QMessageBox::warning + (this, tr("Warning"), tr("<b>Warning when regenerating layer</b><p>When regenerating the derived layer \"%1\" using new data model as input:<p>%2").arg(layerName).arg(message), QMessageBox::Ok); +} + +void +MainWindow::alignmentFailed(QString transformName, QString message) { QMessageBox::warning (this, - tr("Failed to generate layer"), - tr("<b>Layer generation failed</b><p>Failed to generate a derived layer.<p>The layer transform \"%1\" failed.<p>This may mean that a plugin failed to initialise, perhaps because it rejected the processing block size that was requested.") - .arg(transformName), - QMessageBox::Ok); -} - -void -MainWindow::modelRegenerationFailed(QString layerName, QString transformName) -{ - QMessageBox::warning - (this, - tr("Failed to regenerate layer"), - tr("<b>Layer generation failed</b><p>Failed to regenerate derived layer \"%1\".<p>The layer transform \"%2\" failed to run.<p>This may mean that the layer used a plugin that is not currently available.") - .arg(layerName).arg(transformName), + tr("Failed to calculate alignment"), + tr("<b>Alignment calculation failed</b><p>Failed to calculate an audio alignment using transform \"%1\":<p>%2") + .arg(transformName).arg(message), QMessageBox::Ok); } @@ -3230,508 +3376,15 @@ void MainWindow::showLayerTree() { - if (!m_layerTreeView.isNull()) { - m_layerTreeView->show(); - m_layerTreeView->raise(); + if (!m_layerTreeDialog.isNull()) { + m_layerTreeDialog->show(); + m_layerTreeDialog->raise(); return; } - //!!! should use an actual dialog class - - m_layerTreeView = new QTreeView(); - LayerTreeModel *tree = new LayerTreeModel(m_paneStack); - m_layerTreeView->resize(500, 300); //!!! - m_layerTreeView->setModel(tree); - m_layerTreeView->expandAll(); - m_layerTreeView->show(); -} - -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") { - - if (message.getArgCount() == 1 && - message.getArg(0).canConvert(QVariant::String)) { - QString path = message.getArg(0).toString(); - if (open(path, ReplaceMainModel) != FileOpenSucceeded) { - std::cerr << "MainWindow::handleOSCMessage: File open failed for path \"" - << path.toStdString() << "\"" << std::endl; - } - //!!! we really need to spin here and not return until the - // file has been completely decoded... - } - - } else if (message.getMethod() == "openadditional") { - - if (message.getArgCount() == 1 && - message.getArg(0).canConvert(QVariant::String)) { - QString path = message.getArg(0).toString(); - if (open(path, CreateAdditionalModel) != FileOpenSucceeded) { - std::cerr << "MainWindow::handleOSCMessage: File open failed for path \"" - << path.toStdString() << "\"" << std::endl; - } - } - - } else if (message.getMethod() == "recent" || - message.getMethod() == "last") { - - int n = 0; - if (message.getMethod() == "recent" && - message.getArgCount() == 1 && - message.getArg(0).canConvert(QVariant::Int)) { - n = message.getArg(0).toInt() - 1; - } - std::vector<QString> recent = m_recentFiles.getRecent(); - if (n >= 0 && n < int(recent.size())) { - if (open(recent[n], ReplaceMainModel) != FileOpenSucceeded) { - std::cerr << "MainWindow::handleOSCMessage: File open failed for path \"" - << recent[n].toStdString() << "\"" << std::endl; - } - } - - } else if (message.getMethod() == "save") { - - QString path; - if (message.getArgCount() == 1 && - message.getArg(0).canConvert(QVariant::String)) { - path = message.getArg(0).toString(); - if (QFileInfo(path).exists()) { - std::cerr << "MainWindow::handleOSCMessage: Refusing to overwrite existing file in save" << std::endl; - } else { - saveSessionFile(path); - } - } - - } else if (message.getMethod() == "export") { - - QString path; - if (getMainModel()) { - if (message.getArgCount() == 1 && - message.getArg(0).canConvert(QVariant::String)) { - path = message.getArg(0).toString(); - if (QFileInfo(path).exists()) { - std::cerr << "MainWindow::handleOSCMessage: Refusing to overwrite existing file in export" << std::endl; - } else { - WavFileWriter writer(path, - getMainModel()->getSampleRate(), - getMainModel()->getChannelCount()); - MultiSelection ms = m_viewManager->getSelection(); - if (!ms.getSelections().empty()) { - writer.writeModel(getMainModel(), &ms); - } else { - writer.writeModel(getMainModel()); - } - } - } - } - - } else if (message.getMethod() == "jump" || - message.getMethod() == "play") { - - if (getMainModel()) { - - unsigned long frame = m_viewManager->getPlaybackFrame(); - bool selection = false; - bool play = (message.getMethod() == "play"); - - if (message.getArgCount() == 1) { - - if (message.getArg(0).canConvert(QVariant::String) && - message.getArg(0).toString() == "selection") { - - selection = true; - - } else if (message.getArg(0).canConvert(QVariant::String) && - message.getArg(0).toString() == "end") { - - frame = getMainModel()->getEndFrame(); - - } else if (message.getArg(0).canConvert(QVariant::Double)) { - - double time = message.getArg(0).toDouble(); - if (time < 0.0) time = 0.0; - - frame = lrint(time * getMainModel()->getSampleRate()); - } - } - - if (frame > getMainModel()->getEndFrame()) { - frame = getMainModel()->getEndFrame(); - } - - if (play) { - m_viewManager->setPlaySelectionMode(selection); - } - - if (selection) { - MultiSelection::SelectionList sl = m_viewManager->getSelections(); - if (!sl.empty()) { - frame = sl.begin()->getStartFrame(); - } - } - - m_viewManager->setPlaybackFrame(frame); - - if (play && !m_playSource->isPlaying()) { - m_playSource->play(frame); - } - } - - } else if (message.getMethod() == "stop") { - - if (m_playSource->isPlaying()) m_playSource->stop(); - - } else if (message.getMethod() == "loop") { - - if (message.getArgCount() == 1 && - message.getArg(0).canConvert(QVariant::String)) { - - QString str = message.getArg(0).toString(); - if (str == "on") { - m_viewManager->setPlayLoopMode(true); - } else if (str == "off") { - m_viewManager->setPlayLoopMode(false); - } - } - - } else if (message.getMethod() == "solo") { - - if (message.getArgCount() == 1 && - message.getArg(0).canConvert(QVariant::String)) { - - QString str = message.getArg(0).toString(); - if (str == "on") { - m_viewManager->setPlaySoloMode(true); - } else if (str == "off") { - m_viewManager->setPlaySoloMode(false); - } - } - - } else if (message.getMethod() == "select" || - message.getMethod() == "addselect") { - - if (getMainModel()) { - - int f0 = getMainModel()->getStartFrame(); - int f1 = getMainModel()->getEndFrame(); - - bool done = false; - - if (message.getArgCount() == 2 && - message.getArg(0).canConvert(QVariant::Double) && - message.getArg(1).canConvert(QVariant::Double)) { - - double t0 = message.getArg(0).toDouble(); - double t1 = message.getArg(1).toDouble(); - if (t1 < t0) { double temp = t0; t0 = t1; t1 = temp; } - if (t0 < 0.0) t0 = 0.0; - if (t1 < 0.0) t1 = 0.0; - - f0 = lrint(t0 * getMainModel()->getSampleRate()); - f1 = lrint(t1 * getMainModel()->getSampleRate()); - - Pane *pane = m_paneStack->getCurrentPane(); - Layer *layer = 0; - if (pane) layer = pane->getSelectedLayer(); - if (layer) { - size_t resolution; - layer->snapToFeatureFrame(pane, f0, resolution, - Layer::SnapLeft); - layer->snapToFeatureFrame(pane, f1, resolution, - Layer::SnapRight); - } - - } else if (message.getArgCount() == 1 && - message.getArg(0).canConvert(QVariant::String)) { - - QString str = message.getArg(0).toString(); - if (str == "none") { - m_viewManager->clearSelections(); - done = true; - } - } - - if (!done) { - if (message.getMethod() == "select") { - m_viewManager->setSelection(Selection(f0, f1)); - } else { - m_viewManager->addSelection(Selection(f0, f1)); - } - } - } - - } else if (message.getMethod() == "add") { - - if (getMainModel()) { - - if (message.getArgCount() >= 1 && - message.getArg(0).canConvert(QVariant::String)) { - - int channel = -1; - if (message.getArgCount() == 2 && - message.getArg(0).canConvert(QVariant::Int)) { - channel = message.getArg(0).toInt(); - if (channel < -1 || - channel > int(getMainModel()->getChannelCount())) { - std::cerr << "WARNING: MainWindow::handleOSCMessage: channel " - << channel << " out of range" << std::endl; - channel = -1; - } - } - - QString str = message.getArg(0).toString(); - - LayerFactory::LayerType type = - LayerFactory::getInstance()->getLayerTypeForName(str); - - if (type == LayerFactory::UnknownLayer) { - std::cerr << "WARNING: MainWindow::handleOSCMessage: unknown layer " - << "type " << str.toStdString() << std::endl; - } else { - - PaneConfiguration configuration(type, - getMainModel(), - channel); - - addPane(configuration, - tr("Add %1 Pane") - .arg(LayerFactory::getInstance()-> - getLayerPresentationName(type))); - } - } - } - - } else if (message.getMethod() == "undo") { - - CommandHistory::getInstance()->undo(); - - } else if (message.getMethod() == "redo") { - - CommandHistory::getInstance()->redo(); - - } else if (message.getMethod() == "set") { - - if (message.getArgCount() == 2 && - message.getArg(0).canConvert(QVariant::String) && - message.getArg(1).canConvert(QVariant::Double)) { - - QString property = message.getArg(0).toString(); - float value = (float)message.getArg(1).toDouble(); - - if (property == "gain") { - if (value < 0.0) value = 0.0; - m_fader->setValue(value); - if (m_playTarget) m_playTarget->setOutputGain(value); - } else if (property == "speedup") { - m_playSpeed->setMappedValue(value); - } else if (property == "overlays") { - if (value < 0.5) { - m_viewManager->setOverlayMode(ViewManager::NoOverlays); - } else if (value < 1.5) { - m_viewManager->setOverlayMode(ViewManager::MinimalOverlays); - } else if (value < 2.5) { - m_viewManager->setOverlayMode(ViewManager::StandardOverlays); - } else { - m_viewManager->setOverlayMode(ViewManager::AllOverlays); - } - } else if (property == "zoomwheels") { - m_viewManager->setZoomWheelsEnabled(value > 0.5); - } else if (property == "propertyboxes") { - bool toggle = ((value < 0.5) != - (m_paneStack->getLayoutStyle() == PaneStack::NoPropertyStacks)); - if (toggle) togglePropertyBoxes(); - } - - } 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); - } - } - - } else if (message.getMethod() == "setcurrent") { - - int paneIndex = -1, layerIndex = -1; - bool wantLayer = false; - - if (message.getArgCount() >= 1 && - message.getArg(0).canConvert(QVariant::Int)) { - - paneIndex = message.getArg(0).toInt() - 1; - - if (message.getArgCount() >= 2 && - message.getArg(1).canConvert(QVariant::Int)) { - wantLayer = true; - layerIndex = message.getArg(1).toInt() - 1; - } - } - - 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 if (message.getMethod() == "delete") { - - if (message.getArgCount() == 1 && - message.getArg(0).canConvert(QVariant::String)) { - - QString target = message.getArg(0).toString(); - - if (target == "pane") { - - deleteCurrentPane(); - - } else if (target == "layer") { - - deleteCurrentLayer(); - - } else { - - std::cerr << "WARNING: MainWindow::handleOSCMessage: Unknown delete target " << target.toStdString() << std::endl; - } - } - - } else if (message.getMethod() == "zoom") { - - if (message.getArgCount() == 1) { - if (message.getArg(0).canConvert(QVariant::String) && - message.getArg(0).toString() == "in") { - zoomIn(); - } else if (message.getArg(0).canConvert(QVariant::String) && - message.getArg(0).toString() == "out") { - zoomOut(); - } else if (message.getArg(0).canConvert(QVariant::String) && - message.getArg(0).toString() == "default") { - zoomDefault(); - } else if (message.getArg(0).canConvert(QVariant::Double)) { - double level = message.getArg(0).toDouble(); - Pane *currentPane = m_paneStack->getCurrentPane(); - if (level < 1.0) level = 1.0; - if (currentPane) currentPane->setZoomLevel(lrint(level)); - } - } - - } else if (message.getMethod() == "zoomvertical") { - - Pane *pane = m_paneStack->getCurrentPane(); - Layer *layer = 0; - if (pane && pane->getLayerCount() > 0) { - layer = pane->getLayer(pane->getLayerCount() - 1); - } - int defaultStep = 0; - int steps = 0; - if (layer) { - steps = layer->getVerticalZoomSteps(defaultStep); - if (message.getArgCount() == 1 && steps > 0) { - if (message.getArg(0).canConvert(QVariant::String) && - message.getArg(0).toString() == "in") { - int step = layer->getCurrentVerticalZoomStep() + 1; - if (step < steps) layer->setVerticalZoomStep(step); - } else if (message.getArg(0).canConvert(QVariant::String) && - message.getArg(0).toString() == "out") { - int step = layer->getCurrentVerticalZoomStep() - 1; - if (step >= 0) layer->setVerticalZoomStep(step); - } else if (message.getArg(0).canConvert(QVariant::String) && - message.getArg(0).toString() == "default") { - layer->setVerticalZoomStep(defaultStep); - } - } else if (message.getArgCount() == 2) { - if (message.getArg(0).canConvert(QVariant::Double) && - message.getArg(1).canConvert(QVariant::Double)) { - double min = message.getArg(0).toDouble(); - double max = message.getArg(1).toDouble(); - layer->setDisplayExtents(min, max); - } - } - } - - } 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)) { - - TransformId transform = message.getArg(0).toString(); - - Layer *newLayer = m_document->createDerivedLayer - (transform, - getMainModel(), - ModelTransformerFactory::getInstance()->getDefaultContextForTransformer - (transform, getMainModel()), - ""); - - 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() - << "\"" << std::endl; - } - + m_layerTreeDialog = new LayerTreeDialog(m_paneStack); + m_layerTreeDialog->setAttribute(Qt::WA_DeleteOnClose); // see below + m_layerTreeDialog->show(); } void @@ -3766,10 +3419,6 @@ contextHelpChanged(tr("Adjust the master playback level")); } else if (w == m_playSpeed) { contextHelpChanged(tr("Adjust the master playback speed")); - } else if (w == m_playSharpen && w->isEnabled()) { - contextHelpChanged(tr("Toggle transient sharpening for playback time scaling")); - } else if (w == m_playMono && w->isEnabled()) { - contextHelpChanged(tr("Toggle mono mode for playback time scaling")); } } @@ -3788,7 +3437,7 @@ void MainWindow::help() { - openHelpUrl(tr("http://www.sonicvisualiser.org/doc/reference/1.0/en/")); + openHelpUrl(tr("http://www.sonicvisualiser.org/doc/reference/1.2/en/")); } void @@ -3815,7 +3464,7 @@ QString aboutText; aboutText += tr("<h3>About Sonic Visualiser</h3>"); - aboutText += tr("<p>Sonic Visualiser is a program for viewing and exploring audio data for<br>semantic music analysis and annotation.</p>"); + aboutText += tr("<p>Sonic Visualiser is a program for viewing and exploring audio data for semantic music analysis and annotation.</p>"); aboutText += tr("<p>%1 : %2 configuration</p>") .arg(version) .arg(debug ? tr("Debug") : tr("Release")); @@ -3897,11 +3546,11 @@ #endif aboutText += - "<p>Sonic Visualiser Copyright © 2005 - 2007 Chris Cannam and<br>" + "<p>Sonic Visualiser Copyright © 2005 - 2008 Chris Cannam and " "Queen Mary, University of London.</p>" - "<p>This program is free software; you can redistribute it and/or<br>" - "modify it under the terms of the GNU General Public License as<br>" - "published by the Free Software Foundation; either version 2 of the<br>" + "<p>This program is free software; you can redistribute it and/or " + "modify it under the terms of the GNU General Public License as " + "published by the Free Software Foundation; either version 2 of the " "License, or (at your option) any later version.<br>See the file " "COPYING included with this distribution for more information.</p>";
--- a/main/MainWindow.h Tue Nov 13 13:51:07 2007 +0000 +++ b/main/MainWindow.h Wed Feb 27 11:59:42 2008 +0000 @@ -31,6 +31,7 @@ #include "framework/SVFileReader.h" #include "data/fileio/FileFinder.h" #include "data/fileio/FileSource.h" +#include "widgets/LayerTreeDialog.h" #include <map> class Document; @@ -99,6 +100,7 @@ virtual void toolSelectSelected(); virtual void toolEditSelected(); virtual void toolDrawSelected(); + virtual void toolEraseSelected(); virtual void toolMeasureSelected(); virtual void documentModified(); @@ -111,11 +113,16 @@ virtual void setInstantsCounterCycle(); virtual void resetInstantsCounters(); - virtual void modelGenerationFailed(QString); - virtual void modelRegenerationFailed(QString, QString); + virtual void modelGenerationFailed(QString, QString); + virtual void modelGenerationWarning(QString, QString); + virtual void modelRegenerationFailed(QString, QString, QString); + virtual void modelRegenerationWarning(QString, QString, QString); + virtual void alignmentFailed(QString, QString); virtual void rightButtonMenuRequested(Pane *, QPoint point); + virtual void propertyStacksResized(int); + virtual void addPane(); virtual void addLayer(); virtual void renameCurrentLayer(); @@ -130,11 +137,11 @@ virtual void setupRecentTransformsMenu(); virtual void playSpeedChanged(int); - virtual void playSharpenToggled(); - virtual void playMonoToggled(); virtual void playSoloToggled(); virtual void alignToggled(); + virtual void currentPaneChanged(Pane *); + virtual void speedUpPlayback(); virtual void slowDownPlayback(); virtual void restoreNormalPlayback(); @@ -163,8 +170,6 @@ Overview *m_overview; Fader *m_fader; AudioDial *m_playSpeed; - QPushButton *m_playSharpen; - QPushButton *m_playMono; WaveformLayer *m_panLayer; bool m_mainMenusCreated; @@ -189,34 +194,37 @@ bool m_soloModified; bool m_prevSolo; + QFrame *m_playControlsSpacer; + int m_playControlsWidth; + QPointer<PreferencesDialog> m_preferencesDialog; - QPointer<QTreeView> m_layerTreeView; + QPointer<LayerTreeDialog> m_layerTreeDialog; KeyReference *m_keyReference; - struct PaneConfiguration { - PaneConfiguration(LayerFactory::LayerType _layer + struct LayerConfiguration { + LayerConfiguration(LayerFactory::LayerType _layer = LayerFactory::TimeRuler, - Model *_source = 0, - int _channel = -1) : + Model *_source = 0, + int _channel = -1) : layer(_layer), sourceModel(_source), channel(_channel) { } LayerFactory::LayerType layer; Model *sourceModel; int channel; }; - typedef std::map<QAction *, PaneConfiguration> PaneActionMap; + typedef std::map<QAction *, LayerConfiguration> PaneActionMap; PaneActionMap m_paneActions; + typedef std::map<QAction *, LayerConfiguration> LayerActionMap; + LayerActionMap m_layerActions; + typedef std::map<QAction *, TransformId> TransformActionMap; TransformActionMap m_transformActions; typedef std::map<TransformId, QAction *> TransformActionReverseMap; TransformActionReverseMap m_transformActionsReverse; - typedef std::map<QAction *, LayerFactory::LayerType> LayerActionMap; - LayerActionMap m_layerActions; - typedef std::map<QAction *, Layer *> ExistingLayerActionMap; ExistingLayerActionMap m_existingLayerActions; ExistingLayerActionMap m_sliceActions; @@ -237,7 +245,7 @@ virtual void setupExistingLayersMenus(); virtual void setupToolbars(); - virtual void addPane(const PaneConfiguration &configuration, QString text); + virtual void addPane(const LayerConfiguration &configuration, QString text); virtual void closeEvent(QCloseEvent *e); virtual bool checkSaveModified();
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/main/OSCHandler.cpp Wed Feb 27 11:59:42 2008 +0000 @@ -0,0 +1,520 @@ +/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */ + +/* + Sonic Visualiser + An audio file viewer and annotation editor. + Centre for Digital Music, Queen Mary, University of London. + This file copyright 2006-2007 Chris Cannam and QMUL. + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. See the file + COPYING included with this distribution for more information. +*/ + +#include "MainWindow.h" +#include "data/osc/OSCQueue.h" + +#include "layer/WaveformLayer.h" +#include "view/ViewManager.h" +#include "view/Pane.h" +#include "view/PaneStack.h" +#include "data/model/WaveFileModel.h" +#include "base/CommandHistory.h" +#include "audioio/AudioCallbackPlaySource.h" +#include "audioio/AudioCallbackPlayTarget.h" +#include "framework/Document.h" +#include "data/fileio/WavFileWriter.h" +#include "plugin/transform/TransformFactory.h" +#include "widgets/Fader.h" +#include "widgets/AudioDial.h" + +#include <QFileInfo> + +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") { + + if (message.getArgCount() == 1 && + message.getArg(0).canConvert(QVariant::String)) { + QString path = message.getArg(0).toString(); + if (open(path, ReplaceMainModel) != FileOpenSucceeded) { + std::cerr << "MainWindow::handleOSCMessage: File open failed for path \"" + << path.toStdString() << "\"" << std::endl; + } + //!!! we really need to spin here and not return until the + // file has been completely decoded... + } + + } else if (message.getMethod() == "openadditional") { + + if (message.getArgCount() == 1 && + message.getArg(0).canConvert(QVariant::String)) { + QString path = message.getArg(0).toString(); + if (open(path, CreateAdditionalModel) != FileOpenSucceeded) { + std::cerr << "MainWindow::handleOSCMessage: File open failed for path \"" + << path.toStdString() << "\"" << std::endl; + } + } + + } else if (message.getMethod() == "recent" || + message.getMethod() == "last") { + + int n = 0; + if (message.getMethod() == "recent" && + message.getArgCount() == 1 && + message.getArg(0).canConvert(QVariant::Int)) { + n = message.getArg(0).toInt() - 1; + } + std::vector<QString> recent = m_recentFiles.getRecent(); + if (n >= 0 && n < int(recent.size())) { + if (open(recent[n], ReplaceMainModel) != FileOpenSucceeded) { + std::cerr << "MainWindow::handleOSCMessage: File open failed for path \"" + << recent[n].toStdString() << "\"" << std::endl; + } + } + + } else if (message.getMethod() == "save") { + + QString path; + if (message.getArgCount() == 1 && + message.getArg(0).canConvert(QVariant::String)) { + path = message.getArg(0).toString(); + if (QFileInfo(path).exists()) { + std::cerr << "MainWindow::handleOSCMessage: Refusing to overwrite existing file in save" << std::endl; + } else { + saveSessionFile(path); + } + } + + } else if (message.getMethod() == "export") { + + QString path; + if (getMainModel()) { + if (message.getArgCount() == 1 && + message.getArg(0).canConvert(QVariant::String)) { + path = message.getArg(0).toString(); + if (QFileInfo(path).exists()) { + std::cerr << "MainWindow::handleOSCMessage: Refusing to overwrite existing file in export" << std::endl; + } else { + WavFileWriter writer(path, + getMainModel()->getSampleRate(), + getMainModel()->getChannelCount()); + MultiSelection ms = m_viewManager->getSelection(); + if (!ms.getSelections().empty()) { + writer.writeModel(getMainModel(), &ms); + } else { + writer.writeModel(getMainModel()); + } + } + } + } + + } else if (message.getMethod() == "jump" || + message.getMethod() == "play") { + + if (getMainModel()) { + + unsigned long frame = m_viewManager->getPlaybackFrame(); + bool selection = false; + bool play = (message.getMethod() == "play"); + + if (message.getArgCount() == 1) { + + if (message.getArg(0).canConvert(QVariant::String) && + message.getArg(0).toString() == "selection") { + + selection = true; + + } else if (message.getArg(0).canConvert(QVariant::String) && + message.getArg(0).toString() == "end") { + + frame = getMainModel()->getEndFrame(); + + } else if (message.getArg(0).canConvert(QVariant::Double)) { + + double time = message.getArg(0).toDouble(); + if (time < 0.0) time = 0.0; + + frame = lrint(time * getMainModel()->getSampleRate()); + } + } + + if (frame > getMainModel()->getEndFrame()) { + frame = getMainModel()->getEndFrame(); + } + + if (play) { + m_viewManager->setPlaySelectionMode(selection); + } + + if (selection) { + MultiSelection::SelectionList sl = m_viewManager->getSelections(); + if (!sl.empty()) { + frame = sl.begin()->getStartFrame(); + } + } + + m_viewManager->setPlaybackFrame(frame); + + if (play && !m_playSource->isPlaying()) { + m_playSource->play(frame); + } + } + + } else if (message.getMethod() == "stop") { + + if (m_playSource->isPlaying()) m_playSource->stop(); + + } else if (message.getMethod() == "loop") { + + if (message.getArgCount() == 1 && + message.getArg(0).canConvert(QVariant::String)) { + + QString str = message.getArg(0).toString(); + if (str == "on") { + m_viewManager->setPlayLoopMode(true); + } else if (str == "off") { + m_viewManager->setPlayLoopMode(false); + } + } + + } else if (message.getMethod() == "solo") { + + if (message.getArgCount() == 1 && + message.getArg(0).canConvert(QVariant::String)) { + + QString str = message.getArg(0).toString(); + if (str == "on") { + m_viewManager->setPlaySoloMode(true); + } else if (str == "off") { + m_viewManager->setPlaySoloMode(false); + } + } + + } else if (message.getMethod() == "select" || + message.getMethod() == "addselect") { + + if (getMainModel()) { + + int f0 = getMainModel()->getStartFrame(); + int f1 = getMainModel()->getEndFrame(); + + bool done = false; + + if (message.getArgCount() == 2 && + message.getArg(0).canConvert(QVariant::Double) && + message.getArg(1).canConvert(QVariant::Double)) { + + double t0 = message.getArg(0).toDouble(); + double t1 = message.getArg(1).toDouble(); + if (t1 < t0) { double temp = t0; t0 = t1; t1 = temp; } + if (t0 < 0.0) t0 = 0.0; + if (t1 < 0.0) t1 = 0.0; + + f0 = lrint(t0 * getMainModel()->getSampleRate()); + f1 = lrint(t1 * getMainModel()->getSampleRate()); + + Pane *pane = m_paneStack->getCurrentPane(); + Layer *layer = 0; + if (pane) layer = pane->getSelectedLayer(); + if (layer) { + size_t resolution; + layer->snapToFeatureFrame(pane, f0, resolution, + Layer::SnapLeft); + layer->snapToFeatureFrame(pane, f1, resolution, + Layer::SnapRight); + } + + } else if (message.getArgCount() == 1 && + message.getArg(0).canConvert(QVariant::String)) { + + QString str = message.getArg(0).toString(); + if (str == "none") { + m_viewManager->clearSelections(); + done = true; + } + } + + if (!done) { + if (message.getMethod() == "select") { + m_viewManager->setSelection(Selection(f0, f1)); + } else { + m_viewManager->addSelection(Selection(f0, f1)); + } + } + } + + } else if (message.getMethod() == "add") { + + if (getMainModel()) { + + if (message.getArgCount() >= 1 && + message.getArg(0).canConvert(QVariant::String)) { + + int channel = -1; + if (message.getArgCount() == 2 && + message.getArg(0).canConvert(QVariant::Int)) { + channel = message.getArg(0).toInt(); + if (channel < -1 || + channel > int(getMainModel()->getChannelCount())) { + std::cerr << "WARNING: MainWindow::handleOSCMessage: channel " + << channel << " out of range" << std::endl; + channel = -1; + } + } + + QString str = message.getArg(0).toString(); + + LayerFactory::LayerType type = + LayerFactory::getInstance()->getLayerTypeForName(str); + + if (type == LayerFactory::UnknownLayer) { + std::cerr << "WARNING: MainWindow::handleOSCMessage: unknown layer " + << "type " << str.toStdString() << std::endl; + } else { + + LayerConfiguration configuration(type, + getMainModel(), + channel); + + addPane(configuration, + tr("Add %1 Pane") + .arg(LayerFactory::getInstance()-> + getLayerPresentationName(type))); + } + } + } + + } else if (message.getMethod() == "undo") { + + CommandHistory::getInstance()->undo(); + + } else if (message.getMethod() == "redo") { + + CommandHistory::getInstance()->redo(); + + } else if (message.getMethod() == "set") { + + if (message.getArgCount() == 2 && + message.getArg(0).canConvert(QVariant::String) && + message.getArg(1).canConvert(QVariant::Double)) { + + QString property = message.getArg(0).toString(); + float value = (float)message.getArg(1).toDouble(); + + if (property == "gain") { + if (value < 0.0) value = 0.0; + m_fader->setValue(value); + if (m_playTarget) m_playTarget->setOutputGain(value); + } else if (property == "speedup") { + m_playSpeed->setMappedValue(value); + } else if (property == "overlays") { + if (value < 0.5) { + m_viewManager->setOverlayMode(ViewManager::NoOverlays); + } else if (value < 1.5) { + m_viewManager->setOverlayMode(ViewManager::MinimalOverlays); + } else if (value < 2.5) { + m_viewManager->setOverlayMode(ViewManager::StandardOverlays); + } else { + m_viewManager->setOverlayMode(ViewManager::AllOverlays); + } + } else if (property == "zoomwheels") { + m_viewManager->setZoomWheelsEnabled(value > 0.5); + } else if (property == "propertyboxes") { + bool toggle = ((value < 0.5) != + (m_paneStack->getLayoutStyle() == PaneStack::NoPropertyStacks)); + if (toggle) togglePropertyBoxes(); + } + + } 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); + } + } + + } else if (message.getMethod() == "setcurrent") { + + int paneIndex = -1, layerIndex = -1; + bool wantLayer = false; + + if (message.getArgCount() >= 1 && + message.getArg(0).canConvert(QVariant::Int)) { + + paneIndex = message.getArg(0).toInt() - 1; + + if (message.getArgCount() >= 2 && + message.getArg(1).canConvert(QVariant::Int)) { + wantLayer = true; + layerIndex = message.getArg(1).toInt() - 1; + } + } + + 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 if (message.getMethod() == "delete") { + + if (message.getArgCount() == 1 && + message.getArg(0).canConvert(QVariant::String)) { + + QString target = message.getArg(0).toString(); + + if (target == "pane") { + + deleteCurrentPane(); + + } else if (target == "layer") { + + deleteCurrentLayer(); + + } else { + + std::cerr << "WARNING: MainWindow::handleOSCMessage: Unknown delete target " << target.toStdString() << std::endl; + } + } + + } else if (message.getMethod() == "zoom") { + + if (message.getArgCount() == 1) { + if (message.getArg(0).canConvert(QVariant::String) && + message.getArg(0).toString() == "in") { + zoomIn(); + } else if (message.getArg(0).canConvert(QVariant::String) && + message.getArg(0).toString() == "out") { + zoomOut(); + } else if (message.getArg(0).canConvert(QVariant::String) && + message.getArg(0).toString() == "default") { + zoomDefault(); + } else if (message.getArg(0).canConvert(QVariant::Double)) { + double level = message.getArg(0).toDouble(); + Pane *currentPane = m_paneStack->getCurrentPane(); + if (level < 1.0) level = 1.0; + if (currentPane) currentPane->setZoomLevel(lrint(level)); + } + } + + } else if (message.getMethod() == "zoomvertical") { + + Pane *pane = m_paneStack->getCurrentPane(); + Layer *layer = 0; + if (pane && pane->getLayerCount() > 0) { + layer = pane->getLayer(pane->getLayerCount() - 1); + } + int defaultStep = 0; + int steps = 0; + if (layer) { + steps = layer->getVerticalZoomSteps(defaultStep); + if (message.getArgCount() == 1 && steps > 0) { + if (message.getArg(0).canConvert(QVariant::String) && + message.getArg(0).toString() == "in") { + int step = layer->getCurrentVerticalZoomStep() + 1; + if (step < steps) layer->setVerticalZoomStep(step); + } else if (message.getArg(0).canConvert(QVariant::String) && + message.getArg(0).toString() == "out") { + int step = layer->getCurrentVerticalZoomStep() - 1; + if (step >= 0) layer->setVerticalZoomStep(step); + } else if (message.getArg(0).canConvert(QVariant::String) && + message.getArg(0).toString() == "default") { + layer->setVerticalZoomStep(defaultStep); + } + } else if (message.getArgCount() == 2) { + if (message.getArg(0).canConvert(QVariant::Double) && + message.getArg(1).canConvert(QVariant::Double)) { + double min = message.getArg(0).toDouble(); + double max = message.getArg(1).toDouble(); + layer->setDisplayExtents(min, max); + } + } + } + + } 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)) { + + TransformId transformId = message.getArg(0).toString(); + + Transform transform = TransformFactory::getInstance()-> + getDefaultTransformFor(transformId); + + Layer *newLayer = m_document->createDerivedLayer + (transform, getMainModel()); + + if (newLayer) { + m_document->addLayerToView(pane, newLayer); + m_recentTransforms.add(transformId); + m_paneStack->setCurrentLayer(pane, newLayer); + } + } + + } else { + std::cerr << "WARNING: MainWindow::handleOSCMessage: Unknown or unsupported " + << "method \"" << message.getMethod().toStdString() + << "\"" << std::endl; + } + +}
--- a/main/PreferencesDialog.cpp Tue Nov 13 13:51:07 2007 +0000 +++ b/main/PreferencesDialog.cpp Wed Feb 27 11:59:42 2008 +0000 @@ -30,6 +30,7 @@ #include <QLineEdit> #include <QFileDialog> #include <QMessageBox> +#include <QSpinBox> #include "widgets/WindowTypeSelector.h" #include "widgets/IconLoader.h" @@ -144,6 +145,13 @@ this, SLOT(tempDirButtonClicked())); tempDirButton->setFixedSize(QSize(24, 24)); + QCheckBox *showSplash = new QCheckBox; + m_showSplash = prefs->getShowSplash(); + showSplash->setCheckState(m_showSplash ? Qt::Checked : Qt::Unchecked); + connect(showSplash, SIGNAL(stateChanged(int)), + this, SLOT(showSplashChanged(int))); + +#ifndef Q_WS_MAC QComboBox *bgMode = new QComboBox; int bg = prefs->getPropertyRangeAndValue("Background Mode", &min, &max, &deflt); @@ -155,6 +163,20 @@ connect(bgMode, SIGNAL(currentIndexChanged(int)), this, SLOT(backgroundModeChanged(int))); +#endif + + QSpinBox *fontSize = new QSpinBox; + int fs = prefs->getPropertyRangeAndValue("View Font Size", &min, &max, + &deflt); + m_viewFontSize = fs; + fontSize->setMinimum(min); + fontSize->setMaximum(max); + fontSize->setSuffix(" pt"); + fontSize->setSingleStep(1); + fontSize->setValue(fs); + + connect(fontSize, SIGNAL(valueChanged(int)), + this, SLOT(viewFontSizeChanged(int))); // General tab @@ -170,10 +192,29 @@ row, 0); subgrid->addWidget(propertyLayout, row++, 1, 1, 2); +#ifndef Q_WS_MAC subgrid->addWidget(new QLabel(tr("%1:").arg(prefs->getPropertyLabel ("Background Mode"))), row, 0); subgrid->addWidget(bgMode, row++, 1, 1, 2); +#endif + + subgrid->addWidget(new QLabel(tr("%1:").arg(prefs->getPropertyLabel + ("View Font Size"))), + row, 0); + subgrid->addWidget(fontSize, row++, 1, 1, 2); + + subgrid->addWidget(new QLabel(tr("%1:").arg(prefs->getPropertyLabel + ("Show Splash Screen"))), + row, 0); + subgrid->addWidget(showSplash, row++, 1, 1, 1); + + subgrid->addWidget(new QLabel(tr("%1:").arg(prefs->getPropertyLabel + ("Temporary Directory Root"))), + row, 0); + subgrid->addWidget(m_tempDirRootEdit, row, 1, 1, 1); + subgrid->addWidget(tempDirButton, row, 2, 1, 1); + row++; subgrid->addWidget(new QLabel(tr("%1:").arg(prefs->getPropertyLabel ("Resample On Load"))), @@ -185,13 +226,6 @@ row, 0); subgrid->addWidget(resampleQuality, row++, 1, 1, 2); - subgrid->addWidget(new QLabel(tr("%1:").arg(prefs->getPropertyLabel - ("Temporary Directory Root"))), - row, 0); - subgrid->addWidget(m_tempDirRootEdit, row, 1, 1, 1); - subgrid->addWidget(tempDirButton, row, 2, 1, 1); - row++; - subgrid->setRowStretch(row, 10); tab->addTab(frame, tr("&General")); @@ -288,6 +322,14 @@ } void +PreferencesDialog::showSplashChanged(int state) +{ + m_showSplash = (state == Qt::Checked); + m_applyButton->setEnabled(true); + m_changesOnRestart = true; +} + +void PreferencesDialog::tempDirRootChanged(QString r) { m_tempDirRoot = r; @@ -315,6 +357,13 @@ } void +PreferencesDialog::viewFontSizeChanged(int sz) +{ + m_viewFontSize = sz; + m_applyButton->setEnabled(true); +} + +void PreferencesDialog::okClicked() { applyClicked(); @@ -333,8 +382,10 @@ prefs->setTuningFrequency(m_tuningFrequency); prefs->setResampleQuality(m_resampleQuality); prefs->setResampleOnLoad(m_resampleOnLoad); + prefs->setShowSplash(m_showSplash); prefs->setTemporaryDirectoryRoot(m_tempDirRoot); prefs->setBackgroundMode(Preferences::BackgroundMode(m_backgroundMode)); + prefs->setViewFontSize(m_viewFontSize); m_applyButton->setEnabled(false);
--- a/main/PreferencesDialog.h Tue Nov 13 13:51:07 2007 +0000 +++ b/main/PreferencesDialog.h Wed Feb 27 11:59:42 2008 +0000 @@ -44,6 +44,8 @@ void resampleOnLoadChanged(int state); void tempDirRootChanged(QString root); void backgroundModeChanged(int mode); + void viewFontSizeChanged(int sz); + void showSplashChanged(int state); void tempDirButtonClicked(); @@ -65,6 +67,8 @@ bool m_resampleOnLoad; QString m_tempDirRoot; int m_backgroundMode; + int m_viewFontSize; + bool m_showSplash; bool m_changesOnRestart; };
--- a/main/main.cpp Tue Nov 13 13:51:07 2007 +0000 +++ b/main/main.cpp Wed Feb 27 11:59:42 2008 +0000 @@ -32,6 +32,7 @@ #include <QIcon> #include <QSessionManager> #include <QDir> +#include <QSplashScreen> #include <iostream> #include <signal.h> @@ -53,7 +54,11 @@ Document, SVFileReader - Turning one model (e.g. audio) into another (e.g. more audio, or a - curve extracted from it): Transform and subclasses + curve extracted from it): Transform, encapsulating the data that need + to be stored to be able to reproduce a given transformation; + TransformFactory, for discovering the available types of transform; + ModelTransformerFactory, ModelTransformer and subclasses, providing + the mechanisms for applying transforms to data models - Creating the plugins used by transforms: RealTimePluginFactory, FeatureExtractionPluginFactory. See also the API documentation for @@ -229,6 +234,18 @@ QApplication::setOrganizationDomain("sonicvisualiser.org"); QApplication::setApplicationName(QApplication::tr("Sonic Visualiser")); + QPixmap pixmap(":/icons/sv-splash.png"); + QSplashScreen splash(pixmap); + + QSettings settings; + + settings.beginGroup("Preferences"); + if (settings.value("show-splash", true).toBool()) { + splash.show(); + application.processEvents(); + } + settings.endGroup(); + QIcon icon; int sizes[] = { 16, 22, 24, 32, 48, 64, 128 }; for (int i = 0; i < sizeof(sizes)/sizeof(sizes[0]); ++i) { @@ -266,8 +283,8 @@ qRegisterMetaType<size_t>("size_t"); qRegisterMetaType<PropertyContainer::PropertyName>("PropertyContainer::PropertyName"); - MainWindow gui(audioOutput, oscSupport); - application.setMainWindow(&gui); + MainWindow *gui = new MainWindow(audioOutput, oscSupport); + application.setMainWindow(gui); QDesktopWidget *desktop = QApplication::desktop(); QRect available = desktop->availableGeometry(); @@ -277,21 +294,20 @@ if (height < 450) height = available.height() * 2 / 3; if (width > height * 2) width = height * 2; - QSettings settings; settings.beginGroup("MainWindow"); QSize size = settings.value("size", QSize(width, height)).toSize(); - gui.resize(size); + gui->resize(size); if (settings.contains("position")) { - gui.move(settings.value("position").toPoint()); + gui->move(settings.value("position").toPoint()); } settings.endGroup(); - gui.show(); + gui->show(); // The MainWindow class seems to have trouble dealing with this if // it tries to adapt to this preference before the constructor is // complete. As a lazy hack, apply it explicitly from here - gui.preferenceChanged("Property Box Layout"); + gui->preferenceChanged("Property Box Layout"); bool haveSession = false; bool haveMainModel = false; @@ -308,7 +324,7 @@ if (path.endsWith("sv")) { if (!haveSession) { - status = gui.openSessionFile(path); + status = gui->openSessionFile(path); if (status == MainWindow::FileOpenSucceeded) { haveSession = true; haveMainModel = true; @@ -320,24 +336,24 @@ } if (status != MainWindow::FileOpenSucceeded) { if (!haveMainModel) { - status = gui.open(path, MainWindow::ReplaceMainModel); + status = gui->open(path, MainWindow::ReplaceMainModel); if (status == MainWindow::FileOpenSucceeded) { haveMainModel = true; } } else { if (haveSession && !havePriorCommandLineModel) { - status = gui.open(path, MainWindow::AskUser); + status = gui->open(path, MainWindow::AskUser); if (status == MainWindow::FileOpenSucceeded) { havePriorCommandLineModel = true; } } else { - status = gui.open(path, MainWindow::CreateAdditionalModel); + status = gui->open(path, MainWindow::CreateAdditionalModel); } } } if (status == MainWindow::FileOpenFailed) { QMessageBox::critical - (&gui, QMessageBox::tr("Failed to open file"), + (gui, QMessageBox::tr("Failed to open file"), QMessageBox::tr("File or URL \"%1\" could not be opened").arg(path)); } } @@ -351,6 +367,7 @@ settings.endGroup(); #endif + splash.finish(gui); /* TipDialog tipDialog; @@ -359,10 +376,11 @@ } */ int rv = application.exec(); -// std::cerr << "application.exec() returned " << rv << std::endl; + std::cerr << "application.exec() returned " << rv << std::endl; cleanupMutex.lock(); TempDirectory::getInstance()->cleanup(); + application.releaseMainWindow(); #ifdef HAVE_FFTW3F @@ -375,5 +393,7 @@ } #endif + delete gui; + return rv; }
--- a/sonic-visualiser.qrc Tue Nov 13 13:51:07 2007 +0000 +++ b/sonic-visualiser.qrc Wed Feb 27 11:59:42 2008 +0000 @@ -28,6 +28,7 @@ <file>icons/text.png</file> <file>icons/draw.png</file> <file>icons/draw-curve.png</file> + <file>icons/erase.png</file> <file>icons/measure.png</file> <file>icons/measure1cursor.xbm</file> <file>icons/measure1mask.xbm</file> @@ -66,6 +67,10 @@ <file>icons/help.png</file> <file>icons/emptypage.png</file> <file>icons/cross.png</file> + <file>icons/normalise.png</file> + <file>icons/normalise-columns.png</file> + <file>icons/invert-vertical.png</file> + <file>icons/show-peaks.png</file> <file>icons/sv-16x16.png</file> <file>icons/sv-22x22.png</file> <file>icons/sv-24x24.png</file> @@ -73,6 +78,7 @@ <file>icons/sv-48x48.png</file> <file>icons/sv-64x64.png</file> <file>icons/sv-128x128.png</file> + <file>icons/sv-splash.png</file> <file>samples/bass.wav</file> <file>samples/beep.wav</file> <file>samples/bounce.wav</file>
--- a/sv.pro Tue Nov 13 13:51:07 2007 +0000 +++ b/sv.pro Wed Feb 27 11:59:42 2008 +0000 @@ -1,7 +1,7 @@ TEMPLATE = app -SV_UNIT_PACKAGES = vamp vamp-hostsdk fftw3f samplerate jack portaudio mad id3tag oggz fishsound lrdf raptor sndfile liblo +SV_UNIT_PACKAGES = vamp vamp-hostsdk rubberband fftw3 fftw3f samplerate jack portaudio mad id3tag oggz fishsound lrdf raptor sndfile liblo load(../sv.prf) CONFIG += sv qt thread warn_on stl rtti exceptions @@ -36,6 +36,7 @@ HEADERS += main/MainWindow.h \ main/PreferencesDialog.h SOURCES += main/main.cpp \ + main/OSCHandler.cpp \ main/MainWindow.cpp \ main/PreferencesDialog.cpp RESOURCES += sonic-visualiser.qrc