2 Copyright (C) 2000 Paul Davis
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 2 of the License, or
7 (at your option) any later version.
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, write to the Free Software
16 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
21 #include "gtk2ardour-config.h"
29 #include "pbd/stl_delete.h"
30 #include "pbd/xml++.h"
31 #include "pbd/failed_constructor.h"
33 #include <gtkmm2ext/click_box.h>
34 #include <gtkmm2ext/fastmeter.h>
35 #include <gtkmm2ext/barcontroller.h>
36 #include <gtkmm2ext/utils.h>
37 #include <gtkmm2ext/doi.h>
38 #include <gtkmm2ext/slider_controller.h>
40 #include "midi++/manager.h"
42 #include "ardour/plugin.h"
43 #include "ardour/plugin_insert.h"
44 #include "ardour/ladspa_plugin.h"
46 #include "ardour/lv2_plugin.h"
48 #include "ardour/session.h"
52 #include "ardour_ui.h"
54 #include "plugin_ui.h"
56 #include "gui_thread.h"
57 #include "automation_controller.h"
62 using namespace ARDOUR
;
64 using namespace Gtkmm2ext
;
67 GenericPluginUI::GenericPluginUI (boost::shared_ptr
<PluginInsert
> pi
, bool scrollable
)
69 button_table (initial_button_rows
, initial_button_cols
),
70 output_table (initial_output_rows
, initial_output_cols
),
71 hAdjustment(0.0, 0.0, 0.0),
72 vAdjustment(0.0, 0.0, 0.0),
73 scroller_view(hAdjustment
, vAdjustment
),
75 is_scrollable(scrollable
)
77 set_name ("PluginEditor");
78 set_border_width (10);
79 //set_homogeneous (false);
81 pack_start (main_contents
, false, false);
82 settings_box
.set_homogeneous (false);
84 HBox
* constraint_hbox
= manage (new HBox
);
85 HBox
* smaller_hbox
= manage (new HBox
);
86 smaller_hbox
->set_spacing (4);
87 Label
* combo_label
= manage (new Label (_("<span size=\"large\">Presets</span>")));
88 combo_label
->set_use_markup (true);
90 latency_button
.add (latency_label
);
91 latency_button
.signal_clicked().connect (sigc::mem_fun (*this, &PlugUIBase::latency_button_clicked
));
94 smaller_hbox
->pack_start (latency_button
, false, false, 10);
95 smaller_hbox
->pack_start (_preset_box
, false, false);
96 smaller_hbox
->pack_start (add_button
, false, false);
97 smaller_hbox
->pack_start (save_button
, false, false);
98 smaller_hbox
->pack_start (delete_button
, false, false);
99 smaller_hbox
->pack_start (bypass_button
, false, true);
101 constraint_hbox
->set_spacing (5);
102 constraint_hbox
->set_homogeneous (false);
104 VBox
* v1_box
= manage (new VBox
);
105 VBox
* v2_box
= manage (new VBox
);
106 pack_end (plugin_analysis_expander
, true, true);
108 v1_box
->pack_start (*smaller_hbox
, false, true);
109 v2_box
->pack_start (focus_button
, false, true);
111 main_contents
.pack_start (settings_box
, false, false);
113 constraint_hbox
->pack_end (*v2_box
, false, false);
114 constraint_hbox
->pack_end (*v1_box
, false, false);
116 main_contents
.pack_start (*constraint_hbox
, false, false);
118 if ( is_scrollable
) {
119 scroller
.set_policy (Gtk::POLICY_AUTOMATIC
, Gtk::POLICY_AUTOMATIC
);
120 scroller
.set_name ("PluginEditor");
121 scroller_view
.set_name("PluginEditor");
122 scroller_view
.add (hpacker
);
123 scroller
.add (scroller_view
);
125 main_contents
.pack_start (scroller
, true, true);
129 main_contents
.pack_start (hpacker
, false, false);
132 pi
->ActiveChanged
.connect (active_connection
, invalidator (*this), boost::bind (&GenericPluginUI::processor_active_changed
, this, boost::weak_ptr
<Processor
>(pi
)), gui_context());
134 bypass_button
.set_active (!pi
->active());
139 GenericPluginUI::~GenericPluginUI ()
141 if (output_controls
.size() > 0) {
142 screen_update_connection
.disconnect();
147 GenericPluginUI::build ()
155 int output_row
, output_col
;
156 int button_row
, button_col
;
157 int output_rows
, output_cols
;
158 int button_rows
, button_cols
;
161 hpacker
.set_spacing (10);
163 output_rows
= initial_output_rows
;
164 output_cols
= initial_output_cols
;
165 button_rows
= initial_button_rows
;
166 button_cols
= initial_button_cols
;
172 button_table
.set_homogeneous (false);
173 button_table
.set_row_spacings (2);
174 button_table
.set_col_spacings (2);
175 output_table
.set_homogeneous (true);
176 output_table
.set_row_spacings (2);
177 output_table
.set_col_spacings (2);
178 button_table
.set_border_width (5);
179 output_table
.set_border_width (5);
181 hpacker
.set_border_width (10);
183 bt_frame
= manage (new Frame
);
184 bt_frame
->set_name ("BaseFrame");
185 bt_frame
->add (button_table
);
186 hpacker
.pack_start(*bt_frame
, true, true);
188 box
= manage (new VBox
);
189 box
->set_border_width (5);
190 box
->set_spacing (1);
192 frame
= manage (new Frame
);
193 frame
->set_name ("BaseFrame");
194 frame
->set_label (_("Controls"));
196 hpacker
.pack_start(*frame
, true, true);
198 /* find all ports. build control elements for all appropriate control ports */
200 for (i
= 0; i
< plugin
->parameter_count(); ++i
) {
202 if (plugin
->parameter_is_control (i
)) {
204 /* Don't show latency control ports */
206 if (plugin
->describe_parameter (Evoral::Parameter(PluginAutomation
, 0, i
)) == X_("latency")) {
212 /* if we are scrollable, just use one long column */
214 if (!is_scrollable
) {
216 frame
= manage (new Frame
);
217 frame
->set_name ("BaseFrame");
218 box
= manage (new VBox
);
220 box
->set_border_width (5);
221 box
->set_spacing (1);
224 hpacker
.pack_start(*frame
,true,true);
230 boost::shared_ptr
<ARDOUR::AutomationControl
> c
231 = boost::dynamic_pointer_cast
<ARDOUR::AutomationControl
>(
232 insert
->control(Evoral::Parameter(PluginAutomation
, 0, i
)));
234 if ((cui
= build_control_ui (i
, c
)) == 0) {
235 error
<< string_compose(_("Plugin Editor: could not build control element for port %1"), i
) << endmsg
;
239 if (cui
->controller
|| cui
->clickbox
|| cui
->combo
) {
241 box
->pack_start (*cui
, false, false);
243 } else if (cui
->button
) {
245 if (button_row
== button_rows
) {
247 if (++button_col
== button_cols
) {
249 button_table
.resize (button_rows
, button_cols
);
253 button_table
.attach (*cui
, button_col
, button_col
+ 1, button_row
, button_row
+1,
257 } else if (cui
->display
) {
259 output_table
.attach (*cui
, output_col
, output_col
+ 1, output_row
, output_row
+1,
262 // TODO: The meters should be divided into multiple rows
264 if (++output_col
== output_cols
) {
266 output_table
.resize (output_rows
, output_cols
);
269 /* old code, which divides meters into
270 * columns first, rows later. New code divides into one row
272 if (output_row == output_rows) {
274 if (++output_col == output_cols) {
276 output_table.resize (output_rows, output_cols);
280 output_table.attach (*cui, output_col, output_col + 1, output_row, output_row+1,
287 /* HACK: ideally the preferred height would be queried from
288 the complete hpacker, but I can't seem to get that
289 information in time, so this is an estimation
297 if (box
->children().empty()) {
298 hpacker
.remove (*frame
);
301 if (button_table
.children().empty()) {
302 hpacker
.remove (*bt_frame
);
305 if (!output_table
.children().empty()) {
306 frame
= manage (new Frame
);
307 frame
->set_name ("BaseFrame");
308 frame
->add (output_table
);
309 hpacker
.pack_end (*frame
, true, true);
314 output_table
.show_all ();
315 button_table
.show_all ();
318 GenericPluginUI::ControlUI::ControlUI ()
319 : automate_button (X_("")) // force creation of a label
321 automate_button
.set_name ("PluginAutomateButton");
322 ARDOUR_UI::instance()->set_tip (automate_button
, _("Automation control"));
324 /* XXX translators: use a string here that will be at least as long
325 as the longest automation label (see ::automation_state_changed()
326 below). be sure to include a descender.
329 set_size_request_to_display_given_text (automate_button
, _("Mgnual"), 15, 10);
338 GenericPluginUI::ControlUI::~ControlUI()
341 delete meterinfo
->meter
;
347 GenericPluginUI::automation_state_changed (ControlUI
* cui
)
349 /* update button label */
351 // don't lock to avoid deadlock because we're triggered by
352 // AutomationControl::Changed() while the automation lock is taken
353 switch (insert
->get_parameter_automation_state (cui
->parameter())
354 & (Off
|Play
|Touch
|Write
)) {
356 cui
->automate_button
.set_label (_("Manual"));
359 cui
->automate_button
.set_label (_("Play"));
362 cui
->automate_button
.set_label (_("Write"));
365 cui
->automate_button
.set_label (_("Touch"));
368 cui
->automate_button
.set_label (_("???"));
374 static void integer_printer (char buf
[32], Adjustment
&adj
, void */
*arg*/
)
376 snprintf (buf
, 32, "%.0f", adj
.get_value());
380 GenericPluginUI::print_parameter (char *buf
, uint32_t len
, uint32_t param
)
382 plugin
->print_parameter (param
, buf
, len
);
385 GenericPluginUI::ControlUI
*
386 GenericPluginUI::build_control_ui (guint32 port_index
, boost::shared_ptr
<AutomationControl
> mcontrol
)
388 ControlUI
* control_ui
= 0;
393 Plugin::ParameterDescriptor desc
;
395 plugin
->get_parameter_descriptor (port_index
, desc
);
397 control_ui
= manage (new ControlUI ());
398 control_ui
->combo
= 0;
399 control_ui
->combo_map
= 0;
400 control_ui
->control
= mcontrol
;
401 control_ui
->update_pending
= false;
402 control_ui
->label
.set_text (desc
.label
);
403 control_ui
->label
.set_alignment (0.0, 0.5);
404 control_ui
->label
.set_name ("PluginParameterLabel");
406 control_ui
->set_spacing (5);
408 Gtk::Requisition
req (control_ui
->automate_button
.size_request());
410 if (plugin
->parameter_is_input (port_index
)) {
412 boost::shared_ptr
<LadspaPlugin
> lp
;
414 boost::shared_ptr
<LV2Plugin
> lv2p
;
416 if ((lp
= boost::dynamic_pointer_cast
<LadspaPlugin
>(plugin
)) != 0) {
418 // FIXME: not all plugins have a numeric unique ID
419 uint32_t id
= atol (lp
->unique_id().c_str());
420 lrdf_defaults
* defaults
= lrdf_get_scale_values(id
, port_index
);
422 if (defaults
&& defaults
->count
> 0) {
424 control_ui
->combo
= new Gtk::ComboBoxText
;
425 //control_ui->combo->set_value_in_list(true, false);
426 set_popdown_strings (*control_ui
->combo
, setup_scale_values(port_index
, control_ui
));
427 control_ui
->combo
->signal_changed().connect (sigc::bind (sigc::mem_fun(*this, &GenericPluginUI::control_combo_changed
), control_ui
));
428 mcontrol
->Changed
.connect (control_connections
, invalidator (*this), boost::bind (&GenericPluginUI::ui_parameter_changed
, this, control_ui
), gui_context());
429 control_ui
->pack_start(control_ui
->label
, true, true);
430 control_ui
->pack_start(*control_ui
->combo
, false, true);
432 update_control_display(control_ui
);
434 lrdf_free_setting_values(defaults
);
439 } else if ((lv2p
= boost::dynamic_pointer_cast
<LV2Plugin
>(plugin
)) != 0) {
441 SLV2Port port
= lv2p
->slv2_port(port_index
);
442 SLV2ScalePoints points
= slv2_port_get_scale_points(lv2p
->slv2_plugin(), port
);
445 control_ui
->combo
= new Gtk::ComboBoxText
;
446 //control_ui->combo->set_value_in_list(true, false);
447 set_popdown_strings (*control_ui
->combo
, setup_scale_values(port_index
, control_ui
));
448 control_ui
->combo
->signal_changed().connect (sigc::bind (sigc::mem_fun(*this, &GenericPluginUI::control_combo_changed
), control_ui
));
449 mcontrol
->Changed
.connect (control_connections
, invalidator (*this), boost::bind (&GenericPluginUI::ui_parameter_changed
, this, control_ui
), gui_context());
450 control_ui
->pack_start(control_ui
->label
, true, true);
451 control_ui
->pack_start(*control_ui
->combo
, false, true);
453 update_control_display(control_ui
);
455 slv2_scale_points_free(points
);
465 control_ui
->button
= manage (new ToggleButton ());
466 control_ui
->button
->set_name ("PluginEditorButton");
467 control_ui
->button
->set_size_request (20, 20);
469 control_ui
->pack_start (control_ui
->label
, true, true);
470 control_ui
->pack_start (*control_ui
->button
, false, true);
471 control_ui
->pack_start (control_ui
->automate_button
, false, false);
473 control_ui
->button
->signal_clicked().connect (sigc::bind (sigc::mem_fun(*this, &GenericPluginUI::control_port_toggled
), control_ui
));
474 control_ui
->automate_button
.signal_clicked().connect (bind (mem_fun(*this, &GenericPluginUI::astate_clicked
), control_ui
, (uint32_t) port_index
));
476 mcontrol
->Changed
.connect (control_connections
, invalidator (*this), boost::bind (&GenericPluginUI::toggle_parameter_changed
, this, control_ui
), gui_context());
477 mcontrol
->alist()->automation_state_changed
.connect (control_connections
, invalidator (*this), boost::bind (&GenericPluginUI::automation_state_changed
, this, control_ui
), gui_context());
479 if (plugin
->get_parameter (port_index
) > 0.5){
480 control_ui
->button
->set_active(true);
483 automation_state_changed (control_ui
);
488 /* create the controller */
490 control_ui
->controller
= AutomationController::create(insert
, mcontrol
->parameter(), mcontrol
);
492 /* XXX this code is not right yet, because it doesn't handle
493 the absence of bounds in any sensible fashion.
496 Adjustment
* adj
= control_ui
->controller
->adjustment();
497 boost::shared_ptr
<PluginInsert::PluginControl
> pc
= boost::dynamic_pointer_cast
<PluginInsert::PluginControl
> (control_ui
->control
);
499 adj
->set_lower (pc
->user_to_ui (desc
.lower
));
500 adj
->set_upper (pc
->user_to_ui (desc
.upper
));
502 adj
->set_step_increment (desc
.step
);
503 adj
->set_page_increment (desc
.largestep
);
505 if (desc
.integer_step
) {
506 control_ui
->clickbox
= new ClickBox (adj
, "PluginUIClickBox");
507 Gtkmm2ext::set_size_request_to_display_given_text (*control_ui
->clickbox
, "g9999999", 2, 2);
508 control_ui
->clickbox
->set_print_func (integer_printer
, 0);
510 //sigc::slot<void,char*,uint32_t> pslot = sigc::bind (sigc::mem_fun(*this, &GenericPluginUI::print_parameter), (uint32_t) port_index);
512 control_ui
->controller
->set_size_request (200, req
.height
);
513 control_ui
->controller
->set_name (X_("PluginSlider"));
514 control_ui
->controller
->set_style (BarController::LeftToRight
);
515 control_ui
->controller
->set_use_parent (true);
516 control_ui
->controller
->set_logarithmic (desc
.logarithmic
);
518 control_ui
->controller
->StartGesture
.connect (sigc::bind (sigc::mem_fun(*this, &GenericPluginUI::start_touch
), control_ui
));
519 control_ui
->controller
->StopGesture
.connect (sigc::bind (sigc::mem_fun(*this, &GenericPluginUI::stop_touch
), control_ui
));
523 adj
->set_value (pc
->plugin_to_ui (plugin
->get_parameter (port_index
)));
525 /* XXX memory leak: SliderController not destroyed by ControlUI
526 destructor, and manage() reports object hierarchy
530 control_ui
->pack_start (control_ui
->label
, true, true);
531 if (desc
.integer_step
) {
532 control_ui
->pack_start (*control_ui
->clickbox
, false, false);
534 control_ui
->pack_start (*control_ui
->controller
, false, false);
537 control_ui
->pack_start (control_ui
->automate_button
, false, false);
538 control_ui
->automate_button
.signal_clicked().connect (sigc::bind (sigc::mem_fun(*this, &GenericPluginUI::astate_clicked
), control_ui
, (uint32_t) port_index
));
540 automation_state_changed (control_ui
);
542 mcontrol
->Changed
.connect (control_connections
, invalidator (*this), boost::bind (&GenericPluginUI::ui_parameter_changed
, this, control_ui
), gui_context());
543 mcontrol
->alist()->automation_state_changed
.connect (control_connections
, invalidator (*this), boost::bind (&GenericPluginUI::automation_state_changed
, this, control_ui
), gui_context());
545 input_controls
.push_back (control_ui
);
547 } else if (plugin
->parameter_is_output (port_index
)) {
549 control_ui
->display
= manage (new EventBox
);
550 control_ui
->display
->set_name ("ParameterValueDisplay");
552 control_ui
->display_label
= manage (new Label
);
554 control_ui
->display_label
->set_name ("ParameterValueDisplay");
556 control_ui
->display
->add (*control_ui
->display_label
);
557 Gtkmm2ext::set_size_request_to_display_given_text (*control_ui
->display
, "-99,99", 2, 2);
559 control_ui
->display
->show_all ();
562 /* TODO: only make a meter if the port is Hinted for it */
564 MeterInfo
* info
= new MeterInfo(port_index
);
565 control_ui
->meterinfo
= info
;
567 info
->meter
= new FastMeter (5, 5, FastMeter::Vertical
);
569 info
->min_unbound
= desc
.min_unbound
;
570 info
->max_unbound
= desc
.max_unbound
;
572 info
->min
= desc
.lower
;
573 info
->max
= desc
.upper
;
575 control_ui
->vbox
= manage (new VBox
);
576 control_ui
->hbox
= manage (new HBox
);
578 control_ui
->label
.set_angle(90);
579 control_ui
->hbox
->pack_start (control_ui
->label
, false, false);
580 control_ui
->hbox
->pack_start (*info
->meter
, false, false);
582 control_ui
->vbox
->pack_start (*control_ui
->hbox
, false, false);
584 control_ui
->vbox
->pack_start (*control_ui
->display
, false, false);
586 control_ui
->pack_start (*control_ui
->vbox
);
588 control_ui
->meterinfo
->meter
->show_all();
589 control_ui
->meterinfo
->packed
= true;
591 output_controls
.push_back (control_ui
);
594 mcontrol
->Changed
.connect (control_connections
, invalidator (*this), boost::bind (&GenericPluginUI::ui_parameter_changed
, this, control_ui
), gui_context());
600 GenericPluginUI::start_touch (GenericPluginUI::ControlUI
* cui
)
602 cui
->control
->start_touch (cui
->control
->session().transport_frame());
606 GenericPluginUI::stop_touch (GenericPluginUI::ControlUI
* cui
)
608 cui
->control
->stop_touch (false, cui
->control
->session().transport_frame());
612 GenericPluginUI::astate_clicked (ControlUI
* cui
, uint32_t /*port*/)
614 using namespace Menu_Helpers
;
616 if (automation_menu
== 0) {
617 automation_menu
= manage (new Menu
);
618 automation_menu
->set_name ("ArdourContextMenu");
621 MenuList
& items (automation_menu
->items());
624 items
.push_back (MenuElem (_("Manual"),
625 sigc::bind (sigc::mem_fun(*this, &GenericPluginUI::set_automation_state
), (AutoState
) Off
, cui
)));
626 items
.push_back (MenuElem (_("Play"),
627 sigc::bind (sigc::mem_fun(*this, &GenericPluginUI::set_automation_state
), (AutoState
) Play
, cui
)));
628 items
.push_back (MenuElem (_("Write"),
629 sigc::bind (sigc::mem_fun(*this, &GenericPluginUI::set_automation_state
), (AutoState
) Write
, cui
)));
630 items
.push_back (MenuElem (_("Touch"),
631 sigc::bind (sigc::mem_fun(*this, &GenericPluginUI::set_automation_state
), (AutoState
) Touch
, cui
)));
633 automation_menu
->popup (1, gtk_get_current_event_time());
637 GenericPluginUI::set_automation_state (AutoState state
, ControlUI
* cui
)
639 insert
->set_parameter_automation_state (cui
->parameter(), state
);
643 GenericPluginUI::toggle_parameter_changed (ControlUI
* cui
)
645 float val
= cui
->control
->get_value();
647 if (!cui
->ignore_change
) {
649 cui
->button
->set_active (true);
651 cui
->button
->set_active (false);
657 GenericPluginUI::ui_parameter_changed (ControlUI
* cui
)
659 if (!cui
->update_pending
) {
660 cui
->update_pending
= true;
661 Gtkmm2ext::UI::instance()->call_slot (MISSING_INVALIDATOR
, boost::bind (&GenericPluginUI::update_control_display
, this, cui
));
666 GenericPluginUI::update_control_display (ControlUI
* cui
)
668 /* XXX how do we handle logarithmic stuff here ? */
670 cui
->update_pending
= false;
672 float val
= cui
->control
->get_value();
674 cui
->ignore_change
++;
677 std::map
<string
,float>::iterator it
;
678 for (it
= cui
->combo_map
->begin(); it
!= cui
->combo_map
->end(); ++it
) {
679 if (it
->second
== val
) {
680 cui
->combo
->set_active_text(it
->first
);
684 } else if (cui
->button
) {
687 cui
->button
->set_active (true);
689 cui
->button
->set_active (false);
693 if( cui
->controller
) {
694 cui
->controller
->display_effective_value();
699 if (cui->logarithmic) {
702 if (val != cui->adjustment->get_value()) {
703 cui->adjustment->set_value (val);
706 cui
->ignore_change
--;
710 GenericPluginUI::control_port_toggled (ControlUI
* cui
)
712 cui
->ignore_change
++;
713 insert
->automation_control (cui
->parameter())->set_value (cui
->button
->get_active());
714 cui
->ignore_change
--;
718 GenericPluginUI::control_combo_changed (ControlUI
* cui
)
720 if (!cui
->ignore_change
) {
721 string value
= cui
->combo
->get_active_text();
722 std::map
<string
,float> mapping
= *cui
->combo_map
;
723 insert
->automation_control(cui
->parameter())->set_value(mapping
[value
]);
728 GenericPluginUI::processor_active_changed (boost::weak_ptr
<Processor
> weak_processor
)
730 ENSURE_GUI_THREAD (*this, &GenericPluginUI::processor_active_changed
, weak_processor
)
732 boost::shared_ptr
<Processor
> processor
= weak_processor
.lock();
734 bypass_button
.set_active (!processor
|| !processor
->active());
738 GenericPluginUI::start_updating (GdkEventAny
*)
740 if (output_controls
.size() > 0 ) {
741 screen_update_connection
.disconnect();
742 screen_update_connection
= ARDOUR_UI::instance()->RapidScreenUpdate
.connect
743 (sigc::mem_fun(*this, &GenericPluginUI::output_update
));
749 GenericPluginUI::stop_updating (GdkEventAny
*)
751 for (vector
<ControlUI
*>::iterator i
= input_controls
.begin(); i
!= input_controls
.end(); ++i
) {
752 (*i
)->controller
->stop_updating ();
755 if (output_controls
.size() > 0 ) {
756 screen_update_connection
.disconnect();
763 GenericPluginUI::output_update ()
765 for (vector
<ControlUI
*>::iterator i
= output_controls
.begin(); i
!= output_controls
.end(); ++i
) {
766 float val
= plugin
->get_parameter ((*i
)->parameter().id());
768 snprintf (buf
, sizeof(buf
), "%.2f", val
);
769 (*i
)->display_label
->set_text (buf
);
771 /* autoscaling for the meter */
772 if ((*i
)->meterinfo
&& (*i
)->meterinfo
->packed
) {
774 if (val
< (*i
)->meterinfo
->min
) {
775 if ((*i
)->meterinfo
->min_unbound
)
776 (*i
)->meterinfo
->min
= val
;
778 val
= (*i
)->meterinfo
->min
;
781 if (val
> (*i
)->meterinfo
->max
) {
782 if ((*i
)->meterinfo
->max_unbound
)
783 (*i
)->meterinfo
->max
= val
;
785 val
= (*i
)->meterinfo
->max
;
788 if ((*i
)->meterinfo
->max
> (*i
)->meterinfo
->min
) {
789 float lval
= (val
- (*i
)->meterinfo
->min
) / ((*i
)->meterinfo
->max
- (*i
)->meterinfo
->min
) ;
790 (*i
)->meterinfo
->meter
->set (lval
);
797 GenericPluginUI::setup_scale_values(guint32 port_index
, ControlUI
* cui
)
799 vector
<string
> enums
;
800 boost::shared_ptr
<LadspaPlugin
> lp
;
802 boost::shared_ptr
<LV2Plugin
> lv2p
;
805 if ((lp
= boost::dynamic_pointer_cast
<LadspaPlugin
>(plugin
)) != 0) {
806 // all LADPSA plugins have a numeric unique ID
807 uint32_t id
= atol (lp
->unique_id().c_str());
809 cui
->combo_map
= new std::map
<string
, float>;
810 lrdf_defaults
* defaults
= lrdf_get_scale_values(id
, port_index
);
812 for (uint32_t i
= 0; i
< defaults
->count
; ++i
) {
813 enums
.push_back(defaults
->items
[i
].label
);
814 pair
<string
, float> newpair
;
815 newpair
.first
= defaults
->items
[i
].label
;
816 newpair
.second
= defaults
->items
[i
].value
;
817 cui
->combo_map
->insert(newpair
);
820 lrdf_free_setting_values(defaults
);
824 } else if ((lv2p
= boost::dynamic_pointer_cast
<LV2Plugin
>(plugin
)) != 0) {
826 SLV2Port port
= lv2p
->slv2_port(port_index
);
827 SLV2ScalePoints points
= slv2_port_get_scale_points(lv2p
->slv2_plugin(), port
);
828 cui
->combo_map
= new std::map
<string
, float>;
830 for (unsigned i
=0; i
< slv2_scale_points_size(points
); ++i
) {
831 SLV2ScalePoint p
= slv2_scale_points_get_at(points
, i
);
832 SLV2Value label
= slv2_scale_point_get_label(p
);
833 SLV2Value value
= slv2_scale_point_get_value(p
);
834 if (label
&& (slv2_value_is_float(value
) || slv2_value_is_int(value
))) {
835 enums
.push_back(slv2_value_as_string(label
));
836 pair
<string
, float> newpair
;
837 newpair
.first
= slv2_value_as_string(label
);
838 newpair
.second
= slv2_value_as_float(value
);
839 cui
->combo_map
->insert(newpair
);
843 slv2_scale_points_free(points
);