Skip to content

Protocols ​

The device layer covers what most apps need. Use a protocol package for a message the device layer does not send, for a tool that inspects traffic, or to decide yourself when a connection opens and closes.

The layers ​

@corewire/devices          AppleTV, HomePod: connection upkeep, capabilities
├── @corewire/airplay      AirPlay 2 sessions, URL playback, audio streams, timing
│   ├── /mrp               Media Remote on the AirPlay data channel
│   ├── /raop              RAOP audio streaming
│   └── /rtsp              The RTSP client the others build on
├── @corewire/companion-link
└── @corewire/core         pairing, encryption, transport, mDNS, codecs, errors, logging

@corewire/audio-source sits beside them. It depends on core and produces the AudioSource that AirPlay and RAOP stream.

Sessions live once ​

A device object reconnects. A protocol session does not. connect() returns a session that is ready to use. TCP is open, and pairing and encryption are done. The session then ends exactly once, with a reason:

ReasonMeaning
localThis side closed it, or gave up on a setup step
remoteThe device closed it
timeoutThe keepalive went unanswered (AirPlay), or the socket did not open in time
errorA socket or frame broke

When it ends, its closed event fires with the reason and an optional error, its signal aborts, and every channel, timer and pending request on it goes too. To continue, connect again. The device layer does that, with backoff and a fresh lookup.

ts
import { connect } from '@corewire/airplay';

const session = await connect({address: '192.168.1.30'});

session.on('closed', (reason, error) => {
    console.log('session ended', reason, error?.message);
});

session.signal.addEventListener('abort', () => console.log('aborted'));

closeReason is undefined while the session is open, and the reason afterwards. isOpen gives the same as a boolean.

Models without I/O ​

MediaRemoteState (MRP) and CompanionLinkState (Companion Link) are models. They derive what plays, the volume, the keyboard and the power state from messages, and do no I/O themselves. You can pass one to connect() or MediaRemote.open() to keep it, and its listeners, across sessions. You can also feed it recorded traffic and get the same events as on a live session.

Pages ​

CoreWire is released under the MIT license.