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

49
50
51
#define HEADER_SIZE (sizeof(packet_header_t))
#define PACKET_AVAILABLE_SIZE(params) ((params)->fMtu - sizeof(packet_header_t))

sletz's avatar
sletz committed
52
53
namespace Jack
{
54
55
    typedef struct _session_params session_params_t;
    typedef struct _packet_header packet_header_t;
56
    typedef struct _net_transport_data net_transport_data_t;
57
58
59
    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
60

61
62
63
64
65
66
    enum JackNetEncoder {

        JackFloatEncoder = 0,
        JackIntEncoder = 1,
        JackCeltEncoder = 2,
    };
sletz's avatar
sletz committed
67
68
69

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

moret's avatar
moret committed
70
71
72
73
74
75
76
77
78
79
80
81
    /**
    \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
82

83
    Data encoding : headers (session_params and packet_header) are encoded using HTN kind of functions but float data
sletz's avatar
sletz committed
84
    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
85
    */
sletz's avatar
sletz committed
86

87
88
    struct _session_params
    {
moret's avatar
moret committed
89
90
91
92
93
94
95
96
97
        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
98
99
100
101
        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
102
103
        uint32_t fSampleRate;               //session sample rate
        uint32_t fPeriodSize;               //period size
104
        uint32_t fSampleEncoder;            //samples encoder
sletz's avatar
sletz committed
105
        uint32_t fKBps;                     //KB per second for CELT encoder
moret's avatar
moret committed
106
        uint32_t fSlaveSyncMode;            //is the slave in sync mode ?
107
        uint32_t fNetworkLatency;           //network latency
108
    };
sletz's avatar
sletz committed
109
110
111

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

moret's avatar
moret committed
112
113
114
    /**
    \Brief This enum groups network error by type
    */
115

116
117
118
119
120
121
122
123
124
125
    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
126

127
    typedef enum _net_status net_status_t;
sletz's avatar
sletz committed
128
129
130

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

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

135
136
    enum _sync_packet_type
    {
137
138
139
140
141
142
        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
143
    };
sletz's avatar
sletz committed
144

145
    typedef enum _sync_packet_type sync_packet_type_t;
sletz's avatar
sletz committed
146
147
148
149


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

moret's avatar
moret committed
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
    /**
    \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

    */
168

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

183
184
185
186
187
188
189
190
//net timebase master

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

    enum _net_timebase_master
    {
191
192
193
194
        NO_CHANGE = 0,
        RELEASE_TIMEBASEMASTER = 1,
        TIMEBASEMASTER = 2,
        CONDITIONAL_TIMEBASEMASTER = 3
195
196
197
198
199
    };

    typedef enum _net_timebase_master net_timebase_master_t;


200
201
//transport data ******************************************************************************

moret's avatar
moret committed
202
    /**
203
    \Brief This structure contains transport data to be sent over the network
moret's avatar
moret committed
204
    */
205

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

sletz's avatar
sletz committed
214
 //midi data ***********************************************************************************
sletz's avatar
sletz committed
215

moret's avatar
moret committed
216
217
    /**
    \Brief Midi buffer and operations class
218

moret's avatar
moret committed
219
220
221
222
223
224
225
226
227
    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)
228

moret's avatar
moret committed
229
    */
230

231
    class SERVER_EXPORT NetMidiBuffer
232
    {
233
        private:
sletz's avatar
sletz committed
234

235
236
237
238
239
240
            int fNPorts;
            size_t fMaxBufsize;
            int fMaxPcktSize;
            char* fBuffer;
            char* fNetBuffer;
            JackMidiBuffer** fPortBuffer;
sletz's avatar
sletz committed
241

sletz's avatar
sletz committed
242
            size_t fCycleSize;  // needed size in bytes ofr an entire cycle
243
244

        public:
sletz's avatar
sletz committed
245

sletz's avatar
sletz committed
246
            NetMidiBuffer(session_params_t* params, uint32_t nports, char* net_buffer);
247
248
249
            ~NetMidiBuffer();

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

sletz's avatar
sletz committed
251
252
            // needed size in bytes for an entire cycle
            size_t GetCycleSize();
sletz's avatar
sletz committed
253

sletz's avatar
sletz committed
254
            int GetNumPackets(int data_sizen, int max_size);
sletz's avatar
sletz committed
255

256
257
            //utility
            void DisplayEvents();
sletz's avatar
sletz committed
258

259
260
            //jack<->buffer
            int RenderFromJackPorts();
sletz's avatar
sletz committed
261
            void RenderToJackPorts();
sletz's avatar
sletz committed
262

263
            //network<->buffer
264
            void RenderFromNetwork(int sub_cycle, size_t copy_size);
265
            int RenderToNetwork(int sub_cycle, size_t total_size);
266

sletz's avatar
sletz committed
267
268
            void SetBuffer(int index, JackMidiBuffer* buffer);
            JackMidiBuffer* GetBuffer(int index);
269
    };
sletz's avatar
sletz committed
270
271
272

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

sletz's avatar
sletz committed
273
    class SERVER_EXPORT NetAudioBuffer
274
    {
sletz's avatar
sletz committed
275

276
        public:
sletz's avatar
sletz committed
277

sletz's avatar
sletz committed
278
            NetAudioBuffer()
279
            {}
sletz's avatar
sletz committed
280
            virtual ~NetAudioBuffer()
281
            {}
sletz's avatar
sletz committed
282

sletz's avatar
sletz committed
283
284
            // needed syze in bytes ofr an entire cycle
            virtual size_t GetCycleSize() = 0;
sletz's avatar
sletz committed
285

sletz's avatar
sletz committed
286
287
            // cycle duration in sec
            virtual float GetCycleDuration() = 0;
sletz's avatar
sletz committed
288

sletz's avatar
sletz committed
289
            virtual int GetNumPackets() = 0;
sletz's avatar
sletz committed
290

291
            //jack<->buffer
sletz's avatar
sletz committed
292
293
            virtual void RenderFromJackPorts() = 0;
            virtual void RenderToJackPorts() = 0;
sletz's avatar
sletz committed
294

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

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

sletz's avatar
sletz committed
302
303
            virtual void SetBuffer(int index, sample_t* buffer) = 0;
            virtual sample_t* GetBuffer(int index) = 0;
304
305
   };

moret's avatar
moret committed
306
307
    /**
    \Brief Audio buffer and operations class
308

moret's avatar
moret committed
309
310
311
312
    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.
313

moret's avatar
moret committed
314
    */
sletz's avatar
sletz committed
315

316
    struct JackPortList {
sletz's avatar
sletz committed
317

sletz's avatar
sletz committed
318
319
        // "[---Header---|--audio data--|--audio data--]..."

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

sletz's avatar
sletz committed
329
        int fLastSubCycle;
sletz's avatar
sletz committed
330

331
332
333
334
        JackPortList(session_params_t* params, uint32_t nports)
        {
            fNPorts = nports;
            fPeriodSize = params->fPeriodSize;
335
336
            fPacketSize = params->fMtu - sizeof(packet_header_t);

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

sletz's avatar
sletz committed
345
            fSubPeriodBytesSize = fSubPeriodSize * sizeof(sample_t);
sletz's avatar
sletz committed
346

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

sletz's avatar
sletz committed
352
            fCycleDuration = float(fSubPeriodSize) / float(params->fSampleRate);
sletz's avatar
sletz committed
353
            fCycleSize = params->fMtu * (fPeriodSize / fSubPeriodSize);
sletz's avatar
sletz committed
354

sletz's avatar
sletz committed
355
356
            fLastSubCycle = -1;
        }
sletz's avatar
sletz committed
357

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

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

sletz's avatar
sletz committed
376
        virtual ~JackPortList()
377
378
379
        {
            delete [] fPortBuffer;
        }
sletz's avatar
sletz committed
380

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

sletz's avatar
sletz committed
386
        sample_t* GetBuffer(int index)
387
388
389
        {
            return fPortBuffer[index];
        }
sletz's avatar
sletz committed
390

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

sletz's avatar
sletz committed
398
        // needed syze in bytes for an entire cycle
sletz's avatar
sletz committed
399
400
401
402
        size_t GetCycleSize()
        {
            return fCycleSize;
        }
sletz's avatar
sletz committed
403

sletz's avatar
sletz committed
404
405
406
407
408
        // cycle duration in sec
        float GetCycleDuration()
        {
            return fCycleDuration;
        }
sletz's avatar
sletz committed
409

410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
    #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
428
429
        virtual void RenderFromJackPorts()
        {}
430

sletz's avatar
sletz committed
431
432
        virtual void RenderToJackPorts()
        {}
sletz's avatar
sletz committed
433

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

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

451
            fLastSubCycle = sub_cycle;
sletz's avatar
sletz committed
452
            return res;
sletz's avatar
sletz committed
453
        }
sletz's avatar
sletz committed
454

sletz's avatar
sletz committed
455
        virtual int RenderToNetwork(char* net_buffer, int sub_cycle, uint32_t& port_num)
sletz's avatar
sletz committed
456
        {
457
            for (int port_index = 0; port_index < fNPorts; port_index++) {
458
                float* src = (float*)(fPortBuffer[port_index] + sub_cycle * fSubPeriodSize);
sletz's avatar
sletz committed
459
460
461
462
463
                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
464

465
            port_num = fNPorts;
sletz's avatar
sletz committed
466
            return fNPorts * fSubPeriodBytesSize;
467
        }
sletz's avatar
sletz committed
468

469
470
    #else

sletz's avatar
sletz committed
471
472
        virtual void RenderFromJackPorts()
        {}
473

sletz's avatar
sletz committed
474
        virtual void RenderToJackPorts()
sletz's avatar
sletz committed
475
        {
sletz's avatar
sletz committed
476
            // reset for next cycle
sletz's avatar
sletz committed
477
478
            fLastSubCycle = -1;
        }
sletz's avatar
sletz committed
479

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

485
486
487
488
489
            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
490
                res = NET_PACKET_ERROR;
sletz's avatar
sletz committed
491
            }
sletz's avatar
sletz committed
492

493
            fLastSubCycle = sub_cycle;
sletz's avatar
sletz committed
494
            return res;
sletz's avatar
sletz committed
495
        }
sletz's avatar
sletz committed
496

sletz's avatar
sletz committed
497
        virtual int RenderToNetwork(char* net_buffer, int sub_cycle, uint32_t& port_num)
sletz's avatar
sletz committed
498
        {
499
500
501
502
            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
503
            return fNPorts * fSubPeriodBytesSize;
504
505
506
        }

    #endif
sletz's avatar
sletz committed
507

508
509
510
511
512
        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
513
            // Default behaviour: all ports are active
514
515
516
            port_num = fNPorts;
        }

517
    };
sletz's avatar
sletz committed
518

519
520
    struct JackOptimizedPortList : JackPortList {

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

524
525
526
527
        JackOptimizedPortList(session_params_t* params, uint32_t nports)
            :JackPortList(params, nports)
        {}

sletz's avatar
sletz committed
528
529
530
        virtual ~JackOptimizedPortList()
        {}

531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
        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
547

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

    #ifdef __BIG_ENDIAN__

        // TODO

    #else

        //network<->buffer
sletz's avatar
sletz committed
562
        virtual int RenderFromNetwork(char* net_buffer, int cycle, int sub_cycle, size_t copy_size, uint32_t port_num)
563
        {
sletz's avatar
sletz committed
564
565
            int res = 0;

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

575
576
577
578
579
580
581
582
583
584
585
            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
586

587
588
589
590
                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);
591
                    if (fPortBuffer[port_index]) {
592
                        memcpy(fPortBuffer[active_port] + sub_cycle * sub_period_size, (char*)(active_port_address + 1), sub_period_bytes_size - sizeof(int));
593
                    }
594
                }
595

596
597
                if (sub_cycle != fLastSubCycle + 1) {
                    jack_error("Packet(s) missing from... %d %d", fLastSubCycle, sub_cycle);
sletz's avatar
sletz committed
598
                    res = NET_PACKET_ERROR;
599
                }
sletz's avatar
sletz committed
600

601
                fLastSubCycle = sub_cycle;
602
            }
sletz's avatar
sletz committed
603
604

            return res;
605
606
        }

sletz's avatar
sletz committed
607
        virtual int RenderToNetwork(char* net_buffer,int sub_cycle, uint32_t& port_num)
608
        {
sletz's avatar
sletz committed
609
            // Init active port count
610
611
612
            port_num = 0;

            for (int port_index = 0; port_index < fNPorts; port_index++) {
sletz's avatar
sletz committed
613
                // Only copy from active ports : write the active port number then audio data
614
615
616
617
618
619
620
621
622
623
624
625
626
                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

627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
        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++) {
653
                // Use -1 when port is actually connected on other side
sletz's avatar
sletz committed
654
655
656
657
658
                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);
                }
659
660
661
662
                active_port_address++;
            }
        }

663
664
    };

sletz's avatar
sletz committed
665
    class SERVER_EXPORT NetFloatAudioBuffer : public NetAudioBuffer
666
    {
667
        private:
sletz's avatar
sletz committed
668

669
670
671
        #ifdef OPTIMIZED_PROTOCOL
            JackOptimizedPortList fPortBuffer;
        #else
672
            JackPortList fPortBuffer;
673
        #endif
674
            char* fNetBuffer;
sletz's avatar
sletz committed
675

676
        public:
sletz's avatar
sletz committed
677

sletz's avatar
sletz committed
678
            NetFloatAudioBuffer(session_params_t* params, uint32_t nports, char* net_buffer);
sletz's avatar
sletz committed
679
            ~NetFloatAudioBuffer();
sletz's avatar
sletz committed
680

sletz's avatar
sletz committed
681
682
            // needed size in bytes for an entire cycle
            size_t GetCycleSize();
sletz's avatar
sletz committed
683

sletz's avatar
sletz committed
684
            // cycle duration in sec
sletz's avatar
sletz committed
685
686
687
688
            float GetCycleDuration()
            {
                return fPortBuffer.GetCycleDuration();
            }
sletz's avatar
sletz committed
689

sletz's avatar
sletz committed
690
691
692
693
            int GetNumPackets()
            {
                return fPortBuffer.GetNumPackets();
            }
sletz's avatar
sletz committed
694

695
            //jack<->buffer
sletz's avatar
sletz committed
696
697
            void RenderFromJackPorts();
            void RenderToJackPorts();
698

sletz's avatar
sletz committed
699
700
            void SetBuffer(int index, sample_t* buffer);
            sample_t* GetBuffer(int index);
sletz's avatar
sletz committed
701

sletz's avatar
sletz committed
702
            //network<->buffer
sletz's avatar
sletz committed
703
            int RenderFromNetwork(int cycle, int sub_cycle, size_t copy_size, uint32_t port_num);
704
705
706
707
            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);
708
    };
sletz's avatar
sletz committed
709

nedko's avatar
nedko committed
710
#if HAVE_CELT
sletz's avatar
sletz committed
711
712
713
714
715
716

#include <celt/celt.h>

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

718
719
720
            CELTMode** fCeltMode;
            CELTEncoder** fCeltEncoder;
            CELTDecoder** fCeltDecoder;
sletz's avatar
sletz committed
721

sletz's avatar
sletz committed
722
723
            int fCompressedSizeByte;
            jack_nframes_t fPeriodSize;
724

sletz's avatar
sletz committed
725
            int fNumPackets;
sletz's avatar
sletz committed
726
727
            float fCycleDuration;   // in sec
            size_t fCycleSize;      // needed size in bytes for an entire cycle
sletz's avatar
sletz committed
728

sletz's avatar
sletz committed
729
730
            size_t fSubPeriodBytesSize;
            size_t fLastSubPeriodBytesSize;
sletz's avatar
sletz committed
731

sletz's avatar
sletz committed
732
733
            sample_t** fPortBuffer;
            char* fNetBuffer;
734
            unsigned char** fCompressedBuffer;
sletz's avatar
sletz committed
735

sletz's avatar
sletz committed
736
737
            int fNPorts;
            int fLastSubCycle;
sletz's avatar
sletz committed
738

sletz's avatar
sletz committed
739
            void FreeCelt();
sletz's avatar
sletz committed
740

sletz's avatar
sletz committed
741
        public:
sletz's avatar
sletz committed
742

743
            NetCeltAudioBuffer(session_params_t* params, uint32_t nports, char* net_buffer, int kbps);
744
            virtual ~NetCeltAudioBuffer();
sletz's avatar
sletz committed
745

sletz's avatar
sletz committed
746
747
            // needed size in bytes for an entire cycle
            size_t GetCycleSize();
sletz's avatar
sletz committed
748

sletz's avatar
sletz committed
749
750
751
             // cycle duration in sec
            float GetCycleDuration();
            int GetNumPackets();
sletz's avatar
sletz committed
752

sletz's avatar
sletz committed
753
754
            void SetBuffer(int index, sample_t* buffer);
            sample_t* GetBuffer(int index);
sletz's avatar
sletz committed
755

sletz's avatar
sletz committed
756
            //jack<->buffer
sletz's avatar
sletz committed
757
758
            void RenderFromJackPorts();
            void RenderToJackPorts();
sletz's avatar
sletz committed
759
760

            //network<->buffer
sletz's avatar
sletz committed
761
            int RenderFromNetwork(int cycle, int sub_cycle, size_t copy_size, uint32_t port_num);
sletz's avatar
sletz committed
762
            int RenderToNetwork(int sub_cycle, uint32_t&  port_num);
sletz's avatar
sletz committed
763
764
765
    };

#endif
sletz's avatar
sletz committed
766
767
768
769

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

sletz's avatar
sletz committed
771
772
            int fCompressedSizeByte;
            jack_nframes_t fPeriodSize;
sletz's avatar
sletz committed
773

sletz's avatar
sletz committed
774
            int fNumPackets;
sletz's avatar
sletz committed
775
776
            float fCycleDuration;   // in sec
            size_t fCycleSize;      // needed size in bytes for an entire cycle
sletz's avatar
sletz committed
777

sletz's avatar
sletz committed
778
779
            size_t fSubPeriodSize;
            size_t fSubPeriodBytesSize;
780
            size_t fLastSubPeriodSize;
sletz's avatar
sletz committed
781
            size_t fLastSubPeriodBytesSize;
sletz's avatar
sletz committed
782

sletz's avatar
sletz committed
783
784
            sample_t** fPortBuffer;
            char* fNetBuffer;
785
            short** fIntBuffer;
sletz's avatar
sletz committed
786

sletz's avatar
sletz committed
787
788
            int fNPorts;
            int fLastSubCycle;
sletz's avatar
sletz committed
789

sletz's avatar
sletz committed
790
        public:
sletz's avatar
sletz committed
791

sletz's avatar
sletz committed
792
            NetIntAudioBuffer(session_params_t* params, uint32_t nports, char* net_buffer);
793
            virtual ~NetIntAudioBuffer();
sletz's avatar
sletz committed
794

sletz's avatar
sletz committed
795
796
            // needed size in bytes for an entire cycle
            size_t GetCycleSize();
sletz's avatar
sletz committed
797

sletz's avatar
sletz committed
798
799
800
             // cycle duration in sec
            float GetCycleDuration();
            int GetNumPackets();
sletz's avatar
sletz committed
801

sletz's avatar
sletz committed
802
803
            void SetBuffer(int index, sample_t* buffer);
            sample_t* GetBuffer(int index);
sletz's avatar
sletz committed
804

sletz's avatar
sletz committed
805
            //jack<->buffer
sletz's avatar
sletz committed
806
807
            void RenderFromJackPorts();
            void RenderToJackPorts();
sletz's avatar
sletz committed
808
809

            //network<->buffer
sletz's avatar
sletz committed
810
            int RenderFromNetwork(int cycle, int sub_cycle, size_t copy_size, uint32_t port_num);
sletz's avatar
sletz committed
811
            int RenderToNetwork(int sub_cycle, uint32_t& port_num);
sletz's avatar
sletz committed
812
813
    };

sletz's avatar
sletz committed
814
    /*
815
    #define AUDIO_BUFFER_SIZE 8
sletz's avatar
sletz committed
816

sletz's avatar
sletz committed
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
849
850
851
852
853
854
855
    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];
        }

    };

856
857
    class SERVER_EXPORT NetBufferedAudioBuffer : public NetAudioBuffer
    {
sletz's avatar
sletz committed
858

859
        private:
860
            char* fNetBuffer;
861
862
863
            JackPortListAllocate fPortBuffer[AUDIO_BUFFER_SIZE];
            sample_t** fJackPortBuffer;
            int fMaxCycle;
sletz's avatar
sletz committed
864

865
        public:
sletz's avatar
sletz committed
866
            NetBufferedAudioBuffer(session_params_t* params, uint32_t nports, char* net_buffer);
867
            ~NetBufferedAudioBuffer();
868

sletz's avatar
sletz committed
869
870
            // needed syze in bytes ofr an entire cycle
            size_t GetCycleSize();
sletz's avatar
sletz committed
871

sletz's avatar
sletz committed
872
873
874
875
876
             // cycle duration in sec
            float GetCycleDuration()
            {
                return fPortBuffer[0].GetCycleDuration();
            }
sletz's avatar
sletz committed
877

878
            //jack<->buffer
sletz's avatar
sletz committed
879
880
            void RenderFromJackPorts(int sub_cycle);
            void RenderToJackPorts(int cycle, int sub_cycle);
sletz's avatar
sletz committed
881
            //void FinishRenderToJackPorts(int cycle);
sletz's avatar
sletz committed
882

sletz's avatar
sletz committed
883
            //network<->buffer
884
            void RenderFromNetwork(int sub_cycle, size_t copy_size)
sletz's avatar
sletz committed
885
            {
sletz's avatar
sletz committed
886
887
                // TODO
            }
888
            int RenderToNetwork(int sub_cycle, size_t total_size)
sletz's avatar
sletz committed
889
            {
sletz's avatar
sletz committed
890
891
892
                // TODO
                return 0;
            }
893

sletz's avatar
sletz committed
894
895
            void SetBuffer(int index, sample_t* buffer);
            sample_t* GetBuffer(int index);
896
    };
sletz's avatar
sletz committed
897
    */
sletz's avatar
sletz committed
898

sletz's avatar
sletz committed
899
    //utility *************************************************************************************
900
901

    //socket API management
902
903
    SERVER_EXPORT int SocketAPIInit();
    SERVER_EXPORT int SocketAPIEnd();
904
    //n<-->h functions
sletz's avatar
sletz committed
905
906
907
908
909
910
911