badosu | Is there any Qt lv2 plugin that uses ui:Qt4UI? | 00:02 |
---|---|---|
drobilla | synthv2 and friends, I think | 00:14 |
*** falktx has quit IRC | 00:35 | |
badosu | Thanks, I managed to create the QT port | 01:24 |
*** NickSB2 has joined #lv2 | 01:53 | |
*** gianMOD has joined #lv2 | 02:02 | |
*** gianMOD has quit IRC | 02:36 | |
badosu | Wow, using a raw Makefile to compile a QT application is hard | 03:53 |
badosu | I finished it, now I just need to sort out the ttl issue with multiple GUIs: https://github.com/badosu/BadAmp | 05:44 |
drobilla | badosu: Currently they must be different UIs (i.e. have a different URI) | 07:17 |
drobilla | badosu: Been some talk of providing a way for the same UI to provide several implementations dynamically, so the UI is more semantic (full, tiny, mixer strip, etc) and the widget type is more of an implementation detail for hosts to choose appropriately, but no API for that yet | 07:18 |
*** zth_studiocomp has quit IRC | 08:43 | |
*** zth_studiocomp has joined #lv2 | 08:45 | |
*** edogawa has joined #lv2 | 08:46 | |
*** edogawa has quit IRC | 09:20 | |
*** gianMOD has joined #lv2 | 09:56 | |
*** ricardocrudo has joined #lv2 | 10:14 | |
*** gianMOD has quit IRC | 11:03 | |
*** gianMOD has joined #lv2 | 11:03 | |
*** gianMOD has quit IRC | 11:04 | |
*** ricardocrudo has quit IRC | 11:09 | |
*** falktx has joined #lv2 | 11:12 | |
*** gianMOD has joined #lv2 | 11:28 | |
*** ricardocrudo has joined #lv2 | 11:44 | |
*** gianMOD has quit IRC | 12:41 | |
*** ricardocrudo has quit IRC | 12:45 | |
*** rncbc_jolla has joined #lv2 | 13:28 | |
*** gianMOD has joined #lv2 | 13:42 | |
*** gianMOD has quit IRC | 13:47 | |
*** gianMOD has joined #lv2 | 13:50 | |
*** NickSB2 has quit IRC | 13:56 | |
*** ricardocrudo has joined #lv2 | 14:06 | |
*** gianMOD has quit IRC | 14:12 | |
*** sigma6 has joined #lv2 | 14:23 | |
*** gianMOD has joined #lv2 | 14:24 | |
*** gianMOD has quit IRC | 15:39 | |
*** gianMOD has joined #lv2 | 15:40 | |
*** gianMOD has quit IRC | 15:41 | |
*** gianMOD has joined #lv2 | 15:42 | |
*** gianMOD has quit IRC | 15:43 | |
*** gianMOD has joined #lv2 | 15:44 | |
*** gianMOD has quit IRC | 16:12 | |
*** gianMOD has joined #lv2 | 16:17 | |
*** gianMOD has quit IRC | 16:37 | |
*** ricardocrudo has quit IRC | 16:42 | |
*** gianMOD has joined #lv2 | 16:55 | |
*** ricardocrudo has joined #lv2 | 16:56 | |
*** rncbc_jolla has quit IRC | 16:58 | |
*** rncbc_jolla has joined #lv2 | 16:59 | |
*** gianMOD has quit IRC | 17:12 | |
*** gianMOD has joined #lv2 | 17:13 | |
*** ricardocrudo has quit IRC | 17:14 | |
*** gianMOD has quit IRC | 17:17 | |
*** sigma6 has quit IRC | 17:26 | |
*** rncbc has joined #lv2 | 17:39 | |
*** gianMOD has joined #lv2 | 17:50 | |
*** greenkobold has joined #lv2 | 18:37 | |
*** gianMOD has quit IRC | 18:42 | |
* drobilla idly wonders how much less hated LV2 would be if it was JSON-LD instead of Turtle | 18:53 | |
drobilla | Odd one, that. On the one hand a naive RDF serialization to JSON looks like utter crap | 18:53 |
drobilla | But it is clever how you can define a context to make things look like 'dumb' key value (string keys) but map to something meaningful | 18:53 |
*** gianMOD has joined #lv2 | 19:10 | |
*** gianMOD has quit IRC | 19:27 | |
* drobilla tinkers with lv2/Plugin.hpp | 19:51 | |
drobilla | I'm half tempted to just make a monolithic one with stubs for all extensions. There, there's your damned single file class for dummies | 19:52 |
drobilla | That makes optional/required feature stuff tricky though, the mixin thing ala lvtk can deal with that nicely | 19:52 |
falktx | drobilla: please don't use all those template trickery lvtk does | 19:53 |
falktx | it looks awful | 19:54 |
falktx | and also very hard to understand | 19:54 |
drobilla | falktx: I agree, though it can be better with C++11 | 19:54 |
drobilla | The trouble is, I don't think you can get an 'override this method' sort of thing without mixins | 19:54 |
drobilla | e.g. worker callback | 19:54 |
falktx | you can make virtual classes | 19:55 |
drobilla | overhead. | 19:55 |
falktx | which take Plugin as a constructor | 19:55 |
falktx | plugin devs will then subclass Plugin, Worker, State etc | 19:55 |
drobilla | I had considered that, but then they would have to be templates anyway if you want access to your plugin fields | 19:55 |
falktx | hm? | 19:55 |
falktx | as long as you pass Plugin* in those classes constructor, there's no need for templates | 19:56 |
falktx | templates might be useful for atom types though, and forge | 19:56 |
drobilla | Plugin* is a base class with nothing in it | 19:56 |
falktx | yes | 19:56 |
drobilla | You can cast it every time, sure | 19:56 |
drobilla | But this is starting to get not a heck of a lot prettier than the mixin thing | 19:56 |
falktx | Worker and State can be virtual classes that take Plugin* var in contructor | 19:56 |
falktx | drobilla: have you started this? | 19:57 |
drobilla | falktx: vaguely | 19:57 |
falktx | I'm super bored today so I might try this | 19:57 |
drobilla | If it's going to be C++, having a bunch of nasty upcasting in there seems pretty brutal | 19:57 |
* drobilla wonders if some kind of C++ slot thingie can make callbacks decent | 19:58 | |
falktx | heh | 19:59 |
drobilla | Maybe the things like workers can be templates that take a class sort of like you say, but instead of dealing with the 'crossing a bunch of object' boundaries, they require their template type (the plugin) to adhere to some API | 19:59 |
falktx | I'd prefer to have it work without any possible std:: stuff | 19:59 |
drobilla | e.g. having a worker() method with a given signature | 20:00 |
drobilla | falktx: Me too, though I think maybe I just don't give a shit about pre-C++11 if something there turns out to be handy | 20:00 |
falktx | new names should be used though | 20:00 |
falktx | override, nullptr, etc | 20:00 |
* falktx hates NULL macro | 20:02 | |
drobilla | template<typename Plugin> class Worker { Worker(Plugin* plug) {...} response(...) { plug->response(..); } }; ? | 20:03 |
falktx | why is template needed? | 20:03 |
drobilla | because response is defined in the user's derived plugin class | 20:03 |
falktx | the plugin will call it, so it will need a point to a Worker class instance right? | 20:04 |
drobilla | So you get the same illusion that your plugin is just a class that needs to implement this and that method | 20:04 |
drobilla | falktx: That's a case where the host calls it, so in your plugin you just know whatever method gets called | 20:05 |
drobilla | falktx: In the case where plugin calls it, just walling m_worker.whatever() should do | 20:05 |
drobilla | calling* | 20:05 |
falktx | I need to start coding this to perfetly understand what it needs | 20:05 |
drobilla | No need to override those, so worker.schedule() is fine | 20:06 |
drobilla | I think it's basically a requirement that additional methods just look like additional methods, though. Otherwise things get ugly. | 20:06 |
drobilla | If we can achieve that without mixin hell, that would be lovely | 20:06 |
*** edogawa has joined #lv2 | 20:06 | |
drobilla | Unfortunately no solution other than a monolithic class will give us one big class documentation thing with all the possible methods | 20:07 |
drobilla | falktx: I can send you my stub Plugin if you want | 20:07 |
falktx | sure | 20:07 |
falktx | for me the solution is to make the basic extensions in the base plugin class | 20:07 |
falktx | say state, atom and urid-map | 20:07 |
drobilla | Yeah, but what's "basic"... | 20:08 |
falktx | then other things have their own virtual class | 20:08 |
drobilla | I'm tempted to do so anyway, even though it's horribly unmodular | 20:08 |
falktx | well, worker is not basic | 20:08 |
drobilla | But the plugin needs to deal with setup for them anyway, since the feature array needs to be processed somehow and whether it succeded checked and so on | 20:08 |
drobilla | Hm, I suppose instead of magic template duck typing, the plugin could be required to inherit from worker::Interface | 20:09 |
drobilla | If that was virtual, the worker, uh, not-mixin could not be a template | 20:10 |
drobilla | I'm not sure if using virtual at all is the best idea | 20:10 |
falktx | a good test for this class will be implementing one of the examples with it | 20:11 |
drobilla | falktx: Yes. I've been wondering what kind of example | 20:12 |
drobilla | I also plan to do a nicer forge and atom iterators | 20:12 |
falktx | eg-sampler? | 20:12 |
drobilla | for (const atom::Event* ev : input) { ... } | 20:12 |
falktx | for (auto ev : input) { ... } | 20:13 |
falktx | :) | 20:13 |
drobilla | falktx: Maybe I should just make a C++ branch? | 20:13 |
drobilla | atoms are a bit tricky. you can't really make ideal C++ wrappers that work nicely with nesting but are still just normal atoms in memory | 20:14 |
falktx | let me do a design first and show it | 20:14 |
drobilla | I've been tinkering with some variadict template hackery that would allow it syntactically though, for forge(dict(lv2.label, "whatever", lv2.index 5)) and so on | 20:14 |
drobilla | falktx: I figured it be easier that way, but okay. Cleaning up header | 20:15 |
falktx | what's the simplest lv2 example? | 20:15 |
drobilla | amp | 20:17 |
falktx | I'll do whatever that requires first, and show it to you | 20:17 |
drobilla | One problem with not using mixins is that overriding default methods like connect_port isn't possible | 20:18 |
drobilla | meaning e.g. Plugin needs to have a vector of void* for port buffers, no choice for the dev on how to do this | 20:19 |
*** gianMOD has joined #lv2 | 20:19 | |
drobilla | actually, I guess not, the descriptor maker thing can take a template | 20:19 |
falktx | drobilla: can we assume buf-size, urid-map and options as being required? | 20:21 |
drobilla | falktx: no. | 20:21 |
falktx | :( | 20:21 |
drobilla | Well, why? | 20:21 |
falktx | urid-map is obvious | 20:22 |
falktx | buf-size for actually knowing the values | 20:22 |
drobilla | Well, ideally we have a clean design for these things, so there should be little cost | 20:22 |
falktx | buf-size requires options to work | 20:22 |
drobilla | I think an official wrapper shouldn't assume anything. That's one of the differences between an official one and a "whatever I need" header full of assumptions | 20:22 |
drobilla | It also makes it much easier for us to be sure it's done/good/solid. Wraps precisely what's there, done. | 20:23 |
falktx | drobilla: should this be a header devs will subclass, or one devs will copy and adjust? | 20:23 |
drobilla | I'll get sloppy if we unfortunately really have to be for some good reason, but ideally not. | 20:23 |
drobilla | falktx: subclass. Though people can copy it if they like. | 20:24 |
drobilla | It will be installed like any other LV2 header, though probably not with a binary compatibility guarantee since it's not a host:plugin interface | 20:24 |
falktx | ok | 20:25 |
falktx | brb | 20:25 |
*** falktx has quit IRC | 20:25 | |
*** gianMOD has quit IRC | 20:28 | |
*** falktx has joined #lv2 | 20:30 | |
drobilla | This adds a few restrictions that prevent some of the things lvtk does. I think maybe Plugin should just have zero state whatsoever, and also be RT instantiable | 20:30 |
*** rncbc has quit IRC | 20:31 | |
falktx | I think I missed something | 20:32 |
falktx | I logged off after my "brb" | 20:33 |
*** rncbc has joined #lv2 | 20:33 | |
*** rncbc_jolla has quit IRC | 20:34 | |
drobilla | falktx: Nope. By "this" I just meant the requirement that the interface not impose any restrictions beyond what LV2 itself does | 20:34 |
drobilla | falktx: I think we can still make things quite nice this way, though | 20:34 |
* drobilla wishes so hard we just made the damned descriptor struct extensible | 20:35 | |
drobilla | Little too much wooo decentralized extensions kool-aid back in the day | 20:36 |
*** gianMOD has joined #lv2 | 20:38 | |
drobilla | Not sure if we can make implementing lv2_descriptor go away, though it is probably better we just use the new Lib discovery API anyway | 20:38 |
falktx | but it needs to handle implementing the descriptor for several plugins in the same binary | 20:40 |
falktx | so perhaps it can be a separate cpp file | 20:40 |
drobilla | Maybe. Including code is definitely questionable. | 20:41 |
drobilla | Not sure how extension_data can be nice without mixins | 20:41 |
drobilla | I think a derived class mixin is necessary to make the static callbacks work | 20:44 |
drobilla | e.g. class MyPlugin : public Plugin<MyPlugin> | 20:44 |
drobilla | Either that or virtual everything | 20:44 |
falktx | you need virtual stuff so you can reimplement | 20:48 |
*** gianMOD has quit IRC | 20:49 | |
falktx | drobilla: can we assume ports are static? | 20:49 |
falktx | it would allow to hide connect_port implementation | 20:49 |
drobilla | The answer to "can we assume *" is no :) | 20:49 |
drobilla | falktx: I plan to add a run_on extension to eliminate that blasted thing entirely soon | 20:50 |
drobilla | I think this guideline is the only way to actually get this done and ensure we don't shoot ourselves in the foot | 20:50 |
drobilla | class MyPlugin : public lv2::Plugin { void run_on(void** bufs) { ((float*)bufs[1]) = ((const float*)bufs[0]) * 2.0f; } }; | 20:52 |
drobilla | Which I wish we could do with const-correctness :/ | 20:52 |
drobilla | non-mixin option is make the status wrappers template functions, I suppose | 20:55 |
falktx | eg-amp is a bit too simple :P | 20:55 |
drobilla | yep. | 20:55 |
drobilla | Something like fifths is probably better | 20:55 |
drobilla | MIDI-only though | 20:56 |
drobilla | Trying the template functions (non-mixin) approach | 21:01 |
drobilla | falktx: I'll send you a stub that works shortly | 21:01 |
drobilla | and by "send" I mean push a C++ branch. Might as well just get this ball rolling properly | 21:01 |
falktx | let me show you eg-amp in c++ | 21:02 |
drobilla | maybe a MIDI gate | 21:02 |
drobilla | falktx: ok | 21:02 |
*** NickSB2 has joined #lv2 | 21:02 | |
falktx | drobilla: https://gist.github.com/falkTX/45f8c2f441bc37848583 | 21:03 |
falktx | those PortIndexes should not be uppercase, those are usually for macros | 21:04 |
* falktx adjusts | 21:04 | |
falktx | drobilla: updated | 21:06 |
drobilla | better before :P | 21:06 |
falktx | I disagree, but whatever, it's not the api | 21:07 |
falktx | I'll do midigate next | 21:07 |
drobilla | VST hath rotted thy mind | 21:08 |
falktx | not vst, it's the common c++ practice in some apis | 21:08 |
falktx | well, which includes vst | 21:08 |
* drobilla tries to think of the simplest possible thing with a worker method | 21:11 | |
drobilla | maybe something dumb and synthetic that "calculates" a parameter there just because | 21:11 |
*** ricardocrudo has joined #lv2 | 21:20 | |
drobilla | Speaking of naming conventions, I know _ prefix is "bad", but everything else is so awful. | 21:25 |
drobilla | I reluctantly am doing the m_ thing | 21:25 |
drobilla | Implicit "this" is one of the dumbest ideas to come out of the 90's quasi-OO nonsense | 21:25 |
drobilla | Now everything's fucked and the C++ standard is considering working around it by definining foo.bar(x) as syntactic sugar for bar(foo, x) to make anything higher-order not horribly painful | 21:26 |
drobilla | Good work, guys | 21:26 |
falktx | I need a good name for the C feature structs as c++ | 21:26 |
falktx | maybe using non-lv2 prefixed names in a LV2 namespace | 21:29 |
falktx | so it becomes LV2::Plugin and LV2::URID_Map | 21:29 |
drobilla | lv2::Plugin etc | 21:32 |
falktx | lv2 or LV2 ? | 21:32 |
drobilla | (namespaces lowercase) | 21:32 |
falktx | why is that? | 21:34 |
drobilla | Got a working plugin | 21:41 |
drobilla | falktx: Just the most common convention | 21:41 |
drobilla | acronyms are maybe a weird case | 21:41 |
drobilla | Something clever to make connect_port go away would be nice, but you can't have a polymorphic vector... | 21:43 |
drobilla | or we could just add run_on and ignore that problem | 21:44 |
* drobilla needs to consider if/how lilv could isolate hosts from this entirely | 21:44 | |
drobilla | aaaaaaaaaaaaaand I pushed to master | 21:45 |
drobilla | mother. | 21:45 |
drobilla | fucker. | 21:45 |
drobilla | Hooray for sloppy commit logs | 21:47 |
drobilla | falktx: there is a c++ branch now | 21:47 |
drobilla | Maybe we can make a fancy descriptor wrapper that delegates to the next in the list to achieve an automatic lv2_descriptor() without code | 21:48 |
drobilla | But I think I'll try to wrap the Library API and see how that goes anyway, maybe just don't care | 21:48 |
falktx | drobilla: midigate https://gist.github.com/falkTX/2da8087fd8dc3dd1380b | 21:49 |
drobilla | falktx: Thanks. I don't just want to port all the existing examples to c++ though | 21:53 |
drobilla | falktx: extension implementation like that needs some way to deal with requiredness | 21:53 |
falktx | drobilla: on your code the plugin class actually does nothing | 21:55 |
falktx | code-wise it's not needed | 21:55 |
falktx | it also makes that the devs need to implement all functions (called by template) | 21:56 |
drobilla | correct on the first. not the second | 21:59 |
falktx | drobilla: here's my current c++ class https://gist.github.com/falkTX/31b0b6955a60bff9501c | 21:59 |
drobilla | It is essentially documentation. | 21:59 |
falktx | my idea as you see was to make the plugins subclass the needed features | 22:01 |
drobilla | Not much point with URIMap and the like | 22:01 |
drobilla | Worker, yes | 22:01 |
drobilla | I guess it means you can call a method on self which is a bit shorter | 22:02 |
drobilla | Maybe they should all take a pointer to plugin in their constructor, and set valid = false on it if they're mandatory but the feature is not present | 22:03 |
drobilla | and instantiate() wrapper can detect this and fail automatically (delete and return NULL) | 22:03 |
drobilla | Adds state to Plugin, but oh well. | 22:05 |
drobilla | No way to fancily delegate to super without mixins | 22:05 |
*** rncbc has quit IRC | 22:07 | |
*** gianMOD has joined #lv2 | 22:10 | |
drobilla | I can't think of any way other than the flag thing | 22:18 |
*** ricardocrudo has quit IRC | 22:21 | |
drobilla | falktx: I think extensions should go in their dirs, namespace lv2::ext | 22:24 |
drobilla | falktx: Not sure if headers should be split up into classes or just ext.hpp | 22:24 |
falktx | I'm still trying to get something to look decent | 22:26 |
drobilla | I'm working on Lib | 22:27 |
* drobilla debates using std::vector | 22:27 | |
falktx | the core plugin class is too simple | 22:27 |
drobilla | too simple how? | 22:27 |
falktx | some basic features really need to be there | 22:27 |
drobilla | Well, that's LV2 | 22:28 |
falktx | uridMap() and uridUnmap() should be provided by the plugin class | 22:28 |
drobilla | What's "basic" to you is completely unnecessary for others | 22:28 |
drobilla | This is the difference between a sloppy convenience header and standard ones | 22:28 |
drobilla | I don't want to have long pointless arguments about what counts as "basic" or "official" or whatever | 22:28 |
drobilla | People forming committees to define LV2 "profiles" and all that nonsense. | 22:28 |
falktx | hmm, maybe we can have the base stuff in separate classes, then a plugin+features all-in-one | 22:29 |
drobilla | Is inheriting from the features you need really all that burdensome? | 22:29 |
falktx | no, but gets extensive pretty quick | 22:30 |
drobilla | If we ever have a dyn-data thing some day, those things can automatically emit feature optional/required data and so on. it's nice. | 22:30 |
drobilla | falktx: Well, yes, we have way too many damned extensions, but that's a problem itself | 22:30 |
falktx | beginners will have to go through all features to know how to do something | 22:30 |
drobilla | Though most don't actually correspond to any such class | 22:30 |
drobilla | I don't think veneering over the spec in some weird hybrid thing that includes some things but not others because someone arbitrarily chose so at the moment is a very solid path forward | 22:31 |
drobilla | (Plus it'll probably just let us fuck up how we do extensions and not notice) | 22:31 |
drobilla | Lack of one big ol' header and/or class doc with all the methods anyone will ever care about is mildly unfortunate, granted | 22:32 |
drobilla | I wish LV2 was less like this, but it is | 22:34 |
falktx | still, having the features in the plugin... it's just a small update away when a new official lv2 api comes | 22:34 |
drobilla | Examples are the ultimate docs anyway. As long as the actual plugin code looks nice, it's fine. | 22:34 |
drobilla | I don't see what you mean. | 22:34 |
falktx | I expect the c++ header to be updated together with the c headers | 22:35 |
drobilla | They will be. | 22:35 |
drobilla | Well, let's entertain the idea of a monolithic header, then | 22:36 |
drobilla | How to deal with features? optional and required, and failing | 22:36 |
drobilla | One downside is that some features are usable on the UI side too. Code duplication. | 22:36 |
falktx | we just get whatever the host provides | 22:36 |
falktx | and return safely if it's not available | 22:37 |
drobilla | Yes, but if you require one and the host doesn't provide it, just crashing is hardly a great solution | 22:37 |
drobilla | Return safely how? | 22:37 |
falktx | the ttl should include the requirement | 22:37 |
falktx | return nullptr etc | 22:37 |
drobilla | Yes, but how? | 22:37 |
drobilla | You want one class with everything baked in, so... how? | 22:37 |
drobilla | Seems to me any possible solution is at least as verbose as inheriting from a feature | 22:37 |
falktx | I mean I want to have stuff like "makePath()", "uridMap()" etc in the plugin class | 22:39 |
falktx | it will make documentation much easier | 22:39 |
drobilla | Which means monolithic class with everything LV2 in it. | 22:39 |
falktx | yes | 22:39 |
falktx | if the dev calls something, it must list that as required in the ttl | 22:39 |
falktx | the function documentation must say that | 22:40 |
drobilla | They do, but welcome to the real world. People fuck it up. | 22:40 |
drobilla | Presumably most feature implementations will not be overhead-free, too | 22:40 |
drobilla | Deprecation of anything becomes a mess | 22:40 |
drobilla | The only real downside is lack of a doxygen page that describes all possible methods in a flat class | 22:41 |
drobilla | Doesn't really seem to weigh out very well | 22:41 |
drobilla | and an example plugin that implements a stub of everything is as good if not better anyway | 22:41 |
falktx | it's only a few extra pointers | 22:42 |
falktx | vs using 3-4 more subclasses | 22:42 |
falktx | well, a few pointers and a few functions | 22:42 |
drobilla | I suppose a hybrid solution is possible | 22:44 |
drobilla | Plugin defined empty stubs for all the functions as it does currently | 22:44 |
drobilla | But the actual implementations that do all the C wrapping crap are in thingies you need to inherit | 22:44 |
drobilla | and those thingies can deal with the magic feature getting and so on | 22:45 |
drobilla | So the whole thing isn't crammed into a massive nasty header, yet there's still a single class doc that documents all methods | 22:45 |
drobilla | and still overhead/state free | 22:45 |
drobilla | (well, maybe a valid bool) | 22:45 |
drobilla | Doc-wise this would actually be pretty nice, since the method docs can describe what you need to do for that method to actually work | 22:47 |
falktx | drobilla: is this any good? https://gist.github.com/falkTX/31b0b6955a60bff9501c | 22:57 |
drobilla | falktx: lv2::Plugin can't have the overhead of every extension | 22:58 |
drobilla | falktx: The features themselves are approaching the right thing | 22:59 |
drobilla | falktx: But *instantiation* needs to fail if a required feature is not given | 22:59 |
drobilla | falktx: Having them set a flag on Plugin is the only way I can think of doing this | 22:59 |
falktx | we have lv2_instantiate to check for features | 23:00 |
falktx | and then only create the plugin class if they are all present | 23:00 |
drobilla | How can it do so? | 23:01 |
drobilla | dynamic_cast I guess, but ick | 23:01 |
*** edogawa has quit IRC | 23:03 | |
falktx | I don't see why this is such a big issue | 23:05 |
falktx | the plugin lists the *required* features in the ttl | 23:05 |
drobilla | Well, it is a simple fact that I have seen this happen all the time | 23:05 |
falktx | if a non-supported host still load it, it's broken | 23:05 |
drobilla | A decent wrapper can easily gracefully deal with this situation | 23:05 |
falktx | yes | 23:06 |
drobilla | That attitude just results in shitty flaky code | 23:06 |
drobilla | So unless there's some good reason it can't deal with it nicely, it should | 23:06 |
drobilla | In making standard wrappers I'm shooting for something solid we can rely on as, well, solid, and jive with extension in the future, and overhead-free | 23:07 |
drobilla | It requires a bit more thought than a whatever-the-fuck-I-want header utility for local projects, but c'est la vie | 23:07 |
drobilla | We're at, what, the 2 hour mark now? It's not quite rabbit hole territory yet :) | 23:07 |
drobilla | One of the main benefits of C++ is the smarter compiler makes enforcing things easy, so it's harder (or ideally impossible) to screw things up | 23:08 |
falktx | now you get me thinking | 23:08 |
drobilla | If we inherit from feature classes, it should be easy to ensure that a plugin not passed the required features is not instantiated whatsoever | 23:09 |
falktx | this header file should play nice with external extensions | 23:09 |
drobilla | Well, yes, that is one case where completely monolithic obviously falls apart | 23:09 |
falktx | but typing all the feature[i].URI == "that-uri" is tiresome | 23:10 |
falktx | maybe the features can be a simple template | 23:10 |
drobilla | I think avtk gets it mostly right | 23:10 |
falktx | you mean lvtk | 23:11 |
drobilla | er, right | 23:11 |
drobilla | Feature implementation classes can take a required parameter, and the features list | 23:11 |
drobilla | they'll scan the features themselves | 23:11 |
drobilla | (which is a bit more expensive than doing it once, but oh well) | 23:11 |
drobilla | So all plugin authors have to do is MyPlug(features) : URIMap(true, features) {} | 23:12 |
drobilla | The mixins let you not even have to do that, but other things get uglier | 23:12 |
falktx | what is the first "true" for ? | 23:14 |
falktx | required vs optional? | 23:14 |
drobilla | yeah | 23:14 |
drobilla | template parameter in lvtk, but I don't think there's a point to that, this way | 23:14 |
falktx | so it throws if not found? | 23:15 |
drobilla | Well, that's the question | 23:15 |
drobilla | The only non-exception solution I can think of is pass them a pointer to MyPlugin as well | 23:15 |
drobilla | They can do plug->set_valid(false) if things go pear shaped | 23:15 |
drobilla | Which kills the "overhead free" thing, but only by a bool... | 23:15 |
falktx | but for that you can simply pass a bool reference | 23:15 |
drobilla | ah-hah, so you can | 23:16 |
drobilla | though then the Plugin constructor interface would need to as well, which is a tad weird | 23:16 |
drobilla | better'n state, though | 23:16 |
falktx | I think the constructor needs an 'uri' parameter too | 23:19 |
drobilla | Well, instantiate probably should too, but it doesn't | 23:20 |
falktx | I mean for the feature class | 23:21 |
drobilla | Which means it's inherently static anyway | 23:22 |
falktx | I'll show you in 2mins | 23:22 |
drobilla | OK | 23:22 |
* drobilla wonders why the hell he made lib access via a function in the first place | 23:24 | |
falktx | drobilla: https://gist.github.com/falkTX/31b0b6955a60bff9501c | 23:28 |
falktx | drobilla: the c++ features get simple enough I think | 23:29 |
drobilla | I suppose that works | 23:30 |
drobilla | I don't think virtual is needed, though. Nothing will ever be freeing the plugin from a base class pointer | 23:30 |
falktx | it gets a compiler warning with -Wextra if it's not there | 23:31 |
drobilla | What warning? | 23:32 |
drobilla | Probably because you inherited from it with something virtual | 23:33 |
falktx | ah wait, it was -Weffc++ | 23:34 |
drobilla | That warns about everything ever | 23:34 |
falktx | I use it on my own code | 23:34 |
falktx | lv2.hpp:67:8: warning: base class ‘struct lv2::Feature<LV2_State_Make_Path>’ has a non-virtual destructor [-Weffc++] | 23:34 |
falktx | it doesn't hurt to have it there | 23:34 |
* drobilla shrugs | 23:34 | |
drobilla | Well, yes it does. It makes a vtable. | 23:34 |
falktx | the constructor already does that afaik | 23:35 |
drobilla | Nope. Nothing here will have vtables. | 23:35 |
drobilla | Seems everything can be done cleanly enough without. | 23:35 |
drobilla | Overhead-free wrapper >>> C++ as second class bloated citizen | 23:36 |
drobilla | Things like worker are the trickier part | 23:36 |
drobilla | Well, there's a sort of host-feature and plugin-interface split here | 23:36 |
drobilla | (The terminology surrounding this stuff is messier than it should be) | 23:37 |
falktx | first the features, then interfaces | 23:37 |
drobilla | The latter is going to affect the design, though. I wouldn't invest too much time before having the base sane | 23:38 |
drobilla | e.g. the 'feature' is probably going to need to be a template that takes a MyPlugin | 23:38 |
falktx | well in my case is to make the 2 example actually compile | 23:39 |
falktx | if it doesn't build it's a bad sign | 23:39 |
drobilla | Sure. Main goal for today is to get amp compiling with library, then a "feature implementation" and/or "interface implementation" base class in there if one is required | 23:42 |
drobilla | Then you or whoever can work on the repo to flesh things out | 23:42 |
drobilla | I wonder if inheriting from a C struct and not adding any virtuals or fields is guaranteed to get you something binary compatible... | 23:44 |
drobilla | Could make the static wrappers cleaner | 23:44 |
falktx | the external ui does that actually | 23:45 |
falktx | since it has no "handle" | 23:45 |
drobilla | That whole handle thing is an unfortunate mess, too :/ | 23:45 |
drobilla | What we should have done is had a standard LV2-wide extensible struct header | 23:46 |
drobilla | size, maybe version, handle | 23:46 |
drobilla | Hm. So could/should Plugin/Lib inherit from LV2_Descriptor/LV2_Lib_Descriptor... | 23:48 |
falktx | hmmm now we need a way to know if a feature is available | 23:49 |
falktx | (on the plugin constructor) | 23:49 |
drobilla | This brings me back to MyPlug : public lv2::Plugin<MyPlug> | 23:49 |
drobilla | i.e. template<class Derived> Plugin; | 23:50 |
falktx | that's sorta the same case | 23:51 |
drobilla | I'm just wondering if it's worth if it the only point is making the static stuff a bit cleaner, which plugin authors don't give a crap about | 23:52 |
falktx | what should the dev do to check if a required feature is not present in the plugin constructor? | 23:58 |
falktx | we can itenerate over the features uris, but that won't look very c++-ish | 23:58 |
Generated by irclog2html.py 2.13.0 by Marius Gedminas - find it at mg.pov.lt!