JackNetInterface.cpp 31.3 KB
Newer Older
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
/*
Copyright (C) 2001 Paul Davis
Copyright (C) 2008 Romain Moret at Grame

This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/

#include "JackNetInterface.h"
#include "JackException.h"
22
#include "JackPlatformPlug.h"
23
#include <assert.h>
24
25
26

using namespace std;

27
28
29
30
31
32
/*  
 TODO : since midi buffers now uses up to BUFFER_SIZE_MAX frames, 
 probably also use BUFFER_SIZE_MAX in everything related to MIDI events 
 handling (see MidiBufferInit in JackMidiPort.cpp)
*/

33
34
35
36
namespace Jack
{
    // JackNetInterface*******************************************

37
38
39
40
41
42
43
44
45
46
47
    JackNetInterface::JackNetInterface() : fSocket()
    {
        fMulticastIP = NULL;
        fTxBuffer = NULL;
        fRxBuffer = NULL;
        fNetAudioCaptureBuffer = NULL;
        fNetAudioPlaybackBuffer = NULL;
        fNetMidiCaptureBuffer = NULL;
        fNetMidiPlaybackBuffer = NULL;
    }

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

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

    JackNetInterface::~JackNetInterface()
    {
moret's avatar
moret committed
73
        jack_log ( "JackNetInterface::~JackNetInterface" );
moret's avatar
moret committed
74

75
76
77
78
79
80
81
82
83
84
        fSocket.Close();
        delete[] fTxBuffer;
        delete[] fRxBuffer;
        delete[] fMulticastIP;
        delete fNetAudioCaptureBuffer;
        delete fNetAudioPlaybackBuffer;
        delete fNetMidiCaptureBuffer;
        delete fNetMidiPlaybackBuffer;
    }

moret's avatar
moret committed
85
86
    jack_nframes_t JackNetInterface::SetFramesPerPacket()
    {
moret's avatar
moret committed
87
        jack_log ( "JackNetInterface::SetFramesPerPacket" );
moret's avatar
moret committed
88

moret's avatar
moret committed
89
90
91
92
        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
93
        return ( fParams.fFramesPerPacket = ( period > fParams.fPeriodSize ) ? fParams.fPeriodSize : period );
moret's avatar
moret committed
94
95
96
97
    }

    int JackNetInterface::SetNetBufferSize()
    {
moret's avatar
moret committed
98
        jack_log ( "JackNetInterface::SetNetBufferSize" );
moret's avatar
moret committed
99

moret's avatar
moret committed
100
101
102
103
104
105
        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
106
                                     fParams.fPeriodSize * sizeof ( sample_t ) / ( fParams.fMtu - sizeof ( packet_header_t ) ) );
moret's avatar
moret committed
107
        //bufsize = sync + audio + midi
108
        bufsize = 10 * (fParams.fMtu + ( int ) audio_size + ( int ) midi_size);
moret's avatar
moret committed
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
138
139
140
141
142

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

150
151
    void JackNetInterface::SetParams()
    {
moret's avatar
moret committed
152
        //number of audio subcycles (packets)
153
154
        fNSubProcess = fParams.fPeriodSize / fParams.fFramesPerPacket;

moret's avatar
moret committed
155
156
157
        //payload size
        fPayloadSize = fParams.fMtu - sizeof ( packet_header_t );

158
159
160
161
162
163
164
        //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
165
        fTxHeader.fIsLastPckt = 0;
166
167
168
169
170
171
172
173

        //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
174
        fRxHeader.fIsLastPckt = 0;
175
176
177
178

        //network buffers
        fTxBuffer = new char[fParams.fMtu];
        fRxBuffer = new char[fParams.fMtu];
179
180
        assert ( fTxBuffer );
        assert ( fRxBuffer );
181

moret's avatar
moret committed
182
        //net audio/midi buffers'addresses
183
184
185
186
        fTxData = fTxBuffer + sizeof ( packet_header_t );
        fRxData = fRxBuffer + sizeof ( packet_header_t );
    }

187
    // JackNetMasterInterface ************************************************************************************
188

189
    bool JackNetMasterInterface::Init()
190
    {
191
        jack_log ( "JackNetMasterInterface::Init, ID %u.", fParams.fID );
192
193

        session_params_t params;
194
        uint attempt = 0;
195
196
197
198
199
        int rx_bytes = 0;

        //socket
        if ( fSocket.NewSocket() == SOCKET_ERROR )
        {
200
201
            jack_error ( "Can't create socket : %s", StrError ( NET_ERROR_CODE ) );
            return false;
202
203
        }

204
        //timeout on receive (for init)
205
        if ( fSocket.SetTimeOut ( MASTER_INIT_TIMEOUT ) < 0 )
206
207
            jack_error ( "Can't set timeout : %s", StrError ( NET_ERROR_CODE ) );

208
209
210
211
212
213
        //connect
        if ( fSocket.Connect() == SOCKET_ERROR )
        {
            jack_error ( "Can't connect : %s", StrError ( NET_ERROR_CODE ) );
            return false;
        }
214

moret's avatar
moret committed
215
        //set the number of complete audio frames we can put in a packet
moret's avatar
moret committed
216
217
        SetFramesPerPacket();

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

238
        //set the new timeout for the socket
moret's avatar
moret committed
239
        if ( SetRxTimeout() == SOCKET_ERROR )
240
241
242
243
        {
            jack_error ( "Can't set rx timeout : %s", StrError ( NET_ERROR_CODE ) );
            return false;
        }
244

245
        //set the new rx buffer size
moret's avatar
moret committed
246
        if ( SetNetBufferSize() == SOCKET_ERROR )
247
        {
moret's avatar
moret committed
248
            jack_error ( "Can't set net buffer sizes : %s", StrError ( NET_ERROR_CODE ) );
249
            return false;
250
        }
251
252

        return true;
253
254
    }

moret's avatar
moret committed
255
256
    int JackNetMasterInterface::SetRxTimeout()
    {
moret's avatar
moret committed
257
258
        jack_log ( "JackNetMasterInterface::SetRxTimeout" );

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

269
    void JackNetMasterInterface::SetParams()
moret's avatar
moret committed
270
    {
271
        jack_log ( "JackNetMasterInterface::SetParams" );
moret's avatar
moret committed
272
273
274

        JackNetInterface::SetParams();

275
276
        fTxHeader.fDataStream = 's';
        fRxHeader.fDataStream = 'r';
moret's avatar
moret committed
277
278

        //midi net buffers
279
280
        fNetMidiCaptureBuffer = new NetMidiBuffer ( &fParams, fParams.fSendMidiChannels, fTxData );
        fNetMidiPlaybackBuffer = new NetMidiBuffer ( &fParams, fParams.fReturnMidiChannels, fRxData );
281
282
        assert ( fNetMidiCaptureBuffer );
        assert ( fNetMidiPlaybackBuffer );
moret's avatar
moret committed
283
284

        //audio net buffers
285
286
        fNetAudioCaptureBuffer = new NetAudioBuffer ( &fParams, fParams.fSendAudioChannels, fTxData );
        fNetAudioPlaybackBuffer = new NetAudioBuffer ( &fParams, fParams.fReturnAudioChannels, fRxData );
287
288
        assert ( fNetAudioCaptureBuffer );
        assert ( fNetAudioPlaybackBuffer );
moret's avatar
moret committed
289
290
291
292
293
294

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

295
    void JackNetMasterInterface::Exit()
296
    {
297
298
299
300
        jack_log ( "JackNetMasterInterface::Exit, ID %u", fParams.fID );

        //stop process
        fRunning = false;
301

302
303
304
305
306
307
308
309
310
        //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();
311

312
313
        // UGLY temporary way to be sure the thread does not call code possibly causing a deadlock in JackEngine.
        ThreadExit();
314
315
316
317
318
    }

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

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

        //audio
        if ( fParams.fSendAudioChannels )
        {
            fTxHeader.fDataType = 'a';
            for ( subproc = 0; subproc < fNSubProcess; subproc++ )
            {
                fTxHeader.fSubCycle = subproc;
moret's avatar
moret committed
396
                fTxHeader.fIsLastPckt = ( subproc == ( fNSubProcess - 1 ) ) ? 1 : 0;
397
398
399
400
401
402
403
404
405
                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;
406
407
    }

408
    int JackNetMasterInterface::SyncRecv()
409
    {
410
411
        int rx_bytes = 0;
        int cycle_offset = 0;
412
        packet_header_t* rx_head = reinterpret_cast<packet_header_t*> ( fRxBuffer );
413
414
415
416
417
418
419
        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 )
420
        {
421
            case 's' :
moret's avatar
moret committed
422
423
424
425
426
                //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)
427
428
429
430
431
                if ( cycle_offset < 2 )
                    return 0;
                else
                    rx_bytes = Recv ( rx_head->fPacketSize, 0 );
                break;
432

433
434
435
436
437
438
439
440
441
442
            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;
443

444
445
446
447
448
449
450
451
452
            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;
453
        }
454

moret's avatar
moret committed
455
        fRxHeader.fIsLastPckt = rx_head->fIsLastPckt;
456
457
458
        return rx_bytes;
    }

459
    int JackNetMasterInterface::DataRecv()
460
461
    {
        int rx_bytes = 0;
462
463
        uint jumpcnt = 0;
        uint midi_recvd_pckt = 0;
464
465
        packet_header_t* rx_head = reinterpret_cast<packet_header_t*> ( fRxBuffer );

moret's avatar
moret committed
466
        while ( !fRxHeader.fIsLastPckt )
467
        {
moret's avatar
moret committed
468
469
470
471
            //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
472
            //if no data
moret's avatar
moret committed
473
            if ( ( rx_bytes == 0 ) && ( ++jumpcnt == fNSubProcess ) )
474
            {
moret's avatar
moret committed
475
476
477
478
479
480
481
482
                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 )
483
                {
moret's avatar
moret committed
484
485
486
                    case 'm':   //midi
                        Recv ( rx_head->fPacketSize, 0 );
                        fRxHeader.fCycle = rx_head->fCycle;
moret's avatar
moret committed
487
                        fRxHeader.fIsLastPckt = rx_head->fIsLastPckt;
moret's avatar
moret committed
488
489
490
491
492
                        fNetMidiPlaybackBuffer->RenderFromNetwork ( rx_head->fSubCycle, rx_bytes - sizeof ( packet_header_t ) );
                        if ( ++midi_recvd_pckt == rx_head->fNMidiPckt )
                            fNetMidiPlaybackBuffer->RenderToJackPorts();
                        jumpcnt = 0;
                        break;
493

moret's avatar
moret committed
494
495
496
497
498
499
                    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
500
                        fRxHeader.fIsLastPckt = rx_head->fIsLastPckt;
moret's avatar
moret committed
501
502
503
                        fNetAudioPlaybackBuffer->RenderToJackPorts ( rx_head->fSubCycle );
                        jumpcnt = 0;
                        break;
504

moret's avatar
moret committed
505
506
507
                    case 's':   //sync
                        if ( rx_head->fCycle == fTxHeader.fCycle )
                            return 0;
508
                        break;
509
510
511
                }
            }
        }
512
        return rx_bytes;
513
514
    }

515
516
// JackNetSlaveInterface ************************************************************************************************

moret's avatar
moret committed
517
518
    uint JackNetSlaveInterface::fSlaveCounter = 0;

519
    bool JackNetSlaveInterface::Init()
520
    {
521
        jack_log ( "JackNetSlaveInterface::Init()" );
522

523
524
525
526
        //set the parameters to send
        strcpy ( fParams.fPacketType, "params" );
        fParams.fProtocolVersion = 'a';
        SetPacketType ( &fParams, SLAVE_AVAILABLE );
527

528
529
530
        //init loop : get a master and start, do it until connection is ok
        net_status_t status;
        do
531
        {
532
533
            //first, get a master, do it until a valid connection is running
            do
534
            {
535
536
537
                status = GetNetMaster();
                if ( status == NET_SOCKET_ERROR )
                    return false;
538
            }
539
            while ( status != NET_CONNECTED );
540

541
542
            //then tell the master we are ready
            jack_info ( "Initializing connection with %s...", fParams.fMasterNetName );
moret's avatar
moret committed
543
            status = SendStartToMaster();
544
545
            if ( status == NET_ERROR )
                return false;
546
        }
547
        while ( status != NET_ROLLING );
548

549
550
        return true;
    }
551

552
    net_status_t JackNetSlaveInterface::GetNetMaster()
553
    {
554
555
        jack_log ( "JackNetSlaveInterface::GetNetMaster()" );
        //utility
556
557
558
559
560
561
        session_params_t params;
        int rx_bytes = 0;

        //socket
        if ( fSocket.NewSocket() == SOCKET_ERROR )
        {
562
563
            jack_error ( "Fatal error : network unreachable - %s", StrError ( NET_ERROR_CODE ) );
            return NET_SOCKET_ERROR;
564
565
        }

566
567
568
569
570
        //bind the socket
        if ( fSocket.Bind() == SOCKET_ERROR )
            jack_error ( "Can't bind the socket : %s", StrError ( NET_ERROR_CODE ) );

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

574
        //disable local loop
moret's avatar
moret committed
575
        if ( fSocket.SetLocalLoop() == SOCKET_ERROR )
576
            jack_error ( "Can't disable multicast loop : %s", StrError ( NET_ERROR_CODE ) );
577

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

moret's avatar
moret committed
595
596
597
598
599
600
601
        //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 ) );

602
603
        //connect the socket
        if ( fSocket.Connect() == SOCKET_ERROR )
604
        {
605
606
            jack_error ( "Error in connect : %s", StrError ( NET_ERROR_CODE ) );
            return NET_CONNECT_ERROR;
607
608
        }

moret's avatar
moret committed
609
        return NET_CONNECTED;
610
611
    }

moret's avatar
moret committed
612
    net_status_t JackNetSlaveInterface::SendStartToMaster()
613
    {
moret's avatar
moret committed
614
        jack_log ( "JackNetSlaveInterface::SendStartToMaster" );
moret's avatar
moret committed
615

616
617
618
        //tell the master to start
        SetPacketType ( &fParams, START_MASTER );
        if ( fSocket.Send ( &fParams, sizeof ( session_params_t ), 0 ) == SOCKET_ERROR )
619
        {
620
621
            jack_error ( "Error in send : %s", StrError ( NET_ERROR_CODE ) );
            return ( fSocket.GetError() == NET_CONN_ERROR ) ? NET_ERROR : NET_SEND_ERROR;
622
        }
623
        return NET_ROLLING;
624
625
    }

626
    void JackNetSlaveInterface::SetParams()
moret's avatar
moret committed
627
    {
628
        jack_log ( "JackNetSlaveInterface::SetParams" );
moret's avatar
moret committed
629
630
631

        JackNetInterface::SetParams();

632
633
        fTxHeader.fDataStream = 'r';
        fRxHeader.fDataStream = 's';
moret's avatar
moret committed
634
635

        //midi net buffers
636
637
        fNetMidiCaptureBuffer = new NetMidiBuffer ( &fParams, fParams.fSendMidiChannels, fRxData );
        fNetMidiPlaybackBuffer = new NetMidiBuffer ( &fParams, fParams.fReturnMidiChannels, fTxData );
moret's avatar
moret committed
638
639

        //audio net buffers
640
641
        fNetAudioCaptureBuffer = new NetAudioBuffer ( &fParams, fParams.fSendAudioChannels, fRxData );
        fNetAudioPlaybackBuffer = new NetAudioBuffer ( &fParams, fParams.fReturnAudioChannels, fTxData );
moret's avatar
moret committed
642
643
644
645
646
647

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

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

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

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

moret's avatar
moret committed
717
718
719
            if ( rx_bytes == SOCKET_ERROR )
                return rx_bytes;
            if ( rx_bytes && ( rx_head->fDataStream == 's' ) && ( rx_head->fID == fParams.fID ) )
720
            {
moret's avatar
moret committed
721
                switch ( rx_head->fDataType )
722
                {
moret's avatar
moret committed
723
724
725
                    case 'm':   //midi
                        rx_bytes = Recv ( rx_head->fPacketSize, 0 );
                        fRxHeader.fCycle = rx_head->fCycle;
moret's avatar
moret committed
726
                        fRxHeader.fIsLastPckt = rx_head->fIsLastPckt;
moret's avatar
moret committed
727
728
729
730
                        fNetMidiCaptureBuffer->RenderFromNetwork ( rx_head->fSubCycle, rx_bytes - sizeof ( packet_header_t ) );
                        if ( ++recvd_midi_pckt == rx_head->fNMidiPckt )
                            fNetMidiCaptureBuffer->RenderToJackPorts();
                        break;
731

moret's avatar
moret committed
732
733
734
735
736
737
                    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
738
                        fRxHeader.fIsLastPckt = rx_head->fIsLastPckt;
moret's avatar
moret committed
739
740
                        fNetAudioCaptureBuffer->RenderToJackPorts ( rx_head->fSubCycle );
                        break;
741

moret's avatar
moret committed
742
743
744
                    case 's':   //sync
                        jack_info ( "NetSlave : overloaded, skipping receive." );
                        return 0;
745
                }
746
747
            }
        }
748
749
        fRxHeader.fCycle = rx_head->fCycle;
        return 0;
750
751
    }

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

767
    int JackNetSlaveInterface::DataSend()
768
769
    {
        uint subproc;
770

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

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