1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* This Source Code Form is subject to the terms of the Mozilla Public
3  * License, v. 2.0. If a copy of the MPL was not distributed with this
4  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
5 
6 #ifndef WIDGET_WINDOWS_WINDOWSSTMCPROVIDER_H_
7 #define WIDGET_WINDOWS_WINDOWSSTMCPROVIDER_H_
8 
9 #ifndef __MINGW32__
10 
11 #  include <functional>
12 #  include <Windows.Media.h>
13 #  include <wrl.h>
14 
15 #  include "mozilla/dom/FetchImageHelper.h"
16 #  include "mozilla/dom/MediaController.h"
17 #  include "mozilla/dom/MediaControlKeySource.h"
18 #  include "mozilla/UniquePtr.h"
19 
20 using ISMTC = ABI::Windows::Media::ISystemMediaTransportControls;
21 using SMTCProperty = ABI::Windows::Media::SystemMediaTransportControlsProperty;
22 using ISMTCDisplayUpdater =
23     ABI::Windows::Media::ISystemMediaTransportControlsDisplayUpdater;
24 
25 using ABI::Windows::Foundation::IAsyncOperation;
26 using ABI::Windows::Storage::Streams::IDataWriter;
27 using ABI::Windows::Storage::Streams::IRandomAccessStream;
28 using ABI::Windows::Storage::Streams::IRandomAccessStreamReference;
29 using Microsoft::WRL::ComPtr;
30 
31 class WindowsSMTCProvider final : public mozilla::dom::MediaControlKeySource {
32   NS_INLINE_DECL_THREADSAFE_REFCOUNTING(WindowsSMTCProvider, override)
33 
34  public:
35   WindowsSMTCProvider();
36 
37   bool IsOpened() const override;
38   bool Open() override;
39   void Close() override;
40 
41   void SetPlaybackState(
42       mozilla::dom::MediaSessionPlaybackState aState) override;
43 
44   void SetMediaMetadata(
45       const mozilla::dom::MediaMetadataBase& aMetadata) override;
46 
47   void SetSupportedMediaKeys(const MediaKeysArray& aSupportedKeys) override;
48 
49  private:
50   ~WindowsSMTCProvider();
51   void UnregisterEvents();
52   bool RegisterEvents();
53 
54   void OnButtonPressed(mozilla::dom::MediaControlKey aKey) const;
55   // Enable the SMTC interface
56   bool EnableControl(bool aEnabled) const;
57   // Sets the play, pause, next, previous buttons on the SMTC interface by
58   // mSupportedKeys
59   bool UpdateButtons() const;
60   bool IsKeySupported(mozilla::dom::MediaControlKey aKey) const;
61   bool EnableKey(mozilla::dom::MediaControlKey aKey, bool aEnable) const;
62 
63   bool InitDisplayAndControls();
64 
65   // Sets the Metadata for the currently playing media and sets the playback
66   // type to "MUSIC"
67   bool SetMusicMetadata(const wchar_t* aArtist, const wchar_t* aTitle,
68                         const wchar_t* aAlbumArtist);
69 
70   // Sets one of the artwork to the SMTC interface asynchronously
71   void LoadThumbnail(const nsTArray<mozilla::dom::MediaImage>& aArtwork);
72   // Stores the image at index aIndex of the mArtwork to the Thumbnail
73   // asynchronously
74   void LoadImageAtIndex(const size_t aIndex);
75   // Stores the raw binary data of an image to mImageStream and set it to the
76   // Thumbnail asynchronously
77   void LoadImage(const char* aImageData, uint32_t aDataSize);
78   // Sets the Thumbnail to the image stored in mImageStream
79   bool SetThumbnail(const nsAString& aUrl);
80   void ClearThumbnail();
81 
82   bool UpdateThumbnail(const nsAString& aUrl);
83   void CancelPendingStoreAsyncOperation() const;
84 
85   void ClearMetadata();
86 
87   bool mInitialized = false;
88 
89   // A bit table indicating what keys are enabled
90   uint32_t mSupportedKeys = 0;
91 
92   ComPtr<ISMTC> mControls;
93   ComPtr<ISMTCDisplayUpdater> mDisplay;
94 
95   // Use mImageDataWriter to write the binary data of image into mImageStream
96   // and refer the image by mImageStreamReference and then set it to the SMTC
97   // interface
98   ComPtr<IDataWriter> mImageDataWriter;
99   ComPtr<IRandomAccessStream> mImageStream;
100   ComPtr<IRandomAccessStreamReference> mImageStreamReference;
101   ComPtr<IAsyncOperation<unsigned int>> mStoreAsyncOperation;
102 
103   // mThumbnailUrl is the url of the current Thumbnail
104   // mProcessingUrl is the url that is being processed. The process starts from
105   // fetching an image from the url and then storing the fetched image to the
106   // mImageStream. If mProcessingUrl is not empty, it means there is an image is
107   // in processing
108   // mThumbnailUrl and mProcessingUrl won't be set at the same time and they can
109   // only be touched on main thread
110   nsString mThumbnailUrl;
111   nsString mProcessingUrl;
112 
113   // mArtwork can only be used in main thread in case of data racing
114   CopyableTArray<mozilla::dom::MediaImage> mArtwork;
115   size_t mNextImageIndex;
116 
117   mozilla::UniquePtr<mozilla::dom::FetchImageHelper> mImageFetcher;
118   mozilla::MozPromiseRequestHolder<mozilla::dom::ImagePromise>
119       mImageFetchRequest;
120 
121   HWND mWindow;  // handle to the invisible window
122 
123   // EventRegistrationTokens are used to have a handle on a callback (to remove
124   // it again)
125   EventRegistrationToken mButtonPressedToken;
126 };
127 
128 #endif  // __MINGW32__
129 #endif  // WIDGET_WINDOWS_WINDOWSSTMCPROVIDER_H_
130