Jamoma API  0.6.0.a19
TTOscSocket.cpp
1 /*
2  * Jamoma OSC Receiver
3  * Copyright © 2011, Théo de la Hogue
4  *
5  * License: This code is licensed under the terms of the "New BSD License"
6  * http://creativecommons.org/licenses/BSD/
7  */
8 
9 #include "TTOscSocket.h"
10 #include <thread>
11 #include <chrono>
12 TTPtr TTOscSocketListenerCreate(TTPtr anArgument)
13 {
14  TTOscSocketPtr anOscSocket = (TTOscSocketPtr) anArgument;
15 
16  try
17  {
18  anOscSocket->mSocketListener = new UdpListeningReceiveSocket(IpEndpointName(IpEndpointName::ANY_ADDRESS, anOscSocket->mPort), anOscSocket);
19  }
20  catch (const std::runtime_error& /*error*/)
21  {
22  anOscSocket->mSocketListenerStatus = kOscSocketConnectionFailed;
23  return NULL;
24  }
25 
26  while (TTOscSocketListenerRun(anArgument))
27  ;
28 
29  return NULL;
30 }
31 
32 TTBoolean TTOscSocketListenerRun(TTPtr anArgument)
33 {
34  TTOscSocketPtr anOscSocket= (TTOscSocketPtr) anArgument;
35 
36  if (anOscSocket->mSocketListener)
37  {
38  try
39  {
40  anOscSocket->mSocketListenerStatus = kOscSocketConnectionSucceeded;
41  anOscSocket->mSocketListener->Run();
42  }
43  catch (const std::exception& exception)
44  {
45  TTLogError("TTOscSocketListener : \"%s\"\n", exception.what());
46 
47  if (std::strcmp(exception.what(), "element size must be multiple of four") == 0)
48  return YES;
49 
50  anOscSocket->mSocketListenerStatus = kOscSocketConnectionFailed;
51  return NO;
52  }
53  }
54 
55  return NO;
56 }
57 
59 {
60  mOwner = owner;
61  mPort = port;
62 
63  mSocketListenerStatus = kOscSocketConnectionTrying;
64  mSocketListener = NULL;
65  mSocketListenerThread = new TTThread(TTOscSocketListenerCreate, this);
66 
67  mSocketTransmitter = NULL;
68 }
69 
70 TTOscSocket::TTOscSocket(const TTString& address, const TTUInt16 port)
71 {
72  mAddress = address;
73  mPort = port;
74 
75  mSocketTransmitter = new UdpTransmitSocket(IpEndpointName(address.data(), port));
76 
77  mSocketListenerStatus = kOscSocketConnectionTrying;
78  mSocketListener = NULL;
79 }
80 
81 TTOscSocket::~TTOscSocket()
82 {
83  unsigned int usecToStopTheSelect = 20000;
84 
85  if (mSocketListener) {
86 
87  mSocketListener->AsynchronousBreak();
88 
89  std::this_thread::sleep_for(std::chrono::microseconds(usecToStopTheSelect));
90 
91  delete mSocketListener;
92  mSocketListener = NULL;
93 
94  mSocketListenerStatus = kOscSocketConnectionTrying;
95  }
96 
97  if (mSocketTransmitter) {
98 
99  delete mSocketTransmitter;
100  mSocketTransmitter = NULL;
101  }
102 }
103 
104 void TTOscSocket::ProcessMessage(const osc::ReceivedMessage&m, const IpEndpointName& remoteEndPoint)
105 {
106  TTValue receivedMessage = TTSymbol(m.AddressPattern());
107  TTValue none;
108 
109  osc::ReceivedMessage::const_iterator arguments = m.ArgumentsBegin();
110 
111  while (arguments != m.ArgumentsEnd())
112  {
113  if (arguments->IsChar())
114  receivedMessage.append(arguments->AsChar());
115 
116  else if (arguments->IsInt32())
117  {
118  TTInt32 i = arguments->AsInt32();
119  receivedMessage.append((int)i);
120  }
121  else if (arguments->IsFloat())
122  receivedMessage.append((TTFloat64)arguments->AsFloat());
123 
124  else if (arguments->IsString())
125  receivedMessage.append(TTSymbol(arguments->AsString()));
126 
127  else
128  TTLogError("TTOscSocket::ProcessMessage : the type of an argument is not handled");
129 
130  arguments++;
131  }
132 
133  this->mOwner->sendMessage(TTSymbol("oscSocketReceive"), receivedMessage, none);
134 }
135 
136 TTErr TTOscSocket::SendMessage(TTSymbol& message, const TTValue& arguments)
137 {
138  TTUInt32 bufferSize = computeMessageSize(message, arguments);
139 
140  if (!bufferSize)
141  return kTTErrGeneric;
142 
143 #ifdef TT_PLATFORM_WIN
144  char* buffer = (char*)malloc(bufferSize);
145 #else
146  char buffer[bufferSize];
147 #endif
148 
149  osc::OutboundPacketStream oscStream(buffer, bufferSize);
150 
151  oscStream << osc::BeginMessage(message.c_str());
152 
153 
154  TTSymbol symValue;
155  TTInt32 intValue;
156  TTFloat64 floatValue;
157  TTDataType valueType;
158 
159  for (TTUInt32 i = 0; i < arguments.size(); ++i) {
160  valueType = arguments[i].type();
161 
162  if (valueType == kTypeSymbol) {
163  symValue = arguments[i];
164  oscStream << symValue.c_str();
165  }
166  else if (valueType == kTypeBoolean) {
167  intValue = arguments[i];
168  oscStream << intValue;
169  }
170  else if (valueType == kTypeUInt8 || valueType == kTypeUInt16 || valueType == kTypeUInt32 || valueType == kTypeUInt64) {
171  intValue = arguments[i];
172  oscStream << intValue;
173  }
174  else if (valueType == kTypeInt8 || valueType == kTypeInt16 || valueType == kTypeInt32 || valueType == kTypeInt64) {
175  intValue = arguments[i];
176  oscStream << intValue;
177  }
178  else if (valueType == kTypeFloat32 || valueType == kTypeFloat64) {
179  floatValue = arguments[i];
180  oscStream << (float)floatValue;
181  }
182  else {
183 
184 #ifdef TT_PLATFORM_WIN
185  free(buffer);
186 #endif
187  return kTTErrGeneric;
188  }
189  }
190 
191  oscStream << osc::EndMessage;
192 
193  mSocketTransmitter->Send(oscStream.Data(), oscStream.Size());
194  oscStream.Clear();
195 
196 #ifdef TT_PLATFORM_WIN
197  free(buffer);
198 #endif
199 
200  return kTTErrNone;
201 }
202 
203 TTOscSocketConnectionFlag TTOscSocket::getSocketListenerStatus()
204 {
205  return mSocketListenerStatus;
206 }
207 
208 TTUInt32 TTOscSocket::computeMessageSize(TTSymbol& message, const TTValue& arguments)
209  {
210  TTUInt32 result = 0;
211 
212  result += 8; //#bundle
213  result += 8; //timetag
214  result += 4; //datasize
215 
216  TTUInt32 messageSize = message.string().size();
217  messageSize += 1; // /0 for end of string
218 
219  result += ((messageSize/4) + 1) * 4;
220 
221  TTUInt32 argumentSize = arguments.size();
222  argumentSize += 1; // , for indicating this is an argument string information
223 
224  result += ((argumentSize/4) + 1) * 4; // ArgumentTag Size
225 
226  for (TTUInt32 i = 0; i < arguments.size(); ++i) {
227 
228  if (arguments[i].type() == kTypeSymbol) {
229 
230  TTSymbol symValue;
231  symValue = arguments[i];
232  TTUInt32 stringSize = symValue.string().size();
233  stringSize += 1; // /0 for end of string
234  result += ((stringSize/4) + 1) * 4; // String Size
235  }
236  else if (arguments[i].type() == kTypeBoolean) {
237  result += 1; // Boolean size
238  }
239  else if (arguments[i].type() == kTypeUInt8 || arguments[i].type() == kTypeInt8) {
240  result += 2; // Int8 size
241  }
242  else if (arguments[i].type() == kTypeUInt16 || arguments[i].type() == kTypeInt16) {
243  result += 4; // Int16 size
244  }
245  else if (arguments[i].type() == kTypeUInt32 || arguments[i].type() == kTypeInt32 || arguments[i].type() == kTypeFloat32) {
246  result += 4; // Float32/Int32 size
247  }
248  else if (arguments[i].type() == kTypeUInt64 || arguments[i].type() == kTypeInt64 || arguments[i].type() == kTypeFloat64) {
249  result += 8; // Float64/Int64 size
250  }
251  else
252  return 0; // Error
253  }
254 
255  return result;
256  }
TTErr sendMessage(const TTSymbol name)
TODO: Document this function.
bool TTBoolean
Boolean flag, same as Boolean on the Mac.
Definition: TTBase.h:167
std::uint16_t TTUInt16
16 bit unsigned integer
Definition: TTBase.h:176
8-bit unsigned integer, range is 0 through 255.
Definition: TTBase.h:274
64-bit unsigned integer, range is 0 through 18,446,744,073,709,551,615.
Definition: TTBase.h:280
size_type size() const noexcept
Return the number of elements.
TTDataType
TTBlue Data Types Enumeration of data types used through out TTBlue, including the TTValue class and ...
Definition: TTBase.h:269
Base class for all first-class Jamoma objects.
Definition: TTObjectBase.h:109
this flag means the OSC socket failed to connect
Definition: TTOscSocket.h:34
Symbol type.
Definition: TTBase.h:282
double TTFloat64
64 bit floating point number
Definition: TTBase.h:188
16-bit unsigned integer, range is 0 through 65,535.
Definition: TTBase.h:276
void append(const T &anElementValueToAppend)
Insert a single TTElement at the end.
Definition: TTValue.h:243
TTOscSocketConnectionFlag
Connection flag used to know if the OSC socket manage to connect to a port.
Definition: TTOscSocket.h:31
void * TTPtr
A generic pointer.
Definition: TTBase.h:248
16-bit signed integer, range is −32,768 through 32,767.
Definition: TTBase.h:275
64-bit floating point
Definition: TTBase.h:272
TTOscSocket is ...
Definition: TTOscSocket.h:39
The TTSymbol class is used to represent a string and efficiently pass and compare that string...
Definition: TTSymbol.h:26
this flag means the OSC socket is trying to connect
Definition: TTOscSocket.h:32
void TTFOUNDATION_EXPORT TTLogError(TTImmutableCString message,...)
Platform and host independent method for posting errors.
Definition: TTBase.cpp:572
Boolean (1/0) or (true/false) flag.
Definition: TTBase.h:281
const char * c_str() const
Return a pointer to the internal string as a C-string.
Definition: TTSymbol.h:77
std::int32_t TTInt32
32 bit signed integer
Definition: TTBase.h:177
this flag means the OSC socket connection succeeded
Definition: TTOscSocket.h:33
64-bit signed integer, ragne is −9,223,372,036,854,775,808 through 9,223,372,036,854,775,807
Definition: TTBase.h:279
32-bit floating point
Definition: TTBase.h:271
32-bit signed integer, range is -2,147,483,648 through 2,147,483,647.
Definition: TTBase.h:277
Something went wrong, but what exactly is not known. Typically used for context-specific problems...
Definition: TTBase.h:344
TTErr
Jamoma Error Codes Enumeration of error codes that might be returned by any of the TTBlue functions a...
Definition: TTBase.h:342
std::uint32_t TTUInt32
32 bit unsigned integer
Definition: TTBase.h:178
size_t size() const
Find out the length of a string.
Definition: TTString.h:144
TTOscSocket(const TTObjectBasePtr owner, const TTUInt16 port)
Create a socket to receive osc messages.
Definition: TTOscSocket.cpp:58
friend TTPtr TTOscSocketListenerCreate(TTPtr anArgument)
...
Definition: TTOscSocket.cpp:12
32-bit unsigned integer, range is 0 through 4,294,967,295.
Definition: TTBase.h:278
8-bit signed integer, range is -128 through 127.
Definition: TTBase.h:273
No Error.
Definition: TTBase.h:343
The TTString class is used to represent a string.
Definition: TTString.h:34
[doxygenAppendixC_copyExample]
Definition: TTValue.h:34