none
Windows Media Player Remoting in C#

    Question

  • Hey,

    I'm trying to setup up remoting for Windows Media Player in C#.  Remoting in the sense of controling a separate WMP instance, not networking.  I have no problems using the WMP control and playing media within the C# app but that creates a separate instance of WMP which isn't really what I want.  For C++, there's a relevant sample (\Multimedia\WMP_11\cpp\RemoteSkin in the SDK) to follow but I'm not sure how all of the COM calls are supposed to be translated into C#.

     

    I think the problem is that I need to create a class that implements IServiceProvider and IWMPRemoteMediaServices and assign that to the Site parameter on the AxHost, since that seems to be approximately what the C++ version does.  It's the Site part that I'm not really sure about but I could also be completely wrong.  I've got pretty good knowledge of both C++ and C# but I've only had a bit of experience with COM and interop stuff.  The relevant code (I think) from the sample (with error checking removed) is below.

     

    Thanks,

    tj963

     

    ---------------

     

    CComPtr<IWMPPlayer4> m_spPlayer;

     

    CComPtr<IObjectWithSite> spHostObject;

    CComPtr<IAxWinHostWindow> spHost;

    CComObject<CRemoteHost> *pRemoteHost = NULL;

     

    // Create an ActiveX control container

    AtlAxWinInit();

    CAxWindow* m_pView = new CAxWindow();

     

    ::GetWindowRect(GetDlgItem(IDC_RANGE), &rcClient);

    ScreenToClient(&rcClient);

    m_pView->Create(m_hWnd, rcClient, NULL, WS_CHILD | WS_VISIBLE | WS_CLIPCHILDREN, WS_EX_CLIENTEDGE);

     

    hr = m_pView->QueryHost(IID_IObjectWithSite, (void **)&spHostObject);

     

    // Create remote host which implements IServiceProvider and IWMPRemoteMediaServices

    hr = CComObject<CRemoteHost>::CreateInstance(&pRemoteHost);

    pRemoteHost->AddRef();

     

    // Set site to the remote host

    hr = spHostObject->SetSite((IWMPRemoteMediaServices *)pRemoteHost);

    hr = m_pView->QueryHost(&spHost);

     

    // Create WMP Control here

    hr = spHost->CreateControl(CComBSTR(L"{6BF52A52-394A-11d3-B153-00C04F79FAA6}"), m_pView->m_hWnd, NULL);

    hr = m_pView->QueryControl(&m_spPlayer);

    Saturday, March 08, 2008 12:15 AM

Answers

  • I heard of solution that is writing a really thin C++ COM object wrapper around the remote MP object that implemented all the interfaces. For more details, please visit this article. Also, you can contact the author to get more information about the solution.
    Monday, March 10, 2008 8:54 AM

All replies

  • I heard of solution that is writing a really thin C++ COM object wrapper around the remote MP object that implemented all the interfaces. For more details, please visit this article. Also, you can contact the author to get more information about the solution.
    Monday, March 10, 2008 8:54 AM
  • Yes, I heard of this solution too, and have been trying to get hold of the code for about two weeks now!
    See Eric's update at the bottom, or direct link here.

    MS have, in their wisdom, taken down gotdotnet, so the code has disappeared Sad


    I have got in touch with Eric and he no longer has a copy of the code.

    I'm also trying to get a remoted WMP instance working in C#, and have been looking at that SDK code above aswell.
    Why why why do they still not support .NET properly - they've been promising it for years now!

    Am beginning to run out of options, since my COM C++ experience is so rusty.
    I'm determined not give up though, but would love to see this old gotdotnet example to see the code of someone who is more confident in the murky world of C++ COM.

    I'll try and keep this updated with any progress...

    Cheers,
    Westy

    Wednesday, March 19, 2008 4:31 PM
  • Oh wow, must be my lucky day!

    Have found Jonathan Dibble's code!

    From here (which I looked at the other week) - look for the WmpRemote.zip link (which 404's for some reason).
    Copy and paste the location and go to the directory of the zip file, and voila, there it is - this is the bit I didn't try the other week...

    Hope this helps.
    I'm going to have a look at it now Smile

    Cheers,
    Westy
    Wednesday, March 19, 2008 4:50 PM
  • Ok, on first inspection... it works (so long as WMP is running already).

    Will look into that, although might not be a huge issue for me since am using a watcher that looks for WMP starting and stopping.


    Looks very professional though, with generated documentation etc.
    Diving into the code now Smile

    Westy

    Edit: Heh, would have taken me ages to start playing around with all those COM attributes etc.
    Looks like this guy knows his onions...
    Wednesday, March 19, 2008 5:00 PM
  • Thanks a lot for finding wmpremote.zip -- it really looks like it brings the promise of wmp-remote-controlled-thru-C#  closer to reality.  I'm looking to be able to call the WMP API's functions directly though, without using their UI -- which the code doesn't really go into.

    For instance, I want to be able to set an onclick event to fire a player.fastForward() action.

    Do you have any idea or suggestions on how to do this?  The author mentions this in passing, but unfortunately all COM talk is greek to me.

    Thanks!

    J
    Friday, March 28, 2008 12:02 PM
  • Yeah, he was a little vague, but it makes sense if you try out his directions; what you need to do is modify AttachInterfaces to expose the WMP objects you need.

    For events you need to dig a bit dipper, and make the remoted control look like the real OCX.
    Shouldn't need that for simple play controls though, just expose the IWMPlayer4 object (or the controls property of it).

    I did it like this:
            protected override void AttachInterfaces()
            {
                try
                {   
                    //Get the IOleObject for Windows Media Player.
                    IOleObject oleObject = this.GetOcx() as IOleObject;
                   
                    if (oleObject != null)
                    {
                        //Set the Client Site for the WMP control.
                        oleObject.SetClientSite(this as IOleClientSite);

                        // Try and get the OCX as a WMP player
                        _wmp = this.GetOcx() as IWMPPlayer4;

                        if (_wmp == null)
                        {
                            throw new Exception(string.Format("OCX is not an IWMPPlayer4! GetType returns '{0}'",
                                                              this.GetOcx().GetType()));
                        }
                    }
                    else
                    {
                        throw new Exception("Failed to get WMP OCX as an IOleObject?!");
                    }

                    return;
                }
                catch (System.Exception ex )
                {
                    System.Diagnostics.Debug.WriteLine(ex.ToString());
                }
            }


    Obviously you need to add a reference to the COM WMP.dll, and a member variable to the control, but it's all pretty trivial and works.

    I use the controls interface to retrieve the currently playing track for instance Smile

    Good luck,
    Westy
    Tuesday, April 01, 2008 4:23 PM
  • How has this worked out for you?  I am writing a monitor in C# that is to watch the current Windows Media Player and gather information about the media that is playing or has played, simple information like Title, Artist, Genre, Album Title and Duration.  I do not need to control Windows Media Player.  Can I use this Remoting code to create Events that will be able to gather the information that I need?  Do you ahve any advise for me in trying to do this.  My C# is pretty good but my C++ is not so good and my understanding of COM and ActiveX is sketchy at best.

    Also, what do you use for the watcher to know if the Windows Media Player is active?

    Regards,
    Dick
    Saturday, April 12, 2008 12:13 AM
  • Hi Dick !

    I am a french student and I would to do similar things for a project...

    For examples I would like to get path of current playlist and access informations concerning the tracks into this playlist...

    Did you find solution to do that in c# ?

    thank you
    chti_juanito
    Wednesday, July 30, 2008 10:25 AM
  • chti_juanito,

    Yes, the remoted solution here works well for me.  If you need details let me know.
    Dick
    Tuesday, August 05, 2008 7:18 AM
  • thanks for the great expertise in this post!

    i was wondering whether you could advise how to exactly get access to the _WMPOCXEvents as well?

    i.e. unpack Jonathan Dibble's comment: "Additionally, you can run AxImp WMP.DLL /source to generate a C# wrapper for the WMP ActiveX Control.  If you do, merge the generated AttachInterfaces method with the one from <see cref="RemotedWindowsMediaPlayer.AttachInterfaces"/>.  This will give you a much fuller control with all properties and events automatically generated for you."

     

    I understand how to use AxImp tool on WMP.dll i think, but not sure what the second sentence means in practical terms? If there's any example code like Westy Work provided here before, that would be immensely helpful!

    Wednesday, April 27, 2011 11:31 AM