fix incorrect accumulation of export video options each time the dialog is used
[ardour.git] / gtk2_ardour / transport_masters_dialog.cc
index 92d828fa625224ec82e9189b7362c32ac9643f6b..33d0ce5ca4fa0b4ba7c0e823f494bc7fa1cd29ba 100644 (file)
@@ -52,6 +52,8 @@ TransportMastersWidget::TransportMastersWidget ()
        pack_start (table, PACK_EXPAND_WIDGET, 12);
        pack_start (add_button, FALSE, FALSE);
 
+       add_button.signal_clicked ().connect (sigc::mem_fun (*this, &TransportMastersWidget::add_master));
+
        col_title[0].set_markup (string_compose ("<span weight=\"bold\">%1</span>", _("Use")));
        col_title[1].set_markup (string_compose ("<span weight=\"bold\">%1</span>", _("Name")));
        col_title[2].set_markup (string_compose ("<span weight=\"bold\">%1</span>", _("Type")));
@@ -64,7 +66,7 @@ TransportMastersWidget::TransportMastersWidget ()
        col_title[9].set_markup (string_compose ("<span weight=\"bold\">%1</span>", _("Data Source")));
        col_title[10].set_markup (string_compose ("<span weight=\"bold\">%1</span>", _("Active\nCommands")));
        col_title[11].set_markup (string_compose ("<span weight=\"bold\">%1</span>", _("Clock\nSynced")));
-       col_title[12].set_markup (string_compose ("<span weight=\"bold\">%1</span>", _("29.97/30")));
+       col_title[12].set_markup (string_compose ("<span weight=\"bold\">%1</span>", _("29.97/\n30")));
        col_title[13].set_markup (string_compose ("<span weight=\"bold\">%1</span>", _("Remove")));
 
        set_tooltip (col_title[12], _("<b>When enabled</b> the external timecode source is assumed to use 29.97 fps instead of 30000/1001.\n"
@@ -81,6 +83,8 @@ TransportMastersWidget::TransportMastersWidget ()
        table.set_spacings (6);
 
        TransportMasterManager::instance().CurrentChanged.connect (current_connection, invalidator (*this), boost::bind (&TransportMastersWidget::current_changed, this, _1, _2), gui_context());
+       TransportMasterManager::instance().Added.connect (add_connection, invalidator (*this), boost::bind (&TransportMastersWidget::rebuild, this), gui_context());
+       TransportMasterManager::instance().Removed.connect (remove_connection, invalidator (*this), boost::bind (&TransportMastersWidget::rebuild, this), gui_context());
 
        rebuild ();
 }
@@ -92,6 +96,12 @@ TransportMastersWidget::~TransportMastersWidget ()
        }
 }
 
+void
+TransportMastersWidget::set_transport_master (boost::shared_ptr<TransportMaster> tm)
+{
+       _session->request_sync_source (tm);
+}
+
 void
 TransportMastersWidget::current_changed (boost::shared_ptr<TransportMaster> old_master, boost::shared_ptr<TransportMaster> new_master)
 {
@@ -103,6 +113,35 @@ TransportMastersWidget::current_changed (boost::shared_ptr<TransportMaster> old_
        }
 }
 
+void
+TransportMastersWidget::add_master ()
+{
+       AddTransportMasterDialog d;
+
+       d.present ();
+       string name;
+
+       while (name.empty()) {
+
+               int r = d.run ();
+
+               switch (r) {
+               case RESPONSE_ACCEPT:
+                       name = d.get_name();
+                       break;
+               default:
+                       return;
+               }
+       }
+
+       d.hide ();
+
+       if (TransportMasterManager::instance().add (d.get_type(), name)) {
+               MessageDialog msg (_("New transport master not added - check error log for details"));
+               msg.run ();
+       }
+}
+
 void
 TransportMastersWidget::rebuild ()
 {
@@ -123,9 +162,11 @@ TransportMastersWidget::rebuild ()
 
        uint32_t n = 1;
 
+       Gtk::RadioButtonGroup use_button_group;
+
        for (TransportMasterManager::TransportMasters::const_iterator m = masters.begin(); m != masters.end(); ++m, ++n) {
 
-               Row* r = new Row;
+               Row* r = new Row (*this);
                rows.push_back (r);
 
                r->tm = *m;
@@ -170,7 +211,8 @@ TransportMastersWidget::rebuild ()
                        col++;
                }
 
-               r->label_box.set_events (Gdk::BUTTON_PRESS_MASK|Gdk::BUTTON_RELEASE_MASK);
+               table.show_all ();
+
                r->label_box.signal_button_press_event().connect (sigc::mem_fun (*r, &TransportMastersWidget::Row::name_press));
                r->port_combo.signal_changed().connect (sigc::mem_fun (*r, &TransportMastersWidget::Row::port_choice_changed));
                r->use_button.signal_toggled().connect (sigc::mem_fun (*r, &TransportMastersWidget::Row::use_button_toggled));
@@ -198,8 +240,9 @@ TransportMastersWidget::rebuild ()
        }
 }
 
-TransportMastersWidget::Row::Row ()
-       : request_option_menu (0)
+TransportMastersWidget::Row::Row (TransportMastersWidget& p)
+       : parent (p)
+       , request_option_menu (0)
        , remove_button (X_("x"))
        , name_editor (0)
        , save_when (0)
@@ -223,9 +266,20 @@ TransportMastersWidget::Row::name_press (GdkEventButton* ev)
        return false;
 }
 
+bool
+TransportMastersWidget::idle_remove (TransportMastersWidget::Row* row)
+{
+       TransportMasterManager::instance().remove (row->tm->name());
+       return false;
+}
+
 void
 TransportMastersWidget::Row::remove_clicked ()
 {
+       /* have to do this via an idle callback, because it will destroy the
+          widget from which this callback was initiated.
+       */
+       Glib::signal_idle().connect (sigc::bind (sigc::mem_fun (parent, &TransportMastersWidget::idle_remove), this));
 }
 
 void
@@ -267,7 +321,7 @@ void
 TransportMastersWidget::Row::use_button_toggled ()
 {
        if (use_button.get_active()) {
-               Config->set_sync_source (tm->type());
+               parent.set_transport_master (tm);
        }
 }
 
@@ -448,11 +502,17 @@ TransportMastersWidget::Row::update (Session* s, samplepos_t now)
                                last.set_text ("");
                        }
                        current.set_text (Timecode::timecode_format_time (t));
-                       timestamp.set_markup (tm->position_string());
                        delta.set_markup (tm->delta_string ());
 
                        char gap[32];
-                       snprintf (gap, sizeof (gap), "%.3fs", (when - now) / (float) AudioEngine::instance()->sample_rate());
+                       const float seconds = (when - now) / (float) AudioEngine::instance()->sample_rate();
+                       if (abs (seconds) < 1.0) {
+                               snprintf (gap, sizeof (gap), "%.3fs", seconds);
+                       } else if (abs (seconds) < 4.0) {
+                               snprintf (gap, sizeof (gap), "%ds", (int) floor (seconds));
+                       } else {
+                               snprintf (gap, sizeof (gap), "%s", _(">4s ago"));
+                       }
                        timestamp.set_text (gap);
                        save_when = when;
 
@@ -461,16 +521,25 @@ TransportMastersWidget::Row::update (Session* s, samplepos_t now)
                        if (save_when) {
                                char gap[32];
 
-                               snprintf (gap, sizeof (gap), "%.3fs", (save_when - now) / (float) AudioEngine::instance()->sample_rate());
+                               const float seconds = (when - now) / (float) AudioEngine::instance()->sample_rate();
+                               if (abs (seconds) < 1.0) {
+                                       snprintf (gap, sizeof (gap), "%.3fs", seconds);
+                               } else if (abs (seconds) < 4.0) {
+                                       snprintf (gap, sizeof (gap), "%ds", (int) floor (seconds));
+                               } else {
+                                       snprintf (gap, sizeof (gap), "%s", _(">4s ago"));
+                               }
                                timestamp.set_text (gap);
                                save_when = when;
                        }
+                       delta.set_text ("");
+                       current.set_text ("");
                }
        }
 }
 
 void
-       TransportMastersWidget::update (samplepos_t /* audible */)
+TransportMastersWidget::update (samplepos_t /* audible */)
 {
        samplepos_t now = AudioEngine::instance()->sample_time ();
 
@@ -516,3 +585,61 @@ TransportMastersWindow::set_session (ARDOUR::Session* s)
        ArdourWindow::set_session (s);
        w.set_session (s);
 }
+
+TransportMastersWidget::AddTransportMasterDialog::AddTransportMasterDialog ()
+       : ArdourDialog (_("Add Transport Master"), true, false)
+       , name_label (_("Name"))
+       , type_label (_("Type"))
+{
+       name_hbox.set_spacing (6);
+       name_hbox.pack_start (name_label, false, false);
+       name_hbox.pack_start (name_entry, true, true);
+
+       type_hbox.set_spacing (6);
+       type_hbox.pack_start (type_label, false, false);
+       type_hbox.pack_start (type_combo, true, true);
+
+       vector<string> s;
+
+       s.push_back (X_("MTC"));
+       s.push_back (X_("LTC"));
+       s.push_back (X_("MIDI Clock"));
+
+       set_popdown_strings (type_combo, s);
+       type_combo.set_active_text (X_("LTC"));
+
+       get_vbox()->pack_start (name_hbox, false, false);
+       get_vbox()->pack_start (type_hbox, false, false);
+
+       add_button (_("Cancel"), RESPONSE_CANCEL);
+       add_button (_("Add"), RESPONSE_ACCEPT);
+
+       name_entry.show ();
+       type_combo.show ();
+       name_label.show ();
+       type_label.show ();
+       name_hbox.show ();
+       type_hbox.show ();
+
+       name_entry.signal_activate().connect (sigc::bind (sigc::mem_fun (*this, &Gtk::Dialog::response), Gtk::RESPONSE_ACCEPT));
+}
+
+string
+TransportMastersWidget::AddTransportMasterDialog::get_name () const
+{
+       return name_entry.get_text ();
+}
+
+SyncSource
+TransportMastersWidget::AddTransportMasterDialog::get_type() const
+{
+       string t = type_combo.get_active_text ();
+
+       if (t == X_("MTC")) {
+               return MTC;
+       } else if (t == X_("MIDI Clock")) {
+               return MIDIClock;
+       }
+
+       return LTC;
+}