3 * NetJack - Packet Handling functions
5 * used by the driver and the jacknet_client
7 * Copyright (C) 2006 Torben Hohn <torbenh@gmx.de>
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
23 * $Id: net_driver.c,v 1.16 2006/03/20 19:41:37 torbenh Exp $
36 #include <jack/types.h>
37 #include <jack/engine.h>
39 #include <sys/types.h>
40 #include <sys/socket.h>
41 #include <netinet/in.h>
43 #include <samplerate.h>
45 #include "net_driver.h"
46 #include "netjack_packet.h"
51 packet_header_hton(jacknet_packet_header
*pkthdr
)
53 pkthdr
->channels
= htonl(pkthdr
->channels
);
54 pkthdr
->period_size
= htonl(pkthdr
->period_size
);
55 pkthdr
->sample_rate
= htonl(pkthdr
->sample_rate
);
56 pkthdr
->sync_state
= htonl(pkthdr
->sync_state
);
57 pkthdr
->transport_frame
= htonl(pkthdr
->transport_frame
);
58 pkthdr
->transport_state
= htonl(pkthdr
->transport_state
);
59 pkthdr
->framecnt
= htonl(pkthdr
->framecnt
);
60 pkthdr
->latency
= htonl(pkthdr
->latency
);
61 pkthdr
->reply_port
= htonl(pkthdr
->reply_port
);
62 pkthdr
->mtu
= htonl(pkthdr
->mtu
);
63 pkthdr
->fragment_nr
= htonl(pkthdr
->fragment_nr
);
67 packet_header_ntoh(jacknet_packet_header
*pkthdr
)
69 pkthdr
->channels
= ntohl(pkthdr
->channels
);
70 pkthdr
->period_size
= ntohl(pkthdr
->period_size
);
71 pkthdr
->sample_rate
= ntohl(pkthdr
->sample_rate
);
72 pkthdr
->sync_state
= ntohl(pkthdr
->sync_state
);
73 pkthdr
->transport_frame
= ntohl(pkthdr
->transport_frame
);
74 pkthdr
->transport_state
= ntohl(pkthdr
->transport_state
);
75 pkthdr
->framecnt
= ntohl(pkthdr
->framecnt
);
76 pkthdr
->latency
= ntohl(pkthdr
->latency
);
77 pkthdr
->reply_port
= ntohl(pkthdr
->reply_port
);
78 pkthdr
->mtu
= ntohl(pkthdr
->mtu
);
79 pkthdr
->fragment_nr
= ntohl(pkthdr
->fragment_nr
);
82 int get_sample_size(int bitdepth
)
85 return sizeof(int8_t);
87 return sizeof(int16_t);
89 return sizeof(int32_t);
93 // fragmented packet IO
95 int netjack_recvfrom(int sockfd
, char *packet_buf
, int pkt_size
, int flags
, struct sockaddr
*addr
, socklen_t
*addr_size
, int mtu
)
100 int fragment_payload_size
;
102 // Copy the packet header to the tx pack first.
103 //memcpy(tx_packet, packet_buf, sizeof(jacknet_packet_header));
105 jacknet_packet_header
*pkthdr
;
107 // Now loop and send all
110 // wait for fragment_nr == 0
113 rx_packet
= alloca(mtu
);
114 dataX
= rx_packet
+ sizeof(jacknet_packet_header
);
116 fragment_payload_size
= mtu
- sizeof(jacknet_packet_header
);
118 // Copy the packet header to the tx pack first.
119 //memcpy(tx_packet, packet_buf, sizeof(jacknet_packet_header));
121 pkthdr
= (jacknet_packet_header
*)rx_packet
;
123 // Now loop and send all
124 packet_bufX
= packet_buf
+ sizeof(jacknet_packet_header
);
129 return recvfrom(sockfd
, packet_buf
, pkt_size
, flags
, addr
, addr_size
);
133 rcv_len
= recvfrom(sockfd
, rx_packet
, mtu
, 0, addr
, addr_size
);
137 if (rcv_len
>= sizeof(jacknet_packet_header
)) {
138 //printf("got fragmentooooo_nr = %d recv_len = %d\n", ntohl(pkthdr->fragment_nr), rcv_len);
139 if ((ntohl(pkthdr
->fragment_nr
)) != 0)
146 //printf("ok... lets go...\n");
147 // ok... we have read a fragement 0;
148 // copy the packet header...
149 memcpy(packet_buf
, rx_packet
, sizeof(jacknet_packet_header
));
151 int fragment_count
= 0;
153 while (packet_bufX
<= (packet_buf
+ pkt_size
- fragment_payload_size
)) {
155 //printf("enter loop: fragment_count = %d, pkthdr->fragment_nr = %d\n", fragment_count, pkthdr->fragment_nr);
156 // check fragment number.
157 if ((ntohl(pkthdr
->fragment_nr
)) != fragment_count
) {
158 printf("got unexpected fragment %d (expected %d)\n", ntohl(pkthdr
->fragment_nr
), fragment_count
);
159 return sizeof(jacknet_packet_header
) + (fragment_count
) * fragment_payload_size
;
161 //printf("expected fragment %d\n", fragment_count);
163 // copy the payload into the packet buffer...
164 memcpy(packet_bufX
, dataX
, fragment_payload_size
);
166 rcv_len
= recvfrom(sockfd
, rx_packet
, mtu
, 0, addr
, addr_size
);
167 //printf("got fragmen_nr = %d rcv_len = %d\n", ntohl(pkthdr->fragment_nr), rcv_len);
168 //printf("got fragmen_nr = %d\n", ntohl(pkthdr->fragment_nr));
172 packet_bufX
+= fragment_payload_size
;
176 //printf("at the end rcv_len = %d\n ", rcv_len);
177 int last_payload_size
= packet_bufX
- packet_buf
- pkt_size
;
178 memcpy(packet_bufX
, dataX
, rcv_len
- sizeof(jacknet_packet_header
));
183 int netjack_recv(int sockfd
, char *packet_buf
, int pkt_size
, int flags
, int mtu
)
185 if (pkt_size
<= mtu
) {
186 return recv(sockfd
, packet_buf
, pkt_size
, flags
);
188 char *rx_packet
= alloca(mtu
);
189 char *dataX
= rx_packet
+ sizeof(jacknet_packet_header
);
191 int fragment_payload_size
= mtu
- sizeof(jacknet_packet_header
);
192 jacknet_packet_header
*pkthdr
= (jacknet_packet_header
*)rx_packet
;
194 // Now loop and send all
195 char *packet_bufX
= packet_buf
+ sizeof(jacknet_packet_header
);
197 // wait for fragment_nr == 0
200 rcv_len
= recv(sockfd
, rx_packet
, mtu
, flags
);
204 if (rcv_len
>= sizeof(jacknet_packet_header
)) {
205 //printf("got fragmentooo_nr = %d\n", ntohl(pkthdr->fragment_nr));
206 if (ntohl(pkthdr
->fragment_nr
) != 0)
212 //printf("ok we got a fragment 0\n");
213 // ok... we have read a fragement 0;
214 // copy the packet header...
215 memcpy(packet_buf
, rx_packet
, sizeof(jacknet_packet_header
));
217 int fragment_count
= 0;
219 while (packet_bufX
<= (packet_buf
+ pkt_size
- fragment_payload_size
)) {
221 // check fragment number.
222 if (ntohl(pkthdr
->fragment_nr
) != fragment_count
) {
223 printf("got unexpected fragment %d (expected %d)\n", ntohl(pkthdr
->fragment_nr
), fragment_count
);
224 return sizeof(jacknet_packet_header
) + (fragment_count
- 1) * fragment_payload_size
;
227 // copy the payload into the packet buffer...
228 memcpy(packet_bufX
, dataX
, fragment_payload_size
);
230 rcv_len
= recv(sockfd
, rx_packet
, mtu
, flags
);
231 //printf("got fragmen_nr = %d rcv_len = %d\n", ntohl(pkthdr->fragment_nr), rcv_len);
235 packet_bufX
+= fragment_payload_size
;
239 //int last_payload_size = packet_bufX - packet_buf - pkt_size;
240 //memcpy(packet_bufX, dataX, rcv_len - sizeof(jacknet_packet_header));
245 void netjack_sendto(int sockfd
, char *packet_buf
, int pkt_size
, int flags
, struct sockaddr
*addr
, int addr_size
, int mtu
)
248 char *tx_packet
, *dataX
;
249 jacknet_packet_header
*pkthdr
;
251 tx_packet
= alloca(mtu
+ 10);
252 dataX
= tx_packet
+ sizeof(jacknet_packet_header
);
253 pkthdr
= (jacknet_packet_header
*)tx_packet
;
255 int fragment_payload_size
= mtu
- sizeof(jacknet_packet_header
);
257 if (pkt_size
<= mtu
) {
258 sendto(sockfd
, packet_buf
, pkt_size
, flags
, addr
, addr_size
);
261 // Copy the packet header to the tx pack first.
262 memcpy(tx_packet
, packet_buf
, sizeof(jacknet_packet_header
));
264 // Now loop and send all
265 char *packet_bufX
= packet_buf
+ sizeof(jacknet_packet_header
);
268 while (packet_bufX
< (packet_buf
+ pkt_size
- fragment_payload_size
)) {
269 pkthdr
->fragment_nr
= htonl(frag_cnt
++);
270 memcpy(dataX
, packet_bufX
, fragment_payload_size
);
272 int err
= sendto(sockfd
, tx_packet
, mtu
, flags
, addr
, addr_size
);
274 packet_bufX
+= fragment_payload_size
;
277 int last_payload_size
= packet_buf
+ pkt_size
- packet_bufX
;
278 memcpy(dataX
, packet_bufX
, last_payload_size
);
279 pkthdr
->fragment_nr
= htonl(frag_cnt
);
280 //printf("last fragment_count = %d, payload_size = %d\n", fragment_count, last_payload_size);
282 // sendto(last_pack_size);
283 sendto(sockfd
, tx_packet
, last_payload_size
+ sizeof(jacknet_packet_header
), flags
, addr
, addr_size
);
287 // render functions for float
288 void render_payload_to_jack_ports_float( void *packet_payload
, jack_nframes_t net_period_down
, JSList
*capture_ports
, JSList
*capture_srcs
, jack_nframes_t nframes
)
291 JSList
*node
= capture_ports
;
292 JSList
*src_node
= capture_srcs
;
294 uint32_t *packet_bufX
= (uint32_t *)packet_payload
;
296 while (node
!= NULL
) {
301 jack_port_t
*port
= (jack_port_t
*) node
->data
;
302 jack_default_audio_sample_t
* buf
= jack_port_get_buffer (port
, nframes
);
304 if (net_period_down
!= nframes
) {
305 SRC_STATE
*src_state
= src_node
->data
;
306 for (i
= 0; i
< net_period_down
; i
++) {
307 packet_bufX
[i
] = ntohl(packet_bufX
[i
]);
310 src
.data_in
= (float *)packet_bufX
;
311 src
.input_frames
= net_period_down
;
314 src
.output_frames
= nframes
;
316 src
.src_ratio
= (float) nframes
/ (float) net_period_down
;
317 src
.end_of_input
= 0;
319 src_set_ratio(src_state
, src
.src_ratio
);
320 src_process(src_state
, &src
);
321 src_node
= jack_slist_next (src_node
);
323 for (i
= 0; i
< net_period_down
; i
++) {
324 val
.i
= packet_bufX
[i
];
325 val
.i
= ntohl(val
.i
);
330 packet_bufX
= (packet_bufX
+ net_period_down
);
331 node
= jack_slist_next (node
);
336 void render_jack_ports_to_payload_float (JSList
*playback_ports
, JSList
*playback_srcs
, jack_nframes_t nframes
, void *packet_payload
, jack_nframes_t net_period_up
)
339 JSList
*node
= playback_ports
;
340 JSList
*src_node
= playback_srcs
;
342 uint32_t *packet_bufX
= (uint32_t *)packet_payload
;
344 while (node
!= NULL
) {
348 jack_port_t
*port
= (jack_port_t
*) node
->data
;
349 jack_default_audio_sample_t
* buf
= jack_port_get_buffer (port
, nframes
);
351 if (net_period_up
!= nframes
) {
352 SRC_STATE
*src_state
= src_node
->data
;
354 src
.input_frames
= nframes
;
356 src
.data_out
= (float *) packet_bufX
;
357 src
.output_frames
= net_period_up
;
359 src
.src_ratio
= (float) net_period_up
/ (float) nframes
;
360 src
.end_of_input
= 0;
362 src_set_ratio(src_state
, src
.src_ratio
);
363 src_process(src_state
, &src
);
365 for (i
= 0; i
< net_period_up
; i
++) {
366 packet_bufX
[i
] = htonl(packet_bufX
[i
]);
368 src_node
= jack_slist_next (src_node
);
370 for (i
= 0; i
< net_period_up
; i
++) {
372 val
.i
= htonl(val
.i
);
373 packet_bufX
[i
] = val
.i
;
377 packet_bufX
= (packet_bufX
+ net_period_up
);
378 node
= jack_slist_next (node
);
383 // render functions for 16bit
384 void render_payload_to_jack_ports_16bit( void *packet_payload
, jack_nframes_t net_period_down
, JSList
*capture_ports
, JSList
*capture_srcs
, jack_nframes_t nframes
)
387 JSList
*node
= capture_ports
;
388 JSList
*src_node
= capture_srcs
;
390 uint16_t *packet_bufX
= (uint16_t *)packet_payload
;
392 while (node
!= NULL
) {
397 jack_port_t
*port
= (jack_port_t
*) node
->data
;
398 jack_default_audio_sample_t
* buf
= jack_port_get_buffer (port
, nframes
);
400 float *floatbuf
= alloca(sizeof(float) * net_period_down
);
402 if (net_period_down
!= nframes
) {
403 SRC_STATE
*src_state
= src_node
->data
;
404 for (i
= 0; i
< net_period_down
; i
++) {
405 floatbuf
[i
] = ((float) ntohs(packet_bufX
[i
])) / 32767.0 - 1.0;
408 src
.data_in
= floatbuf
;
409 src
.input_frames
= net_period_down
;
412 src
.output_frames
= nframes
;
414 src
.src_ratio
= (float) nframes
/ (float) net_period_down
;
415 src
.end_of_input
= 0;
417 src_set_ratio(src_state
, src
.src_ratio
);
418 src_process(src_state
, &src
);
419 src_node
= jack_slist_next (src_node
);
421 for (i
= 0; i
< net_period_down
; i
++) {
422 buf
[i
] = ((float) ntohs(packet_bufX
[i
])) / 32768.0 - 1.0;
426 packet_bufX
= (packet_bufX
+ net_period_down
);
427 node
= jack_slist_next (node
);
432 void render_jack_ports_to_payload_16bit (JSList
*playback_ports
, JSList
*playback_srcs
, jack_nframes_t nframes
, void *packet_payload
, jack_nframes_t net_period_up
)
435 JSList
*node
= playback_ports
;
436 JSList
*src_node
= playback_srcs
;
438 uint16_t *packet_bufX
= (uint16_t *)packet_payload
;
440 while (node
!= NULL
) {
443 jack_port_t
*port
= (jack_port_t
*) node
->data
;
444 jack_default_audio_sample_t
* buf
= jack_port_get_buffer (port
, nframes
);
446 if (net_period_up
!= nframes
) {
447 SRC_STATE
*src_state
= src_node
->data
;
449 float *floatbuf
= alloca(sizeof(float) * net_period_up
);
452 src
.input_frames
= nframes
;
454 src
.data_out
= floatbuf
;
455 src
.output_frames
= net_period_up
;
457 src
.src_ratio
= (float) net_period_up
/ (float) nframes
;
458 src
.end_of_input
= 0;
460 src_set_ratio(src_state
, src
.src_ratio
);
461 src_process(src_state
, &src
);
463 for (i
= 0; i
< net_period_up
; i
++) {
464 packet_bufX
[i
] = htons((floatbuf
[i
] + 1.0) * 32767.0);
466 src_node
= jack_slist_next (src_node
);
468 for (i
= 0; i
< net_period_up
; i
++) {
469 packet_bufX
[i
] = htons((buf
[i
] + 1.0) * 32767.0);
473 packet_bufX
= (packet_bufX
+ net_period_up
);
474 node
= jack_slist_next (node
);
479 // render functions for 8bit
481 void render_payload_to_jack_ports_8bit(void *packet_payload
, jack_nframes_t net_period_down
, JSList
*capture_ports
, JSList
*capture_srcs
, jack_nframes_t nframes
)
484 JSList
*node
= capture_ports
;
485 JSList
*src_node
= capture_srcs
;
487 int8_t *packet_bufX
= (int8_t *)packet_payload
;
489 while (node
!= NULL
) {
494 jack_port_t
*port
= (jack_port_t
*) node
->data
;
495 jack_default_audio_sample_t
* buf
= jack_port_get_buffer (port
, nframes
);
497 float *floatbuf
= alloca(sizeof(float) * net_period_down
);
499 if (net_period_down
!= nframes
) {
500 SRC_STATE
*src_state
= src_node
->data
;
501 for (i
= 0; i
< net_period_down
; i
++) {
502 floatbuf
[i
] = ((float) packet_bufX
[i
]) / 127.0;
505 src
.data_in
= floatbuf
;
506 src
.input_frames
= net_period_down
;
509 src
.output_frames
= nframes
;
511 src
.src_ratio
= (float) nframes
/ (float) net_period_down
;
512 src
.end_of_input
= 0;
514 src_set_ratio(src_state
, src
.src_ratio
);
515 src_process(src_state
, &src
);
516 src_node
= jack_slist_next (src_node
);
518 for (i
= 0; i
< net_period_down
; i
++) {
519 buf
[i
] = ((float) packet_bufX
[i
]) / 127.0;
523 packet_bufX
= (packet_bufX
+ net_period_down
);
524 node
= jack_slist_next (node
);
529 void render_jack_ports_to_payload_8bit(JSList
*playback_ports
, JSList
*playback_srcs
, jack_nframes_t nframes
, void *packet_payload
, jack_nframes_t net_period_up
)
532 JSList
*node
= playback_ports
;
533 JSList
*src_node
= playback_srcs
;
535 int8_t *packet_bufX
= (int8_t *)packet_payload
;
537 while (node
!= NULL
) {
540 jack_port_t
*port
= (jack_port_t
*) node
->data
;
541 jack_default_audio_sample_t
* buf
= jack_port_get_buffer (port
, nframes
);
543 if (net_period_up
!= nframes
) {
544 SRC_STATE
*src_state
= src_node
->data
;
546 float *floatbuf
= alloca(sizeof(float) * net_period_up
);
549 src
.input_frames
= nframes
;
551 src
.data_out
= floatbuf
;
552 src
.output_frames
= net_period_up
;
554 src
.src_ratio
= (float) net_period_up
/ (float) nframes
;
555 src
.end_of_input
= 0;
557 src_set_ratio(src_state
, src
.src_ratio
);
558 src_process(src_state
, &src
);
560 for (i
= 0; i
< net_period_up
; i
++) {
561 packet_bufX
[i
] = floatbuf
[i
] * 127.0;
563 src_node
= jack_slist_next (src_node
);
565 for (i
= 0; i
< net_period_up
; i
++) {
566 packet_bufX
[i
] = buf
[i
] * 127.0;
570 packet_bufX
= (packet_bufX
+ net_period_up
);
571 node
= jack_slist_next (node
);
576 // wrapper functions with bitdepth argument...
577 void render_payload_to_jack_ports(int bitdepth
, void *packet_payload
, jack_nframes_t net_period_down
, JSList
*capture_ports
, JSList
*capture_srcs
, jack_nframes_t nframes
)
580 render_payload_to_jack_ports_8bit(packet_payload
, net_period_down
, capture_ports
, capture_srcs
, nframes
);
581 else if (bitdepth
== 16)
582 render_payload_to_jack_ports_16bit(packet_payload
, net_period_down
, capture_ports
, capture_srcs
, nframes
);
584 render_payload_to_jack_ports_float(packet_payload
, net_period_down
, capture_ports
, capture_srcs
, nframes
);
587 void render_jack_ports_to_payload(int bitdepth
, JSList
*playback_ports
, JSList
*playback_srcs
, jack_nframes_t nframes
, void *packet_payload
, jack_nframes_t net_period_up
)
590 render_jack_ports_to_payload_8bit(playback_ports
, playback_srcs
, nframes
, packet_payload
, net_period_up
);
591 else if (bitdepth
== 16)
592 render_jack_ports_to_payload_16bit(playback_ports
, playback_srcs
, nframes
, packet_payload
, net_period_up
);
594 render_jack_ports_to_payload_float(playback_ports
, playback_srcs
, nframes
, packet_payload
, net_period_up
);