GUI options to select FLAC as media format
[ardour.git] / gtk2_ardour / luadialog.cc
index 62a1e4d682e5ce466cf6eba1b4159bf386b1cf24..5932b234df99e0ce46ff4abe5de5f98b099fd95a 100644 (file)
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
  */
 
+#include <algorithm>
+
 #include <gtkmm.h>
 
 #include "ardour/dB.h"
 #include "ardour/rc_configuration.h"
 
-#include "gtkmm2ext/slider_controller.h"
 #include "gtkmm2ext/utils.h"
 
+#include "widgets/ardour_dropdown.h"
+#include "widgets/slider_controller.h"
+
+#include "stripable_colorpicker.h"
 #include "ardour_dialog.h"
-#include "ardour_dropdown.h"
 #include "luadialog.h"
+#include "splash.h"
 #include "utils.h"
 
 using namespace LuaDialog;
@@ -43,8 +48,24 @@ Message::Message (std::string const& title, std::string const& msg, Message::Mes
 int
 Message::run ()
 {
+
+       bool splash_pushed = false;
+       Splash* spl = Splash::instance();
+       if (spl && spl->is_visible()) {
+               spl->pop_back_for (_message_dialog);
+               splash_pushed = true;
+       }
+
        int rv = _message_dialog.run ();
        _message_dialog.hide ();
+
+       if (splash_pushed) {
+               spl = Splash::instance();
+               if (spl) {
+                       spl->pop_front();
+               }
+       }
+
        switch (rv) {
                case Gtk::RESPONSE_OK:
                        return 0;
@@ -103,13 +124,80 @@ Message::to_gtk_mt (MessageType mt)
  * Lua Dialog Widgets
  */
 
+class LuaDialogLabel : public LuaDialogWidget
+{
+public:
+       LuaDialogLabel (std::string const& title, Gtk::AlignmentEnum xalign)
+               : LuaDialogWidget ("", "", 0, 2)
+               , _lbl (title, xalign, Gtk::ALIGN_CENTER, false)
+       { }
+
+       Gtk::Widget* widget ()
+       {
+               return &_lbl;
+       }
+
+       void assign (luabridge::LuaRef* rv) const { }
+protected:
+       Gtk::Label _lbl;
+};
+
+
+class LuaDialogHeading : public LuaDialogLabel
+{
+public:
+       LuaDialogHeading (std::string const& title, Gtk::AlignmentEnum xalign)
+       : LuaDialogLabel ("<b>" + title + "</b>", xalign)
+       {
+               _lbl.set_use_markup ();
+       }
+};
+
+class LuaHSeparator : public LuaDialogWidget
+{
+public:
+       LuaHSeparator ()
+               : LuaDialogWidget ("", "", 0, 2)
+       {}
+
+       Gtk::Widget* widget ()
+       {
+               return &_sep;
+       }
+
+       void assign (luabridge::LuaRef* rv) const { }
+protected:
+       Gtk::HSeparator _sep;
+};
+
+class LuaColorPicker : public LuaDialogWidget
+{
+public:
+       LuaColorPicker (std::string const& key)
+               : LuaDialogWidget (key, "", 0, 1)
+       {}
+
+       Gtk::Widget* widget ()
+       {
+               return &_cs;
+       }
+       void assign (luabridge::LuaRef* rv) const {
+               uint32_t rgba = ARDOUR_UI_UTILS::gdk_color_to_rgba(_cs.get_color());
+               (*rv)[_key] = rgba;
+       }
+protected:
+       Gtk::ColorButton _cs;
+};
+
 class LuaDialogCheckbox : public LuaDialogWidget
 {
 public:
        LuaDialogCheckbox (std::string const& key, std::string const& title, bool on)
-               : LuaDialogWidget (key, "")
-               , _cb (title)
+               : LuaDialogWidget (key, "", 1, 1)
        {
+               if (!title.empty ()) {
+                       _cb.add_label (title, false, 0);
+               }
                _cb.set_active (on);
        }
 
@@ -155,9 +243,9 @@ class LuaDialogFader : public LuaDialogWidget
 public:
        LuaDialogFader (std::string const& key, std::string const& title, double dflt)
                : LuaDialogWidget (key, title)
-               , _db_adjustment (ARDOUR::gain_to_slider_position_with_max (1.0, ARDOUR::Config->get_max_gain()), 0, 1, 0.01, 0.1)
+               , _db_adjustment (ARDOUR::gain_to_slider_position_with_max (1.0, ARDOUR::Config->get_max_gain ()), 0, 1, 0.01, 0.1)
        {
-               _db_slider = Gtk::manage (new Gtkmm2ext::HSliderController (&_db_adjustment, boost::shared_ptr<PBD::Controllable>(), 220, 18));
+               _db_slider = Gtk::manage (new ArdourWidgets::HSliderController (&_db_adjustment, boost::shared_ptr<PBD::Controllable> (), 220, 18));
 
                _fader_centering_box.pack_start (*_db_slider, true, false);
 
@@ -169,9 +257,9 @@ public:
 
                Gtkmm2ext::set_size_request_to_display_given_text (_db_display, "-99.00", 12, 0);
 
-               _db_adjustment.signal_value_changed().connect (sigc::mem_fun (*this, &LuaDialogFader::db_changed));
-               _db_display.signal_activate().connect (sigc::mem_fun (*this, &LuaDialogFader::on_activate));
-               _db_display.signal_key_press_event().connect (sigc::mem_fun (*this, &LuaDialogFader::on_key_press), false);
+               _db_adjustment.signal_value_changed ().connect (sigc::mem_fun (*this, &LuaDialogFader::db_changed));
+               _db_display.signal_activate ().connect (sigc::mem_fun (*this, &LuaDialogFader::on_activate));
+               _db_display.signal_key_press_event ().connect (sigc::mem_fun (*this, &LuaDialogFader::on_key_press), false);
 
                double coeff_val = dB_to_coefficient (dflt);
                _db_adjustment.set_value (ARDOUR::gain_to_slider_position_with_max (coeff_val, ARDOUR::Config->get_max_gain ()));
@@ -185,14 +273,14 @@ public:
 
        void assign (luabridge::LuaRef* rv) const
        {
-               double const val = ARDOUR::slider_position_to_gain_with_max (_db_adjustment.get_value (), ARDOUR::Config->get_max_gain());
+               double const val = ARDOUR::slider_position_to_gain_with_max (_db_adjustment.get_value (), ARDOUR::Config->get_max_gain ());
                (*rv)[_key] = accurate_coefficient_to_dB (val);
        }
 
 protected:
        void db_changed ()
        {
-               double const val = ARDOUR::slider_position_to_gain_with_max (_db_adjustment.get_value (), ARDOUR::Config->get_max_gain());
+               double const val = ARDOUR::slider_position_to_gain_with_max (_db_adjustment.get_value (), ARDOUR::Config->get_max_gain ());
                char buf[16];
                if (val == 0.0) {
                        snprintf (buf, sizeof (buf), "-inf");
@@ -218,7 +306,7 @@ protected:
        }
 
        Gtk::Adjustment _db_adjustment;
-       Gtkmm2ext::HSliderController* _db_slider;
+       ArdourWidgets::HSliderController* _db_slider;
        Gtk::Entry _db_display;
        Gtk::HBox _box;
        Gtk::VBox _fader_centering_box;
@@ -270,7 +358,7 @@ public:
                , _adj (dflt, lower, upper, step, step, 0)
                , _spin (_adj)
        {
-               _spin.set_digits(digits);
+               _spin.set_digits (digits);
        }
 
        Gtk::Widget* widget ()
@@ -356,7 +444,7 @@ public:
                : LuaDialogWidget (key, title)
                , _rv (0)
        {
-               populate (_dd.items(), values, dflt);
+               populate (_dd.items (), values, dflt);
        }
 
        ~LuaDialogDropDown ()
@@ -385,19 +473,28 @@ protected:
        void populate (Gtk::Menu_Helpers::MenuList& items, luabridge::LuaRef values, std::string const& dflt)
        {
                using namespace Gtk::Menu_Helpers;
+               std::vector<std::string> keys;
+
                for (luabridge::Iterator i (values); !i.isNil (); ++i) {
                        if (!i.key ().isString ())  { continue; }
-                       std::string key = i.key ().cast<std::string> ();
-                       if (i.value ().isTable ())  {
+                       keys.push_back (i.key ().cast<std::string> ());
+               }
+
+               std::sort (keys.begin(), keys.end());
+
+               for (std::vector<std::string>::const_iterator i = keys.begin (); i != keys.end(); ++i) {
+                       std::string key = *i;
+
+                       if (values[key].isTable ())  {
                                Gtk::Menu* menu  = Gtk::manage (new Gtk::Menu);
                                items.push_back (MenuElem (key, *menu));
-                               populate (menu->items(), i.value (), dflt);
+                               populate (menu->items (), values[key], dflt);
                                continue;
                        }
-                       luabridge::LuaRef* ref = new luabridge::LuaRef (i.value ());
+                       luabridge::LuaRef* ref = new luabridge::LuaRef (values[key]);
                        _refs.push_back (ref);
-                       items.push_back (MenuElem (i.key ().cast<std::string> (),
-                                               sigc::bind (sigc::mem_fun(*this, &LuaDialogDropDown::dd_select), key, ref)));
+                       items.push_back (MenuElem (key,
+                                               sigc::bind (sigc::mem_fun (*this, &LuaDialogDropDown::dd_select), key, ref)));
 
                        if (!_rv || key == dflt) {
                                _rv = ref;
@@ -411,11 +508,46 @@ protected:
                _rv = rv;
        }
 
-       ArdourDropdown _dd;
+       ArdourWidgets::ArdourDropdown _dd;
        std::vector<luabridge::LuaRef*> _refs;
        luabridge::LuaRef* _rv;
 };
 
+class LuaFileChooser : public LuaDialogWidget
+{
+public:
+       LuaFileChooser (std::string const& key, std::string const& title, Gtk::FileChooserAction a, const std::string& path)
+               : LuaDialogWidget (key, title)
+               , _fc (a)
+       {
+               if (!path.empty ()) {
+                       switch (a) {
+                               case Gtk::FILE_CHOOSER_ACTION_OPEN:
+                               case Gtk::FILE_CHOOSER_ACTION_SAVE:
+                               case Gtk::FILE_CHOOSER_ACTION_SELECT_FOLDER:
+                                       _fc.set_filename (path);
+                                       break;
+                               case Gtk::FILE_CHOOSER_ACTION_CREATE_FOLDER:
+                                       break;
+                       }
+               }
+       }
+
+       Gtk::Widget* widget ()
+       {
+               return &_fc;
+       }
+
+       void assign (luabridge::LuaRef* rv) const
+       {
+               (*rv)[_key] = std::string (_fc.get_filename ());
+       }
+
+protected:
+       Gtk::FileChooserButton _fc;
+};
+
+
 
 /*******************************************************************************
  * Lua Parameter Dialog
@@ -430,26 +562,60 @@ Dialog::Dialog (std::string const& title, luabridge::LuaRef lr)
        for (luabridge::Iterator i (lr); !i.isNil (); ++i) {
                if (!i.key ().isNumber ())  { continue; }
                if (!i.value ().isTable ()) { continue; }
-               if (!i.value ()["key"].isString ()) { continue; }
                if (!i.value ()["title"].isString ()) { continue; }
                if (!i.value ()["type"].isString ()) { continue; }
 
-               std::string key = i.value ()["key"].cast<std::string> ();
                std::string title = i.value ()["title"].cast<std::string> ();
                std::string type = i.value ()["type"].cast<std::string> ();
+               std::string key;
 
-               if (type == "checkbox") {
+               if (i.value ()["key"].isString ()) {
+                       key = i.value ()["key"].cast<std::string> ();
+               }
+
+               LuaDialogWidget* w = NULL;
+
+               if (type == "heading") {
+                       Gtk::AlignmentEnum xalign = Gtk::ALIGN_CENTER;
+                       if (i.value ()["align"].isString ()) {
+                               std::string align = i.value ()["align"].cast <std::string> ();
+                               if (align == "left") {
+                                       xalign = Gtk::ALIGN_LEFT;
+                               } else if (align == "right") {
+                                       xalign = Gtk::ALIGN_RIGHT;
+                               }
+                       }
+                       w = new LuaDialogHeading (title, xalign);
+               } else if (type == "label") {
+                       Gtk::AlignmentEnum xalign = Gtk::ALIGN_CENTER;
+                       if (i.value ()["align"].isString ()) {
+                               std::string align = i.value ()["align"].cast <std::string> ();
+                               if (align == "left") {
+                                       xalign = Gtk::ALIGN_LEFT;
+                               } else if (align == "right") {
+                                       xalign = Gtk::ALIGN_RIGHT;
+                               }
+                       }
+                       w = new LuaDialogLabel (title, xalign);
+               } else if (type == "hseparator") {
+                       w = new LuaHSeparator ();
+               }
+               /* the following widgets do require a key */
+               else if (key.empty ()) {
+                       continue;
+               }
+               else if (type == "checkbox") {
                        bool dflt = false;
                        if (i.value ()["default"].isBoolean ()) {
                                dflt = i.value ()["default"].cast<bool> ();
                        }
-                       _widgets.push_back (new LuaDialogCheckbox (key, title, dflt));
+                       w = new LuaDialogCheckbox (key, title, dflt);
                } else if (type == "entry") {
                        std::string dflt;
                        if (i.value ()["default"].isString ()) {
                                dflt = i.value ()["default"].cast<std::string> ();
                        }
-                       _widgets.push_back (new LuaDialogEntry (key, title, dflt));
+                       w = new LuaDialogEntry (key, title, dflt);
                } else if (type == "radio") {
                        std::string dflt;
                        if (!i.value ()["values"].isTable ()) {
@@ -458,13 +624,13 @@ Dialog::Dialog (std::string const& title, luabridge::LuaRef lr)
                        if (i.value ()["default"].isString ()) {
                                dflt = i.value ()["default"].cast<std::string> ();
                        }
-                       _widgets.push_back (new LuaDialogRadio (key, title, i.value ()["values"], dflt));
+                       w = new LuaDialogRadio (key, title, i.value ()["values"], dflt);
                } else if (type == "fader") {
                        double dflt = 0;
                        if (i.value ()["default"].isNumber ()) {
                                dflt = i.value ()["default"].cast<double> ();
                        }
-                       _widgets.push_back (new LuaDialogFader (key, title, dflt));
+                       w = new LuaDialogFader (key, title, dflt);
                } else if (type == "slider") {
                        double lower, upper, dflt;
                        int digits = 0;
@@ -480,7 +646,7 @@ Dialog::Dialog (std::string const& title, luabridge::LuaRef lr)
                        if (i.value ()["digits"].isNumber ()) {
                                digits = i.value ()["digits"].cast<int> ();
                        }
-                       _widgets.push_back (new LuaDialogSlider (key, title, lower, upper, dflt, digits, i.value ()["scalepoints"]));
+                       w = new LuaDialogSlider (key, title, lower, upper, dflt, digits, i.value ()["scalepoints"]);
                } else if (type == "number") {
                        double lower, upper, dflt, step;
                        int digits = 0;
@@ -501,7 +667,7 @@ Dialog::Dialog (std::string const& title, luabridge::LuaRef lr)
                        if (i.value ()["digits"].isNumber ()) {
                                digits = i.value ()["digits"].cast<int> ();
                        }
-                       _widgets.push_back (new LuaDialogSpinBox (key, title, lower, upper, dflt, step, digits));
+                       w = new LuaDialogSpinBox (key, title, lower, upper, dflt, step, digits);
                } else if (type == "dropdown") {
                        std::string dflt;
                        if (!i.value ()["values"].isTable ()) {
@@ -510,27 +676,78 @@ Dialog::Dialog (std::string const& title, luabridge::LuaRef lr)
                        if (i.value ()["default"].isString ()) {
                                dflt = i.value ()["default"].cast<std::string> ();
                        }
-                       _widgets.push_back (new LuaDialogDropDown (key, title, i.value ()["values"], dflt));
+                       w = new LuaDialogDropDown (key, title, i.value ()["values"], dflt);
+               } else if (type == "file") {
+                       std::string path;
+                       if (i.value ()["path"].isString ()) {
+                               path = i.value ()["path"].cast<std::string> ();
+                       }
+                       w = new LuaFileChooser (key, title, Gtk::FILE_CHOOSER_ACTION_OPEN, path);
+               } else if (type == "folder") {
+                       std::string path;
+                       if (i.value ()["path"].isString ()) {
+                               path = i.value ()["path"].cast<std::string> ();
+                       }
+                       w = new LuaFileChooser (key, title, Gtk::FILE_CHOOSER_ACTION_SELECT_FOLDER, path);
+               } else if (type == "color") {
+                       w = new LuaColorPicker (key);
+               }
+
+               if (w) {
+                       if (i.value ()["col"].isNumber ()) {
+                               w->set_col (i.value ()["col"].cast<int> ());
+                       }
+                       if (i.value ()["colspan"].isNumber ()) {
+                               w->set_span (i.value ()["colspan"].cast<int> ());
+                       }
+                       _widgets.push_back(w);
                }
        }
 
-       _ad.add_button (Gtk::Stock::OK, Gtk::RESPONSE_ACCEPT);
        _ad.add_button (Gtk::Stock::CANCEL, Gtk::RESPONSE_CANCEL);
+       _ad.add_button (Gtk::Stock::OK, Gtk::RESPONSE_ACCEPT);
+
+       Gtk::Table* table = Gtk::manage (new Gtk::Table ());
+       table->set_col_spacings (20);
+       table->set_row_spacings (8);
+       table->signal_size_allocate ().connect (sigc::mem_fun (this, &Dialog::table_size_alloc));
+
+       _scroller.set_shadow_type(Gtk::SHADOW_NONE);
+       _scroller.set_border_width(0);
+       _scroller.add (*table);
+       _scroller.set_policy (Gtk::POLICY_NEVER, Gtk::POLICY_NEVER);
+
+       _ad.get_vbox ()->pack_start (_scroller);
 
-       Gtk::Table* table = Gtk::manage (new Gtk::Table());
-       table->set_spacings (6);
-       _ad.get_vbox ()->pack_start (*table);
        int row = 0;
+       int last_end = -1;
+
+       for (DialogWidgets::const_iterator i = _widgets.begin (); i != _widgets.end (); ++i) {
+               int col = (*i)->col();
+               int cend = col + (*i)->span();
+
+               if (col < last_end) {
+                       ++row;
+               }
+               last_end = cend;
 
-       for (DialogWidgets::const_iterator i = _widgets.begin (); i != _widgets.end () ; ++i) {
                std::string const& label = (*i)->label ();
                if (!label.empty ()) {
-                       Gtk::Label* lbl = Gtk::manage (new Gtk::Label ("<b>" + label + ":</b>", Gtk::ALIGN_END, Gtk::ALIGN_CENTER, false));
-                       lbl->set_use_markup ();
-                       table->attach (*lbl, 0, 1, row, row + 1, Gtk::FILL | Gtk::EXPAND, Gtk::SHRINK);
+                       /* items with implicit label (title) */
+                       Gtk::Label* lbl = Gtk::manage (new Gtk::Label (label + ":", Gtk::ALIGN_END, Gtk::ALIGN_CENTER, false));
+                       if (cend - col > 1) {
+                               table->attach (*lbl, col, col + 1, row, row + 1, Gtk::FILL | Gtk::EXPAND, Gtk::SHRINK);
+                               table->attach (*((*i)->widget ()), col + 1, cend, row, row + 1, Gtk::FILL | Gtk::EXPAND, Gtk::SHRINK);
+                       } else {
+                               Gtk::HBox* hb = Gtk::manage (new Gtk::HBox());
+                               hb->set_spacing(4);
+                               hb->pack_start (*lbl, true, false);
+                               hb->pack_start (*(*i)->widget (), true, false);
+                               table->attach (*hb, col, cend, row, row + 1, Gtk::FILL | Gtk::EXPAND, Gtk::SHRINK);
+                       }
+               } else {
+                       table->attach (*((*i)->widget ()), col, cend, row, row + 1, Gtk::FILL | Gtk::EXPAND, Gtk::SHRINK);
                }
-               table->attach (*((*i)->widget ()), 1, 2, row, row + 1, Gtk::FILL | Gtk::EXPAND, Gtk::SHRINK);
-               ++row;
        }
 }
 
@@ -550,7 +767,7 @@ Dialog::run (lua_State *L)
                case Gtk::RESPONSE_ACCEPT:
                        break;
                default:
-      lua_pushnil (L);
+                       lua_pushnil (L);
                        return 1;
        }
 
@@ -561,3 +778,13 @@ Dialog::run (lua_State *L)
        luabridge::push (L, rv);
        return 1;
 }
+
+void
+Dialog::table_size_alloc (Gtk::Allocation& allocation)
+{
+       /* XXX: consider using 0.75 * screen-height instead of 512 */
+       if (allocation.get_height () > 512) {
+               _scroller.set_policy (Gtk::POLICY_NEVER, Gtk::POLICY_AUTOMATIC);
+               _ad.set_size_request (-1, 512);
+       }
+}