базовое воспроизведение с программно созданным проигрывателем Windows Media

Я пытался "просто быстро интегрировать" проигрыватель Windows Media через COM для воспроизведения отдельных файлов из локальной файловой системы или http-источников, но из-за скудной документации и онлайн-ресурсов его использование без встраивания в какой-то контейнер Ole, я не мог заставить этот якобы тривиальный вариант использования работать.

Инициализация и т. д. работает нормально, но на самом деле воспроизведение какого-либо файла всегда терпит неудачу.

Пример кода, начиная с инициализации (обработка ошибок удалена, в основном переведено из пример C# в MSDN, выполненный в основном потоке):

CComPtr<IWMPPlayer> player;
player.CoCreateInstance(__uuidof(WindowsMediaPlayer), 0, CLSCTX_INPROC_SERVER);
CComQIPtr<IWMPCore3> core(player);
CComPtr<IWMPControls> controls;
core->get_controls(&controls);
CComPtr<IWMPPlaylist> playlist;
core->get_currentPlaylist(&playlist);
CComBSTR path("c:\\bar.mp3"); // alternatively http://foo/bar.mp3

Первый подход к воспроизведению чего-либо дает "команда недоступна":

core->put_url(path);
// ... waiting after that for WMP to load doesn't make a difference
controls->play(); // returns 0x000D1105 - NS_S_WMPCORE_COMMAND_NOT_AVAILABLE

Второй подход производит только S_OKs, но на самом деле ничего не воспроизводится:

CComPtr<IWMPMedia> media;
core->newMedia(path, &media);
playlist->appendItem(media);
controls->playItem(media); // returns S_OK, but doesn't play

Еще я заметил, что core->get_playState() всегда возвращает wmposMediaOpening, сколько бы я ни ждал.

Я наткнулся на один поток, который предполагает, что многопоточность может не работать должным образом с WMP, и этот код работает в многопоточном апартаменте. Может быть проблема в этом?
Если нет, то что еще может помешать WMP воспроизвести файлы?

Примечательная предыстория:
Экземпляр WMP создается в DLL с браузером в качестве хост-процесса.

Обновление:
Попытка использования простого DirectShow, который должен использовать WMP, выявила более конкретную проблему — см. вопрос для этого.


person Georg Fritzsche    schedule 20.12.2009    source источник


Ответы (2)


WMP поддерживает два метода автоматизации: встроенный ActiveX или COM-сервер. Для встроенного использования вы добавляете ActiveX через тег объекта (выполняете некоторые сценарии через IHTMLWindow2 из вашего BHO/Band) или скрытую форму и автоматизируете оттуда. См. раздел Использование элемента управления проигрывателя Windows Media на веб-странице и Размещение элемента управления проигрывателя Windows Media в приложении Windows для примеров кодов.

Для использования COM-сервера просто создайте проигрыватель как COM-сервер и автоматизируйте его. Вы можете либо сделать его механизмом воспроизведения без пользовательского интерфейса или удалить его, чтобы у вас был полноценный пользовательский интерфейс< /а>.

Проигрыватель Windows Media воспроизводится асинхронно, например, он может вызывать IMediaControl::Run и немедленно возвращаться при вызове put_URL (другой немедленный вызов воспроизведения завершится ошибкой, поскольку он уже воспроизводится). Если вам не нужно автоматическое воспроизведение, я думаю, вам нужен IWMPSettings::put_autoStart.

WMP предполагает, что находится в основном потоке. Если вы находитесь в рабочем потоке или потоке MTA, я предлагаю вам включить другой процесс, чтобы автоматизировать его, или удалить его как внепроцессный сервер.

person Sheng Jiang 蒋晟    schedule 22.12.2009
comment
Наконец-то отзыв, спасибо. Я пытаюсь запустить его как in-proc-COM-сервер без пользовательского интерфейса. WMP создается в основном потоке, и там же возникает функция put_URL(). Однако даже при длительном ожидании запрос открытого состояния всегда приводит к wmposMediaOpening, и он никогда не начинает играть (независимо от того, вызываю ли я play() или нет). Любые идеи по этому поводу? - person Georg Fritzsche; 23.12.2009
comment
Я предлагаю вам удаленный WMP и автоматизировать его таким же образом, чтобы увидеть, есть ли у вас какие-либо окна сообщений. - person Sheng Jiang 蒋晟; 23.12.2009

После дальнейшего расследования выяснилось, что на самом деле это было вызвано обходным решением VS2005 для VS2008 AtlSetPerUserRegistration(), которое всегда было активным, но должно было только для регистрации/отмены регистрации содержащихся COM-серверов.

Обходной путь заменяет HKEY_LOCAL_MACHINE на HKEY_CURRENT_USER, что, очевидно, приводит к сбою некоторых компонентов, если они создаются в процессе.

person Georg Fritzsche    schedule 27.12.2009