**
** This package is free software; you can redistribute it and/or
** modify it under the terms of the GNU General Public License as
**
** This package is free software; you can redistribute it and/or
** modify it under the terms of the GNU General Public License as
/*synfig::warning("Succeeded in setting the desc to new one: %d x %d, %.2f fps [%.2f,%.2f]",
desc.get_w(),desc.get_h(),desc.get_frame_rate(),
(float)desc.get_time_start(),(float)desc.get_time_end());*/
/*synfig::warning("Succeeded in setting the desc to new one: %d x %d, %.2f fps [%.2f,%.2f]",
desc.get_w(),desc.get_h(),desc.get_frame_rate(),
(float)desc.get_time_start(),(float)desc.get_time_end());*/
//connect our information to his...
//synfig::warning("Connecting to the end frame function...");
target->signal_frame_done().connect(sigc::mem_fun(*this,&Preview::frame_finish));
//connect our information to his...
//synfig::warning("Connecting to the end frame function...");
target->signal_frame_done().connect(sigc::mem_fun(*this,&Preview::frame_finish));
//set the options
//synfig::warning("Setting Canvas");
target->set_canvas(get_canvas());
target->set_quality(quality);
//set the options
//synfig::warning("Setting Canvas");
target->set_canvas(get_canvas());
target->set_quality(quality);
int neww = (int)floor(desc.get_w()*zoom+0.5),
newh = (int)floor(desc.get_h()*zoom+0.5);
float newfps = fps;
int neww = (int)floor(desc.get_w()*zoom+0.5),
newh = (int)floor(desc.get_h()*zoom+0.5);
float newfps = fps;
/*synfig::warning("Setting the render description: %d x %d, %f fps, [%f,%f]",
neww,newh,newfps, overbegin?begintime:(float)desc.get_time_start(),
overend?endtime:(float)desc.get_time_end());*/
/*synfig::warning("Setting the render description: %d x %d, %f fps, [%f,%f]",
neww,newh,newfps, overbegin?begintime:(float)desc.get_time_start(),
overend?endtime:(float)desc.get_time_end());*/
desc.set_time_end(std::min(endtime,(float)desc.get_time_end()));
//synfig::warning("Set end time to %.2f...",(float)desc.get_time_end());
}
desc.set_time_end(std::min(endtime,(float)desc.get_time_end()));
//synfig::warning("Set end time to %.2f...",(float)desc.get_time_end());
}
-
- //HACK - BECAUSE THE RENDERER CAN'T RENDER INCLUDING THE LAST FRAME
- desc.set_time_end(desc.get_time_end() + 1.3/fps);
-
+
+ //HACK - add on one extra frame because the renderer can't render the last frame
+ desc.set_time_end(desc.get_time_end() + 1.000001/fps);
+
//now tell it to go... with inherited prog. reporting...
//synfig::info("Rendering Asynchronously...");
if(renderer) renderer->stop();
//now tell it to go... with inherited prog. reporting...
//synfig::info("Rendering Asynchronously...");
if(renderer) renderer->stop();
float time = targ->get_time();
const Surface &surf = targ->get_surface();
const RendDesc& r = targ->get_rend_desc();
float time = targ->get_time();
const Surface &surf = targ->get_surface();
const RendDesc& r = targ->get_rend_desc();
convert_color_format(buffer, surf[0], surf.get_w()*surf.get_h(), pf, App::gamma);
convert_color_format(buffer, surf[0], surf.get_w()*surf.get_h(), pf, App::gamma);
Gdk::Pixbuf::create_from_data(
buffer, // pointer to the data
Gdk::COLORSPACE_RGB, // the colorspace
Gdk::Pixbuf::create_from_data(
buffer, // pointer to the data
Gdk::COLORSPACE_RGB, // the colorspace
surf.get_w()*synfig::channels(pf), // stride (pitch)
sigc::ptr_fun(free_guint8)
);
surf.get_w()*synfig::channels(pf), // stride (pitch)
sigc::ptr_fun(free_guint8)
);
//add the flipbook element to the list (assume time is correct)
//synfig::info("Prev: Adding %f s to the list", time);
frames.push_back(fe);
//add the flipbook element to the list (assume time is correct)
//synfig::info("Prev: Adding %f s to the list", time);
frames.push_back(fe);
Widget_Preview::Widget_Preview()
:Gtk::Table(5,5,false),
adj_time_scrub(0,0,1000,1,10,0),
scr_time_scrub(adj_time_scrub),
b_loop(/*_("Loop")*/),
Widget_Preview::Widget_Preview()
:Gtk::Table(5,5,false),
adj_time_scrub(0,0,1000,1,10,0),
scr_time_scrub(adj_time_scrub),
b_loop(/*_("Loop")*/),
adj_sound(0,0,4),
l_lasttime("0s"),
playing(false)
{
//connect to expose events
//signal_expose_event().connect(sigc::mem_fun(*this, &studio::Widget_Preview::redraw));
adj_sound(0,0,4),
l_lasttime("0s"),
playing(false)
{
//connect to expose events
//signal_expose_event().connect(sigc::mem_fun(*this, &studio::Widget_Preview::redraw));
//manage all the change in values etc...
adj_time_scrub.signal_value_changed().connect(sigc::mem_fun(*this,&Widget_Preview::slider_move));
scr_time_scrub.signal_event().connect(sigc::mem_fun(*this,&Widget_Preview::scroll_move_event));
draw_area.signal_expose_event().connect(sigc::mem_fun(*this,&Widget_Preview::redraw));
//manage all the change in values etc...
adj_time_scrub.signal_value_changed().connect(sigc::mem_fun(*this,&Widget_Preview::slider_move));
scr_time_scrub.signal_event().connect(sigc::mem_fun(*this,&Widget_Preview::scroll_move_event));
draw_area.signal_expose_event().connect(sigc::mem_fun(*this,&Widget_Preview::redraw));
//Set up signals to modify time value as it should be...
disp_sound.signal_start_scrubbing().connect(sigc::mem_fun(*this,&Widget_Preview::scrub_updated));
disp_sound.signal_scrub().connect(sigc::mem_fun(*this,&Widget_Preview::scrub_updated));
//Set up signals to modify time value as it should be...
disp_sound.signal_start_scrubbing().connect(sigc::mem_fun(*this,&Widget_Preview::scrub_updated));
disp_sound.signal_scrub().connect(sigc::mem_fun(*this,&Widget_Preview::scrub_updated));
attach(draw_area, 0, 1, 0, 1);
attach(scr_time_scrub, 0, 1, 1, 2, Gtk::EXPAND|Gtk::FILL, Gtk::SHRINK);
attach(draw_area, 0, 1, 0, 1);
attach(scr_time_scrub, 0, 1, 1, 2, Gtk::EXPAND|Gtk::FILL, Gtk::SHRINK);
hbox->pack_start(b_loop,Gtk::PACK_SHRINK,0);
//attach(b_loop,0,1,2,3,Gtk::EXPAND|Gtk::FILL,Gtk::SHRINK);
hbox->pack_start(b_loop,Gtk::PACK_SHRINK,0);
//attach(b_loop,0,1,2,3,Gtk::EXPAND|Gtk::FILL,Gtk::SHRINK);
button = manage(new Gtk::Button(/*_("Play")*/));
button->signal_clicked().connect(sigc::mem_fun(*this,&Widget_Preview::play));
button = manage(new Gtk::Button(/*_("Play")*/));
button->signal_clicked().connect(sigc::mem_fun(*this,&Widget_Preview::play));
hbox->pack_start(*button,Gtk::PACK_SHRINK,0);
//attach(*button,1,2,2,3,Gtk::EXPAND|Gtk::FILL,Gtk::SHRINK);
hbox->pack_start(*button,Gtk::PACK_SHRINK,0);
//attach(*button,1,2,2,3,Gtk::EXPAND|Gtk::FILL,Gtk::SHRINK);
button = manage(new Gtk::Button(/*_("Stop")*/));
button->signal_clicked().connect(sigc::mem_fun(*this,&Widget_Preview::stop));
button = manage(new Gtk::Button(/*_("Stop")*/));
button->signal_clicked().connect(sigc::mem_fun(*this,&Widget_Preview::stop));
hbox->pack_start(*button,Gtk::PACK_SHRINK,0);
//attach(*button,2,3,2,3,Gtk::EXPAND|Gtk::FILL,Gtk::SHRINK);
hbox->pack_start(*button,Gtk::PACK_SHRINK,0);
//attach(*button,2,3,2,3,Gtk::EXPAND|Gtk::FILL,Gtk::SHRINK);
//attack the stop render and erase all buttons to same line...
{
Gtk::VSeparator *vsep = manage(new Gtk::VSeparator);
hbox->pack_start(*vsep,Gtk::PACK_SHRINK,0);
}
//attack the stop render and erase all buttons to same line...
{
Gtk::VSeparator *vsep = manage(new Gtk::VSeparator);
hbox->pack_start(*vsep,Gtk::PACK_SHRINK,0);
}
button = manage(new Gtk::Button(/*_("Halt Render")*/));
button->signal_clicked().connect(sigc::mem_fun(*this,&Widget_Preview::stoprender));
button = manage(new Gtk::Button(/*_("Halt Render")*/));
button->signal_clicked().connect(sigc::mem_fun(*this,&Widget_Preview::stoprender));
hbox->pack_start(*button,Gtk::PACK_SHRINK,0);
//attach(*button,2,3,3,4,Gtk::EXPAND|Gtk::FILL,Gtk::SHRINK);
hbox->pack_start(*button,Gtk::PACK_SHRINK,0);
//attach(*button,2,3,3,4,Gtk::EXPAND|Gtk::FILL,Gtk::SHRINK);
button = manage(new Gtk::Button(/*_("Re-Preview")*/));
button->signal_clicked().connect(sigc::mem_fun(*this,&Widget_Preview::repreview));
button = manage(new Gtk::Button(/*_("Re-Preview")*/));
button->signal_clicked().connect(sigc::mem_fun(*this,&Widget_Preview::repreview));
hbox->pack_start(*button,Gtk::PACK_SHRINK,0);
//attach(*button,0,2,4,5,Gtk::EXPAND|Gtk::FILL,Gtk::SHRINK);
hbox->pack_start(*button,Gtk::PACK_SHRINK,0);
//attach(*button,0,2,4,5,Gtk::EXPAND|Gtk::FILL,Gtk::SHRINK);
button = manage(new Gtk::Button(/*_("Erase All")*/));
button->signal_clicked().connect(sigc::mem_fun(*this,&Widget_Preview::eraseall));
button = manage(new Gtk::Button(/*_("Erase All")*/));
button->signal_clicked().connect(sigc::mem_fun(*this,&Widget_Preview::eraseall));
hbox->pack_start(*button,Gtk::PACK_SHRINK,0);
//attach(*button,2,3,4,5,Gtk::EXPAND|Gtk::FILL,Gtk::SHRINK);
hbox->pack_start(*button,Gtk::PACK_SHRINK,0);
//attach(*button,2,3,4,5,Gtk::EXPAND|Gtk::FILL,Gtk::SHRINK);
hbox->show_all();
attach(*hbox,0,1,2,3,Gtk::EXPAND|Gtk::FILL,Gtk::SHRINK|Gtk::FILL);
hbox->show_all();
attach(*hbox,0,1,2,3,Gtk::EXPAND|Gtk::FILL,Gtk::SHRINK|Gtk::FILL);
- //attach(*manage(new Gtk::Label("Last Rendered: ")),0,1,3,4,Gtk::SHRINK,Gtk::SHRINK);
+ //attach(*manage(new Gtk::Label(_("Last Rendered: "))),0,1,3,4,Gtk::SHRINK,Gtk::SHRINK);
}
//l_lasttime.show();
hbox->pack_start(l_lasttime,Gtk::PACK_SHRINK,0);
hbox->show_all();
attach(*hbox,0,1,3,4,Gtk::EXPAND|Gtk::FILL,Gtk::SHRINK);
//attach(l_lasttime,0,1,3,4,Gtk::EXPAND|Gtk::FILL,Gtk::SHRINK);
}
//l_lasttime.show();
hbox->pack_start(l_lasttime,Gtk::PACK_SHRINK,0);
hbox->show_all();
attach(*hbox,0,1,3,4,Gtk::EXPAND|Gtk::FILL,Gtk::SHRINK);
//attach(l_lasttime,0,1,3,4,Gtk::EXPAND|Gtk::FILL,Gtk::SHRINK);
//5th row
disp_sound.set_size_request(-1,32);
attach(disp_sound,0,1,4,5,Gtk::EXPAND|Gtk::FILL,Gtk::SHRINK);
//5th row
disp_sound.set_size_request(-1,32);
attach(disp_sound,0,1,4,5,Gtk::EXPAND|Gtk::FILL,Gtk::SHRINK);
//use time to find closest frame...
studio::Preview::FlipBook::const_iterator beg = preview->begin(),end = preview->end();
studio::Preview::FlipBook::const_iterator i;
//use time to find closest frame...
studio::Preview::FlipBook::const_iterator beg = preview->begin(),end = preview->end();
studio::Preview::FlipBook::const_iterator i;
//And render the drawing area
Glib::RefPtr<Gdk::Pixbuf> pxnew, px = currentbuf;
//And render the drawing area
Glib::RefPtr<Gdk::Pixbuf> pxnew, px = currentbuf;
//figure out the scaling factors...
float sx, sy;
int nw,nh;
sx = draw_area.get_width() / (float)px->get_width();
sy = draw_area.get_height() / (float)px->get_height();
//figure out the scaling factors...
float sx, sy;
int nw,nh;
sx = draw_area.get_width() / (float)px->get_width();
sy = draw_area.get_height() / (float)px->get_height();
//scale to a new pixmap and then copy over to the window
nw = (int)(px->get_width()*sx);
nh = (int)(px->get_height()*sx);
//scale to a new pixmap and then copy over to the window
nw = (int)(px->get_width()*sx);
nh = (int)(px->get_height()*sx);
//synfig::info("Now to draw to the window...");
//copy to window
Glib::RefPtr<Gdk::Window> wind = draw_area.get_window();
//synfig::info("Now to draw to the window...");
//copy to window
Glib::RefPtr<Gdk::Window> wind = draw_area.get_window();
if(!wind) synfig::warning("The destination window is broken...");
if(!surf) synfig::warning("The destination is not drawable...");
if(!wind) synfig::warning("The destination window is broken...");
if(!surf) synfig::warning("The destination is not drawable...");
+ better memory footprint
*/
//px->composite(const Glib::RefPtr<Gdk::Pixbuf>& dest, int dest_x, int dest_y, int dest_width, int dest_height, double offset_x, double offset_y, double scale_x, double scale_y, InterpType interp_type, int overall_alpha) const
+ better memory footprint
*/
//px->composite(const Glib::RefPtr<Gdk::Pixbuf>& dest, int dest_x, int dest_y, int dest_width, int dest_height, double offset_x, double offset_y, double scale_x, double scale_y, InterpType interp_type, int overall_alpha) const
Gdk::RGB_DITHER_NONE, // RgbDither
0, 0 // Dither offset X and Y
);
Gdk::RGB_DITHER_NONE, // RgbDither
0, 0 // Dither offset X and Y
);
Glib::ustring timecode(Time((double)timedisp).round(preview->get_global_fps())
.get_string(preview->get_global_fps(),
App::get_time_format()));
//synfig::info("Time for preview draw is: %s for time %g", timecode.c_str(), adj_time_scrub.get_value());
Glib::ustring timecode(Time((double)timedisp).round(preview->get_global_fps())
.get_string(preview->get_global_fps(),
App::get_time_format()));
//synfig::info("Time for preview draw is: %s for time %g", timecode.c_str(), adj_time_scrub.get_value());
gc->set_rgb_fg_color(Gdk::Color("#FF0000"));
layout->set_text(timecode);
surf->draw_layout(gc,4,4,layout);
gc->set_rgb_fg_color(Gdk::Color("#FF0000"));
layout->set_text(timecode);
surf->draw_layout(gc,4,4,layout);
{
float diff = timer.pop_time();
//synfig::info("Play update: diff = %.2f",diff);
{
float diff = timer.pop_time();
//synfig::info("Play update: diff = %.2f",diff);
//adjust it to be synced with the audio if it can...
{
double newtime = audiotime;
if(audio && audio->is_playing()) audio->get_current_time(newtime);
//adjust it to be synced with the audio if it can...
{
double newtime = audiotime;
if(audio && audio->is_playing()) audio->get_current_time(newtime);
if(newtime != audiotime)
{
//synfig::info("Adjusted time from %.3lf to %.3lf", time,newtime);
time = audiotime = newtime;
}
}
if(newtime != audiotime)
{
//synfig::info("Adjusted time from %.3lf to %.3lf", time,newtime);
time = audiotime = newtime;
}
}
//update the window to the correct image we might want to do this later...
//update();
//synfig::warning("Did update pu");
//update the window to the correct image we might want to do this later...
//update();
//synfig::warning("Did update pu");
//synfig::info("Scrubbing to %.3f, setting adj to %.3f",oldt,t);
//synfig::info("Scrubbing to %.3f, setting adj to %.3f",oldt,t);
if(adj_time_scrub.get_value() != t)
{
adj_time_scrub.set_value(t);
adj_time_scrub.value_changed();
}
}
if(adj_time_scrub.get_value() != t)
{
adj_time_scrub.set_value(t);
adj_time_scrub.value_changed();
}
}
adj_time_scrub.set_lower(start);
adj_time_scrub.set_upper(end);
adj_time_scrub.set_value(start);
adj_time_scrub.set_step_increment(rate);
adj_time_scrub.set_page_increment(10*rate);
adj_time_scrub.set_lower(start);
adj_time_scrub.set_upper(end);
adj_time_scrub.set_value(start);
adj_time_scrub.set_step_increment(rate);
adj_time_scrub.set_page_increment(10*rate);
//if the begin time and the end time are the same there is only a single frame
singleframe = end==start;
}else
//if the begin time and the end time are the same there is only a single frame
singleframe = end==start;
}else
adj_time_scrub.set_upper(0);
adj_time_scrub.set_value(0);
adj_time_scrub.set_step_increment(0);
adj_time_scrub.set_upper(0);
adj_time_scrub.set_value(0);
adj_time_scrub.set_step_increment(0);
//connect so future information will be found...
prevchanged = prev->signal_changed().connect(sigc::mem_fun(*this,&Widget_Preview::whenupdated));
prev->signal_destroyed().connect(sigc::mem_fun(*this,&Widget_Preview::disconnect_preview));
//connect so future information will be found...
prevchanged = prev->signal_changed().connect(sigc::mem_fun(*this,&Widget_Preview::whenupdated));
prev->signal_destroyed().connect(sigc::mem_fun(*this,&Widget_Preview::disconnect_preview));
update(); //we don't want to call play update because that will try to advance the timer
//synfig::warning("Did update p");
update(); //we don't want to call play update because that will try to advance the timer
//synfig::warning("Did update p");
//approximate length of time in seconds, right?
double rate = /*std::min(*/adj_time_scrub.get_step_increment()/*,1/30.0)*/;
int timeout = (int)floor(1000*rate);
//approximate length of time in seconds, right?
double rate = /*std::min(*/adj_time_scrub.get_step_increment()/*,1/30.0)*/;
int timeout = (int)floor(1000*rate);
-
- timecon = Glib::signal_timeout().connect(sigc::mem_fun(*this,&Widget_Preview::play_update),timeout);
- timer.reset();
+
+ timecon = Glib::signal_timeout().connect(sigc::mem_fun(*this,&Widget_Preview::play_update),timeout);
+ timer.reset();
//disconnect any previous signals
scrstartcon.disconnect(); scrstopcon.disconnect(); scrubcon.disconnect();
//disconnect any previous signals
scrstartcon.disconnect(); scrstopcon.disconnect(); scrubcon.disconnect();
//connect the new signals
scrstartcon = disp_sound.signal_start_scrubbing().connect(sigc::mem_fun(*a,&AudioContainer::start_scrubbing));
scrstopcon = disp_sound.signal_stop_scrubbing().connect(sigc::mem_fun(*a,&AudioContainer::stop_scrubbing));
//connect the new signals
scrstartcon = disp_sound.signal_start_scrubbing().connect(sigc::mem_fun(*a,&AudioContainer::start_scrubbing));
scrstopcon = disp_sound.signal_stop_scrubbing().connect(sigc::mem_fun(*a,&AudioContainer::stop_scrubbing));
- preview->renderer.detach();
+ // don't crash if the render has already been stopped
+ if (!preview->renderer)
+ return;
+
+ if (preview->renderer->updating)
+ preview->renderer->stop();
+ else
+ preview->renderer.detach();