]> git.sesse.net Git - kdenlive/blob - src/audioscopes/abstractaudioscopewidget.h
3bc6beadb5e8c7ae1d60b8ba2f2914d27fce3aa6
[kdenlive] / src / audioscopes / abstractaudioscopewidget.h
1 /***************************************************************************
2  *   Copyright (C) 2010 by Simon Andreas Eugster (simon.eu@gmail.com)      *
3  *   This file is part of kdenlive. See www.kdenlive.org.                  *
4  *                                                                         *
5  *   This program is free software; you can redistribute it and/or modify  *
6  *   it under the terms of the GNU General Public License as published by  *
7  *   the Free Software Foundation; either version 2 of the License, or     *
8  *   (at your option) any later version.                                   *
9  ***************************************************************************/
10
11 #ifndef ABSTRACTAUDIOSCOPEWIDGET_H
12 #define ABSTRACTAUDIOSCOPEWIDGET_H
13
14
15 #include <QtCore>
16 #include <QWidget>
17
18 class QMenu;
19
20 class Monitor;
21 class Render;
22
23 class AbstractAudioScopeWidget : public QWidget
24 {
25     Q_OBJECT
26 public:
27     AbstractAudioScopeWidget(Monitor *projMonitor, Monitor *clipMonitor, bool trackMouse = false, QWidget *parent = 0);
28     virtual ~AbstractAudioScopeWidget(); // Must be virtual because of inheritance, to avoid memory leaks
29     QPalette m_scopePalette;
30
31     /** Initializes widget settings (reads configuration).
32       Has to be called in the implementing object. */
33     void init();
34
35     /** Does this scope have auto-refresh enabled */
36     bool autoRefreshEnabled();
37
38     ///// Unimplemented /////
39
40     virtual QString widgetName() const = 0;
41
42     ///// Variables /////
43     static const QPen penThick;
44     static const QPen penThin;
45     static const QPen penLight;
46     static const QPen penDark;
47
48 protected:
49     ///// Variables /////
50
51     Monitor *m_projMonitor;
52     Monitor *m_clipMonitor;
53     Render *m_activeRender;
54
55
56     /** The context menu. Feel free to add new entries in your implementation. */
57     QMenu *m_menu;
58
59     /** Enables auto refreshing of the scope.
60         This is when a new frame is shown on the active monitor.
61         Resize events always force a recalculation. */
62     QAction *m_aAutoRefresh;
63
64     /** Realtime rendering. Should be disabled if it is not supported.
65         Use the accelerationFactor variable passed to the render functions as a hint of
66         how many times faster the scope should be calculated. */
67     QAction *m_aRealtime;
68
69     /** The mouse position; Updated when the mouse enters the widget
70         AND mouse tracking has been enabled. */
71     QPoint m_mousePos;
72     /** Knows whether the mouse currently lies within the widget or not.
73         Can e.g. be used for drawing a HUD only when the mouse is in the widget. */
74     bool m_mouseWithinWidget;
75
76     /** Offset from the widget's borders */
77     const uchar offset;
78
79     /** The rect on the widget we're painting in.
80         Can be used by the implementing widget, e.g. in the render methods.
81         Is updated when necessary (size changes). */
82     QRect m_scopeRect;
83
84     /** Images storing the calculated layers. Will be used on repaint events. */
85     QImage m_imgHUD;
86     QImage m_imgScope;
87     QImage m_imgBackground;
88
89     /** The acceleration factors can be accessed also by other renderer tasks,
90         e.g. to display the scope's acceleration factor in the HUD renderer. */
91     int m_accelFactorHUD;
92     int m_accelFactorScope;
93     int m_accelFactorBackground;
94
95     /** Reads the widget's configuration.
96         Can be extended in the implementing subclass (make sure to run readConfig as well). */
97     virtual void readConfig();
98     /** Writes the widget configuration.
99         Implementing widgets have to implement an own method and run it in their destructor. */
100     void writeConfig();
101     /** Identifier for the widget's configuration. */
102     QString configName();
103
104
105     ///// Unimplemented Methods /////
106
107     /** Where on the widget we can paint in.
108         May also update other variables that depend on the widget's size.  */
109     virtual QRect scopeRect() = 0;
110
111     /** @brief HUD renderer. Must emit signalHUDRenderingFinished(). @see renderScope */
112     virtual QImage renderHUD(uint accelerationFactor) = 0;
113     /** @brief Scope renderer. Must emit signalScopeRenderingFinished()
114         when calculation has finished, to allow multi-threading.
115         accelerationFactor hints how much faster than usual the calculation should be accomplished, if possible. */
116     virtual QImage renderScope(uint accelerationFactor,
117                                const QVector<int16_t> audioFrame, const int freq, const int num_channels, const int num_samples) = 0;
118     /** @brief Background renderer. Must emit signalBackgroundRenderingFinished(). @see renderScope */
119     virtual QImage renderBackground(uint accelerationFactor) = 0;
120
121     /** Must return true if the HUD layer depends on the input monitor.
122         If it does not, then it does not need to be re-calculated when
123         a new frame from the monitor is incoming. */
124     virtual bool isHUDDependingOnInput() const = 0;
125     /** @see isHUDDependingOnInput() */
126     virtual bool isScopeDependingOnInput() const = 0;
127     /** @see isHUDDependingOnInput() */
128     virtual bool isBackgroundDependingOnInput() const = 0;
129
130     ///// Can be reimplemented /////
131     /** Calculates the acceleration factor to be used by the render thread.
132         This method can be refined in the subclass if required. */
133     virtual uint calculateAccelFactorHUD(uint oldMseconds, uint oldFactor);
134     virtual uint calculateAccelFactorScope(uint oldMseconds, uint oldFactor);
135     virtual uint calculateAccelFactorBackground(uint oldMseconds, uint oldFactor);
136
137     ///// Reimplemented /////
138
139     void mouseMoveEvent(QMouseEvent *);
140     void leaveEvent(QEvent *);
141     void mouseReleaseEvent(QMouseEvent *);
142     void paintEvent(QPaintEvent *);
143     void resizeEvent(QResizeEvent *);
144     void showEvent(QShowEvent *); // Called when the widget is activated via the Menu entry
145     //    void raise(); // Called only when  manually calling the event -> useless
146
147
148 protected slots:
149     /** Forces an update of all layers. */
150     void forceUpdate(bool doUpdate = true);
151     void forceUpdateHUD();
152     void forceUpdateScope();
153     void forceUpdateBackground();
154     void slotAutoRefreshToggled(bool);
155
156 signals:
157     /** mseconds represent the time taken for the calculation,
158         accelerationFactor is the acceleration factor that has been used. */
159     void signalHUDRenderingFinished(uint mseconds, uint accelerationFactor);
160     void signalScopeRenderingFinished(uint mseconds, uint accelerationFactor);
161     void signalBackgroundRenderingFinished(uint mseconds, uint accelerationFactor);
162
163     /** For the mouse position itself see m_mousePos.
164         To check whether the mouse has leaved the widget, see m_mouseWithinWidget. */
165     void signalMousePositionChanged();
166
167     /** Do we need the renderer to send its frames to us? */
168     void requestAutoRefresh(bool);
169
170 private:
171
172     /** Counts the number of frames that have been rendered in the active monitor.
173       The frame number will be reset when the calculation starts for the current frame. */
174     QAtomicInt m_newHUDFrames;
175     QAtomicInt m_newScopeFrames;
176     QAtomicInt m_newBackgroundFrames;
177
178     /** Counts the number of updates that, unlike new frames, force a recalculation
179       of the scope, like for example a resize event. */
180     QAtomicInt m_newHUDUpdates;
181     QAtomicInt m_newScopeUpdates;
182     QAtomicInt m_newBackgroundUpdates;
183
184     /** The semaphores ensure that the QFutures for the HUD/Scope/Background threads cannot
185       be assigned a new thread while it is still running. (Could cause deadlocks and other
186       nasty things known from parallelism.) */
187     QSemaphore m_semaphoreHUD;
188     QSemaphore m_semaphoreScope;
189     QSemaphore m_semaphoreBackground;
190
191     QFuture<QImage> m_threadHUD;
192     QFuture<QImage> m_threadScope;
193     QFuture<QImage> m_threadBackground;
194
195     bool initialDimensionUpdateDone;
196     bool m_requestForcedUpdate;
197
198 //    QImage m_scopeImage;
199     QVector<int16_t> m_audioFrame; //NEW
200     int m_freq;
201     int m_nChannels;
202     int m_nSamples;
203
204     QString m_widgetName;
205
206     void prodHUDThread();
207     void prodScopeThread();
208     void prodBackgroundThread();
209
210 public slots:
211     /** @brief Must be called when the active monitor has shown a new frame.
212       This slot must be connected in the implementing class, it is *not*
213       done in this abstract class. */
214 //    void slotActiveMonitorChanged(bool isClipMonitor);
215
216 private slots:
217     void customContextMenuRequested(const QPoint &pos);
218     /** To be called when a new frame has been received.
219       The scope then decides whether and when it wants to recalculate the scope, depending
220       on whether it is currently visible and whether a calculation thread is already running. */
221     void slotRenderZoneUpdated();
222 //    void slotRenderZoneUpdated(QImage);//OLD
223     void slotReceiveAudio(const QVector<int16_t>& sampleData, int freq, int num_channels, int num_samples); // NEW, TODO comment
224     /** The following slots are called when rendering of a component has finished. They e.g. update
225       the widget and decide whether to immediately restart the calculation thread. */
226     void slotHUDRenderingFinished(uint mseconds, uint accelerationFactor);
227     void slotScopeRenderingFinished(uint mseconds, uint accelerationFactor);
228     void slotBackgroundRenderingFinished(uint mseconds, uint accelerationFactor);
229
230     /** Resets the acceleration factors to 1 when realtime rendering is disabled. */
231     void slotResetRealtimeFactor(bool realtimeChecked);
232
233 };
234
235 #endif // ABSTRACTAUDIOSCOPEWIDGET_H