Open Lighting Architecture
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
OSCNode.h
1 /*
2  * This program is free software; you can redistribute it and/or modify
3  * it under the terms of the GNU General Public License as published by
4  * the Free Software Foundation; either version 2 of the License, or
5  * (at your option) any later version.
6  *
7  * This program is distributed in the hope that it will be useful,
8  * but WITHOUT ANY WARRANTY; without even the implied warranty of
9  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10  * GNU Library General Public License for more details.
11  *
12  * You should have received a copy of the GNU General Public License
13  * along with this program; if not, write to the Free Software
14  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
15  *
16  * OSCNode.h
17  * A DMX orientated, C++ wrapper around liblo.
18  * Copyright (C) 2012 Simon Newton
19  */
20 
21 #ifndef PLUGINS_OSC_OSCNODE_H_
22 #define PLUGINS_OSC_OSCNODE_H_
23 
24 #include <lo/lo.h>
25 #include <ola/DmxBuffer.h>
26 #include <ola/ExportMap.h>
27 #include <ola/io/Descriptor.h>
28 #include <ola/io/SelectServerInterface.h>
29 #include <ola/network/SocketAddress.h>
30 #include <stdint.h>
31 #include <map>
32 #include <memory>
33 #include <string>
34 #include <vector>
35 #include "plugins/osc/OSCTarget.h"
36 
37 namespace ola {
38 namespace plugin {
39 namespace osc {
40 
41 using ola::ExportMap;
44 using std::auto_ptr;
45 using std::map;
46 using std::string;
47 using std::vector;
48 
77 class OSCNode {
78  public:
79  // The different data formats we can send in.
80  enum DataFormat {
81  FORMAT_BLOB,
82  FORMAT_INT_ARRAY,
83  FORMAT_INT_INDIVIDUAL,
84  FORMAT_FLOAT_ARRAY,
85  FORMAT_FLOAT_INDIVIDUAL,
86  };
87 
88  // The options for the OSCNode object.
89  struct OSCNodeOptions {
90  uint16_t listen_port; // UDP port to listen on
91 
92  OSCNodeOptions() : listen_port(DEFAULT_OSC_PORT) {}
93  };
94 
95  // The callback run when we receive new DMX data.
97 
99  ExportMap *export_map,
100  const OSCNodeOptions &options);
101  ~OSCNode();
102 
103  bool Init();
104  void Stop();
105 
106  // Sending methods
107  void AddTarget(unsigned int group, const OSCTarget &target);
108  bool RemoveTarget(unsigned int group, const OSCTarget &target);
109  bool SendData(unsigned int group, DataFormat data_format,
110  const ola::DmxBuffer &data);
111 
112  // Receiving methods
113  bool RegisterAddress(const string &osc_address, DMXCallback *callback);
114 
115  // Called by the liblo handlers.
116  void SetUniverse(const string &osc_address, const uint8_t *data,
117  unsigned int size);
118  void SetSlot(const string &osc_address, uint16_t slot, uint8_t value);
119 
120  // The port OSC is listening on.
121  uint16_t ListeningPort() const;
122 
123  private:
124  class NodeOSCTarget {
125  public:
126  explicit NodeOSCTarget(const OSCTarget &target);
127  ~NodeOSCTarget();
128 
129  bool operator==(const NodeOSCTarget &other) const {
130  return (socket_address == other.socket_address &&
131  osc_address == other.osc_address);
132  }
133 
134  bool operator==(const OSCTarget &other) const {
135  return (socket_address == other.socket_address &&
136  osc_address == other.osc_address);
137  }
138 
139  IPV4SocketAddress socket_address;
140  string osc_address;
141  lo_address liblo_address;
142 
143  private:
144  NodeOSCTarget(const NodeOSCTarget&);
145  NodeOSCTarget& operator=(const NodeOSCTarget&);
146  };
147 
148  typedef vector<NodeOSCTarget*> OSCTargetVector;
149 
150  struct OSCOutputGroup {
151  OSCTargetVector targets;
152  DmxBuffer dmx; // holds the last values.
153  };
154 
155  struct OSCInputGroup {
156  explicit OSCInputGroup(DMXCallback *callback) : callback(callback) {}
157 
158  DmxBuffer dmx;
159  auto_ptr<DMXCallback> callback;
160  };
161 
162  typedef map<unsigned int, OSCOutputGroup*> OutputGroupMap;
163  typedef map<string, OSCInputGroup*> InputUniverseMap;
164 
165  struct SlotMessage {
166  unsigned int slot;
167  lo_message message;
168  };
169 
170  SelectServerInterface *m_ss;
171  const uint16_t m_listen_port;
172  auto_ptr<ola::io::UnmanagedFileDescriptor> m_descriptor;
173  lo_server m_osc_server;
174  OutputGroupMap m_output_map;
175  InputUniverseMap m_input_map;
176 
177  void DescriptorReady();
178  bool SendBlob(const DmxBuffer &data, const OSCTargetVector &targets);
179  bool SendIndividualFloats(const DmxBuffer &data,
180  OSCOutputGroup *group);
181  bool SendIndividualInts(const DmxBuffer &data,
182  OSCOutputGroup *group);
183  bool SendIntArray(const DmxBuffer &data,
184  const OSCTargetVector &targets);
185  bool SendFloatArray(const DmxBuffer &data,
186  const OSCTargetVector &targets);
187  bool SendMessageToTargets(lo_message message,
188  const OSCTargetVector &targets);
189  bool SendIndividualMessages(const DmxBuffer &data,
190  OSCOutputGroup *group,
191  const string &osc_type);
192 
193  static const uint16_t DEFAULT_OSC_PORT = 7770;
194  static const char OSC_PORT_VARIABLE[];
195 };
196 } // namespace osc
197 } // namespace plugin
198 } // namespace ola
199 #endif // PLUGINS_OSC_OSCNODE_H_