mirror of
				https://gitlab.freedesktop.org/pipewire/pipewire.git
				synced 2025-11-03 09:01:54 -05:00 
			
		
		
		
	Merge branch 'master' into 'fix_san_build'
# Conflicts: # src/modules/module-rtp/apple-midi.h
This commit is contained in:
		
						commit
						2429674970
					
				
					 7 changed files with 124 additions and 8 deletions
				
			
		| 
						 | 
				
			
			@ -527,6 +527,34 @@ static void recv_state_changed(void *data, bool started, const char *error)
 | 
			
		|||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void recv_send_feedback(void *data, uint32_t seqnum)
 | 
			
		||||
{
 | 
			
		||||
	struct session *sess = data;
 | 
			
		||||
	struct impl *impl = sess->impl;
 | 
			
		||||
	struct iovec iov[1];
 | 
			
		||||
	struct msghdr msg;
 | 
			
		||||
	struct rtp_apple_midi_rs hdr;
 | 
			
		||||
 | 
			
		||||
	if (!sess->ctrl_ready || !sess->receiving)
 | 
			
		||||
		return;
 | 
			
		||||
 | 
			
		||||
	spa_zero(hdr);
 | 
			
		||||
	hdr.cmd = htonl(APPLE_MIDI_CMD_RS);
 | 
			
		||||
	hdr.ssrc = htonl(sess->ssrc);
 | 
			
		||||
	hdr.seqnum = htonl(seqnum);
 | 
			
		||||
 | 
			
		||||
	iov[0].iov_base = &hdr;
 | 
			
		||||
	iov[0].iov_len = sizeof(hdr);
 | 
			
		||||
 | 
			
		||||
	spa_zero(msg);
 | 
			
		||||
	msg.msg_name = &sess->ctrl_addr;
 | 
			
		||||
	msg.msg_namelen = sess->ctrl_len;
 | 
			
		||||
	msg.msg_iov = iov;
 | 
			
		||||
	msg.msg_iovlen = 1;
 | 
			
		||||
 | 
			
		||||
	send_packet(impl->ctrl_source->fd, &msg);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static const struct rtp_stream_events send_stream_events = {
 | 
			
		||||
	RTP_VERSION_STREAM_EVENTS,
 | 
			
		||||
	.destroy = send_destroy,
 | 
			
		||||
| 
						 | 
				
			
			@ -538,6 +566,7 @@ static const struct rtp_stream_events recv_stream_events = {
 | 
			
		|||
	RTP_VERSION_STREAM_EVENTS,
 | 
			
		||||
	.destroy = recv_destroy,
 | 
			
		||||
	.state_changed = recv_state_changed,
 | 
			
		||||
	.send_feedback = recv_send_feedback,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
static void free_session(struct session *sess)
 | 
			
		||||
| 
						 | 
				
			
			@ -784,6 +813,31 @@ static void parse_apple_midi_cmd_ok(struct impl *impl, bool ctrl, uint8_t *buffe
 | 
			
		|||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void parse_apple_midi_cmd_no(struct impl *impl, bool ctrl, uint8_t *buffer,
 | 
			
		||||
		ssize_t len, struct sockaddr_storage *sa, socklen_t salen)
 | 
			
		||||
{
 | 
			
		||||
	struct rtp_apple_midi *hdr = (struct rtp_apple_midi*)buffer;
 | 
			
		||||
	uint32_t initiator = ntohl(hdr->initiator);
 | 
			
		||||
	struct session *sess;
 | 
			
		||||
 | 
			
		||||
	sess = find_session_by_initiator(impl, initiator, ctrl);
 | 
			
		||||
	if (sess == NULL || !sess->we_initiated) {
 | 
			
		||||
		pw_log_warn("received NO from nonexisting session %u", initiator);
 | 
			
		||||
		return;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (ctrl) {
 | 
			
		||||
		pw_log_info("got ctrl NO %08x %u", initiator, sess->data_ready);
 | 
			
		||||
		sess->ctrl_ready = false;
 | 
			
		||||
	} else {
 | 
			
		||||
		pw_log_info("got data NO %08x %u, session canceled", initiator,
 | 
			
		||||
				sess->ctrl_ready);
 | 
			
		||||
		sess->data_ready = false;
 | 
			
		||||
		if (!sess->ctrl_ready)
 | 
			
		||||
			session_update_state(sess, SESSION_STATE_INIT);
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void parse_apple_midi_cmd_ck(struct impl *impl, bool ctrl, uint8_t *buffer,
 | 
			
		||||
		ssize_t len, struct sockaddr_storage *sa, socklen_t salen)
 | 
			
		||||
{
 | 
			
		||||
| 
						 | 
				
			
			@ -878,6 +932,24 @@ static void parse_apple_midi_cmd_by(struct impl *impl, bool ctrl, uint8_t *buffe
 | 
			
		|||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void parse_apple_midi_cmd_rs(struct impl *impl, bool ctrl, uint8_t *buffer,
 | 
			
		||||
		ssize_t len, struct sockaddr_storage *sa, socklen_t salen)
 | 
			
		||||
{
 | 
			
		||||
	struct rtp_apple_midi_rs *hdr = (struct rtp_apple_midi_rs*)buffer;
 | 
			
		||||
	struct session *sess;
 | 
			
		||||
	uint32_t ssrc, seqnum;
 | 
			
		||||
 | 
			
		||||
	ssrc = ntohl(hdr->ssrc);
 | 
			
		||||
	sess = find_session_by_ssrc(impl, ssrc);
 | 
			
		||||
	if (sess == NULL) {
 | 
			
		||||
		pw_log_warn("unknown SSRC %u", ssrc);
 | 
			
		||||
		return;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	seqnum = ntohl(hdr->seqnum);
 | 
			
		||||
	pw_log_debug("got RS seqnum %u", seqnum);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void parse_apple_midi_cmd(struct impl *impl, bool ctrl, uint8_t *buffer,
 | 
			
		||||
		ssize_t len, struct sockaddr_storage *sa, socklen_t salen)
 | 
			
		||||
{
 | 
			
		||||
| 
						 | 
				
			
			@ -889,12 +961,18 @@ static void parse_apple_midi_cmd(struct impl *impl, bool ctrl, uint8_t *buffer,
 | 
			
		|||
	case APPLE_MIDI_CMD_OK:
 | 
			
		||||
		parse_apple_midi_cmd_ok(impl, ctrl, buffer, len, sa, salen);
 | 
			
		||||
		break;
 | 
			
		||||
	case APPLE_MIDI_CMD_NO:
 | 
			
		||||
		parse_apple_midi_cmd_no(impl, ctrl, buffer, len, sa, salen);
 | 
			
		||||
		break;
 | 
			
		||||
	case APPLE_MIDI_CMD_CK:
 | 
			
		||||
		parse_apple_midi_cmd_ck(impl, ctrl, buffer, len, sa, salen);
 | 
			
		||||
		break;
 | 
			
		||||
	case APPLE_MIDI_CMD_BY:
 | 
			
		||||
		parse_apple_midi_cmd_by(impl, ctrl, buffer, len, sa, salen);
 | 
			
		||||
		break;
 | 
			
		||||
	case APPLE_MIDI_CMD_RS:
 | 
			
		||||
		parse_apple_midi_cmd_rs(impl, ctrl, buffer, len, sa, salen);
 | 
			
		||||
		break;
 | 
			
		||||
	default:
 | 
			
		||||
		break;
 | 
			
		||||
	}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -32,11 +32,18 @@ struct rtp_apple_midi_ck {
 | 
			
		|||
	uint32_t ts3_l;
 | 
			
		||||
} __attribute__ ((packed));
 | 
			
		||||
 | 
			
		||||
struct rtp_apple_midi_rs {
 | 
			
		||||
	uint32_t cmd;
 | 
			
		||||
	uint32_t ssrc;
 | 
			
		||||
	uint32_t seqnum;
 | 
			
		||||
} __attribute__ ((packed));
 | 
			
		||||
 | 
			
		||||
#define APPLE_MIDI_CMD_IN	(0xffff0000 | 'I'<<8 | 'N')
 | 
			
		||||
#define APPLE_MIDI_CMD_NO	(0xffff0000 | 'N'<<8 | 'O')
 | 
			
		||||
#define APPLE_MIDI_CMD_OK	(0xffff0000 | 'O'<<8 | 'K')
 | 
			
		||||
#define APPLE_MIDI_CMD_CK	(0xffff0000 | 'C'<<8 | 'K')
 | 
			
		||||
#define APPLE_MIDI_CMD_BY	(0xffff0000 | 'B'<<8 | 'Y')
 | 
			
		||||
#define APPLE_MIDI_CMD_RS	(0xffff0000 | 'R'<<8 | 'S')
 | 
			
		||||
 | 
			
		||||
#ifdef __cplusplus
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -142,7 +142,7 @@ static int receive_rtp_audio(struct impl *impl, uint8_t *buffer, ssize_t len)
 | 
			
		|||
 | 
			
		||||
	if (!impl->have_sync) {
 | 
			
		||||
		pw_log_info("sync to timestamp:%u seq:%u ts_offset:%u SSRC:%u target:%u direct:%u",
 | 
			
		||||
				write, impl->seq-1, impl->ts_offset, impl->ssrc,
 | 
			
		||||
				timestamp, seq, impl->ts_offset, impl->ssrc,
 | 
			
		||||
				impl->target_buffer, impl->direct_timestamp);
 | 
			
		||||
 | 
			
		||||
		/* we read from timestamp, keeping target_buffer of data
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -126,6 +126,13 @@ static int get_midi_size(uint8_t *p, uint32_t avail)
 | 
			
		|||
	}
 | 
			
		||||
	return size;
 | 
			
		||||
}
 | 
			
		||||
static int parse_journal(struct impl *impl, uint8_t *packet, uint16_t seq, uint32_t len)
 | 
			
		||||
{
 | 
			
		||||
	struct rtp_midi_journal *j = (struct rtp_midi_journal*)packet;
 | 
			
		||||
	uint16_t seqnum = ntohs(j->checkpoint_seqnum);
 | 
			
		||||
	rtp_stream_emit_send_feedback(impl, seqnum);
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static double get_time(struct impl *impl)
 | 
			
		||||
{
 | 
			
		||||
| 
						 | 
				
			
			@ -143,8 +150,8 @@ static double get_time(struct impl *impl)
 | 
			
		|||
	return t;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int receive_midi(struct impl *impl, uint8_t *packet,
 | 
			
		||||
		uint32_t timestamp, uint32_t payload_offset, uint32_t plen)
 | 
			
		||||
static int receive_midi(struct impl *impl, uint8_t *packet, uint32_t timestamp,
 | 
			
		||||
		uint16_t seq, uint32_t payload_offset, uint32_t plen)
 | 
			
		||||
{
 | 
			
		||||
	uint32_t write;
 | 
			
		||||
	struct rtp_midi_header *hdr;
 | 
			
		||||
| 
						 | 
				
			
			@ -160,7 +167,7 @@ static int receive_midi(struct impl *impl, uint8_t *packet,
 | 
			
		|||
		 * midi events and render them in the corresponding cycle */
 | 
			
		||||
		if (!impl->have_sync) {
 | 
			
		||||
			pw_log_info("sync to timestamp:%u seq:%u ts_offset:%u SSRC:%u direct:%d",
 | 
			
		||||
				timestamp, impl->seq-1, impl->ts_offset, impl->ssrc,
 | 
			
		||||
				timestamp, seq, impl->ts_offset, impl->ssrc,
 | 
			
		||||
				impl->direct_timestamp);
 | 
			
		||||
			impl->have_sync = true;
 | 
			
		||||
		}
 | 
			
		||||
| 
						 | 
				
			
			@ -186,7 +193,7 @@ static int receive_midi(struct impl *impl, uint8_t *packet,
 | 
			
		|||
			spa_dll_set_bw(&impl->dll, SPA_DLL_BW_MIN, 256, impl->rate);
 | 
			
		||||
 | 
			
		||||
			pw_log_info("sync to timestamp:%u seq:%u ts_offset:%u SSRC:%u direct:%d",
 | 
			
		||||
				timestamp, impl->seq-1, impl->ts_offset, impl->ssrc,
 | 
			
		||||
				timestamp, seq, impl->ts_offset, impl->ssrc,
 | 
			
		||||
				impl->direct_timestamp);
 | 
			
		||||
			impl->have_sync = true;
 | 
			
		||||
			impl->ring.readindex = impl->ring.writeindex;
 | 
			
		||||
| 
						 | 
				
			
			@ -221,6 +228,8 @@ static int receive_midi(struct impl *impl, uint8_t *packet,
 | 
			
		|||
		pw_log_warn("invalid packet %d > %d", end, plen);
 | 
			
		||||
		return -EINVAL;
 | 
			
		||||
	}
 | 
			
		||||
	if (hdr->j)
 | 
			
		||||
		parse_journal(impl, &packet[end], seq, plen - end);
 | 
			
		||||
 | 
			
		||||
	ptr = SPA_PTROFF(impl->buffer, write & BUFFER_MASK2, void);
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -258,6 +267,8 @@ static int receive_midi(struct impl *impl, uint8_t *packet,
 | 
			
		|||
 | 
			
		||||
	write += b.state.offset;
 | 
			
		||||
	spa_ringbuffer_write_update(&impl->ring, write);
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -297,7 +308,7 @@ static int receive_rtp_midi(struct impl *impl, uint8_t *buffer, ssize_t len)
 | 
			
		|||
 | 
			
		||||
	impl->receiving = true;
 | 
			
		||||
 | 
			
		||||
	return receive_midi(impl, buffer, timestamp, hlen, len);
 | 
			
		||||
	return receive_midi(impl, buffer, timestamp, seq, hlen, len);
 | 
			
		||||
 | 
			
		||||
short_packet:
 | 
			
		||||
	pw_log_warn("short packet received");
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -58,17 +58,34 @@ struct rtp_midi_header {
 | 
			
		|||
	unsigned z:1;
 | 
			
		||||
	unsigned j:1;
 | 
			
		||||
	unsigned b:1;
 | 
			
		||||
	uint8_t len_b;
 | 
			
		||||
#elif __BYTE_ORDER == __BIG_ENDIAN
 | 
			
		||||
	unsigned b:1;
 | 
			
		||||
	unsigned j:1;
 | 
			
		||||
	unsigned z:1;
 | 
			
		||||
	unsigned p:1;
 | 
			
		||||
	unsigned len:4;
 | 
			
		||||
	uint8_t len_b;
 | 
			
		||||
#endif
 | 
			
		||||
	uint8_t len_b;
 | 
			
		||||
} __attribute__ ((packed));
 | 
			
		||||
 | 
			
		||||
struct rtp_midi_journal {
 | 
			
		||||
#if __BYTE_ORDER == __LITTLE_ENDIAN
 | 
			
		||||
	unsigned totchan:4;
 | 
			
		||||
	unsigned H:1;
 | 
			
		||||
	unsigned A:1;
 | 
			
		||||
	unsigned Y:1;
 | 
			
		||||
	unsigned S:1;
 | 
			
		||||
#elif __BYTE_ORDER == __BIG_ENDIAN
 | 
			
		||||
	unsigned S:1;
 | 
			
		||||
	unsigned Y:1;
 | 
			
		||||
	unsigned A:1;
 | 
			
		||||
	unsigned H:1;
 | 
			
		||||
	unsigned totchan:4;
 | 
			
		||||
#endif
 | 
			
		||||
	uint16_t checkpoint_seqnum;
 | 
			
		||||
} __attribute__ ((packed));
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#ifdef __cplusplus
 | 
			
		||||
}
 | 
			
		||||
#endif
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -31,6 +31,7 @@
 | 
			
		|||
#define rtp_stream_emit_destroy(s)		rtp_stream_emit(s, destroy, 0)
 | 
			
		||||
#define rtp_stream_emit_state_changed(s,n,e)	rtp_stream_emit(s, state_changed,0,n,e)
 | 
			
		||||
#define rtp_stream_emit_send_packet(s,i,l)	rtp_stream_emit(s, send_packet,0,i,l)
 | 
			
		||||
#define rtp_stream_emit_send_feedback(s,seq)	rtp_stream_emit(s, send_feedback,0,seq)
 | 
			
		||||
 | 
			
		||||
struct impl {
 | 
			
		||||
	struct spa_audio_info info;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -32,6 +32,8 @@ struct rtp_stream_events {
 | 
			
		|||
	void (*state_changed) (void *data, bool started, const char *error);
 | 
			
		||||
 | 
			
		||||
	void (*send_packet) (void *data, struct iovec *iov, size_t iovlen);
 | 
			
		||||
 | 
			
		||||
	void (*send_feedback) (void *data, uint32_t senum);
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct rtp_stream *rtp_stream_new(struct pw_core *core,
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue