initial MPMedia bridge

This commit is contained in:
zackslash
2023-10-18 23:25:57 +01:00
parent 560c0955ac
commit 944491d133
4 changed files with 142 additions and 0 deletions
+7
View File
@@ -38,6 +38,7 @@ type App struct {
Player *player.Player
UpdateChecker UpdateChecker
MPRISHandler *MPRISHandler
MPMediaHandler *MPMediaHandler
// UI callbacks to be set in main
OnReactivate func()
@@ -110,6 +111,7 @@ func StartupApp(appName, displayAppName, appVersionTag, configFile, latestReleas
})
a.setupMPRIS(displayAppName)
a.setupMPMedia()
return a, nil
}
@@ -231,6 +233,11 @@ func (a *App) setupMPRIS(mprisAppName string) {
a.MPRISHandler.Start()
}
func (a *App) setupMPMedia() {
a.MPMediaHandler = NewMPMediaHandler(a.Player, a.PlaybackManager)
a.MPMediaHandler.ArtURLLookup = a.ImageManager.GetCoverArtUrl
}
func (a *App) LoginToDefaultServer(string) error {
serverCfg := a.ServerManager.GetDefaultServer()
if serverCfg == nil {
+70
View File
@@ -0,0 +1,70 @@
package backend
/**
* This file handles implementation of MacOS native controls via the native 'MediaPlayer' framework
**/
// #cgo CFLAGS: -x objective-c
// #cgo LDFLAGS: -framework Cocoa -framework MediaPlayer
// #include "mpmediabridge.h"
import (
"C"
)
import (
"fmt"
"unsafe"
"github.com/dweymouth/supersonic/backend/mediaprovider"
"github.com/dweymouth/supersonic/player"
)
type MPMediaHandler struct {
player *player.Player
playbackManager *PlaybackManager
ArtURLLookup func(trackID string) (string, error)
}
func NewMPMediaHandler(player *player.Player, playbackManager *PlaybackManager) *MPMediaHandler {
mp := &MPMediaHandler{
player: player,
playbackManager: playbackManager,
}
mp.playbackManager.OnSongChange(func(track, _ *mediaprovider.Track) {
if mp.ArtURLLookup != nil {
mp.ArtURLLookup(track.CoverArtID)
}
cTitle := C.CString(track.Name)
defer C.free(unsafe.Pointer(cTitle))
artist := ""
if len(track.ArtistNames) > 0 {
artist = track.ArtistNames[0]
}
cArtist := C.CString(artist)
defer C.free(unsafe.Pointer(cArtist))
// TODO: pass in local URL for image (can be loaded via NSImage)
C.setNowPlayingInfo(cTitle, cArtist)
})
mp.player.OnStopped(func() {
// TODO: media stopped playing
fmt.Println("Stopped")
})
mp.player.OnPlaying(func() {
// TODO: media playing
fmt.Println("Playing")
})
mp.player.OnPaused(func() {
// TODO: media paused
fmt.Println("Paused")
})
return mp
}
+18
View File
@@ -0,0 +1,18 @@
/**
* mpmediabridge.h
*
* This file provides a C bridge to the Objective-C framework for macOS media playback.
* It offers a simplified interface to interact with the MPNowPlayingInfoCenter and other
* related media playback functionalities in macOS without dealing directly with
* Objective-C code.
*/
#include <AppKit/AppKit.h>
#include <MediaPlayer/MediaPlayer.h>
/**
* Updates the "Now Playing" information on macOS for media playback
* using the MPNowPlayingInfoCenter API to set the metadata
* for the currently playing media in the system's "Now Playing" interface.
*/
void setNowPlayingInfo(const char *title, const char *artist);
+47
View File
@@ -0,0 +1,47 @@
#import "mpmediabridge.h"
/**
* Native Objective-C function for setting "Now Playing" information on macOS for media playback using the native APIs.
*/
void setNowPlayingInfoNative(const char *title, const char *artist, double trackDuration, NSImage *artworkImage, double elapsedTime) {
// TODO: the remove command center logic needs to move
MPRemoteCommandCenter *commandCenter = [MPRemoteCommandCenter sharedCommandCenter];
[commandCenter.playCommand addTargetWithHandler:^MPRemoteCommandHandlerStatus(MPRemoteCommandEvent * _Nonnull event) {
// TODO: Handle play command
return MPRemoteCommandHandlerStatusSuccess;
}];
[commandCenter.pauseCommand addTargetWithHandler:^MPRemoteCommandHandlerStatus(MPRemoteCommandEvent * _Nonnull event) {
// TODO: Handle pause command
return MPRemoteCommandHandlerStatusSuccess;
}];
[commandCenter.togglePlayPauseCommand addTargetWithHandler:^MPRemoteCommandHandlerStatus(MPRemoteCommandEvent * _Nonnull event) {
// TODO: Handle toggle command
return MPRemoteCommandHandlerStatusSuccess;
}];
MPNowPlayingInfoCenter *infoCenter = [MPNowPlayingInfoCenter defaultCenter];
NSDictionary *nowPlayingInfo = @{
MPMediaItemPropertyTitle: [NSString stringWithUTF8String:title],
MPMediaItemPropertyArtist: [NSString stringWithUTF8String:artist],
MPMediaItemPropertyPlaybackDuration: @(trackDuration),
MPNowPlayingInfoPropertyElapsedPlaybackTime: @(elapsedTime)
};
infoCenter.nowPlayingInfo = nowPlayingInfo;
infoCenter.playbackState = MPNowPlayingPlaybackStatePlaying;
}
/**
* 'C' bridge function for 'setNowPlayingInfoNative'
*/
void setNowPlayingInfo(const char *title, const char *artist) {
const char *imagePath = "/path/to/image.png";
double trackDuration = 300.0;
double elapsedTime = 120.0;
setNowPlayingInfoNative(title, artist, trackDuration, NULL, elapsedTime);
}