X-Git-Url: https://git.carlh.net/gitweb/?a=blobdiff_plain;f=gtk2_ardour%2Fpanner_ui.cc;h=ccce2ec9f16ff1092ba66b4569ebb430abbbe280;hb=0565c75ce8344ecd2e4b42edeabc9cace5f3c091;hp=d39db280757253772a27dc430a3d25e4cc0f6e6f;hpb=4b233612261e2d13ebbd1931f4d999c6da1451e9;p=ardour.git diff --git a/gtk2_ardour/panner_ui.cc b/gtk2_ardour/panner_ui.cc index d39db28075..ccce2ec9f1 100644 --- a/gtk2_ardour/panner_ui.cc +++ b/gtk2_ardour/panner_ui.cc @@ -14,8 +14,6 @@ You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - - $Id$ */ #include @@ -35,65 +33,43 @@ #include "gui_thread.h" #include -#include #include +#include #include "i18n.h" using namespace ARDOUR; +using namespace PBD; using namespace Gtkmm2ext; using namespace Gtk; using namespace sigc; -/* XPM */ -static const gchar * forwdblarrow_xpm[] = { -"20 11 3 1", -" c None", -". c #000000", -"+ c #FFFFFF", -" .. ", -" .+. ", -" .++. ", -" ..............+++. ", -" .+++++++++++++++++.", -" ...................", -" .+++++++++++++++++.", -" ..............+++. ", -" .++. ", -" .+. ", -" .. "}; - -/* XPM */ -static const gchar * revdblarrow_xpm[] = { -"20 11 3 1", -" c None", -". c #000000", -"+ c #FFFFFF", -" .. ", -" .+. ", -" .++. ", -" ..............+++. ", -" .+++++++++++++++++.", -" ...................", -" .+++++++++++++++++.", -" .+++..............", -" .++. ", -" .+. ", -" .. "}; - - -PannerUI::PannerUI (IO& io, Session& s) + +PannerUI::PannerUI (boost::shared_ptr io, Session& s) : _io (io), _session (s), - panning_up_arrow (GTK_ARROW_UP, Gtk::SHADOW_OUT), - panning_down_arrow (GTK_ARROW_DOWN, Gtk::SHADOW_OUT), - panning_link_button (_("link")) - + hAdjustment(0.0, 0.0, 0.0), + vAdjustment(0.0, 0.0, 0.0), + panning_viewport(hAdjustment, vAdjustment), + panning_up_arrow (Gtk::ARROW_UP, Gtk::SHADOW_OUT), + panning_down_arrow (Gtk::ARROW_DOWN, Gtk::SHADOW_OUT), + panning_link_button (_("link")), + pan_automation_style_button (""), + pan_automation_state_button ("") { ignore_toggle = false; pan_menu = 0; in_pan_update = false; + pan_automation_style_button.set_name ("MixerAutomationModeButton"); + pan_automation_state_button.set_name ("MixerAutomationPlaybackButton"); + + ARDOUR_UI::instance()->tooltips().set_tip (pan_automation_state_button, _("Pan automation mode")); + ARDOUR_UI::instance()->tooltips().set_tip (pan_automation_style_button, _("Pan automation type")); + + //set_size_request_to_display_given_text (pan_automation_state_button, X_("O"), 2, 2); + //set_size_request_to_display_given_text (pan_automation_style_button, X_("0"), 2, 2); + pan_bar_packer.set_size_request (-1, 61); panning_viewport.set_size_request (61, 61); @@ -104,25 +80,47 @@ PannerUI::PannerUI (IO& io, Session& s) ARDOUR_UI::instance()->tooltips().set_tip (panning_link_direction_button, _("panning link direction")); - panning_link_box.pack_start (panning_link_button, true, true); - panning_link_box.pack_start (panning_link_direction_button, true, true); + pan_automation_style_button.unset_flags (Gtk::CAN_FOCUS); + pan_automation_state_button.unset_flags (Gtk::CAN_FOCUS); + + using namespace Menu_Helpers; + pan_astate_menu.items().push_back (MenuElem (_("Off"), + bind (mem_fun (_io->panner(), &Panner::set_automation_state), (AutoState) Off))); + pan_astate_menu.items().push_back (MenuElem (_("Play"), + bind (mem_fun (_io->panner(), &Panner::set_automation_state), (AutoState) Play))); + pan_astate_menu.items().push_back (MenuElem (_("Write"), + bind (mem_fun (_io->panner(), &Panner::set_automation_state), (AutoState) Write))); + pan_astate_menu.items().push_back (MenuElem (_("Touch"), + bind (mem_fun (_io->panner(), &Panner::set_automation_state), (AutoState) Touch))); + + pan_astyle_menu.items().push_back (MenuElem (_("Trim"))); + pan_astyle_menu.items().push_back (MenuElem (_("Abs"))); + + pan_astate_menu.set_name ("ArdourContextMenu"); + pan_astyle_menu.set_name ("ArdourContextMenu"); + + pan_automation_style_button.signal_button_press_event().connect (mem_fun(*this, &PannerUI::pan_automation_style_button_event), false); + pan_automation_state_button.signal_button_press_event().connect (mem_fun(*this, &PannerUI::pan_automation_state_button_event), false); panning_link_button.set_name (X_("PanningLinkButton")); panning_link_direction_button.set_name (X_("PanningLinkDirectionButton")); + panning_link_box.pack_start (panning_link_button, true, true); + panning_link_box.pack_start (panning_link_direction_button, true, true); + panning_link_box.pack_start (pan_automation_state_button, true, true); + /* the pixmap will be reset at some point, but the key thing is that we need a pixmap in the button just to get started. */ + panning_link_direction_button.add (*(manage (new Image (get_xpm("forwardblarrow.xpm"))))); - panning_link_direction_button.add (*(manage (new Pixmap (forwdblarrow_xpm)))); - - panning_link_direction_button.clicked.connect + panning_link_direction_button.signal_clicked().connect (mem_fun(*this, &PannerUI::panning_link_direction_clicked)); panning_link_button.signal_button_press_event().connect - (mem_fun(*this, &PannerUI::panning_link_button_press)); + (mem_fun(*this, &PannerUI::panning_link_button_press), false); panning_link_button.signal_button_release_event().connect - (mem_fun(*this, &PannerUI::panning_link_button_release)); + (mem_fun(*this, &PannerUI::panning_link_button_release), false); panning_up.set_border_width (3); panning_down.set_border_width (3); @@ -134,48 +132,51 @@ PannerUI::PannerUI (IO& io, Session& s) panning_down_arrow.set_name (X_("PanScrollerArrow")); pan_vbox.set_spacing (4); - pan_vbox.pack_start (panning_viewport, false, false); - pan_vbox.pack_start (panning_link_box, false, false); + pan_vbox.pack_start (panning_viewport, Gtk::PACK_SHRINK); + pan_vbox.pack_start (panning_link_box, Gtk::PACK_SHRINK); pack_start (pan_vbox, true, false); - pan_vbox.show_all (); - show (); panner = 0; - _io.panner().Changed.connect (mem_fun(*this, &PannerUI::panner_changed)); - _io.panner().LinkStateChanged.connect (mem_fun(*this, &PannerUI::update_pan_linkage)); - _io.panner().StateChanged.connect (mem_fun(*this, &PannerUI::update_pan_state)); + set_width(Narrow); + + _io->panner().Changed.connect (mem_fun(*this, &PannerUI::panner_changed)); + _io->panner().LinkStateChanged.connect (mem_fun(*this, &PannerUI::update_pan_linkage)); + _io->panner().StateChanged.connect (mem_fun(*this, &PannerUI::update_pan_state)); pan_changed (0); update_pan_sensitive (); update_pan_linkage (); + pan_automation_state_changed (); } -gint +bool PannerUI::panning_link_button_press (GdkEventButton* ev) { - return stop_signal (panning_link_button, "button-press-event"); + cerr << "link press\n"; + return true; } -gint +bool PannerUI::panning_link_button_release (GdkEventButton* ev) { + cerr << "link release\n"; if (!ignore_toggle) { - _io.panner().set_linked (!_io.panner().linked()); + _io->panner().set_linked (!_io->panner().linked()); } - return TRUE; + return true; } void PannerUI::panning_link_direction_clicked() { - switch (_io.panner().link_direction()) { + switch (_io->panner().link_direction()) { case Panner::SameDirection: - _io.panner().set_link_direction (Panner::OppositeDirection); + _io->panner().set_link_direction (Panner::OppositeDirection); break; default: - _io.panner().set_link_direction (Panner::SameDirection); + _io->panner().set_link_direction (Panner::SameDirection); break; } } @@ -185,7 +186,7 @@ PannerUI::update_pan_linkage () { ENSURE_GUI_THREAD(mem_fun(*this, &PannerUI::update_pan_linkage)); - bool x = _io.panner().linked(); + bool x = _io->panner().linked(); bool bx = panning_link_button.get_active(); if (x != bx) { @@ -197,12 +198,12 @@ PannerUI::update_pan_linkage () panning_link_direction_button.set_sensitive (x); - switch (_io.panner().link_direction()) { + switch (_io->panner().link_direction()) { case Panner::SameDirection: - static_cast (panning_link_direction_button.get_child())->set (forwdblarrow_xpm); + panning_link_direction_button.set_image (*(manage (new Image (get_xpm ("forwardblarrow.xpm"))))); break; default: - static_cast (panning_link_direction_button.get_child())->set (revdblarrow_xpm); + panning_link_direction_button.set_image (*(manage (new Image (get_xpm("revdblarrow.xpm"))))); break; } } @@ -219,7 +220,7 @@ PannerUI::set_width (Width w) for (vector::iterator i = pan_bars.begin(); i != pan_bars.end(); ++i) { (*i)->set_size_request (61, 15); } - static_cast (panning_link_button.get_child())->set_text (_("link")); + panning_link_button.set_label (_("link")); break; case Narrow: panning_viewport.set_size_request (31, 61); @@ -229,7 +230,7 @@ PannerUI::set_width (Width w) for (vector::iterator i = pan_bars.begin(); i != pan_bars.end(); ++i) { (*i)->set_size_request (31, 15); } - static_cast (panning_link_button.get_child())->set_text (_("L")); + panning_link_button.set_label (_("L")); break; } @@ -258,17 +259,6 @@ PannerUI::~PannerUI () } -gint -PannerUI::entry_focus_event (GdkEventFocus* ev) -{ - if (ev->in) { - ARDOUR_UI::instance()->allow_focus (true); - } else { - ARDOUR_UI::instance()->allow_focus (false); - } - return TRUE; -} - void PannerUI::panner_changed () { @@ -286,7 +276,7 @@ PannerUI::update_pan_state () void PannerUI::setup_pan () { - uint32_t nouts = _io.n_outputs (); + uint32_t nouts = _io->n_outputs (); if (nouts == 0 || nouts == 1) { @@ -300,7 +290,7 @@ PannerUI::setup_pan () } else if (nouts == 2) { vector::size_type asz; - uint32_t npans = _io.panner().size(); + uint32_t npans = _io->panner().size(); while (!pan_adjustments.empty()) { delete pan_bars.back(); @@ -316,32 +306,26 @@ PannerUI::setup_pan () /* initialize adjustment with current value of panner */ - _io.panner()[asz]->get_position (x); + _io->panner()[asz]->get_position (x); pan_adjustments.push_back (new Adjustment (x, 0, 1.0, 0.05, 0.1)); - pan_adjustments.back()->value_changed.connect (bind (mem_fun(*this, &PannerUI::pan_adjustment_changed), (uint32_t) asz)); + pan_adjustments.back()->signal_value_changed().connect (bind (mem_fun(*this, &PannerUI::pan_adjustment_changed), (uint32_t) asz)); - _io.panner()[asz]->Changed.connect (bind (mem_fun(*this, &PannerUI::pan_value_changed), (uint32_t) asz)); + _io->panner()[asz]->Changed.connect (bind (mem_fun(*this, &PannerUI::pan_value_changed), (uint32_t) asz)); bc = new BarController (*pan_adjustments[asz], - &_io.panner()[asz]->midi_control(), + _io->panner()[asz]->control(), bind (mem_fun(*this, &PannerUI::pan_printer), pan_adjustments[asz])); - if (_session.midi_port()) { - _io.panner()[asz]->reset_midi_control (_session.midi_port(), true); - } - bc->set_name ("PanSlider"); - bc->set_shadow_type (GTK_SHADOW_NONE); + bc->set_shadow_type (Gtk::SHADOW_NONE); bc->set_style (BarController::Line); - bc->get_spin_button().signal_focus_in_event()().connect (mem_fun(*this, &PannerUI::entry_focus_event)); - bc->get_spin_button().signal_focus_out_event()().connect (mem_fun(*this, &PannerUI::entry_focus_event)); - bc->StartGesture.connect (bind (mem_fun (_io, &IO::start_pan_touch), (uint32_t) asz)); - bc->StopGesture.connect (bind (mem_fun (_io, &IO::end_pan_touch), (uint32_t) asz)); + bc->StartGesture.connect (bind (mem_fun (*_io, &IO::start_pan_touch), (uint32_t) asz)); + bc->StopGesture.connect (bind (mem_fun (*_io, &IO::end_pan_touch), (uint32_t) asz)); char buf[64]; - snprintf (buf, sizeof (buf), _("panner for channel %u"), asz + 1); + snprintf (buf, sizeof (buf), _("panner for channel %zu"), asz + 1); ARDOUR_UI::instance()->tooltips().set_tip (bc->event_widget(), buf); bc->event_widget().signal_button_release_event().connect @@ -385,13 +369,13 @@ PannerUI::setup_pan () } if (panner == 0) { - panner = new Panner2d (_io.panner(), w, 61); + panner = new Panner2d (_io->panner(), w, 61); panner->set_name ("MixerPanZone"); panner->show (); } update_pan_sensitive (); - panner->reset (_io.n_inputs()); + panner->reset (_io->n_inputs()); panner->set_size_request (w, 61); /* and finally, add it to the panner frame */ @@ -402,7 +386,7 @@ PannerUI::setup_pan () } } -gint +bool PannerUI::pan_button_event (GdkEventButton* ev, uint32_t which) { switch (ev->button) { @@ -413,13 +397,13 @@ PannerUI::pan_button_event (GdkEventButton* ev, uint32_t which) } build_pan_menu (which); pan_menu->popup (1, ev->time); - return TRUE; + return true; break; default: - return FALSE; + return false; } - return FALSE; // what's wrong with gcc? + return false; // what's wrong with gcc? } void @@ -434,17 +418,17 @@ PannerUI::build_pan_menu (uint32_t which) /* set state first, connect second */ - (dynamic_cast (items.back()))->set_active (_io.panner()[which]->muted()); - (dynamic_cast (items.back()))->toggled.connect + (dynamic_cast (&items.back()))->set_active (_io->panner()[which]->muted()); + (dynamic_cast (&items.back()))->signal_toggled().connect (bind (mem_fun(*this, &PannerUI::pan_mute), which)); items.push_back (CheckMenuElem (_("Bypass"), mem_fun(*this, &PannerUI::pan_bypass_toggle))); - bypass_menu_item = static_cast (items.back()); + bypass_menu_item = static_cast (&items.back()); /* set state first, connect second */ - bypass_menu_item->set_active (_io.panner().bypassed()); - bypass_menu_item->toggled.connect (mem_fun(*this, &PannerUI::pan_bypass_toggle)); + bypass_menu_item->set_active (_io->panner().bypassed()); + bypass_menu_item->signal_toggled().connect (mem_fun(*this, &PannerUI::pan_bypass_toggle)); items.push_back (MenuElem (_("Reset"), mem_fun(*this, &PannerUI::pan_reset))); items.push_back (SeparatorElem()); @@ -454,15 +438,15 @@ PannerUI::build_pan_menu (uint32_t which) void PannerUI::pan_mute (uint32_t which) { - StreamPanner* sp = _io.panner()[which]; + StreamPanner* sp = _io->panner()[which]; sp->set_muted (!sp->muted()); } void PannerUI::pan_bypass_toggle () { - if (bypass_menu_item && (_io.panner().bypassed() != bypass_menu_item->get_active())) { - _io.panner().set_bypassed (!_io.panner().bypassed()); + if (bypass_menu_item && (_io->panner().bypassed() != bypass_menu_item->get_active())) { + _io->panner().set_bypassed (!_io->panner().bypassed()); } } @@ -474,11 +458,11 @@ PannerUI::pan_reset () void PannerUI::effective_pan_display () { - if (_io.panner().empty()) { + if (_io->panner().empty()) { return; } - switch (_io.n_outputs()) { + switch (_io->n_outputs()) { case 0: case 1: /* relax */ @@ -501,18 +485,21 @@ PannerUI::pan_changed (void *src) return; } - switch (_io.panner().size()) { + switch (_io->panner().size()) { case 0: - panning_link_box.set_sensitive (false); + panning_link_direction_button.set_sensitive (false); + panning_link_button.set_sensitive (false); return; case 1: - panning_link_box.set_sensitive (false); + panning_link_direction_button.set_sensitive (false); + panning_link_button.set_sensitive (false); break; default: - panning_link_box.set_sensitive (true); + panning_link_direction_button.set_sensitive (true); + panning_link_button.set_sensitive (true); } - uint32_t nouts = _io.n_outputs(); + uint32_t nouts = _io->n_outputs(); switch (nouts) { case 0: @@ -533,11 +520,11 @@ PannerUI::pan_changed (void *src) void PannerUI::pan_adjustment_changed (uint32_t which) { - if (!in_pan_update && which < _io.panner().size()) { + if (!in_pan_update && which < _io->panner().size()) { float xpos; float val = pan_adjustments[which]->get_value (); - _io.panner()[which]->get_position (xpos); + _io->panner()[which]->get_position (xpos); /* add a kinda-sorta detent for the middle */ @@ -554,7 +541,7 @@ PannerUI::pan_adjustment_changed (uint32_t which) if (!Panner::equivalent (val, xpos)) { - _io.panner()[which]->set_position (val); + _io->panner()[which]->set_position (val); /* XXX the panner objects have no access to the session, so do this here. ick. @@ -569,11 +556,11 @@ PannerUI::pan_value_changed (uint32_t which) { ENSURE_GUI_THREAD (bind (mem_fun(*this, &PannerUI::pan_value_changed), which)); - if (which < _io.panner().size()) { + if (_io->n_outputs() > 1 && which < _io->panner().size()) { float xpos; float val = pan_adjustments[which]->get_value (); - _io.panner()[which]->get_position (xpos); + _io->panner()[which]->get_position (xpos); if (!Panner::equivalent (val, xpos)) { in_pan_update = true; @@ -599,14 +586,14 @@ PannerUI::update_pan_bars (bool only_if_aplay) float xpos, val; if (only_if_aplay) { - AutomationList& alist (_io.panner()[n]->automation()); + AutomationList& alist (_io->panner()[n]->automation()); if (!alist.automation_playback()) { continue; } } - _io.panner()[n]->get_effective_position (xpos); + _io->panner()[n]->get_effective_position (xpos); val = (*i)->get_value (); if (!Panner::equivalent (val, xpos)) { @@ -637,9 +624,9 @@ PannerUI::pan_printer (char *buf, uint32_t len, Adjustment* adj) void PannerUI::update_pan_sensitive () { - bool sensitive = !(_io.panner().automation_state() & Play); + bool sensitive = !(_io->panner().automation_state() & Play); - switch (_io.n_outputs()) { + switch (_io->n_outputs()) { case 0: case 1: break; @@ -656,3 +643,157 @@ PannerUI::update_pan_sensitive () } } +gint +PannerUI::pan_automation_state_button_event (GdkEventButton *ev) +{ + using namespace Menu_Helpers; + + if (ev->type == GDK_BUTTON_RELEASE) { + return TRUE; + } + + switch (ev->button) { + case 1: + pan_astate_menu.popup (1, ev->time); + break; + default: + break; + } + + return TRUE; +} + +gint +PannerUI::pan_automation_style_button_event (GdkEventButton *ev) +{ + if (ev->type == GDK_BUTTON_RELEASE) { + return TRUE; + } + + switch (ev->button) { + case 1: + pan_astyle_menu.popup (1, ev->time); + break; + default: + break; + } + return TRUE; +} + +void +PannerUI::pan_automation_style_changed () +{ + ENSURE_GUI_THREAD(mem_fun(*this, &PannerUI::pan_automation_style_changed)); + + switch (_width) { + case Wide: + pan_automation_style_button.set_label (astyle_string(_io->panner().automation_style())); + break; + case Narrow: + pan_automation_style_button.set_label (short_astyle_string(_io->panner().automation_style())); + break; + } +} + +void +PannerUI::pan_automation_state_changed () +{ + ENSURE_GUI_THREAD(mem_fun(*this, &PannerUI::pan_automation_state_changed)); + + bool x; + + switch (_width) { + case Wide: + pan_automation_state_button.set_label (astate_string(_io->panner().automation_state())); + break; + case Narrow: + pan_automation_state_button.set_label (short_astate_string(_io->panner().automation_state())); + break; + } + + /* when creating a new session, we get to create busses (and + sometimes tracks) with no outputs by the time they get + here. + */ + + if (_io->panner().empty()) { + return; + } + + x = (_io->panner().front()->automation().automation_state() != Off); + + if (pan_automation_state_button.get_active() != x) { + ignore_toggle = true; + pan_automation_state_button.set_active (x); + ignore_toggle = false; + } + + update_pan_sensitive (); + + /* start watching automation so that things move */ + + pan_watching.disconnect(); + + if (x) { + pan_watching = ARDOUR_UI::RapidScreenUpdate.connect (mem_fun (*this, &PannerUI::effective_pan_display)); + } +} + +string +PannerUI::astate_string (AutoState state) +{ + return _astate_string (state, false); +} + +string +PannerUI::short_astate_string (AutoState state) +{ + return _astate_string (state, true); +} + +string +PannerUI::_astate_string (AutoState state, bool shrt) +{ + string sstr; + + switch (state) { + case Off: + sstr = (shrt ? "O" : _("O")); + break; + case Play: + sstr = (shrt ? "P" : _("P")); + break; + case Touch: + sstr = (shrt ? "T" : _("T")); + break; + case Write: + sstr = (shrt ? "W" : _("W")); + break; + } + + return sstr; +} + +string +PannerUI::astyle_string (AutoStyle style) +{ + return _astyle_string (style, false); +} + +string +PannerUI::short_astyle_string (AutoStyle style) +{ + return _astyle_string (style, true); +} + +string +PannerUI::_astyle_string (AutoStyle style, bool shrt) +{ + if (style & Trim) { + return _("Trim"); + } else { + /* XXX it might different in different languages */ + + return (shrt ? _("Abs") : _("Abs")); + } +}