added RCU handling of Session route list, and major use of shared_ptr<T> everywhere...
[ardour.git] / gtk2_ardour / mixer_ui.cc
index 98e9a6c41c4f31985cc775dd3fa037c42efbc4ca..c2eb588b2f2744865d085574155f36aff585e3cf 100644 (file)
@@ -23,7 +23,9 @@
 
 #include <gtkmm/accelmap.h>
 
-#include <pbd/lockmonitor.h>
+#include <pbd/convert.h>
+#include <glibmm/thread.h>
+
 #include <gtkmm2ext/gtk_ui.h>
 #include <gtkmm2ext/utils.h>
 #include <gtkmm2ext/stop_signal.h>
@@ -32,7 +34,7 @@
 #include <ardour/session.h>
 #include <ardour/audio_track.h>
 #include <ardour/session_route.h>
-#include <ardour/diskstream.h>
+#include <ardour/audio_diskstream.h>
 #include <ardour/plugin_manager.h>
 
 #include "mixer_ui.h"
 #include "i18n.h"
 
 using namespace ARDOUR;
+using namespace PBD;
 using namespace Gtk;
 using namespace Glib;
 using namespace Gtkmm2ext;
 using namespace sigc;
 using namespace std;
 
+using PBD::atoi;
+
 Mixer_UI::Mixer_UI (AudioEngine& eng)
        : Window (Gtk::WINDOW_TOPLEVEL),
          engine (eng)
@@ -81,10 +86,11 @@ Mixer_UI::Mixer_UI (AudioEngine& eng)
        track_display.append_column (_("Visible"), track_columns.visible);
        track_display.get_column (0)->set_data (X_("colnum"), GUINT_TO_POINTER(0));
        track_display.get_column (1)->set_data (X_("colnum"), GUINT_TO_POINTER(1));
+       track_display.get_column (0)->set_expand(true);
+       track_display.get_column (1)->set_expand(false);
        track_display.set_name (X_("MixerTrackDisplayList"));
        track_display.get_selection()->set_mode (Gtk::SELECTION_NONE);
        track_display.set_reorderable (true);
-       track_display.set_size_request (100, -1);
        track_display.set_headers_visible (true);
 
        track_model->signal_row_deleted().connect (mem_fun (*this, &Mixer_UI::track_list_delete));
@@ -101,18 +107,19 @@ Mixer_UI::Mixer_UI (AudioEngine& eng)
 
        group_model = ListStore::create (group_columns);
        group_display.set_model (group_model);
-       group_display.append_column (_("groupname"), group_columns.text);
-       group_display.append_column (_("active"), group_columns.active);
-       group_display.append_column (_("visible"), group_columns.visible);
+       group_display.append_column (_("Group"), group_columns.text);
+       group_display.append_column (_("Active"), group_columns.active);
+       group_display.append_column (_("Visible"), group_columns.visible);
        group_display.get_column (0)->set_data (X_("colnum"), GUINT_TO_POINTER(0));
        group_display.get_column (1)->set_data (X_("colnum"), GUINT_TO_POINTER(1));
        group_display.get_column (2)->set_data (X_("colnum"), GUINT_TO_POINTER(2));
+       group_display.get_column (0)->set_expand(true);
+       group_display.get_column (1)->set_expand(false);
+       group_display.get_column (2)->set_expand(false);
        group_display.set_name ("MixerGroupList");
        group_display.get_selection()->set_mode (Gtk::SELECTION_SINGLE);
        group_display.set_reorderable (true);
-       group_display.set_size_request (150, -1);
        group_display.set_headers_visible (true);
-               group_display.set_headers_clickable (false);
        group_display.set_rules_hint (true);
 
        /* name is directly editable */
@@ -140,16 +147,28 @@ Mixer_UI::Mixer_UI (AudioEngine& eng)
        group_display_scroller.add (group_display);
        group_display_scroller.set_policy (Gtk::POLICY_NEVER, Gtk::POLICY_AUTOMATIC);
 
-       HButtonBox* mix_group_display_button_box = manage (new HButtonBox());
+       HBox* mix_group_display_button_box = manage (new HBox());
+
+       Button* mix_group_add_button = manage (new Button ());
+       Button* mix_group_remove_button = manage (new Button ());
+
+       Widget* w;
+
+       w = manage (new Image (Stock::ADD, ICON_SIZE_BUTTON));
+       w->show();
+       mix_group_add_button->add (*w);
+
+       w = manage (new Image (Stock::REMOVE, ICON_SIZE_BUTTON));
+       w->show();
+       mix_group_remove_button->add (*w);
+
        mix_group_display_button_box->set_homogeneous (true);
-       Button* mix_group_add_button = manage (new Button (Stock::ADD));
-       Button* mix_group_remove_button = manage (new Button (Stock::REMOVE));
 
        mix_group_add_button->signal_clicked().connect (mem_fun (*this, &Mixer_UI::new_mix_group));
        mix_group_remove_button->signal_clicked().connect (mem_fun (*this, &Mixer_UI::remove_selected_mix_group));
 
-       mix_group_display_button_box->pack_start (*mix_group_add_button);
-       mix_group_display_button_box->pack_start (*mix_group_remove_button);
+       mix_group_display_button_box->add (*mix_group_remove_button);
+       mix_group_display_button_box->add (*mix_group_add_button);
 
        group_display_vbox.pack_start (group_display_scroller, true, true);
        group_display_vbox.pack_start (*mix_group_display_button_box, false, false);
@@ -162,8 +181,8 @@ Mixer_UI::Mixer_UI (AudioEngine& eng)
        group_display_frame.set_shadow_type (Gtk::SHADOW_IN);
        group_display_frame.add (group_display_vbox);
 
-       rhs_pane1.add1 (track_display_frame);
-       rhs_pane1.add2 (group_display_frame);
+       rhs_pane1.pack1 (track_display_frame);
+       rhs_pane1.pack2 (group_display_frame);
 
        list_vpacker.pack_start (rhs_pane1, true, true);
 
@@ -232,7 +251,7 @@ Mixer_UI::show_window ()
 }
 
 void
-Mixer_UI::add_strip (Route* route)
+Mixer_UI::add_strip (boost::shared_ptr<Route> route)
 {
        ENSURE_GUI_THREAD(bind (mem_fun(*this, &Mixer_UI::add_strip), route));
        
@@ -242,7 +261,7 @@ Mixer_UI::add_strip (Route* route)
                return;
        }
 
-       strip = new MixerStrip (*this, *session, *route);
+       strip = new MixerStrip (*this, *session, route);
        strips.push_back (strip);
 
        strip->set_width (_strip_width);
@@ -291,7 +310,7 @@ void
 Mixer_UI::follow_strip_selection ()
 {
        for (list<MixerStrip *>::iterator i = strips.begin(); i != strips.end(); ++i) {
-               (*i)->set_selected (_selection.selected (&(*i)->route()));
+               (*i)->set_selected (_selection.selected ((*i)->route()));
        }
 }
 
@@ -305,13 +324,13 @@ Mixer_UI::strip_button_release_event (GdkEventButton *ev, MixerStrip *strip)
                   at the same time.
                */
                
-               if (_selection.selected (&strip->route())) {
-                       _selection.remove (&strip->route());
+               if (_selection.selected (strip->route())) {
+                       _selection.remove (strip->route());
                } else {
                        if (Keyboard::modifier_state_equals (ev->state, Keyboard::Shift)) {
-                               _selection.add (&strip->route());
+                               _selection.add (strip->route());
                        } else {
-                               _selection.set (&strip->route());
+                               _selection.set (strip->route());
                        }
                }
        }
@@ -387,7 +406,6 @@ Mixer_UI::hide_strip (MixerStrip* ms)
  gint
  Mixer_UI::start_updating ()
  {
-        screen_update_connection = ARDOUR_UI::instance()->RapidScreenUpdate.connect (mem_fun(*this, &Mixer_UI::update_strips));
         fast_screen_update_connection = ARDOUR_UI::instance()->SuperRapidScreenUpdate.connect (mem_fun(*this, &Mixer_UI::fast_update_strips));
         return 0;
  }
@@ -395,21 +413,10 @@ Mixer_UI::hide_strip (MixerStrip* ms)
  gint
  Mixer_UI::stop_updating ()
  {
-        screen_update_connection.disconnect();
         fast_screen_update_connection.disconnect();
         return 0;
  }
 
- void
- Mixer_UI::update_strips ()
- {
-        if (is_mapped () && session) {
-                for (list<MixerStrip *>::iterator i = strips.begin(); i != strips.end(); ++i) {
-                        (*i)->update ();
-                }
-        }
- }
-
  void
  Mixer_UI::fast_update_strips ()
  {
@@ -437,7 +444,7 @@ Mixer_UI::set_all_strips_visibility (bool yn)
                        continue;
                }
                
-               if (strip->route().master() || strip->route().control()) {
+               if (strip->route()->master() || strip->route()->control()) {
                        continue;
                }
 
@@ -465,11 +472,11 @@ Mixer_UI::set_all_audio_visibility (int tracks, bool yn)
                        continue;
                }
 
-               if (strip->route().master() || strip->route().control()) {
+               if (strip->route()->master() || strip->route()->control()) {
                        continue;
                }
 
-               AudioTrack* at = dynamic_cast<AudioTrack*> (&strip->route());
+               AudioTrack* at = strip->audio_track();
 
                switch (tracks) {
                case 0:
@@ -563,11 +570,11 @@ Mixer_UI::redisplay_track_list ()
 
                if (visible) {
                        strip->set_marked_for_display (true);
-                       strip->route().set_order_key (N_("signal"), order);
+                       strip->route()->set_order_key (N_("signal"), order);
 
                        if (strip->packed()) {
 
-                               if (strip->route().master() || strip->route().control()) {
+                               if (strip->route()->master() || strip->route()->control()) {
                                        out_packer.reorder_child (*strip, -1);
                                } else {
                                        strip_packer.reorder_child (*strip, -1); /* put at end */
@@ -575,7 +582,7 @@ Mixer_UI::redisplay_track_list ()
 
                        } else {
 
-                               if (strip->route().master() || strip->route().control()) {
+                               if (strip->route()->master() || strip->route()->control()) {
                                        out_packer.pack_start (*strip, false, false);
                                } else {
                                        strip_packer.pack_start (*strip, false, false);
@@ -586,7 +593,7 @@ Mixer_UI::redisplay_track_list ()
 
                } else {
 
-                       if (strip->route().master() || strip->route().control()) {
+                       if (strip->route()->master() || strip->route()->control()) {
                                /* do nothing, these cannot be hidden */
                        } else {
                                strip_packer.remove (*strip);
@@ -597,7 +604,7 @@ Mixer_UI::redisplay_track_list ()
 }
 
 struct SignalOrderRouteSorter {
-    bool operator() (Route* a, Route* b) {
+    bool operator() (boost::shared_ptr<Route> a, boost::shared_ptr<Route> b) {
            /* use of ">" forces the correct sort order */
            return a->order_key ("signal") < b->order_key ("signal");
     }
@@ -606,16 +613,17 @@ struct SignalOrderRouteSorter {
 void
 Mixer_UI::initial_track_display ()
 {
-       Session::RouteList routes = session->get_routes();
+       boost::shared_ptr<Session::RouteList> routes = session->get_routes();
+       Session::RouteList copy (*routes);
        SignalOrderRouteSorter sorter;
 
-       routes.sort (sorter);
+       copy.sort (sorter);
        
        no_track_list_redisplay = true;
 
        track_model->clear ();
 
-       for (Session::RouteList::iterator i = routes.begin(); i != routes.end(); ++i) {
+       for (Session::RouteList::iterator i = copy.begin(); i != copy.end(); ++i) {
                add_strip (*i);
        }
 
@@ -663,7 +671,7 @@ Mixer_UI::track_display_button_press (GdkEventButton* ev)
                        MixerStrip* strip = (*iter)[track_columns.strip];
                        if (strip) {
 
-                               if (!strip->route().master() && !strip->route().control()) {
+                               if (!strip->route()->master() && !strip->route()->control()) {
                                        bool visible = (*iter)[track_columns.visible];
                                        (*iter)[track_columns.visible] = !visible;
                                }
@@ -708,7 +716,7 @@ Mixer_UI::strip_name_changed (void* src, MixerStrip* mx)
        
        for (i = rows.begin(); i != rows.end(); ++i) {
                if ((*i)[track_columns.strip] == mx) {
-                       (*i)[track_columns.text] = mx->route().name();
+                       (*i)[track_columns.text] = mx->route()->name();
                        return;
                }
        } 
@@ -817,7 +825,6 @@ Mixer_UI::mix_groups_changed ()
 
        /* just rebuild the while thing */
 
-       group_display.set_model (Glib::RefPtr<TreeModel>(0));
        group_model->clear ();
 
        {
@@ -830,32 +837,12 @@ Mixer_UI::mix_groups_changed ()
        }
 
        session->foreach_mix_group (mem_fun (*this, &Mixer_UI::add_mix_group));
-       group_display.set_model (group_model);
 }
 
-
 void
 Mixer_UI::new_mix_group ()
 {
-#if 0
-       ArdourPrompter prompter;
-       string result;
-
-       prompter.set_prompt (_("Name for new mix group"));
-       prompter.show_all ();
-       
-       switch (prompter.run ()) {
-       case Gtk::RESPONSE_ACCEPT:
-               prompter.get_result (result);
-               if (result.length()) {
-                       session->add_mix_group (result);
-               }       
-               break;
-       }
-#else 
-       session->add_mix_group ("unnamed");
-#endif
-
+       session->add_mix_group ("");
 }
 
 void
@@ -970,14 +957,30 @@ Mixer_UI::add_mix_group (RouteGroup* group)
 
 {
        ENSURE_GUI_THREAD(bind (mem_fun(*this, &Mixer_UI::add_mix_group), group));
+       bool focus = false;
+
+       in_group_row_change = true;
 
        TreeModel::Row row = *(group_model->append());
        row[group_columns.active] = group->is_active();
        row[group_columns.visible] = true;
-       row[group_columns.text] = group->name();
        row[group_columns.group] = group;
+       if (!group->name().empty()) {
+               row[group_columns.text] = group->name();
+       } else {
+               row[group_columns.text] = _("unnamed");
+               focus = true;
+       }
 
        group->FlagsChanged.connect (bind (mem_fun(*this, &Mixer_UI::group_flags_changed), group));
+       
+       if (focus) {
+               TreeViewColumn* col = group_display.get_column (0);
+               CellRendererText* name_cell = dynamic_cast<CellRendererText*>(group_display.get_column_cell_renderer (0));
+               group_display.set_cursor (group_model->get_path (row), *col, *name_cell, true);
+       }
+
+       in_group_row_change = false;
 }
 
 bool