File: remote_server.h

package info (click to toggle)
faust 2.81.10%2Bds-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 431,496 kB
  • sloc: cpp: 283,941; ansic: 116,215; javascript: 18,529; sh: 14,356; vhdl: 14,052; java: 5,900; python: 5,091; objc: 3,852; makefile: 2,725; cs: 1,672; lisp: 1,146; ruby: 954; yacc: 586; xml: 471; lex: 247; awk: 111; tcl: 26
file content (407 lines) | stat: -rwxr-xr-x 12,656 bytes parent folder | download | duplicates (4)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
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
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
/************************************************************************
 ************************************************************************
 FAUST compiler
 Copyright (C) 2003-2015 GRAME, Centre National de Creation Musicale
 ---------------------------------------------------------------------
 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.
 ************************************************************************
 ************************************************************************/

#ifndef _SERVER_h
#define _SERVER_h

#include <sstream>
#include <iostream>
#include <fstream>
#include <fcntl.h>
#include <stdlib.h>
#include <list>
#include <map>
#include <vector>
#include <set>
#include <microhttpd.h>
#include <netdb.h>
#include <arpa/inet.h>

#define LLVM_DSP 1
/*
 #define OSCCTRL 1
 #define HTTPCTRL 1
 #define MIDICTRL 1
 #define NETJACK 1
 */

#ifdef LLVM_DSP_FACTORY
#include "faust/dsp/llvm-dsp.h"
#else
#include "faust/dsp/interpreter-dsp.h"
#endif

#include "faust/audio/audio.h"

#ifdef OSCCTRL
#include "faust/gui/OSCUI.h"
#endif

#ifdef HTTPCTRL
#include "faust/gui/httpdUI.h"
#endif

#ifdef MIDICTRL
#include "faust/gui/MidiUI.h"
#endif

#include "TMutex.h"

#define POSTBUFFERSIZE 512
#define GET 0
#define POST 1

#ifdef WIN32
#define    EXPORT __declspec(dllexport)
#else
#define    EXPORT __attribute__ ((visibility("default")))
#endif

using namespace std;

typedef bool (*createFactoryDSPCallback) (dsp_factory* factory, void* arg);
typedef bool (*createInstanceDSPCallback) (dsp* dsp, void* arg);
typedef bool (*deleteFactoryDSPCallback) (dsp_factory* factory, void* arg);
typedef bool (*deleteInstanceDSPCallback) (dsp* dsp, void* arg);

/*
 TODO :
 
 - possibly return 'machine code' to client side?
 - better define where the DSP instance and the audio driver is going to run (server or client side)
 
 */

// Structure wrapping llvm_dsp with all its needed elements (audio/interface/...)

class audio_dsp {
    
    protected:
    
        string fInstanceKey;
        string fName;
    
        dsp* fDSP;          // DSP Instance
        audio* fAudio;      // Audio driver
    
    #ifdef OSCCTRL
        OSCUI* fOSCUI;      // OSC controler
    #endif
    
    #ifdef HTTPCTRL
        httpdUI* fHttpdUI;  // Httpd controler
    #endif
    
    #ifdef MIDICTRL
        MidiUI* fMidiUI;    // MIDIcontroler
    #endif
    
        createInstanceDSPCallback fCreateDSPInstanceCb;
        void* fCreateDSPInstanceCb_arg;
    
        deleteInstanceDSPCallback fDeleteDSPInstanceCb;
        void* fDeleteDSPInstanceCb_arg;
    
    public:
    
        audio_dsp(dsp_factory* factory,
                  bool poly, int voices, bool group,
                  bool osc, bool httpd, bool midi,
                  const string& name, const string& key,
                  createInstanceDSPCallback cb1, void* cb1_arg,
                  deleteInstanceDSPCallback cb2, void* cb2_arg);
        virtual ~audio_dsp();
    
        virtual bool init(int sr, int bs);
    
        virtual bool start()
        {
            return fAudio->start();
        }
        void stop()
        {
            fAudio->stop();
        }
    
        virtual bool isActive() { return true; }
    
        string  getKey() { return fInstanceKey; }
        void    setKey(const string& key) { fInstanceKey = key; }
        string  getName() { return fName; }
        void    setName(string name) { fName = name; }
    
};

// Structure handled by libmicrohttp related to a connection

enum {
    ERROR_FACTORY_NOTFOUND,
    ERROR_INSTANCE_NOTCREATED,
    ERROR_INSTANCE_NOTFOUND
};


typedef set<dsp_factory*> FactoryTable;  // TO CHECK
#define FactoryTableIt FactoryTable::iterator

class DSPServer;

struct dsp_server_connection_info {
    
    int fAnswercode;    // internally used by libmicrohttpd to see where things went wrong or right
    
    string fAnswer;     // the answer sent to the user after upload
    
    string fAudioType;  // audio driver type
    
    //-----DATAS RECEIVED TO CREATE NEW DSP FACTORY---------
    string fNameApp;
    string fFaustCode;
    string fTarget;
    vector<string> fCompilationOptions;
    string fOptLevel;
    
    //------DATAS RECEIVED TO CREATE NEW NetJack DSP INSTANCE-------
    string fIP;
    string fPort;
    string fCompression;
    string fMTU;
    string fLatency;
    string fSHAKey;
    string fInstanceKey;
    
    //------DATAS RECEIVED TO CREATE POLYPOHONIC -------
    string fPoly;
    string fVoices;
    string fGroup;
    
    //------DATAS RECEIVED TO CREATE NEW local Audio INSTANCE-------
    string fSampleRate;
    string fBufferSize;
    string fOSC;
    string fHTTPD;
    string fMIDI;
    
    dsp_server_connection_info();
    virtual ~dsp_server_connection_info() {}
    
    void getJson(dsp_factory* factory);
    bool getFactoryFromSHAKey(DSPServer* server);
    
    int iteratePost(const char* key, const char* data, size_t size);
    
    dsp_factory* createFactory(DSPServer* server, string& error);
    dsp_factory* crossCompileFactory(DSPServer* server, string& error);
    
    virtual int postProcess(const char* upload_data, size_t* upload_data_size)
    {
        return MHD_NO;
    }
    
};

struct dsp_server_connection_info_post : public dsp_server_connection_info {
    
    MHD_PostProcessor* fPostprocessor;     // the POST processor used internally by libmicrohttpd
    
    dsp_server_connection_info_post(MHD_Connection* connection);
    
    virtual ~dsp_server_connection_info_post()
    {
        MHD_destroy_post_processor(fPostprocessor);
    }
    
    int postProcess(const char* upload_data, size_t* upload_data_size)
    {
        MHD_post_process(fPostprocessor, upload_data, *upload_data_size);
        *upload_data_size = 0;
        return MHD_YES;
    }
};

struct dsp_server_connection_info_get : public dsp_server_connection_info  {
    
    dsp_server_connection_info_get():dsp_server_connection_info()
    {}
};

// Same prototype LLVM/REMOTE DSP are using for allocation/desallocation

class DSPServer {
    
        friend struct dsp_server_connection_info_post;
        friend struct dsp_server_connection_info;
    
    private:
    
        createFactoryDSPCallback fCreateDSPFactoryCb;
        void* fCreateDSPFactoryCb_arg;
    
        deleteFactoryDSPCallback fDeleteDSPFactoryCb;
        void* fDeleteDSPFactoryCb_arg;
    
        createInstanceDSPCallback fCreateDSPInstanceCb;
        void* fCreateDSPInstanceCb_arg;
    
        deleteInstanceDSPCallback fDeleteDSPInstanceCb;
        void* fDeleteDSPInstanceCb_arg;
    
        TMutex fLocker;
        pthread_t fThread;
        int fPort;
    
        // Factories that can be instanciated.
        // The remote client asking for a new DSP Instance has to send an SHA key corresponding to an existing factory
        FactoryTable fFactories;
    
        // List of currently running DSP. Use to keep track of Audio that would have lost their connection
        list<audio_dsp*> fRunningDsp;
        MHD_Daemon* fDaemon;    // Running http daemon
    
        void open(audio_dsp* dsp);
    
        // Creates the html to send back
        int sendPage(MHD_Connection* connection, const string& page, int status_code, const string& type);
    
        void stopNotActiveDSP();
    
        // Reaction to a GET request
        int answerGet(MHD_Connection* connection, const char* url);
    
        // Reaction to a POST request
        int answerPost(MHD_Connection* connection, const char* url,
                       const char* upload_data, size_t* upload_data_size,
                       void** con_cls);
    
        // Reaction to a /CreateInstance request --> Creates llvm_dsp_instance & NetJack slave
        bool createInstance(dsp_server_connection_info* con_info);
    
        // Reaction to a /Delete request --> stops NetJack slave and delete object
        bool deleteInstance(const string& instance_key);
    
        int createConnection(MHD_Connection* connection, const char* method, void** con_cls);
    
        bool start(const string& instance_key);
        bool stop(const string& instance_key);
    
        bool getAvailableFactories(MHD_Connection* connection);
    
        bool getFactoryFromSHAKey(MHD_Connection* connection, dsp_server_connection_info* info);
        bool createFactory(MHD_Connection* connection, dsp_server_connection_info* info);
    
        bool createInstance(MHD_Connection* connection, dsp_server_connection_info* info);
        bool deleteInstance(MHD_Connection* connection, dsp_server_connection_info* info);
    
        bool start(MHD_Connection* connection, dsp_server_connection_info* info);
        bool stop(MHD_Connection* connection, dsp_server_connection_info* info);
    
        bool crossCompileFactory(MHD_Connection* connection, dsp_server_connection_info* info);
    
        bool deleteFactory(MHD_Connection* connection, dsp_server_connection_info* info);
    
        // Register Service as available
        static void* registration(void* arg);
    
        // Callback of another thread to wait netjack audio connection without blocking the server
        static void* open(void* arg);
    
        // Callback that processes the data send to the server
        static int iteratePost(void* coninfo_cls, MHD_ValueKind kind, const char* key,
                               const char* filename, const char* content_type,
                               const char* transfer_encoding, const char* data,
                               uint64_t off, size_t size);
    
        static void requestCompleted(void* cls, MHD_Connection* connection, void** con_cls, MHD_RequestTerminationCode toe);
    
        // Reaction to any kind of connection to the Server
        static int answerToConnection(void* cls, MHD_Connection* connection,
                                      const char* url, const char* method,
                                      const char* version, const char* upload_data,
                                      size_t* upload_data_size, void** con_cls);
    
    public:
    
        DSPServer(int argc, const char* argv[]);
        virtual ~DSPServer();
    
        // Start server on specified port
        bool start(int port = 7777);
        void stop();
    
        void setCreateDSPFactoryCallback(createFactoryDSPCallback callback, void* callback_arg)
        {
            fCreateDSPFactoryCb = callback;
            fCreateDSPFactoryCb_arg = callback_arg;
        }
        void setDeleteDSPFactoryCallback(deleteFactoryDSPCallback callback, void* callback_arg)
        {
            fDeleteDSPFactoryCb = callback;
            fDeleteDSPFactoryCb_arg = callback_arg;
        }
    
        void setCreateDSPInstanceCallback(createInstanceDSPCallback callback, void* callback_arg)
        {
            fCreateDSPInstanceCb = callback;
            fCreateDSPInstanceCb_arg = callback_arg;
        }
        void setDeleteDSPInstanceCallback(deleteInstanceDSPCallback callback, void* callback_arg)
        {
            fDeleteDSPInstanceCb = callback;
            fDeleteDSPInstanceCb_arg = callback_arg;
        }
    
};

// Helper class

struct AudioStarter {
    
    DSPServer* fServer;
    audio_dsp* fDSP;
    
    AudioStarter(DSPServer* server, audio_dsp* dsp):fServer(server),fDSP(dsp)
    {}
    
};

// Public C++ API

class EXPORT remote_dsp_server {
    
    public:
    
        bool start(int port = 7777);
        void stop();
    
        void setCreateDSPFactoryCallback(createFactoryDSPCallback callback, void* callback_arg);
        void setDeleteDSPFactoryCallback(deleteFactoryDSPCallback callback, void* callback_arg);
    
        void setCreateDSPInstanceCallback(createInstanceDSPCallback callback, void* callback_arg);
        void setDeleteDSPInstanceCallback(deleteInstanceDSPCallback callback, void* callback_arg);
    
};

EXPORT remote_dsp_server* createRemoteDSPServer(int argc, const char* argv[]);

EXPORT void deleteRemoteDSPServer(remote_dsp_server* compiler);

#endif