Work towards removal of Session's Diskstream list.
[ardour.git] / gtk2_ardour / audio_time_axis.cc
index e4155682fe9aefb1f666f6e7bdd5f637c050d835..ebaf3fdc2cc83467b25ec6966d595a28f1b58fab 100644 (file)
 
 #include <pbd/error.h>
 #include <pbd/stl_delete.h>
+#include <pbd/whitespace.h>
 
-#include <gtkmm2ext/utils.h>
-#include <gtkmm2ext/selector.h>
 #include <gtkmm2ext/gtk_ui.h>
+#include <gtkmm2ext/selector.h>
 #include <gtkmm2ext/stop_signal.h>
 #include <gtkmm2ext/bindable_button.h>
+#include <gtkmm2ext/utils.h>
 
-#include <ardour/session.h>
-#include <ardour/session_playlist.h>
 #include <ardour/audioplaylist.h>
-#include <ardour/diskstream.h>
-#include <ardour/utils.h>
-#include <ardour/playlist.h>
-#include <ardour/ladspa_plugin.h>
+#include <ardour/audio_diskstream.h>
 #include <ardour/insert.h>
+#include <ardour/ladspa_plugin.h>
 #include <ardour/location.h>
 #include <ardour/panner.h>
+#include <ardour/playlist.h>
+#include <ardour/session.h>
+#include <ardour/session_playlist.h>
+#include <ardour/utils.h>
 
 #include "ardour_ui.h"
-#include "public_editor.h"
 #include "audio_time_axis.h"
-#include "streamview.h"
-#include "canvas-simplerect.h"
-#include "playlist_selector.h"
-#include "plugin_selector.h"
-#include "plugin_ui.h"
-#include "regionview.h"
 #include "automation_gain_line.h"
 #include "automation_pan_line.h"
 #include "automation_time_axis.h"
-#include "redirect_automation_time_axis.h"
+#include "canvas_impl.h"
+#include "crossfade_view.h"
+#include "enums.h"
 #include "gain_automation_time_axis.h"
+#include "gui_thread.h"
+#include "keyboard.h"
 #include "pan_automation_time_axis.h"
+#include "playlist_selector.h"
+#include "plugin_selector.h"
+#include "plugin_ui.h"
+#include "point_selection.h"
+#include "prompter.h"
+#include "public_editor.h"
 #include "redirect_automation_line.h"
+#include "redirect_automation_time_axis.h"
+#include "regionview.h"
+#include "rgb_macros.h"
 #include "selection.h"
-#include "point_selection.h"
-#include "enums.h"
+#include "simplerect.h"
+#include "streamview.h"
 #include "utils.h"
-#include "keyboard.h"
-#include "rgb_macros.h"
-#include "prompter.h"
-#include "crossfade_view.h"
-#include "gui_thread.h"
 
 #include <ardour/audio_track.h>
 
 #include "i18n.h"
 
 using namespace ARDOUR;
-//using namespace sigc;
+using namespace PBD;
 using namespace LADSPA;
 using namespace Gtk;
 using namespace Editing;
 
-static const gchar * small_x_xpm[] = {
-"11 11 2 1",
-"      c None",
-".     c #000000",
-"           ",
-"           ",
-"  .     .  ",
-"   .   .   ",
-"    . .    ",
-"     .     ",
-"    . .    ",
-"   .   .   ",
-"  .     .  ",
-"           ",
-"           "};
-
-AudioTimeAxisView::AudioTimeAxisView (PublicEditor& ed, Session& sess, Route& rt, Widget *canvas)
+
+AudioTimeAxisView::AudioTimeAxisView (PublicEditor& ed, Session& sess, Route& rt, Canvas& canvas)
        : AxisView(sess),
          RouteUI(rt, sess, _("m"), _("s"), _("r")), // mute, solo, and record
          TimeAxisView(sess,ed,(TimeAxisView*) 0, canvas),
@@ -133,11 +120,9 @@ AudioTimeAxisView::AudioTimeAxisView (PublicEditor& ed, Session& sess, Route& rt
 
        ignore_toggle = false;
 
-       rec_enable_button->set_active (false);
        mute_button->set_active (false);
        solo_button->set_active (false);
        
-       rec_enable_button->set_name ("TrackRecordEnableButton");
        mute_button->set_name ("TrackMuteButton");
        solo_button->set_name ("SoloButton");
        edit_group_button.set_name ("TrackGroupButton");
@@ -147,41 +132,47 @@ AudioTimeAxisView::AudioTimeAxisView (PublicEditor& ed, Session& sess, Route& rt
        visual_button.set_name ("TrackVisualButton");
        hide_button.set_name ("TrackRemoveButton");
 
-       hide_button.add (*(manage (new Image (Gdk::Pixbuf::create_from_xpm_data(small_x_xpm)))));
-       
-       _route.mute_changed.connect (mem_fun(*this, &RouteUI::mute_changed));
-       _route.solo_changed.connect (mem_fun(*this, &RouteUI::solo_changed));
-       _route.solo_safe_changed.connect (mem_fun(*this, &RouteUI::solo_changed));
-
-       _route.panner().Changed.connect (mem_fun(*this, &AudioTimeAxisView::update_pans));
-
-       solo_button->signal_button_press_event().connect (mem_fun(*this, &RouteUI::solo_press));
-       solo_button->signal_button_release_event().connect (mem_fun(*this, &RouteUI::solo_release));
-       mute_button->signal_button_press_event().connect (mem_fun(*this, &RouteUI::mute_press));
-       mute_button->signal_button_release_event().connect (mem_fun(*this, &RouteUI::mute_release));
-       rec_enable_button->signal_button_press_event().connect (mem_fun(*this, &RouteUI::rec_enable_press));
-       edit_group_button.signal_button_release_event().connect (mem_fun(*this, &AudioTimeAxisView::edit_click));
+       hide_button.add (*(manage (new Image (get_xpm("small_x.xpm")))));
+
+       solo_button->signal_button_press_event().connect (mem_fun (*this, &AudioTimeAxisView::select_me), false);
+       mute_button->signal_button_press_event().connect (mem_fun (*this, &AudioTimeAxisView::select_me), false);
+       playlist_button.signal_button_press_event().connect (mem_fun (*this, &AudioTimeAxisView::select_me), false);
+       automation_button.signal_button_press_event().connect (mem_fun (*this, &AudioTimeAxisView::select_me), false);
+       size_button.signal_button_press_event().connect (mem_fun (*this, &AudioTimeAxisView::select_me), false);
+       visual_button.signal_button_press_event().connect (mem_fun (*this, &AudioTimeAxisView::select_me), false);
+       hide_button.signal_button_press_event().connect (mem_fun (*this, &AudioTimeAxisView::select_me), false);
+
+       solo_button->signal_button_press_event().connect (mem_fun(*this, &RouteUI::solo_press), false);
+       solo_button->signal_button_release_event().connect (mem_fun(*this, &RouteUI::solo_release), false);
+       mute_button->signal_button_press_event().connect (mem_fun(*this, &RouteUI::mute_press), false);
+       mute_button->signal_button_release_event().connect (mem_fun(*this, &RouteUI::mute_release), false);
+       edit_group_button.signal_button_release_event().connect (mem_fun(*this, &AudioTimeAxisView::edit_click), false);
        playlist_button.signal_clicked().connect (mem_fun(*this, &AudioTimeAxisView::playlist_click));
        automation_button.signal_clicked().connect (mem_fun(*this, &AudioTimeAxisView::automation_click));
-       size_button.signal_button_release_event().connect (mem_fun(*this, &AudioTimeAxisView::size_click));
+       size_button.signal_button_release_event().connect (mem_fun(*this, &AudioTimeAxisView::size_click), false);
        visual_button.signal_clicked().connect (mem_fun(*this, &AudioTimeAxisView::visual_click));
        hide_button.signal_clicked().connect (mem_fun(*this, &AudioTimeAxisView::hide_click));
 
-       name_entry.signal_activate().connect (mem_fun(*this, &AudioTimeAxisView::name_entry_activated));
-       name_entry.signal_focus_out_event().connect (mem_fun(*this, &AudioTimeAxisView::name_entry_focus_out_handler));
-       name_entry.signal_button_press_event().connect (mem_fun(*this, &AudioTimeAxisView::name_entry_button_press_handler));
-       name_entry.signal_button_release_event().connect (mem_fun(*this, &AudioTimeAxisView::name_entry_button_release_handler));
-       name_entry.signal_key_release_event().connect (mem_fun(*this, &AudioTimeAxisView::name_entry_key_release_handler));
-       
+       // FIXME: hack (pretty colours)
+       if (is_audio_track())
+               controls_ebox.set_name ("AudioTimeAxisViewControlsBaseUnselected");
+       else
+               controls_ebox.set_name ("MidiTimeAxisViewControlsBaseUnselected");
+
        if (is_audio_track()) {
-               controls_table.attach (*rec_enable_button, 6, 7, 0, 1, Gtk::FILL|Gtk::EXPAND, Gtk::FILL|Gtk::EXPAND, 0, 0);
+               rec_enable_button->set_active (false);
+               rec_enable_button->set_name ("TrackRecordEnableButton");
+               rec_enable_button->signal_button_press_event().connect (mem_fun (*this, &AudioTimeAxisView::select_me), false);
+               rec_enable_button->signal_button_press_event().connect (mem_fun(*this, &RouteUI::rec_enable_press));
+               controls_table.attach (*rec_enable_button, 5, 6, 0, 1, Gtk::FILL|Gtk::EXPAND, Gtk::FILL|Gtk::EXPAND, 0, 0);
+               ARDOUR_UI::instance()->tooltips().set_tip(*rec_enable_button, _("Record"));
        }
-       controls_table.attach (*mute_button, 7, 8, 0, 1, Gtk::FILL|Gtk::EXPAND, Gtk::FILL|Gtk::EXPAND, 0, 0);
-       controls_table.attach (*solo_button, 8, 9, 0, 1, Gtk::FILL|Gtk::EXPAND, Gtk::FILL|Gtk::FILL|Gtk::EXPAND, 0, 0);
 
-       controls_table.attach (edit_group_button, 7, 8, 1, 2, Gtk::FILL|Gtk::EXPAND, Gtk::FILL|Gtk::EXPAND, 0, 0);
+       controls_table.attach (*mute_button, 6, 7, 0, 1, Gtk::FILL|Gtk::EXPAND, Gtk::FILL|Gtk::EXPAND, 0, 0);
+       controls_table.attach (*solo_button, 7, 8, 0, 1, Gtk::FILL|Gtk::EXPAND, Gtk::FILL|Gtk::FILL|Gtk::EXPAND, 0, 0);
+
+       controls_table.attach (edit_group_button, 6, 7, 1, 2, Gtk::FILL|Gtk::EXPAND, Gtk::FILL|Gtk::EXPAND, 0, 0);
 
-       ARDOUR_UI::instance()->tooltips().set_tip(*rec_enable_button, _("Record"));
        ARDOUR_UI::instance()->tooltips().set_tip(*solo_button,_("Solo"));
        ARDOUR_UI::instance()->tooltips().set_tip(*mute_button,_("Mute"));
        ARDOUR_UI::instance()->tooltips().set_tip(edit_group_button,_("Edit Group"));
@@ -198,9 +189,8 @@ AudioTimeAxisView::AudioTimeAxisView (PublicEditor& ed, Session& sess, Route& rt
        controls_table.attach (size_button, 2, 3, 1, 2, Gtk::FILL|Gtk::EXPAND, Gtk::FILL|Gtk::EXPAND);
        controls_table.attach (automation_button, 3, 4, 1, 2, Gtk::FILL|Gtk::EXPAND, Gtk::FILL|Gtk::EXPAND);
 
-       if (is_audio_track()) {
-               controls_table.attach (playlist_button, 6, 7, 1, 2, Gtk::FILL|Gtk::EXPAND, Gtk::FILL|Gtk::EXPAND);
-
+       if (is_audio_track() && audio_track()->mode() == ARDOUR::Normal) {
+               controls_table.attach (playlist_button, 5, 6, 1, 2, Gtk::FILL|Gtk::EXPAND, Gtk::FILL|Gtk::EXPAND);
        }
 
        /* remove focus from the buttons */
@@ -230,8 +220,9 @@ AudioTimeAxisView::AudioTimeAxisView (PublicEditor& ed, Session& sess, Route& rt
        _route.mute_changed.connect (mem_fun(*this, &RouteUI::mute_changed));
        _route.solo_changed.connect (mem_fun(*this, &RouteUI::solo_changed));
        _route.redirects_changed.connect (mem_fun(*this, &AudioTimeAxisView::redirects_changed));
-
        _route.name_changed.connect (mem_fun(*this, &AudioTimeAxisView::route_name_changed));
+       _route.solo_safe_changed.connect (mem_fun(*this, &RouteUI::solo_changed));
+       _route.panner().Changed.connect (mem_fun(*this, &AudioTimeAxisView::update_pans));
 
        if (is_audio_track()) {
 
@@ -239,8 +230,8 @@ AudioTimeAxisView::AudioTimeAxisView (PublicEditor& ed, Session& sess, Route& rt
 
                audio_track()->FreezeChange.connect (mem_fun(*this, &AudioTimeAxisView::map_frozen));
 
-               audio_track()->diskstream_changed.connect (mem_fun(*this, &AudioTimeAxisView::diskstream_changed));
-               get_diskstream()->speed_changed.connect (mem_fun(*this, &AudioTimeAxisView::speed_changed));
+               audio_track()->DiskstreamChanged.connect (mem_fun(*this, &AudioTimeAxisView::diskstream_changed));
+               get_diskstream()->SpeedChanged.connect (mem_fun(*this, &AudioTimeAxisView::speed_changed));
 
                controls_ebox.set_name ("AudioTrackControlsBaseUnselected");
                controls_base_selected_name = "AudioTrackControlsBaseSelected";
@@ -257,7 +248,6 @@ AudioTimeAxisView::AudioTimeAxisView (PublicEditor& ed, Session& sess, Route& rt
                map_frozen ();
 
        } else {
-
                /* bus */
 
                controls_ebox.set_name ("BusControlsBaseUnselected");
@@ -266,6 +256,7 @@ AudioTimeAxisView::AudioTimeAxisView (PublicEditor& ed, Session& sess, Route& rt
        }
 
        editor.ZoomChanged.connect (mem_fun(*this, &AudioTimeAxisView::reset_samples_per_unit));
+       ColorChanged.connect (mem_fun (*this, &AudioTimeAxisView::color_handler));
 }
 
 AudioTimeAxisView::~AudioTimeAxisView ()
@@ -342,29 +333,32 @@ AudioTimeAxisView::edit_click (GdkEventButton *ev)
        using namespace Menu_Helpers;
 
        MenuList& items = edit_group_menu.items ();
+       RadioMenuItem::Group group;
 
        items.clear ();
-       items.push_back (RadioMenuElem (edit_group_menu_radio_group, _("No group"), 
-                                  bind (mem_fun(*this, &AudioTimeAxisView::set_edit_group_from_menu), (RouteGroup *) 0)));
+       items.push_back (RadioMenuElem (group, _("No group"), 
+                                       bind (mem_fun(*this, &AudioTimeAxisView::set_edit_group_from_menu), (RouteGroup *) 0)));
        
        if (_route.edit_group() == 0) {
                static_cast<RadioMenuItem*>(&items.back())->set_active ();
        }
-
-       _session.foreach_edit_group (this, &AudioTimeAxisView::add_edit_group_menu_item);
+       
+       _session.foreach_edit_group (bind (mem_fun (*this, &AudioTimeAxisView::add_edit_group_menu_item), &group));
        edit_group_menu.popup (ev->button, ev->time);
 
        return FALSE;
 }
 
 void
-AudioTimeAxisView::add_edit_group_menu_item (RouteGroup *eg)
+AudioTimeAxisView::add_edit_group_menu_item (RouteGroup *eg, RadioMenuItem::Group* group)
 {
        using namespace Menu_Helpers;
 
        MenuList &items = edit_group_menu.items();
-       items.push_back (RadioMenuElem (edit_group_menu_radio_group,
-                                       eg->name(), bind (mem_fun(*this, &AudioTimeAxisView::set_edit_group_from_menu), eg)));
+
+       cerr << "adding edit group called " << eg->name() << endl;
+
+       items.push_back (RadioMenuElem (*group, eg->name(), bind (mem_fun(*this, &AudioTimeAxisView::set_edit_group_from_menu), eg)));
        if (_route.edit_group() == eg) {
                static_cast<RadioMenuItem*>(&items.back())->set_active ();
        }
@@ -391,7 +385,7 @@ AudioTimeAxisView::playlist_changed ()
        label_view ();
 
        if (is_audio_track()) {
-               set_playlist (get_diskstream()->playlist());
+               set_playlist (dynamic_cast<AudioPlaylist*>(get_diskstream()->playlist()));
        }
 }
 
@@ -484,30 +478,26 @@ AudioTimeAxisView::show_timestretch (jack_nframes_t start, jack_nframes_t end)
 #endif
 
        if (timestretch_rect == 0) {
-               timestretch_rect = gnome_canvas_item_new (GNOME_CANVAS_GROUP(canvas_display),
-                                                       gnome_canvas_simplerect_get_type(),
-                                                       "x1", 0.0,
-                                                       "y1", 0.0,
-                                                       "x2", 0.0,
-                                                       "y2", 0.0,
-                                                       "fill_color_rgba", color_map[cTimeStretchFill],
-                                                       "outline_color_rgba" , color_map[cTimeStretchOutline],
-                                                       NULL);
-       }
-
-       gnome_canvas_item_show (timestretch_rect);
-       gnome_canvas_item_raise_to_top (timestretch_rect);
-       
+               timestretch_rect = new SimpleRect (*canvas_display);
+               timestretch_rect->property_x1() =  0.0;
+               timestretch_rect->property_y1() =  0.0;
+               timestretch_rect->property_x2() =  0.0;
+               timestretch_rect->property_y2() =  0.0;
+               timestretch_rect->property_fill_color_rgba() =  color_map[cTimeStretchFill];
+               timestretch_rect->property_outline_color_rgba() = color_map[cTimeStretchOutline];
+       }
+
+       timestretch_rect->show ();
+       timestretch_rect->raise_to_top ();
+
        x1 = start / editor.get_current_zoom();
        x2 = (end - 1) / editor.get_current_zoom();
        y2 = height - 2;
        
-       gtk_object_set (GTK_OBJECT(timestretch_rect), 
-                       "x1", x1,
-                       "y1", 1.0,
-                       "x2", x2,
-                       "y2", y2,
-                       NULL);
+       timestretch_rect->property_x1() = x1;
+       timestretch_rect->property_y1() = 1.0;
+       timestretch_rect->property_x2() = x2;
+       timestretch_rect->property_y2() = y2;
 }
 
 void
@@ -516,7 +506,7 @@ AudioTimeAxisView::hide_timestretch ()
        TimeAxisView::hide_timestretch ();
 
        if (timestretch_rect) {
-               gnome_canvas_item_hide (timestretch_rect);
+               timestretch_rect->hide ();
        }
 }
 
@@ -595,7 +585,7 @@ AudioTimeAxisView::set_state (const XMLNode& node)
 void
 AudioTimeAxisView::set_height (TrackHeight h)
 {
-       bool height_changed = (h != (TrackHeight)height);
+       bool height_changed = (height == 0) || (h != height_style);
 
        TimeAxisView::set_height (h);
 
@@ -603,31 +593,36 @@ AudioTimeAxisView::set_height (TrackHeight h)
 
        view->set_height ((double) height);
 
-       switch (height) {
+       switch (height_style) {
        case Largest:
                xml_node->add_property ("track_height", "largest");
-               controls_table.show_all ();
-               name_label.hide ();
+               show_name_entry ();
+               hide_name_label ();
+               controls_table.show_all();
                break;
        case Large:
                xml_node->add_property ("track_height", "large");
-               controls_table.show_all ();
-               name_label.hide ();
+               show_name_entry ();
+               hide_name_label ();
+               controls_table.show_all();
                break;
        case Larger:
                xml_node->add_property ("track_height", "larger");
-               controls_table.show_all ();
-               name_label.hide ();
+               show_name_entry ();
+               hide_name_label ();
+               controls_table.show_all();
                break;
        case Normal:
                xml_node->add_property ("track_height", "normal");
-               controls_table.show_all ();
-               name_label.hide ();
+               show_name_entry ();
+               hide_name_label ();
+               controls_table.show_all();
                break;
        case Smaller:
                xml_node->add_property ("track_height", "smaller");
                controls_table.show_all ();
-               name_label.hide ();
+               show_name_entry ();
+               hide_name_label ();
                edit_group_button.hide ();
                hide_button.hide ();
                visual_button.hide ();
@@ -639,9 +634,9 @@ AudioTimeAxisView::set_height (TrackHeight h)
                xml_node->add_property ("track_height", "small");
                controls_table.hide_all ();
                controls_table.show ();
+               hide_name_entry ();
+               show_name_label ();
                name_label.set_text (_route.name());
-               name_label.show ();
-               name_hbox.show ();
                break;
        }
 
@@ -719,28 +714,30 @@ AudioTimeAxisView::build_display_menu ()
        items.push_back (MenuElem (_("Show all crossfades"), mem_fun(*this, &AudioTimeAxisView::show_all_xfades)));
        items.push_back (SeparatorElem());
 
+       build_remote_control_menu ();
+       items.push_back (MenuElem (_("Remote Control ID"), *remote_control_menu));
 
        automation_action_menu = manage (new Menu);
        MenuList& automation_items = automation_action_menu->items();
        automation_action_menu->set_name ("ArdourContextMenu");
        
-       automation_items.push_back (MenuElem (_("show all automation"),
+       automation_items.push_back (MenuElem (_("Show all automation"),
                                              mem_fun(*this, &AudioTimeAxisView::show_all_automation)));
 
-       automation_items.push_back (MenuElem (_("show existing automation"),
+       automation_items.push_back (MenuElem (_("Show existing automation"),
                                              mem_fun(*this, &AudioTimeAxisView::show_existing_automation)));
 
-       automation_items.push_back (MenuElem (_("hide all automation"),
+       automation_items.push_back (MenuElem (_("Hide all automation"),
                                              mem_fun(*this, &AudioTimeAxisView::hide_all_automation)));
 
        automation_items.push_back (SeparatorElem());
 
-       automation_items.push_back (CheckMenuElem (_("gain"), 
+       automation_items.push_back (CheckMenuElem (_("Fader"), 
                                                   mem_fun(*this, &AudioTimeAxisView::toggle_gain_track)));
        gain_automation_item = static_cast<CheckMenuItem*> (&automation_items.back());
        gain_automation_item->set_active(show_gain_automation);
 
-       automation_items.push_back (CheckMenuElem (_("pan"),
+       automation_items.push_back (CheckMenuElem (_("Pan"),
                                                   mem_fun(*this, &AudioTimeAxisView::toggle_pan_track)));
        pan_automation_item = static_cast<CheckMenuItem*> (&automation_items.back());
        pan_automation_item->set_active(show_pan_automation);
@@ -777,12 +774,12 @@ AudioTimeAxisView::build_display_menu ()
 
                RadioMenuItem::Group align_group;
                
-               alignment_items.push_back (RadioMenuElem (align_group, _("align with existing material"), bind (mem_fun(*this, &AudioTimeAxisView::set_align_style), ExistingMaterial)));
+               alignment_items.push_back (RadioMenuElem (align_group, _("Align with existing material"), bind (mem_fun(*this, &AudioTimeAxisView::set_align_style), ExistingMaterial)));
                align_existing_item = dynamic_cast<RadioMenuItem*>(&alignment_items.back());
                if (get_diskstream()->alignment_style() == ExistingMaterial) {
                        align_existing_item->set_active();
                }
-               alignment_items.push_back (RadioMenuElem (align_group, _("align with capture time"), bind (mem_fun(*this, &AudioTimeAxisView::set_align_style), CaptureTime)));
+               alignment_items.push_back (RadioMenuElem (align_group, _("Align with capture time"), bind (mem_fun(*this, &AudioTimeAxisView::set_align_style), CaptureTime)));
                align_capture_item = dynamic_cast<RadioMenuItem*>(&alignment_items.back());
                if (get_diskstream()->alignment_style() == CaptureTime) {
                        align_capture_item->set_active();
@@ -833,19 +830,24 @@ AudioTimeAxisView::rename_current_playlist ()
        string name;
 
        AudioPlaylist *pl;
-       DiskStream *ds;
+       AudioDiskstream *ds;
 
-       if (((ds = get_diskstream()) == 0) ||((pl = ds->playlist()) == 0)) {
+       if (((ds = dynamic_cast<AudioDiskstream*>(get_diskstream())) == 0) || ds->destructive()
+                       || ((pl = dynamic_cast<AudioPlaylist*>(ds->playlist())) == 0)) {
                return;
        }
 
        prompter.set_prompt (_("Name for playlist"));
        prompter.set_initial_text (pl->name());
+       prompter.add_button (_("Rename"), Gtk::RESPONSE_ACCEPT);
+       prompter.set_response_sensitive (Gtk::RESPONSE_ACCEPT, false);
 
        switch (prompter.run ()) {
-       case GTK_RESPONSE_ACCEPT:
+       case Gtk::RESPONSE_ACCEPT:
                prompter.get_result (name);
-               pl->set_name (name);
+               if (name.length()) {
+                       pl->set_name (name);
+               }
                break;
 
        default:
@@ -854,84 +856,94 @@ AudioTimeAxisView::rename_current_playlist ()
 }
 
 void
-AudioTimeAxisView::playlist_selected (AudioPlaylist *pl)
-{
-       DiskStream *ds;
-
-       if ((ds = get_diskstream()) != 0) {
-               ds->use_playlist (pl);
-       }
-}
-
-void
-AudioTimeAxisView::use_copy_playlist ()
+AudioTimeAxisView::use_copy_playlist (bool prompt)
 {
        AudioPlaylist *pl;
-       DiskStream *ds;
+       AudioDiskstream *ds;
        string name;
 
-       if (((ds = get_diskstream()) == 0) || ((pl = ds->playlist()) == 0)) {
+       if (((ds = dynamic_cast<AudioDiskstream*>(get_diskstream())) == 0) || ds->destructive()
+                       || ((pl = dynamic_cast<AudioPlaylist*>(ds->playlist())) == 0)) {
                return;
        }
        
-       ArdourPrompter prompter (true);
-       string new_name = Playlist::bump_name (pl->name(), _session);
-       
-       prompter.set_prompt (_("Name for playlist"));
-       prompter.set_initial_text (new_name);
-       prompter.show_all ();
+       name = Playlist::bump_name (pl->name(), _session);
 
-       switch (prompter.run ()) {
-       case GTK_RESPONSE_ACCEPT:
-               prompter.get_result (name);
+       if (prompt) {
+
+               ArdourPrompter prompter (true);
+               
+               prompter.set_prompt (_("Name for Playlist"));
+               prompter.set_initial_text (name);
+               prompter.add_button (Gtk::Stock::NEW, Gtk::RESPONSE_ACCEPT);
+               prompter.set_response_sensitive (Gtk::RESPONSE_ACCEPT, false);
+               prompter.show_all ();
+               
+               switch (prompter.run ()) {
+               case Gtk::RESPONSE_ACCEPT:
+                       prompter.get_result (name);
+                       break;
+                       
+               default:
+                       return;
+               }
+       }
+
+       if (name.length()) {
                ds->use_copy_playlist ();
-               pl = ds->playlist();
+               pl = dynamic_cast<AudioPlaylist*>(ds->playlist());
                pl->set_name (name);
-               break;
-
-       default:
-               break;
        }
 }
 
 void
-AudioTimeAxisView::use_new_playlist ()
+AudioTimeAxisView::use_new_playlist (bool prompt)
 {
        AudioPlaylist *pl;
-       DiskStream *ds;
+       AudioDiskstream *ds;
        string name;
 
-       if (((ds = get_diskstream()) == 0) || ((pl = ds->playlist()) == 0)) {
+       if (((ds = dynamic_cast<AudioDiskstream*>(get_diskstream())) == 0) || ds->destructive()
+                       || ((pl = dynamic_cast<AudioPlaylist*>(ds->playlist())) == 0)) {
                return;
        }
+       
+       name = Playlist::bump_name (pl->name(), _session);
 
-       ArdourPrompter prompter (true);
-       string new_name = Playlist::bump_name (pl->name(), _session);
+       if (prompt) {
+               
+               ArdourPrompter prompter (true);
+               
+               prompter.set_prompt (_("Name for Playlist"));
+               prompter.set_initial_text (name);
+               prompter.add_button (Gtk::Stock::NEW, Gtk::RESPONSE_ACCEPT);
+               prompter.set_response_sensitive (Gtk::RESPONSE_ACCEPT, false);
+               
+               switch (prompter.run ()) {
+               case Gtk::RESPONSE_ACCEPT:
+                       prompter.get_result (name);
+                       break;
+                       
+               default:
+                       return;
+               }
+       }
 
-       prompter.set_prompt (_("Name for playlist"));
-       prompter.set_initial_text (new_name);
-       
-       switch (prompter.run ()) {
-       case GTK_RESPONSE_ACCEPT:
-               prompter.get_result (name);
+       if (name.length()) {
                ds->use_new_playlist ();
-               pl = ds->playlist();
+               pl = dynamic_cast<AudioPlaylist*>(ds->playlist());
                pl->set_name (name);
-               break;
-
-       default:
-               break;
        }
-}      
+}
 
 void
 AudioTimeAxisView::clear_playlist ()
 {
        AudioPlaylist *pl;
-       DiskStream *ds;
+       AudioDiskstream *ds;
        
-       if ((ds = get_diskstream()) != 0) {
-               if ((pl = ds->playlist()) != 0) {
+       if ((ds = dynamic_cast<AudioDiskstream*>(get_diskstream())) != 0) {
+               if ((pl = dynamic_cast<AudioPlaylist*>(ds->playlist())) != 0) {
                        editor.clear_playlist (*pl);
                }
        }
@@ -986,10 +998,10 @@ AudioTimeAxisView::diskstream_changed (void *src)
 void
 AudioTimeAxisView::update_diskstream_display ()
 {
-       DiskStream *ds;
+       AudioDiskstream *ds;
 
-       if ((ds = get_diskstream()) != 0) {
-               set_playlist (ds->playlist ());
+       if ((ds = dynamic_cast<AudioDiskstream*>(get_diskstream())) != 0) {
+               set_playlist (dynamic_cast<AudioPlaylist*> (ds->playlist ()));
        }
 
        map_frozen ();
@@ -1000,14 +1012,19 @@ AudioTimeAxisView::selection_click (GdkEventButton* ev)
 {
        PublicEditor::TrackViewList* tracks = editor.get_valid_views (this, _route.edit_group());
 
-       if (Keyboard::modifier_state_contains (ev->state, Keyboard::Shift)) {
-               if (editor.get_selection().selected (this)) {
-                       editor.get_selection().remove (*tracks);
-               } else {
-                       editor.get_selection().add (*tracks);
-               }
-       } else {
+       switch (Keyboard::selection_type (ev->state)) {
+       case Selection::Toggle:
+               /* XXX this is not right */
+               editor.get_selection().add (*tracks);
+               break;
+               
+       case Selection::Set:
                editor.get_selection().set (*tracks);
+               break;
+
+       case Selection::Extend:
+               /* not defined yet */
+               break;
        }
 
        delete tracks;
@@ -1038,10 +1055,10 @@ AudioTimeAxisView::get_selectables (jack_nframes_t start, jack_nframes_t end, do
                speed = get_diskstream()->speed();
        }
        
-       jack_nframes_t start_adjusted = (jack_nframes_t) (start * speed);
-       jack_nframes_t end_adjusted = (jack_nframes_t) (end * speed);
-       
-       if (view && touched (top, bot)) {
+       jack_nframes_t start_adjusted = session_frame_to_track_frame(start, speed);
+       jack_nframes_t end_adjusted   = session_frame_to_track_frame(end, speed);
+
+       if (view && ((top < 0.0 && bot < 0.0)) || touched (top, bot)) {
                view->get_selectables (start_adjusted, end_adjusted, results);
        }
 
@@ -1085,7 +1102,7 @@ AudioTimeAxisView::name() const
 Playlist *
 AudioTimeAxisView::playlist () const 
 {
-       DiskStream *ds;
+       Diskstream *ds;
 
        if ((ds = get_diskstream()) != 0) {
                return ds->playlist(); 
@@ -1094,59 +1111,11 @@ AudioTimeAxisView::playlist () const
        }
 }
 
-gint 
-AudioTimeAxisView::name_entry_button_press_handler (GdkEventButton *ev)
-{
-       if (ev->button == 3) {
-               return stop_signal (name_entry, "button_press_event");
-       }
-       return FALSE;
-}
-
-gint 
-AudioTimeAxisView::name_entry_button_release_handler (GdkEventButton *ev)
-{
-       return FALSE;
-}
-
-gint
-AudioTimeAxisView::name_entry_focus_out_handler (GdkEventFocus* ev)
-{
-       name_entry_changed ();
-       return TRUE;
-}
-
-gint
-AudioTimeAxisView::name_entry_key_release_handler (GdkEventKey* ev)
-{
-       switch (ev->keyval) {
-       case GDK_Tab:
-       case GDK_Up:
-       case GDK_Down:
-               name_entry_changed ();
-               return TRUE;
-
-       default:
-               return FALSE;
-       }
-}
-
-void
-AudioTimeAxisView::name_entry_activated ()
-{
-       /* this should drop focus from the entry,
-          and cause a call to name_entry_changed()
-       */
-       controls_ebox.grab_focus();
-}
-
 void
 AudioTimeAxisView::name_entry_changed ()
 {
        string x;
 
-       ARDOUR_UI::generic_focus_out_event (0);
-
        x = name_entry.get_text ();
        
        if (x == _route.name()) {
@@ -1177,14 +1146,20 @@ AudioTimeAxisView::visual_click ()
 void
 AudioTimeAxisView::hide_click ()
 {
-       editor.unselect_strip_in_display (*this);
+       editor.hide_track_in_display (*this);
+}
+
+ARDOUR::AudioDiskstream*
+AudioTimeAxisView::get_diskstream() const
+{
+       return dynamic_cast<ARDOUR::AudioDiskstream*>(RouteUI::get_diskstream());
 }
 
 Region*
 AudioTimeAxisView::find_next_region (jack_nframes_t pos, RegionPoint point, int32_t dir)
 {
-       DiskStream *stream;
-       AudioPlaylist *playlist;
+       Diskstream *stream;
+       Playlist *playlist;
 
        if ((stream = get_diskstream()) != 0 && (playlist = stream->playlist()) != 0) {
                return playlist->find_next_region (pos, point, dir);
@@ -1199,15 +1174,20 @@ AudioTimeAxisView::add_gain_automation_child ()
        XMLProperty* prop;
        AutomationLine* line;
 
-       gain_track = new GainAutomationTimeAxisView (_session, _route, editor, *this, parent_canvas, _("gain"),
+       gain_track = new GainAutomationTimeAxisView (_session,
+                                                    _route,
+                                                    editor,
+                                                    *this,
+                                                    parent_canvas,
+                                                    _("gain"),
                                                     _route.gain_automation_curve());
        
-       
-       line = new AutomationGainLine ("automation gain", _session, *gain_track,
-                                      gain_track->canvas_display,
-                                      _route.gain_automation_curve(),
-                                      slot (mem_fun (ed, &PublicEditor::canvas_control_point_event)),
-                                      slot (mem_fun (ed, &PublicEditor::canvas_line_event)));
+       line = new AutomationGainLine ("automation gain",
+                                      _session,
+                                      *gain_track,
+                                      *gain_track->canvas_display,
+                                      _route.gain_automation_curve());
+
        line->set_line_color (color_map[cAutomationLine]);
        
 
@@ -1284,10 +1264,8 @@ AudioTimeAxisView::update_pans ()
                AutomationLine* line;
 
                line = new AutomationPanLine ("automation pan", _session, *pan_track,
-                                             pan_track->canvas_display, 
-                                             (*p)->automation(),
-                                             PublicEditor::canvas_control_point_event,
-                                             PublicEditor::canvas_line_event);
+                                             *pan_track->canvas_display, 
+                                             (*p)->automation());
 
                if (p == _route.panner().begin()) {
                        /* first line is a nice orange */
@@ -1310,7 +1288,7 @@ AudioTimeAxisView::toggle_gain_track ()
        if (showit != gain_track->marked_for_display()) {
                if (showit) {
                        gain_track->set_marked_for_display (true);
-                       gnome_canvas_item_show (gain_track->canvas_display);
+                       gain_track->canvas_display->show();
                        gain_track->get_state_node()->add_property ("shown", X_("yes"));
                } else {
                        gain_track->set_marked_for_display (false);
@@ -1346,7 +1324,7 @@ AudioTimeAxisView::toggle_pan_track ()
        if (showit != pan_track->marked_for_display()) {
                if (showit) {
                        pan_track->set_marked_for_display (true);
-                       gnome_canvas_item_show (pan_track->canvas_display);
+                       pan_track->canvas_display->show();
                        pan_track->get_state_node()->add_property ("shown", X_("yes"));
                } else {
                        pan_track->set_marked_for_display (false);
@@ -1467,9 +1445,7 @@ AudioTimeAxisView::add_redirect_automation_curve (Redirect *redirect, uint32_t w
 
        ral = new RedirectAutomationLine (name, 
                                          *redirect, what, _session, *ran->view,
-                                         ran->view->canvas_display, redirect->automation_list (what), 
-                                         PublicEditor::canvas_control_point_event,
-                                         PublicEditor::canvas_line_event);
+                                         *ran->view->canvas_display, redirect->automation_list (what));
        
        ral->set_line_color (color_map[cRedirectAutomationLine]);
        ral->queue_reset ();
@@ -1621,7 +1597,7 @@ AudioTimeAxisView::redirect_menu_item_toggled (AudioTimeAxisView::RedirectAutoma
 
                if (showit) {
                        ran->view->set_marked_for_display (true);
-                       gnome_canvas_item_show (ran->view->canvas_display);
+                       ran->view->canvas_display->show();
                } else {
                        rai->redirect->mark_automation_visible (ran->what, true);
                        ran->view->set_marked_for_display (false);
@@ -1757,7 +1733,7 @@ bool
 AudioTimeAxisView::cut_copy_clear (Selection& selection, CutCopyOp op)
 {
        Playlist* what_we_got;
-       DiskStream* ds = get_diskstream();
+       AudioDiskstream* ds = dynamic_cast<AudioDiskstream*>(get_diskstream());
        Playlist* playlist;
        bool ret = false;
 
@@ -1773,8 +1749,8 @@ AudioTimeAxisView::cut_copy_clear (Selection& selection, CutCopyOp op)
        float speed = ds->speed();
        if (speed != 1.0f) {
                for (TimeSelection::iterator i = time.begin(); i != time.end(); ++i) {
-                       (*i).start = (jack_nframes_t)floor( (float) (*i).start * speed);
-                       (*i).end   = (jack_nframes_t)floor( (float) (*i).end   * speed);
+                       (*i).start = session_frame_to_track_frame((*i).start, speed);
+                       (*i).end   = session_frame_to_track_frame((*i).end,   speed);
                }
        }
        
@@ -1823,7 +1799,7 @@ AudioTimeAxisView::paste (jack_nframes_t pos, float times, Selection& selection,
        }
 
        if (get_diskstream()->speed() != 1.0f)
-               pos = (jack_nframes_t) floor( (float) pos * get_diskstream()->speed() );
+               pos = session_frame_to_track_frame(pos, get_diskstream()->speed() );
        
        _session.add_undo (playlist->get_memento());
        playlist->paste (**p, pos, times);
@@ -1890,10 +1866,10 @@ AudioTimeAxisView::build_playlist_menu (Gtk::Menu * menu)
        playlist_items.push_back (MenuElem (_("Rename"), mem_fun(*this, &AudioTimeAxisView::rename_current_playlist)));
        playlist_items.push_back (SeparatorElem());
 
-       playlist_items.push_back (MenuElem (_("New"), mem_fun(*this, &AudioTimeAxisView::use_new_playlist)));
-       playlist_items.push_back (MenuElem (_("New Copy"), mem_fun(*this, &AudioTimeAxisView::use_copy_playlist)));
+       playlist_items.push_back (MenuElem (_("New"), mem_fun(editor, &PublicEditor::new_playlists)));
+       playlist_items.push_back (MenuElem (_("New Copy"), mem_fun(editor, &PublicEditor::copy_playlists)));
        playlist_items.push_back (SeparatorElem());
-       playlist_items.push_back (MenuElem (_("Clear Current"), mem_fun(*this, &AudioTimeAxisView::clear_playlist)));
+       playlist_items.push_back (MenuElem (_("Clear Current"), mem_fun(editor, &PublicEditor::clear_playlists)));
        playlist_items.push_back (SeparatorElem());
        playlist_items.push_back (MenuElem(_("Select"), mem_fun(*this, &AudioTimeAxisView::show_playlist_selector)));
 
@@ -1915,7 +1891,6 @@ AudioTimeAxisView::map_frozen ()
 
        ENSURE_GUI_THREAD (mem_fun(*this, &AudioTimeAxisView::map_frozen));
 
-
        switch (audio_track()->freeze_state()) {
        case AudioTrack::Frozen:
                playlist_button.set_sensitive (false);
@@ -1993,7 +1968,29 @@ AudioTimeAxisView::route_active_changed ()
 }
 
 XMLNode* 
-AudioTimeAxisView::get_child_xml_node (std::string childname)
+AudioTimeAxisView::get_child_xml_node (const string & childname)
 {
        return RouteUI::get_child_xml_node (childname);
 }
+
+void
+AudioTimeAxisView::color_handler (ColorID id, uint32_t val)
+{
+       switch (id) {
+       case cTimeStretchOutline:
+               timestretch_rect->property_outline_color_rgba() = val;
+               break;
+       case cTimeStretchFill:
+               timestretch_rect->property_fill_color_rgba() = val;
+               break;
+       default:
+               break;
+       }
+}
+
+bool
+AudioTimeAxisView::select_me (GdkEventButton* ev)
+{
+       editor.get_selection().add (this);
+       return false;
+}