/* === S Y N F I G ========================================================= */ /*! \file preview.h ** \brief Previews an animation ** ** $Id$ ** ** \legal ** Copyright (c) 2002-2005 Robert B. Quattlebaum Jr., Adrian Bentley ** ** This package 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 package 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. ** \endlegal */ /* ========================================================================= */ /* === S T A R T =========================================================== */ #ifndef __SYNFIG_PREVIEW_H #define __SYNFIG_PREVIEW_H /* === H E A D E R S ======================================================= */ #include #include /* indirectly includes winnt.h on WIN32 - needs to be included before gtkmm headers, which fix this */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "widgets/widget_sound.h" #include "dials/jackdial.h" #include #ifdef WITH_JACK #include #include #endif #include /* === M A C R O S ========================================================= */ /* === T Y P E D E F S ===================================================== */ /* === C L A S S E S & S T R U C T S ======================================= */ namespace studio { class AsyncRenderer; class Preview : public sigc::trackable, public etl::shared_object { public: class FlipbookElem { public: float t; Glib::RefPtr buf; //at whatever resolution they are rendered at (resized at run time) cairo_surface_t* surface; FlipbookElem(): t(), surface(NULL) { } //Copy constructor FlipbookElem(const FlipbookElem& other): t(other.t) ,buf(other.buf), surface(cairo_surface_reference(other.surface)) { } ~FlipbookElem() { if(surface) cairo_surface_destroy(surface); } }; etl::handle renderer; sigc::signal signal_destroyed_; //so things can reference us without fear typedef std::vector FlipBook; private: FlipBook frames; studio::CanvasView::LooseHandle canvasview; //synfig::RendDesc description; //for rendering the preview... float zoom,fps; float begintime,endtime; float jack_offset; bool overbegin,overend; bool use_cairo; int quality; float global_fps; //expose the frame information etc. class Preview_Target; class Preview_Target_Cairo; void frame_finish(const Preview_Target *); sigc::signal0 sig_changed; public: Preview(const studio::CanvasView::LooseHandle &h = studio::CanvasView::LooseHandle(), float zoom = 0.5f, float fps = 15); ~Preview(); float get_zoom() const {return zoom;} void set_zoom(float z){zoom = z;} float get_fps() const {return fps;} void set_fps(float f){fps = f;} float get_global_fps() const {return global_fps;} void set_global_fps(float f){global_fps = f;} float get_jack_offset() const {return jack_offset;} void set_jack_offset(float t){jack_offset = t;} float get_begintime() const { if(overbegin) return begintime; else if(canvasview) return get_canvas()->rend_desc().get_time_start(); else return -1; } float get_endtime() const { if(overend) return endtime; else if(canvasview) return get_canvas()->rend_desc().get_time_end(); else return -1; } void set_begintime(float t) {begintime = t;} void set_endtime(float t) {endtime = t;} bool get_overbegin() const {return overbegin;} void set_overbegin(bool b) {overbegin = b;} bool get_overend() const {return overend;} void set_overend(bool b) {overend = b;} bool get_use_cairo() const {return use_cairo;} void set_use_cairo(bool b) {use_cairo = b;} int get_quality() const {return quality;} void set_quality(int i) {quality = i;} synfig::Canvas::Handle get_canvas() const {return canvasview->get_canvas();} studio::CanvasView::Handle get_canvasview() const {return canvasview;} void set_canvasview(const studio::CanvasView::LooseHandle &h); //signal interface sigc::signal & signal_destroyed() { return signal_destroyed_; } //sigc::signal &signal_desc_change() {return signal_desc_change_;} //functions for exposing iterators through the preview FlipBook::iterator begin() {return frames.begin();} FlipBook::iterator end() {return frames.end();} FlipBook::const_iterator begin() const {return frames.begin();} FlipBook::const_iterator end() const {return frames.end();} void push_back(FlipbookElem fe) { frames.push_back(fe); } // Used to clear the FlipBook. Do not use directly the std::vector<>::clear member // because the cairo_surface_t* wouldn't be destroyed. void clear(); unsigned int numframes() const {return frames.size();} void render(); sigc::signal0 &signal_changed() { return sig_changed; } }; class Widget_Preview : public Gtk::Table { Gtk::DrawingArea draw_area; Glib::RefPtr adj_time_scrub; //the adjustment for the managed scrollbar Gtk::HScale scr_time_scrub; Gtk::ToggleButton b_loop; Gtk::ScrolledWindow preview_window; //Glib::RefPtr gc_area; Glib::RefPtr currentbuf; cairo_surface_t* current_surface; int currentindex; //double timeupdate; double timedisp; double audiotime; //preview encapsulation etl::handle preview; sigc::connection prevchanged; Gtk::ToggleButton *jackbutton; Widget_Time *offset_widget; Glib::RefPtr adj_sound; Gtk::Label l_lasttime; Gtk::Label l_currenttime; //only for internal stuff, doesn't set anything bool playing; bool singleframe; bool toolbarisshown; //for accurate time tracking etl::clock timer; //int curindex; //for later sigc::connection timecon; synfig::SoundProcessor soundProcessor; void slider_move(); //later to be a time_slider that's cooler bool play_update(); //bool play_frameupdate(); void update(); void scrub_updated(double t); void repreview(); void whenupdated(); void eraseall(); bool scroll_move_event(GdkEvent *); void disconnect_preview(Preview *); bool redraw(const Cairo::RefPtr &cr); void preview_draw(); void hide_toolbar(); void show_toolbar(); public: Widget_Preview(); ~Widget_Preview(); //sets a signal to identify disconnection (so we don't hold onto it)... void set_preview(etl::handle prev); void clear(); void play(); void pause(); void seek(const synfig::Time &t); synfig::Time get_position() const; synfig::Time get_time_start() const; synfig::Time get_time_end() const; void on_play_pause_pressed(); void seek_frame(int frames); void stoprender(); bool get_loop_flag() const {return b_loop.get_active();} void set_loop_flag(bool b) {return b_loop.set_active(b);} virtual void on_show(); virtual void on_hide(); protected: class ModelColumns : public Gtk::TreeModel::ColumnRecord { public: ModelColumns() { add(factor_id); add(factor_value); } Gtk::TreeModelColumn factor_id; Gtk::TreeModelColumn factor_value; }; ModelColumns factors; Gtk::ComboBoxText zoom_preview; Glib::RefPtr factor_refTreeModel; private: Gtk::HBox *toolbar; Gtk::Button *play_button; Gtk::Button *pause_button; bool on_key_pressed(GdkEventKey*); void on_zoom_entry_activated(); bool is_time_equal_to_current_frame(const synfig::Time &time); JackDial *jackdial; bool jack_enabled; bool jack_is_playing; synfig::Time jack_time; synfig::Time jack_offset; synfig::Time jack_initial_time; bool get_jack_enabled() { return jack_enabled; } void set_jack_enabled(bool value); #ifdef WITH_JACK void toggle_jack_button(); void on_jack_offset_changed(); Glib::Dispatcher jack_dispatcher; jack_client_t *jack_client; bool jack_synchronizing; void on_jack_sync(); static int jack_sync_callback(jack_transport_state_t state, jack_position_t *pos, void *arg); #endif }; }; // END of namespace studio /* === E N D =============================================================== */ #endif