update mixer-meter (width) and panner if channel count changes
[ardour.git] / gtk2_ardour / editor_canvas.cc
index 6da76503a72ca95876b60c284cdd4ebcc97d62a2..1a6dc863e182e86a9cc791e5b4dde58fe25c511e 100644 (file)
@@ -29,6 +29,7 @@
 
 #include "ardour/profile.h"
 #include "ardour/rc_configuration.h"
+#include "ardour/smf_source.h"
 
 #include "ardour_ui.h"
 #include "editor.h"
 #include "waveview.h"
 #include "simplerect.h"
 #include "simpleline.h"
-#include "imageframe.h"
 #include "waveview_p.h"
 #include "simplerect_p.h"
 #include "simpleline_p.h"
-#include "imageframe_p.h"
 #include "canvas_impl.h"
 #include "canvas-noevent-text.h"
 #include "editing.h"
@@ -51,6 +50,7 @@
 #include "region_view.h"
 #include "editor_group_tabs.h"
 #include "editor_summary.h"
+#include "video_timeline.h"
 #include "keyboard.h"
 #include "editor_cursors.h"
 #include "mouse_cursors.h"
@@ -87,14 +87,12 @@ static void ardour_canvas_type_init()
        Glib::wrap_register(gnome_canvas_simpleline_get_type(), &Gnome::Canvas::SimpleLine_Class::wrap_new);
        Glib::wrap_register(gnome_canvas_simplerect_get_type(), &Gnome::Canvas::SimpleRect_Class::wrap_new);
        Glib::wrap_register(gnome_canvas_waveview_get_type(), &Gnome::Canvas::WaveView_Class::wrap_new);
-       // Glib::wrap_register(gnome_canvas_imageframe_get_type(), &Gnome::Canvas::ImageFrame_Class::wrap_new);
 
        // Register the gtkmm gtypes:
 
        (void) Gnome::Canvas::WaveView::get_type();
        (void) Gnome::Canvas::SimpleLine::get_type();
        (void) Gnome::Canvas::SimpleRect::get_type();
-       (void) Gnome::Canvas::ImageFrame::get_type();
 }
 
 void
@@ -106,6 +104,9 @@ Editor::initialize_canvas ()
                track_canvas = new ArdourCanvas::CanvasAA ();
        }
 
+       track_canvas->set_can_default (true);
+       set_default (*track_canvas);
+
        ArdourCanvas::init ();
        ardour_canvas_type_init ();
 
@@ -183,6 +184,17 @@ Editor::initialize_canvas ()
        cd_marker_bar->property_outline_pixels() = 1;
        cd_marker_bar->property_outline_what() = 0x8;
 
+       videotl_bar_group = new ArdourCanvas::Group (*track_canvas->root ());
+       if (Profile->get_sae()) {
+               videotl_bar = new ArdourCanvas::SimpleRect (*videotl_bar_group, 0.0, 0.0, phys_width, (timebar_height * videotl_bar_height - 1));
+               videotl_bar->property_outline_pixels() = 1;
+       } else {
+               videotl_bar = new ArdourCanvas::SimpleRect (*videotl_bar_group, 0.0, 0.0, phys_width, (timebar_height * videotl_bar_height));
+               videotl_bar->property_outline_pixels() = 0;
+       }
+       videotl_bar->property_outline_what() = (0x1 | 0x8);
+       ARDOUR_UI::instance()->video_timeline = new VideoTimeLine(this, videotl_bar_group, (timebar_height * videotl_bar_height));
+
        timebar_group =  new ArdourCanvas::Group (*track_canvas->root(), 0.0, 0.0);
        cursor_group = new ArdourCanvas::Group (*track_canvas->root(), 0.0, 0.0);
 
@@ -192,6 +204,7 @@ Editor::initialize_canvas ()
        transport_marker_group = new ArdourCanvas::Group (*timebar_group, 0.0, timebar_height * 2.0);
        marker_group = new ArdourCanvas::Group (*timebar_group, 0.0, timebar_height);
        cd_marker_group = new ArdourCanvas::Group (*timebar_group, 0.0, 0.0);
+       videotl_group = new ArdourCanvas::Group (*timebar_group, 0.0, 0.0);
 
        cd_marker_bar_drag_rect = new ArdourCanvas::SimpleRect (*cd_marker_group, 0.0, 0.0, 100, timebar_height);
        cd_marker_bar_drag_rect->property_outline_pixels() = 0;
@@ -236,6 +249,7 @@ Editor::initialize_canvas ()
        meter_bar->signal_event().connect (sigc::bind (sigc::mem_fun (*this, &Editor::canvas_meter_bar_event), meter_bar));
        marker_bar->signal_event().connect (sigc::bind (sigc::mem_fun (*this, &Editor::canvas_marker_bar_event), marker_bar));
        cd_marker_bar->signal_event().connect (sigc::bind (sigc::mem_fun (*this, &Editor::canvas_cd_marker_bar_event), cd_marker_bar));
+       videotl_bar_group->signal_event().connect (sigc::bind (sigc::mem_fun (*this, &Editor::canvas_videotl_bar_event), videotl_bar));
        range_marker_bar->signal_event().connect (sigc::bind (sigc::mem_fun (*this, &Editor::canvas_range_marker_bar_event), range_marker_bar));
        transport_marker_bar->signal_event().connect (sigc::bind (sigc::mem_fun (*this, &Editor::canvas_transport_marker_bar_event), transport_marker_bar));
 
@@ -256,8 +270,8 @@ Editor::initialize_canvas ()
 
        track_canvas->set_name ("EditorMainCanvas");
        track_canvas->add_events (Gdk::POINTER_MOTION_HINT_MASK | Gdk::SCROLL_MASK | Gdk::KEY_PRESS_MASK | Gdk::KEY_RELEASE_MASK);
-       track_canvas->signal_leave_notify_event().connect (sigc::mem_fun(*this, &Editor::left_track_canvas));
-       track_canvas->signal_enter_notify_event().connect (sigc::mem_fun(*this, &Editor::entered_track_canvas));
+       track_canvas->signal_leave_notify_event().connect (sigc::mem_fun(*this, &Editor::left_track_canvas), false);
+       track_canvas->signal_enter_notify_event().connect (sigc::mem_fun(*this, &Editor::entered_track_canvas), false);
        track_canvas->set_flags (CAN_FOCUS);
 
        /* set up drag-n-drop */
@@ -388,16 +402,33 @@ Editor::track_canvas_drag_data_received (const RefPtr<Gdk::DragContext>& context
 }
 
 bool
-Editor::idle_drop_paths (vector<string> paths, framepos_t frame, double ypos)
+Editor::idle_drop_paths (vector<string> paths, framepos_t frame, double ypos, bool copy)
 {
-       drop_paths_part_two (paths, frame, ypos);
+       drop_paths_part_two (paths, frame, ypos, copy);
        return false;
 }
 
 void
-Editor::drop_paths_part_two (const vector<string>& paths, framepos_t frame, double ypos)
+Editor::drop_paths_part_two (const vector<string>& paths, framepos_t frame, double ypos, bool copy)
 {
        RouteTimeAxisView* tv;
+       
+       /* MIDI files must always be imported, because we consider them
+        * writable. So split paths into two vectors, and follow the import
+        * path on the MIDI part.
+        */
+
+       vector<string> midi_paths;
+       vector<string> audio_paths;
+
+       for (vector<string>::const_iterator i = paths.begin(); i != paths.end(); ++i) {
+               if (SMFSource::safe_midi_file_extension (*i)) {
+                       midi_paths.push_back (*i);
+               } else {
+                       audio_paths.push_back (*i);
+               }
+       }
+
 
        std::pair<TimeAxisView*, int> const tvp = trackview_by_y_position (ypos);
        if (tvp.first == 0) {
@@ -406,24 +437,28 @@ Editor::drop_paths_part_two (const vector<string>& paths, framepos_t frame, doub
 
                frame = 0;
 
-               if (Profile->get_sae() || Config->get_only_copy_imported_files()) {
-                       do_import (paths, Editing::ImportDistinctFiles, Editing::ImportAsTrack, SrcBest, frame);
+               do_import (midi_paths, Editing::ImportDistinctFiles, ImportAsTrack, SrcBest, frame);
+               
+               if (Profile->get_sae() || Config->get_only_copy_imported_files() || copy) {
+                       do_import (audio_paths, Editing::ImportDistinctFiles, Editing::ImportAsTrack, SrcBest, frame);
                } else {
-                       do_embed (paths, Editing::ImportDistinctFiles, ImportAsTrack, frame);
+                       do_embed (audio_paths, Editing::ImportDistinctFiles, ImportAsTrack, frame);
                }
 
        } else if ((tv = dynamic_cast<RouteTimeAxisView*> (tvp.first)) != 0) {
 
-               /* check that its an audio track, not a bus */
+               /* check that its a track, not a bus */
 
                if (tv->track()) {
                        /* select the track, then embed/import */
                        selection->set (tv);
 
-                       if (Profile->get_sae() || Config->get_only_copy_imported_files()) {
-                               do_import (paths, Editing::ImportSerializeFiles, Editing::ImportToTrack, SrcBest, frame);
+                       do_import (midi_paths, Editing::ImportSerializeFiles, ImportToTrack, SrcBest, frame);
+
+                       if (Profile->get_sae() || Config->get_only_copy_imported_files() || copy) {
+                               do_import (audio_paths, Editing::ImportSerializeFiles, Editing::ImportToTrack, SrcBest, frame);
                        } else {
-                               do_embed (paths, Editing::ImportSerializeFiles, ImportToTrack, frame);
+                               do_embed (audio_paths, Editing::ImportSerializeFiles, ImportToTrack, frame);
                        }
                }
        }
@@ -457,29 +492,21 @@ Editor::drop_paths (const RefPtr<Gdk::DragContext>& context,
 
                snap_to (frame);
 
+               bool copy = ((context->get_actions() & (Gdk::ACTION_COPY | Gdk::ACTION_LINK | Gdk::ACTION_MOVE)) == Gdk::ACTION_COPY);
 #ifdef GTKOSX
                /* We are not allowed to call recursive main event loops from within
                   the main event loop with GTK/Quartz. Since import/embed wants
                   to push up a progress dialog, defer all this till we go idle.
                */
-               Glib::signal_idle().connect (sigc::bind (sigc::mem_fun (*this, &Editor::idle_drop_paths), paths, frame, cy));
+               Glib::signal_idle().connect (sigc::bind (sigc::mem_fun (*this, &Editor::idle_drop_paths), paths, frame, cy, copy));
 #else
-               drop_paths_part_two (paths, frame, cy);
+               drop_paths_part_two (paths, frame, cy, copy);
 #endif
        }
 
        context->drag_finish (true, false, time);
 }
 
-void
-Editor::drop_regions (const RefPtr<Gdk::DragContext>& /*context*/,
-                     int /*x*/, int /*y*/,
-                     const SelectionData& /*data*/,
-                     guint /*info*/, guint /*time*/)
-{
-       _drags->end_grab (0);
-}
-
 /** If the editor window is arranged such that the edge of the trackview is right up
  *  against the edge of the screen, autoscroll will not work very well.  In this situation,
  *  we start autoscrolling some distance in from the right-hand-side of the screen edge;
@@ -491,9 +518,20 @@ Editor::autoscroll_fudge_threshold () const
        return current_page_frames() / 6;
 }
 
+/** @param allow_horiz true to allow horizontal autoscroll, otherwise false.
+ *  @param allow_vert true to allow vertical autoscroll, otherwise false.
+ *  @param moving_left true if we are moving left, so we only want to autoscroll on the left of the canvas,
+ *  otherwise false, so we only want to autoscroll on the right of the canvas.
+ *  @param moving_up true if we are moving up, so we only want to autoscroll at the top of the canvas,
+ *  otherwise false, so we only want to autoscroll at the bottom of the canvas.
+ */
 void
-Editor::maybe_autoscroll (bool allow_horiz, bool allow_vert)
+Editor::maybe_autoscroll (bool allow_horiz, bool allow_vert, bool moving_left, bool moving_up)
 {
+       if (!Config->get_autoscroll_editor ()) {
+               return;
+       }
+       
        bool startit = false;
 
        /* Work out the distance between the right hand edge of the trackview and the edge of
@@ -522,10 +560,10 @@ Editor::maybe_autoscroll (bool allow_horiz, bool allow_vert)
 
        autoscroll_y = 0;
        autoscroll_x = 0;
-       if (ty < canvas_timebars_vsize && allow_vert) {
+       if (ty < canvas_timebars_vsize && moving_up && allow_vert) {
                autoscroll_y = -1;
                startit = true;
-       } else if (ty > _canvas_height && allow_vert) {
+       } else if (ty > _canvas_height && !moving_up && allow_vert) {
                autoscroll_y = 1;
                startit = true;
        }
@@ -536,12 +574,12 @@ Editor::maybe_autoscroll (bool allow_horiz, bool allow_vert)
        }
 
        if (_drags->current_pointer_frame() > rightmost_frame && allow_horiz) {
-               if (rightmost_frame < max_framepos) {
+               if (rightmost_frame < max_framepos && !moving_left) {
                        autoscroll_x = 1;
                        startit = true;
                }
        } else if (_drags->current_pointer_frame() < leftmost_frame && allow_horiz) {
-               if (leftmost_frame > 0) {
+               if (leftmost_frame > 0 && moving_left) {
                        autoscroll_x = -1;
                        startit = true;
                }
@@ -724,6 +762,8 @@ bool
 Editor::left_track_canvas (GdkEventCrossing */*ev*/)
 {
        DropDownKeys ();
+       within_track_canvas = false;
+       //cerr << "left track canvas\n";
        set_entered_track (0);
        set_entered_regionview (0);
        reset_canvas_action_sensitivity (false);
@@ -733,6 +773,8 @@ Editor::left_track_canvas (GdkEventCrossing */*ev*/)
 bool
 Editor::entered_track_canvas (GdkEventCrossing */*ev*/)
 {
+       //cerr << "entered track canvas\n";
+       within_track_canvas = true;
        reset_canvas_action_sensitivity (true);
        return FALSE;
 }
@@ -790,6 +832,8 @@ Editor::set_horizontal_position (double p)
                _summary->set_overlays_dirty ();
        }
 
+       update_video_timeline();
+
        HorizontalPositionChanged (); /* EMIT SIGNAL */
 
 #ifndef GTKOSX
@@ -800,7 +844,6 @@ Editor::set_horizontal_position (double p)
                }
        }
 #endif
-
 }
 
 void
@@ -840,6 +883,9 @@ Editor::color_handler()
        cd_marker_bar->property_fill_color_rgba() = ARDOUR_UI::config()->canvasvar_CDMarkerBar.get();
        cd_marker_bar->property_outline_color_rgba() = ARDOUR_UI::config()->canvasvar_MarkerBarSeparator.get();
 
+       videotl_bar->property_fill_color_rgba() = ARDOUR_UI::config()->canvasvar_VideoBar.get();
+       videotl_bar->property_outline_color_rgba() = ARDOUR_UI::config()->canvasvar_MarkerBarSeparator.get();
+
        range_marker_bar->property_fill_color_rgba() = ARDOUR_UI::config()->canvasvar_RangeMarkerBar.get();
        range_marker_bar->property_outline_color_rgba() = ARDOUR_UI::config()->canvasvar_MarkerBarSeparator.get();