JackNetInterface.cpp 36.5 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
45
46
47
    JackNetInterface::JackNetInterface() : fSocket()
    {
        fMulticastIP = NULL;
        fTxBuffer = NULL;
        fRxBuffer = NULL;
        fNetAudioCaptureBuffer = NULL;
        fNetAudioPlaybackBuffer = NULL;
        fNetMidiCaptureBuffer = NULL;
        fNetMidiPlaybackBuffer = NULL;
    }

moret's avatar
moret committed
48
    JackNetInterface::JackNetInterface ( const char* multicast_ip, int port ) : fSocket ( multicast_ip, port )
49
    {
moret's avatar
moret committed
50
        fMulticastIP = strdup ( multicast_ip );
51
52
53
54
55
56
        fTxBuffer = NULL;
        fRxBuffer = NULL;
        fNetAudioCaptureBuffer = NULL;
        fNetAudioPlaybackBuffer = NULL;
        fNetMidiCaptureBuffer = NULL;
        fNetMidiPlaybackBuffer = NULL;
57
58
    }

moret's avatar
moret committed
59
    JackNetInterface::JackNetInterface ( session_params_t& params, JackNetSocket& socket, const char* multicast_ip ) : fSocket ( socket )
60
    {
moret's avatar
moret committed
61
        fParams = params;
moret's avatar
moret committed
62
        fMulticastIP = strdup ( multicast_ip );
63
64
65
66
67
68
        fTxBuffer = NULL;
        fRxBuffer = NULL;
        fNetAudioCaptureBuffer = NULL;
        fNetAudioPlaybackBuffer = NULL;
        fNetMidiCaptureBuffer = NULL;
        fNetMidiPlaybackBuffer = NULL;
69
70
71
72
    }

    JackNetInterface::~JackNetInterface()
    {
moret's avatar
moret committed
73
        jack_log ( "JackNetInterface::~JackNetInterface" );
moret's avatar
moret committed
74

75
76
77
78
79
80
81
82
83
84
        fSocket.Close();
        delete[] fTxBuffer;
        delete[] fRxBuffer;
        delete[] fMulticastIP;
        delete fNetAudioCaptureBuffer;
        delete fNetAudioPlaybackBuffer;
        delete fNetMidiCaptureBuffer;
        delete fNetMidiPlaybackBuffer;
    }

85
    void JackNetInterface::SetFramesPerPacket()
moret's avatar
moret committed
86
    {
moret's avatar
moret committed
87
        jack_log ( "JackNetInterface::SetFramesPerPacket" );
moret's avatar
moret committed
88

89
90
91
92
93
94
95
        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
96
97
98
99
    }

    int JackNetInterface::SetNetBufferSize()
    {
moret's avatar
moret committed
100
        jack_log ( "JackNetInterface::SetNetBufferSize" );
moret's avatar
moret committed
101

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

        //tx buffer
        if ( fSocket.SetOption ( SOL_SOCKET, SO_SNDBUF, &bufsize, sizeof ( bufsize ) ) == SOCKET_ERROR )
114
            return SOCKET_ERROR;
moret's avatar
moret committed
115
116
117

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

120
        return 0;
moret's avatar
moret committed
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
    }

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

155
156
    void JackNetInterface::SetParams()
    {
moret's avatar
moret committed
157
        //number of audio subcycles (packets)
158
159
        fNSubProcess = fParams.fPeriodSize / fParams.fFramesPerPacket;

moret's avatar
moret committed
160
161
162
        //payload size
        fPayloadSize = fParams.fMtu - sizeof ( packet_header_t );

163
164
165
166
167
168
169
        //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
170
        fTxHeader.fIsLastPckt = 0;
171
172
173
174
175
176
177
178

        //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
179
        fRxHeader.fIsLastPckt = 0;
180
181
182
183

        //network buffers
        fTxBuffer = new char[fParams.fMtu];
        fRxBuffer = new char[fParams.fMtu];
184
185
        assert ( fTxBuffer );
        assert ( fRxBuffer );
186

moret's avatar
moret committed
187
        //net audio/midi buffers'addresses
188
189
190
191
        fTxData = fTxBuffer + sizeof ( packet_header_t );
        fRxData = fRxBuffer + sizeof ( packet_header_t );
    }

192
    // JackNetMasterInterface ************************************************************************************
193

194
    bool JackNetMasterInterface::Init()
195
    {
196
        jack_log ( "JackNetMasterInterface::Init, ID %u.", fParams.fID );
197

198
        session_params_t host_params;
199
        uint attempt = 0;
200
201
202
203
204
        int rx_bytes = 0;

        //socket
        if ( fSocket.NewSocket() == SOCKET_ERROR )
        {
205
206
            jack_error ( "Can't create socket : %s", StrError ( NET_ERROR_CODE ) );
            return false;
207
208
        }

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

moret's avatar
moret committed
220
        //set the number of complete audio frames we can put in a packet
moret's avatar
moret committed
221
222
        SetFramesPerPacket();

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

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

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

        return true;
265
266
    }

moret's avatar
moret committed
267
268
    int JackNetMasterInterface::SetRxTimeout()
    {
moret's avatar
moret committed
269
270
        jack_log ( "JackNetMasterInterface::SetRxTimeout" );

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

281
    void JackNetMasterInterface::SetParams()
moret's avatar
moret committed
282
    {
283
        jack_log ( "JackNetMasterInterface::SetParams" );
moret's avatar
moret committed
284
285
286

        JackNetInterface::SetParams();

287
288
        fTxHeader.fDataStream = 's';
        fRxHeader.fDataStream = 'r';
moret's avatar
moret committed
289
290

        //midi net buffers
291
292
        fNetMidiCaptureBuffer = new NetMidiBuffer ( &fParams, fParams.fSendMidiChannels, fTxData );
        fNetMidiPlaybackBuffer = new NetMidiBuffer ( &fParams, fParams.fReturnMidiChannels, fRxData );
293
294
        assert ( fNetMidiCaptureBuffer );
        assert ( fNetMidiPlaybackBuffer );
moret's avatar
moret committed
295
296

        //audio net buffers
297
298
        fNetAudioCaptureBuffer = new NetAudioBuffer ( &fParams, fParams.fSendAudioChannels, fTxData );
        fNetAudioPlaybackBuffer = new NetAudioBuffer ( &fParams, fParams.fReturnAudioChannels, fRxData );
299
300
        assert ( fNetAudioCaptureBuffer );
        assert ( fNetAudioPlaybackBuffer );
moret's avatar
moret committed
301
302

        //audio netbuffer length
303
304
        fAudioTxLen = sizeof ( packet_header_t ) + fNetAudioCaptureBuffer->GetSize();
        fAudioRxLen = sizeof ( packet_header_t ) + fNetAudioPlaybackBuffer->GetSize();
moret's avatar
moret committed
305
306
    }

307
    void JackNetMasterInterface::Exit()
308
    {
309
310
311
312
        jack_log ( "JackNetMasterInterface::Exit, ID %u", fParams.fID );

        //stop process
        fRunning = false;
313

314
315
316
317
        //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() );
318
319
320
321
        
        session_params_t net_params;
        SessionParamsHToN(&fParams, &net_params);

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

329
330
        // UGLY temporary way to be sure the thread does not call code possibly causing a deadlock in JackEngine.
        ThreadExit();
331
332
    }

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

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

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

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

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

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

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

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

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

moret's avatar
moret committed
551
                    case 's':   //sync
552
                        /* SL: 25/01/09
moret's avatar
moret committed
553
554
                        if ( rx_head->fCycle == fTxHeader.fCycle )
                            return 0;
555
                        */
556
                        jack_info("NetMaster : overloaded, skipping receive from '%s'", fParams.fName);
557
                        return 0;
558
559
560
                }
            }
        }
561
        return rx_bytes;
562
563
    }

564
565
// JackNetSlaveInterface ************************************************************************************************

moret's avatar
moret committed
566
567
    uint JackNetSlaveInterface::fSlaveCounter = 0;

568
    bool JackNetSlaveInterface::Init()
569
    {
570
        jack_log ( "JackNetSlaveInterface::Init()" );
571

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

577
578
579
        //init loop : get a master and start, do it until connection is ok
        net_status_t status;
        do
580
        {
581
582
            //first, get a master, do it until a valid connection is running
            do
583
            {
584
585
586
                status = GetNetMaster();
                if ( status == NET_SOCKET_ERROR )
                    return false;
587
            }
588
            while ( status != NET_CONNECTED );
589

590
591
            //then tell the master we are ready
            jack_info ( "Initializing connection with %s...", fParams.fMasterNetName );
moret's avatar
moret committed
592
            status = SendStartToMaster();
593
594
            if ( status == NET_ERROR )
                return false;
595
        }
596
        while ( status != NET_ROLLING );
597

598
599
        return true;
    }
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
    
    // 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;
    }
642

643
    net_status_t JackNetSlaveInterface::GetNetMaster()
644
    {
645
646
        jack_log ( "JackNetSlaveInterface::GetNetMaster()" );
        //utility
647
        session_params_t host_params;
648
649
650
651
652
        int rx_bytes = 0;

        //socket
        if ( fSocket.NewSocket() == SOCKET_ERROR )
        {
653
654
            jack_error ( "Fatal error : network unreachable - %s", StrError ( NET_ERROR_CODE ) );
            return NET_SOCKET_ERROR;
655
656
        }

657
658
659
660
661
        //bind the socket
        if ( fSocket.Bind() == SOCKET_ERROR )
            jack_error ( "Can't bind the socket : %s", StrError ( NET_ERROR_CODE ) );

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

665
        //disable local loop
moret's avatar
moret committed
666
        if ( fSocket.SetLocalLoop() == SOCKET_ERROR )
667
            jack_error ( "Can't disable multicast loop : %s", StrError ( NET_ERROR_CODE ) );
668

669
670
        //send 'AVAILABLE' until 'SLAVE_SETUP' received
        jack_info ( "Waiting for a master..." );
671
672
        do
        {
673
            //send 'available'
674
675
676
            session_params_t net_params;
            SessionParamsHToN(&fParams, &net_params);
            if ( fSocket.SendTo ( &net_params, sizeof ( session_params_t ), 0, fMulticastIP ) == SOCKET_ERROR )
677
                jack_error ( "Error in data send : %s", StrError ( NET_ERROR_CODE ) );
678
                
679
            //filter incoming packets : don't exit while no error is detected
680
681
682
            memset(&net_params, 0, sizeof ( session_params_t ));
            rx_bytes = fSocket.CatchHost ( &net_params, sizeof ( session_params_t ), 0 );
            SessionParamsNToH(&net_params, &host_params);
683
            if ( ( rx_bytes == SOCKET_ERROR ) && ( fSocket.GetError() != NET_NO_DATA ) )
684
            {
685
686
                jack_error ( "Can't receive : %s", StrError ( NET_ERROR_CODE ) );
                return NET_RECV_ERROR;
687
688
            }
        }
689
        while ( strcmp ( host_params.fPacketType, fParams.fPacketType )  && ( GetPacketType ( &host_params ) != SLAVE_SETUP ) );
690

moret's avatar
moret committed
691
        //everything is OK, copy parameters
692
        fParams = host_params;
moret's avatar
moret committed
693
694
695
696
697

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

698
699
        //connect the socket
        if ( fSocket.Connect() == SOCKET_ERROR )
700
        {
701
702
            jack_error ( "Error in connect : %s", StrError ( NET_ERROR_CODE ) );
            return NET_CONNECT_ERROR;
703
704
        }

moret's avatar
moret committed
705
        return NET_CONNECTED;
706
707
    }

moret's avatar
moret committed
708
    net_status_t JackNetSlaveInterface::SendStartToMaster()
709
    {
moret's avatar
moret committed
710
        jack_log ( "JackNetSlaveInterface::SendStartToMaster" );
moret's avatar
moret committed
711

712
        //tell the master to start
713
        session_params_t net_params;
714
        SetPacketType ( &fParams, START_MASTER );
715
716
        SessionParamsHToN(&fParams, &net_params);
        if ( fSocket.Send ( &net_params, sizeof ( session_params_t ), 0 ) == SOCKET_ERROR )
717
        {
718
719
            jack_error ( "Error in send : %s", StrError ( NET_ERROR_CODE ) );
            return ( fSocket.GetError() == NET_CONN_ERROR ) ? NET_ERROR : NET_SEND_ERROR;
720
        }
721
        return NET_ROLLING;
722
723
    }

724
    void JackNetSlaveInterface::SetParams()
moret's avatar
moret committed
725
    {
726
        jack_log ( "JackNetSlaveInterface::SetParams" );
moret's avatar
moret committed
727
728
729

        JackNetInterface::SetParams();

730
731
        fTxHeader.fDataStream = 'r';
        fRxHeader.fDataStream = 's';
moret's avatar
moret committed
732
733

        //midi net buffers
734
735
        fNetMidiCaptureBuffer = new NetMidiBuffer ( &fParams, fParams.fSendMidiChannels, fRxData );
        fNetMidiPlaybackBuffer = new NetMidiBuffer ( &fParams, fParams.fReturnMidiChannels, fTxData );
moret's avatar
moret committed
736
737

        //audio net buffers
738
739
        fNetAudioCaptureBuffer = new NetAudioBuffer ( &fParams, fParams.fSendAudioChannels, fRxData );
        fNetAudioPlaybackBuffer = new NetAudioBuffer ( &fParams, fParams.fReturnAudioChannels, fTxData );
moret's avatar
moret committed
740
741
742
743
744
745

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

746
    int JackNetSlaveInterface::Recv ( size_t size, int flags )
747
    {
748
749
750
751
752
753
754
755
756
757
758
759
        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
760
                throw JackNetException();
761
762
            }
            else
sletz's avatar
sletz committed
763
                jack_error ( "Fatal error in slave receive : %s", StrError ( NET_ERROR_CODE ) );
764
        }
765
766
767
        
        packet_header_t* header = reinterpret_cast<packet_header_t*>(fRxBuffer);
        PacketHeaderNToH(header, header);
768
        return rx_bytes;
769
770
    }

771
    int JackNetSlaveInterface::Send ( size_t size, int flags )
772
    {
773
774
        packet_header_t* header = reinterpret_cast<packet_header_t*>(fTxBuffer);
        PacketHeaderHToN(header, header);
775
        int tx_bytes = fSocket.Send ( fTxBuffer, size, flags );
776
         
777
778
        //handle errors
        if ( tx_bytes == SOCKET_ERROR )
779
780
        {
            net_error_t error = fSocket.GetError();
781
782
            //if a network error occurs, this exception will restart the driver
            if ( error == NET_CONN_ERROR )
783
            {
784
                jack_error ( "Connection lost." );
moret's avatar
moret committed
785
                throw JackNetException();
786
            }
787
            else
sletz's avatar
sletz committed
788
                jack_error ( "Fatal error in slave send : %s", StrError ( NET_ERROR_CODE ) );
789
790
791
792
        }
        return tx_bytes;
    }

793
    int JackNetSlaveInterface::SyncRecv()
794
    {
795
796
797
798
        int rx_bytes = 0;
        packet_header_t* rx_head = reinterpret_cast<packet_header_t*> ( fRxBuffer );
        //receive sync (launch the cycle)
        do
799
        {
800
801
802
803
804
            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;
        }
805
806
        while ((strcmp(rx_head->fPacketType, "header") != 0) && (rx_head->fDataType != 's'));
        
moret's avatar
moret committed
807
        fRxHeader.fIsLastPckt = rx_head->fIsLastPckt;
808
809
810
811
812
813
        return rx_bytes;
    }

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

moret's avatar
moret committed
818
        while ( !fRxHeader.fIsLastPckt )
819
        {
moret's avatar
moret committed
820
821
            rx_bytes = Recv ( fParams.fMtu, MSG_PEEK );
            //error here, problem with recv, just skip the cycle (return -1)
moret's avatar
moret committed
822

moret's avatar
moret committed
823
824
825
            if ( rx_bytes == SOCKET_ERROR )
                return rx_bytes;
            if ( rx_bytes && ( rx_head->fDataStream == 's' ) && ( rx_head->fID == fParams.fID ) )
826
            {
moret's avatar
moret committed
827
                switch ( rx_head->fDataType )
828
                {
moret's avatar
moret committed
829
830
831
                    case 'm':   //midi
                        rx_bytes = Recv ( rx_head->fPacketSize, 0 );
                        fRxHeader.fCycle = rx_head->fCycle;
moret's avatar
moret committed
832
                        fRxHeader.fIsLastPckt = rx_head->fIsLastPckt;
moret's avatar
moret committed
833
834
835
836
                        fNetMidiCaptureBuffer->RenderFromNetwork ( rx_head->fSubCycle, rx_bytes - sizeof ( packet_header_t ) );
                        if ( ++recvd_midi_pckt == rx_head->fNMidiPckt )
                            fNetMidiCaptureBuffer->RenderToJackPorts();
                        break;
837

moret's avatar
moret committed
838
839
                    case 'a':   //audio
                        rx_bytes = Recv ( rx_head->fPacketSize, 0 );
840
841
842
                        //SL: 25/01/09
                        // if ( !IsNextPacket() )
                        //    jack_error ( "Packet(s) missing..." );
843
844
845
                        if (recvd_audio_pckt++ != rx_head->fSubCycle) {
                            jack_error("Packet(s) missing from '%s'...", fParams.fMasterNetName);
                        }
moret's avatar
moret committed
846
847
                        fRxHeader.fCycle = rx_head->fCycle;
                        fRxHeader.fSubCycle = rx_head->fSubCycle;
moret's avatar
moret committed
848
                        fRxHeader.fIsLastPckt = rx_head->fIsLastPckt;
moret's avatar
moret committed
849
850
                        fNetAudioCaptureBuffer->RenderToJackPorts ( rx_head->fSubCycle );
                        break;
851

moret's avatar
moret committed
852
853
854
                    case 's':   //sync
                        jack_info ( "NetSlave : overloaded, skipping receive." );
                        return 0;
855
                }
856
857
            }
        }
858
859
        fRxHeader.fCycle = rx_head->fCycle;
        return 0;
860
861
    }

862
    int JackNetSlaveInterface::SyncSend()
863
    {
864
865
866
867
868
        //tx header
        if ( fParams.fSlaveSyncMode )
            fTxHeader.fCycle = fRxHeader.fCycle;
        else
            fTxHeader.fCycle++;
869
870
        fTxHeader.fSubCycle = 0;
        fTxHeader.fDataType = 's';
871
        fTxHeader.fIsLastPckt = ( fParams.fReturnMidiChannels == 0 && fParams.fReturnAudioChannels == 0) ?  1 : 0;
872
873
874
875
876
        fTxHeader.fPacketSize = fParams.fMtu;
        memcpy ( fTxBuffer, &fTxHeader, sizeof ( packet_header_t ) );
        return Send ( fTxHeader.fPacketSize, 0 );
    }

877
    int JackNetSlaveInterface::DataSend()
878
879
    {
        uint subproc;
880

881
        //midi
882
        if ( fParams.fReturnMidiChannels > 0)
883
884
        {
            fTxHeader.fDataType = 'm';
885
            fTxHeader.fMidiDataSize = fNetMidiPlaybackBuffer->RenderFromJackPorts();
moret's avatar
moret committed
886
            fTxHeader.fNMidiPckt = GetNMidiPckt();
887
888
889
            for ( subproc = 0; subproc < fTxHeader.fNMidiPckt; subproc++ )
            {
                fTxHeader.fSubCycle = subproc;
moret's avatar
moret committed
890
                fTxHeader.fIsLastPckt = ( ( subproc == ( fTxHeader.fNMidiPckt - 1 ) ) && !fParams.fReturnAudioChannels ) ? 1 : 0;
891
                fTxHeader.fPacketSize = sizeof ( packet_header_t ) + fNetMidiPlaybackBuffer->RenderToNetwork ( subproc, fTxHeader.fMidiDataSize );
892
893
                memcpy ( fTxBuffer, &fTxHeader, sizeof ( packet_header_t ) );
                if ( Send ( fTxHeader.fPacketSize, 0 ) == SOCKET_ERROR )
moret's avatar
moret committed
894
                    return SOCKET_ERROR;
895
896
897
898
            }
        }

        //audio
899
        if ( fParams.fReturnAudioChannels > 0)
900
901
        {
            fTxHeader.fDataType = 'a';
902
903
            fTxHeader.fMidiDataSize = 0;
            fTxHeader.fNMidiPckt = 0;
904
905
906
            for ( subproc = 0; subproc < fNSubProcess; subproc++ )
            {
                fTxHeader.fSubCycle = subproc;
moret's avatar
moret committed
907
                fTxHeader.fIsLastPckt = ( subproc == ( fNSubProcess - 1 ) ) ? 1 : 0;
908
909
                fTxHeader.fPacketSize = fAudioTxLen;
                memcpy ( fTxBuffer, &fTxHeader, sizeof ( packet_header_t ) );