Called by Roon.
I have more patches for this, but I split them up for easier review.
-- v3: windows.media.mediacontrol: Implement some ISystemMediaTransportControls properties. windows.media.mediacontrol/tests: Add some ISystemMediaTransportControls properties tests. windows.media.mediacontrol: Implement ISystemMediaTransportControlsInterop::GetForWindow(). windows.media.mediacontrol/tests: Add ISystemMediaTransportControlsInterop::GetForWindow() tests. windows.media.mediacontrol: Add ISystemMediaTransportControlsInterop stub interface. include: Add systemmediatransportcontrolsinterop.idl file. windows.media.mediacontrol: Add stub DLL. include: Add ISystemMediaTransportControls interface definition.
From: Mohamad Al-Jaf mohamadaljaf@gmail.com
--- include/windows.media.idl | 168 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 168 insertions(+)
diff --git a/include/windows.media.idl b/include/windows.media.idl index 03d03a6389f..4896f66b45b 100644 --- a/include/windows.media.idl +++ b/include/windows.media.idl @@ -26,9 +26,24 @@ import "windows.foundation.idl"; namespace Windows.Media { typedef enum AudioProcessing AudioProcessing; + typedef enum MediaPlaybackStatus MediaPlaybackStatus; + typedef enum SoundLevel SoundLevel; + typedef enum SystemMediaTransportControlsButton SystemMediaTransportControlsButton; + typedef enum SystemMediaTransportControlsProperty SystemMediaTransportControlsProperty;
interface IMediaControl; interface IMediaMarker; + interface ISystemMediaTransportControls; + interface ISystemMediaTransportControls2; + interface ISystemMediaTransportControlsButtonPressedEventArgs; + interface ISystemMediaTransportControlsDisplayUpdater; + interface ISystemMediaTransportControlsPropertyChangedEventArgs; + interface ISystemMediaTransportControlsStatics; + + runtimeclass SystemMediaTransportControls; + runtimeclass SystemMediaTransportControlsButtonPressedEventArgs; + runtimeclass SystemMediaTransportControlsDisplayUpdater; + runtimeclass SystemMediaTransportControlsPropertyChangedEventArgs;
declare { @@ -36,6 +51,8 @@ namespace Windows.Media interface Windows.Foundation.Collections.IIterator<Windows.Media.IMediaMarker*>; interface Windows.Foundation.Collections.IVectorView<Windows.Media.IMediaMarker*>; interface Windows.Foundation.Collections.IVector<Windows.Media.IMediaMarker*>; + interface Windows.Foundation.TypedEventHandler<Windows.Media.SystemMediaTransportControls*, Windows.Media.SystemMediaTransportControlsButtonPressedEventArgs*>; + interface Windows.Foundation.TypedEventHandler<Windows.Media.SystemMediaTransportControls*, Windows.Media.SystemMediaTransportControlsPropertyChangedEventArgs*>; }
[ @@ -47,6 +64,53 @@ namespace Windows.Media Raw = 1, };
+ [ + contract(Windows.Foundation.UniversalApiContract, 1.0) + ] + enum MediaPlaybackStatus + { + Closed = 0, + Changing = 1, + Stopped = 2, + Playing = 3, + Paused = 4, + }; + + [ + contract(Windows.Foundation.UniversalApiContract, 1.0) + ] + enum SoundLevel + { + Muted = 0, + Low = 1, + Full = 2, + }; + + [ + contract(Windows.Foundation.UniversalApiContract, 1.0) + ] + enum SystemMediaTransportControlsButton + { + Play = 0, + Pause = 1, + Stop = 2, + Record = 3, + FastForward = 4, + Rewind = 5, + Next = 6, + Previous = 7, + ChannelUp = 8, + ChannelDown = 9, + }; + + [ + contract(Windows.Foundation.UniversalApiContract, 1.0) + ] + enum SystemMediaTransportControlsProperty + { + SoundLevel = 0, + }; + [ contract(Windows.Foundation.UniversalApiContract, 1.0), uuid(1803def8-dca5-4b6f-9c20-e3d3c0643625) @@ -58,4 +122,108 @@ namespace Windows.Media [propget] HRESULT Text([out, retval] HSTRING *value); }
+ [ + contract(Windows.Foundation.UniversalApiContract, 1.0), + exclusiveto(Windows.Media.SystemMediaTransportControls), + uuid(99fa3ff4-1742-42a6-902e-087d41f965ec) + ] + interface ISystemMediaTransportControls : IInspectable + { + [propget] HRESULT PlaybackStatus([out, retval] Windows.Media.MediaPlaybackStatus *value); + [propput] HRESULT PlaybackStatus([in] Windows.Media.MediaPlaybackStatus value); + [propget] HRESULT DisplayUpdater([out, retval] Windows.Media.SystemMediaTransportControlsDisplayUpdater **value); + [propget] HRESULT SoundLevel([out, retval] Windows.Media.SoundLevel *value); + [propget] HRESULT IsEnabled([out, retval] boolean *value); + [propput] HRESULT IsEnabled([in] boolean value); + [propget] HRESULT IsPlayEnabled([out, retval] boolean *value); + [propput] HRESULT IsPlayEnabled([in] boolean value); + [propget] HRESULT IsStopEnabled([out, retval] boolean *value); + [propput] HRESULT IsStopEnabled([in] boolean value); + [propget] HRESULT IsPauseEnabled([out, retval] boolean *value); + [propput] HRESULT IsPauseEnabled([in] boolean value); + [propget] HRESULT IsRecordEnabled([out, retval] boolean *value); + [propput] HRESULT IsRecordEnabled([in] boolean value); + [propget] HRESULT IsFastForwardEnabled([out, retval] boolean *value); + [propput] HRESULT IsFastForwardEnabled([in] boolean value); + [propget] HRESULT IsRewindEnabled([out, retval] boolean *value); + [propput] HRESULT IsRewindEnabled([in] boolean value); + [propget] HRESULT IsPreviousEnabled([out, retval] boolean *value); + [propput] HRESULT IsPreviousEnabled([in] boolean value); + [propget] HRESULT IsNextEnabled([out, retval] boolean *value); + [propput] HRESULT IsNextEnabled([in] boolean value); + [propget] HRESULT IsChannelUpEnabled([out, retval] boolean *value); + [propput] HRESULT IsChannelUpEnabled([in] boolean value); + [propget] HRESULT IsChannelDownEnabled([out, retval] boolean *value); + [propput] HRESULT IsChannelDownEnabled([in] boolean value); + [eventadd] HRESULT ButtonPressed( + [in] Windows.Foundation.TypedEventHandler<Windows.Media.SystemMediaTransportControls *, Windows.Media.SystemMediaTransportControlsButtonPressedEventArgs *> *handler, + [out, retval] EventRegistrationToken *token + ); + [eventremove] HRESULT ButtonPressed([in] EventRegistrationToken token); + [eventadd] HRESULT PropertyChanged( + [in] Windows.Foundation.TypedEventHandler<Windows.Media.SystemMediaTransportControls *, Windows.Media.SystemMediaTransportControlsPropertyChangedEventArgs *> *handler, + [out, retval] EventRegistrationToken *token + ); + [eventremove] HRESULT PropertyChanged([in] EventRegistrationToken token); + } + + [ + contract(Windows.Foundation.UniversalApiContract, 1.0), + exclusiveto(Windows.Media.SystemMediaTransportControlsButtonPressedEventArgs), + uuid(b7f47116-a56f-4dc8-9e11-92031f4a87c2) + ] + interface ISystemMediaTransportControlsButtonPressedEventArgs : IInspectable + { + [propget] HRESULT Button([out, retval] Windows.Media.SystemMediaTransportControlsButton *value); + } + + [ + contract(Windows.Foundation.UniversalApiContract, 1.0), + exclusiveto(Windows.Media.SystemMediaTransportControlsPropertyChangedEventArgs), + uuid(d0ca0936-339b-4cb3-8eeb-737607f56e08) + ] + interface ISystemMediaTransportControlsPropertyChangedEventArgs : IInspectable + { + [propget] HRESULT Property([out, retval] Windows.Media.SystemMediaTransportControlsProperty *value); + } + + [ + contract(Windows.Foundation.UniversalApiContract, 1.0), + marshaling_behavior(agile), + static(Windows.Media.ISystemMediaTransportControlsStatics, Windows.Foundation.UniversalApiContract, 1.0), + threading(mta) + ] + runtimeclass SystemMediaTransportControls + { + [default] interface Windows.Media.ISystemMediaTransportControls; + [contract(Windows.Foundation.UniversalApiContract, 1.0)] interface Windows.Media.ISystemMediaTransportControls2; + } + + [ + contract(Windows.Foundation.UniversalApiContract, 1.0), + marshaling_behavior(agile) + ] + runtimeclass SystemMediaTransportControlsButtonPressedEventArgs + { + [default] interface Windows.Media.ISystemMediaTransportControlsButtonPressedEventArgs; + } + + [ + contract(Windows.Foundation.UniversalApiContract, 1.0), + marshaling_behavior(agile), + threading(both) + ] + runtimeclass SystemMediaTransportControlsDisplayUpdater + { + [default] interface Windows.Media.ISystemMediaTransportControlsDisplayUpdater; + } + + [ + contract(Windows.Foundation.UniversalApiContract, 1.0), + marshaling_behavior(agile) + ] + runtimeclass SystemMediaTransportControlsPropertyChangedEventArgs + { + [default] interface Windows.Media.ISystemMediaTransportControlsPropertyChangedEventArgs; + } }
From: Mohamad Al-Jaf mohamadaljaf@gmail.com
--- configure.ac | 2 + dlls/windows.media.mediacontrol/Makefile.in | 8 + dlls/windows.media.mediacontrol/classes.idl | 23 +++ dlls/windows.media.mediacontrol/main.c | 139 ++++++++++++++++++ dlls/windows.media.mediacontrol/private.h | 38 +++++ .../tests/Makefile.in | 5 + .../tests/mediacontrol.c | 86 +++++++++++ .../windows.media.mediacontrol.spec | 11 ++ 8 files changed, 312 insertions(+) create mode 100644 dlls/windows.media.mediacontrol/Makefile.in create mode 100644 dlls/windows.media.mediacontrol/classes.idl create mode 100644 dlls/windows.media.mediacontrol/main.c create mode 100644 dlls/windows.media.mediacontrol/private.h create mode 100644 dlls/windows.media.mediacontrol/tests/Makefile.in create mode 100644 dlls/windows.media.mediacontrol/tests/mediacontrol.c create mode 100644 dlls/windows.media.mediacontrol/windows.media.mediacontrol.spec
diff --git a/configure.ac b/configure.ac index 4803b7abea4..5676e35f2b9 100644 --- a/configure.ac +++ b/configure.ac @@ -3163,6 +3163,8 @@ WINE_CONFIG_MAKEFILE(dlls/windows.globalization) WINE_CONFIG_MAKEFILE(dlls/windows.globalization/tests) WINE_CONFIG_MAKEFILE(dlls/windows.media.devices) WINE_CONFIG_MAKEFILE(dlls/windows.media.devices/tests) +WINE_CONFIG_MAKEFILE(dlls/windows.media.mediacontrol) +WINE_CONFIG_MAKEFILE(dlls/windows.media.mediacontrol/tests) WINE_CONFIG_MAKEFILE(dlls/windows.media.speech) WINE_CONFIG_MAKEFILE(dlls/windows.media.speech/tests) WINE_CONFIG_MAKEFILE(dlls/windows.media) diff --git a/dlls/windows.media.mediacontrol/Makefile.in b/dlls/windows.media.mediacontrol/Makefile.in new file mode 100644 index 00000000000..d4bb8bf4d3e --- /dev/null +++ b/dlls/windows.media.mediacontrol/Makefile.in @@ -0,0 +1,8 @@ +MODULE = windows.media.mediacontrol.dll +IMPORTS = combase + +C_SRCS = \ + main.c + +IDL_SRCS = \ + classes.idl diff --git a/dlls/windows.media.mediacontrol/classes.idl b/dlls/windows.media.mediacontrol/classes.idl new file mode 100644 index 00000000000..35f3e786399 --- /dev/null +++ b/dlls/windows.media.mediacontrol/classes.idl @@ -0,0 +1,23 @@ +/* + * Runtime Classes for windows.media.mediacontrol.dll + * + * Copyright (C) 2023 Mohamad Al-Jaf + * + * 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 + */ + +#pragma makedep register + +#include "windows.media.idl" diff --git a/dlls/windows.media.mediacontrol/main.c b/dlls/windows.media.mediacontrol/main.c new file mode 100644 index 00000000000..506e068cf60 --- /dev/null +++ b/dlls/windows.media.mediacontrol/main.c @@ -0,0 +1,139 @@ +/* WinRT Windows.Media.MediaControl Implementation + * + * Copyright (C) 2023 Mohamad Al-Jaf + * + * 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 + */ + +#include "initguid.h" +#include "private.h" + +#include "wine/debug.h" + +WINE_DEFAULT_DEBUG_CHANNEL(mediacontrol); + +struct media_control_statics +{ + IActivationFactory IActivationFactory_iface; + LONG ref; +}; + +static inline struct media_control_statics *impl_from_IActivationFactory( IActivationFactory *iface ) +{ + return CONTAINING_RECORD( iface, struct media_control_statics, IActivationFactory_iface ); +} + +static HRESULT WINAPI factory_QueryInterface( IActivationFactory *iface, REFIID iid, void **out ) +{ + struct media_control_statics *impl = impl_from_IActivationFactory( iface ); + + TRACE( "iface %p, iid %s, out %p.\n", iface, debugstr_guid( iid ), out ); + + if (IsEqualGUID( iid, &IID_IUnknown ) || + IsEqualGUID( iid, &IID_IInspectable ) || + IsEqualGUID( iid, &IID_IAgileObject ) || + IsEqualGUID( iid, &IID_IActivationFactory )) + { + *out = &impl->IActivationFactory_iface; + IInspectable_AddRef( *out ); + return S_OK; + } + + FIXME( "%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid( iid ) ); + *out = NULL; + return E_NOINTERFACE; +} + +static ULONG WINAPI factory_AddRef( IActivationFactory *iface ) +{ + struct media_control_statics *impl = impl_from_IActivationFactory( iface ); + ULONG ref = InterlockedIncrement( &impl->ref ); + TRACE( "iface %p increasing refcount to %lu.\n", iface, ref ); + return ref; +} + +static ULONG WINAPI factory_Release( IActivationFactory *iface ) +{ + struct media_control_statics *impl = impl_from_IActivationFactory( iface ); + ULONG ref = InterlockedDecrement( &impl->ref ); + TRACE( "iface %p decreasing refcount to %lu.\n", iface, ref ); + return ref; +} + +static HRESULT WINAPI factory_GetIids( IActivationFactory *iface, ULONG *iid_count, IID **iids ) +{ + FIXME( "iface %p, iid_count %p, iids %p stub!\n", iface, iid_count, iids ); + return E_NOTIMPL; +} + +static HRESULT WINAPI factory_GetRuntimeClassName( IActivationFactory *iface, HSTRING *class_name ) +{ + FIXME( "iface %p, class_name %p stub!\n", iface, class_name ); + return E_NOTIMPL; +} + +static HRESULT WINAPI factory_GetTrustLevel( IActivationFactory *iface, TrustLevel *trust_level ) +{ + FIXME( "iface %p, trust_level %p stub!\n", iface, trust_level ); + return E_NOTIMPL; +} + +static HRESULT WINAPI factory_ActivateInstance( IActivationFactory *iface, IInspectable **instance ) +{ + FIXME( "iface %p, instance %p stub!\n", iface, instance ); + return E_NOTIMPL; +} + +static const struct IActivationFactoryVtbl factory_vtbl = +{ + factory_QueryInterface, + factory_AddRef, + factory_Release, + /* IInspectable methods */ + factory_GetIids, + factory_GetRuntimeClassName, + factory_GetTrustLevel, + /* IActivationFactory methods */ + factory_ActivateInstance, +}; + +static struct media_control_statics media_control_statics = +{ + {&factory_vtbl}, + 1, +}; + +static IActivationFactory *media_control_factory = &media_control_statics.IActivationFactory_iface; + +HRESULT WINAPI DllGetClassObject( REFCLSID clsid, REFIID riid, void **out ) +{ + FIXME( "clsid %s, riid %s, out %p stub!\n", debugstr_guid( clsid ), debugstr_guid( riid ), out ); + return CLASS_E_CLASSNOTAVAILABLE; +} + +HRESULT WINAPI DllGetActivationFactory( HSTRING classid, IActivationFactory **factory ) +{ + const WCHAR *buffer = WindowsGetStringRawBuffer( classid, NULL ); + + TRACE( "class %s, factory %p.\n", debugstr_hstring( classid ), factory ); + + *factory = NULL; + + if (!wcscmp( buffer, RuntimeClass_Windows_Media_SystemMediaTransportControls )) + IActivationFactory_QueryInterface( media_control_factory, &IID_IActivationFactory, (void **)factory ); + + if (*factory) return S_OK; + return CLASS_E_CLASSNOTAVAILABLE; +} diff --git a/dlls/windows.media.mediacontrol/private.h b/dlls/windows.media.mediacontrol/private.h new file mode 100644 index 00000000000..676bc10fc87 --- /dev/null +++ b/dlls/windows.media.mediacontrol/private.h @@ -0,0 +1,38 @@ +/* WinRT Windows.Media.MediaControl Implementation + * + * Copyright (C) 2023 Mohamad Al-Jaf + * + * 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 + */ + +#ifndef __WINE_WINDOWS_MEDIA_MEDIACONTROL_PRIVATE_H +#define __WINE_WINDOWS_MEDIA_MEDIACONTROL_PRIVATE_H + +#include <stdarg.h> + +#define COBJMACROS +#include "windef.h" +#include "winbase.h" +#include "winstring.h" + +#include "activation.h" + +#define WIDL_using_Windows_Foundation +#define WIDL_using_Windows_Foundation_Collections +#include "windows.foundation.h" +#define WIDL_using_Windows_Media +#include "windows.media.h" + +#endif diff --git a/dlls/windows.media.mediacontrol/tests/Makefile.in b/dlls/windows.media.mediacontrol/tests/Makefile.in new file mode 100644 index 00000000000..ab07a0ef546 --- /dev/null +++ b/dlls/windows.media.mediacontrol/tests/Makefile.in @@ -0,0 +1,5 @@ +TESTDLL = windows.media.mediacontrol.dll +IMPORTS = combase + +C_SRCS = \ + mediacontrol.c diff --git a/dlls/windows.media.mediacontrol/tests/mediacontrol.c b/dlls/windows.media.mediacontrol/tests/mediacontrol.c new file mode 100644 index 00000000000..70913ea3d00 --- /dev/null +++ b/dlls/windows.media.mediacontrol/tests/mediacontrol.c @@ -0,0 +1,86 @@ +/* + * Copyright (C) 2023 Mohamad Al-Jaf + * + * 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 COBJMACROS +#include "initguid.h" +#include <stdarg.h> + +#include "windef.h" +#include "winbase.h" +#include "winstring.h" + +#include "roapi.h" + +#define WIDL_using_Windows_Foundation +#define WIDL_using_Windows_Foundation_Collections +#include "windows.foundation.h" +#define WIDL_using_Windows_Media +#include "windows.media.h" + +#include "wine/test.h" + +#define check_interface( obj, iid ) check_interface_( __LINE__, obj, iid ) +static void check_interface_( unsigned int line, void *obj, const IID *iid ) +{ + IUnknown *iface = obj; + IUnknown *unk; + HRESULT hr; + + hr = IUnknown_QueryInterface( iface, iid, (void **)&unk ); + ok_(__FILE__, line)( hr == S_OK, "got hr %#lx.\n", hr ); + IUnknown_Release( unk ); +} + +static void test_MediaControlStatics(void) +{ + static const WCHAR *media_control_statics_name = L"Windows.Media.SystemMediaTransportControls"; + IActivationFactory *factory; + HSTRING str; + HRESULT hr; + LONG ref; + + hr = WindowsCreateString( media_control_statics_name, wcslen( media_control_statics_name ), &str ); + ok( hr == S_OK, "got hr %#lx.\n", hr ); + + hr = RoGetActivationFactory( str, &IID_IActivationFactory, (void **)&factory ); + WindowsDeleteString( str ); + ok( hr == S_OK || broken( hr == REGDB_E_CLASSNOTREG ), "got hr %#lx.\n", hr ); + if (hr == REGDB_E_CLASSNOTREG) + { + win_skip( "%s runtimeclass not registered, skipping tests.\n", wine_dbgstr_w( media_control_statics_name ) ); + return; + } + + check_interface( factory, &IID_IUnknown ); + check_interface( factory, &IID_IInspectable ); + check_interface( factory, &IID_IAgileObject ); + + ref = IActivationFactory_Release( factory ); + ok( ref == 1, "got ref %ld.\n", ref ); +} + +START_TEST(mediacontrol) +{ + HRESULT hr; + + hr = RoInitialize( RO_INIT_MULTITHREADED ); + ok( hr == S_OK, "RoInitialize failed, hr %#lx\n", hr ); + + test_MediaControlStatics(); + + RoUninitialize(); +} diff --git a/dlls/windows.media.mediacontrol/windows.media.mediacontrol.spec b/dlls/windows.media.mediacontrol/windows.media.mediacontrol.spec new file mode 100644 index 00000000000..daa9b156f62 --- /dev/null +++ b/dlls/windows.media.mediacontrol/windows.media.mediacontrol.spec @@ -0,0 +1,11 @@ +@ stub CreateCaptureAudioStateMonitor +@ stub CreateCaptureAudioStateMonitorForCategory +@ stub CreateCaptureAudioStateMonitorForCategoryAndDeviceId +@ stub CreateCaptureAudioStateMonitorForCategoryAndDeviceRole +@ stub CreateRenderAudioStateMonitor +@ stub CreateRenderAudioStateMonitorForCategory +@ stub CreateRenderAudioStateMonitorForCategoryAndDeviceId +@ stub CreateRenderAudioStateMonitorForCategoryAndDeviceRole +@ stdcall -private DllCanUnloadNow() +@ stdcall -private DllGetActivationFactory(ptr ptr) +@ stdcall -private DllGetClassObject(ptr ptr ptr)
From: Mohamad Al-Jaf mohamadaljaf@gmail.com
--- include/Makefile.in | 1 + .../systemmediatransportcontrolsinterop.idl | 28 +++++++++++++++++++ 2 files changed, 29 insertions(+) create mode 100644 include/systemmediatransportcontrolsinterop.idl
diff --git a/include/Makefile.in b/include/Makefile.in index 7d7697bc015..987e45dffa9 100644 --- a/include/Makefile.in +++ b/include/Makefile.in @@ -733,6 +733,7 @@ SOURCES = \ structuredquerycondition.idl \ svrapi.h \ synchapi.h \ + systemmediatransportcontrolsinterop.idl \ t2embapi.h \ tapi.h \ taskschd.idl \ diff --git a/include/systemmediatransportcontrolsinterop.idl b/include/systemmediatransportcontrolsinterop.idl new file mode 100644 index 00000000000..1679176be04 --- /dev/null +++ b/include/systemmediatransportcontrolsinterop.idl @@ -0,0 +1,28 @@ +/* + * Copyright (C) 2023 Mohamad Al-Jaf + * + * 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 + */ + +import "inspectable.idl"; + +[ + object, + uuid(ddb0472d-c911-4a1f-86d9-dc3d71a95f5a) +] +interface ISystemMediaTransportControlsInterop : IInspectable +{ + HRESULT GetForWindow([in] HWND window, [in] REFIID riid, [out, retval, iid_is(riid)] void **control); +}
From: Mohamad Al-Jaf mohamadaljaf@gmail.com
--- dlls/windows.media.mediacontrol/classes.idl | 1 + dlls/windows.media.mediacontrol/main.c | 30 ++++++++++++++ dlls/windows.media.mediacontrol/private.h | 39 +++++++++++++++++++ .../tests/mediacontrol.c | 7 ++++ 4 files changed, 77 insertions(+)
diff --git a/dlls/windows.media.mediacontrol/classes.idl b/dlls/windows.media.mediacontrol/classes.idl index 35f3e786399..b58facdc46a 100644 --- a/dlls/windows.media.mediacontrol/classes.idl +++ b/dlls/windows.media.mediacontrol/classes.idl @@ -20,4 +20,5 @@
#pragma makedep register
+#include "systemmediatransportcontrolsinterop.idl" #include "windows.media.idl" diff --git a/dlls/windows.media.mediacontrol/main.c b/dlls/windows.media.mediacontrol/main.c index 506e068cf60..2bd5e02b7bc 100644 --- a/dlls/windows.media.mediacontrol/main.c +++ b/dlls/windows.media.mediacontrol/main.c @@ -27,6 +27,7 @@ WINE_DEFAULT_DEBUG_CHANNEL(mediacontrol); struct media_control_statics { IActivationFactory IActivationFactory_iface; + ISystemMediaTransportControlsInterop ISystemMediaTransportControlsInterop_iface; LONG ref; };
@@ -51,6 +52,13 @@ static HRESULT WINAPI factory_QueryInterface( IActivationFactory *iface, REFIID return S_OK; }
+ if (IsEqualGUID( iid, &IID_ISystemMediaTransportControlsInterop )) + { + *out = &impl->ISystemMediaTransportControlsInterop_iface; + IInspectable_AddRef( *out ); + return S_OK; + } + FIXME( "%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid( iid ) ); *out = NULL; return E_NOINTERFACE; @@ -109,9 +117,31 @@ static const struct IActivationFactoryVtbl factory_vtbl = factory_ActivateInstance, };
+DEFINE_IINSPECTABLE( media_control_statics, ISystemMediaTransportControlsInterop, struct media_control_statics, IActivationFactory_iface ) + +static HRESULT WINAPI media_control_statics_GetForWindow( ISystemMediaTransportControlsInterop *iface, HWND window, REFIID riid, void **control ) +{ + FIXME( "iface %p, window %p, riid %s, control %p stub!\n", iface, window, debugstr_guid( riid ), control ); + return E_NOTIMPL; +} + +static const struct ISystemMediaTransportControlsInteropVtbl media_control_statics_vtbl = +{ + media_control_statics_QueryInterface, + media_control_statics_AddRef, + media_control_statics_Release, + /* IInspectable methods */ + media_control_statics_GetIids, + media_control_statics_GetRuntimeClassName, + media_control_statics_GetTrustLevel, + /* ISystemMediaTransportControlsInterop methods */ + media_control_statics_GetForWindow, +}; + static struct media_control_statics media_control_statics = { {&factory_vtbl}, + {&media_control_statics_vtbl}, 1, };
diff --git a/dlls/windows.media.mediacontrol/private.h b/dlls/windows.media.mediacontrol/private.h index 676bc10fc87..b5f4e6f262e 100644 --- a/dlls/windows.media.mediacontrol/private.h +++ b/dlls/windows.media.mediacontrol/private.h @@ -34,5 +34,44 @@ #include "windows.foundation.h" #define WIDL_using_Windows_Media #include "windows.media.h" +#include "systemmediatransportcontrolsinterop.h" + +#define DEFINE_IINSPECTABLE_( pfx, iface_type, impl_type, impl_from, iface_mem, expr ) \ + static inline impl_type *impl_from( iface_type *iface ) \ + { \ + return CONTAINING_RECORD( iface, impl_type, iface_mem ); \ + } \ + static HRESULT WINAPI pfx##_QueryInterface( iface_type *iface, REFIID iid, void **out ) \ + { \ + impl_type *impl = impl_from( iface ); \ + return IInspectable_QueryInterface( (IInspectable *)(expr), iid, out ); \ + } \ + static ULONG WINAPI pfx##_AddRef( iface_type *iface ) \ + { \ + impl_type *impl = impl_from( iface ); \ + return IInspectable_AddRef( (IInspectable *)(expr) ); \ + } \ + static ULONG WINAPI pfx##_Release( iface_type *iface ) \ + { \ + impl_type *impl = impl_from( iface ); \ + return IInspectable_Release( (IInspectable *)(expr) ); \ + } \ + static HRESULT WINAPI pfx##_GetIids( iface_type *iface, ULONG *iid_count, IID **iids ) \ + { \ + impl_type *impl = impl_from( iface ); \ + return IInspectable_GetIids( (IInspectable *)(expr), iid_count, iids ); \ + } \ + static HRESULT WINAPI pfx##_GetRuntimeClassName( iface_type *iface, HSTRING *class_name ) \ + { \ + impl_type *impl = impl_from( iface ); \ + return IInspectable_GetRuntimeClassName( (IInspectable *)(expr), class_name ); \ + } \ + static HRESULT WINAPI pfx##_GetTrustLevel( iface_type *iface, TrustLevel *trust_level ) \ + { \ + impl_type *impl = impl_from( iface ); \ + return IInspectable_GetTrustLevel( (IInspectable *)(expr), trust_level ); \ + } +#define DEFINE_IINSPECTABLE( pfx, iface_type, impl_type, base_iface ) \ + DEFINE_IINSPECTABLE_( pfx, iface_type, impl_type, impl_from_##iface_type, iface_type##_iface, &impl->base_iface )
#endif diff --git a/dlls/windows.media.mediacontrol/tests/mediacontrol.c b/dlls/windows.media.mediacontrol/tests/mediacontrol.c index 70913ea3d00..cc7fcce052c 100644 --- a/dlls/windows.media.mediacontrol/tests/mediacontrol.c +++ b/dlls/windows.media.mediacontrol/tests/mediacontrol.c @@ -30,6 +30,7 @@ #include "windows.foundation.h" #define WIDL_using_Windows_Media #include "windows.media.h" +#include "systemmediatransportcontrolsinterop.h"
#include "wine/test.h"
@@ -48,6 +49,7 @@ static void check_interface_( unsigned int line, void *obj, const IID *iid ) static void test_MediaControlStatics(void) { static const WCHAR *media_control_statics_name = L"Windows.Media.SystemMediaTransportControls"; + ISystemMediaTransportControlsInterop *media_control_interop_statics; IActivationFactory *factory; HSTRING str; HRESULT hr; @@ -69,6 +71,11 @@ static void test_MediaControlStatics(void) check_interface( factory, &IID_IInspectable ); check_interface( factory, &IID_IAgileObject );
+ hr = IActivationFactory_QueryInterface( factory, &IID_ISystemMediaTransportControlsInterop, (void **)&media_control_interop_statics ); + ok( hr == S_OK, "got hr %#lx.\n", hr ); + + ref = ISystemMediaTransportControlsInterop_Release( media_control_interop_statics ); + ok( ref == 2, "got ref %ld.\n", ref ); ref = IActivationFactory_Release( factory ); ok( ref == 1, "got ref %ld.\n", ref ); }
From: Mohamad Al-Jaf mohamadaljaf@gmail.com
--- dlls/windows.media.mediacontrol/tests/Makefile.in | 2 +- .../tests/mediacontrol.c | 14 ++++++++++++++ 2 files changed, 15 insertions(+), 1 deletion(-)
diff --git a/dlls/windows.media.mediacontrol/tests/Makefile.in b/dlls/windows.media.mediacontrol/tests/Makefile.in index ab07a0ef546..b0bceb0ac75 100644 --- a/dlls/windows.media.mediacontrol/tests/Makefile.in +++ b/dlls/windows.media.mediacontrol/tests/Makefile.in @@ -1,5 +1,5 @@ TESTDLL = windows.media.mediacontrol.dll -IMPORTS = combase +IMPORTS = combase user32
C_SRCS = \ mediacontrol.c diff --git a/dlls/windows.media.mediacontrol/tests/mediacontrol.c b/dlls/windows.media.mediacontrol/tests/mediacontrol.c index cc7fcce052c..6b0b2f9a15f 100644 --- a/dlls/windows.media.mediacontrol/tests/mediacontrol.c +++ b/dlls/windows.media.mediacontrol/tests/mediacontrol.c @@ -50,7 +50,9 @@ static void test_MediaControlStatics(void) { static const WCHAR *media_control_statics_name = L"Windows.Media.SystemMediaTransportControls"; ISystemMediaTransportControlsInterop *media_control_interop_statics; + ISystemMediaTransportControls *media_control_statics = NULL; IActivationFactory *factory; + HWND window = NULL; HSTRING str; HRESULT hr; LONG ref; @@ -74,6 +76,18 @@ static void test_MediaControlStatics(void) hr = IActivationFactory_QueryInterface( factory, &IID_ISystemMediaTransportControlsInterop, (void **)&media_control_interop_statics ); ok( hr == S_OK, "got hr %#lx.\n", hr );
+ hr = ISystemMediaTransportControlsInterop_GetForWindow( media_control_interop_statics, NULL, &IID_ISystemMediaTransportControls, (void **)&media_control_statics ); + todo_wine ok( hr == E_POINTER || broken(hr == 0x80070578) /* Win8 */, "got hr %#lx.\n", hr ); + + window = CreateWindowExA( 0, "static", 0, 0, CW_USEDEFAULT, CW_USEDEFAULT, 800, 600, NULL, NULL, GetModuleHandleA( NULL ), 0 ); + ok( window != NULL, "Failed to create a window\n" ); + hr = ISystemMediaTransportControlsInterop_GetForWindow( media_control_interop_statics, window, &IID_ISystemMediaTransportControlsInterop, (void **)&media_control_statics ); + todo_wine ok( hr == E_NOINTERFACE || broken(hr == 0x80070578) /* Win8 */, "got hr %#lx.\n", hr ); + hr = ISystemMediaTransportControlsInterop_GetForWindow( media_control_interop_statics, window, &IID_ISystemMediaTransportControls, (void **)&media_control_statics ); + todo_wine ok( hr == S_OK || broken(hr == 0x80070578) /* Win8 */, "got hr %#lx.\n", hr ); + if (media_control_statics) ISystemMediaTransportControls_Release( media_control_statics ); + + DestroyWindow( window ); ref = ISystemMediaTransportControlsInterop_Release( media_control_interop_statics ); ok( ref == 2, "got ref %ld.\n", ref ); ref = IActivationFactory_Release( factory );
From: Mohamad Al-Jaf mohamadaljaf@gmail.com
--- dlls/windows.media.mediacontrol/main.c | 314 +++++++++++++++++- .../tests/mediacontrol.c | 26 +- 2 files changed, 334 insertions(+), 6 deletions(-)
diff --git a/dlls/windows.media.mediacontrol/main.c b/dlls/windows.media.mediacontrol/main.c index 2bd5e02b7bc..8c17ccbe4df 100644 --- a/dlls/windows.media.mediacontrol/main.c +++ b/dlls/windows.media.mediacontrol/main.c @@ -117,12 +117,322 @@ static const struct IActivationFactoryVtbl factory_vtbl = factory_ActivateInstance, };
+struct media_control +{ + ISystemMediaTransportControls ISystemMediaTransportControls_iface; + LONG ref; + + HWND window; +}; + +static inline struct media_control *impl_from_ISystemMediaTransportControls( ISystemMediaTransportControls *iface ) +{ + return CONTAINING_RECORD( iface, struct media_control, ISystemMediaTransportControls_iface ); +} + +static HRESULT WINAPI media_control_QueryInterface( ISystemMediaTransportControls *iface, REFIID iid, void **out ) +{ + struct media_control *impl = impl_from_ISystemMediaTransportControls( iface ); + + TRACE( "iface %p, iid %s, out %p.\n", iface, debugstr_guid( iid ), out ); + + if (IsEqualGUID( iid, &IID_IUnknown ) || + IsEqualGUID( iid, &IID_IInspectable ) || + IsEqualGUID( iid, &IID_IAgileObject ) || + IsEqualGUID( iid, &IID_ISystemMediaTransportControls )) + { + *out = &impl->ISystemMediaTransportControls_iface; + IInspectable_AddRef( *out ); + return S_OK; + } + + FIXME( "%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid( iid ) ); + *out = NULL; + return E_NOINTERFACE; +} + +static ULONG WINAPI media_control_AddRef( ISystemMediaTransportControls *iface ) +{ + struct media_control *impl = impl_from_ISystemMediaTransportControls( iface ); + ULONG ref = InterlockedIncrement( &impl->ref ); + TRACE( "iface %p increasing refcount to %lu.\n", iface, ref ); + return ref; +} + +static ULONG WINAPI media_control_Release( ISystemMediaTransportControls *iface ) +{ + struct media_control *impl = impl_from_ISystemMediaTransportControls( iface ); + ULONG ref = InterlockedDecrement( &impl->ref ); + + TRACE( "iface %p decreasing refcount to %lu.\n", iface, ref ); + + if (!ref) free( impl ); + return ref; +} + +static HRESULT WINAPI media_control_GetIids( ISystemMediaTransportControls *iface, ULONG *iid_count, IID **iids ) +{ + FIXME( "iface %p, iid_count %p, iids %p stub!\n", iface, iid_count, iids ); + return E_NOTIMPL; +} + +static HRESULT WINAPI media_control_GetRuntimeClassName( ISystemMediaTransportControls *iface, HSTRING *class_name ) +{ + FIXME( "iface %p, class_name %p stub!\n", iface, class_name ); + return E_NOTIMPL; +} + +static HRESULT WINAPI media_control_GetTrustLevel( ISystemMediaTransportControls *iface, TrustLevel *trust_level ) +{ + FIXME( "iface %p, trust_level %p stub!\n", iface, trust_level ); + return E_NOTIMPL; +} + +static HRESULT WINAPI media_control_get_PlaybackStatus( ISystemMediaTransportControls *iface, MediaPlaybackStatus *value ) +{ + FIXME( "iface %p, value %p stub!\n", iface, value ); + return E_NOTIMPL; +} + +static HRESULT WINAPI media_control_put_PlaybackStatus( ISystemMediaTransportControls *iface, MediaPlaybackStatus value ) +{ + FIXME( "iface %p, value %d stub!\n", iface, value ); + return E_NOTIMPL; +} + +static HRESULT WINAPI media_control_get_DisplayUpdater( ISystemMediaTransportControls *iface, __x_ABI_CWindows_CMedia_CISystemMediaTransportControlsDisplayUpdater **value ) +{ + FIXME( "iface %p, value %p stub!\n", iface, value ); + return E_NOTIMPL; +} + +static HRESULT WINAPI media_control_get_SoundLevel( ISystemMediaTransportControls *iface, SoundLevel *value ) +{ + FIXME( "iface %p, value %p stub!\n", iface, value ); + return E_NOTIMPL; +} + +static HRESULT WINAPI media_control_get_IsEnabled( ISystemMediaTransportControls *iface, boolean *value ) +{ + FIXME( "iface %p, value %p stub!\n", iface, value ); + return E_NOTIMPL; +} + +static HRESULT WINAPI media_control_put_IsEnabled( ISystemMediaTransportControls *iface, boolean value ) +{ + FIXME( "iface %p, value %d stub!\n", iface, value ); + return E_NOTIMPL; +} + +static HRESULT WINAPI media_control_get_IsPlayEnabled( ISystemMediaTransportControls *iface, boolean *value ) +{ + FIXME( "iface %p, value %p stub!\n", iface, value ); + return E_NOTIMPL; +} + +static HRESULT WINAPI media_control_put_IsPlayEnabled( ISystemMediaTransportControls *iface, boolean value ) +{ + FIXME( "iface %p, value %d stub!\n", iface, value ); + return E_NOTIMPL; +} + +static HRESULT WINAPI media_control_get_IsStopEnabled( ISystemMediaTransportControls *iface, boolean *value ) +{ + FIXME( "iface %p, value %p stub!\n", iface, value ); + return E_NOTIMPL; +} + +static HRESULT WINAPI media_control_put_IsStopEnabled( ISystemMediaTransportControls *iface, boolean value ) +{ + FIXME( "iface %p, value %d stub!\n", iface, value ); + return E_NOTIMPL; +} + +static HRESULT WINAPI media_control_get_IsPauseEnabled( ISystemMediaTransportControls *iface, boolean *value ) +{ + FIXME( "iface %p, value %p stub!\n", iface, value ); + return E_NOTIMPL; +} + +static HRESULT WINAPI media_control_put_IsPauseEnabled( ISystemMediaTransportControls *iface, boolean value ) +{ + FIXME( "iface %p, value %d stub!\n", iface, value ); + return E_NOTIMPL; +} + +static HRESULT WINAPI media_control_get_IsRecordEnabled( ISystemMediaTransportControls *iface, boolean *value ) +{ + FIXME( "iface %p, value %p stub!\n", iface, value ); + return E_NOTIMPL; +} + +static HRESULT WINAPI media_control_put_IsRecordEnabled( ISystemMediaTransportControls *iface, boolean value ) +{ + FIXME( "iface %p, value %d stub!\n", iface, value ); + return E_NOTIMPL; +} + +static HRESULT WINAPI media_control_get_IsFastForwardEnabled( ISystemMediaTransportControls *iface, boolean *value ) +{ + FIXME( "iface %p, value %p stub!\n", iface, value ); + return E_NOTIMPL; +} + +static HRESULT WINAPI media_control_put_IsFastForwardEnabled( ISystemMediaTransportControls *iface, boolean value ) +{ + FIXME( "iface %p, value %d stub!\n", iface, value ); + return E_NOTIMPL; +} + +static HRESULT WINAPI media_control_get_IsRewindEnabled( ISystemMediaTransportControls *iface, boolean *value ) +{ + FIXME( "iface %p, value %p stub!\n", iface, value ); + return E_NOTIMPL; +} + +static HRESULT WINAPI media_control_put_IsRewindEnabled( ISystemMediaTransportControls *iface, boolean value ) +{ + FIXME( "iface %p, value %d stub!\n", iface, value ); + return E_NOTIMPL; +} + +static HRESULT WINAPI media_control_get_IsPreviousEnabled( ISystemMediaTransportControls *iface, boolean *value ) +{ + FIXME( "iface %p, value %p stub!\n", iface, value ); + return E_NOTIMPL; +} + +static HRESULT WINAPI media_control_put_IsPreviousEnabled( ISystemMediaTransportControls *iface, boolean value ) +{ + FIXME( "iface %p, value %d stub!\n", iface, value ); + return E_NOTIMPL; +} + +static HRESULT WINAPI media_control_get_IsNextEnabled( ISystemMediaTransportControls *iface, boolean *value ) +{ + FIXME( "iface %p, value %p stub!\n", iface, value ); + return E_NOTIMPL; +} + +static HRESULT WINAPI media_control_put_IsNextEnabled( ISystemMediaTransportControls *iface, boolean value ) +{ + FIXME( "iface %p, value %d stub!\n", iface, value ); + return E_NOTIMPL; +} + +static HRESULT WINAPI media_control_get_IsChannelUpEnabled( ISystemMediaTransportControls *iface, boolean *value ) +{ + FIXME( "iface %p, value %p stub!\n", iface, value ); + return E_NOTIMPL; +} + +static HRESULT WINAPI media_control_put_IsChannelUpEnabled( ISystemMediaTransportControls *iface, boolean value ) +{ + FIXME( "iface %p, value %d stub!\n", iface, value ); + return E_NOTIMPL; +} + +static HRESULT WINAPI media_control_get_IsChannelDownEnabled( ISystemMediaTransportControls *iface, boolean *value ) +{ + FIXME( "iface %p, value %p stub!\n", iface, value ); + return E_NOTIMPL; +} + +static HRESULT WINAPI media_control_put_IsChannelDownEnabled( ISystemMediaTransportControls *iface, boolean value ) +{ + FIXME( "iface %p, value %d stub!\n", iface, value ); + return E_NOTIMPL; +} + +static HRESULT WINAPI media_control_add_ButtonPressed( ISystemMediaTransportControls *iface, + ITypedEventHandler_SystemMediaTransportControls_SystemMediaTransportControlsButtonPressedEventArgs *handler, EventRegistrationToken *token ) +{ + FIXME( "iface %p, handler %p, token %p stub!\n", iface, handler, token ); + return E_NOTIMPL; +} + +static HRESULT WINAPI media_control_remove_ButtonPressed( ISystemMediaTransportControls *iface, EventRegistrationToken token ) +{ + FIXME( "iface %p, token %#I64x stub!\n", iface, token.value ); + return E_NOTIMPL; +} + +static HRESULT WINAPI media_control_add_PropertyChanged( ISystemMediaTransportControls *iface, + ITypedEventHandler_SystemMediaTransportControls_SystemMediaTransportControlsPropertyChangedEventArgs *handler, EventRegistrationToken *token ) +{ + FIXME( "iface %p, handler %p, token %p stub!\n", iface, handler, token ); + return E_NOTIMPL; +} + +static HRESULT WINAPI media_control_remove_PropertyChanged( ISystemMediaTransportControls *iface, EventRegistrationToken token ) +{ + FIXME( "iface %p, token %#I64x stub!\n", iface, token.value ); + return E_NOTIMPL; +} + +static const struct ISystemMediaTransportControlsVtbl media_control_vtbl = +{ + media_control_QueryInterface, + media_control_AddRef, + media_control_Release, + /* IInspectable methods */ + media_control_GetIids, + media_control_GetRuntimeClassName, + media_control_GetTrustLevel, + /* ISystemMediaTransportControls methods */ + media_control_get_PlaybackStatus, + media_control_put_PlaybackStatus, + media_control_get_DisplayUpdater, + media_control_get_SoundLevel, + media_control_get_IsEnabled, + media_control_put_IsEnabled, + media_control_get_IsPlayEnabled, + media_control_put_IsPlayEnabled, + media_control_get_IsStopEnabled, + media_control_put_IsStopEnabled, + media_control_get_IsPauseEnabled, + media_control_put_IsPauseEnabled, + media_control_get_IsRecordEnabled, + media_control_put_IsRecordEnabled, + media_control_get_IsFastForwardEnabled, + media_control_put_IsFastForwardEnabled, + media_control_get_IsRewindEnabled, + media_control_put_IsRewindEnabled, + media_control_get_IsPreviousEnabled, + media_control_put_IsPreviousEnabled, + media_control_get_IsNextEnabled, + media_control_put_IsNextEnabled, + media_control_get_IsChannelUpEnabled, + media_control_put_IsChannelUpEnabled, + media_control_get_IsChannelDownEnabled, + media_control_put_IsChannelDownEnabled, + media_control_add_ButtonPressed, + media_control_remove_ButtonPressed, + media_control_add_PropertyChanged, + media_control_remove_PropertyChanged, +}; + DEFINE_IINSPECTABLE( media_control_statics, ISystemMediaTransportControlsInterop, struct media_control_statics, IActivationFactory_iface )
static HRESULT WINAPI media_control_statics_GetForWindow( ISystemMediaTransportControlsInterop *iface, HWND window, REFIID riid, void **control ) { - FIXME( "iface %p, window %p, riid %s, control %p stub!\n", iface, window, debugstr_guid( riid ), control ); - return E_NOTIMPL; + struct media_control *impl; + HRESULT hr; + + TRACE( "iface %p, window %p, riid %s, control %p\n", iface, window, debugstr_guid( riid ), control ); + + if (!window) return E_POINTER; + if (!(impl = calloc( 1, sizeof(*impl) ))) return E_OUTOFMEMORY; + + impl->ISystemMediaTransportControls_iface.lpVtbl = &media_control_vtbl; + impl->ref = 2; + impl->window = window; + + TRACE( "created ISystemMediaTransportControls %p.\n", *control ); + + hr = ISystemMediaTransportControls_QueryInterface( &impl->ISystemMediaTransportControls_iface, riid, control ); + ISystemMediaTransportControls_Release( &impl->ISystemMediaTransportControls_iface ); + return hr; }
static const struct ISystemMediaTransportControlsInteropVtbl media_control_statics_vtbl = diff --git a/dlls/windows.media.mediacontrol/tests/mediacontrol.c b/dlls/windows.media.mediacontrol/tests/mediacontrol.c index 6b0b2f9a15f..b97340f2bff 100644 --- a/dlls/windows.media.mediacontrol/tests/mediacontrol.c +++ b/dlls/windows.media.mediacontrol/tests/mediacontrol.c @@ -46,6 +46,16 @@ static void check_interface_( unsigned int line, void *obj, const IID *iid ) IUnknown_Release( unk ); }
+static void check_interface_GetForWindow( void *media_control_interop_statics, HWND window, const IID *iid ) +{ + ISystemMediaTransportControls *media_control_statics = NULL; + HRESULT hr; + + hr = ISystemMediaTransportControlsInterop_GetForWindow( media_control_interop_statics, window, iid, (void **)&media_control_statics ); + ok( hr == S_OK || broken(hr == 0x80070578) /* Win8 */, "got hr %#lx.\n", hr ); + if (media_control_statics) ISystemMediaTransportControls_Release( media_control_statics ); +} + static void test_MediaControlStatics(void) { static const WCHAR *media_control_statics_name = L"Windows.Media.SystemMediaTransportControls"; @@ -77,16 +87,24 @@ static void test_MediaControlStatics(void) ok( hr == S_OK, "got hr %#lx.\n", hr );
hr = ISystemMediaTransportControlsInterop_GetForWindow( media_control_interop_statics, NULL, &IID_ISystemMediaTransportControls, (void **)&media_control_statics ); - todo_wine ok( hr == E_POINTER || broken(hr == 0x80070578) /* Win8 */, "got hr %#lx.\n", hr ); + ok( hr == E_POINTER || broken(hr == 0x80070578) /* Win8 */, "got hr %#lx.\n", hr );
window = CreateWindowExA( 0, "static", 0, 0, CW_USEDEFAULT, CW_USEDEFAULT, 800, 600, NULL, NULL, GetModuleHandleA( NULL ), 0 ); ok( window != NULL, "Failed to create a window\n" ); hr = ISystemMediaTransportControlsInterop_GetForWindow( media_control_interop_statics, window, &IID_ISystemMediaTransportControlsInterop, (void **)&media_control_statics ); - todo_wine ok( hr == E_NOINTERFACE || broken(hr == 0x80070578) /* Win8 */, "got hr %#lx.\n", hr ); + ok( hr == E_NOINTERFACE || broken(hr == 0x80070578) /* Win8 */, "got hr %#lx.\n", hr ); + + check_interface_GetForWindow( media_control_interop_statics, window, &IID_IUnknown ); + check_interface_GetForWindow( media_control_interop_statics, window, &IID_IInspectable ); + check_interface_GetForWindow( media_control_interop_statics, window, &IID_IAgileObject ); + hr = ISystemMediaTransportControlsInterop_GetForWindow( media_control_interop_statics, window, &IID_ISystemMediaTransportControls, (void **)&media_control_statics ); - todo_wine ok( hr == S_OK || broken(hr == 0x80070578) /* Win8 */, "got hr %#lx.\n", hr ); - if (media_control_statics) ISystemMediaTransportControls_Release( media_control_statics ); + ok( hr == S_OK || broken(hr == 0x80070578) /* Win8 */, "got hr %#lx.\n", hr ); + if (!media_control_statics) goto done;
+ ref = ISystemMediaTransportControls_Release( media_control_statics ); + ok( ref == 1 || broken(ref == 3) /* Win10 1507 */ || broken(ref == 2) /* Win10 1607 */, "got ref %ld.\n", ref ); +done: DestroyWindow( window ); ref = ISystemMediaTransportControlsInterop_Release( media_control_interop_statics ); ok( ref == 2, "got ref %ld.\n", ref );
From: Mohamad Al-Jaf mohamadaljaf@gmail.com
--- .../tests/mediacontrol.c | 44 +++++++++++++++++++ 1 file changed, 44 insertions(+)
diff --git a/dlls/windows.media.mediacontrol/tests/mediacontrol.c b/dlls/windows.media.mediacontrol/tests/mediacontrol.c index b97340f2bff..45695fe5432 100644 --- a/dlls/windows.media.mediacontrol/tests/mediacontrol.c +++ b/dlls/windows.media.mediacontrol/tests/mediacontrol.c @@ -63,6 +63,7 @@ static void test_MediaControlStatics(void) ISystemMediaTransportControls *media_control_statics = NULL; IActivationFactory *factory; HWND window = NULL; + BOOLEAN value; HSTRING str; HRESULT hr; LONG ref; @@ -102,6 +103,49 @@ static void test_MediaControlStatics(void) ok( hr == S_OK || broken(hr == 0x80070578) /* Win8 */, "got hr %#lx.\n", hr ); if (!media_control_statics) goto done;
+ hr = ISystemMediaTransportControls_put_PlaybackStatus( media_control_statics, -1 ); + todo_wine ok( hr == E_INVALIDARG, "got hr %#lx.\n", hr ); + hr = ISystemMediaTransportControls_put_PlaybackStatus( media_control_statics, 5 ); + todo_wine ok( hr == E_INVALIDARG, "got hr %#lx.\n", hr ); + hr = ISystemMediaTransportControls_put_PlaybackStatus( media_control_statics, MediaPlaybackStatus_Closed ); + todo_wine ok( hr == S_OK || broken(hr == S_FALSE) /* Win10 1507,1607 */, "got hr %#lx.\n", hr ); + + hr = ISystemMediaTransportControls_put_IsPlayEnabled( media_control_statics, FALSE ); + todo_wine ok( hr == S_OK || broken(hr == S_FALSE) /* Win10 1507,1607 */, "got hr %#lx.\n", hr ); + hr = ISystemMediaTransportControls_put_IsPauseEnabled( media_control_statics, FALSE ); + todo_wine ok( hr == S_OK || broken(hr == S_FALSE) /* Win10 1507,1607 */, "got hr %#lx.\n", hr ); + hr = ISystemMediaTransportControls_put_IsPreviousEnabled( media_control_statics, FALSE ); + todo_wine ok( hr == S_OK || broken(hr == S_FALSE) /* Win10 1507,1607 */, "got hr %#lx.\n", hr ); + hr = ISystemMediaTransportControls_put_IsNextEnabled( media_control_statics, FALSE ); + todo_wine ok( hr == S_OK || broken(hr == S_FALSE) /* Win10 1507,1607 */, "got hr %#lx.\n", hr ); + hr = ISystemMediaTransportControls_put_IsEnabled( media_control_statics, FALSE ); + todo_wine ok( hr == S_OK, "got hr %#lx.\n", hr ); + + value = TRUE; + hr = ISystemMediaTransportControls_get_IsPlayEnabled( media_control_statics, &value ); + todo_wine ok( hr == S_OK, "got hr %#lx.\n", hr ); + todo_wine ok( value == FALSE, "got value %d.\n", value ); + + value = TRUE; + hr = ISystemMediaTransportControls_get_IsPauseEnabled( media_control_statics, &value ); + todo_wine ok( hr == S_OK, "got hr %#lx.\n", hr ); + todo_wine ok( value == FALSE, "got value %d.\n", value ); + + value = TRUE; + hr = ISystemMediaTransportControls_get_IsPreviousEnabled( media_control_statics, &value ); + todo_wine ok( hr == S_OK, "got hr %#lx.\n", hr ); + todo_wine ok( value == FALSE, "got value %d.\n", value ); + + value = TRUE; + hr = ISystemMediaTransportControls_get_IsNextEnabled( media_control_statics, &value ); + todo_wine ok( hr == S_OK, "got hr %#lx.\n", hr ); + todo_wine ok( value == FALSE, "got value %d.\n", value ); + + value = TRUE; + hr = ISystemMediaTransportControls_get_IsEnabled( media_control_statics, &value ); + todo_wine ok( hr == S_OK, "got hr %#lx.\n", hr ); + todo_wine ok( value == FALSE, "got value %d.\n", value ); + ref = ISystemMediaTransportControls_Release( media_control_statics ); ok( ref == 1 || broken(ref == 3) /* Win10 1507 */ || broken(ref == 2) /* Win10 1607 */, "got ref %ld.\n", ref ); done:
From: Mohamad Al-Jaf mohamadaljaf@gmail.com
Called by Roon. --- dlls/windows.media.mediacontrol/main.c | 103 ++++++++++++++---- .../tests/mediacontrol.c | 36 +++--- 2 files changed, 97 insertions(+), 42 deletions(-)
diff --git a/dlls/windows.media.mediacontrol/main.c b/dlls/windows.media.mediacontrol/main.c index 8c17ccbe4df..b052ef5dda3 100644 --- a/dlls/windows.media.mediacontrol/main.c +++ b/dlls/windows.media.mediacontrol/main.c @@ -123,6 +123,12 @@ struct media_control LONG ref;
HWND window; + MediaPlaybackStatus media_playback_status; + boolean is_play_enabled; + boolean is_pause_enabled; + boolean is_previous_enabled; + boolean is_next_enabled; + boolean is_enabled; };
static inline struct media_control *impl_from_ISystemMediaTransportControls( ISystemMediaTransportControls *iface ) @@ -190,14 +196,23 @@ static HRESULT WINAPI media_control_GetTrustLevel( ISystemMediaTransportControls
static HRESULT WINAPI media_control_get_PlaybackStatus( ISystemMediaTransportControls *iface, MediaPlaybackStatus *value ) { - FIXME( "iface %p, value %p stub!\n", iface, value ); - return E_NOTIMPL; + struct media_control *impl = impl_from_ISystemMediaTransportControls( iface ); + + TRACE( "iface %p, value %p\n", iface, value ); + + *value = impl->media_playback_status; + return S_OK; }
static HRESULT WINAPI media_control_put_PlaybackStatus( ISystemMediaTransportControls *iface, MediaPlaybackStatus value ) { - FIXME( "iface %p, value %d stub!\n", iface, value ); - return E_NOTIMPL; + struct media_control *impl = impl_from_ISystemMediaTransportControls( iface ); + + TRACE( "iface %p, value %d\n", iface, value ); + + if (value < MediaPlaybackStatus_Closed || value > MediaPlaybackStatus_Paused) return E_INVALIDARG; + impl->media_playback_status = value; + return S_OK; }
static HRESULT WINAPI media_control_get_DisplayUpdater( ISystemMediaTransportControls *iface, __x_ABI_CWindows_CMedia_CISystemMediaTransportControlsDisplayUpdater **value ) @@ -214,26 +229,42 @@ static HRESULT WINAPI media_control_get_SoundLevel( ISystemMediaTransportControl
static HRESULT WINAPI media_control_get_IsEnabled( ISystemMediaTransportControls *iface, boolean *value ) { - FIXME( "iface %p, value %p stub!\n", iface, value ); - return E_NOTIMPL; + struct media_control *impl = impl_from_ISystemMediaTransportControls( iface ); + + TRACE( "iface %p, value %p\n", iface, value ); + + *value = impl->is_enabled; + return S_OK; }
static HRESULT WINAPI media_control_put_IsEnabled( ISystemMediaTransportControls *iface, boolean value ) { - FIXME( "iface %p, value %d stub!\n", iface, value ); - return E_NOTIMPL; + struct media_control *impl = impl_from_ISystemMediaTransportControls( iface ); + + TRACE( "iface %p, value %d\n", iface, value ); + + impl->is_enabled = value; + return S_OK; }
static HRESULT WINAPI media_control_get_IsPlayEnabled( ISystemMediaTransportControls *iface, boolean *value ) { - FIXME( "iface %p, value %p stub!\n", iface, value ); - return E_NOTIMPL; + struct media_control *impl = impl_from_ISystemMediaTransportControls( iface ); + + TRACE( "iface %p, value %p\n", iface, value ); + + *value = impl->is_play_enabled; + return S_OK; }
static HRESULT WINAPI media_control_put_IsPlayEnabled( ISystemMediaTransportControls *iface, boolean value ) { - FIXME( "iface %p, value %d stub!\n", iface, value ); - return E_NOTIMPL; + struct media_control *impl = impl_from_ISystemMediaTransportControls( iface ); + + TRACE( "iface %p, value %d\n", iface, value ); + + impl->is_play_enabled = value; + return S_OK; }
static HRESULT WINAPI media_control_get_IsStopEnabled( ISystemMediaTransportControls *iface, boolean *value ) @@ -250,14 +281,22 @@ static HRESULT WINAPI media_control_put_IsStopEnabled( ISystemMediaTransportCont
static HRESULT WINAPI media_control_get_IsPauseEnabled( ISystemMediaTransportControls *iface, boolean *value ) { - FIXME( "iface %p, value %p stub!\n", iface, value ); - return E_NOTIMPL; + struct media_control *impl = impl_from_ISystemMediaTransportControls( iface ); + + TRACE( "iface %p, value %p\n", iface, value ); + + *value = impl->is_pause_enabled; + return S_OK; }
static HRESULT WINAPI media_control_put_IsPauseEnabled( ISystemMediaTransportControls *iface, boolean value ) { - FIXME( "iface %p, value %d stub!\n", iface, value ); - return E_NOTIMPL; + struct media_control *impl = impl_from_ISystemMediaTransportControls( iface ); + + TRACE( "iface %p, value %d\n", iface, value ); + + impl->is_pause_enabled = value; + return S_OK; }
static HRESULT WINAPI media_control_get_IsRecordEnabled( ISystemMediaTransportControls *iface, boolean *value ) @@ -298,26 +337,42 @@ static HRESULT WINAPI media_control_put_IsRewindEnabled( ISystemMediaTransportCo
static HRESULT WINAPI media_control_get_IsPreviousEnabled( ISystemMediaTransportControls *iface, boolean *value ) { - FIXME( "iface %p, value %p stub!\n", iface, value ); - return E_NOTIMPL; + struct media_control *impl = impl_from_ISystemMediaTransportControls( iface ); + + TRACE( "iface %p, value %p\n", iface, value ); + + *value = impl->is_previous_enabled; + return S_OK; }
static HRESULT WINAPI media_control_put_IsPreviousEnabled( ISystemMediaTransportControls *iface, boolean value ) { - FIXME( "iface %p, value %d stub!\n", iface, value ); - return E_NOTIMPL; + struct media_control *impl = impl_from_ISystemMediaTransportControls( iface ); + + TRACE( "iface %p, value %d\n", iface, value ); + + impl->is_previous_enabled = value; + return S_OK; }
static HRESULT WINAPI media_control_get_IsNextEnabled( ISystemMediaTransportControls *iface, boolean *value ) { - FIXME( "iface %p, value %p stub!\n", iface, value ); - return E_NOTIMPL; + struct media_control *impl = impl_from_ISystemMediaTransportControls( iface ); + + TRACE( "iface %p, value %p\n", iface, value ); + + *value = impl->is_next_enabled; + return S_OK; }
static HRESULT WINAPI media_control_put_IsNextEnabled( ISystemMediaTransportControls *iface, boolean value ) { - FIXME( "iface %p, value %d stub!\n", iface, value ); - return E_NOTIMPL; + struct media_control *impl = impl_from_ISystemMediaTransportControls( iface ); + + TRACE( "iface %p, value %d\n", iface, value ); + + impl->is_next_enabled = value; + return S_OK; }
static HRESULT WINAPI media_control_get_IsChannelUpEnabled( ISystemMediaTransportControls *iface, boolean *value ) diff --git a/dlls/windows.media.mediacontrol/tests/mediacontrol.c b/dlls/windows.media.mediacontrol/tests/mediacontrol.c index 45695fe5432..a714cb84b44 100644 --- a/dlls/windows.media.mediacontrol/tests/mediacontrol.c +++ b/dlls/windows.media.mediacontrol/tests/mediacontrol.c @@ -104,47 +104,47 @@ static void test_MediaControlStatics(void) if (!media_control_statics) goto done;
hr = ISystemMediaTransportControls_put_PlaybackStatus( media_control_statics, -1 ); - todo_wine ok( hr == E_INVALIDARG, "got hr %#lx.\n", hr ); + ok( hr == E_INVALIDARG, "got hr %#lx.\n", hr ); hr = ISystemMediaTransportControls_put_PlaybackStatus( media_control_statics, 5 ); - todo_wine ok( hr == E_INVALIDARG, "got hr %#lx.\n", hr ); + ok( hr == E_INVALIDARG, "got hr %#lx.\n", hr ); hr = ISystemMediaTransportControls_put_PlaybackStatus( media_control_statics, MediaPlaybackStatus_Closed ); - todo_wine ok( hr == S_OK || broken(hr == S_FALSE) /* Win10 1507,1607 */, "got hr %#lx.\n", hr ); + ok( hr == S_OK || broken(hr == S_FALSE) /* Win10 1507,1607 */, "got hr %#lx.\n", hr );
hr = ISystemMediaTransportControls_put_IsPlayEnabled( media_control_statics, FALSE ); - todo_wine ok( hr == S_OK || broken(hr == S_FALSE) /* Win10 1507,1607 */, "got hr %#lx.\n", hr ); + ok( hr == S_OK || broken(hr == S_FALSE) /* Win10 1507,1607 */, "got hr %#lx.\n", hr ); hr = ISystemMediaTransportControls_put_IsPauseEnabled( media_control_statics, FALSE ); - todo_wine ok( hr == S_OK || broken(hr == S_FALSE) /* Win10 1507,1607 */, "got hr %#lx.\n", hr ); + ok( hr == S_OK || broken(hr == S_FALSE) /* Win10 1507,1607 */, "got hr %#lx.\n", hr ); hr = ISystemMediaTransportControls_put_IsPreviousEnabled( media_control_statics, FALSE ); - todo_wine ok( hr == S_OK || broken(hr == S_FALSE) /* Win10 1507,1607 */, "got hr %#lx.\n", hr ); + ok( hr == S_OK || broken(hr == S_FALSE) /* Win10 1507,1607 */, "got hr %#lx.\n", hr ); hr = ISystemMediaTransportControls_put_IsNextEnabled( media_control_statics, FALSE ); - todo_wine ok( hr == S_OK || broken(hr == S_FALSE) /* Win10 1507,1607 */, "got hr %#lx.\n", hr ); + ok( hr == S_OK || broken(hr == S_FALSE) /* Win10 1507,1607 */, "got hr %#lx.\n", hr ); hr = ISystemMediaTransportControls_put_IsEnabled( media_control_statics, FALSE ); - todo_wine ok( hr == S_OK, "got hr %#lx.\n", hr ); + ok( hr == S_OK, "got hr %#lx.\n", hr );
value = TRUE; hr = ISystemMediaTransportControls_get_IsPlayEnabled( media_control_statics, &value ); - todo_wine ok( hr == S_OK, "got hr %#lx.\n", hr ); - todo_wine ok( value == FALSE, "got value %d.\n", value ); + ok( hr == S_OK, "got hr %#lx.\n", hr ); + ok( value == FALSE, "got value %d.\n", value );
value = TRUE; hr = ISystemMediaTransportControls_get_IsPauseEnabled( media_control_statics, &value ); - todo_wine ok( hr == S_OK, "got hr %#lx.\n", hr ); - todo_wine ok( value == FALSE, "got value %d.\n", value ); + ok( hr == S_OK, "got hr %#lx.\n", hr ); + ok( value == FALSE, "got value %d.\n", value );
value = TRUE; hr = ISystemMediaTransportControls_get_IsPreviousEnabled( media_control_statics, &value ); - todo_wine ok( hr == S_OK, "got hr %#lx.\n", hr ); - todo_wine ok( value == FALSE, "got value %d.\n", value ); + ok( hr == S_OK, "got hr %#lx.\n", hr ); + ok( value == FALSE, "got value %d.\n", value );
value = TRUE; hr = ISystemMediaTransportControls_get_IsNextEnabled( media_control_statics, &value ); - todo_wine ok( hr == S_OK, "got hr %#lx.\n", hr ); - todo_wine ok( value == FALSE, "got value %d.\n", value ); + ok( hr == S_OK, "got hr %#lx.\n", hr ); + ok( value == FALSE, "got value %d.\n", value );
value = TRUE; hr = ISystemMediaTransportControls_get_IsEnabled( media_control_statics, &value ); - todo_wine ok( hr == S_OK, "got hr %#lx.\n", hr ); - todo_wine ok( value == FALSE, "got value %d.\n", value ); + ok( hr == S_OK, "got hr %#lx.\n", hr ); + ok( value == FALSE, "got value %d.\n", value );
ref = ISystemMediaTransportControls_Release( media_control_statics ); ok( ref == 1 || broken(ref == 3) /* Win10 1507 */ || broken(ref == 2) /* Win10 1607 */, "got ref %ld.\n", ref );
On Thu Oct 5 04:22:00 2023 +0000, Mohamad Al-Jaf wrote:
changed this line in [version 3 of the diff](/wine/wine/-/merge_requests/3993/diffs?diff_id=73955&start_sha=4f760fd159f97150f39db192ac645a2545ab607e#5e9af6ce750d12df25e936b03f914b533e8b0cf1_494_487)
Yeah, this looks like the right way to do it. I added some tests to check for the common interfaces and it does look like it uses `QueryInterface`.
On Mon Oct 2 17:10:50 2023 +0000, Rémi Bernon wrote:
Maybe better to keep the `FIXME` and change them to "semi-stub", because this doesn't really do anything (unless you have a plan to make them do something useful shortly).
Aren't these methods just properties that get and set the values that are passed to them? Are you referring to the media control? I think that's implemented in the MediaPlayer class. This class seems to mainly house the properties of the media so that MediaPlayer can populate and update the UI. It looks like function that handles updating the UI is `ISystemMediaTransportControlsDisplayUpdater::Update()`, which Roon calls.
Also, this class can be used with custom media players just to keep track of the properties.
One last thing, there's a lot of properties that Roon calls, I don't think it's particularly helpful to keep them as `FIXME`, but it's your call.
This merge request was approved by Rémi Bernon.
On Thu Oct 5 07:51:50 2023 +0000, Mohamad Al-Jaf wrote:
Aren't these methods just properties that get and set the values that are passed to them? Are you referring to the media control? I think that's implemented in the MediaPlayer class. This class seems to mainly house the properties of the media so that MediaPlayer can populate and update the UI. It looks like function that handles updating the UI is `ISystemMediaTransportControlsDisplayUpdater::Update()`, which Roon calls. Also, this class can be used with custom media players just to keep track of the properties. One last thing, there's a lot of properties that Roon calls, I don't think it's particularly helpful to keep them as `FIXME`, but it's your call.
I thought maybe setting the properties could trigger something more than just storing the value but it probably doesn't matter too much.