1 /*
2
3 Faust Project
4
5 Copyright (C) 2012-2014 Grame
6
7 This library is free software; you can redistribute it and/or
8 modify it under the terms of the GNU Lesser General Public
9 License as published by the Free Software Foundation; either
10 version 2.1 of the License, or (at your option) any later version.
11
12 This library is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 Lesser General Public License for more details.
16
17 You should have received a copy of the GNU Lesser General Public
18 License along with this library; if not, write to the Free Software
19 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20
21 Grame Research Laboratory, 11 cours de Verdun Gensoul, 69002 Lyon - France
22 research@grame.fr
23
24 */
25 #ifdef _WIN32
26 #include <winsock2.h>
27 #else
28 #include <netdb.h>
29 #include <unistd.h>
30 #endif
31
32 #include <stdlib.h>
33 #include <iostream>
34 #include <sstream>
35
36 #include "HTTPDControler.h"
37 #include "FaustFactory.h"
38 #include "HTTPDSetup.h"
39 #include "jsonfactory.h"
40 #include "htmlfactory.h"
41 #include "RootNode.h"
42
43 using namespace std;
44
45 namespace httpdfaust
46 {
47
48 #define kVersion 0.73f
49 #define kVersionStr "0.73"
50
51 static const char* kPortOpt = "-port";
52
53 //--------------------------------------------------------------------------
54 // utility for command line arguments
55 //--------------------------------------------------------------------------
getPortOption(int argc,char * argv[],const string & option,int defaultValue)56 static int getPortOption(int argc, char* argv[], const string& option, int defaultValue)
57 {
58 for (int i = 0; i < argc-1; i++) {
59 if (option == argv[i]) {
60 int val = strtol( argv[i+1], 0, 10);
61 if (val) return val;
62 }
63 }
64 return defaultValue;
65 }
66
67 //--------------------------------------------------------------------------
68 // utility for host name and ip address
69 //--------------------------------------------------------------------------
getNetInfos(string & name,string & ip)70 static bool getNetInfos(string& name, string& ip)
71 {
72 char szBuffer[1024];
73
74 if (gethostname(szBuffer, sizeof(szBuffer)))
75 return false;
76
77 name = szBuffer;
78 struct hostent *host = gethostbyname(szBuffer);
79 if (!host) return false;
80
81 stringstream s;
82 unsigned char * ptr = (unsigned char*)host->h_addr;
83 s << int(ptr[0]) << "." << int(ptr[1]) << "." << int(ptr[2]) << "." << int(ptr[3]);
84 ip = s.str();
85 return true;
86 }
87
88
89 //--------------------------------------------------------------------------
HTTPDControler(int argc,char * argv[],const char * applicationname,bool init)90 HTTPDControler::HTTPDControler(int argc, char* argv[], const char* applicationname, bool init)
91 : fTCPPort(kTCPBasePort), fJson(0), fInit(init)
92 {
93 fTCPPort = getPortOption(argc, argv, kPortOpt, fTCPPort);
94 fFactory = new FaustFactory();
95 fHttpd = new HTTPDSetup();
96
97 string host, ip;
98 getNetInfos (host, ip);
99 if (host.find('.') == string::npos) host.clear(); // ignore non qualifed domain names and uses IP number
100 const char* hostname = host.size() ? host.c_str() : (ip.size() ? ip.c_str() : "localhost");
101 fJson = new jsonfactory(applicationname, hostname, fTCPPort);
102 fHtml = new htmlfactory(applicationname, hostname, fTCPPort);
103 }
104
~HTTPDControler()105 HTTPDControler::~HTTPDControler()
106 {
107 stop();
108 delete fFactory;
109 delete fHttpd;
110 delete fJson;
111 }
112
113 //--------------------------------------------------------------------------
version()114 float HTTPDControler::version() { return kVersion; }
versionstr()115 const char* HTTPDControler::versionstr() { return kVersionStr; }
116
117 //--------------------------------------------------------------------------
118 // Add a node in the current group (top of the group stack)
addnode(const char * type,const char * label,float * zone,float init,float min,float max,float step)119 template<> void HTTPDControler::addnode<float>(const char* type, const char* label, float* zone, float init, float min, float max, float step)
120 {
121 fFactory->addnode(label, zone, init, min, max, fInit);
122 fJson->addnode<float>(type, label, init, min, max, step, fCurrentMeta);
123 fHtml->addnode(type, label, init, min, max, step);
124 fCurrentMeta.clear();
125 }
addnode(const char * type,const char * label,float * zone,float min,float max)126 template<> void HTTPDControler::addnode<float>(const char* type, const char* label, float* zone, float min, float max)
127 {
128 fFactory->addnode(label, zone, min, max, fInit);
129 fJson->addnode<float>(type, label, min, max, fCurrentMeta);
130 fHtml->addnode(type, label, min, max);
131 fCurrentMeta.clear();
132 }
addnode(const char * type,const char * label,float * zone)133 template<> void HTTPDControler::addnode<float>(const char* type, const char* label, float* zone)
134 {
135 fFactory->addnode(label, zone, 0.f, 0.f, 1.f, fInit);
136 fJson->addnode<float>(type, label, fCurrentMeta);
137 fHtml->addnode(type, label);
138 fCurrentMeta.clear();
139 }
140
addnode(const char * type,const char * label,double * zone,double min,double max)141 template<> void HTTPDControler::addnode<double>(const char* type, const char* label, double* zone, double min, double max)
142 {
143 fFactory->addnode(label, zone, min, max, fInit);
144 fJson->addnode<double>(type, label, min, max, fCurrentMeta);
145 fHtml->addnode(type, label, float(min), float(max));
146 fCurrentMeta.clear();
147 }
148
addnode(const char * type,const char * label,double * zone,double init,double min,double max,double step)149 template<> void HTTPDControler::addnode<double>(const char* type, const char* label, double* zone, double init, double min, double max, double step)
150 {
151 fFactory->addnode(label, zone, init, min, max, fInit);
152 fJson->addnode<double>(type, label, init, min, max, step, fCurrentMeta);
153 fHtml->addnode(type, label, float(init), float(min), float(max), float(step));
154 fCurrentMeta.clear();
155 }
addnode(const char * type,const char * label,double * zone)156 template<> void HTTPDControler::addnode<double>(const char* type, const char* label, double* zone)
157 {
158 fFactory->addnode(label, zone, 0., 0., 1., fInit);
159 fJson->addnode<double>(type, label, fCurrentMeta);
160 fHtml->addnode(type, label);
161 fCurrentMeta.clear();
162 }
163
164 //--------------------------------------------------------------------------
opengroup(const char * type,const char * label)165 void HTTPDControler::opengroup(const char* type, const char* label)
166 {
167 fFactory->opengroup(label);
168 fJson->opengroup(type, label, fCurrentMeta);
169 fHtml->opengroup(type, label);
170 fCurrentMeta.clear();
171 }
172
173 //--------------------------------------------------------------------------
closegroup()174 void HTTPDControler::closegroup ()
175 {
176 fFactory->closegroup();
177 fJson->closegroup();
178 fHtml->closegroup();
179 }
180
181 //--------------------------------------------------------------------------
182 // start the network services
run()183 void HTTPDControler::run()
184 {
185 SMessageDriven root = fFactory->root(); // first get the root node
186 if (root) {
187 // and cast it to a RootNode
188 RootNode * rootnode = dynamic_cast<RootNode*>((MessageDriven*)root);
189 // starts the network services
190 if (fHttpd->start(root, fTCPPort)) {
191 fJson->root().setPort(fTCPPort);
192 string json = fJson->root().json(); // fJson->root().json(true); to 'flatten' JSON
193 if (rootnode) rootnode->setJSON(json);
194 stringstream strhtml;
195 fHtml->root().setPort(fTCPPort);
196 fHtml->root().print(strhtml, json);
197 if (rootnode) rootnode->setHtml(strhtml.str());
198 // and outputs a message
199 cout << "Faust httpd server version " << version() << " is running on TCP port " << fTCPPort << endl;
200 }
201 }
202 }
203
204 //--------------------------------------------------------------------------
stop()205 void HTTPDControler::stop()
206 {
207 fHttpd->stop();
208 }
209
210 //------------------------------Accessor to json Interface
getJSON()211 string HTTPDControler::getJSON()
212 {
213 return fJson->root().json();
214 }
215
setInputs(int numInputs)216 void HTTPDControler::setInputs(int numInputs)
217 {
218 fJson->root().setInputs(numInputs);
219 }
220
setOutputs(int numOutputs)221 void HTTPDControler::setOutputs(int numOutputs)
222 {
223 fJson->root().setOutputs(numOutputs);
224 }
225
226 }
227