Apply LV2 changes from 2.0.
[ardour.git] / gtk2_ardour / lv2_plugin_ui.cc
1 /*
2     Copyright (C) 2008 Paul Davis 
3     Author: Dave Robillard
4
5     This program is free software; you can redistribute it and/or modify
6     it under the terms of the GNU General Public License as published by
7     the Free Software Foundation; either version 2 of the License, or
8     (at your option) any later version.
9
10     This program is distributed in the hope that it will be useful,
11     but WITHOUT ANY WARRANTY; without even the implied warranty of
12     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13     GNU General Public License for more details.
14
15     You should have received a copy of the GNU General Public License
16     along with this program; if not, write to the Free Software
17     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18
19 */
20
21 #include <ardour/processor.h>
22 #include <ardour/lv2_plugin.h>
23
24 #include "ardour_ui.h"
25 #include "lv2_plugin_ui.h"
26
27 using namespace Gtk;
28 using namespace ARDOUR;
29 using namespace PBD;
30
31 void
32 LV2PluginUI::lv2_ui_write(LV2UI_Controller controller,
33              uint32_t         port_index,
34              uint32_t         buffer_size,
35              uint32_t         format,
36              const void*      buffer)
37 {
38         LV2PluginUI* me = (LV2PluginUI*)controller;
39         if (*(float*)buffer != me->_values[port_index])
40                 me->_lv2->set_parameter(port_index, *(float*)buffer);
41 }
42
43 void
44 LV2PluginUI::parameter_changed (uint32_t port_index, float val)
45 {
46         if (val != _values[port_index]) {
47                 const LV2UI_Descriptor* ui_desc = slv2_ui_instance_get_descriptor(_inst);
48                 LV2UI_Handle ui_handle = slv2_ui_instance_get_handle(_inst);
49                 if (ui_desc->port_event)
50                         ui_desc->port_event(ui_handle, port_index, 4, 0, &val);
51                 _values[port_index] = val;
52         }
53 }
54
55 bool
56 LV2PluginUI::start_updating(GdkEventAny* event)
57 {
58         if (!_output_ports.empty()) {
59                 _screen_update_connection.disconnect();
60                 _screen_update_connection = ARDOUR_UI::instance()->RapidScreenUpdate.connect 
61                         (mem_fun(*this, &LV2PluginUI::output_update));
62         }
63         return false;
64 }
65
66 bool
67 LV2PluginUI::stop_updating(GdkEventAny* event)
68 {
69         if (!_output_ports.empty()) {
70                 _screen_update_connection.disconnect();
71         }
72         return false;
73 }
74
75 void
76 LV2PluginUI::output_update()
77 {
78         /* FIXME only works with control output ports (which is all we support now anyway) */
79         uint32_t nports = _output_ports.size();
80         for (uint32_t i = 0; i < nports; ++i) {
81                 uint32_t index = _output_ports[i];
82                 parameter_changed(index, _lv2->get_parameter(index));
83         }
84         
85 }
86
87 LV2PluginUI::LV2PluginUI (boost::shared_ptr<PluginInsert> pi, boost::shared_ptr<LV2Plugin> lv2p)
88         : PlugUIBase (pi)
89         , _lv2(lv2p)
90 {
91         _inst = slv2_ui_instantiate(
92                         _lv2->slv2_plugin(), _lv2->slv2_ui(), LV2PluginUI::lv2_ui_write, this,
93                         _lv2->features());
94                         
95         uint32_t num_ports = slv2_plugin_get_num_ports(lv2p->slv2_plugin());
96         for (uint32_t i = 0; i < num_ports; ++i) {
97                 if (lv2p->parameter_is_output(i) && lv2p->parameter_is_control(i) && is_update_wanted(i)) {
98                         _output_ports.push_back(i);
99                 }
100         }
101         
102         GtkWidget* c_widget = (GtkWidget*)slv2_ui_instance_get_widget(_inst);
103         _gui_widget = Glib::wrap(c_widget);
104         _gui_widget->show_all();
105         pack_start(*_gui_widget, true, true);
106         
107         _values = new float[num_ports];
108         for (uint32_t i = 0; i < num_ports; ++i) {
109                 bool ok;
110                 _values[i] = lv2p->nth_parameter(i, ok);
111                 if (ok)
112                         lv2_ui_write(this, i, 4, /* FIXME: format */0, &_values[i]);
113         }
114                 
115         _lv2->ParameterChanged.connect(mem_fun(*this, &LV2PluginUI::parameter_changed));
116 }
117
118 LV2PluginUI::~LV2PluginUI ()
119 {
120         delete[] _values;
121         // plugin destructor destroys the GUI
122 }
123
124 int
125 LV2PluginUI::get_preferred_height ()
126 {
127         Gtk::Requisition r = size_request();
128         return r.height;
129 }
130
131 int
132 LV2PluginUI::get_preferred_width ()
133 {
134         Gtk::Requisition r = size_request();
135         return r.width;
136 }
137
138 int
139 LV2PluginUI::package (Gtk::Window& win)
140 {
141         /* forward configure events to plugin window */
142         win.signal_configure_event().connect (mem_fun (*this, &LV2PluginUI::configure_handler));
143         win.signal_map_event().connect (mem_fun (*this, &LV2PluginUI::start_updating));
144         win.signal_unmap_event().connect (mem_fun (*this, &LV2PluginUI::stop_updating));
145         return 0;
146 }
147
148 bool
149 LV2PluginUI::configure_handler (GdkEventConfigure* ev)
150 {
151         cout << "CONFIGURE" << endl;
152         return false;
153 }
154
155 bool
156 LV2PluginUI::is_update_wanted(uint32_t index)
157 {
158         /* FIXME this should check the port notification properties, which nobody sets now anyway :) */
159         return true;
160 }