JackNetInterface.cpp 37.9 KB
Newer Older
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
/*
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"
22
#include "JackPlatformPlug.h"
23
#include <assert.h>
24
25
26

using namespace std;

27
28
29
30
31
32
/*  
 TODO : since midi buffers now uses up to BUFFER_SIZE_MAX frames, 
 probably also use BUFFER_SIZE_MAX in everything related to MIDI events 
 handling (see MidiBufferInit in JackMidiPort.cpp)
*/

33
34
35
36
namespace Jack
{
    // JackNetInterface*******************************************

37
38
39
40
41
42
43
44
    JackNetInterface::JackNetInterface() : fSocket()
    {
        fTxBuffer = NULL;
        fRxBuffer = NULL;
        fNetAudioCaptureBuffer = NULL;
        fNetAudioPlaybackBuffer = NULL;
        fNetMidiCaptureBuffer = NULL;
        fNetMidiPlaybackBuffer = NULL;
45
46
        memset(&fSendTransportData, 0, sizeof(net_transport_data_t));
        memset(&fReturnTransportData, 0, sizeof(net_transport_data_t));
47
48
    }

moret's avatar
moret committed
49
    JackNetInterface::JackNetInterface ( const char* multicast_ip, int port ) : fSocket ( multicast_ip, port )
50
    {
51
        strcpy(fMulticastIP, multicast_ip);
52
53
54
55
56
57
        fTxBuffer = NULL;
        fRxBuffer = NULL;
        fNetAudioCaptureBuffer = NULL;
        fNetAudioPlaybackBuffer = NULL;
        fNetMidiCaptureBuffer = NULL;
        fNetMidiPlaybackBuffer = NULL;
58
59
        memset(&fSendTransportData, 0, sizeof(net_transport_data_t));
        memset(&fReturnTransportData, 0, sizeof(net_transport_data_t));
60
61
    }

moret's avatar
moret committed
62
    JackNetInterface::JackNetInterface ( session_params_t& params, JackNetSocket& socket, const char* multicast_ip ) : fSocket ( socket )
63
    {
moret's avatar
moret committed
64
        fParams = params;
65
        strcpy(fMulticastIP, multicast_ip);
66
67
68
69
70
71
        fTxBuffer = NULL;
        fRxBuffer = NULL;
        fNetAudioCaptureBuffer = NULL;
        fNetAudioPlaybackBuffer = NULL;
        fNetMidiCaptureBuffer = NULL;
        fNetMidiPlaybackBuffer = NULL;
72
73
        memset(&fSendTransportData, 0, sizeof(net_transport_data_t));
        memset(&fReturnTransportData, 0, sizeof(net_transport_data_t));
74
75
76
77
    }

    JackNetInterface::~JackNetInterface()
    {
moret's avatar
moret committed
78
        jack_log ( "JackNetInterface::~JackNetInterface" );
moret's avatar
moret committed
79

80
81
82
83
84
85
86
87
88
        fSocket.Close();
        delete[] fTxBuffer;
        delete[] fRxBuffer;
        delete fNetAudioCaptureBuffer;
        delete fNetAudioPlaybackBuffer;
        delete fNetMidiCaptureBuffer;
        delete fNetMidiPlaybackBuffer;
    }

89
    void JackNetInterface::SetFramesPerPacket()
moret's avatar
moret committed
90
    {
moret's avatar
moret committed
91
        jack_log ( "JackNetInterface::SetFramesPerPacket" );
moret's avatar
moret committed
92

93
94
95
96
97
98
99
        if (fParams.fSendAudioChannels == 0 && fParams.fReturnAudioChannels == 0) {
            fParams.fFramesPerPacket = fParams.fPeriodSize;
        } else {
            jack_nframes_t period = ( int ) powf ( 2.f, ( int ) ( log (float ( fParams.fMtu - sizeof ( packet_header_t ) )
                                               / ( max ( fParams.fReturnAudioChannels, fParams.fSendAudioChannels ) * sizeof ( sample_t ) ) ) / log ( 2. ) ) );
            fParams.fFramesPerPacket = ( period > fParams.fPeriodSize ) ? fParams.fPeriodSize : period;
        }
moret's avatar
moret committed
100
101
102
103
    }

    int JackNetInterface::SetNetBufferSize()
    {
moret's avatar
moret committed
104
        jack_log ( "JackNetInterface::SetNetBufferSize" );
moret's avatar
moret committed
105

moret's avatar
moret committed
106
        float audio_size, midi_size;
107
        int bufsize;
moret's avatar
moret committed
108
109
110
111
        //audio
        audio_size = fParams.fMtu * ( fParams.fPeriodSize / fParams.fFramesPerPacket );
        //midi
        midi_size = fParams.fMtu * ( max ( fParams.fSendMidiChannels, fParams.fReturnMidiChannels ) *
moret's avatar
moret committed
112
                                     fParams.fPeriodSize * sizeof ( sample_t ) / ( fParams.fMtu - sizeof ( packet_header_t ) ) );
moret's avatar
moret committed
113
        //bufsize = sync + audio + midi
114
        bufsize = MAX_LATENCY * (fParams.fMtu + ( int ) audio_size + ( int ) midi_size);
moret's avatar
moret committed
115
116
117

        //tx buffer
        if ( fSocket.SetOption ( SOL_SOCKET, SO_SNDBUF, &bufsize, sizeof ( bufsize ) ) == SOCKET_ERROR )
118
            return SOCKET_ERROR;
moret's avatar
moret committed
119
120
121

        //rx buffer
        if ( fSocket.SetOption ( SOL_SOCKET, SO_RCVBUF, &bufsize, sizeof ( bufsize ) ) == SOCKET_ERROR )
122
            return SOCKET_ERROR;
moret's avatar
moret committed
123

124
        return 0;
moret's avatar
moret committed
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
    }

    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
144
        if ( fRxHeader.fCycle <= 1 ) {
moret's avatar
moret committed
145
            return true;
146
        }
moret's avatar
moret committed
147
        //same PcktID (cycle), next SubPcktID (subcycle)
148
149
150
        if ( ( fRxHeader.fSubCycle < ( fNSubProcess - 1 ) ) && ( rx_head->fCycle == fRxHeader.fCycle ) && ( rx_head->fSubCycle == ( fRxHeader.fSubCycle + 1 ) ) ) {
             return true;
        }
moret's avatar
moret committed
151
        //next PcktID (cycle), SubPcktID reset to 0 (first subcyle)
152
        if ( ( rx_head->fCycle == ( fRxHeader.fCycle + 1 ) ) && ( fRxHeader.fSubCycle == ( fNSubProcess - 1 ) ) && ( rx_head->fSubCycle == 0 ) ) {
moret's avatar
moret committed
153
            return true;
154
        }
moret's avatar
moret committed
155
        //else, packet(s) missing, return false
moret's avatar
moret committed
156
157
158
        return false;
    }

159
160
    void JackNetInterface::SetParams()
    {
moret's avatar
moret committed
161
        //number of audio subcycles (packets)
162
163
        fNSubProcess = fParams.fPeriodSize / fParams.fFramesPerPacket;

moret's avatar
moret committed
164
165
166
        //payload size
        fPayloadSize = fParams.fMtu - sizeof ( packet_header_t );

167
168
169
170
171
172
173
        //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
174
        fTxHeader.fIsLastPckt = 0;
175
176
177
178
179
180
181
182

        //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
183
        fRxHeader.fIsLastPckt = 0;
184
185
186
187

        //network buffers
        fTxBuffer = new char[fParams.fMtu];
        fRxBuffer = new char[fParams.fMtu];
188
189
        assert ( fTxBuffer );
        assert ( fRxBuffer );
190

moret's avatar
moret committed
191
        //net audio/midi buffers'addresses
192
193
194
195
        fTxData = fTxBuffer + sizeof ( packet_header_t );
        fRxData = fRxBuffer + sizeof ( packet_header_t );
    }

196
    // JackNetMasterInterface ************************************************************************************
197

198
    bool JackNetMasterInterface::Init()
199
    {
200
        jack_log ( "JackNetMasterInterface::Init, ID %u.", fParams.fID );
201

202
        session_params_t host_params;
203
        uint attempt = 0;
204
205
206
207
208
        int rx_bytes = 0;

        //socket
        if ( fSocket.NewSocket() == SOCKET_ERROR )
        {
209
210
            jack_error ( "Can't create socket : %s", StrError ( NET_ERROR_CODE ) );
            return false;
211
212
        }

213
        //timeout on receive (for init)
214
        if ( fSocket.SetTimeOut ( MASTER_INIT_TIMEOUT ) < 0 )
215
            jack_error ( "Can't set timeout : %s", StrError ( NET_ERROR_CODE ) );
216
            
217
218
219
220
221
222
        //connect
        if ( fSocket.Connect() == SOCKET_ERROR )
        {
            jack_error ( "Can't connect : %s", StrError ( NET_ERROR_CODE ) );
            return false;
        }
223

moret's avatar
moret committed
224
        //set the number of complete audio frames we can put in a packet
moret's avatar
moret committed
225
226
        SetFramesPerPacket();

227
228
        //send 'SLAVE_SETUP' until 'START_MASTER' received
        jack_info ( "Sending parameters to %s ...", fParams.fSlaveNetName );
229
230
        do
        {
231
            session_params_t net_params;
232
            SetPacketType ( &fParams, SLAVE_SETUP );
233
234
235
            SessionParamsHToN(&fParams, &net_params);
            
            if ( fSocket.Send ( &net_params, sizeof ( session_params_t ), 0 ) == SOCKET_ERROR )
236
                jack_error ( "Error in send : ", StrError ( NET_ERROR_CODE ) );
237
238
239
                
            memset(&net_params, 0, sizeof ( session_params_t ));
            if ( ( ( rx_bytes = fSocket.Recv ( &net_params, sizeof ( session_params_t ), 0 ) ) == SOCKET_ERROR ) && ( fSocket.GetError() != NET_NO_DATA ) )
240
            {
241
242
                jack_error ( "Problem with network." );
                return false;
243
            }
244
245
            
            SessionParamsNToH(&net_params, &host_params);
246
        }
247
        while ( ( GetPacketType ( &host_params ) != START_MASTER ) && ( ++attempt < SLAVE_SETUP_RETRY ) );
248
        if ( attempt == SLAVE_SETUP_RETRY )
249
        {
250
251
            jack_error ( "Slave doesn't respond, exiting." );
            return false;
252
253
        }

254
        //set the new timeout for the socket
moret's avatar
moret committed
255
        if ( SetRxTimeout() == SOCKET_ERROR )
256
257
258
259
        {
            jack_error ( "Can't set rx timeout : %s", StrError ( NET_ERROR_CODE ) );
            return false;
        }
260

261
        //set the new rx buffer size
moret's avatar
moret committed
262
        if ( SetNetBufferSize() == SOCKET_ERROR )
263
        {
moret's avatar
moret committed
264
            jack_error ( "Can't set net buffer sizes : %s", StrError ( NET_ERROR_CODE ) );
265
            return false;
266
        }
267
268

        return true;
269
270
    }

moret's avatar
moret committed
271
272
    int JackNetMasterInterface::SetRxTimeout()
    {
moret's avatar
moret committed
273
274
        jack_log ( "JackNetMasterInterface::SetRxTimeout" );

moret's avatar
moret committed
275
        float time = 0;
moret's avatar
moret committed
276
277
        //slow or normal mode, short timeout on recv (2 audio subcycles)
        if ( ( fParams.fNetworkMode == 's' ) || ( fParams.fNetworkMode == 'n' ) )
moret's avatar
moret committed
278
            time = 2000000.f * ( static_cast<float> ( fParams.fFramesPerPacket ) / static_cast<float> ( fParams.fSampleRate ) );
moret's avatar
moret committed
279
        //fast mode, wait for 75% of the entire cycle duration
moret's avatar
moret committed
280
281
282
283
284
        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 ) );
    }

285
    void JackNetMasterInterface::SetParams()
moret's avatar
moret committed
286
    {
287
        jack_log ( "JackNetMasterInterface::SetParams" );
moret's avatar
moret committed
288
289
290

        JackNetInterface::SetParams();

291
292
        fTxHeader.fDataStream = 's';
        fRxHeader.fDataStream = 'r';
moret's avatar
moret committed
293
294

        //midi net buffers
295
296
        fNetMidiCaptureBuffer = new NetMidiBuffer ( &fParams, fParams.fSendMidiChannels, fTxData );
        fNetMidiPlaybackBuffer = new NetMidiBuffer ( &fParams, fParams.fReturnMidiChannels, fRxData );
297
298
        assert ( fNetMidiCaptureBuffer );
        assert ( fNetMidiPlaybackBuffer );
moret's avatar
moret committed
299
300

        //audio net buffers
301
302
        fNetAudioCaptureBuffer = new NetAudioBuffer ( &fParams, fParams.fSendAudioChannels, fTxData );
        fNetAudioPlaybackBuffer = new NetAudioBuffer ( &fParams, fParams.fReturnAudioChannels, fRxData );
303
304
        assert ( fNetAudioCaptureBuffer );
        assert ( fNetAudioPlaybackBuffer );
moret's avatar
moret committed
305
306

        //audio netbuffer length
307
308
        fAudioTxLen = sizeof ( packet_header_t ) + fNetAudioCaptureBuffer->GetSize();
        fAudioRxLen = sizeof ( packet_header_t ) + fNetAudioPlaybackBuffer->GetSize();
moret's avatar
moret committed
309
310
    }

311
    void JackNetMasterInterface::Exit()
312
    {
313
314
315
316
        jack_log ( "JackNetMasterInterface::Exit, ID %u", fParams.fID );

        //stop process
        fRunning = false;
317

318
319
320
321
        //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() );
322
323
324
325
        
        session_params_t net_params;
        SessionParamsHToN(&fParams, &net_params);

326
327
        if ( mcast_socket.NewSocket() == SOCKET_ERROR )
            jack_error ( "Can't create socket : %s", StrError ( NET_ERROR_CODE ) );
328
        if ( mcast_socket.SendTo ( &net_params, sizeof ( session_params_t ), 0, fMulticastIP ) == SOCKET_ERROR )
329
            jack_error ( "Can't send suicide request : %s", StrError ( NET_ERROR_CODE ) );
330
            
331
        mcast_socket.Close();
332

333
334
        // UGLY temporary way to be sure the thread does not call code possibly causing a deadlock in JackEngine.
        ThreadExit();
335
336
    }

337
    int JackNetMasterInterface::Recv ( size_t size, int flags )
338
    {
339
340
        int rx_bytes;
        if ( ( ( rx_bytes = fSocket.Recv ( fRxBuffer, size, flags ) ) == SOCKET_ERROR ) && fRunning )
341
342
        {
            net_error_t error = fSocket.GetError();
343
344
345
346
            //no data isn't really a network error, so just return 0 avalaible read bytes
            if ( error == NET_NO_DATA )
                return 0;
            else if ( error == NET_CONN_ERROR )
347
348
349
            {
                //fatal connection issue, exit
                jack_error ( "'%s' : %s, exiting.", fParams.fName, StrError ( NET_ERROR_CODE ) );
350
                //ask to the manager to properly remove the master
351
352
                Exit();
            }
moret's avatar
moret committed
353
            else
354
                jack_error ( "Error in master receive : %s", StrError ( NET_ERROR_CODE ) );
355
        }
356
357
358
359
        
        packet_header_t* header = reinterpret_cast<packet_header_t*>(fRxBuffer);
        PacketHeaderNToH(header, header);
        return rx_bytes;
360
    }
361
362
    
    int JackNetMasterInterface::Send ( size_t size, int flags )
363
    {
364
365
366
367
368
        int tx_bytes;
        packet_header_t* header = reinterpret_cast<packet_header_t*>(fTxBuffer);
        PacketHeaderHToN(header, header);
        
        if ( ( ( tx_bytes = fSocket.Send ( fTxBuffer, size, flags ) ) == SOCKET_ERROR ) && fRunning )
369
370
        {
            net_error_t error = fSocket.GetError();
371
            if ( error == NET_CONN_ERROR )
372
            {
373
374
375
                //fatal connection issue, exit
                jack_error ( "'%s' : %s, exiting.", fParams.fName, StrError ( NET_ERROR_CODE ) );
                Exit();
376
            }
moret's avatar
moret committed
377
            else
378
                jack_error ( "Error in master send : %s", StrError ( NET_ERROR_CODE ) );
379
        }
380
        return tx_bytes;
381
    }
382
383
384
    
    bool JackNetMasterInterface::IsSynched()
    {
sletz's avatar
sletz committed
385
        if (fParams.fNetworkMode == 's') {
386
            return (fCycleOffset < 3);
sletz's avatar
sletz committed
387
        } else {
388
            return true;
sletz's avatar
sletz committed
389
        }
390
391
    }
    
392
    int JackNetMasterInterface::SyncSend()
393
    {
394
395
396
        fTxHeader.fCycle++;
        fTxHeader.fSubCycle = 0;
        fTxHeader.fDataType = 's';
397
        fTxHeader.fIsLastPckt = ( fParams.fSendMidiChannels == 0 && fParams.fSendAudioChannels == 0) ?  1 : 0;
398
399
400
401
402
403
404
405
406
        fTxHeader.fPacketSize = fParams.fMtu;
        memcpy ( fTxBuffer, &fTxHeader, sizeof ( packet_header_t ) );
        return Send ( fTxHeader.fPacketSize, 0 );
    }

    int JackNetMasterInterface::DataSend()
    {
        uint subproc;
        //midi
407
        if ( fParams.fSendMidiChannels > 0)
408
        {
409
410
411
            //set global header fields and get the number of midi packets
            fTxHeader.fDataType = 'm';
            fTxHeader.fMidiDataSize = fNetMidiCaptureBuffer->RenderFromJackPorts();
moret's avatar
moret committed
412
            fTxHeader.fNMidiPckt = GetNMidiPckt();
413
            for ( subproc = 0; subproc < fTxHeader.fNMidiPckt; subproc++ )
414
            {
415
                fTxHeader.fSubCycle = subproc;
416
                fTxHeader.fIsLastPckt = ( ( subproc == ( fTxHeader.fNMidiPckt - 1 ) ) && (fParams.fSendAudioChannels == 0)) ? 1 : 0;
417
                fTxHeader.fPacketSize = sizeof ( packet_header_t ) + fNetMidiCaptureBuffer->RenderToNetwork ( subproc, fTxHeader.fMidiDataSize );
418
419
420
                memcpy ( fTxBuffer, &fTxHeader, sizeof ( packet_header_t ) );
                if ( Send ( fTxHeader.fPacketSize, 0 ) == SOCKET_ERROR )
                    return SOCKET_ERROR;
421
422
            }
        }
423
424

        //audio
425
        if ( fParams.fSendAudioChannels > 0)
426
427
        {
            fTxHeader.fDataType = 'a';
428
429
            fTxHeader.fMidiDataSize = 0;
            fTxHeader.fNMidiPckt = 0;
430
431
432
            for ( subproc = 0; subproc < fNSubProcess; subproc++ )
            {
                fTxHeader.fSubCycle = subproc;
moret's avatar
moret committed
433
                fTxHeader.fIsLastPckt = ( subproc == ( fNSubProcess - 1 ) ) ? 1 : 0;
434
435
436
437
438
439
440
441
442
                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;
443
444
    }

445
    int JackNetMasterInterface::SyncRecv()
446
447
    {
        packet_header_t* rx_head = reinterpret_cast<packet_header_t*> ( fRxBuffer );
448
449
        int rx_bytes = Recv ( fParams.fMtu, MSG_PEEK );
        
450
451
452
        if ( ( rx_bytes == 0 ) || ( rx_bytes == SOCKET_ERROR ) )
            return rx_bytes;

453
        fCycleOffset = fTxHeader.fCycle - rx_head->fCycle;
454
      
455
        switch ( fParams.fNetworkMode )
456
        {
457
            case 's' :
moret's avatar
moret committed
458
459
460
461
462
                //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)
463
                if (fCycleOffset < 2)
464
                     return 0;
465
466
                else
                    rx_bytes = Recv ( rx_head->fPacketSize, 0 );
467
468
469
470
                    
                if (fCycleOffset > 2) {
                    jack_info("Warning : '%s' runs in slow network mode, but data received too late (%d cycle(s) offset)", fParams.fName, fCycleOffset);
                }
471
                break;
472

473
474
475
476
477
            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
478
                if (fCycleOffset < 1)
479
480
481
                    return 0;
                else
                    rx_bytes = Recv ( rx_head->fPacketSize, 0 );
482
483
484
                    
                if (fCycleOffset != 1) 
                    jack_info("'%s' can't run in normal network mode, data received too late (%d cycle(s) offset)", fParams.fName, fCycleOffset);
485
                break;
486

487
488
489
490
491
492
            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 );
493
494
495
                
                if (fCycleOffset != 0)
                    jack_info("'%s' can't run in fast network mode, data received too late (%d cycle(s) offset)", fParams.fName, fCycleOffset);
496
                break;
497
        }
498

moret's avatar
moret committed
499
        fRxHeader.fIsLastPckt = rx_head->fIsLastPckt;
500
501
        return rx_bytes;
    }
502
    
503
    int JackNetMasterInterface::DataRecv()
504
505
    {
        int rx_bytes = 0;
506
        uint jumpcnt = 0;
507
        uint recvd_midi_pckt = 0;
508
        uint recvd_audio_pckt = 0;
509
        packet_header_t* rx_head = reinterpret_cast<packet_header_t*> ( fRxBuffer );
510
        
moret's avatar
moret committed
511
        while ( !fRxHeader.fIsLastPckt )
512
        {
moret's avatar
moret committed
513
514
            //how much data is queued on the rx buffer ?
            rx_bytes = Recv ( fParams.fMtu, MSG_PEEK );
515
              
moret's avatar
moret committed
516
517
            if ( rx_bytes == SOCKET_ERROR )
                return rx_bytes;
moret's avatar
moret committed
518
            //if no data
moret's avatar
moret committed
519
            if ( ( rx_bytes == 0 ) && ( ++jumpcnt == fNSubProcess ) )
520
            {
moret's avatar
moret committed
521
522
523
524
525
526
527
528
                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 )
529
                {
moret's avatar
moret committed
530
                    case 'm':   //midi
531
                        rx_bytes = Recv ( rx_head->fPacketSize, 0 );
moret's avatar
moret committed
532
                        fRxHeader.fCycle = rx_head->fCycle;
moret's avatar
moret committed
533
                        fRxHeader.fIsLastPckt = rx_head->fIsLastPckt;
moret's avatar
moret committed
534
                        fNetMidiPlaybackBuffer->RenderFromNetwork ( rx_head->fSubCycle, rx_bytes - sizeof ( packet_header_t ) );
535
                        if ( ++recvd_midi_pckt == rx_head->fNMidiPckt )
moret's avatar
moret committed
536
537
538
                            fNetMidiPlaybackBuffer->RenderToJackPorts();
                        jumpcnt = 0;
                        break;
539

moret's avatar
moret committed
540
                    case 'a':   //audio
541
                        rx_bytes = Recv ( rx_head->fPacketSize, 0 );
542
543
544
                        // SL: 25/01/09
                        // if ( !IsNextPacket() )
                        //    jack_error ( "Packet(s) missing from '%s'...", fParams.fName );
545
546
547
                        if (recvd_audio_pckt++ != rx_head->fSubCycle) {
                            jack_error("Packet(s) missing from '%s'...", fParams.fSlaveNetName);
                        }
moret's avatar
moret committed
548
549
                        fRxHeader.fCycle = rx_head->fCycle;
                        fRxHeader.fSubCycle = rx_head->fSubCycle;
moret's avatar
moret committed
550
                        fRxHeader.fIsLastPckt = rx_head->fIsLastPckt;
moret's avatar
moret committed
551
552
553
                        fNetAudioPlaybackBuffer->RenderToJackPorts ( rx_head->fSubCycle );
                        jumpcnt = 0;
                        break;
554

moret's avatar
moret committed
555
                    case 's':   //sync
556
                        /* SL: 25/01/09
moret's avatar
moret committed
557
558
                        if ( rx_head->fCycle == fTxHeader.fCycle )
                            return 0;
559
                        */
560
                        jack_info("NetMaster : overloaded, skipping receive from '%s'", fParams.fName);
561
                        return 0;
562
563
564
                }
            }
        }
565
        return rx_bytes;
566
    }
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
    
    int JackNetMasterInterface::EncodeSyncPacket()
    {
        //this method contains every step of sync packet informations coding
        //first of all, reset sync packet
        memset ( fTxData, 0, fPayloadSize );

        //then, first step : transport
        if ( fParams.fTransportSync )
        {
            if ( EncodeTransportData() < 0 )
                return -1;
            //copy to TxBuffer
            memcpy ( fTxData, &fSendTransportData, sizeof ( net_transport_data_t ) );
        }
        //then others (freewheel etc.)
        //...
        return 0;
    }

    int JackNetMasterInterface::DecodeSyncPacket()
    {
        //this method contains every step of sync packet informations decoding process
        //first : transport
        if ( fParams.fTransportSync )
        {
            //copy received transport data to transport data structure
            memcpy ( &fReturnTransportData, fRxData, sizeof ( net_transport_data_t ) );
            if ( DecodeTransportData() < 0 )
                return -1;
        }
        //then others
        //...
        return 0;
    }
602

603
604
// JackNetSlaveInterface ************************************************************************************************

moret's avatar
moret committed
605
606
    uint JackNetSlaveInterface::fSlaveCounter = 0;

607
    bool JackNetSlaveInterface::Init()
608
    {
609
        jack_log ( "JackNetSlaveInterface::Init()" );
610

611
612
        //set the parameters to send
        strcpy ( fParams.fPacketType, "params" );
613
        fParams.fProtocolVersion = SLAVE_PROTOCOL;
614
        SetPacketType ( &fParams, SLAVE_AVAILABLE );
615

616
617
618
        //init loop : get a master and start, do it until connection is ok
        net_status_t status;
        do
619
        {
620
621
            //first, get a master, do it until a valid connection is running
            do
622
            {
623
624
625
                status = GetNetMaster();
                if ( status == NET_SOCKET_ERROR )
                    return false;
626
            }
627
            while ( status != NET_CONNECTED );
628

629
630
            //then tell the master we are ready
            jack_info ( "Initializing connection with %s...", fParams.fMasterNetName );
moret's avatar
moret committed
631
            status = SendStartToMaster();
632
633
            if ( status == NET_ERROR )
                return false;
634
        }
635
        while ( status != NET_ROLLING );
636

637
638
        return true;
    }
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
    
    // Separate the connection protocol into two separated step
    
    bool JackNetSlaveInterface::InitConnection()
    {
        jack_log ( "JackNetSlaveInterface::InitConnection()" );

        //set the parameters to send
        strcpy (fParams.fPacketType, "params");
        fParams.fProtocolVersion = SLAVE_PROTOCOL;
        SetPacketType (&fParams, SLAVE_AVAILABLE);

        net_status_t status;
        do
        {
            //get a master
            status = GetNetMaster();
            if (status == NET_SOCKET_ERROR)
                return false;
        }
        while (status != NET_CONNECTED);
  
        return true;
    }
    
    bool JackNetSlaveInterface::InitRendering()
    {
        jack_log("JackNetSlaveInterface::InitRendering()");

        net_status_t status;
        do
        {
            //then tell the master we are ready
            jack_info("Initializing connection with %s...", fParams.fMasterNetName);
            status = SendStartToMaster();
            if (status == NET_ERROR)
                return false;
        }
        while (status != NET_ROLLING);   
        
        return true;
    }
681

682
    net_status_t JackNetSlaveInterface::GetNetMaster()
683
    {
684
685
        jack_log ( "JackNetSlaveInterface::GetNetMaster()" );
        //utility
686
        session_params_t host_params;
687
688
689
690
691
        int rx_bytes = 0;

        //socket
        if ( fSocket.NewSocket() == SOCKET_ERROR )
        {
692
693
            jack_error ( "Fatal error : network unreachable - %s", StrError ( NET_ERROR_CODE ) );
            return NET_SOCKET_ERROR;
694
695
        }

696
697
698
699
700
        //bind the socket
        if ( fSocket.Bind() == SOCKET_ERROR )
            jack_error ( "Can't bind the socket : %s", StrError ( NET_ERROR_CODE ) );

        //timeout on receive
701
        if ( fSocket.SetTimeOut ( SLAVE_INIT_TIMEOUT ) == SOCKET_ERROR )
702
703
            jack_error ( "Can't set timeout : %s", StrError ( NET_ERROR_CODE ) );

704
        //disable local loop
moret's avatar
moret committed
705
        if ( fSocket.SetLocalLoop() == SOCKET_ERROR )
706
            jack_error ( "Can't disable multicast loop : %s", StrError ( NET_ERROR_CODE ) );
707

708
709
        //send 'AVAILABLE' until 'SLAVE_SETUP' received
        jack_info ( "Waiting for a master..." );
710
711
        do
        {
712
            //send 'available'
713
714
715
            session_params_t net_params;
            SessionParamsHToN(&fParams, &net_params);
            if ( fSocket.SendTo ( &net_params, sizeof ( session_params_t ), 0, fMulticastIP ) == SOCKET_ERROR )
716
                jack_error ( "Error in data send : %s", StrError ( NET_ERROR_CODE ) );
717
                
718
            //filter incoming packets : don't exit while no error is detected
719
720
721
            memset(&net_params, 0, sizeof ( session_params_t ));
            rx_bytes = fSocket.CatchHost ( &net_params, sizeof ( session_params_t ), 0 );
            SessionParamsNToH(&net_params, &host_params);
722
            if ( ( rx_bytes == SOCKET_ERROR ) && ( fSocket.GetError() != NET_NO_DATA ) )
723
            {
724
725
                jack_error ( "Can't receive : %s", StrError ( NET_ERROR_CODE ) );
                return NET_RECV_ERROR;
726
727
            }
        }
728
        while ( strcmp ( host_params.fPacketType, fParams.fPacketType )  && ( GetPacketType ( &host_params ) != SLAVE_SETUP ) );
729

moret's avatar
moret committed
730
        //everything is OK, copy parameters
731
        fParams = host_params;
moret's avatar
moret committed
732
733
734
735
736

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

737
738
        //connect the socket
        if ( fSocket.Connect() == SOCKET_ERROR )
739
        {
740
741
            jack_error ( "Error in connect : %s", StrError ( NET_ERROR_CODE ) );
            return NET_CONNECT_ERROR;
742
743
        }

moret's avatar
moret committed
744
        return NET_CONNECTED;
745
746
    }

moret's avatar
moret committed
747
    net_status_t JackNetSlaveInterface::SendStartToMaster()
748
    {
moret's avatar
moret committed
749
        jack_log ( "JackNetSlaveInterface::SendStartToMaster" );
moret's avatar
moret committed
750

751
        //tell the master to start
752
        session_params_t net_params;
753
        SetPacketType ( &fParams, START_MASTER );
754
755
        SessionParamsHToN(&fParams, &net_params);
        if ( fSocket.Send ( &net_params, sizeof ( session_params_t ), 0 ) == SOCKET_ERROR )
756
        {
757
758
            jack_error ( "Error in send : %s", StrError ( NET_ERROR_CODE ) );
            return ( fSocket.GetError() == NET_CONN_ERROR ) ? NET_ERROR : NET_SEND_ERROR;
759
        }
760
        return NET_ROLLING;
761
762
    }

763
    void JackNetSlaveInterface::SetParams()
moret's avatar
moret committed
764
    {
765
        jack_log ( "JackNetSlaveInterface::SetParams" );
moret's avatar
moret committed
766
767
768

        JackNetInterface::SetParams();

769
770
        fTxHeader.fDataStream = 'r';
        fRxHeader.fDataStream = 's';
moret's avatar
moret committed
771
772

        //midi net buffers
773
774
        fNetMidiCaptureBuffer = new NetMidiBuffer ( &fParams, fParams.fSendMidiChannels, fRxData );
        fNetMidiPlaybackBuffer = new NetMidiBuffer ( &fParams, fParams.fReturnMidiChannels, fTxData );
moret's avatar
moret committed
775
776

        //audio net buffers
777
778
        fNetAudioCaptureBuffer = new NetAudioBuffer ( &fParams, fParams.fSendAudioChannels, fRxData );
        fNetAudioPlaybackBuffer = new NetAudioBuffer ( &fParams, fParams.fReturnAudioChannels, fTxData );
moret's avatar
moret committed
779
780
781
782
783
784

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

785
    int JackNetSlaveInterface::Recv ( size_t size, int flags )
786
    {
787
788
789
790
791
792
793
794
795
796
797
798
        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
799
                throw JackNetException();
800
801
            }
            else
sletz's avatar
sletz committed
802
                jack_error ( "Fatal error in slave receive : %s", StrError ( NET_ERROR_CODE ) );
803
        }
804
805
806
        
        packet_header_t* header = reinterpret_cast<packet_header_t*>(fRxBuffer);
        PacketHeaderNToH(header, header);
807
        return rx_bytes;
808
809
    }

810
    int JackNetSlaveInterface::Send ( size_t size, int flags )
811
    {
812
813
        packet_header_t* header = reinterpret_cast<packet_header_t*>(fTxBuffer);
        PacketHeaderHToN(header, header);
814
        int tx_bytes = fSocket.Send ( fTxBuffer, size, flags );
815
         
816
817
        //handle errors
        if ( tx_bytes == SOCKET_ERROR )
818
819
        {
            net_error_t error = fSocket.GetError();
820
821
            //if a network error occurs, this exception will restart the driver
            if ( error == NET_CONN_ERROR )
822
            {
823
                jack_error ( "Connection lost." );
moret's avatar
moret committed
824
                throw JackNetException();
825
            }
826
            else
sletz's avatar
sletz committed
827
                jack_error ( "Fatal error in slave send : %s", StrError ( NET_ERROR_CODE ) );
828
829
830
831
        }
        return tx_bytes;
    }

832
    int JackNetSlaveInterface::SyncRecv()
833
    {
834
835
836
837
        int rx_bytes = 0;
        packet_header_t* rx_head = reinterpret_cast<packet_header_t*> ( fRxBuffer );
        //receive sync (launch the cycle)
        do
838
        {
839
840
841
842
843
            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;
        }
844
845
        while ((strcmp(rx_head->fPacketType, "header") != 0) && (rx_head->fDataType != 's'));
        
moret's avatar
moret committed
846
        fRxHeader.fIsLastPckt = rx_head->fIsLastPckt;
847
848
849
850
851
852
        return rx_bytes;
    }

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

moret's avatar
moret committed
857
        while ( !fRxHeader.fIsLastPckt )
858
        {
moret's avatar
moret committed
859
860
            rx_bytes = Recv ( fParams.fMtu, MSG_PEEK );
            //error here, problem with recv, just skip the cycle (return -1)
moret's avatar
moret committed
861

moret's avatar
moret committed
862
863
864
            if ( rx_bytes == SOCKET_ERROR )
                return rx_bytes;
            if ( rx_bytes && ( rx_head->fDataStream == 's' ) && ( rx_head->fID == fParams.fID ) )
865
            {
moret's avatar
moret committed
866
                switch ( rx_head->fDataType )
867
                {
moret's avatar
moret committed
868
869
870
                    case 'm':   //midi
                        rx_bytes = Recv ( rx_head->fPacketSize, 0 );
                        fRxHeader.fCycle = rx_head->fCycle;
moret's avatar
moret committed
871
                        fRxHeader.fIsLastPckt = rx_head->fIsLastPckt;
moret's avatar
moret committed
872
873
874
875
                        fNetMidiCaptureBuffer->RenderFromNetwork ( rx_head->fSubCycle, rx_bytes - sizeof ( packet_header_t ) );
                        if ( ++recvd_midi_pckt == rx_head->fNMidiPckt )
                            fNetMidiCaptureBuffer->RenderToJackPorts();
                        break;
876

moret's avatar
moret committed
877
878
                    case 'a':   //audio
                        rx_bytes = Recv ( rx_head->fPacketSize, 0 );
879
880
881
                        //SL: 25/01/09
                        // if ( !IsNextPacket() )
                        //    jack_error ( "Packet(s) missing..." );
882
883
884
                        if (recvd_audio_pckt++ != rx_head->fSubCycle) {
                            jack_error("Packet(s) missing from '%s'...", fParams.fMasterNetName);
                        }
moret's avatar
moret committed
885
886
                        fRxHeader.fCycle = rx_head->fCycle;
                        fRxHeader.fSubCycle = rx_head->fSubCycle;
moret's avatar
moret committed
887
                        fRxHeader.fIsLastPckt = rx_head->fIsLastPckt;
moret's avatar
moret committed
888
889
                        fNetAudioCaptureBuffer->RenderToJackPorts ( rx_head->fSubCycle );
                        break;
890

moret's avatar
moret committed
891
892
893
                    case 's':   //sync
                        jack_info ( "NetSlave : overloaded, skipping receive." );
                        return 0;
894
                }
895
896
            }
        }
897
898
        fRxHeader.fCycle = rx_head->fCycle;
        return 0;
899
900
    }

901
    int JackNetSlaveInterface::SyncSend()
902
    {
903
904
905
906
907
        //tx header
        if ( fParams.fSlaveSyncMode )
            fTxHeader.fCycle = fRxHeader.fCycle;
        else
            fTxHeader.fCycle++;
908
909
        fTxHeader.fSubCycle = 0;
        fTxHeader.fDataType = 's';
910
        fTxHeader.fIsLastPckt = ( fParams.fReturnMidiChannels == 0 && fParams.fReturnAudioChannels == 0) ?  1 : 0;
911
912
913
914
915
        fTxHeader.fPacketSize = fParams.fMtu;
        memcpy ( fTxBuffer, &fTxHeader, sizeof ( packet_header_t ) );
        return Send ( fTxHeader.fPacketSize, 0 );
    }

916
    int JackNetSlaveInterface::DataSend()
917
918
    {
        uint subproc;
919

920
        //midi
921
        if ( fParams.fReturnMidiChannels > 0)
922
923
        {
            fTxHeader.fDataType = 'm';
924
            fTxHeader.fMidiDataSize = fNetMidiPlaybackBuffer->RenderFromJackPorts();
moret's avatar
moret committed
925
            fTxHeader.fNMidiPckt = GetNMidiPckt();
926
927
928
            for ( subproc = 0; subproc < fTxHeader.fNMidiPckt; subproc++ )
            {
                fTxHeader.fSubCycle = subproc;
moret's avatar
moret committed
929
                fTxHeader.fIsLastPckt = ( ( subproc == ( fTxHeader.fNMidiPckt - 1 )