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