Setting media playback info in MacOs not working

Viewed 142

I'm a newbie in ObjC and MacOs development. My final goal is understand how setting playback info works from ObjC to try to implement that later on Rust (using generated ObjC runtime bindings).

So right now I'm trying to write small piece of code on ObjC that would set playback info (without actually playing anything). I have found https://github.com/MarshallOfSound/electron-media-service/blob/master/src/darwin/service.mm and used it as a base.

Here's code I have right now:

#import <Foundation/Foundation.h>
#import <AppKit/AppKit.h>
#import <objc/runtime.h>
#include "MediaPlayer/MPNowPlayingInfoCenter.h"
#include "MediaPlayer/MPRemoteCommandCenter.h"
#include "MediaPlayer/MPRemoteCommand.h"
#include "MediaPlayer/MPMediaItem.h"
#include "MediaPlayer/MPRemoteCommandEvent.h"


@interface NativeMediaController : NSObject { }
@end

@implementation NativeMediaController
- (MPRemoteCommandHandlerStatus)remotePlay {
    NSLog(@"Play");
    return MPRemoteCommandHandlerStatusSuccess;
  }
- (MPRemoteCommandHandlerStatus)remotePause {
    NSLog(@"Pause");
    return MPRemoteCommandHandlerStatusSuccess;
  }
- (MPRemoteCommandHandlerStatus)remoteTogglePlayPause {
    NSLog(@"PlayPause");
    return MPRemoteCommandHandlerStatusSuccess;
  }
- (MPRemoteCommandHandlerStatus)remoteNext {
    NSLog(@"Next");
    return MPRemoteCommandHandlerStatusSuccess;
  }
- (MPRemoteCommandHandlerStatus)remotePrev {
    NSLog(@"Previous");
    return MPRemoteCommandHandlerStatusSuccess;
  }

- (MPRemoteCommandHandlerStatus)remoteChangePlaybackPosition:(MPChangePlaybackPositionCommandEvent*)event {
    NSLog(@"ChangePlaybackPosition");
  return MPRemoteCommandHandlerStatusSuccess;
}

- (MPRemoteCommandHandlerStatus)move:(MPChangePlaybackPositionCommandEvent*)event {
    NSLog(@"Move");
  return MPRemoteCommandHandlerStatusSuccess;
}
@end

int main(int argc, const char * argv[]) {
    @autoreleasepool {
        // insert code here...
        NSLog(@"Hello, World!");
        NativeMediaController* controller = [[NativeMediaController alloc] init];

        MPRemoteCommandCenter *remoteCommandCenter = [MPRemoteCommandCenter sharedCommandCenter];
        [remoteCommandCenter playCommand].enabled = true;
        [remoteCommandCenter pauseCommand].enabled = true;
        [remoteCommandCenter togglePlayPauseCommand].enabled = true;
        [remoteCommandCenter changePlaybackPositionCommand].enabled = true;
        [remoteCommandCenter nextTrackCommand].enabled = true;
        [remoteCommandCenter previousTrackCommand].enabled = true;

        [[remoteCommandCenter playCommand] addTarget:controller action:@selector(remotePlay)];
        [[remoteCommandCenter pauseCommand] addTarget:controller action:@selector(remotePause)];
        [[remoteCommandCenter togglePlayPauseCommand] addTarget:controller action:@selector(remoteTogglePlayPause)];
        [[remoteCommandCenter changePlaybackPositionCommand] addTarget:controller action:@selector(remoteChangePlaybackPosition:)];
        [[remoteCommandCenter nextTrackCommand] addTarget:controller action:@selector(remoteNext)];
        [[remoteCommandCenter previousTrackCommand] addTarget:controller action:@selector(remotePrev)];
        
        NSMutableDictionary *songInfo = [[NSMutableDictionary alloc] init];
        [songInfo setObject:[NSString stringWithUTF8String:"Test title"] forKey:MPMediaItemPropertyTitle];
        [songInfo setObject:[NSString stringWithUTF8String:"Test artist"] forKey:MPMediaItemPropertyArtist];
        [songInfo setObject:[NSString stringWithUTF8String:"Test albumtitle"] forKey:MPMediaItemPropertyAlbumTitle];
        [songInfo setObject:[NSNumber numberWithFloat:60.0] forKey:MPNowPlayingInfoPropertyElapsedPlaybackTime];
        [songInfo setObject:[NSNumber numberWithFloat:360.0] forKey:MPMediaItemPropertyPlaybackDuration];
        [songInfo setObject:[NSNumber numberWithFloat:112233] forKey:MPMediaItemPropertyPersistentID];
        
        [MPNowPlayingInfoCenter defaultCenter].playbackState = MPNowPlayingPlaybackStatePlaying;
        [[MPNowPlayingInfoCenter defaultCenter] setNowPlayingInfo:songInfo];
        NSLog(@"End!");
        
        char input[50] = {0};
        printf("Enter anything to quit: ");
        scanf("%s", input);
    }
    return 0;
}

When this code is executed I see no effect in MacOs playing info widget. Unfortunately right now I have no idea how to debug this or where can I find better ObjC example.

1 Answers

Finally, I found the reason that caused my problem playing with Apple Swift example. There're two requirements to show playback widget (i didn't find them documented anywhere) that have been missing:

  • You should register a callback for at least one action (play, pause)
  • You should build your application as an App, not as Console. If your program is not shown in the dock as a running app - the playback widget wouldn't work.
Related