Fix for bug 115698 -- crashes when sounds are playing and a window is closed. Create QuickTime movies using a permanent, singleton GWorld port, rather than using the current port, to ensure that they always have a valid port. Also fix some loop logic, and a problem where a time was not cancelled because base and derived classes erroneously duplicated some member variables. r=pinkerton, sr=beard/scc, a=scc
git-svn-id: svn://10.0.0.236/trunk@117386 18797224-902f-48f8-a5cc-f745e15eee43
This commit is contained in:
@@ -161,17 +161,15 @@ protected:
|
||||
OSErr TaskActiveMovies(PRBool *outAllMoviesDone);
|
||||
|
||||
static PRBool TaskOneMovie(Movie inMovie); // return true if done
|
||||
|
||||
|
||||
protected:
|
||||
|
||||
nsCOMPtr<nsISound> mSound; // back ptr, owned and released when play done
|
||||
nsCOMPtr<nsITimer> mTimer;
|
||||
|
||||
Movie mMovie; // the original movie, kept around as long as this request is cached
|
||||
Handle mDataHandle; // data handle, has to persist for the lifetime of any movies
|
||||
// depending on it
|
||||
|
||||
nsVoidArray mMovies; // list of playing movie clones, which are transient.
|
||||
|
||||
};
|
||||
|
||||
#pragma mark -
|
||||
@@ -638,6 +636,58 @@ nsSystemSoundRequest::SoundCallback(SndChannelPtr chan, SndCommand *theCmd)
|
||||
|
||||
#pragma mark -
|
||||
|
||||
// This class should only ever be instantiated once, statically.
|
||||
// Its job is to create, own and destroy the singleton GWorld.
|
||||
class nsMoviePortOwner
|
||||
{
|
||||
public:
|
||||
|
||||
static GWorldPtr GetSingletonMoviePort();
|
||||
|
||||
private:
|
||||
|
||||
// private ctor and dtor. Only GetSingletonMoviePort() can instantiate us.
|
||||
nsMoviePortOwner() {}
|
||||
|
||||
~nsMoviePortOwner()
|
||||
{
|
||||
if (sMoviePort)
|
||||
{
|
||||
::DisposeGWorld(sMoviePort);
|
||||
sMoviePort = nsnull;
|
||||
}
|
||||
}
|
||||
|
||||
void EnsureMoviePort()
|
||||
{
|
||||
if (!sMoviePort)
|
||||
{
|
||||
Rect gWorldBounds = {0, 0, 12, 12};
|
||||
(void)::NewGWorld(&sMoviePort, 8, &gWorldBounds, nil, nil, 0);
|
||||
}
|
||||
}
|
||||
|
||||
GWorldPtr GetMoviePort()
|
||||
{
|
||||
EnsureMoviePort();
|
||||
return sMoviePort;
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
static GWorldPtr sMoviePort;
|
||||
|
||||
};
|
||||
|
||||
GWorldPtr nsMoviePortOwner::sMoviePort = nsnull;
|
||||
|
||||
GWorldPtr nsMoviePortOwner::GetSingletonMoviePort()
|
||||
{
|
||||
static nsMoviePortOwner sMoviePortOwner;
|
||||
return sMoviePortOwner.GetMoviePort();
|
||||
}
|
||||
|
||||
|
||||
NS_IMPL_ISUPPORTS_INHERITED1(nsMovieSoundRequest, nsSoundRequest, nsIStreamLoaderObserver);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
@@ -792,7 +842,7 @@ nsMovieSoundRequest::PlaySound()
|
||||
nsresult rv;
|
||||
|
||||
// we'll have a timer already if the sound is still playing from a previous
|
||||
// request. In that case, we cloen the movie into a new one, so we can play it
|
||||
// request. In that case, we clone the movie into a new one, so we can play it
|
||||
// again from the start.
|
||||
if (!mTimer)
|
||||
{
|
||||
@@ -874,10 +924,14 @@ nsMovieSoundRequest::Notify(nsITimer *timer)
|
||||
OSErr
|
||||
nsMovieSoundRequest::ImportMovie(Handle inDataHandle, long inDataSize, const nsACString& contentType)
|
||||
{
|
||||
GWorldPtr moviePort = nsMoviePortOwner::GetSingletonMoviePort();
|
||||
Handle dataRef = nil;
|
||||
OSErr err = noErr;
|
||||
OSType fileFormat;
|
||||
|
||||
if (!moviePort)
|
||||
return memFullErr;
|
||||
|
||||
{
|
||||
StHandleLocker locker(inDataHandle);
|
||||
fileFormat = GetFileFormat(*inDataHandle, inDataSize, contentType);
|
||||
@@ -894,6 +948,11 @@ nsMovieSoundRequest::ImportMovie(Handle inDataHandle, long inDataSize, const nsA
|
||||
long outFlags = 0;
|
||||
ComponentResult compErr = noErr;
|
||||
|
||||
// set the port to our singleton GWorld before creating
|
||||
// the movie. This will ensure that the movie uses this port, and
|
||||
// not one of our (transient) windows.
|
||||
StGWorldPortSetter gWorldSetter(moviePort);
|
||||
|
||||
if (!miComponent) {
|
||||
err = paramErr;
|
||||
goto bail;
|
||||
@@ -932,7 +991,7 @@ nsMovieSoundRequest::ImportMovie(Handle inDataHandle, long inDataSize, const nsA
|
||||
}
|
||||
|
||||
::GoToEndOfMovie(mMovie); // simplifies the logic in PlaySound()
|
||||
|
||||
|
||||
bail:
|
||||
if (miComponent)
|
||||
::CloseComponent(miComponent);
|
||||
@@ -950,7 +1009,7 @@ nsMovieSoundRequest::DisposeMovieData()
|
||||
for (PRInt32 i = 0; i < mMovies.Count(); i ++)
|
||||
{
|
||||
Movie thisMovie = (Movie)mMovies.ElementAt(i);
|
||||
::DisposeMovie(mMovie);
|
||||
::DisposeMovie(thisMovie);
|
||||
}
|
||||
|
||||
mMovies.Clear();
|
||||
@@ -993,11 +1052,11 @@ nsMovieSoundRequest::TaskActiveMovies(PRBool *outAllMoviesDone)
|
||||
PRBool allMoviesDone = PR_FALSE;
|
||||
|
||||
allMoviesDone = TaskOneMovie(mMovie);
|
||||
|
||||
|
||||
PRInt32 initMovieCount = mMovies.Count();
|
||||
PRInt32 curIndex = 0;
|
||||
|
||||
for (PRInt32 i = 0; i < initMovieCount; i ++)
|
||||
|
||||
while (curIndex < mMovies.Count())
|
||||
{
|
||||
Movie thisMovie = (Movie)mMovies.ElementAt(curIndex);
|
||||
PRBool thisMovieDone = TaskOneMovie(thisMovie);
|
||||
@@ -1044,3 +1103,4 @@ nsMovieSoundRequest::HaveQuickTime()
|
||||
return (err == noErr) && ((long)EnterMovies != kUnresolvedCFragSymbolAddress);
|
||||
}
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user