00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025 #ifndef LV2GUI_HPP
00026 #define LV2GUI_HPP
00027
00028 #include <cstdlib>
00029 #include <cstring>
00030 #include <map>
00031
00032 #include <gtkmm/box.h>
00033 #include <gtkmm/main.h>
00034 #include <gtkmm/widget.h>
00035
00036 #include <lv2_ui.h>
00037 #include <lv2_ui_presets.h>
00038 #include <lv2_uri_map.h>
00039 #include <lv2_event_helpers.h>
00040 #include <lv2_osc.h>
00041 #include <lv2types.hpp>
00042
00043
00044 namespace LV2 {
00045
00046
00049 typedef std::vector<LV2UI_Descriptor*> GUIDescList;
00050
00051
00055 GUIDescList& get_lv2g2g_descriptors();
00056
00057
00104 template <bool Required = true>
00105 struct NoUserResize {
00106
00111 template <class Derived> struct I : public Extension<Required> {
00112
00114 static void map_feature_handlers(FeatureHandlerMap& hmap) {
00115 hmap["http://ll-plugins.nongnu.org/lv2/dev/ui#noUserResize"] =
00116 &I<Derived>::handle_feature;
00117 }
00118
00120 static void handle_feature(void* instance, void* data) {
00121 Derived* d = reinterpret_cast<Derived*>(instance);
00122 I<Derived>* e = static_cast<I<Derived>*>(d);
00123 e->m_ok = true;
00124 }
00125
00126 };
00127
00128 };
00129
00130
00140 template <bool Required = true>
00141 struct FixedSize {
00142
00147 template <class Derived> struct I : public Extension<Required> {
00148
00150 static void map_feature_handlers(FeatureHandlerMap& hmap) {
00151 hmap["http://ll-plugins.nongnu.org/lv2/dev/ui#fixedSize"] =
00152 &I<Derived>::handle_feature;
00153 }
00154
00156 static void handle_feature(void* instance, void* data) {
00157 Derived* d = reinterpret_cast<Derived*>(instance);
00158 I<Derived>* e = static_cast<I<Derived>*>(d);
00159 e->m_ok = true;
00160 }
00161
00162 };
00163
00164 };
00165
00166
00175 template <bool Required = true>
00176 struct Presets {
00177
00182 template <class Derived> struct I : public Extension<Required> {
00183
00185 I() : m_hdesc(0), m_host_support(false) { }
00186
00188 static void map_feature_handlers(FeatureHandlerMap& hmap) {
00189 hmap[LV2_UI_PRESETS_URI] = &I<Derived>::handle_feature;
00190 }
00191
00193 static void handle_feature(void* instance, void* data) {
00194 Derived* d = reinterpret_cast<Derived*>(instance);
00195 I<Derived>* e = static_cast<I<Derived>*>(d);
00196 e->m_hdesc = static_cast<LV2UI_Presets_Feature*>(data);
00197 e->m_ok = (e->m_hdesc != 0);
00198 e->m_host_support = (e->m_hdesc != 0);
00199 }
00200
00201
00207 void preset_added(uint32_t number,
00208 char const* name) {
00209
00210 }
00211
00216 void preset_removed(uint32_t number) {
00217
00218 }
00219
00223 void presets_cleared() {
00224
00225 }
00226
00233 void current_preset_changed(uint32_t number) {
00234
00235 }
00236
00240 static void const* extension_data(char const* uri) {
00241 static LV2UI_Presets_GDesc desc = { &_preset_added,
00242 &_preset_removed,
00243 &_presets_cleared,
00244 &_current_preset_changed };
00245 if (!std::strcmp(uri, LV2_UI_PRESETS_URI))
00246 return &desc;
00247 return 0;
00248 }
00249
00250 protected:
00251
00254 void change_preset(uint32_t preset) {
00255 if (m_hdesc)
00256 m_hdesc->change_preset(static_cast<Derived*>(this)->controller(),
00257 preset);
00258 }
00259
00263 void save_preset(uint32_t preset, char const* name) {
00264 if (m_hdesc)
00265 m_hdesc->save_preset(static_cast<Derived*>(this)->controller(),
00266 preset, name);
00267 }
00268
00271 bool host_supports_presets() const {
00272 return m_host_support;
00273 }
00274
00275 private:
00276
00277 static void _preset_added(LV2UI_Handle gui,
00278 uint32_t number,
00279 char const* name) {
00280 static_cast<Derived*>(gui)->preset_added(number, name);
00281 }
00282
00283 static void _preset_removed(LV2UI_Handle gui,
00284 uint32_t number) {
00285 static_cast<Derived*>(gui)->preset_removed(number);
00286 }
00287
00288 static void _presets_cleared(LV2UI_Handle gui) {
00289 static_cast<Derived*>(gui)->presets_cleared();
00290 }
00291
00292 static void _current_preset_changed(LV2UI_Handle gui,
00293 uint32_t number) {
00294 static_cast<Derived*>(gui)->current_preset_changed(number);
00295 }
00296
00297
00298 LV2UI_Presets_Feature* m_hdesc;
00299 bool m_host_support;
00300
00301 };
00302
00303 };
00304
00305
00312 template <bool Required = true>
00313 struct WriteMIDI {
00314
00315 enum {
00316 EVENT_BUFFER_SIZE = 4
00317 };
00318
00323 template <class Derived> struct I : Extension<Required> {
00324
00326 I() : m_midi_type(0) {
00327 m_buffer = lv2_event_buffer_new(sizeof(LV2_Event) + EVENT_BUFFER_SIZE,
00328 0);
00329 }
00330
00332 bool check_ok() {
00333 Derived* d = static_cast<Derived*>(this);
00334 m_midi_type = d->
00335 uri_to_id(LV2_EVENT_URI, "http://lv2plug.in/ns/ext/midi#MidiEvent");
00336 m_event_buffer_format = d->
00337 uri_to_id(LV2_UI_URI, "http://lv2plug.in/ns/extensions/ui#Events");
00338 return !Required || (m_midi_type && m_event_buffer_format);
00339 }
00340
00341 protected:
00342
00353 bool write_midi(uint32_t port, uint32_t size, const uint8_t* data) {
00354 if (m_midi_type == 0)
00355 return false;
00356 LV2_Event_Buffer* buffer;
00357 if (size <= 4)
00358 buffer = m_buffer;
00359 else
00360 buffer = lv2_event_buffer_new(sizeof(LV2_Event) + size, 0);
00361 lv2_event_buffer_reset(m_buffer, 0, m_buffer->data);
00362 LV2_Event_Iterator iter;
00363 lv2_event_begin(&iter, m_buffer);
00364 lv2_event_write(&iter, 0, 0, m_midi_type, size, data);
00365 static_cast<Derived*>(this)->
00366 write(port, m_buffer->header_size + m_buffer->capacity,
00367 m_event_buffer_format, m_buffer);
00368 if (size > 4)
00369 std::free(buffer);
00370 return true;
00371 }
00372
00373 uint32_t m_midi_type;
00374 uint32_t m_event_buffer_format;
00375 LV2_Event_Buffer* m_buffer;
00376
00377 };
00378
00379 };
00380
00381
00391 template <bool Required = true>
00392 struct WriteOSC {
00393
00398 template <class Derived> struct I : Extension<Required> {
00399
00400 I() : m_osc_type(0) {
00401 m_buffer = lv2_event_buffer_new(sizeof(LV2_Event) + 256, 0);
00402 }
00403
00404 bool check_ok() {
00405 Derived* d = static_cast<Derived*>(this);
00406 m_osc_type = d->
00407 uri_to_id(LV2_EVENT_URI, "http://lv2plug.in/ns/ext/osc#OscEvent");
00408 m_event_buffer_format = d->
00409 uri_to_id(LV2_UI_URI, "http://lv2plug.in/ns/extensions/ui#Events");
00410 return !Required || (m_osc_type && m_event_buffer_format);
00411 }
00412
00413 protected:
00414
00415 bool write_osc(uint32_t port, const char* path, const char* types, ...) {
00416 if (m_osc_type == 0)
00417 return false;
00418
00419 lv2_event_buffer_reset(m_buffer, 0, m_buffer->data);
00420 LV2_Event_Iterator iter;
00421 lv2_event_begin(&iter, m_buffer);
00422 va_list ap;
00423 va_start(ap, types);
00424 uint32_t size = lv2_osc_event_vsize(path, types, ap);
00425 va_end(ap);
00426 if (!size)
00427 return false;
00428 va_start(ap, types);
00429 bool success = lv2_osc_buffer_vappend(&iter, 0, 0, m_osc_type,
00430 path, types, size, ap);
00431 va_end(ap);
00432 if (success) {
00433 static_cast<Derived*>(this)->
00434 write(port, m_buffer->header_size + m_buffer->capacity,
00435 m_event_buffer_format, m_buffer);
00436 return true;
00437 }
00438 return false;
00439 }
00440
00441 uint32_t m_osc_type;
00442 uint32_t m_event_buffer_format;
00443 LV2_Event_Buffer* m_buffer;
00444
00445 };
00446
00447 };
00448
00449
00466 template<class Derived, class Ext1 = End, class Ext2 = End, class Ext3 = End,
00467 class Ext4 = End, class Ext5 = End, class Ext6 = End,
00468 class Ext7 = End, class Ext8 = End, class Ext9 = End>
00469 class GUI : public Gtk::HBox, public MixinTree<Derived,
00470 Ext1, Ext2, Ext3, Ext4,
00471 Ext5, Ext6, Ext7, Ext8, Ext9> {
00472 public:
00473
00477 inline GUI() {
00478 m_ctrl = s_ctrl;
00479 m_wfunc = s_wfunc;
00480 m_features = s_features;
00481 m_bundle_path = s_bundle_path;
00482 s_ctrl = 0;
00483 s_wfunc = 0;
00484 s_features = 0;
00485 s_bundle_path = 0;
00486 if (m_features) {
00487 FeatureHandlerMap hmap;
00488 Derived::map_feature_handlers(hmap);
00489 for (const Feature* const* iter = m_features; *iter != 0; ++iter) {
00490 FeatureHandlerMap::iterator miter;
00491 miter = hmap.find((*iter)->URI);
00492 if (miter != hmap.end())
00493 miter->second(static_cast<Derived*>(this), (*iter)->data);
00494 }
00495 }
00496 }
00497
00500 inline void port_event(uint32_t port, uint32_t buffer_size,
00501 uint32_t format, void const* buffer) { }
00502
00504 static int register_class(char const* uri) {
00505 LV2UI_Descriptor* desc = new LV2UI_Descriptor;
00506 std::memset(desc, 0, sizeof(LV2UI_Descriptor));
00507 desc->URI = strdup(uri);
00508 desc->instantiate = &Derived::create_ui_instance;
00509 desc->cleanup = &Derived::delete_ui_instance;
00510 desc->port_event = &Derived::_port_event;
00511 desc->extension_data = &Derived::extension_data;
00512 get_lv2g2g_descriptors().push_back(desc);
00513 return get_lv2g2g_descriptors().size() - 1;
00514 }
00515
00516 protected:
00517
00522 inline void write(uint32_t port, uint32_t buffer_size,
00523 uint32_t format, void const* buffer) {
00524 (*m_wfunc)(m_ctrl, port, buffer_size, format, buffer);
00525 }
00526
00528 inline void write_control(uint32_t port, float value) {
00529 write(port, sizeof(float), 0, &value);
00530 }
00531
00534 inline LV2::Feature const* const* features() {
00535 return m_features;
00536 }
00537
00539 inline char const* bundle_path() const {
00540 return m_bundle_path;
00541 }
00542
00543 public:
00547 inline void* controller() {
00548 return m_ctrl;
00549 }
00550
00551
00552 private:
00553
00554
00555
00556 friend class WriteMIDI<true>::I<Derived>;
00557 friend class WriteMIDI<false>::I<Derived>;
00558 friend class WriteOSC<true>::I<Derived>;
00559 friend class WriteOSC<false>::I<Derived>;
00560
00565 static LV2UI_Handle create_ui_instance(struct _LV2UI_Descriptor const*
00566 descriptor,
00567 char const* plugin_uri,
00568 char const* bundle_path,
00569 LV2UI_Write_Function write_func,
00570 LV2UI_Controller ctrl,
00571 LV2UI_Widget* widget,
00572 Feature const* const* features) {
00573
00574
00575
00576
00577 s_ctrl = ctrl;
00578 s_wfunc = write_func;
00579 s_features = features;
00580 s_bundle_path = bundle_path;
00581
00582
00583
00584 Gtk::Main::init_gtkmm_internals();
00585
00586
00587 Derived* t = new Derived(plugin_uri);
00588 *widget = static_cast<Gtk::Widget*>(t)->gobj();
00589
00590
00591 if (t->check_ok())
00592 return reinterpret_cast<LV2UI_Handle>(t);
00593 delete t;
00594 return 0;
00595 }
00596
00597
00602 static void delete_ui_instance(LV2UI_Handle instance) {
00603 delete static_cast<Derived*>(instance);
00604 }
00605
00606
00610 static void _port_event(LV2UI_Handle instance, uint32_t port,
00611 uint32_t buffer_size, uint32_t format,
00612 void const* buffer) {
00613 static_cast<Derived*>(instance)->port_event(port, buffer_size,
00614 format, buffer);
00615 }
00616
00617
00618 void* m_ctrl;
00619 LV2UI_Write_Function m_wfunc;
00620 LV2::Feature const* const* m_features;
00621 char const* m_bundle_path;
00622
00623 static void* s_ctrl;
00624 static LV2UI_Write_Function s_wfunc;
00625 static LV2::Feature const* const* s_features;
00626 static char const* s_bundle_path;
00627
00628 };
00629
00630
00631
00632 template<class Derived, class Ext1, class Ext2, class Ext3, class Ext4,
00633 class Ext5, class Ext6, class Ext7, class Ext8, class Ext9>
00634 void* GUI<Derived, Ext1, Ext2, Ext3, Ext4,
00635 Ext5, Ext6, Ext7, Ext8, Ext9>::s_ctrl = 0;
00636
00637 template<class Derived, class Ext1, class Ext2, class Ext3, class Ext4,
00638 class Ext5, class Ext6, class Ext7, class Ext8, class Ext9>
00639 LV2UI_Write_Function GUI<Derived, Ext1, Ext2, Ext3, Ext4,
00640 Ext5, Ext6, Ext7, Ext8, Ext9>::s_wfunc = 0;
00641
00642 template<class Derived, class Ext1, class Ext2, class Ext3, class Ext4,
00643 class Ext5, class Ext6, class Ext7, class Ext8, class Ext9>
00644 LV2::Feature const* const* GUI<Derived, Ext1, Ext2, Ext3, Ext4,
00645 Ext5, Ext6, Ext7, Ext8, Ext9>::s_features = 0;
00646
00647 template<class Derived, class Ext1, class Ext2, class Ext3, class Ext4,
00648 class Ext5, class Ext6, class Ext7, class Ext8, class Ext9>
00649 char const* GUI<Derived, Ext1, Ext2, Ext3, Ext4,
00650 Ext5, Ext6, Ext7, Ext8, Ext9>::s_bundle_path = 0;
00651
00652
00653 }
00654
00655
00656 #endif