MainWorkflow.h 15.5 KB
Newer Older
1 2 3 4
/*****************************************************************************
 * MainWorkflow.h : Will query all of the track workflows to render the final
 *                  image
 *****************************************************************************
Ludovic Fauvet's avatar
Ludovic Fauvet committed
5
 * Copyright (C) 2008-2010 VideoLAN
6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
 *
 * Authors: Hugo Beauzee-Luyssen <hugo@vlmc.org>
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 2
 * of the License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
 *****************************************************************************/

#ifndef MAINWORKFLOW_H
#define MAINWORKFLOW_H

27
#include "EffectsEngine.h"
28
#include "Singleton.hpp"
29
#include <QXmlStreamWriter>
30
#include "Types.h"
31

32
class   Clip;
33
class   ClipHelper;
34
class   EffectsEngine;
35
class   Effect;
36
class   TrackHandler;
37
class   TrackWorkflow;
38 39 40
namespace   Workflow
{
    class   Frame;
41
    class   AudioSample;
42
}
43

44 45 46 47 48
class   QDomDocument;
class   QDomElement;
class   QMutex;
class   QReadWriteLock;

49 50 51
#include <QObject>
#include <QUuid>

52 53 54
/**
 *  \class  Represent the Timeline backend.
 */
55
class   MainWorkflow : public QObject, public Singleton<MainWorkflow>
56 57 58 59
{
    Q_OBJECT

    public:
60
        EffectsEngine::EffectHelper     *addEffect( Effect* effect, quint32 trackId,
61
                                                    const QUuid &uuid, Workflow::TrackType type );
62

63 64 65
        /**
         *  \brief      Initialize the workflow for the render.
         *
66 67
         *  \param      width   The width to use with this render session.
         *  \param      height  The height to use with this render session.
68
         *  This will basically activate all the tracks, newLengthso they can render.
69
         */
70
        void                    startRender( quint32 width, quint32 height, double fps );
71 72 73 74 75 76 77 78 79
        /**
         *  \brief      Gets a frame from the workflow
         *
         *  \return A pointer to an output buffer. This pointer must NOT be released.
         *          Both types of this output buffer are not guarantied to be filled.
         *          However, if VideoTrack was passed as trackType, the video member of
         *          the output buffer is guarantied to be filled. The same applies for
         *          AudioTrack
         *  \param  trackType   The type of track you wish to get the render from.
80
         *  \param  paused      The paused state of the renderer
81
         */
82
        const Workflow::OutputBuffer    *getOutput( Workflow::TrackType trackType, bool paused );
83 84 85
        /**
         *  \brief              Set the workflow position by the desired frame
         *  \param              currentFrame: The desired frame to render from
86
         *  \param              reason: The program part which required this frame change
87
                                        (to avoid cyclic events)
88
        */
89
        void                    setCurrentFrame( qint64 currentFrame,
90
                                                Vlmc::FrameChangedReason reason );
91

92
        /**
93
         *  \brief              Get the workflow length in frames.
94 95
         *  \return             Returns the global length of the workflow
         *                      in frames.
96
        */
97
        qint64                  getLengthFrame() const;
98

99
        /**
100
         *  \brief              Get the currently rendered frame.
101 102 103
         *  \param      lock    If true, m_currentFrameLock will be locked for read.
         *                      If false, it won't be locked. This is usefull when calling
         *                      getCurentFrame from underlying workflows
104
         *  \return             Returns the current frame.
105 106
         *  \warning            Locks the m_currentFrameLock ReadWriteLock, unless false is
         *                      passed.
107
         */
108
        qint64                  getCurrentFrame( bool lock = true ) const;
109

110
        /**
111 112 113 114 115
         *  \brief      Stops the rendering.
         *
         *  This will stop every ClipWorkflow that are currently rendering.
         *  Calling this methid will cause the workflow to return to frame 0, and emit
         *  the signal frameChanged(), with the reason: Renderer
116 117 118
         */
        void                    stop();

119 120 121 122 123 124 125
        /**
         *  \brief              Unconditionnaly switch to the next frame.
         *
         *  \param  trackType   The type of the frame counter to increment.
         *                      Though it seems odd to speak about frame for AudioTrack,
         *                      it's mainly a render position used for
         *                      synchronisation purpose.
126
         *  \sa         previousFrame( Workflow::TrackType );
127
         */
128
        void                    nextFrame( Workflow::TrackType trackType );
129 130 131 132 133 134 135
        /**
         *  \brief      Unconditionnaly switch to the previous frame.
         *
         *  \param      trackType   The type of the frame counter to decrement.
         *                          Though it seems odd to speak about frame for
         *                          AudioTrack, it's mainly a render position used for
         *                          synchronisation purpose.
136
         *  \sa         nextFrame( Workflow::TrackType );
137
         */
138
        void                    previousFrame( Workflow::TrackType trackType );
139

140 141 142 143 144 145 146 147 148 149
        /**
         *  \brief              Return the given clip position.
         *
         *  \param      uuid        The clip uuid
         *  \param      trackId     The track containing the clip
         *  \param      trackType   The type of the track containing the clip
         *  \return                 The given clip position, in frame. If not found, -1
         *                          is returned.
         */
        qint64                  getClipPosition( const QUuid& uuid, unsigned int trackId,
150
                                                Workflow::TrackType trackType ) const;
151

152 153 154 155 156 157 158
        /**
         *  \brief      Mute a track.
         *
         *  A muted track will not be asked for render. It won't even emit endReached
         *  signal. To summerize, a mutted track is an hard deactivated track.
         *  \param  trackId     The id of the track to mute
         *  \param  trackType   The type of the track to mute.
159
         *  \sa     unmuteTrack( unsigned int, Workflow::TrackType );
160 161
         */
        void                    muteTrack( unsigned int trackId,
162
                                           Workflow::TrackType trackType );
163 164 165 166 167
        /**
         *  \brief      Unmute a track.
         *
         *  \param  trackId     The id of the track to unmute
         *  \param  trackType   The type of the track to unmute.
168
         *  \sa     muteTrack( unsigned int, Workflow::TrackType );
169 170
         */
        void                    unmuteTrack( unsigned int trackId,
171
                                             Workflow::TrackType trackType );
172

173 174 175 176 177 178 179 180
        /**
         *  \brief      Mute a clip.
         *
         *  \param  uuid        The clip's uuid.
         *  \param  trackId     The id of the track containing the clip.
         *  \param  trackType   The type of the track containing the clip.
         */
        void                    muteClip( const QUuid& uuid, unsigned int trackId,
181
                                          Workflow::TrackType trackType );
182 183 184 185 186 187 188 189 190

        /**
         *  \brief      Unmute a clip.
         *
         *  \param  uuid        The clip's uuid.
         *  \param  trackId     The id of the track containing the clip.
         *  \param  trackType   The type of the track containing the clip.
         */
        void                    unmuteClip( const QUuid& uuid, unsigned int trackId,
191
                                          Workflow::TrackType trackType );
192

193 194 195 196 197 198
        /**
         *  \brief              Get the number of track for a specific type
         *
         *  \param  trackType   The type of the tracks to count
         *  \return             The number of track for the type trackType
         */
199
        int                     getTrackCount( Workflow::TrackType trackType ) const;
200

201 202 203 204 205 206 207 208 209
        /**
         *  \brief      Get the width used for rendering.
         *
         *  This value is used by the ClipWorkflow that generates the frames.
         *  If this value is edited in the preferences, it will only change after the
         *  current render has been stopped.
         *  \return     The width (in pixels) of the currently rendered frames
         *  \sa         getHeight()
         */
210
        quint32                getWidth() const;
211 212 213 214 215 216 217 218 219
        /**
         *  \brief      Get the height used for rendering.
         *
         *  This value is used by the ClipWorkflow that generates the frames.
         *  If this value is edited in the preferences, it will only change after the
         *  current render has been stopped.
         *  \return     The height (in pixels) of the currently rendered frames
         *  \sa         getWidth()
         */
220
        quint32                getHeight() const;
221

222 223 224 225 226 227 228 229
        /**
         *  \brief          Will render one frame only
         *
         *  It will change the ClipWorkflow frame getting mode from Get to Pop, just for
         *  one frame
         */
        void                    renderOneFrame();

230 231 232 233 234 235 236 237 238
        /**
         *  \brief              Set the render speed.
         *
         *  This will activate or deactivate vlc's pace-control
         *  \param  val         If true, ClipWorkflow will use no-pace-control
         *                      else, pace-control.
         */
        void                    setFullSpeedRender( bool val );

239 240 241 242 243 244 245 246
        /**
         *  \return     true if the current workflow contains the clip which the uuid was
         *              passed. Falsed otherwise.
         *
         *  \param      uuid    The Clip uuid, not the ClipHelper's.
         */
        bool                    contains( const QUuid& uuid ) const;

247 248 249 250 251 252 253 254
        /**
         *  \brief      Stop the frame computing process.
         *
         *  This will stop all the currently running ClipWorkflow.
         *  This is meant to be called just before the stop() method.
         */
        void                    stopFrameComputing();

255 256
        TrackWorkflow           *track( Workflow::TrackType type, quint32 trackId );

257
        const Workflow::Frame   *blackOutput() const;
258

259
    private:
260
        MainWorkflow( int trackCount = 64 );
261
        ~MainWorkflow();
262 263 264 265 266 267 268
        /**
         *  \brief  Compute the length of the workflow.
         *
         *  This is meant to be used internally, after an operation occurs on the workflow
         *  such as adding a clip, removing it...
         *  This method will update the attribute m_lengthFrame
         */
269 270
        void                    computeLength();

271
        /**
272 273 274 275
         *  \param      uuid : The clip helper's uuid.
         *  \param      trackId : the track id
         *  \param      trackType : the track type (audio or video)
         *  \returns    The clip helper that matches the given UUID, or NULL.
276
         */
277 278
        ClipHelper*             getClipHelper( const QUuid& uuid, unsigned int trackId,
                                               Workflow::TrackType trackType );
279

280
    private:
281 282 283
        /// Pre-filled buffer used when there's nothing to render
        Workflow::Frame         *m_blackOutput;

284
        /// Lock for the m_currentFrame atribute.
285
        QReadWriteLock*                 m_currentFrameLock;
286 287 288
        /**
         *  \brief  An array of currently rendered frame.
         *
289
         *  This must be indexed with Workflow::TrackType.
290 291 292 293 294 295
         *  The Audio array entry is designed to synchronize the renders internally, as it
         *  is not actually a frame.
         *  If you wish to know which frame is really rendered, you must use
         *  m_currentFrame[MainWorkflow::VideoTrack], which is the value that will be used
         *  when setCurrentFrame() is called.
         */
296
        qint64*                         m_currentFrame;
297
        /// The workflow length, in frame.
298
        qint64                          m_lengthFrame;
299
        /// This boolean describe is a render has been started
300
        bool                            m_renderStarted;
301
        QMutex*                         m_renderStartedMutex;
302

303
        /// Contains the trackhandler, indexed by Workflow::TrackType
304 305
        TrackHandler**                  m_tracks;

306
        /// Width used for the render
307
        quint32                         m_width;
Hugo Beauzee-Luyssen's avatar
Hugo Beauzee-Luyssen committed
308
        /// Height used for the render
309
        quint32                         m_height;
310

311
        friend class                    Singleton<MainWorkflow>;
312

313
    private slots:
314 315 316 317 318 319 320
        /**
         *  \brief  Called when a track end is reached
         *
         *  If all track has reached end, the mainWorkflowEndReached() signal will be
         *  emitted;
         *  \sa     mainWorkflowEndReached()
         */
321
        void                            tracksEndReached();
322

323
    public slots:
324 325 326 327 328
        /**
         *  \brief  load a project based on a QDomElement
         *
         *  \param  project             The project node to load.
         */
329
        void                            loadProject( const QDomElement& project );
330
        /**
331
         *  \brief          Save the project on a XML stream.
332
         *
333
         *  \param  project The XML stream representing the project
334
         */
335
        void                            saveProject( QXmlStreamWriter& project ) const;
336 337 338 339 340 341
        /**
         *  \brief      Clear the workflow.
         *
         *  Calling this method will cause every clip workflow to be deleted, along with
         *  the associated Clip.
         *  This method will emit cleared() signal once finished.
342
         *  \sa     reCip( const QUuid&, unsigned int, Workflow::TrackType )
343 344
         *  \sa     cleared()
         */
345
        void                            clear();
346

347 348
        void                            lengthUpdated( qint64 lengthUpdated );

349
    signals:
350
        /**
351 352 353 354 355
         *  \brief      Used to notify a change to the timeline and preview widget cursor
         *
         *  \param      newFrame    The new rendered frame
         *  \param      reason      The reason for changing frame. Usually, if emitted
         *                          from the MainWorkflow, this should be "Renderer"
356
         */
357
        void                    frameChanged( qint64 newFrame,
358
                                              Vlmc::FrameChangedReason reason );
359

360 361 362 363 364 365
        /**
         *  \brief  Emitted when workflow end is reached
         *
         *  Workflow end is reached when tracksEndReached() is called, and no more tracks
         *  are activated (ie. they all reached end)
         */
366
        void                    mainWorkflowEndReached();
367

368 369 370 371 372
        /**
         *  \brief  Emitted when the workflow is cleared.
         *
         *  \sa     clear();
         */
373
        void                    cleared();
374 375 376 377 378 379 380

        /**
         *  \brief  Emitted when the global length of the workflow changes.
         *
         *  \param  newLength   The new length, in frames
         */
        void                    lengthChanged( qint64 );
381 382 383
};

#endif // MAINWORKFLOW_H