Chris@127: /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */ Chris@127: Chris@127: /* Chris@127: Sonic Visualiser Chris@127: An audio file viewer and annotation editor. Chris@127: Centre for Digital Music, Queen Mary, University of London. Chris@182: This file copyright 2006 Chris Cannam and QMUL. Chris@127: Chris@127: This program is free software; you can redistribute it and/or Chris@127: modify it under the terms of the GNU General Public License as Chris@127: published by the Free Software Foundation; either version 2 of the Chris@127: License, or (at your option) any later version. See the file Chris@127: COPYING included with this distribution for more information. Chris@127: */ Chris@127: Chris@127: #ifndef _VIEW_MANAGER_H_ Chris@127: #define _VIEW_MANAGER_H_ Chris@127: Chris@127: #include Chris@127: #include Chris@292: #include Chris@127: Chris@127: #include Chris@127: Chris@376: #include "base/ViewManagerBase.h" Chris@128: #include "base/Selection.h" Chris@128: #include "base/Command.h" Chris@128: #include "base/Clipboard.h" Chris@127: Chris@127: class AudioPlaySource; Chris@127: class Model; Chris@127: Chris@211: enum PlaybackFollowMode { Chris@815: Chris@815: /** Chris@815: * View scrolls continuously during playback, keeping the playback Chris@815: * position at the centre. Chris@815: */ Chris@211: PlaybackScrollContinuous, Chris@815: Chris@815: /** Chris@815: * View follows playback page-by-page, but dragging the view Chris@815: * relocates playback to the centre frame. This is the classic Chris@815: * Sonic Visualiser behaviour. Chris@815: */ Chris@815: PlaybackScrollPageWithCentre, Chris@815: Chris@815: /** Chris@815: * View follows playback page-by-page, and the play head is moved Chris@815: * (by the user) separately from dragging the view. This is Chris@815: * roughly the behaviour of a typical DAW or audio editor. Chris@815: */ Chris@211: PlaybackScrollPage, Chris@815: Chris@815: /** Chris@815: * View is detached from playback. It doesn't follow playback, and Chris@815: * dragging the view does not affect the play head. Chris@815: */ Chris@211: PlaybackIgnore Chris@211: }; Chris@211: Chris@211: class View; Chris@211: Chris@127: /** Chris@127: * The ViewManager manages properties that may need to be synchronised Chris@127: * between separate Views. For example, it handles signals associated Chris@127: * with changes to the global pan and zoom, and it handles selections. Chris@127: * Chris@127: * Views should be implemented in such a way as to work Chris@127: * correctly whether they are supplied with a ViewManager or not. Chris@127: */ Chris@127: Chris@376: class ViewManager : public ViewManagerBase Chris@127: { Chris@127: Q_OBJECT Chris@127: Chris@127: public: Chris@127: ViewManager(); Chris@127: virtual ~ViewManager(); Chris@127: Chris@127: void setAudioPlaySource(AudioPlaySource *source); Chris@127: Chris@127: bool isPlaying() const; Chris@127: Chris@806: int getGlobalCentreFrame() const; // the set method is a slot Chris@806: int getGlobalZoom() const; Chris@127: Chris@806: int getPlaybackFrame() const; // the set method is a slot Chris@127: Chris@301: // Only meaningful in solo mode, and used for optional alignment feature Chris@301: Model *getPlaybackModel() const; Chris@301: void setPlaybackModel(Model *); Chris@301: Chris@806: int alignPlaybackFrameToReference(int) const; Chris@806: int alignReferenceToPlaybackFrame(int) const; Chris@333: Chris@127: bool haveInProgressSelection() const; Chris@127: const Selection &getInProgressSelection(bool &exclusive) const; Chris@127: void setInProgressSelection(const Selection &selection, bool exclusive); Chris@127: void clearInProgressSelection(); Chris@127: Chris@127: const MultiSelection &getSelection() const; Chris@127: Chris@127: const MultiSelection::SelectionList &getSelections() const; Chris@127: void setSelection(const Selection &selection); Chris@127: void addSelection(const Selection &selection); Chris@127: void removeSelection(const Selection &selection); Chris@127: void clearSelections(); Chris@806: int constrainFrameToSelection(int frame) const; Chris@127: Chris@127: /** Chris@762: * Adding a selection normally emits the selectionChangedByUser Chris@762: * signal. Call this to add a selection without emitting that signal. Chris@762: * This is used in session file load, for example. Chris@762: */ Chris@762: void addSelectionQuietly(const Selection &selection); Chris@762: Chris@762: /** Chris@127: * Return the selection that contains a given frame. Chris@127: * If defaultToFollowing is true, and if the frame is not in a Chris@127: * selected area, return the next selection after the given frame. Chris@127: * Return the empty selection if no appropriate selection is found. Chris@127: */ Chris@806: Selection getContainingSelection(int frame, bool defaultToFollowing) const; Chris@127: Chris@127: Clipboard &getClipboard() { return m_clipboard; } Chris@127: Chris@127: enum ToolMode { Chris@127: NavigateMode, Chris@127: SelectMode, Chris@711: EditMode, Chris@257: DrawMode, Chris@335: EraseMode, gyorgyf@645: MeasureMode, gyorgyf@645: NoteEditMode //GF: Tonioni: this tool mode will be context sensitive. Chris@127: }; Chris@127: ToolMode getToolMode() const { return m_toolMode; } Chris@127: void setToolMode(ToolMode mode); Chris@127: Chris@711: /// Override the tool mode for a specific view Chris@711: void setToolModeFor(const View *v, ToolMode mode); Chris@711: /// Return override mode if it exists for this view or global mode otherwise Chris@711: ToolMode getToolModeFor(const View *v) const; Chris@711: /// Clear all current view-specific overrides Chris@711: void clearToolModeOverrides(); Chris@711: Chris@127: bool getPlayLoopMode() const { return m_playLoopMode; } Chris@127: void setPlayLoopMode(bool on); Chris@127: Chris@127: bool getPlaySelectionMode() const { return m_playSelectionMode; } Chris@127: void setPlaySelectionMode(bool on); Chris@127: Chris@301: bool getPlaySoloMode() const { return m_playSoloMode; } Chris@301: void setPlaySoloMode(bool on); Chris@301: Chris@314: bool getAlignMode() const { return m_alignMode; } Chris@314: void setAlignMode(bool on); Chris@314: Chris@326: void setIlluminateLocalFeatures(bool i) { m_illuminateLocalFeatures = i; } Chris@326: void setShowWorkTitle(bool show) { m_showWorkTitle = show; } matthiasm@822: void setShowDuration(bool show) { m_showDuration = show; } Chris@326: Chris@224: /** Chris@224: * The sample rate that is used for playback. This is usually the Chris@224: * rate of the main model, but not always. Models whose rates Chris@224: * differ from this will play back at the wrong speed -- there is Chris@224: * no per-model resampler. Chris@224: */ Chris@806: int getPlaybackSampleRate() const; Chris@224: Chris@224: /** Chris@224: * The sample rate of the audio output device. If the playback Chris@224: * sample rate differs from this, everything will be resampled at Chris@224: * the output stage. Chris@224: */ Chris@806: int getOutputSampleRate() const; Chris@224: Chris@224: /** Chris@224: * The sample rate of the current main model. This may in theory Chris@224: * differ from the playback sample rate, in which case even the Chris@224: * main model will play at the wrong speed. Chris@224: */ Chris@806: int getMainModelSampleRate() const { return m_mainModelSampleRate; } Chris@224: Chris@806: void setMainModelSampleRate(int sr) { m_mainModelSampleRate = sr; } Chris@127: Chris@896: /** Chris@896: * Take a "design pixel" size and scale it for the actual Chris@896: * display. This is relevant to hi-dpi systems that do not do Chris@896: * pixel doubling (i.e. Windows and Linux rather than OS/X). Chris@896: */ Chris@896: int scalePixelSize(int pixels); Chris@896: Chris@127: enum OverlayMode { Chris@127: NoOverlays, Chris@741: GlobalOverlays, Chris@741: StandardOverlays, Chris@127: AllOverlays Chris@127: }; Chris@127: void setOverlayMode(OverlayMode mode); Chris@127: OverlayMode getOverlayMode() const { return m_overlayMode; } Chris@127: Chris@607: void setShowCentreLine(bool show); Chris@607: bool shouldShowCentreLine() const { return m_showCentreLine; } Chris@607: Chris@607: bool shouldShowDuration() const { matthiasm@822: return m_overlayMode != NoOverlays && m_showDuration; Chris@189: } Chris@189: bool shouldShowFrameCount() const { Chris@607: return m_showCentreLine && shouldShowDuration(); Chris@607: } Chris@607: bool shouldShowVerticalScale() const { Chris@189: return m_overlayMode != NoOverlays; Chris@189: } Chris@607: bool shouldShowVerticalColourScale() const { Chris@607: return m_overlayMode == AllOverlays; Chris@189: } Chris@189: bool shouldShowSelectionExtents() const { Chris@741: return m_overlayMode != NoOverlays && m_overlayMode != GlobalOverlays; Chris@189: } Chris@189: bool shouldShowLayerNames() const { Chris@189: return m_overlayMode == AllOverlays; Chris@189: } Chris@195: bool shouldShowScaleGuides() const { Chris@195: return m_overlayMode != NoOverlays; Chris@195: } Chris@326: bool shouldShowWorkTitle() const { Chris@326: return m_showWorkTitle; Chris@326: } Chris@326: bool shouldIlluminateLocalFeatures() const { Chris@326: return m_illuminateLocalFeatures; Chris@326: } Chris@741: bool shouldShowFeatureLabels() const { Chris@741: return m_overlayMode != NoOverlays && m_overlayMode != GlobalOverlays; Chris@741: } Chris@189: Chris@133: void setZoomWheelsEnabled(bool enable); Chris@133: bool getZoomWheelsEnabled() const { return m_zoomWheelsEnabled; } Chris@133: Chris@292: void setGlobalDarkBackground(bool dark); Chris@292: bool getGlobalDarkBackground() const; Chris@292: Chris@127: signals: Chris@211: /** Emitted when user causes the global centre frame to change. */ Chris@806: void globalCentreFrameChanged(int frame); Chris@127: Chris@211: /** Emitted when user scrolls a view, but doesn't affect global centre. */ Chris@806: void viewCentreFrameChanged(View *v, int frame); Chris@211: Chris@211: /** Emitted when a view zooms. */ Chris@806: void viewZoomLevelChanged(View *v, int zoom, bool locked); Chris@133: Chris@127: /** Emitted when the playback frame changes. */ Chris@806: void playbackFrameChanged(int frame); Chris@127: Chris@127: /** Emitted when the output levels change. Values in range 0.0 -> 1.0. */ Chris@127: void outputLevelsChanged(float left, float right); Chris@127: Chris@731: /** Emitted whenever the selection has changed. */ Chris@127: void selectionChanged(); Chris@127: Chris@731: /** Emitted when the selection has been changed through an Chris@731: * explicit selection-editing action. *Not* emitted when the Chris@731: * selection has been changed through undo or redo. */ Chris@731: void selectionChangedByUser(); Chris@731: Chris@127: /** Emitted when the in-progress (rubberbanding) selection has changed. */ Chris@127: void inProgressSelectionChanged(); Chris@127: Chris@127: /** Emitted when the tool mode has been changed. */ Chris@127: void toolModeChanged(); Chris@127: Chris@127: /** Emitted when the play loop mode has been changed. */ Chris@127: void playLoopModeChanged(); Chris@177: void playLoopModeChanged(bool); Chris@127: Chris@127: /** Emitted when the play selection mode has been changed. */ Chris@127: void playSelectionModeChanged(); Chris@177: void playSelectionModeChanged(bool); Chris@127: Chris@301: /** Emitted when the play solo mode has been changed. */ Chris@301: void playSoloModeChanged(); Chris@301: void playSoloModeChanged(bool); Chris@301: Chris@314: /** Emitted when the alignment mode has been changed. */ Chris@314: void alignModeChanged(); Chris@314: void alignModeChanged(bool); Chris@314: Chris@127: /** Emitted when the overlay mode has been changed. */ Chris@127: void overlayModeChanged(); Chris@127: Chris@607: /** Emitted when the centre line visibility has been changed. */ Chris@607: void showCentreLineChanged(); Chris@607: Chris@133: /** Emitted when the zoom wheels have been toggled. */ Chris@133: void zoomWheelsEnabledChanged(); Chris@133: Chris@502: /** Emitted when any loggable activity has occurred. */ Chris@502: void activity(QString); Chris@502: Chris@211: public slots: Chris@806: void viewCentreFrameChanged(int, bool, PlaybackFollowMode); Chris@806: void viewZoomLevelChanged(int, bool); Chris@806: void setGlobalCentreFrame(int); Chris@806: void setPlaybackFrame(int); Chris@689: void playStatusChanged(bool playing); Chris@211: Chris@127: protected slots: Chris@127: void checkPlayStatus(); Chris@806: void seek(int); Chris@806: //!!! void considerZoomChange(void *, int, bool); Chris@127: Chris@127: protected: Chris@127: AudioPlaySource *m_playSource; Chris@806: int m_globalCentreFrame; Chris@806: int m_globalZoom; Chris@806: mutable int m_playbackFrame; Chris@301: Model *m_playbackModel; //!!! Chris@806: int m_mainModelSampleRate; Chris@127: Chris@127: float m_lastLeft; Chris@127: float m_lastRight; Chris@127: Chris@127: MultiSelection m_selections; Chris@127: Selection m_inProgressSelection; Chris@127: bool m_inProgressExclusive; Chris@127: Chris@127: Clipboard m_clipboard; Chris@127: Chris@127: ToolMode m_toolMode; Chris@711: std::map m_toolModeOverrides; Chris@127: Chris@127: bool m_playLoopMode; Chris@127: bool m_playSelectionMode; Chris@301: bool m_playSoloMode; Chris@314: bool m_alignMode; Chris@127: Chris@762: void setSelections(const MultiSelection &ms, bool quietly = false); Chris@127: void signalSelectionChange(); Chris@127: Chris@127: class SetSelectionCommand : public Command Chris@127: { Chris@127: public: Chris@127: SetSelectionCommand(ViewManager *vm, const MultiSelection &ms); Chris@127: virtual ~SetSelectionCommand(); Chris@127: virtual void execute(); Chris@127: virtual void unexecute(); Chris@127: virtual QString getName() const; Chris@127: Chris@127: protected: Chris@127: ViewManager *m_vm; Chris@127: MultiSelection m_oldSelection; Chris@127: MultiSelection m_newSelection; Chris@127: }; Chris@127: Chris@127: OverlayMode m_overlayMode; Chris@133: bool m_zoomWheelsEnabled; Chris@607: bool m_showCentreLine; Chris@326: bool m_illuminateLocalFeatures; Chris@326: bool m_showWorkTitle; matthiasm@822: bool m_showDuration; Chris@292: Chris@292: QPalette m_lightPalette; Chris@292: QPalette m_darkPalette; Chris@127: }; Chris@127: Chris@127: #endif Chris@127: