JackNetTool.h 31.4 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

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.

*/
sletz's avatar
sletz committed
19
20

#include "JackMidiPort.h"
21
#include "JackTools.h"
22
#include "JackPlatformPlug.h"
23
#include "types.h"
24
#include "transport.h"
sletz's avatar
sletz committed
25
#ifndef WIN32
26
#include <netinet/in.h>
sletz's avatar
sletz committed
27
#endif
sletz's avatar
sletz committed
28
29
#include <cmath>

moret's avatar
moret committed
30
31
using namespace std;

sletz's avatar
sletz committed
32
33
#ifndef htonll
#ifdef __BIG_ENDIAN__
34
35
#define htonll(x) (x)
#define ntohll(x) (x)
sletz's avatar
sletz committed
36
#else
37
38
#define htonll(x) ((((uint64_t)htonl(x)) << 32) + htonl(x >> 32))
#define ntohll(x) ((((uint64_t)ntohl(x)) << 32) + ntohl(x >> 32))
sletz's avatar
sletz committed
39
40
41
#endif
#endif

42
43
#define MASTER_PROTOCOL 4
#define SLAVE_PROTOCOL 4
44

sletz's avatar
sletz committed
45
46
#define NET_PACKET_ERROR -2

47
48
#define OPTIMIZED_PROTOCOL

sletz's avatar
sletz committed
49
50
namespace Jack
{
51
52
    typedef struct _session_params session_params_t;
    typedef struct _packet_header packet_header_t;
53
    typedef struct _net_transport_data net_transport_data_t;
54
55
56
    typedef struct sockaddr socket_address_t;
    typedef struct in_addr address_t;
    typedef jack_default_audio_sample_t sample_t;
sletz's avatar
sletz committed
57

58
59
60
61
62
63
    enum JackNetEncoder {

        JackFloatEncoder = 0,
        JackIntEncoder = 1,
        JackCeltEncoder = 2,
    };
sletz's avatar
sletz committed
64
65
66

//session params ******************************************************************************

moret's avatar
moret committed
67
68
69
70
71
72
73
74
75
76
77
78
    /**
    \brief This structure containes master/slave connection parameters, it's used to setup the whole system

    We have :
        - some info like version, type and packet id
        - names
        - network parameters (hostnames and mtu)
        - nunber of audio and midi channels
        - sample rate and buffersize
        - number of audio frames in one network packet (depends on the channel number)
        - is the NetDriver in Sync or ASync mode ?
        - is the NetDriver linked with the master's transport
sletz's avatar
sletz committed
79

80
    Data encoding : headers (session_params and packet_header) are encoded using HTN kind of functions but float data
sletz's avatar
sletz committed
81
    are kept in LITTLE_ENDIAN format (to avoid 2 conversions in the more common LITTLE_ENDIAN <==> LITTLE_ENDIAN connection case).
moret's avatar
moret committed
82
    */
sletz's avatar
sletz committed
83

84
85
    struct _session_params
    {
moret's avatar
moret committed
86
87
88
89
90
91
92
93
94
        char fPacketType[7];                //packet type ('param')
        char fProtocolVersion;              //version
        uint32_t fPacketID;                 //indicates the packet type
        char fName[JACK_CLIENT_NAME_SIZE];  //slave's name
        char fMasterNetName[256];           //master hostname (network)
        char fSlaveNetName[256];            //slave hostname (network)
        uint32_t fMtu;                      //connection mtu
        uint32_t fID;                       //slave's ID
        uint32_t fTransportSync;            //is the transport synced ?
sletz's avatar
sletz committed
95
96
97
98
        int32_t fSendAudioChannels;         //number of master->slave channels
        int32_t fReturnAudioChannels;       //number of slave->master channels
        int32_t fSendMidiChannels;          //number of master->slave midi channels
        int32_t fReturnMidiChannels;        //number of slave->master midi channels
moret's avatar
moret committed
99
100
        uint32_t fSampleRate;               //session sample rate
        uint32_t fPeriodSize;               //period size
101
        uint32_t fSampleEncoder;            //samples encoder
sletz's avatar
sletz committed
102
        uint32_t fKBps;                     //KB per second for CELT encoder
moret's avatar
moret committed
103
        uint32_t fSlaveSyncMode;            //is the slave in sync mode ?
104
        uint32_t fNetworkLatency;           //network latency
105
    };
sletz's avatar
sletz committed
106
107
108

//net status **********************************************************************************

moret's avatar
moret committed
109
110
111
    /**
    \Brief This enum groups network error by type
    */
112

113
114
115
116
117
118
119
120
121
122
    enum  _net_status
    {
        NET_SOCKET_ERROR = 0,
        NET_CONNECT_ERROR,
        NET_ERROR,
        NET_SEND_ERROR,
        NET_RECV_ERROR,
        NET_CONNECTED,
        NET_ROLLING
    };
sletz's avatar
sletz committed
123

124
    typedef enum _net_status net_status_t;
sletz's avatar
sletz committed
125
126
127

//sync packet type ****************************************************************************

moret's avatar
moret committed
128
129
130
    /**
    \Brief This enum indicates the type of a sync packet (used in the initialization phase)
    */
131

132
133
    enum _sync_packet_type
    {
134
135
136
137
138
139
        INVALID = 0,        //...
        SLAVE_AVAILABLE,    //a slave is available
        SLAVE_SETUP,        //slave configuration
        START_MASTER,       //slave is ready, start master
        START_SLAVE,        //master is ready, activate slave
        KILL_MASTER         //master must stop
140
    };
sletz's avatar
sletz committed
141

142
    typedef enum _sync_packet_type sync_packet_type_t;
sletz's avatar
sletz committed
143
144
145
146


//packet header *******************************************************************************

moret's avatar
moret committed
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
    /**
    \Brief This structure is a complete header

    A header indicates :
        - it is a header
        - the type of data the packet contains (sync, midi or audio)
        - the path of the packet (send -master->slave- or return -slave->master-)
        - the unique ID of the slave
        - the sample's bitdepth (unused for now)
        - the size of the midi data contains in the packet (indicates how much midi data will be sent)
        - the number of midi packet(s) : more than one is very unusual, it depends on the midi load
        - the ID of the current cycle (used to check missing packets)
        - the ID of the packet subcycle (for audio data)
        - a flag indicating this packet is the last of the cycle (for sync robustness, it's better to process this way)
        - a flag indicating if, in async mode, the previous graph was not finished or not
        - padding to fill 64 bytes

    */
165

166
167
    struct _packet_header
    {
sletz's avatar
sletz committed
168
        char fPacketType[7];        //packet type ('headr')
169
        char fDataType;             //a for audio, m for midi and s for sync
170
        char fDataStream;           //s for send, r for return
171
        uint32_t fID;               //unique ID of the slave
sletz's avatar
sletz committed
172
        uint32_t fNumPacket;        //number of data packets of the cycle
moret's avatar
moret committed
173
        uint32_t fPacketSize;       //packet size in bytes
174
        uint32_t fActivePorts;      //number of active ports
175
176
        uint32_t fCycle;            //process cycle counter
        uint32_t fSubCycle;         //midi/audio subcycle counter
moret's avatar
moret committed
177
        uint32_t fIsLastPckt;       //is it the last packet of a given cycle ('y' or 'n')
178
    };
sletz's avatar
sletz committed
179

180
181
182
183
184
185
186
187
//net timebase master

    /**
    \Brief This enum describes timebase master's type
    */

    enum _net_timebase_master
    {
188
189
190
191
        NO_CHANGE = 0,
        RELEASE_TIMEBASEMASTER = 1,
        TIMEBASEMASTER = 2,
        CONDITIONAL_TIMEBASEMASTER = 3
192
193
194
195
196
    };

    typedef enum _net_timebase_master net_timebase_master_t;


197
198
//transport data ******************************************************************************

moret's avatar
moret committed
199
    /**
200
    \Brief This structure contains transport data to be sent over the network
moret's avatar
moret committed
201
    */
202

moret's avatar
moret committed
203
204
    struct _net_transport_data
    {
205
206
        uint32_t fNewState;             //is it a state change
        uint32_t fTimebaseMaster;       //is there a new timebase master
moret's avatar
moret committed
207
        int32_t fState;                 //current cycle state
208
        jack_position_t fPosition;      //current cycle position
moret's avatar
moret committed
209
    };
sletz's avatar
sletz committed
210

sletz's avatar
sletz committed
211
 //midi data ***********************************************************************************
sletz's avatar
sletz committed
212

moret's avatar
moret committed
213
214
    /**
    \Brief Midi buffer and operations class
215

moret's avatar
moret committed
216
217
218
219
220
221
222
223
224
    This class is a toolset to manipulate Midi buffers.
    A JackMidiBuffer has a fixed size, which is the same than an audio buffer size.
    An intermediate fixed size buffer allows to uninterleave midi data (from jack ports).
    But for a big majority of the process cycles, this buffer is filled less than 1%,
    Sending over a network 99% of useless data seems completely unappropriate.
    The idea is to count effective midi data, and then send the smallest packet we can.
    To do it, we use an intermediate buffer.
    We have two methods to convert data from jack ports to intermediate buffer,
    And two others to convert this intermediate buffer to a network buffer (header + payload data)
225

moret's avatar
moret committed
226
    */
227

228
    class SERVER_EXPORT NetMidiBuffer
229
    {
230
        private:
sletz's avatar
sletz committed
231

232
233
234
235
236
237
            int fNPorts;
            size_t fMaxBufsize;
            int fMaxPcktSize;
            char* fBuffer;
            char* fNetBuffer;
            JackMidiBuffer** fPortBuffer;
sletz's avatar
sletz committed
238

sletz's avatar
sletz committed
239
            size_t fCycleSize;  // needed size in bytes ofr an entire cycle
240
241

        public:
sletz's avatar
sletz committed
242

sletz's avatar
sletz committed
243
            NetMidiBuffer(session_params_t* params, uint32_t nports, char* net_buffer);
244
245
246
            ~NetMidiBuffer();

            void Reset();
sletz's avatar
sletz committed
247

sletz's avatar
sletz committed
248
249
            // needed size in bytes for an entire cycle
            size_t GetCycleSize();
sletz's avatar
sletz committed
250

sletz's avatar
sletz committed
251
            int GetNumPackets(int data_sizen, int max_size);
sletz's avatar
sletz committed
252

253
254
            //utility
            void DisplayEvents();
sletz's avatar
sletz committed
255

256
257
            //jack<->buffer
            int RenderFromJackPorts();
sletz's avatar
sletz committed
258
            void RenderToJackPorts();
sletz's avatar
sletz committed
259

260
            //network<->buffer
261
            void RenderFromNetwork(int sub_cycle, size_t copy_size);
262
            int RenderToNetwork(int sub_cycle, size_t total_size);
263

sletz's avatar
sletz committed
264
265
            void SetBuffer(int index, JackMidiBuffer* buffer);
            JackMidiBuffer* GetBuffer(int index);
266
    };
sletz's avatar
sletz committed
267
268
269

// audio data *********************************************************************************

sletz's avatar
sletz committed
270
    class SERVER_EXPORT NetAudioBuffer
271
    {
sletz's avatar
sletz committed
272

273
        public:
sletz's avatar
sletz committed
274

sletz's avatar
sletz committed
275
            NetAudioBuffer()
276
            {}
sletz's avatar
sletz committed
277
            virtual ~NetAudioBuffer()
278
            {}
sletz's avatar
sletz committed
279

sletz's avatar
sletz committed
280
281
            // needed syze in bytes ofr an entire cycle
            virtual size_t GetCycleSize() = 0;
sletz's avatar
sletz committed
282

sletz's avatar
sletz committed
283
284
            // cycle duration in sec
            virtual float GetCycleDuration() = 0;
sletz's avatar
sletz committed
285

sletz's avatar
sletz committed
286
            virtual int GetNumPackets() = 0;
sletz's avatar
sletz committed
287

288
            //jack<->buffer
sletz's avatar
sletz committed
289
290
            virtual void RenderFromJackPorts() = 0;
            virtual void RenderToJackPorts() = 0;
sletz's avatar
sletz committed
291

sletz's avatar
sletz committed
292
            //network<->buffer
sletz's avatar
sletz committed
293
            virtual int RenderFromNetwork(int cycle, int sub_cycle, size_t copy_size, uint32_t port_num) = 0;
294
295
            virtual void ActivePortsFromNetwork(char* net_buffer, uint32_t port_num) {}

sletz's avatar
sletz committed
296
            virtual int RenderToNetwork(int sub_cycle, uint32_t& port_num) = 0;
297
            virtual void ActivePortsToNetwork(char* net_buffer, uint32_t& port_num) {}
298

sletz's avatar
sletz committed
299
300
            virtual void SetBuffer(int index, sample_t* buffer) = 0;
            virtual sample_t* GetBuffer(int index) = 0;
301
302
   };

moret's avatar
moret committed
303
304
    /**
    \Brief Audio buffer and operations class
305

moret's avatar
moret committed
306
307
308
309
    This class is a toolset to manipulate audio buffers.
    The manipulation of audio buffers is similar to midi buffer, except those buffers have fixed size.
    The interleaving/uninterleaving operations are simplier here because audio buffers have fixed size,
    So there is no need of an intermediate buffer as in NetMidiBuffer.
310

moret's avatar
moret committed
311
    */
sletz's avatar
sletz committed
312

313
    struct JackPortList {
sletz's avatar
sletz committed
314

sletz's avatar
sletz committed
315
316
        // "[---Header---|--audio data--|--audio data--]..."

317
318
319
320
        jack_nframes_t fPeriodSize;
        jack_nframes_t fSubPeriodSize;
        size_t fSubPeriodBytesSize;
        sample_t** fPortBuffer;
321
        int fPacketSize;
322
        int fNPorts;
sletz's avatar
sletz committed
323
324
        size_t fCycleSize;      // needed size in bytes for an entire cycle
        float fCycleDuration;   // in sec
sletz's avatar
sletz committed
325

sletz's avatar
sletz committed
326
        int fLastSubCycle;
sletz's avatar
sletz committed
327

328
329
330
331
        JackPortList(session_params_t* params, uint32_t nports)
        {
            fNPorts = nports;
            fPeriodSize = params->fPeriodSize;
332
333
            fPacketSize = params->fMtu - sizeof(packet_header_t);

sletz's avatar
sletz committed
334
            if (params->fSendAudioChannels == 0 && params->fReturnAudioChannels == 0) {
sletz's avatar
sletz committed
335
336
                fSubPeriodSize = params->fPeriodSize;
            } else {
337
                jack_nframes_t period = (int) powf(2.f,(int)(log(float(fPacketSize)
sletz's avatar
sletz committed
338
                                                   / (max(params->fReturnAudioChannels, params->fSendAudioChannels) * sizeof(sample_t))) / log(2.)));
339
                fSubPeriodSize = (period > fPeriodSize) ? fPeriodSize : period;
sletz's avatar
sletz committed
340
            }
sletz's avatar
sletz committed
341

sletz's avatar
sletz committed
342
            fSubPeriodBytesSize = fSubPeriodSize * sizeof(sample_t);
sletz's avatar
sletz committed
343

344
            fPortBuffer = new sample_t* [fNPorts];
345
            for (int port_index = 0; port_index < fNPorts; port_index++) {
346
                fPortBuffer[port_index] = NULL;
347
            }
sletz's avatar
sletz committed
348

sletz's avatar
sletz committed
349
            fCycleDuration = float(fSubPeriodSize) / float(params->fSampleRate);
sletz's avatar
sletz committed
350
            fCycleSize = params->fMtu * (fPeriodSize / fSubPeriodSize);
sletz's avatar
sletz committed
351

sletz's avatar
sletz committed
352
353
            fLastSubCycle = -1;
        }
sletz's avatar
sletz committed
354

355
        virtual int GetNumPackets()
sletz's avatar
sletz committed
356
        {
sletz's avatar
sletz committed
357
            /*
sletz's avatar
sletz committed
358
            jack_log("GetNumPackets packet = %d  fPeriodSize = %d fSubPeriodSize = %d fSubPeriodBytesSize = %d",
359
                fPeriodSize / fSubPeriodSize, fPeriodSize, fSubPeriodSize, fSubPeriodBytesSize);
sletz's avatar
sletz committed
360
            */
sletz's avatar
sletz committed
361
            return fPeriodSize / fSubPeriodSize;
362
        }
sletz's avatar
sletz committed
363

364
365
366
367
368
369
370
371
        JackPortList()
        {
            fNPorts = 0;
            fPeriodSize = 0;
            fSubPeriodSize = 0;
            fSubPeriodBytesSize = 0;
            fPortBuffer = 0;
        }
sletz's avatar
sletz committed
372

sletz's avatar
sletz committed
373
        virtual ~JackPortList()
374
375
376
        {
            delete [] fPortBuffer;
        }
sletz's avatar
sletz committed
377

sletz's avatar
sletz committed
378
        void SetBuffer(int index, sample_t* buffer)
379
380
381
        {
            fPortBuffer[index] = buffer;
        }
sletz's avatar
sletz committed
382

sletz's avatar
sletz committed
383
        sample_t* GetBuffer(int index)
384
385
386
        {
            return fPortBuffer[index];
        }
sletz's avatar
sletz committed
387

388
389
        void Copy(sample_t** buffers)
        {
sletz's avatar
sletz committed
390
            for (int port_index = 0; port_index < fNPorts; port_index++)
391
392
                memcpy(buffers[port_index], fPortBuffer[port_index], fPeriodSize * sizeof(float));
        }
sletz's avatar
sletz committed
393

sletz's avatar
sletz committed
394
        // needed syze in bytes for an entire cycle
sletz's avatar
sletz committed
395
396
397
398
        size_t GetCycleSize()
        {
            return fCycleSize;
        }
sletz's avatar
sletz committed
399

sletz's avatar
sletz committed
400
401
402
403
404
        // cycle duration in sec
        float GetCycleDuration()
        {
            return fCycleDuration;
        }
sletz's avatar
sletz committed
405

406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
    #ifdef __BIG_ENDIAN__

        static inline float SwapFloat(float f)
        {
              union
              {
                float f;
                unsigned char b[4];
              } dat1, dat2;

              dat1.f = f;
              dat2.b[0] = dat1.b[3];
              dat2.b[1] = dat1.b[2];
              dat2.b[2] = dat1.b[1];
              dat2.b[3] = dat1.b[0];
              return dat2.f;
        }

sletz's avatar
sletz committed
424
425
        virtual void RenderFromJackPorts()
        {}
426

sletz's avatar
sletz committed
427
428
        virtual void RenderToJackPorts()
        {}
sletz's avatar
sletz committed
429

sletz's avatar
sletz committed
430
        //network<->buffer
sletz's avatar
sletz committed
431
        virtual int RenderFromNetwork(char* net_buffer, int cycle, int sub_cycle, size_t copy_size, uint32_t port_num)
sletz's avatar
sletz committed
432
        {
sletz's avatar
sletz committed
433
434
            int res = 0;

435
            for (int port_index = 0; port_index < fNPorts; port_index++) {
436
                float* src = (float*)(net_buffer + port_index * fSubPeriodBytesSize);
437
                float* dst = (float*)(fPortBuffer[port_index] + sub_cycle * fSubPeriodSize);
438
439
440
                for (unsigned int sample = 0; sample < fSubPeriodBytesSize / sizeof(float); sample++) {
                    dst[sample] = SwapFloat(src[sample]);
                }
sletz's avatar
sletz committed
441
            }
442
443
            if (sub_cycle != fLastSubCycle + 1) {
                jack_error("Packet(s) missing from... %d %d", fLastSubCycle, sub_cycle);
sletz's avatar
sletz committed
444
                res = NET_PACKET_ERROR;
445
            }
sletz's avatar
sletz committed
446

447
            fLastSubCycle = sub_cycle;
sletz's avatar
sletz committed
448
            return res;
sletz's avatar
sletz committed
449
        }
sletz's avatar
sletz committed
450

sletz's avatar
sletz committed
451
        virtual int RenderToNetwork(char* net_buffer, int sub_cycle, uint32_t& port_num)
sletz's avatar
sletz committed
452
        {
453
            for (int port_index = 0; port_index < fNPorts; port_index++) {
454
                float* src = (float*)(fPortBuffer[port_index] + sub_cycle * fSubPeriodSize);
sletz's avatar
sletz committed
455
456
457
458
459
                float* dst = (float*)(net_buffer + port_index * fSubPeriodBytesSize);
                for (unsigned int sample = 0; sample < fSubPeriodBytesSize / sizeof(float); sample++) {
                    dst[sample] = SwapFloat(src[sample]);
                }
            }
sletz's avatar
sletz committed
460

461
            port_num = fNPorts;
sletz's avatar
sletz committed
462
            return fNPorts * fSubPeriodBytesSize;
463
        }
sletz's avatar
sletz committed
464

465
466
    #else

sletz's avatar
sletz committed
467
468
        virtual void RenderFromJackPorts()
        {}
469

sletz's avatar
sletz committed
470
        virtual void RenderToJackPorts()
sletz's avatar
sletz committed
471
        {
sletz's avatar
sletz committed
472
            // reset for next cycle
sletz's avatar
sletz committed
473
474
            fLastSubCycle = -1;
        }
sletz's avatar
sletz committed
475

476
        //network<->buffer
sletz's avatar
sletz committed
477
        virtual int RenderFromNetwork(char* net_buffer, int cycle, int sub_cycle, size_t copy_size, uint32_t port_num)
478
        {
sletz's avatar
sletz committed
479
480
            int res = 0;

481
482
483
484
485
            for (int port_index = 0; port_index < fNPorts; port_index++) {
                memcpy(fPortBuffer[port_index] + sub_cycle * fSubPeriodSize, net_buffer + port_index * fSubPeriodBytesSize, fSubPeriodBytesSize);
            }
            if (sub_cycle != fLastSubCycle + 1) {
                jack_error("Packet(s) missing from... %d %d", fLastSubCycle, sub_cycle);
sletz's avatar
sletz committed
486
                res = NET_PACKET_ERROR;
sletz's avatar
sletz committed
487
            }
sletz's avatar
sletz committed
488

489
            fLastSubCycle = sub_cycle;
sletz's avatar
sletz committed
490
            return res;
sletz's avatar
sletz committed
491
        }
sletz's avatar
sletz committed
492

sletz's avatar
sletz committed
493
        virtual int RenderToNetwork(char* net_buffer, int sub_cycle, uint32_t& port_num)
sletz's avatar
sletz committed
494
        {
495
496
497
498
            for (int port_index = 0; port_index < fNPorts; port_index++) {
                memcpy(net_buffer + port_index * fSubPeriodBytesSize, fPortBuffer[port_index] + sub_cycle * fSubPeriodSize, fSubPeriodBytesSize);
            }
            port_num = fNPorts;
sletz's avatar
sletz committed
499
            return fNPorts * fSubPeriodBytesSize;
500
501
502
        }

    #endif
sletz's avatar
sletz committed
503

504
505
506
507
508
        virtual void ActivePortsFromNetwork(char* net_buffer, uint32_t port_num)
        {}

        virtual void ActivePortsToNetwork(char* net_buffer, uint32_t& port_num)
        {
sletz's avatar
sletz committed
509
            // Default behaviour: all ports are active
510
511
512
            port_num = fNPorts;
        }

513
    };
sletz's avatar
sletz committed
514

515
516
    struct JackOptimizedPortList : JackPortList {

517
        // Consuming port list is transmitted in the Sync packed
sletz's avatar
sletz committed
518
519
        // "[---Header---|--active_port_num---audio data--|--active_port_num---audio data--]..."

520
521
522
523
        JackOptimizedPortList(session_params_t* params, uint32_t nports)
            :JackPortList(params, nports)
        {}

sletz's avatar
sletz committed
524
525
526
        virtual ~JackOptimizedPortList()
        {}

527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
        int GetNumPackets()
        {
            // Count active ports
            int active_ports = 0;
            for (int port_index = 0; port_index < fNPorts; port_index++) {
                if (fPortBuffer[port_index]) active_ports++;
            }

            if (active_ports == 0) {
                fSubPeriodSize = fPeriodSize;
            } else {
                jack_nframes_t period = (int) powf(2.f, (int)(log(float(fPacketSize) / (active_ports * sizeof(sample_t))) / log(2.)));
                fSubPeriodSize = (period > fPeriodSize) ? fPeriodSize : period;
            }

            fSubPeriodBytesSize = fSubPeriodSize * sizeof(sample_t) + sizeof(uint32_t); // The port number in coded on 4 bytes
sletz's avatar
sletz committed
543

sletz's avatar
sletz committed
544
            /*
sletz's avatar
sletz committed
545
546
            jack_log("GetNumPackets packet = %d  fPeriodSize = %d fSubPeriodSize = %d fSubPeriodBytesSize = %d",
                fPeriodSize / fSubPeriodSize, fPeriodSize, fSubPeriodSize, fSubPeriodBytesSize);
sletz's avatar
sletz committed
547
            */
548
            return fPeriodSize / fSubPeriodSize; // At least one packet
549
550
551
552
553
554
555
556
557
        }

    #ifdef __BIG_ENDIAN__

        // TODO

    #else

        //network<->buffer
sletz's avatar
sletz committed
558
        virtual int RenderFromNetwork(char* net_buffer, int cycle, int sub_cycle, size_t copy_size, uint32_t port_num)
559
        {
sletz's avatar
sletz committed
560
561
            int res = 0;

sletz's avatar
sletz committed
562
563
564
565
566
567
568
569
            // Cleanup all JACK ports at the beginning of the cycle
            if (sub_cycle == 0) {
                for (int port_index = 0; port_index < fNPorts; port_index++) {
                    if (fPortBuffer[port_index])
                        memset(fPortBuffer[port_index], 0, fPeriodSize * sizeof(sample_t));
                }
            }

570
571
572
573
574
575
576
577
578
579
580
            if (port_num > 0)  {

                /// Setup rendering parameters
                int sub_period_size, sub_period_bytes_size;
                if (port_num == 0) {
                    sub_period_size = fPeriodSize;
                } else {
                    jack_nframes_t period = (int) powf(2.f, (int)(log(float(fPacketSize) / (port_num * sizeof(sample_t))) / log(2.)));
                    sub_period_size = (period > fPeriodSize) ? fPeriodSize : period;
                }
                sub_period_bytes_size = sub_period_size * sizeof(sample_t) + sizeof(uint32_t); // The port number in coded on 4 bytes
581

582
583
584
585
586
587
588
                for (uint32_t port_index = 0; port_index < port_num; port_index++) {
                    // Only copy to active ports : read the active port number then audio data
                    int* active_port_address = (int*)(net_buffer + port_index * sub_period_bytes_size);
                    int active_port = (int)(*active_port_address);
                    if (fPortBuffer[port_index])
                        memcpy(fPortBuffer[active_port] + sub_cycle * sub_period_size, (char*)(active_port_address + 1), sub_period_bytes_size - sizeof(int));
                }
589

590
591
                if (sub_cycle != fLastSubCycle + 1) {
                    jack_error("Packet(s) missing from... %d %d", fLastSubCycle, sub_cycle);
sletz's avatar
sletz committed
592
                    res = NET_PACKET_ERROR;
593
                }
sletz's avatar
sletz committed
594

595
                fLastSubCycle = sub_cycle;
596
            }
sletz's avatar
sletz committed
597
598

            return res;
599
600
        }

sletz's avatar
sletz committed
601
        virtual int RenderToNetwork(char* net_buffer,int sub_cycle, uint32_t& port_num)
602
        {
sletz's avatar
sletz committed
603
            // Init active port count
604
605
606
            port_num = 0;

            for (int port_index = 0; port_index < fNPorts; port_index++) {
sletz's avatar
sletz committed
607
                // Only copy from active ports : write the active port number then audio data
608
609
610
611
612
613
614
615
616
617
618
619
620
                if (fPortBuffer[port_index]) {
                    int* active_port_address = (int*)(net_buffer + port_num * fSubPeriodBytesSize);
                    *active_port_address = port_index;
                    memcpy((char*)(active_port_address + 1), fPortBuffer[port_index] + sub_cycle * fSubPeriodSize, fSubPeriodBytesSize - sizeof(uint32_t));
                    port_num++;
                }
            }

            return port_num * fSubPeriodBytesSize;
        }

    #endif

621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
        virtual void ActivePortsToNetwork(char* net_buffer, uint32_t& port_num)
        {
            // Init active port count
            port_num = 0;
            short* active_port_address = (short*)net_buffer;

            for (int port_index = 0; port_index < fNPorts; port_index++) {
                // Write the active port number
                if (fPortBuffer[port_index]) {
                    *active_port_address = port_index;
                    active_port_address++;
                    port_num++;
                    assert(port_num < 512);
                }
            }
        }

        virtual void ActivePortsFromNetwork(char* net_buffer, uint32_t port_num)
        {
            short* active_port_address = (short*)net_buffer;

            for (int port_index = 0; port_index < fNPorts; port_index++) {
                fPortBuffer[port_index] = NULL;
            }

            for (uint port_index = 0; port_index < port_num; port_index++) {
647
                // Use -1 when port is actually connected on other side
sletz's avatar
sletz committed
648
649
650
651
652
                if (*active_port_address >= 0 && *active_port_address < fNPorts) {
                    fPortBuffer[*active_port_address] = (sample_t*)-1;
                } else {
                    jack_error("ActivePortsFromNetwork: incorrect port = %d", *active_port_address);
                }
653
654
655
656
                active_port_address++;
            }
        }

657
658
    };

sletz's avatar
sletz committed
659
    class SERVER_EXPORT NetFloatAudioBuffer : public NetAudioBuffer
660
    {
661
        private:
sletz's avatar
sletz committed
662

663
664
665
        #ifdef OPTIMIZED_PROTOCOL
            JackOptimizedPortList fPortBuffer;
        #else
666
            JackPortList fPortBuffer;
667
        #endif
668
            char* fNetBuffer;
sletz's avatar
sletz committed
669

670
        public:
sletz's avatar
sletz committed
671

sletz's avatar
sletz committed
672
            NetFloatAudioBuffer(session_params_t* params, uint32_t nports, char* net_buffer);
sletz's avatar
sletz committed
673
            ~NetFloatAudioBuffer();
sletz's avatar
sletz committed
674

sletz's avatar
sletz committed
675
676
            // needed size in bytes for an entire cycle
            size_t GetCycleSize();
sletz's avatar
sletz committed
677

sletz's avatar
sletz committed
678
            // cycle duration in sec
sletz's avatar
sletz committed
679
680
681
682
            float GetCycleDuration()
            {
                return fPortBuffer.GetCycleDuration();
            }
sletz's avatar
sletz committed
683

sletz's avatar
sletz committed
684
685
686
687
            int GetNumPackets()
            {
                return fPortBuffer.GetNumPackets();
            }
sletz's avatar
sletz committed
688

689
            //jack<->buffer
sletz's avatar
sletz committed
690
691
            void RenderFromJackPorts();
            void RenderToJackPorts();
692

sletz's avatar
sletz committed
693
694
            void SetBuffer(int index, sample_t* buffer);
            sample_t* GetBuffer(int index);
sletz's avatar
sletz committed
695

sletz's avatar
sletz committed
696
            //network<->buffer
sletz's avatar
sletz committed
697
            int RenderFromNetwork(int cycle, int sub_cycle, size_t copy_size, uint32_t port_num);
698
699
700
701
            void ActivePortsFromNetwork(char* net_buffer, uint32_t port_num);

            int RenderToNetwork(int sub_cycle, uint32_t&  ort_num);
            void ActivePortsToNetwork(char* net_buffer, uint32_t& port_num);
702
    };
sletz's avatar
sletz committed
703

nedko's avatar
nedko committed
704
#if HAVE_CELT
sletz's avatar
sletz committed
705
706
707
708
709
710

#include <celt/celt.h>

    class SERVER_EXPORT NetCeltAudioBuffer : public NetAudioBuffer
    {
        private:
sletz's avatar
sletz committed
711

712
713
714
            CELTMode** fCeltMode;
            CELTEncoder** fCeltEncoder;
            CELTDecoder** fCeltDecoder;
sletz's avatar
sletz committed
715

sletz's avatar
sletz committed
716
717
718
            int fCompressedSizeByte;
            jack_nframes_t fPeriodSize;
            int fNumPackets;
sletz's avatar
sletz committed
719
720
            float fCycleDuration;   // in sec
            size_t fCycleSize;      // needed size in bytes for an entire cycle
sletz's avatar
sletz committed
721

sletz's avatar
sletz committed
722
723
            size_t fSubPeriodBytesSize;
            size_t fLastSubPeriodBytesSize;
sletz's avatar
sletz committed
724

sletz's avatar
sletz committed
725
726
            sample_t** fPortBuffer;
            char* fNetBuffer;
727
            unsigned char** fCompressedBuffer;
sletz's avatar
sletz committed
728

sletz's avatar
sletz committed
729
730
            int fNPorts;
            int fLastSubCycle;
sletz's avatar
sletz committed
731

sletz's avatar
sletz committed
732
            void FreeCelt();
sletz's avatar
sletz committed
733

sletz's avatar
sletz committed
734
        public:
sletz's avatar
sletz committed
735

736
            NetCeltAudioBuffer(session_params_t* params, uint32_t nports, char* net_buffer, int kbps);
sletz's avatar
sletz committed
737
            ~NetCeltAudioBuffer();
sletz's avatar
sletz committed
738

sletz's avatar
sletz committed
739
740
            // needed size in bytes for an entire cycle
            size_t GetCycleSize();
sletz's avatar
sletz committed
741

sletz's avatar
sletz committed
742
743
744
             // cycle duration in sec
            float GetCycleDuration();
            int GetNumPackets();
sletz's avatar
sletz committed
745

sletz's avatar
sletz committed
746
747
            void SetBuffer(int index, sample_t* buffer);
            sample_t* GetBuffer(int index);
sletz's avatar
sletz committed
748

sletz's avatar
sletz committed
749
            //jack<->buffer
sletz's avatar
sletz committed
750
751
            void RenderFromJackPorts();
            void RenderToJackPorts();
sletz's avatar
sletz committed
752
753

            //network<->buffer
sletz's avatar
sletz committed
754
            int RenderFromNetwork(int cycle, int sub_cycle, size_t copy_size, uint32_t port_num);
sletz's avatar
sletz committed
755
            int RenderToNetwork(int sub_cycle, uint32_t&  port_num);
sletz's avatar
sletz committed
756
757
758
    };

#endif
sletz's avatar
sletz committed
759
760
761
762

    class SERVER_EXPORT NetIntAudioBuffer : public NetAudioBuffer
    {
        private:
sletz's avatar
sletz committed
763

sletz's avatar
sletz committed
764
765
            int fCompressedSizeByte;
            jack_nframes_t fPeriodSize;
sletz's avatar
sletz committed
766

sletz's avatar
sletz committed
767
            int fNumPackets;
sletz's avatar
sletz committed
768
769
            float fCycleDuration;   // in sec
            size_t fCycleSize;      // needed size in bytes for an entire cycle
sletz's avatar
sletz committed
770

sletz's avatar
sletz committed
771
772
773
774
            size_t fSubPeriodSize;
            size_t fSubPeriodBytesSize;
            size_t fLastSubPeriodSize;;
            size_t fLastSubPeriodBytesSize;
sletz's avatar
sletz committed
775

sletz's avatar
sletz committed
776
777
778
            sample_t** fPortBuffer;
            char* fNetBuffer;
            short ** fIntBuffer;
sletz's avatar
sletz committed
779

sletz's avatar
sletz committed
780
781
            int fNPorts;
            int fLastSubCycle;
sletz's avatar
sletz committed
782

sletz's avatar
sletz committed
783
        public:
sletz's avatar
sletz committed
784

sletz's avatar
sletz committed
785
786
            NetIntAudioBuffer(session_params_t* params, uint32_t nports, char* net_buffer);
            ~NetIntAudioBuffer();
sletz's avatar
sletz committed
787

sletz's avatar
sletz committed
788
789
            // needed size in bytes for an entire cycle
            size_t GetCycleSize();
sletz's avatar
sletz committed
790

sletz's avatar
sletz committed
791
792
793
             // cycle duration in sec
            float GetCycleDuration();
            int GetNumPackets();
sletz's avatar
sletz committed
794

sletz's avatar
sletz committed
795
796
            void SetBuffer(int index, sample_t* buffer);
            sample_t* GetBuffer(int index);
sletz's avatar
sletz committed
797

sletz's avatar
sletz committed
798
            //jack<->buffer
sletz's avatar
sletz committed
799
800
            void RenderFromJackPorts();
            void RenderToJackPorts();
sletz's avatar
sletz committed
801
802

            //network<->buffer
sletz's avatar
sletz committed
803
            int RenderFromNetwork(int cycle, int sub_cycle, size_t copy_size, uint32_t port_num);
sletz's avatar
sletz committed
804
            int RenderToNetwork(int sub_cycle, uint32_t& port_num);
sletz's avatar
sletz committed
805
806
    };

sletz's avatar
sletz committed
807
    /*
808
    #define AUDIO_BUFFER_SIZE 8
sletz's avatar
sletz committed
809

sletz's avatar
sletz committed
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
    struct JackPortListAllocate : public JackPortList {

        JackPortListAllocate()
        {
            fNPorts = 0;
            fPeriodSize = 0;
            fSubPeriodSize = 0;
            fSubPeriodBytesSize = 0;
            fPortBuffer = 0;
        }

        ~JackPortListAllocate()
        {
            for (int port_index = 0; port_index < fNPorts; port_index++)
                delete [] fPortBuffer[port_index];
            delete [] fPortBuffer;
        }

        void Init(session_params_t* params, uint32_t nports)
        {
            fNPorts = nports;
            fPeriodSize = params->fPeriodSize;

            if (params->fSendAudioChannels == 0 && params->fReturnAudioChannels == 0) {
                fSubPeriodSize = params->fPeriodSize;
            } else {
                jack_nframes_t period = (int) powf(2.f, (int)(log(float((params->fMtu - sizeof(packet_header_t)))
                                                   / (max(params->fReturnAudioChannels, params->fSendAudioChannels) * sizeof(sample_t))) / log(2.)));
                fSubPeriodSize = (period > params->fPeriodSize) ? params->fPeriodSize : period;
            }

            fSubPeriodBytesSize = fSubPeriodSize * sizeof(sample_t);
            fPortBuffer = new sample_t* [fNPorts];
            for (int port_index = 0; port_index < fNPorts; port_index++)
                fPortBuffer[port_index] = new sample_t[fPeriodSize];
        }

    };

849
850
    class SERVER_EXPORT NetBufferedAudioBuffer : public NetAudioBuffer
    {
sletz's avatar
sletz committed
851

852
        private:
853
            char* fNetBuffer;
854
855
856
            JackPortListAllocate fPortBuffer[AUDIO_BUFFER_SIZE];
            sample_t** fJackPortBuffer;
            int fMaxCycle;
sletz's avatar
sletz committed
857

858
        public:
sletz's avatar
sletz committed
859
            NetBufferedAudioBuffer(session_params_t* params, uint32_t nports, char* net_buffer);
860
            ~NetBufferedAudioBuffer();
861

sletz's avatar
sletz committed
862
863
            // needed syze in bytes ofr an entire cycle
            size_t GetCycleSize();
sletz's avatar
sletz committed
864

sletz's avatar
sletz committed
865
866
867
868
869
             // cycle duration in sec
            float GetCycleDuration()
            {
                return fPortBuffer[0].GetCycleDuration();
            }
sletz's avatar
sletz committed
870

871
            //jack<->buffer
sletz's avatar
sletz committed
872
873
            void RenderFromJackPorts(int sub_cycle);
            void RenderToJackPorts(int cycle, int sub_cycle);
sletz's avatar
sletz committed
874
            //void FinishRenderToJackPorts(int cycle);
sletz's avatar
sletz committed
875

sletz's avatar
sletz committed
876
            //network<->buffer
877
            void RenderFromNetwork(int sub_cycle, size_t copy_size)
sletz's avatar
sletz committed
878
            {
sletz's avatar
sletz committed
879
880
                // TODO
            }
881
            int RenderToNetwork(int sub_cycle, size_t total_size)
sletz's avatar
sletz committed
882
            {
sletz's avatar
sletz committed
883
884
885
                // TODO
                return 0;
            }
886

sletz's avatar
sletz committed
887
888
            void SetBuffer(int index, sample_t* buffer);
            sample_t* GetBuffer(int index);
889
    };
sletz's avatar
sletz committed
890
    */
sletz's avatar
sletz committed
891

sletz's avatar
sletz committed
892
    //utility *************************************************************************************
893
894

    //socket API management
895
896
    SERVER_EXPORT int SocketAPIInit();
    SERVER_EXPORT int SocketAPIEnd();
897
    //n<-->h functions
sletz's avatar
sletz committed
898
899
900
901
902
903
904
905
    SERVER_EXPORT void SessionParamsHToN(session_params_t* src_params, session_params_t* dst_params);
    SERVER_EXPORT void SessionParamsNToH(session_params_t* src_params, session_params_t* dst_params);
    SERVER_EXPORT void PacketHeaderHToN(packet_header_t* src_header, packet_header_t* dst_header);
    SERVER_EXPORT void PacketHeaderNToH(packet_header_t* src_header, packet_header_t* dst_header);
    SERVER_EXPORT void MidiBufferHToN(JackMidiBuffer* src_buffer, JackMidiBuffer* dst_buffer);
    SERVER_EXPORT void MidiBufferNToH(JackMidiBuffer* src_buffer, JackMidiBuffer* dst_buffer);
    SERVER_EXPORT void TransportDataHToN(net_transport_data_t* src_params, net_transport_data_t* dst_params);
    SERVER_EXPORT void TransportDataNToH(net_transport_data_t* src_params, net_transport_data_t* dst_params);
906
    //display session parameters
sletz's avatar
sletz committed
907
    SERVER_EXPORT void SessionParamsDisplay(session_params_t* params);
908
    //display packet header
sletz's avatar
sletz committed
909
    SERVER_EXPORT void PacketHeaderDisplay(packet_header_t* header);
910
    //get the packet type from a sesion parameters
sletz's avatar
sletz committed
911
    SERVER_EXPORT sync_packet_type_t GetPacketType(session_params_t* params);
912
    //set the packet type in a session parameters
sletz's avatar
sletz committed
913
    SERVER_EXPORT int SetPacketType(session_params_t* params, sync_packet_type_t packet_type);
914
    //transport utility
sletz's avatar
sletz committed
915
916
    SERVER_EXPORT const char* GetTransportState(int transport_state);
    SERVER_EXPORT void NetTransportDataDisplay(net_transport_data_t* data);
sletz's avatar
sletz committed
917
}