Allolib  1.0
C++ Components For Interactive Multimedia
al_ParameterServer.hpp
1 #ifndef AL_PARAMETERSERVER_H
2 #define AL_PARAMETERSERVER_H
3 
4 /* Allolib --
5  Multimedia / virtual environment application class library
6 
7  Copyright (C) 2009. AlloSphere Research Group, Media Arts & Technology,
8  UCSB. Copyright (C) 2012-2018. The Regents of the University of California.
9  All rights reserved.
10 
11  Redistribution and use in source and binary forms, with or without
12  modification, are permitted provided that the following conditions are
13  met:
14 
15  Redistributions of source code must retain the above copyright
16  notice, this list of conditions and the following disclaimer.
17 
18  Redistributions in binary form must reproduce the above
19  copyright notice, this list of conditions and the following disclaimer in the
20  documentation and/or other materials provided with the
21  distribution.
22 
23  Neither the name of the University of California nor the names
24  of its contributors may be used to endorse or promote products derived from
25  this software without specific prior written permission.
26 
27  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
28  IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
29  IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
30  PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
31  CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
32  EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
33  PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
34  OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
35  WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
36  OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
37  ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
38 
39  File description:
40  Expose parameters on the network
41  File author(s):
42  AndrĂ©s Cabrera mantaraya36@gmail.com
43 */
44 
45 #include <mutex>
46 
47 #include "al/protocol/al_OSC.hpp"
48 #include "al/ui/al_Parameter.hpp"
49 #include "al/ui/al_ParameterBundle.hpp"
50 
51 namespace al {
52 
53 constexpr int handshakeServerPort = 16987;
54 constexpr int listenerFirstPort = 14000;
55 
56 class ParameterServer;
57 
58 class OSCNode {
59 public:
60  OSCNode() {
61  mCommandHandler.node = this;
62 
63  mNetworkListener.appendHandler(mCommandHandler);
64  }
65 
66  void startCommandListener(std::string address = "0.0.0.0");
67 
68  virtual void runCommand(osc::Message &m) = 0;
69 
70  void registerServerHandler(osc::PacketHandler *handler);
71 
72 private:
73  class CommandHandler : public osc::PacketHandler {
74  public:
75  OSCNode *node;
76  virtual void onMessage(osc::Message &m) override {
77  std::cout << "command handler got" << std::endl;
78  m.print();
79  node->runCommand(m);
80  }
81  } mCommandHandler;
82  osc::Recv mNetworkListener;
83 };
84 
85 class OSCNotifier {
86 public:
87  OSCNotifier();
88  virtual ~OSCNotifier();
89 
95  virtual void addListener(std::string IPaddress, uint16_t oscPort) {
96  auto newListenerSocket = new osc::Send;
97 
98  if (newListenerSocket->open(oscPort, IPaddress.c_str())) {
99  mListenerLock.lock();
100  mOSCSenders.push_back(newListenerSocket);
101  mListenerLock.unlock();
102  // std::cout << "Registered listener " << IPaddress << ":"
103  //<< oscPort<< std::endl;
104  } else {
105  delete newListenerSocket;
106  std::cerr << "ERROR: Could not register listener " << IPaddress << ":"
107  << oscPort << std::endl;
108  }
109  }
110 
123  void notifyListeners(std::string OSCaddress, float value,
124  ValueSource *src = nullptr);
125  void notifyListeners(std::string OSCaddress, int value,
126  ValueSource *src = nullptr);
127  void notifyListeners(std::string OSCaddress, std::string value,
128  ValueSource *src = nullptr);
129  void notifyListeners(std::string OSCaddress, Vec3f value,
130  ValueSource *src = nullptr);
131  void notifyListeners(std::string OSCaddress, Vec4f value,
132  ValueSource *src = nullptr);
133  void notifyListeners(std::string OSCaddress, Pose value,
134  ValueSource *src = nullptr);
135  void notifyListeners(std::string OSCaddress, Color value,
136  ValueSource *src = nullptr);
137 
138  void notifyListeners(std::string OSCaddress, ParameterMeta *param,
139  ValueSource *src);
140 
141  void send(osc::Packet &p) {
142  mListenerLock.lock();
143  for (osc::Send *sender : mOSCSenders) {
144  sender->send(p);
145  // std::cout << "Notifying " << sender->address() << ":" <<
146  // sender->port()
147  // << std::endl;
148  }
149  mListenerLock.unlock();
150  }
151  void startHandshakeServer(std::string address = "0.0.0.0");
152 
153  void appendCommandHandler(osc::PacketHandler &handler) {
154  mHandshakeServer.appendHandler(handler);
155  }
156 
157 protected:
158  std::mutex mListenerLock;
159  std::vector<osc::Send *> mOSCSenders;
160  std::vector<std::pair<std::string, int>> mConnectedNodes;
161 
163  public:
164  OSCNotifier *notifier;
165  ParameterServer *mParameterServer;
166  virtual void onMessage(osc::Message &m) override;
167  } mHandshakeHandler;
168 
169  osc::Recv mHandshakeServer;
170 
171  std::vector<std::pair<std::string, uint16_t>> mNodes;
172  std::mutex mNodeLock;
173 
174 private:
175 };
176 
187  public OSCNotifier,
188  public OSCNode {
189  friend class PresetServer; // To be able to take over the OSC server
190 public:
206  // ParameterServer() : mServer(nullptr) {};
207  ParameterServer(std::string oscAddress = "", int oscPort = 9010,
208  bool autoStart = true);
209  ~ParameterServer();
210 
215  void configure(uint16_t port, std::string addr = "") {
216  mOscPort = port;
217  mOscAddress = addr;
218  }
222  bool listen(int oscPort = -1, std::string oscAddress = "");
223 
228 
233 
238 
245  void print(std::ostream &stream = std::cout);
246 
252  void stopServer();
253 
254  bool serverRunning();
255 
259  std::vector<Parameter *> parameters();
260  std::vector<ParameterString *> stringParameters();
261  std::vector<ParameterVec3 *> vec3Parameters();
262  std::vector<ParameterVec4 *> vec4Parameters();
263  std::vector<ParameterPose *> poseParameters();
264 
266  template <class ParameterType>
267  ParameterServer &operator<<(ParameterType &newParam) {
268  return registerParameter(newParam);
269  }
270 
272  template <class ParameterType>
273  ParameterServer &operator<<(ParameterType *newParam) {
274  return registerParameter(*newParam);
275  }
276 
279  return registerParameterBundle(bundle);
280  }
281 
290 
291  void clearOSCListeners() { mPacketHandlers.clear(); }
292 
293  void registerOSCConsumer(osc::MessageConsumer *consumer,
294  std::string rootPath = "");
295 
296  void notifyAll();
297 
305  void sendAllParameters(std::string IPaddress, int oscPort);
306 
307  void sendParameterDetails(std::string IPaddress, int oscPort);
308 
309  void requestAllParameters(std::string IPaddress, int oscPort);
310 
311  virtual void onMessage(osc::Message &m) override;
312 
313  uint16_t serverPort() { return mServer->port(); }
314 
315  void verbose(bool verbose = true) { mVerbose = verbose; }
316  static bool setParameterValueFromMessage(ParameterMeta *param,
317  std::string address,
318  osc::Message &m);
319 
320  virtual void runCommand(osc::Message &m) override;
321 
322 protected:
323  static void changeCallback(float value, void *sender, void *userData,
324  void *blockThis);
325  static void changeStringCallback(std::string value, void *sender,
326  void *userData, void *blockThis);
327  static void changeVec3Callback(Vec3f value, void *sender, void *userData,
328  void *blockThis);
329  static void changeVec4Callback(Vec4f value, void *sender, void *userData,
330  void *blockThis);
331  static void changePoseCallback(Pose value, void *sender, void *userData,
332  void *blockThis);
333 
334  void printParameterInfo(ParameterMeta *p);
335 
336  void printBundleInfo(ParameterBundle *bundle, std::string id, int depth = 0);
337 
338  void setValuesForBundleGroup(osc::Message &m,
339  std::vector<ParameterBundle *> bundleGroup,
340  std::string rootAddress);
341 
342  std::vector<std::pair<std::string, uint16_t>>
343  mNotifiers; // List of primary nodes
344 
345  std::vector<osc::PacketHandler *> mPacketHandlers;
346  std::vector<std::pair<osc::MessageConsumer *, std::string>> mMessageConsumers;
347  osc::Recv *mServer;
348  std::mutex mServerLock;
349 
350  std::vector<ParameterMeta *> mParameters;
351  std::map<std::string, std::vector<ParameterBundle *>> mParameterBundles;
352  std::map<std::string, int> mCurrentActiveBundle;
353  std::mutex mParameterLock;
354 
355  std::string mOscAddress;
356  int mOscPort;
357 
358  bool mVerbose{false};
359 };
360 
361 } // namespace al
362 
363 #endif // AL_PARAMETERSERVER_H
virtual void onMessage(osc::Message &m) override
Called for each message contained in packet.
void notifyListeners(std::string OSCaddress, float value, ValueSource *src=nullptr)
Notify the listeners of value changes.
virtual void addListener(std::string IPaddress, uint16_t oscPort)
addListener enables notifiying via OSC that a preset has changed
The ParameterMeta class defines the base interface for Parameter metadata.
The ParameterServer class creates an OSC server to receive parameter values.
ParameterServer & registerParameterBundle(ParameterBundle &bundle)
ParameterServer & operator<<(ParameterType &newParam)
Register parameter using the streaming operator.
ParameterServer & registerParameter(ParameterMeta &param)
void configure(uint16_t port, std::string addr="")
Set cached configuration. These values are used if listen() is called without arguments.
void stopServer()
stopServer stops the OSC server thread. Calling this function is sometimes required when this object ...
std::vector< Parameter * > parameters()
Get the list of registered parameters.
virtual void onMessage(osc::Message &m) override
Called for each message contained in packet.
bool listen(int oscPort=-1, std::string oscAddress="")
void print(std::ostream &stream=std::cout)
print prints information about the server to std::out
void registerOSCListener(osc::PacketHandler *handler)
Append a listener to the osc server.
ParameterServer & operator<<(ParameterBundle &bundle)
Register parameter bundle using the streaming operator.
void sendAllParameters(std::string IPaddress, int oscPort)
send all currently regeistered parameter values
ParameterServer & operator<<(ParameterType *newParam)
Register parameter using the streaming operator.
ParameterServer(std::string oscAddress="", int oscPort=9010, bool autoStart=true)
ParameterServer constructor.
void unregisterParameter(ParameterMeta &param)
A local coordinate frame.
Definition: al_Pose.hpp:63
void print() const
Pretty-print message information.
Socket for receiving OSC packets.
Definition: al_OSC.hpp:399
Recv & appendHandler(PacketHandler &v)
Add a packet handler to list. All handlers get all messages.
Definition: al_OSC.hpp:438
Definition: al_App.hpp:23
Vec< 4, float > Vec4f
float 4-vector
Definition: al_Vec.hpp:62
Vec< 3, float > Vec3f
float 3-vector
Definition: al_Vec.hpp:59