openairplay / airplay2-receiver

AirPlay 2 Receiver - Python implementation
2.13k stars 133 forks source link

Continue branch-sender from ckdo #36

Closed TheSpookyCat closed 2 years ago

TheSpookyCat commented 3 years ago

Would anyone be interested in the continuation of this branch by ckdo: https://github.com/ckdo/airplay2-receiver/tree/branch-sender

I feel like it'd be a really good addition if done well.

Neustradamus commented 3 years ago

@systemcrash: There are several branches:

systemcrash commented 3 years ago

Noted. The important bit: "if done well" :)

ckdo has done some good work. Have you tested any of those branches?

TheSpookyCat commented 3 years ago

I'm unable to test those branches easily as they don't have the latest Feature Flags system - HKPairing breaks it for iOS 15 db 2

TheSpookyCat commented 3 years ago

I'll scour through what CKDO has done and see if I can intertwine it with what we've currently got, then. Thanks.

TheSpookyCat commented 2 years ago

@systemcrash Well, the meat of it is there. It's definitely got potential to be usable, though I've been really struggling with RSTP authentication.

I'm currently at the point where I'm getting and even if I implement the HTTP digest auth it rejects it anyway.

----- AUTH SETUP RESPONSE -----
Content-Length: 0
Server: AirTunes/566.25.43
WWW-Authenticate: Digest realm="airplay", nonce="M[...]Q/"
CSeq: 2

401
----- AUTH SETUP RESPONSE ERROR OCCURED -----
TheSpookyCat commented 2 years ago

I went to look for inspiration and found a lovely package called pyatv - it's designed to interface with Apple TVs.

I thought that surely it must be achievable since I only want to find out what the currently playing song is. It did manage to connect, and pair, but it failed to perform any actions. I assume this is because the module treats play/pause/play+pause/etc as the same: the play key. So it's sending data to a device which doesn't support an Apple TV remote, and the device subsequently rejects. I'd be more than happy to implement some sort of pyatv wrapper as part of the ap2 module, but even better would be to be able to extract how they're handling RTSP + Auth. Would just like to hear some thoughts before I go and attempt anything major.

postlund commented 2 years ago

As maintainer for pyatv, I can add that it does not support any AirPlay 2 features other than system and transient pairing in order to set up a remote control stream to tunnel the MRP protocol over. This is required in tvOS 15 as the "regular" MRP (which has its own zeroconfs service) is removed. The same functionality also works with the HomePod (which uses transient pairing). The MRP protocol is apple internal so I expect this to not work with any other devices than the Apple TV and HomePod.

Also, pyatv only has very basic AirPlay 1 support for streaming audio. No controls are implemented at all. As far as I know, AirPlay doesn't allow tapping in on someone else's stream. So you can't really see what is streamed by someone else to an AirPlay receiver (or execute any other commands, like play or pause). That is only supported by the sender as it has full control of the stream anyways. An exception is of course events back from the receiver, e.g. when pressing a physical button on the receiver (if supported). I guess that is why they use MRP to deal with this gap and display metadata and audio playback control in iOS via control center. I've documented some parts of that here (scroll down to the AirPlay 2 section, direct linking doesn't work properly). I can probably support any pyatv related questions if needed.

TheSpookyCat commented 2 years ago

Well then, if you don't mind, I couldn't find anything anywhere explaining which endpoint to send my RTSP data to. It's noted in the explanation that

ID in o= property (4018537194) seems to match what is used for rtsp endpoint (rtsp://xxx/4018537194)

I'd love to know how to get this so I can start testing it on my own devices.

postlund commented 2 years ago

Well then, if you don't mind, I couldn't find anything anywhere explaining which endpoint to send my RTSP data to. It's noted in the explanation that

ID in o= property (4018537194) seems to match what is used for rtsp endpoint (rtsp://xxx/4018537194)

I'd love to know how to get this so I can start testing it on my own devices.

Yes, that seems to generally be the case. I'm not entirely sure what you are trying to do though? What you are referring to is AirPlay v1 stuff, is that what you want to use?

TheSpookyCat commented 2 years ago

I'm trying to work out all the steps to where ckdo originally got to so I have at least half a clue what's going on. I've been testing this by trying out simple commands, like fetching the speaker info. From what I can see, ckdo was implementing the ap2 authentication over RTSP but it just needs a little tinkering with.

Afterwards, I'd like to make it into a script with command line arguments that people can utilise with relative ease, the same as ap2-recvier

Neustradamus commented 2 years ago

@systemcrash: Have you looked?

systemcrash commented 2 years ago

I had a look at this myself, and I'm indifferent: this project is the receiver portion. But having the capability is OK. I'm OK without it, however.

TheSpookyCat commented 2 years ago

Then would it maybe be favourable to, once the current ambitions are complete, call this project finished. Iirc the original intentions of this project are to provide a baseline for a future and more thorough implementation, no?

systemcrash commented 2 years ago

Calling something complete is a matter of philosophy, I think. I would always be open to more PRs and additions, although it seems the core of this app has largely been successful. It got ported to Go, and was possibly inspiration for other people doing similar ventures. We've not actually implemented PTP fully, yet. So... there's that :)

There seems to be more attention to the C (compiled) version of the receiver: it's a bit more comprehensive, and it has recently implemented the 'open' version of FP crypto. Porting that to Py would be... fun :smile: It would actually work. It's just a time-consuming venture, probably better in lib form (see what ckdo did for ALAC lib a while back).

I had fun working on this (and am open to devoting more effort in the future).

Neustradamus commented 2 years ago

@systemcrash: Have you "added" all good codes?

systemcrash commented 2 years ago

I'm not sure - what did you have in mind specifically?

Neustradamus commented 2 years ago

@systemcrash: Nothing to add in current upstream code?