LV2 Toolkit  1.2.0
ui.hpp
1 /*
2  ui.hpp - Wrapper library to make it easier to write LV2 UIs in C++
3  Copyright (C) 2012 Michael Fisher <mfisher31@gmail.com>
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 3 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., 51 Franklin Street, Fifth Floor,
18  Boston, MA 02110-1301 USA
19 */
20 
21 #ifndef LVTK_UI_HPP
22 #define LVTK_UI_HPP
23 
24 #include <cstdlib>
25 #include <cstring>
26 #include <iomanip>
27 #include <iostream>
28 #include <map>
29 
30 #include <lv2/lv2plug.in/ns/extensions/ui/ui.h>
31 
32 #include <lvtk/feature.hpp>
33 #include <lvtk/ext/common.h>
34 #include <lvtk/ext/data_access.hpp>
35 #include <lvtk/ext/instance_access.hpp>
36 
37 #include "private/debug.hpp"
38 #include "private/ui_features.hpp"
39 
40 namespace lvtk
41 {
42 
44  #define widget_cast(w) reinterpret_cast<LV2UI_Widget*> (w)
45 
47  class UIDescList : public std::vector<LV2UI_Descriptor>
48  {
49  public:
50  ~UIDescList();
51  };
52 
56  UIDescList&
57  get_lv2g2g_descriptors();
58 
89  template<class Derived, class Ext1 = end, class Ext2 = end,
90  class Ext3 = end, class Ext4 = end, class Ext5 = end,
91  class Ext6 = end, class Ext7 = end, class Ext8 = end,
92  class Ext9 = end>
93  class UI : public MixinTree<Derived, Ext1, Ext2, Ext3, Ext4, Ext5, Ext6,
94  Ext7, Ext8, Ext9>
95  {
96  public:
97 
101  inline
102  UI()
103  {
104  m_ctrl = s_ctrl;
105  m_wfunc = s_wfunc;
106  m_features = s_features;
107  m_bundle_path = s_bundle_path;
108  s_ctrl = 0;
109  s_wfunc = 0;
110  s_features = 0;
111  s_bundle_path = 0;
112  if (m_features)
113  {
114  FeatureHandlerMap hmap;
115  Derived::map_feature_handlers(hmap);
116  for (const lvtk::Feature* const * iter = m_features;
117  *iter != 0; ++iter)
118  {
119  FeatureHandlerMap::iterator miter;
120  miter = hmap.find((*iter)->URI);
121  if (miter != hmap.end())
122  {
123  miter->second(static_cast<Derived*>(this),
124  (*iter)->data);
125  }
126  }
127  }
128  }
129 
132  inline void
133  port_event(uint32_t port, uint32_t buffer_size, uint32_t format,
134  void const* buffer)
135  {
136  }
137 
143  static int
144  register_class(char const* uri)
145  {
146  LV2UI_Descriptor desc;
147  std::memset(&desc, 0, sizeof(LV2UI_Descriptor));
148  desc.URI = strdup(uri);
149  desc.instantiate = &Derived::create_ui_instance;
150  desc.cleanup = &Derived::delete_ui_instance;
151  desc.port_event = &Derived::_port_event;
152  desc.extension_data = &Derived::extension_data;
153 
154  get_lv2g2g_descriptors().push_back(desc);
155  return get_lv2g2g_descriptors().size() - 1;
156  }
157 
158  protected:
159 
164  inline void
165  write(uint32_t port, uint32_t buffer_size, uint32_t format,
166  void const* buffer)
167  {
168  (*m_wfunc)(m_ctrl, port, buffer_size, format, buffer);
169  }
170 
172  inline void
173  write_control(uint32_t port, float value)
174  {
175  write(port, sizeof(float), 0, &value);
176  }
177 
183  inline Feature const* const *
185  {
186  return m_features;
187  }
188 
190  inline char const*
191  bundle_path() const
192  {
193  return m_bundle_path;
194  }
195 
196  public:
202  inline void*
204  {
205  return m_ctrl;
206  }
207 
208  private:
209 
210  // This is quite ugly but needed to allow these mixins to call
211  // protected functions in the UI class, which we want.
212 #if defined (LVTK_EXTRAS_ENABLED)
213  friend class WriteMIDI<true>::I<Derived>;
214  friend class WriteMIDI<false>::I<Derived>;
215  friend class WriteOSC<true>::I<Derived>;
216  friend class WriteOSC<false>::I<Derived>;
217 #endif
218 
224  static LV2UI_Handle
225  create_ui_instance (LV2UI_Descriptor const* descriptor,
226  char const* plugin_uri, char const* bundle_path,
227  LV2UI_Write_Function write_func, LV2UI_Controller ctrl,
228  LV2UI_Widget* widget, LV2_Feature const* const * features)
229  {
230  /* Copy some data to static variables so the subclasses don't have to
231  bother with it - this is threadsafe since hosts are not allowed
232  to instantiate the same plugin concurrently */
233  s_ctrl = ctrl;
234  s_wfunc = write_func;
235  s_features = features;
236  s_bundle_path = bundle_path;
237 
239  if (LVTK_DEBUG)
240  {
241  std::clog << "[LV2::UI] Creating UI...\n\n"
242  << " Plugin URI: \"" << plugin_uri << "\"\n"
243  << " Bundle path: \"" << bundle_path << "\"\n"
244  << " UI Features:\n";
245  lvtk::Feature const* const * iter;
246  for (iter = features; *iter; ++iter)
247  std::clog << " \"" << (*iter)->URI << "\"\n";
248  }
249 
250  // create the UI object
251  if (LVTK_DEBUG)
252  std::clog << " Creating LV2 Widget..." << std::endl;
253  Derived* ui = new Derived(plugin_uri);
254  *widget = ui->widget();
255 
257  if (ui->check_ok() && *widget != NULL)
258  {
259  return reinterpret_cast<LV2UI_Handle>(ui);
260  }
261 
262  delete ui;
263  return 0;
264  }
265 
271  static void
272  delete_ui_instance(LV2UI_Handle instance)
273  {
274  delete static_cast<Derived*>(instance);
275  }
276 
281  static void
282  _port_event(LV2UI_Handle instance, uint32_t port,
283  uint32_t buffer_size, uint32_t format, void const* buffer)
284  {
285  static_cast<Derived*>(instance)->port_event(port, buffer_size,
286  format, buffer);
287  }
288 
289  void* m_ctrl;
290  LV2UI_Write_Function m_wfunc;
291  lvtk::Feature const* const * m_features;
292  char const* m_bundle_path;
293 
294  static void* s_ctrl;
295  static LV2UI_Write_Function s_wfunc;
296  static lvtk::Feature const* const * s_features;
297  static char const* s_bundle_path;
298 
299  };
300 
301  /* Yes, static variables are messy. */
302  template<class Derived, class Ext1, class Ext2, class Ext3, class Ext4,
303  class Ext5, class Ext6, class Ext7, class Ext8, class Ext9>
305  0;
306 
307  template<class Derived, class Ext1, class Ext2, class Ext3, class Ext4,
308  class Ext5, class Ext6, class Ext7, class Ext8, class Ext9>
309  LV2UI_Write_Function UI<Derived, Ext1, Ext2, Ext3, Ext4, Ext5, Ext6,
310  Ext7, Ext8, Ext9>::s_wfunc = 0;
311 
312  template<class Derived, class Ext1, class Ext2, class Ext3, class Ext4,
313  class Ext5, class Ext6, class Ext7, class Ext8, class Ext9>
314  lvtk::Feature const* const * UI<Derived, Ext1, Ext2, Ext3, Ext4, Ext5,
315  Ext6, Ext7, Ext8, Ext9>::s_features = 0;
316 
317  template<class Derived, class Ext1, class Ext2, class Ext3, class Ext4,
318  class Ext5, class Ext6, class Ext7, class Ext8, class Ext9>
319  char const* UI<Derived, Ext1, Ext2, Ext3, Ext4, Ext5, Ext6, Ext7, Ext8,
320  Ext9>::s_bundle_path = 0;
321 
322 }
323 
324 #endif /* LVTK_UI_HPP */
Definition: ui.hpp:47
void write_control(uint32_t port, float value)
Definition: ui.hpp:173
void write(uint32_t port, uint32_t buffer_size, uint32_t format, void const *buffer)
Definition: ui.hpp:165
Definition: write_midi.hpp:44
void * controller()
Definition: ui.hpp:203
LV2_Feature Feature
Definition: feature.hpp:41
static int register_class(char const *uri)
Definition: ui.hpp:144
Definition: feature.hpp:34
void port_event(uint32_t port, uint32_t buffer_size, uint32_t format, void const *buffer)
Definition: ui.hpp:133
Definition: ui.hpp:93
Feature const *const * features()
Definition: ui.hpp:184
map< string, FeatureHandler > FeatureHandlerMap
Definition: feature.hpp:57
char const * bundle_path() const
Definition: ui.hpp:191