SplitmediaLabsLimited / xjs

XSplit JS Framework. Make plugins for XSplit Broadcaster, quickly and easily.
Other
39 stars 11 forks source link

Feature request: Better error reporting when changing source values #297

Closed matthijskooijman closed 4 years ago

matthijskooijman commented 4 years ago

I'm working (together with @BrendaH) on an extension that replaces the source values for sources in a presentation using some regexes. This potentially results in sources pointing to non-existent files, which I'd like to report to the user if that happens.

Currently setValue() just accepts non-existent files happily. XBC does know that the file is missing, as indicated when opening the source settings window in the GUI afterwards.

I can imagine that setValue() would raise an error when the source does not exist. On the other hand, if that would be done, it is no longer possible to assign a path to a source if you do not currently have the corresponding file on your computer, which seems like a big limitation.

I've looked for an API that exposes the the "missing source" error status (or broader, maybe some source health status) that XBC shows in the GUI, but could not find one.

Currently, I am using the getFileInfo() for MediaSources(), which throws when the file does not exist or is otherwise invalid, and using the fact that an ImageSource changes from type BITMAP to type FILE when the image does not exist, but that is not really general.

I think I could use DLL access to explicitly check for file existence, but:

So, could some status be exposed for a source?

SML-MeSo commented 4 years ago

Will have to discuss with the team since the missing source error status is only available for file-type sources such as MediaSource, FlashSource, HtmlSource, etc. Maybe we can include other checks for the remaining types...

As for your usage, I think you can use these steps (via xjs.exec), if you need to for now, for checking of status (the one used by source properties dialog):

const videoItemID = myItem._id; // get the videoitem ID xjs.exec('SearchVideoItem', videoItemID); // attach the videoitem xjs.exec('GetLocalPropertyAsync', 'prop:itemavail', status => console.log(status)) // get availability, returns as 1 or 0

Unfortunately, should you need a return to xjs.exec, the last parameter should be a callback, so up to you to promisify it.

matthijskooijman commented 4 years ago

Will have to discuss with the team since the missing source error status is only available for file-type sources such as MediaSource, FlashSource, HtmlSource, etc. Maybe we can include other checks for the remaining types...

For us, that would probably sufficient, and already a good addition.

As for your usage, I think you can use these steps (via xjs.exec), if you need to for now, for checking of status (the one used by source properties dialog):

Ah, nice, I'll try that. Am I understanding correctly that something like Item.get('prop:itemavail', myItem._id) would essentially do the same thing (but cannot be used since the Item class is internal)?

I also looked around the source for SearchVideoItem and AFAICS it attaches an item (or source?) to one of 2 slots that can be used for further manipulation? The name is probably legacy, since it seems to work on non-video items as well. Looking at the code for Item.attach(), I am a bit confused about how this works. There seems to be no synchronization there (other than allowing locking source plugins to slot 0) for parallel requests. E.g. Item.get first does an attach and then a GetLocalPropertyAsync passing the slot number rather than the item id to get the property. Since the attach is async, how are problems prevented when you do multiple gets in parallel, so first kick of a dozen attaches, then after all of them return, the GetLocalPropertyAsync's are started, all operating on the last attached item? This does not seem to happen in practice (we initially processed sources in parallel which worked, but did seem a bit slower than doing them sequentially as we do now), so I guess there is some mechanism in place here?

SML-MeSo commented 4 years ago

Item.get('prop:itemavail', myItem._id)

Yup, that's basically it.

Oh, and attaching thru AttachVideoItem and SearchVideoItem is sync, which kind of prevents the calls to be misdirected. In theory, it would be better to do a single attach, call all property settings to that videoitem, then proceed to the next one. The XJS framework prioritized ease of use over efficiency, and opted to introduce simpler methods, which is sufficient for normal uses. However, that was also one of the reasons why the exec function was exposed, to provide an alternate way to use new properties without waiting for the actual XJS framework, and as an option to bypass some of these inefficiencies, especially for plugins and extensions having multiple and core-API-intensive processes.

matthijskooijman commented 4 years ago

Great, the xjs.exec approach seems to work fine, thanks!

Oh, and attaching thru AttachVideoItem and SearchVideoItem is sync, which kind of prevents the calls to be misdirected.

Ah, if they're synchronous, then things would work out I guess. Looking at xjs.exec I can't see any evidence of sync-ness, but I guess you'll know ;-)

In theory, it would be better to do a single attach, call all property settings to that videoitem, then proceed to the next one.

I think this already happens: attach does a quick return if the right item is already attached. And that could very well explain while changing our code to process 1 source at a time is indeed faster than doing them in parallel :-)