]> git.sesse.net Git - kdenlive/blob - src/scopes/scopemanager.cpp
Missing files from scope manager merge
[kdenlive] / src / scopes / scopemanager.cpp
1 /***************************************************************************
2  *   Copyright (C) 2011 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 #include "scopemanager.h"
12
13 #include <QDockWidget>
14
15 #include "definitions.h"
16 #include "monitormanager.h"
17 #include "kdenlivesettings.h"
18
19 //#define DEBUG_SM
20 #ifdef DEBUG_SM
21 #include <QtCore/QDebug>
22 #endif
23
24 ScopeManager::ScopeManager(MonitorManager *monitorManager) :
25     m_monitorManager(monitorManager),
26     m_lastConnectedRenderer(NULL)
27 {
28     m_signalMapper = new QSignalMapper(this);
29
30     bool b = true;
31     b &= connect(m_monitorManager, SIGNAL(checkColorScopes()), this, SLOT(slotUpdateActiveRenderer()));
32     b &= connect(m_signalMapper, SIGNAL(mapped(QString)), this, SLOT(slotRequestFrame(QString)));
33     Q_ASSERT(b);
34
35     slotUpdateActiveRenderer();
36 }
37
38 bool ScopeManager::addScope(AbstractAudioScopeWidget *audioScope, QDockWidget *audioScopeWidget)
39 {
40     bool added = false;
41     int exists = false;
42     // Only add the scope if it does not exist yet in the list
43     for (int i = 0; i < m_audioScopes.size(); i++) {
44         if (m_audioScopes[i].scope == audioScope) {
45             exists = true;
46             break;
47         }
48     }
49     if (!exists) {
50         // Add scope to the list, set up signal/slot connections
51 #ifdef DEBUG_SM
52         qDebug() << "Adding scope to scope manager: " << audioScope->widgetName();
53 #endif
54
55         m_signalMapper->setMapping(audioScopeWidget, QString(audioScope->widgetName()));
56
57         AudioScopeData asd;
58         asd.scope = audioScope;
59         asd.scopeDockWidget = audioScopeWidget;
60         m_audioScopes.append(asd);
61
62         bool b = true;
63         b &= connect(audioScope, SIGNAL(requestAutoRefresh(bool)), this, SLOT(slotCheckActiveScopes()));
64 //         b &= connect(audioScope, SIGNAL(signalFrameRequest(QString)), this, SLOT(slotRequestFrame(QString)));
65         if (audioScopeWidget != NULL) {
66             b &= connect(audioScopeWidget, SIGNAL(visibilityChanged(bool)), this, SLOT(slotCheckActiveScopes()));
67             b &= connect(audioScopeWidget, SIGNAL(visibilityChanged(bool)), m_signalMapper, SLOT(map()));
68         }
69         Q_ASSERT(b);
70
71         added = true;
72     }
73     return added;
74 }
75 bool ScopeManager::addScope(AbstractGfxScopeWidget *colorScope, QDockWidget *colorScopeWidget)
76 {
77     bool added = false;
78     int exists = false;
79     for (int i = 0; i < m_colorScopes.size(); i++) {
80         if (m_colorScopes[i].scope == colorScope) {
81             exists = true;
82             break;
83         }
84     }
85     if (!exists) {
86 #ifdef DEBUG_SM
87         qDebug() << "Adding scope to scope manager: " << colorScope->widgetName();
88 #endif
89
90         m_signalMapper->setMapping(colorScopeWidget, QString(colorScope->widgetName()));
91
92         GfxScopeData gsd;
93         gsd.scope = colorScope;
94         gsd.scopeDockWidget = colorScopeWidget;
95         m_colorScopes.append(gsd);
96
97         bool b = true;
98         b &= connect(colorScope, SIGNAL(requestAutoRefresh(bool)), this, SLOT(slotCheckActiveScopes()));
99         b &= connect(colorScope, SIGNAL(signalFrameRequest(QString)), this, SLOT(slotRequestFrame(QString)));
100         if (colorScopeWidget != NULL) {
101             b &= connect(colorScopeWidget, SIGNAL(visibilityChanged(bool)), this, SLOT(slotCheckActiveScopes()));
102             b &= connect(colorScopeWidget, SIGNAL(visibilityChanged(bool)), m_signalMapper, SLOT(map()));
103         }
104         Q_ASSERT(b);
105
106         added = true;
107     }
108     return added;
109 }
110
111
112 void ScopeManager::slotDistributeAudio(QVector<int16_t> sampleData, int freq, int num_channels, int num_samples)
113 {
114 #ifdef DEBUG_SM
115     qDebug() << "ScopeManager: Starting to distribute audio.";
116 #endif
117     for (int i = 0; i < m_audioScopes.size(); i++) {
118         // Distribute audio to all scopes that are visible and want to be refreshed
119         if (!m_audioScopes[i].scope->visibleRegion().isEmpty()) {
120             if (m_audioScopes[i].scope->autoRefreshEnabled()) {
121                 m_audioScopes[i].scope->slotReceiveAudio(sampleData, freq, num_channels, num_samples);
122 #ifdef DEBUG_SM
123                 qDebug() << "ScopeManager: Distributed audio to " << m_audioScopes[i].scope->widgetName();
124 #endif
125             }
126         }
127     }
128
129     checkActiveAudioScopes();
130 }
131 void ScopeManager::slotDistributeFrame(QImage image)
132 {
133 #ifdef DEBUG_SM
134     qDebug() << "ScopeManager: Starting to distribute frame.";
135 #endif
136     for (int i = 0; i < m_colorScopes.size(); i++) {
137         if (!m_colorScopes[i].scope->visibleRegion().isEmpty()) {
138             if (m_colorScopes[i].scope->autoRefreshEnabled()) {
139                 m_colorScopes[i].scope->slotRenderZoneUpdated(image);
140 #ifdef DEBUG_SM
141                 qDebug() << "ScopeManager: Distributed frame to " << m_colorScopes[i].scope->widgetName();
142 #endif
143             } else if (m_colorScopes[i].singleFrameRequested) {
144                 // Special case: Auto refresh is disabled, but user requested an update (e.g. by clicking).
145                 // Force the scope to update.
146                 m_colorScopes[i].singleFrameRequested = false;
147                 m_colorScopes[i].scope->slotRenderZoneUpdated(image);
148                 m_colorScopes[i].scope->forceUpdateScope();
149 #ifdef DEBUG_SM
150                 qDebug() << "ScopeManager: Distributed forced frame to " << m_colorScopes[i].scope->widgetName();
151 #endif
152             }
153         }
154     }
155
156     checkActiveColourScopes();
157 }
158
159
160 void ScopeManager::slotRequestFrame(const QString widgetName)
161 {
162 #ifdef DEBUG_SM
163     qDebug() << "ScopeManager: New frame was requested by " << widgetName;
164 #endif
165
166     // Search for the scope in the lists and tag it to trigger a forced update
167     // in the distribution slots
168     for (int i = 0; i < m_colorScopes.size(); i++) {
169         if (m_colorScopes[i].scope->widgetName() == widgetName) {
170             m_colorScopes[i].singleFrameRequested = true;
171             break;
172         }
173     }
174     for (int i = 0; i < m_audioScopes.size(); i++) {
175         if (m_audioScopes[i].scope->widgetName() == widgetName) {
176             m_audioScopes[i].singleFrameRequested = true;
177             break;
178         }
179     }
180     m_lastConnectedRenderer->sendFrameUpdate();
181 }
182
183
184
185 void ScopeManager::slotUpdateActiveRenderer()
186 {
187     bool b = true;
188
189     // Disconnect old connections
190     if (m_lastConnectedRenderer != NULL) {
191 #ifdef DEBUG_SM
192         qDebug() << "Disconnected previous renderer: " << m_lastConnectedRenderer->name();
193 #endif
194         b &= m_lastConnectedRenderer->disconnect(this);
195         Q_ASSERT(b);
196     }
197
198     m_lastConnectedRenderer = m_monitorManager->activeRenderer();
199
200     // Connect new renderer
201     if (m_lastConnectedRenderer != NULL) {
202         b &= connect(m_lastConnectedRenderer, SIGNAL(frameUpdated(QImage)),
203                 this, SLOT(slotDistributeFrame(QImage)), Qt::UniqueConnection);
204         b &= connect(m_lastConnectedRenderer, SIGNAL(audioSamplesSignal(QVector<int16_t>,int,int,int)),
205                 this, SLOT(slotDistributeAudio(QVector<int16_t>,int,int,int)), Qt::UniqueConnection);
206         Q_ASSERT(b);
207
208 #ifdef DEBUG_SM
209         qDebug() << "Renderer connected to ScopeManager: " << m_lastConnectedRenderer->name();
210 #endif
211
212         if (imagesAcceptedByScopes()) {
213 #ifdef DEBUG_SM
214             qDebug() << "Some scopes accept images, triggering frame update.";
215 #endif
216             m_lastConnectedRenderer->sendFrameUpdate();
217         }
218     }
219 }
220
221
222 void ScopeManager::slotCheckActiveScopes()
223 {
224 #ifdef DEBUG_SM
225     qDebug() << "Checking active scopes ...";
226 #endif
227     checkActiveAudioScopes();
228     checkActiveColourScopes();
229 }
230
231
232 bool ScopeManager::audioAcceptedByScopes() const
233 {
234     bool accepted = false;
235     for (int i = 0; i < m_audioScopes.size(); i++) {
236         if (!m_audioScopes[i].scope->visibleRegion().isEmpty() && m_audioScopes[i].scope->autoRefreshEnabled()) {
237             accepted = true;
238             break;
239         }
240     }
241 #ifdef DEBUG_SM
242     qDebug() << "Any scope accepting audio? " << accepted;
243 #endif
244     return accepted;
245 }
246 bool ScopeManager::imagesAcceptedByScopes() const
247 {
248     bool accepted = false;
249     for (int i = 0; i < m_colorScopes.size(); i++) {
250         if (!m_colorScopes[i].scope->visibleRegion().isEmpty() && m_colorScopes[i].scope->autoRefreshEnabled()) {
251             accepted = true;
252             break;
253         }
254     }
255 #ifdef DEBUG_SM
256     qDebug() << "Any scope accepting images? " << accepted;
257 #endif
258     return accepted;
259 }
260
261
262
263 void ScopeManager::checkActiveAudioScopes()
264 {
265     bool audioStillRequested = audioAcceptedByScopes();
266
267 #ifdef DEBUG_SM
268     qDebug() << "ScopeManager: New audio data still requested? " << audioStillRequested;
269 #endif
270
271     KdenliveSettings::setMonitor_audio(audioStillRequested);
272     m_monitorManager->slotUpdateAudioMonitoring();
273 }
274 void ScopeManager::checkActiveColourScopes()
275 {
276     bool imageStillRequested = imagesAcceptedByScopes();
277
278 #ifdef DEBUG_SM
279     qDebug() << "ScopeManager: New frames still requested? " << imageStillRequested;
280 #endif
281
282     // Notify monitors whether frames are still required
283     Monitor *monitor;
284     monitor = static_cast<Monitor*>( m_monitorManager->monitor(Kdenlive::projectMonitor) );
285     if (monitor != NULL) { monitor->render->sendFrameForAnalysis = imageStillRequested; }
286
287     monitor = static_cast<Monitor*>( m_monitorManager->monitor(Kdenlive::clipMonitor) );
288     if (monitor != NULL) { monitor->render->sendFrameForAnalysis = imageStillRequested; }
289
290     RecMonitor *recMonitor = static_cast<RecMonitor*>( m_monitorManager->monitor(Kdenlive::recordMonitor) );
291     if (recMonitor != NULL) { recMonitor->analyseFrames(imageStillRequested); }
292 }
293