Controlling Visualizations from C++?
WMPTalk.com Forum Index WMPTalk.com
Discuss Windows Media Player
 
 FAQFAQ   MemberlistMemberlist     RegisterRegister 
 ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 
 
Google
 
Web wmptalk.com
Controlling Visualizations from C++?

 
Post new topic   Reply to topic    WMPTalk.com Forum Index -> SDK
Author Message
TMS
Guest





Posted: Fri Oct 15, 2004 9:01 pm    Post subject: Controlling Visualizations from C++? Reply with quote

Greetings.

Are there interfaces that would enable me to list the available
visualizations and select which one is used from a C++ program? I'm accessing
media player as an embedded control in a dialog using Visual C++ 6.0.

The thread "Future WMP object model directions?" included the following from
godofcpu:

"Since the release of WMP 10, I am very happy with the completeness of the
SDK. There is nothing that I can think of that I can't find someway to do
with the SDK, although some require some hacks and more work then I would
like, i.e. controlling visualizations." (BTW: godofcpu, thanks again for
the info on accessing album art. The code snippet was helpful, too.)

Any info appreciated,

Regards,
--- TMS

Back to top
godofcpu
Guest





Posted: Mon Oct 18, 2004 8:07 pm    Post subject: RE: Controlling Visualizations from C++? Reply with quote

Aw, I knew someone was eventually gonna ask about that. It's really quite a
clever method, if I do say so myself, but is very involved and took me about
a month to get done right.

No there aren't interfaces directly available from C++ that let you access
the visualizations. The way I did it was through a very much hacked method
that I believe is also very similar to how windows media center controls
visualizations and is what actually got me started on looking for a way on
how they did it.

This is a very complicated method and will require you to have quite a bit
of knowledge of how COM works, but it seems to work very well once done.
The key is in the fact that you can control the visualizations however you
want from a custom skin, you can communicate from C++ to the skin through the
IWMPRemoteMediaServices::GetScriptableObject method and you can specify
whatever custom skin you want from C++. Now for me since my interface is in
Direct3D, I couldn't just use the media player UI and show the skin with vis
controls on it, if you don't have this restricition, then your easy way to
controlling visualizations is just to show a custom skin with visualization
controls. I just use my skin to give me access to the things only exposed
through skin interfaces.

I can't post all the code for everything directly since the program I wrote
this for is commercial, but I will try and give you a start and try to show
you how to call the Effects.NextPreset function through the skin however,
you can get the list of all effects and the other things exposed by the skin
through similar means.

The first thing you need is a custom skin, this is my complete skin I use.
The only thing on the skin is the visualzations. The only time I show the
skin is when visualizations are playing:
<THEME>
<VIEW
onload="JScript: OnLoad();"
titlebar="false"
resizable="false"
backgroundcolor="black"
Quote:

<EFFECTS

id = "oEffects"
top = "0"
left = "0"
width = "wmpprop:view.width"
height = "wmpprop:view.height"
/>
</VIEW>
</THEME>


Next you need to make a javascript file for the skin that gets called when
the OnLoad even happens. The WMSkinInterface object is actually a COM
interface implemented in C++ that is visible to the javascript applictation
i.e.
//******************************************************************************
//OnLoad
//Desc: When the file is loaded return a function struct filled with pointers
// to all the functions that enable the C++ app to use them directl
//******************************************************************************
function OnLoad()
{
var p = new FunctionStruct();

p.PreviousPreset = oEffects.nextPreset;

WMSkinInterface.VisFunctions = p;
}

//******************************************************************************
//FunctionStruct
//Desc: Placeholder function to pass back the functions in the file as COM
// object
//******************************************************************************
function FunctionStruct(){}





Now in your C++ program you need to implemented the IWMPRemoteMediaServices
interface and the method GetScriptableObject
//***************************************************************************
// GetScriptableObject()
// Return the scriptable object for communicating with the skin
//***************************************************************************
HRESULT CRemoteHost::GetScriptableObject(BSTR * pbstrName, IDispatch **
ppDispatch)
{
if(pbstrName)
{
*pbstrName = ::SysAllocString(L"WMSkinInterface");
}
if(ppDispatch)
{

*ppDispatch = &m_WMSkinInterface;
}
return S_OK;
}







Now you now need to implement the interface that gets passed back to the
skin as an IDispatch object and implement the vDispInvoke method. I used the
CDynamicObject code on www.codeproject.com for this. Make sure you add a
property called "VisFunctions" to it that gets used by the javascript portion
of hte skin.

HRESULT WMSkinInterface::vDispInvoke(
void FAR* _this,
ITypeInfo FAR* ptinfo,
DISPID dispidMember,
unsigned short wFlags,
DISPPARAMS FAR* pparams,
VARIANT FAR* pvarResult,
EXCEPINFO* pexcepinfo,
unsigned int FAR* puArgErr )
{
/*
This is where all the work really takes place...
Since we know most of the methods, functions etc....
*/
switch (dispidMember)
{
case WMSKININTERFACE_VISFUNCTION:
return HandleVisFunctions(wFlags,pparams,pvarResult);
};

return S_OK;
}

//******************************************************************************
//HandleVisFunctions
//Desc: We should handle the PUT property for the 1 member we expose as put
to get
// the pointer to the skin interfaces we set the "VisFunctions" equal to in
// the PUT operation.

//******************************************************************************
HRESULT WMSkinInterface::HandleVisFunctions(unsigned short wFlags,
DISPPARAMS FAR* pparams,
VARIANT FAR* pvarResult)
{
if(wFlags & DISPATCH_PROPERTYPUT)
{
HRESULT hr;

//Add all the entries in the COM array to the effects array
IDispatch* pdispFunction = (IDispatch*) pparams->rgvarg->pdispVal;;
hr = pdispFunction->QueryInterface(IID_IDispatchEx, (void
**)&m_pSkinFunctions);
if (FAILED(hr))
return hr;
}
else
{
//Get is not implemented
ASSERT(FALSE);
}

return S_OK;
}

//******************************************************************************
//DispatchNextPreset
//Desc: Call the NextPreset method implemented in the skin through
m_pSkinFunctions
//******************************************************************************
HRESULT WMSkinInterface::DispatchNextPreset()
{
HRESULT hr;
DISPPARAMS dispparamsNoArgs = {NULL, NULL, 0, 0};
DISPID dispidFunction;
VARIANT var;

// Get dispatch id for the GetCurrentEffect function
hr =
m_pSkinFunctions->GetDispID(CComBSTR(CStringW("NextPreset").GetString()), 0,
&dispidFunction);
if (FAILED(hr))
return hr;

hr = m_pSkinFunctions->InvokeEx(dispidFunction, LOCALE_USER_DEFAULT,
DISPATCH_METHOD, &dispparamsNoArgs,
&var, NULL, NULL);
return hr;
}


That's it, if you got this far, all that you should now have to do is call
DispatchNextPreset whenever you want to change the visualization.

"TMS" wrote:

Quote:
Greetings.

Are there interfaces that would enable me to list the available
visualizations and select which one is used from a C++ program? I'm accessing
media player as an embedded control in a dialog using Visual C++ 6.0.

The thread "Future WMP object model directions?" included the following from
godofcpu:

"Since the release of WMP 10, I am very happy with the completeness of the
SDK. There is nothing that I can think of that I can't find someway to do
with the SDK, although some require some hacks and more work then I would
like, i.e. controlling visualizations." (BTW: godofcpu, thanks again for
the info on accessing album art. The code snippet was helpful, too.)

Any info appreciated,

Regards,
--- TMS
Back to top
TMS
Guest





Posted: Tue Oct 19, 2004 8:05 am    Post subject: RE: Controlling Visualizations from C++? Reply with quote

Thanks very much. 'Looks like I've got some homework to do :-)

I had wondered about something vaguely along the lines of your approach when
I saw that you could apparently get the information from the EFFECTS
interface for a skin. I was thinking about whether I could get the JScript to
pass the data via some ActiveX control that was hooked into my C++ program,
but that's as far as I got with that. You've saved me a lot of
experimentation that probably would have ended in frustration!

....It's a bit unfortunate that skins can access these settings but that
they're not available directly as interfaces from the player control, isn't
it?

--- TMS

"godofcpu" wrote:

Quote:
Aw, I knew someone was eventually gonna ask about that. It's really quite a
clever method, if I do say so myself, but is very involved and took me about
a month to get done right.

No there aren't interfaces directly available from C++ that let you access
the visualizations. The way I did it was through a very much hacked method
that I believe is also very similar to how windows media center controls
visualizations and is what actually got me started on looking for a way on
how they did it.

This is a very complicated method and will require you to have quite a bit
of knowledge of how COM works, but it seems to work very well once done.
The key is in the fact that you can control the visualizations however you
want from a custom skin, you can communicate from C++ to the skin through the
IWMPRemoteMediaServices::GetScriptableObject method and you can specify
whatever custom skin you want from C++. Now for me since my interface is in
Direct3D, I couldn't just use the media player UI and show the skin with vis
controls on it, if you don't have this restricition, then your easy way to
controlling visualizations is just to show a custom skin with visualization
controls. I just use my skin to give me access to the things only exposed
through skin interfaces.

I can't post all the code for everything directly since the program I wrote
this for is commercial, but I will try and give you a start and try to show
you how to call the Effects.NextPreset function through the skin however,
you can get the list of all effects and the other things exposed by the skin
through similar means.

The first thing you need is a custom skin, this is my complete skin I use.
The only thing on the skin is the visualzations. The only time I show the
skin is when visualizations are playing:
THEME
<VIEW
onload="JScript: OnLoad();"
titlebar="false"
resizable="false"
backgroundcolor="black"

<EFFECTS
id = "oEffects"
top = "0"
left = "0"
width = "wmpprop:view.width"
height = "wmpprop:view.height"
/
</VIEW
/THEME


Next you need to make a javascript file for the skin that gets called when
the OnLoad even happens. The WMSkinInterface object is actually a COM
interface implemented in C++ that is visible to the javascript applictation
i.e.:
//******************************************************************************
//OnLoad
//Desc: When the file is loaded return a function struct filled with pointers
// to all the functions that enable the C++ app to use them directly
//******************************************************************************
function OnLoad()
{
var p = new FunctionStruct();

p.PreviousPreset = oEffects.nextPreset;

WMSkinInterface.VisFunctions = p;
}

//******************************************************************************
//FunctionStruct
//Desc: Placeholder function to pass back the functions in the file as COM
// objects
//******************************************************************************
function FunctionStruct(){}





Now in your C++ program you need to implemented the IWMPRemoteMediaServices
interface and the method GetScriptableObject
//***************************************************************************
// GetScriptableObject()
// Return the scriptable object for communicating with the skin
//***************************************************************************
HRESULT CRemoteHost::GetScriptableObject(BSTR * pbstrName, IDispatch **
ppDispatch)
{
if(pbstrName)
{
*pbstrName = ::SysAllocString(L"WMSkinInterface");
}
if(ppDispatch)
{

*ppDispatch = &m_WMSkinInterface;
}
return S_OK;
}







Now you now need to implement the interface that gets passed back to the
skin as an IDispatch object and implement the vDispInvoke method. I used the
CDynamicObject code on www.codeproject.com for this. Make sure you add a
property called "VisFunctions" to it that gets used by the javascript portion
of hte skin.

HRESULT WMSkinInterface::vDispInvoke(
void FAR* _this,
ITypeInfo FAR* ptinfo,
DISPID dispidMember,
unsigned short wFlags,
DISPPARAMS FAR* pparams,
VARIANT FAR* pvarResult,
EXCEPINFO* pexcepinfo,
unsigned int FAR* puArgErr )
{
/*
This is where all the work really takes place...
Since we know most of the methods, functions etc....
*/
switch (dispidMember)
{
case WMSKININTERFACE_VISFUNCTION:
return HandleVisFunctions(wFlags,pparams,pvarResult);
};

return S_OK;
}

//******************************************************************************
//HandleVisFunctions
//Desc: We should handle the PUT property for the 1 member we expose as put
to get
// the pointer to the skin interfaces we set the "VisFunctions" equal to in
// the PUT operation.

//******************************************************************************
HRESULT WMSkinInterface::HandleVisFunctions(unsigned short wFlags,
DISPPARAMS FAR* pparams,
VARIANT FAR* pvarResult)
{
if(wFlags & DISPATCH_PROPERTYPUT)
{
HRESULT hr;

//Add all the entries in the COM array to the effects array
IDispatch* pdispFunction = (IDispatch*) pparams->rgvarg->pdispVal;;
hr = pdispFunction->QueryInterface(IID_IDispatchEx, (void
**)&m_pSkinFunctions);
if (FAILED(hr))
return hr;
}
else
{
//Get is not implemented
ASSERT(FALSE);
}

return S_OK;
}

//******************************************************************************
//DispatchNextPreset
//Desc: Call the NextPreset method implemented in the skin through
m_pSkinFunctions
//******************************************************************************
HRESULT WMSkinInterface::DispatchNextPreset()
{
HRESULT hr;
DISPPARAMS dispparamsNoArgs = {NULL, NULL, 0, 0};
DISPID dispidFunction;
VARIANT var;

// Get dispatch id for the GetCurrentEffect function
hr =
m_pSkinFunctions->GetDispID(CComBSTR(CStringW("NextPreset").GetString()), 0,
&dispidFunction);
if (FAILED(hr))
return hr;

hr = m_pSkinFunctions->InvokeEx(dispidFunction, LOCALE_USER_DEFAULT,
DISPATCH_METHOD, &dispparamsNoArgs,
&var, NULL, NULL);
return hr;
}


That's it, if you got this far, all that you should now have to do is call
DispatchNextPreset whenever you want to change the visualization.

"TMS" wrote:

Greetings.

Are there interfaces that would enable me to list the available
visualizations and select which one is used from a C++ program? I'm accessing
media player as an embedded control in a dialog using Visual C++ 6.0.

The thread "Future WMP object model directions?" included the following from
godofcpu:

"Since the release of WMP 10, I am very happy with the completeness of the
SDK. There is nothing that I can think of that I can't find someway to do
with the SDK, although some require some hacks and more work then I would
like, i.e. controlling visualizations." (BTW: godofcpu, thanks again for
the info on accessing album art. The code snippet was helpful, too.)

Any info appreciated,

Regards,
--- TMS


Back to top
godofcpu
Guest





Posted: Wed Oct 20, 2004 6:21 pm    Post subject: RE: Controlling Visualizations from C++? Reply with quote

Yeah, I would've loved to see this functionality in the C++ sdk and given
that I was able to "beat" wmp into doing what I wanted, it doesn't seem like
there any real technical reason for leaving it out.

Although, since you must show the skin to show visualziations, I can kinda
see a case for microsoft not percieving a need for this functionality since
you can just add your own skin controls for it, but it still leaves out the
possibilty of progamatic control or really custom UIs and a bunch of other
atypical uses.

"TMS" wrote:

Quote:
Thanks very much. 'Looks like I've got some homework to do :-)

I had wondered about something vaguely along the lines of your approach when
I saw that you could apparently get the information from the EFFECTS
interface for a skin. I was thinking about whether I could get the JScript to
pass the data via some ActiveX control that was hooked into my C++ program,
but that's as far as I got with that. You've saved me a lot of
experimentation that probably would have ended in frustration!

...It's a bit unfortunate that skins can access these settings but that
they're not available directly as interfaces from the player control, isn't
it?

--- TMS
Back to top
TMS
Guest





Posted: Thu Oct 21, 2004 12:07 am    Post subject: RE: Controlling Visualizations from C++? Reply with quote

Gee, implementing programatic control with a custom UI is all I wanted to do
:-) Maybe that's not so atypical after all...!

I'm displaying the control in a window frame in a dialog box, ala the "WMPL"
example. (Except that I've set the uimode to 'none' so all I get is the
window for the visualizations and no controls.) Works great and doesn't
require me to do anything with skins, except of course, unless I want to
change the animation apparently...

Still, I'm glad that at least there's some route to get to this info at all,
albeit a bit 'hacky'.

Thanks again -

Regards,
--- TMS



"godofcpu" wrote:

Quote:
Yeah, I would've loved to see this functionality in the C++ sdk and given
that I was able to "beat" wmp into doing what I wanted, it doesn't seem like
there any real technical reason for leaving it out.

Although, since you must show the skin to show visualziations, I can kinda
see a case for microsoft not percieving a need for this functionality since
you can just add your own skin controls for it, but it still leaves out the
possibilty of progamatic control or really custom UIs and a bunch of other
atypical uses.

"TMS" wrote:

Thanks very much. 'Looks like I've got some homework to do :-)

I had wondered about something vaguely along the lines of your approach when
I saw that you could apparently get the information from the EFFECTS
interface for a skin. I was thinking about whether I could get the JScript to
pass the data via some ActiveX control that was hooked into my C++ program,
but that's as far as I got with that. You've saved me a lot of
experimentation that probably would have ended in frustration!

...It's a bit unfortunate that skins can access these settings but that
they're not available directly as interfaces from the player control, isn't
it?

--- TMS

Back to top
garyishero
Guest





Posted: Thu Oct 21, 2004 6:56 am    Post subject: RE: Controlling Visualizations from C++? Reply with quote

"TMS" wrote:

Quote:
Gee, implementing programatic control with a custom UI is all I wanted to do
:-) Maybe that's not so atypical after all...!

I'm displaying the control in a window frame in a dialog box, ala the "WMPL"
example. (Except that I've set the uimode to 'none' so all I get is the
window for the visualizations and no controls.) Works great and doesn't
require me to do anything with skins, except of course, unless I want to
change the animation apparently...

Still, I'm glad that at least there's some route to get to this info at all,
albeit a bit 'hacky'.

Thanks again -

Regards,
--- TMS



"godofcpu" wrote:

Yeah, I would've loved to see this functionality in the C++ sdk and given
that I was able to "beat" wmp into doing what I wanted, it doesn't seem like
there any real technical reason for leaving it out.

Although, since you must show the skin to show visualziations, I can kinda
see a case for microsoft not percieving a need for this functionality since
you can just add your own skin controls for it, but it still leaves out the
possibilty of progamatic control or really custom UIs and a bunch of other
atypical uses.

"TMS" wrote:

Thanks very much. 'Looks like I've got some homework to do :-)

I had wondered about something vaguely along the lines of your approach when
I saw that you could apparently get the information from the EFFECTS
interface for a skin. I was thinking about whether I could get the JScript to
pass the data via some ActiveX control that was hooked into my C++ program,
but that's as far as I got with that. You've saved me a lot of
experimentation that probably would have ended in frustration!

...It's a bit unfortunate that skins can access these settings but that
they're not available directly as interfaces from the player control, isn't
it?

--- TMS

Back to top
 
Post new topic   Reply to topic    WMPTalk.com Forum Index -> SDK All times are GMT
Page 1 of 1

 
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum



Microsoft Office Forum New Topics
Powered by phpBB