JackNetInterface.cpp 31.2 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
27
28
29
30

using namespace std;

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

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

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

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

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

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

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

moret's avatar
moret committed
83
84
85
86
        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
87
        return ( fParams.fFramesPerPacket = ( period > fParams.fPeriodSize ) ? fParams.fPeriodSize : period );
moret's avatar
moret committed
88
89
90
91
    }

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

moret's avatar
moret committed
94
95
96
97
98
99
        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
100
                                     fParams.fPeriodSize * sizeof ( sample_t ) / ( fParams.fMtu - sizeof ( packet_header_t ) ) );
moret's avatar
moret committed
101
102
        //bufsize = sync + audio + midi
        bufsize = fParams.fMtu + ( int ) audio_size + ( int ) midi_size;
moret's avatar
moret committed
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
136

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

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

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

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

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

        //network buffers
        fTxBuffer = new char[fParams.fMtu];
        fRxBuffer = new char[fParams.fMtu];
173
174
        assert(fTxBuffer);
        assert(fRxBuffer);
175

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

181
    // JackNetMasterInterface ************************************************************************************
182

183
    bool JackNetMasterInterface::Init()
184
    {
185
        jack_log ( "JackNetMasterInterface::Init, ID %u.", fParams.fID );
186
187

        session_params_t params;
188
        uint attempt = 0;
189
190
191
192
193
        int rx_bytes = 0;

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

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

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

moret's avatar
moret committed
209
        //set the number of complete audio frames we can put in a packet
moret's avatar
moret committed
210
211
        SetFramesPerPacket();

212
213
        //send 'SLAVE_SETUP' until 'START_MASTER' received
        jack_info ( "Sending parameters to %s ...", fParams.fSlaveNetName );
214
215
        do
        {
216
217
218
219
            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 ) )
220
            {
221
222
                jack_error ( "Problem with network." );
                return false;
223
224
            }
        }
225
226
        while ( ( GetPacketType ( &params ) != START_MASTER ) && ( ++attempt < SLAVE_SETUP_RETRY ) );
        if ( attempt == SLAVE_SETUP_RETRY )
227
        {
228
229
            jack_error ( "Slave doesn't respond, exiting." );
            return false;
230
231
        }

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

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

        return true;
247
248
    }

moret's avatar
moret committed
249
250
    int JackNetMasterInterface::SetRxTimeout()
    {
moret's avatar
moret committed
251
252
        jack_log ( "JackNetMasterInterface::SetRxTimeout" );

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

263
    void JackNetMasterInterface::SetParams()
moret's avatar
moret committed
264
    {
265
        jack_log ( "JackNetMasterInterface::SetParams" );
moret's avatar
moret committed
266
267
268

        JackNetInterface::SetParams();

269
270
        fTxHeader.fDataStream = 's';
        fRxHeader.fDataStream = 'r';
moret's avatar
moret committed
271
272

        //midi net buffers
273
274
        fNetMidiCaptureBuffer = new NetMidiBuffer ( &fParams, fParams.fSendMidiChannels, fTxData );
        fNetMidiPlaybackBuffer = new NetMidiBuffer ( &fParams, fParams.fReturnMidiChannels, fRxData );
275
276
        assert(fNetMidiCaptureBuffer);
        assert(fNetMidiPlaybackBuffer);
moret's avatar
moret committed
277
278

        //audio net buffers
279
280
        fNetAudioCaptureBuffer = new NetAudioBuffer ( &fParams, fParams.fSendAudioChannels, fTxData );
        fNetAudioPlaybackBuffer = new NetAudioBuffer ( &fParams, fParams.fReturnAudioChannels, fRxData );
281
282
        assert(fNetAudioCaptureBuffer);
        assert(fNetAudioPlaybackBuffer);
moret's avatar
moret committed
283
284
285
286
287
288

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

289
    void JackNetMasterInterface::Exit()
290
    {
291
292
293
294
        jack_log ( "JackNetMasterInterface::Exit, ID %u", fParams.fID );

        //stop process
        fRunning = false;
295
        
296
297
298
299
300
301
302
303
304
        //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();
305
306
307
        
        // UGLY temporary way to be sure the thread does not call code possibly causing a deadlock in JackEngine.
        ThreadExit();
308
309
310
311
312
    }

    int JackNetMasterInterface::Send ( size_t size, int flags )
    {
        int tx_bytes;
moret's avatar
moret committed
313
        if ( ( ( tx_bytes = fSocket.Send ( fTxBuffer, size, flags ) ) == SOCKET_ERROR ) && fRunning )
314
315
        {
            net_error_t error = fSocket.GetError();
moret's avatar
moret committed
316
            if ( error == NET_CONN_ERROR )
317
318
319
320
321
            {
                //fatal connection issue, exit
                jack_error ( "'%s' : %s, exiting.", fParams.fName, StrError ( NET_ERROR_CODE ) );
                Exit();
            }
moret's avatar
moret committed
322
            else
323
324
325
326
327
328
329
330
                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
331
        if ( ( ( rx_bytes = fSocket.Recv ( fRxBuffer, size, flags ) ) == SOCKET_ERROR ) && fRunning )
332
333
334
        {
            net_error_t error = fSocket.GetError();
            //no data isn't really a network error, so just return 0 avalaible read bytes
335
            if ( error == NET_NO_DATA )
336
                return 0;
moret's avatar
moret committed
337
            else if ( error == NET_CONN_ERROR )
338
            {
339
340
341
342
                //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();
343
            }
moret's avatar
moret committed
344
            else
345
                jack_error ( "Error in receive : %s", StrError ( NET_ERROR_CODE ) );
346
347
348
349
        }
        return rx_bytes;
    }

350
    int JackNetMasterInterface::SyncSend()
351
    {
352
353
354
        fTxHeader.fCycle++;
        fTxHeader.fSubCycle = 0;
        fTxHeader.fDataType = 's';
moret's avatar
moret committed
355
        fTxHeader.fIsLastPckt = ( !fParams.fSendMidiChannels && !fParams.fSendAudioChannels ) ?  1 : 0;
356
357
358
359
360
361
362
363
364
365
        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 )
366
        {
367
368
369
            //set global header fields and get the number of midi packets
            fTxHeader.fDataType = 'm';
            fTxHeader.fMidiDataSize = fNetMidiCaptureBuffer->RenderFromJackPorts();
moret's avatar
moret committed
370
            fTxHeader.fNMidiPckt = GetNMidiPckt();
371
            for ( subproc = 0; subproc < fTxHeader.fNMidiPckt; subproc++ )
372
            {
373
                fTxHeader.fSubCycle = subproc;
moret's avatar
moret committed
374
                fTxHeader.fIsLastPckt = ( ( subproc == ( fTxHeader.fNMidiPckt - 1 ) ) && !fParams.fSendAudioChannels ) ? 1 : 0;
moret's avatar
moret committed
375
376
                fTxHeader.fPacketSize = sizeof ( packet_header_t );
                fTxHeader.fPacketSize += fNetMidiCaptureBuffer->RenderToNetwork ( subproc, fTxHeader.fMidiDataSize );
377
378
379
                memcpy ( fTxBuffer, &fTxHeader, sizeof ( packet_header_t ) );
                if ( Send ( fTxHeader.fPacketSize, 0 ) == SOCKET_ERROR )
                    return SOCKET_ERROR;
380
381
            }
        }
382
383
384
385
386
387
388
389

        //audio
        if ( fParams.fSendAudioChannels )
        {
            fTxHeader.fDataType = 'a';
            for ( subproc = 0; subproc < fNSubProcess; subproc++ )
            {
                fTxHeader.fSubCycle = subproc;
moret's avatar
moret committed
390
                fTxHeader.fIsLastPckt = ( subproc == ( fNSubProcess - 1 ) ) ? 1 : 0;
391
392
393
394
395
396
397
398
399
                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;
400
401
    }

402
    int JackNetMasterInterface::SyncRecv()
403
    {
404
405
        int rx_bytes = 0;
        int cycle_offset = 0;
406
        packet_header_t* rx_head = reinterpret_cast<packet_header_t*> ( fRxBuffer );
407
408
409
410
411
412
413
        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 )
414
        {
415
            case 's' :
moret's avatar
moret committed
416
417
418
419
420
                //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)
421
422
423
424
425
                if ( cycle_offset < 2 )
                    return 0;
                else
                    rx_bytes = Recv ( rx_head->fPacketSize, 0 );
                break;
426
                
427
428
429
430
431
432
433
434
435
436
            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;
437
                
438
439
440
441
442
443
444
445
446
            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;
447
        }
448
        
moret's avatar
moret committed
449
        fRxHeader.fIsLastPckt = rx_head->fIsLastPckt;
450
451
452
        return rx_bytes;
    }

453
    int JackNetMasterInterface::DataRecv()
454
455
    {
        int rx_bytes = 0;
456
457
        uint jumpcnt = 0;
        uint midi_recvd_pckt = 0;
458
459
        packet_header_t* rx_head = reinterpret_cast<packet_header_t*> ( fRxBuffer );

moret's avatar
moret committed
460
        while ( !fRxHeader.fIsLastPckt )
461
        {
moret's avatar
moret committed
462
463
464
465
            //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
466
            //if no data
moret's avatar
moret committed
467
            if ( ( rx_bytes == 0 ) && ( ++jumpcnt == fNSubProcess ) )
468
            {
moret's avatar
moret committed
469
470
471
472
473
474
475
476
                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 )
477
                {
moret's avatar
moret committed
478
479
480
                    case 'm':   //midi
                        Recv ( rx_head->fPacketSize, 0 );
                        fRxHeader.fCycle = rx_head->fCycle;
moret's avatar
moret committed
481
                        fRxHeader.fIsLastPckt = rx_head->fIsLastPckt;
moret's avatar
moret committed
482
483
484
485
486
                        fNetMidiPlaybackBuffer->RenderFromNetwork ( rx_head->fSubCycle, rx_bytes - sizeof ( packet_header_t ) );
                        if ( ++midi_recvd_pckt == rx_head->fNMidiPckt )
                            fNetMidiPlaybackBuffer->RenderToJackPorts();
                        jumpcnt = 0;
                        break;
487
                        
moret's avatar
moret committed
488
489
490
491
492
493
                    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
494
                        fRxHeader.fIsLastPckt = rx_head->fIsLastPckt;
moret's avatar
moret committed
495
496
497
                        fNetAudioPlaybackBuffer->RenderToJackPorts ( rx_head->fSubCycle );
                        jumpcnt = 0;
                        break;
498
                        
moret's avatar
moret committed
499
500
501
                    case 's':   //sync
                        if ( rx_head->fCycle == fTxHeader.fCycle )
                            return 0;
502
                        break;
503
504
505
                }
            }
        }
506
        return rx_bytes;
507
508
    }

509
510
// JackNetSlaveInterface ************************************************************************************************

moret's avatar
moret committed
511
512
    uint JackNetSlaveInterface::fSlaveCounter = 0;

513
    bool JackNetSlaveInterface::Init()
514
    {
515
        jack_log ( "JackNetSlaveInterface::Init()" );
516

517
518
519
520
        //set the parameters to send
        strcpy ( fParams.fPacketType, "params" );
        fParams.fProtocolVersion = 'a';
        SetPacketType ( &fParams, SLAVE_AVAILABLE );
521

522
523
524
        //init loop : get a master and start, do it until connection is ok
        net_status_t status;
        do
525
        {
526
527
            //first, get a master, do it until a valid connection is running
            do
528
            {
529
530
531
                status = GetNetMaster();
                if ( status == NET_SOCKET_ERROR )
                    return false;
532
            }
533
            while ( status != NET_CONNECTED );
534

535
536
            //then tell the master we are ready
            jack_info ( "Initializing connection with %s...", fParams.fMasterNetName );
moret's avatar
moret committed
537
            status = SendStartToMaster();
538
539
            if ( status == NET_ERROR )
                return false;
540
        }
541
        while ( status != NET_ROLLING );
542

543
544
        return true;
    }
545

546
    net_status_t JackNetSlaveInterface::GetNetMaster()
547
    {
548
549
        jack_log ( "JackNetSlaveInterface::GetNetMaster()" );
        //utility
550
551
552
553
554
555
        session_params_t params;
        int rx_bytes = 0;

        //socket
        if ( fSocket.NewSocket() == SOCKET_ERROR )
        {
556
557
            jack_error ( "Fatal error : network unreachable - %s", StrError ( NET_ERROR_CODE ) );
            return NET_SOCKET_ERROR;
558
559
        }

560
561
562
563
564
        //bind the socket
        if ( fSocket.Bind() == SOCKET_ERROR )
            jack_error ( "Can't bind the socket : %s", StrError ( NET_ERROR_CODE ) );

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

568
        //disable local loop
moret's avatar
moret committed
569
        if ( fSocket.SetLocalLoop() == SOCKET_ERROR )
570
            jack_error ( "Can't disable multicast loop : %s", StrError ( NET_ERROR_CODE ) );
571

572
573
        //send 'AVAILABLE' until 'SLAVE_SETUP' received
        jack_info ( "Waiting for a master..." );
574
575
        do
        {
576
577
578
579
580
581
            //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 ) )
582
            {
583
584
                jack_error ( "Can't receive : %s", StrError ( NET_ERROR_CODE ) );
                return NET_RECV_ERROR;
585
586
            }
        }
587
        while ( strcmp ( params.fPacketType, fParams.fPacketType ) && ( GetPacketType ( &params ) != SLAVE_SETUP ) );
588

moret's avatar
moret committed
589
590
591
592
593
594
595
        //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 ) );

596
597
        //connect the socket
        if ( fSocket.Connect() == SOCKET_ERROR )
598
        {
599
600
            jack_error ( "Error in connect : %s", StrError ( NET_ERROR_CODE ) );
            return NET_CONNECT_ERROR;
601
602
        }

moret's avatar
moret committed
603
        return NET_CONNECTED;
604
605
    }

moret's avatar
moret committed
606
    net_status_t JackNetSlaveInterface::SendStartToMaster()
607
    {
moret's avatar
moret committed
608
        jack_log ( "JackNetSlaveInterface::SendStartToMaster" );
moret's avatar
moret committed
609

610
611
612
        //tell the master to start
        SetPacketType ( &fParams, START_MASTER );
        if ( fSocket.Send ( &fParams, sizeof ( session_params_t ), 0 ) == SOCKET_ERROR )
613
        {
614
615
            jack_error ( "Error in send : %s", StrError ( NET_ERROR_CODE ) );
            return ( fSocket.GetError() == NET_CONN_ERROR ) ? NET_ERROR : NET_SEND_ERROR;
616
        }
617
        return NET_ROLLING;
618
619
    }

620
    void JackNetSlaveInterface::SetParams()
moret's avatar
moret committed
621
    {
622
        jack_log ( "JackNetSlaveInterface::SetParams" );
moret's avatar
moret committed
623
624
625

        JackNetInterface::SetParams();

626
627
        fTxHeader.fDataStream = 'r';
        fRxHeader.fDataStream = 's';
moret's avatar
moret committed
628
629

        //midi net buffers
630
631
        fNetMidiCaptureBuffer = new NetMidiBuffer ( &fParams, fParams.fSendMidiChannels, fRxData );
        fNetMidiPlaybackBuffer = new NetMidiBuffer ( &fParams, fParams.fReturnMidiChannels, fTxData );
moret's avatar
moret committed
632
633

        //audio net buffers
634
635
        fNetAudioCaptureBuffer = new NetAudioBuffer ( &fParams, fParams.fSendAudioChannels, fRxData );
        fNetAudioPlaybackBuffer = new NetAudioBuffer ( &fParams, fParams.fReturnAudioChannels, fTxData );
moret's avatar
moret committed
636
637
638
639
640
641

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

642
    int JackNetSlaveInterface::Recv ( size_t size, int flags )
643
    {
644
645
646
647
648
649
650
651
652
653
654
655
        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
656
                throw JackNetException();
657
658
659
660
661
            }
            else
                jack_error ( "Fatal error in receive : %s", StrError ( NET_ERROR_CODE ) );
        }
        return rx_bytes;
662
663
    }

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

683
    int JackNetSlaveInterface::SyncRecv()
684
    {
685
686
687
688
        int rx_bytes = 0;
        packet_header_t* rx_head = reinterpret_cast<packet_header_t*> ( fRxBuffer );
        //receive sync (launch the cycle)
        do
689
        {
690
691
692
693
694
695
            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
696
        fRxHeader.fIsLastPckt = rx_head->fIsLastPckt;
697
698
699
700
701
702
703
704
705
        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
706
        while ( !fRxHeader.fIsLastPckt )
707
        {
moret's avatar
moret committed
708
709
            rx_bytes = Recv ( fParams.fMtu, MSG_PEEK );
            //error here, problem with recv, just skip the cycle (return -1)
moret's avatar
moret committed
710

moret's avatar
moret committed
711
712
713
            if ( rx_bytes == SOCKET_ERROR )
                return rx_bytes;
            if ( rx_bytes && ( rx_head->fDataStream == 's' ) && ( rx_head->fID == fParams.fID ) )
714
            {
moret's avatar
moret committed
715
                switch ( rx_head->fDataType )
716
                {
moret's avatar
moret committed
717
718
719
                    case 'm':   //midi
                        rx_bytes = Recv ( rx_head->fPacketSize, 0 );
                        fRxHeader.fCycle = rx_head->fCycle;
moret's avatar
moret committed
720
                        fRxHeader.fIsLastPckt = rx_head->fIsLastPckt;
moret's avatar
moret committed
721
722
723
724
                        fNetMidiCaptureBuffer->RenderFromNetwork ( rx_head->fSubCycle, rx_bytes - sizeof ( packet_header_t ) );
                        if ( ++recvd_midi_pckt == rx_head->fNMidiPckt )
                            fNetMidiCaptureBuffer->RenderToJackPorts();
                        break;
725
                        
moret's avatar
moret committed
726
727
728
729
730
731
                    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
732
                        fRxHeader.fIsLastPckt = rx_head->fIsLastPckt;
moret's avatar
moret committed
733
734
                        fNetAudioCaptureBuffer->RenderToJackPorts ( rx_head->fSubCycle );
                        break;
735
         
moret's avatar
moret committed
736
737
738
                    case 's':   //sync
                        jack_info ( "NetSlave : overloaded, skipping receive." );
                        return 0;
739
                }
740
741
            }
        }
742
743
        fRxHeader.fCycle = rx_head->fCycle;
        return 0;
744
745
    }

746
    int JackNetSlaveInterface::SyncSend()
747
    {
748
749
750
751
752
        //tx header
        if ( fParams.fSlaveSyncMode )
            fTxHeader.fCycle = fRxHeader.fCycle;
        else
            fTxHeader.fCycle++;
753
754
        fTxHeader.fSubCycle = 0;
        fTxHeader.fDataType = 's';
moret's avatar
moret committed
755
        fTxHeader.fIsLastPckt = ( !fParams.fReturnMidiChannels && !fParams.fReturnAudioChannels ) ?  1 : 0;
756
757
758
759
760
        fTxHeader.fPacketSize = fParams.fMtu;
        memcpy ( fTxBuffer, &fTxHeader, sizeof ( packet_header_t ) );
        return Send ( fTxHeader.fPacketSize, 0 );
    }

761
    int JackNetSlaveInterface::DataSend()
762
763
    {
        uint subproc;
764

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

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