Developers     Developer center

Developer center

under hero banner

Source SDK Development Guide

WSB_Config

Usage

The WSB_Config methods are ones whose default implementations can be replaced and customized for different platforms. Currently, there is only one such method: WSB_Config_ValidateActionResult.

WSB_Config_ValidateActionResult can be called to analyze a SHI_ActionResult. A SHI_ActionResult is obtained, for example, when WSB_PlaybackEnabler_PerformPlayAction is called. A SHI_ActionResult is also obtained whenever a license is found during a license search initiated by a call to WSB_PlaybackEnabler_EnableMediaFile or WSB_RightsEnabler_EnableMediaFile.

The SHI_ActionResult contains information about access rights and requirements that must be satisfied prior to playing the relevant content (such as the content for which a license was being searched). These requirements include constraints referred to as obligations and callbacks. Obligations represent things that the application is required to perform or obey. Callbacks are functions that the application is required to call under specified conditions.

WSB_Config_ValidateActionResult has four parameters:

  1. A pointer to the SHI_ActionResult you want analyzed.
  2. A WSB_Boolean whose value should be WSB_TRUE if the SHI_ActionResult was generated as a result of a SHI_Action_Perform (which is the case if it was generated by a call to WSB_PlaybackEnabler_PerformPlayAction). The value should be WSB_FALSE if the SHI_ActionResult was generated as a result of a SHI_Action_Check, which is the case whenever a license is found during a license search.
  3. The name of an action. WSB_Config_ValidateActionResult determines whether the specified action is allowed. Typically, you want to know whether playback of the content is allowed, so for this parameter you specify SHI_ACTION_PLAY. The text below assumes you have specified this action.
  4. Any parameters required by the action. This is typically NULL, since the Play action does not have any parameters. WSB_Config_ValidateActionResult calls WSB_ActionResultInfo_Create, passing it the SHI_ActionResult, and then subsequently calls WSB_ActionResultInfo methods to determine whether the Play action is allowed (that is, whether the content governed by the license is allowed to be played) and whether all of the mandatory obligations and callbacks (if any) can be satisfied. If the action is granted and all mandatory obligations and callbacks can be satisfied, WSB_Config_ValidateActionResult returns WSB_SUCCESS. If the action is not granted, it returns WSB_ERROR_DRM_DENY_RIGHTS, and it returns
    WSB_ERROR_DRM_LICENSE_UNSUPPORTED if there are mandatory callbacks or obligations that cannot be satisfied. If the Play action is not granted, you can call WSB_ExplainActionResultFailure to get a more detailed error code as to why the action is not granted.

WSB_Config_ValidateActionResult Default and Sample Implementations

WSB_Config_ValidateActionResult is a replaceable function. That is, there is a default implementation, but that implementation can be replaced prior to building Wasabi. The header file declaring the function is at
$WASABI_HOME/Source/Config/Validator/WsbConfigActionResultValidator.h The default implementation is at
$WASABI_HOME/Source/Config/Validator/Default/WsbConfigActionResultValidator.cpp The default implementation refuses access to the content if either the Play action is not granted or there are any mandatory obligations or callbacks.

There is also a sample more complex implementation at $WASABI_HOME/Source/Config/Validator/Sample/WsbConfigActionResultValidator.cpp This sample validator allows mandatory DTCP output control obligations and MS3 do-not-store obligations, which are described further in the sample .cpp file and in the Marlin Output Control Specification. It also allows BasicCCI DigitalOnlyToken and APS parameter values. The sample code cannot be used as is. It shows how to allow such obligations, but the code must in addition in some cases take actions required to properly enforce the specified constraints. For example, if the device supports CGMS-A (for the Analog Protection System), then allowing the BasicCCI APS parameter is okay, as long as the corresponding output control flags have been set in the device hardware or software.

The default validator can always be used for an application that does not support any obligations or callbacks. If an application could actually support some obligations or callbacks, or the device has characteristics that would make a particular obligation or callback irrelevant, then the default validator should be replaced with a more suitable validator. For example, if a device would never store MS3 content, then a mandatory do-not-store obligation could be considered to be satisfied, and the existence of such an obligation should not result in denying access to the content.

WSB_EcmDecrypter

Usage

A WSB_EcmDecrypter object can be used to aid an application processing a Marlin Broadband Transport Stream (Marlin BBTS), which is an MPEG-2 Transport Stream containing Marlin-protected content. The WSB_EcmDecrypter interface contains methods for processing PMTs (Program Map Tables), ECMs (Entitlement Control Messages), CATs (Conditional Access Tables), and MRTs (Marlin Rights Tables), supplying the client information needed, such as the traffic keys required to decrypt the Transport Stream media content packets. Usage of WSB_EcmDecrypter is illustrated in the example utility named WasabiEcmDecrypter.cpp.

Creating a WSB_EcmDecrypter Object

Call WSB_EcmDecrypter_Create to create an instance of a WSB_EcmDecrypter object. You pass it the address of a WSB_EcmDecrypter pointer that is set by this method to refer to the WSB_EcmDecrypter object that the method creates. You also pass it an indication of the format in which you want the traffic keys supplied, either WSB_MP2TS_KEY_FORMAT_CLEAR (indicating cleartext 16-byte AES keys, with 16-byte initialization vectors) or WSB_MP2TS_KEY_FORMAT_SKB (indicating Secure Key Box-exported keys, that is, keys exported using the SKB API SKB_SecureData_Export method). There is also a parameter for specifying key format parameters, but there are not yet any such parameters defined, so currently just specify NULL for key_format_params. Also pass WSB_EcmDecrypter_Create a “listener” that is notified of events occurring while the WSB_EcmDecrypter_UpdateEcm and WSB_EcmDecrypter_UpdateMrt methods are processing ECMs (known as KSMTs in IEC 62455) and MRTs (Marlin Rights Tables), respectively. A listener is declared as follows:

typedef struct {
/** Listener instance pointer; gets passed into callback
* methods.
*/
void* instance;
/**
* Callback method invoked on a new or updated media file
* detection.
*/
WSB_Result (*OnNewMediaFile)(void* instance,
WSB_MediaFile* media_file,
WSB_KeyManager* key_manager);
/**
* Callback method invoked on a new MPEG2 TS traffic key.
*/
void (*OnKsmInfoChange)(void* instance,
const WSB_KsmInfo* key_info,
WSB_UInt32 change_mask);
} WSB_EcmDecrypter_Listener;

WSB_EcmDecrypter Methods and Usage

The WSB_EcmDecrypter interface has four methods that facilitate the processing of Marlin BBTS streams: WSB_EcmDecrypter_UpdatePmt,

WSB_EcmDecrypter_UpdateEcm, WSB_EcmDecrypter_UpdateCat, and WSB_EcmDecrypter_UpdateMrt. A client basically processes a Marlin BBTS stream the same way it processes any MPEG-2 TS stream whose content it plays, except for needing to do a few Marlin-specific steps. One of the first things the client should do is create a WSB_PlaybackEnabler object that is needed in subsequent steps.

Here is an example call:

WSB_PlaybackEnabler* enabler = NULL;
WSB_PlaybackEnabler_Create(enabler_listener, &enabler);

The client should also create a WSB_EcmDecrypter, after first defining the listener callback methods that are called by the WSB_EcmDecrypter when it is processing an ECM. These callback methods are described below. Sample code for creation of a WSB_EcmDecrypter object is the following:

WSB_EcmDecrypter* ecm_dec = NULL;
WSB_EcmDecrypter_Create(
ecm_listener, WSB_MP2TS_KEY_FORMAT_CLEAR, NULL, &ecm_dec);

The client should have a URL to the content to be played. If there is any chance the URL is an MS3 (Marlin Simple Secure Streaming) URL, WSB_PlaybackEnabler_ResolveUrl should be called. Here’s a sample call, where url is the original URL, and content_url is a pointer to where the method stores the content URL (which is the same as the original URL, if it was not an MS3 URL):

SHI_Data* content_url = NULL;
WSB_PlaybackEnabler_ResolveUrl(enabler, url, &content_url);

The client should then use the content URL to obtain the content, and should start processing it
as usual, for example extracting PAT and PMT tables.

Processing PMTs and ECMs

The WSB_EcmDecrypter_UpdatePmt method should be called by the client to process a PMT (Program Management Table). Pass it a pointer to the table bytes and an indication of the number of bytes. This method extracts from the PMT useful information it may need later, such as the CA descriptor, and returns to the caller the PID (Packet ID) of the ECMs (Entitlement Control Messages) for the program referenced by the PMT. Here is a sample call:
WSB_EcmDecrypter_UpdatePmt(ecm_dec, pmt, pmt_length, &ecm_pid);

For each ECM with that PID, the client should call WSB_EcmDecrypter_UpdateEcm, providing it a pointer to the ECM bytes and an indication of the number of bytes. Here is a sample call:

WSB_EcmDecrypter_UpdateEcm(ecm_dec, ecm, ecm_length);

This method processes the ECM. Whenever it encounters a new content ID specified in the ECM, it calls the WSB_EcmDecrypter listener method OnNewMediaFile, passing it a pointer to a WSB_MediaFile object representing the content, and a pointer to a WSB_KeyManager in which the keys needed to decrypt the Marlin content should be stored. The OnNewMediaFile method must try to “enable” the new media file through the WSB_PlaybackEnabler API, ensuring that a license for the content is found and evaluated to determine whether playback of the content is allowed, and, if so, also ensuring that the WSB_KeyManager object is filled in with the keys needed to decrypt the content. Sample pseudocode is the following, where enabler is assumed to be the WSB_PlaybackEnabler object previously created by a call to WSB_PlaybackEnabler_Create:

ecm_listener.OnNewMediaFile(media_file, key_manager) {
// Try to have a valid license for the content found:
WSB_PlaybackEnabler_EnableMediaFile(
enabler, media_file, NULL, 0);

// If a license was found, determine whether playback is allowed:
WSB_PlaybackEnabler_PerformPlayAction(enabler, &action_result);

// Handle any DRM/license issues here.
// Determine whether app can handle all critical obligations
// and callbacks... If so, and playback is allowed, call the
// following to obtain the content keys and supply them to
// the WSB_KeyManager:
WSB_PlaybackEnabler_AcceptActionResult(
enabler, key_manager, NULL);
}

Whenever WSB_EcmDecrypter_UpdateEcm encounters in the ECM a new traffic key and any other ECM/KSM information changes, it decrypts the traffic key (which was encrypted using the Marlin content key) and it calls the listener’s OnKsmInfoChange method, passing it a WSB_KsmInfo structure and a change mask indicating which of the WSB_KsmInfo fields have been modified since the last time OnKsmInfoChange was called. The WSB_KsmInfo structure is defined as follows:

typedef struct {
/**
* A set of WSB_KsmInfoFlag values, bitwise or'ed together,
* indicating which fields of the structure were present in the
* ECM.
*/
WSB_UInt32 present_mask;
WSB_Mpeg2TsTrafficKey_Format format;
const void* format_params;
WSB_Mpeg2TsTrafficKey_Parity current_key_parity;
const WSB_Byte* current_key;
WSB_Size current_key_size;
const WSB_Byte* current_iv;
WSB_Size current_iv_size;
const WSB_Byte* next_key;
WSB_Size next_key_size;
const WSB_Byte* next_iv;
WSB_Size next_iv_size;
WSB_Mpeg2TsTrafficKey_ProtectionSystem protection;
WSB_Size access_criteria_count;
WSB_UInt64 timestamp;
WSB_UInt8 key_lifetime;
WSB_UInt8 permissions_category;
} WSB_KsmInfo;

The current_key_parity indicates whether the key specified by current_key is an even key (if the value is WSB_ MP2TS_KEY_EVEN) or an odd key (WSB_ MP2TS_KEY_ODD). As you can see, the current key, and the next key, and their initialization vectors, are specified, as well as other information such as access criteria and timestamps, whose meanings and usage are defined in the Marlin BBTS Specification.

The OnNewKsmInfo method should do whatever it needs to do to utilize the new traffic key and other information, so that it can decrypt subsequent TS content packets using the appropriate key.

Processing CATs and MRTs

The WSB_EcmDecrypter_UpdateCat method should be called by the client to process a CAT (Conditional Access Table). Pass it a pointer to the table bytes and an indication of the number of bytes. This method extracts from the CAT useful information it may need later, and returns to the caller (in the final parameter pointed to by the call) the PID (Packet ID) of the MRT (Marlin Rights Table).

Here is a sample call:

WSB_EcmDecrypter_UpdateCat(ecm_dec, cat, cat_length, &mrt_pid);

For each MRT with that PID, the client should call WSB_EcmDecrypter_UpdateMrt, providing it a pointer to the MRT bytes and an indication of the number of bytes.

Here is a sample call:

WSB_EcmDecrypter_UpdateMrt(ecm_dec, mrt, mrt_length);

This method processes the MRT. Whenever it encounters a new Silent License Acquisition URL, it calls the WSB_EcmDecrypter listener method OnNewMediaFile, passing it a pointer to a WSB_MediaFile object representing the content, and a pointer to a WSB_KeyManager in which the keys needed to decrypt the Marlin content should be stored. If the client has already found a license for the specified content, the OnNewMediaFile method can simply ignore the
call. Otherwise, the passed-in WSB_MediaFile will now include the Silent License Acquisition URL, which may make it possible to now obtain the license when
WSB_PlaybackEnabler_EnableMediaFile is called. OnNewMediaFile should call that method and, if successful, call the other methods shown in the sample OnNewMediaFile shown above, to determine whether playback is allowed and to fill in the WSB_KeyManager with the content keys.

Destroying the WSB_EcmDecrypter

When you are done with the WSB_EcmDecrypter object, destroy it by calling WSB_EcmDecrypter_Destroy.

WSB_KeyManager

Usage

A WSB_KeyManager object can be used to get content keys for a playback session. Call WSB_KeyManager_CreateEx to create an instance of a WSB_KeyManager object, passing it a WSB_ContentKeyFormatInfo structure indicating the format in which content keys should be stored in the WSB_KeyManager.

This structure is defined as follows:

typedef struct {
WSB_ContentKeyFormat format;
const void* parameters;
/**< NULL except for format WSB_CONTENT_KEY_FORMAT_SKB_CUSTOM */
} WSB_ContentKeyFormatInfo;

WSB_ContentKeyFormat is one of the following:

typedef enum {
WSB_CONTENT_KEY_FORMAT_CLEARTEXT,
WSB_CONTENT_KEY_FORMAT_SKB_STANDARD,
WSB_CONTENT_KEY_FORMAT_SKB_CUSTOM
} WSB_ContentKeyFormat;

Here, SKB refers to Secure Key Box, and the standard and custom SKB formats are as defined in the SKB API. Calling WSB_KeyManager_Create will create an instance of a WSB_KeyManager object in which the content key format is WSB_CONTENT_KEY_FORMAT_CLEARTEXT. The WSB_KeyManager_GetContentKeyFormatInfo method can be called to obtain the WSB_ContentKeyFormatInfo for the passed-in WSB_KeyManager. To obtain a particular key that has been stored in the WSB_KeyManager (by the Playback Enabler), call WSB_KeyManager_GetKeyByName. You pass it a string representing the “name” of the key.

This string could be one of the following:

  1. A content ID.
  2. “@track.n”, where n is the track ID (e.g., “@track.1”), for content that has a track-based protection scheme.
  3. “@file” for content that has a file-based protection scheme.

You also pass, in the key_data parameter, a pointer to a buffer in which the key data should be written, and, in the key_data_size parameter, an indication of the buffer size. The key length can be queried by setting key_data to NULL. That is, if you pass NULL for the key_data buffer pointer, this method simply returns the key length in *key_data_size, and returns WSB_SUCCESS.

At any given time, the WSB_KeyManager is considered to hold the keys for a particular media file. Whenever you want to reuse it to hold the keys for a different media file, first call WSB_KeyManager_Clear to clear its context and remove the keys it currently holds.

When you are done with the WSB_KeyManager object, destroy it by calling WSB_KeyManager_Destroy.

WSB_LicenseStore and WSB_License

A WSB_LicenseStore object is used to access the Wasabi License Store database in which licenses may be stored. Its methods can be called to store licenses, to obtain licenses that are stored, and to remove licenses from the License Store.

Obtaining a WSB_LicenseStore Object

The WSB_LicenseStore_Open method is called to open the License Store and create a new WSB_LicenseStore object to refer to it. If the License Store (database) does not yet exist, it is created.

WSB_LicenseStore Methods

Once the License Store is open, WSB_LicenseStore_AddLicense can be called to add a license into the License Store. In the call, you specify the license data and its size, as well as an optional tag string in which you can specify whatever textual information you like, such as the name of the application that is adding the license to the License Store. This method returns the license ID assigned by the License Store to the license that was added.

WSB_LicenseStore_RemoveLicense removes from the License Store the license with a specified license ID.

WSB_LicenseStore_GetLicenseById can be called to obtain from the License Store a license with a particular license ID.

WSB_LicenseStore_FindLicensesByContentIds is passed an array of one or more content IDs, and it finds in the License Store the license(s) with the specified content ID(s). It returns a SHI_Data object of type SHI_DATA_TYPE_ARRAY containing the licenses. If you call the method with an empty content ID list, all licenses in the License Store are returned, but please note that it is far better to instead call WSB_LicenseStore_EnumerateLicenses to obtain all the licenses and control which license-related data is included, especially if there are a large number of licenses in the License Store.

WSB_LicenseStore_FindContentIdsByLicense is passed a license ID and returns an array of the content ID(s) governed by the license with the specified license ID. WSB_LicenseStore_EnumerateLicenses obtains from the License Store an array of WSB_License objects representing all the licenses in the License Store. Since there may be a large number of licenses in the License Store, it may be useful to reduce the amount of memory required for each of the returned WSB_License objects by specifying, in a flags parameter, which license-related data (the bytes for the license, the expiration date, the insertion date, and/or the tag) you want to be included. Any such items whose corresponding value is not set in the flags parameter is not included. WSB_LicenseStore_EnumerateContentIds obtains from the License Store an array of all content IDs governed by the licenses in the License Store.

When you are done with the WSB_LicenseStore object, close the License Store and release the WSB_LicenseStore by calling WSB_LicenseStore_Close.

WSB_License Methods

A WSB_License object represents information about a license. WSB_License objects are created as a result of calls to WSB_LicenseStore_GetLicenseById
(which obtains the license with a specified ID), WSB_LicenseStore_FindLicensesByContentIds, (which obtains the license or licenses with
specified content IDs), and WSB_LicenseStore_EnumerateLicenses (which obtains all licenses in the License Store). The WSB_License objects are pointed to from a structure in the SHI_Data returned by those methods. The caller is responsible for calling SHI_Data_Release to release the SHI_Data object when it is no longer needed. The WSB_License objects pointed to from the SHI_Data are also freed by the SHI_Data_Release call.

WSB_License Methods

Various methods can be called to obtain information about a particular license. In most cases, the specified WSB_License passed as a parameter has the requested information and will return it. However, if the license was obtained as one of the licenses returned by a call to WSB_LicenseStore_EnumerateLicenses, and the flags in that call did not indicate that the specified type of information should be included, then a suitable return value, such as a NULL or a -1, indicates that such data is not available through that particular WSB_License.

Call WSB_License_GetId to obtain the license ID for the license referenced by a particular WSB_License.

WSB_License_GetExpirationDate returns the license expiration date. The value is represented as the number of UTC (Coordinated Universal Time) minutes since January 1, 1970.

WSB_License_GetInsertionDate returns the time when the license was added to the License Store. As with WSB_License_GetExpirationDate, the value is represented as the number of UTC minutes since January 1, 1970. WSB_License_GetData returns a byte array containing the bytes representing the license.
WSB_License_GetTag returns the license tag for a specified license. A license tag can be set when a license is added to the License Store (see WSB_LicenseStore_AddLicense). It is simply a NULL-terminated character string that could, for example, indicate the name of the application that inserted the license. WSB_License_GetPriority is not currently used.

WSB_MediaFile and WSB_TrackInfo

A WSB_MediaFile object can be used to obtain information about a media file, to embed a license within a media file, and to obtain a license embedded within a media file.

Obtaining a WSB_MediaFile Object

Call WSB_MediaFile_Open to open a specified media file and create a WSB_MediaFile object referencing it. Pass it either a filename or an HTTP URL. If you know the MIME type, pass that as well.

Obtaining File Information

A WSB_MediaFile is used to obtain various types of information about the media file it references. WSB_MediaFile_GetName returns the file name, WSB_MediaFile_GetProtectionType returns the protection type (indicating whether it is a DCF file, a PDCF file, etc.), and WSB_MediaFile_GetContentType returns the file’s content type as a MIME type. The MIME type represents the media data type before protection. The following constants are defined for
this property:

#define WSB_CONTENT_TYPE_VIDEO_MP4 "video/mp4"
#define WSB_CONTENT_TYPE_AUDIO_MP4 "audio/mp4"
#define WSB_CONTENT_TYPE_VIDEO_MPEG2TS "video/MP2T"
#define WSB_CONTENT_TYPE_DASH "application/dash+xml"
#define WSB_CONTENT_TYPE_HLS "application/vnd.apple.mpegurl"
#define WSB_CONTENT_TYPE_DCF "application/vnd.oma.drm.dcf"
#define WSB_CONTENT_TYPE_DECE "video/vnd.dece.mp4"

Note: MIME types are case-insensitive.

If the protection type is WSB_PROTECTION_TYPE_DCF, you can call WSB_MediaFile_GetContentId to obtain the content ID for the content in the media file. This is only relevant for DCF files, which have a single content ID, reported at the file level. For files that do not have a content ID at the file level (e.g., PDCF files, which report content IDs on a per-track basis), this method returns NULL. To obtain the content ID for a particular track in a PDCF file, create a WSB_TrackInfo object referencing the track (see “Track Related Methods” below) and then call WSB_TrackInfo_GetContentId.

Call WSB_MediaFile_GetProgress to find out the total number of bytes for the file (if known) and the number that are currently available, which are less than the total number if the file is currently being downloaded. If the type of media doesn’t enable gathering the total size information, such as in streaming, the total number of bytes reported is zero.

Call WSB_MediaFile_GetMetadata to obtain the metadata for the file, indicating information such as the album, artist, lyrics, copyright, and so on. You pass this method the address of a SHI_Attribute pointer that is set to point to a SHI_Attribute object containing the metadata. The SHI_Attribute type is SHI_ATTRIBUTE_TYPE_LIST, and each child of the list is an attribute for a single metadata item. The caller is responsible for calling SHI_Attribute_Release to release the SHI_Attribute object when it is no longer needed.

Obtaining Media Information

If you call WSB_MediaFile_GetMediaInfo, passing it a pointer to a WSB_MediaInfo structure, it will fill in that structure with the following information:

typedef struct WSB_MediaInfo {
WSB_MediaType type;
WSB_MediaFormat format;
WSB_UInt32 duration; /**< in ms */
WSB_UInt32 bitrate; /**< in bits/sec */
WSB_StreamEncryptionMethod encryption_method;
union {
WSB_AudioMediaInfo audio;
WSB_VideoMediaInfo video;
} specific;
} WSB_MediaInfo;

The structures referenced by WSB_MediaInfo are the following:

typedef enum {
WSB_MEDIA_TYPE_UNKNOWN = 0,
WSB_MEDIA_TYPE_AUDIO = 1,
WSB_MEDIA_TYPE_VIDEO = 2
} WSB_MediaType;

typedef enum {
WSB_MEDIA_FORMAT_UNKNOWN = 0,
WSB_MEDIA_FORMAT_AAC = 1,
WSB_MEDIA_FORMAT_AVC = 2,
WSB_MEDIA_FORMAT_MP3 = 3,
WSB_MEDIA_FORMAT_MPEG4_VID = 4
} WSB_MediaFormat;

typedef enum {
WSB_STREAM_ENCRYPTION_METHOD_UNKNOWN = 0,
WSB_STREAM_ENCRYPTION_METHOD_NULL = 1,
WSB_STREAM_ENCRYPTION_METHOD_AES_128_CBC = 2,
WSB_STREAM_ENCRYPTION_METHOD_AES_128_CTR = 3,
WSB_STREAM_ENCRYPTION_METHOD_DVB_CSA = 4
} WSB_StreamEncryptionMethod;

typedef struct WSB_AudioMediaInfo {
WSB_UInt32 channel_count;
WSB_UInt32 sample_rate;
WSB_UInt32 sample_size;
} WSB_AudioMediaInfo;

typedef struct WSB_VideoMediaInfo {
WSB_UInt32 width;
WSB_UInt32 height;
WSB_UInt32 depth;
} WSB_VideoMediaInfo;

Track-Related Methods

Call WSB_MediaFile_GetTrackCount to find out the number of tracks in the media file. To obtain information about a particular track, call WSB_MediaFile_GetTrackInfo. This method returns a WSB_TrackInfo object whose methods can be called to obtain various types ofinformation about the track.

License-Related Methods

If the license corresponding to the content in the file is embedded in the file, WSB_MediaFile_GetLicense returns the embedded license. If you have a license that you want embedded within a media file, call

WSB_MediaFile_SetLicense.

WSB_MediaFile_GetRightsIssuerUrls returns the rights issuer URLs corresponding to each content ID in a specified media file. You pass it a pointer to the relevant WSB_MediaFile, and the address of a SHI_Attribute pointer. This pointer is set to NULL if no rights issuer URLs are found. Otherwise, this method creates a SHI_Attribute of type

SHI_ATTRIBUTE_TYPE_LIST, and sets the passed-in SHI_Attribute pointer to refer to this SHI_Attribute. The names of the children in the list are content IDs, and for each, the value is of type SHI_ATTRIBUTE_TYPE_STRING and it contains the rights issuer URL associated with that content ID. The caller is responsible for releasing the SHI_Attribute when no longer needed (the children will automatically be released) by calling SHI_Attribute_Release. WSB_MediaFile_GetSilentLicenseAcquisitionUrls returns the silent license acquisition URLs contained in the media file, which are used as needed (e.g., by the Wasabi Rights Enabler) to attempt to obtain the license corresponding to the content in the file, if the license is not embedded within the file. Pass this method a pointer to the relevant WSB_MediaFile, and the address of a SHI_Attribute pointer. This pointer is set to NULL if no silent license acquisition URLs are found.

Otherwise, this method creates a SHI_Attribute of type SHI_ATTRIBUTE_TYPE_LIST, and sets the passed-in SHI_Attribute pointer to refer to this SHI_Attribute. The names of the children in the list are content IDs, and for each, the value is of type SHI_ATTRIBUTE_TYPE_STRING and it contains the silent license acquisition URL associated with that content ID. The caller is responsible for releasing the SHI_Attribute when no longer needed (the children will automatically be released) by calling SHI_Attribute_Release.

Releasing the WSB_MediaFile

When you no longer need a WSB_MediaFile object, close the media file it references and release the WSB_MediaFile by calling WSB_MediaFile_Close.

WSB_TrackInfo Methods

A WSB_TrackInfo object represents information about a track in a media file.

Obtaining WSB_TrackInfo Objects

WSB_TrackInfo objects are created as a result of calls to WSB_MediaFile_GetTrackInfo. You pass that method a WSB_MediaFile representing the file whose track information you want to obtain, and a 0-based index indicating the number of the track whose information you want.

WSB_TrackInfo Methods

Once you have a WSB_TrackInfo object, you can call WSB_TrackInfo_GetTrackId to obtain the track ID, and WSB_TrackInfo_GetContentId to obtain the content ID.

If you call WSB_TrackInfo_GetMediaInfo, and pass it a pointer to a WSB_MediaInfo structure, it will fill in the structure with the following information:

typedef struct WSB_MediaInfo {
WSB_MediaType type;
WSB_MediaFormat format;
WSB_UInt32 duration; /**< in ms */
WSB_UInt32 bitrate; /**< in bits/sec */
WSB_StreamEncryptionMethod encryption_method;
union {
WSB_AudioMediaInfo audio;
WSB_VideoMediaInfo video;
} specific;
} WSB_MediaInfo;

When you no longer need a WSB_TrackInfo, release it by calling WSB_TrackInfo_Release.

Media File-related Data Types

The enums and structures utilized by WSB_MediaFile and WSB_TrackInfo objects are the following:

WSB_ AudioMediaInfo Information about audio media

WSB_FileProgress Information about the total number of bytes in a file, and the number that are currently available, e.g., while a download is in progress

WSB_MediaFileProtectionType Identifiers for media file protection types

WSB_MediaFormat Identifiers for media formats

WSB_MediaInfo Comprehensive information about amedia file, including the WSB_MediaType, WSB_MediaFormat, etc.

WSB_MediaType Identifiers for the different media types

WSB_StreamEncryptionMethod Identifiers for stream encryption methods

WSB_VideoMediaInfo Information about video media

WSB_PlaybackEnabler

A WSB_PlaybackEnabler object can be used to do everything possible to obtain a valid license for a given WSB_MediaFile object or for content with a specified content ID (using an internal WSB_RightsEnabler object) and then exercise this license and populate a WSB_KeyManager object with the content keys.

Creating a WSB_PlaybackEnabler and Registering a Callback Listener

A WSB_PlaybackEnabler object is created by calling WSB_PlaybackEnabler_Create. You pass this method the address of a WSB_PlaybackEnabler pointer that is set to refer to the WSB_PlaybackEnabler object that the method creates. You also pass it a “listener” that is optionally notified of events occurring while the WSB_PlaybackEnabler_EnableMediaFile or
WSB_PlaybackEnabler_EnableContentId method (see below) is looking for a valid license. If
the listener’s handler method pointer is not NULL, the handler method is called for each
event, and its event argument specifies the type of event and supplies event information. The
listener is a WSB_RightsEnabler_EventListener which, is defined as follows:

typedef struct {
void* instance;
WSB_RightsEnabler_ContinuationType
(*handler)(void* instance,
const WSB_RightsEnabler_Event* event);
} WSB_RightsEnabler_EventListener;

As an example, if the event type is WSB_RIGHTSENABLER_EVENT_TYPE_LICENSE, the event data structure
is a WSB_RightsEnabler_LicenseEvent, defined as follows:

typedef struct {
WSB_RightsEnabler_Event base;
WSB_Result processing_result;
const void* license_data;
WSB_Size license_data_size;
WSB_Boolean is_granted;
SHI_ActionResult* action_result;
} WSB_RightsEnabler_LicenseEvent;

This event contains the license, an indication of whether the license that was found grants
access to the content, and a pointer to a SHI_ActionResult containing information about the
license requirements, including constraints referred to as obligations and callbacks.
The processing_result is WSB_SUCCESS if the license was processed correctly,
WSB_ERROR_DRM_BAD_LICENSE_FORMAT if the license format is invalid, or
WSB_ERROR_DRM_CLIENT_SYSTEM_ERROR if the license could not be processed
because of a DRM system failure.

Obtaining a Content URL from an MS3 URL

MS3 (Marlin Simple Secure Streaming) compound URLs allow a client to retrieve both the
content URL and the access rights to the content using the MS3 protocol. All MS3 URLs use the
HTTPS scheme, and thus employ TLS to securely obtain content and rights.

If there is any possibility that the content URL is an MS3 URL, the caller should invoke
WSB_PlaybackEnabler_ResolveUrl. This function returns the URL, unchanged, if it is not
an MS3 URL. Otherwise, it retrieves the access rights (an SAS, Stream Access Statement)
and extract from the compound URL the content URL, and returns the content URL to the
caller. The application can then proceed with enabling the media file or content, as described in
the next section. Regardless of whether or not the suppled URL is an MS3 URL, a content URL
is returned, so the caller can use this value in any case. The return value is a SHI_Data
object, of type SHI_DATA_TYPE_STRING. The content URL should be freed by the caller when
no longer needed by calling SHI_Data_Release.

The WSB_PlaybackEnabler API does not otherwise handle content URLs.
In the case of a media file or stream that is Marlin-defined, the content URL returned by this API
should be passed to WSB_MediaFile_Open in order to open the specified content file and
create a WSB_MediaFile object referencing it that can be passed to
WSB_PlaybackEnabler_EnableMediaFile.

Obtaining a Valid License

Two different methods can be called to try to obtain a working license for content. Call
WSB_PlaybackEnabler_EnableMediaFile if you can obtain a WSB_MediaFile referencing
a media file or stream whose format is Marlin-defined—and thus Wasabi knows how to process
it, for example to extract an embedded license or silent license acquisition URL, if any. Call
WSB_PlaybackEnabler_EnableContentId when you cannot obtain such a WSB_MediaFile,
but a license or MS3 SAS may grant access to content with a specified ID. It is useful, for
example, for situations where the content ID changes during streaming. It is also useful in
situations where a license grants access to content in a media file whose format is not Marlin defined.
In this case, an application can use this method to find such a license and can
subsequently use the Wasabi Key Manager to obtain the content key(s) from the license.

For either method, if you actually already have a license for the content, and you want the
method to check whether that license is currently valid, then you can optionally also pass the
license bytes and a value indicating the number of bytes.

WSB_PlaybackEnabler_EnableMediaFile calls WSB_MediaFile and WSB_TrackInfo
methods to obtain the content IDs and track IDs (if it is a type of file that has tracks) for the
media file. If no errors occur, it then calls WSB_RightsEnabler_EnableMediaFile, which performs a number of steps to do everything possible to try to find a currently valid license.

WSB_PlaybackEnabler_EnableContentId calls WSB_RightsEnabler_EnableContentId.

Prior to calling either of those methods, you can optionally call
WSB_PlaybackEnabler_SetRightsEnablerOptions to set option flags controlling
WSB_RightsEnabler_EnableMediaFile behavior. By default, all flags are off. The possible flags,
defined in WsbRightsEnabler.h, are named the following:

WSB_RIGHTSENABLER_OPTION_FLAG_DISABLE_SLA
WSB_RIGHTSENABLER_OPTION_FLAG_DISABLE_LINK_RENEWAL
WSB_RIGHTSENABLER_OPTION_FLAG_DISABLE_STORING_LICENSE_IN_FILE

Each of these flags disables a particular potential action normally taken by
WSB_RightsEnabler_EnableMediaFile or WSB_RightsEnabler_EnableContentId.

Whenever WSB_RightsEnabler_EnableMediaFile or WSB_RightsEnabler_EnableContentId
finds a license, the license is supplied to the Playback Enabler in an event of type
WSB_RIGHTSENABLER_EVENT_TYPE_LICENSE. The Playback Enabler stores the license
data and also forwards the event to the client listener passed in the call to
WSB_PlaybackEnabler_Create, if the listener handler method pointer is not NULL. This case
is described first, followed by information regarding what happens if it is NULL.

The listener should determine whether it is satisfied with the specified license (in which case, it
returns WSB_RIGHTSENABLER_HALT_SEARCH) or would prefer to have the search continue
for another license (in which case, it returns WSB_RIGHTSENABLER_CONTINUE_SEARCH).

In order to examine the license, it is common to call WSB_Config_ValidateActionResult. If the Play action is granted and all mandatory obligations and callbacks can be satisfied,
WSB_Config_ValidateActionResult returns WSB_SUCCESS. If the action is not granted, it
returns WSB_ERROR_DRM_DENY_RIGHTS, and it returns
WSB_ERROR_DRM_LICENSE_UNSUPPORTED if there are mandatory callbacks or
obligations that cannot be satisfied.

If the action is not granted, you can call WSB_ExplainActionResultFailure to obtain an
error code with a more explicit explanation as to why the action is not granted (such as the
license having expired).

Here is an example of how a listener handler method might handle a license event:

static WSB_RightsEnabler_ContinuationType
OnEnablerEvent(void* instance, const WSB_RightsEnabler_Event* event)
{
WSB_Result result;
// we're only interested in license data
if (event->type == WSB_RIGHTSENABLER_EVENT_TYPE_LICENSE) {
WSB_RightsEnabler_LicenseEvent* license_event =
(WSB_RightsEnabler_LicenseEvent*)event;
if (WSB_FAILED(license_event->processing_result)) {
// license just could not be processed; handle this case
. . .;
} else {
result = WSB_Config_ValidateActionResult(
license_event->action_result,
WSB_FALSE,
SHI_ACTION_PLAY,
NULL);
if (WSB_SUCCEEDED(result)) {
// we've found a valid license!
return WSB_RIGHTSENABLER_HALT_SEARCH;
} else if (result == WSB_ERROR_DRM_DENY_RIGHTS) {
// play action not granted, get more information
SHI_Data* goto_url_data = NULL;
result = WSB_ExplainActionResultFailure(
license_event->action_result,
NULL,
media_file,
&goto_url_data);
/* if desired, save or further process this result */
. . .
}
}
}
return WSB_RIGHTSENABLER_CONTINUE_SEARCH;
}

If the listener handler method is NULL, then when a license is supplied to the Playback
Enabler, the Playback Enabler does the same things as the client listener would typically do
(described above), except that it always returns WSB_RIGHTSENABLER_HALT_SEARCH if
WSB_Config_ValidateActionResult returns WSB_SUCCESS. In other words, the default
behavior is that the Playback Enabler always stops the search as soon as any valid license is
found.

In the case of MS3 content, the WSB_PlaybackEnabler_EnableMediaFile or
WSB_PlaybackEnabler_EnableContentId method should still be invoked, and a NULL
license_data parameter should be supplied. The rights acquired during the call to
WSB_PlaybackEnabler_ResolveURL is used to enable the media file.

Checking the License and Obtaining Keys

At any point after calling WSB_PlaybackEnabler_EnableMediaFile or
WSB_PlaybackEnabler_EnableContentId, and prior to attempting content playback, call
WSB_PlaybackEnabler_PerformPlayAction to perform the “Play” action on the license (or, in
the case of MS3 content, the access rights). Essentially, this determines whether the Play action
is currently allowed, and creates a SHI_ActionResult containing information about what is
allowed and what is required. WSB_PlaybackEnabler_PerformPlayAction does not actually play
the content, but it must be executed as one of the steps prior to playing the content. Pass this
method the address of a SHI_ActionResult pointer that will be set to refer to the
SHI_ActionResult object created by this call. A WSB_Result of WSB_SUCCESS does not mean
that the Play action is granted. The SHI_ActionResult returned by the call must be analyzed to
determine that, as described in the following.

The SHI_ActionResult should be analyzed by calling WSB_Config_ValidateActionResult. As
stated above, this method is responsible for analyzing the SHI_ActionResult to determine
whether the Play action is granted, and whether all of the mandatory obligations and callbacks
(if any) can be satisfied.

WSB_Config_ValidateActionResult returns WSB_SUCCESS if the application should be
allowed access to the protected content. In this case, call WSB_KeyManager_Create to
instantiate a WSB_KeyManager object, and then call
WSB_PlaybackEnabler_AcceptActionResult, passing it the WSB_KeyManager. This method
obtains the content keys and supply them to the WSB_KeyManager. This method also has
an optional parameter specifying the address of a SHI_Action pointer which, if specified, is
set to refer to the internal SHI_Action object, which may be needed for exercising callbacks. The
caller does not take ownership, and therefore must not destroy this SHI_Action.

Destroying the WSB_PlaybackEnabler

When the WSB_PlaybackEnabler object is no longer needed, destroy it by calling
WSB_PlaybackEnabler_Destroy.

WSB_ProxyManager

A WSB_ProxyManager object can be used to set global (per application) proxies for HTTP and HTTPS transactions.

Call WSB_ProxyManager_SetHttpProxy to set the proxy to be used for HTTP transactions. You pass it the hostname and port.

Call WSB_ProxyManager_SetHttpsProxy to set the proxy to be used for HTTPS transactions. As with WSB_ProxyManager_SetHttpProxy, you pass the hostname and port to be used.

Here is how proxy selection works in ExpressPlay SDK:

  • If the proxies have been set using the WSB_ProxyManager methods, then those proxies are utilized.
  • For convenience in testing and in running sample applications (not for running applications in production environments), it is possible to use a proxy without modifying the code to call the WSB_ProxyManager methods. If proxies are not set, as described above, or are unusable (e.g., set to an empty string), ExpressPlay SDK checks the values of certain environment variables, as described in the following, to try to determine what proxies to use, if any.
  • An environment variable named NEPTUNE_NET_CONFIG_PROXY_SELECTOR can have 3 values. If it is set to no proxy (or the variable does not exist), then no proxy is used. If it is set to system, then that indicates that the system’s default proxies (if set) should be used. If it is set to env, then the proxy set in the http_proxy environment variable is used for HTTP transactions, and the proxy set in the https_proxy environment variable is used for HTTPS transactions.
  • However, there are two other environment variables whose values affect which proxy is actually used, and even whether a proxy is used. The NO_PROXY environment variable contains a comma-separated list of hosts for which no proxy should be used. If it has the special value of “*”, then no proxies are used for any hosts. The environment variable named ALL_PROXY specifies the proxy that should be used if the proxy hostname set in http_proxy or https_proxy is invalid.

Please note that http_proxy must be all lowercase, but https_proxy, no_proxy, and all_proxy can each be either all lowercase or all uppercase.

WSB_RightsEnabler

A WSB_RightsEnabler object can be used to have everything possible done to obtain a license
granting access to specified content. A WSB_RightsEnabler object is created and utilized
internally as needed by other Wasabi classes, such as WSB_PlaybackEnabler, and the
Rights Enabler functionality is also available to external applications via the
WSB_RightsEnabler methods.

Creating a WSB_RightsEnabler Object

A WSB_RightsEnabler object is created by calling WSB_RightsEnabler_Create. You pass it
the address of a WSB_RightsEnabler pointer that is set by this method to refer to the
WSB_RightsEnabler object that the method creates. You also pass it a “listener” that is
notified of events occurring while the WSB_RightsEnabler_EnableMediaFile or
WSB_RightsEnabler_EnableContentId method (see below) is looking for a valid license. The
listener’s handler method is called for each event, and its event argument specifies the
type of event and supplies event information, as discussed below under “Event Structures.” The
listener has the following type:

typedef struct {
void* instance;
WSB_RightsEnabler_ContinuationType
(*handler)(void* instance,
const WSB_RightsEnabler_Event* event);
} WSB_RightsEnabler_EventListener

The handler return value is of the following type:

typedef enum {
WSB_RIGHTSENABLER_HALT_SEARCH,
WSB_RIGHTSENABLER_CONTINUE_SEARCH
} WSB_RightsEnabler_ContinuationType;

The return value is primarily relevant for license events. When such an event occurs, indicating
that a license was found, the handler can decide whether it wants the Rights Enabler to stop
looking or to continue the search for a different license (as discussed further below), and the
handler indicates its choice by the appropriate return value. For other events, the return value is
considered more of a request, and a request to halt may or may not be satisfied due to internal
reasons.

Event Structures

WSB_RightsEnabler_Event is the base class for all event structures. It is defined as follows:

typedef struct {
WSB_RightsEnabler_EventType type;
} WSB_RightsEnabler_Event;

The types of events that may be reported to the listener are the following:

typedef enum {
WSB_RIGHTSENABLER_EVENT_TYPE_GOTO_URL,
WSB_RIGHTSENABLER_EVENT_TYPE_TRANSACTION,
WSB_RIGHTSENABLER_EVENT_TYPE_LICENSE
} WSB_RightsEnabler_EventType;

When the listener is called, it is passed a pointer to a WSB_RightsEnabler_Event. A more
detailed structure, with WSB_RightsEnabler_Event as the base, is actually passed to the
listener, and this structure depends on the event type. The event pointer should be cast to the
appropriate data structure type. The data structures to which events of various types should be
cast are the following:

Event Type Data Structure
WSB_RIGHTSENABLER_EVENT_TYPE_
GOTO_URL
WSB_RightsEnabler_GotoURLEvent
WSB_RIGHTSENABLER_EVENT_TYPE_
LICENSE
WSB_RightsEnabler_LicenseEvent
WSB_RIGHTSENABLER_EVENT_TYPE_
TRANSACTION
WSB_RightsEnabler_TransactionEvent

If the Rights Enabler has been directed to a service for obtaining needed rights, the
WSB_RightsEnabler_GotoURLEvent reports this fact and specifies the URL that the Rights
Enabler was directed to.

typedef struct {
WSB_RightsEnabler_Event base;
const char* url;
} WSB_RightsEnabler_GotoURLEvent;

Whenever the Rights Enabler finds a license, it calls the listener with a WSB_RightsEnabler_LicenseEvent:

typedef struct {
WSB_RightsEnabler_Event base;
WSB_Result processing_result;
const void* license_data;
WSB_Size license_data_size;
WSB_Boolean is_granted;
SHI_ActionResult* action_result;
} WSB_RightsEnabler_LicenseEvent;

This event contains the license, an indication of whether the license that was found grants
access to the content, and a pointer to a SHI_ActionResult that contains information about the
license requirements, including constraints referred to as obligations and callbacks. The
processing_result is WSB_SUCCESS if the license was processed correctly,
WSB_ERROR_DRM_BAD_LICENSE_FORMAT if the license format is invalid, or
WSB_ERROR_DRM_CLIENT_SYSTEM_ERROR if the license could not be processed
because of a DRM system failure.

When the listener receives an event of this type, it should decide whether it is satisfied with the
specified license or would prefer to have the Rights Enabler continue its search for another
license. In the former case, the listener handler method should return
WSB_RIGHTSENABLER_HALT_SEARCH. Otherwise it should return
WSB_RIGHTSENABLER_CONTINUE_SEARCH. In order to determine whether or not to
continue the search, or simply to get information about the license requirements, the listener
may want to analyze the SHI_ActionResult. It can do so, for example, by calling
WSB_Config_ValidateActionResult to determine whether content playback is allowed and
whether all of the mandatory obligations and callbacks (if any) can be satisfied.

A WSB_RightsEnabler_TransactionEvent indicates that a service transaction (link renewal or
silent license acquisition) has been initiated in an attempt to obtain rights.

typedef struct {
WSB_RightsEnabler_Event base;
WSB_RightsEnabler_TransactionType transaction_type;
} WSB_RightsEnabler_TransactionEvent;

Obtaining a Valid License

The purpose of the WSB_RightsEnabler object is to try everything possible to obtain a working
license for content with one or more specified IDs. Call WSB_RightsEnabler_EnableMediaFile
or WSB_RightsEnabler_EnableContentId to invoke this functionality. The former is called
when you can create a WSB_MediaFile referencing a media file or stream whose format is
Marlin-defined—and thus Wasabi knows how to process it, for example to extract an embedded
license or silent license acquisition URL, if any. The latter is called when you cannot create such
a WSB_MediaFile. It is useful, for example, for situations where the content ID changes during
streaming. It is also useful in situations where a license grants access to content in a media file
whose format is not Marlin-defined.

First, prior to calling either of those methods, you can optionally call WSB_RightsEnabler_SetOptions to set option flags controlling their behavior, disabling one or more actions normally taken (which are described below). By default, all flags are off. The flags that can be set are the following:

WSB_RIGHTSENABLER_OPTION_FLAG_DISABLE_SLA

If this flag is set, no silent license acquisitions are attempted.

WSB_RIGHTSENABLER_OPTION_FLAG_DISABLE_LINK_RENEWAL

If this flag is set, no subscription links are renewed.

WSB_RIGHTSENABLER_OPTION_FLAG_DISABLE_STORING_LICENSE_IN_FILE

If this flag is set, WSB_RightsEnabler_EnableMediaFile does not attempt to write a valid
license to the media file.

WSB_RightsEnabler_EnableMediaFile

Prior to calling WSB_RightsEnabler_EnableMediaFile, you create a WSB_MediaFile referencing
the media file or stream whose content you want to find a license for, and you obtain from that
media file/stream the content ID(s). You then pass WSB_RightsEnabler_EnableMediaFile the WSB_MediaFile, an array of the content IDs, and a number indicating how many content IDs are in the array. If you actually already have a license
for the content, and you want this method to check whether that license is currently valid, then
you can optionally also pass the license bytes and a value indicating the number of bytes.

WSB_RightsEnabler_EnableMediaFile performs the steps below, in order, in an attempt to find
a license for the content with the specified content IDs. For each license it finds, it returns the
license to the caller in a WSB_RightsEnabler_LicenseEvent structure passed to the listener
registered in the call to WSB_RightsEnabler_Create. In that event structure, the Rights Enabler
also provides the information as to whether or not the license grants access, and supplies the
SHI_ActionResult containing further information about the license requirements, as discussed in
the previous section. The listener returns to the Rights Enabler a
WSB_RightsEnabler_ContinuationType value instructing the Rights Enabler whether to halt the
search or to continue searching for another license. If the latter, the Rights Enabler continues
the search steps shown below. Otherwise, the search is stopped.

If the most recent license found before the search was halted is a valid one, and
WSB_RIGHTSENABLER_OPTION_FLAG_DISABLE_STORING_LICENSE_IN_FILE is not set,
WSB_RightsEnabler_EnableMediaFile then tries to write the license to the media file, if it is not
already embedded within that media file. If WSB_RightsEnabler_EnableMediaFile cannot
embed the license within the media file, or the specified option is set,
WSB_RightsEnabler_EnableMediaFile stores the license in the Wasabi License Store. In
any case, it then returns to the caller.

Here are the steps WSB_RightsEnabler_EnableMediaFile performs to try to find a currently
valid license:

  1. Check the license that was passed in (if any).
  2. Check the license embedded in the media file (if any).
  3. Check the License Store to see whether it contains a license for the content.
  4. If WSB_RIGHTSENABLER_OPTION_FLAG_DISABLE_LINK_RENEWAL is not set, try
    automatic renewal of the subscription (if any) to the content, and recheck all of the
    licenses found up to this point—the passed-in license, the embedded license, or a
    license in the License Store, in that order.
  5. If the media file/stream has a silent license acquisition header, and
    WSB_RIGHTSENABLER_OPTION_FLAG_DISABLE_SLA is not set, then use the specified
    URL to attempt to automatically acquire a license. Check whether the returned license is
    valid. If not, try updating the subscription referenced by the license (if any) and then
    check (and report in a license event) the license again.

Please note: During WSB_RightsEnabler_EnableMediaFile execution, control programs that
govern access to content will be executed. There is a limit of 40 million execution steps allowed,
and if that number is reached (which would only happen if there was a control program bug
resulting in an infinite loop), WSB_RightsEnabler_EnableMediaFile returns
WSB_ERROR_DRM_DENY_RIGHTS.

WSB_RightsEnabler_EnableContentId

WSB_RightsEnabler_EnableContentId essentially performs the same actions as
WSB_RightsEnabler_EnableMediaFile to find a license, except that in this case, there is no
WSB_MediaFile, therefore, no media file-related actions are performed by the method. As with
WSB_RightsEnabler_EnableMediaFile, WSB_RightsEnabler_EnableContentId returns each
license it finds to the caller in a WSB_RightsEnabler_LicenseEvent structure passed to the
listener registered in the call to WSB_RightsEnabler_Create.

Here are the steps taken by WSB_RightsEnabler_EnableContentId to try to find a valid license:

  1. Check the license that was passed in (if any).
  2. Check the License Store to see whether it contains a license for the content.
  3. If WSB_RIGHTSENABLER_OPTION_FLAG_DISABLE_LINK_RENEWAL is not set, try
    automatic renewal of the subscription (if any) to the content, and recheck all of the
    licenses found up to this point—the passed-in license or a license in the License Store,
    in that order.
  4. If a silent license acquisition URL was passed in the call, and
    WSB_RIGHTSENABLER_OPTION_FLAG_DISABLE_SLA is not set, then use the specified
    URL to attempt to automatically acquire a license. Check whether the returned license is
    valid. If not, try updating the subscription referenced by the license (if any) and then
    check (and report in a license event) the license again.

Destroying the WSB_RightsEnabler

When the WSB_RightsEnabler object is no longer needed, destroy it by calling
WSB_RightsEnabler_Destroy.

Rights Enabler-related Data Types

The enums and structures utilized by WSB_RightsEnabler objects are the following:

WSB_RightsEnabler_Event Base structure for all event structures
WSB_RightsEnabler_EventListener Structure pairing a listener instance value
with a function pointer for receiving events
WSB_RightsEnabler_EventType Identifiers for event types
WSB_RightsEnabler_GotoURLEvent Event data for reporting that the Rights
Enabler has been directed to a service for obtaining the license
SB_RightsEnabler_LicenseEvent Event data for reporting a valid license
that was found
WSB_RightsEnabler_TransactionEvent Event data for reporting that a data
service transaction has been initiated in an attempt to obtain the needed rights
WSB_RightsEnabler_TransactionType Identifiers for transactions