JackNetInterface.cpp 39 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
42
43
44
45
46
47
    JackNetInterface::JackNetInterface() : fSocket()
    {
        fTxBuffer = NULL;
        fRxBuffer = NULL;
        fNetAudioCaptureBuffer = NULL;
        fNetAudioPlaybackBuffer = NULL;
        fNetMidiCaptureBuffer = NULL;
        fNetMidiPlaybackBuffer = NULL;
48
49
        memset(&fSendTransportData, 0, sizeof(net_transport_data_t));
        memset(&fReturnTransportData, 0, sizeof(net_transport_data_t));
50
51
    }

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

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

    JackNetInterface::~JackNetInterface()
    {
moret's avatar
moret committed
81
        jack_log ( "JackNetInterface::~JackNetInterface" );
moret's avatar
moret committed
82

83
84
85
86
87
88
89
90
91
        fSocket.Close();
        delete[] fTxBuffer;
        delete[] fRxBuffer;
        delete fNetAudioCaptureBuffer;
        delete fNetAudioPlaybackBuffer;
        delete fNetMidiCaptureBuffer;
        delete fNetMidiPlaybackBuffer;
    }

92
    void JackNetInterface::SetFramesPerPacket()
moret's avatar
moret committed
93
    {
moret's avatar
moret committed
94
        jack_log ( "JackNetInterface::SetFramesPerPacket" );
moret's avatar
moret committed
95

96
97
98
        if (fParams.fSendAudioChannels == 0 && fParams.fReturnAudioChannels == 0) {
            fParams.fFramesPerPacket = fParams.fPeriodSize;
        } else {
sletz's avatar
sletz committed
99
            jack_nframes_t period = ( int ) powf ( 2.f, ( int ) ( log (float (PACKET_AVAILABLE_SIZE)
100
101
102
                                               / ( max ( fParams.fReturnAudioChannels, fParams.fSendAudioChannels ) * sizeof ( sample_t ) ) ) / log ( 2. ) ) );
            fParams.fFramesPerPacket = ( period > fParams.fPeriodSize ) ? fParams.fPeriodSize : period;
        }
moret's avatar
moret committed
103
104
105
106
107
    }

    int JackNetInterface::SetNetBufferSize()
    {
        float audio_size, midi_size;
108
        int bufsize;
moret's avatar
moret committed
109
110
111
112
        //audio
        audio_size = fParams.fMtu * ( fParams.fPeriodSize / fParams.fFramesPerPacket );
        //midi
        midi_size = fParams.fMtu * ( max ( fParams.fSendMidiChannels, fParams.fReturnMidiChannels ) *
sletz's avatar
sletz committed
113
                                     fParams.fPeriodSize * sizeof(sample_t) / PACKET_AVAILABLE_SIZE);
moret's avatar
moret committed
114
        //bufsize = sync + audio + midi
115
        bufsize = MAX_LATENCY * (fParams.fMtu + ( int ) audio_size + ( int ) midi_size);
sletz's avatar
sletz committed
116
117
        
        jack_log("SetNetBufferSize bufsize = %d", bufsize);
moret's avatar
moret committed
118
119
120

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

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

127
        return 0;
moret's avatar
moret committed
128
129
130
131
132
133
    }

    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
sletz's avatar
sletz committed
134
135
        
        if (fTxHeader.fMidiDataSize <= PACKET_AVAILABLE_SIZE) {
moret's avatar
moret committed
136
            return 1;
sletz's avatar
sletz committed
137
138
139
140
141
        } else { //get the number of needed packets (simply slice the biiig buffer)
            return (fTxHeader.fMidiDataSize % PACKET_AVAILABLE_SIZE) 
                    ? (fTxHeader.fMidiDataSize / PACKET_AVAILABLE_SIZE + 1) 
                    : fTxHeader.fMidiDataSize / PACKET_AVAILABLE_SIZE;
        }
moret's avatar
moret committed
142
143
144
145
146
147
    }

    bool JackNetInterface::IsNextPacket()
    {
        packet_header_t* rx_head = reinterpret_cast<packet_header_t*> ( fRxBuffer );
        //ignore first cycle
148
        if ( fRxHeader.fCycle <= 1 ) {
moret's avatar
moret committed
149
            return true;
150
        }
moret's avatar
moret committed
151
        //same PcktID (cycle), next SubPcktID (subcycle)
152
153
154
        if ( ( fRxHeader.fSubCycle < ( fNSubProcess - 1 ) ) && ( rx_head->fCycle == fRxHeader.fCycle ) && ( rx_head->fSubCycle == ( fRxHeader.fSubCycle + 1 ) ) ) {
             return true;
        }
moret's avatar
moret committed
155
        //next PcktID (cycle), SubPcktID reset to 0 (first subcyle)
156
        if ( ( rx_head->fCycle == ( fRxHeader.fCycle + 1 ) ) && ( fRxHeader.fSubCycle == ( fNSubProcess - 1 ) ) && ( rx_head->fSubCycle == 0 ) ) {
moret's avatar
moret committed
157
            return true;
158
        }
moret's avatar
moret committed
159
        //else, packet(s) missing, return false
moret's avatar
moret committed
160
161
162
        return false;
    }

163
164
    void JackNetInterface::SetParams()
    {
moret's avatar
moret committed
165
        //number of audio subcycles (packets)
166
167
168
169
170
171
172
173
174
        fNSubProcess = fParams.fPeriodSize / fParams.fFramesPerPacket;

        //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
175
        fTxHeader.fIsLastPckt = 0;
176
177
178
179
180
181
182
183

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

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

moret's avatar
moret committed
192
        //net audio/midi buffers'addresses
sletz's avatar
sletz committed
193
194
        fTxData = fTxBuffer + HEADER_SIZE;
        fRxData = fRxBuffer + HEADER_SIZE;
195
196
    }

197
    // JackNetMasterInterface ************************************************************************************
198

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

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

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

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

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

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

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

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

        return true;
266
267
    }

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

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

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

        JackNetInterface::SetParams();

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

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

        //audio net buffers
298
299
300
301
302
303
        fNetAudioCaptureBuffer = new NetSingleAudioBuffer ( &fParams, fParams.fSendAudioChannels, fTxData );
        fNetAudioPlaybackBuffer = new NetSingleAudioBuffer ( &fParams, fParams.fReturnAudioChannels, fRxData );
        
        //fNetAudioCaptureBuffer = new NetBufferedAudioBuffer ( &fParams, fParams.fSendAudioChannels, fTxData );
        //fNetAudioPlaybackBuffer = new NetBufferedAudioBuffer ( &fParams, fParams.fReturnAudioChannels, fRxData );     
     
304
305
        assert ( fNetAudioCaptureBuffer );
        assert ( fNetAudioPlaybackBuffer );
moret's avatar
moret committed
306
307
    }

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

        //stop process
        fRunning = false;
314

315
316
317
318
        //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() );
319
320
        
        session_params_t net_params;
sletz's avatar
sletz committed
321
        memset(&net_params, 0, sizeof ( session_params_t ));
322
323
        SessionParamsHToN(&fParams, &net_params);

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

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

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

        //audio
424
        if ( fParams.fSendAudioChannels > 0)
425
426
        {
            fTxHeader.fDataType = 'a';
427
428
            fTxHeader.fMidiDataSize = 0;
            fTxHeader.fNMidiPckt = 0;
sletz's avatar
sletz committed
429
            for (subproc = 0; subproc < fNSubProcess; subproc++)
430
431
            {
                fTxHeader.fSubCycle = subproc;
sletz's avatar
sletz committed
432
                fTxHeader.fIsLastPckt = (subproc == (fNSubProcess - 1)) ? 1 : 0;
sletz's avatar
sletz committed
433
                fTxHeader.fPacketSize = HEADER_SIZE + fNetAudioPlaybackBuffer->GetSize();
sletz's avatar
sletz committed
434
435
436
                memcpy(fTxBuffer, &fTxHeader, HEADER_SIZE);
                fNetAudioCaptureBuffer->RenderFromJackPorts(subproc);
                if (Send(fTxHeader.fPacketSize, 0) == SOCKET_ERROR)
437
438
439
440
441
                    return SOCKET_ERROR;
            }
        }

        return 0;
442
443
    }

444
    int JackNetMasterInterface::SyncRecv()
445
446
    {
        packet_header_t* rx_head = reinterpret_cast<packet_header_t*> ( fRxBuffer );
sletz's avatar
sletz committed
447
        int rx_bytes = Recv(HEADER_SIZE, MSG_PEEK);
448
        
449
450
451
        if ( ( rx_bytes == 0 ) || ( rx_bytes == SOCKET_ERROR ) )
            return rx_bytes;

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

473
474
475
476
477
            case 'n' :
                //normal use of the network :
                //  - extra latency is set to one cycle, what is the time needed to receive streams using full network bandwidth
                //  - if the network is too fast, just wait the next cycle, the benefit here is the master's cycle is shorter
                //  - indeed, data is supposed to be on the network rx buffer, so we don't have to wait for it
sletz's avatar
sletz committed
478
                if (fCycleOffset < CYCLE_OFFSET_NORMAL) {
479
                    return 0;
sletz's avatar
sletz committed
480
                } else {
481
                    rx_bytes = Recv ( rx_head->fPacketSize, 0 );
sletz's avatar
sletz committed
482
                }
483
                    
sletz's avatar
sletz committed
484
                if (fCycleOffset > CYCLE_OFFSET_NORMAL)  {
485
                    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
486
                }
487
                break;
488

489
490
491
492
493
494
            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 );
495
                
sletz's avatar
sletz committed
496
                if (fCycleOffset > CYCLE_OFFSET_FAST) {
497
                    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
498
                }
499
                break;
500
        }
501

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

moret's avatar
moret committed
538
                    case 'a':   //audio
539
                        rx_bytes = Recv ( rx_head->fPacketSize, 0 );
sletz's avatar
sletz committed
540
541
                        if (!IsNextPacket()) {
                            jack_error("Packet(s) missing from '%s'...", fParams.fMasterNetName);
542
                        }
moret's avatar
moret committed
543
544
                        fRxHeader.fCycle = rx_head->fCycle;
                        fRxHeader.fSubCycle = rx_head->fSubCycle;
moret's avatar
moret committed
545
                        fRxHeader.fIsLastPckt = rx_head->fIsLastPckt;
546
547
                        fNetAudioPlaybackBuffer->RenderToJackPorts ( rx_head->fCycle,  rx_head->fSubCycle);
                        last_cycle = rx_head->fCycle;
moret's avatar
moret committed
548
                        break;
549

moret's avatar
moret committed
550
                    case 's':   //sync
551
                        jack_info("NetMaster : overloaded, skipping receive from '%s'", fParams.fName);
552
553
                        // Finish rendering (copy to JACK ports)
                        fNetAudioPlaybackBuffer->FinishRenderToJackPorts(last_cycle); 
554
                        return 0;
555
556
557
                }
            }
        }
558
559
560
        
        // Finish rendering (copy to JACK ports)
        fNetAudioPlaybackBuffer->FinishRenderToJackPorts(last_cycle); 
561
        return rx_bytes;
562
    }
563
    
sletz's avatar
sletz committed
564
    void JackNetMasterInterface::EncodeSyncPacket()
565
566
567
    {
        //this method contains every step of sync packet informations coding
        //first of all, reset sync packet
sletz's avatar
sletz committed
568
        memset ( fTxData, 0, PACKET_AVAILABLE_SIZE );
569
570

        //then, first step : transport
sletz's avatar
sletz committed
571
572
573
        if (fParams.fTransportSync) {
            EncodeTransportData();
            TransportDataHToN( &fSendTransportData,  &fSendTransportData);
574
575
576
577
578
579
580
            //copy to TxBuffer
            memcpy ( fTxData, &fSendTransportData, sizeof ( net_transport_data_t ) );
        }
        //then others (freewheel etc.)
        //...
    }

sletz's avatar
sletz committed
581
    void JackNetMasterInterface::DecodeSyncPacket()
582
583
584
    {
        //this method contains every step of sync packet informations decoding process
        //first : transport
sletz's avatar
sletz committed
585
        if (fParams.fTransportSync) {
586
587
            //copy received transport data to transport data structure
            memcpy ( &fReturnTransportData, fRxData, sizeof ( net_transport_data_t ) );
sletz's avatar
sletz committed
588
589
            TransportDataNToH( &fReturnTransportData,  &fReturnTransportData);
            DecodeTransportData();
590
591
592
593
        }
        //then others
        //...
    }
594

595
596
// JackNetSlaveInterface ************************************************************************************************

moret's avatar
moret committed
597
598
    uint JackNetSlaveInterface::fSlaveCounter = 0;

599
    bool JackNetSlaveInterface::Init()
600
    {
601
        jack_log ( "JackNetSlaveInterface::Init()" );
602

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

608
609
610
        //init loop : get a master and start, do it until connection is ok
        net_status_t status;
        do
611
        {
612
613
            //first, get a master, do it until a valid connection is running
            do
614
            {
sletz's avatar
sletz committed
615
                status = SendAvailableToMaster();
616
617
                if ( status == NET_SOCKET_ERROR )
                    return false;
618
            }
619
            while ( status != NET_CONNECTED );
620

621
622
            //then tell the master we are ready
            jack_info ( "Initializing connection with %s...", fParams.fMasterNetName );
moret's avatar
moret committed
623
            status = SendStartToMaster();
624
625
            if ( status == NET_ERROR )
                return false;
626
        }
627
        while ( status != NET_ROLLING );
628

629
630
        return true;
    }
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
    
    // 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
sletz's avatar
sletz committed
647
            status = SendAvailableToMaster();
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
            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;
    }
673

sletz's avatar
sletz committed
674
    net_status_t JackNetSlaveInterface::SendAvailableToMaster()
675
    {
sletz's avatar
sletz committed
676
        jack_log ( "JackNetSlaveInterface::SendAvailableToMaster()" );
677
        //utility
678
        session_params_t host_params;
679
        int rx_bytes = 0;
sletz's avatar
sletz committed
680
681
        
        jack_log ( "sizeof (session_params_t) %d", sizeof (session_params_t) );
682
683

        //socket
sletz's avatar
sletz committed
684
        if ( fSocket.NewSocket() == SOCKET_ERROR ) {
685
686
            jack_error ( "Fatal error : network unreachable - %s", StrError ( NET_ERROR_CODE ) );
            return NET_SOCKET_ERROR;
687
688
        }

689
        //bind the socket
sletz's avatar
sletz committed
690
        if ( fSocket.Bind() == SOCKET_ERROR ) {
691
            jack_error ( "Can't bind the socket : %s", StrError ( NET_ERROR_CODE ) );
sletz's avatar
sletz committed
692
693
            return NET_SOCKET_ERROR;
        }
694
695

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

699
        //disable local loop
moret's avatar
moret committed
700
        if ( fSocket.SetLocalLoop() == SOCKET_ERROR )
701
            jack_error ( "Can't disable multicast loop : %s", StrError ( NET_ERROR_CODE ) );
702

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

        //set the new buffer sizes
sletz's avatar
sletz committed
731
        if ( SetNetBufferSize() == SOCKET_ERROR ) {
moret's avatar
moret committed
732
            jack_error ( "Can't set net buffer sizes : %s", StrError ( NET_ERROR_CODE ) );
sletz's avatar
sletz committed
733
734
             return NET_SOCKET_ERROR;
        }
moret's avatar
moret committed
735

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

moret's avatar
moret committed
742
        return NET_CONNECTED;
743
744
    }

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

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

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

        JackNetInterface::SetParams();

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

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

        //audio net buffers
778
779
780
781
782
        fNetAudioCaptureBuffer = new NetSingleAudioBuffer ( &fParams, fParams.fSendAudioChannels, fRxData );
        fNetAudioPlaybackBuffer = new NetSingleAudioBuffer ( &fParams, fParams.fReturnAudioChannels, fTxData );
        
        //fNetAudioCaptureBuffer = new NetBufferedAudioBuffer ( &fParams, fParams.fSendAudioChannels, fRxData );
        //fNetAudioPlaybackBuffer = new NetBufferedAudioBuffer ( &fParams, fParams.fReturnAudioChannels, fTxData );
sletz's avatar
sletz committed
783
784
785
        
        assert ( fNetAudioCaptureBuffer );
        assert ( fNetAudioPlaybackBuffer );
moret's avatar
moret committed
786
787
    }

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

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

833
    int JackNetSlaveInterface::SyncRecv()
834
    {
835
836
        int rx_bytes = 0;
        packet_header_t* rx_head = reinterpret_cast<packet_header_t*> ( fRxBuffer );
sletz's avatar
sletz committed
837
        
838
839