JackNetInterface.cpp 30 KB
Newer Older
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
/*
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"

#define DEFAULT_MULTICAST_IP "225.3.19.154"
#define DEFAULT_PORT 19000

using namespace std;

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

    JackNetInterface::JackNetInterface ( const char* ip, int port ) : fSocket ( ip, port )
    {
moret's avatar
moret committed
35
        jack_log ( "JackNetInterface::JackNetInterface ip = %s port = %d", ip, port );
36

37
        fMulticastIP = strdup ( ip );
38
39
    }

moret's avatar
moret committed
40
    JackNetInterface::JackNetInterface ( session_params_t& params, JackNetSocket& socket, const char* multicast_ip ) : fSocket ( socket )
41
    {
moret's avatar
moret committed
42
        jack_log ( "JackNetInterface::JackNetInterface ID = %d", params.fID );
43
44

        fParams = params;
moret's avatar
moret committed
45
        fMulticastIP = strdup ( multicast_ip );
46
47
48
49
    }

    JackNetInterface::~JackNetInterface()
    {
moret's avatar
moret committed
50
        jack_log ( "JackNetInterface::~JackNetInterface" );
51
52
53
54
55
56
57
58
59
60
        fSocket.Close();
        delete[] fTxBuffer;
        delete[] fRxBuffer;
        delete[] fMulticastIP;
        delete fNetAudioCaptureBuffer;
        delete fNetAudioPlaybackBuffer;
        delete fNetMidiCaptureBuffer;
        delete fNetMidiPlaybackBuffer;
    }

moret's avatar
moret committed
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
    jack_nframes_t JackNetInterface::SetFramesPerPacket()
    {
        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 ) ) );
        ( period > fParams.fPeriodSize ) ? fParams.fFramesPerPacket = fParams.fPeriodSize : fParams.fFramesPerPacket = period;
        return fParams.fFramesPerPacket;
    }

    int JackNetInterface::SetNetBufferSize()
    {
        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 ) *
                                           fParams.fPeriodSize * sizeof ( sample_t ) / ( fParams.fMtu - sizeof ( packet_header_t ) ) );
        //size of sync + audio + midi
        bufsize = 2 * ( fParams.fMtu + ( int ) audio_size + ( int ) midi_size );

        //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;
        //next PcktID (cycle), SubPcktID reset to 1 (first subcyle)
        if ( ( rx_head->fCycle == ( fRxHeader.fCycle + 1 ) ) && ( fRxHeader.fSubCycle == ( fNSubProcess - 1 ) ) && ( rx_head->fSubCycle == 0 ) )
            return true;
        //else, next is'nt next, return false
        return false;
    }

123
124
    void JackNetInterface::SetParams()
    {
moret's avatar
moret committed
125
        SetFramesPerPacket();
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
        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;

        //RX header init
        strcpy ( fRxHeader.fPacketType, "header" );
        fRxHeader.fID = fParams.fID;
        fRxHeader.fCycle = 0;
        fRxHeader.fSubCycle = 0;
        fRxHeader.fMidiDataSize = 0;
        fRxHeader.fBitdepth = fParams.fBitdepth;

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

        //net audio/midi buffers
        fTxData = fTxBuffer + sizeof ( packet_header_t );
        fRxData = fRxBuffer + sizeof ( packet_header_t );

        //payload size
        fPayloadSize = fParams.fMtu - sizeof ( packet_header_t );
    }

156
    // JackNetMasterInterface ************************************************************************************
157

158
    bool JackNetMasterInterface::Init()
159
    {
160
        jack_log ( "JackNetMasterInterface::Init, ID %u.", fParams.fID );
161
162

        session_params_t params;
163
        uint attempt = 0;
164
165
166
167
168
        int rx_bytes = 0;

        //socket
        if ( fSocket.NewSocket() == SOCKET_ERROR )
        {
169
170
            jack_error ( "Can't create socket : %s", StrError ( NET_ERROR_CODE ) );
            return false;
171
172
        }

173
174
        //timeout on receive (for init)
        if ( fSocket.SetTimeOut ( 1000000 ) < 0 )
175
176
            jack_error ( "Can't set timeout : %s", StrError ( NET_ERROR_CODE ) );

177
178
179
180
181
182
        //connect
        if ( fSocket.Connect() == SOCKET_ERROR )
        {
            jack_error ( "Can't connect : %s", StrError ( NET_ERROR_CODE ) );
            return false;
        }
183

184
185
        //send 'SLAVE_SETUP' until 'START_MASTER' received
        jack_info ( "Sending parameters to %s ...", fParams.fSlaveNetName );
186
187
        do
        {
188
189
190
191
            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 ) )
192
            {
193
194
                jack_error ( "Problem with network." );
                return false;
195
196
            }
        }
197
198
        while ( ( GetPacketType ( &params ) != START_MASTER ) && ( ++attempt < 5 ) );
        if ( attempt == 5 )
199
        {
200
201
            jack_error ( "Slave doesn't respond, exiting." );
            return false;
202
203
        }

204
        //set the new timeout for the socket
moret's avatar
moret committed
205
        if ( SetRxTimeout() == SOCKET_ERROR )
206
207
208
209
        {
            jack_error ( "Can't set rx timeout : %s", StrError ( NET_ERROR_CODE ) );
            return false;
        }
210

211
        //set the new rx buffer size
moret's avatar
moret committed
212
        if ( SetNetBufferSize() == SOCKET_ERROR )
213
        {
moret's avatar
moret committed
214
            jack_error ( "Can't set net buffer sizes : %s", StrError ( NET_ERROR_CODE ) );
215
            return false;
216
        }
217
218

        return true;
219
220
    }

moret's avatar
moret committed
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
    int JackNetMasterInterface::SetRxTimeout()
    {
        float time = 0;
        //slow mode, very short timeout on recv
        if ( fParams.fNetworkMode == 's' )
            time = 1000000.f * ( static_cast<float> ( fParams.fFramesPerPacket ) / static_cast<float> ( fParams.fSampleRate ) );
        //normal mode, short timeout on recv
        else if ( fParams.fNetworkMode == 'n' )
            time = 2000000.f * ( static_cast<float> ( fParams.fFramesPerPacket ) / static_cast<float> ( fParams.fSampleRate ) );
        //fast mode, wait for the entire cycle duration
        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 ) );
    }

236
    void JackNetMasterInterface::SetParams()
moret's avatar
moret committed
237
    {
238
        jack_log ( "JackNetMasterInterface::SetParams" );
moret's avatar
moret committed
239
240
241

        JackNetInterface::SetParams();

242
243
        fTxHeader.fDataStream = 's';
        fRxHeader.fDataStream = 'r';
moret's avatar
moret committed
244
245

        //midi net buffers
246
247
        fNetMidiCaptureBuffer = new NetMidiBuffer ( &fParams, fParams.fSendMidiChannels, fTxData );
        fNetMidiPlaybackBuffer = new NetMidiBuffer ( &fParams, fParams.fReturnMidiChannels, fRxData );
moret's avatar
moret committed
248
249

        //audio net buffers
250
251
        fNetAudioCaptureBuffer = new NetAudioBuffer ( &fParams, fParams.fSendAudioChannels, fTxData );
        fNetAudioPlaybackBuffer = new NetAudioBuffer ( &fParams, fParams.fReturnAudioChannels, fRxData );
moret's avatar
moret committed
252
253
254
255
256
257

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

258
    void JackNetMasterInterface::Exit()
259
    {
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
        jack_log ( "JackNetMasterInterface::Exit, ID %u", fParams.fID );

        //stop process
        fRunning = false;
        //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();
    }

    int JackNetMasterInterface::Send ( size_t size, int flags )
    {
        int tx_bytes;
        if ( ( tx_bytes = fSocket.Send ( fTxBuffer, size, flags ) ) == SOCKET_ERROR )
279
280
        {
            net_error_t error = fSocket.GetError();
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
            if ( fRunning && ( error == NET_CONN_ERROR ) )
            {
                //fatal connection issue, exit
                jack_error ( "'%s' : %s, exiting.", fParams.fName, StrError ( NET_ERROR_CODE ) );
                Exit();
            }
            else if ( fRunning )
                jack_error ( "Error in send : %s", StrError ( NET_ERROR_CODE ) );
        }
        return tx_bytes;
    }

    int JackNetMasterInterface::Recv ( size_t size, int flags )
    {
        int rx_bytes;
        if ( ( rx_bytes = fSocket.Recv ( fRxBuffer, size, flags ) ) == SOCKET_ERROR )
        {
            net_error_t error = fSocket.GetError();
            //no data isn't really a network error, so just return 0 avalaible read bytes
300
            if ( error == NET_NO_DATA )
301
302
                return 0;
            else if ( fRunning && ( error == NET_CONN_ERROR ) )
303
            {
304
305
306
307
                //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();
308
            }
309
310
            else if ( fRunning )
                jack_error ( "Error in receive : %s", StrError ( NET_ERROR_CODE ) );
311
312
313
314
        }
        return rx_bytes;
    }

315
    int JackNetMasterInterface::SyncSend()
316
    {
317
318
319
320
321
322
323
324
325
326
327
328
329
330
        fTxHeader.fCycle++;
        fTxHeader.fSubCycle = 0;
        fTxHeader.fDataType = 's';
        fTxHeader.fIsLastPckt = ( !fParams.fSendMidiChannels && !fParams.fSendAudioChannels ) ?  'y' : 'n';
        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 )
331
        {
332
333
334
            //set global header fields and get the number of midi packets
            fTxHeader.fDataType = 'm';
            fTxHeader.fMidiDataSize = fNetMidiCaptureBuffer->RenderFromJackPorts();
moret's avatar
moret committed
335
            fTxHeader.fNMidiPckt = GetNMidiPckt();
336
            for ( subproc = 0; subproc < fTxHeader.fNMidiPckt; subproc++ )
337
            {
338
339
340
341
342
343
344
345
346
347
348
                //fill the packet header fields
                fTxHeader.fSubCycle = subproc;
                if ( ( subproc == ( fTxHeader.fNMidiPckt - 1 ) ) && !fParams.fSendAudioChannels )
                    fTxHeader.fIsLastPckt = 'y';
                //get the data from buffer
                fTxHeader.fPacketSize = fNetMidiCaptureBuffer->RenderToNetwork ( subproc, fTxHeader.fMidiDataSize );
                fTxHeader.fPacketSize += sizeof ( packet_header_t );
                memcpy ( fTxBuffer, &fTxHeader, sizeof ( packet_header_t ) );
                //and send
                if ( Send ( fTxHeader.fPacketSize, 0 ) == SOCKET_ERROR )
                    return SOCKET_ERROR;
349
350
            }
        }
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372

        //audio
        if ( fParams.fSendAudioChannels )
        {
            fTxHeader.fDataType = 'a';
            for ( subproc = 0; subproc < fNSubProcess; subproc++ )
            {
                //set the header
                fTxHeader.fSubCycle = subproc;
                if ( subproc == ( fNSubProcess - 1 ) )
                    fTxHeader.fIsLastPckt = 'y';
                fTxHeader.fPacketSize = fAudioTxLen;
                memcpy ( fTxBuffer, &fTxHeader, sizeof ( packet_header_t ) );
                //get the data
                fNetAudioCaptureBuffer->RenderFromJackPorts ( subproc );
                //and send
                if ( Send ( fTxHeader.fPacketSize, 0 ) == SOCKET_ERROR )
                    return SOCKET_ERROR;
            }
        }

        return 0;
373
374
    }

375
    int JackNetMasterInterface::SyncRecv()
376
    {
377
378
        int rx_bytes = 0;
        int cycle_offset = 0;
379
        packet_header_t* rx_head = reinterpret_cast<packet_header_t*> ( fRxBuffer );
380
381
382
383
384
385
386
387

        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 )
388
        {
389
            case 's' :
moret's avatar
moret committed
390
391
392
393
394
                //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)
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
                if ( cycle_offset < 2 )
                    return 0;
                else
                    rx_bytes = Recv ( rx_head->fPacketSize, 0 );
                break;
            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;
            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;
419
420
421
422
        }
        return rx_bytes;
    }

423
    int JackNetMasterInterface::DataRecv()
424
425
    {
        int rx_bytes = 0;
426
427
        uint jumpcnt = 0;
        uint midi_recvd_pckt = 0;
428
429
        packet_header_t* rx_head = reinterpret_cast<packet_header_t*> ( fRxBuffer );

moret's avatar
moret committed
430
        while ( rx_head->fIsLastPckt != 'y' )
431
        {
moret's avatar
moret committed
432
433
434
435
436
437
            //how much data is queued on the rx buffer ?
            rx_bytes = Recv ( fParams.fMtu, MSG_PEEK );
            if ( rx_bytes == SOCKET_ERROR )
                return rx_bytes;
            //if no data,
            if ( ( rx_bytes == 0 ) && ( ++jumpcnt == fNSubProcess ) )
438
            {
moret's avatar
moret committed
439
440
441
442
443
444
445
446
                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 )
447
                {
moret's avatar
moret committed
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
                    case 'm':   //midi
                        Recv ( rx_head->fPacketSize, 0 );
                        fRxHeader.fCycle = rx_head->fCycle;
                        fNetMidiPlaybackBuffer->RenderFromNetwork ( rx_head->fSubCycle, rx_bytes - sizeof ( packet_header_t ) );
                        if ( ++midi_recvd_pckt == rx_head->fNMidiPckt )
                            fNetMidiPlaybackBuffer->RenderToJackPorts();
                        jumpcnt = 0;
                        break;
                    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;
                        fNetAudioPlaybackBuffer->RenderToJackPorts ( rx_head->fSubCycle );
                        jumpcnt = 0;
                        break;
                    case 's':   //sync
                        if ( rx_head->fCycle == fTxHeader.fCycle )
                            return 0;
468
469
470
                }
            }
        }
471
        return rx_bytes;
472
473
    }

474
475
476
// JackNetSlaveInterface ************************************************************************************************

    bool JackNetSlaveInterface::Init()
477
    {
478
        jack_log ( "JackNetSlaveInterface::Init()" );
479

480
481
482
483
        //set the parameters to send
        strcpy ( fParams.fPacketType, "params" );
        fParams.fProtocolVersion = 'a';
        SetPacketType ( &fParams, SLAVE_AVAILABLE );
484

485
486
487
        //init loop : get a master and start, do it until connection is ok
        net_status_t status;
        do
488
        {
489
490
491
            //first, get a master, do it until a valid connection is running
            jack_info ( "Initializing Net Slave..." );
            do
492
            {
493
494
495
                status = GetNetMaster();
                if ( status == NET_SOCKET_ERROR )
                    return false;
496
            }
497
            while ( status != NET_CONNECTED );
498

499
500
501
502
503
            //then tell the master we are ready
            jack_info ( "Initializing connection with %s...", fParams.fMasterNetName );
            status = SendMasterStartSync();
            if ( status == NET_ERROR )
                return false;
504
        }
505
        while ( status != NET_ROLLING );
506

507
508
        return true;
    }
509

510
    net_status_t JackNetSlaveInterface::GetNetMaster()
511
    {
512
513
        jack_log ( "JackNetSlaveInterface::GetNetMaster()" );
        //utility
514
515
        session_params_t params;
        int rx_bytes = 0;
516
        unsigned char loop = 0;
517
518
519
520

        //socket
        if ( fSocket.NewSocket() == SOCKET_ERROR )
        {
521
522
            jack_error ( "Fatal error : network unreachable - %s", StrError ( NET_ERROR_CODE ) );
            return NET_SOCKET_ERROR;
523
524
        }

525
526
527
528
529
530
        //bind the socket
        if ( fSocket.Bind() == SOCKET_ERROR )
            jack_error ( "Can't bind the socket : %s", StrError ( NET_ERROR_CODE ) );

        //timeout on receive
        if ( fSocket.SetTimeOut ( 2000000 ) == SOCKET_ERROR )
531
532
            jack_error ( "Can't set timeout : %s", StrError ( NET_ERROR_CODE ) );

533
534
535
        //disable local loop
        if ( fSocket.SetOption ( IPPROTO_IP, IP_MULTICAST_LOOP, &loop, sizeof ( loop ) ) == SOCKET_ERROR )
            jack_error ( "Can't disable multicast loop : %s", StrError ( NET_ERROR_CODE ) );
536

moret's avatar
moret committed
537
538
539
540
        //set the new rx buffer size
        if ( SetNetBufferSize() == SOCKET_ERROR )
            jack_error ( "Can't set net buffer sizes : %s", StrError ( NET_ERROR_CODE ) );

541
542
        //send 'AVAILABLE' until 'SLAVE_SETUP' received
        jack_info ( "Waiting for a master..." );
543
544
        do
        {
545
546
547
548
549
550
            //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 ) )
551
            {
552
553
                jack_error ( "Can't receive : %s", StrError ( NET_ERROR_CODE ) );
                return NET_RECV_ERROR;
554
555
            }
        }
556
        while ( strcmp ( params.fPacketType, fParams.fPacketType ) && ( GetPacketType ( &params ) != SLAVE_SETUP ) );
557

558
559
        //connect the socket
        if ( fSocket.Connect() == SOCKET_ERROR )
560
        {
561
562
            jack_error ( "Error in connect : %s", StrError ( NET_ERROR_CODE ) );
            return NET_CONNECT_ERROR;
563
564
        }

565
566
567
568
569
570
571
572
573
574
575
576
        //everything is OK, copy parameters and return
        fParams = params;

        return NET_CONNECTED;
    }

    net_status_t JackNetSlaveInterface::SendMasterStartSync()
    {
        jack_log ( "JackNetSlaveInterface::GetNetMasterStartSync()" );
        //tell the master to start
        SetPacketType ( &fParams, START_MASTER );
        if ( fSocket.Send ( &fParams, sizeof ( session_params_t ), 0 ) == SOCKET_ERROR )
577
        {
578
579
            jack_error ( "Error in send : %s", StrError ( NET_ERROR_CODE ) );
            return ( fSocket.GetError() == NET_CONN_ERROR ) ? NET_ERROR : NET_SEND_ERROR;
580
        }
581
        return NET_ROLLING;
582
583
    }

584
    void JackNetSlaveInterface::SetParams()
moret's avatar
moret committed
585
    {
586
        jack_log ( "JackNetSlaveInterface::SetParams" );
moret's avatar
moret committed
587
588
589

        JackNetInterface::SetParams();

590
591
        fTxHeader.fDataStream = 'r';
        fRxHeader.fDataStream = 's';
moret's avatar
moret committed
592
593

        //midi net buffers
594
595
        fNetMidiCaptureBuffer = new NetMidiBuffer ( &fParams, fParams.fSendMidiChannels, fRxData );
        fNetMidiPlaybackBuffer = new NetMidiBuffer ( &fParams, fParams.fReturnMidiChannels, fTxData );
moret's avatar
moret committed
596
597

        //audio net buffers
598
599
        fNetAudioCaptureBuffer = new NetAudioBuffer ( &fParams, fParams.fSendAudioChannels, fRxData );
        fNetAudioPlaybackBuffer = new NetAudioBuffer ( &fParams, fParams.fReturnAudioChannels, fTxData );
moret's avatar
moret committed
600
601
602
603
604
605

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

606
    int JackNetSlaveInterface::Recv ( size_t size, int flags )
607
    {
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
        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." );
                throw JackDriverException();
            }
            else
                jack_error ( "Fatal error in receive : %s", StrError ( NET_ERROR_CODE ) );
        }
        return rx_bytes;
626
627
    }

628
    int JackNetSlaveInterface::Send ( size_t size, int flags )
629
    {
630
631
632
        int tx_bytes = fSocket.Send ( fTxBuffer, size, flags );
        //handle errors
        if ( tx_bytes == SOCKET_ERROR )
633
634
        {
            net_error_t error = fSocket.GetError();
635
636
            //if a network error occurs, this exception will restart the driver
            if ( error == NET_CONN_ERROR )
637
            {
638
639
                jack_error ( "Connection lost." );
                throw JackDriverException();
640
            }
641
642
            else
                jack_error ( "Fatal error in send : %s", StrError ( NET_ERROR_CODE ) );
643
644
645
646
        }
        return tx_bytes;
    }

647
    int JackNetSlaveInterface::SyncRecv()
648
    {
649
650
651
652
        int rx_bytes = 0;
        packet_header_t* rx_head = reinterpret_cast<packet_header_t*> ( fRxBuffer );
        //receive sync (launch the cycle)
        do
653
        {
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
            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' ) );
        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
669
        while ( rx_head->fIsLastPckt != 'y' );
670
        {
moret's avatar
moret committed
671
672
673
674
675
            rx_bytes = Recv ( fParams.fMtu, MSG_PEEK );
            //error here, problem with recv, just skip the cycle (return -1)
            if ( rx_bytes == SOCKET_ERROR )
                return rx_bytes;
            if ( rx_bytes && ( rx_head->fDataStream == 's' ) && ( rx_head->fID == fParams.fID ) )
676
            {
moret's avatar
moret committed
677
                switch ( rx_head->fDataType )
678
                {
moret's avatar
moret committed
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
                    case 'm':   //midi
                        rx_bytes = Recv ( rx_head->fPacketSize, 0 );
                        fRxHeader.fCycle = rx_head->fCycle;
                        fNetMidiCaptureBuffer->RenderFromNetwork ( rx_head->fSubCycle, rx_bytes - sizeof ( packet_header_t ) );
                        if ( ++recvd_midi_pckt == rx_head->fNMidiPckt )
                            fNetMidiCaptureBuffer->RenderToJackPorts();
                        break;
                    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;
                        fNetAudioCaptureBuffer->RenderToJackPorts ( rx_head->fSubCycle );
                        break;
                    case 's':   //sync
                        jack_info ( "NetSlave : overloaded, skipping receive." );
                        return 0;
697
                }
698
699
            }
        }
700
701
        fRxHeader.fCycle = rx_head->fCycle;
        return 0;
702
703
    }

704
    int JackNetSlaveInterface::SyncSend()
705
    {
706
707
708
709
710
        //tx header
        if ( fParams.fSlaveSyncMode )
            fTxHeader.fCycle = fRxHeader.fCycle;
        else
            fTxHeader.fCycle++;
711
712
        fTxHeader.fSubCycle = 0;
        fTxHeader.fDataType = 's';
713
        fTxHeader.fIsLastPckt = ( !fParams.fReturnMidiChannels && !fParams.fReturnAudioChannels ) ?  'y' : 'n';
714
715
716
717
718
        fTxHeader.fPacketSize = fParams.fMtu;
        memcpy ( fTxBuffer, &fTxHeader, sizeof ( packet_header_t ) );
        return Send ( fTxHeader.fPacketSize, 0 );
    }

719
    int JackNetSlaveInterface::DataSend()
720
721
    {
        uint subproc;
722

723
        //midi
724
        if ( fParams.fReturnMidiChannels )
725
726
        {
            fTxHeader.fDataType = 'm';
727
            fTxHeader.fMidiDataSize = fNetMidiPlaybackBuffer->RenderFromJackPorts();
moret's avatar
moret committed
728
            fTxHeader.fNMidiPckt = GetNMidiPckt();
729
730
731
            for ( subproc = 0; subproc < fTxHeader.fNMidiPckt; subproc++ )
            {
                fTxHeader.fSubCycle = subproc;
732
                if ( ( subproc == ( fTxHeader.fNMidiPckt - 1 ) ) && !fParams.fReturnAudioChannels )
733
                    fTxHeader.fIsLastPckt = 'y';
734
                fTxHeader.fPacketSize = fNetMidiPlaybackBuffer->RenderToNetwork ( subproc, fTxHeader.fMidiDataSize );
735
736
737
                fTxHeader.fPacketSize += sizeof ( packet_header_t );
                memcpy ( fTxBuffer, &fTxHeader, sizeof ( packet_header_t ) );
                if ( Send ( fTxHeader.fPacketSize, 0 ) == SOCKET_ERROR )
moret's avatar
moret committed
738
                    return SOCKET_ERROR;
739
740
741
742
            }
        }

        //audio
743
        if ( fParams.fReturnAudioChannels )
744
745
746
747
748
749
750
751
752
        {
            fTxHeader.fDataType = 'a';
            for ( subproc = 0; subproc < fNSubProcess; subproc++ )
            {
                fTxHeader.fSubCycle = subproc;
                if ( subproc == ( fNSubProcess - 1 ) )
                    fTxHeader.fIsLastPckt = 'y';
                fTxHeader.fPacketSize = fAudioTxLen;
                memcpy ( fTxBuffer, &fTxHeader, sizeof ( packet_header_t ) );
753
                fNetAudioPlaybackBuffer->RenderFromJackPorts ( subproc );
754
                if ( Send ( fTxHeader.fPacketSize, 0 ) == SOCKET_ERROR )
moret's avatar
moret committed
755
                    return SOCKET_ERROR;
756
757
758
759
760
            }
        }
        return 0;
    }
}