JackNetInterface.cpp 35.3 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
    net_status_t JackNetSlaveInterface::GetNetMaster()
602
    {
603
604
        jack_log ( "JackNetSlaveInterface::GetNetMaster()" );
        //utility
605
        session_params_t host_params;
606
607
608
609
610
        int rx_bytes = 0;

        //socket
        if ( fSocket.NewSocket() == SOCKET_ERROR )
        {
611
612
            jack_error ( "Fatal error : network unreachable - %s", StrError ( NET_ERROR_CODE ) );
            return NET_SOCKET_ERROR;
613
614
        }

615
616
617
618
619
        //bind the socket
        if ( fSocket.Bind() == SOCKET_ERROR )
            jack_error ( "Can't bind the socket : %s", StrError ( NET_ERROR_CODE ) );

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

623
        //disable local loop
moret's avatar
moret committed
624
        if ( fSocket.SetLocalLoop() == SOCKET_ERROR )
625
            jack_error ( "Can't disable multicast loop : %s", StrError ( NET_ERROR_CODE ) );
626

627
628
        //send 'AVAILABLE' until 'SLAVE_SETUP' received
        jack_info ( "Waiting for a master..." );
629
630
        do
        {
631
            //send 'available'
632
633
634
            session_params_t net_params;
            SessionParamsHToN(&fParams, &net_params);
            if ( fSocket.SendTo ( &net_params, sizeof ( session_params_t ), 0, fMulticastIP ) == SOCKET_ERROR )
635
                jack_error ( "Error in data send : %s", StrError ( NET_ERROR_CODE ) );
636
                
637
            //filter incoming packets : don't exit while no error is detected
638
639
640
            memset(&net_params, 0, sizeof ( session_params_t ));
            rx_bytes = fSocket.CatchHost ( &net_params, sizeof ( session_params_t ), 0 );
            SessionParamsNToH(&net_params, &host_params);
641
            if ( ( rx_bytes == SOCKET_ERROR ) && ( fSocket.GetError() != NET_NO_DATA ) )
642
            {
643
644
                jack_error ( "Can't receive : %s", StrError ( NET_ERROR_CODE ) );
                return NET_RECV_ERROR;
645
646
            }
        }
647
        while ( strcmp ( host_params.fPacketType, fParams.fPacketType )  && ( GetPacketType ( &host_params ) != SLAVE_SETUP ) );
648

moret's avatar
moret committed
649
        //everything is OK, copy parameters
650
        fParams = host_params;
moret's avatar
moret committed
651
652
653
654
655

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

656
657
        //connect the socket
        if ( fSocket.Connect() == SOCKET_ERROR )
658
        {
659
660
            jack_error ( "Error in connect : %s", StrError ( NET_ERROR_CODE ) );
            return NET_CONNECT_ERROR;
661
662
        }

moret's avatar
moret committed
663
        return NET_CONNECTED;
664
665
    }

moret's avatar
moret committed
666
    net_status_t JackNetSlaveInterface::SendStartToMaster()
667
    {
moret's avatar
moret committed
668
        jack_log ( "JackNetSlaveInterface::SendStartToMaster" );
moret's avatar
moret committed
669

670
        //tell the master to start
671
        session_params_t net_params;
672
        SetPacketType ( &fParams, START_MASTER );
673
674
        SessionParamsHToN(&fParams, &net_params);
        if ( fSocket.Send ( &net_params, sizeof ( session_params_t ), 0 ) == SOCKET_ERROR )
675
        {
676
677
            jack_error ( "Error in send : %s", StrError ( NET_ERROR_CODE ) );
            return ( fSocket.GetError() == NET_CONN_ERROR ) ? NET_ERROR : NET_SEND_ERROR;
678
        }
679
        return NET_ROLLING;
680
681
    }

682
    void JackNetSlaveInterface::SetParams()
moret's avatar
moret committed
683
    {
684
        jack_log ( "JackNetSlaveInterface::SetParams" );
moret's avatar
moret committed
685
686
687

        JackNetInterface::SetParams();

688
689
        fTxHeader.fDataStream = 'r';
        fRxHeader.fDataStream = 's';
moret's avatar
moret committed
690
691

        //midi net buffers
692
693
        fNetMidiCaptureBuffer = new NetMidiBuffer ( &fParams, fParams.fSendMidiChannels, fRxData );
        fNetMidiPlaybackBuffer = new NetMidiBuffer ( &fParams, fParams.fReturnMidiChannels, fTxData );
moret's avatar
moret committed
694
695

        //audio net buffers
696
697
        fNetAudioCaptureBuffer = new NetAudioBuffer ( &fParams, fParams.fSendAudioChannels, fRxData );
        fNetAudioPlaybackBuffer = new NetAudioBuffer ( &fParams, fParams.fReturnAudioChannels, fTxData );
moret's avatar
moret committed
698
699
700
701
702
703

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

704
    int JackNetSlaveInterface::Recv ( size_t size, int flags )
705
    {
706
707
708
709
710
711
712
713
714
715
716
717
        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
718
                throw JackNetException();
719
720
            }
            else
sletz's avatar
sletz committed
721
                jack_error ( "Fatal error in slave receive : %s", StrError ( NET_ERROR_CODE ) );
722
        }
723
724
725
        
        packet_header_t* header = reinterpret_cast<packet_header_t*>(fRxBuffer);
        PacketHeaderNToH(header, header);
726
        return rx_bytes;
727
728
    }

729
    int JackNetSlaveInterface::Send ( size_t size, int flags )
730
    {
731
732
        packet_header_t* header = reinterpret_cast<packet_header_t*>(fTxBuffer);
        PacketHeaderHToN(header, header);
733
        int tx_bytes = fSocket.Send ( fTxBuffer, size, flags );
734
         
735
736
        //handle errors
        if ( tx_bytes == SOCKET_ERROR )
737
738
        {
            net_error_t error = fSocket.GetError();
739
740
            //if a network error occurs, this exception will restart the driver
            if ( error == NET_CONN_ERROR )
741
            {
742
                jack_error ( "Connection lost." );
moret's avatar
moret committed
743
                throw JackNetException();
744
            }
745
            else
sletz's avatar
sletz committed
746
                jack_error ( "Fatal error in slave send : %s", StrError ( NET_ERROR_CODE ) );
747
748
749
750
        }
        return tx_bytes;
    }

751
    int JackNetSlaveInterface::SyncRecv()
752
    {
753
754
755
756
        int rx_bytes = 0;
        packet_header_t* rx_head = reinterpret_cast<packet_header_t*> ( fRxBuffer );
        //receive sync (launch the cycle)
        do
757
        {
758
759
760
761
762
763
            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
764
        fRxHeader.fIsLastPckt = rx_head->fIsLastPckt;
765
766
767
768
769
770
        return rx_bytes;
    }

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

moret's avatar
moret committed
775
        while ( !fRxHeader.fIsLastPckt )
776
        {
moret's avatar
moret committed
777
778
            rx_bytes = Recv ( fParams.fMtu, MSG_PEEK );
            //error here, problem with recv, just skip the cycle (return -1)
moret's avatar
moret committed
779

moret's avatar
moret committed
780
781
782
            if ( rx_bytes == SOCKET_ERROR )
                return rx_bytes;
            if ( rx_bytes && ( rx_head->fDataStream == 's' ) && ( rx_head->fID == fParams.fID ) )
783
            {
moret's avatar
moret committed
784
                switch ( rx_head->fDataType )
785
                {
moret's avatar
moret committed
786
787
788
                    case 'm':   //midi
                        rx_bytes = Recv ( rx_head->fPacketSize, 0 );
                        fRxHeader.fCycle = rx_head->fCycle;
moret's avatar
moret committed
789
                        fRxHeader.fIsLastPckt = rx_head->fIsLastPckt;
moret's avatar
moret committed
790
791
792
793
                        fNetMidiCaptureBuffer->RenderFromNetwork ( rx_head->fSubCycle, rx_bytes - sizeof ( packet_header_t ) );
                        if ( ++recvd_midi_pckt == rx_head->fNMidiPckt )
                            fNetMidiCaptureBuffer->RenderToJackPorts();
                        break;
794

moret's avatar
moret committed
795
796
                    case 'a':   //audio
                        rx_bytes = Recv ( rx_head->fPacketSize, 0 );
797
798
799
                        //SL: 25/01/09
                        // if ( !IsNextPacket() )
                        //    jack_error ( "Packet(s) missing..." );
800
801
802
                        if (recvd_audio_pckt++ != rx_head->fSubCycle) {
                            jack_error("Packet(s) missing from '%s'...", fParams.fMasterNetName);
                        }
moret's avatar
moret committed
803
804
                        fRxHeader.fCycle = rx_head->fCycle;
                        fRxHeader.fSubCycle = rx_head->fSubCycle;
moret's avatar
moret committed
805
                        fRxHeader.fIsLastPckt = rx_head->fIsLastPckt;
moret's avatar
moret committed
806
807
                        fNetAudioCaptureBuffer->RenderToJackPorts ( rx_head->fSubCycle );
                        break;
808

moret's avatar
moret committed
809
810
811
                    case 's':   //sync
                        jack_info ( "NetSlave : overloaded, skipping receive." );
                        return 0;
812
                }
813
814
            }
        }
815
816
        fRxHeader.fCycle = rx_head->fCycle;
        return 0;
817
818
    }

819
    int JackNetSlaveInterface::SyncSend()
820
    {
821
822
823
824
825
        //tx header
        if ( fParams.fSlaveSyncMode )
            fTxHeader.fCycle = fRxHeader.fCycle;
        else
            fTxHeader.fCycle++;
826
827
        fTxHeader.fSubCycle = 0;
        fTxHeader.fDataType = 's';
828
        fTxHeader.fIsLastPckt = ( fParams.fReturnMidiChannels == 0 && fParams.fReturnAudioChannels == 0) ?  1 : 0;
829
830
831
832
833
        fTxHeader.fPacketSize = fParams.fMtu;
        memcpy ( fTxBuffer, &fTxHeader, sizeof ( packet_header_t ) );
        return Send ( fTxHeader.fPacketSize, 0 );
    }

834
    int JackNetSlaveInterface::DataSend()
835
836
    {
        uint subproc;
837

838
        //midi
839
        if ( fParams.fReturnMidiChannels > 0)
840
841
        {
            fTxHeader.fDataType = 'm';
842
            fTxHeader.fMidiDataSize = fNetMidiPlaybackBuffer->RenderFromJackPorts();
moret's avatar
moret committed
843
            fTxHeader.fNMidiPckt = GetNMidiPckt();
844
845
846
            for ( subproc = 0; subproc < fTxHeader.fNMidiPckt; subproc++ )
            {
                fTxHeader.fSubCycle = subproc;
moret's avatar
moret committed
847
                fTxHeader.fIsLastPckt = ( ( subproc == ( fTxHeader.fNMidiPckt - 1 ) ) && !fParams.fReturnAudioChannels ) ? 1 : 0;
848
                fTxHeader.fPacketSize = sizeof ( packet_header_t ) + fNetMidiPlaybackBuffer->RenderToNetwork ( subproc, fTxHeader.fMidiDataSize );
849
850
                memcpy ( fTxBuffer, &fTxHeader, sizeof ( packet_header_t ) );
                if ( Send ( fTxHeader.fPacketSize, 0 ) == SOCKET_ERROR )
moret's avatar
moret committed
851
                    return SOCKET_ERROR;
852
853
854
855
            }
        }

        //audio
856
        if ( fParams.fReturnAudioChannels > 0)
857
858
        {
            fTxHeader.fDataType = 'a';
859
860
            fTxHeader.fMidiDataSize = 0;
            fTxHeader.fNMidiPckt = 0;
861
862
863
            for ( subproc = 0; subproc < fNSubProcess; subproc++ )
            {
                fTxHeader.fSubCycle = subproc;
moret's avatar
moret committed
864
                fTxHeader.fIsLastPckt = ( subproc == ( fNSubProcess - 1 ) ) ? 1 : 0;
865
866
                fTxHeader.fPacketSize = fAudioTxLen;
                memcpy ( fTxBuffer, &fTxHeader, sizeof ( packet_header_t ) );
867
                fNetAudioPlaybackBuffer->RenderFromJackPorts ( subproc );
868
                if ( Send ( fTxHeader.fPacketSize, 0 ) == SOCKET_ERROR )
moret's avatar
moret committed
869
                    return SOCKET_ERROR;
870
871
872
873
            }
        }
        return 0;
    }
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
    
    //network sync------------------------------------------------------------------------
    int JackNetSlaveInterface::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