r199@gandalf: fugalh | 2006-07-26 17:22:38 -0600
[ardour.git] / gtk2_ardour / audio_time_axis.cc
index 4ec1e3da2a0392aae091b0d9b0a1264f5adad118..ebc97be77b9ae9125180ba646d45f4d7d5fac228 100644 (file)
@@ -38,7 +38,7 @@
 #include <gtkmm2ext/utils.h>
 
 #include <ardour/audioplaylist.h>
-#include <ardour/diskstream.h>
+#include <ardour/audio_diskstream.h>
 #include <ardour/insert.h>
 #include <ardour/ladspa_plugin.h>
 #include <ardour/location.h>
 #include "i18n.h"
 
 using namespace ARDOUR;
+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, Canvas& canvas)
        : AxisView(sess),
@@ -148,18 +134,21 @@ 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));
+       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);
+       rec_enable_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);
        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), false);
        playlist_button.signal_clicked().connect (mem_fun(*this, &AudioTimeAxisView::playlist_click));
@@ -193,9 +182,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()) {
+       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 */
@@ -225,8 +213,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()) {
 
@@ -338,29 +327,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 ();
        }
@@ -587,7 +579,7 @@ AudioTimeAxisView::set_state (const XMLNode& node)
 void
 AudioTimeAxisView::set_height (TrackHeight h)
 {
-       bool height_changed = (h != height_style);
+       bool height_changed = (height == 0) || (h != height_style);
 
        TimeAxisView::set_height (h);
 
@@ -716,28 +708,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);
@@ -774,12 +768,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();
@@ -830,19 +824,16 @@ AudioTimeAxisView::rename_current_playlist ()
        string name;
 
        AudioPlaylist *pl;
-       DiskStream *ds;
-
-       /* neither conditions are supposed to be true at this
-          time, but to leave the design flexible, allow
-          them to be in the future without causing crashes
-       */
+       AudioDiskstream *ds;
 
-       if (((ds = get_diskstream()) == 0) ||((pl = ds->playlist()) == 0)) {
+       if (((ds = get_diskstream()) == 0) || ds->destructive() || ((pl = 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:
@@ -861,15 +852,10 @@ void
 AudioTimeAxisView::use_copy_playlist (bool prompt)
 {
        AudioPlaylist *pl;
-       DiskStream *ds;
+       AudioDiskstream *ds;
        string name;
 
-       /* neither conditions are supposed to be true at this
-          time, but to leave the design flexible, allow
-          them to be in the future without causing crashes
-       */
-
-       if (((ds = get_diskstream()) == 0) || ((pl = ds->playlist()) == 0)) {
+       if (((ds = get_diskstream()) == 0) || ds->destructive() || ((pl = ds->playlist()) == 0)) {
                return;
        }
        
@@ -879,8 +865,10 @@ AudioTimeAxisView::use_copy_playlist (bool prompt)
 
                ArdourPrompter prompter (true);
                
-               prompter.set_prompt (_("Name for playlist"));
+               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 ()) {
@@ -904,15 +892,10 @@ void
 AudioTimeAxisView::use_new_playlist (bool prompt)
 {
        AudioPlaylist *pl;
-       DiskStream *ds;
+       AudioDiskstream *ds;
        string name;
-       
-       /* neither conditions are supposed to be true at this
-          time, but to leave the design flexible, allow
-          them to be in the future without causing crashes
-       */
-       
-       if (((ds = get_diskstream()) == 0) || ((pl = ds->playlist()) == 0)) {
+
+       if (((ds = get_diskstream()) == 0) || ds->destructive() || ((pl = ds->playlist()) == 0)) {
                return;
        }
        
@@ -922,8 +905,10 @@ AudioTimeAxisView::use_new_playlist (bool prompt)
                
                ArdourPrompter prompter (true);
                
-               prompter.set_prompt (_("Name for playlist"));
+               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:
@@ -946,7 +931,7 @@ void
 AudioTimeAxisView::clear_playlist ()
 {
        AudioPlaylist *pl;
-       DiskStream *ds;
+       AudioDiskstream *ds;
        
        if ((ds = get_diskstream()) != 0) {
                if ((pl = ds->playlist()) != 0) {
@@ -1004,7 +989,7 @@ AudioTimeAxisView::diskstream_changed (void *src)
 void
 AudioTimeAxisView::update_diskstream_display ()
 {
-       DiskStream *ds;
+       AudioDiskstream *ds;
 
        if ((ds = get_diskstream()) != 0) {
                set_playlist (ds->playlist ());
@@ -1064,7 +1049,7 @@ AudioTimeAxisView::get_selectables (jack_nframes_t start, jack_nframes_t end, do
        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 && touched (top, bot)) {
+       if (view && ((top < 0.0 && bot < 0.0)) || touched (top, bot)) {
                view->get_selectables (start_adjusted, end_adjusted, results);
        }
 
@@ -1108,7 +1093,7 @@ AudioTimeAxisView::name() const
 Playlist *
 AudioTimeAxisView::playlist () const 
 {
-       DiskStream *ds;
+       AudioDiskstream *ds;
 
        if ((ds = get_diskstream()) != 0) {
                return ds->playlist(); 
@@ -1158,7 +1143,7 @@ AudioTimeAxisView::hide_click ()
 Region*
 AudioTimeAxisView::find_next_region (jack_nframes_t pos, RegionPoint point, int32_t dir)
 {
-       DiskStream *stream;
+       AudioDiskstream *stream;
        AudioPlaylist *playlist;
 
        if ((stream = get_diskstream()) != 0 && (playlist = stream->playlist()) != 0) {
@@ -1733,7 +1718,7 @@ bool
 AudioTimeAxisView::cut_copy_clear (Selection& selection, CutCopyOp op)
 {
        Playlist* what_we_got;
-       DiskStream* ds = get_diskstream();
+       AudioDiskstream* ds = get_diskstream();
        Playlist* playlist;
        bool ret = false;
 
@@ -1754,12 +1739,14 @@ AudioTimeAxisView::cut_copy_clear (Selection& selection, CutCopyOp op)
                }
        }
        
+        XMLNode &before, &after;
        switch (op) {
        case Cut:
-               _session.add_undo (playlist->get_memento());
+                before = playlist->get_state();
                if ((what_we_got = playlist->cut (time)) != 0) {
                        editor.get_cut_buffer().add (what_we_got);
-                       _session.add_redo_no_execute (playlist->get_memento());
+                        after = playlist->get_state();
+                       _session.add_command (MementoCommand<Playlist>(*playlist, before, after));
                        ret = true;
                }
                break;
@@ -1770,9 +1757,9 @@ AudioTimeAxisView::cut_copy_clear (Selection& selection, CutCopyOp op)
                break;
 
        case Clear:
-               _session.add_undo (playlist->get_memento());
+               before = playlist->get_state();
                if ((what_we_got = playlist->cut (time)) != 0) {
-                       _session.add_redo_no_execute (playlist->get_memento());
+                       _session.add_command(MementoCommand<Playlist>(*playlist, before, after));
                        what_we_got->unref ();
                        ret = true;
                }
@@ -1801,9 +1788,10 @@ AudioTimeAxisView::paste (jack_nframes_t pos, float times, Selection& selection,
        if (get_diskstream()->speed() != 1.0f)
                pos = session_frame_to_track_frame(pos, get_diskstream()->speed() );
        
-       _session.add_undo (playlist->get_memento());
+        XMLNode &before = playlist->get_state();
        playlist->paste (**p, pos, times);
-       _session.add_redo_no_execute (playlist->get_memento());
+        _session.add_command(MementoCommand<Playlist>(*playlist, before, 
+                                                      playlist->get_state()));
 
        return true;
 }
@@ -1988,3 +1976,10 @@ AudioTimeAxisView::color_handler (ColorID id, uint32_t val)
                break;
        }
 }
+
+bool
+AudioTimeAxisView::select_me (GdkEventButton* ev)
+{
+       editor.get_selection().add (this);
+       return false;
+}