JackNetInterface.cpp 31 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
24
25
26
27
28
29

using namespace std;

namespace Jack
{
    // JackNetInterface*******************************************

30
31
32
33
34
35
36
37
38
39
40
    JackNetInterface::JackNetInterface() : fSocket()
    {
        fMulticastIP = NULL;
        fTxBuffer = NULL;
        fRxBuffer = NULL;
        fNetAudioCaptureBuffer = NULL;
        fNetAudioPlaybackBuffer = NULL;
        fNetMidiCaptureBuffer = NULL;
        fNetMidiPlaybackBuffer = NULL;
    }

moret's avatar
moret committed
41
    JackNetInterface::JackNetInterface ( const char* multicast_ip, int port ) : fSocket ( multicast_ip, port )
42
    {
moret's avatar
moret committed
43
        fMulticastIP = strdup ( multicast_ip );
44
45
46
47
48
49
        fTxBuffer = NULL;
        fRxBuffer = NULL;
        fNetAudioCaptureBuffer = NULL;
        fNetAudioPlaybackBuffer = NULL;
        fNetMidiCaptureBuffer = NULL;
        fNetMidiPlaybackBuffer = NULL;
50
51
    }

moret's avatar
moret committed
52
    JackNetInterface::JackNetInterface ( session_params_t& params, JackNetSocket& socket, const char* multicast_ip ) : fSocket ( socket )
53
    {
moret's avatar
moret committed
54
        fParams = params;
moret's avatar
moret committed
55
        fMulticastIP = strdup ( multicast_ip );
56
57
58
59
60
61
        fTxBuffer = NULL;
        fRxBuffer = NULL;
        fNetAudioCaptureBuffer = NULL;
        fNetAudioPlaybackBuffer = NULL;
        fNetMidiCaptureBuffer = NULL;
        fNetMidiPlaybackBuffer = NULL;
62
63
64
65
    }

    JackNetInterface::~JackNetInterface()
    {
moret's avatar
moret committed
66
        jack_log ( "JackNetInterface::~JackNetInterface" );
moret's avatar
moret committed
67

68
69
70
71
72
73
74
75
76
77
        fSocket.Close();
        delete[] fTxBuffer;
        delete[] fRxBuffer;
        delete[] fMulticastIP;
        delete fNetAudioCaptureBuffer;
        delete fNetAudioPlaybackBuffer;
        delete fNetMidiCaptureBuffer;
        delete fNetMidiPlaybackBuffer;
    }

moret's avatar
moret committed
78
79
    jack_nframes_t JackNetInterface::SetFramesPerPacket()
    {
moret's avatar
moret committed
80
        jack_log ( "JackNetInterface::SetFramesPerPacket" );
moret's avatar
moret committed
81

moret's avatar
moret committed
82
83
84
85
        if ( !fParams.fSendAudioChannels && !fParams.fReturnAudioChannels )
            return ( fParams.fFramesPerPacket = fParams.fPeriodSize );
        jack_nframes_t period = ( int ) powf ( 2.f, ( int ) ( log ( ( fParams.fMtu - sizeof ( packet_header_t ) )
                                               / ( max ( fParams.fReturnAudioChannels, fParams.fSendAudioChannels ) * sizeof ( sample_t ) ) ) / log ( 2 ) ) );
moret's avatar
moret committed
86
        return ( fParams.fFramesPerPacket = ( period > fParams.fPeriodSize ) ? fParams.fPeriodSize : period );
moret's avatar
moret committed
87
88
89
90
    }

    int JackNetInterface::SetNetBufferSize()
    {
moret's avatar
moret committed
91
        jack_log ( "JackNetInterface::SetNetBufferSize" );
moret's avatar
moret committed
92

moret's avatar
moret committed
93
94
95
96
97
98
        float audio_size, midi_size;
        int bufsize, res = 0;
        //audio
        audio_size = fParams.fMtu * ( fParams.fPeriodSize / fParams.fFramesPerPacket );
        //midi
        midi_size = fParams.fMtu * ( max ( fParams.fSendMidiChannels, fParams.fReturnMidiChannels ) *
moret's avatar
moret committed
99
                                     fParams.fPeriodSize * sizeof ( sample_t ) / ( fParams.fMtu - sizeof ( packet_header_t ) ) );
moret's avatar
moret committed
100
101
        //bufsize = sync + audio + midi
        bufsize = fParams.fMtu + ( int ) audio_size + ( int ) midi_size;
moret's avatar
moret committed
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135

        //tx buffer
        if ( fSocket.SetOption ( SOL_SOCKET, SO_SNDBUF, &bufsize, sizeof ( bufsize ) ) == SOCKET_ERROR )
            res = SOCKET_ERROR;

        //rx buffer
        if ( fSocket.SetOption ( SOL_SOCKET, SO_RCVBUF, &bufsize, sizeof ( bufsize ) ) == SOCKET_ERROR )
            res = SOCKET_ERROR;

        return res;
    }

    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
        if ( fRxHeader.fCycle <= 1 )
            return true;
        //same PcktID (cycle), next SubPcktID (subcycle)
        if ( ( fRxHeader.fSubCycle < ( fNSubProcess - 1 ) ) && ( rx_head->fCycle == fRxHeader.fCycle ) && ( rx_head->fSubCycle == ( fRxHeader.fSubCycle + 1 ) ) )
            return true;
moret's avatar
moret committed
136
        //next PcktID (cycle), SubPcktID reset to 0 (first subcyle)
moret's avatar
moret committed
137
138
        if ( ( rx_head->fCycle == ( fRxHeader.fCycle + 1 ) ) && ( fRxHeader.fSubCycle == ( fNSubProcess - 1 ) ) && ( rx_head->fSubCycle == 0 ) )
            return true;
moret's avatar
moret committed
139
        //else, packet(s) missing, return false
moret's avatar
moret committed
140
141
142
        return false;
    }

143
144
    void JackNetInterface::SetParams()
    {
moret's avatar
moret committed
145
        //number of audio subcycles (packets)
146
147
        fNSubProcess = fParams.fPeriodSize / fParams.fFramesPerPacket;

moret's avatar
moret committed
148
149
150
        //payload size
        fPayloadSize = fParams.fMtu - sizeof ( packet_header_t );

151
152
153
154
155
156
157
        //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
158
        fTxHeader.fIsLastPckt = 0;
159
160
161
162
163
164
165
166

        //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
167
        fRxHeader.fIsLastPckt = 0;
168
169
170
171
172

        //network buffers
        fTxBuffer = new char[fParams.fMtu];
        fRxBuffer = new char[fParams.fMtu];

moret's avatar
moret committed
173
        //net audio/midi buffers'addresses
174
175
176
177
        fTxData = fTxBuffer + sizeof ( packet_header_t );
        fRxData = fRxBuffer + sizeof ( packet_header_t );
    }

178
    // JackNetMasterInterface ************************************************************************************
179

180
    bool JackNetMasterInterface::Init()
181
    {
182
        jack_log ( "JackNetMasterInterface::Init, ID %u.", fParams.fID );
183
184

        session_params_t params;
185
        uint attempt = 0;
186
187
188
189
190
        int rx_bytes = 0;

        //socket
        if ( fSocket.NewSocket() == SOCKET_ERROR )
        {
191
192
            jack_error ( "Can't create socket : %s", StrError ( NET_ERROR_CODE ) );
            return false;
193
194
        }

195
        //timeout on receive (for init)
196
        if ( fSocket.SetTimeOut ( MASTER_INIT_TIMEOUT ) < 0 )
197
198
            jack_error ( "Can't set timeout : %s", StrError ( NET_ERROR_CODE ) );

199
200
201
202
203
204
        //connect
        if ( fSocket.Connect() == SOCKET_ERROR )
        {
            jack_error ( "Can't connect : %s", StrError ( NET_ERROR_CODE ) );
            return false;
        }
205

moret's avatar
moret committed
206
        //set the number of complete audio frames we can put in a packet
moret's avatar
moret committed
207
208
        SetFramesPerPacket();

209
210
        //send 'SLAVE_SETUP' until 'START_MASTER' received
        jack_info ( "Sending parameters to %s ...", fParams.fSlaveNetName );
211
212
        do
        {
213
214
215
216
            SetPacketType ( &fParams, SLAVE_SETUP );
            if ( fSocket.Send ( &fParams, sizeof ( session_params_t ), 0 ) == SOCKET_ERROR )
                jack_error ( "Error in send : ", StrError ( NET_ERROR_CODE ) );
            if ( ( ( rx_bytes = fSocket.Recv ( &params, sizeof ( session_params_t ), 0 ) ) == SOCKET_ERROR ) && ( fSocket.GetError() != NET_NO_DATA ) )
217
            {
218
219
                jack_error ( "Problem with network." );
                return false;
220
221
            }
        }
222
223
        while ( ( GetPacketType ( &params ) != START_MASTER ) && ( ++attempt < SLAVE_SETUP_RETRY ) );
        if ( attempt == SLAVE_SETUP_RETRY )
224
        {
225
226
            jack_error ( "Slave doesn't respond, exiting." );
            return false;
227
228
        }

229
        //set the new timeout for the socket
moret's avatar
moret committed
230
        if ( SetRxTimeout() == SOCKET_ERROR )
231
232
233
234
        {
            jack_error ( "Can't set rx timeout : %s", StrError ( NET_ERROR_CODE ) );
            return false;
        }
235

236
        //set the new rx buffer size
moret's avatar
moret committed
237
        if ( SetNetBufferSize() == SOCKET_ERROR )
238
        {
moret's avatar
moret committed
239
            jack_error ( "Can't set net buffer sizes : %s", StrError ( NET_ERROR_CODE ) );
240
            return false;
241
        }
242
243

        return true;
244
245
    }

moret's avatar
moret committed
246
247
    int JackNetMasterInterface::SetRxTimeout()
    {
moret's avatar
moret committed
248
249
        jack_log ( "JackNetMasterInterface::SetRxTimeout" );

moret's avatar
moret committed
250
        float time = 0;
moret's avatar
moret committed
251
252
        //slow or normal mode, short timeout on recv (2 audio subcycles)
        if ( ( fParams.fNetworkMode == 's' ) || ( fParams.fNetworkMode == 'n' ) )
moret's avatar
moret committed
253
            time = 2000000.f * ( static_cast<float> ( fParams.fFramesPerPacket ) / static_cast<float> ( fParams.fSampleRate ) );
moret's avatar
moret committed
254
        //fast mode, wait for 75% of the entire cycle duration
moret's avatar
moret committed
255
256
257
258
259
        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 ) );
    }

260
    void JackNetMasterInterface::SetParams()
moret's avatar
moret committed
261
    {
262
        jack_log ( "JackNetMasterInterface::SetParams" );
moret's avatar
moret committed
263
264
265

        JackNetInterface::SetParams();

266
267
        fTxHeader.fDataStream = 's';
        fRxHeader.fDataStream = 'r';
moret's avatar
moret committed
268
269

        //midi net buffers
270
271
        fNetMidiCaptureBuffer = new NetMidiBuffer ( &fParams, fParams.fSendMidiChannels, fTxData );
        fNetMidiPlaybackBuffer = new NetMidiBuffer ( &fParams, fParams.fReturnMidiChannels, fRxData );
moret's avatar
moret committed
272
273

        //audio net buffers
274
275
        fNetAudioCaptureBuffer = new NetAudioBuffer ( &fParams, fParams.fSendAudioChannels, fTxData );
        fNetAudioPlaybackBuffer = new NetAudioBuffer ( &fParams, fParams.fReturnAudioChannels, fRxData );
moret's avatar
moret committed
276
277
278
279
280
281

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

282
    void JackNetMasterInterface::Exit()
283
    {
284
285
286
287
        jack_log ( "JackNetMasterInterface::Exit, ID %u", fParams.fID );

        //stop process
        fRunning = false;
288
        
289
290
291
292
293
294
295
296
297
        //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() );
        if ( mcast_socket.NewSocket() == SOCKET_ERROR )
            jack_error ( "Can't create socket : %s", StrError ( NET_ERROR_CODE ) );
        if ( mcast_socket.SendTo ( &fParams, sizeof ( session_params_t ), 0, fMulticastIP ) == SOCKET_ERROR )
            jack_error ( "Can't send suicide request : %s", StrError ( NET_ERROR_CODE ) );
        mcast_socket.Close();
298
299
300
        
        // UGLY temporary way to be sure the thread does not call code possibly causing a deadlock in JackEngine.
        ThreadExit();
301
302
303
304
305
    }

    int JackNetMasterInterface::Send ( size_t size, int flags )
    {
        int tx_bytes;
moret's avatar
moret committed
306
        if ( ( ( tx_bytes = fSocket.Send ( fTxBuffer, size, flags ) ) == SOCKET_ERROR ) && fRunning )
307
308
        {
            net_error_t error = fSocket.GetError();
moret's avatar
moret committed
309
            if ( error == NET_CONN_ERROR )
310
311
312
313
314
            {
                //fatal connection issue, exit
                jack_error ( "'%s' : %s, exiting.", fParams.fName, StrError ( NET_ERROR_CODE ) );
                Exit();
            }
moret's avatar
moret committed
315
            else
316
317
318
319
320
321
322
323
                jack_error ( "Error in send : %s", StrError ( NET_ERROR_CODE ) );
        }
        return tx_bytes;
    }

    int JackNetMasterInterface::Recv ( size_t size, int flags )
    {
        int rx_bytes;
moret's avatar
moret committed
324
        if ( ( ( rx_bytes = fSocket.Recv ( fRxBuffer, size, flags ) ) == SOCKET_ERROR ) && fRunning )
325
326
327
        {
            net_error_t error = fSocket.GetError();
            //no data isn't really a network error, so just return 0 avalaible read bytes
328
            if ( error == NET_NO_DATA )
329
                return 0;
moret's avatar
moret committed
330
            else if ( error == NET_CONN_ERROR )
331
            {
332
333
334
335
                //fatal connection issue, exit
                jack_error ( "'%s' : %s, exiting.", fParams.fName, StrError ( NET_ERROR_CODE ) );
                //ask to the manager to properly remove the master
                Exit();
336
            }
moret's avatar
moret committed
337
            else
338
                jack_error ( "Error in receive : %s", StrError ( NET_ERROR_CODE ) );
339
340
341
342
        }
        return rx_bytes;
    }

343
    int JackNetMasterInterface::SyncSend()
344
    {
345
346
347
        fTxHeader.fCycle++;
        fTxHeader.fSubCycle = 0;
        fTxHeader.fDataType = 's';
moret's avatar
moret committed
348
        fTxHeader.fIsLastPckt = ( !fParams.fSendMidiChannels && !fParams.fSendAudioChannels ) ?  1 : 0;
349
350
351
352
353
354
355
356
357
358
        fTxHeader.fPacketSize = fParams.fMtu;
        memcpy ( fTxBuffer, &fTxHeader, sizeof ( packet_header_t ) );
        return Send ( fTxHeader.fPacketSize, 0 );
    }

    int JackNetMasterInterface::DataSend()
    {
        uint subproc;
        //midi
        if ( fParams.fSendMidiChannels )
359
        {
360
361
362
            //set global header fields and get the number of midi packets
            fTxHeader.fDataType = 'm';
            fTxHeader.fMidiDataSize = fNetMidiCaptureBuffer->RenderFromJackPorts();
moret's avatar
moret committed
363
            fTxHeader.fNMidiPckt = GetNMidiPckt();
364
            for ( subproc = 0; subproc < fTxHeader.fNMidiPckt; subproc++ )
365
            {
366
                fTxHeader.fSubCycle = subproc;
moret's avatar
moret committed
367
                fTxHeader.fIsLastPckt = ( ( subproc == ( fTxHeader.fNMidiPckt - 1 ) ) && !fParams.fSendAudioChannels ) ? 1 : 0;
moret's avatar
moret committed
368
369
                fTxHeader.fPacketSize = sizeof ( packet_header_t );
                fTxHeader.fPacketSize += fNetMidiCaptureBuffer->RenderToNetwork ( subproc, fTxHeader.fMidiDataSize );
370
371
372
                memcpy ( fTxBuffer, &fTxHeader, sizeof ( packet_header_t ) );
                if ( Send ( fTxHeader.fPacketSize, 0 ) == SOCKET_ERROR )
                    return SOCKET_ERROR;
373
374
            }
        }
375
376
377
378
379
380
381
382

        //audio
        if ( fParams.fSendAudioChannels )
        {
            fTxHeader.fDataType = 'a';
            for ( subproc = 0; subproc < fNSubProcess; subproc++ )
            {
                fTxHeader.fSubCycle = subproc;
moret's avatar
moret committed
383
                fTxHeader.fIsLastPckt = ( subproc == ( fNSubProcess - 1 ) ) ? 1 : 0;
384
385
386
387
388
389
390
391
392
                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;
393
394
    }

395
    int JackNetMasterInterface::SyncRecv()
396
    {
397
398
        int rx_bytes = 0;
        int cycle_offset = 0;
399
        packet_header_t* rx_head = reinterpret_cast<packet_header_t*> ( fRxBuffer );
400
401
402
403
404
405
406
        rx_bytes = Recv ( fParams.fMtu, MSG_PEEK );
        if ( ( rx_bytes == 0 ) || ( rx_bytes == SOCKET_ERROR ) )
            return rx_bytes;

        cycle_offset = fTxHeader.fCycle - rx_head->fCycle;

        switch ( fParams.fNetworkMode )
407
        {
408
            case 's' :
moret's avatar
moret committed
409
410
411
412
413
                //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)
414
415
416
417
418
                if ( cycle_offset < 2 )
                    return 0;
                else
                    rx_bytes = Recv ( rx_head->fPacketSize, 0 );
                break;
419
                
420
421
422
423
424
425
426
427
428
429
            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
                if ( cycle_offset < 1 )
                    return 0;
                else
                    rx_bytes = Recv ( rx_head->fPacketSize, 0 );
                break;
430
                
431
432
433
434
435
436
437
438
439
            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 );
                if ( cycle_offset )
                    jack_error ( "'%s' can't run in fast network mode, data received too late (%d cycle(s) offset)", fParams.fName, cycle_offset );
                break;
440
        }
441
        
moret's avatar
moret committed
442
        fRxHeader.fIsLastPckt = rx_head->fIsLastPckt;
443
444
445
        return rx_bytes;
    }

446
    int JackNetMasterInterface::DataRecv()
447
448
    {
        int rx_bytes = 0;
449
450
        uint jumpcnt = 0;
        uint midi_recvd_pckt = 0;
451
452
        packet_header_t* rx_head = reinterpret_cast<packet_header_t*> ( fRxBuffer );

moret's avatar
moret committed
453
        while ( !fRxHeader.fIsLastPckt )
454
        {
moret's avatar
moret committed
455
456
457
458
            //how much data is queued on the rx buffer ?
            rx_bytes = Recv ( fParams.fMtu, MSG_PEEK );
            if ( rx_bytes == SOCKET_ERROR )
                return rx_bytes;
moret's avatar
moret committed
459
            //if no data
moret's avatar
moret committed
460
            if ( ( rx_bytes == 0 ) && ( ++jumpcnt == fNSubProcess ) )
461
            {
moret's avatar
moret committed
462
463
464
465
466
467
468
469
                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 )
470
                {
moret's avatar
moret committed
471
472
473
                    case 'm':   //midi
                        Recv ( rx_head->fPacketSize, 0 );
                        fRxHeader.fCycle = rx_head->fCycle;
moret's avatar
moret committed
474
                        fRxHeader.fIsLastPckt = rx_head->fIsLastPckt;
moret's avatar
moret committed
475
476
477
478
479
                        fNetMidiPlaybackBuffer->RenderFromNetwork ( rx_head->fSubCycle, rx_bytes - sizeof ( packet_header_t ) );
                        if ( ++midi_recvd_pckt == rx_head->fNMidiPckt )
                            fNetMidiPlaybackBuffer->RenderToJackPorts();
                        jumpcnt = 0;
                        break;
480
                        
moret's avatar
moret committed
481
482
483
484
485
486
                    case 'a':   //audio
                        Recv ( rx_head->fPacketSize, 0 );
                        if ( !IsNextPacket() )
                            jack_error ( "Packet(s) missing from '%s'...", fParams.fName );
                        fRxHeader.fCycle = rx_head->fCycle;
                        fRxHeader.fSubCycle = rx_head->fSubCycle;
moret's avatar
moret committed
487
                        fRxHeader.fIsLastPckt = rx_head->fIsLastPckt;
moret's avatar
moret committed
488
489
490
                        fNetAudioPlaybackBuffer->RenderToJackPorts ( rx_head->fSubCycle );
                        jumpcnt = 0;
                        break;
491
                        
moret's avatar
moret committed
492
493
494
                    case 's':   //sync
                        if ( rx_head->fCycle == fTxHeader.fCycle )
                            return 0;
495
                        break;
496
497
498
                }
            }
        }
499
        return rx_bytes;
500
501
    }

502
503
// JackNetSlaveInterface ************************************************************************************************

moret's avatar
moret committed
504
505
    uint JackNetSlaveInterface::fSlaveCounter = 0;

506
    bool JackNetSlaveInterface::Init()
507
    {
508
        jack_log ( "JackNetSlaveInterface::Init()" );
509

510
511
512
513
        //set the parameters to send
        strcpy ( fParams.fPacketType, "params" );
        fParams.fProtocolVersion = 'a';
        SetPacketType ( &fParams, SLAVE_AVAILABLE );
514

515
516
517
        //init loop : get a master and start, do it until connection is ok
        net_status_t status;
        do
518
        {
519
520
            //first, get a master, do it until a valid connection is running
            do
521
            {
522
523
524
                status = GetNetMaster();
                if ( status == NET_SOCKET_ERROR )
                    return false;
525
            }
526
            while ( status != NET_CONNECTED );
527

528
529
            //then tell the master we are ready
            jack_info ( "Initializing connection with %s...", fParams.fMasterNetName );
moret's avatar
moret committed
530
            status = SendStartToMaster();
531
532
            if ( status == NET_ERROR )
                return false;
533
        }
534
        while ( status != NET_ROLLING );
535

536
537
        return true;
    }
538

539
    net_status_t JackNetSlaveInterface::GetNetMaster()
540
    {
541
542
        jack_log ( "JackNetSlaveInterface::GetNetMaster()" );
        //utility
543
544
545
546
547
548
        session_params_t params;
        int rx_bytes = 0;

        //socket
        if ( fSocket.NewSocket() == SOCKET_ERROR )
        {
549
550
            jack_error ( "Fatal error : network unreachable - %s", StrError ( NET_ERROR_CODE ) );
            return NET_SOCKET_ERROR;
551
552
        }

553
554
555
556
557
        //bind the socket
        if ( fSocket.Bind() == SOCKET_ERROR )
            jack_error ( "Can't bind the socket : %s", StrError ( NET_ERROR_CODE ) );

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

561
        //disable local loop
moret's avatar
moret committed
562
        if ( fSocket.SetLocalLoop() == SOCKET_ERROR )
563
            jack_error ( "Can't disable multicast loop : %s", StrError ( NET_ERROR_CODE ) );
564

565
566
        //send 'AVAILABLE' until 'SLAVE_SETUP' received
        jack_info ( "Waiting for a master..." );
567
568
        do
        {
569
570
571
572
573
574
            //send 'available'
            if ( fSocket.SendTo ( &fParams, sizeof ( session_params_t ), 0, fMulticastIP ) == SOCKET_ERROR )
                jack_error ( "Error in data send : %s", StrError ( NET_ERROR_CODE ) );
            //filter incoming packets : don't exit while no error is detected
            rx_bytes = fSocket.CatchHost ( &params, sizeof ( session_params_t ), 0 );
            if ( ( rx_bytes == SOCKET_ERROR ) && ( fSocket.GetError() != NET_NO_DATA ) )
575
            {
576
577
                jack_error ( "Can't receive : %s", StrError ( NET_ERROR_CODE ) );
                return NET_RECV_ERROR;
578
579
            }
        }
580
        while ( strcmp ( params.fPacketType, fParams.fPacketType ) && ( GetPacketType ( &params ) != SLAVE_SETUP ) );
581

moret's avatar
moret committed
582
583
584
585
586
587
588
        //everything is OK, copy parameters
        fParams = params;

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

589
590
        //connect the socket
        if ( fSocket.Connect() == SOCKET_ERROR )
591
        {
592
593
            jack_error ( "Error in connect : %s", StrError ( NET_ERROR_CODE ) );
            return NET_CONNECT_ERROR;
594
595
        }

moret's avatar
moret committed
596
        return NET_CONNECTED;
597
598
    }

moret's avatar
moret committed
599
    net_status_t JackNetSlaveInterface::SendStartToMaster()
600
    {
moret's avatar
moret committed
601
        jack_log ( "JackNetSlaveInterface::SendStartToMaster" );
moret's avatar
moret committed
602

603
604
605
        //tell the master to start
        SetPacketType ( &fParams, START_MASTER );
        if ( fSocket.Send ( &fParams, sizeof ( session_params_t ), 0 ) == SOCKET_ERROR )
606
        {
607
608
            jack_error ( "Error in send : %s", StrError ( NET_ERROR_CODE ) );
            return ( fSocket.GetError() == NET_CONN_ERROR ) ? NET_ERROR : NET_SEND_ERROR;
609
        }
610
        return NET_ROLLING;
611
612
    }

613
    void JackNetSlaveInterface::SetParams()
moret's avatar
moret committed
614
    {
615
        jack_log ( "JackNetSlaveInterface::SetParams" );
moret's avatar
moret committed
616
617
618

        JackNetInterface::SetParams();

619
620
        fTxHeader.fDataStream = 'r';
        fRxHeader.fDataStream = 's';
moret's avatar
moret committed
621
622

        //midi net buffers
623
624
        fNetMidiCaptureBuffer = new NetMidiBuffer ( &fParams, fParams.fSendMidiChannels, fRxData );
        fNetMidiPlaybackBuffer = new NetMidiBuffer ( &fParams, fParams.fReturnMidiChannels, fTxData );
moret's avatar
moret committed
625
626

        //audio net buffers
627
628
        fNetAudioCaptureBuffer = new NetAudioBuffer ( &fParams, fParams.fSendAudioChannels, fRxData );
        fNetAudioPlaybackBuffer = new NetAudioBuffer ( &fParams, fParams.fReturnAudioChannels, fTxData );
moret's avatar
moret committed
629
630
631
632
633
634

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

635
    int JackNetSlaveInterface::Recv ( size_t size, int flags )
636
    {
637
638
639
640
641
642
643
644
645
646
647
648
        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
649
                throw JackNetException();
650
651
652
653
654
            }
            else
                jack_error ( "Fatal error in receive : %s", StrError ( NET_ERROR_CODE ) );
        }
        return rx_bytes;
655
656
    }

657
    int JackNetSlaveInterface::Send ( size_t size, int flags )
658
    {
659
660
661
        int tx_bytes = fSocket.Send ( fTxBuffer, size, flags );
        //handle errors
        if ( tx_bytes == SOCKET_ERROR )
662
663
        {
            net_error_t error = fSocket.GetError();
664
665
            //if a network error occurs, this exception will restart the driver
            if ( error == NET_CONN_ERROR )
666
            {
667
                jack_error ( "Connection lost." );
moret's avatar
moret committed
668
                throw JackNetException();
669
            }
670
671
            else
                jack_error ( "Fatal error in send : %s", StrError ( NET_ERROR_CODE ) );
672
673
674
675
        }
        return tx_bytes;
    }

676
    int JackNetSlaveInterface::SyncRecv()
677
    {
678
679
680
681
        int rx_bytes = 0;
        packet_header_t* rx_head = reinterpret_cast<packet_header_t*> ( fRxBuffer );
        //receive sync (launch the cycle)
        do
682
        {
683
684
685
686
687
688
            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
689
        fRxHeader.fIsLastPckt = rx_head->fIsLastPckt;
690
691
692
693
694
695
696
697
698
        return rx_bytes;
    }

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

moret's avatar
moret committed
699
        while ( !fRxHeader.fIsLastPckt )
700
        {
moret's avatar
moret committed
701
702
            rx_bytes = Recv ( fParams.fMtu, MSG_PEEK );
            //error here, problem with recv, just skip the cycle (return -1)
moret's avatar
moret committed
703

moret's avatar
moret committed
704
705
706
            if ( rx_bytes == SOCKET_ERROR )
                return rx_bytes;
            if ( rx_bytes && ( rx_head->fDataStream == 's' ) && ( rx_head->fID == fParams.fID ) )
707
            {
moret's avatar
moret committed
708
                switch ( rx_head->fDataType )
709
                {
moret's avatar
moret committed
710
711
712
                    case 'm':   //midi
                        rx_bytes = Recv ( rx_head->fPacketSize, 0 );
                        fRxHeader.fCycle = rx_head->fCycle;
moret's avatar
moret committed
713
                        fRxHeader.fIsLastPckt = rx_head->fIsLastPckt;
moret's avatar
moret committed
714
715
716
717
                        fNetMidiCaptureBuffer->RenderFromNetwork ( rx_head->fSubCycle, rx_bytes - sizeof ( packet_header_t ) );
                        if ( ++recvd_midi_pckt == rx_head->fNMidiPckt )
                            fNetMidiCaptureBuffer->RenderToJackPorts();
                        break;
718
                        
moret's avatar
moret committed
719
720
721
722
723
724
                    case 'a':   //audio
                        rx_bytes = Recv ( rx_head->fPacketSize, 0 );
                        if ( !IsNextPacket() )
                            jack_error ( "Packet(s) missing..." );
                        fRxHeader.fCycle = rx_head->fCycle;
                        fRxHeader.fSubCycle = rx_head->fSubCycle;
moret's avatar
moret committed
725
                        fRxHeader.fIsLastPckt = rx_head->fIsLastPckt;
moret's avatar
moret committed
726
727
                        fNetAudioCaptureBuffer->RenderToJackPorts ( rx_head->fSubCycle );
                        break;
728
         
moret's avatar
moret committed
729
730
731
                    case 's':   //sync
                        jack_info ( "NetSlave : overloaded, skipping receive." );
                        return 0;
732
                }
733
734
            }
        }
735
736
        fRxHeader.fCycle = rx_head->fCycle;
        return 0;
737
738
    }

739
    int JackNetSlaveInterface::SyncSend()
740
    {
741
742
743
744
745
        //tx header
        if ( fParams.fSlaveSyncMode )
            fTxHeader.fCycle = fRxHeader.fCycle;
        else
            fTxHeader.fCycle++;
746
747
        fTxHeader.fSubCycle = 0;
        fTxHeader.fDataType = 's';
moret's avatar
moret committed
748
        fTxHeader.fIsLastPckt = ( !fParams.fReturnMidiChannels && !fParams.fReturnAudioChannels ) ?  1 : 0;
749
750
751
752
753
        fTxHeader.fPacketSize = fParams.fMtu;
        memcpy ( fTxBuffer, &fTxHeader, sizeof ( packet_header_t ) );
        return Send ( fTxHeader.fPacketSize, 0 );
    }

754
    int JackNetSlaveInterface::DataSend()
755
756
    {
        uint subproc;
757

758
        //midi
759
        if ( fParams.fReturnMidiChannels )
760
761
        {
            fTxHeader.fDataType = 'm';
762
            fTxHeader.fMidiDataSize = fNetMidiPlaybackBuffer->RenderFromJackPorts();
moret's avatar
moret committed
763
            fTxHeader.fNMidiPckt = GetNMidiPckt();
764
765
766
            for ( subproc = 0; subproc < fTxHeader.fNMidiPckt; subproc++ )
            {
                fTxHeader.fSubCycle = subproc;
moret's avatar
moret committed
767
                fTxHeader.fIsLastPckt = ( ( subproc == ( fTxHeader.fNMidiPckt - 1 ) ) && !fParams.fReturnAudioChannels ) ? 1 : 0;
moret's avatar
moret committed
768
769
                fTxHeader.fPacketSize = sizeof ( packet_header_t );
                fTxHeader.fPacketSize += fNetMidiPlaybackBuffer->RenderToNetwork ( subproc, fTxHeader.fMidiDataSize );
770
771
                memcpy ( fTxBuffer, &fTxHeader, sizeof ( packet_header_t ) );
                if ( Send ( fTxHeader.fPacketSize, 0 ) == SOCKET_ERROR )
moret's avatar
moret committed
772
                    return SOCKET_ERROR;
773
774
775
776
            }
        }

        //audio
777
        if ( fParams.fReturnAudioChannels )
778
779
780
781
782
        {
            fTxHeader.fDataType = 'a';
            for ( subproc = 0; subproc < fNSubProcess; subproc++ )
            {
                fTxHeader.fSubCycle = subproc;
moret's avatar
moret committed
783
                fTxHeader.fIsLastPckt = ( subproc == ( fNSubProcess - 1 ) ) ? 1 : 0;
784
785
                fTxHeader.fPacketSize = fAudioTxLen;
                memcpy ( fTxBuffer, &fTxHeader, sizeof ( packet_header_t ) );
786
                fNetAudioPlaybackBuffer->RenderFromJackPorts ( subproc );
787
                if ( Send ( fTxHeader.fPacketSize, 0 ) == SOCKET_ERROR )
moret's avatar
moret committed
788
                    return SOCKET_ERROR;
789
790
791
792
793
            }
        }
        return 0;
    }
}