RealSystem consolidates windowing functions in the client core and provides these functions to rendering plug-ins as a platform-independent service. This means that rendering plug-ins do not need to implement window subclassing. Instead, the client core supplies a "site" and the rendering plug-in registers as a "site user." The rendering plug-in can then send data to the client core without providing platform-specific commands for displaying the data.
The RealSystem sites feature also supports "Wall of TVs," which allows a renderer to display data in more than one site simultaneously. In this case the renderer simply sends rendered data to a special default object instantiated by the client. That object then handles displaying the data in the multiple sites without placing any additional burden on the renderer.
To use RealSystem sites, a rendering plug-in implements the following:
IRMASiteUser
. Header file: rmawin.h
. A display renderer implements this interface, which the client uses to associate the renderer with a site object and inform the renderer of events.
IRMASiteUserSupplier
. Header file: rmawin.h
. This interface is used with multiple sites to get instances of the objects that use the sites.
IRMASiteWatcher
. Header file: rmawin.h
. The rendering plug-in can implement this interface if it needs to monitor a window's size and position changes.
The RealSystem top-level client implements this interface:
IRMASiteSupplier
. Header file: rmawin.h
. Interface implemented by the top-level client for use by the client core.
The RealSystem client core implements these interfaces:
IRMASiteFullScreen
. Header file: rmawin.h
. Interface implemented by the client core for use by the top-level client.
IRMASiteManager
. Header file: rmawin.h
. Interface implemented by the client core for use by the top-level client.
IRMAMultiInstanceSiteUserSupplier
. Header file: rmawin.h
. This interface is implemented by a special object that acts as a site user supplier for any site user that wants support for multiple instances. The site user must work as a windowless site for this to work. The default object also implements IRMASite
to allow the site user object to control all the sites through a single interface instance.
The client core implements these interfaces for site objects:
IRMASite
. Header file: rmawin.h
. All site objects implement this interface.
IRMASiteWindowed
. Header file: rmawin.h
. Site objects associated with platform-specific window objects on Microsoft Windows or X-Windows implement this interface.
IRMASiteWindowless
. Header file: rmawin.h
. Site objects that are not associated with platform-specific window objects, hence "windowless," implement this interface. This is always used on the Macintosh, as well as on other platforms when data is rendered in a Web browser.
During rendering plug-in initialization, RealSystem queries the plug-in for its display type. If the rendering plug-in returns RMA_DISPLAY_WINDOW
to indicate that it is a display renderer, the system queries for the plug-in's support of the site interfaces. The plug-in's response to these queries determines whether it supports a single site (one instance of rendered data) or multiple sites (one or more instances of rendered data).
To support a single site, the rendering plug-in implements IRMASiteUser
but not IRMASiteUserSupplier
. When the client calls IRMASiteUser::NeedsWindowedSites
, the renderer responds with TRUE
to render in an operating system-specific window (Windows or UNIX) through IRMASite
and IRMASiteWindowed
. It responds with FALSE
to render operating system-generically through IRMASite
and IRMASiteWindowless
. The following figure illustrates the relationships between objects and main windowing interfaces in an operating system-generic single site.
RealNetworks recommends that a rendering plug-in supports the multisite feature ("Wall of TVs"), which lets the plug-in render data to more than one site. To do this, the plug-in can implement IRMASiteUser
and use its own methods of rendering to the various sites. However, RealSystem provides the Multi-Instance Site User Supplier (MISUS) object, a standard method of rendering to multiple sites with no extra overhead. To use this feature, however, the plug-in must render data in an OS-generic, "windowless" manner. The client's MISUS object then manages the multiple sites.
To support the multisite feature, the plug-in implements IRMASiteUser
. When the system queries for IRMASiteUserSupplier
, the plug-in responds by querying for that same interface through IRMAMultiInstanceSiteUserSupplier
. This latter interface is for the MISUS object, the special window management object instantiated by the client. That object will become the "site" where the renderer sends its data. It will also be the site user supplier for the actual sites (one or more) where the display events occur.
The following extract from a RealSystem SDK sample file shows how the plug-in responds to the interface query. Here, m_pMISUS
has been defined as a pointer to IRMAMultiInstanceSiteUserSupplier
:
else if (IsEqualIID(riid, IID_IRMASiteUser
Supplier))
{
if (m_pMISUS)
{
return m_pMISUS-QueryInterface(IID_IRMASiteUser
Supplier,ppvObj);
}
else
{
*ppvObj = NULL;
return PNR_UNEXPECTED;
}
}
Because multisite support requires that the renderer function in a "windowless" state, the plug-in returns FALSE
when the system calls IRMASiteUser::NeedsWindowedSites
. Before it begins to render data, the plug-in must create an instance of the MISUS object and call the object's IRMAMultiInstanceSiteUserSupplier::SetSingleSiteUser
method to identify itself as the site user. This can happen during plug-in initialization in the IRMARenderer::StartStream
method. The following extract from a RealSystem SDK sample file illustrates this.
m_pCommonClassFactory-CreateInstance(CLSID_IRMAMultiInstanceSiteUserSupplier, (void**)&m_pMISUS);
m_pMISUS-SetSingleSiteUser((IUnknown*)(IRMASiteUser
*)this);
The plug-in then sends rendered data to the MISUS object through IRMASite
and IRMASiteWindowless
methods. The MISUS object handles displaying the data in the actual sites. The rendering plug-in does not need to have any knowledge of the number of sites being used.
The client calls the plug-in's IRMASiteUser::AttachSite
method to pass it a pointer to the site object that receives the rendered data. When the multisite feature is used, the MISUS object becomes the site object. The following example illustrates this:
CExampleRenderer::
AttachSite(IRMASite* /*IN*/ pSite)
{
if (m_pMISUSSite) return PNR_UNEXPECTED;
m_pMISUSSite = pSite;
m_pMISUSSite-AddRef()
;
Within the IRMASiteUser::AttachSite
call, the renderer should use IRMASite::SetSize
to set the site size from information received in the stream header.
![]() |
Note |
---|
Typically, the system calls IRMARenderer::OnHeader before calling
IRMASiteUser::AttachSite . Therefore, the renderer should not call the site
object or the MISUS object in IRMARenderer::OnHeader .
|
To inform the renderer of an event, the client calls the renderer's IRMASiteUser::HandleEvent
method, using the PNxEvent
structure defined in header file pnwintyp.h. The following example illustrates this:
IRMASiteUser::
HandleEvent(PNxEvent*)
The plug-in can then use the methods of IRMASite
, as well as IRMASiteWindowless
or IRMASiteWindowed
to handle the site display.
The PNxEvent
structure contains the following public input members:
ULONG32 event;
void* window;
void* param1;
void* param2;
The following table describes how to use these members for different platforms.
![]() |
Note |
---|
On the Macintosh, the origin, port and clipping region are set before the
renderer's IRMASiteUser::HandleEvent method is called. This way the
renderer can always assume that its "window" is located at 0,0 and that
its port is set up correctly.
|
The rendering plug-in implements IRMASiteWatcher
if it needs to monitor and, if necessary, override a window's size and position changes. It attaches to the site as a watcher with IRMASite::AttachWatcher
. It can later detach itself from the site as a watcher with IRMASite::DetachWatcher
.
The client core then notifies the renderer about changes in window size and placement with IRMASiteWatcher::ChangingPosition
or IRMASiteWatcher::ChangingSize
, passing the renderer the old and new postion or size parameters, respectively.
When the presentation ends, the client calls the plug-in's IRMASiteUser::DetachSite
method to release the site. If the renderer uses the MISUS object, it needs to call that object's IRMAMultiInstanceSiteUserSupplier::ReleaseSingleSiteUser
method and then release the object.
If you are building a top-level client, you should add site support as described in this section. The top-level client implements IRMASiteSupplier
, which the client core uses to inform the top-level of the need for sites. The top-level then uses IRMASiteManager
to communicate with the client core.
![]() |
Additional Information |
---|
See "Chapter 20: Top-Level Client". |
When the client core needs a site, it calls IRMASiteSupplier::SitesNeeded
to pass the top-level client a request ID and a pointer to an IRMAValues
interface that contains the site properties. The top-level client then creates the window and calls IRMASiteManager::AddSite
to pass the core a pointer to the IRMASite
interface.
The client core calls IRMASiteSupplier::SitesNotNeeded
when it is finished with a site. The top-level client then destroys the window and calls IRMASiteManager::RemoveSite
to pass the core a pointer to the IRMASite
interface.
If the presentation layout changes so that new windows are needed or existing windows are not, the client core calls IRMASiteSupplier::BeginChangeLayout
to notify the top-level client. The top-level can then expect to receive IRMASiteSupplier::SitesNeeded
and IRMASiteSupplier::SitesNotNeeded
calls. The core calls IRMASiteSupplier::DoneChangeLayout
when the new presentation layout is complete.
The RealSystem SDK provides sample code that demonstrates how to write a top-level client that lets you capture or intercept video frames. Possible reasons to do this include applying some visual effects to the frames of video, displaying frames using a non-standard windowing API (for example, on Unix you might want to support GTK instead of Motif) , or grabbing "thumbnail" images (that is, the first frame of a clip).
![]() |
Note |
---|
Although this sample appears to show how to implement a windowless
site, it actually demonstrates how to implement IRMASiteWindowed , and is
only called windowless because it does not actually display any windows.
|
The sample code is implemented in the following files:
/samples/advanced/exwlsite/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/advanced/exwlsite/exaumgr.cpp
This sample file contains the implementation of a class that handles authentication requests from the client core.
/samples/advanced/exwlsite/excontxt.cpp
This sample file contains the implementation of a class that handles the client context.
/samples/advanced/exwlsite/exerror.cpp
This sample file contains the implementation of a class that reports the severity and type of error that occurred.
/samples/advanced/exwlsite/exnwsite.cpp
This sample file contains the implementation of a class that manages the site by handling users, placing the window, managing child sites, and supervising events that occur on the site.
/samples/advanced/exwlsite/exsitsup.cpp
This sample file contains the implementation of a class that creates and destroys the site.
/samples/advanced/exwlsite/exvsurf.cpp
This sample file contains the implementation of a class that manages the data that is drawn on the video surface.
/samples/advanced/exwlsite/fivemlist.cpp
This sample file contains a generalized linked list implementation.
/samples/advanced/exwlsite/fivemmap.cpp
This sample file contains a "five minute map", a generalized key/value map.
/samples/advanced/exwlsite/main.cpp
This sample file builds an example top-level client that demonstrates how to capture or intercept video frames. This sample can be used to develop a custom top-level client or as a testing tool for plug-ins.