pixbufs instead of pixmaps; function-scope local fd's for reading from a FileSource
[ardour.git] / gtk2_ardour / ardour_ui2.cc
index 804027092f962f2a14c71da50ff3d85326472756..c55ba08f8ff175f93096d542b576e7197e31fbfd 100644 (file)
@@ -29,7 +29,6 @@
 #include <pbd/error.h>
 #include <pbd/basename.h>
 #include <pbd/fastlog.h>
-#include <gtkmm2ext/pix.h>
 #include <gtkmm2ext/utils.h>
 #include <gtkmm2ext/click_box.h>
 #include <gtkmm2ext/tearoff.h>
@@ -53,21 +52,9 @@ using namespace Gtk;
 using namespace Glib;
 using namespace sigc;
 
-
-static const gchar *psync_strings[] = {
-       N_("Internal"),
-       N_("Slave to MTC"),
-       N_("Sync with JACK"),
-       0
-};
-
-static vector<string> positional_sync_strings;
-
 int    
 ARDOUR_UI::setup_windows ()
 {
-       using namespace Menu_Helpers;
-
        if (create_editor ()) {
                error << _("UI: cannot setup editor") << endmsg;
                return -1;
@@ -127,35 +114,11 @@ ARDOUR_UI::setup_adjustables ()
        adjuster_table.attach (*mmc_id_button, 2, 3, 1, 2, FILL, FILL, 5, 5);
 }
 
-static const gchar * loop_xpm[] = {
-"19 19 3 1",
-"      c None",
-".     c #000000",
-"+     c #FFFFFF",
-"       ...         ",
-"       .+..        ",
-"       .++..       ",
-"     ...+++....    ",
-"   ...++++++++...  ",
-"  ..+++.+++..+++.. ",
-" ..++...++.....++..",
-" .++.. .+..   ..++.",
-" .+..  ...     ..+.",
-" .+.            .+.",
-" .+..     ...  ..+.",
-" .++..   ..+. ..++.",
-" ..++.....++...++..",
-"  ..+++..+++.+++.. ",
-"   ...++++++++...  ",
-"     ....+++...    ",
-"        ..++.      ",
-"         ..+.      ",
-"          ...      "};
-
 void
 ARDOUR_UI::transport_stopped ()
 {
        stop_button.set_active (true);
+       
        roll_button.set_active (false);
        play_selection_button.set_active (false);
        auto_loop_button.set_active (false);
@@ -172,7 +135,6 @@ void
 ARDOUR_UI::transport_rolling ()
 {
        stop_button.set_active (false);
-
        if (session->get_play_range()) {
 
                play_selection_button.set_active (true);
@@ -201,7 +163,7 @@ ARDOUR_UI::transport_rolling ()
 void
 ARDOUR_UI::transport_rewinding ()
 {
-       stop_button.set_active (false);
+       stop_button.set_active(false);
        roll_button.set_active (true);
        play_selection_button.set_active (false);
        auto_loop_button.set_active (false);
@@ -235,23 +197,42 @@ ARDOUR_UI::setup_transport ()
                                                 static_cast<Widget*>(&transport_frame)));
        transport_tearoff->Attach.connect (bind (mem_fun(*this, &ARDOUR_UI::reattach_tearoff), static_cast<Box*> (&top_packer), 
                                                 static_cast<Widget*> (&transport_frame), 1));
+       transport_tearoff->Hidden.connect (bind (mem_fun(*this, &ARDOUR_UI::detach_tearoff), static_cast<Box*>(&top_packer), 
+                                                static_cast<Widget*>(&transport_frame)));
+       transport_tearoff->Visible.connect (bind (mem_fun(*this, &ARDOUR_UI::reattach_tearoff), static_cast<Box*> (&top_packer), 
+                                                 static_cast<Widget*> (&transport_frame), 1));
+       
+       shuttle_box.set_name ("TransportButton");
+       goto_start_button.set_name ("TransportButton");
+       goto_end_button.set_name ("TransportButton");
+       roll_button.set_name ("TransportButton");
+       stop_button.set_name ("TransportButton");
+       play_selection_button.set_name ("TransportButton");
+       rec_button.set_name ("TransportRecButton");
+       auto_loop_button.set_name ("TransportButton");
+       auto_return_button.set_name ("TransportButton");
+       auto_play_button.set_name ("TransportButton");
+       auto_input_button.set_name ("TransportButton");
+       punch_in_button.set_name ("TransportButton");
+       punch_out_button.set_name ("TransportButton");
+       click_button.set_name ("TransportButton");
+       time_master_button.set_name ("TransportButton");
 
        vector<Gdk::Color> colors;
        Gdk::Color c;
 
        /* record button has 3 color states, so we set 2 extra here */
-
-       c.set_rgb_p (0.91, 0.68, 0.68);
+       set_color(c, rgba_from_style ("TransportRecButton", 0xff, 0, 0, 0, "bg", Gtk::STATE_PRELIGHT, false ));
        colors.push_back (c);
-       c.set_rgb_p (1, 0, 0);
+       
+       set_color(c, rgba_from_style ("TransportRecButton", 0xff, 0, 0, 0, "bg", Gtk::STATE_ACTIVE, false ));
        colors.push_back (c);
+       
        rec_button.set_colors (colors);
-
        colors.clear ();
-
+       
        /* other buttons get 2 color states, so add one here */
-
-       c.set_rgb_p (0.66, 0.97, 0.18);
+       set_color(c, rgba_from_style ("TransportButton", 0x7f, 0xff, 0x7f, 0, "bg", Gtk::STATE_ACTIVE, false ));
        colors.push_back (c);
 
        stop_button.set_colors (colors);
@@ -283,7 +264,7 @@ ARDOUR_UI::setup_transport ()
        w = manage (new Image (Stock::MEDIA_RECORD, ICON_SIZE_BUTTON));
        w->show();
        rec_button.add (*w);
-       w = manage (new Image (Gdk::Pixbuf::create_from_xpm_data(loop_xpm)));
+       w = manage (new Image (get_xpm("loop.xpm")));
        w->show();
        auto_loop_button.add (*w);
 
@@ -318,61 +299,16 @@ ARDOUR_UI::setup_transport ()
        ARDOUR_UI::instance()->tooltips().set_tip (punch_in_button, _("Start recording at auto-punch start"));
        ARDOUR_UI::instance()->tooltips().set_tip (punch_out_button, _("Stop recording at auto-punch end"));
        ARDOUR_UI::instance()->tooltips().set_tip (click_button, _("Enable/Disable audio click"));
+       ARDOUR_UI::instance()->tooltips().set_tip (sync_option_combo, _("Positional sync source"));
        ARDOUR_UI::instance()->tooltips().set_tip (time_master_button, _("Does Ardour control the time?"));
        ARDOUR_UI::instance()->tooltips().set_tip (shuttle_box, _("Shuttle speed control"));
        ARDOUR_UI::instance()->tooltips().set_tip (shuttle_units_button, _("Select semitones or %%-age for speed display"));
        ARDOUR_UI::instance()->tooltips().set_tip (speed_display_box, _("Current transport speed"));
        
        shuttle_box.set_flags (CAN_FOCUS);
-       shuttle_box.set_events (shuttle_box.get_events() | Gdk::ENTER_NOTIFY_MASK|Gdk::LEAVE_NOTIFY_MASK|Gdk::BUTTON_RELEASE_MASK|Gdk::BUTTON_PRESS_MASK|Gdk::POINTER_MOTION_MASK);
+       shuttle_box.add_events (Gdk::ENTER_NOTIFY_MASK|Gdk::LEAVE_NOTIFY_MASK|Gdk::BUTTON_RELEASE_MASK|Gdk::BUTTON_PRESS_MASK|Gdk::POINTER_MOTION_MASK);
        shuttle_box.set_size_request (100, 15);
 
-       shuttle_box.set_name ("TransportButton");
-       goto_start_button.set_name ("TransportButton");
-       goto_end_button.set_name ("TransportButton");
-       roll_button.set_name ("TransportButton");
-       stop_button.set_name ("TransportButton");
-       play_selection_button.set_name ("TransportButton");
-       rec_button.set_name ("TransportRecButton");
-       auto_loop_button.set_name ("TransportButton");
-       auto_return_button.set_name ("TransportButton");
-       auto_play_button.set_name ("TransportButton");
-       auto_input_button.set_name ("TransportButton");
-       punch_in_button.set_name ("TransportButton");
-       punch_out_button.set_name ("TransportButton");
-       click_button.set_name ("TransportButton");
-       time_master_button.set_name ("TransportButton");
-
-       goto_start_button.unset_flags (CAN_FOCUS);
-       goto_end_button.unset_flags (CAN_FOCUS);
-       roll_button.unset_flags (CAN_FOCUS);
-       stop_button.unset_flags (CAN_FOCUS);
-       play_selection_button.unset_flags (CAN_FOCUS);
-       rec_button.unset_flags (CAN_FOCUS);
-       auto_loop_button.unset_flags (CAN_FOCUS);
-       auto_return_button.unset_flags (CAN_FOCUS);
-       auto_play_button.unset_flags (CAN_FOCUS);
-       auto_input_button.unset_flags (CAN_FOCUS);
-       punch_out_button.unset_flags (CAN_FOCUS);
-       punch_in_button.unset_flags (CAN_FOCUS);
-       click_button.unset_flags (CAN_FOCUS);
-       time_master_button.unset_flags (CAN_FOCUS);
-       
-       goto_start_button.set_events (goto_start_button.get_events() & ~(Gdk::ENTER_NOTIFY_MASK|Gdk::LEAVE_NOTIFY_MASK));
-       goto_end_button.set_events (goto_end_button.get_events() & ~(Gdk::ENTER_NOTIFY_MASK|Gdk::LEAVE_NOTIFY_MASK));
-       roll_button.set_events (roll_button.get_events() & ~(Gdk::ENTER_NOTIFY_MASK|Gdk::LEAVE_NOTIFY_MASK));
-       stop_button.set_events (stop_button.get_events() & ~(Gdk::ENTER_NOTIFY_MASK|Gdk::LEAVE_NOTIFY_MASK));
-       play_selection_button.set_events (play_selection_button.get_events() & ~(Gdk::ENTER_NOTIFY_MASK|Gdk::LEAVE_NOTIFY_MASK));
-       rec_button.set_events (rec_button.get_events() & ~(Gdk::ENTER_NOTIFY_MASK|Gdk::LEAVE_NOTIFY_MASK));
-       auto_loop_button.set_events (auto_loop_button.get_events() & ~(Gdk::ENTER_NOTIFY_MASK|Gdk::LEAVE_NOTIFY_MASK));
-       auto_return_button.set_events (auto_return_button.get_events() & ~(Gdk::ENTER_NOTIFY_MASK|Gdk::LEAVE_NOTIFY_MASK));
-       auto_play_button.set_events (auto_play_button.get_events() & ~(Gdk::ENTER_NOTIFY_MASK|Gdk::LEAVE_NOTIFY_MASK));
-       auto_input_button.set_events (auto_input_button.get_events() & ~(Gdk::ENTER_NOTIFY_MASK|Gdk::LEAVE_NOTIFY_MASK));
-       click_button.set_events (click_button.get_events() & ~(Gdk::ENTER_NOTIFY_MASK|Gdk::LEAVE_NOTIFY_MASK));
-       punch_in_button.set_events (punch_in_button.get_events() & ~(Gdk::ENTER_NOTIFY_MASK|Gdk::LEAVE_NOTIFY_MASK));
-       punch_out_button.set_events (punch_out_button.get_events() & ~(Gdk::ENTER_NOTIFY_MASK|Gdk::LEAVE_NOTIFY_MASK));
-       time_master_button.set_events (punch_out_button.get_events() & ~(Gdk::ENTER_NOTIFY_MASK|Gdk::LEAVE_NOTIFY_MASK));
-
        shuttle_box.signal_button_press_event().connect (mem_fun(*this, &ARDOUR_UI::shuttle_box_button_press));
        shuttle_box.signal_button_release_event().connect (mem_fun(*this, &ARDOUR_UI::shuttle_box_button_release));
        shuttle_box.signal_motion_notify_event().connect (mem_fun(*this, &ARDOUR_UI::shuttle_box_motion));
@@ -392,14 +328,12 @@ ARDOUR_UI::setup_transport ()
        ARDOUR_UI::instance()->tooltips().set_tip (primary_clock, _("Primary clock"));
        ARDOUR_UI::instance()->tooltips().set_tip (secondary_clock, _("secondary clock"));
 
-       /* options */
-
-       auto_return_button.signal_toggled().connect (mem_fun(*this,&ARDOUR_UI::toggle_auto_return));
-       auto_play_button.signal_toggled().connect (mem_fun(*this,&ARDOUR_UI::toggle_auto_play));
-       auto_input_button.signal_toggled().connect (mem_fun(*this,&ARDOUR_UI::toggle_auto_input));
-       click_button.signal_toggled().connect (mem_fun(*this,&ARDOUR_UI::toggle_click));
-       punch_in_button.signal_toggled().connect (mem_fun(*this,&ARDOUR_UI::toggle_punch_in));
-       punch_out_button.signal_toggled().connect (mem_fun(*this,&ARDOUR_UI::toggle_punch_out));
+       ActionManager::get_action ("Transport", "ToggleAutoReturn")->connect_proxy (auto_return_button);
+       ActionManager::get_action ("Transport", "ToggleAutoPlay")->connect_proxy (auto_play_button);
+       ActionManager::get_action ("Transport", "ToggleAutoInput")->connect_proxy (auto_input_button);
+       ActionManager::get_action ("Transport", "ToggleClick")->connect_proxy (click_button);
+       ActionManager::get_action ("Transport", "TogglePunchIn")->connect_proxy (punch_in_button);
+       ActionManager::get_action ("Transport", "TogglePunchOut")->connect_proxy (punch_out_button);
 
        preroll_button.unset_flags (CAN_FOCUS);
        preroll_button.set_events (preroll_button.get_events() & ~(Gdk::ENTER_NOTIFY_MASK|Gdk::LEAVE_NOTIFY_MASK));
@@ -459,9 +393,7 @@ ARDOUR_UI::setup_transport ()
        sdframe->set_shadow_type (SHADOW_IN);
        sdframe->add (speed_display_box);
 
-       positional_sync_strings = internationalize (psync_strings);
-
-       set_popdown_strings (sync_option_combo, positional_sync_strings);
+       mtc_port_changed ();
        sync_option_combo.set_active_text (positional_sync_strings.front());
        sync_option_combo.signal_changed().connect (mem_fun (*this, &ARDOUR_UI::sync_option_changed));
 
@@ -621,12 +553,73 @@ ARDOUR_UI::audition_blink (bool onoff)
        }
 }
 
+void
+ARDOUR_UI::build_shuttle_context_menu ()
+{
+       using namespace Menu_Helpers;
+
+       shuttle_context_menu = new Menu();
+       MenuList& items = shuttle_context_menu->items();
+
+       Menu* speed_menu = manage (new Menu());
+       MenuList& speed_items = speed_menu->items();
+
+       RadioMenuItem::Group group;
+
+       speed_items.push_back (RadioMenuElem (group, "8", bind (mem_fun (*this, &ARDOUR_UI::set_shuttle_max_speed), 8.0f)));
+       if (shuttle_max_speed == 8.0) {
+               static_cast<RadioMenuItem*>(&speed_items.back())->set_active ();        
+       }
+       speed_items.push_back (RadioMenuElem (group, "6", bind (mem_fun (*this, &ARDOUR_UI::set_shuttle_max_speed), 6.0f)));
+       if (shuttle_max_speed == 6.0) {
+               static_cast<RadioMenuItem*>(&speed_items.back())->set_active ();        
+       }
+       speed_items.push_back (RadioMenuElem (group, "4", bind (mem_fun (*this, &ARDOUR_UI::set_shuttle_max_speed), 4.0f)));
+       if (shuttle_max_speed == 4.0) {
+               static_cast<RadioMenuItem*>(&speed_items.back())->set_active ();        
+       }
+       speed_items.push_back (RadioMenuElem (group, "3", bind (mem_fun (*this, &ARDOUR_UI::set_shuttle_max_speed), 3.0f)));
+       if (shuttle_max_speed == 3.0) {
+               static_cast<RadioMenuItem*>(&speed_items.back())->set_active ();        
+       }
+       speed_items.push_back (RadioMenuElem (group, "2", bind (mem_fun (*this, &ARDOUR_UI::set_shuttle_max_speed), 2.0f)));
+       if (shuttle_max_speed == 2.0) {
+               static_cast<RadioMenuItem*>(&speed_items.back())->set_active ();        
+       }
+       speed_items.push_back (RadioMenuElem (group, "1.5", bind (mem_fun (*this, &ARDOUR_UI::set_shuttle_max_speed), 1.5f)));
+       if (shuttle_max_speed == 1.5) {
+               static_cast<RadioMenuItem*>(&speed_items.back())->set_active ();        
+       }
+
+       items.push_back (MenuElem (_("Maximum speed"), *speed_menu));
+}
+
+void
+ARDOUR_UI::show_shuttle_context_menu ()
+{
+       if (shuttle_context_menu == 0) {
+               build_shuttle_context_menu ();
+       }
+
+       shuttle_context_menu->popup (1, 0);
+}
+
+void
+ARDOUR_UI::set_shuttle_max_speed (float speed)
+{
+       shuttle_max_speed = speed;
+}
 
 gint
 ARDOUR_UI::shuttle_box_button_press (GdkEventButton* ev)
 {
        if (!session) {
-               return TRUE;
+               return true;
+       }
+
+       if (Keyboard::is_context_menu_event (ev)) {
+               show_shuttle_context_menu ();
+               return true;
        }
 
        switch (ev->button) {
@@ -638,20 +631,20 @@ ARDOUR_UI::shuttle_box_button_press (GdkEventButton* ev)
 
        case 2:
        case 3:
-               return TRUE;
+               return true;
                break;
        }
 
-       return TRUE;
+       return true;
 }
 
 gint
 ARDOUR_UI::shuttle_box_button_release (GdkEventButton* ev)
 {
        if (!session) {
-               return TRUE;
+               return true;
        }
-
+       
        switch (ev->button) {
        case 1:
                mouse_shuttle (ev->x, true);
@@ -662,7 +655,7 @@ ARDOUR_UI::shuttle_box_button_release (GdkEventButton* ev)
                        session->request_transport_speed (1.0);
                        shuttle_box.queue_draw ();
                }
-               return TRUE;
+               return true;
 
        case 2:
                if (session->transport_rolling()) {
@@ -672,10 +665,10 @@ ARDOUR_UI::shuttle_box_button_release (GdkEventButton* ev)
                        shuttle_fract = 0;
                }
                shuttle_box.queue_draw ();
-               return TRUE;
+               return true;
 
        case 3:
-               return TRUE;
+               return true;
                
        case 4:
                shuttle_fract += 0.005;
@@ -687,14 +680,14 @@ ARDOUR_UI::shuttle_box_button_release (GdkEventButton* ev)
 
        use_shuttle_fract (true);
 
-       return TRUE;
+       return true;
 }
 
 gint
 ARDOUR_UI::shuttle_box_motion (GdkEventMotion* ev)
 {
        if (!session || !shuttle_grabbed) {
-               return TRUE;
+               return true;
        }
 
        return mouse_shuttle (ev->x, false);
@@ -714,7 +707,7 @@ ARDOUR_UI::mouse_shuttle (double x, bool force)
 
        shuttle_fract = distance / half_width;
        use_shuttle_fract (force);
-       return TRUE;
+       return true;
 }
 
 void
@@ -744,7 +737,7 @@ ARDOUR_UI::use_shuttle_fract (bool force)
                fract = -fract;
        }
 
-       session->request_transport_speed (8.0 * fract); // Formula A2
+       session->request_transport_speed (shuttle_max_speed * fract); // Formula A2
        shuttle_box.queue_draw ();
 }
 
@@ -771,7 +764,7 @@ ARDOUR_UI::shuttle_box_expose (GdkEventExpose* event)
                        0,
                        x,
                        shuttle_box.get_height());
-       return TRUE;
+       return true;
 }
 
 void
@@ -901,3 +894,25 @@ ARDOUR_UI::sync_option_changed ()
                session->request_slave_source (Session::JACK);
        } 
 }
+
+void
+ARDOUR_UI::maximise_editing_space ()
+{
+       if (!editor) {
+               return;
+       }
+
+       transport_tearoff->set_visible (false);
+       editor->maximise_editing_space ();
+}
+
+void
+ARDOUR_UI::restore_editing_space ()
+{
+       if (!editor) {
+               return;
+       }
+
+       transport_tearoff->set_visible (true);
+       editor->restore_editing_space ();
+}