From af707897735a34ab1a82c7307dc61b12c14027a9 Mon Sep 17 00:00:00 2001 From: Paul Davis Date: Tue, 14 Mar 2006 03:43:54 +0000 Subject: [PATCH] improvements (!) to waveform display for destructive tracks, plus a generic fix that avoid waveview attemting to read peaks before they are ready git-svn-id: svn://localhost/trunk/ardour2@388 d708f5d6-7413-0410-9779-e7cbd77b26cf --- gtk2_ardour/canvas-waveview.c | 4 +-- gtk2_ardour/canvas-waveview.h | 2 +- gtk2_ardour/gain_meter.cc | 15 ++++++-- gtk2_ardour/streamview.cc | 50 +++++++++++++++++++-------- gtk2_ardour/taperegionview.cc | 1 + gtk2_ardour/utils.cc | 24 ++++++++++--- libs/ardour/ardour/audioregion.h | 2 +- libs/ardour/ardour/source.h | 2 ++ libs/ardour/audioregion.cc | 4 +-- libs/ardour/destructive_filesource.cc | 10 ++---- libs/ardour/diskstream.cc | 13 ++++--- libs/ardour/source.cc | 23 ++++++++++-- 12 files changed, 109 insertions(+), 41 deletions(-) diff --git a/gtk2_ardour/canvas-waveview.c b/gtk2_ardour/canvas-waveview.c index 37c13cf4e2..84881ae32b 100644 --- a/gtk2_ardour/canvas-waveview.c +++ b/gtk2_ardour/canvas-waveview.c @@ -391,12 +391,12 @@ gnome_canvas_waveview_ensure_cache (GnomeCanvasWaveView *waveview, gulong start_ /* but make sure it doesn't extend beyond the end of the source material */ - rf3 = (gulong) (waveview->sourcefile_length_function (waveview->data_src)) + 1; + rf3 = (gulong) (waveview->sourcefile_length_function (waveview->data_src, waveview->samples_per_unit)) + 1; rf3 -= new_cache_start; #if DEBUG_CACHE fprintf (stderr, "\n\nAVAILABLE FRAMES = %lu of %lu, start = %lu, sstart = %lu, cstart = %lu\n", - rf3, waveview->sourcefile_length_function (waveview->data_src), + rf3, waveview->sourcefile_length_function (waveview->data_src, waveview->samples_per_unit), waveview->region_start, start_sample, new_cache_start); #endif diff --git a/gtk2_ardour/canvas-waveview.h b/gtk2_ardour/canvas-waveview.h index 46d5b6c138..97ac91f622 100644 --- a/gtk2_ardour/canvas-waveview.h +++ b/gtk2_ardour/canvas-waveview.h @@ -76,7 +76,7 @@ struct _GnomeCanvasWaveView guint32 channel; void (*peak_function)(void*,gulong,gulong,gulong,gpointer,guint32,double); gulong (*length_function)(void *); - gulong (*sourcefile_length_function)(void*); + gulong (*sourcefile_length_function)(void*,double); void (*gain_curve_function)(void *arg, double start, double end, float* vector, guint32 veclen); void *gain_src; diff --git a/gtk2_ardour/gain_meter.cc b/gtk2_ardour/gain_meter.cc index 07b7751b29..549620a1c8 100644 --- a/gtk2_ardour/gain_meter.cc +++ b/gtk2_ardour/gain_meter.cc @@ -82,6 +82,13 @@ was_pressed () cerr << "was pressed\n"; } +bool +was_button (GdkEventButton* ev) +{ + cerr << "Bp/R: " << ev->type << endl; + return false; +} + GainMeter::GainMeter (IO& io, Session& s) : _io (io), _session (s), @@ -123,6 +130,12 @@ GainMeter::GainMeter (IO& io, Session& s) gain_unit_button.signal_clicked().connect (ptr_fun (was_pressed)); + meter_point_button.signal_button_press_event().connect (mem_fun (*this, &GainMeter::meter_press)); + meter_point_button.signal_button_release_event().connect (mem_fun (*this, &GainMeter::meter_release)); + g_signal_connect (meter_point_button.gobj(), "button-press-event", (void (*)()) was_button, 0); + g_signal_connect (meter_point_button.gobj(), "button-release-event", (void (*)()) was_button, 0); + + top_table.set_col_spacings (2); top_table.set_homogeneous (true); top_table.attach (gain_unit_button, 0, 1, 0, 1); @@ -156,8 +169,6 @@ GainMeter::GainMeter (IO& io, Session& s) set_size_request_to_display_given_text (meter_point_button, _("tupni"), 2, 2); - meter_point_button.signal_button_press_event().connect (mem_fun(*this, &GainMeter::meter_press)); - meter_point_button.signal_button_release_event().connect (mem_fun(*this, &GainMeter::meter_release)); top_table.attach (meter_point_button, 1, 2, 0, 1); } diff --git a/gtk2_ardour/streamview.cc b/gtk2_ardour/streamview.cc index a4ee1c9c5e..862efdb4c5 100644 --- a/gtk2_ardour/streamview.cc +++ b/gtk2_ardour/streamview.cc @@ -535,7 +535,7 @@ StreamView::set_selected_regionviews (AudioRegionSelection& regions) { bool selected; - cerr << _trackview.name() << " (selected = " << regions.size() << ")" << endl; + // cerr << _trackview.name() << " (selected = " << regions.size() << ")" << endl; for (list::iterator i = region_views.begin(); i != region_views.end(); ++i) { selected = false; @@ -546,7 +546,7 @@ StreamView::set_selected_regionviews (AudioRegionSelection& regions) } } - cerr << "\tregion " << (*i)->region.name() << " selected = " << selected << endl; + // cerr << "\tregion " << (*i)->region.name() << " selected = " << selected << endl; (*i)->set_selected (selected, this); } } @@ -618,11 +618,12 @@ StreamView::setup_rec_box () // cerr << "\trolling\n"; - if (!rec_active - && _trackview.session().record_status() == Session::Recording - && _trackview.get_diskstream()->record_enabled()) { + if (!rec_active && + _trackview.session().record_status() == Session::Recording && + _trackview.get_diskstream()->record_enabled()) { + + if (_trackview.audio_track()->mode() == Normal && use_rec_regions && rec_regions.size() == rec_rects.size()) { - if (use_rec_regions && rec_regions.size() == rec_rects.size()) { /* add a new region, but don't bother if they set use_rec_regions mid-record */ AudioRegion::SourceList sources; @@ -664,7 +665,17 @@ StreamView::setup_rec_box () DiskStream& ds = at->disk_stream(); jack_nframes_t frame_pos = ds.current_capture_start (); gdouble xstart = _trackview.editor.frame_to_pixel (frame_pos); - gdouble xend = xstart; + gdouble xend; + + switch (_trackview.audio_track()->mode()) { + case Normal: + xend = xstart; + break; + + case Destructive: + xend = xstart + 2; + break; + } ArdourCanvas::SimpleRect * rec_rect = new Gnome::Canvas::SimpleRect (*canvas_group); rec_rect->property_x1() = xstart; @@ -749,21 +760,32 @@ StreamView::setup_rec_box () void StreamView::update_rec_box () { - /* only update the last box */ if (rec_active && rec_rects.size() > 0) { + /* only update the last box */ RecBoxInfo & rect = rec_rects.back(); jack_nframes_t at = _trackview.get_diskstream()->current_capture_end(); + double xstart; + double xend; + + switch (_trackview.audio_track()->mode()) { + case Normal: + rect.length = at - rect.start; + xstart = _trackview.editor.frame_to_pixel (rect.start); + xend = _trackview.editor.frame_to_pixel (at); + break; + + case Destructive: + rect.length = 2; + xstart = _trackview.editor.frame_to_pixel (at); + xend = xstart + 2; + break; + } - rect.length = at - rect.start; - - gdouble xstart = _trackview.editor.frame_to_pixel ( rect.start ); - gdouble xend = _trackview.editor.frame_to_pixel ( at ); - rect.rectangle->property_x1() = xstart; rect.rectangle->property_x2() = xend; } } - + AudioRegionView* StreamView::find_view (const AudioRegion& region) { diff --git a/gtk2_ardour/taperegionview.cc b/gtk2_ardour/taperegionview.cc index da7adc7935..b5f0d6d46b 100644 --- a/gtk2_ardour/taperegionview.cc +++ b/gtk2_ardour/taperegionview.cc @@ -103,6 +103,7 @@ TapeAudioRegionView::init (double amplitude_above_axis, Gdk::Color& basic_color, /* every time the wave data changes and peaks are ready, redraw */ + for (uint32_t n = 0; n < region.n_channels(); ++n) { region.source(n).PeaksReady.connect (bind (mem_fun(*this, &TapeAudioRegionView::update), n)); } diff --git a/gtk2_ardour/utils.cc b/gtk2_ardour/utils.cc index 19d896fd0d..91f69a444e 100644 --- a/gtk2_ardour/utils.cc +++ b/gtk2_ardour/utils.cc @@ -512,6 +512,14 @@ bool key_press_focus_accelerator_handler (Gtk::Window& window, GdkEventKey* ev) { GtkWindow* win = window.gobj(); + GtkWidget* focus = gtk_window_get_focus (win); + bool special_handling_of_unmodified_accelerators = false; + + if (focus) { + if (GTK_IS_ENTRY(focus)) { + special_handling_of_unmodified_accelerators = true; + } + } /* This exists to allow us to override the way GTK handles key events. The normal sequence is: @@ -544,9 +552,17 @@ key_press_focus_accelerator_handler (Gtk::Window& window, GdkEventKey* ev) all "normal text" accelerators. */ - if (ev->state & ~Gdk::SHIFT_MASK) { - - /* modifiers in effect, accelerate first */ + if (!special_handling_of_unmodified_accelerators || + ev->state & (Gdk::MOD1_MASK| + Gdk::MOD2_MASK| + Gdk::MOD3_MASK| + Gdk::MOD4_MASK| + Gdk::MOD5_MASK| + Gdk::CONTROL_MASK| + Gdk::LOCK_MASK)) { + + /* no special handling or modifiers in effect: accelerate first */ + if (!gtk_window_activate_key (win, ev)) { return gtk_window_propagate_key_event (win, ev); } else { @@ -555,7 +571,7 @@ key_press_focus_accelerator_handler (Gtk::Window& window, GdkEventKey* ev) } /* no modifiers, propagate first */ - + if (!gtk_window_propagate_key_event (win, ev)) { return gtk_window_activate_key (win, ev); } diff --git a/libs/ardour/ardour/audioregion.h b/libs/ardour/ardour/audioregion.h index fa6b3aeecc..c716bf9707 100644 --- a/libs/ardour/ardour/audioregion.h +++ b/libs/ardour/ardour/audioregion.h @@ -223,7 +223,7 @@ class AudioRegion : public Region extern "C" { int region_read_peaks_from_c (void *arg, uint32_t npeaks, uint32_t start, uint32_t length, intptr_t data, uint32_t n_chan, double samples_per_unit); uint32_t region_length_from_c (void *arg); - uint32_t sourcefile_length_from_c (void *arg); + uint32_t sourcefile_length_from_c (void *arg, double); } #endif /* __ardour_audio_region_h__ */ diff --git a/libs/ardour/ardour/source.h b/libs/ardour/ardour/source.h index 9a9bccfc58..7a5e2eb23a 100644 --- a/libs/ardour/ardour/source.h +++ b/libs/ardour/ardour/source.h @@ -64,6 +64,8 @@ class Source : public Stateful, public sigc::trackable return _length; } + virtual jack_nframes_t available_peaks (double zoom) const; + virtual jack_nframes_t read (Sample *dst, jack_nframes_t start, jack_nframes_t cnt, char * workbuf) const { return 0; } diff --git a/libs/ardour/audioregion.cc b/libs/ardour/audioregion.cc index 59ddd12c47..23db0a0604 100644 --- a/libs/ardour/audioregion.cc +++ b/libs/ardour/audioregion.cc @@ -1397,9 +1397,9 @@ uint32_t region_length_from_c (void *arg) return ((AudioRegion *) arg)->length(); } -uint32_t sourcefile_length_from_c (void *arg) +uint32_t sourcefile_length_from_c (void *arg, double zoom_factor) { - return ( (AudioRegion *) arg)->source().length() ; + return ( (AudioRegion *) arg)->source().available_peaks (zoom_factor) ; } } /* extern "C" */ diff --git a/libs/ardour/destructive_filesource.cc b/libs/ardour/destructive_filesource.cc index c18fedd982..1ca6b5be5a 100644 --- a/libs/ardour/destructive_filesource.cc +++ b/libs/ardour/destructive_filesource.cc @@ -69,6 +69,7 @@ jack_nframes_t DestructiveFileSource::xfade_frames = 64; DestructiveFileSource::DestructiveFileSource (string path, jack_nframes_t rate, bool repair_first, SampleFormat samp_format) : FileSource (path, rate, repair_first, samp_format) { + cerr << "DESTRUCTO DISK STREAM, " << _name << endl; if (out_coefficient == 0) { setup_standard_crossfades (rate); } @@ -83,6 +84,7 @@ DestructiveFileSource::DestructiveFileSource (string path, jack_nframes_t rate, DestructiveFileSource::DestructiveFileSource (const XMLNode& node, jack_nframes_t rate) : FileSource (node, rate) { + cerr << "from XML, DESTRUCTO DISK STREAM, " << _name << endl; if (out_coefficient == 0) { setup_standard_crossfades (rate); } @@ -259,8 +261,6 @@ DestructiveFileSource::crossfade (Sample* data, jack_nframes_t cnt, int fade_in, jack_nframes_t DestructiveFileSource::write (Sample* data, jack_nframes_t cnt, char * workbuf) { - cerr << _name << ": write " << cnt << " to " << file_pos << " start ? " << _capture_start << " end ? " << _capture_end << endl; - { LockMonitor lm (_lock, __LINE__, __FILE__); @@ -273,8 +273,6 @@ DestructiveFileSource::write (Sample* data, jack_nframes_t cnt, char * workbuf) /* move to the correct location place */ file_pos = capture_start_frame; - cerr << "First frame of capture will be at " << file_pos << " and last at: " << file_pos + cnt << endl; - // split cnt in half jack_nframes_t subcnt = cnt / 2; jack_nframes_t ofilepos = file_pos; @@ -302,8 +300,6 @@ DestructiveFileSource::write (Sample* data, jack_nframes_t cnt, char * workbuf) /* move to the correct location place */ file_pos = capture_start_frame; - cerr << "First frame of capture will be at " << file_pos << endl; - if (crossfade (data, cnt, 1, workbuf) != cnt) { return 0; } @@ -327,8 +323,6 @@ DestructiveFileSource::write (Sample* data, jack_nframes_t cnt, char * workbuf) } file_pos += cnt; - //cerr << this << ' ' << _name << " at end of write, file_pos = " << file_pos << " length = " << ((int) &_length - (int) this) << ' ' << &_length << ' ' << _length << endl; - if (_build_peakfiles) { PeakBuildRecord *pbr = 0; diff --git a/libs/ardour/diskstream.cc b/libs/ardour/diskstream.cc index 80a562ab21..78f6d13335 100644 --- a/libs/ardour/diskstream.cc +++ b/libs/ardour/diskstream.cc @@ -603,7 +603,7 @@ DiskStream::check_record_status (jack_nframes_t transport_frame, jack_nframes_t } /* change state */ - + /* if per-track or global rec-enable turned on while the other was already on, we've started recording */ if ((change & track_rec_enabled) && record_enabled() && (!(change & global_rec_enabled) && can_record) || @@ -692,7 +692,7 @@ DiskStream::check_record_status (jack_nframes_t transport_frame, jack_nframes_t } else if (!record_enabled() || !can_record) { /* stop recording */ - + last_recordable_frame = transport_frame + _capture_offset; if (_alignment_style == ExistingMaterial) { @@ -1608,8 +1608,6 @@ DiskStream::do_flush (char * workbuf, bool force_flush) } } - - if ((!(*chan).write_source) || (*chan).write_source->write (vector.buf[0], to_write, workbuf) != to_write) { error << string_compose(_("DiskStream %1: cannot write to disk"), _id) << endmsg; return -1; @@ -1963,6 +1961,9 @@ DiskStream::get_state () char buf[64]; LocaleGuard lg (X_("POSIX")); + snprintf (buf, sizeof(buf), "0x%x", _flags); + node->add_property ("flags", buf); + snprintf (buf, sizeof(buf), "%zd", channels.size()); node->add_property ("channels", buf); @@ -2047,6 +2048,10 @@ DiskStream::set_state (const XMLNode& node) } } + if ((prop = node.property ("_flags")) != 0) { + _flags = atoi (prop->value().c_str()); + } + if ((prop = node.property ("channels")) != 0) { nchans = atoi (prop->value().c_str()); } diff --git a/libs/ardour/source.cc b/libs/ardour/source.cc index 2a6337d441..fb09293fd5 100644 --- a/libs/ardour/source.cc +++ b/libs/ardour/source.cc @@ -545,19 +545,21 @@ Source::read_peaks (PeakData *peaks, jack_nframes_t npeaks, jack_nframes_t start tnp = min ((_length/frames_per_peak - current_stored_peak), (jack_nframes_t) expected_peaks); to_read = min (chunksize, tnp); + off_t fend = lseek (peakfile, 0, SEEK_END); + if ((nread = ::pread (peakfile, staging, sizeof (PeakData) * to_read, start_byte)) != sizeof (PeakData) * to_read) { cerr << "Source[" << _name << "]: cannot read peak data from peakfile (" - << nread + << (nread / sizeof(PeakData)) << " peaks instead of " << to_read << ") (" << strerror (errno) << ')' << " at start_byte = " << start_byte - << " _length = " << _length + << " _length = " << _length << " versus len = " << fend << " expected maxpeaks = " << (_length - current_frame)/frames_per_peak << " npeaks was " << npeaks << endl; @@ -699,7 +701,7 @@ Source::build_peaks () } #ifdef DEBUG_PEAK_BUILD - cerr << "build peaks with " << pending_peak_builds.size() << " requests pending\n"; + cerr << "build peaks with " << copy.size() << " requests pending\n"; #endif for (list::iterator i = copy.begin(); i != copy.end(); ++i) { @@ -732,6 +734,7 @@ Source::build_peaks () } if (pr_signal) { + off_t fend = lseek (peakfile, 0, SEEK_END); PeaksReady (); /* EMIT SIGNAL */ } } @@ -849,3 +852,17 @@ Source::release () { if (_use_cnt) --_use_cnt; } + +jack_nframes_t +Source::available_peaks (double zoom_factor) const +{ + if (zoom_factor < frames_per_peak) { + return length(); // peak data will come from the audio file + } + + /* peak data comes from peakfile */ + + LockMonitor lm (_lock, __LINE__, __FILE__); + off_t end = lseek (peakfile, 0, SEEK_END); + return (end/sizeof(PeakData)) * frames_per_peak; +}