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 |
A top-level client typically implements the following interfaces:
IRMAClientAdviseSink
. Header file: rmaclsnk.h
. The top-level client implements this interface to receive notifications from the client core about changes in a presentation's playback status.
IRMASiteSupplier
. Header file: rmawin.h
. A top-level client implements this interface for use by the client core when displaying data in windows. See "Chapter 12: Sites (Windowing)" for more information.
IRMAAuthenticationManager
. Header file: rmaauth.h
. The top-level client implements this interface to receive notification to gather a username and password.
IRMAPacketHook
. Header file: rmaphook.h
. The top-level client implements this interface to receive presentation recording information from the client core.
IRMAVolumeAdviseSink
. Header file: rmaausvc.h
. A client can implement this interface to receive notifications of changes in volume level or mute state. Refer to "Chapter 13: Audio Services" for more information.
IRMAErrorSink
. Header file: rmaerror.h
. A top-level client can implement this interface to receive notice of system errors. See "Chapter 15: Status Codes and Errors" for more information.
IRMAPropWatchResponse
. Header file: rmamon.h
. The top-level client can implement this interface to receive notifications when monitored resources in the RealServer registry change.
![]() |
Additional Information |
---|
See "Chapter 9: Monitor Plug-in". |
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.
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:
IRMAClientEngine::CreatePlayer
Creates a new IRMAPlayer
interface. The top-level client creates a new player object for each presentation. A rendering plug-in can create a new player object to, for example, start a new time and insert an instantaneous sound into the presentation.
![]() |
Additional Information |
---|
See "Implementing Midstream Playback and Instant Sounds". |
IRMAClientEngine::ClosePlayer
IRMAClientEngine::GetPlayerCount
Returns the number of player objects currently associated with the client core.
IRMAClientEngine::GetPlayer
Returns a player object supported by the client core. The top-level client or plug-in uses this after getting the player object count.
IRMAClientEngine::EventOccurred
Passes operating system events to all player objects. The header file pnwintyp.h defines the cross-platform event structure.
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.
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.
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.
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:
IRMAPlayer::AddAdviseSink
Becomes a client advise sink and receive notifications of player status.
![]() |
Additional Information |
---|
See "Getting Information about a Presentation". |
IRMAPlayer::GetClientContext
IRMAPlayer::SetClientContext
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:
IRMAPlayer::Begin
Begins playback of all sources or restart playback after a pause.
IRMAPlayer::OpenURL
Opens the specified URL. The top-level client calls this when the user specifies a location or file to open. Instead of using this method, rendering plug-ins can cause the client or browser to open a URL through hypernavigation.
![]() |
Additional Information |
---|
See "Hypernavigating". |
IRMAPlayer::Pause
Pauses playback of all sources. If IRMAPlayer::Pause
is called multiple times, IRMAPlayer::Begin
must be called the same number of times to restart the presentation. If a renderer and the top-level client both call IRMAPlayer::Pause
, for example, they must both call IRMAPlayer::Begin
before the presentation restarts. The opposite is not true, however. Calling IRMAPlayer::Pause
always pauses the presentation regardless of how many times IRMAPlayer::Begin
was called to start the presentation.
IRMAPlayer::Seek
Seeks in the playback timeline to the designated time, expressed in milliseconds from the start of the presentation timeline.
IRMAPlayer::Stop
Stops playback of all sources. If restarted, the presentation commences at the beginning of its timeline.
The following IRMAPlayer
methods let the top-level client or rendering plug-in gather information about the presentation:
IRMAPlayer::GetCurrentPlayTime
Get the current time on the presentation timeline. Rendering plug-ins do not need to call this method because they receive updates automatically from the client based on their requested synchronization parameters.
![]() |
Additional Information |
---|
See "Timing and Synchronization". |
IRMAPlayer::GetSource
Return a pointer to a designated stream source object. The top-level client or renderer can then use IRMAStreamSource
to access the stream source object. This object can provide access to the individual stream objects, which use IRMAStream
. The rendering plug-in section contains information on using these objects and interfaces.
IRMAPlayer::GetSourceCount
Return the number of stream sources in the player presentation.
IRMAPlayer::IsDone
Ask the player object if the current presentation has finished.
IRMAPlayer::IsLive
Ask the player object if the current presentation contains a live broadcast source.
The following IRMAPlayer2
methods let the rendering plug-in get or set preroll properties of the player:
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:
IRMAClientAdviseSink::OnPosLength
Presentation timeline's current position or total length has changed. The method supplies the new position and length.
IRMAClientAdviseSink::OnPresentationOpened
IRMAClientAdviseSink::OnPresentationClosed
IRMAClientAdviseSink::OnStatisticsChanged
IRMAClientAdviseSink::OnPreSeek
Seek is about to occur. The method passes the last stream time value before the seek and the new time value for when the seek completes. Renderers are passed this information through IRMARenderer::OnPreSeek
.
IRMAClientAdviseSink::OnPostSeek
Seek has finished. The call includes the time in the stream timeline when the seek occurred, and the new time following the seek. Renderers are passed this information through IRMARenderer::OnPostSeek
.
IRMAClientAdviseSink::OnStop
IRMAClientAdviseSink::OnPause
Presentation paused. The call includes the last time in the presentation timeline before the pause.
IRMAClientAdviseSink::OnBegin
Presentation has begun or restarted. The call includes the time in the timeline where the presentation began or restarted.
IRMAClientAdviseSink::OnBuffering
Presentation is buffering. The call includes the reason for buffering and the percent complete.
IRMAClientAdviseSink::OnContacting
Client core is contacting host. The call includes a pointer to a buffer containing the host address.
The top-level client can manipulate groups in a RealSystem presentation by using the following interfaces:
IRMAGroupManager
A top-level client or rendering plug-in uses this interface to add or remove sinks; create or add groups; get, set, or remove groups, or get the number of groups in a presentation.
IRMAGroupSink
A top-level client can use this interface to receive notifications of tracks added to a group, tracks removed from a group, tracks started or stopped in a group, and groups added to or removed from a presentation.
IRMAGroup
IRMAGroupManager
uses this interface to add a track to a group, remove a track from a group, start or get a track in a group, get the number of tracks in a group, and get or set properties of a group.
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.
The IRMAPacketHook
interface lets the top-level client "hook" packets for recording:
IRMAPacketHookManager::InitHook
on the client core to identify itself as the IRMAPacketHook
interface.
IRMAPacketHookManager::StartHook
to start recording.
IRMAPacketHook::OnStart
.
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. |
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.
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. |
IRMAPacketHookManager::StopHook
to stop or pause recording. It closes the hook with IRMAPacketHookManager::CloseHook
.
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:
/samples/intermed/testplay/exadvsnk.cpp
This sample file contains a class that implements the IRMAAdviseSink
interface. Methods in this class will be called by the client core to inform the top-level client when certain events have occurred.
/samples/intermed/testplay/exaumgr.cpp
This sample file contains the implementation of a class that handles authentication requests from the client core.
/samples/intermed/testplay/excontxt.cpp
This sample file contains the implementation of a class that handles the client context.
/samples/intermed/testplay/exerror.cpp
This sample file contains the implementation of a class that reports the severity and type of error that occurred.
/samples/intermed/testplay/exsitsup.cpp
This sample file contains the implementation of a class that creates and destroys the site.
/samples/intermed/testplay/fivemmap.cpp
This sample file contains a "five minute map", a generalized key/value map.
/samples/intermed/testplay/main.cpp
This sample file builds an example top-level client that can be used to develop a custom top-level client or as a testing tool for plug-ins.
![]() |
Additional Information |
---|
See "Testing with TestPlay". |
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".