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.
25 #include <pbd/stl_delete.h>
26 #include <pbd/xml++.h>
27 #include <pbd/failed_constructor.h>
29 #include <gtkmm2ext/click_box.h>
30 #include <gtkmm2ext/fastmeter.h>
31 #include <gtkmm2ext/barcontroller.h>
32 #include <gtkmm2ext/utils.h>
33 #include <gtkmm2ext/doi.h>
34 #include <gtkmm2ext/slider_controller.h>
36 #include <midi++/manager.h>
38 #include <ardour/plugin.h>
39 #include <ardour/insert.h>
40 #include <ardour/ladspa_plugin.h>
42 #include <ardour/lv2_plugin.h>
47 #include "ardour_ui.h"
49 #include "plugin_ui.h"
51 #include "gui_thread.h"
56 using namespace ARDOUR
;
58 using namespace Gtkmm2ext
;
62 GenericPluginUI::GenericPluginUI (boost::shared_ptr
<PluginInsert
> pi
, bool scrollable
)
64 button_table (initial_button_rows
, initial_button_cols
),
65 output_table (initial_output_rows
, initial_output_cols
),
66 hAdjustment(0.0, 0.0, 0.0),
67 vAdjustment(0.0, 0.0, 0.0),
68 scroller_view(hAdjustment
, vAdjustment
),
70 is_scrollable(scrollable
)
72 set_name ("PluginEditor");
73 set_border_width (10);
74 set_homogeneous (false);
76 HBox
* constraint_hbox
= manage (new HBox
);
77 HBox
* smaller_hbox
= manage (new HBox
);
78 Label
* combo_label
= manage (new Label (_("<span size=\"large\">Presets</span>")));
79 combo_label
->set_use_markup (true);
81 smaller_hbox
->pack_start (*combo_label
, false, false, 10);
82 smaller_hbox
->pack_start (preset_combo
, false, false);
83 smaller_hbox
->pack_start (save_button
, false, false);
84 smaller_hbox
->pack_start (bypass_button
, false, true);
86 constraint_hbox
->set_spacing (5);
87 constraint_hbox
->set_homogeneous (false);
89 VBox
* v1_box
= manage (new VBox
);
90 VBox
* v2_box
= manage (new VBox
);
92 v1_box
->pack_start (*smaller_hbox
, false, true);
93 v2_box
->pack_start (focus_button
, false, true);
95 constraint_hbox
->pack_end (*v2_box
, false, false);
96 constraint_hbox
->pack_end (*v1_box
, false, false);
98 pack_start (*constraint_hbox
, false, false);
100 if ( is_scrollable
) {
101 scroller
.set_policy (Gtk::POLICY_AUTOMATIC
, Gtk::POLICY_AUTOMATIC
);
102 scroller
.set_name ("PluginEditor");
103 scroller_view
.set_name("PluginEditor");
104 scroller_view
.add (hpacker
);
105 scroller
.add (scroller_view
);
107 pack_start (scroller
, true, true);
111 pack_start (hpacker
, false, false);
117 GenericPluginUI::~GenericPluginUI ()
119 if (output_controls
.size() > 0) {
120 screen_update_connection
.disconnect();
125 GenericPluginUI::build ()
133 int output_row
, output_col
;
134 int button_row
, button_col
;
135 int output_rows
, output_cols
;
136 int button_rows
, button_cols
;
137 guint32 n_ins
=0, n_outs
= 0;
140 hpacker
.set_spacing (10);
142 output_rows
= initial_output_rows
;
143 output_cols
= initial_output_cols
;
144 button_rows
= initial_button_rows
;
145 button_cols
= initial_button_cols
;
151 button_table
.set_homogeneous (false);
152 button_table
.set_row_spacings (2);
153 button_table
.set_col_spacings (2);
154 output_table
.set_homogeneous (true);
155 output_table
.set_row_spacings (2);
156 output_table
.set_col_spacings (2);
157 button_table
.set_border_width (5);
158 output_table
.set_border_width (5);
160 hpacker
.set_border_width (10);
162 bt_frame
= manage (new Frame
);
163 bt_frame
->set_name ("BaseFrame");
164 bt_frame
->add (button_table
);
165 hpacker
.pack_start(*bt_frame
, true, true);
167 box
= manage (new VBox
);
168 box
->set_border_width (5);
169 box
->set_spacing (1);
171 frame
= manage (new Frame
);
172 frame
->set_name ("BaseFrame");
173 frame
->set_label (_("Controls"));
175 hpacker
.pack_start(*frame
, true, true);
177 /* find all ports. build control elements for all appropriate control ports */
179 for (i
= 0; i
< plugin
->parameter_count(); ++i
) {
181 if (plugin
->parameter_is_control (i
)) {
183 /* Don't show latency control ports */
185 if (plugin
->describe_parameter (i
) == X_("latency")) {
191 /* if we are scrollable, just use one long column */
193 if (!is_scrollable
) {
195 frame
= manage (new Frame
);
196 frame
->set_name ("BaseFrame");
197 box
= manage (new VBox
);
199 box
->set_border_width (5);
200 box
->set_spacing (1);
203 hpacker
.pack_start(*frame
,true,true);
209 if ((cui
= build_control_ui (i
, plugin
->get_nth_control (i
))) == 0) {
210 error
<< string_compose(_("Plugin Editor: could not build control element for port %1"), i
) << endmsg
;
214 if (cui
->control
|| cui
->clickbox
|| cui
->combo
) {
216 box
->pack_start (*cui
, false, false);
218 } else if (cui
->button
) {
220 if (button_row
== button_rows
) {
222 if (++button_col
== button_cols
) {
224 button_table
.resize (button_rows
, button_cols
);
228 button_table
.attach (*cui
, button_col
, button_col
+ 1, button_row
, button_row
+1,
232 } else if (cui
->display
) {
234 output_table
.attach (*cui
, output_col
, output_col
+ 1, output_row
, output_row
+1,
237 // TODO: The meters should be divided into multiple rows
239 if (++output_col
== output_cols
) {
241 output_table
.resize (output_rows
, output_cols
);
244 /* old code, which divides meters into
245 * columns first, rows later. New code divides into one row
247 if (output_row == output_rows) {
249 if (++output_col == output_cols) {
251 output_table.resize (output_rows, output_cols);
255 output_table.attach (*cui, output_col, output_col + 1, output_row, output_row+1,
262 /* HACK: ideally the preferred height would be queried from
263 the complete hpacker, but I can't seem to get that
264 information in time, so this is an estimation
272 n_ins
= plugin
->get_info()->n_inputs
;
273 n_outs
= plugin
->get_info()->n_outputs
;
275 if (box
->children().empty()) {
276 hpacker
.remove (*frame
);
279 if (button_table
.children().empty()) {
280 hpacker
.remove (*bt_frame
);
283 if (!output_table
.children().empty()) {
284 frame
= manage (new Frame
);
285 frame
->set_name ("BaseFrame");
286 frame
->add (output_table
);
287 hpacker
.pack_end (*frame
, true, true);
292 output_table
.show_all ();
293 button_table
.show_all ();
296 GenericPluginUI::ControlUI::ControlUI ()
297 : automate_button (X_("")) // force creation of a label
299 automate_button
.set_name ("PluginAutomateButton");
300 ARDOUR_UI::instance()->tooltips().set_tip (automate_button
, _("Automation control"));
302 /* XXX translators: use a string here that will be at least as long
303 as the longest automation label (see ::automation_state_changed()
304 below). be sure to include a descender.
307 set_size_request_to_display_given_text (*automate_button
.get_child(), _("Mgnual"), 5, 5);
318 GenericPluginUI::ControlUI::~ControlUI()
325 delete meterinfo
->meter
;
331 GenericPluginUI::automation_state_changed (ControlUI
* cui
)
333 /* update button label */
335 switch (insert
->get_port_automation_state (cui
->port_index
) & (Off
|Play
|Touch
|Write
)) {
337 cui
->automate_button
.set_label (_("Manual"));
340 cui
->automate_button
.set_label (_("Play"));
343 cui
->automate_button
.set_label (_("Write"));
346 cui
->automate_button
.set_label (_("Touch"));
349 cui
->automate_button
.set_label (_("???"));
355 static void integer_printer (char buf
[32], Adjustment
&adj
, void *arg
)
357 snprintf (buf
, 32, "%.0f", adj
.get_value());
361 GenericPluginUI::print_parameter (char *buf
, uint32_t len
, uint32_t param
)
363 plugin
->print_parameter (param
, buf
, len
);
366 GenericPluginUI::ControlUI
*
367 GenericPluginUI::build_control_ui (guint32 port_index
, PBD::Controllable
* mcontrol
)
370 ControlUI
* control_ui
;
371 Plugin::ParameterDescriptor desc
;
373 plugin
->get_parameter_descriptor (port_index
, desc
);
375 control_ui
= manage (new ControlUI ());
376 control_ui
->adjustment
= 0;
377 control_ui
->combo
= 0;
378 control_ui
->combo_map
= 0;
379 control_ui
->port_index
= port_index
;
380 control_ui
->update_pending
= false;
381 control_ui
->label
.set_text (desc
.label
);
382 control_ui
->label
.set_alignment (0.0, 0.5);
383 control_ui
->label
.set_name ("PluginParameterLabel");
385 control_ui
->set_spacing (5);
387 Gtk::Requisition
req (control_ui
->automate_button
.size_request());
389 if (plugin
->parameter_is_input (port_index
)) {
391 boost::shared_ptr
<LadspaPlugin
> lp
;
393 boost::shared_ptr
<LV2Plugin
> lv2p
;
395 if ((lp
= boost::dynamic_pointer_cast
<LadspaPlugin
>(plugin
)) != 0) {
397 // all LADPSA plugins have a numeric unique ID
398 uint32_t id
= atol (lp
->unique_id().c_str());
400 lrdf_defaults
* defaults
= lrdf_get_scale_values(id
, port_index
);
402 if (defaults
&& defaults
->count
> 0) {
404 control_ui
->combo
= new Gtk::ComboBoxText
;
405 //control_ui->combo->set_value_in_list(true, false);
406 set_popdown_strings (*control_ui
->combo
, setup_scale_values(port_index
, control_ui
));
407 control_ui
->combo
->signal_changed().connect (bind (mem_fun(*this, &GenericPluginUI::control_combo_changed
), control_ui
));
408 plugin
->ParameterChanged
.connect (bind (mem_fun (*this, &GenericPluginUI::parameter_changed
), control_ui
));
409 control_ui
->pack_start(control_ui
->label
, true, true);
410 control_ui
->pack_start(*control_ui
->combo
, false, true);
412 update_control_display(control_ui
);
414 lrdf_free_setting_values(defaults
);
419 } else if ((lv2p
= boost::dynamic_pointer_cast
<LV2Plugin
>(plugin
)) != 0) {
421 SLV2Port port
= lv2p
->slv2_port(port_index
);
422 SLV2ScalePoints points
= slv2_port_get_scale_points(lv2p
->slv2_plugin(), port
);
425 control_ui
->combo
= new Gtk::ComboBoxText
;
426 //control_ui->combo->set_value_in_list(true, false);
427 set_popdown_strings (*control_ui
->combo
, setup_scale_values(port_index
, control_ui
));
428 control_ui
->combo
->signal_changed().connect (bind (mem_fun(*this, &GenericPluginUI::control_combo_changed
), control_ui
));
429 plugin
->ParameterChanged
.connect (bind (mem_fun (*this, &GenericPluginUI::parameter_changed
), control_ui
));
430 control_ui
->pack_start(control_ui
->label
, true, true);
431 control_ui
->pack_start(*control_ui
->combo
, false, true);
433 update_control_display(control_ui
);
435 slv2_scale_points_free(points
);
445 control_ui
->button
= manage (new ToggleButton ());
446 control_ui
->button
->set_name ("PluginEditorButton");
447 control_ui
->button
->set_size_request (20, 20);
449 control_ui
->pack_start (control_ui
->label
, true, true);
450 control_ui
->pack_start (*control_ui
->button
, false, true);
451 //control_ui->pack_start (control_ui->automate_button, false, false);
453 if(plugin
->get_parameter (port_index
) > 0.5){
454 control_ui
->button
->set_active(true);
457 control_ui
->button
->signal_clicked().connect (bind (mem_fun(*this, &GenericPluginUI::control_port_toggled
), control_ui
));
459 plugin
->ParameterChanged
.connect (bind (mem_fun(*this, &GenericPluginUI::toggle_parameter_changed
), control_ui
));
464 control_ui
->adjustment
= new Adjustment (0, 0, 0, 0, 0);
466 /* XXX this code is not right yet, because it doesn't handle
467 the absence of bounds in any sensible fashion.
470 control_ui
->adjustment
->set_lower (desc
.lower
);
471 control_ui
->adjustment
->set_upper (desc
.upper
);
473 control_ui
->logarithmic
= desc
.logarithmic
;
474 if (control_ui
->logarithmic
) {
475 if (control_ui
->adjustment
->get_lower() == 0.0) {
476 control_ui
->adjustment
->set_lower (control_ui
->adjustment
->get_upper()/10000);
478 control_ui
->adjustment
->set_upper (log(control_ui
->adjustment
->get_upper()));
479 control_ui
->adjustment
->set_lower (log(control_ui
->adjustment
->get_lower()));
482 control_ui
->adjustment
->set_step_increment (desc
.step
);
483 control_ui
->adjustment
->set_page_increment (desc
.largestep
);
485 if (desc
.integer_step
) {
486 control_ui
->clickbox
= new ClickBox (control_ui
->adjustment
, "PluginUIClickBox");
487 Gtkmm2ext::set_size_request_to_display_given_text (*control_ui
->clickbox
, "g9999999", 2, 2);
488 control_ui
->clickbox
->set_print_func (integer_printer
, 0);
490 sigc::slot
<void,char*,uint32_t> pslot
= sigc::bind (mem_fun(*this, &GenericPluginUI::print_parameter
), (uint32_t) port_index
);
492 control_ui
->control
= new BarController (*control_ui
->adjustment
, *mcontrol
, pslot
);
493 control_ui
->control
->set_size_request (200, req
.height
);
494 control_ui
->control
->set_name (X_("PluginSlider"));
495 control_ui
->control
->set_style (BarController::LeftToRight
);
496 control_ui
->control
->set_use_parent (true);
498 control_ui
->control
->StartGesture
.connect (bind (mem_fun(*this, &GenericPluginUI::start_touch
), control_ui
));
499 control_ui
->control
->StopGesture
.connect (bind (mem_fun(*this, &GenericPluginUI::stop_touch
), control_ui
));
503 if (control_ui
->logarithmic
) {
504 control_ui
->adjustment
->set_value(log(plugin
->get_parameter(port_index
)));
506 control_ui
->adjustment
->set_value(plugin
->get_parameter(port_index
));
509 /* XXX memory leak: SliderController not destroyed by ControlUI
510 destructor, and manage() reports object hierarchy
514 control_ui
->pack_start (control_ui
->label
, true, true);
515 if (desc
.integer_step
) {
516 control_ui
->pack_start (*control_ui
->clickbox
, false, false);
518 control_ui
->pack_start (*control_ui
->control
, false, false);
521 control_ui
->pack_start (control_ui
->automate_button
, false, false);
522 control_ui
->adjustment
->signal_value_changed().connect (bind (mem_fun(*this, &GenericPluginUI::control_adjustment_changed
), control_ui
));
523 control_ui
->automate_button
.signal_clicked().connect (bind (mem_fun(*this, &GenericPluginUI::astate_clicked
), control_ui
, (uint32_t) port_index
));
525 automation_state_changed (control_ui
);
527 plugin
->ParameterChanged
.connect (bind (mem_fun(*this, &GenericPluginUI::parameter_changed
), control_ui
));
528 insert
->automation_list (port_index
).automation_state_changed
.connect
529 (bind (mem_fun(*this, &GenericPluginUI::automation_state_changed
), control_ui
));
531 } else if (plugin
->parameter_is_output (port_index
)) {
533 control_ui
->display
= manage (new EventBox
);
534 control_ui
->display
->set_name ("ParameterValueDisplay");
536 control_ui
->display_label
= manage (new Label
);
538 control_ui
->display_label
->set_name ("ParameterValueDisplay");
540 control_ui
->display
->add (*control_ui
->display_label
);
541 Gtkmm2ext::set_size_request_to_display_given_text (*control_ui
->display
, "-99,99", 2, 2);
543 control_ui
->display
->show_all ();
546 /* TODO: only make a meter if the port is Hinted for it */
548 MeterInfo
* info
= new MeterInfo(port_index
);
549 control_ui
->meterinfo
= info
;
551 info
->meter
= new FastMeter (5, 5, FastMeter::Vertical
);
553 info
->min_unbound
= desc
.min_unbound
;
554 info
->max_unbound
= desc
.max_unbound
;
556 info
->min
= desc
.lower
;
557 info
->max
= desc
.upper
;
559 control_ui
->vbox
= manage (new VBox
);
560 control_ui
->hbox
= manage (new HBox
);
562 control_ui
->label
.set_angle(90);
563 control_ui
->hbox
->pack_start (control_ui
->label
, false, false);
564 control_ui
->hbox
->pack_start (*info
->meter
, false, false);
566 control_ui
->vbox
->pack_start (*control_ui
->hbox
, false, false);
568 control_ui
->vbox
->pack_start (*control_ui
->display
, false, false);
570 control_ui
->pack_start (*control_ui
->vbox
);
572 control_ui
->meterinfo
->meter
->show_all();
573 control_ui
->meterinfo
->packed
= true;
575 output_controls
.push_back (control_ui
);
577 plugin
->ParameterChanged
.connect (bind (mem_fun(*this, &GenericPluginUI::parameter_changed
), control_ui
));
584 GenericPluginUI::start_touch (GenericPluginUI::ControlUI
* cui
)
586 insert
->automation_list (cui
->port_index
).start_touch ();
590 GenericPluginUI::stop_touch (GenericPluginUI::ControlUI
* cui
)
592 insert
->automation_list (cui
->port_index
).stop_touch ();
596 GenericPluginUI::astate_clicked (ControlUI
* cui
, uint32_t port
)
598 using namespace Menu_Helpers
;
600 if (automation_menu
== 0) {
601 automation_menu
= manage (new Menu
);
602 automation_menu
->set_name ("ArdourContextMenu");
605 MenuList
& items (automation_menu
->items());
608 items
.push_back (MenuElem (_("Manual"),
609 bind (mem_fun(*this, &GenericPluginUI::set_automation_state
), (AutoState
) Off
, cui
)));
610 items
.push_back (MenuElem (_("Play"),
611 bind (mem_fun(*this, &GenericPluginUI::set_automation_state
), (AutoState
) Play
, cui
)));
612 items
.push_back (MenuElem (_("Write"),
613 bind (mem_fun(*this, &GenericPluginUI::set_automation_state
), (AutoState
) Write
, cui
)));
614 items
.push_back (MenuElem (_("Touch"),
615 bind (mem_fun(*this, &GenericPluginUI::set_automation_state
), (AutoState
) Touch
, cui
)));
617 automation_menu
->popup (1, gtk_get_current_event_time());
621 GenericPluginUI::set_automation_state (AutoState state
, ControlUI
* cui
)
623 insert
->set_port_automation_state (cui
->port_index
, state
);
627 GenericPluginUI::control_adjustment_changed (ControlUI
* cui
)
629 if (cui
->ignore_change
) {
633 double value
= cui
->adjustment
->get_value();
635 if (cui
->logarithmic
) {
639 insert
->set_parameter (cui
->port_index
, (float) value
);
643 GenericPluginUI::toggle_parameter_changed (uint32_t abs_port_id
, float val
, ControlUI
* cui
)
645 if (!cui
->ignore_change
&& cui
->port_index
== abs_port_id
) {
647 cui
->button
->set_active (true);
649 cui
->button
->set_active (false);
655 GenericPluginUI::parameter_changed (uint32_t abs_port_id
, float val
, ControlUI
* cui
)
657 if (cui
->port_index
== abs_port_id
) {
658 if (!cui
->update_pending
) {
659 cui
->update_pending
= true;
660 Gtkmm2ext::UI::instance()->call_slot (bind (mem_fun(*this, &GenericPluginUI::update_control_display
), 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
= plugin
->get_parameter (cui
->port_index
);
674 cui
->ignore_change
++;
676 std::map
<string
,float>::iterator it
;
677 for (it
= cui
->combo_map
->begin(); it
!= cui
->combo_map
->end(); ++it
) {
678 if (it
->second
== val
) {
679 cui
->combo
->set_active_text(it
->first
);
684 if (cui
->logarithmic
) {
687 if (val
!= cui
->adjustment
->get_value()) {
688 cui
->adjustment
->set_value (val
);
691 cui
->ignore_change
--;
695 GenericPluginUI::control_port_toggled (ControlUI
* cui
)
697 cui
->ignore_change
++;
698 insert
->set_parameter (cui
->port_index
, cui
->button
->get_active());
699 cui
->ignore_change
--;
703 GenericPluginUI::control_combo_changed (ControlUI
* cui
)
705 if (!cui
->ignore_change
) {
706 string value
= cui
->combo
->get_active_text();
707 std::map
<string
,float> mapping
= *cui
->combo_map
;
708 insert
->set_parameter (cui
->port_index
, mapping
[value
]);
714 GenericPluginUI::start_updating (GdkEventAny
* ignored
)
716 if (output_controls
.size() > 0 ) {
717 screen_update_connection
.disconnect();
718 screen_update_connection
= ARDOUR_UI::instance()->RapidScreenUpdate
.connect
719 (mem_fun(*this, &GenericPluginUI::output_update
));
725 GenericPluginUI::stop_updating (GdkEventAny
* ignored
)
727 if (output_controls
.size() > 0 ) {
728 screen_update_connection
.disconnect();
734 GenericPluginUI::output_update ()
736 for (vector
<ControlUI
*>::iterator i
= output_controls
.begin(); i
!= output_controls
.end(); ++i
) {
737 float val
= plugin
->get_parameter ((*i
)->port_index
);
739 snprintf (buf
, sizeof(buf
), "%.2f", val
);
740 (*i
)->display_label
->set_text (buf
);
742 /* autoscaling for the meter */
743 if ((*i
)->meterinfo
&& (*i
)->meterinfo
->packed
) {
745 if (val
< (*i
)->meterinfo
->min
) {
746 if ((*i
)->meterinfo
->min_unbound
)
747 (*i
)->meterinfo
->min
= val
;
749 val
= (*i
)->meterinfo
->min
;
752 if (val
> (*i
)->meterinfo
->max
) {
753 if ((*i
)->meterinfo
->max_unbound
)
754 (*i
)->meterinfo
->max
= val
;
756 val
= (*i
)->meterinfo
->max
;
759 if ((*i
)->meterinfo
->max
> (*i
)->meterinfo
->min
) {
760 float lval
= (val
- (*i
)->meterinfo
->min
) / ((*i
)->meterinfo
->max
- (*i
)->meterinfo
->min
) ;
761 (*i
)->meterinfo
->meter
->set (lval
);
768 GenericPluginUI::setup_scale_values(guint32 port_index
, ControlUI
* cui
)
770 vector
<string
> enums
;
771 boost::shared_ptr
<LadspaPlugin
> lp
;
773 boost::shared_ptr
<LV2Plugin
> lv2p
;
776 if ((lp
= boost::dynamic_pointer_cast
<LadspaPlugin
>(plugin
)) != 0) {
777 // all LADPSA plugins have a numeric unique ID
778 uint32_t id
= atol (lp
->unique_id().c_str());
780 cui
->combo_map
= new std::map
<string
, float>;
781 lrdf_defaults
* defaults
= lrdf_get_scale_values(id
, port_index
);
783 for (uint32_t i
= 0; i
< defaults
->count
; ++i
) {
784 enums
.push_back(defaults
->items
[i
].label
);
785 pair
<string
, float> newpair
;
786 newpair
.first
= defaults
->items
[i
].label
;
787 newpair
.second
= defaults
->items
[i
].value
;
788 cui
->combo_map
->insert(newpair
);
791 lrdf_free_setting_values(defaults
);
795 } else if ((lv2p
= boost::dynamic_pointer_cast
<LV2Plugin
>(plugin
)) != 0) {
797 SLV2Port port
= lv2p
->slv2_port(port_index
);
798 SLV2ScalePoints points
= slv2_port_get_scale_points(lv2p
->slv2_plugin(), port
);
799 cui
->combo_map
= new std::map
<string
, float>;
801 for (unsigned i
=0; i
< slv2_scale_points_size(points
); ++i
) {
802 SLV2ScalePoint p
= slv2_scale_points_get_at(points
, i
);
803 SLV2Value label
= slv2_scale_point_get_label(p
);
804 SLV2Value value
= slv2_scale_point_get_value(p
);
805 if (label
&& (slv2_value_is_float(value
) || slv2_value_is_int(value
))) {
806 enums
.push_back(slv2_value_as_string(label
));
807 pair
<string
, float> newpair
;
808 newpair
.first
= slv2_value_as_string(label
);
809 newpair
.second
= slv2_value_as_float(value
);
810 cui
->combo_map
->insert(newpair
);
814 slv2_scale_points_free(points
);