lbajardsilogic@0: /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */ lbajardsilogic@0: lbajardsilogic@0: /* lbajardsilogic@0: Sonic Visualiser lbajardsilogic@0: An audio file viewer and annotation editor. lbajardsilogic@0: Centre for Digital Music, Queen Mary, University of London. lbajardsilogic@0: This file copyright 2006 Chris Cannam and QMUL. lbajardsilogic@0: lbajardsilogic@0: This program is free software; you can redistribute it and/or lbajardsilogic@0: modify it under the terms of the GNU General Public License as lbajardsilogic@0: published by the Free Software Foundation; either version 2 of the lbajardsilogic@0: License, or (at your option) any later version. See the file lbajardsilogic@0: COPYING included with this distribution for more information. lbajardsilogic@0: */ lbajardsilogic@0: lbajardsilogic@0: #include "ViewManager.h" lbajardsilogic@0: #include "base/AudioPlaySource.h" lbajardsilogic@0: #include "data/model/Model.h" lbajardsilogic@0: #include "base/CommandHistory.h" lbajardsilogic@0: #include "View.h" lbajardsilogic@0: #include "system/System.h" lbajardsilogic@0: lbajardsilogic@0: #include lbajardsilogic@0: lbajardsilogic@0: #include lbajardsilogic@0: lbajardsilogic@0: //#define DEBUG_VIEW_MANAGER 1 lbajardsilogic@0: lbajardsilogic@0: ViewManager::ViewManager() : lbajardsilogic@0: m_playSource(0), lbajardsilogic@0: m_globalCentreFrame(0), lbajardsilogic@0: m_globalZoom(1024), lbajardsilogic@0: m_playbackFrame(0), lbajardsilogic@0: m_mainModelSampleRate(0), lbajardsilogic@0: m_lastLeft(0), lbajardsilogic@0: m_lastRight(0), lbajardsilogic@0: m_inProgressExclusive(true), lbajardsilogic@0: m_toolMode(NavigateMode), lbajardsilogic@0: m_playLoopMode(false), lbajardsilogic@0: m_playSelectionMode(false), lbajardsilogic@0: m_overlayMode(StandardOverlays), lbajardsilogic@0: m_zoomWheelsEnabled(true) lbajardsilogic@0: { lbajardsilogic@0: QSettings settings; lbajardsilogic@0: settings.beginGroup("MainWindow"); lbajardsilogic@0: m_overlayMode = OverlayMode lbajardsilogic@0: (settings.value("overlay-mode", int(m_overlayMode)).toInt()); lbajardsilogic@0: m_zoomWheelsEnabled = lbajardsilogic@0: settings.value("zoom-wheels-enabled", m_zoomWheelsEnabled).toBool(); lbajardsilogic@0: settings.endGroup(); lbajardsilogic@0: /*!!! lbajardsilogic@0: connect(this, lbajardsilogic@0: SIGNAL(zoomLevelChanged(void *, unsigned long, bool)), lbajardsilogic@0: SLOT(considerZoomChange(void *, unsigned long, bool))); lbajardsilogic@0: */ lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: ViewManager::~ViewManager() lbajardsilogic@0: { lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: unsigned long lbajardsilogic@0: ViewManager::getGlobalCentreFrame() const lbajardsilogic@0: { lbajardsilogic@0: #ifdef DEBUG_VIEW_MANAGER lbajardsilogic@0: std::cout << "ViewManager::getGlobalCentreFrame: returning " << m_globalCentreFrame << std::endl; lbajardsilogic@0: #endif lbajardsilogic@0: return m_globalCentreFrame; lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: void lbajardsilogic@0: ViewManager::setGlobalCentreFrame(unsigned long f) lbajardsilogic@0: { lbajardsilogic@0: #ifdef DEBUG_VIEW_MANAGER lbajardsilogic@0: std::cout << "ViewManager::setGlobalCentreFrame to " << f << std::endl; lbajardsilogic@0: #endif lbajardsilogic@0: m_globalCentreFrame = f; lbajardsilogic@0: emit globalCentreFrameChanged(f); lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: unsigned long lbajardsilogic@0: ViewManager::getGlobalZoom() const lbajardsilogic@0: { lbajardsilogic@0: #ifdef DEBUG_VIEW_MANAGER lbajardsilogic@0: std::cout << "ViewManager::getGlobalZoom: returning " << m_globalZoom << std::endl; lbajardsilogic@0: #endif lbajardsilogic@0: return m_globalZoom; lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: unsigned long lbajardsilogic@0: ViewManager::getPlaybackFrame() const lbajardsilogic@0: { lbajardsilogic@0: if (m_playSource && m_playSource->isPlaying()) { lbajardsilogic@0: m_playbackFrame = m_playSource->getCurrentPlayingFrame(); lbajardsilogic@0: } lbajardsilogic@0: return m_playbackFrame; lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: void lbajardsilogic@0: ViewManager::setPlaybackFrame(unsigned long f) lbajardsilogic@0: { lbajardsilogic@0: if (m_playbackFrame != f) { lbajardsilogic@0: m_playbackFrame = f; lbajardsilogic@0: emit playbackFrameChanged(f); lbajardsilogic@0: if (m_playSource && m_playSource->isPlaying()) { lbajardsilogic@0: m_playSource->play(f); lbajardsilogic@0: } lbajardsilogic@0: } lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: bool lbajardsilogic@0: ViewManager::haveInProgressSelection() const lbajardsilogic@0: { lbajardsilogic@0: return !m_inProgressSelection.isEmpty(); lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: const Selection & lbajardsilogic@0: ViewManager::getInProgressSelection(bool &exclusive) const lbajardsilogic@0: { lbajardsilogic@0: exclusive = m_inProgressExclusive; lbajardsilogic@0: return m_inProgressSelection; lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: void lbajardsilogic@0: ViewManager::setInProgressSelection(const Selection &selection, bool exclusive) lbajardsilogic@0: { lbajardsilogic@0: m_inProgressExclusive = exclusive; lbajardsilogic@0: m_inProgressSelection = selection; lbajardsilogic@0: if (exclusive) clearSelections(); lbajardsilogic@0: emit inProgressSelectionChanged(); lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: void lbajardsilogic@0: ViewManager::clearInProgressSelection() lbajardsilogic@0: { lbajardsilogic@0: m_inProgressSelection = Selection(); lbajardsilogic@0: emit inProgressSelectionChanged(); lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: const MultiSelection & lbajardsilogic@0: ViewManager::getSelection() const lbajardsilogic@0: { lbajardsilogic@0: return m_selections; lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: const MultiSelection::SelectionList & lbajardsilogic@0: ViewManager::getSelections() const lbajardsilogic@0: { lbajardsilogic@0: return m_selections.getSelections(); lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: void lbajardsilogic@0: ViewManager::setSelection(const Selection &selection) lbajardsilogic@0: { lbajardsilogic@0: MultiSelection ms(m_selections); lbajardsilogic@0: ms.setSelection(selection); lbajardsilogic@0: setSelections(ms); lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: void lbajardsilogic@0: ViewManager::addSelection(const Selection &selection) lbajardsilogic@0: { lbajardsilogic@0: MultiSelection ms(m_selections); lbajardsilogic@0: ms.addSelection(selection); lbajardsilogic@0: setSelections(ms); lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: void lbajardsilogic@0: ViewManager::removeSelection(const Selection &selection) lbajardsilogic@0: { lbajardsilogic@0: MultiSelection ms(m_selections); lbajardsilogic@0: ms.removeSelection(selection); lbajardsilogic@0: setSelections(ms); lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: void lbajardsilogic@0: ViewManager::clearSelections() lbajardsilogic@0: { lbajardsilogic@0: MultiSelection ms(m_selections); lbajardsilogic@0: ms.clearSelections(); lbajardsilogic@0: setSelections(ms); lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: void lbajardsilogic@0: ViewManager::setSelections(const MultiSelection &ms) lbajardsilogic@0: { lbajardsilogic@0: if (m_selections.getSelections() == ms.getSelections()) return; lbajardsilogic@0: SetSelectionCommand *command = new SetSelectionCommand(this, ms); lbajardsilogic@0: CommandHistory::getInstance()->addCommand(command); lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: void lbajardsilogic@0: ViewManager::signalSelectionChange() lbajardsilogic@0: { lbajardsilogic@0: emit selectionChanged(); lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: ViewManager::SetSelectionCommand::SetSelectionCommand(ViewManager *vm, lbajardsilogic@0: const MultiSelection &ms) : lbajardsilogic@0: m_vm(vm), lbajardsilogic@0: m_oldSelection(vm->m_selections), lbajardsilogic@0: m_newSelection(ms) lbajardsilogic@0: { lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: ViewManager::SetSelectionCommand::~SetSelectionCommand() { } lbajardsilogic@0: lbajardsilogic@0: void lbajardsilogic@0: ViewManager::SetSelectionCommand::execute() lbajardsilogic@0: { lbajardsilogic@0: m_vm->m_selections = m_newSelection; lbajardsilogic@0: m_vm->signalSelectionChange(); lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: void lbajardsilogic@0: ViewManager::SetSelectionCommand::unexecute() lbajardsilogic@0: { lbajardsilogic@0: m_vm->m_selections = m_oldSelection; lbajardsilogic@0: m_vm->signalSelectionChange(); lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: QString lbajardsilogic@0: ViewManager::SetSelectionCommand::getName() const lbajardsilogic@0: { lbajardsilogic@0: if (m_newSelection.getSelections().empty()) return tr("Clear Selection"); lbajardsilogic@0: else return tr("Select"); lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: Selection lbajardsilogic@0: ViewManager::getContainingSelection(size_t frame, bool defaultToFollowing) const lbajardsilogic@0: { lbajardsilogic@0: return m_selections.getContainingSelection(frame, defaultToFollowing); lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: void lbajardsilogic@0: ViewManager::setToolMode(ToolMode mode) lbajardsilogic@0: { lbajardsilogic@0: m_toolMode = mode; lbajardsilogic@0: lbajardsilogic@0: emit toolModeChanged(); lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: void lbajardsilogic@0: ViewManager::setPlayLoopMode(bool mode) lbajardsilogic@0: { lbajardsilogic@0: if (m_playLoopMode != mode) { lbajardsilogic@0: lbajardsilogic@0: m_playLoopMode = mode; lbajardsilogic@0: lbajardsilogic@0: emit playLoopModeChanged(); lbajardsilogic@0: emit playLoopModeChanged(mode); lbajardsilogic@0: } lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: void lbajardsilogic@0: ViewManager::setPlaySelectionMode(bool mode) lbajardsilogic@0: { lbajardsilogic@0: if (m_playSelectionMode != mode) { lbajardsilogic@0: lbajardsilogic@0: m_playSelectionMode = mode; lbajardsilogic@0: lbajardsilogic@0: emit playSelectionModeChanged(); lbajardsilogic@0: emit playSelectionModeChanged(mode); lbajardsilogic@0: } lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: size_t lbajardsilogic@0: ViewManager::getPlaybackSampleRate() const lbajardsilogic@0: { lbajardsilogic@0: if (m_playSource) { lbajardsilogic@0: return m_playSource->getSourceSampleRate(); lbajardsilogic@0: } lbajardsilogic@0: return 0; lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: size_t lbajardsilogic@0: ViewManager::getOutputSampleRate() const lbajardsilogic@0: { lbajardsilogic@0: if (m_playSource) { lbajardsilogic@0: return m_playSource->getTargetSampleRate(); lbajardsilogic@0: } lbajardsilogic@0: return 0; lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: void lbajardsilogic@0: ViewManager::setAudioPlaySource(AudioPlaySource *source) lbajardsilogic@0: { lbajardsilogic@0: if (!m_playSource) { lbajardsilogic@0: QTimer::singleShot(100, this, SLOT(checkPlayStatus())); lbajardsilogic@0: } lbajardsilogic@0: m_playSource = source; lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: void lbajardsilogic@0: ViewManager::playStatusChanged(bool /* playing */) lbajardsilogic@0: { lbajardsilogic@0: checkPlayStatus(); lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: void lbajardsilogic@0: ViewManager::checkPlayStatus() lbajardsilogic@0: { lbajardsilogic@0: if (m_playSource && m_playSource->isPlaying()) { lbajardsilogic@0: lbajardsilogic@0: float left = 0, right = 0; lbajardsilogic@0: if (m_playSource->getOutputLevels(left, right)) { lbajardsilogic@0: if (left != m_lastLeft || right != m_lastRight) { lbajardsilogic@0: emit outputLevelsChanged(left, right); lbajardsilogic@0: m_lastLeft = left; lbajardsilogic@0: m_lastRight = right; lbajardsilogic@0: } lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: m_playbackFrame = m_playSource->getCurrentPlayingFrame(); lbajardsilogic@0: lbajardsilogic@0: #ifdef DEBUG_VIEW_MANAGER lbajardsilogic@0: std::cout << "ViewManager::checkPlayStatus: Playing, frame " << m_playbackFrame << ", levels " << m_lastLeft << "," << m_lastRight << std::endl; lbajardsilogic@0: #endif lbajardsilogic@0: lbajardsilogic@0: emit playbackFrameChanged(m_playbackFrame); lbajardsilogic@0: lbajardsilogic@0: QTimer::singleShot(20, this, SLOT(checkPlayStatus())); lbajardsilogic@0: lbajardsilogic@0: } else { lbajardsilogic@0: lbajardsilogic@0: QTimer::singleShot(100, this, SLOT(checkPlayStatus())); lbajardsilogic@0: lbajardsilogic@0: if (m_lastLeft != 0.0 || m_lastRight != 0.0) { lbajardsilogic@0: emit outputLevelsChanged(0.0, 0.0); lbajardsilogic@0: m_lastLeft = 0.0; lbajardsilogic@0: m_lastRight = 0.0; lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: #ifdef DEBUG_VIEW_MANAGER lbajardsilogic@0: // std::cout << "ViewManager::checkPlayStatus: Not playing" << std::endl; lbajardsilogic@0: #endif lbajardsilogic@0: } lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: bool lbajardsilogic@0: ViewManager::isPlaying() const lbajardsilogic@0: { lbajardsilogic@0: return m_playSource && m_playSource->isPlaying(); lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: void lbajardsilogic@0: ViewManager::viewCentreFrameChanged(unsigned long f, bool locked, lbajardsilogic@0: PlaybackFollowMode mode) lbajardsilogic@0: { lbajardsilogic@0: View *v = dynamic_cast(sender()); lbajardsilogic@0: lbajardsilogic@0: if (locked) { lbajardsilogic@0: m_globalCentreFrame = f; lbajardsilogic@0: emit globalCentreFrameChanged(f); lbajardsilogic@0: } else { lbajardsilogic@0: if (v) emit viewCentreFrameChanged(v, f); lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: if (mode == PlaybackIgnore) { lbajardsilogic@0: return; lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: seek(f); lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: void lbajardsilogic@0: ViewManager::seek(unsigned long f) lbajardsilogic@0: { lbajardsilogic@0: #ifdef DEBUG_VIEW_MANAGER lbajardsilogic@0: std::cout << "ViewManager::seek(" << f << ")" << std::endl; lbajardsilogic@0: #endif lbajardsilogic@0: lbajardsilogic@0: if (m_playSource && m_playSource->isPlaying()) { lbajardsilogic@0: unsigned long playFrame = m_playSource->getCurrentPlayingFrame(); lbajardsilogic@191: unsigned long diff = MAX(f, playFrame) - MIN(f, playFrame); lbajardsilogic@0: if (diff > 20000) { lbajardsilogic@0: m_playbackFrame = f; lbajardsilogic@0: m_playSource->play(f); lbajardsilogic@0: #ifdef DEBUG_VIEW_MANAGER lbajardsilogic@0: std::cout << "ViewManager::considerSeek: reseeking from " << playFrame << " to " << f << std::endl; lbajardsilogic@0: #endif lbajardsilogic@0: emit playbackFrameChanged(f); lbajardsilogic@0: } lbajardsilogic@0: } else { lbajardsilogic@0: if (m_playbackFrame != f) { lbajardsilogic@0: m_playbackFrame = f; lbajardsilogic@0: emit playbackFrameChanged(f); lbajardsilogic@0: } lbajardsilogic@0: } lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: void lbajardsilogic@0: ViewManager::viewZoomLevelChanged(unsigned long z, bool locked) lbajardsilogic@0: { lbajardsilogic@0: View *v = dynamic_cast(sender()); lbajardsilogic@0: lbajardsilogic@0: if (!v) { lbajardsilogic@0: std::cerr << "ViewManager::viewZoomLevelChanged: WARNING: sender is not a view" << std::endl; lbajardsilogic@0: return; lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: //!!! emit zoomLevelChanged(); lbajardsilogic@0: lbajardsilogic@0: if (locked) { lbajardsilogic@0: m_globalZoom = z; lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: #ifdef DEBUG_VIEW_MANAGER lbajardsilogic@0: std::cout << "ViewManager::viewZoomLevelChanged(" << v << ", " << z << ", " << locked << ")" << std::endl; lbajardsilogic@0: #endif lbajardsilogic@0: lbajardsilogic@0: emit viewZoomLevelChanged(v, z, locked); lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: void lbajardsilogic@0: ViewManager::setOverlayMode(OverlayMode mode) lbajardsilogic@0: { lbajardsilogic@0: if (m_overlayMode != mode) { lbajardsilogic@0: m_overlayMode = mode; lbajardsilogic@0: emit overlayModeChanged(); lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: QSettings settings; lbajardsilogic@0: settings.beginGroup("MainWindow"); lbajardsilogic@0: settings.setValue("overlay-mode", int(m_overlayMode)); lbajardsilogic@0: settings.endGroup(); lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: void lbajardsilogic@0: ViewManager::setZoomWheelsEnabled(bool enabled) lbajardsilogic@0: { lbajardsilogic@0: if (m_zoomWheelsEnabled != enabled) { lbajardsilogic@0: m_zoomWheelsEnabled = enabled; lbajardsilogic@0: emit zoomWheelsEnabledChanged(); lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: QSettings settings; lbajardsilogic@0: settings.beginGroup("MainWindow"); lbajardsilogic@0: settings.setValue("zoom-wheels-enabled", m_zoomWheelsEnabled); lbajardsilogic@0: settings.endGroup(); lbajardsilogic@0: } lbajardsilogic@0: