JackNetInterface.cpp 41.5 KB
Newer Older
1
/*
sletz's avatar
sletz committed
2
Copyright (C) 2008-2011 Romain Moret at Grame
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20

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"
21
#include "JackPlatformPlug.h"
22
#include <assert.h>
23
24
25

using namespace std;

sletz's avatar
sletz committed
26
#define PACKET_AVAILABLE_SIZE (fParams.fMtu - sizeof(packet_header_t))
sletz's avatar
sletz committed
27
#define HEADER_SIZE (sizeof(packet_header_t))
sletz's avatar
sletz committed
28

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

35
36
37
38
namespace Jack
{
    // JackNetInterface*******************************************

39
40
    JackNetInterface::JackNetInterface() : fSocket()
    {
sletz's avatar
sletz committed
41
        Initialize();
42
43
    }

sletz's avatar
sletz committed
44
    JackNetInterface::JackNetInterface(const char* multicast_ip, int port) : fSocket(multicast_ip, port)
45
    {
46
        strcpy(fMulticastIP, multicast_ip);
sletz's avatar
sletz committed
47
        Initialize();
48
49
    }

sletz's avatar
sletz committed
50
    JackNetInterface::JackNetInterface(session_params_t& params, JackNetSocket& socket, const char* multicast_ip) : fSocket(socket)
51
    {
moret's avatar
moret committed
52
        fParams = params;
53
        strcpy(fMulticastIP, multicast_ip);
sletz's avatar
sletz committed
54
55
        Initialize();
    }
sletz's avatar
sletz committed
56

sletz's avatar
sletz committed
57
58
    void JackNetInterface::Initialize()
    {
59
60
61
62
63
64
        fTxBuffer = NULL;
        fRxBuffer = NULL;
        fNetAudioCaptureBuffer = NULL;
        fNetAudioPlaybackBuffer = NULL;
        fNetMidiCaptureBuffer = NULL;
        fNetMidiPlaybackBuffer = NULL;
65
66
        memset(&fSendTransportData, 0, sizeof(net_transport_data_t));
        memset(&fReturnTransportData, 0, sizeof(net_transport_data_t));
67
68
    }

sletz's avatar
sletz committed
69
70
71
72
73
74
75
76
77
78
79
    void JackNetInterface::FreeNetworkBuffers()
    {
        delete fNetMidiCaptureBuffer;
        delete fNetMidiPlaybackBuffer;
        delete fNetAudioCaptureBuffer;
        delete fNetAudioPlaybackBuffer;
        fNetMidiCaptureBuffer = NULL;
        fNetMidiPlaybackBuffer = NULL;
        fNetAudioCaptureBuffer = NULL;
        fNetAudioPlaybackBuffer = NULL;
    }
sletz's avatar
sletz committed
80

81
82
    JackNetInterface::~JackNetInterface()
    {
sletz's avatar
sletz committed
83
        jack_log("JackNetInterface::~JackNetInterface");
moret's avatar
moret committed
84

85
86
87
88
89
90
91
92
93
        fSocket.Close();
        delete[] fTxBuffer;
        delete[] fRxBuffer;
        delete fNetAudioCaptureBuffer;
        delete fNetAudioPlaybackBuffer;
        delete fNetMidiCaptureBuffer;
        delete fNetMidiPlaybackBuffer;
    }

moret's avatar
moret committed
94
95
    int JackNetInterface::SetNetBufferSize()
    {
sletz's avatar
sletz committed
96
        // audio
sletz's avatar
sletz committed
97
        float audio_size = (fNetAudioCaptureBuffer)
sletz's avatar
sletz committed
98
99
                        ? fNetAudioCaptureBuffer->GetCycleSize()
                        : (fNetAudioPlaybackBuffer) ? fNetAudioPlaybackBuffer->GetCycleSize() : 0;
sletz's avatar
sletz committed
100
        jack_log("audio_size %f", audio_size);
sletz's avatar
sletz committed
101

sletz's avatar
sletz committed
102
        // midi
sletz's avatar
sletz committed
103
        float midi_size = (fNetMidiCaptureBuffer)
sletz's avatar
sletz committed
104
105
                        ? fNetMidiCaptureBuffer->GetCycleSize()
                        : (fNetMidiPlaybackBuffer) ? fNetMidiPlaybackBuffer->GetCycleSize() : 0;
sletz's avatar
sletz committed
106
        jack_log("midi_size %f", midi_size);
sletz's avatar
sletz committed
107

sletz's avatar
sletz committed
108
109
        // bufsize = sync + audio + midi
        int bufsize = NETWORK_MAX_LATENCY * (fParams.fMtu + (int)audio_size + (int)midi_size);
sletz's avatar
sletz committed
110
        jack_log("SetNetBufferSize bufsize = %d", bufsize);
moret's avatar
moret committed
111

sletz's avatar
sletz committed
112
        // tx buffer
sletz's avatar
sletz committed
113
        if (fSocket.SetOption(SOL_SOCKET, SO_SNDBUF, &bufsize, sizeof(bufsize)) == SOCKET_ERROR)
114
            return SOCKET_ERROR;
moret's avatar
moret committed
115

sletz's avatar
sletz committed
116
        // rx buffer
sletz's avatar
sletz committed
117
        if (fSocket.SetOption(SOL_SOCKET, SO_RCVBUF, &bufsize, sizeof(bufsize)) == SOCKET_ERROR)
118
            return SOCKET_ERROR;
moret's avatar
moret committed
119

120
        return 0;
moret's avatar
moret committed
121
122
    }

sletz's avatar
sletz committed
123
    bool JackNetInterface::SetParams()
moret's avatar
moret committed
124
    {
sletz's avatar
sletz committed
125
        // TX header init
sletz's avatar
sletz committed
126
        strcpy(fTxHeader.fPacketType, "header");
127
128
129
        fTxHeader.fID = fParams.fID;
        fTxHeader.fCycle = 0;
        fTxHeader.fSubCycle = 0;
moret's avatar
moret committed
130
        fTxHeader.fIsLastPckt = 0;
131

sletz's avatar
sletz committed
132
        // RX header init
sletz's avatar
sletz committed
133
        strcpy(fRxHeader.fPacketType, "header");
134
135
136
        fRxHeader.fID = fParams.fID;
        fRxHeader.fCycle = 0;
        fRxHeader.fSubCycle = 0;
moret's avatar
moret committed
137
        fRxHeader.fIsLastPckt = 0;
138

sletz's avatar
sletz committed
139
        // network buffers
140
141
        fTxBuffer = new char[fParams.fMtu];
        fRxBuffer = new char[fParams.fMtu];
sletz's avatar
sletz committed
142
143
        assert(fTxBuffer);
        assert(fRxBuffer);
144

sletz's avatar
sletz committed
145
        // net audio/midi buffers'addresses
sletz's avatar
sletz committed
146
147
        fTxData = fTxBuffer + HEADER_SIZE;
        fRxData = fRxBuffer + HEADER_SIZE;
sletz's avatar
sletz committed
148

sletz's avatar
sletz committed
149
        return true;
150
151
    }

sletz's avatar
sletz committed
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
    int JackNetInterface::MidiSend(NetMidiBuffer* buffer, int midi_channnels, int audio_channels)
    {
        if (midi_channnels > 0) {
            // set global header fields and get the number of midi packets
            fTxHeader.fDataType = 'm';
            uint data_size = buffer->RenderFromJackPorts();
            fTxHeader.fNumPacket = buffer->GetNumPackets(data_size, PACKET_AVAILABLE_SIZE);

            for (uint subproc = 0; subproc < fTxHeader.fNumPacket; subproc++) {
                fTxHeader.fSubCycle = subproc;
                // fTxHeader.fIsLastPckt = ((subproc == (fTxHeader.fNumPacket - 1)) && !fParams.fReturnAudioChannels) ? 1 : 0;
                fTxHeader.fIsLastPckt = ((subproc == (fTxHeader.fNumPacket - 1)) && audio_channels == 0) ? 1 : 0;
                fTxHeader.fPacketSize = HEADER_SIZE + buffer->RenderToNetwork(subproc, data_size);
                memcpy(fTxBuffer, &fTxHeader, HEADER_SIZE);
                if (Send(fTxHeader.fPacketSize, 0) == SOCKET_ERROR)
                    return SOCKET_ERROR;
            }
        }
        return 0;
    }

    int JackNetInterface::AudioSend(NetAudioBuffer* buffer, int audio_channels)
    {
        // audio
        if (audio_channels > 0) {
            fTxHeader.fDataType = 'a';
            buffer->RenderFromJackPorts();
            fTxHeader.fNumPacket = buffer->GetNumPackets();

            for (uint subproc = 0; subproc < fTxHeader.fNumPacket; subproc++) {
                fTxHeader.fSubCycle = subproc;
                fTxHeader.fIsLastPckt = (subproc == (fTxHeader.fNumPacket - 1)) ? 1 : 0;
                fTxHeader.fPacketSize = HEADER_SIZE + buffer->RenderToNetwork(subproc, fTxHeader.fActivePorts);
                memcpy(fTxBuffer, &fTxHeader, HEADER_SIZE);
                // PacketHeaderDisplay(&fTxHeader);
                if (Send(fTxHeader.fPacketSize, 0) == SOCKET_ERROR)
                    return SOCKET_ERROR;
            }
        }
        return 0;
    }

    int JackNetInterface::MidiRecv(packet_header_t* rx_head, NetMidiBuffer* buffer, uint& recvd_midi_pckt)
    {
        int rx_bytes = Recv(rx_head->fPacketSize, 0);
        fRxHeader.fCycle = rx_head->fCycle;
        fRxHeader.fIsLastPckt = rx_head->fIsLastPckt;
        buffer->RenderFromNetwork(rx_head->fSubCycle, rx_bytes - HEADER_SIZE);
        // Last midi packet is received, so finish rendering...
        if (++recvd_midi_pckt == rx_head->fNumPacket)
            buffer->RenderToJackPorts();
        return rx_bytes;
    }

    int JackNetInterface::AudioRecv(packet_header_t* rx_head, NetAudioBuffer* buffer)
    {
        int rx_bytes = Recv(rx_head->fPacketSize, 0);
        fRxHeader.fCycle = rx_head->fCycle;
        fRxHeader.fSubCycle = rx_head->fSubCycle;
        fRxHeader.fIsLastPckt = rx_head->fIsLastPckt;
        fRxHeader.fActivePorts = rx_head->fActivePorts;
        rx_bytes = buffer->RenderFromNetwork(rx_head->fCycle, rx_head->fSubCycle, rx_bytes - HEADER_SIZE, fRxHeader.fActivePorts);
        // Last audio packet is received, so finish rendering...
        if (fRxHeader.fIsLastPckt)
            buffer->RenderToJackPorts();
        return rx_bytes;
    }

    int JackNetInterface::FinishRecv(NetAudioBuffer* buffer)
    {
        // TODO : finish midi and audio rendering ?
        buffer->RenderToJackPorts();
        return NET_PACKET_ERROR;
    }

227
    // JackNetMasterInterface ************************************************************************************
228

229
    bool JackNetMasterInterface::Init()
230
    {
sletz's avatar
sletz committed
231
        jack_log("JackNetMasterInterface::Init, ID %u", fParams.fID);
232

233
        session_params_t host_params;
234
        uint attempt = 0;
235
236
        int rx_bytes = 0;

sletz's avatar
sletz committed
237
        // socket
sletz's avatar
sletz committed
238
239
        if (fSocket.NewSocket() == SOCKET_ERROR) {
            jack_error("Can't create socket : %s", StrError(NET_ERROR_CODE));
240
            return false;
241
242
        }

sletz's avatar
sletz committed
243
        // timeout on receive (for init)
sletz's avatar
sletz committed
244
245
        if (fSocket.SetTimeOut(MASTER_INIT_TIMEOUT) < 0)
            jack_error("Can't set timeout : %s", StrError(NET_ERROR_CODE));
246

sletz's avatar
sletz committed
247
        // connect
sletz's avatar
sletz committed
248
249
        if (fSocket.Connect() == SOCKET_ERROR) {
            jack_error("Can't connect : %s", StrError(NET_ERROR_CODE));
250
251
            return false;
        }
252

sletz's avatar
sletz committed
253
        // send 'SLAVE_SETUP' until 'START_MASTER' received
sletz's avatar
sletz committed
254
        jack_info("Sending parameters to %s...", fParams.fSlaveNetName);
255
256
        do
        {
257
            session_params_t net_params;
sletz's avatar
sletz committed
258
259
            memset(&net_params, 0, sizeof(session_params_t));
            SetPacketType(&fParams, SLAVE_SETUP);
260
            SessionParamsHToN(&fParams, &net_params);
261

sletz's avatar
sletz committed
262
            if (fSocket.Send(&net_params, sizeof(session_params_t), 0) == SOCKET_ERROR)
sletz's avatar
sletz committed
263
                jack_error("Error in send : %s", StrError(NET_ERROR_CODE));
264

sletz's avatar
sletz committed
265
            memset(&net_params, 0, sizeof(session_params_t));
sletz's avatar
sletz committed
266
            if (((rx_bytes = fSocket.Recv(&net_params, sizeof(session_params_t), 0)) == SOCKET_ERROR) && (fSocket.GetError() != NET_NO_DATA))
267
            {
sletz's avatar
sletz committed
268
                jack_error("Problem with network");
269
                return false;
270
            }
271

272
            SessionParamsNToH(&net_params, &host_params);
273
        }
sletz's avatar
sletz committed
274
275
276
        while ((GetPacketType(&host_params) != START_MASTER) && (++attempt < SLAVE_SETUP_RETRY));
        if (attempt == SLAVE_SETUP_RETRY) {
            jack_error("Slave doesn't respond, exiting");
277
            return false;
278
279
        }

280
        return true;
281
282
    }

sletz's avatar
sletz committed
283
284
285
286
287
288
    int JackNetMasterInterface::SetRxTimeout()
    {
        jack_log("JackNetMasterInterface::SetRxTimeout");
        float time = 3 * 1000000.f * (static_cast<float>(fParams.fPeriodSize) / static_cast<float>(fParams.fSampleRate));
        return fSocket.SetTimeOut(static_cast<int>(time));
    }
moret's avatar
moret committed
289

sletz's avatar
sletz committed
290
    bool JackNetMasterInterface::SetParams()
moret's avatar
moret committed
291
    {
sletz's avatar
sletz committed
292
293
        jack_log("JackNetMasterInterface::SetParams audio in = %d audio out = %d MIDI in = %d MIDI out = %d",
            fParams.fSendAudioChannels, fParams.fReturnAudioChannels, fParams.fSendMidiChannels, fParams.fReturnMidiChannels);
moret's avatar
moret committed
294
295
296

        JackNetInterface::SetParams();

297
298
        fTxHeader.fDataStream = 's';
        fRxHeader.fDataStream = 'r';
moret's avatar
moret committed
299

sletz's avatar
sletz committed
300
301
302
        fMaxCycleOffset = fParams.fNetworkLatency;

        // midi net buffers
sletz's avatar
sletz committed
303
        if (fParams.fSendMidiChannels > 0)
sletz's avatar
sletz committed
304
            fNetMidiCaptureBuffer = new NetMidiBuffer(&fParams, fParams.fSendMidiChannels, fTxData);
sletz's avatar
sletz committed
305

sletz's avatar
sletz committed
306
        if (fParams.fReturnMidiChannels > 0)
sletz's avatar
sletz committed
307
            fNetMidiPlaybackBuffer = new NetMidiBuffer(&fParams, fParams.fReturnMidiChannels, fRxData);
sletz's avatar
sletz committed
308

sletz's avatar
sletz committed
309
        try {
sletz's avatar
sletz committed
310

sletz's avatar
sletz committed
311
            // audio net buffers
sletz's avatar
sletz committed
312
            if (fParams.fSendAudioChannels > 0) {
sletz's avatar
sletz committed
313

314
                switch (fParams.fSampleEncoder) {
sletz's avatar
sletz committed
315

316
                    case JackFloatEncoder:
sletz's avatar
sletz committed
317
                        fNetAudioCaptureBuffer = new NetFloatAudioBuffer(&fParams, fParams.fSendAudioChannels, fTxData);
318
                        break;
sletz's avatar
sletz committed
319

320
                    case JackIntEncoder:
sletz's avatar
sletz committed
321
                        fNetAudioCaptureBuffer = new NetIntAudioBuffer(&fParams, fParams.fSendAudioChannels, fTxData);
322
                        break;
sletz's avatar
sletz committed
323

324
                    case JackCeltEncoder:
nedko's avatar
nedko committed
325
                    #if HAVE_CELT
sletz's avatar
sletz committed
326
                        fNetAudioCaptureBuffer = new NetCeltAudioBuffer(&fParams, fParams.fSendAudioChannels, fTxData, fParams.fKBps);
327
328
329
                    #endif
                        break;
                }
sletz's avatar
sletz committed
330

sletz's avatar
sletz committed
331
332
                assert(fNetAudioCaptureBuffer);
            }
sletz's avatar
sletz committed
333

sletz's avatar
sletz committed
334
            if (fParams.fReturnAudioChannels > 0) {
sletz's avatar
sletz committed
335

336
                switch (fParams.fSampleEncoder) {
sletz's avatar
sletz committed
337

338
                    case JackFloatEncoder:
sletz's avatar
sletz committed
339
                        fNetAudioPlaybackBuffer = new NetFloatAudioBuffer(&fParams, fParams.fReturnAudioChannels, fRxData);
340
                        break;
sletz's avatar
sletz committed
341

342
                    case JackIntEncoder:
sletz's avatar
sletz committed
343
                        fNetAudioPlaybackBuffer = new NetIntAudioBuffer(&fParams, fParams.fReturnAudioChannels, fRxData);
344
                        break;
sletz's avatar
sletz committed
345

346
                    case JackCeltEncoder:
nedko's avatar
nedko committed
347
                    #if HAVE_CELT
sletz's avatar
sletz committed
348
                        fNetAudioPlaybackBuffer = new NetCeltAudioBuffer(&fParams, fParams.fReturnAudioChannels, fRxData, fParams.fKBps);
349
350
351
                    #endif
                        break;
                }
sletz's avatar
sletz committed
352

sletz's avatar
sletz committed
353
354
                assert(fNetAudioPlaybackBuffer);
            }
sletz's avatar
sletz committed
355

sletz's avatar
sletz committed
356
357
358
359
        } catch (exception&) {
            jack_error("NetAudioBuffer allocation error...");
            return false;
        }
moret's avatar
moret committed
360

sletz's avatar
sletz committed
361
        // set the new timeout for the socket
sletz's avatar
sletz committed
362
363
        if (SetRxTimeout() == SOCKET_ERROR) {
            jack_error("Can't set rx timeout : %s", StrError(NET_ERROR_CODE));
sletz's avatar
sletz committed
364
            goto error;
sletz's avatar
sletz committed
365
        }
moret's avatar
moret committed
366

sletz's avatar
sletz committed
367
        // set the new rx buffer size
sletz's avatar
sletz committed
368
369
        if (SetNetBufferSize() == SOCKET_ERROR) {
            jack_error("Can't set net buffer sizes : %s", StrError(NET_ERROR_CODE));
sletz's avatar
sletz committed
370
371
            goto error;
        }
sletz's avatar
sletz committed
372

sletz's avatar
sletz committed
373
        return true;
sletz's avatar
sletz committed
374

sletz's avatar
sletz committed
375
    error:
sletz's avatar
sletz committed
376
        FreeNetworkBuffers();
sletz's avatar
sletz committed
377
        return false;
moret's avatar
moret committed
378
379
    }

380
    void JackNetMasterInterface::Exit()
381
    {
sletz's avatar
sletz committed
382
        jack_log("JackNetMasterInterface::Exit, ID %u", fParams.fID);
383

sletz's avatar
sletz committed
384
        // stop process
385
        fRunning = false;
386

sletz's avatar
sletz committed
387
        // send a 'multicast euthanasia request' - new socket is required on macosx
sletz's avatar
sletz committed
388
389
390
        jack_info("Exiting '%s'", fParams.fName);
        SetPacketType(&fParams, KILL_MASTER);
        JackNetSocket mcast_socket(fMulticastIP, fSocket.GetPort());
391

392
        session_params_t net_params;
sletz's avatar
sletz committed
393
        memset(&net_params, 0, sizeof(session_params_t));
394
395
        SessionParamsHToN(&fParams, &net_params);

sletz's avatar
sletz committed
396
397
398
399
        if (mcast_socket.NewSocket() == SOCKET_ERROR)
            jack_error("Can't create socket : %s", StrError(NET_ERROR_CODE));
        if (mcast_socket.SendTo(&net_params, sizeof(session_params_t), 0, fMulticastIP) == SOCKET_ERROR)
            jack_error("Can't send suicide request : %s", StrError(NET_ERROR_CODE));
400

401
402
403
        mcast_socket.Close();
    }

sletz's avatar
sletz committed
404
405
    void JackNetMasterInterface::FatalError()
    {
sletz's avatar
sletz committed
406
        // fatal connection issue, exit
sletz's avatar
sletz committed
407
        jack_error("'%s' : %s, exiting", fParams.fName, StrError(NET_ERROR_CODE));
sletz's avatar
sletz committed
408
        // ask to the manager to properly remove the master
sletz's avatar
sletz committed
409
410
411
412
413
        Exit();
        // UGLY temporary way to be sure the thread does not call code possibly causing a deadlock in JackEngine.
        ThreadExit();
    }

sletz's avatar
sletz committed
414
    int JackNetMasterInterface::Recv(size_t size, int flags)
415
    {
416
        int rx_bytes;
sletz's avatar
sletz committed
417

sletz's avatar
sletz committed
418
        if (((rx_bytes = fSocket.Recv(fRxBuffer, size, flags)) == SOCKET_ERROR) && fRunning) {
419
420

            /*
421
            net_error_t error = fSocket.GetError();
sletz's avatar
sletz committed
422
            // no data isn't really a network error, so just return 0 available read bytes
sletz's avatar
sletz committed
423
            if (error == NET_NO_DATA) {
424
                return 0;
sletz's avatar
sletz committed
425
            } else if (error == NET_CONN_ERROR) {
sletz's avatar
sletz committed
426
                FatalError();
sletz's avatar
sletz committed
427
            } else {
sletz's avatar
sletz committed
428
                jack_error("Error in master receive : %s", StrError(NET_ERROR_CODE));
429
            }
430
431
            */

sletz's avatar
sletz committed
432
            FatalError();
433
        }
434

435
436
437
        packet_header_t* header = reinterpret_cast<packet_header_t*>(fRxBuffer);
        PacketHeaderNToH(header, header);
        return rx_bytes;
438
    }
439

sletz's avatar
sletz committed
440
    int JackNetMasterInterface::Send(size_t size, int flags)
441
    {
442
443
444
        int tx_bytes;
        packet_header_t* header = reinterpret_cast<packet_header_t*>(fTxBuffer);
        PacketHeaderHToN(header, header);
445

sletz's avatar
sletz committed
446
        if (((tx_bytes = fSocket.Send(fTxBuffer, size, flags)) == SOCKET_ERROR) && fRunning) {
sletz's avatar
sletz committed
447
            /*
448
            net_error_t error = fSocket.GetError();
sletz's avatar
sletz committed
449
            if (error == NET_CONN_ERROR) {
sletz's avatar
sletz committed
450
                FatalError();
sletz's avatar
sletz committed
451
452
            } else {
                jack_error("Error in master send : %s", StrError(NET_ERROR_CODE));
453
            }
sletz's avatar
sletz committed
454
455
            */
            FatalError();
456
        }
457
        return tx_bytes;
458
    }
459

460
461
    bool JackNetMasterInterface::IsSynched()
    {
462
        return (fCycleOffset <= fMaxCycleOffset);
463
    }
464

465
    int JackNetMasterInterface::SyncSend()
466
    {
467
468
469
        fTxHeader.fCycle++;
        fTxHeader.fSubCycle = 0;
        fTxHeader.fDataType = 's';
470
        fTxHeader.fIsLastPckt = (fParams.fSendMidiChannels == 0 && fParams.fSendAudioChannels == 0) ? 1 : 0;
sletz's avatar
sletz committed
471
        fTxHeader.fPacketSize = fParams.fMtu;
sletz's avatar
sletz committed
472

473
474
475
476
        // Write active ports list
        if (fNetAudioPlaybackBuffer)
            fNetAudioPlaybackBuffer->ActivePortsToNetwork(fTxData, fTxHeader.fActivePorts);

sletz's avatar
sletz committed
477
        memcpy(fTxBuffer, &fTxHeader, HEADER_SIZE);
sletz's avatar
sletz committed
478
        // PacketHeaderDisplay(&fTxHeader);
sletz's avatar
sletz committed
479
        return Send(fTxHeader.fPacketSize, 0);
480
481
482
483
    }

    int JackNetMasterInterface::DataSend()
    {
sletz's avatar
sletz committed
484
        /*
485
        uint subproc;
sletz's avatar
sletz committed
486
487
        uint data_size;

sletz's avatar
sletz committed
488
        // midi
sletz's avatar
sletz committed
489
        if (fParams.fSendMidiChannels > 0) {
sletz's avatar
sletz committed
490
            // set global header fields and get the number of midi packets
491
            fTxHeader.fDataType = 'm';
sletz's avatar
sletz committed
492
            data_size = fNetMidiCaptureBuffer->RenderFromJackPorts();
sletz's avatar
sletz committed
493
            fTxHeader.fNumPacket = fNetMidiCaptureBuffer->GetNumPackets(data_size, PACKET_AVAILABLE_SIZE);
sletz's avatar
sletz committed
494

sletz's avatar
sletz committed
495
            for (subproc = 0; subproc < fTxHeader.fNumPacket; subproc++) {
496
                fTxHeader.fSubCycle = subproc;
sletz's avatar
sletz committed
497
498
                fTxHeader.fIsLastPckt = ((subproc == (fTxHeader.fNumPacket - 1)) && (fParams.fSendAudioChannels == 0)) ? 1 : 0;
                fTxHeader.fPacketSize = HEADER_SIZE + fNetMidiCaptureBuffer->RenderToNetwork(subproc, data_size);
sletz's avatar
sletz committed
499
500
                memcpy(fTxBuffer, &fTxHeader, HEADER_SIZE);
                if (Send(fTxHeader.fPacketSize, 0) == SOCKET_ERROR)
501
                    return SOCKET_ERROR;
502
503
            }
        }
sletz's avatar
sletz committed
504
505
506
507
        */

        if (MidiSend(fNetMidiCaptureBuffer, fParams.fSendMidiChannels, fParams.fSendAudioChannels) == SOCKET_ERROR)
            return SOCKET_ERROR;
508

sletz's avatar
sletz committed
509
510
        /*
        // audio
sletz's avatar
sletz committed
511
        if (fParams.fSendAudioChannels > 0) {
512
            fTxHeader.fDataType = 'a';
sletz's avatar
sletz committed
513
            fNetAudioCaptureBuffer->RenderFromJackPorts();
sletz's avatar
sletz committed
514
            fTxHeader.fNumPacket = fNetAudioCaptureBuffer->GetNumPackets();
sletz's avatar
sletz committed
515

sletz's avatar
sletz committed
516
            for (subproc = 0; subproc < fTxHeader.fNumPacket; subproc++) {
517
                fTxHeader.fSubCycle = subproc;
sletz's avatar
sletz committed
518
                fTxHeader.fIsLastPckt = (subproc == (fTxHeader.fNumPacket - 1)) ? 1 : 0;
519
                fTxHeader.fPacketSize = HEADER_SIZE + fNetAudioCaptureBuffer->RenderToNetwork(subproc, fTxHeader.fActivePorts);
sletz's avatar
sletz committed
520
                memcpy(fTxBuffer, &fTxHeader, HEADER_SIZE);
sletz's avatar
sletz committed
521
                // PacketHeaderDisplay(&fTxHeader);
sletz's avatar
sletz committed
522
                if (Send(fTxHeader.fPacketSize, 0) == SOCKET_ERROR)
523
524
525
526
                    return SOCKET_ERROR;
            }
        }
        return 0;
sletz's avatar
sletz committed
527
528
        */
        return AudioSend(fNetAudioPlaybackBuffer, fParams.fSendAudioChannels);
529
530
    }

531
    int JackNetMasterInterface::SyncRecv()
532
    {
sletz's avatar
sletz committed
533
        packet_header_t* rx_head = reinterpret_cast<packet_header_t*>(fRxBuffer);
sletz's avatar
sletz committed
534
        int rx_bytes = Recv(fParams.fMtu, MSG_PEEK);
535

sletz's avatar
sletz committed
536
        if ((rx_bytes == 0) || (rx_bytes == SOCKET_ERROR)) {
sletz's avatar
sletz committed
537
            // 0 bytes considered an error (lost connection)
sletz's avatar
sletz committed
538
539
            return SOCKET_ERROR;
        }
540

541
        fCycleOffset = fTxHeader.fCycle - rx_head->fCycle;
542

543
544
545
546
        // Read active ports list
        if (fNetAudioCaptureBuffer)
            fNetAudioCaptureBuffer->ActivePortsFromNetwork(fRxData, rx_head->fActivePorts);

547
548
549
550
551
        if (fCycleOffset < fMaxCycleOffset) {
            return 0;
        } else {
            rx_bytes = Recv(rx_head->fPacketSize, 0);
        }
552

moret's avatar
moret committed
553
        fRxHeader.fIsLastPckt = rx_head->fIsLastPckt;
554
555
        return rx_bytes;
    }
556

557
    int JackNetMasterInterface::DataRecv()
558
559
    {
        int rx_bytes = 0;
560
        uint recvd_midi_pckt = 0;
sletz's avatar
sletz committed
561
        packet_header_t* rx_head = reinterpret_cast<packet_header_t*>(fRxBuffer);
562

sletz's avatar
sletz committed
563
564
        while (!fRxHeader.fIsLastPckt) {
            // how much data is queued on the rx buffer ?
sletz's avatar
sletz committed
565
            rx_bytes = Recv(fParams.fMtu, MSG_PEEK);
566

sletz's avatar
sletz committed
567
            // error here, problem with recv, just skip the cycle (return -1)
sletz's avatar
sletz committed
568
            if (rx_bytes == SOCKET_ERROR)
moret's avatar
moret committed
569
                return rx_bytes;
sletz's avatar
sletz committed
570

sletz's avatar
sletz committed
571
572
573
574
575
576
            if (rx_bytes && (rx_head->fDataStream == 'r') && (rx_head->fID == fParams.fID)) {
                // read data
                switch (rx_head->fDataType) {

                    case 'm':   // midi
                        /*
sletz's avatar
sletz committed
577
                        rx_bytes = Recv(rx_head->fPacketSize, 0);
moret's avatar
moret committed
578
                        fRxHeader.fCycle = rx_head->fCycle;
moret's avatar
moret committed
579
                        fRxHeader.fIsLastPckt = rx_head->fIsLastPckt;
sletz's avatar
sletz committed
580
                        fNetMidiPlaybackBuffer->RenderFromNetwork(rx_head->fSubCycle, rx_bytes - HEADER_SIZE);
sletz's avatar
sletz committed
581
582
                        // Last midi packet is received, so finish rendering...
                        if (++recvd_midi_pckt == rx_head->fNumPacket)
moret's avatar
moret committed
583
                            fNetMidiPlaybackBuffer->RenderToJackPorts();
sletz's avatar
sletz committed
584
585
                        */
                        rx_bytes = MidiRecv(rx_head, fNetMidiPlaybackBuffer, recvd_midi_pckt);
moret's avatar
moret committed
586
                        break;
587

sletz's avatar
sletz committed
588
589
                    case 'a':   // audio
                        /*
sletz's avatar
sletz committed
590
                        rx_bytes = Recv(rx_head->fPacketSize, 0);
moret's avatar
moret committed
591
592
                        fRxHeader.fCycle = rx_head->fCycle;
                        fRxHeader.fSubCycle = rx_head->fSubCycle;
moret's avatar
moret committed
593
                        fRxHeader.fIsLastPckt = rx_head->fIsLastPckt;
594
                        fRxHeader.fActivePorts = rx_head->fActivePorts;
sletz's avatar
sletz committed
595
                        rx_bytes = fNetAudioPlaybackBuffer->RenderFromNetwork(rx_head->fCycle, rx_head->fSubCycle, rx_bytes - HEADER_SIZE, fRxHeader.fActivePorts);
sletz's avatar
sletz committed
596
597
                        // Last audio packet is received, so finish rendering...
                        if (fRxHeader.fIsLastPckt)
sletz's avatar
sletz committed
598
                            fNetAudioPlaybackBuffer->RenderToJackPorts();
sletz's avatar
sletz committed
599
600
                        */
                        rx_bytes = AudioRecv(rx_head, fNetAudioPlaybackBuffer);
moret's avatar
moret committed
601
                        break;
602

sletz's avatar
sletz committed
603
                    case 's':   // sync
604
                        jack_info("NetMaster : overloaded, skipping receive from '%s'", fParams.fName);
sletz's avatar
sletz committed
605
                        /*
sletz's avatar
sletz committed
606
                        // TODO : finish midi and audio rendering ?
sletz's avatar
sletz committed
607
                        fNetAudioPlaybackBuffer->RenderToJackPorts();
sletz's avatar
sletz committed
608
                        return NET_PACKET_ERROR;
sletz's avatar
sletz committed
609
610
                        */
                        return FinishRecv(fNetAudioPlaybackBuffer);
611
612
613
                }
            }
        }
sletz's avatar
sletz committed
614

615
        return rx_bytes;
616
    }
617

618
    void JackNetMasterInterface::EncodeSyncPacket()
619
    {
sletz's avatar
sletz committed
620
621
        // This method contains every step of sync packet informations coding
        // first of all, reset sync packet
sletz's avatar
sletz committed
622
        memset(fTxData, 0, PACKET_AVAILABLE_SIZE);
623

sletz's avatar
sletz committed
624
        // then, first step : transport
625
        if (fParams.fTransportSync) {
sletz's avatar
sletz committed
626
            // desactivated...
sletz's avatar
sletz committed
627
            // EncodeTransportData();
sletz's avatar
sletz committed
628
            TransportDataHToN(&fSendTransportData,  &fSendTransportData);
sletz's avatar
sletz committed
629
            // copy to TxBuffer
sletz's avatar
sletz committed
630
            memcpy(fTxData, &fSendTransportData, sizeof(net_transport_data_t));
631
        }
sletz's avatar
sletz committed
632
633
        // then others (freewheel etc.)
        // ...
634
635
    }

636
    void JackNetMasterInterface::DecodeSyncPacket()
637
    {
sletz's avatar
sletz committed
638
639
        // This method contains every step of sync packet informations decoding process
        // first : transport
640
        if (fParams.fTransportSync) {
sletz's avatar
sletz committed
641
            // copy received transport data to transport data structure
sletz's avatar
sletz committed
642
643
644
            memcpy(&fReturnTransportData, fRxData, sizeof(net_transport_data_t));
            TransportDataNToH(&fReturnTransportData,  &fReturnTransportData);
            // desactivated...
sletz's avatar
sletz committed
645
            // DecodeTransportData();
646
        }
sletz's avatar
sletz committed
647
648
        // then others
        // ...
649
    }
650

651
652
// JackNetSlaveInterface ************************************************************************************************

moret's avatar
moret committed
653
654
    uint JackNetSlaveInterface::fSlaveCounter = 0;

655
    bool JackNetSlaveInterface::Init()
656
    {
sletz's avatar
sletz committed
657
        jack_log("JackNetSlaveInterface::Init()");
658

sletz's avatar
sletz committed
659
        // set the parameters to send
sletz's avatar
sletz committed
660
        strcpy(fParams.fPacketType, "params");
661
        fParams.fProtocolVersion = SLAVE_PROTOCOL;
sletz's avatar
sletz committed
662
        SetPacketType(&fParams, SLAVE_AVAILABLE);
663

sletz's avatar
sletz committed
664
        // init loop : get a master and start, do it until connection is ok
665
        net_status_t status;
666
        do {
sletz's avatar
sletz committed
667
            // first, get a master, do it until a valid connection is running
668
            do {
669
                status = SendAvailableToMaster();
sletz's avatar
sletz committed
670
                if (status == NET_SOCKET_ERROR)
671
                    return false;
672
            }
sletz's avatar
sletz committed
673
            while (status != NET_CONNECTED);
674

sletz's avatar
sletz committed
675
            // then tell the master we are ready
sletz's avatar
sletz committed
676
            jack_info("Initializing connection with %s...", fParams.fMasterNetName);
moret's avatar
moret committed
677
            status = SendStartToMaster();
sletz's avatar
sletz committed
678
            if (status == NET_ERROR)
679
                return false;
680
        }
sletz's avatar
sletz committed
681
        while (status != NET_ROLLING);
682

683
684
        return true;
    }
685

686
    // Separate the connection protocol into two separated step
sletz's avatar
sletz committed
687
    bool JackNetSlaveInterface::InitConnection(int time_out)
688
    {
sletz's avatar
sletz committed
689
        jack_log("JackNetSlaveInterface::InitConnection()");
sletz's avatar
sletz committed
690
        uint try_count = (time_out > 0) ? ((1000000 * time_out) / SLAVE_INIT_TIMEOUT) : LONG_MAX;
691

sletz's avatar
sletz committed
692
        // set the parameters to send
sletz's avatar
sletz committed
693
        strcpy(fParams.fPacketType, "params");
694
        fParams.fProtocolVersion = SLAVE_PROTOCOL;
sletz's avatar
sletz committed
695
        SetPacketType(&fParams, SLAVE_AVAILABLE);
696
697

        net_status_t status;
698
        do {
sletz's avatar
sletz committed
699
            // get a master
sletz's avatar
sletz committed
700
            status = SendAvailableToMaster(try_count);
701
702
703
            if (status == NET_SOCKET_ERROR)
                return false;
        }
sletz's avatar
sletz committed
704
        while (status != NET_CONNECTED && --try_count > 0);
705

sletz's avatar
sletz committed
706
        return (try_count != 0);
707
    }
708

709
710
711
712
713
    bool JackNetSlaveInterface::InitRendering()
    {
        jack_log("JackNetSlaveInterface::InitRendering()");

        net_status_t status;
714
        do {
sletz's avatar
sletz committed
715
            // then tell the master we are ready
716
717
718
719
720
            jack_info("Initializing connection with %s...", fParams.fMasterNetName);
            status = SendStartToMaster();
            if (status == NET_ERROR)
                return false;
        }
721
722
        while (status != NET_ROLLING);

723
724
        return true;
    }
725

sletz's avatar
sletz committed
726
    net_status_t JackNetSlaveInterface::SendAvailableToMaster(long try_count)
727
    {
sletz's avatar
sletz committed
728
        jack_log("JackNetSlaveInterface::SendAvailableToMaster()");
sletz's avatar
sletz committed
729
        // utility
730
        session_params_t host_params;
731
732
        int rx_bytes = 0;

sletz's avatar
sletz committed
733
        // socket
sletz's avatar
sletz committed
734
735
        if (fSocket.NewSocket() == SOCKET_ERROR) {
            jack_error("Fatal error : network unreachable - %s", StrError(NET_ERROR_CODE));
736
            return NET_SOCKET_ERROR;
737
738
        }

sletz's avatar
sletz committed
739
        // bind the socket
sletz's avatar
sletz committed
740
741
        if (fSocket.Bind() == SOCKET_ERROR) {
            jack_error("Can't bind the socket : %s", StrError(NET_ERROR_CODE));
742
743
            return NET_SOCKET_ERROR;
        }
744

sletz's avatar
sletz committed
745
        // timeout on receive
sletz's avatar
sletz committed
746
747
        if (fSocket.SetTimeOut(SLAVE_INIT_TIMEOUT) == SOCKET_ERROR)
            jack_error("Can't set timeout : %s", StrError(NET_ERROR_CODE));
748

sletz's avatar
sletz committed
749
        // disable local loop
sletz's avatar
sletz committed
750
751
        if (fSocket.SetLocalLoop() == SOCKET_ERROR)
            jack_error("Can't disable multicast loop : %s", StrError(NET_ERROR_CODE));
752

sletz's avatar
sletz committed
753
        // send 'AVAILABLE' until 'SLAVE_SETUP' received
sletz's avatar
sletz committed
754
        jack_info("Waiting for a master...");
755
        do {
sletz's avatar
sletz committed
756
            // send 'available'
757
            session_params_t net_params;
sletz's avatar
sletz committed
758
            memset(&net_params, 0, sizeof(session_params_t));
759
            SessionParamsHToN(&fParams, &net_params);
sletz's avatar
sletz committed
760
761
            if (fSocket.SendTo(&net_params, sizeof(session_params_t), 0, fMulticastIP) == SOCKET_ERROR)
                jack_error("Error in data send : %s", StrError(NET_ERROR_CODE));
762

sletz's avatar
sletz committed
763
            // filter incoming packets : don't exit while no error is detected
sletz's avatar
sletz committed
764
765
            memset(&net_params, 0, sizeof(session_params_t));
            rx_bytes = fSocket.CatchHost(&net_params, sizeof(session_params_t), 0);
766
            SessionParamsNToH(&net_params, &host_params);
767
            if ((rx_bytes == SOCKET_ERROR) && (fSocket.GetError() != NET_NO_DATA)) {
sletz's avatar
sletz committed
768
                jack_error("Can't receive : %s", StrError(NET_ERROR_CODE));
769
                return NET_RECV_ERROR;