JackNetInterface.cpp 30.8 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
/*
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*******************************************

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

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

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

    JackNetInterface::~JackNetInterface()
    {
moret's avatar
moret committed
69
        jack_log ( "JackNetInterface::~JackNetInterface" );
70
71
72
73
74
75
76
77
78
79
        fSocket.Close();
        delete[] fTxBuffer;
        delete[] fRxBuffer;
        delete[] fMulticastIP;
        delete fNetAudioCaptureBuffer;
        delete fNetAudioPlaybackBuffer;
        delete fNetMidiCaptureBuffer;
        delete fNetMidiPlaybackBuffer;
    }

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

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

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

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

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

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

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

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

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

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

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

180
    // JackNetMasterInterface ************************************************************************************
181

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

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

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

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

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

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

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

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

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

        return true;
246
247
    }

moret's avatar
moret committed
248
249
250
251
252
    int JackNetMasterInterface::SetRxTimeout()
    {
        float time = 0;
        //slow mode, very short timeout on recv
        if ( fParams.fNetworkMode == 's' )
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
255
        //normal mode, short timeout on recv
        else if ( fParams.fNetworkMode == 'n' )
moret's avatar
moret committed
256
            time = 4000000.f * ( static_cast<float> ( fParams.fFramesPerPacket ) / static_cast<float> ( fParams.fSampleRate ) );
moret's avatar
moret committed
257
258
259
260
261
262
        //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 ) );
    }

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 );
moret's avatar
moret committed
275
276

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

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

285
    void JackNetMasterInterface::Exit()
286
    {
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
        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 )
306
307
        {
            net_error_t error = fSocket.GetError();
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
            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
327
            if ( error == NET_NO_DATA )
328
329
                return 0;
            else if ( fRunning && ( error == NET_CONN_ERROR ) )
330
            {
331
332
333
334
                //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();
335
            }
336
337
            else if ( fRunning )
                jack_error ( "Error in receive : %s", StrError ( NET_ERROR_CODE ) );
338
339
340
341
        }
        return rx_bytes;
    }

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

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

394
    int JackNetMasterInterface::SyncRecv()
395
    {
396
397
        int rx_bytes = 0;
        int cycle_offset = 0;
398
        packet_header_t* rx_head = reinterpret_cast<packet_header_t*> ( fRxBuffer );
399
400
401
402
403
404
405
        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 )
406
        {
407
            case 's' :
moret's avatar
moret committed
408
409
410
411
412
                //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)
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
                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;
437
        }
moret's avatar
moret committed
438
        fRxHeader.fIsLastPckt = rx_head->fIsLastPckt;
439
440
441
        return rx_bytes;
    }

442
    int JackNetMasterInterface::DataRecv()
443
444
    {
        int rx_bytes = 0;
445
446
        uint jumpcnt = 0;
        uint midi_recvd_pckt = 0;
447
448
        packet_header_t* rx_head = reinterpret_cast<packet_header_t*> ( fRxBuffer );

moret's avatar
moret committed
449
        while ( !fRxHeader.fIsLastPckt )
450
        {
moret's avatar
moret committed
451
452
453
454
            //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
455
            //if no data
moret's avatar
moret committed
456
            if ( ( rx_bytes == 0 ) && ( ++jumpcnt == fNSubProcess ) )
457
            {
moret's avatar
moret committed
458
459
460
461
462
463
464
465
                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 )
466
                {
moret's avatar
moret committed
467
468
469
                    case 'm':   //midi
                        Recv ( rx_head->fPacketSize, 0 );
                        fRxHeader.fCycle = rx_head->fCycle;
moret's avatar
moret committed
470
                        fRxHeader.fIsLastPckt = rx_head->fIsLastPckt;
moret's avatar
moret committed
471
472
473
474
475
476
477
478
479
480
481
                        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;
moret's avatar
moret committed
482
                        fRxHeader.fIsLastPckt = rx_head->fIsLastPckt;
moret's avatar
moret committed
483
484
485
486
487
488
                        fNetAudioPlaybackBuffer->RenderToJackPorts ( rx_head->fSubCycle );
                        jumpcnt = 0;
                        break;
                    case 's':   //sync
                        if ( rx_head->fCycle == fTxHeader.fCycle )
                            return 0;
489
490
491
                }
            }
        }
492
        return rx_bytes;
493
494
    }

495
496
497
// JackNetSlaveInterface ************************************************************************************************

    bool JackNetSlaveInterface::Init()
498
    {
499
        jack_log ( "JackNetSlaveInterface::Init()" );
500

501
502
503
504
        //set the parameters to send
        strcpy ( fParams.fPacketType, "params" );
        fParams.fProtocolVersion = 'a';
        SetPacketType ( &fParams, SLAVE_AVAILABLE );
505

506
507
508
        //init loop : get a master and start, do it until connection is ok
        net_status_t status;
        do
509
        {
510
511
            //first, get a master, do it until a valid connection is running
            do
512
            {
513
514
515
                status = GetNetMaster();
                if ( status == NET_SOCKET_ERROR )
                    return false;
516
            }
517
            while ( status != NET_CONNECTED );
518

519
520
            //then tell the master we are ready
            jack_info ( "Initializing connection with %s...", fParams.fMasterNetName );
moret's avatar
moret committed
521
            status = SendStartToMaster();
522
523
            if ( status == NET_ERROR )
                return false;
524
        }
525
        while ( status != NET_ROLLING );
526

527
528
        return true;
    }
529

530
    net_status_t JackNetSlaveInterface::GetNetMaster()
531
    {
532
533
        jack_log ( "JackNetSlaveInterface::GetNetMaster()" );
        //utility
534
535
        session_params_t params;
        int rx_bytes = 0;
536
        unsigned char loop = 0;
537
538
539
540

        //socket
        if ( fSocket.NewSocket() == SOCKET_ERROR )
        {
541
542
            jack_error ( "Fatal error : network unreachable - %s", StrError ( NET_ERROR_CODE ) );
            return NET_SOCKET_ERROR;
543
544
        }

545
546
547
548
549
550
        //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 )
551
552
            jack_error ( "Can't set timeout : %s", StrError ( NET_ERROR_CODE ) );

553
554
555
        //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 ) );
556

557
558
        //send 'AVAILABLE' until 'SLAVE_SETUP' received
        jack_info ( "Waiting for a master..." );
559
560
        do
        {
561
562
563
564
565
566
            //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 ) )
567
            {
568
569
                jack_error ( "Can't receive : %s", StrError ( NET_ERROR_CODE ) );
                return NET_RECV_ERROR;
570
571
            }
        }
572
        while ( strcmp ( params.fPacketType, fParams.fPacketType ) && ( GetPacketType ( &params ) != SLAVE_SETUP ) );
573

moret's avatar
moret committed
574
575
576
577
578
579
580
        //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 ) );

581
582
        //connect the socket
        if ( fSocket.Connect() == SOCKET_ERROR )
583
        {
584
585
            jack_error ( "Error in connect : %s", StrError ( NET_ERROR_CODE ) );
            return NET_CONNECT_ERROR;
586
587
        }

moret's avatar
moret committed
588
        return NET_CONNECTED;
589
590
    }

moret's avatar
moret committed
591
    net_status_t JackNetSlaveInterface::SendStartToMaster()
592
    {
moret's avatar
moret committed
593
        jack_log ( "JackNetSlaveInterface::SendStartToMaster" );
moret's avatar
moret committed
594

595
596
597
        //tell the master to start
        SetPacketType ( &fParams, START_MASTER );
        if ( fSocket.Send ( &fParams, sizeof ( session_params_t ), 0 ) == SOCKET_ERROR )
598
        {
599
600
            jack_error ( "Error in send : %s", StrError ( NET_ERROR_CODE ) );
            return ( fSocket.GetError() == NET_CONN_ERROR ) ? NET_ERROR : NET_SEND_ERROR;
601
        }
602
        return NET_ROLLING;
603
604
    }

605
    void JackNetSlaveInterface::SetParams()
moret's avatar
moret committed
606
    {
607
        jack_log ( "JackNetSlaveInterface::SetParams" );
moret's avatar
moret committed
608
609
610

        JackNetInterface::SetParams();

611
612
        fTxHeader.fDataStream = 'r';
        fRxHeader.fDataStream = 's';
moret's avatar
moret committed
613
614

        //midi net buffers
615
616
        fNetMidiCaptureBuffer = new NetMidiBuffer ( &fParams, fParams.fSendMidiChannels, fRxData );
        fNetMidiPlaybackBuffer = new NetMidiBuffer ( &fParams, fParams.fReturnMidiChannels, fTxData );
moret's avatar
moret committed
617
618

        //audio net buffers
619
620
        fNetAudioCaptureBuffer = new NetAudioBuffer ( &fParams, fParams.fSendAudioChannels, fRxData );
        fNetAudioPlaybackBuffer = new NetAudioBuffer ( &fParams, fParams.fReturnAudioChannels, fTxData );
moret's avatar
moret committed
621
622
623
624
625
626

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

627
    int JackNetSlaveInterface::Recv ( size_t size, int flags )
628
    {
629
630
631
632
633
634
635
636
637
638
639
640
        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
641
                throw JackNetException();
642
643
644
645
646
            }
            else
                jack_error ( "Fatal error in receive : %s", StrError ( NET_ERROR_CODE ) );
        }
        return rx_bytes;
647
648
    }

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

668
    int JackNetSlaveInterface::SyncRecv()
669
    {
670
671
672
673
        int rx_bytes = 0;
        packet_header_t* rx_head = reinterpret_cast<packet_header_t*> ( fRxBuffer );
        //receive sync (launch the cycle)
        do
674
        {
675
676
677
678
679
680
            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
681
        fRxHeader.fIsLastPckt = rx_head->fIsLastPckt;
682
683
684
685
686
687
688
689
690
        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
691
        while ( !fRxHeader.fIsLastPckt )
692
        {
moret's avatar
moret committed
693
694
            rx_bytes = Recv ( fParams.fMtu, MSG_PEEK );
            //error here, problem with recv, just skip the cycle (return -1)
moret's avatar
moret committed
695

moret's avatar
moret committed
696
697
698
            if ( rx_bytes == SOCKET_ERROR )
                return rx_bytes;
            if ( rx_bytes && ( rx_head->fDataStream == 's' ) && ( rx_head->fID == fParams.fID ) )
699
            {
moret's avatar
moret committed
700
                switch ( rx_head->fDataType )
701
                {
moret's avatar
moret committed
702
703
704
                    case 'm':   //midi
                        rx_bytes = Recv ( rx_head->fPacketSize, 0 );
                        fRxHeader.fCycle = rx_head->fCycle;
moret's avatar
moret committed
705
                        fRxHeader.fIsLastPckt = rx_head->fIsLastPckt;
moret's avatar
moret committed
706
707
708
709
710
711
712
713
714
715
                        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;
moret's avatar
moret committed
716
                        fRxHeader.fIsLastPckt = rx_head->fIsLastPckt;
moret's avatar
moret committed
717
718
719
720
721
                        fNetAudioCaptureBuffer->RenderToJackPorts ( rx_head->fSubCycle );
                        break;
                    case 's':   //sync
                        jack_info ( "NetSlave : overloaded, skipping receive." );
                        return 0;
722
                }
723
724
            }
        }
725
726
        fRxHeader.fCycle = rx_head->fCycle;
        return 0;
727
728
    }

729
    int JackNetSlaveInterface::SyncSend()
730
    {
731
732
733
734
735
        //tx header
        if ( fParams.fSlaveSyncMode )
            fTxHeader.fCycle = fRxHeader.fCycle;
        else
            fTxHeader.fCycle++;
736
737
        fTxHeader.fSubCycle = 0;
        fTxHeader.fDataType = 's';
moret's avatar
moret committed
738
        fTxHeader.fIsLastPckt = ( !fParams.fReturnMidiChannels && !fParams.fReturnAudioChannels ) ?  1 : 0;
739
740
741
742
743
        fTxHeader.fPacketSize = fParams.fMtu;
        memcpy ( fTxBuffer, &fTxHeader, sizeof ( packet_header_t ) );
        return Send ( fTxHeader.fPacketSize, 0 );
    }

744
    int JackNetSlaveInterface::DataSend()
745
746
    {
        uint subproc;
747

748
        //midi
749
        if ( fParams.fReturnMidiChannels )
750
751
        {
            fTxHeader.fDataType = 'm';
752
            fTxHeader.fMidiDataSize = fNetMidiPlaybackBuffer->RenderFromJackPorts();
moret's avatar
moret committed
753
            fTxHeader.fNMidiPckt = GetNMidiPckt();
754
755
756
            for ( subproc = 0; subproc < fTxHeader.fNMidiPckt; subproc++ )
            {
                fTxHeader.fSubCycle = subproc;
moret's avatar
moret committed
757
                fTxHeader.fIsLastPckt = ( ( subproc == ( fTxHeader.fNMidiPckt - 1 ) ) && !fParams.fReturnAudioChannels ) ? 1 : 0;
moret's avatar
moret committed
758
759
                fTxHeader.fPacketSize = sizeof ( packet_header_t );
                fTxHeader.fPacketSize += fNetMidiPlaybackBuffer->RenderToNetwork ( subproc, fTxHeader.fMidiDataSize );
760
761
                memcpy ( fTxBuffer, &fTxHeader, sizeof ( packet_header_t ) );
                if ( Send ( fTxHeader.fPacketSize, 0 ) == SOCKET_ERROR )
moret's avatar
moret committed
762
                    return SOCKET_ERROR;
763
764
765
766
            }
        }

        //audio
767
        if ( fParams.fReturnAudioChannels )
768
769
770
771
772
        {
            fTxHeader.fDataType = 'a';
            for ( subproc = 0; subproc < fNSubProcess; subproc++ )
            {
                fTxHeader.fSubCycle = subproc;
moret's avatar
moret committed
773
                fTxHeader.fIsLastPckt = ( subproc == ( fNSubProcess - 1 ) ) ? 1 : 0;
774
775
                fTxHeader.fPacketSize = fAudioTxLen;
                memcpy ( fTxBuffer, &fTxHeader, sizeof ( packet_header_t ) );
776
                fNetAudioPlaybackBuffer->RenderFromJackPorts ( subproc );
777
                if ( Send ( fTxHeader.fPacketSize, 0 ) == SOCKET_ERROR )
moret's avatar
moret committed
778
                    return SOCKET_ERROR;
779
780
781
782
783
            }
        }
        return 0;
    }
}