previous next

Chapter 20: Top-Level Client

A RealSystem client such as RealPlayer consists of two major parts, the top-level client and the client core. The core handles data transport with RealServer and provides RealSystem features such as Audio Services. The top-level supplies the user interface, communicating to the core and other components, such as rendering plug-ins, through RealSystem interfaces.

The RealSystem SDK provides the interfaces required to link to the client core. This section describes how to incorporate RealSystem client methods into an application to communicate with RealServer and render RealSystem files through the client's rendering, file format, and file system plug-ins. The various plug-in sections describe how the plug-ins communicate to the client core response interfaces.

Note
This chapter does not explain how to use ActiveX or Java to embed RealPlayer functionality in Web pages. For more on this topic, see Embedded RealPlayer Extended Functionality Guide, which is available for download at http://service.real.com/help/library/index.html

Interfaces

A top-level client typically implements the following interfaces:

Building a Client

You can build a top-level client with any development tools. On start-up, the top-level client loads the client core (rmacore.dll) and calls that library's CreateEngine function to return a pointer to the client engine object. The top-level client can then use IRMAClientEngine to utilize the client core and create a player object. On shutdown, the top-level client calls the C-style function CloseEngine to close the client engine.

Using the Client Core

The top-level client receives a pointer to the client core when it creates the client engine at start-up. A rendering plug-in uses IRMAPlayer::GetClientEngine to get a pointer to the client core object. The top-level client or plug-in can then use IRMAClientEngine methods to set up new player objects:

Enumerating Plug-Ins

A top-level client can use the core's plug-in enumerator interfaces to find all plug-ins or all plug-ins that support a specific interface. This includes rendering, file format, and file system plug-ins. To return the total number of plug-ins supported by the client core, the top-level client calls IRMAPluginEnumerator::GetNumOfPlugins. It can then call IRMAPluginEnumerator::GetPlugin to return an instance of a plug-in.

To determine how many plug-ins expose a specific interface, the client calls IRMAPluginGroupEnumerator::Init to pass the enumerator object an interface ID. The client can then call IRMAPluginEnumerator::GetNumOfPlugins to get the number of plug-ins that support that interface. It uses IRMAPluginEnumerator::GetPlugin to return an instance of a plug-in.

Handling Password Authentication

When file authentication is required, the top-level client handles the password input from the user. For example, RealPlayer uses a pop-up dialog box to gather the user's username and password. If you are implementing RealSystem client functionality, you need to ensure that your application handles password input.

Additional Information
See "Chapter 19: Authentication".

When it receives a password request from a server, the client core calls IRMAAuthenticationManager::HandleAuthenticationRequest to query the top-level client for the username and password. The top-level client then retrieves the username and password by the appropriate means, passing the strings back with IRMAAuthenticationManagerResponse::AuthenticationRequestDone.

If the connection is to RealServer, the client core handles the transmission of the username and password. If the Server connection is through HTTP, the client uses the HTTP file system plug-in to send the username and password back as a WWW-authorization header through IRMAPassword::AsString. Note that the file system plug-in prepends "authorization" before sending back the string.

Using select on UNIX

On UNIX, top-level clients should use the IRMAClientEngineSelector::Select method in place of the UNIX select. To the top-level client, this method appears identical to the UNIX select, as it includes file descriptor sets and a timeout value. But using this method instead of UNIX select() lets the client core perform the necessary actions that allow it to select on the sets.

A top-level client that does not need to control the main loop can call IRMAClientEngineSelector::Select with no timeout value and possibly nothing set in the file descriptor sets if it does not have anything it needs to read or write from. If the top-level client needs to poll the client core, it can call this method with a timeout of 0 (zero). The core does a quick select to determine what needs to be done.

Note
IRMAClientEngineSelector::Select returns whenever the inner select does. This lets the top-level client pass nothing in the call, which for a normal select would return only when interrupted by a signal.

Using a Player Object

For each presentation, there is at least one player object that top-level clients and rendering plug-ins can access through IRMAPlayer and IRMAPlayer2. A presentation can also have multiple objects. An audio renderer can, for example, create a new player object to start a new timeline and insert an instantaneous sound into the presentation.

Additional Information
See "Implementing Midstream Playback and Instant Sounds". See "Using the Client Core" for information on creating new player objects.

The top-level client uses the following IRMAPlayer methods to associate itself with the client core:

The IRMAPlayer interface includes several methods that let the top-level client or rendering plug-in control the presentation. The top-level client typically calls these methods in response to user input:

The following IRMAPlayer methods let the top-level client or rendering plug-in gather information about the presentation:

The following IRMAPlayer2 methods let the rendering plug-in get or set preroll properties of the player:

Getting Information about a Presentation

The top-level client can use IRMAPlayer::AddAdviseSink to receive notifications of presentation status from a player object. The client core then uses the following IRMAClientAdviseSink methods to inform the top-level client about presentation changes:

Manipulating Groups in a Presentation

The top-level client can manipulate groups in a RealSystem presentation by using the following interfaces:

Recording a Presentation

The top-level client can include recording capability that lets the user write all or part of a RealSystem presentation to a single file on the client machine. The file includes all recordable streams (some streams can prohibit recording) in a container file format such as the RealMedia File Format. Because this file captures the playback and not the original data sources, it does not contain the stream control information that file format plug-ins used to create the original streams. So while providing acceptable local playback on client machines, the recorded file is not suitable for playback over a network.

Successfully recording a presentation requires that the plug-ins used to render the presentation streams implement recording support to supply datatype information. For example, RealVideo and RealFlash record private timing information in packet portions opaque to RealSystem. The renderers must adjust this information to create a new timeline in cases where the user starts recording after a presentation has begun. As well, renderers for datatypes such as RealFlash may need to provide the required layout or keyframe data that was received before the user started recording.

Additional Information
See "Providing Recording Information to the Client".

The top-level client implements IRMAPacketHook, which is similar to the IRMAFormatResponse interface that file format plug-ins use to provide streaming data to RealSystem. However, this interface allows aggregation of multiple streams from independent sources into a single playback source.

Hooking Data for Recording

The IRMAPacketHook interface lets the top-level client "hook" packets for recording:

  1. The top-level client calls IRMAPacketHookManager::InitHook on the client core to identify itself as the IRMAPacketHook interface.

  2. The top-level client calls IRMAPacketHookManager::StartHook to start recording.

  3. The client core calls IRMAPacketHook::OnStart.

  4. The client core calls IRMAPacketHook::OnFileHeader to pass the top-level client a pointer to an IRMAValues interface that contains an "aggregated" file header that contains a default title author and copyright section for the entire presentation, as well as the total stream count.

    Additional Information
    See "Using IRMAValues to Create Indexed Lists" for the basics of creating and reading values interfaces.

  5. For each stream, the client core calls IRMAPacketHook::OnStreamHeader passing the top-level client a pointer to an IRMAValues interface containing the stream header information. The stream header has 1 for the Recordable property if the stream can be recorded, 0 if it cannot be recorded.

    Note
    A stream is not recordable if the source that it orginated from was missing the Recordable property, or if the stream renderer does not provide recording support. The top-level client is responsible for notifying the user of any parts of the presentation that cannot be recorded.

  6. For the various streams, the client core calls IRMAPacketHook::OnPacket passing the top-level client a pointer to IRMAPacket interfaces containing the stream data.

    Additional Information
    See "Using IRMAPacket to Create Stream Packets" for the basics of packet creation and reading.

  7. The top-level client then writes the data to a container file format, such as the RealMedia File Format.

  8. The top-level client calls IRMAPacketHookManager::StopHook to stop or pause recording. It closes the hook with IRMAPacketHookManager::CloseHook.

Modifying the Top-level Client Sample Code

The RealSystem SDK provides several sample versions of a top-level client. Each sample demonstates one or more different nuances for using these top-level clients.

The TestPlay application is a sample top-level client that does not include a graphical user interface. It is provided as source code in the /samples/intermed/testplay directory. You can use TestPlay as the basis for building your own RealSystem client. The TestPlay sample contains the following files:

Another version of TestPlay is located in the /samples/intermed/exauddev directory. This version of TestPlay demonstrates how to implement low-level audio support in the top-level client. The FakeAudioDevice interface used in the exauddev.cpp file is analagous to some operating system-specific audio services, such as DirectSound. The purpose of the sample is to show how to get audio packets from the core, then pass them to an abstracted and generic audio device. The sample, however does not actually do anything with the audio packets.

Another TestPlay sample is located in the /samples/advanced/exwlsite directory. For more information on this sample, see "Modifying the Site Sample Code".


Copyright © 2000 RealNetworks
For technical support, please contact supportsdk@real.com.
This file last updated on 05/17/00 at 13:37:07.
previous next