Skip to main content
Inspiring
August 14, 2020
Question

Update main After Effects UI from custom UI thread

  • August 14, 2020
  • 1 reply
  • 1195 views

Hi. I am running  a custom UI in a separate thread. The custom UI sets a global counter when the user clicks on Update button.

Then I call, in the custom UI thread

AEGP_SuiteHandler suites(sP);
suites.AdvAppSuite2()->PF_RefreshAllWindows();

the sP value is set in GlobalSetup as sP = in_data->pica_basicP;

The plan is that I can use the global counter to update a hidden param in UpdateParameterUI to force render.

However, the app is crashing on the line

suites.AdvAppSuite2()->PF_RefreshAllWindows();

 

Any ideas ?

 

This topic has been closed for replies.

1 reply

AnmolMAuthor
Inspiring
August 14, 2020

@shachar I'll post some notes from your replies to similar questions. It would be nice to have an example of a custom UI thread and how it interacts with main Adobe app.

 

in general, the AE API is not thread safe. there are very few calls that are, and they are noted so in the docs. (such as AEGP_CauseIdleRoutinesToBeCalled)

you can only call AE when AE is actually listening, which means either from the ui thread, render thread, or in some occasions, other threads that are created by the iterations suites, but only while executing that suite call from one of the main threads...

lookup AEGP_CheckoutOrRender_ItemFrame_AsyncManager in the docs. you'll either have to adapt your process to that mechnism, or get your frame data from one of the main thread,s and the do you processing on whatever thread you like without calling AE from it.

AND

there are some very few calls that can by made asynchronously. most of

which are rendering related calls that are indeed multi-threaded but are

all executed during a single render call.

the one exception is AEGP_CauseIdleRoutinesToBeCalled(), which is safe to

call from any thread. all other attempts to talk to AE from a custom thread

instead of one of AE's calls will result in catastrophic crashes...

to do what you describe, you should probably use idle_hook to execute your

changes, and instead of storing an AEGP_EffectRef, you should store your

effect's index on the layer, layer id and comp item id. then during idle

hook you lookup the comp, the layer in the comp and the effect on the

layer, to get a fresh AEGP_EffectRefH for usage during that idle hook call.

all other item refs such as AEGP_LayerH and AEGP_CompH are not guaranteed

to keep beyond the scope of a single AE call. (sometimes they do, but often

they don't)

AND

1. AEGP_CauseIdleRoutinesToBeCalled(). it can be called from the non-main

thread (as long as you acquire it from the main thread), and causes idle

hook to be called ASAP. this can shorten your interactive time lag.

2. create your window as an AE panel (see the "panelator" sample project).

i think panels can interact with AE's API during mouse

down/click/draw/ect...

Adobe Expert
August 14, 2020

welp, that pretty much sums it up...

i'd just add that it's perfectly fine to do ui work in a separate thread, just do the actual ui update on the designated AE evetns. during said event, access your separete thread's data (probably using some mutex). that's it.

AnmolMAuthor
Inspiring
August 14, 2020

To make sure I understood this...

In EntryPointFunc() add,

case PF_Cmd_COMPLETELY_GENERAL:
			err = RespondtoAEGP(in_data,
				out_data,
				params,
				output,
				extra);

Example of RespondToAEGP

static PF_Err
RespondtoAEGP(
	PF_InData* in_data,
	PF_OutData* out_data,
	PF_ParamDef* params[],
	PF_LayerDef* output,
	void* extraP)
{
	PF_Err			err = PF_Err_NONE;
	AEGP_SuiteHandler suites(in_data->pica_basicP);

	// Get data from extraP if needed, else just use shared static var with mutex
        // Make changes to Adobe stuff here
	return err;
}

And in the custom UI thread add, use static var sP, previously set in GlobalSetup - sP = in_data->pica_basicP;

AEGP_SuiteHandler		suites(sP);
suites.UtilitySuite6()->AEGP_CauseIdleRoutinesToBeCalled();

Is that all correct ?