Hey Stefan,
since you're brain storming here and started a discussion, I'm taking this to the list and off the bug tracker. There are a few reasons I have not attempted to add enforcement with the new IDL API. First, the range information the IDL layer has is informal and mostly passed from *.idl to the __aida_aux_data__() method as opaque string. Second, even if the IDL layer was extended to parse the information and we'd start to formally specify what information has and has not to be present per property, it's not clear to me at what layer we'd generate automatic enforcement. Note that it gets even more tricky in the actual implementation, see my inline remarks below. On 31.08.2018 21:33, Stefan Westerfeld wrote:
The above actually needs to be changed to the following order: if (int (self->denominator) != val) { val = CLAMP (val, 1, 256); // ... notify (prop); } Here's why: a) A user enters -77 at the UI, which is reflected by a text entry or slider. b) The UI sends -77 through the IDL layer. c) The impl refuses -77 and CLAMPs it to 0, or maybe retains the old value, e.g. 10. d) Because the value the UI displays (-77) and the value that was sent (-77) is different from the resulting value in the impl (e.g. 0 or 10), a change notification *must* be sent back to the UI (and other monitoring instances), in order for the UI to be notified that the value being displayed has to be updated by querying the impl again. Now, whether the impl CLAMPs or ignores the setting is entirely up to the implementation. And whether a property needs undo recording (e.g. a bpm change) or no undo recording (like a play position or loop pointer), is also entirely up to the implementation. Furthermore, whether a value can currently be changed (like the instrument setup used on a track) may depend on whether a project is currently in playback mode or not (that's the BSE_SOURCE_PREPARED flag in libbse), so entirely up to the implementation.
There's no "pspec" in the new API, while we still generate compat pspecs for the old beast-gtk code from the IDL aux info, there's no such thing in ebeast. I.e. checks can only be performed against __aida_aux_data__ strings. And without special knowledge about properties, etc, those look just like a bunch of foreign gibberish characters.
As I said, above, we don't have that anymore.
That would break the SynDrum trigger button.
That highly depends on the property and I'd rather not push that into the IDL layer as well.
Notification is implemented at the Bse::Object layer, not the IDL layer below that, so that'd be tricky also.
Yeah, I appreciate that in principle, but I hope I have succeeded in outlining why I thought there's no trivial and obvious way to implement this. I hear what you mainly want to simplify though, and I think a good chunk of that can be achieved with convenience macros, even if that's less elegant to the trained C++ eye. Assuming we move properties in to the *Impl classes and out of the C structs at some point, this could look like: void SongImpl::bpm (int val) { const bool changed = UPDATE_UNDO_PROPERTY (bpm_, val); if (changed) this->trigger_other_updates(); } With the following impl details, UPDATE_UNDO_PROPERTY(member_,value) would: 1) compare this->bpm_ != value 2) extract aux_info strings for "bpm", to perforrm range constraints 2) push the old value to undo (there could be an UPDATE_PROPERTY variant without undo) 3) notify("bpm"), the string "bpm" is probably best inferred from __func__, since that's the one IDL generated piece of information that UPDATE_PROPERTY has access to which perfectly matches the property name. We would need a couple test cases to assert that the runtime platform really assigns the property setter name to __func__ correctly, though. But afaik, that should be true for g++ (linux, windows) and clang (linux, windows, macos). As long as we keep the C structs around, we probably have to live with something like: BseSong *self = as<BseSong*>(); UPDATE_UNDO_C_PROPERTY(&self->bpm, val); Note that meta info about "bpm" can still be extracted and notifications for "bpm" can still be sent out by this macro, if we infer the property name from __func__.
-- Yours sincerely, Tim Janik --- https://testbit.eu/timj/ Free software author. |