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 <map>
00030
00031 #include <gtkmm/box.h>
00032 #include <gtkmm/main.h>
00033 #include <gtkmm/widget.h>
00034
00035 #include <lv2_ui.h>
00036 #include <lv2_ui_presets.h>
00037 #include <lv2_uri_map.h>
00038 #include <lv2_event_helpers.h>
00039 #include <lv2_osc.h>
00040 #include <lv2types.hpp>
00041
00042
00043 namespace LV2 {
00044
00045
00048 typedef std::vector<LV2UI_Descriptor*> GUIDescList;
00049
00050
00054 GUIDescList& get_lv2g2g_descriptors();
00055
00056
00103 template <bool Required = true>
00104 struct NoUserResize {
00105
00110 template <class Derived> struct I : public Extension<Required> {
00111
00113 static void map_feature_handlers(FeatureHandlerMap& hmap) {
00114 hmap["http://ll-plugins.nongnu.org/lv2/dev/ui#noUserResize"] =
00115 &I<Derived>::handle_feature;
00116 }
00117
00119 static void handle_feature(void* instance, void* data) {
00120 Derived* d = reinterpret_cast<Derived*>(instance);
00121 I<Derived>* e = static_cast<I<Derived>*>(d);
00122 e->m_ok = true;
00123 }
00124
00125 };
00126
00127 };
00128
00129
00139 template <bool Required = true>
00140 struct FixedSize {
00141
00146 template <class Derived> struct I : public Extension<Required> {
00147
00149 static void map_feature_handlers(FeatureHandlerMap& hmap) {
00150 hmap["http://ll-plugins.nongnu.org/lv2/dev/ui#fixedSize"] =
00151 &I<Derived>::handle_feature;
00152 }
00153
00155 static void handle_feature(void* instance, void* data) {
00156 Derived* d = reinterpret_cast<Derived*>(instance);
00157 I<Derived>* e = static_cast<I<Derived>*>(d);
00158 e->m_ok = true;
00159 }
00160
00161 };
00162
00163 };
00164
00165
00174 template <bool Required = true>
00175 struct Presets {
00176
00181 template <class Derived> struct I : public Extension<Required> {
00182
00184 I() : m_hdesc(0), m_host_support(false) { }
00185
00187 static void map_feature_handlers(FeatureHandlerMap& hmap) {
00188 hmap[LV2_UI_PRESETS_URI] = &I<Derived>::handle_feature;
00189 }
00190
00192 static void handle_feature(void* instance, void* data) {
00193 Derived* d = reinterpret_cast<Derived*>(instance);
00194 I<Derived>* e = static_cast<I<Derived>*>(d);
00195 e->m_hdesc = static_cast<LV2UI_Presets_Feature*>(data);
00196 e->m_ok = (e->m_hdesc != 0);
00197 e->m_host_support = (e->m_hdesc != 0);
00198 }
00199
00200
00206 void preset_added(uint32_t number,
00207 char const* name) {
00208
00209 }
00210
00215 void preset_removed(uint32_t number) {
00216
00217 }
00218
00222 void presets_cleared() {
00223
00224 }
00225
00232 void current_preset_changed(uint32_t number) {
00233
00234 }
00235
00239 static void const* extension_data(char const* uri) {
00240 static LV2UI_Presets_GDesc desc = { &_preset_added,
00241 &_preset_removed,
00242 &_presets_cleared,
00243 &_current_preset_changed };
00244 if (!std::strcmp(uri, LV2_UI_URI "#ext_presetss"))
00245 return &desc;
00246 return 0;
00247 }
00248
00249 protected:
00250
00253 void change_preset(uint32_t preset) {
00254 if (m_hdesc)
00255 m_hdesc->change_preset(static_cast<Derived*>(this)->controller(),
00256 preset);
00257 }
00258
00262 void save_preset(uint32_t preset, char const* name) {
00263 if (m_hdesc)
00264 m_hdesc->save_preset(static_cast<Derived*>(this)->controller(),
00265 preset, name);
00266 }
00267
00270 bool host_supports_presets() const {
00271 return m_host_support;
00272 }
00273
00274 private:
00275
00276 static void _preset_added(LV2UI_Handle gui,
00277 uint32_t number,
00278 char const* name) {
00279 static_cast<Derived*>(gui)->preset_added(number, name);
00280 }
00281
00282 static void _preset_removed(LV2UI_Handle gui,
00283 uint32_t number) {
00284 static_cast<Derived*>(gui)->preset_removed(number);
00285 }
00286
00287 static void _presets_cleared(LV2UI_Handle gui) {
00288 static_cast<Derived*>(gui)->presets_cleared();
00289 }
00290
00291 static void _current_preset_changed(LV2UI_Handle gui,
00292 uint32_t number) {
00293 static_cast<Derived*>(gui)->current_preset_changed(number);
00294 }
00295
00296
00297 LV2UI_Presets_Feature* m_hdesc;
00298 bool m_host_support;
00299
00300 };
00301
00302 };
00303
00304
00311 template <bool Required = true>
00312 struct WriteMIDI {
00313
00314 enum {
00315 EVENT_BUFFER_SIZE = 4
00316 };
00317
00322 template <class Derived> struct I : Extension<Required> {
00323
00324 I() : m_midi_type(0) {
00325 m_buffer = lv2_event_buffer_new(sizeof(LV2_Event) + EVENT_BUFFER_SIZE,
00326 0);
00327 }
00328
00329 bool check_ok() {
00330 Derived* d = static_cast<Derived*>(this);
00331 m_midi_type = d->
00332 uri_to_id(LV2_EVENT_URI, "http://lv2plug.in/ns/ext/midi#MidiEvent");
00333 m_event_buffer_format = d->
00334 uri_to_id(LV2_UI_URI, "http://lv2plug.in/ns/extensions/ui#Events");
00335 return !Required || (m_midi_type && m_event_buffer_format);
00336 }
00337
00338 protected:
00339
00340 bool write_midi(uint32_t port, uint32_t size, const uint8_t* data) {
00341 if (m_midi_type == 0)
00342 return false;
00343 LV2_Event_Buffer* buffer;
00344 if (size <= 4)
00345 buffer = m_buffer;
00346 else
00347 buffer = lv2_event_buffer_new(sizeof(LV2_Event) + size, 0);
00348 lv2_event_buffer_reset(m_buffer, 0, m_buffer->data);
00349 LV2_Event_Iterator iter;
00350 lv2_event_begin(&iter, m_buffer);
00351 lv2_event_write(&iter, 0, 0, m_midi_type, size, data);
00352 static_cast<Derived*>(this)->
00353 write(port, m_buffer->header_size + m_buffer->capacity,
00354 m_event_buffer_format, m_buffer);
00355 if (size > 4)
00356 std::free(buffer);
00357 return true;
00358 }
00359
00360 uint32_t m_midi_type;
00361 uint32_t m_event_buffer_format;
00362 LV2_Event_Buffer* m_buffer;
00363
00364 };
00365
00366 };
00367
00368
00378 template <bool Required = true>
00379 struct WriteOSC {
00380
00385 template <class Derived> struct I : Extension<Required> {
00386
00387 I() : m_osc_type(0) {
00388 m_buffer = lv2_event_buffer_new(sizeof(LV2_Event) + 256, 0);
00389 }
00390
00391 bool check_ok() {
00392 Derived* d = static_cast<Derived*>(this);
00393 m_osc_type = d->
00394 uri_to_id(LV2_EVENT_URI, "http://lv2plug.in/ns/ext/osc#OscEvent");
00395 m_event_buffer_format = d->
00396 uri_to_id(LV2_UI_URI, "http://lv2plug.in/ns/extensions/ui#Events");
00397 return !Required || (m_osc_type && m_event_buffer_format);
00398 }
00399
00400 protected:
00401
00402 bool write_osc(uint32_t port, const char* path, const char* types, ...) {
00403 if (m_osc_type == 0)
00404 return false;
00405
00406 lv2_event_buffer_reset(m_buffer, 0, m_buffer->data);
00407 LV2_Event_Iterator iter;
00408 lv2_event_begin(&iter, m_buffer);
00409 va_list ap;
00410 va_start(ap, types);
00411 uint32_t size = lv2_osc_event_vsize(path, types, ap);
00412 va_end(ap);
00413 if (!size)
00414 return false;
00415 va_start(ap, types);
00416 bool success = lv2_osc_buffer_vappend(&iter, 0, 0, m_osc_type,
00417 path, types, size, ap);
00418 va_end(ap);
00419 if (success) {
00420 static_cast<Derived*>(this)->
00421 write(port, m_buffer->header_size + m_buffer->capacity,
00422 m_event_buffer_format, m_buffer);
00423 return true;
00424 }
00425 return false;
00426 }
00427
00428 uint32_t m_osc_type;
00429 uint32_t m_event_buffer_format;
00430 LV2_Event_Buffer* m_buffer;
00431
00432 };
00433
00434 };
00435
00436
00453 template<class Derived, class Ext1 = End, class Ext2 = End, class Ext3 = End,
00454 class Ext4 = End, class Ext5 = End, class Ext6 = End,
00455 class Ext7 = End, class Ext8 = End, class Ext9 = End>
00456 class GUI : public Gtk::HBox, public MixinTree<Derived,
00457 Ext1, Ext2, Ext3, Ext4,
00458 Ext5, Ext6, Ext7, Ext8, Ext9> {
00459 public:
00460
00464 inline GUI() {
00465 m_ctrl = s_ctrl;
00466 m_wfunc = s_wfunc;
00467 m_features = s_features;
00468 m_bundle_path = s_bundle_path;
00469 s_ctrl = 0;
00470 s_wfunc = 0;
00471 s_features = 0;
00472 s_bundle_path = 0;
00473 if (m_features) {
00474 FeatureHandlerMap hmap;
00475 Derived::map_feature_handlers(hmap);
00476 for (const Feature* const* iter = m_features; *iter != 0; ++iter) {
00477 FeatureHandlerMap::iterator miter;
00478 miter = hmap.find((*iter)->URI);
00479 if (miter != hmap.end())
00480 miter->second(static_cast<Derived*>(this), (*iter)->data);
00481 }
00482 }
00483 }
00484
00487 inline void port_event(uint32_t port, uint32_t buffer_size,
00488 uint32_t format, void const* buffer) { }
00489
00491 static int register_class(char const* uri) {
00492 LV2UI_Descriptor* desc = new LV2UI_Descriptor;
00493 std::memset(desc, 0, sizeof(LV2UI_Descriptor));
00494 desc->URI = strdup(uri);
00495 desc->instantiate = &Derived::create_ui_instance;
00496 desc->cleanup = &Derived::delete_ui_instance;
00497 desc->port_event = &Derived::_port_event;
00498 desc->extension_data = &Derived::extension_data;
00499 get_lv2g2g_descriptors().push_back(desc);
00500 return get_lv2g2g_descriptors().size() - 1;
00501 }
00502
00503 protected:
00504
00509 inline void write(uint32_t port, uint32_t buffer_size,
00510 uint32_t format, void const* buffer) {
00511 (*m_wfunc)(m_ctrl, port, buffer_size, format, buffer);
00512 }
00513
00515 inline void write_control(uint32_t port, float value) {
00516 write(port, sizeof(float), 0, &value);
00517 }
00518
00521 inline LV2::Feature const* const* features() {
00522 return m_features;
00523 }
00524
00526 inline char const* bundle_path() const {
00527 return m_bundle_path;
00528 }
00529
00530 public:
00534 inline void* controller() {
00535 return m_ctrl;
00536 }
00537
00538
00539 private:
00540
00541
00542
00543 friend class WriteMIDI<true>::I<Derived>;
00544 friend class WriteMIDI<false>::I<Derived>;
00545 friend class WriteOSC<true>::I<Derived>;
00546 friend class WriteOSC<false>::I<Derived>;
00547
00552 static LV2UI_Handle create_ui_instance(struct _LV2UI_Descriptor const*
00553 descriptor,
00554 char const* plugin_uri,
00555 char const* bundle_path,
00556 LV2UI_Write_Function write_func,
00557 LV2UI_Controller ctrl,
00558 LV2UI_Widget* widget,
00559 Feature const* const* features) {
00560
00561
00562
00563
00564 s_ctrl = ctrl;
00565 s_wfunc = write_func;
00566 s_features = features;
00567 s_bundle_path = bundle_path;
00568
00569
00570
00571 Gtk::Main::init_gtkmm_internals();
00572
00573
00574 Derived* t = new Derived(plugin_uri);
00575 *widget = static_cast<Gtk::Widget*>(t)->gobj();
00576
00577
00578 if (t->check_ok())
00579 return reinterpret_cast<LV2UI_Handle>(t);
00580 delete t;
00581 return 0;
00582 }
00583
00584
00589 static void delete_ui_instance(LV2UI_Handle instance) {
00590 delete static_cast<Derived*>(instance);
00591 }
00592
00593
00597 static void _port_event(LV2UI_Handle instance, uint32_t port,
00598 uint32_t buffer_size, uint32_t format,
00599 void const* buffer) {
00600 static_cast<Derived*>(instance)->port_event(port, buffer_size,
00601 format, buffer);
00602 }
00603
00604
00605 void* m_ctrl;
00606 LV2UI_Write_Function m_wfunc;
00607 LV2::Feature const* const* m_features;
00608 char const* m_bundle_path;
00609
00610 static void* s_ctrl;
00611 static LV2UI_Write_Function s_wfunc;
00612 static LV2::Feature const* const* s_features;
00613 static char const* s_bundle_path;
00614
00615 };
00616
00617
00618
00619 template<class Derived, class Ext1, class Ext2, class Ext3, class Ext4,
00620 class Ext5, class Ext6, class Ext7, class Ext8, class Ext9>
00621 void* GUI<Derived, Ext1, Ext2, Ext3, Ext4,
00622 Ext5, Ext6, Ext7, Ext8, Ext9>::s_ctrl = 0;
00623
00624 template<class Derived, class Ext1, class Ext2, class Ext3, class Ext4,
00625 class Ext5, class Ext6, class Ext7, class Ext8, class Ext9>
00626 LV2UI_Write_Function GUI<Derived, Ext1, Ext2, Ext3, Ext4,
00627 Ext5, Ext6, Ext7, Ext8, Ext9>::s_wfunc = 0;
00628
00629 template<class Derived, class Ext1, class Ext2, class Ext3, class Ext4,
00630 class Ext5, class Ext6, class Ext7, class Ext8, class Ext9>
00631 LV2::Feature const* const* GUI<Derived, Ext1, Ext2, Ext3, Ext4,
00632 Ext5, Ext6, Ext7, Ext8, Ext9>::s_features = 0;
00633
00634 template<class Derived, class Ext1, class Ext2, class Ext3, class Ext4,
00635 class Ext5, class Ext6, class Ext7, class Ext8, class Ext9>
00636 char const* GUI<Derived, Ext1, Ext2, Ext3, Ext4,
00637 Ext5, Ext6, Ext7, Ext8, Ext9>::s_bundle_path = 0;
00638
00639
00640 }
00641
00642
00643 #endif