JackNetInterface.cpp 30.1 KB
Newer Older
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
/*
Copyright (C) 2001 Paul Davis
Copyright (C) 2008 Romain Moret at Grame

This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.

*/

#include "JackNetInterface.h"
#include "JackException.h"

#define DEFAULT_MULTICAST_IP "225.3.19.154"
#define DEFAULT_PORT 19000

using namespace std;

namespace Jack
{
    // JackNetInterface*******************************************

moret's avatar
moret committed
33
    JackNetInterface::JackNetInterface ( const char* multicast_ip, int port ) : fSocket ( multicast_ip, port )
34
    {
moret's avatar
moret committed
35
        fMulticastIP = strdup ( multicast_ip );
36
37
    }

moret's avatar
moret committed
38
    JackNetInterface::JackNetInterface ( session_params_t& params, JackNetSocket& socket, const char* multicast_ip ) : fSocket ( socket )
39
    {
moret's avatar
moret committed
40
        fParams = params;
moret's avatar
moret committed
41
        fMulticastIP = strdup ( multicast_ip );
42
43
44
45
    }

    JackNetInterface::~JackNetInterface()
    {
moret's avatar
moret committed
46
        jack_log ( "JackNetInterface::~JackNetInterface" );
moret's avatar
moret committed
47

48
49
50
51
52
53
54
55
56
57
        fSocket.Close();
        delete[] fTxBuffer;
        delete[] fRxBuffer;
        delete[] fMulticastIP;
        delete fNetAudioCaptureBuffer;
        delete fNetAudioPlaybackBuffer;
        delete fNetMidiCaptureBuffer;
        delete fNetMidiPlaybackBuffer;
    }

moret's avatar
moret committed
58
59
    jack_nframes_t JackNetInterface::SetFramesPerPacket()
    {
moret's avatar
moret committed
60
        jack_log ( "JackNetInterface::SetFramesPerPacket" );
moret's avatar
moret committed
61

moret's avatar
moret committed
62
63
64
65
        if ( !fParams.fSendAudioChannels && !fParams.fReturnAudioChannels )
            return ( fParams.fFramesPerPacket = fParams.fPeriodSize );
        jack_nframes_t period = ( int ) powf ( 2.f, ( int ) ( log ( ( fParams.fMtu - sizeof ( packet_header_t ) )
                                               / ( max ( fParams.fReturnAudioChannels, fParams.fSendAudioChannels ) * sizeof ( sample_t ) ) ) / log ( 2 ) ) );
moret's avatar
moret committed
66
        return ( fParams.fFramesPerPacket = ( period > fParams.fPeriodSize ) ? fParams.fPeriodSize : period );
moret's avatar
moret committed
67
68
69
70
    }

    int JackNetInterface::SetNetBufferSize()
    {
moret's avatar
moret committed
71
        jack_log ( "JackNetInterface::SetNetBufferSize" );
moret's avatar
moret committed
72

moret's avatar
moret committed
73
74
75
76
77
78
        float audio_size, midi_size;
        int bufsize, res = 0;
        //audio
        audio_size = fParams.fMtu * ( fParams.fPeriodSize / fParams.fFramesPerPacket );
        //midi
        midi_size = fParams.fMtu * ( max ( fParams.fSendMidiChannels, fParams.fReturnMidiChannels ) *
moret's avatar
moret committed
79
                                     fParams.fPeriodSize * sizeof ( sample_t ) / ( fParams.fMtu - sizeof ( packet_header_t ) ) );
moret's avatar
moret committed
80
81
        //bufsize = sync + audio + midi
        bufsize = fParams.fMtu + ( int ) audio_size + ( int ) midi_size;
moret's avatar
moret committed
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115

        //tx buffer
        if ( fSocket.SetOption ( SOL_SOCKET, SO_SNDBUF, &bufsize, sizeof ( bufsize ) ) == SOCKET_ERROR )
            res = SOCKET_ERROR;

        //rx buffer
        if ( fSocket.SetOption ( SOL_SOCKET, SO_RCVBUF, &bufsize, sizeof ( bufsize ) ) == SOCKET_ERROR )
            res = SOCKET_ERROR;

        return res;
    }

    int JackNetInterface::GetNMidiPckt()
    {
        //even if there is no midi data, jack need an empty buffer to know there is no event to read
        //99% of the cases : all data in one packet
        if ( fTxHeader.fMidiDataSize <= ( fParams.fMtu - sizeof ( packet_header_t ) ) )
            return 1;
        //else, get the number of needed packets (simply slice the biiig buffer)
        int npckt = fTxHeader.fMidiDataSize / ( fParams.fMtu - sizeof ( packet_header_t ) );
        if ( fTxHeader.fMidiDataSize % ( fParams.fMtu - sizeof ( packet_header_t ) ) )
            return ++npckt;
        return npckt;
    }

    bool JackNetInterface::IsNextPacket()
    {
        packet_header_t* rx_head = reinterpret_cast<packet_header_t*> ( fRxBuffer );
        //ignore first cycle
        if ( fRxHeader.fCycle <= 1 )
            return true;
        //same PcktID (cycle), next SubPcktID (subcycle)
        if ( ( fRxHeader.fSubCycle < ( fNSubProcess - 1 ) ) && ( rx_head->fCycle == fRxHeader.fCycle ) && ( rx_head->fSubCycle == ( fRxHeader.fSubCycle + 1 ) ) )
            return true;
moret's avatar
moret committed
116
        //next PcktID (cycle), SubPcktID reset to 0 (first subcyle)
moret's avatar
moret committed
117
118
        if ( ( rx_head->fCycle == ( fRxHeader.fCycle + 1 ) ) && ( fRxHeader.fSubCycle == ( fNSubProcess - 1 ) ) && ( rx_head->fSubCycle == 0 ) )
            return true;
moret's avatar
moret committed
119
        //else, packet(s) missing, return false
moret's avatar
moret committed
120
121
122
        return false;
    }

123
124
    void JackNetInterface::SetParams()
    {
moret's avatar
moret committed
125
        //number of audio subcycles (packets)
126
127
        fNSubProcess = fParams.fPeriodSize / fParams.fFramesPerPacket;

moret's avatar
moret committed
128
129
130
        //payload size
        fPayloadSize = fParams.fMtu - sizeof ( packet_header_t );

131
132
133
134
135
136
137
        //TX header init
        strcpy ( fTxHeader.fPacketType, "header" );
        fTxHeader.fID = fParams.fID;
        fTxHeader.fCycle = 0;
        fTxHeader.fSubCycle = 0;
        fTxHeader.fMidiDataSize = 0;
        fTxHeader.fBitdepth = fParams.fBitdepth;
moret's avatar
moret committed
138
        fTxHeader.fIsLastPckt = 0;
139
140
141
142
143
144
145
146

        //RX header init
        strcpy ( fRxHeader.fPacketType, "header" );
        fRxHeader.fID = fParams.fID;
        fRxHeader.fCycle = 0;
        fRxHeader.fSubCycle = 0;
        fRxHeader.fMidiDataSize = 0;
        fRxHeader.fBitdepth = fParams.fBitdepth;
moret's avatar
moret committed
147
        fRxHeader.fIsLastPckt = 0;
148
149
150
151
152

        //network buffers
        fTxBuffer = new char[fParams.fMtu];
        fRxBuffer = new char[fParams.fMtu];

moret's avatar
moret committed
153
        //net audio/midi buffers'addresses
154
155
156
157
        fTxData = fTxBuffer + sizeof ( packet_header_t );
        fRxData = fRxBuffer + sizeof ( packet_header_t );
    }

158
    // JackNetMasterInterface ************************************************************************************
159

160
    bool JackNetMasterInterface::Init()
161
    {
162
        jack_log ( "JackNetMasterInterface::Init, ID %u.", fParams.fID );
163
164

        session_params_t params;
165
        uint attempt = 0;
166
167
168
169
170
        int rx_bytes = 0;

        //socket
        if ( fSocket.NewSocket() == SOCKET_ERROR )
        {
171
172
            jack_error ( "Can't create socket : %s", StrError ( NET_ERROR_CODE ) );
            return false;
173
174
        }

175
176
        //timeout on receive (for init)
        if ( fSocket.SetTimeOut ( 1000000 ) < 0 )
177
178
            jack_error ( "Can't set timeout : %s", StrError ( NET_ERROR_CODE ) );

179
180
181
182
183
184
        //connect
        if ( fSocket.Connect() == SOCKET_ERROR )
        {
            jack_error ( "Can't connect : %s", StrError ( NET_ERROR_CODE ) );
            return false;
        }
185

moret's avatar
moret committed
186
        //set the number of complete audio frames we can put in a packet
moret's avatar
moret committed
187
188
        SetFramesPerPacket();

189
190
        //send 'SLAVE_SETUP' until 'START_MASTER' received
        jack_info ( "Sending parameters to %s ...", fParams.fSlaveNetName );
191
192
        do
        {
193
194
195
196
            SetPacketType ( &fParams, SLAVE_SETUP );
            if ( fSocket.Send ( &fParams, sizeof ( session_params_t ), 0 ) == SOCKET_ERROR )
                jack_error ( "Error in send : ", StrError ( NET_ERROR_CODE ) );
            if ( ( ( rx_bytes = fSocket.Recv ( &params, sizeof ( session_params_t ), 0 ) ) == SOCKET_ERROR ) && ( fSocket.GetError() != NET_NO_DATA ) )
197
            {
198
199
                jack_error ( "Problem with network." );
                return false;
200
201
            }
        }
202
203
        while ( ( GetPacketType ( &params ) != START_MASTER ) && ( ++attempt < 5 ) );
        if ( attempt == 5 )
204
        {
205
206
            jack_error ( "Slave doesn't respond, exiting." );
            return false;
207
208
        }

209
        //set the new timeout for the socket
moret's avatar
moret committed
210
        if ( SetRxTimeout() == SOCKET_ERROR )
211
212
213
214
        {
            jack_error ( "Can't set rx timeout : %s", StrError ( NET_ERROR_CODE ) );
            return false;
        }
215

216
        //set the new rx buffer size
moret's avatar
moret committed
217
        if ( SetNetBufferSize() == SOCKET_ERROR )
218
        {
moret's avatar
moret committed
219
            jack_error ( "Can't set net buffer sizes : %s", StrError ( NET_ERROR_CODE ) );
220
            return false;
221
        }
222
223

        return true;
224
225
    }

moret's avatar
moret committed
226
227
228
229
230
    int JackNetMasterInterface::SetRxTimeout()
    {
        float time = 0;
        //slow mode, very short timeout on recv
        if ( fParams.fNetworkMode == 's' )
moret's avatar
moret committed
231
            time = 2000000.f * ( static_cast<float> ( fParams.fFramesPerPacket ) / static_cast<float> ( fParams.fSampleRate ) );
moret's avatar
moret committed
232
233
        //normal mode, short timeout on recv
        else if ( fParams.fNetworkMode == 'n' )
moret's avatar
moret committed
234
            time = 4000000.f * ( static_cast<float> ( fParams.fFramesPerPacket ) / static_cast<float> ( fParams.fSampleRate ) );
moret's avatar
moret committed
235
236
237
238
239
240
        //fast mode, wait for the entire cycle duration
        else if ( fParams.fNetworkMode == 'f' )
            time = 750000.f * ( static_cast<float> ( fParams.fPeriodSize ) / static_cast<float> ( fParams.fSampleRate ) );
        return fSocket.SetTimeOut ( static_cast<int> ( time ) );
    }

241
    void JackNetMasterInterface::SetParams()
moret's avatar
moret committed
242
    {
243
        jack_log ( "JackNetMasterInterface::SetParams" );
moret's avatar
moret committed
244
245
246

        JackNetInterface::SetParams();

247
248
        fTxHeader.fDataStream = 's';
        fRxHeader.fDataStream = 'r';
moret's avatar
moret committed
249
250

        //midi net buffers
251
252
        fNetMidiCaptureBuffer = new NetMidiBuffer ( &fParams, fParams.fSendMidiChannels, fTxData );
        fNetMidiPlaybackBuffer = new NetMidiBuffer ( &fParams, fParams.fReturnMidiChannels, fRxData );
moret's avatar
moret committed
253
254

        //audio net buffers
255
256
        fNetAudioCaptureBuffer = new NetAudioBuffer ( &fParams, fParams.fSendAudioChannels, fTxData );
        fNetAudioPlaybackBuffer = new NetAudioBuffer ( &fParams, fParams.fReturnAudioChannels, fRxData );
moret's avatar
moret committed
257
258
259
260
261
262

        //audio netbuffer length
        fAudioTxLen = sizeof ( packet_header_t ) + fNetAudioPlaybackBuffer->GetSize();
        fAudioRxLen = sizeof ( packet_header_t ) + fNetAudioCaptureBuffer->GetSize();
    }

263
    void JackNetMasterInterface::Exit()
264
    {
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
        jack_log ( "JackNetMasterInterface::Exit, ID %u", fParams.fID );

        //stop process
        fRunning = false;
        //send a 'multicast euthanasia request' - new socket is required on macosx
        jack_info ( "Exiting '%s'", fParams.fName );
        SetPacketType ( &fParams, KILL_MASTER );
        JackNetSocket mcast_socket ( fMulticastIP, fSocket.GetPort() );
        if ( mcast_socket.NewSocket() == SOCKET_ERROR )
            jack_error ( "Can't create socket : %s", StrError ( NET_ERROR_CODE ) );
        if ( mcast_socket.SendTo ( &fParams, sizeof ( session_params_t ), 0, fMulticastIP ) == SOCKET_ERROR )
            jack_error ( "Can't send suicide request : %s", StrError ( NET_ERROR_CODE ) );
        mcast_socket.Close();
    }

    int JackNetMasterInterface::Send ( size_t size, int flags )
    {
        int tx_bytes;
        if ( ( tx_bytes = fSocket.Send ( fTxBuffer, size, flags ) ) == SOCKET_ERROR )
284
285
        {
            net_error_t error = fSocket.GetError();
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
            if ( fRunning && ( error == NET_CONN_ERROR ) )
            {
                //fatal connection issue, exit
                jack_error ( "'%s' : %s, exiting.", fParams.fName, StrError ( NET_ERROR_CODE ) );
                Exit();
            }
            else if ( fRunning )
                jack_error ( "Error in send : %s", StrError ( NET_ERROR_CODE ) );
        }
        return tx_bytes;
    }

    int JackNetMasterInterface::Recv ( size_t size, int flags )
    {
        int rx_bytes;
        if ( ( rx_bytes = fSocket.Recv ( fRxBuffer, size, flags ) ) == SOCKET_ERROR )
        {
            net_error_t error = fSocket.GetError();
            //no data isn't really a network error, so just return 0 avalaible read bytes
305
            if ( error == NET_NO_DATA )
306
307
                return 0;
            else if ( fRunning && ( error == NET_CONN_ERROR ) )
308
            {
309
310
311
312
                //fatal connection issue, exit
                jack_error ( "'%s' : %s, exiting.", fParams.fName, StrError ( NET_ERROR_CODE ) );
                //ask to the manager to properly remove the master
                Exit();
313
            }
314
315
            else if ( fRunning )
                jack_error ( "Error in receive : %s", StrError ( NET_ERROR_CODE ) );
316
317
318
319
        }
        return rx_bytes;
    }

320
    int JackNetMasterInterface::SyncSend()
321
    {
322
323
324
        fTxHeader.fCycle++;
        fTxHeader.fSubCycle = 0;
        fTxHeader.fDataType = 's';
moret's avatar
moret committed
325
        fTxHeader.fIsLastPckt = ( !fParams.fSendMidiChannels && !fParams.fSendAudioChannels ) ?  1 : 0;
326
327
328
329
330
331
332
333
334
335
        fTxHeader.fPacketSize = fParams.fMtu;
        memcpy ( fTxBuffer, &fTxHeader, sizeof ( packet_header_t ) );
        return Send ( fTxHeader.fPacketSize, 0 );
    }

    int JackNetMasterInterface::DataSend()
    {
        uint subproc;
        //midi
        if ( fParams.fSendMidiChannels )
336
        {
337
338
339
            //set global header fields and get the number of midi packets
            fTxHeader.fDataType = 'm';
            fTxHeader.fMidiDataSize = fNetMidiCaptureBuffer->RenderFromJackPorts();
moret's avatar
moret committed
340
            fTxHeader.fNMidiPckt = GetNMidiPckt();
341
            for ( subproc = 0; subproc < fTxHeader.fNMidiPckt; subproc++ )
342
            {
343
                fTxHeader.fSubCycle = subproc;
moret's avatar
moret committed
344
                fTxHeader.fIsLastPckt = ( ( subproc == ( fTxHeader.fNMidiPckt - 1 ) ) && !fParams.fSendAudioChannels ) ? 1 : 0;
moret's avatar
moret committed
345
346
                fTxHeader.fPacketSize = sizeof ( packet_header_t );
                fTxHeader.fPacketSize += fNetMidiCaptureBuffer->RenderToNetwork ( subproc, fTxHeader.fMidiDataSize );
347
348
349
                memcpy ( fTxBuffer, &fTxHeader, sizeof ( packet_header_t ) );
                if ( Send ( fTxHeader.fPacketSize, 0 ) == SOCKET_ERROR )
                    return SOCKET_ERROR;
350
351
            }
        }
352
353
354
355
356
357
358
359

        //audio
        if ( fParams.fSendAudioChannels )
        {
            fTxHeader.fDataType = 'a';
            for ( subproc = 0; subproc < fNSubProcess; subproc++ )
            {
                fTxHeader.fSubCycle = subproc;
moret's avatar
moret committed
360
                fTxHeader.fIsLastPckt = ( subproc == ( fNSubProcess - 1 ) ) ? 1 : 0;
361
362
363
364
365
366
367
368
369
                fTxHeader.fPacketSize = fAudioTxLen;
                memcpy ( fTxBuffer, &fTxHeader, sizeof ( packet_header_t ) );
                fNetAudioCaptureBuffer->RenderFromJackPorts ( subproc );
                if ( Send ( fTxHeader.fPacketSize, 0 ) == SOCKET_ERROR )
                    return SOCKET_ERROR;
            }
        }

        return 0;
370
371
    }

372
    int JackNetMasterInterface::SyncRecv()
373
    {
374
375
        int rx_bytes = 0;
        int cycle_offset = 0;
376
        packet_header_t* rx_head = reinterpret_cast<packet_header_t*> ( fRxBuffer );
377
378
379
380
381
382
383
        rx_bytes = Recv ( fParams.fMtu, MSG_PEEK );
        if ( ( rx_bytes == 0 ) || ( rx_bytes == SOCKET_ERROR ) )
            return rx_bytes;

        cycle_offset = fTxHeader.fCycle - rx_head->fCycle;

        switch ( fParams.fNetworkMode )
384
        {
385
            case 's' :
moret's avatar
moret committed
386
387
388
389
390
                //slow mode : allow to use full bandwidth and heavy process on the slave
                //  - extra latency is set to two cycles, one cycle for send/receive operations + one cycle for heavy process on the slave
                //  - if the network is two fast, just wait the next cycle, this mode allows a shorter cycle duration for the master
                //  - this mode will skip the two first cycles, thus it lets time for data to be processed and queued on the socket rx buffer
                //the slow mode is the safest mode because it wait twice the bandwidth relative time (send/return + process)
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
                if ( cycle_offset < 2 )
                    return 0;
                else
                    rx_bytes = Recv ( rx_head->fPacketSize, 0 );
                break;
            case 'n' :
                //normal use of the network :
                //  - extra latency is set to one cycle, what is the time needed to receive streams using full network bandwidth
                //  - if the network is too fast, just wait the next cycle, the benefit here is the master's cycle is shorter
                //  - indeed, data is supposed to be on the network rx buffer, so we don't have to wait for it
                if ( cycle_offset < 1 )
                    return 0;
                else
                    rx_bytes = Recv ( rx_head->fPacketSize, 0 );
                break;
            case 'f' :
                //fast mode suppose the network bandwith is larger than required for the transmission (only a few channels for example)
                //    - packets can be quickly received, quickly is here relative to the cycle duration
                //    - here, receive data, we can't keep it queued on the rx buffer,
                //    - but if there is a cycle offset, tell the user, that means we're not in fast mode anymore, network is too slow
                rx_bytes = Recv ( rx_head->fPacketSize, 0 );
                if ( cycle_offset )
                    jack_error ( "'%s' can't run in fast network mode, data received too late (%d cycle(s) offset)", fParams.fName, cycle_offset );
                break;
415
        }
moret's avatar
moret committed
416
        fRxHeader.fIsLastPckt = rx_head->fIsLastPckt;
417
418
419
        return rx_bytes;
    }

420
    int JackNetMasterInterface::DataRecv()
421
422
    {
        int rx_bytes = 0;
423
424
        uint jumpcnt = 0;
        uint midi_recvd_pckt = 0;
425
426
        packet_header_t* rx_head = reinterpret_cast<packet_header_t*> ( fRxBuffer );

moret's avatar
moret committed
427
        while ( !fRxHeader.fIsLastPckt )
428
        {
moret's avatar
moret committed
429
430
431
432
            //how much data is queued on the rx buffer ?
            rx_bytes = Recv ( fParams.fMtu, MSG_PEEK );
            if ( rx_bytes == SOCKET_ERROR )
                return rx_bytes;
moret's avatar
moret committed
433
            //if no data
moret's avatar
moret committed
434
            if ( ( rx_bytes == 0 ) && ( ++jumpcnt == fNSubProcess ) )
435
            {
moret's avatar
moret committed
436
437
438
439
440
441
442
443
                jack_error ( "No data from %s...", fParams.fName );
                jumpcnt = 0;
            }
            //else if data is valid,
            if ( rx_bytes && ( rx_head->fDataStream == 'r' ) && ( rx_head->fID == fParams.fID ) )
            {
                //read data
                switch ( rx_head->fDataType )
444
                {
moret's avatar
moret committed
445
446
447
                    case 'm':   //midi
                        Recv ( rx_head->fPacketSize, 0 );
                        fRxHeader.fCycle = rx_head->fCycle;
moret's avatar
moret committed
448
                        fRxHeader.fIsLastPckt = rx_head->fIsLastPckt;
moret's avatar
moret committed
449
450
451
452
453
454
455
456
457
458
459
                        fNetMidiPlaybackBuffer->RenderFromNetwork ( rx_head->fSubCycle, rx_bytes - sizeof ( packet_header_t ) );
                        if ( ++midi_recvd_pckt == rx_head->fNMidiPckt )
                            fNetMidiPlaybackBuffer->RenderToJackPorts();
                        jumpcnt = 0;
                        break;
                    case 'a':   //audio
                        Recv ( rx_head->fPacketSize, 0 );
                        if ( !IsNextPacket() )
                            jack_error ( "Packet(s) missing from '%s'...", fParams.fName );
                        fRxHeader.fCycle = rx_head->fCycle;
                        fRxHeader.fSubCycle = rx_head->fSubCycle;
moret's avatar
moret committed
460
                        fRxHeader.fIsLastPckt = rx_head->fIsLastPckt;
moret's avatar
moret committed
461
462
463
464
465
466
                        fNetAudioPlaybackBuffer->RenderToJackPorts ( rx_head->fSubCycle );
                        jumpcnt = 0;
                        break;
                    case 's':   //sync
                        if ( rx_head->fCycle == fTxHeader.fCycle )
                            return 0;
467
468
469
                }
            }
        }
470
        return rx_bytes;
471
472
    }

473
474
475
// JackNetSlaveInterface ************************************************************************************************

    bool JackNetSlaveInterface::Init()
476
    {
477
        jack_log ( "JackNetSlaveInterface::Init()" );
478

479
480
481
482
        //set the parameters to send
        strcpy ( fParams.fPacketType, "params" );
        fParams.fProtocolVersion = 'a';
        SetPacketType ( &fParams, SLAVE_AVAILABLE );
483

484
485
486
        //init loop : get a master and start, do it until connection is ok
        net_status_t status;
        do
487
        {
488
489
            //first, get a master, do it until a valid connection is running
            do
490
            {
491
492
493
                status = GetNetMaster();
                if ( status == NET_SOCKET_ERROR )
                    return false;
494
            }
495
            while ( status != NET_CONNECTED );
496

497
498
            //then tell the master we are ready
            jack_info ( "Initializing connection with %s...", fParams.fMasterNetName );
moret's avatar
moret committed
499
            status = SendStartToMaster();
500
501
            if ( status == NET_ERROR )
                return false;
502
        }
503
        while ( status != NET_ROLLING );
504

505
506
        return true;
    }
507

508
    net_status_t JackNetSlaveInterface::GetNetMaster()
509
    {
510
511
        jack_log ( "JackNetSlaveInterface::GetNetMaster()" );
        //utility
512
513
        session_params_t params;
        int rx_bytes = 0;
514
        unsigned char loop = 0;
515
516
517
518

        //socket
        if ( fSocket.NewSocket() == SOCKET_ERROR )
        {
519
520
            jack_error ( "Fatal error : network unreachable - %s", StrError ( NET_ERROR_CODE ) );
            return NET_SOCKET_ERROR;
521
522
        }

523
524
525
526
527
528
        //bind the socket
        if ( fSocket.Bind() == SOCKET_ERROR )
            jack_error ( "Can't bind the socket : %s", StrError ( NET_ERROR_CODE ) );

        //timeout on receive
        if ( fSocket.SetTimeOut ( 2000000 ) == SOCKET_ERROR )
529
530
            jack_error ( "Can't set timeout : %s", StrError ( NET_ERROR_CODE ) );

531
532
533
        //disable local loop
        if ( fSocket.SetOption ( IPPROTO_IP, IP_MULTICAST_LOOP, &loop, sizeof ( loop ) ) == SOCKET_ERROR )
            jack_error ( "Can't disable multicast loop : %s", StrError ( NET_ERROR_CODE ) );
534

535
536
        //send 'AVAILABLE' until 'SLAVE_SETUP' received
        jack_info ( "Waiting for a master..." );
537
538
        do
        {
539
540
541
542
543
544
            //send 'available'
            if ( fSocket.SendTo ( &fParams, sizeof ( session_params_t ), 0, fMulticastIP ) == SOCKET_ERROR )
                jack_error ( "Error in data send : %s", StrError ( NET_ERROR_CODE ) );
            //filter incoming packets : don't exit while no error is detected
            rx_bytes = fSocket.CatchHost ( &params, sizeof ( session_params_t ), 0 );
            if ( ( rx_bytes == SOCKET_ERROR ) && ( fSocket.GetError() != NET_NO_DATA ) )
545
            {
546
547
                jack_error ( "Can't receive : %s", StrError ( NET_ERROR_CODE ) );
                return NET_RECV_ERROR;
548
549
            }
        }
550
        while ( strcmp ( params.fPacketType, fParams.fPacketType ) && ( GetPacketType ( &params ) != SLAVE_SETUP ) );
551

moret's avatar
moret committed
552
553
554
555
556
557
558
        //everything is OK, copy parameters
        fParams = params;

        //set the new buffer sizes
        if ( SetNetBufferSize() == SOCKET_ERROR )
            jack_error ( "Can't set net buffer sizes : %s", StrError ( NET_ERROR_CODE ) );

559
560
        //connect the socket
        if ( fSocket.Connect() == SOCKET_ERROR )
561
        {
562
563
            jack_error ( "Error in connect : %s", StrError ( NET_ERROR_CODE ) );
            return NET_CONNECT_ERROR;
564
565
        }

moret's avatar
moret committed
566
        return NET_CONNECTED;
567
568
    }

moret's avatar
moret committed
569
    net_status_t JackNetSlaveInterface::SendStartToMaster()
570
    {
moret's avatar
moret committed
571
        jack_log ( "JackNetSlaveInterface::SendStartToMaster" );
moret's avatar
moret committed
572

573
574
575
        //tell the master to start
        SetPacketType ( &fParams, START_MASTER );
        if ( fSocket.Send ( &fParams, sizeof ( session_params_t ), 0 ) == SOCKET_ERROR )
576
        {
577
578
            jack_error ( "Error in send : %s", StrError ( NET_ERROR_CODE ) );
            return ( fSocket.GetError() == NET_CONN_ERROR ) ? NET_ERROR : NET_SEND_ERROR;
579
        }
580
        return NET_ROLLING;
581
582
    }

583
    void JackNetSlaveInterface::SetParams()
moret's avatar
moret committed
584
    {
585
        jack_log ( "JackNetSlaveInterface::SetParams" );
moret's avatar
moret committed
586
587
588

        JackNetInterface::SetParams();

589
590
        fTxHeader.fDataStream = 'r';
        fRxHeader.fDataStream = 's';
moret's avatar
moret committed
591
592

        //midi net buffers
593
594
        fNetMidiCaptureBuffer = new NetMidiBuffer ( &fParams, fParams.fSendMidiChannels, fRxData );
        fNetMidiPlaybackBuffer = new NetMidiBuffer ( &fParams, fParams.fReturnMidiChannels, fTxData );
moret's avatar
moret committed
595
596

        //audio net buffers
597
598
        fNetAudioCaptureBuffer = new NetAudioBuffer ( &fParams, fParams.fSendAudioChannels, fRxData );
        fNetAudioPlaybackBuffer = new NetAudioBuffer ( &fParams, fParams.fReturnAudioChannels, fTxData );
moret's avatar
moret committed
599
600
601
602
603
604

        //audio netbuffer length
        fAudioTxLen = sizeof ( packet_header_t ) + fNetAudioPlaybackBuffer->GetSize();
        fAudioRxLen = sizeof ( packet_header_t ) + fNetAudioCaptureBuffer->GetSize();
    }

605
    int JackNetSlaveInterface::Recv ( size_t size, int flags )
606
    {
607
608
609
610
611
612
613
614
615
616
617
618
        int rx_bytes = fSocket.Recv ( fRxBuffer, size, flags );
        //handle errors
        if ( rx_bytes == SOCKET_ERROR )
        {
            net_error_t error = fSocket.GetError();
            //no data isn't really an error in realtime processing, so just return 0
            if ( error == NET_NO_DATA )
                jack_error ( "No data, is the master still running ?" );
            //if a network error occurs, this exception will restart the driver
            else if ( error == NET_CONN_ERROR )
            {
                jack_error ( "Connection lost." );
moret's avatar
moret committed
619
                throw JackNetException();
620
621
622
623
624
            }
            else
                jack_error ( "Fatal error in receive : %s", StrError ( NET_ERROR_CODE ) );
        }
        return rx_bytes;
625
626
    }

627
    int JackNetSlaveInterface::Send ( size_t size, int flags )
628
    {
629
630
631
        int tx_bytes = fSocket.Send ( fTxBuffer, size, flags );
        //handle errors
        if ( tx_bytes == SOCKET_ERROR )
632
633
        {
            net_error_t error = fSocket.GetError();
634
635
            //if a network error occurs, this exception will restart the driver
            if ( error == NET_CONN_ERROR )
636
            {
637
                jack_error ( "Connection lost." );
moret's avatar
moret committed
638
                throw JackNetException();
639
            }
640
641
            else
                jack_error ( "Fatal error in send : %s", StrError ( NET_ERROR_CODE ) );
642
643
644
645
        }
        return tx_bytes;
    }

646
    int JackNetSlaveInterface::SyncRecv()
647
    {
648
649
650
651
        int rx_bytes = 0;
        packet_header_t* rx_head = reinterpret_cast<packet_header_t*> ( fRxBuffer );
        //receive sync (launch the cycle)
        do
652
        {
653
654
655
656
657
658
            rx_bytes = Recv ( fParams.fMtu, 0 );
            //connection issue, send will detect it, so don't skip the cycle (return 0)
            if ( rx_bytes == SOCKET_ERROR )
                return rx_bytes;
        }
        while ( !rx_bytes && ( rx_head->fDataType != 's' ) );
moret's avatar
moret committed
659
        fRxHeader.fIsLastPckt = rx_head->fIsLastPckt;
660
661
662
663
664
665
666
667
668
        return rx_bytes;
    }

    int JackNetSlaveInterface::DataRecv()
    {
        uint recvd_midi_pckt = 0;
        int rx_bytes = 0;
        packet_header_t* rx_head = reinterpret_cast<packet_header_t*> ( fRxBuffer );

moret's avatar
moret committed
669
        while ( !fRxHeader.fIsLastPckt )
670
        {
moret's avatar
moret committed
671
672
            rx_bytes = Recv ( fParams.fMtu, MSG_PEEK );
            //error here, problem with recv, just skip the cycle (return -1)
moret's avatar
moret committed
673

moret's avatar
moret committed
674
675
676
            if ( rx_bytes == SOCKET_ERROR )
                return rx_bytes;
            if ( rx_bytes && ( rx_head->fDataStream == 's' ) && ( rx_head->fID == fParams.fID ) )
677
            {
moret's avatar
moret committed
678
                switch ( rx_head->fDataType )
679
                {
moret's avatar
moret committed
680
681
682
                    case 'm':   //midi
                        rx_bytes = Recv ( rx_head->fPacketSize, 0 );
                        fRxHeader.fCycle = rx_head->fCycle;
moret's avatar
moret committed
683
                        fRxHeader.fIsLastPckt = rx_head->fIsLastPckt;
moret's avatar
moret committed
684
685
686
687
688
689
690
691
692
693
                        fNetMidiCaptureBuffer->RenderFromNetwork ( rx_head->fSubCycle, rx_bytes - sizeof ( packet_header_t ) );
                        if ( ++recvd_midi_pckt == rx_head->fNMidiPckt )
                            fNetMidiCaptureBuffer->RenderToJackPorts();
                        break;
                    case 'a':   //audio
                        rx_bytes = Recv ( rx_head->fPacketSize, 0 );
                        if ( !IsNextPacket() )
                            jack_error ( "Packet(s) missing..." );
                        fRxHeader.fCycle = rx_head->fCycle;
                        fRxHeader.fSubCycle = rx_head->fSubCycle;
moret's avatar
moret committed
694
                        fRxHeader.fIsLastPckt = rx_head->fIsLastPckt;
moret's avatar
moret committed
695
696
697
698
699
                        fNetAudioCaptureBuffer->RenderToJackPorts ( rx_head->fSubCycle );
                        break;
                    case 's':   //sync
                        jack_info ( "NetSlave : overloaded, skipping receive." );
                        return 0;
700
                }
701
702
            }
        }
703
704
        fRxHeader.fCycle = rx_head->fCycle;
        return 0;
705
706
    }

707
    int JackNetSlaveInterface::SyncSend()
708
    {
709
710
711
712
713
        //tx header
        if ( fParams.fSlaveSyncMode )
            fTxHeader.fCycle = fRxHeader.fCycle;
        else
            fTxHeader.fCycle++;
714
715
        fTxHeader.fSubCycle = 0;
        fTxHeader.fDataType = 's';
moret's avatar
moret committed
716
        fTxHeader.fIsLastPckt = ( !fParams.fReturnMidiChannels && !fParams.fReturnAudioChannels ) ?  1 : 0;
717
718
719
720
721
        fTxHeader.fPacketSize = fParams.fMtu;
        memcpy ( fTxBuffer, &fTxHeader, sizeof ( packet_header_t ) );
        return Send ( fTxHeader.fPacketSize, 0 );
    }

722
    int JackNetSlaveInterface::DataSend()
723
724
    {
        uint subproc;
725

726
        //midi
727
        if ( fParams.fReturnMidiChannels )
728
729
        {
            fTxHeader.fDataType = 'm';
730
            fTxHeader.fMidiDataSize = fNetMidiPlaybackBuffer->RenderFromJackPorts();
moret's avatar
moret committed
731
            fTxHeader.fNMidiPckt = GetNMidiPckt();
732
733
734
            for ( subproc = 0; subproc < fTxHeader.fNMidiPckt; subproc++ )
            {
                fTxHeader.fSubCycle = subproc;
moret's avatar
moret committed
735
                fTxHeader.fIsLastPckt = ( ( subproc == ( fTxHeader.fNMidiPckt - 1 ) ) && !fParams.fReturnAudioChannels ) ? 1 : 0;
moret's avatar
moret committed
736
737
                fTxHeader.fPacketSize = sizeof ( packet_header_t );
                fTxHeader.fPacketSize += fNetMidiPlaybackBuffer->RenderToNetwork ( subproc, fTxHeader.fMidiDataSize );
738
739
                memcpy ( fTxBuffer, &fTxHeader, sizeof ( packet_header_t ) );
                if ( Send ( fTxHeader.fPacketSize, 0 ) == SOCKET_ERROR )
moret's avatar
moret committed
740
                    return SOCKET_ERROR;
741
742
743
744
            }
        }

        //audio
745
        if ( fParams.fReturnAudioChannels )
746
747
748
749
750
        {
            fTxHeader.fDataType = 'a';
            for ( subproc = 0; subproc < fNSubProcess; subproc++ )
            {
                fTxHeader.fSubCycle = subproc;
moret's avatar
moret committed
751
                fTxHeader.fIsLastPckt = ( subproc == ( fNSubProcess - 1 ) ) ? 1 : 0;
752
753
                fTxHeader.fPacketSize = fAudioTxLen;
                memcpy ( fTxBuffer, &fTxHeader, sizeof ( packet_header_t ) );
754
                fNetAudioPlaybackBuffer->RenderFromJackPorts ( subproc );
755
                if ( Send ( fTxHeader.fPacketSize, 0 ) == SOCKET_ERROR )
moret's avatar
moret committed
756
                    return SOCKET_ERROR;
757
758
759
760
761
            }
        }
        return 0;
    }
}