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