# Setup

## Requirements

The PRESTOplay SDK for Apple is available as an XCFramework and can be integrated via Swift Package Manager (SPM) or CocoaPods. All required dependencies are either:

- Contained in the bundle repository
- Available on a public repository like CocoaPods or Swift Package Manager (SPM)

To work with the PRESTOplay SDK for Apple you need to use the Xcode for your application builds.

## License

Create License Keys tied to your application bundle through https://downloads.castlabs.com

The license model allows activating additional plugins and changing the expiration date of the license remotely. This helps avoid service interruptions when the license expires and you cannot quickly redeploy your application.

In our download portal you go to the license you need and select Manage keys: As you do not have any keys associated with the license, you will be shown this message: Please select Create a key. After this you are taken to this screen:

### License User Identification

By default, the licensing portal automatically generates a PRESTOplay for Apple license with “User ID required” flag enabled.

This means that in order to start playback (besides passing the license key), customer needs to pass `User ID` as well (or `viewerId` in the SDK analytics terminology).

Below you can find a place in the `PlayerConfiguration` to set the `userId` assigned to the SDK license:

    let playerConfig = PlayerConfiguration(with: URL(string: stream)!)
    playerConfig.userId = "user-id-app"

## Project setup

1. Unzip the installation bundle

2. Add `PRESTOplay.xcframework` file to your project “Frameworks, Libraries, and Embedded Content”. Choose “Embed & Sign” as the “Embed Option”

3. (Optional) Repeat step (2) for any additional plugin frameworks

## Initialization

Pass the license string and the list of plugins you want to activate to the `register()` method

    import PRESTOplay
    import CastlabsApple
    import CastlabsVT

    let _ = PRESTOplaySDK.shared.setup("LICENSE", [HLSPlugin(), VTPlugin()])

## Jailbreak detection

During `PRESTOplaySDK.shared.setup(...)`, the SDK performs a device-integrity check and blocks initialization on jailbroken devices.

On Apple platforms, this is reported as a fatal error:

- `PRESTOerror.type == .sdk_jailbroken_device_detected`

The setup call returns this error directly:

    if let error = PRESTOplaySDK.shared.setup("LICENSE", [HLSPlugin()]) {
        if error.type == .sdk_jailbroken_device_detected {
            // Device integrity check failed.
        }
    }

It’s your app’s responsibility to set the correct category for `AVAudioSession`. If your app does only playback, `AVAudioSessionCategory.playback` is sufficient. If your app does playback and record, use `AVAudioSessionCategory.playAndRecord`. You only need to do this once per app lifetime.

    let audioSession = AVAudioSession.sharedInstance()
    do {
        try audioSession.setCategory(.playback)
        try audioSession.setActive(true, options: .notifyOthersOnDeactivation)
    } catch {
        log_e("Cannot initialize audio session")
    }

## Error handling

Because all player preparations and most playback operations occur asynchronously, errors are reported through the `PRESTOplaySDK.shared.onError` block. Attach your handler before opening any content. Opening content can already raise an error, for example if the manifest URL does not provide data, and those errors are only reported through the `onError` callback.

    PRESTOplaySDK.shared.onError = { component, error in
        if error.type == .player_avplayer_error &&
            error.severity == .warning {
            // filtered error
        }
    }

Fatal errors are also reported in the `PlayerAPI` `onState` block as they impact the overall session state.

## SDK assumptions

1. Minimal supported iOS/iPadOS/tvOS version is set to 13.
2. Frameworks in SDK are built as dynamic frameworks.

### Supported platforms

- iOS/iPadOS and tvOS: Unified iOS, iPadOS, and tvOS SDK enable comprehensive support for each platform, ensuring seamless API interoperability and feature compatibility.

- Mac: The SDK provides support for Macs with Apple Silicon.

## Test projects

Included in the main package `examples/` directory.

1. `examples`

Simple demo examples that test the building of core features and plugin integrations. They are meant to work without any user interaction and with a very simple UI.

Examples are built with UIKit.

1. `examples/Demos`

More complicated demo (all-in-one app) with specialized examples and use-cases. For instance: if you want to present / test WebVTT subtitles it is fine to create a `Demo` for that use-case.

Demo applications are built with `SwiftUI`.

## Crash reports

If a crash occurs when using our release builds, you will see that part of the stack trace is obfuscated due to security reasons. However there’s still a way to re-symbolicate the crash if you send us the load address of our libraries at crash time.

Crash dumps retrieved directly from the device

If the crash dump is retrieved directly from the device via Xcode (Window → Devices → View Device Logs), all the info we need is in the crash log itself:

- Architecture: Check if ARM or ARM-64 in the Code Type line

- Load address: Either check in the Binary Images, or directly from the stack line (the load address in the line “0 CastlabsDASH 0x00460b8a 0x2be000 + 1715082” is 0x2be000)

Crash dumps retrieved via Crashlytics

Crashlytics doesn’t let you know the load address of the binaries, but it still reports the actual address in memory of a symbol, not the offset from the load address, in its stack traces. You need to attach information about the load addresses to the crash dump via Crashlytics Key-Value system.

Get load addresses and pass them to Crashlytics

    var index: UInt32 = 0
    while index < _dyld_image_count() {
        let header = _dyld_get_image_header(index)
        if let name = String(validatingUTF8: _dyld_get_image_name(index)), name.contains("Castlabs") {
            header.debugDescription
            break
        }
        index += 1
    }

Retrieve them from Crashlytics web UI: select a crash then choose “View All Sessions”. Download the stack trace and text file and copy the pseudo-json with the load addresses for the “CASTLABS LOAD ADDRESSES” key in the “Keys” section.

The Crashlytics stack trace does not specify the CPU architecture, but it contains the device type so you can match it up by looking at the device specs.

## CocoaPods and Swift Package Manager

Our SDK can be included and set up via CocoaPods or Swift Package Manager (SPM).

The list of supported plugins for each platform can be found in the SDK bundle: `configs/` (for instance: `configs/release-ios-plugins`, `configs/release-tvos-plugins`, `configs/release-catalyst-plugins`).

Access to Cocoapods and SPM is public for `v4`. Please check `examples` to see pods or SPM integrations.

CocoaPods version required is >= 1.10.0. The SDK consists of Dynamic Frameworks.

## Swift Package Manager packages

We provide two SPM repositories, depending on the integration mode you want:

- Complete package (includes all SPM dependency declarations for supported integrations): https://github.com/castlabs/prestoplay-apple-spm
- Core package (framework binaries only, no extra third-party SPM dependencies): https://github.com/castlabs/prestoplay-apple-core-spm

Use the complete package when you want a single package that already declares external dependencies (Google Cast, IMA, Broadpeak, Youbora, Conviva, Mux, Protobuf).

Use the core package when you want to control third-party dependency integration manually in your app.

### Widevine integration

`CastlabsVTWithWidevine` requires the Widevine framework to be added manually to your Xcode project. The framework is part of the package downloaded from the Download Portal.

## Third-party dependency versions

Dependency | Version
--- | ---
NpawPluginPkg | 7.3.31
ConvivaSDK | 4.0.47
SmartLib-v3/Generic | 06.00.02.845a8c7
SmartLib-v3/Generic+tvOS | 06.00.02.845a8c7
google-cast-sdk-dynamic-xcframework | 4.8.4
GoogleAds-IMA-iOS-SDK | 3.27.4
GoogleAds-IMA-tvOS-SDK | 4.12.0
Mux-Stats-Core | 5.13.0

Dependency versions used by our SPM templates are defined in `configs/deps-versions` in the SDK package.

The generated complete SPM package also contains these resolved versions:

- https://github.com/castlabs/prestoplay-apple-spm