summaryrefslogtreecommitdiff
path: root/gtk2_ardour
diff options
context:
space:
mode:
authorPaul Davis <paul@linuxaudiosystems.com>2008-09-19 14:38:46 +0000
committerPaul Davis <paul@linuxaudiosystems.com>2008-09-19 14:38:46 +0000
commit6f8cd634501efd70711b148b4ac0e0ce2aa5cc95 (patch)
tree07df4b771792ec9a0b8ba7c8c01db0234f1efe22 /gtk2_ardour
parent60f588f21d6ad62335d72e8dc682abf8859107ea (diff)
chris goddard's region list patch; port 2.X marker drag/move changes to 3.0; compilation fixes-post-evoral
git-svn-id: svn://localhost/ardour2/branches/3.0@3760 d708f5d6-7413-0410-9779-e7cbd77b26cf
Diffstat (limited to 'gtk2_ardour')
-rw-r--r--gtk2_ardour/ardour_ui.cc27
-rw-r--r--gtk2_ardour/audio_clock.cc1
-rw-r--r--gtk2_ardour/audio_clock.h3
-rw-r--r--gtk2_ardour/draginfo.h6
-rw-r--r--gtk2_ardour/editor.cc26
-rw-r--r--gtk2_ardour/editor.h19
-rw-r--r--gtk2_ardour/editor_canvas.cc1
-rw-r--r--gtk2_ardour/editor_mouse.cc275
-rw-r--r--gtk2_ardour/editor_ops.cc124
-rw-r--r--gtk2_ardour/editor_region_list.cc297
-rw-r--r--gtk2_ardour/editor_selection.cc38
-rw-r--r--gtk2_ardour/marker_selection.h1
-rw-r--r--gtk2_ardour/selection.cc34
-rw-r--r--gtk2_ardour/selection.h2
-rw-r--r--gtk2_ardour/time_axis_view.cc6
15 files changed, 693 insertions, 167 deletions
diff --git a/gtk2_ardour/ardour_ui.cc b/gtk2_ardour/ardour_ui.cc
index 6c59837abc..a9dbc01db1 100644
--- a/gtk2_ardour/ardour_ui.cc
+++ b/gtk2_ardour/ardour_ui.cc
@@ -224,7 +224,7 @@ ARDOUR_UI::ARDOUR_UI (int *argcp, char **argvp[])
// We do not have jack linked in yet so;
last_shuttle_request = last_peak_grab = 0; // get_microseconds();
-
+
ARDOUR::Diskstream::DiskOverrun.connect (mem_fun(*this, &ARDOUR_UI::disk_overrun_handler));
ARDOUR::Diskstream::DiskUnderrun.connect (mem_fun(*this, &ARDOUR_UI::disk_underrun_handler));
@@ -933,15 +933,11 @@ ARDOUR_UI::update_disk_space()
nframes_t frames = session->available_capture_duration();
char buf[64];
-
+ nframes_t fr = session->frame_rate();
+
if (frames == max_frames) {
strcpy (buf, _("Disk: 24hrs+"));
} else {
- int hrs;
- int mins;
- int secs;
- nframes_t fr = session->frame_rate();
-
rec_enabled_streams = 0;
session->foreach_route (this, &ARDOUR_UI::count_recenabled_streams);
@@ -949,16 +945,29 @@ ARDOUR_UI::update_disk_space()
frames /= rec_enabled_streams;
}
+ int hrs;
+ int mins;
+ int secs;
+
hrs = frames / (fr * 3600);
frames -= hrs * fr * 3600;
mins = frames / (fr * 60);
frames -= mins * fr * 60;
secs = frames / fr;
-
+
snprintf (buf, sizeof(buf), _("Disk: %02dh:%02dm:%02ds"), hrs, mins, secs);
}
-
+
disk_space_label.set_text (buf);
+
+ // An attempt to make the disk space label flash red when space has run out.
+
+ if (frames < fr * 60 * 5) {
+ /* disk_space_box.style ("disk_space_label_empty"); */
+ } else {
+ /* disk_space_box.style ("disk_space_label"); */
+ }
+
}
gint
diff --git a/gtk2_ardour/audio_clock.cc b/gtk2_ardour/audio_clock.cc
index 23b9787408..58db7f636b 100644
--- a/gtk2_ardour/audio_clock.cc
+++ b/gtk2_ardour/audio_clock.cc
@@ -1994,6 +1994,7 @@ AudioClock::set_mode (Mode m)
if (!is_transient) {
ModeChanged (); /* EMIT SIGNAL */
+ mode_changed (); /* EMIT SIGNAL */
}
}
diff --git a/gtk2_ardour/audio_clock.h b/gtk2_ardour/audio_clock.h
index fe3eef30dc..7c1b6d386b 100644
--- a/gtk2_ardour/audio_clock.h
+++ b/gtk2_ardour/audio_clock.h
@@ -61,11 +61,12 @@ class AudioClock : public Gtk::HBox
void set_session (ARDOUR::Session *s);
sigc::signal<void> ValueChanged;
+ sigc::signal<void> mode_changed;
sigc::signal<void> ChangeAborted;
static sigc::signal<void> ModeChanged;
static std::vector<AudioClock*> clocks;
-
+
static bool has_focus() { return _has_focus; }
private:
diff --git a/gtk2_ardour/draginfo.h b/gtk2_ardour/draginfo.h
index 4b91fa6c1b..6d3a6b8de3 100644
--- a/gtk2_ardour/draginfo.h
+++ b/gtk2_ardour/draginfo.h
@@ -20,6 +20,8 @@
#ifndef __gtk2_ardour_drag_info_h_
#define __gtk2_ardour_drag_info_h_
+#include <list>
+
#include <gdk/gdk.h>
#include <stdint.h>
@@ -64,7 +66,9 @@ struct DragInfo {
bool move_threshold_passed;
bool want_move_threshold;
bool brushing;
- ARDOUR::Location* copied_location;
+ std::list<ARDOUR::Location*> copied_locations;
+
+ void clear_copied_locations ();
};
struct LineDragInfo {
diff --git a/gtk2_ardour/editor.cc b/gtk2_ardour/editor.cc
index 170e9b57e2..510b0f8537 100644
--- a/gtk2_ardour/editor.cc
+++ b/gtk2_ardour/editor.cc
@@ -195,6 +195,15 @@ show_me_the_size (Requisition* r, const char* what)
cerr << "size of " << what << " = " << r->width << " x " << r->height << endl;
}
+void
+DragInfo::clear_copied_locations ()
+{
+ for (list<Location*>::iterator i = copied_locations.begin(); i != copied_locations.end(); ++i) {
+ delete *i;
+ }
+ copied_locations.clear ();
+}
+
Editor::Editor ()
:
/* time display buttons */
@@ -263,7 +272,6 @@ Editor::Editor ()
clicked_control_point = 0;
last_update_frame = 0;
drag_info.item = 0;
- drag_info.copied_location = 0;
current_mixer_strip = 0;
current_bbt_points = 0;
@@ -641,7 +649,12 @@ Editor::Editor ()
region_list_display.set_model (region_list_model);
region_list_display.append_column (_("Regions"), region_list_columns.name);
- region_list_display.set_headers_visible (false);
+ region_list_display.append_column (_("Start"), region_list_columns.start);
+ region_list_display.append_column (_("End"), region_list_columns.end);
+ region_list_display.append_column (_("Length"), region_list_columns.length);
+ region_list_display.append_column (_("Used"), region_list_columns.used);
+ region_list_display.append_column (_("Path to parent file"), region_list_columns.path);
+ region_list_display.set_headers_visible (true);
CellRendererText* region_name_cell = dynamic_cast<CellRendererText*>(region_list_display.get_column_cell_renderer (0));
region_name_cell->property_editable() = true;
@@ -656,7 +669,7 @@ Editor::Editor ()
region_list_display.get_selection()->set_mode (SELECTION_MULTIPLE);
region_list_display.add_object_drag (region_list_columns.region.index(), "regions");
-
+
/* setup DnD handling */
list<TargetEntry> region_list_target_table;
@@ -669,8 +682,8 @@ Editor::Editor ()
region_list_display.signal_drag_data_received().connect (mem_fun(*this, &Editor::region_list_display_drag_data_received));
region_list_scroller.add (region_list_display);
- region_list_scroller.set_policy (POLICY_NEVER, POLICY_AUTOMATIC);
-
+ region_list_scroller.set_policy (POLICY_AUTOMATIC, POLICY_AUTOMATIC);
+
region_list_display.signal_key_press_event().connect (mem_fun(*this, &Editor::region_list_display_key_press));
region_list_display.signal_key_release_event().connect (mem_fun(*this, &Editor::region_list_display_key_release));
region_list_display.signal_button_press_event().connect (mem_fun(*this, &Editor::region_list_display_button_press), false);
@@ -678,6 +691,9 @@ Editor::Editor ()
region_list_display.get_selection()->signal_changed().connect (mem_fun(*this, &Editor::region_list_selection_changed));
// region_list_display.signal_popup_menu().connect (bind (mem_fun (*this, &Editor::show_region_list_display_context_menu), 1, 0));
+ ARDOUR_UI::instance()->secondary_clock.mode_changed.connect (mem_fun(*this, &Editor::redisplay_regions));
+ ARDOUR::Region::RegionPropertyChanged.connect (mem_fun(*this, &Editor::update_region_row));
+
named_selection_scroller.add (named_selection_display);
named_selection_scroller.set_policy (POLICY_NEVER, POLICY_AUTOMATIC);
diff --git a/gtk2_ardour/editor.h b/gtk2_ardour/editor.h
index 32de17a8a1..d2b0043d66 100644
--- a/gtk2_ardour/editor.h
+++ b/gtk2_ardour/editor.h
@@ -128,7 +128,7 @@ class Editor : public PublicEditor
public:
Editor ();
~Editor ();
-
+
void connect_to_session (ARDOUR::Session *);
ARDOUR::Session* current_session() const { return session; }
void first_idle ();
@@ -545,6 +545,8 @@ class Editor : public PublicEditor
void set_selected_track (TimeAxisView&, Selection::Operation op = Selection::Set, bool no_remove=false);
void select_all_tracks ();
+ int get_regionview_count_from_region_list (boost::shared_ptr<ARDOUR::Region> region);
+
bool set_selected_control_point_from_click (Selection::Operation op = Selection::Set, bool no_remove=false);
void set_selected_track_from_click (bool press, Selection::Operation op = Selection::Set, bool no_remove=false);
void set_selected_track_as_side_effect (bool force = false);
@@ -926,13 +928,23 @@ class Editor : public PublicEditor
struct RegionListDisplayModelColumns : public Gtk::TreeModel::ColumnRecord {
RegionListDisplayModelColumns() {
- add (name);
+ add (name);
add (region);
add (color_);
+ add (start);
+ add (end);
+ add (length);
+ add (used);
+ add (path);
}
- Gtk::TreeModelColumn<Glib::ustring> name;
+ Gtk::TreeModelColumn<Glib::ustring> name;
Gtk::TreeModelColumn<boost::shared_ptr<ARDOUR::Region> > region;
Gtk::TreeModelColumn<Gdk::Color> color_;
+ Gtk::TreeModelColumn<Glib::ustring> start;
+ Gtk::TreeModelColumn<Glib::ustring> end;
+ Gtk::TreeModelColumn<Glib::ustring> length;
+ Gtk::TreeModelColumn<Glib::ustring> used;
+ Gtk::TreeModelColumn<Glib::ustring> path;
};
RegionListDisplayModelColumns region_list_columns;
@@ -1080,6 +1092,7 @@ class Editor : public PublicEditor
void add_regions_to_region_display (std::vector<boost::weak_ptr<ARDOUR::Region> > & );
void region_hidden (boost::shared_ptr<ARDOUR::Region>);
void redisplay_regions ();
+ void update_region_row (boost::shared_ptr<ARDOUR::Region>);
bool no_region_list_redisplay;
void insert_into_tmp_regionlist(boost::shared_ptr<ARDOUR::Region>);
diff --git a/gtk2_ardour/editor_canvas.cc b/gtk2_ardour/editor_canvas.cc
index b74ece99be..27a6eb479e 100644
--- a/gtk2_ardour/editor_canvas.cc
+++ b/gtk2_ardour/editor_canvas.cc
@@ -207,6 +207,7 @@ Editor::initialize_canvas ()
range_bar_drag_rect = new ArdourCanvas::SimpleRect (*range_marker_group, 0.0, 0.0, 100, timebar_height);
range_bar_drag_rect->property_outline_pixels() = 0;
+ range_bar_drag_rect->hide ();
transport_bar_drag_rect = new ArdourCanvas::SimpleRect (*transport_marker_group, 0.0, 0.0, 100, timebar_height);
transport_bar_drag_rect->property_outline_pixels() = 0;
diff --git a/gtk2_ardour/editor_mouse.cc b/gtk2_ardour/editor_mouse.cc
index d0931e4579..ed7f46df08 100644
--- a/gtk2_ardour/editor_mouse.cc
+++ b/gtk2_ardour/editor_mouse.cc
@@ -1879,11 +1879,7 @@ Editor::finalize_drag ()
drag_info.last_pointer_frame = 0;
drag_info.current_pointer_frame = 0;
drag_info.brushing = false;
-
- if (drag_info.copied_location) {
- delete drag_info.copied_location;
- drag_info.copied_location = 0;
- }
+ drag_info.clear_copied_locations ();
}
void
@@ -1928,7 +1924,7 @@ Editor::start_grab (GdkEvent* event, Gdk::Cursor *cursor)
drag_info.want_move_threshold = false;
drag_info.pointer_frame_offset = 0;
drag_info.brushing = false;
- drag_info.copied_location = 0;
+ drag_info.clear_copied_locations ();
drag_info.original_x = 0;
drag_info.original_y = 0;
@@ -2320,6 +2316,7 @@ Editor::update_marker_drag_item (Location *location)
}
}
+
void
Editor::start_marker_grab (ArdourCanvas::Item* item, GdkEvent* event)
{
@@ -2343,7 +2340,6 @@ Editor::start_marker_grab (ArdourCanvas::Item* item, GdkEvent* event)
_dragging_edit_point = true;
- drag_info.copied_location = new Location (*location);
drag_info.pointer_frame_offset = drag_info.grab_frame - (is_start ? location->start() : location->end());
update_marker_drag_item (location);
@@ -2369,28 +2365,67 @@ Editor::start_marker_grab (ArdourCanvas::Item* item, GdkEvent* event)
selection->toggle (marker);
break;
case Selection::Set:
- selection->set (marker);
+ if (!selection->selected (marker)) {
+ selection->set (marker);
+ }
break;
case Selection::Extend:
- selection->add (marker);
+ {
+ Locations::LocationList ll;
+ list<Marker*> to_add;
+ nframes64_t s, e;
+ selection->markers.range (s, e);
+ s = min (marker->position(), s);
+ e = max (marker->position(), e);
+ s = min (s, e);
+ e = max (s, e);
+ if (e < max_frames) {
+ ++e;
+ }
+ session->locations()->find_all_between (s, e, ll, Location::Flags (0));
+ for (Locations::LocationList::iterator i = ll.begin(); i != ll.end(); ++i) {
+ LocationMarkers* lm = find_location_markers (*i);
+ if (lm) {
+ if (lm->start) {
+ to_add.push_back (lm->start);
+ }
+ if (lm->end) {
+ to_add.push_back (lm->end);
+ }
+ }
+ }
+ if (!to_add.empty()) {
+ selection->add (to_add);
+ }
break;
+ }
case Selection::Add:
selection->add (marker);
break;
}
+
+ /* set up copies for us to manipulate during the drag */
+
+ drag_info.clear_copied_locations ();
+
+ for (MarkerSelection::iterator i = selection->markers.begin(); i != selection->markers.end(); ++i) {
+ Location *l = find_location_from_marker (*i, is_start);
+ drag_info.copied_locations.push_back (new Location (*l));
+ }
}
void
Editor::marker_drag_motion_callback (ArdourCanvas::Item* item, GdkEvent* event)
{
nframes64_t f_delta;
- Marker* marker = (Marker *) drag_info.data;
- Location *real_location;
- Location *copy_location;
+ nframes64_t newframe;
bool is_start;
bool move_both = false;
+ Marker* dragged_marker = (Marker*) drag_info.data;
+ Marker* marker;
+ Location *real_location;
+ Location *copy_location;
- nframes64_t newframe;
if (drag_info.pointer_frame_offset <= drag_info.current_pointer_frame) {
newframe = drag_info.current_pointer_frame - drag_info.pointer_frame_offset;
} else {
@@ -2407,102 +2442,196 @@ Editor::marker_drag_motion_callback (ArdourCanvas::Item* item, GdkEvent* event)
return;
}
- /* call this to find out if its the start or end */
-
- if ((real_location = find_location_from_marker (marker, is_start)) == 0) {
- return;
+ if (Keyboard::modifier_state_equals (event->button.state, Keyboard::PrimaryModifier)) {
+ move_both = true;
}
- if (real_location->locked()) {
+ MarkerSelection::iterator i;
+ list<Location*>::iterator x;
+
+ /* find the marker we're dragging, and compute the delta */
+
+ for (i = selection->markers.begin(), x = drag_info.copied_locations.begin();
+ x != drag_info.copied_locations.end() && i != selection->markers.end();
+ ++i, ++x) {
+
+ copy_location = *x;
+ marker = *i;
+
+ if (marker == dragged_marker) {
+
+ if ((real_location = find_location_from_marker (marker, is_start)) == 0) {
+ /* que pasa ?? */
+ return;
+ }
+
+ if (real_location->is_mark()) {
+ f_delta = newframe - copy_location->start();
+ } else {
+
+
+ switch (marker->type()) {
+ case Marker::Start:
+ case Marker::LoopStart:
+ case Marker::PunchIn:
+ f_delta = newframe - copy_location->start();
+ break;
+
+ case Marker::End:
+ case Marker::LoopEnd:
+ case Marker::PunchOut:
+ f_delta = newframe - copy_location->end();
+ break;
+ default:
+ /* what kind of marker is this ? */
+ return;
+ }
+ }
+ break;
+ }
+ }
+
+ if (i == selection->markers.end()) {
+ /* hmm, impossible - we didn't find the dragged marker */
return;
}
- /* use the copy that we're "dragging" around */
-
- copy_location = drag_info.copied_location;
+ /* now move them all */
- f_delta = copy_location->end() - copy_location->start();
-
- if (Keyboard::modifier_state_equals (event->button.state, Keyboard::PrimaryModifier)) {
- move_both = true;
- }
+ for (i = selection->markers.begin(), x = drag_info.copied_locations.begin();
+ x != drag_info.copied_locations.end() && i != selection->markers.end();
+ ++i, ++x) {
- if (copy_location->is_mark()) {
- /* just move it */
+ copy_location = *x;
+ marker = *i;
- copy_location->set_start (newframe);
+ /* call this to find out if its the start or end */
+
+ if ((real_location = find_location_from_marker (marker, is_start)) == 0) {
+ continue;
+ }
+
+ if (real_location->locked()) {
+ continue;
+ }
- } else {
+ if (copy_location->is_mark()) {
- if (is_start) { // start-of-range marker
+ /* just move it */
- if (move_both) {
- copy_location->set_start (newframe);
- copy_location->set_end (newframe + f_delta);
- } else if (newframe < copy_location->end()) {
- copy_location->set_start (newframe);
- } else {
- snap_to (next, 1, true);
- copy_location->set_end (next);
- copy_location->set_start (newframe);
- }
+ copy_location->set_start (copy_location->start() + f_delta);
+
+ } else {
- } else { // end marker
+ nframes64_t new_start = copy_location->start() + f_delta;
+ nframes64_t new_end = copy_location->end() + f_delta;
- if (move_both) {
- copy_location->set_end (newframe);
- copy_location->set_start (newframe - f_delta);
- } else if (newframe > copy_location->start()) {
- copy_location->set_end (newframe);
+ if (is_start) { // start-of-range marker
+
+ if (move_both) {
+ copy_location->set_start (new_start);
+ copy_location->set_end (new_end);
+ } else if (new_start < copy_location->end()) {
+ copy_location->set_start (new_start);
+ } else {
+ snap_to (next, 1, true);
+ copy_location->set_end (next);
+ copy_location->set_start (newframe);
+ }
+
+ } else { // end marker
- } else if (newframe > 0) {
- snap_to (next, -1, true);
- copy_location->set_start (next);
- copy_location->set_end (newframe);
+ if (move_both) {
+ copy_location->set_end (new_end);
+ copy_location->set_start (new_start);
+ } else if (new_end > copy_location->start()) {
+ copy_location->set_end (new_end);
+ } else if (newframe > 0) {
+ snap_to (next, -1, true);
+ copy_location->set_start (next);
+ copy_location->set_end (newframe);
+ }
}
}
+ update_marker_drag_item (copy_location);
+
+ LocationMarkers* lm = find_location_markers (real_location);
+
+ if (lm) {
+ lm->set_position (copy_location->start(), copy_location->end());
+ }
}
drag_info.last_pointer_frame = drag_info.current_pointer_frame;
drag_info.first_move = false;
- update_marker_drag_item (copy_location);
-
- LocationMarkers* lm = find_location_markers (real_location);
- lm->set_position (copy_location->start(), copy_location->end());
- edit_point_clock.set (copy_location->start());
+ if (drag_info.copied_locations.empty()) {
+ abort();
+ }
+ edit_point_clock.set (drag_info.copied_locations.front()->start());
show_verbose_time_cursor (newframe, 10);
+
+#ifdef GTKOSX
+ track_canvas->update_now ();
+#endif
}
void
Editor::marker_drag_finished_callback (ArdourCanvas::Item* item, GdkEvent* event)
{
if (drag_info.first_move) {
- /* just a click, do nothing but whatever selection occured */
+
+ /* just a click, do nothing but finish
+ off the selection process
+ */
+
+ Selection::Operation op = Keyboard::selection_type (event->button.state);
+ Marker* marker = (Marker *) drag_info.data;
+
+ switch (op) {
+ case Selection::Set:
+ if (selection->selected (marker) && selection->markers.size() > 1) {
+ selection->set (marker);
+ }
+ break;
+
+ case Selection::Toggle:
+ case Selection::Extend:
+ case Selection::Add:
+ break;
+ }
+
return;
}
_dragging_edit_point = false;
- Marker* marker = (Marker *) drag_info.data;
- bool is_start;
begin_reversible_command ( _("move marker") );
XMLNode &before = session->locations()->get_state();
-
- Location * location = find_location_from_marker (marker, is_start);
- if (location) {
-
- if (location->locked()) {
- return;
- }
+ MarkerSelection::iterator i;
+ list<Location*>::iterator x;
+ bool is_start;
- if (location->is_mark()) {
- location->set_start (drag_info.copied_location->start());
- } else {
- location->set (drag_info.copied_location->start(), drag_info.copied_location->end());
+ for (i = selection->markers.begin(), x = drag_info.copied_locations.begin();
+ x != drag_info.copied_locations.end() && i != selection->markers.end();
+ ++i, ++x) {
+
+ Location * location = find_location_from_marker ((*i), is_start);
+
+ if (location) {
+
+ if (location->locked()) {
+ return;
+ }
+
+ if (location->is_mark()) {
+ location->set_start ((*x)->start());
+ } else {
+ location->set ((*x)->start(), (*x)->end());
+ }
}
}
@@ -3696,6 +3825,12 @@ Editor::region_drag_motion_callback (ArdourCanvas::Item* item, GdkEvent* event)
/* for evaluation of the track position of iy1, we have to adjust
to allow for the vertical scrolling adjustment and the height of the timebars.
*/
+
+ cerr << "adjust y from " << iy1 << " using "
+ << vertical_adjustment.get_value() << " - "
+ << canvas_timebars_vsize
+ << endl;
+
iy1 += vertical_adjustment.get_value() - canvas_timebars_vsize;
TimeAxisView* tvp2 = trackview_by_y_position (iy1);
diff --git a/gtk2_ardour/editor_ops.cc b/gtk2_ardour/editor_ops.cc
index d52f4da231..df2752bd93 100644
--- a/gtk2_ardour/editor_ops.cc
+++ b/gtk2_ardour/editor_ops.cc
@@ -426,40 +426,45 @@ Editor::nudge_forward (bool next, bool force_playhead)
} else if (!force_playhead && !selection->markers.empty()) {
bool is_start;
- Location* loc = find_location_from_marker (selection->markers.front(), is_start);
- if (loc) {
-
- begin_reversible_command (_("nudge location forward"));
-
- XMLNode& before (loc->get_state());
-
- if (is_start) {
- distance = get_nudge_distance (loc->start(), next_distance);
- if (next) {
- distance = next_distance;
- }
- if (max_frames - distance > loc->start() + loc->length()) {
- loc->set_start (loc->start() + distance);
- } else {
- loc->set_start (max_frames - loc->length());
- }
- } else {
- distance = get_nudge_distance (loc->end(), next_distance);
- if (next) {
- distance = next_distance;
- }
- if (max_frames - distance > loc->end()) {
- loc->set_end (loc->end() + distance);
+ begin_reversible_command (_("nudge location forward"));
+
+ for (MarkerSelection::iterator i = selection->markers.begin(); i != selection->markers.end(); ++i) {
+
+ Location* loc = find_location_from_marker ((*i), is_start);
+
+ if (loc) {
+
+ XMLNode& before (loc->get_state());
+
+ if (is_start) {
+ distance = get_nudge_distance (loc->start(), next_distance);
+ if (next) {
+ distance = next_distance;
+ }
+ if (max_frames - distance > loc->start() + loc->length()) {
+ loc->set_start (loc->start() + distance);
+ } else {
+ loc->set_start (max_frames - loc->length());
+ }
} else {
- loc->set_end (max_frames);
+ distance = get_nudge_distance (loc->end(), next_distance);
+ if (next) {
+ distance = next_distance;
+ }
+ if (max_frames - distance > loc->end()) {
+ loc->set_end (loc->end() + distance);
+ } else {
+ loc->set_end (max_frames);
+ }
}
+ XMLNode& after (loc->get_state());
+ session->add_command (new MementoCommand<Location>(*loc, &before, &after));
}
- XMLNode& after (loc->get_state());
- session->add_command (new MementoCommand<Location>(*loc, &before, &after));
- commit_reversible_command ();
}
+ commit_reversible_command ();
+
} else {
distance = get_nudge_distance (playhead_cursor->current_frame, next_distance);
session->request_locate (playhead_cursor->current_frame + distance);
@@ -506,41 +511,48 @@ Editor::nudge_backward (bool next, bool force_playhead)
} else if (!force_playhead && !selection->markers.empty()) {
bool is_start;
- Location* loc = find_location_from_marker (selection->markers.front(), is_start);
-
- if (loc) {
- begin_reversible_command (_("nudge location forward"));
- XMLNode& before (loc->get_state());
+ begin_reversible_command (_("nudge location forward"));
- if (is_start) {
- distance = get_nudge_distance (loc->start(), next_distance);
- if (next) {
- distance = next_distance;
- }
- if (distance < loc->start()) {
- loc->set_start (loc->start() - distance);
- } else {
- loc->set_start (0);
- }
- } else {
- distance = get_nudge_distance (loc->end(), next_distance);
-
- if (next) {
- distance = next_distance;
- }
+ for (MarkerSelection::iterator i = selection->markers.begin(); i != selection->markers.end(); ++i) {
- if (distance < loc->end() - loc->length()) {
- loc->set_end (loc->end() - distance);
+ Location* loc = find_location_from_marker ((*i), is_start);
+
+ if (loc) {
+
+ XMLNode& before (loc->get_state());
+
+ if (is_start) {
+ distance = get_nudge_distance (loc->start(), next_distance);
+ if (next) {
+ distance = next_distance;
+ }
+ if (distance < loc->start()) {
+ loc->set_start (loc->start() - distance);
+ } else {
+ loc->set_start (0);
+ }
} else {
- loc->set_end (loc->length());
+ distance = get_nudge_distance (loc->end(), next_distance);
+
+ if (next) {
+ distance = next_distance;
+ }
+
+ if (distance < loc->end() - loc->length()) {
+ loc->set_end (loc->end() - distance);
+ } else {
+ loc->set_end (loc->length());
+ }
}
+
+ XMLNode& after (loc->get_state());
+ session->add_command (new MementoCommand<Location>(*loc, &before, &after));
}
-
- XMLNode& after (loc->get_state());
- session->add_command (new MementoCommand<Location>(*loc, &before, &after));
}
-
+
+ commit_reversible_command ();
+
} else {
distance = get_nudge_distance (playhead_cursor->current_frame, next_distance);
diff --git a/gtk2_ardour/editor_region_list.cc b/gtk2_ardour/editor_region_list.cc
index 121550f86f..c37540e2b1 100644
--- a/gtk2_ardour/editor_region_list.cc
+++ b/gtk2_ardour/editor_region_list.cc
@@ -30,6 +30,7 @@
#include <ardour/silentfilesource.h>
#include <ardour/session_region.h>
+
#include <gtkmm2ext/stop_signal.h>
#include "editor.h"
@@ -41,6 +42,7 @@
#include "region_view.h"
#include "utils.h"
+
#include "i18n.h"
using namespace sigc;
@@ -89,10 +91,18 @@ void
Editor::add_region_to_region_display (boost::shared_ptr<Region> region)
{
string str;
+ char start_str[16];
+ char end_str[16];
+ char length_str[16];
+ char used_str[8];
+ int used;
TreeModel::Row row;
Gdk::Color c;
bool missing_source;
+ BBT_Time bbt; // FIXME Why do these have to be declared here ?
+ SMPTE::Time smpte; // FIXME I would like them declared in the case statment where they are used.
+
missing_source = boost::dynamic_pointer_cast<SilentFileSource>(region->source());
if (!show_automatic_regions_in_region_list && region->automatic()) {
@@ -100,12 +110,10 @@ Editor::add_region_to_region_display (boost::shared_ptr<Region> region)
}
if (region->hidden()) {
-
TreeModel::iterator iter = region_list_model->get_iter ("0");
TreeModel::Row parent;
TreeModel::Row child;
-
if (!iter) {
parent = *(region_list_model->append());
@@ -113,21 +121,16 @@ Editor::add_region_to_region_display (boost::shared_ptr<Region> region)
parent[region_list_columns.name] = _("Hidden");
boost::shared_ptr<Region> proxy = parent[region_list_columns.region];
proxy.reset ();
-
} else {
-
if ((*iter)[region_list_columns.name] != _("Hidden")) {
-
parent = *(region_list_model->insert(iter));
parent[region_list_columns.name] = _("Hidden");
boost::shared_ptr<Region> proxy = parent[region_list_columns.region];
proxy.reset ();
-
} else {
parent = *iter;
}
-
}
row = *(region_list_model->append (parent.children()));
@@ -149,17 +152,16 @@ Editor::add_region_to_region_display (boost::shared_ptr<Region> region)
row = *(region_list_model->append());
if (missing_source) {
c.set_rgb(65535,0,0); // FIXME: error color from style
+ } else if (region->automatic()){
+ c.set_rgb(0,65535,0); // FIXME: error color from style
} else {
set_color(c, rgba_from_style ("RegionListWholeFile", 0xff, 0, 0, 0, "fg", Gtk::STATE_NORMAL, false ));
}
row[region_list_columns.color_] = c;
if (region->source()->name()[0] == '/') { // external file
-
if (region->whole_file()) {
-
boost::shared_ptr<AudioFileSource> afs = boost::dynamic_pointer_cast<AudioFileSource>(region->source());
-
str = ".../";
if (afs) {
@@ -173,9 +175,7 @@ Editor::add_region_to_region_display (boost::shared_ptr<Region> region)
}
} else {
-
str = region->name();
-
}
if (region->n_channels() > 1) {
@@ -186,14 +186,16 @@ Editor::add_region_to_region_display (boost::shared_ptr<Region> region)
str += ']';
}
- if (missing_source) {
- str += _(" (MISSING)");
- }
+ //if (missing_source) {
+ // str += _(" (MISSING)");
+ //}
row[region_list_columns.name] = str;
row[region_list_columns.region] = region;
- return;
+ if (region->automatic()) {
+ return;
+ }
} else {
@@ -204,7 +206,6 @@ Editor::add_region_to_region_display (boost::shared_ptr<Region> region)
bool found_parent = false;
for (i = rows.begin(); i != rows.end(); ++i) {
-
boost::shared_ptr<Region> rr = (*i)[region_list_columns.region];
boost::shared_ptr<AudioRegion> r = boost::dynamic_pointer_cast<AudioRegion>(rr);
@@ -228,21 +229,101 @@ Editor::add_region_to_region_display (boost::shared_ptr<Region> region)
}
}
}
-
if (!found_parent) {
row = *(region_list_model->append());
- }
-
+ }
+ }
+
+ used = get_regionview_count_from_region_list(region);
+ sprintf (used_str, "%4d" , used);
+
+ switch (ARDOUR_UI::instance()->secondary_clock.mode ()) {
+ case AudioClock::SMPTE:
+ case AudioClock::Off: /* If the secondary clock is off, default to SMPTE */
+ session->smpte_time (region->position(), smpte);
+ sprintf (start_str, "%02d:%02d:%02d:%02d", smpte.hours, smpte.minutes, smpte.seconds, smpte.frames);
+
+ session->smpte_time (region->position() + region->length() - 1, smpte);
+ sprintf (end_str, "%02d:%02d:%02d:%02d", smpte.hours, smpte.minutes, smpte.seconds, smpte.frames);
+
+ session->smpte_time (region->length(), smpte);
+ sprintf (length_str, "%02d:%02d:%02d:%02d", smpte.hours, smpte.minutes, smpte.seconds, smpte.frames);
+ break;
+
+ case AudioClock::BBT:
+ session->tempo_map().bbt_time (region->position(), bbt);
+ sprintf (start_str, "%03d|%02d|%04d" , bbt.bars, bbt.beats, bbt.ticks);
+ session->tempo_map().bbt_time (region->position() + region->length() - 1, bbt);
+ sprintf (end_str, "%03d|%02d|%04d" , bbt.bars, bbt.beats, bbt.ticks);
+ session->tempo_map().bbt_time (region->length(), bbt);
+ sprintf (length_str, "%03d|%02d|%04d" , bbt.bars, bbt.beats, bbt.ticks);
+ break;
+
+ case AudioClock::MinSec:
+ nframes_t left;
+ int hrs;
+ int mins;
+ float secs;
+
+ left = region->position();
+ hrs = (int) floor (left / (session->frame_rate() * 60.0f * 60.0f));
+ left -= (nframes_t) floor (hrs * session->frame_rate() * 60.0f * 60.0f);
+ mins = (int) floor (left / (session->frame_rate() * 60.0f));
+ left -= (nframes_t) floor (mins * session->frame_rate() * 60.0f);
+ secs = left / (float) session->frame_rate();
+ sprintf (start_str, "%02d:%02d:%06.3f", hrs, mins, secs);
+
+ left = region->position() + region->length() - 1;
+ hrs = (int) floor (left / (session->frame_rate() * 60.0f * 60.0f));
+ left -= (nframes_t) floor (hrs * session->frame_rate() * 60.0f * 60.0f);
+ mins = (int) floor (left / (session->frame_rate() * 60.0f));
+ left -= (nframes_t) floor (mins * session->frame_rate() * 60.0f);
+ secs = left / (float) session->frame_rate();
+ sprintf (end_str, "%02d:%02d:%06.3f", hrs, mins, secs);
+
+ left = region->length();
+ hrs = (int) floor (left / (session->frame_rate() * 60.0f * 60.0f));
+ left -= (nframes_t) floor (hrs * session->frame_rate() * 60.0f * 60.0f);
+ mins = (int) floor (left / (session->frame_rate() * 60.0f));
+ left -= (nframes_t) floor (mins * session->frame_rate() * 60.0f);
+ secs = left / (float) session->frame_rate();
+ sprintf (length_str, "%02d:%02d:%06.3f", hrs, mins, secs);
+ break;
+ case AudioClock::Frames:
+ snprintf (start_str, sizeof (start_str), "%u", region->position());
+ snprintf (end_str, sizeof (end_str), "%u", (region->position() + region->length() - 1));
+ snprintf (length_str, sizeof (length_str), "%u", region->length());
+ break;
+
+ default:
+ break;
}
row[region_list_columns.region] = region;
+ if (used > 1) {
+ row[region_list_columns.start] = "Multiple";
+ row[region_list_columns.end] = "Multiple";
+ } else {
+ row[region_list_columns.start] = start_str;
+ row[region_list_columns.end] = end_str;
+ }
+
+ row[region_list_columns.length] = length_str;
+ row[region_list_columns.used] = used_str;
+
+ if (missing_source) {
+ row[region_list_columns.path] = _("(MISSING) ") + region->source()->name();
+ } else {
+ row[region_list_columns.path] = region->source()->name();
+ }
+
if (region->n_channels() > 1) {
row[region_list_columns.name] = string_compose("%1 [%2]", region->name(), region->n_channels());
} else {
row[region_list_columns.name] = region->name();
- }
+ }
}
@@ -356,6 +437,180 @@ Editor::redisplay_regions ()
}
}
+
+void
+Editor::update_region_row (boost::shared_ptr<Region> region)
+{
+ if (!region || !session) {
+ return;
+ }
+
+ char start_str[16];
+ char end_str[16];
+ char length_str[16];
+ char used_str[8];
+ int used;
+ bool missing_source;
+ bool matched_region = false;
+ BBT_Time bbt;
+ SMPTE::Time smpte;
+
+ missing_source = boost::dynamic_pointer_cast<SilentFileSource>(region->source());
+
+ TreeModel::iterator found_region;
+
+ if (show_automatic_regions_in_region_list) {
+
+ TreeModel::iterator i;
+ TreeModel::iterator ii;
+ TreeModel::Children rows = region_list_model->children();
+
+ for (i = rows.begin(); i != rows.end(); ++i) {
+
+ cerr << "Parent " << (*i)[region_list_columns.name] << "\n";
+
+ TreeModel::Children subrows = (*i).children();
+
+ for (ii = subrows.begin(); ii != subrows.end(); ++ii) {
+
+ cerr << "Compare " << region->name() << " with child " << (*ii)[region_list_columns.name] << "\n";
+
+ boost::shared_ptr<Region> compared_region = (*ii)[region_list_columns.region];
+
+ if (region == compared_region) {
+ cerr << "Matched\n";
+ matched_region = true;
+ found_region = ii;
+ break;
+ }
+ }
+
+ if (matched_region) {
+ break;
+ }
+ }
+
+ } else {
+
+ TreeModel::iterator i;
+ TreeModel::Children rows = region_list_model->children();
+
+ for (i = rows.begin(); i != rows.end(); ++i) {
+
+ cerr << "Compare " << region->name() << " with " << (*i)[region_list_columns.name] << "\n";
+
+ boost::shared_ptr<Region> compared_region = (*i)[region_list_columns.region];
+
+ if (region == compared_region) {
+ cerr << "Matched\n";
+ matched_region = true;
+ found_region = i;
+ break;
+ }
+
+ }
+ }
+
+ if (!matched_region) {
+ cerr << "Returning - No match\n\n";
+ return;
+ }
+
+ used = get_regionview_count_from_region_list(region);
+ sprintf (used_str, "%4d" , used);
+
+ switch (ARDOUR_UI::instance()->secondary_clock.mode ()) {
+ case AudioClock::SMPTE:
+ case AudioClock::Off: // If the secondary clock is off, default to SMPTE
+ session->smpte_time (region->position(), smpte);
+ sprintf (start_str, "%02d:%02d:%02d:%02d", smpte.hours, smpte.minutes, smpte.seconds, smpte.frames);
+
+ session->smpte_time (region->position() + region->length() - 1, smpte);
+ sprintf (end_str, "%02d:%02d:%02d:%02d", smpte.hours, smpte.minutes, smpte.seconds, smpte.frames);
+
+ session->smpte_time (region->length(), smpte);
+ sprintf (length_str, "%02d:%02d:%02d:%02d", smpte.hours, smpte.minutes, smpte.seconds, smpte.frames);
+ break;
+
+ case AudioClock::BBT:
+ session->tempo_map().bbt_time (region->position(), bbt);
+ sprintf (start_str, "%03d|%02d|%04d" , bbt.bars, bbt.beats, bbt.ticks);
+ session->tempo_map().bbt_time (region->position() + region->length() - 1, bbt);
+ sprintf (end_str, "%03d|%02d|%04d" , bbt.bars, bbt.beats, bbt.ticks);
+ session->tempo_map().bbt_time (region->length(), bbt);
+ sprintf (length_str, "%03d|%02d|%04d" , bbt.bars, bbt.beats, bbt.ticks);
+ break;
+
+ case AudioClock::MinSec:
+ nframes_t left;
+ int hrs;
+ int mins;
+ float secs;
+
+ left = region->position();
+ hrs = (int) floor (left / (session->frame_rate() * 60.0f * 60.0f));
+ left -= (nframes_t) floor (hrs * session->frame_rate() * 60.0f * 60.0f);
+ mins = (int) floor (left / (session->frame_rate() * 60.0f));
+ left -= (nframes_t) floor (mins * session->frame_rate() * 60.0f);
+ secs = left / (float) session->frame_rate();
+ sprintf (start_str, "%02d:%02d:%06.3f", hrs, mins, secs);
+
+ left = region->position() + region->length() - 1;
+ hrs = (int) floor (left / (session->frame_rate() * 60.0f * 60.0f));
+ left -= (nframes_t) floor (hrs * session->frame_rate() * 60.0f * 60.0f);
+ mins = (int) floor (left / (session->frame_rate() * 60.0f));
+ left -= (nframes_t) floor (mins * session->frame_rate() * 60.0f);
+ secs = left / (float) session->frame_rate();
+ sprintf (end_str, "%02d:%02d:%06.3f", hrs, mins, secs);
+
+ left = region->length();
+ hrs = (int) floor (left / (session->frame_rate() * 60.0f * 60.0f));
+ left -= (nframes_t) floor (hrs * session->frame_rate() * 60.0f * 60.0f);
+ mins = (int) floor (left / (session->frame_rate() * 60.0f));
+ left -= (nframes_t) floor (mins * session->frame_rate() * 60.0f);
+ secs = left / (float) session->frame_rate();
+ sprintf (length_str, "%02d:%02d:%06.3f", hrs, mins, secs);
+ break;
+
+ case AudioClock::Frames:
+ snprintf (start_str, sizeof (start_str), "%u", region->position());
+ snprintf (end_str, sizeof (end_str), "%u", (region->position() + region->length() - 1));
+ snprintf (length_str, sizeof (length_str), "%u", region->length());
+ break;
+
+ default:
+ break;
+ }
+
+ cerr << "Updating " << (*found_region)[region_list_columns.name] << "\n";
+
+ if (used > 1) {
+ (*found_region)[region_list_columns.start] = "Multiple";
+ (*found_region)[region_list_columns.end] = "Multiple";
+ } else {
+ (*found_region)[region_list_columns.start] = start_str;
+ (*found_region)[region_list_columns.end] = end_str;
+ }
+
+ (*found_region)[region_list_columns.length] = length_str;
+ (*found_region)[region_list_columns.used] = used_str;
+
+ if (missing_source) {
+ (*found_region)[region_list_columns.path] = _("(MISSING) ") + region->source()->name();
+ } else {
+ (*found_region)[region_list_columns.path] = region->source()->name();
+ }
+
+ if (region->n_channels() > 1) {
+ (*found_region)[region_list_columns.name] = string_compose("%1 [%2]", region->name(), region->n_channels());
+ } else {
+ (*found_region)[region_list_columns.name] = region->name();
+ }
+
+ cerr << "Returning after updating\n\n";
+ //return;
+}
+
void
Editor::build_region_list_menu ()
{
diff --git a/gtk2_ardour/editor_selection.cc b/gtk2_ardour/editor_selection.cc
index f35391cff5..e1c6f4e7ea 100644
--- a/gtk2_ardour/editor_selection.cc
+++ b/gtk2_ardour/editor_selection.cc
@@ -362,6 +362,44 @@ Editor::get_equivalent_regions (RegionView* basis, vector<RegionView*>& equivale
equivalent_regions.push_back (basis);
}
+int
+Editor::get_regionview_count_from_region_list (boost::shared_ptr<Region> region)
+{
+ int region_count = 0;
+
+ for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
+
+ RouteTimeAxisView* tatv;
+
+ if ((tatv = dynamic_cast<RouteTimeAxisView*> (*i)) != 0) {
+
+ boost::shared_ptr<Playlist> pl;
+ vector<boost::shared_ptr<Region> > results;
+ RegionView* marv;
+ boost::shared_ptr<Diskstream> ds;
+
+ if ((ds = tatv->get_diskstream()) == 0) {
+ /* bus */
+ continue;
+ }
+
+ if ((pl = (ds->playlist())) != 0) {
+ pl->get_region_list_equivalent_regions (region, results);
+ }
+
+ for (vector<boost::shared_ptr<Region> >::iterator ir = results.begin(); ir != results.end(); ++ir) {
+ if ((marv = tatv->view()->find_view (*ir)) != 0) {
+ region_count++;
+ }
+ }
+
+ }
+ }
+
+ return region_count;
+}
+
+
bool
Editor::set_selected_regionview_from_click (bool press, Selection::Operation op, bool no_track_remove)
{
diff --git a/gtk2_ardour/marker_selection.h b/gtk2_ardour/marker_selection.h
index aa1413ed3e..ae6417f6c6 100644
--- a/gtk2_ardour/marker_selection.h
+++ b/gtk2_ardour/marker_selection.h
@@ -26,6 +26,7 @@
struct MarkerSelection : public std::list<Marker*>
{
+ void range (nframes64_t& start, nframes64_t& end);
};
#endif /* __ardour_gtk_marker_selection_h__ */
diff --git a/gtk2_ardour/selection.cc b/gtk2_ardour/selection.cc
index 2f9601fcec..3f6c282d3a 100644
--- a/gtk2_ardour/selection.cc
+++ b/gtk2_ardour/selection.cc
@@ -609,6 +609,12 @@ Selection::set (boost::shared_ptr<Evoral::ControlList> ac)
}
bool
+Selection::selected (Marker* m)
+{
+ return find (markers.begin(), markers.end(), m) != markers.end();
+}
+
+bool
Selection::selected (TimeAxisView* tv)
{
return find (tracks.begin(), tracks.end(), tv) != tracks.end();
@@ -801,3 +807,31 @@ Selection::add (Marker* m)
MarkersChanged();
}
}
+
+void
+Selection::add (const list<Marker*>& m)
+{
+ markers.insert (markers.end(), m.begin(), m.end());
+ MarkersChanged ();
+}
+
+void
+MarkerSelection::range (nframes64_t& s, nframes64_t& e)
+{
+ s = max_frames;
+ e = 0;
+
+ for (MarkerSelection::iterator i = begin(); i != end(); ++i) {
+
+ if ((*i)->position() < s) {
+ s = (*i)->position();
+ }
+
+ if ((*i)->position() > e) {
+ e = (*i)->position();
+ }
+ }
+
+ s = std::min (s, e);
+ e = std::max (s, e);
+}
diff --git a/gtk2_ardour/selection.h b/gtk2_ardour/selection.h
index c6923e663c..1e2257fc15 100644
--- a/gtk2_ardour/selection.h
+++ b/gtk2_ardour/selection.h
@@ -99,6 +99,7 @@ class Selection : public sigc::trackable
bool selected (TimeAxisView*);
bool selected (RegionView*);
+ bool selected (Marker*);
void set (std::list<Selectable*>&);
void add (std::list<Selectable*>&);
@@ -136,6 +137,7 @@ class Selection : public sigc::trackable
void add (boost::shared_ptr<ARDOUR::Playlist>);
void add (const std::list<boost::shared_ptr<ARDOUR::Playlist> >&);
void add (Marker*);
+ void add (const std::list<Marker*>&);
void add (const RegionSelection&);
void remove (TimeAxisView*);
diff --git a/gtk2_ardour/time_axis_view.cc b/gtk2_ardour/time_axis_view.cc
index f31ee1a10c..1f6d1f9da6 100644
--- a/gtk2_ardour/time_axis_view.cc
+++ b/gtk2_ardour/time_axis_view.cc
@@ -1181,10 +1181,14 @@ TimeAxisView::color_handler ()
TimeAxisView*
TimeAxisView::covers_y_position (double y)
{
+ if (y_position < 0) {
+ abort ();
+ }
+
if (hidden()) {
return 0;
}
-
+
cerr << name() << " check for " << y << " within " << y_position << " and + " << height << endl;
if (y_position <= y && y < (y_position + height)) {