X-Git-Url: https://git.pterodactylus.net/?a=blobdiff_plain;f=synfig-studio%2Ftags%2Fsynfigstudio_0_61_06%2Fsrc%2Fgtkmm%2Fwidget_sound.cpp;fp=synfig-studio%2Ftags%2Fsynfigstudio_0_61_06%2Fsrc%2Fgtkmm%2Fwidget_sound.cpp;h=d8ad2b3b8dd4c70a09db958227ae3c4cbe207228;hb=5fd3dd11683d8b3e3aae5a4655f1525b91bc3e67;hp=0000000000000000000000000000000000000000;hpb=e9077d5c0858c23469cc10d6aeb8ad1d6d86caae;p=synfig.git diff --git a/synfig-studio/tags/synfigstudio_0_61_06/src/gtkmm/widget_sound.cpp b/synfig-studio/tags/synfigstudio_0_61_06/src/gtkmm/widget_sound.cpp new file mode 100644 index 0000000..d8ad2b3 --- /dev/null +++ b/synfig-studio/tags/synfigstudio_0_61_06/src/gtkmm/widget_sound.cpp @@ -0,0 +1,321 @@ +/* === S Y N F I G ========================================================= */ +/*! \file widget_sound.cpp +** \brief Widget Sound Implementation File +** +** $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 +*/ +/* ========================================================================= */ + +/* === H E A D E R S ======================================================= */ + +#ifdef USING_PCH +# include "pch.h" +#else +#ifdef HAVE_CONFIG_H +# include +#endif + +#include + +#include +#include + +#include "widget_sound.h" +#include "audiocontainer.h" + +#endif + +/* === U S I N G =========================================================== */ + +using namespace std; +using namespace etl; +//using namespace synfig; + +using studio::AudioProfile; + +/* === M A C R O S ========================================================= */ + +/* === G L O B A L S ======================================================= */ + +/* === P R O C E D U R E S ================================================= */ + +/* === M E T H O D S ======================================================= */ + +/* === E N T R Y P O I N T ================================================= */ + +studio::Widget_Sound::Widget_Sound() +{ +} + +studio::Widget_Sound::~Widget_Sound() +{ +} + +void studio::Widget_Sound::set_position(double t) +{ + //synfig::info("Setting position to %.2lf s", t); + if(adj_timescale && t != adj_timescale->get_value()) + { + float upper = adj_timescale->get_upper(); + float lower = adj_timescale->get_lower(); + float framesize = upper - lower; + + if(t < lower) + { + lower -= ceil((lower-t)/framesize)*framesize; + upper = lower + framesize; + adj_timescale->set_lower(lower); adj_timescale->set_upper(upper); + adj_timescale->set_value(t); + adj_timescale->changed(); adj_timescale->value_changed(); + }else + if(t > upper) + { + lower += ceil((t-upper)/framesize)*framesize; + upper = lower + framesize; + adj_timescale->set_lower(lower); adj_timescale->set_upper(upper); + adj_timescale->set_value(t); + adj_timescale->changed(); adj_timescale->value_changed(); + }else + { + adj_timescale->set_value(t); + adj_timescale->value_changed(); + } + } +} + +double studio::Widget_Sound::get_position() const +{ + if(adj_timescale) + { + return adj_timescale->get_value(); + } + return 0; +} + +bool studio::Widget_Sound::set_profile(etl::handle p) +{ + clear(); + + //set the profile + audioprof = p; + + if(!audioprof) + { + clear(); + return false; + } + + return true; +} + +etl::handle studio::Widget_Sound::get_profile() const +{ + return audioprof; +} + +void studio::Widget_Sound::clear() +{ + audioprof.detach(); +} + +void studio::Widget_Sound::draw() +{ + on_expose_event(); +} + +bool studio::Widget_Sound::on_expose_event(GdkEventExpose *heh) +{ + if(!get_window()) return false; + + //clear the background to dark grey + Glib::RefPtr gc = Gdk::GC::create(get_window()); + + if(!gc) return false; + + { + Gdk::Rectangle r(0,0,get_width(),get_height()); + get_window()->begin_paint_rect(r); + } + Gdk::Color c("#3f3f3f"); + gc->set_rgb_fg_color(c); + gc->set_background(c); + + int w = get_width(); + int baseline = get_height()/2; + get_window()->draw_rectangle(gc,true,0,0,w,get_height()); + + //set up the color to be blue + c.set_rgb_p(0,0.5,1); + gc->set_rgb_fg_color(c); + + //draw the base line + get_window()->draw_line(gc,0,baseline,w,baseline); + + //redraw all the samples from begin to end, but only if we have samples to draw (or there is no space to draw) + + //synfig::warning("Ok rendered everything, now must render actual sound wave"); + if(!audioprof || !adj_timescale || !w) + { + get_window()->end_paint(); + return true; + } + + //draw you fool! + float framesize = adj_timescale->get_upper() - adj_timescale->get_lower(); + if(framesize) + { + float delta=0,cum=0; + + //position in sample space + int begin=0,end=0; + int cur=0,maxs=0,mins=0; + + int i=0; //pixel counter + + //etl::clock check; check.reset(); + + float position = adj_timescale->get_value(); + float samplerate = audioprof->get_samplerate(); + int posi = 0; + //enforce position inside of frame size + { + float offset = audioprof->get_offset(); + + //clamp begin and end to framesize + float beginf = adj_timescale->get_lower(); + float endf = adj_timescale->get_upper(); + + posi = round_to_int((position-beginf)*w/framesize); + //posi = (int)((position-beginf)*w/framesize); + + //calculate in sample space from seconds + begin = round_to_int((beginf - offset)*samplerate); + end = round_to_int((endf - offset)*samplerate); + //begin = (int)((beginf - offset)*samplerate); + //end = (int)((endf - offset)*samplerate); + } + + delta = (end - begin)/(float)w; //samples per pixel + + /*synfig::warning("Rendering a framesize of %f secs from [%d,%d) samples to %d samples, took %f sec", + framesize, begin, end, w, check());*/ + + cur = begin; + i = 0; cum = 0; + for(int i=0;idraw_line(gc,i,baseline+bot,i,baseline+top); + } + } + + //synfig::warning("Drawing audio line"); + c.set_rgb_p(1,0,0); + gc->set_rgb_fg_color(c); + get_window()->draw_line(gc,posi,0,posi,get_height()); + } + get_window()->end_paint(); + + return true; +} + +//--- Handle the single clicking and dragging for scrubbing + +bool studio::Widget_Sound::on_motion_notify_event(GdkEventMotion* event) +{ + Gdk::ModifierType mod = Gdk::ModifierType(event->state); + + //if we are scrubbing + if(mod & Gdk::BUTTON1_MASK) + { + //Can't do this if we don't have a time frame (heheh...) + if(!adj_timescale) return false; + + double beg = adj_timescale->get_lower(), end = adj_timescale->get_upper(); + + //find event position in time + double t = beg + event->x * (end-beg) / get_width(); + + //signal that we are scrubbing to this new value... + signal_scrub()(t); + + + // We should be able to just call + // Widget_Timeslider::on_motion_notify_event(), + // but that seems to cause the program to halt + // for some reason. So for now, let's do the job ourselves + //adj_timescale->set_value(t); + //adj_timescale->changed(); + //return true; + } + + return Widget_Timeslider::on_motion_notify_event(event); +} + +bool studio::Widget_Sound::on_button_press_event(GdkEventButton *event) +{ + //Assume button PRESS + + //if we are starting... using left click + if(event->button == 1) + { + if(!adj_timescale) return false; + + double beg = adj_timescale->get_lower(), end = adj_timescale->get_upper(); + + //find event position in time + double t = beg + event->x * (end-beg) / get_width(); + + //signal the attached scrubbing devices... + signal_start_scrubbing()(t); + + return true; + } + + return Widget_Timeslider::on_button_press_event(event); +} + +bool studio::Widget_Sound::on_button_release_event(GdkEventButton *event) +{ + //Assume button RELEASE + + //if we are ending... using left click + if(event->button == 1) + { + //signal the scrubbing device... to stop + signal_stop_scrubbing()(); + + return true; + } + + return Widget_Timeslider::on_button_release_event(event); +}