diff options
author | Paul Davis <paul@linuxaudiosystems.com> | 2010-03-03 23:38:42 +0000 |
---|---|---|
committer | Paul Davis <paul@linuxaudiosystems.com> | 2010-03-03 23:38:42 +0000 |
commit | a7eb8f47335904c6b9c30b86d6a7be3946d13655 (patch) | |
tree | 0a54147c22eb9fc1ec8bd8e1c646a2df542a7e7d /gtk2_ardour/strip_silence_dialog.cc | |
parent | fba09a3d19c460fb55e374a24b9f02cf774e2573 (diff) |
fixes and improvements for strip silence, with lots of thread debugging
git-svn-id: svn://localhost/ardour2/branches/3.0@6724 d708f5d6-7413-0410-9779-e7cbd77b26cf
Diffstat (limited to 'gtk2_ardour/strip_silence_dialog.cc')
-rw-r--r-- | gtk2_ardour/strip_silence_dialog.cc | 235 |
1 files changed, 215 insertions, 20 deletions
diff --git a/gtk2_ardour/strip_silence_dialog.cc b/gtk2_ardour/strip_silence_dialog.cc index 2be04f7fcb..56210c9373 100644 --- a/gtk2_ardour/strip_silence_dialog.cc +++ b/gtk2_ardour/strip_silence_dialog.cc @@ -17,6 +17,8 @@ */ +#include <iostream> + #include <gtkmm/table.h> #include <gtkmm/label.h> #include <gtkmm/stock.h> @@ -34,17 +36,32 @@ #include "i18n.h" using namespace ARDOUR; +using namespace std; +using namespace ArdourCanvas; + +Glib::StaticMutex StripSilenceDialog::run_lock; +Glib::Cond* StripSilenceDialog::thread_waiting = 0; +Glib::Cond* StripSilenceDialog::thread_run = 0; +bool StripSilenceDialog::thread_should_exit = false; +InterThreadInfo StripSilenceDialog::itt; +StripSilenceDialog* StripSilenceDialog::current = 0; /** Construct Strip silence dialog box */ StripSilenceDialog::StripSilenceDialog (std::list<boost::shared_ptr<ARDOUR::AudioRegion> > const & regions) - : ArdourDialog (_("Strip Silence")), _wave_width (640), _wave_height (64) + : ArdourDialog (_("Strip Silence")) + , _wave_width (640) + , _wave_height (64) + , restart_queued (false) { + if (thread_waiting == 0) { + thread_waiting = new Glib::Cond; + thread_run = new Glib::Cond; + } + for (std::list<boost::shared_ptr<ARDOUR::AudioRegion> >::const_iterator i = regions.begin(); i != regions.end(); ++i) { Wave w; w.region = *i; - w.view = 0; - w.samples_per_unit = 1; _waves.push_back (w); } @@ -91,18 +108,15 @@ StripSilenceDialog::StripSilenceDialog (std::list<boost::shared_ptr<ARDOUR::Audi hbox->pack_start (*table, false, false); - Gtk::VBox* v = Gtk::manage (new Gtk::VBox); - Gtk::Button* b = Gtk::manage (new Gtk::Button (_("Update display"))); - b->signal_clicked().connect (sigc::mem_fun (*this, &StripSilenceDialog::update_silence_rects)); - v->pack_start (*b, false, false); - hbox->pack_start (*v, false, false); + _segment_count_label.set_text (_("Silent segments: none")); + hbox->pack_start (_segment_count_label, false, false); - get_vbox()->add (*hbox); + get_vbox()->pack_start (*hbox, false, false); add_button (Gtk::Stock::CANCEL, Gtk::RESPONSE_CANCEL); add_button (Gtk::Stock::APPLY, Gtk::RESPONSE_OK); - _canvas = new ArdourCanvas::CanvasAA (); + _canvas = new CanvasAA (); _canvas->signal_size_allocate().connect (sigc::mem_fun (*this, &StripSilenceDialog::canvas_allocation)); _canvas->set_size_request (_wave_width, _wave_height * _waves.size ()); @@ -110,6 +124,9 @@ StripSilenceDialog::StripSilenceDialog (std::list<boost::shared_ptr<ARDOUR::Audi show_all (); + _threshold.get_adjustment()->signal_value_changed().connect (sigc::mem_fun (*this, &StripSilenceDialog::maybe_start_silence_detection)); + _minimum_length.get_adjustment()->signal_value_changed().connect (sigc::mem_fun (*this, &StripSilenceDialog::maybe_start_silence_detection)); + create_waves (); update_silence_rects (); } @@ -119,7 +136,7 @@ StripSilenceDialog::~StripSilenceDialog () { for (std::list<Wave>::iterator i = _waves.begin(); i != _waves.end(); ++i) { delete i->view; - for (std::list<ArdourCanvas::SimpleRect*>::iterator j = i->silence_rects.begin(); j != i->silence_rects.end(); ++j) { + for (std::list<SimpleRect*>::iterator j = i->silence_rects.begin(); j != i->silence_rects.end(); ++j) { delete *j; } } @@ -165,32 +182,67 @@ StripSilenceDialog::peaks_ready () void StripSilenceDialog::canvas_allocation (Gtk::Allocation& alloc) { + int n = 0; + _canvas->set_scroll_region (0.0, 0.0, alloc.get_width(), alloc.get_height()); _wave_width = alloc.get_width (); + _wave_height = alloc.get_height (); - for (std::list<Wave>::iterator i = _waves.begin(); i != _waves.end(); ++i) { + for (std::list<Wave>::iterator i = _waves.begin(); i != _waves.end(); ++i, ++n) { i->samples_per_unit = ((double) i->region->length() / _wave_width); + + if (i->view) { + i->view->property_y() = n * _wave_height; + i->view->property_samples_per_unit() = i->samples_per_unit; + i->view->property_height() = _wave_height; + } } + + redraw_silence_rects (); +} + +void +StripSilenceDialog::redraw_silence_rects () +{ + int n = 0; + + for (std::list<Wave>::iterator i = _waves.begin(); i != _waves.end(); ++i) { + + std::list<std::pair<frameoffset_t, framecnt_t> >::const_iterator j; + std::list<SimpleRect*>::iterator r; + + for (j = i->silence.begin(), r = i->silence_rects.begin(); + j != i->silence.end() && r != i->silence_rects.end(); ++j, ++r) { + (*r)->property_x1() = j->first / i->samples_per_unit; + (*r)->property_x2() = j->second / i->samples_per_unit; + (*r)->property_y1() = n * _wave_height; + (*r)->property_y2() = (n + 1) * _wave_height; + (*r)->property_outline_pixels() = 0; + (*r)->property_fill_color_rgba() = RGBA_TO_UINT (128, 128, 128, 128); + } + + ++n; + } } void StripSilenceDialog::update_silence_rects () { int n = 0; + uint32_t max_segments = 0; + uint32_t sc; for (std::list<Wave>::iterator i = _waves.begin(); i != _waves.end(); ++i) { - for (std::list<ArdourCanvas::SimpleRect*>::iterator j = i->silence_rects.begin(); j != i->silence_rects.end(); ++j) { + for (std::list<SimpleRect*>::iterator j = i->silence_rects.begin(); j != i->silence_rects.end(); ++j) { delete *j; } - i->silence_rects.clear (); + i->silence_rects.clear (); + sc = 0; - std::list<std::pair<frameoffset_t, framecnt_t> > const silence = - i->region->find_silence (dB_to_coefficient (threshold ()), minimum_length ()); - - for (std::list<std::pair<frameoffset_t, framecnt_t> >::const_iterator j = silence.begin(); j != silence.end(); ++j) { + for (std::list<std::pair<frameoffset_t, framecnt_t> >::const_iterator j = i->silence.begin(); j != i->silence.end(); ++j) { - ArdourCanvas::SimpleRect* r = new ArdourCanvas::SimpleRect (*(_canvas->root())); + SimpleRect* r = new SimpleRect (*(_canvas->root())); r->property_x1() = j->first / i->samples_per_unit; r->property_x2() = j->second / i->samples_per_unit; r->property_y1() = n * _wave_height; @@ -198,9 +250,152 @@ StripSilenceDialog::update_silence_rects () r->property_outline_pixels() = 0; r->property_fill_color_rgba() = RGBA_TO_UINT (128, 128, 128, 128); i->silence_rects.push_back (r); - + sc++; } + max_segments = max (max_segments, sc); ++n; } + + _segment_count_label.set_text (string_compose (_("Silent segments: %1"), max_segments)); +} + +bool +StripSilenceDialog::_detection_done (void* arg) +{ + StripSilenceDialog* ssd = (StripSilenceDialog*) arg; + return ssd->detection_done (); +} + +bool +StripSilenceDialog::detection_done () +{ + get_window()->set_cursor (Gdk::Cursor (Gdk::LEFT_PTR)); + update_silence_rects (); + return false; +} + +void* +StripSilenceDialog::_detection_thread_work (void* arg) +{ + StripSilenceDialog* ssd = (StripSilenceDialog*) arg; + return ssd->detection_thread_work (); +} + +void* +StripSilenceDialog::detection_thread_work () +{ + ARDOUR_UI::instance()->register_thread ("gui", pthread_self(), "silence", 32); + + cerr << pthread_self() << ": thread exists\n"; + + while (1) { + + run_lock.lock (); + cerr << pthread_self() << ": thread notes that its waiting\n"; + thread_waiting->signal (); + cerr << pthread_self() << ": thread waits to run\n"; + thread_run->wait (run_lock); + + cerr << pthread_self() << ": silence thread active\n"; + + if (thread_should_exit) { + thread_waiting->signal (); + run_lock.unlock (); + cerr << pthread_self() << ": silence thread exited\n"; + break; + } + + if (current) { + StripSilenceDialog* ssd = current; + run_lock.unlock (); + + for (std::list<Wave>::iterator i = ssd->_waves.begin(); i != ssd->_waves.end(); ++i) { + i->silence = i->region->find_silence (dB_to_coefficient (ssd->threshold ()), ssd->minimum_length (), ssd->itt); + } + + if (!ssd->itt.cancel) { + g_idle_add ((gboolean (*)(void*)) StripSilenceDialog::_detection_done, ssd); + } + } + + cerr << pthread_self() << ": silence iteration done\n"; + } + + return 0; +} + +void +StripSilenceDialog::maybe_start_silence_detection () +{ + if (!restart_queued) { + restart_queued = true; + Glib::signal_idle().connect (sigc::mem_fun (*this, &StripSilenceDialog::start_silence_detection)); + } +} + +bool +StripSilenceDialog::start_silence_detection () +{ + Glib::Mutex::Lock lm (run_lock); + restart_queued = false; + + if (!itt.thread) { + + itt.done = false; + itt.cancel = false; + itt.progress = 0.0; + current = this; + + pthread_create (&itt.thread, 0, StripSilenceDialog::_detection_thread_work, this); + /* wait for it to get started */ + cerr << "Wait for new thread to be ready\n"; + thread_waiting->wait (run_lock); + cerr << "\tits ready\n"; + + } else { + + /* stop whatever the thread is doing */ + + itt.cancel = 1; + current = 0; + + while (!itt.done) { + cerr << "tell existing thread to stop\n"; + thread_run->signal (); + cerr << "wait for existing thread to stop\n"; + thread_waiting->wait (run_lock); + cerr << "its stopped\n"; + } + } + + + itt.cancel = false; + itt.done = false; + itt.progress = 0.0; + current = this; + + /* and start it up (again) */ + + cerr << "signal thread to run again\n"; + thread_run->signal (); + + /* change cursor */ + + get_window()->set_cursor (Gdk::Cursor (Gdk::WATCH)); + + /* don't call again until needed */ + + return false; +} + +void +StripSilenceDialog::stop_thread () +{ + Glib::Mutex::Lock lm (run_lock); + + itt.cancel = true; + thread_should_exit = true; + thread_run->signal (); + thread_waiting->wait (run_lock); } |