docs: Add examples and undocumented callback funcs#10756
Conversation
RytoEX
left a comment
There was a problem hiding this comment.
Some notes. Would appreciate a review from someone else who is more familiar with these functions.
|
Applied requested changes, thanks |
Adds the following undocumented functions: - calldata_set_data - calldata_get_int - calldata_get_float - calldata_get_bool - calldata_get_ptr - calldata_get_string - calldata_get_data
RytoEX
left a comment
There was a problem hiding this comment.
Looks fine to me, though would still appreciate a second opinion from someone more familiar with the usage of these items.
|
Maybe cc @gxalpha or @FiniteSingularity |
| .. function:: void calldata_set_ptr(calldata_t *data, const char *name, void *ptr) | ||
|
|
||
| Sets a pointer parameter. | ||
| Sets a pointer parameter. This does not have to be a pointer to a pointer. |
| ---------------- | ||
|
|
||
| Use :c:func:`signal_handler_connect()` to connect callbacks to the following | ||
| core OBS signals: |
There was a problem hiding this comment.
| core OBS signals: | |
| global core libobs signals: |
| :param data: Calldata structure | ||
| :param name: Parameter name | ||
| :param in: Pointer to the value to be stored | ||
| :param new_size: Size of the value to be stored |
There was a problem hiding this comment.
cc @RytoEX "of value to be stored" sounds off to me, but I'm not a native English speaker. Is this correct?
| :param data: Calldata structure | ||
| :param name: Parameter name | ||
| :param val: Pointer to an integer receiving the parameter | ||
| :return: ``true`` if the stored value is successfully cast |
There was a problem hiding this comment.
IMO "is successfully cast" implies more type safety guarantees than there actually are. I guess saying it does a cast is technically correct, but since it doesn't check for anything other than the size of the data (unlike e.g. an std::variant), I find "successful" a bit misleading.
I would just do something like this:
| :return: ``true`` if the stored value is successfully cast | |
| :return: ``true`` on success, ``false`` otherwise |
|
|
||
| .. function:: bool calldata_get_int(const calldata_t *data, const char *name, long long *val) | ||
|
|
||
| Gets an integer parameter. See :c:func:`calldata_int` for a simpler call. |
There was a problem hiding this comment.
Maybe just this?
| Gets an integer parameter. See :c:func:`calldata_int` for a simpler call. | |
| Gets an integer parameter. See also :c:func:`calldata_int`. |
Alternatively, explain the use cases for the respective functions in the docs for both functions. See the relevant header file:
obs-studio/libobs/callback/calldata.h
Lines 124 to 129 in 1ecea56
| Example connecting to ``rename`` signal from :ref:`source_signal_handler_reference`, | ||
| declared as ``void rename(ptr source, string new_name, string prev_name)``: | ||
|
|
||
| .. code:: cpp | ||
|
|
||
| /* Sample source data */ | ||
| struct my_source { | ||
| obs_source_t *source; | ||
| char *prev_name; | ||
| ... | ||
| }; | ||
|
|
||
| void rename_cb(void *data, calldata_t *cd) { | ||
| struct my_source *ms = data; | ||
| obs_source_t *source = calldata_ptr(cd, "source"); | ||
| /* We could also just access the source from our source data */ | ||
| source = ms->source; | ||
| const char *new_name = calldata_string(cd, "new_name"); | ||
| const char *prev_name = calldata_string(cd, "prev_name"); | ||
|
|
||
| /* Do processing here */ | ||
|
|
||
| /* `prev_name` will be freed after the callback, so if we want a | ||
| * reference to it after the callback, we must duplicate it. | ||
| */ | ||
| bfree(ms->prev_name); | ||
| ms->prev_name = bstrdup(prev_name); | ||
| } | ||
|
|
||
| /* Assuming `ms` already contains our source data */ | ||
| struct my_source *ms; | ||
| signal_handler_t *sh = obs_source_get_signal_handler(ms->source); | ||
| signal_handler_connect(sh, "rename", rename_cb, ms); | ||
|
|
There was a problem hiding this comment.
Not a fan of how long this example is. I think it should be fine to cut it down a bit:
| Example connecting to ``rename`` signal from :ref:`source_signal_handler_reference`, | |
| declared as ``void rename(ptr source, string new_name, string prev_name)``: | |
| .. code:: cpp | |
| /* Sample source data */ | |
| struct my_source { | |
| obs_source_t *source; | |
| char *prev_name; | |
| ... | |
| }; | |
| void rename_cb(void *data, calldata_t *cd) { | |
| struct my_source *ms = data; | |
| obs_source_t *source = calldata_ptr(cd, "source"); | |
| /* We could also just access the source from our source data */ | |
| source = ms->source; | |
| const char *new_name = calldata_string(cd, "new_name"); | |
| const char *prev_name = calldata_string(cd, "prev_name"); | |
| /* Do processing here */ | |
| /* `prev_name` will be freed after the callback, so if we want a | |
| * reference to it after the callback, we must duplicate it. | |
| */ | |
| bfree(ms->prev_name); | |
| ms->prev_name = bstrdup(prev_name); | |
| } | |
| /* Assuming `ms` already contains our source data */ | |
| struct my_source *ms; | |
| signal_handler_t *sh = obs_source_get_signal_handler(ms->source); | |
| signal_handler_connect(sh, "rename", rename_cb, ms); | |
| Example connecting to ``rename`` signal from :ref:`source_signal_handler_reference`: | |
| .. code:: cpp | |
| obs_source_t *source = ...; | |
| void rename_cb(void *data, calldata_t *cd) { | |
| obs_source_t *source = calldata_ptr(cd, "source"); | |
| const char *new_name = calldata_string(cd, "new_name"); | |
| const char *prev_name = calldata_string(cd, "prev_name"); | |
| /* Do processing here */ | |
| } | |
| signal_handler_t *sh = obs_source_get_signal_handler(source); | |
| signal_handler_connect(sh, "rename", rename_cb, NULL); |
If you want to emphasize the lifetime of the calldata_t object, just a comment like this below /* Do processing here */:
/* Keep in mind that any pointers from ``cd`` are only valid in the scope of the callback */
| /* Sample source data */ | ||
| struct my_source { | ||
| obs_source_t *source; | ||
| bool active; | ||
| ... | ||
| }; | ||
|
|
||
| static void proc_activate(void *data, calldata_t *cd) | ||
| { | ||
| struct my_source *ms = data; | ||
| ms->active = calldata_bool(cd, "active"); | ||
| } | ||
|
|
||
| /* Assuming `ms` already contains our source data */ | ||
| struct my_source *ms; | ||
| proc_handler_t *ph = obs_source_get_proc_handler(ms->source); | ||
| proc_handler_add(ph, "void activate(bool active)", | ||
| proc_activate, ms); |
There was a problem hiding this comment.
Shorter version:
| /* Sample source data */ | |
| struct my_source { | |
| obs_source_t *source; | |
| bool active; | |
| ... | |
| }; | |
| static void proc_activate(void *data, calldata_t *cd) | |
| { | |
| struct my_source *ms = data; | |
| ms->active = calldata_bool(cd, "active"); | |
| } | |
| /* Assuming `ms` already contains our source data */ | |
| struct my_source *ms; | |
| proc_handler_t *ph = obs_source_get_proc_handler(ms->source); | |
| proc_handler_add(ph, "void activate(bool active)", | |
| proc_activate, ms); | |
| obs_source_t *source = ...; | |
| static void proc_activate(void *data, calldata_t *cd) | |
| { | |
| bool active = calldata_bool(cd, "active"); | |
| /* Do processing here */ | |
| } | |
| proc_handler_t *ph = obs_source_get_proc_handler(source); | |
| proc_handler_add(ph, "void activate(bool active)", proc_activate, NULL); |
| Adds a procedure to a procedure handler. Will fail if the declaration string | ||
| has invalid syntax or a procedure with the same name was already added. Other | ||
| than the function identifier, the ``decl_string`` is mostly for | ||
| documentation, as libobs does not strictly enforce how the parameters are | ||
| handled. |
There was a problem hiding this comment.
I would remove anything after "Will fail if the declaration string has invalid syntax or a procedure with the same name was already added.", I'd say the missing verification is more of a somewhat unfortunate implementation detail.
Adds the following undocumented functions:
Description
Also adds details and examples on the following functions

Disclaimer: For the additional text under the Common Source Signals, Source-specific signals and procedures, and Core OBS Signals, I first wrote my own description for it, and had ChatGPT assistance for grammar and conciseness improvements, and manually reviewed its responses, not using them blindly.
Motivation and Context
Undocumented functions, and unclear how to use source signals and procs. Let's lower the barrier to entry for developers.
How Has This Been Tested?
Built the docs and viewed locally. Code examples aren't fully tested, but i wrote those first in an ide (for syntax highlighting and code completion, ensuring the functions exist) and having references in the obs source code that i merely adapted. I've also used these functions before so I know them.
Types of changes
Checklist: