--------------------------------------------------------------------------------------------------------------------
Hello all,
does anybody have a snippet of C++ code to stop and restart a given
plugin? I want to "intercept" at DOM level (i.e. when I parse the
<embed> tag) the
Flash Movie Player plugin, stop it, change the "wmode" parameter of
the node
and restart it. This is because I am grabbing the pixels of the
rendered HTML page and draw everything on an OpenGL texture, but, by
default, Flash draws on a separate window, so all I get are white
pixels. I want to see if changing on-the-fly the "wmode" parameter to
"opaque" (which forces Flash to draw in the same "background" window)
and restarting the plugin in order to reload the parameter solves the
problem.
Obviously, I already tried to change the wmode value in the DOM node,
but it does not work. I bet I must force the plugin to reload its
parameters, hence the idea to stop and restart it.
I actually do a deep parse of the DOM tree, so I can get the
nsIDOMNode of the <embed> tag, and queryInterface for its iContent
etc.
BTW, I do already have found some code to get the nsIPluginHost,
nsiPluginManager, and enumerate the nsIDOMplugins... but I cannot
understand the relation between nsIDOMPlugin and NSIPluginInstance
(which has interesting methods).
I checked a TON of code on MXR but I cannot get a grasp on it.
Also, I discovered some old code using nsIObjectFrame (which also has
interesting methods)
but now that interface is external-linkage, so I cannot include the
header and use it. Damn.
Which way should be the best one? Which classes/interfaces are the
best to go for? Is the workaround completely nuts?
Thank you very much,
Aaron Brancotti
It might be good to have a saner API for this (say on
nsIObjectLoadingContent). File a bug?
-Boris
>
> http://bonsai.mozilla.org/cvsblame.cgi?file=mozilla/layout/base/nsPre...
Yeah. Just half an hour before reading your answer, I finally
discovered the damn nsIObjectLoadingContent which goes from a DOMNode
to the plugin instance. And yes, I saw the two static functions, but I
was able to use directly only the Start one, because the Stop has some
external-linkage stuff (nsIFrame, nsIObjectFrame etc...)... so I dug
into nsIObjectFrame::StopPlugin() code, and again - apart from some
stuff on frames and views which I cannot replicate and anyway should
not interest me, because I am NOT destroying anything, I am just
stopping and restarting the plugin - I finally understood that, to
stop a plugin, it is enough to call pluginInstance->Stop() and
pluginHost->StopPluginInstance(pluginInstance).
And - guess what? - IT WORKS! :) I am happily grabbing YouTube pixels
now. Thanks, once again.
> It might be good to have a saner API for this (say on
> nsIObjectLoadingContent). File a bug?
well, in fact is quite complex, not for the plugins itself - sure it
should be stated somewhere that those two calls are enough for the
plugin itself to stop properly - but the real mess is all the code one
cannot replicate because is external linkage. All nsIFrames etc...
BTW: while digging, I found something I cannot understand: there is
the concept of "delayed stop", which you apply only ifdef WIN_XP and
with Real audio. See http://mxr.mozilla.org/firefox/source/layout/generic/nsObjectFrame.cpp#1904
... but then some funcs are called, BOOL delayedStop seems not to be
altered, and then I find http://mxr.mozilla.org/firefox/source/layout/generic/nsObjectFrame.cpp#1773
is called... how this could even return TRUE? delayedStop can be true
only if the plugin is Real, and if so, it cannot be QuickTime or
Flip4Mac.. Or I am missing something?
Anyway, it somewhat works. Gotta check listeners now... thanks again.
Aaron
Yeah, I just meant those as starting points.
>> It might be good to have a saner API for this (say on
>> nsIObjectLoadingContent). File a bug?
>
> well, in fact is quite complex, not for the plugins itself - sure it
> should be stated somewhere that those two calls are enough for the
> plugin itself to stop properly - but the real mess is all the code one
> cannot replicate because is external linkage. All nsIFrames etc...
Right, hence it might be a good idea to have an API on
nsIObjectLoadingContent or similar that lets you do this.
> BTW: while digging, I found something I cannot understand: there is
> the concept of "delayed stop", which you apply only ifdef WIN_XP and
> with Real audio.
No, it's also used in nsObjectFrame::Destroy for all plugins.
> See http://mxr.mozilla.org/firefox/source/layout/generic/nsObjectFrame.cpp#1904
> ... but then some funcs are called, BOOL delayedStop seems not to be
> altered, and then I find http://mxr.mozilla.org/firefox/source/layout/generic/nsObjectFrame.cpp#1773
> is called... how this could even return TRUE? delayedStop can be true
> only if the plugin is Real, and if so, it cannot be QuickTime or
> Flip4Mac.. Or I am missing something?
Yes, the second caller of StopPluginInternal (the one in Destroy).
-Boris
me stoooopid. duh.
I stop the plugin with
rv = pluginInstance->Stop();
rv = pluginHost->StopPluginInstance(pluginInstance);
this stops everything and kills Flash. Audio/Video are gone.
I change the wmode, then restart the plugin with
nsCOMPtr<nsIPluginInstance> newPluginInstance;
rv = objlc->EnsureInstantiation(getter_AddRefs
(newPluginInstance));
and Flash restarts. wmode is OK now, and I can grab the pixels. So far
so good.
But this new plugin instance never dies. If I change page or reload, I
keep hearing the movie audio track.
I checked for listeners on the nsIContent, no unload or mutation
listeners. I also tried
rv = owner->SetInstance(newPluginInstance);
but nothing changes (should I do that anyway?)
I am digging into code to understand what I am missing, but cannot
find the missing piece.
Also: If I try to Stop() the plugin, and then Start() it, without
reinstatiating, it does not work, while it is stated (in
nsIPluginInstance.h) that Start() "may be called after the plugin is
stopped (via the Stop method)". (would be probably useless for me, but
just for the records...)
What I am missing?
Thanks once again,
Aaron
Presumably because the frame has a pointer to the old plugin instance or
something? You'd have to trace through the teardown code to see where
it goes awry....
-Boris
thx!
Have you considered following my advice and filing a bug on having an
API available that would do all this correctly for you?
-Boris
Oh, yeah, I will SURELY do that. But I need a fix now, fast and
furious. :) I will post it next week.
thx
Aa