From c99ae648f05073f3b1d607cb15b826d2525a38a7 Mon Sep 17 00:00:00 2001 From: Carl Hetherington Date: Thu, 11 Jun 2009 01:05:01 +0000 Subject: [PATCH] Add a widget giving an overview of the editor, as (what I think is being) suggested in #2714. Many caveats: most notably that it looks quite ugly and you can't (yet) turn it off. git-svn-id: svn://localhost/ardour2/branches/3.0@5162 d708f5d6-7413-0410-9779-e7cbd77b26cf --- gtk2_ardour/audio_region_view.cc | 2 - gtk2_ardour/editor.cc | 43 +++--- gtk2_ardour/editor.h | 6 + gtk2_ardour/editor_canvas.cc | 5 +- gtk2_ardour/editor_canvas_events.cc | 2 +- gtk2_ardour/editor_route_list.cc | 3 + gtk2_ardour/editor_summary.cc | 220 ++++++++++++++++++++++++++++ gtk2_ardour/editor_summary.h | 41 ++++++ gtk2_ardour/port_matrix_body.cc | 1 + gtk2_ardour/wscript | 1 + 10 files changed, 295 insertions(+), 29 deletions(-) create mode 100644 gtk2_ardour/editor_summary.cc create mode 100644 gtk2_ardour/editor_summary.h diff --git a/gtk2_ardour/audio_region_view.cc b/gtk2_ardour/audio_region_view.cc index b36a237da5..ca3c8b3ba1 100644 --- a/gtk2_ardour/audio_region_view.cc +++ b/gtk2_ardour/audio_region_view.cc @@ -864,8 +864,6 @@ AudioRegionView::create_waves () if (wait_for_data) { if (audio_region()->audio_source(n)->peaks_ready (bind (mem_fun(*this, &AudioRegionView::peaks_ready_handler), n), data_ready_connection)) { - // cerr << "\tData is ready\n"; - cerr << "\tData is ready\n"; // cerr << "\tData is ready\n"; create_one_wave (n, true); } else { diff --git a/gtk2_ardour/editor.cc b/gtk2_ardour/editor.cc index e96b7838a6..a49ff6f5a0 100644 --- a/gtk2_ardour/editor.cc +++ b/gtk2_ardour/editor.cc @@ -211,7 +211,7 @@ Editor::Editor () range_mark_label (_("Range Markers")), transport_mark_label (_("Loop/Punch Ranges")), cd_mark_label (_("CD Markers")), - edit_packer (3, 4, true), + edit_packer (4, 4, true), /* the values here don't matter: layout widgets reset them as needed. @@ -437,6 +437,7 @@ Editor::Editor () transport_mark_label.set_no_show_all(); initialize_rulers (); + _summary = new EditorSummary (this); initialize_canvas (); selection->TimeChanged.connect (mem_fun(*this, &Editor::time_selection_changed)); @@ -502,42 +503,26 @@ Editor::Editor () time_canvas_event_box.add (time_canvas_vbox); time_canvas_event_box.set_events (Gdk::BUTTON_PRESS_MASK|Gdk::BUTTON_RELEASE_MASK|Gdk::POINTER_MOTION_MASK); - + edit_packer.set_col_spacings (0); edit_packer.set_row_spacings (0); edit_packer.set_homogeneous (false); edit_packer.set_border_width (0); edit_packer.set_name ("EditorWindow"); -#ifndef THE_OLD_WAY - edit_packer.attach (ruler_label_event_box, 0, 1, 0, 1, FILL, SHRINK, 0, 0); edit_packer.attach (time_button_event_box, 0, 1, 1, 2, FILL, SHRINK, 0, 0); + edit_packer.attach (*_summary , 1, 2, 2, 3, FILL|EXPAND, SHRINK, 0, 0); edit_packer.attach (time_canvas_event_box, 1, 2, 0, 1, FILL|EXPAND, FILL, 0, 0); - edit_packer.attach (controls_layout, 0, 1, 2, 3, FILL, FILL|EXPAND, 0, 0); - edit_packer.attach (track_canvas_event_box, 1, 2, 1, 3, FILL|EXPAND, FILL|EXPAND, 0, 0); - - edit_packer.attach (zoom_box, 0, 1, 3, 4, FILL, FILL, 0, 0); - edit_packer.attach (edit_hscrollbar, 1, 2, 3, 4, FILL|EXPAND, FILL, 0, 0); + edit_packer.attach (controls_layout, 0, 1, 3, 4, FILL, FILL|EXPAND, 0, 0); + edit_packer.attach (track_canvas_event_box, 1, 2, 1, 4, FILL|EXPAND, FILL|EXPAND, 0, 0); - edit_packer.attach (edit_vscrollbar, 3, 4, 2, 3, FILL, FILL|EXPAND, 0, 0); + edit_packer.attach (zoom_box, 0, 1, 4, 5, FILL, FILL, 0, 0); + edit_packer.attach (edit_hscrollbar, 1, 2, 4, 5, FILL|EXPAND, FILL, 0, 0); -#else - - edit_packer.attach (edit_vscrollbar, 0, 1, 0, 4, FILL, FILL|EXPAND, 0, 0); - - edit_packer.attach (ruler_label_event_box, 1, 2, 0, 1, FILL, SHRINK, 0, 0); - edit_packer.attach (time_button_event_box, 1, 2, 1, 2, FILL, SHRINK, 0, 0); - edit_packer.attach (time_canvas_event_box, 2, 3, 0, 1, FILL|EXPAND, FILL, 0, 0); - - edit_packer.attach (controls_layout, 1, 2, 2, 3, FILL, FILL|EXPAND, 0, 0); - edit_packer.attach (track_canvas_event_box, 2, 3, 1, 3, FILL|EXPAND, FILL|EXPAND, 0, 0); - - edit_packer.attach (zoom_box, 1, 2, 3, 4, FILL, FILL, 0, 0); - edit_packer.attach (edit_hscrollbar, 2, 3, 3, 4, FILL|EXPAND, FILL, 0, 0); -#endif + edit_packer.attach (edit_vscrollbar, 3, 4, 3, 4, FILL, FILL|EXPAND, 0, 0); bottom_hbox.set_border_width (2); bottom_hbox.set_spacing (3); @@ -1403,6 +1388,8 @@ Editor::connect_to_session (Session *t) /* register for undo history */ session->register_with_memento_command_factory(_id, this); + _summary->set_session (session); + start_updating (); } @@ -4710,6 +4697,8 @@ Editor::post_zoom () playhead_cursor->set_position (playhead_cursor->current_frame); } + _summary->set_bounds_dirty (); + instant_save (); } @@ -5325,3 +5314,9 @@ Editor::located () _pending_locate_request = false; } + +void +Editor::region_view_added (RegionView *) +{ + _summary->set_dirty (); +} diff --git a/gtk2_ardour/editor.h b/gtk2_ardour/editor.h index 5a45e398d0..4d212d581c 100644 --- a/gtk2_ardour/editor.h +++ b/gtk2_ardour/editor.h @@ -63,6 +63,7 @@ #include "editor_items.h" #include "region_selection.h" #include "canvas.h" +#include "editor_summary.h" namespace Gtkmm2ext { class TearOff; @@ -2215,6 +2216,9 @@ public: void located (); bool _pending_locate_request; + EditorSummary* _summary; + void region_view_added (RegionView *); + friend class Drag; friend class RegionDrag; friend class RegionMoveDrag; @@ -2238,6 +2242,8 @@ public: friend class RegionCreateDrag; friend class RegionMotionDrag; friend class RegionInsertDrag; + + friend class EditorSummary; }; #endif /* __ardour_editor_h__ */ diff --git a/gtk2_ardour/editor_canvas.cc b/gtk2_ardour/editor_canvas.cc index 146f756225..573b3af16a 100644 --- a/gtk2_ardour/editor_canvas.cc +++ b/gtk2_ardour/editor_canvas.cc @@ -362,6 +362,7 @@ Editor::track_canvas_size_allocated () reset_hscrollbar_stepping (); update_fixed_rulers(); redisplay_tempo (false); + _summary->set_bounds_dirty (); Resized (); /* EMIT_SIGNAL */ @@ -773,8 +774,6 @@ Editor::tie_vertical_scrolling () void Editor::scroll_canvas_horizontally () { - nframes64_t time_origin = (nframes64_t) floor (horizontal_adjustment.get_value() * frames_per_unit); - /* horizontal scrolling only */ double x1, y1, x2, y2, x_delta; _master_group->get_bounds (x1, y1, x2, y2); @@ -791,6 +790,8 @@ Editor::scroll_canvas_horizontally () update_fixed_rulers (); redisplay_tempo (true); + _summary->set_bounds_dirty (); + #ifndef GTKOSX if (!autoscroll_active) { /* force rulers and canvas to move in lock step */ diff --git a/gtk2_ardour/editor_canvas_events.cc b/gtk2_ardour/editor_canvas_events.cc index 99868367f0..b86ba76f83 100644 --- a/gtk2_ardour/editor_canvas_events.cc +++ b/gtk2_ardour/editor_canvas_events.cc @@ -170,7 +170,7 @@ Editor::track_canvas_scroll (GdkEventScroll* ev) /* what? */ break; } - + return false; } diff --git a/gtk2_ardour/editor_route_list.cc b/gtk2_ardour/editor_route_list.cc index 964ee38712..340f678228 100644 --- a/gtk2_ardour/editor_route_list.cc +++ b/gtk2_ardour/editor_route_list.cc @@ -130,6 +130,7 @@ Editor::handle_new_route (RouteList& routes) ignore_route_list_reorder = false; route->gui_changed.connect (mem_fun(*this, &Editor::handle_gui_changes)); + tv->view()->RegionViewAdded.connect (mem_fun (*this, &Editor::region_view_added)); tv->GoingAway.connect (bind (mem_fun(*this, &Editor::remove_route), tv)); } @@ -144,6 +145,8 @@ Editor::handle_new_route (RouteList& routes) editor_list_button.set_sensitive(true); route_redisplay_does_not_sync_order_keys = false; + + _summary->set_dirty (); } void diff --git a/gtk2_ardour/editor_summary.cc b/gtk2_ardour/editor_summary.cc new file mode 100644 index 0000000000..3b9de030de --- /dev/null +++ b/gtk2_ardour/editor_summary.cc @@ -0,0 +1,220 @@ +#include "ardour/session.h" +#include "time_axis_view.h" +#include "streamview.h" +#include "editor_summary.h" +#include "gui_thread.h" +#include "editor.h" +#include "region_view.h" + +using namespace std; +using namespace sigc; +using namespace ARDOUR; + +EditorSummary::EditorSummary (Editor* e) + : _editor (e), + _session (0), + _pixmap (0), + _regions_dirty (true), + _width (512), + _height (64), + _pixels_per_frame (1) +{ + +} + +void +EditorSummary::set_session (Session* s) +{ + _session = s; + + Region::RegionPropertyChanged.connect (sigc::hide (mem_fun (*this, &EditorSummary::set_dirty))); + + _session->RegionRemoved.connect (sigc::hide (mem_fun (*this, &EditorSummary::set_dirty))); + _session->EndTimeChanged.connect (mem_fun (*this, &EditorSummary::set_dirty)); + _session->StartTimeChanged.connect (mem_fun (*this, &EditorSummary::set_dirty)); + + set_dirty (); +} + +EditorSummary::~EditorSummary () +{ + if (_pixmap) { + gdk_pixmap_unref (_pixmap); + } +} + +bool +EditorSummary::on_expose_event (GdkEventExpose* event) +{ + Gdk::Rectangle const exposure ( + event->area.x, event->area.y, event->area.width, event->area.height + ); + + Gdk::Rectangle r = exposure; + Gdk::Rectangle content (0, 0, _width, _height); + bool intersects; + r.intersect (content, intersects); + + if (intersects) { + + GdkPixmap* p = get_pixmap (get_window()->gobj ()); + + gdk_draw_drawable ( + get_window()->gobj(), + get_style()->get_fg_gc (Gtk::STATE_NORMAL)->gobj(), + p, + r.get_x(), + r.get_y(), + r.get_x(), + r.get_y(), + r.get_width(), + r.get_height() + ); + } + + cairo_t* cr = gdk_cairo_create (get_window()->gobj()); + + cairo_set_source_rgb (cr, 0, 1, 0); + cairo_set_line_width (cr, 2); + + double const s = (_editor->leftmost_position () - _session->current_start_frame ()) * _pixels_per_frame; + cairo_move_to (cr, s, 0); + cairo_line_to (cr, s, _height); + cairo_stroke (cr); + + double const e = s + _editor->current_page_frames() * _pixels_per_frame; + cairo_move_to (cr, e, 0); + cairo_line_to (cr, e, _height); + cairo_stroke (cr); + + cairo_destroy (cr); + + return true; +} + +GdkPixmap * +EditorSummary::get_pixmap (GdkDrawable* drawable) +{ + if (_regions_dirty) { + + if (_pixmap) { + gdk_pixmap_unref (_pixmap); + } + _pixmap = gdk_pixmap_new (drawable, _width, _height, -1); + + cairo_t* cr = gdk_cairo_create (_pixmap); + render (cr); + cairo_destroy (cr); + + _regions_dirty = false; + } + + return _pixmap; +} + +void +EditorSummary::render (cairo_t* cr) +{ + if (_session == 0) { + return; + } + + cairo_set_source_rgb (cr, 0, 0, 0); + cairo_rectangle (cr, 0, 0, _width, _height); + cairo_fill (cr); + + int N = 0; + + for (PublicEditor::TrackViewList::const_iterator i = _editor->track_views.begin(); i != _editor->track_views.end(); ++i) { + if ((*i)->view()) { + ++N; + } + } + + nframes_t const start = _session->current_start_frame (); + _pixels_per_frame = static_cast (_width) / (_session->current_end_frame() - start); + double const track_height = static_cast (_height) / N; + + cairo_set_line_width (cr, track_height); + + int n = 0; + for (PublicEditor::TrackViewList::const_iterator i = _editor->track_views.begin(); i != _editor->track_views.end(); ++i) { + StreamView* s = (*i)->view (); + if (s) { + + double const v = ((n % 2) == 0) ? 1 : 0.5; + cairo_set_source_rgb (cr, v, v, v); + + s->foreach_regionview (bind ( + mem_fun (*this, &EditorSummary::render_region), + cr, + start, + track_height * (n + 0.5) + )); + ++n; + } + } + +} + +void +EditorSummary::render_region (RegionView* r, cairo_t* cr, nframes_t start, double y) const +{ + cairo_move_to (cr, (r->region()->position() - start) * _pixels_per_frame, y); + cairo_line_to (cr, (r->region()->position() - start + r->region()->length()) * _pixels_per_frame, y); + cairo_stroke (cr); +} + +void +EditorSummary::set_dirty () +{ + ENSURE_GUI_THREAD (mem_fun (*this, &EditorSummary::set_dirty)); + + _regions_dirty = true; + queue_draw (); +} + +void +EditorSummary::set_bounds_dirty () +{ + ENSURE_GUI_THREAD (mem_fun (*this, &EditorSummary::set_bounds_dirty)); + queue_draw (); +} + +void +EditorSummary::on_size_request (Gtk::Requisition *req) +{ + req->width = 64; + req->height = 64; +} + +void +EditorSummary::on_size_allocate (Gtk::Allocation& alloc) +{ + Gtk::EventBox::on_size_allocate (alloc); + + _width = alloc.get_width (); + _height = alloc.get_height (); + + set_dirty (); +} + +bool +EditorSummary::on_button_press_event (GdkEventButton* ev) +{ + if (ev->button == 1) { + + nframes_t f = (ev->x / _pixels_per_frame) + _session->current_start_frame(); + + nframes_t const h = _editor->current_page_frames () / 2; + if (f > h) { + f -= h; + } else { + f = 0; + } + + _editor->reset_x_origin (f); + } + + return true; +} diff --git a/gtk2_ardour/editor_summary.h b/gtk2_ardour/editor_summary.h new file mode 100644 index 0000000000..b9632dc96f --- /dev/null +++ b/gtk2_ardour/editor_summary.h @@ -0,0 +1,41 @@ +#ifndef __gtk_ardour_editor_summary_h__ +#define __gtk_ardour_editor_summary_h__ + +#include + +namespace ARDOUR { + class Session; +} + +class Editor; + +class EditorSummary : public Gtk::EventBox +{ +public: + EditorSummary (Editor *); + ~EditorSummary (); + + void set_session (ARDOUR::Session *); + void set_dirty (); + void set_bounds_dirty (); + +private: + bool on_expose_event (GdkEventExpose *); + void on_size_request (Gtk::Requisition *); + void on_size_allocate (Gtk::Allocation &); + bool on_button_press_event (GdkEventButton *); + + void render (cairo_t *); + GdkPixmap* get_pixmap (GdkDrawable *); + void render_region (RegionView*, cairo_t*, nframes_t, double) const; + + Editor* _editor; + ARDOUR::Session* _session; + GdkPixmap* _pixmap; + bool _regions_dirty; + int _width; + int _height; + double _pixels_per_frame; +}; + +#endif diff --git a/gtk2_ardour/port_matrix_body.cc b/gtk2_ardour/port_matrix_body.cc index 75bf42c9b7..59444ba7ff 100644 --- a/gtk2_ardour/port_matrix_body.cc +++ b/gtk2_ardour/port_matrix_body.cc @@ -508,3 +508,4 @@ PortMatrixBody::component_size_changed () _matrix->setup_scrollbars (); } + diff --git a/gtk2_ardour/wscript b/gtk2_ardour/wscript index 1735f08a65..9b7ab1fd3f 100644 --- a/gtk2_ardour/wscript +++ b/gtk2_ardour/wscript @@ -120,6 +120,7 @@ def build(bld): editor_scrub.cc editor_selection.cc editor_selection_list.cc + editor_summary.cc editor_tempodisplay.cc editor_timefx.cc engine_dialog.cc -- 2.30.2