Beginning with FxFactory 5.0.8, a new API allows any code executing on the system to interact with FxFactory. The primary goals of this API is to allow products that do not rely on the FxFactory runtime to do the following:
Checking for the licensing status of a product allows you to decide whether the product should run in trial mode or with its full feature set. Trial products may choose to render a watermark in its output, hide or limit certain functionality, etc.
When your code detects an error, your code can migrate any diagnostic information about the error to a new tech support contact form (for example: ”An error occurred reading file X when processing a frame with plug-in Y.”) This allows for faster resolution of any problems users may encounter with your product.
The API described above is provided by the FxFactory.framework. This framework is available on your system as long as any recent version of our software is installed.
To get a copy of the FxFactory.framework, all you have to do is install a recent version of FxFactory. The framework’s install location is:
/Library/Frameworks/FxFactory.framework
Add this framework to your project, and make sure it is part of the link phase for the appropriate target (or targets) that will need to use our API. We recommend that you link to our framework weakly, allowing your code to run even if the FxFactory.framework
is missing from the system. The user may have uninstalled FxFactory, or deleted the framework by accident.
Start by adding the framework to your project. Drag the FxFactory.framework
from the Finder to the Frameworks, Libraries, and Embedded Content section of your target:
If this is the first external framework you add to your target, Xcode will automatically create a Frameworks folder in your file hierarchy, and add the FxFactory.framework
to it:
Select the framework:
While the framework is selected, open the inspector and right-click on each target that links against it. Switch the linking strategy to Optional:
When your code weak-links to the FxFactory.framework
, its symbols may not be available at runtime. This would happen if FxFactory is not installed. The recommended approach is to treat the product as unlicensed (e.g. running in trial mode) and request the user to download and install a copy of FxFactory from our website.
Refer to this page on the Apple developer website for a detailed explanation of weak-linking:
In most situations, the app or loadable plug-in you are working on will necessarily have the Hardened Runtime option enabled. Since your software is code-signed using a different identity than FxFactory, the Hardened Runtime will, by default, disallow your code from accessing the FxFactory framework while running.
To solve this problem, you need to enable the Disable Library Validation option available under the Signing & Capabilities section of your Target configuration:
Note that in Debug builds and/or while running your software through the debugger, you may not encounter any problems accessing the FxFactory framework due to the fact that certain rules of the Hardened Runtime are automatically relaxed. Make sure the Disable Library Validation option remains enabled for the Release version of your product.
When planning to use the FxFactory framework from an FxPlug plug-in, you need to take some additional measures to ensure that our framework is allowed to load, and access relevant licensing information for your product.
The entitlements you pick for the PlugInKit wrapper app do not matter, but the ones you choose for the actual FxPlug component do. Make sure the App Sandbox is turned off. If you followed the previous instructions related to the Hardened Runtime your entitlements file should also contain the entry that disables library validation:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "https://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>com.apple.security.app-sandbox</key>
<false/>
<key>com.apple.security.cs.disable-library-validation</key>
<true/>
</dict>
</plist>
It is necessary to turn off the App Sandbox for the PlugInKit process because your plug-in would otherwise be unable to read any licensing information for your product. Since FxFactory records this information via NSUserDefaults
on its own domain, any sandboxed process would not – by default – be able to access this information outside its container. While Apple offers ways for code signed by the same team ID to access common NSUserDefaults
domains, there is no way for one app (FxFactory) to grant access to its domain to just about any other process out there.
If you hard-linked to the FxFactory framework, your code will cause an error if the framework is not installed on disk. When you weak-link your binary to the FxFactory framework (as recommended) the linker resolves all weak symbols automatically if the framework is installed. Symbols remain NULL
otherwise.
Remember to test you code with and without the FxFactory.framework. Drag the framework away from its install location to prevent it from being loaded by your code.
The API exposed by the framework is located in the FxFactoryLicensing.h
header. It is a simple, C-based API. If you have weak-linked your code against the FxFactory framework, check for each function pointer to be non-NULL before invoking it. Heed the warning contained in the official Apple documentation: use the explicit comparison against NULL rather than the ! operator, or else it will not work as expected:
#import <FxFactory/FxFactory.h>
FxFactoryLicensingStatus status = kFxFactoryLicensingStatusProductUnlicensed;
if (FxFactoryGetLicensingStatus != NULL) {
status = FxFactoryGetLicensingStatus(...);
} else {
// Remind user that FxFactory must be installed
}
if (status == kFxFactoryLicensingStatusProductIsLicensed) {
// Product has been purchased.
}
Refer to the documentation in the header for an explanation of the API, the meaning of its parameters, and the meaning of the values returned by each function.
It is important to point out certain requirements and behaviors of the API:
FxFactoryGetLicensingStatus()
is dynamically updated while your code is running. If you wish to handle changes to the licensing status dynamically, refer to the new FxFactoryRegisterLicensingStatusChangeHandler()
API. FxFactory.isInstalled()
, your code can use to check if our APIs can be invoked without crashing the app. FxFactoryGetLicensingStatus
, can be invoked from Swift via FxFactory.licensingStatus(for:)
. Look for the parameter to the NS_SWIFT_NAME
macro in the the header file to determine how each function may be invoked from Swift. The code required to check if your product has been licensed through FxFactory from a Swift app is extremely simple:
import FxFactory
static func isLicensed() -> Bool {
FxFactory.isInstalled() &&
FxFactory.licensingStatus(for: <UUID>) == .productLicensed
}
Where <UUID>
is the string representation of the UUID that uniquely identifies your product within our ecosystem.
If you plan on delivering your software as a codesigned application, remember to add the appopriate entries to the Info.plist
of each deliverable bundle (app, plug-in, etc) to allow FxFactory to update your software:
{
"NSUpdateSecurityPolicy": {
"AllowPackages": [
0: "AZLNLGPTT3"
]
"AllowProcesses": {
"AZLNLGPTT3": [
0: "com.fxfactory.FxFactory”,
1: “com.fxfactory.FxFactory.helper”
]
}
}
}
This is discussed in greater detail on Developer.