JackNetInterface.cpp 41.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;

sletz's avatar
sletz committed
27
#define PACKET_AVAILABLE_SIZE (fParams.fMtu - sizeof(packet_header_t))
sletz's avatar
sletz committed
28
#define HEADER_SIZE (sizeof(packet_header_t))
sletz's avatar
sletz committed
29

30
31
32
33
34
35
/*  
 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)
*/

36
37
38
39
namespace Jack
{
    // JackNetInterface*******************************************

40
41
    JackNetInterface::JackNetInterface() : fSocket()
    {
sletz's avatar
sletz committed
42
        Initialize();
43
44
    }

moret's avatar
moret committed
45
    JackNetInterface::JackNetInterface ( const char* multicast_ip, int port ) : fSocket ( multicast_ip, port )
46
    {
47
        strcpy(fMulticastIP, multicast_ip);
sletz's avatar
sletz committed
48
        Initialize();
49
50
    }

moret's avatar
moret committed
51
    JackNetInterface::JackNetInterface ( session_params_t& params, JackNetSocket& socket, const char* multicast_ip ) : fSocket ( socket )
52
    {
moret's avatar
moret committed
53
        fParams = params;
54
        strcpy(fMulticastIP, multicast_ip);
sletz's avatar
sletz committed
55
56
57
58
59
        Initialize();
    }
    
    void JackNetInterface::Initialize()
    {
60
61
62
63
64
65
        fTxBuffer = NULL;
        fRxBuffer = NULL;
        fNetAudioCaptureBuffer = NULL;
        fNetAudioPlaybackBuffer = NULL;
        fNetMidiCaptureBuffer = NULL;
        fNetMidiPlaybackBuffer = NULL;
66
67
        memset(&fSendTransportData, 0, sizeof(net_transport_data_t));
        memset(&fReturnTransportData, 0, sizeof(net_transport_data_t));
68
    }
sletz's avatar
sletz committed
69
    
sletz's avatar
sletz committed
70
71
72
73
74
75
76
77
78
79
80
81
    void JackNetInterface::FreeNetworkBuffers()
    {
        delete fNetMidiCaptureBuffer;
        delete fNetMidiPlaybackBuffer;
        delete fNetAudioCaptureBuffer;
        delete fNetAudioPlaybackBuffer;
        fNetMidiCaptureBuffer = NULL;
        fNetMidiPlaybackBuffer = NULL;
        fNetAudioCaptureBuffer = NULL;
        fNetAudioPlaybackBuffer = NULL;
    }
    
82
83
    JackNetInterface::~JackNetInterface()
    {
sletz's avatar
sletz committed
84
        jack_log ("JackNetInterface::~JackNetInterface");
moret's avatar
moret committed
85

86
87
88
89
90
91
92
93
94
        fSocket.Close();
        delete[] fTxBuffer;
        delete[] fRxBuffer;
        delete fNetAudioCaptureBuffer;
        delete fNetAudioPlaybackBuffer;
        delete fNetMidiCaptureBuffer;
        delete fNetMidiPlaybackBuffer;
    }

moret's avatar
moret committed
95
96
97
    int JackNetInterface::SetNetBufferSize()
    {
        //audio
sletz's avatar
sletz committed
98
99
100
101
102
        float audio_size = (fNetAudioCaptureBuffer) 
                            ? fNetAudioCaptureBuffer->GetCycleSize() 
                            : (fNetAudioPlaybackBuffer) ? fNetAudioPlaybackBuffer->GetCycleSize() : 0;
        jack_log ("audio_size %f", audio_size);
        
moret's avatar
moret committed
103
        //midi
sletz's avatar
sletz committed
104
105
106
107
108
        float midi_size = (fNetMidiCaptureBuffer) 
                            ? fNetMidiCaptureBuffer->GetCycleSize() 
                            : (fNetMidiPlaybackBuffer) ? fNetMidiPlaybackBuffer->GetCycleSize() : 0;
        jack_log ("midi_size %f", midi_size);
                                     
moret's avatar
moret committed
109
        //bufsize = sync + audio + midi
sletz's avatar
sletz committed
110
        int bufsize = MAX_LATENCY * (fParams.fMtu + (int)audio_size + (int) midi_size);
sletz's avatar
sletz committed
111
        jack_log("SetNetBufferSize bufsize = %d", bufsize);
moret's avatar
moret committed
112
113

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

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

121
        return 0;
moret's avatar
moret committed
122
123
    }

sletz's avatar
sletz committed
124
    bool JackNetInterface::SetParams()
125
126
127
128
129
130
    {
        //TX header init
        strcpy ( fTxHeader.fPacketType, "header" );
        fTxHeader.fID = fParams.fID;
        fTxHeader.fCycle = 0;
        fTxHeader.fSubCycle = 0;
moret's avatar
moret committed
131
        fTxHeader.fIsLastPckt = 0;
132
133
134
135
136
137

        //RX header init
        strcpy ( fRxHeader.fPacketType, "header" );
        fRxHeader.fID = fParams.fID;
        fRxHeader.fCycle = 0;
        fRxHeader.fSubCycle = 0;
moret's avatar
moret committed
138
        fRxHeader.fIsLastPckt = 0;
139
140
141
142

        //network buffers
        fTxBuffer = new char[fParams.fMtu];
        fRxBuffer = new char[fParams.fMtu];
143
144
        assert ( fTxBuffer );
        assert ( fRxBuffer );
145

moret's avatar
moret committed
146
        //net audio/midi buffers'addresses
sletz's avatar
sletz committed
147
148
        fTxData = fTxBuffer + HEADER_SIZE;
        fRxData = fRxBuffer + HEADER_SIZE;
sletz's avatar
sletz committed
149
150
        
        return true;
151
152
    }

153
    // JackNetMasterInterface ************************************************************************************
154

155
    bool JackNetMasterInterface::Init()
156
    {
157
        jack_log ( "JackNetMasterInterface::Init, ID %u.", fParams.fID );
158

159
        session_params_t host_params;
160
        uint attempt = 0;
161
162
163
        int rx_bytes = 0;

        //socket
sletz's avatar
sletz committed
164
        if ( fSocket.NewSocket() == SOCKET_ERROR ) {
165
166
            jack_error ( "Can't create socket : %s", StrError ( NET_ERROR_CODE ) );
            return false;
167
168
        }

169
        //timeout on receive (for init)
170
        if ( fSocket.SetTimeOut ( MASTER_INIT_TIMEOUT ) < 0 )
171
            jack_error ( "Can't set timeout : %s", StrError ( NET_ERROR_CODE ) );
172
            
173
        //connect
sletz's avatar
sletz committed
174
        if ( fSocket.Connect() == SOCKET_ERROR ) {
175
176
177
            jack_error ( "Can't connect : %s", StrError ( NET_ERROR_CODE ) );
            return false;
        }
178

179
        //send 'SLAVE_SETUP' until 'START_MASTER' received
sletz's avatar
sletz committed
180
        jack_info ( "Sending parameters to %s...", fParams.fSlaveNetName );
181
182
        do
        {
183
            session_params_t net_params;
sletz's avatar
sletz committed
184
            memset(&net_params, 0, sizeof ( session_params_t ));
185
            SetPacketType ( &fParams, SLAVE_SETUP );
186
187
188
            SessionParamsHToN(&fParams, &net_params);
            
            if ( fSocket.Send ( &net_params, sizeof ( session_params_t ), 0 ) == SOCKET_ERROR )
189
                jack_error ( "Error in send : ", StrError ( NET_ERROR_CODE ) );
190
                
sletz's avatar
sletz committed
191
192
            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))
193
            {
194
195
                jack_error ( "Problem with network." );
                return false;
196
            }
197
198
            
            SessionParamsNToH(&net_params, &host_params);
199
        }
200
        while ( ( GetPacketType ( &host_params ) != START_MASTER ) && ( ++attempt < SLAVE_SETUP_RETRY ) );
sletz's avatar
sletz committed
201
        if ( attempt == SLAVE_SETUP_RETRY ) {
202
203
            jack_error ( "Slave doesn't respond, exiting." );
            return false;
204
205
        }

206
        return true;
207
208
    }

moret's avatar
moret committed
209
210
    int JackNetMasterInterface::SetRxTimeout()
    {
moret's avatar
moret committed
211
212
        jack_log ( "JackNetMasterInterface::SetRxTimeout" );

moret's avatar
moret committed
213
        float time = 0;
sletz's avatar
sletz committed
214
        
moret's avatar
moret committed
215
        //slow or normal mode, short timeout on recv (2 audio subcycles)
sletz's avatar
sletz committed
216
217
218
219
220
        if ((fParams.fNetworkMode == 's') || (fParams.fNetworkMode == 'n')) {
            time = 2000000.f * ((fNetAudioCaptureBuffer) 
                                ? fNetAudioCaptureBuffer->GetCycleDuration() 
                                : (fNetAudioPlaybackBuffer) ? fNetAudioPlaybackBuffer->GetCycleDuration() : 0);
        }
moret's avatar
moret committed
221
        //fast mode, wait for 75% of the entire cycle duration
sletz's avatar
sletz committed
222
223
224
225
226
        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));
moret's avatar
moret committed
227
228
    }

sletz's avatar
sletz committed
229
    bool JackNetMasterInterface::SetParams()
moret's avatar
moret committed
230
    {
231
        jack_log ( "JackNetMasterInterface::SetParams" );
moret's avatar
moret committed
232
233
234

        JackNetInterface::SetParams();

235
236
        fTxHeader.fDataStream = 's';
        fRxHeader.fDataStream = 'r';
moret's avatar
moret committed
237
238

        //midi net buffers
239
240
        fNetMidiCaptureBuffer = new NetMidiBuffer ( &fParams, fParams.fSendMidiChannels, fTxData );
        fNetMidiPlaybackBuffer = new NetMidiBuffer ( &fParams, fParams.fReturnMidiChannels, fRxData );
241
242
        assert ( fNetMidiCaptureBuffer );
        assert ( fNetMidiPlaybackBuffer );
moret's avatar
moret committed
243

sletz's avatar
sletz committed
244
        try {
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
        
            //audio net buffers
            if (fParams.fSendAudioChannels) {
            
                switch (fParams.fSampleEncoder) {
                    
                    case JackFloatEncoder:
                        fNetAudioCaptureBuffer = new NetFloatAudioBuffer ( &fParams, fParams.fSendAudioChannels, fTxData );
                        break;
                        
                    case JackIntEncoder:
                         fNetAudioCaptureBuffer = new NetIntAudioBuffer ( &fParams, fParams.fSendAudioChannels, fTxData );
                        break;
                        
                    case JackCeltEncoder:
                    #ifdef CELT
                        fNetAudioCaptureBuffer = new NetCeltAudioBuffer ( &fParams, fParams.fSendAudioChannels, fTxData, fParams.fKBps );
                    #endif
                        break;
                }
            }
sletz's avatar
sletz committed
266
                
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
            if (fParams.fReturnAudioChannels) {
                
                switch (fParams.fSampleEncoder) {
                    
                    case JackFloatEncoder:
                         fNetAudioPlaybackBuffer = new NetFloatAudioBuffer ( &fParams, fParams.fReturnAudioChannels, fRxData );
                        break;
                        
                    case JackIntEncoder:
                        fNetAudioPlaybackBuffer = new NetIntAudioBuffer ( &fParams, fParams.fReturnAudioChannels, fRxData );
                        break;
                        
                    case JackCeltEncoder:
                    #ifdef CELT
                        fNetAudioPlaybackBuffer = new NetCeltAudioBuffer ( &fParams, fParams.fReturnAudioChannels, fRxData, fParams.fKBps  );
                    #endif
                        break;
                }
            }
sletz's avatar
sletz committed
286
            
sletz's avatar
sletz committed
287
288
289
290
        } catch (exception&) {
            jack_error("NetAudioBuffer allocation error...");
            return false;
        }
sletz's avatar
sletz committed
291
       
sletz's avatar
sletz committed
292
        //set the new timeout for the socket
sletz's avatar
sletz committed
293
294
        if (SetRxTimeout() == SOCKET_ERROR) {
            jack_error("Can't set rx timeout : %s", StrError(NET_ERROR_CODE));
sletz's avatar
sletz committed
295
296
297
298
            goto error;
        }

        //set the new rx buffer size
sletz's avatar
sletz committed
299
300
        if (SetNetBufferSize() == SOCKET_ERROR) {
            jack_error("Can't set net buffer sizes : %s", StrError(NET_ERROR_CODE));
sletz's avatar
sletz committed
301
302
303
304
305
306
            goto error;
        }
        
        return true;
            
    error:
sletz's avatar
sletz committed
307
        FreeNetworkBuffers();
sletz's avatar
sletz committed
308
        return false;
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
        
        session_params_t net_params;
sletz's avatar
sletz committed
324
        memset(&net_params, 0, sizeof ( session_params_t ));
325
326
        SessionParamsHToN(&fParams, &net_params);

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

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

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

        //audio
sletz's avatar
sletz committed
430
        if (fParams.fSendAudioChannels > 0)
431
432
        {
            fTxHeader.fDataType = 'a';
sletz's avatar
sletz committed
433
434
435
436
            data_size = fNetAudioCaptureBuffer->RenderFromJackPorts();
            fTxHeader.fNumPacket = fNetAudioCaptureBuffer->GetNumPackets();
            
            for (subproc = 0; subproc < fTxHeader.fNumPacket; subproc++)
437
438
            {
                fTxHeader.fSubCycle = subproc;
sletz's avatar
sletz committed
439
440
                fTxHeader.fIsLastPckt = (subproc == (fTxHeader.fNumPacket - 1)) ? 1 : 0;
                fTxHeader.fPacketSize = HEADER_SIZE + fNetAudioCaptureBuffer->RenderToNetwork(subproc, data_size);
sletz's avatar
sletz committed
441
442
                memcpy(fTxBuffer, &fTxHeader, HEADER_SIZE);
                if (Send(fTxHeader.fPacketSize, 0) == SOCKET_ERROR)
443
444
445
446
447
                    return SOCKET_ERROR;
            }
        }

        return 0;
448
    }
sletz's avatar
sletz committed
449
    
450
    int JackNetMasterInterface::SyncRecv()
451
452
    {
        packet_header_t* rx_head = reinterpret_cast<packet_header_t*> ( fRxBuffer );
sletz's avatar
sletz committed
453
        int rx_bytes = Recv(HEADER_SIZE, MSG_PEEK);
454
        
455
456
457
        if ( ( rx_bytes == 0 ) || ( rx_bytes == SOCKET_ERROR ) )
            return rx_bytes;

458
        fCycleOffset = fTxHeader.fCycle - rx_head->fCycle;
459
      
460
        switch ( fParams.fNetworkMode )
461
        {
462
            case 's' :
moret's avatar
moret committed
463
464
465
466
467
                //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)
sletz's avatar
sletz committed
468
                
sletz's avatar
sletz committed
469
                /*
470
                if (fCycleOffset < CYCLE_OFFSET_SLOW) {
sletz's avatar
sletz committed
471
472
                    return 0;
                } else {
473
                    rx_bytes = Recv ( rx_head->fPacketSize, 0 );
sletz's avatar
sletz committed
474
                }
sletz's avatar
sletz committed
475
                */
476
                
sletz's avatar
sletz committed
477
                rx_bytes = Recv ( rx_head->fPacketSize, 0 );
sletz's avatar
sletz committed
478
479
                
                if (fCycleOffset != fLastfCycleOffset)
480
                    jack_info("Warning : '%s' runs in slow network mode, but data received too late (%d cycle(s) offset)", fParams.fName, fCycleOffset);
sletz's avatar
sletz committed
481
                fLastfCycleOffset = fCycleOffset;
482
                break;
483

484
485
486
487
488
            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
sletz's avatar
sletz committed
489
                if (fCycleOffset < CYCLE_OFFSET_NORMAL) {
490
                    return 0;
sletz's avatar
sletz committed
491
                } else {
492
                    rx_bytes = Recv ( rx_head->fPacketSize, 0 );
sletz's avatar
sletz committed
493
                }
494
                    
sletz's avatar
sletz committed
495
                if (fCycleOffset > CYCLE_OFFSET_NORMAL)  {
496
                    jack_info("'%s' can't run in normal network mode, data received too late (%d cycle(s) offset)", fParams.fName, fCycleOffset);
sletz's avatar
sletz committed
497
                }
498
                break;
499

500
501
502
503
504
505
            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 );
506
                
sletz's avatar
sletz committed
507
                if (fCycleOffset > CYCLE_OFFSET_FAST) {
508
                    jack_info("'%s' can't run in fast network mode, data received too late (%d cycle(s) offset)", fParams.fName, fCycleOffset);
sletz's avatar
sletz committed
509
                }
510
                break;
511
        }
512

moret's avatar
moret committed
513
        fRxHeader.fIsLastPckt = rx_head->fIsLastPckt;
514
515
        return rx_bytes;
    }
516
    
517
    int JackNetMasterInterface::DataRecv()
518
519
    {
        int rx_bytes = 0;
sletz's avatar
sletz committed
520
        uint recvd_midi_pckt = 0;
sletz's avatar
sletz committed
521
        uint recvd_audio_pckt = 0;
sletz's avatar
sletz committed
522
      
523
        packet_header_t* rx_head = reinterpret_cast<packet_header_t*> ( fRxBuffer );
524
        
moret's avatar
moret committed
525
        while ( !fRxHeader.fIsLastPckt )
526
        {
moret's avatar
moret committed
527
            //how much data is queued on the rx buffer ?
sletz's avatar
sletz committed
528
            rx_bytes = Recv(HEADER_SIZE, MSG_PEEK);
529
              
sletz's avatar
sletz committed
530
            //error here, problem with recv, just skip the cycle (return -1)
moret's avatar
moret committed
531
532
            if ( rx_bytes == SOCKET_ERROR )
                return rx_bytes;
sletz's avatar
sletz committed
533
          
moret's avatar
moret committed
534
535
536
537
            if ( rx_bytes && ( rx_head->fDataStream == 'r' ) && ( rx_head->fID == fParams.fID ) )
            {
                //read data
                switch ( rx_head->fDataType )
538
                {
moret's avatar
moret committed
539
                    case 'm':   //midi
sletz's avatar
sletz committed
540
                        rx_bytes = Recv(rx_head->fPacketSize, 0);
moret's avatar
moret committed
541
                        fRxHeader.fCycle = rx_head->fCycle;
moret's avatar
moret committed
542
                        fRxHeader.fIsLastPckt = rx_head->fIsLastPckt;
sletz's avatar
sletz committed
543
                        fNetMidiPlaybackBuffer->RenderFromNetwork(rx_head->fSubCycle, rx_bytes - HEADER_SIZE);
sletz's avatar
sletz committed
544
545
                        // Last midi packet is received, so finish rendering...
                        if (++recvd_midi_pckt == rx_head->fNumPacket)
moret's avatar
moret committed
546
547
                            fNetMidiPlaybackBuffer->RenderToJackPorts();
                        break;
548

moret's avatar
moret committed
549
                    case 'a':   //audio
sletz's avatar
sletz committed
550
                        rx_bytes = Recv(rx_head->fPacketSize, 0);
moret's avatar
moret committed
551
552
                        fRxHeader.fCycle = rx_head->fCycle;
                        fRxHeader.fSubCycle = rx_head->fSubCycle;
moret's avatar
moret committed
553
                        fRxHeader.fIsLastPckt = rx_head->fIsLastPckt;
sletz's avatar
sletz committed
554
555
556
                        fNetAudioPlaybackBuffer->RenderFromNetwork (rx_head->fCycle, rx_head->fSubCycle, rx_bytes - HEADER_SIZE);
                        // Last audio packet is received, so finish rendering...
                        if (fRxHeader.fIsLastPckt)
sletz's avatar
sletz committed
557
                            fNetAudioPlaybackBuffer->RenderToJackPorts();
moret's avatar
moret committed
558
                        break;
559

moret's avatar
moret committed
560
                    case 's':   //sync
561
                        jack_info("NetMaster : overloaded, skipping receive from '%s'", fParams.fName);
sletz's avatar
sletz committed
562
                        // TODO : finish midi and audio rendering ?
sletz's avatar
sletz committed
563
                        fNetAudioPlaybackBuffer->RenderToJackPorts();
564
                        return 0;
565
566
567
                }
            }
        }
sletz's avatar
sletz committed
568
 
569
        return rx_bytes;
570
    }
571
    
sletz's avatar
sletz committed
572
    void JackNetMasterInterface::EncodeSyncPacket()
573
574
575
    {
        //this method contains every step of sync packet informations coding
        //first of all, reset sync packet
sletz's avatar
sletz committed
576
        memset ( fTxData, 0, PACKET_AVAILABLE_SIZE );
577
578

        //then, first step : transport
sletz's avatar
sletz committed
579
580
581
        if (fParams.fTransportSync) {
            EncodeTransportData();
            TransportDataHToN( &fSendTransportData,  &fSendTransportData);
582
583
584
585
586
587
588
            //copy to TxBuffer
            memcpy ( fTxData, &fSendTransportData, sizeof ( net_transport_data_t ) );
        }
        //then others (freewheel etc.)
        //...
    }

sletz's avatar
sletz committed
589
    void JackNetMasterInterface::DecodeSyncPacket()
590
591
592
    {
        //this method contains every step of sync packet informations decoding process
        //first : transport
sletz's avatar
sletz committed
593
        if (fParams.fTransportSync) {
594
595
            //copy received transport data to transport data structure
            memcpy ( &fReturnTransportData, fRxData, sizeof ( net_transport_data_t ) );
sletz's avatar
sletz committed
596
597
            TransportDataNToH( &fReturnTransportData,  &fReturnTransportData);
            DecodeTransportData();
598
599
600
601
        }
        //then others
        //...
    }
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
            {
sletz's avatar
sletz committed
623
                status = SendAvailableToMaster();
624
625
                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
    
    // Separate the connection protocol into two separated step
    
sletz's avatar
sletz committed
642
    bool JackNetSlaveInterface::InitConnection(int time_out)
643
    {
sletz's avatar
sletz committed
644
645
646
        jack_log("JackNetSlaveInterface::InitConnection()");
        int try_count = (time_out > 0) ? ((1000000 * time_out) / SLAVE_INIT_TIMEOUT) : LONG_MAX;
   
647
648
649
650
651
652
653
654
655
        //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
sletz's avatar
sletz committed
656
            status = SendAvailableToMaster(try_count);
657
658
659
            if (status == NET_SOCKET_ERROR)
                return false;
        }
sletz's avatar
sletz committed
660
        while (status != NET_CONNECTED && --try_count > 0);
661
  
sletz's avatar
sletz committed
662
        return (try_count != 0);
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
    }
    
    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;
    }
682

sletz's avatar
sletz committed
683
    net_status_t JackNetSlaveInterface::SendAvailableToMaster(long try_count)
684
    {
sletz's avatar
sletz committed
685
        jack_log ( "JackNetSlaveInterface::SendAvailableToMaster()" );
686
        //utility
687
        session_params_t host_params;
688
        int rx_bytes = 0;
sletz's avatar
sletz committed
689
     
690
        //socket
sletz's avatar
sletz committed
691
        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
        //bind the socket
sletz's avatar
sletz committed
697
        if ( fSocket.Bind() == SOCKET_ERROR ) {
698
            jack_error ( "Can't bind the socket : %s", StrError ( NET_ERROR_CODE ) );
sletz's avatar
sletz committed
699
700
            return NET_SOCKET_ERROR;
        }
701
702

        //timeout on receive
sletz's avatar
sletz committed
703
        if ( fSocket.SetTimeOut ( SLAVE_INIT_TIMEOUT ) == SOCKET_ERROR ) 
704
705
            jack_error ( "Can't set timeout : %s", StrError ( NET_ERROR_CODE ) );

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

710
711
        //send 'AVAILABLE' until 'SLAVE_SETUP' received
        jack_info ( "Waiting for a master..." );
712
713
        do
        {
714
            //send 'available'
715
            session_params_t net_params;
sletz's avatar
sletz committed
716
            memset(&net_params, 0, sizeof ( session_params_t ));
717
718
            SessionParamsHToN(&fParams, &net_params);
            if ( fSocket.SendTo ( &net_params, sizeof ( session_params_t ), 0, fMulticastIP ) == SOCKET_ERROR )
719
                jack_error ( "Error in data send : %s", StrError ( NET_ERROR_CODE ) );
720
                
721
            //filter incoming packets : don't exit while no error is detected
722
723
724
            memset(&net_params, 0, sizeof ( session_params_t ));
            rx_bytes = fSocket.CatchHost ( &net_params, sizeof ( session_params_t ), 0 );
            SessionParamsNToH(&net_params, &host_params);
725
            if ( ( rx_bytes == SOCKET_ERROR ) && ( fSocket.GetError() != NET_NO_DATA ) )
726
            {
727
728
                jack_error ( "Can't receive : %s", StrError ( NET_ERROR_CODE ) );
                return NET_RECV_ERROR;
729
730
            }
        }
sletz's avatar
sletz committed
731
        while (strcmp(host_params.fPacketType, fParams.fPacketType)  && (GetPacketType(&host_params) != SLAVE_SETUP)  && (--try_count > 0));
sletz's avatar
sletz committed
732
733
        
        // Time out failure..
sletz's avatar
sletz committed
734
735
        if (try_count == 0) {
            jack_error("Time out error in connect");
sletz's avatar
sletz committed
736
737
            return NET_CONNECT_ERROR;
        }
sletz's avatar
sletz committed
738
   
moret's avatar
moret committed
739
        //everything is OK, copy parameters
sletz's avatar
sletz committed
740
        SessionParamsDisplay(&host_params);
741
        fParams = host_params;
moret's avatar
moret committed
742

743
        //connect the socket
sletz's avatar
sletz committed
744
745
        if (fSocket.Connect() == SOCKET_ERROR) {
            jack_error("Error in connect : %s", StrError(NET_ERROR_CODE));
746
            return NET_CONNECT_ERROR;
747
        }
moret's avatar
moret committed
748
        return NET_CONNECTED;
749
750
    }

moret's avatar
moret committed
751
    net_status_t JackNetSlaveInterface::SendStartToMaster()
752
    {
sletz's avatar
sletz committed
753
        jack_log("JackNetSlaveInterface::SendStartToMaster");
moret's avatar
moret committed
754

755
        //tell the master to start
756
        session_params_t net_params;
sletz's avatar
sletz committed
757
        memset(&net_params, 0, sizeof ( session_params_t ));
758
        SetPacketType ( &fParams, START_MASTER );
759
        SessionParamsHToN(&fParams, &net_params);
sletz's avatar
sletz committed
760
        if (fSocket.Send(&net_params, sizeof(session_params_t), 0) == SOCKET_ERROR)
761
        {
sletz's avatar
sletz committed
762
763
            jack_error("Error in send : %s", StrError(NET_ERROR_CODE));
            return (fSocket.GetError() == NET_CONN_ERROR) ? NET_ERROR : NET_SEND_ERROR;
764
        }
765
        return NET_ROLLING;
766
767
    }

sletz's avatar
sletz committed
768
    bool JackNetSlaveInterface::SetParams()
moret's avatar
moret committed
769
    {
770
        jack_log ( "JackNetSlaveInterface::SetParams" );
moret's avatar
moret committed
771
772
773

        JackNetInterface::SetParams();

774
775
        fTxHeader.fDataStream = 'r';
        fRxHeader.fDataStream = 's';
moret's avatar
moret committed
776
777

        //midi net buffers
778
779
        fNetMidiCaptureBuffer = new NetMidiBuffer ( &fParams, fParams.fSendMidiChannels, fRxData );
        fNetMidiPlaybackBuffer = new NetMidiBuffer ( &fParams, fParams.fReturnMidiChannels, fTxData );
sletz's avatar
sletz committed
780
781
        assert ( fNetMidiCaptureBuffer );
        assert ( fNetMidiPlaybackBuffer );
moret's avatar
moret committed
782
783

        //audio net buffers
sletz's avatar
sletz committed
784
785
        //fNetAudioCaptureBuffer = new NetFloatAudioBuffer ( &fParams, fParams.fSendAudioChannels, fRxData );
        //fNetAudioPlaybackBuffer = new NetFloatAudioBuffer ( &fParams, fParams.fReturnAudioChannels, fTxData );
sletz's avatar
sletz committed
786
787
788
    
        try {
    #ifdef CELT
789
790
791
792
            if (fParams.fSendAudioChannels) {
               // fNetAudioCaptureBuffer = new NetCeltAudioBuffer ( &fParams, fParams.fSendAudioChannels, fRxData );
                fNetAudioCaptureBuffer = new NetIntAudioBuffer ( &fParams, fParams.fSendAudioChannels, fRxData );
            }
sletz's avatar
sletz committed
793
                
794
795
796
797
            if (fParams.fReturnAudioChannels) {
                //fNetAudioPlaybackBuffer = new NetCeltAudioBuffer ( &fParams, fParams.fReturnAudioChannels, fTxData );
                fNetAudioPlaybackBuffer = new NetIntAudioBuffer ( &fParams, fParams.fReturnAudioChannels, fTxData );
            }
sletz's avatar
sletz committed
798
799
800
            
            // fNetAudioCaptureBuffer = new NetIntAudioBuffer ( &fParams, fParams.fSendAudioChannels, fRxData );
           // fNetAudioPlaybackBuffer = new NetIntAudioBuffer ( &fParams, fParams.fReturnAudioChannels, fTxData );
sletz's avatar
sletz committed
801
    #else
sletz's avatar
sletz committed
802
803
804
            fNetAudioCaptureBuffer = new NetFloatAudioBuffer ( &fParams, fParams.fSendAudioChannels, fRxData );
            fNetAudioPlaybackBuffer = new NetFloatAudioBuffer ( &fParams, fParams.fReturnAudioChannels, fTxData );
            
sletz's avatar
sletz committed
805
806
807
            //fNetAudioCaptureBuffer = new NetBufferedAudioBuffer ( &fParams, fParams.fSendAudioChannels, fRxData );
            //fNetAudioPlaybackBuffer = new NetBufferedAudioBuffer ( &fParams, fParams.fReturnAudioChannels, fTxData );
    #endif     
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
    
            
            //audio net buffers
            if (fParams.fSendAudioChannels) {
            
                switch (fParams.fSampleEncoder) {
                    
                    case JackFloatEncoder:
                        fNetAudioCaptureBuffer = new NetFloatAudioBuffer ( &fParams, fParams.fSendAudioChannels, fRxData );
                        break;
                        
                    case JackIntEncoder:
                         fNetAudioCaptureBuffer = new NetIntAudioBuffer ( &fParams, fParams.fSendAudioChannels, fRxData );
                        break;
                        
                    case JackCeltEncoder:
                    #ifdef CELT
                        fNetAudioCaptureBuffer = new NetCeltAudioBuffer ( &fParams, fParams.fSendAudioChannels, fRxData, fParams.fKBps );
                    #endif
                        break;
                }
            }
                
            if (fParams.fReturnAudioChannels) {
                
                switch (fParams.fSampleEncoder) {
                    
                    case JackFloatEncoder:
                         fNetAudioPlaybackBuffer = new NetFloatAudioBuffer ( &fParams, fParams.fReturnAudioChannels, fTxData );
                        break;
                        
                    case JackIntEncoder:
                        fNetAudioPlaybackBuffer = new NetIntAudioBuffer ( &fParams, fParams.fReturnAudioChannels, fTxData);
                        break;
                        
                    case JackCeltEncoder:
                    #ifdef CELT
                        fNetAudioPlaybackBuffer = new NetCeltAudioBuffer ( &fParams, fParams.fReturnAudioChannels, fTxData, fParams.fKBps );
                    #endif
                        break;
                }
            }

sletz's avatar
sletz committed
851
852
853
854
855
        } catch (exception&) {
            jack_error("NetAudioBuffer allocation error...");
            return false;
        }
    
sletz's avatar
sletz committed
856
        //set the new buffer sizes
sletz's avatar
sletz committed
857
858
859
860
861
862
863
864
        if ( SetNetBufferSize() == SOCKET_ERROR ) {
            jack_error ( "Can't set net buffer sizes : %s", StrError ( NET_ERROR_CODE ) );
            goto error;
        }
     
        return true;
        
    error:
sletz's avatar
sletz committed
865
        FreeNetworkBuffers();        
sletz's avatar
sletz committed
866
        return false;
moret's avatar
moret committed
867
868
    }

sletz's avatar
sletz committed
869
    int JackNetSlaveInterface::Recv(size_t size, int flags)
870
    {
sletz's avatar
sletz committed
871
        int rx_bytes = fSocket.Recv(fRxBuffer, size, flags);
872
873
874
875
876
        //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
sletz's avatar
sletz committed
877
            if ( error == NET_NO_DATA ) {
878
879
                jack_error ( "No data, is the master still running ?" );
            //if a network error occurs, this exception will restart the driver
sletz's avatar
sletz committed
880
            } else if ( error == NET_CONN_ERROR ) {
881
                jack_error ( "Connection lost." );
moret's avatar
moret committed
882
                throw JackNetException();
sletz's avatar
sletz committed
883
            } else {
sletz's avatar
sletz committed
884
                jack_error ( "Fatal error in slave receive : %s", StrError ( NET_ERROR_CODE ) );
sletz's avatar
sletz committed
885
            }