remote audio help needed again

I have an app that is playing MP3 that is hosted on a Xojo cloud server.
It’s served up via HTTPS. This works ok.
What isn’t working ok is the player controls.

When I use an iOSHTMLViewer the control shows as a black or white block (depending on dark mode), and while in the simulator it finally appears after the audio has started, on a real device it never refreshes and shows.

I’ve tried calling invalidate.
I’d really prefer to be able to wrap my own controls for play, start, progress etc, but It seems that’s trickier said than done.

I’ll settle for the HTML viewer but I really need it to show up.

Has anyone addressed something like this, or does anyone have any tips for how to work-around?
This is the only thing stopping me from a release candidate today.

Thanks in advance!

Did you check the AVaudioPlayer class in AVFoundation module of iOSKit?
https://developer.apple.com/documentation/avfoundation/avaudioplayer

It seems that is what you need to playback audio with your own controls.

I’m looking at that now.
I did overcome my issue by wrapping a simple HTML document with an audio tag and sending that directly to the HTML Viewer.
I have another problem with it now that it won’t keep playing in the background - seems to keep going to sleep. But Jason King gave me a lead to overcome that.

Alright… some progress.
I could not get the AVAudioPlayer to play from a remote URL, but I’ve updated my code to download the entire MP3 first and then play with the AVaudioPlayer from the local hardware. It works well. It works in the background. It continues to play when I lock my screen. Almost perfect.

The only problem I’m having now is figuring out how to connect with the audio controls that show up on the lock screen or when in the background.

Anyone have experience with this?

It looks like I need to implement this:

MPRemoteCommandCenter

Is there anyone who can give me a boost? These declares in iOS are out of my wheelhouse.

I also checked the MBS project (commercial), but it doesn’t handle this either.

That should be possible to implement in Xojo. Remind me Monday and I can put together the declared for it.

That would be Phenomenal, Jason. Thank you.

@Jason King - Monday Reminder :slight_smile:
The Xojo team should have you on retainer - you contribute so much to this community.

nudge nudge, wink wink.

Sorry been a hectic week. I’ll take a look tonight

Thanks Jason. Happy New Year.
No apology needed!

Ok this is going to be long. Loosely copied from the link you provided. There is an example project in swift as well, but I can’t really read swift so didn’t look at it. Maybe it is useful to someone.

This code is UNTESTED but is probably pretty close to what you need to do

Open event:

Sub Open() SetupControls() SetupNowPlaying() End Sub

Add the functions:

[code]Sub SetupControls()
// setup the AVAudioPlayer here in “self.player”

declare function sharedCommandCenter lib “MediaPlayer” selector “sharedCommandCenter” (clsRef as Ptr) as ptr
declare Function addTarget lib “MediaPlayer” selector “addTargetWithHandler:” (obj_id as ptr, blk as ptr) as ptr
declare sub setEnabled lib “MediaPlayer” selector “enabled” (obj_id as ptr, yesNo as Boolean)

// repeat this for all commands (I believe)
// ie, play, pause, stop, togglePlay/Pause
// nextTrack, previousTrack, etc
// NOTE: you MUST call “setEnabled(XYZcmd, False)” for any of the commands you do not support or your app will not work
// see https://developer.apple.com/documentation/mediaplayer/mpremotecommandcenter?language=objc
declare function playCommand lib “MediaPlayer” selector “playCommand” (obj_id as ptr) as ptr

dim sharedCenter as Ptr = sharedCommandCenter(NSClassFromString(“MPRemoteCommandCenter”))
dim playCmd as Ptr = playCommand(sharedCenter)

// if you want this command (item of the player when displayed on the lock screen) to be disabled do the following
//setEnabled(playCmd, False)

// if you want to handle the command, add a function for it, and add the following
dim blk as new iOSBlock(AddressOf PlayCommandHandler)
call addTarget(playCmd, blk.Handle)

// repeat for all commands you care about…
End Sub
[/code]

[code]Sub SetupNowPlaying()
declare function defaultCenter lib “MediaPlayer” selector “defaultCenter” (clsRef as ptr) as ptr
declare sub setNowPlayingInfo Lib “MediaPlayer” selector “setNowPlayingInfo:” (obj_id as ptr, info as ptr)

Declare function numberWithInt lib FoundationLib selector “numberWithInt:” (clsRef as ptr, int as Integer) as ptr

dim nowPlayingInfo as new Foundation.NSMutableDictionary
nowPlayingInfo.Value(new NSString(“title”)) = new NSString(“My song title”)

// set duration, in seconds
nowPlayingInfo.Value(new NSString(“playbackDuration”)) = numberWithInt(NSClassFromString(“NSNumber”), 10)

// there are other properties that can be set… some easier and some more difficult. if you need them I can try and show how for some
// see https://developer.apple.com/documentation/mediaplayer/mpnowplayinginfocenter?language=objc#1674387

dim defCtr as ptr = defaultCenter(NSClassFromString(“MPNowPlayingInfoCenter”))
setNowPlayingInfo(defCtr, nowPlayingInfo)
End Sub
[/code]

Now add a command handler callback for every command you intend to support (you might need to have like 10 of these depending on the number of events you support)

[code]Function PlayCommandHandler(evt as ptr) As Integer
// possible return values from this function:
const success = 0
const failed = 200
const NoActionableNowPlayingItem = 110
const NoSuchContent = 100

if self.player.rate == 0
self.player.play()
return success
end if

return failed

#Pragma unused evt
End Function
[/code]

First attempt wouldn’t compile, but I’m digging in.

Thank you.

There are some problems with this and I’m trying to work through them but not seeing light.

This bombs it hard.

setEnabled(playCmd, False)

I was hoping to see at least one of the functions do something that I could recognize as a step. Setting the title doesn’t do anything. I’ll keep looking over the weekend, but if anyone wants to hop in and speculate, I could use a nudge in the right direction.

Comment that out for now and see what happens.

I have. I just can’t get anything else to work. None of the controls show up, and the title won’t show. It’s just blank.

Did you add other commands? Like pause fast forward next song etc?

I sure did. Maybe I missed some.

I have tried this every way imaginable. I can certainly get it to compile and have no controls show up, but it runs fine. I can get it to crash hard too.
Can I encourage or incentivize or beg for someone to build a very simple example?

I really need to find the time to learn do to these iOS declares myself sometime!