no bug - Bumping Firefox l10n changesets r=release a=l10n-bump DONTBUILD CLOSED TREE
[gecko.git] / widget / gtk / MPRISServiceHandler.h
blob469090efc0282284d679e41d9f003932141c92df
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_
10 #include <gio/gio.h>
11 #include "mozilla/dom/FetchImageHelper.h"
12 #include "mozilla/dom/MediaControlKeySource.h"
13 #include "mozilla/Attributes.h"
14 #include "mozilla/UniquePtr.h"
15 #include "nsIFile.h"
16 #include "nsMimeTypes.h"
17 #include "nsString.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"
25 namespace mozilla {
26 namespace widget {
28 /**
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
44 * is finally made.
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)
57 public:
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();
62 bool Open() override;
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(dom::MediaControlKey aKey) const;
77 void SetMediaMetadata(const dom::MediaMetadataBase& aMetadata) override;
78 GVariant* GetMetadataAsGVariant() const;
80 void SetSupportedMediaKeys(const MediaKeysArray& aSupportedKeys) override;
82 bool IsMediaKeySupported(dom::MediaControlKey aKey) const;
84 void OwnName(GDBusConnection* aConnection);
86 private:
87 ~MPRISServiceHandler();
89 // Note: Registration Ids for the D-Bus start with 1, so a value of 0
90 // indicates an error (or an object which wasn't initialized yet)
92 // a handle to our bus registration/ownership
93 guint mOwnerId = 0;
94 // This is for the interface org.mpris.MediaPlayer2
95 guint mRootRegistrationId = 0;
96 // This is for the interface org.mpris.MediaPlayer2.Player
97 guint mPlayerRegistrationId = 0;
98 RefPtr<GDBusNodeInfo> mIntrospectionData;
99 GDBusConnection* mConnection = nullptr;
100 bool mInitialized = false;
101 nsAutoCString mIdentity;
102 nsAutoCString mDesktopEntry;
104 // The image format used in MPRIS is based on the mMimeType here. Although
105 // IMAGE_JPEG or IMAGE_BMP are valid types as well but a png image with
106 // transparent background will be converted into a jpeg/bmp file with a
107 // colored background IMAGE_PNG format seems to be the best choice for now.
108 nsCString mMimeType{IMAGE_PNG};
110 // A bitmask indicating what keys are enabled
111 uint32_t mSupportedKeys = 0;
113 class MPRISMetadata : public dom::MediaMetadataBase {
114 public:
115 MPRISMetadata() = default;
116 ~MPRISMetadata() = default;
118 void UpdateFromMetadataBase(const dom::MediaMetadataBase& aMetadata) {
119 mTitle = aMetadata.mTitle;
120 mArtist = aMetadata.mArtist;
121 mAlbum = aMetadata.mAlbum;
122 mArtwork = aMetadata.mArtwork;
124 void Clear() {
125 UpdateFromMetadataBase(MediaMetadataBase::EmptyData());
126 mArtUrl.Truncate();
129 nsCString mArtUrl;
131 MPRISMetadata mMPRISMetadata;
133 // The saved image file fetched from the URL
134 nsCOMPtr<nsIFile> mLocalImageFile;
135 nsCOMPtr<nsIFile> mLocalImageFolder;
137 UniquePtr<dom::FetchImageHelper> mImageFetcher;
138 MozPromiseRequestHolder<dom::ImagePromise> mImageFetchRequest;
140 nsString mFetchingUrl;
141 nsString mCurrentImageUrl;
143 size_t mNextImageIndex = 0;
145 // Load the image at index aIndex of the metadta's artwork to MPRIS
146 // asynchronously
147 void LoadImageAtIndex(const size_t aIndex);
148 bool SetImageToDisplay(const char* aImageData, uint32_t aDataSize);
150 bool RenewLocalImageFile(const char* aImageData, uint32_t aDataSize);
151 bool InitLocalImageFile();
152 bool InitLocalImageFolder();
153 void RemoveAllLocalImages();
154 bool LocalImageFolderExists();
156 // Queries nsAppInfo to get the branded browser name and vendor
157 void InitIdentity();
159 // non-public API, called from events
160 void OnNameAcquired(GDBusConnection* aConnection, const gchar* aName);
161 void OnNameLost(GDBusConnection* aConnection, const gchar* aName);
162 void OnBusAcquired(GDBusConnection* aConnection, const gchar* aName);
164 static void OnNameAcquiredStatic(GDBusConnection* aConnection,
165 const gchar* aName, gpointer aUserData);
166 static void OnNameLostStatic(GDBusConnection* aConnection, const gchar* aName,
167 gpointer aUserData);
168 static void OnBusAcquiredStatic(GDBusConnection* aConnection,
169 const gchar* aName, gpointer aUserData);
171 void EmitEvent(dom::MediaControlKey aKey) const;
173 bool EmitMetadataChanged() const;
175 void SetMediaMetadataInternal(const dom::MediaMetadataBase& aMetadata,
176 bool aClearArtUrl = true);
178 bool EmitSupportedKeyChanged(dom::MediaControlKey aKey,
179 bool aSupported) const;
181 bool EmitPropertiesChangedSignal(GVariant* aParameters) const;
183 void ClearMetadata();
185 RefPtr<GCancellable> mDBusGetCancellable;
187 nsCString mServiceName;
188 void SetServiceName(const char* aName);
189 const char* GetServiceName();
192 } // namespace widget
193 } // namespace mozilla
195 #endif // WIDGET_GTK_MPRIS_SERVICE_HANDLER_H_