Bug 1623971 - P16: Add a method to set image to SMTC thumbnail r=alwu,thomasmo

Add a method to set an image to SMTC's thumbmail asynchronously

Differential Revision: https://phabricator.services.mozilla.com/D77892
This commit is contained in:
Chun-Min Chang 2020-06-19 00:21:13 +00:00
Родитель da1eff4bed
Коммит b0686b64ff
2 изменённых файлов: 138 добавлений и 43 удалений

Просмотреть файл

@ -25,6 +25,7 @@
using namespace ABI::Windows::Foundation;
using namespace ABI::Windows::Media;
using namespace ABI::Windows::Storage::Streams;
using namespace Microsoft::WRL;
using namespace Microsoft::WRL::Wrappers;
using namespace mozilla;
@ -196,6 +197,7 @@ void WindowsSMTCProvider::SetMediaMetadata(
SetMusicMetadata(aMetadata.mArtist.get(), aMetadata.mTitle.get(),
aMetadata.mAlbum.get());
RefreshDisplay();
LoadThumbnail(aMetadata.mArtwork);
}
void WindowsSMTCProvider::UnregisterEvents() {
@ -346,57 +348,132 @@ bool WindowsSMTCProvider::SetMusicMetadata(const wchar_t* aArtist,
return true;
}
bool WindowsSMTCProvider::SetThumbnail(const wchar_t* aUrl) {
void WindowsSMTCProvider::LoadThumbnail(
const nsTArray<mozilla::dom::MediaImage>& aArtwork) {
// TODO: Use FetchImageHelper to fetch one of the image in aArtwork, then set
// it to the thumbnail via LoadImage()
}
void WindowsSMTCProvider::LoadImage(const char* aImageData,
uint32_t aDataSize) {
// 1. Use mImageDataWriter to write the binary data of image into mImageStream
// 2. Refer the image by mImageStreamReference and then set it to the SMTC
// In case of the race condition between they are being destroyed and the
// async operation for image loading, mImageDataWriter, mImageStream, and
// mImageStreamReference are member variables
HRESULT hr = ActivateInstance(
HStringReference(
RuntimeClass_Windows_Storage_Streams_InMemoryRandomAccessStream)
.Get(),
mImageStream.GetAddressOf());
if (FAILED(hr)) {
LOG("Failed to make mImageStream refer to an instance of "
"InMemoryRandomAccessStream");
return;
}
ComPtr<IOutputStream> outputStream;
hr = mImageStream.As(&outputStream);
if (FAILED(hr)) {
LOG("Failed when query IOutputStream interface from mImageStream");
return;
}
ComPtr<IDataWriterFactory> dataWriterFactory;
hr = GetActivationFactory(
HStringReference(RuntimeClass_Windows_Storage_Streams_DataWriter).Get(),
dataWriterFactory.GetAddressOf());
if (FAILED(hr)) {
LOG("Failed to get an activation factory for IDataWriterFactory");
return;
}
hr = dataWriterFactory->CreateDataWriter(outputStream.Get(),
mImageDataWriter.GetAddressOf());
if (FAILED(hr)) {
LOG("Failed to create mImageDataWriter that writes data to mImageStream");
return;
}
hr = mImageDataWriter->WriteBytes(
aDataSize, reinterpret_cast<BYTE*>(const_cast<char*>(aImageData)));
if (FAILED(hr)) {
LOG("Failed to write data to mImageStream");
return;
}
ComPtr<IAsyncOperation<unsigned int>> storeAsyncOperation;
hr = mImageDataWriter->StoreAsync(&storeAsyncOperation);
if (FAILED(hr)) {
LOG("Failed to commit the written data to mImageStream, asynchronously");
return;
}
// Upon the image is stored in mImageStream, set the image to the SMTC
// interface
auto onStoreCompleted = Callback<
IAsyncOperationCompletedHandler<unsigned int>>(
[this, self = RefPtr<WindowsSMTCProvider>(this)](
IAsyncOperation<unsigned int>* aAsyncOp, AsyncStatus aStatus) {
if (aStatus != AsyncStatus::Completed) {
LOG("Asynchronous operation is not completed");
return E_ABORT;
}
IAsyncInfo* asyncInfo;
HRESULT hr = aAsyncOp->QueryInterface(
IID_IAsyncInfo, reinterpret_cast<void**>(&asyncInfo));
if (FAILED(hr)) {
LOG("Failed when query IAsyncInfo from aAsyncOp");
return hr;
}
MOZ_ASSERT(asyncInfo);
asyncInfo->get_ErrorCode(&hr);
if (FAILED(hr)) {
LOG("Failed to get termination status of the asynchronous operation");
return hr;
}
if (!SetThumbnail() || !RefreshDisplay()) {
LOG("Failed to update thumbnail");
}
return S_OK;
});
hr = storeAsyncOperation->put_Completed(onStoreCompleted.Get());
if (FAILED(hr)) {
LOG("Failed to set callback on completeing the asynchronous operation");
}
}
bool WindowsSMTCProvider::SetThumbnail() {
MOZ_ASSERT(mDisplay);
ComPtr<IActivationFactory> streamRefFactory;
MOZ_ASSERT(mImageStream);
ComPtr<IRandomAccessStreamReferenceStatics> streamRefFactory;
HRESULT hr = GetActivationFactory(
HStringReference(
RuntimeClass_Windows_Storage_Streams_RandomAccessStreamReference)
.Get(),
&streamRefFactory);
streamRefFactory.GetAddressOf());
if (FAILED(hr)) {
LOG("SystemMediaTransportControls: Failed at "
"setThumbnail.GetActivationFactory(&StreamRefFactory)");
LOG("Failed to get an activation factory for "
"IRandomAccessStreamReferenceStatics type");
return false;
}
ComPtr<ABI::Windows::Storage::Streams::IRandomAccessStreamReferenceStatics>
streamRefStatic;
hr = streamRefFactory.As(&streamRefStatic);
hr = streamRefFactory->CreateFromStream(mImageStream.Get(),
mImageStreamReference.GetAddressOf());
if (FAILED(hr)) {
LOG("SystemMediaTransportControls: Failed at "
"setThumbnail.StreamRefFactory.As()");
LOG("Failed to create mImageStreamReference from mImageStream");
return false;
}
ComPtr<IUriRuntimeClass> uri;
ComPtr<IUriRuntimeClassFactory> uriFactory;
hr = GetActivationFactory(
HStringReference(RuntimeClass_Windows_Foundation_Uri).Get(), &uriFactory);
if (FAILED(hr)) {
LOG("SystemMediaTransportControls: Failed at "
"setThumbnail.GetActivationFactory(&uriFactory)");
return false;
}
hr = uriFactory->CreateUri(HStringReference(aUrl).Get(), uri.GetAddressOf());
if (FAILED(hr)) {
LOG("SystemMediaTransportControls: Failed at setThumbnail.CreateUri()");
return false;
}
ComPtr<ABI::Windows::Storage::Streams::IRandomAccessStreamReference>
thumbnail;
// When Thumbnail would be a local file: CreateFromFile(file.Get(),
// &streamRef);
hr = streamRefStatic->CreateFromUri(uri.Get(), thumbnail.GetAddressOf());
if (FAILED(hr)) {
LOG("SystemMediaTransportControls: Failed at "
"setThumbnail.CreateFromUri()");
return false;
}
return SUCCEEDED(mDisplay->put_Thumbnail(thumbnail.Get()));
return SUCCEEDED(mDisplay->put_Thumbnail(mImageStreamReference.Get()));
}
#endif // __MINGW32__

Просмотреть файл

@ -20,6 +20,11 @@ using SMTCProperty = ABI::Windows::Media::SystemMediaTransportControlsProperty;
using ISMTCDisplayUpdater =
ABI::Windows::Media::ISystemMediaTransportControlsDisplayUpdater;
using ABI::Windows::Storage::Streams::IDataWriter;
using ABI::Windows::Storage::Streams::IRandomAccessStream;
using ABI::Windows::Storage::Streams::IRandomAccessStreamReference;
using Microsoft::WRL::ComPtr;
struct SMTCControlAttributes {
bool mEnabled;
bool mPlayPauseEnabled;
@ -35,7 +40,7 @@ struct SMTCControlAttributes {
};
class WindowsSMTCProvider final : public mozilla::dom::MediaControlKeySource {
NS_INLINE_DECL_REFCOUNTING(WindowsSMTCProvider, override)
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(WindowsSMTCProvider, override)
public:
WindowsSMTCProvider();
@ -73,13 +78,26 @@ class WindowsSMTCProvider final : public mozilla::dom::MediaControlKeySource {
bool SetMusicMetadata(const wchar_t* aArtist, const wchar_t* aTitle,
const wchar_t* aAlbumArtist);
// Sets the Thumbnail for the currently playing media to the given URL
// Sets one of the artwork to the SMTC interface asynchronously
void LoadThumbnail(const nsTArray<mozilla::dom::MediaImage>& aArtwork);
// Stores the raw binary data of an image to mImageStream and set it to the
// Thumbnail asynchronously
void LoadImage(const char* aImageData, uint32_t aDataSize);
// Sets the Thumbnail to the image stored in mImageStream
// Note: This method does not call update(), you need to do that manually
bool SetThumbnail(const wchar_t* aUrl);
bool SetThumbnail();
bool mInitialized = false;
Microsoft::WRL::ComPtr<ISMTC> mControls;
Microsoft::WRL::ComPtr<ISMTCDisplayUpdater> mDisplay;
ComPtr<ISMTC> mControls;
ComPtr<ISMTCDisplayUpdater> mDisplay;
// Use mImageDataWriter to write the binary data of image into mImageStream
// and refer the image by mImageStreamReference and then set it to the SMTC
// interface
ComPtr<IDataWriter> mImageDataWriter;
ComPtr<IRandomAccessStream> mImageStream;
ComPtr<IRandomAccessStreamReference> mImageStreamReference;
HWND mWindow; // handle to the invisible window
// EventRegistrationTokens are used to have a handle on a callback (to remove