wmp: Implement playback via quartz.
Signed-off-by: Anton Romanov <theli.ua@gmail.com> Signed-off-by: Jacek Caban <jacek@codeweavers.com> Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
parent
6545037efb
commit
f762097f50
|
@ -19,6 +19,7 @@
|
||||||
#include "wmp_private.h"
|
#include "wmp_private.h"
|
||||||
|
|
||||||
#include "wine/debug.h"
|
#include "wine/debug.h"
|
||||||
|
#include <nserror.h>
|
||||||
|
|
||||||
WINE_DEFAULT_DEBUG_CHANNEL(wmp);
|
WINE_DEFAULT_DEBUG_CHANNEL(wmp);
|
||||||
|
|
||||||
|
@ -119,12 +120,20 @@ static HRESULT WINAPI WMPPlayer4_put_URL(IWMPPlayer4 *iface, BSTR url)
|
||||||
{
|
{
|
||||||
WindowsMediaPlayer *This = impl_from_IWMPPlayer4(iface);
|
WindowsMediaPlayer *This = impl_from_IWMPPlayer4(iface);
|
||||||
IWMPMedia *media;
|
IWMPMedia *media;
|
||||||
|
HRESULT hres;
|
||||||
TRACE("(%p)->(%s)\n", This, debugstr_w(url));
|
TRACE("(%p)->(%s)\n", This, debugstr_w(url));
|
||||||
if(url == NULL) {
|
if(url == NULL) {
|
||||||
return E_POINTER;
|
return E_POINTER;
|
||||||
}
|
}
|
||||||
media = create_media_from_url(url);
|
hres = create_media_from_url(url, &media);
|
||||||
return IWMPPlayer4_put_currentMedia(iface, media);
|
if (SUCCEEDED(hres)) {
|
||||||
|
hres = IWMPPlayer4_put_currentMedia(iface, media);
|
||||||
|
IWMPMedia_Release(media); /* put will addref */
|
||||||
|
}
|
||||||
|
if (SUCCEEDED(hres) && This->auto_start) {
|
||||||
|
hres = IWMPControls_play(&This->IWMPControls_iface);
|
||||||
|
}
|
||||||
|
return hres;
|
||||||
}
|
}
|
||||||
|
|
||||||
static HRESULT WINAPI WMPPlayer4_get_openState(IWMPPlayer4 *iface, WMPOpenState *pwmpos)
|
static HRESULT WINAPI WMPPlayer4_get_openState(IWMPPlayer4 *iface, WMPOpenState *pwmpos)
|
||||||
|
@ -1357,16 +1366,60 @@ static HRESULT WINAPI WMPControls_get_isAvailable(IWMPControls *iface, BSTR bstr
|
||||||
|
|
||||||
static HRESULT WINAPI WMPControls_play(IWMPControls *iface)
|
static HRESULT WINAPI WMPControls_play(IWMPControls *iface)
|
||||||
{
|
{
|
||||||
|
HRESULT hres = S_OK;
|
||||||
WindowsMediaPlayer *This = impl_from_IWMPControls(iface);
|
WindowsMediaPlayer *This = impl_from_IWMPControls(iface);
|
||||||
FIXME("(%p)\n", This);
|
WMPMedia *media;
|
||||||
return E_NOTIMPL;
|
|
||||||
|
TRACE("(%p)\n", This);
|
||||||
|
|
||||||
|
if (!This->wmpmedia) {
|
||||||
|
return NS_S_WMPCORE_COMMAND_NOT_AVAILABLE;
|
||||||
|
}
|
||||||
|
|
||||||
|
media = unsafe_impl_from_IWMPMedia(This->wmpmedia);
|
||||||
|
if (!media) {
|
||||||
|
FIXME("No support for non-builtin IWMPMedia implementations\n");
|
||||||
|
return E_INVALIDARG;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!This->filter_graph) {
|
||||||
|
hres = CoCreateInstance(&CLSID_FilterGraph,
|
||||||
|
NULL,
|
||||||
|
CLSCTX_INPROC_SERVER,
|
||||||
|
&IID_IGraphBuilder,
|
||||||
|
(void **)&This->filter_graph);
|
||||||
|
if (SUCCEEDED(hres))
|
||||||
|
hres = IGraphBuilder_RenderFile(This->filter_graph, media->url, NULL);
|
||||||
|
if (SUCCEEDED(hres))
|
||||||
|
hres = IGraphBuilder_QueryInterface(This->filter_graph, &IID_IMediaControl,
|
||||||
|
(void**)&This->media_control);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (SUCCEEDED(hres))
|
||||||
|
hres = IMediaControl_Run(This->media_control);
|
||||||
|
|
||||||
|
if (hres == S_FALSE) {
|
||||||
|
hres = S_OK; /* S_FALSE will mean that graph is transitioning and that is fine */
|
||||||
|
}
|
||||||
|
return hres;
|
||||||
}
|
}
|
||||||
|
|
||||||
static HRESULT WINAPI WMPControls_stop(IWMPControls *iface)
|
static HRESULT WINAPI WMPControls_stop(IWMPControls *iface)
|
||||||
{
|
{
|
||||||
|
HRESULT hres = S_OK;
|
||||||
WindowsMediaPlayer *This = impl_from_IWMPControls(iface);
|
WindowsMediaPlayer *This = impl_from_IWMPControls(iface);
|
||||||
FIXME("(%p)\n", This);
|
TRACE("(%p)\n", This);
|
||||||
return E_NOTIMPL;
|
if (!This->filter_graph) {
|
||||||
|
return NS_S_WMPCORE_COMMAND_NOT_AVAILABLE;
|
||||||
|
}
|
||||||
|
if (This->media_control) {
|
||||||
|
hres = IMediaControl_Stop(This->media_control);
|
||||||
|
IMediaControl_Release(This->media_control);
|
||||||
|
}
|
||||||
|
IGraphBuilder_Release(This->filter_graph);
|
||||||
|
This->filter_graph = NULL;
|
||||||
|
This->media_control = NULL;
|
||||||
|
return hres;
|
||||||
}
|
}
|
||||||
|
|
||||||
static HRESULT WINAPI WMPControls_pause(IWMPControls *iface)
|
static HRESULT WINAPI WMPControls_pause(IWMPControls *iface)
|
||||||
|
@ -1741,16 +1794,36 @@ void init_player(WindowsMediaPlayer *wmp)
|
||||||
|
|
||||||
void destroy_player(WindowsMediaPlayer *wmp)
|
void destroy_player(WindowsMediaPlayer *wmp)
|
||||||
{
|
{
|
||||||
|
IWMPControls_stop(&wmp->IWMPControls_iface);
|
||||||
if(wmp->wmpmedia)
|
if(wmp->wmpmedia)
|
||||||
IWMPMedia_Release(wmp->wmpmedia);
|
IWMPMedia_Release(wmp->wmpmedia);
|
||||||
}
|
}
|
||||||
|
|
||||||
IWMPMedia* create_media_from_url(BSTR url){
|
WMPMedia *unsafe_impl_from_IWMPMedia(IWMPMedia *iface)
|
||||||
|
{
|
||||||
|
if (iface->lpVtbl == &WMPMediaVtbl) {
|
||||||
|
return CONTAINING_RECORD(iface, WMPMedia, IWMPMedia_iface);
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
HRESULT create_media_from_url(BSTR url, IWMPMedia **ppMedia)
|
||||||
|
{
|
||||||
WMPMedia *media = heap_alloc_zero(sizeof(WMPMedia));
|
WMPMedia *media = heap_alloc_zero(sizeof(WMPMedia));
|
||||||
|
|
||||||
|
if (!media) {
|
||||||
|
return E_OUTOFMEMORY;
|
||||||
|
}
|
||||||
|
|
||||||
media->IWMPMedia_iface.lpVtbl = &WMPMediaVtbl;
|
media->IWMPMedia_iface.lpVtbl = &WMPMediaVtbl;
|
||||||
media->url = heap_strdupW(url);
|
media->url = heap_strdupW(url);
|
||||||
media->ref = 1;
|
media->ref = 1;
|
||||||
|
|
||||||
return &media->IWMPMedia_iface;
|
if (media->url) {
|
||||||
|
*ppMedia = &media->IWMPMedia_iface;
|
||||||
|
|
||||||
|
return S_OK;
|
||||||
|
}
|
||||||
|
IWMPMedia_Release(&media->IWMPMedia_iface);
|
||||||
|
return E_OUTOFMEMORY;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,9 @@
|
||||||
TESTDLL = wmp.dll
|
TESTDLL = wmp.dll
|
||||||
IMPORTS = ole32 oleaut32 user32 gdi32
|
IMPORTS = ole32 oleaut32 user32 gdi32
|
||||||
|
|
||||||
C_SRCS = oleobj.c
|
C_SRCS = \
|
||||||
|
media.c \
|
||||||
|
oleobj.c
|
||||||
|
|
||||||
RC_SRCS = \
|
RC_SRCS = \
|
||||||
rsrc.rc
|
rsrc.rc
|
||||||
|
|
Binary file not shown.
|
@ -0,0 +1,120 @@
|
||||||
|
/*
|
||||||
|
* This library is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU Lesser General Public
|
||||||
|
* License as published by the Free Software Foundation; either
|
||||||
|
* version 2.1 of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This library is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public
|
||||||
|
* License along with this library; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define WIN32_LEAN_AND_MEAN
|
||||||
|
#define COBJMACROS
|
||||||
|
#include <wmp.h>
|
||||||
|
#include <olectl.h>
|
||||||
|
#include <nserror.h>
|
||||||
|
|
||||||
|
#include "wine/test.h"
|
||||||
|
|
||||||
|
static const WCHAR mp3file[] = {'t','e','s','t','.','m','p','3',0};
|
||||||
|
static inline WCHAR *load_resource(const WCHAR *name)
|
||||||
|
{
|
||||||
|
static WCHAR pathW[MAX_PATH];
|
||||||
|
DWORD written;
|
||||||
|
HANDLE file;
|
||||||
|
HRSRC res;
|
||||||
|
void *ptr;
|
||||||
|
|
||||||
|
GetTempPathW(sizeof(pathW)/sizeof(WCHAR), pathW);
|
||||||
|
lstrcatW(pathW, name);
|
||||||
|
|
||||||
|
file = CreateFileW(pathW, GENERIC_READ|GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, 0);
|
||||||
|
ok(file != INVALID_HANDLE_VALUE, "file creation failed, at %s, error %d\n", wine_dbgstr_w(pathW),
|
||||||
|
GetLastError());
|
||||||
|
|
||||||
|
res = FindResourceW(NULL, name, (LPCWSTR)RT_RCDATA);
|
||||||
|
ok( res != 0, "couldn't find resource\n" );
|
||||||
|
ptr = LockResource( LoadResource( GetModuleHandleA(NULL), res ));
|
||||||
|
WriteFile( file, ptr, SizeofResource( GetModuleHandleA(NULL), res ), &written, NULL );
|
||||||
|
ok( written == SizeofResource( GetModuleHandleA(NULL), res ), "couldn't write resource\n" );
|
||||||
|
CloseHandle( file );
|
||||||
|
|
||||||
|
return pathW;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void test_wmp(void)
|
||||||
|
{
|
||||||
|
IWMPPlayer4 *player4;
|
||||||
|
IWMPControls *controls;
|
||||||
|
HRESULT hres;
|
||||||
|
BSTR filename;
|
||||||
|
|
||||||
|
IOleObject *oleobj;
|
||||||
|
IWMPSettings *settings;
|
||||||
|
|
||||||
|
hres = CoCreateInstance(&CLSID_WindowsMediaPlayer, NULL, CLSCTX_INPROC_SERVER, &IID_IOleObject, (void**)&oleobj);
|
||||||
|
if(hres == REGDB_E_CLASSNOTREG) {
|
||||||
|
win_skip("CLSID_WindowsMediaPlayer not registered\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
ok(hres == S_OK, "Could not create CLSID_WindowsMediaPlayer instance: %08x\n", hres);
|
||||||
|
|
||||||
|
hres = IOleObject_QueryInterface(oleobj, &IID_IWMPPlayer4, (void**)&player4);
|
||||||
|
ok(hres == S_OK, "Could not get IWMPPlayer4 iface: %08x\n", hres);
|
||||||
|
|
||||||
|
settings = NULL;
|
||||||
|
hres = IWMPPlayer4_get_settings(player4, &settings);
|
||||||
|
ok(hres == S_OK, "get_settings failed: %08x\n", hres);
|
||||||
|
ok(settings != NULL, "settings = NULL\n");
|
||||||
|
|
||||||
|
hres = IWMPSettings_put_autoStart(settings, VARIANT_FALSE);
|
||||||
|
ok(hres == S_OK, "Could not put autoStart in IWMPSettings: %08x\n", hres);
|
||||||
|
IWMPSettings_Release(settings);
|
||||||
|
|
||||||
|
controls = NULL;
|
||||||
|
hres = IWMPPlayer4_get_controls(player4, &controls);
|
||||||
|
ok(hres == S_OK, "get_controls failed: %08x\n", hres);
|
||||||
|
ok(controls != NULL, "controls = NULL\n");
|
||||||
|
|
||||||
|
hres = IWMPControls_play(controls);
|
||||||
|
ok(hres == NS_S_WMPCORE_COMMAND_NOT_AVAILABLE, "IWMPControls_play is available: %08x\n", hres);
|
||||||
|
|
||||||
|
filename = SysAllocString(load_resource(mp3file));
|
||||||
|
|
||||||
|
hres = IWMPPlayer4_put_URL(player4, filename);
|
||||||
|
ok(hres == S_OK, "IWMPPlayer4_put_URL failed: %08x\n", hres);
|
||||||
|
|
||||||
|
hres = IWMPControls_play(controls);
|
||||||
|
ok(hres == S_OK, "IWMPControls_play failed: %08x\n", hres);
|
||||||
|
|
||||||
|
hres = IWMPControls_stop(controls);
|
||||||
|
ok(hres == S_OK, "IWMPControls_stop failed: %08x\n", hres);
|
||||||
|
|
||||||
|
/* Already Stopped */
|
||||||
|
hres = IWMPControls_stop(controls);
|
||||||
|
ok(hres == NS_S_WMPCORE_COMMAND_NOT_AVAILABLE, "IWMPControls_stop is available: %08x\n", hres);
|
||||||
|
|
||||||
|
hres = IWMPControls_play(controls);
|
||||||
|
ok(hres == S_OK, "IWMPControls_play failed: %08x\n", hres);
|
||||||
|
|
||||||
|
IWMPControls_Release(controls);
|
||||||
|
IWMPPlayer4_Release(player4);
|
||||||
|
IOleObject_Release(oleobj);
|
||||||
|
DeleteFileW(filename);
|
||||||
|
SysFreeString(filename);
|
||||||
|
}
|
||||||
|
|
||||||
|
START_TEST(media)
|
||||||
|
{
|
||||||
|
CoInitialize(NULL);
|
||||||
|
|
||||||
|
test_wmp();
|
||||||
|
|
||||||
|
CoUninitialize();
|
||||||
|
}
|
|
@ -70,7 +70,7 @@ DEFINE_EXPECT(GetWindowContext);
|
||||||
DEFINE_EXPECT(ShowObject);
|
DEFINE_EXPECT(ShowObject);
|
||||||
DEFINE_EXPECT(OnShowWindow_FALSE);
|
DEFINE_EXPECT(OnShowWindow_FALSE);
|
||||||
|
|
||||||
static const WCHAR mp4file[] = {'a','v','.','m','p','4',0};
|
static const WCHAR mp3file[] = {'t','e','s','t','.','m','p','3',0};
|
||||||
static inline WCHAR *load_resource(const WCHAR *name)
|
static inline WCHAR *load_resource(const WCHAR *name)
|
||||||
{
|
{
|
||||||
static WCHAR pathW[MAX_PATH];
|
static WCHAR pathW[MAX_PATH];
|
||||||
|
@ -942,8 +942,7 @@ static void test_wmp_ifaces(IOleObject *oleobj)
|
||||||
ok(hres == S_FALSE, "get_currentMedia SUCCEEDED\n");
|
ok(hres == S_FALSE, "get_currentMedia SUCCEEDED\n");
|
||||||
ok(media == NULL, "media != NULL\n");
|
ok(media == NULL, "media != NULL\n");
|
||||||
|
|
||||||
filename = SysAllocString(load_resource(mp4file));
|
filename = SysAllocString(load_resource(mp3file));
|
||||||
|
|
||||||
|
|
||||||
SET_EXPECT(GetContainer);
|
SET_EXPECT(GetContainer);
|
||||||
SET_EXPECT(Invoke_USERMODE);
|
SET_EXPECT(Invoke_USERMODE);
|
||||||
|
@ -1039,6 +1038,7 @@ static void test_wmp_ifaces(IOleObject *oleobj)
|
||||||
|
|
||||||
IWMPSettings_Release(settings);
|
IWMPSettings_Release(settings);
|
||||||
IWMPPlayer_Release(player);
|
IWMPPlayer_Release(player);
|
||||||
|
DeleteFileW(filename);
|
||||||
SysFreeString(filename);
|
SysFreeString(filename);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -18,5 +18,6 @@
|
||||||
|
|
||||||
#include "windef.h"
|
#include "windef.h"
|
||||||
|
|
||||||
/* @makedep: av.mp4 */
|
/* ffmpeg -ar 48000 -t 60 -f s16le -acodec pcm_s16le -ac 2 -i /dev/zero -acodec libmp3lame -aq 4 output.mp3 */
|
||||||
av.mp4 RCDATA "av.mp4"
|
/* @makedep: test.mp3 */
|
||||||
|
test.mp3 RCDATA "test.mp3"
|
||||||
|
|
Binary file not shown.
|
@ -22,6 +22,7 @@
|
||||||
#include "wine/heap.h"
|
#include "wine/heap.h"
|
||||||
#include "wine/unicode.h"
|
#include "wine/unicode.h"
|
||||||
#include "ole2.h"
|
#include "ole2.h"
|
||||||
|
#include "dshow.h"
|
||||||
#include "wmp.h"
|
#include "wmp.h"
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
|
@ -70,11 +71,16 @@ struct WindowsMediaPlayer {
|
||||||
ConnectionPoint *wmpocx;
|
ConnectionPoint *wmpocx;
|
||||||
|
|
||||||
IWMPMedia *wmpmedia;
|
IWMPMedia *wmpmedia;
|
||||||
|
|
||||||
|
/* DirectShow stuff */
|
||||||
|
IGraphBuilder* filter_graph;
|
||||||
|
IMediaControl* media_control;
|
||||||
};
|
};
|
||||||
|
|
||||||
void init_player(WindowsMediaPlayer*) DECLSPEC_HIDDEN;
|
void init_player(WindowsMediaPlayer*) DECLSPEC_HIDDEN;
|
||||||
void destroy_player(WindowsMediaPlayer*) DECLSPEC_HIDDEN;
|
void destroy_player(WindowsMediaPlayer*) DECLSPEC_HIDDEN;
|
||||||
IWMPMedia* create_media_from_url(BSTR url);
|
WMPMedia *unsafe_impl_from_IWMPMedia(IWMPMedia *iface) DECLSPEC_HIDDEN;
|
||||||
|
HRESULT create_media_from_url(BSTR url, IWMPMedia **ppMedia) DECLSPEC_HIDDEN;
|
||||||
void ConnectionPointContainer_Init(WindowsMediaPlayer *wmp) DECLSPEC_HIDDEN;
|
void ConnectionPointContainer_Init(WindowsMediaPlayer *wmp) DECLSPEC_HIDDEN;
|
||||||
void ConnectionPointContainer_Destroy(WindowsMediaPlayer *wmp) DECLSPEC_HIDDEN;
|
void ConnectionPointContainer_Destroy(WindowsMediaPlayer *wmp) DECLSPEC_HIDDEN;
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue