[Sv1-commits] SF.net SVN: sv1: [683] sonic-visualiser/trunk
Brought to you by:
cannam
From: <ca...@us...> - 2007-06-28 14:51:04
|
Revision: 683 http://svn.sourceforge.net/sv1/?rev=683&view=rev Author: cannam Date: 2007-06-28 07:50:58 -0700 (Thu, 28 Jun 2007) Log Message: ----------- * Change a number of keyboard shortcuts -- get rid of all the Alt+ shortcuts and introduce a few more Ctrl+ ones instead, as well as a number of plain single keypresses * Add Playback menu * Add time-ruler support for snap to feature, use it in ffwd/rewind (rewind still needs fixing) * restore layer hierarchy window prior to making it work correctly Modified Paths: -------------- sonic-visualiser/trunk/layer/TimeRulerLayer.cpp sonic-visualiser/trunk/layer/TimeRulerLayer.h sonic-visualiser/trunk/sv/audioio/PhaseVocoderTimeStretcher.cpp sonic-visualiser/trunk/sv/main/MainWindow.cpp sonic-visualiser/trunk/sv/main/MainWindow.h sonic-visualiser/trunk/view/PaneStack.cpp sonic-visualiser/trunk/view/PaneStack.h sonic-visualiser/trunk/view/ViewManager.cpp sonic-visualiser/trunk/view/ViewManager.h sonic-visualiser/trunk/widgets/AudioDial.h sonic-visualiser/trunk/widgets/LayerTree.cpp Modified: sonic-visualiser/trunk/layer/TimeRulerLayer.cpp =================================================================== --- sonic-visualiser/trunk/layer/TimeRulerLayer.cpp 2007-06-26 14:57:29 UTC (rev 682) +++ sonic-visualiser/trunk/layer/TimeRulerLayer.cpp 2007-06-28 14:50:58 UTC (rev 683) @@ -22,6 +22,7 @@ #include <QPainter> #include <iostream> +#include <cmath> using std::cerr; using std::endl; @@ -133,57 +134,130 @@ } } -void -TimeRulerLayer::paint(View *v, QPainter &paint, QRect rect) const +bool +TimeRulerLayer::snapToFeatureFrame(View *v, int &frame, + size_t &resolution, SnapType snap) const { -// std::cerr << "TimeRulerLayer::paint (" << rect.x() << "," << rect.y() -// << ") [" << rect.width() << "x" << rect.height() << "]" << std::endl; + if (!m_model) { + resolution = 1; + return false; + } + + bool q; + int tick = getMajorTickSpacing(v, q); + RealTime rtick = RealTime::fromMilliseconds(tick); + int rate = m_model->getSampleRate(); - if (!m_model || !m_model->isOK()) return; + RealTime rt = RealTime::frame2RealTime(frame, rate); + double ratio = rt / rtick; + int rounded = lrint(ratio); + RealTime rdrt = rtick * rounded; + + int left = RealTime::realTime2Frame(rdrt, rate); + resolution = RealTime::realTime2Frame(rtick, rate); + int right = left + resolution; + + switch (snap) { + + case SnapLeft: + frame = left; + break; + + case SnapRight: + frame = right; + break; + + case SnapNearest: + { + if (abs(frame - left) > abs(right - frame)) { + frame = right; + } else { + frame = left; + } + break; + } + + case SnapNeighbouring: + { + int dl = -1, dr = -1; + int x = v->getXForFrame(frame); + + if (left > v->getStartFrame() && + left < v->getEndFrame()) { + dl = abs(v->getXForFrame(left) - x); + } + + if (right > v->getStartFrame() && + right < v->getEndFrame()) { + dr = abs(v->getXForFrame(right) - x); + } + + int fuzz = 2; + + if (dl >= 0 && dr >= 0) { + if (dl < dr) { + if (dl <= fuzz) { + frame = left; + } + } else { + if (dr < fuzz) { + frame = right; + } + } + } else if (dl >= 0) { + if (dl <= fuzz) { + frame = left; + } + } else if (dr >= 0) { + if (dr <= fuzz) { + frame = right; + } + } + } + } + + return true; +} + +int +TimeRulerLayer::getMajorTickSpacing(View *v, bool &quarterTicks) const +{ + // return value is in milliseconds + + if (!m_model || !v) return 1000; + int sampleRate = m_model->getSampleRate(); - if (!sampleRate) return; + if (!sampleRate) return 1000; long startFrame = v->getStartFrame(); long endFrame = v->getEndFrame(); - int zoomLevel = v->getZoomLevel(); - - long rectStart = startFrame + (rect.x() - 100) * zoomLevel; - long rectEnd = startFrame + (rect.x() + rect.width() + 100) * zoomLevel; -// if (rectStart < startFrame) rectStart = startFrame; -// if (rectEnd > endFrame) rectEnd = endFrame; - -// std::cerr << "TimeRulerLayer::paint: calling paint.save()" << std::endl; - paint.save(); -//!!! paint.setClipRect(v->rect()); - int minPixelSpacing = 50; RealTime rtStart = RealTime::frame2RealTime(startFrame, sampleRate); RealTime rtEnd = RealTime::frame2RealTime(endFrame, sampleRate); -// cerr << "startFrame " << startFrame << ", endFrame " << v->getEndFrame() << ", rtStart " << rtStart << ", rtEnd " << rtEnd << endl; + int count = v->width() / minPixelSpacing; if (count < 1) count = 1; RealTime rtGap = (rtEnd - rtStart) / count; -// cerr << "rtGap is " << rtGap << endl; int incms; - bool quarter = false; + quarterTicks = false; if (rtGap.sec > 0) { incms = 1000; int s = rtGap.sec; if (s > 0) { incms *= 5; s /= 5; } if (s > 0) { incms *= 2; s /= 2; } - if (s > 0) { incms *= 6; s /= 6; quarter = true; } - if (s > 0) { incms *= 5; s /= 5; quarter = false; } + if (s > 0) { incms *= 6; s /= 6; quarterTicks = true; } + if (s > 0) { incms *= 5; s /= 5; quarterTicks = false; } if (s > 0) { incms *= 2; s /= 2; } - if (s > 0) { incms *= 6; s /= 6; quarter = true; } + if (s > 0) { incms *= 6; s /= 6; quarterTicks = true; } while (s > 0) { incms *= 10; s /= 10; - quarter = false; + quarterTicks = false; } } else { incms = 1; @@ -193,8 +267,38 @@ if (ms > 0) { incms *= 5; ms /= 5; } if (ms > 0) { incms *= 2; ms /= 2; } } -// cerr << "incms is " << incms << endl; + return incms; +} + +void +TimeRulerLayer::paint(View *v, QPainter &paint, QRect rect) const +{ +// std::cerr << "TimeRulerLayer::paint (" << rect.x() << "," << rect.y() +// << ") [" << rect.width() << "x" << rect.height() << "]" << std::endl; + + if (!m_model || !m_model->isOK()) return; + + int sampleRate = m_model->getSampleRate(); + if (!sampleRate) return; + + long startFrame = v->getStartFrame(); + long endFrame = v->getEndFrame(); + + int zoomLevel = v->getZoomLevel(); + + long rectStart = startFrame + (rect.x() - 100) * zoomLevel; + long rectEnd = startFrame + (rect.x() + rect.width() + 100) * zoomLevel; + +// std::cerr << "TimeRulerLayer::paint: calling paint.save()" << std::endl; + paint.save(); +//!!! paint.setClipRect(v->rect()); + + int minPixelSpacing = 50; + + bool quarter = false; + int incms = getMajorTickSpacing(v, quarter); + RealTime rt = RealTime::frame2RealTime(rectStart, sampleRate); long ms = rt.sec * 1000 + rt.msec(); ms = (ms / incms) * incms - incms; Modified: sonic-visualiser/trunk/layer/TimeRulerLayer.h =================================================================== --- sonic-visualiser/trunk/layer/TimeRulerLayer.h 2007-06-26 14:57:29 UTC (rev 682) +++ sonic-visualiser/trunk/layer/TimeRulerLayer.h 2007-06-28 14:50:58 UTC (rev 683) @@ -44,6 +44,8 @@ void setLabelHeight(LabelHeight h) { m_labelHeight = h; } LabelHeight getLabelHeight() const { return m_labelHeight; } + virtual bool snapToFeatureFrame(View *, int &, size_t &, SnapType) const; + virtual PropertyList getProperties() const; virtual QString getPropertyLabel(const PropertyName &) const; virtual PropertyType getPropertyType(const PropertyName &) const; @@ -66,6 +68,8 @@ Model *m_model; QColor m_colour; LabelHeight m_labelHeight; + + int getMajorTickSpacing(View *, bool &quarterTicks) const; }; #endif Modified: sonic-visualiser/trunk/sv/audioio/PhaseVocoderTimeStretcher.cpp =================================================================== --- sonic-visualiser/trunk/sv/audioio/PhaseVocoderTimeStretcher.cpp 2007-06-26 14:57:29 UTC (rev 682) +++ sonic-visualiser/trunk/sv/audioio/PhaseVocoderTimeStretcher.cpp 2007-06-28 14:50:58 UTC (rev 683) @@ -545,7 +545,7 @@ isTransient = true; - std::cerr << "isTransient (count = " << count << ", prev = " << m_prevTransientScore << ", diff = " << count - m_prevTransientScore << ", ratio = " << (m_totalCount > 0 ? (float (m_n2sum) / float(m_totalCount * m_n1)) : 1.f) << ", ideal = " << m_ratio << ")" << std::endl; +// std::cerr << "isTransient (count = " << count << ", prev = " << m_prevTransientScore << ", diff = " << count - m_prevTransientScore << ", ratio = " << (m_totalCount > 0 ? (float (m_n2sum) / float(m_totalCount * m_n1)) : 1.f) << ", ideal = " << m_ratio << ")" << std::endl; // } else { // std::cerr << " !transient (count = " << count << ", prev = " << m_prevTransientScore << ", diff = " << count - m_prevTransientScore << ")" << std::endl; } Modified: sonic-visualiser/trunk/sv/main/MainWindow.cpp =================================================================== --- sonic-visualiser/trunk/sv/main/MainWindow.cpp 2007-06-26 14:57:29 UTC (rev 682) +++ sonic-visualiser/trunk/sv/main/MainWindow.cpp 2007-06-28 14:50:58 UTC (rev 683) @@ -117,6 +117,7 @@ m_paneMenu(0), m_layerMenu(0), m_transformsMenu(0), + m_playbackMenu(0), m_existingLayersMenu(0), m_sliceMenu(0), m_recentFilesMenu(0), @@ -124,6 +125,9 @@ m_rightButtonMenu(0), m_rightButtonLayerMenu(0), m_rightButtonTransformsMenu(0), + m_rightButtonPlaybackMenu(0), + m_ffwdAction(0), + m_rwdAction(0), m_documentModified(false), m_openingAudioFile(false), m_abandoning(false), @@ -290,6 +294,7 @@ setupMenus(); setupToolbars(); + setupHelpMenu(); statusBar(); @@ -407,7 +412,6 @@ setupViewMenu(); setupPaneAndLayerMenus(); setupTransformsMenu(); - setupHelpMenu(); m_mainMenusCreated = true; } @@ -530,16 +534,6 @@ connect(action, SIGNAL(triggered()), this, SLOT(preferences())); menu->addAction(action); - /*!!! - menu->addSeparator(); - - action = new QAction(tr("Play / Pause"), this); - action->setShortcut(tr("Space")); - action->setStatusTip(tr("Start or stop playback from the current position")); - connect(action, SIGNAL(triggered()), this, SLOT(play())); - menu->addAction(action); - */ - menu->addSeparator(); action = new QAction(QIcon(":/icons/exit.png"), tr("&Quit"), this); @@ -719,6 +713,7 @@ action = new QAction(QIcon(":/icons/zoom-fit.png"), tr("Zoom to &Fit"), this); + action->setShortcut(tr("F")); action->setStatusTip(tr("Zoom to show the whole file")); connect(action, SIGNAL(triggered()), this, SLOT(zoomToFit())); connect(this, SIGNAL(canZoom(bool)), action, SLOT(setEnabled(bool))); @@ -798,16 +793,13 @@ } settings.endGroup(); -/*!!! This one doesn't work properly yet - menu->addSeparator(); action = new QAction(tr("Show La&yer Hierarchy"), this); - action->setShortcut(tr("Alt+L")); + action->setShortcut(tr("H")); action->setStatusTip(tr("Open a window displaying the hierarchy of panes and layers in this session")); connect(action, SIGNAL(triggered()), this, SLOT(showLayerTree())); menu->addAction(action); - */ } void @@ -832,7 +824,7 @@ QMenu *menu = m_paneMenu; QAction *action = new QAction(QIcon(":/icons/pane.png"), tr("Add &New Pane"), this); - action->setShortcut(tr("Alt+N")); + action->setShortcut(tr("N")); 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))); @@ -866,7 +858,7 @@ action->setStatusTip(tipText); if (type == LayerFactory::Text) { - action->setShortcut(tr("Alt+T")); + action->setShortcut(tr("T")); } connect(action, SIGNAL(triggered()), this, SLOT(addLayer())); @@ -915,7 +907,7 @@ icon = QIcon(":/icons/waveform.png"); mainText = tr("Add &Waveform"); if (menuType == 0) { - shortcutText = tr("Alt+W"); + shortcutText = tr("W"); tipText = tr("Add a new pane showing a waveform view"); } else { tipText = tr("Add a new layer showing a waveform view"); @@ -927,7 +919,7 @@ icon = QIcon(":/icons/spectrogram.png"); mainText = tr("Add &Spectrogram"); if (menuType == 0) { - shortcutText = tr("Alt+S"); + shortcutText = tr("G"); tipText = tr("Add a new pane showing a spectrogram"); } else { tipText = tr("Add a new layer showing a spectrogram"); @@ -938,7 +930,7 @@ icon = QIcon(":/icons/spectrogram.png"); mainText = tr("Add &Melodic Range Spectrogram"); if (menuType == 0) { - shortcutText = tr("Alt+M"); + shortcutText = tr("M"); tipText = tr("Add a new pane showing a spectrogram set up for an overview of note pitches"); } else { tipText = tr("Add a new layer showing a spectrogram set up for an overview of note pitches"); @@ -947,9 +939,9 @@ case LayerFactory::PeakFrequencySpectrogram: icon = QIcon(":/icons/spectrogram.png"); - mainText = tr("Add &Peak Frequency Spectrogram"); + mainText = tr("Add Pea&k Frequency Spectrogram"); if (menuType == 0) { - shortcutText = tr("Alt+P"); + shortcutText = tr("K"); tipText = tr("Add a new pane showing a spectrogram set up for tracking frequencies"); } else { tipText = tr("Add a new layer showing a spectrogram set up for tracking frequencies"); @@ -960,7 +952,7 @@ icon = QIcon(":/icons/spectrum.png"); mainText = tr("Add Spectr&um"); if (menuType == 0) { - shortcutText = tr("Alt+U"); + shortcutText = tr("U"); tipText = tr("Add a new pane showing a frequency spectrum"); } else { tipText = tr("Add a new layer showing a frequency spectrum"); @@ -1094,7 +1086,7 @@ menu->addSeparator(); action = new QAction(QIcon(":/icons/editdelete.png"), tr("&Delete Pane"), this); - action->setShortcut(tr("Alt+D")); + action->setShortcut(tr("Ctrl+Shift+D")); action->setStatusTip(tr("Delete the currently active pane")); connect(action, SIGNAL(triggered()), this, SLOT(deleteCurrentPane())); connect(this, SIGNAL(canDeleteCurrentPane(bool)), action, SLOT(setEnabled(bool))); @@ -1125,7 +1117,7 @@ menu->addSeparator(); action = new QAction(tr("&Rename Layer..."), this); - action->setShortcut(tr("Alt+R")); + action->setShortcut(tr("R")); action->setStatusTip(tr("Rename the currently active layer")); connect(action, SIGNAL(triggered()), this, SLOT(renameCurrentLayer())); connect(this, SIGNAL(canRenameLayer(bool)), action, SLOT(setEnabled(bool))); @@ -1133,7 +1125,7 @@ m_rightButtonLayerMenu->addAction(action); action = new QAction(QIcon(":/icons/editdelete.png"), tr("&Delete Layer"), this); - action->setShortcut(tr("Alt+Shift+D")); + action->setShortcut(tr("Ctrl+D")); action->setStatusTip(tr("Delete the currently active layer")); connect(action, SIGNAL(triggered()), this, SLOT(deleteCurrentLayer())); connect(this, SIGNAL(canDeleteCurrentLayer(bool)), action, SLOT(setEnabled(bool))); @@ -1347,8 +1339,6 @@ void MainWindow::setupHelpMenu() { - if (m_mainMenusCreated) return; - QMenu *menu = menuBar()->addMenu(tr("&Help")); menu->setTearOffEnabled(true); @@ -1377,6 +1367,7 @@ for (size_t i = 0; i < files.size(); ++i) { QAction *action = new QAction(files[i], this); connect(action, SIGNAL(triggered()), this, SLOT(openRecentFile())); + if (i == 0) action->setShortcut(tr("Ctrl+R")); m_recentFilesMenu->addAction(action); } } @@ -1395,6 +1386,7 @@ << "\" in recent transforms list" << std::endl; continue; } + if (i == 0) ti->second->setShortcut(tr("Ctrl+T")); m_recentTransformsMenu->addAction(ti->second); } } @@ -1480,78 +1472,122 @@ void MainWindow::setupToolbars() { - QToolBar *toolbar = addToolBar(tr("Transport Toolbar")); + QMenu *menu = m_playbackMenu = menuBar()->addMenu(tr("Play&back")); + menu->setTearOffEnabled(true); + m_rightButtonMenu->addSeparator(); + m_rightButtonPlaybackMenu = m_rightButtonMenu->addMenu(tr("Playback")); - QAction *action = toolbar->addAction(QIcon(":/icons/rewind-start.png"), - tr("Rewind to Start")); - action->setShortcut(tr("Home")); - action->setStatusTip(tr("Rewind to the start")); - connect(action, SIGNAL(triggered()), this, SLOT(rewindStart())); - connect(this, SIGNAL(canPlay(bool)), action, SLOT(setEnabled(bool))); + QToolBar *toolbar = addToolBar(tr("Playback Toolbar")); - action = toolbar->addAction(QIcon(":/icons/rewind.png"), - tr("Rewind")); - action->setShortcut(tr("PageUp")); - action->setStatusTip(tr("Rewind to the previous time instant in the current layer")); - connect(action, SIGNAL(triggered()), this, SLOT(rewind())); - connect(this, SIGNAL(canRewind(bool)), action, SLOT(setEnabled(bool))); + QAction *rwdStartAction = toolbar->addAction(QIcon(":/icons/rewind-start.png"), + tr("Rewind to Start")); + rwdStartAction->setShortcut(tr("Home")); + rwdStartAction->setStatusTip(tr("Rewind to the start")); + connect(rwdStartAction, SIGNAL(triggered()), this, SLOT(rewindStart())); + connect(this, SIGNAL(canPlay(bool)), rwdStartAction, SLOT(setEnabled(bool))); - action = toolbar->addAction(QIcon(":/icons/playpause.png"), - tr("Play / Pause")); - action->setCheckable(true); - action->setShortcut(tr("Space")); - action->setStatusTip(tr("Start or stop playback from the current position")); - connect(action, SIGNAL(triggered()), this, SLOT(play())); + QAction *m_rwdAction = toolbar->addAction(QIcon(":/icons/rewind.png"), + tr("Rewind")); + m_rwdAction->setShortcut(tr("PgUp")); + connect(m_rwdAction, SIGNAL(triggered()), this, SLOT(rewind())); + connect(this, SIGNAL(canRewind(bool)), m_rwdAction, SLOT(setEnabled(bool))); + + QAction *playAction = toolbar->addAction(QIcon(":/icons/playpause.png"), + tr("Play / Pause")); + playAction->setCheckable(true); + playAction->setShortcut(tr("Space")); + playAction->setStatusTip(tr("Start or stop playback from the current position")); + connect(playAction, SIGNAL(triggered()), this, SLOT(play())); connect(m_playSource, SIGNAL(playStatusChanged(bool)), - action, SLOT(setChecked(bool))); - connect(this, SIGNAL(canPlay(bool)), action, SLOT(setEnabled(bool))); + playAction, SLOT(setChecked(bool))); + connect(this, SIGNAL(canPlay(bool)), playAction, SLOT(setEnabled(bool))); - action = toolbar->addAction(QIcon(":/icons/ffwd.png"), - tr("Fast Forward")); - action->setShortcut(tr("PageDown")); - action->setStatusTip(tr("Fast forward to the next time instant in the current layer")); - connect(action, SIGNAL(triggered()), this, SLOT(ffwd())); - connect(this, SIGNAL(canFfwd(bool)), action, SLOT(setEnabled(bool))); + m_ffwdAction = toolbar->addAction(QIcon(":/icons/ffwd.png"), + tr("Fast Forward")); + m_ffwdAction->setShortcut(tr("PgDown")); + connect(m_ffwdAction, SIGNAL(triggered()), this, SLOT(ffwd())); + connect(this, SIGNAL(canFfwd(bool)), m_ffwdAction, SLOT(setEnabled(bool))); - action = toolbar->addAction(QIcon(":/icons/ffwd-end.png"), - tr("Fast Forward to End")); - action->setShortcut(tr("End")); - action->setStatusTip(tr("Fast-forward to the end")); - connect(action, SIGNAL(triggered()), this, SLOT(ffwdEnd())); - connect(this, SIGNAL(canPlay(bool)), action, SLOT(setEnabled(bool))); + QAction *ffwdEndAction = toolbar->addAction(QIcon(":/icons/ffwd-end.png"), + tr("Fast Forward to End")); + ffwdEndAction->setShortcut(tr("End")); + ffwdEndAction->setStatusTip(tr("Fast-forward to the end")); + connect(ffwdEndAction, SIGNAL(triggered()), this, SLOT(ffwdEnd())); + connect(this, SIGNAL(canPlay(bool)), ffwdEndAction, SLOT(setEnabled(bool))); toolbar = addToolBar(tr("Play Mode Toolbar")); - action = toolbar->addAction(QIcon(":/icons/playselection.png"), - tr("Constrain Playback to Selection")); - action->setCheckable(true); - action->setChecked(m_viewManager->getPlaySelectionMode()); - action->setShortcut(tr("s")); - action->setStatusTip(tr("Constrain playback to the selected area")); + QAction *psAction = toolbar->addAction(QIcon(":/icons/playselection.png"), + tr("Constrain Playback to Selection")); + psAction->setCheckable(true); + psAction->setChecked(m_viewManager->getPlaySelectionMode()); + psAction->setShortcut(tr("s")); + psAction->setStatusTip(tr("Constrain playback to the selected area")); connect(m_viewManager, SIGNAL(playSelectionModeChanged(bool)), - action, SLOT(setChecked(bool))); - connect(action, SIGNAL(triggered()), this, SLOT(playSelectionToggled())); - connect(this, SIGNAL(canPlaySelection(bool)), action, SLOT(setEnabled(bool))); + psAction, SLOT(setChecked(bool))); + connect(psAction, SIGNAL(triggered()), this, SLOT(playSelectionToggled())); + connect(this, SIGNAL(canPlaySelection(bool)), psAction, SLOT(setEnabled(bool))); - action = toolbar->addAction(QIcon(":/icons/playloop.png"), - tr("Loop Playback")); - action->setCheckable(true); - action->setChecked(m_viewManager->getPlayLoopMode()); - action->setShortcut(tr("l")); - action->setStatusTip(tr("Loop playback")); + QAction *plAction = toolbar->addAction(QIcon(":/icons/playloop.png"), + tr("Loop Playback")); + plAction->setCheckable(true); + plAction->setChecked(m_viewManager->getPlayLoopMode()); + plAction->setShortcut(tr("l")); + plAction->setStatusTip(tr("Loop playback")); connect(m_viewManager, SIGNAL(playLoopModeChanged(bool)), - action, SLOT(setChecked(bool))); - connect(action, SIGNAL(triggered()), this, SLOT(playLoopToggled())); - connect(this, SIGNAL(canPlay(bool)), action, SLOT(setEnabled(bool))); + plAction, SLOT(setChecked(bool))); + connect(plAction, SIGNAL(triggered()), this, SLOT(playLoopToggled())); + connect(this, SIGNAL(canPlay(bool)), plAction, SLOT(setEnabled(bool))); + menu->addAction(playAction); + menu->addAction(psAction); + menu->addAction(plAction); + menu->addSeparator(); + menu->addAction(m_rwdAction); + menu->addAction(m_ffwdAction); + menu->addSeparator(); + menu->addAction(rwdStartAction); + menu->addAction(ffwdEndAction); + menu->addSeparator(); + + m_rightButtonPlaybackMenu->addAction(playAction); + m_rightButtonPlaybackMenu->addAction(psAction); + m_rightButtonPlaybackMenu->addAction(plAction); + m_rightButtonPlaybackMenu->addSeparator(); + m_rightButtonPlaybackMenu->addAction(m_rwdAction); + m_rightButtonPlaybackMenu->addAction(m_ffwdAction); + m_rightButtonPlaybackMenu->addSeparator(); + m_rightButtonPlaybackMenu->addAction(rwdStartAction); + m_rightButtonPlaybackMenu->addAction(ffwdEndAction); + m_rightButtonPlaybackMenu->addSeparator(); + + QAction *fastAction = menu->addAction(tr("Speed Up")); + fastAction->setShortcut(tr("Ctrl+PgUp")); + connect(fastAction, SIGNAL(triggered()), this, SLOT(speedUpPlayback())); + connect(this, SIGNAL(canSpeedUpPlayback(bool)), fastAction, SLOT(setEnabled(bool))); + + QAction *slowAction = menu->addAction(tr("Slow Down")); + slowAction->setShortcut(tr("Ctrl+PgDown")); + connect(slowAction, SIGNAL(triggered()), this, SLOT(slowDownPlayback())); + connect(this, SIGNAL(canSlowDownPlayback(bool)), slowAction, SLOT(setEnabled(bool))); + + QAction *normalAction = menu->addAction(tr("Restore Normal Speed")); + normalAction->setShortcut(tr("Ctrl+Home")); + connect(normalAction, SIGNAL(triggered()), this, SLOT(restoreNormalPlayback())); + connect(this, SIGNAL(canChangePlaybackSpeed(bool)), normalAction, SLOT(setEnabled(bool))); + + m_rightButtonPlaybackMenu->addAction(fastAction); + m_rightButtonPlaybackMenu->addAction(slowAction); + m_rightButtonPlaybackMenu->addAction(normalAction); + toolbar = addToolBar(tr("Edit Toolbar")); CommandHistory::getInstance()->registerToolbar(toolbar); toolbar = addToolBar(tr("Tools Toolbar")); QActionGroup *group = new QActionGroup(this); - action = toolbar->addAction(QIcon(":/icons/navigate.png"), - tr("Navigate")); + QAction *action = toolbar->addAction(QIcon(":/icons/navigate.png"), + tr("Navigate")); action->setCheckable(true); action->setChecked(true); action->setShortcut(tr("1")); @@ -1661,9 +1697,9 @@ emit canRenameLayer(haveCurrentLayer); emit canEditLayer(haveCurrentEditableLayer); emit canSelect(haveMainModel && haveCurrentPane); - emit canPlay(/*!!! haveMainModel && */ havePlayTarget); - emit canFfwd(haveCurrentTimeInstantsLayer || haveCurrentTimeValueLayer); - emit canRewind(haveCurrentTimeInstantsLayer || haveCurrentTimeValueLayer); + emit canPlay(havePlayTarget); + emit canFfwd(true); + emit canRewind(true); emit canPaste(haveCurrentEditableLayer && haveClipboardContents); emit canInsertInstant(haveCurrentPane); emit canInsertInstantsAtBoundaries(haveCurrentPane && haveSelection); @@ -1671,6 +1707,30 @@ emit canClearSelection(haveSelection); emit canEditSelection(haveSelection && haveCurrentEditableLayer); emit canSave(m_sessionFile != "" && m_documentModified); + + emit canChangePlaybackSpeed(true); + int v = m_playSpeed->value(); + emit canSpeedUpPlayback(v < m_playSpeed->maximum()); + emit canSlowDownPlayback(v > m_playSpeed->minimum()); + + if (m_ffwdAction && m_rwdAction) { + if (haveCurrentTimeInstantsLayer) { + m_ffwdAction->setText(tr("Fast Forward to Next Instant")); + m_ffwdAction->setStatusTip(tr("Fast forward to the next time instant in the current layer")); + m_rwdAction->setText(tr("Rewind to Previous Instant")); + m_rwdAction->setStatusTip(tr("Rewind to the previous time instant in the current layer")); + } else if (haveCurrentTimeValueLayer) { + m_ffwdAction->setText(tr("Fast Forward to Next Point")); + m_ffwdAction->setStatusTip(tr("Fast forward to the next point in the current layer")); + m_rwdAction->setText(tr("Rewind to Previous Point")); + m_rwdAction->setStatusTip(tr("Rewind to the previous point in the current layer")); + } else { + m_ffwdAction->setText(tr("Fast Forward")); + m_ffwdAction->setStatusTip(tr("Fast forward")); + m_rwdAction->setText(tr("Rewind")); + m_rwdAction->setStatusTip(tr("Rewind")); + } + } } void @@ -3298,27 +3358,30 @@ int frame = m_viewManager->getPlaybackFrame(); ++frame; - Pane *pane = m_paneStack->getCurrentPane(); - if (!pane) return; + Layer *layer = getSnapLayer(); + size_t sr = getMainModel()->getSampleRate(); - Layer *layer = pane->getSelectedLayer(); + if (!layer) { - if (!dynamic_cast<TimeInstantLayer *>(layer) && - !dynamic_cast<TimeValueLayer *>(layer)) return; + frame = RealTime::realTime2Frame + (RealTime::frame2RealTime(frame, sr) + RealTime(2, 0), sr); + if (frame > int(getMainModel()->getEndFrame())) { + frame = getMainModel()->getEndFrame(); + } - size_t resolution = 0; - if (!layer->snapToFeatureFrame(pane, frame, resolution, Layer::SnapRight)) { - frame = getMainModel()->getEndFrame(); + } else { + + size_t resolution = 0; + if (!layer->snapToFeatureFrame(m_paneStack->getCurrentPane(), + frame, resolution, Layer::SnapRight)) { + frame = getMainModel()->getEndFrame(); + } } + + if (frame < 0) frame = 0; if (m_viewManager->getPlaySelectionMode()) { - MultiSelection::SelectionList sl = m_viewManager->getSelections(); - if (!sl.empty()) { - MultiSelection::SelectionList::iterator i = sl.end(); - --i; - int selectionEndFrame = i->getEndFrame(); - if (frame > selectionEndFrame) frame = selectionEndFrame; - } + frame = m_viewManager->constrainFrameToSelection(size_t(frame)); } m_viewManager->setPlaybackFrame(frame); @@ -3332,13 +3395,7 @@ size_t frame = getMainModel()->getEndFrame(); if (m_viewManager->getPlaySelectionMode()) { - MultiSelection::SelectionList sl = m_viewManager->getSelections(); - if (!sl.empty()) { - MultiSelection::SelectionList::iterator i = sl.end(); - --i; - size_t selectionEndFrame = i->getEndFrame(); - if (frame > selectionEndFrame) frame = selectionEndFrame; - } + frame = m_viewManager->constrainFrameToSelection(frame); } m_viewManager->setPlaybackFrame(frame); @@ -3352,25 +3409,30 @@ int frame = m_viewManager->getPlaybackFrame(); if (frame > 0) --frame; - Pane *pane = m_paneStack->getCurrentPane(); - if (!pane) return; + Layer *layer = getSnapLayer(); + size_t sr = getMainModel()->getSampleRate(); - Layer *layer = pane->getSelectedLayer(); + if (!layer) { + + frame = RealTime::realTime2Frame + (RealTime::frame2RealTime(frame, sr) - RealTime(2, 0), sr); + if (frame < int(getMainModel()->getStartFrame())) { + frame = getMainModel()->getStartFrame(); + } - if (!dynamic_cast<TimeInstantLayer *>(layer) && - !dynamic_cast<TimeValueLayer *>(layer)) return; + } else { - size_t resolution = 0; - if (!layer->snapToFeatureFrame(pane, frame, resolution, Layer::SnapLeft)) { - frame = getMainModel()->getEndFrame(); + size_t resolution = 0; + if (!layer->snapToFeatureFrame(m_paneStack->getCurrentPane(), + frame, resolution, Layer::SnapLeft)) { + frame = getMainModel()->getStartFrame(); + } } + if (frame < 0) frame = 0; + if (m_viewManager->getPlaySelectionMode()) { - MultiSelection::SelectionList sl = m_viewManager->getSelections(); - if (!sl.empty()) { - int selectionStartFrame = sl.begin()->getStartFrame(); - if (frame < selectionStartFrame) frame = selectionStartFrame; - } + frame = m_viewManager->constrainFrameToSelection(size_t(frame)); } m_viewManager->setPlaybackFrame(frame); @@ -3384,16 +3446,38 @@ size_t frame = getMainModel()->getStartFrame(); if (m_viewManager->getPlaySelectionMode()) { - MultiSelection::SelectionList sl = m_viewManager->getSelections(); - if (!sl.empty()) { - size_t selectionStartFrame = sl.begin()->getStartFrame(); - if (frame < selectionStartFrame) frame = selectionStartFrame; - } + frame = m_viewManager->constrainFrameToSelection(frame); } m_viewManager->setPlaybackFrame(frame); } +Layer * +MainWindow::getSnapLayer() const +{ + Pane *pane = m_paneStack->getCurrentPane(); + if (!pane) return 0; + + Layer *layer = pane->getSelectedLayer(); + + if (!dynamic_cast<TimeInstantLayer *>(layer) && + !dynamic_cast<TimeValueLayer *>(layer) && + !dynamic_cast<TimeRulerLayer *>(layer)) { + + layer = 0; + + for (int i = pane->getLayerCount(); i > 0; --i) { + Layer *l = pane->getLayer(i-1); + if (dynamic_cast<TimeRulerLayer *>(l)) { + layer = l; + break; + } + } + } + + return layer; +} + void MainWindow::stop() { @@ -3783,28 +3867,29 @@ PlaySpeedRangeMapper mapper(0, 200); float percent = m_playSpeed->mappedValue(); - float factor = mapper.getFactorForValue(percent); -// float factor = mapper.getFactorForPosition(position); -// float percent = mapper.getValueForPosition(position); - std::cerr << "speed = " << position << " percent = " << percent << " factor = " << factor << std::endl; -//!!! bool slow = (position < 100); bool something = (position != 100); -/*!!! + int pc = lrintf(percent); - m_playSpeed->setToolTip(tr("Playback speed: %1%2%") - .arg(!slow ? "+" : "") - .arg(pc)); -*/ + if (!something) { + contextHelpChanged(tr("Playback speed: Normal")); + } else { + contextHelpChanged(tr("Playback speed: %1%2%") + .arg(position > 100 ? "+" : "") + .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); + + updateMenuStates(); } void @@ -3830,6 +3915,30 @@ } void +MainWindow::speedUpPlayback() +{ + int value = m_playSpeed->value(); + value = value + m_playSpeed->pageStep(); + if (value > m_playSpeed->maximum()) value = m_playSpeed->maximum(); + m_playSpeed->setValue(value); +} + +void +MainWindow::slowDownPlayback() +{ + int value = m_playSpeed->value(); + value = value - m_playSpeed->pageStep(); + if (value < m_playSpeed->minimum()) value = m_playSpeed->minimum(); + m_playSpeed->setValue(value); +} + +void +MainWindow::restoreNormalPlayback() +{ + m_playSpeed->setValue(m_playSpeed->defaultValue()); +} + +void MainWindow::playbackFrameChanged(unsigned long frame) { if (!(m_playSource && m_playSource->isPlaying()) || !getMainModel()) return; @@ -4106,8 +4215,9 @@ { QTreeView *view = new QTreeView(); LayerTreeModel *tree = new LayerTreeModel(m_paneStack); - view->expand(tree->index(0, 0, QModelIndex())); view->setModel(tree); +// view->expand(tree->index(0, 0, QModelIndex())); + view->expandAll(); view->show(); } Modified: sonic-visualiser/trunk/sv/main/MainWindow.h =================================================================== --- sonic-visualiser/trunk/sv/main/MainWindow.h 2007-06-26 14:57:29 UTC (rev 682) +++ sonic-visualiser/trunk/sv/main/MainWindow.h 2007-06-28 14:50:58 UTC (rev 683) @@ -109,6 +109,9 @@ void canFfwd(bool); void canRewind(bool); void canPlaySelection(bool); + void canSpeedUpPlayback(bool); + void canSlowDownPlayback(bool); + void canChangePlaybackSpeed(bool); void canSave(bool); public slots: @@ -167,6 +170,9 @@ void playSpeedChanged(int); void playSharpenToggled(); void playMonoToggled(); + void speedUpPlayback(); + void slowDownPlayback(); + void restoreNormalPlayback(); void sampleRateMismatch(size_t, size_t, bool); void audioOverloadPluginDisabled(); @@ -266,6 +272,7 @@ QMenu *m_paneMenu; QMenu *m_layerMenu; QMenu *m_transformsMenu; + QMenu *m_playbackMenu; QMenu *m_existingLayersMenu; QMenu *m_sliceMenu; QMenu *m_recentFilesMenu; @@ -273,7 +280,11 @@ QMenu *m_rightButtonMenu; QMenu *m_rightButtonLayerMenu; QMenu *m_rightButtonTransformsMenu; + QMenu *m_rightButtonPlaybackMenu; + QAction *m_ffwdAction; + QAction *m_rwdAction; + bool m_documentModified; bool m_openingAudioFile; bool m_abandoning; @@ -331,6 +342,8 @@ void addPane(const PaneConfiguration &configuration, QString text); + Layer *getSnapLayer() const; + class PaneCallback : public SVFileReaderPaneCallback { public: Modified: sonic-visualiser/trunk/view/PaneStack.cpp =================================================================== --- sonic-visualiser/trunk/view/PaneStack.cpp 2007-06-26 14:57:29 UTC (rev 682) +++ sonic-visualiser/trunk/view/PaneStack.cpp 2007-06-28 14:50:58 UTC (rev 683) @@ -115,6 +115,9 @@ connect(pane, SIGNAL(rightButtonMenuRequested(QPoint)), this, SLOT(rightButtonMenuRequested(QPoint))); + emit paneAdded(pane); + emit paneAdded(); + if (!m_currentPane) { setCurrentPane(pane); } @@ -208,6 +211,8 @@ } } + emit paneAboutToBeDeleted(pane); + delete pane->parent(); if (m_currentPane == pane) { @@ -217,6 +222,8 @@ setCurrentPane(0); } } + + emit paneDeleted(); } int Modified: sonic-visualiser/trunk/view/PaneStack.h =================================================================== --- sonic-visualiser/trunk/view/PaneStack.h 2007-06-26 14:57:29 UTC (rev 682) +++ sonic-visualiser/trunk/view/PaneStack.h 2007-06-28 14:50:58 UTC (rev 683) @@ -72,6 +72,11 @@ void propertyStacksResized(); void contextHelpChanged(const QString &); + void paneAdded(Pane *pane); + void paneAdded(); + void paneAboutToBeDeleted(Pane *pane); + void paneDeleted(); + public slots: void propertyContainerAdded(PropertyContainer *); void propertyContainerRemoved(PropertyContainer *); Modified: sonic-visualiser/trunk/view/ViewManager.cpp =================================================================== --- sonic-visualiser/trunk/view/ViewManager.cpp 2007-06-26 14:57:29 UTC (rev 682) +++ sonic-visualiser/trunk/view/ViewManager.cpp 2007-06-28 14:50:58 UTC (rev 683) @@ -188,6 +188,26 @@ CommandHistory::getInstance()->addCommand(command); } +size_t +ViewManager::constrainFrameToSelection(size_t frame) const +{ + MultiSelection::SelectionList sl = getSelections(); + if (sl.empty()) return frame; + + size_t selectionStartFrame = sl.begin()->getStartFrame(); + if (frame < selectionStartFrame) { + frame = selectionStartFrame; + return frame; + } + + MultiSelection::SelectionList::iterator i = sl.end(); + --i; + size_t selectionEndFrame = i->getEndFrame(); + if (frame > selectionEndFrame) frame = selectionEndFrame; + + return frame; +} + void ViewManager::signalSelectionChange() { Modified: sonic-visualiser/trunk/view/ViewManager.h =================================================================== --- sonic-visualiser/trunk/view/ViewManager.h 2007-06-26 14:57:29 UTC (rev 682) +++ sonic-visualiser/trunk/view/ViewManager.h 2007-06-28 14:50:58 UTC (rev 683) @@ -76,6 +76,7 @@ void addSelection(const Selection &selection); void removeSelection(const Selection &selection); void clearSelections(); + size_t constrainFrameToSelection(size_t frame) const; /** * Return the selection that contains a given frame. Modified: sonic-visualiser/trunk/widgets/AudioDial.h =================================================================== --- sonic-visualiser/trunk/widgets/AudioDial.h 2007-06-26 14:57:29 UTC (rev 682) +++ sonic-visualiser/trunk/widgets/AudioDial.h 2007-06-28 14:50:58 UTC (rev 683) @@ -75,6 +75,8 @@ const RangeMapper *rangeMapper() const { return m_rangeMapper; } float mappedValue() const; + int defaultValue() const { return m_defaultValue; } + void setShowToolTip(bool show); signals: Modified: sonic-visualiser/trunk/widgets/LayerTree.cpp =================================================================== --- sonic-visualiser/trunk/widgets/LayerTree.cpp 2007-06-26 14:57:29 UTC (rev 682) +++ sonic-visualiser/trunk/widgets/LayerTree.cpp 2007-06-28 14:50:58 UTC (rev 683) @@ -27,9 +27,11 @@ class ViewObjectAssoc : public QObject { public: - ViewObjectAssoc(QObject *parent, View *v, QObject *o) : - QObject(parent), view(v), object(o) { + ViewObjectAssoc(View *v, QObject *o) : + QObject(0), view(v), object(o) { ++extantCount; + std::cerr << "ViewObjectAssoc (now " << extantCount << " extant)" + << std::endl; } virtual ~ViewObjectAssoc() { @@ -50,6 +52,8 @@ QAbstractItemModel(parent), m_stack(stack) { + connect(stack, SIGNAL(paneAdded()), this, SIGNAL(layoutChanged())); + connect(stack, SIGNAL(paneDeleted()), this, SIGNAL(layoutChanged())); } LayerTreeModel::~LayerTreeModel() @@ -156,12 +160,14 @@ if (column == 0) { std::cerr << "parent is pane, returning layer" << std::endl; ViewObjectAssoc *assoc = new ViewObjectAssoc - (const_cast<LayerTreeModel *>(this), pane, layer); +// (const_cast<LayerTreeModel *>(this), pane, layer); + (pane, layer); return createIndex(row, column, assoc); } else { std::cerr << "parent is pane, column != 0, returning model" << std::endl; ViewObjectAssoc *assoc = new ViewObjectAssoc - (const_cast<LayerTreeModel *>(this), pane, layer->getModel()); +// (const_cast<LayerTreeModel *>(this), pane, layer->getModel()); + (pane, layer->getModel()); return createIndex(row, column, assoc); } } This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |