1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
3 * This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this
5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
7 #ifndef WIDGET_GTK_MPRIS_SERVICE_HANDLER_H_
8 #define WIDGET_GTK_MPRIS_SERVICE_HANDLER_H_
11 #include "mozilla/dom/FetchImageHelper.h"
12 #include "mozilla/dom/MediaControlKeySource.h"
13 #include "mozilla/Attributes.h"
14 #include "mozilla/UniquePtr.h"
16 #include "nsMimeTypes.h"
19 #define DBUS_MPRIS_SERVICE_NAME "org.mpris.MediaPlayer2.firefox"
20 #define DBUS_MPRIS_OBJECT_PATH "/org/mpris/MediaPlayer2"
21 #define DBUS_MPRIS_INTERFACE "org.mpris.MediaPlayer2"
22 #define DBUS_MPRIS_PLAYER_INTERFACE "org.mpris.MediaPlayer2.Player"
23 #define DBUS_MPRIS_TRACK_PATH "/org/mpris/MediaPlayer2/firefox"
29 * This class implements the "MPRIS" D-Bus Service
30 * (https://specifications.freedesktop.org/mpris-spec/2.2),
31 * which is used to communicate with the Desktop Environment about the
32 * Multimedia playing in Gecko.
33 * Note that this interface requires many methods which may not be supported by
34 * Gecko, the interface
35 * however provides CanXYZ properties for these methods, so the method is
36 * defined but won't be executed.
38 * Also note that the following defines are for parts that the MPRIS Spec
39 * defines optional. The code won't
40 * compile with any of the defines set, yet, as those aren't implemented yet and
41 * probably never will be of
42 * use for gecko. For sake of completeness, they have been added until the
43 * decision about their implementation
46 * The constexpr'ed methods are capabilities of the user agent known at compile
47 * time, e.g. we decided at
48 * compile time whether we ever want to support closing the user agent via MPRIS
49 * (Quit() and CanQuit()).
51 * Other properties like CanPlay() might depend on the runtime state (is there
52 * media available for playback?)
53 * and thus aren't a constexpr but merely a const method.
55 class MPRISServiceHandler final
: public dom::MediaControlKeySource
{
56 NS_INLINE_DECL_REFCOUNTING(MPRISServiceHandler
, override
)
58 // Note that this constructor does NOT initialize the MPRIS Service but only
59 // this class. The method Open() is responsible for registering and MAY FAIL.
61 MPRISServiceHandler();
63 void Close() override
;
64 bool IsOpened() const override
;
66 // From the EventSource.
67 void SetPlaybackState(dom::MediaSessionPlaybackState aState
) override
;
69 // GetPlaybackState returns dom::PlaybackState. GetPlaybackStatus returns this
70 // state converted into d-bus variants.
71 GVariant
* GetPlaybackStatus() const;
73 const char* Identity() const;
74 const char* DesktopEntry() const;
75 bool PressKey(const dom::MediaControlAction
& aAction
) const;
77 void SetMediaMetadata(const dom::MediaMetadataBase
& aMetadata
) override
;
78 GVariant
* GetMetadataAsGVariant() const;
80 void SetSupportedMediaKeys(const MediaKeysArray
& aSupportedKeys
) override
;
82 void SetPositionState(const Maybe
<dom::PositionState
>& aState
) override
;
83 double GetPositionSeconds() const;
85 bool IsMediaKeySupported(dom::MediaControlKey aKey
) const;
87 void OwnName(GDBusConnection
* aConnection
);
90 ~MPRISServiceHandler();
92 // Note: Registration Ids for the D-Bus start with 1, so a value of 0
93 // indicates an error (or an object which wasn't initialized yet)
95 // a handle to our bus registration/ownership
97 // This is for the interface org.mpris.MediaPlayer2
98 guint mRootRegistrationId
= 0;
99 // This is for the interface org.mpris.MediaPlayer2.Player
100 guint mPlayerRegistrationId
= 0;
101 RefPtr
<GDBusNodeInfo
> mIntrospectionData
;
102 GDBusConnection
* mConnection
= nullptr;
103 bool mInitialized
= false;
104 nsAutoCString mIdentity
;
105 nsAutoCString mDesktopEntry
;
107 // The image format used in MPRIS is based on the mMimeType here. Although
108 // IMAGE_JPEG or IMAGE_BMP are valid types as well but a png image with
109 // transparent background will be converted into a jpeg/bmp file with a
110 // colored background IMAGE_PNG format seems to be the best choice for now.
111 nsCString mMimeType
{IMAGE_PNG
};
113 // A bitmask indicating what keys are enabled
114 uint32_t mSupportedKeys
= 0;
116 Maybe
<dom::PositionState
> mPositionState
;
118 class MPRISMetadata
: public dom::MediaMetadataBase
{
120 MPRISMetadata() = default;
121 ~MPRISMetadata() = default;
123 void UpdateFromMetadataBase(const dom::MediaMetadataBase
& aMetadata
) {
124 mTitle
= aMetadata
.mTitle
;
125 mArtist
= aMetadata
.mArtist
;
126 mAlbum
= aMetadata
.mAlbum
;
127 mUrl
= aMetadata
.mUrl
;
128 mArtwork
= aMetadata
.mArtwork
;
131 UpdateFromMetadataBase(MediaMetadataBase::EmptyData());
137 MPRISMetadata mMPRISMetadata
;
139 // The saved image file fetched from the URL
140 nsCOMPtr
<nsIFile
> mLocalImageFile
;
141 nsCOMPtr
<nsIFile
> mLocalImageFolder
;
143 UniquePtr
<dom::FetchImageHelper
> mImageFetcher
;
144 MozPromiseRequestHolder
<dom::ImagePromise
> mImageFetchRequest
;
146 nsString mFetchingUrl
;
147 nsString mCurrentImageUrl
;
149 size_t mNextImageIndex
= 0;
151 // Load the image at index aIndex of the metadta's artwork to MPRIS
153 void LoadImageAtIndex(const size_t aIndex
);
154 bool SetImageToDisplay(const char* aImageData
, uint32_t aDataSize
);
156 bool RenewLocalImageFile(const char* aImageData
, uint32_t aDataSize
);
157 bool InitLocalImageFile();
158 bool InitLocalImageFolder();
159 void RemoveAllLocalImages();
160 bool LocalImageFolderExists();
162 // Queries nsAppInfo to get the branded browser name and vendor
165 // non-public API, called from events
166 void OnNameAcquired(GDBusConnection
* aConnection
, const gchar
* aName
);
167 void OnNameLost(GDBusConnection
* aConnection
, const gchar
* aName
);
168 void OnBusAcquired(GDBusConnection
* aConnection
, const gchar
* aName
);
170 static void OnNameAcquiredStatic(GDBusConnection
* aConnection
,
171 const gchar
* aName
, gpointer aUserData
);
172 static void OnNameLostStatic(GDBusConnection
* aConnection
, const gchar
* aName
,
174 static void OnBusAcquiredStatic(GDBusConnection
* aConnection
,
175 const gchar
* aName
, gpointer aUserData
);
177 void EmitEvent(const dom::MediaControlAction
& aAction
) const;
179 bool EmitMetadataChanged() const;
181 void SetMediaMetadataInternal(const dom::MediaMetadataBase
& aMetadata
,
182 bool aClearArtUrl
= true);
184 bool EmitSupportedKeyChanged(dom::MediaControlKey aKey
,
185 bool aSupported
) const;
187 bool EmitPropertiesChangedSignal(GVariant
* aParameters
) const;
189 void ClearMetadata();
191 RefPtr
<GCancellable
> mDBusGetCancellable
;
193 nsCString mServiceName
;
194 void SetServiceName(const char* aName
);
195 const char* GetServiceName();
198 } // namespace widget
199 } // namespace mozilla
201 #endif // WIDGET_GTK_MPRIS_SERVICE_HANDLER_H_