forked from mirrors/gecko-dev
		
	 3e316137c4
			
		
	
	
		3e316137c4
		
	
	
	
	
		
			
			The DesktopEntry property allows MPRIS clients to match a player on the bus with application metadata such as its icon. The desktop entry name is computed as the lowercasing of the XRE app info name. This is the same way it's done for g_set_prgname in nsAppRunner. Differential Revision: https://phabricator.services.mozilla.com/D96327
		
			
				
	
	
		
			188 lines
		
	
	
	
		
			6.7 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			188 lines
		
	
	
	
		
			6.7 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
| /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
 | |
|  *
 | |
|  * This Source Code Form is subject to the terms of the Mozilla Public
 | |
|  * License, v. 2.0. If a copy of the MPL was not distributed with this
 | |
|  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 | |
| 
 | |
| #ifndef WIDGET_GTK_MPRIS_SERVICE_HANDLER_H_
 | |
| #define WIDGET_GTK_MPRIS_SERVICE_HANDLER_H_
 | |
| 
 | |
| #include <gio/gio.h>
 | |
| #include "mozilla/dom/FetchImageHelper.h"
 | |
| #include "mozilla/dom/MediaControlKeySource.h"
 | |
| #include "mozilla/Attributes.h"
 | |
| #include "mozilla/UniquePtr.h"
 | |
| #include "nsIFile.h"
 | |
| #include "nsMimeTypes.h"
 | |
| #include "nsString.h"
 | |
| 
 | |
| #define DBUS_MPRIS_SERVICE_NAME "org.mpris.MediaPlayer2.firefox"
 | |
| #define DBUS_MPRIS_OBJECT_PATH "/org/mpris/MediaPlayer2"
 | |
| #define DBUS_MPRIS_INTERFACE "org.mpris.MediaPlayer2"
 | |
| #define DBUS_MPRIS_PLAYER_INTERFACE "org.mpris.MediaPlayer2.Player"
 | |
| #define DBUS_MPRIS_TRACK_PATH "/org/mpris/MediaPlayer2/firefox"
 | |
| 
 | |
| namespace mozilla {
 | |
| namespace widget {
 | |
| 
 | |
| /**
 | |
|  * This class implements the "MPRIS" D-Bus Service
 | |
|  * (https://specifications.freedesktop.org/mpris-spec/2.2),
 | |
|  * which is used to communicate with the Desktop Environment about the
 | |
|  * Multimedia playing in Gecko.
 | |
|  * Note that this interface requires many methods which may not be supported by
 | |
|  * Gecko, the interface
 | |
|  * however provides CanXYZ properties for these methods, so the method is
 | |
|  * defined but won't be executed.
 | |
|  *
 | |
|  * Also note that the following defines are for parts that the MPRIS Spec
 | |
|  * defines optional. The code won't
 | |
|  * compile with any of the defines set, yet, as those aren't implemented yet and
 | |
|  * probably never will be of
 | |
|  * use for gecko. For sake of completeness, they have been added until the
 | |
|  * decision about their implementation
 | |
|  * is finally made.
 | |
|  *
 | |
|  * The constexpr'ed methods are capabilities of the user agent known at compile
 | |
|  * time, e.g. we decided at
 | |
|  * compile time whether we ever want to support closing the user agent via MPRIS
 | |
|  * (Quit() and CanQuit()).
 | |
|  *
 | |
|  * Other properties like CanPlay() might depend on the runtime state (is there
 | |
|  * media available for playback?)
 | |
|  * and thus aren't a constexpr but merely a const method.
 | |
|  */
 | |
| class MPRISServiceHandler final : public dom::MediaControlKeySource {
 | |
|   NS_INLINE_DECL_REFCOUNTING(MPRISServiceHandler, override)
 | |
|  public:
 | |
|   // Note that this constructor does NOT initialize the MPRIS Service but only
 | |
|   // this class. The method Open() is responsible for registering and MAY FAIL.
 | |
| 
 | |
|   // The image format used in MPRIS is based on the mMimeType here. Although
 | |
|   // IMAGE_JPEG or IMAGE_BMP are valid types as well but a png image with
 | |
|   // transparent background will be converted into a jpeg/bmp file with a
 | |
|   // colored background IMAGE_PNG format seems to be the best choice for now.
 | |
|   MPRISServiceHandler() : mMimeType(IMAGE_PNG){};
 | |
|   bool Open() override;
 | |
|   void Close() override;
 | |
|   bool IsOpened() const override;
 | |
| 
 | |
|   // From the EventSource.
 | |
|   void SetPlaybackState(dom::MediaSessionPlaybackState aState) override;
 | |
| 
 | |
|   // GetPlaybackState returns dom::PlaybackState. GetPlaybackStatus returns this
 | |
|   // state converted into d-bus variants.
 | |
|   GVariant* GetPlaybackStatus() const;
 | |
| 
 | |
|   const char* Identity() const;
 | |
|   const char* DesktopEntry() const;
 | |
|   bool PressKey(dom::MediaControlKey aKey) const;
 | |
| 
 | |
|   void SetMediaMetadata(const dom::MediaMetadataBase& aMetadata) override;
 | |
|   GVariant* GetMetadataAsGVariant() const;
 | |
| 
 | |
|   void SetSupportedMediaKeys(const MediaKeysArray& aSupportedKeys) override;
 | |
| 
 | |
|   bool IsMediaKeySupported(dom::MediaControlKey aKey) const;
 | |
| 
 | |
|  private:
 | |
|   ~MPRISServiceHandler();
 | |
| 
 | |
|   // Note: Registration Ids for the D-Bus start with 1, so a value of 0
 | |
|   // indicates an error (or an object which wasn't initialized yet)
 | |
| 
 | |
|   // a handle to our bus registration/ownership
 | |
|   guint mOwnerId = 0;
 | |
|   // This is for the interface org.mpris.MediaPlayer2
 | |
|   guint mRootRegistrationId = 0;
 | |
|   // This is for the interface org.mpris.MediaPlayer2.Player
 | |
|   guint mPlayerRegistrationId = 0;
 | |
|   GDBusNodeInfo* mIntrospectionData = nullptr;
 | |
|   GDBusConnection* mConnection = nullptr;
 | |
|   bool mInitialized = false;
 | |
|   nsAutoCString mIdentity;
 | |
|   nsAutoCString mDesktopEntry;
 | |
| 
 | |
|   nsCString mMimeType;
 | |
| 
 | |
|   // A bitmask indicating what keys are enabled
 | |
|   uint32_t mSupportedKeys = 0;
 | |
| 
 | |
|   class MPRISMetadata : public dom::MediaMetadataBase {
 | |
|    public:
 | |
|     MPRISMetadata() = default;
 | |
|     ~MPRISMetadata() = default;
 | |
| 
 | |
|     void UpdateFromMetadataBase(const dom::MediaMetadataBase& aMetadata) {
 | |
|       mTitle = aMetadata.mTitle;
 | |
|       mArtist = aMetadata.mArtist;
 | |
|       mAlbum = aMetadata.mAlbum;
 | |
|       mArtwork = aMetadata.mArtwork;
 | |
|     }
 | |
|     void Clear() {
 | |
|       UpdateFromMetadataBase(MediaMetadataBase::EmptyData());
 | |
|       mArtUrl.Truncate();
 | |
|     }
 | |
| 
 | |
|     nsCString mArtUrl;
 | |
|   };
 | |
|   MPRISMetadata mMPRISMetadata;
 | |
| 
 | |
|   // The saved image file fetched from the URL
 | |
|   nsCOMPtr<nsIFile> mLocalImageFile;
 | |
|   nsCOMPtr<nsIFile> mLocalImageFolder;
 | |
| 
 | |
|   mozilla::UniquePtr<mozilla::dom::FetchImageHelper> mImageFetcher;
 | |
|   mozilla::MozPromiseRequestHolder<mozilla::dom::ImagePromise>
 | |
|       mImageFetchRequest;
 | |
| 
 | |
|   nsString mFetchingUrl;
 | |
|   nsString mCurrentImageUrl;
 | |
| 
 | |
|   size_t mNextImageIndex = 0;
 | |
| 
 | |
|   // Load the image at index aIndex of the metadta's artwork to MPRIS
 | |
|   // asynchronously
 | |
|   void LoadImageAtIndex(const size_t aIndex);
 | |
|   bool SetImageToDisplay(const char* aImageData, uint32_t aDataSize);
 | |
| 
 | |
|   bool RenewLocalImageFile(const char* aImageData, uint32_t aDataSize);
 | |
|   bool InitLocalImageFile();
 | |
|   bool InitLocalImageFolder();
 | |
|   void RemoveAllLocalImages();
 | |
|   bool LocalImageFolderExists();
 | |
| 
 | |
|   // Queries nsAppInfo to get the branded browser name and vendor
 | |
|   void InitIdentity();
 | |
| 
 | |
|   // non-public API, called from events
 | |
|   void OnNameAcquired(GDBusConnection* aConnection, const gchar* aName);
 | |
|   void OnNameLost(GDBusConnection* aConnection, const gchar* aName);
 | |
|   void OnBusAcquired(GDBusConnection* aConnection, const gchar* aName);
 | |
| 
 | |
|   static void OnNameAcquiredStatic(GDBusConnection* aConnection,
 | |
|                                    const gchar* aName, gpointer aUserData);
 | |
|   static void OnNameLostStatic(GDBusConnection* aConnection, const gchar* aName,
 | |
|                                gpointer aUserData);
 | |
|   static void OnBusAcquiredStatic(GDBusConnection* aConnection,
 | |
|                                   const gchar* aName, gpointer aUserData);
 | |
| 
 | |
|   void EmitEvent(dom::MediaControlKey aKey) const;
 | |
| 
 | |
|   bool EmitMetadataChanged() const;
 | |
| 
 | |
|   void SetMediaMetadataInternal(const dom::MediaMetadataBase& aMetadata,
 | |
|                                 bool aClearArtUrl = true);
 | |
| 
 | |
|   bool EmitSupportedKeyChanged(mozilla::dom::MediaControlKey aKey,
 | |
|                                bool aSupported) const;
 | |
| 
 | |
|   bool EmitPropertiesChangedSignal(GVariant* aParameters) const;
 | |
| 
 | |
|   void ClearMetadata();
 | |
| };
 | |
| 
 | |
| }  // namespace widget
 | |
| }  // namespace mozilla
 | |
| 
 | |
| #endif  // WIDGET_GTK_MPRIS_SERVICE_HANDLER_H_
 |