- Pushing and popping contexts
- Whenever an Xtra might be calling the player back from a message sent directly to its window proc by Windows,
the player calls must be bracketed with calls to PushXtraContext() and PopXtraContext().
The DrContextState must be a local variable in the calling function.
- For example, m_pIDrMovieContext is a IMoaDrMovieContext member of the asset Xtra's object class:
/* This code is sometimes called directly from a Windows event
/ received by the Xtra's wndproc. */
DrContextState drContextState;
if (m_pObj->m_pIDrMovieContext &&
!(m_pObj->m_pIDrMovieContext->PushXtraContext(&drContextState)))
{
... /* Call other Director interfaces at will */
m_pObj->m_pIDrMovieContext->PopXtraContext(&drContextState);
}
- If the PushXtraContext() call is not made or the PopXtraContext() call is dropped, the player may crash or produce other unexpected results.
These calls inform the player what movie context applies and, for the ActiveX control only, provide protection for multiple threads.
- The Xtra needs to acquire an IDrMovieContext interface during a call from the player, for example, during the sprite asset's constructor.
- Use a different instance of IMoaDrMovieContext for each instance of your Xtra class.
The IMoaDrMovieContext includes which movie you are being used in, so if you try to share a single copy between multiple instances,
you will get information about the wrong movie when you make calls to the player.
- Use IMoaDrPlayer to get an IMoaDrMovie interface to the active movie.
Then QueryInterface that interface to get an IMoaDrMovieContext interface.
Release the IMoaDrMovie and IMoaDrPlayer interfaces (unless you need them for other reasons),
and keep the IMoaDrMovieContext as a member of your asset Xtra object.
The following C++ code snippet works:
/* m_pIDrMovieContext is a new member of the asset pObj class */
m_pIDrMovieContext = NULL;
PIMoaDrPlayer pIMoaDrPlayer = NULL;
PIMoaDrMovie pIMoaDrMovie = NULL;
if (!m_pICallback->QueryInterface(&IID_IMoaDrPlayer, (PPMoaVoid)&pIMoaDrPlayer))
{
if (!pIMoaDrPlayer->GetActiveMovie(&pIMoaDrMovie))
{
pIMoaDrMovie->QueryInterface(&IID_IMoaDrMovieContext, (PPMoaVoid)&m_pIDrMovieContext);
pIMoaDrMovie->Release();
}
pIMoaDrPlayer->Release();
}
- The destructor must release, of course:
if (m_pIDrMovieContext != NULL)
{
m_pIDrMovieContext->Release();
m_pIDrMovieContext = NULL;
}