0

I am trying to play a movie using Windows Media Player, later on will add some other functionality. Following is the code I have written:

const CLSID CLSID_WindowsMediaPlayer = {0x6BF52A52, 0x394A, 0x11d3, {0xB1, 0x53, 0x00, 0xC0, 0x4F, 0x79, 0xFA, 0xA6 } };
HRESULT         hr;
IWMPPlayer      *pMediaPlayer = NULL;

hr = CoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
if(FAILED(hr))
{
    std::cout << "ERR -- Could not Initialize COM engine for you" << std::endl;
    return 0;
}

hr = CoCreateInstance(CLSID_WindowsMediaPlayer, NULL, CLSCTX_INPROC_SERVER, IID_IDispatch, (void**)&pMediaPlayer);
if(FAILED(hr))
{
    std::cout << "ERR - Could not get WMPPlayer Interface Pointer" << std::endl;
    return 0;
}
std::cout << "Got MediaPlayer Pointer" << std::endl;

IWMPSettings    *pMediaPlayerSettings = NULL;
hr = pMediaPlayer->get_settings(&pMediaPlayerSettings);
if(FAILED(hr))
{
    std::cout << "ERR - Could not get WMPSettings Interface Pointer" << std::endl;
    ReleaseInterfaces((IUnknown**)&pMediaPlayer);
    return 0;
}
std::cout << "Got MediaPlayerSettings Pointer" << std::endl;

hr = pMediaPlayerSettings->put_autoStart(VARIANT_TRUE);
if(FAILED(hr))
{
    std::cout << "ERR - Could not put auto_start to true" << std::endl;
    ReleaseInterfaces((IUnknown**)&pMediaPlayerSettings);
    ReleaseInterfaces((IUnknown**)&pMediaPlayer);
    return 0;
}
std::cout << "Have put it to autostart" << std::endl;

hr = pMediaPlayerSettings->put_volume(50);
if(FAILED(hr))
{
    std::cout << "ERR - Could not put volume" << std::endl;
    ReleaseInterfaces((IUnknown**)&pMediaPlayerSettings);
    ReleaseInterfaces((IUnknown**)&pMediaPlayer);
    return 0;
}
std::cout << "Have put volume to listen-able" << std::endl;

hr = pMediaPlayer->put_URL(L"C:\\background.mp3");
if(FAILED(hr))
{
    std::cout << "ERR - Could not set URL" << std::endl;
    ReleaseInterfaces((IUnknown**)&pMediaPlayerSettings);
    ReleaseInterfaces((IUnknown**)&pMediaPlayer);
    return 0;
}
std::cout << "Have set URL" << std::endl;

So far all is good. But file is never played. Upon further investigation, I found out that WMPPlayState never becomes wmppsPlaying, So i tested if file is opened using WMPOpenState but here I always get wmposOpeningUnknownURL. I first thought this might be because I have put file in C:, which needs admin rights, but using other location also yields same result. I have checked if the URL i set using put_URL is actually put, and yes, get_URL gives out my set url. I have also tested with different files and formats.

Moreover, Windows Media Player is NOT opened!

2 Answers2

3
  hr = CoInitializeEx(NULL, COINIT_APARTMENTTHREADED);

That's a pretty common selection. We can't see the rest of your code, but the shoe fits. It requires you to do the other thing that's a hard requirement for an STA thread. You must pump a message loop. Failure to do so causes various problems, deadlock is not uncommon. And yes, the state won't change, the signaling between worker threads inside WMP and your apartment thread is borken because you don't pump.

You get a message loop in a GUI app, pick the Win32 Project project template for example, not the Win32 Console Application template. Or add the code, boilerplate is:

MSG msg;
while(GetMessage(&msg, NULL, 0, 0) > 0)
{
    TranslateMessage(&msg);
    DispatchMessage(&msg);
}

And do beware that you don't get a window, you asked for CLSCTX_INPROC_SERVER. In other words, WMP runs in-process, inside your program. Getting a window requires using ActiveX hosting, not something you'd typically want to tackle without significant help from a class library like MFC or Winforms. Maybe what you really meant to do is run it out-of-process so it can display its own window?

Hans Passant
  • 922,412
  • 146
  • 1,693
  • 2,536
  • Thanks you for the answer sir. `CLSCTX_INPROC_SERVER` was there for trial-and-error. If i use `CLSCTX_LOCAL_SERVER`, `CoCreateInstace` fails with `Class Not Registered`. May be this makes it for another question, but isn't automation possible without `ActiveX`? I thought it would be more or less similar to Office Automation. Any further pointers? Because we are going to need a window. –  Aug 16 '14 at 18:02
  • Further research showed this may be because of COM+ server registration by MediaPlayer, So what are the odds that MediaPlayer Automation is possible from raw COM? I kinda found a way that by removing COM+ entry from component service panel might solve the problem but thats not a good way because it means Media Player on client PC will not be able to use COM+, which I vaguely know is used for networked-COM –  Aug 16 '14 at 18:22
2

You can get directly the IWMPPlayer4 interface which is easier to use, like this:

IWMPPlayer4 *pMediaPlayer;

CoCreateInstance(CLSID_WindowsMediaPlayer, NULL, CLSCTX_ALL, IID_IWMPPlayer4, (void**)&pMediaPlayer);
pMediaPlayer->openPlayer(_bstr_t(L"C:\\background.mp3"));
Simon Mourier
  • 132,049
  • 21
  • 248
  • 298