~ubuntu-branches/ubuntu/lucid/jack-audio-connection-kit/lucid

« back to all changes in this revision

Viewing changes to tools/netsource.c

  • Committer: Bazaar Package Importer
  • Author(s): Luca Falavigna
  • Date: 2008-12-06 11:05:15 UTC
  • mfrom: (4.1.3 sid)
  • Revision ID: james.westby@ubuntu.com-20081206110515-xa9v9pajr9jqvfvg
Tags: 0.115.6-1ubuntu1
* Merge from Debian unstable, remaining Ubuntu changes:
  - Redirect stderr in bash completion (Debian #504488).

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
NetJack Client
 
3
 
 
4
Copyright (C) 2008 Marc-Olivier Barre <marco@marcochapeau.org>
 
5
Copyright (C) 2008 Pieter Palmers <pieterpalmers@users.sourceforge.net>
 
6
Copyright (C) 2006 Torben Hohn <torbenh@gmx.de>
 
7
 
 
8
This program is free software; you can redistribute it and/or modify
 
9
it under the terms of the GNU General Public License as published by
 
10
the Free Software Foundation; either version 2 of the License, or
 
11
(at your option) any later version.
 
12
 
 
13
This program is distributed in the hope that it will be useful,
 
14
but WITHOUT ANY WARRANTY; without even the implied warranty of
 
15
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
16
GNU General Public License for more details.
 
17
 
 
18
You should have received a copy of the GNU General Public License
 
19
along with this program; if not, write to the Free Software
 
20
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 
21
 
 
22
*/
 
23
 
 
24
/** @file netsource.c
 
25
 *
 
26
 * @brief This client connects a remote slave JACK to a local JACK server assumed to be the master
 
27
 */
 
28
 
 
29
#include "config.h" 
 
30
 
 
31
#include <stdio.h>
 
32
#include <errno.h>
 
33
#include <unistd.h>
 
34
#include <stdlib.h>
 
35
#include <string.h>
 
36
 
 
37
#include <netinet/in.h>
 
38
#include <netdb.h>
 
39
 
 
40
/* These two required by FreeBSD. */
 
41
#include <sys/types.h>
 
42
#include <sys/socket.h>
 
43
 
 
44
#if HAVE_ALLOCA_H
 
45
#include <alloca.h>
 
46
#endif
 
47
 
 
48
#include <jack/jack.h>
 
49
 
 
50
#include <net_driver.h>
 
51
#include <netjack_packet.h>
 
52
#include <samplerate.h>
 
53
 
 
54
#ifdef HAVE_CELT
 
55
#include <celt/celt.h>
 
56
#endif
 
57
 
 
58
JSList *capture_ports = NULL;
 
59
JSList *capture_srcs = NULL;
 
60
int capture_channels = 0;
 
61
int capture_channels_audio = 2;
 
62
int capture_channels_midi = 1;
 
63
JSList *playback_ports = NULL;
 
64
JSList *playback_srcs = NULL;
 
65
int playback_channels = 0;
 
66
int playback_channels_audio = 2;
 
67
int playback_channels_midi = 1;
 
68
 
 
69
int latency = 5;
 
70
jack_nframes_t factor = 1;
 
71
int bitdepth = 0;
 
72
int mtu = 1400;
 
73
int reply_port = 0;
 
74
jack_client_t *client;
 
75
 
 
76
int state_connected = 0;
 
77
int state_latency = 0;
 
78
int state_netxruns = 0;
 
79
int state_currentframe = 0;
 
80
 
 
81
 
 
82
int outsockfd;
 
83
int insockfd;
 
84
struct sockaddr destaddr;
 
85
struct sockaddr bindaddr;
 
86
 
 
87
int sync_state;
 
88
jack_transport_state_t last_transport_state;
 
89
 
 
90
int framecnt = 0;
 
91
 
 
92
int cont_miss = 0;
 
93
 
 
94
/**
 
95
 * This Function allocates all the I/O Ports which are added the lists.
 
96
 */
 
97
void
 
98
alloc_ports (int n_capture_audio, int n_playback_audio, int n_capture_midi, int n_playback_midi)
 
99
{
 
100
 
 
101
    int port_flags = JackPortIsOutput;
 
102
    int chn;
 
103
    jack_port_t *port;
 
104
    char buf[32];
 
105
 
 
106
    capture_ports = NULL;
 
107
    /* Allocate audio capture channels */
 
108
    for (chn = 0; chn < n_capture_audio; chn++)
 
109
    {
 
110
        snprintf (buf, sizeof (buf) - 1, "capture_%u", chn + 1);
 
111
        port = jack_port_register (client, buf, JACK_DEFAULT_AUDIO_TYPE, port_flags, 0);
 
112
        if (!port)
 
113
        {
 
114
            printf( "jack_netsource: cannot register %s port\n", buf);
 
115
            break;
 
116
        }
 
117
        if( bitdepth == 1000 ) {
 
118
#ifdef HAVE_CELT
 
119
            // XXX: memory leak
 
120
            CELTMode *celt_mode = celt_mode_create( jack_get_sample_rate( client ), 1, jack_get_buffer_size(client), NULL );
 
121
            capture_srcs = jack_slist_append(capture_srcs, celt_decoder_create( celt_mode ) );
 
122
#endif
 
123
        } else {
 
124
            capture_srcs = jack_slist_append (capture_srcs, src_new (SRC_LINEAR, 1, NULL));
 
125
        }
 
126
        capture_ports = jack_slist_append (capture_ports, port);
 
127
    }
 
128
 
 
129
    /* Allocate midi capture channels */
 
130
    for (chn = n_capture_audio; chn < n_capture_midi + n_capture_audio; chn++)
 
131
    {
 
132
        snprintf (buf, sizeof (buf) - 1, "capture_%u", chn + 1);
 
133
        port = jack_port_register (client, buf, JACK_DEFAULT_MIDI_TYPE, port_flags, 0);
 
134
        if (!port)
 
135
        {
 
136
            printf ("jack_netsource: cannot register %s port\n", buf);
 
137
            break;
 
138
        }
 
139
        capture_ports = jack_slist_append(capture_ports, port);
 
140
    }
 
141
 
 
142
    /* Allocate audio playback channels */
 
143
    port_flags = JackPortIsInput;
 
144
    playback_ports = NULL;
 
145
    for (chn = 0; chn < n_playback_audio; chn++)
 
146
    {
 
147
        snprintf (buf, sizeof (buf) - 1, "playback_%u", chn + 1);
 
148
        port = jack_port_register (client, buf, JACK_DEFAULT_AUDIO_TYPE, port_flags, 0);
 
149
        if (!port)
 
150
        {
 
151
            printf ("jack_netsource: cannot register %s port\n", buf);
 
152
            break;
 
153
        }
 
154
        if( bitdepth == 1000 ) {
 
155
#ifdef HAVE_CELT
 
156
            // XXX: memory leak
 
157
            CELTMode *celt_mode = celt_mode_create( jack_get_sample_rate (client), 1, jack_get_buffer_size(client), NULL );
 
158
            playback_srcs = jack_slist_append(playback_srcs, celt_encoder_create( celt_mode ) );
 
159
#endif
 
160
        } else {
 
161
            playback_srcs = jack_slist_append (playback_srcs, src_new (SRC_LINEAR, 1, NULL));
 
162
        }
 
163
        playback_ports = jack_slist_append (playback_ports, port);
 
164
    }
 
165
 
 
166
    /* Allocate midi playback channels */
 
167
    for (chn = n_playback_audio; chn < n_playback_midi + n_playback_audio; chn++)
 
168
    {
 
169
        snprintf (buf, sizeof (buf) - 1, "playback_%u", chn + 1);
 
170
        port = jack_port_register (client, buf, JACK_DEFAULT_MIDI_TYPE, port_flags, 0);
 
171
        if (!port)
 
172
        {
 
173
            printf ("jack_netsource: cannot register %s port\n", buf);
 
174
            break;
 
175
        }
 
176
        playback_ports = jack_slist_append (playback_ports, port);
 
177
    }
 
178
}
 
179
 
 
180
/**
 
181
 * The Sync callback... sync state is set elsewhere...
 
182
 * we will see if this is working correctly.
 
183
 * i dont really believe in it yet.
 
184
 */
 
185
int
 
186
sync_cb (jack_transport_state_t state, jack_position_t *pos, void *arg) 
 
187
{
 
188
    static int latency_count = 0;
 
189
    int retval = sync_state;
 
190
 
 
191
    if (latency_count) {
 
192
        latency_count--;
 
193
        retval = 0;
 
194
    }
 
195
 
 
196
    else if (state == JackTransportStarting && last_transport_state != JackTransportStarting)
 
197
    {
 
198
        retval = 0;
 
199
        latency_count = latency - 1;
 
200
    }
 
201
 
 
202
    last_transport_state = state;
 
203
    return retval;
 
204
}
 
205
 
 
206
/**
 
207
 * The process callback for this JACK application.
 
208
 * It is called by JACK at the appropriate times.
 
209
 */
 
210
int
 
211
process (jack_nframes_t nframes, void *arg)
 
212
{
 
213
    jack_nframes_t net_period;
 
214
 
 
215
    if( bitdepth == 1000 )
 
216
        net_period = factor;
 
217
    else
 
218
        net_period = (float) nframes / (float) factor;
 
219
 
 
220
    int rx_bufsize =  get_sample_size (bitdepth) * capture_channels * net_period + sizeof (jacknet_packet_header);
 
221
    int tx_bufsize =  get_sample_size (bitdepth) * playback_channels * net_period + sizeof (jacknet_packet_header);
 
222
 
 
223
    jack_default_audio_sample_t *buf;
 
224
    jack_port_t *port;
 
225
    JSList *node;
 
226
    channel_t chn;
 
227
    int size, i;
 
228
    const char *porttype;
 
229
 
 
230
    jack_position_t local_trans_pos;
 
231
 
 
232
    uint32_t *packet_buf, *packet_bufX;
 
233
 
 
234
    /* Allocate a buffer where both In and Out Buffer will fit */
 
235
    packet_buf = alloca ((rx_bufsize > tx_bufsize) ? rx_bufsize : tx_bufsize);
 
236
 
 
237
    jacknet_packet_header *pkthdr = (jacknet_packet_header *) packet_buf;
 
238
 
 
239
    packet_bufX = packet_buf + sizeof (jacknet_packet_header) / sizeof (uint32_t);
 
240
 
 
241
    // New Receive Code:
 
242
    if (reply_port)
 
243
        packet_cache_drain_socket(global_packcache, insockfd);
 
244
    else
 
245
        packet_cache_drain_socket(global_packcache, outsockfd);
 
246
 
 
247
    size = packet_cache_retreive_packet( global_packcache, framecnt - latency, (char *)packet_buf, rx_bufsize ); 
 
248
 
 
249
    /* First alternative : we received what we expected. Render the data
 
250
     * to the JACK ports so it can be played. */
 
251
    if (size == rx_bufsize)
 
252
    {
 
253
        if (cont_miss)
 
254
        {
 
255
            //printf("Frame %d  \tRecovered from dropouts\n", framecnt);
 
256
            cont_miss = 0;
 
257
        }
 
258
        render_payload_to_jack_ports (bitdepth, packet_bufX, net_period, capture_ports, capture_srcs, nframes);
 
259
 
 
260
        /* Now evaluate packet header */
 
261
        //if (sync_state != pkthdr->sync_state)
 
262
        //    printf ("Frame %d  \tSync has been set\n", framecnt);
 
263
 
 
264
        state_currentframe = framecnt;
 
265
        //state_latency = framecnt - pkthdr->framecnt;
 
266
        state_connected = 1;
 
267
        sync_state = pkthdr->sync_state;
 
268
    }
 
269
    /* Second alternative : we've received something that's not
 
270
     * as big as expected or we missed a packet. We render silence
 
271
     * to the ouput ports */
 
272
    else
 
273
    {
 
274
        jack_nframes_t latency_estimate;
 
275
        if( packet_cache_find_latency( global_packcache, framecnt, &latency_estimate ) )
 
276
                state_latency = latency_estimate;
 
277
 
 
278
        // Set the counters up.
 
279
        state_currentframe = framecnt;
 
280
        //state_latency = framecnt - pkthdr->framecnt;
 
281
        state_netxruns += 1;
 
282
 
 
283
        //printf ("Frame %d  \tPacket missed or incomplete (expected: %d bytes, got: %d bytes)\n", framecnt, rx_bufsize, size);
 
284
        //printf ("Frame %d  \tPacket missed or incomplete\n", framecnt);
 
285
        cont_miss += 1;
 
286
        chn = 0;
 
287
        node = capture_ports;
 
288
        while (node != NULL)
 
289
        {
 
290
            port = (jack_port_t *) node->data;
 
291
            buf = jack_port_get_buffer (port, nframes);
 
292
            porttype = jack_port_type (port);
 
293
            if (strncmp (porttype, JACK_DEFAULT_AUDIO_TYPE, jack_port_type_size ()) == 0)
 
294
                for (i = 0; i < nframes; i++)
 
295
                    buf[i] = 0.0;
 
296
            else if (strncmp (porttype, JACK_DEFAULT_MIDI_TYPE, jack_port_type_size ()) == 0)
 
297
                jack_midi_clear_buffer (buf);
 
298
            node = jack_slist_next (node);
 
299
            chn++;
 
300
        }
 
301
    }
 
302
    /* reset packet_bufX... */
 
303
    packet_bufX = packet_buf + sizeof (jacknet_packet_header) / sizeof (jack_default_audio_sample_t);
 
304
 
 
305
    /* ---------- Send ---------- */
 
306
    render_jack_ports_to_payload (bitdepth, playback_ports, playback_srcs, nframes, packet_bufX, net_period);
 
307
 
 
308
    /* fill in packet hdr */
 
309
    pkthdr->transport_state = jack_transport_query (client, &local_trans_pos);
 
310
    pkthdr->transport_frame = local_trans_pos.frame;
 
311
    pkthdr->framecnt = framecnt;
 
312
    pkthdr->latency = latency;
 
313
    pkthdr->reply_port = reply_port; 
 
314
    pkthdr->sample_rate = jack_get_sample_rate (client);
 
315
    pkthdr->period_size = nframes;
 
316
 
 
317
    /* playback for us is capture on the other side */
 
318
    pkthdr->capture_channels_audio = playback_channels_audio;
 
319
    pkthdr->playback_channels_audio = capture_channels_audio;
 
320
    pkthdr->capture_channels_midi = playback_channels_midi;
 
321
    pkthdr->playback_channels_midi = capture_channels_midi;
 
322
    pkthdr->mtu = mtu;
 
323
    
 
324
    packet_header_hton (pkthdr);
 
325
    if (cont_miss < 2*latency+5)
 
326
        netjack_sendto (outsockfd, (char *) packet_buf, tx_bufsize, 0, &destaddr, sizeof (destaddr), mtu);
 
327
//    else if (cont_miss >= 10 && cont_miss <= 50)
 
328
//        printf ("Frame %d  \tToo many packets missed (%d). We have stopped sending data\n", framecnt, cont_miss);
 
329
    else if (cont_miss > 50+5*latency)
 
330
    {
 
331
        state_connected = 0;
 
332
        //printf ("Frame %d  \tRealy too many packets missed (%d). Let's reset the counter\n", framecnt, cont_miss);
 
333
        cont_miss = 5;
 
334
    }
 
335
 
 
336
    framecnt++;
 
337
    return 0;      
 
338
}
 
339
 
 
340
/**
 
341
 * This is the shutdown callback for this JACK application.
 
342
 * It is called by JACK if the server ever shuts down or
 
343
 * decides to disconnect the client.
 
344
 */
 
345
 
 
346
void
 
347
jack_shutdown (void *arg)
 
348
{
 
349
    exit (1);
 
350
}
 
351
 
 
352
void
 
353
init_sockaddr_in (struct sockaddr_in *name , const char *hostname , uint16_t port)
 
354
{
 
355
    name->sin_family = AF_INET ;
 
356
    name->sin_port = htons (port);
 
357
    if (hostname)
 
358
    {
 
359
        struct hostent *hostinfo = gethostbyname (hostname);
 
360
        if (hostinfo == NULL)
 
361
            fprintf (stderr, "init_sockaddr_in: unknown host: %s.\n", hostname);
 
362
        name->sin_addr = *(struct in_addr *) hostinfo->h_addr ;
 
363
    }
 
364
    else
 
365
        name->sin_addr.s_addr = htonl (INADDR_ANY) ;
 
366
}
 
367
 
 
368
void 
 
369
printUsage ()
 
370
{
 
371
fprintf (stderr, "usage: jack_netsource -h <host peer> [options]\n"
 
372
        "\n"
 
373
        "  -n <jack name> - Reports a different name to jack\n"
 
374
        "  -s <server name> - The name of the local jack server\n"
 
375
        "  -h <host_peer> - Host name of the slave JACK\n"
 
376
        "  -p <port> - UDP port used by the slave JACK\n"
 
377
        "  -P <num channels> - Number of audio playback channels\n"
 
378
        "  -C <num channels> - Number of audio capture channels\n"
 
379
        "  -o <num channels> - Number of midi playback channels\n"
 
380
        "  -i <num channels> - Number of midi capture channels\n"
 
381
        "  -l <latency> - Network latency in number of NetJack frames\n"
 
382
        "  -r <reply port> - Local UDP port to use\n"
 
383
        "  -f <downsample ratio> - Downsample data in the wire by this factor\n"
 
384
        "  -b <bitdepth> - Set transport to use 16bit or 8bit\n"
 
385
        "  -m <mtu> - Assume this mtu for the link\n"
 
386
        "  -c <bytes> - Use Celt and encode <bytes> per channel and packet.\n"
 
387
        "\n");
 
388
}
 
389
 
 
390
int
 
391
main (int argc, char *argv[])
 
392
{
 
393
    /* Some startup related basics */    
 
394
    char *client_name, *server_name = NULL, *peer_ip;
 
395
    int peer_port = 3000;
 
396
    jack_options_t options = JackNullOption;
 
397
    jack_status_t status;
 
398
 
 
399
    /* Torben's famous state variables, aka "the reporting API" ! */
 
400
    int statecopy_connected, statecopy_latency, statecopy_netxruns;
 
401
 
 
402
    /* Argument parsing stuff */    
 
403
    extern char *optarg;
 
404
    extern int optind, optopt;
 
405
    int errflg=0, c;
 
406
 
 
407
    if (argc < 3)
 
408
    {
 
409
        printUsage ();
 
410
        return 1;
 
411
    }
 
412
    
 
413
    client_name = (char *) malloc (sizeof (char) * 9);
 
414
    peer_ip = (char *) malloc (sizeof (char) * 9);
 
415
    sprintf(client_name, "netsource");
 
416
    sprintf(peer_ip, "localhost");
 
417
 
 
418
    while ((c = getopt (argc, argv, ":n:s:h:p:C:P:i:o:l:r:f:b:m:c:")) != -1)
 
419
    {
 
420
        switch (c)
 
421
        {
 
422
            case 'n':
 
423
            free(client_name);
 
424
            client_name = (char *) malloc (sizeof (char) * strlen (optarg));
 
425
            strcpy (client_name, optarg);
 
426
            break;
 
427
            case 's':
 
428
            server_name = (char *) malloc (sizeof (char) * strlen (optarg));
 
429
            strcpy (server_name, optarg);
 
430
            options |= JackServerName;
 
431
            break;
 
432
            case 'h':
 
433
            free(peer_ip);
 
434
            peer_ip = (char *) malloc (sizeof (char) * strlen (optarg));
 
435
            strcpy (peer_ip, optarg);
 
436
            break;
 
437
            case 'p':
 
438
            peer_port = atoi (optarg);
 
439
            break;
 
440
            case 'P':
 
441
            playback_channels_audio = atoi (optarg);
 
442
            break;
 
443
            case 'C':
 
444
            capture_channels_audio = atoi (optarg);
 
445
            break;
 
446
            case 'o':
 
447
            playback_channels_midi = atoi (optarg);
 
448
            break;
 
449
            case 'i':
 
450
            capture_channels_midi = atoi (optarg);
 
451
            break;
 
452
            case 'l':
 
453
            latency = atoi (optarg);
 
454
            break;
 
455
            case 'r':
 
456
            reply_port = atoi (optarg);
 
457
            break;
 
458
            case 'f':
 
459
            factor = atoi (optarg);
 
460
            break;
 
461
            case 'b':
 
462
            bitdepth = atoi (optarg);
 
463
            break;
 
464
            case 'c':
 
465
#ifdef HAVE_CELT
 
466
            bitdepth = 1000;
 
467
            factor = atoi (optarg);
 
468
#else
 
469
            printf( "not built with celt supprt\n" );
 
470
            exit(10);
 
471
#endif
 
472
            break;
 
473
            case 'm':
 
474
            mtu = atoi (optarg);
 
475
            break;
 
476
            case ':':
 
477
            fprintf (stderr, "Option -%c requires an operand\n", optopt);
 
478
            errflg++;
 
479
            break;
 
480
            case '?':
 
481
            fprintf (stderr, "Unrecognized option: -%c\n", optopt);
 
482
            errflg++;
 
483
        }
 
484
    }
 
485
    if (errflg)
 
486
    {
 
487
        printUsage ();
 
488
        exit (2);
 
489
    }
 
490
 
 
491
    capture_channels = capture_channels_audio + capture_channels_midi;
 
492
    playback_channels = playback_channels_audio + playback_channels_midi;
 
493
    
 
494
    outsockfd = socket (PF_INET, SOCK_DGRAM, 0);
 
495
    insockfd = socket (PF_INET, SOCK_DGRAM, 0);
 
496
    init_sockaddr_in ((struct sockaddr_in *) &destaddr, peer_ip, peer_port);
 
497
    if(reply_port)
 
498
    {
 
499
        init_sockaddr_in ((struct sockaddr_in *) &bindaddr, NULL, reply_port);
 
500
        bind (insockfd, &bindaddr, sizeof (bindaddr));
 
501
    }
 
502
 
 
503
    /* try to become a client of the JACK server */
 
504
    client = jack_client_open (client_name, options, &status, server_name);
 
505
    if (client == NULL)
 
506
    {
 
507
        fprintf (stderr, "jack_client_open() failed, status = 0x%2.0x\n"
 
508
                         "Is the JACK server running ?\n", status);
 
509
        return 1;
 
510
    }
 
511
 
 
512
    /* Set up jack callbacks */
 
513
    jack_set_process_callback (client, process, 0);
 
514
    jack_set_sync_callback (client, sync_cb, 0);
 
515
    jack_on_shutdown (client, jack_shutdown, 0);
 
516
 
 
517
    alloc_ports (capture_channels_audio, playback_channels_audio, capture_channels_midi, playback_channels_midi);
 
518
 
 
519
    jack_nframes_t net_period = (float) jack_get_buffer_size (client) / (float) factor;
 
520
    int rx_bufsize =  get_sample_size (bitdepth) * capture_channels * net_period + sizeof (jacknet_packet_header);
 
521
    global_packcache = packet_cache_new (latency + 5, rx_bufsize, mtu);
 
522
 
 
523
    /* tell the JACK server that we are ready to roll */
 
524
    if (jack_activate (client))
 
525
    {
 
526
        fprintf (stderr, "Cannot activate client");
 
527
        return 1;
 
528
    }
 
529
 
 
530
    /* Now sleep forever... and evaluate the state_ vars */
 
531
 
 
532
    statecopy_connected = 2; // make it report unconnected on start.
 
533
    statecopy_latency = state_latency;
 
534
    statecopy_netxruns = state_netxruns;
 
535
 
 
536
    while (1)
 
537
    {
 
538
        sleep (1);
 
539
        if (statecopy_connected != state_connected)
 
540
        {
 
541
            statecopy_connected = state_connected;
 
542
            if (statecopy_connected)
 
543
            {
 
544
                state_netxruns = 1; // We want to reset the netxrun count on each new connection
 
545
                printf ("Connected :-)\n");
 
546
            }
 
547
            else
 
548
                printf ("Not Connected\n");
 
549
        }
 
550
 
 
551
            if (statecopy_connected)
 
552
            {
 
553
            if (statecopy_netxruns != state_netxruns) {
 
554
            statecopy_netxruns = state_netxruns;
 
555
            printf ("at frame %06d -> total netxruns %d\n", state_currentframe, statecopy_netxruns);
 
556
            }
 
557
        }
 
558
        else
 
559
        {
 
560
            if (statecopy_latency != state_latency)
 
561
            {
 
562
                statecopy_latency = state_latency;
 
563
                if (statecopy_latency > 1)
 
564
                printf ("current latency %d\n", statecopy_latency);
 
565
            }
 
566
        }
 
567
    }
 
568
 
 
569
    /* Never reached. Well we will be a GtkApp someday... */
 
570
    packet_cache_free (global_packcache);
 
571
    jack_client_close (client);
 
572
    exit (0);
 
573
}