1 /* === S Y N F I G ========================================================= */
2 /*!	\file preview.h
3 **	\brief Previews an animation
4 **
5 **	$Id$
6 **
7 **	\legal
8 **	Copyright (c) 2002-2005 Robert B. Quattlebaum Jr., Adrian Bentley
9 **
10 **	This package is free software; you can redistribute it and/or
11 **	modify it under the terms of the GNU General Public License as
12 **	published by the Free Software Foundation; either version 2 of
13 **	the License, or (at your option) any later version.
14 **
15 **	This package is distributed in the hope that it will be useful,
16 **	but WITHOUT ANY WARRANTY; without even the implied warranty of
17 **	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 **	General Public License for more details.
19 **	\endlegal
20 */
21 /* ========================================================================= */
22 
23 /* === S T A R T =========================================================== */
24 
25 #ifndef __SYNFIG_PREVIEW_H
26 #define __SYNFIG_PREVIEW_H
27 
28 /* === H E A D E R S ======================================================= */
29 #include <ETL/handle>
30 #include <ETL/clock> /* indirectly includes winnt.h on WIN32 - needs to be included before gtkmm headers, which fix this */
31 
32 #include <gtkmm/drawingarea.h>
33 #include <gtkmm/table.h>
34 #include <gtkmm/adjustment.h>
35 #include <gtkmm/image.h>
36 #include <gdkmm/pixbuf.h>
37 #include <gtkmm/dialog.h>
38 #include <gtkmm/scrollbar.h>
39 #include <gtkmm/checkbutton.h>
40 #include <gtkmm/tooltip.h>
41 #include <gtkmm/alignment.h>
42 #include <gtkmm/comboboxtext.h>
43 #include <gtkmm/hvscale.h>
44 #include <gtkmm/scrolledwindow.h>
45 #include <gtkmm/liststore.h>
46 
47 #include <glibmm/dispatcher.h>
48 
49 #include <synfig/time.h>
50 #include <synfig/vector.h>
51 #include <synfig/renddesc.h>
52 #include <synfig/canvas.h>
53 
54 #include "widgets/widget_sound.h"
55 #include "dials/jackdial.h"
56 
57 #include <vector>
58 
59 #ifdef WITH_JACK
60 #include <jack/jack.h>
61 #include <jack/transport.h>
62 #endif
63 
64 #include <synfig/soundprocessor.h>
65 
66 /* === M A C R O S ========================================================= */
67 
68 /* === T Y P E D E F S ===================================================== */
69 
70 /* === C L A S S E S & S T R U C T S ======================================= */
71 
72 namespace studio {
73 class AsyncRenderer;
74 class CanvasView;
75 
76 class Preview : public sigc::trackable, public etl::shared_object
77 {
78 public:
79 	class FlipbookElem
80 	{
81 	public:
82 		float t;
83 		Glib::RefPtr<Gdk::Pixbuf> buf; //at whatever resolution they are rendered at (resized at run time)
84 		cairo_surface_t* surface;
FlipbookElem()85 		FlipbookElem(): t(), surface(NULL) { }
86 		//Copy constructor
FlipbookElem(const FlipbookElem & other)87 		FlipbookElem(const FlipbookElem& other): t(other.t) ,buf(other.buf), surface(cairo_surface_reference(other.surface))
88 		{
89 		}
~FlipbookElem()90 		~FlipbookElem()
91 		{
92 			if(surface)
93 				cairo_surface_destroy(surface);
94 		}
95 	};
96 
97 	etl::handle<studio::AsyncRenderer>	renderer;
98 
99 	sigc::signal<void, Preview *>	signal_destroyed_;	//so things can reference us without fear
100 
101 	typedef std::vector<FlipbookElem>	 FlipBook;
102 private:
103 
104 	FlipBook frames;
105 
106 	etl::loose_handle<CanvasView> canvasview;
107 
108 	//synfig::RendDesc		description; //for rendering the preview...
109 	float	zoom,fps;
110 	float	begintime,endtime;
111 	float	jack_offset;
112 	bool 	overbegin,overend;
113 	int		quality;
114 
115 	float	global_fps;
116 
117 	//expose the frame information etc.
118 	class Preview_Target;
119 	class Preview_Target_Cairo;
120 	void frame_finish(const Preview_Target *);
121 
122 	sigc::signal0<void>	sig_changed;
123 
124 public:
125 
126 	explicit Preview(const etl::loose_handle<CanvasView> &h = etl::loose_handle<CanvasView>(),
127 				float zoom = 0.5f, float fps = 15);
128 	~Preview();
129 
get_zoom()130 	float 	get_zoom() const {return zoom;}
set_zoom(float z)131 	void	set_zoom(float z){zoom = z;}
132 
get_fps()133 	float 	get_fps() const {return fps;}
set_fps(float f)134 	void	set_fps(float f){fps = f;}
135 
get_global_fps()136 	float 	get_global_fps() const {return global_fps;}
set_global_fps(float f)137 	void	set_global_fps(float f){global_fps = f;}
138 
get_jack_offset()139 	float   get_jack_offset() const {return jack_offset;}
set_jack_offset(float t)140 	void	set_jack_offset(float t){jack_offset = t;}
141 
get_begintime()142 	float	get_begintime() const
143 	{
144 		if(overbegin)
145 			return begintime;
146 		else if(canvasview)
147 			return get_canvas()->rend_desc().get_time_start();
148 		else return -1;
149 	}
150 
get_endtime()151 	float	get_endtime() const
152 	{
153 		if(overend)
154 			return endtime;
155 		else if(canvasview)
156 			return get_canvas()->rend_desc().get_time_end();
157 		else return -1;
158 	}
159 
set_begintime(float t)160 	void	set_begintime(float t)	{begintime = t;}
set_endtime(float t)161 	void	set_endtime(float t) 	{endtime = t;}
162 
get_overbegin()163 	bool get_overbegin() const {return overbegin;}
set_overbegin(bool b)164 	void set_overbegin(bool b) {overbegin = b;}
165 
get_overend()166 	bool get_overend() const {return overend;}
set_overend(bool b)167 	void set_overend(bool b) {overend = b;}
168 
get_quality()169 	int		get_quality() const {return quality;}
set_quality(int i)170 	void	set_quality(int i)	{quality = i;}
171 
172 	etl::handle<synfig::Canvas> get_canvas() const;
173 	etl::handle<CanvasView> get_canvasview() const;
174 
175 	void set_canvasview(const etl::loose_handle<CanvasView> &h);
176 
177 	//signal interface
signal_destroyed()178 	sigc::signal<void, Preview *> &	signal_destroyed() { return signal_destroyed_; }
179 	//sigc::signal<void, const synfig::RendDesc &>	&signal_desc_change() {return signal_desc_change_;}
180 
181 	//functions for exposing iterators through the preview
begin()182 	FlipBook::iterator	begin() 	{return frames.begin();}
end()183 	FlipBook::iterator	end() 		{return frames.end();}
184 
begin()185 	FlipBook::const_iterator	begin() const {return frames.begin();}
end()186 	FlipBook::const_iterator	end() const	  {return frames.end();}
push_back(FlipbookElem fe)187 	void push_back(FlipbookElem fe) { frames.push_back(fe); }
188 	// Used to clear the FlipBook. Do not use directly the std::vector<>::clear member
189 	// because the cairo_surface_t* wouldn't be destroyed.
190 	void clear();
191 
numframes()192 	unsigned int				numframes() const  {return frames.size();}
193 
194 	void render();
195 
signal_changed()196 	sigc::signal0<void>	&signal_changed() { return sig_changed; }
197 };
198 
199 class Widget_Preview : public Gtk::Table
200 {
201 	Gtk::DrawingArea	draw_area;
202 	Glib::RefPtr<Gtk::Adjustment> adj_time_scrub; //the adjustment for the managed scrollbar
203 	Gtk::HScale		scr_time_scrub;
204 	Gtk::ToggleButton	b_loop;
205 	Gtk::ScrolledWindow	preview_window;
206 	//Glib::RefPtr<Gdk::GC>		gc_area;
207 	Glib::RefPtr<Gdk::Pixbuf>	currentbuf;
208 	int					currentindex;
209 	//double			timeupdate;
210 	double				timedisp;
211 	double				audiotime;
212 
213 	//preview encapsulation
214 	etl::handle<Preview>	preview;
215 	sigc::connection	prevchanged;
216 
217 	Gtk::ToggleButton *jackbutton;
218 	Widget_Time *offset_widget;
219 	Glib::RefPtr<Gtk::Adjustment> adj_sound;
220 
221 	Gtk::Label		l_lasttime;
222 	Gtk::Label		l_currenttime;
223 
224 	//only for internal stuff, doesn't set anything
225 	bool 	playing;
226 	bool	singleframe;
227 	bool	toolbarisshown;
228 
229 	//for accurate time tracking
230 	etl::clock	timer;
231 
232 	//int		curindex; //for later
233 	sigc::connection	timecon;
234 
235 	synfig::SoundProcessor soundProcessor;
236 
237 	void slider_move(); //later to be a time_slider that's cooler
238 	bool play_update();
239 
240 	//bool play_frameupdate();
241 	void update();
242 
243 	void scrub_updated(double t);
244 
245 	void repreview();
246 
247 	void whenupdated();
248 
249 	void eraseall();
250 
251 	bool scroll_move_event(GdkEvent *);
252 	void disconnect_preview(Preview *);
253 
254 	bool redraw(const Cairo::RefPtr<Cairo::Context> &cr);
255 	void preview_draw();
256 
257 	void hide_toolbar();
258 	void show_toolbar();
259 
260 public:
261 
262 	Widget_Preview();
263 	~Widget_Preview();
264 
265 	//sets a signal to identify disconnection (so we don't hold onto it)...
266 	void set_preview(etl::handle<Preview> prev);
267 
268 	void clear();
269 
270 	void play();
271 	void pause();
272 	void seek(const synfig::Time &t);
273 	synfig::Time get_position() const;
274 	synfig::Time get_time_start() const;
275 	synfig::Time get_time_end() const;
276 
277 
278 	void on_play_pause_pressed();
279 
280 	void seek_frame(int frames);
281 
282 	void stoprender();
283 
get_loop_flag()284 	bool get_loop_flag() const {return b_loop.get_active();}
set_loop_flag(bool b)285 	void set_loop_flag(bool b) {return b_loop.set_active(b);}
286 
287 	virtual void on_show();
288 	virtual void on_hide();
289 
290 protected:
291 
292 	class ModelColumns : public Gtk::TreeModel::ColumnRecord
293 	{
294 	public:
295 
ModelColumns()296 		ModelColumns()
297 		{
298 			add(factor_id);
299 			add(factor_value);
300 		}
301 
302 		Gtk::TreeModelColumn<Glib::ustring> factor_id;
303 		Gtk::TreeModelColumn<Glib::ustring> factor_value;
304 
305 	};
306 
307 	ModelColumns factors;
308 
309 	Gtk::ComboBoxText zoom_preview;
310 	Glib::RefPtr<Gtk::ListStore> factor_refTreeModel;
311 
312 private:
313 
314 	Gtk::HBox *toolbar;
315 	Gtk::Button *play_button;
316 	Gtk::Button *pause_button;
317 	bool on_key_pressed(GdkEventKey*);
318 	void on_zoom_entry_activated();
319 
320 	bool is_time_equal_to_current_frame(const synfig::Time &time);
321 
322 	JackDial *jackdial;
323 	bool jack_enabled;
324 	bool jack_is_playing;
325 	synfig::Time jack_time;
326 	synfig::Time jack_offset;
327 	synfig::Time jack_initial_time;
328 
get_jack_enabled()329 	bool get_jack_enabled() { return jack_enabled; }
330 	void set_jack_enabled(bool value);
331 
332 #ifdef WITH_JACK
333 	void toggle_jack_button();
334 	void on_jack_offset_changed();
335 	Glib::Dispatcher jack_dispatcher;
336 	jack_client_t *jack_client;
337 	bool jack_synchronizing;
338 	void on_jack_sync();
339 	static int jack_sync_callback(jack_transport_state_t state, jack_position_t *pos, void *arg);
340 #endif
341 };
342 
343 }; // END of namespace studio
344 
345 /* === E N D =============================================================== */
346 
347 #endif
348