1 /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */ 2 3 /* 4 Sonic Visualiser 5 An audio file viewer and annotation editor. 6 Centre for Digital Music, Queen Mary, University of London. 7 This file copyright 2006 Chris Cannam and QMUL. 8 9 This program is free software; you can redistribute it and/or 10 modify it under the terms of the GNU General Public License as 11 published by the Free Software Foundation; either version 2 of the 12 License, or (at your option) any later version. See the file 13 COPYING included with this distribution for more information. 14 */ 15 16 #ifndef SV_VIEW_MANAGER_H 17 #define SV_VIEW_MANAGER_H 18 19 #include <QObject> 20 #include <QTimer> 21 #include <QPalette> 22 23 #include <map> 24 25 #include "base/ViewManagerBase.h" 26 #include "base/Selection.h" 27 #include "base/Command.h" 28 #include "base/Clipboard.h" 29 #include "base/BaseTypes.h" 30 #include "base/ZoomLevel.h" 31 32 #include "data/model/Model.h" 33 34 class AudioPlaySource; 35 class AudioRecordTarget; 36 class Model; 37 38 enum PlaybackFollowMode { 39 40 /** 41 * View scrolls continuously during playback, keeping the playback 42 * position at the centre. 43 */ 44 PlaybackScrollContinuous, 45 46 /** 47 * View follows playback page-by-page, but dragging the view 48 * relocates playback to the centre frame. This is the classic 49 * Sonic Visualiser behaviour. 50 */ 51 PlaybackScrollPageWithCentre, 52 53 /** 54 * View follows playback page-by-page, and the play head is moved 55 * (by the user) separately from dragging the view. This is 56 * roughly the behaviour of a typical DAW or audio editor. 57 */ 58 PlaybackScrollPage, 59 60 /** 61 * View is detached from playback. It doesn't follow playback, and 62 * dragging the view does not affect the play head. 63 */ 64 PlaybackIgnore 65 }; 66 67 class View; 68 69 /** 70 * The ViewManager manages properties that may need to be synchronised 71 * between separate Views. For example, it handles signals associated 72 * with changes to the global pan and zoom, and it handles selections. 73 * 74 * Views should be implemented in such a way as to work 75 * correctly whether they are supplied with a ViewManager or not. 76 */ 77 78 class ViewManager : public ViewManagerBase 79 { 80 Q_OBJECT 81 82 public: 83 ViewManager(); 84 virtual ~ViewManager(); 85 86 void setAudioPlaySource(AudioPlaySource *source) override; 87 void setAudioRecordTarget(AudioRecordTarget *target) override; 88 89 bool isPlaying() const; 90 bool isRecording() const; 91 92 sv_frame_t getGlobalCentreFrame() const; // the set method is a slot 93 ZoomLevel getGlobalZoom() const; 94 95 sv_frame_t getPlaybackFrame() const; // the set method is a slot 96 97 // Only meaningful in solo mode, and used for optional alignment feature 98 ModelId getPlaybackModel() const; 99 void setPlaybackModel(ModelId); 100 101 sv_frame_t alignPlaybackFrameToReference(sv_frame_t) const override; 102 sv_frame_t alignReferenceToPlaybackFrame(sv_frame_t) const override; 103 104 bool haveInProgressSelection() const; 105 const Selection &getInProgressSelection(bool &exclusive) const; 106 void setInProgressSelection(const Selection &selection, bool exclusive); 107 void clearInProgressSelection(); 108 109 const MultiSelection &getSelection() const override; 110 111 const MultiSelection::SelectionList &getSelections() const override; 112 void setSelection(const Selection &selection); 113 void addSelection(const Selection &selection); 114 void removeSelection(const Selection &selection); 115 void clearSelections(); 116 sv_frame_t constrainFrameToSelection(sv_frame_t frame) const override; 117 118 /** 119 * Adding a selection normally emits the selectionChangedByUser 120 * signal. Call this to add a selection without emitting that signal. 121 * This is used in session file load, for example. 122 */ 123 void addSelectionQuietly(const Selection &selection); 124 125 /** 126 * Return the selection that contains a given frame. 127 * If defaultToFollowing is true, and if the frame is not in a 128 * selected area, return the next selection after the given frame. 129 * Return the empty selection if no appropriate selection is found. 130 */ 131 Selection getContainingSelection(sv_frame_t frame, bool defaultToFollowing) const override; 132 getClipboard()133 Clipboard &getClipboard() { return m_clipboard; } 134 135 enum ToolMode { 136 NavigateMode, 137 SelectMode, 138 EditMode, 139 DrawMode, 140 EraseMode, 141 MeasureMode, 142 NoteEditMode //GF: Tonioni: this tool mode will be context sensitive. 143 }; getToolMode()144 ToolMode getToolMode() const { return m_toolMode; } 145 void setToolMode(ToolMode mode); 146 147 /// Override the tool mode for a specific view 148 void setToolModeFor(const View *v, ToolMode mode); 149 /// Return override mode if it exists for this view or global mode otherwise 150 ToolMode getToolModeFor(const View *v) const; 151 /// Clear all current view-specific overrides 152 void clearToolModeOverrides(); 153 getPlayLoopMode()154 bool getPlayLoopMode() const override { return m_playLoopMode; } 155 void setPlayLoopMode(bool on); 156 getPlaySelectionMode()157 bool getPlaySelectionMode() const override { return m_playSelectionMode; } 158 void setPlaySelectionMode(bool on); 159 getPlaySoloMode()160 bool getPlaySoloMode() const override { return m_playSoloMode; } 161 void setPlaySoloMode(bool on); 162 getAlignMode()163 bool getAlignMode() const override { return m_alignMode; } 164 void setAlignMode(bool on); 165 setIlluminateLocalFeatures(bool i)166 void setIlluminateLocalFeatures(bool i) { m_illuminateLocalFeatures = i; } setShowWorkTitle(bool show)167 void setShowWorkTitle(bool show) { m_showWorkTitle = show; } setShowDuration(bool show)168 void setShowDuration(bool show) { m_showDuration = show; } 169 170 /** 171 * The sample rate that is used for playback. This is usually the 172 * rate of the main model, but not always. Models whose rates 173 * differ from this will play back at the wrong speed -- there is 174 * no per-model resampler. 175 */ 176 sv_samplerate_t getPlaybackSampleRate() const; 177 178 /** 179 * The sample rate of the audio output device. If the playback 180 * sample rate differs from this, everything will be resampled at 181 * the output stage (but not before). 182 */ 183 sv_samplerate_t getDeviceSampleRate() const; 184 185 /** 186 * The sample rate of the current main model. This may in theory 187 * differ from the playback sample rate, in which case even the 188 * main model will play at the wrong speed. 189 */ getMainModelSampleRate()190 sv_samplerate_t getMainModelSampleRate() const { return m_mainModelSampleRate; } 191 setMainModelSampleRate(sv_samplerate_t sr)192 void setMainModelSampleRate(sv_samplerate_t sr) { m_mainModelSampleRate = sr; } 193 194 /** 195 * Take a "design pixel" size and scale it for the actual 196 * display. This is relevant to hi-dpi systems that do not do 197 * pixel doubling (i.e. Windows and Linux rather than OS/X). 198 */ 199 static int scalePixelSize(int pixels); 200 201 enum OverlayMode { 202 NoOverlays, 203 GlobalOverlays, 204 StandardOverlays, 205 AllOverlays 206 }; 207 void setOverlayMode(OverlayMode mode); getOverlayMode()208 OverlayMode getOverlayMode() const { return m_overlayMode; } 209 210 void setShowCentreLine(bool show); shouldShowCentreLine()211 bool shouldShowCentreLine() const { return m_showCentreLine; } 212 shouldShowDuration()213 bool shouldShowDuration() const { 214 return m_overlayMode != NoOverlays && m_showDuration; 215 } shouldShowFrameCount()216 bool shouldShowFrameCount() const { 217 return m_showCentreLine && shouldShowDuration(); 218 } shouldShowVerticalScale()219 bool shouldShowVerticalScale() const { 220 return m_overlayMode != NoOverlays; 221 } shouldShowVerticalColourScale()222 bool shouldShowVerticalColourScale() const { 223 return m_overlayMode == AllOverlays; 224 } shouldShowHorizontalValueScale()225 bool shouldShowHorizontalValueScale() const { // for layers where x != time 226 return m_overlayMode != NoOverlays; 227 } shouldShowSelectionExtents()228 bool shouldShowSelectionExtents() const { 229 return m_overlayMode != NoOverlays && m_overlayMode != GlobalOverlays; 230 } shouldShowLayerNames()231 bool shouldShowLayerNames() const { 232 return m_overlayMode == AllOverlays; 233 } shouldShowScaleGuides()234 bool shouldShowScaleGuides() const { 235 return m_overlayMode != NoOverlays; 236 } shouldShowWorkTitle()237 bool shouldShowWorkTitle() const { 238 return m_showWorkTitle; 239 } shouldIlluminateLocalFeatures()240 bool shouldIlluminateLocalFeatures() const { 241 return m_illuminateLocalFeatures; 242 } shouldShowFeatureLabels()243 bool shouldShowFeatureLabels() const { 244 return m_overlayMode != NoOverlays && m_overlayMode != GlobalOverlays; 245 } 246 247 void setZoomWheelsEnabled(bool enable); getZoomWheelsEnabled()248 bool getZoomWheelsEnabled() const { return m_zoomWheelsEnabled; } 249 250 /** 251 * Enable or disable opportunistic editing. This allows certain 252 * edits while not in edit modes - e.g. double-click on an item 253 * while in navigate mode to open an edit dialog. It is enabled by 254 * default, but it may be undesirable if the application is 255 * intended to be "read-only". 256 * 257 * This setting makes no difference to behaviour when actually in 258 * editing modes. 259 * 260 * Unlike some other options, this is considered to be 261 * application-build-specific and is not restored from settings. 262 */ 263 void setOpportunisticEditingEnabled(bool enable); getOpportunisticEditingEnabled()264 bool getOpportunisticEditingEnabled() const { 265 return m_opportunisticEditingEnabled; 266 } 267 268 void setGlobalDarkBackground(bool dark); 269 bool getGlobalDarkBackground() const; 270 271 signals: 272 /** Emitted when user causes the global centre frame to change. */ 273 void globalCentreFrameChanged(sv_frame_t frame); 274 275 /** Emitted when user scrolls a view, but doesn't affect global centre. */ 276 void viewCentreFrameChanged(View *v, sv_frame_t frame); 277 278 /** Emitted when a view zooms. */ 279 void viewZoomLevelChanged(View *v, ZoomLevel zoom, bool locked); 280 281 /** Emitted when the playback frame changes. */ 282 void playbackFrameChanged(sv_frame_t frame); 283 284 /** Emitted when the output or record levels change. Values in range 0.0 -> 1.0. */ 285 void monitoringLevelsChanged(float left, float right); 286 287 /** Emitted whenever the selection has changed. */ 288 void selectionChanged(); 289 290 /** Emitted when the selection has been changed through an 291 * explicit selection-editing action. *Not* emitted when the 292 * selection has been changed through undo or redo. */ 293 void selectionChangedByUser(); 294 295 /** Emitted when the in-progress (rubberbanding) selection has changed. */ 296 void inProgressSelectionChanged(); 297 298 /** Emitted when the tool mode has been changed. */ 299 void toolModeChanged(); 300 301 /** Emitted when the play loop mode has been changed. */ 302 void playLoopModeChanged(); 303 void playLoopModeChanged(bool); 304 305 /** Emitted when the play selection mode has been changed. */ 306 void playSelectionModeChanged(); 307 void playSelectionModeChanged(bool); 308 309 /** Emitted when the play solo mode has been changed. */ 310 void playSoloModeChanged(); 311 void playSoloModeChanged(bool); 312 313 /** Emitted when the alignment mode has been changed. */ 314 void alignModeChanged(); 315 void alignModeChanged(bool); 316 317 /** Emitted when the overlay mode has been changed. */ 318 void overlayModeChanged(); 319 320 /** Emitted when the centre line visibility has been changed. */ 321 void showCentreLineChanged(); 322 323 /** Emitted when the zoom wheels have been toggled. */ 324 void zoomWheelsEnabledChanged(); 325 326 /** Emitted when editing-enabled has been toggled. */ 327 void opportunisticEditingEnabledChanged(); 328 329 /** Emitted when any loggable activity has occurred. */ 330 void activity(QString); 331 332 public slots: 333 void viewCentreFrameChanged(sv_frame_t, bool, PlaybackFollowMode); 334 void viewZoomLevelChanged(ZoomLevel, bool); 335 void setGlobalCentreFrame(sv_frame_t); 336 void setPlaybackFrame(sv_frame_t); 337 void playStatusChanged(bool playing); 338 void recordStatusChanged(bool recording); 339 340 protected slots: 341 void checkPlayStatus(); 342 void seek(sv_frame_t); 343 //!!! void considerZoomChange(void *, int, bool); 344 345 protected: 346 AudioPlaySource *m_playSource; 347 AudioRecordTarget *m_recordTarget; 348 349 sv_frame_t m_globalCentreFrame; 350 ZoomLevel m_globalZoom; 351 mutable sv_frame_t m_playbackFrame; 352 ModelId m_playbackModel; 353 sv_samplerate_t m_mainModelSampleRate; 354 355 float m_lastLeft; 356 float m_lastRight; 357 358 MultiSelection m_selections; 359 Selection m_inProgressSelection; 360 bool m_inProgressExclusive; 361 362 Clipboard m_clipboard; 363 364 ToolMode m_toolMode; 365 std::map<const View *, ToolMode> m_toolModeOverrides; 366 367 bool m_playLoopMode; 368 bool m_playSelectionMode; 369 bool m_playSoloMode; 370 bool m_alignMode; 371 372 void setSelections(const MultiSelection &ms, bool quietly = false); 373 void signalSelectionChange(); 374 375 class SetSelectionCommand : public Command 376 { 377 public: 378 SetSelectionCommand(ViewManager *vm, const MultiSelection &ms); 379 virtual ~SetSelectionCommand(); 380 void execute() override; 381 void unexecute() override; 382 QString getName() const override; 383 384 protected: 385 ViewManager *m_vm; 386 MultiSelection m_oldSelection; 387 MultiSelection m_newSelection; 388 }; 389 390 OverlayMode m_overlayMode; 391 bool m_zoomWheelsEnabled; 392 bool m_opportunisticEditingEnabled; 393 bool m_showCentreLine; 394 bool m_illuminateLocalFeatures; 395 bool m_showWorkTitle; 396 bool m_showDuration; 397 398 QPalette m_lightPalette; 399 QPalette m_darkPalette; 400 }; 401 402 #endif 403 404