00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #include "OSCQueue.h"
00022
00023 #include <iostream>
00024
00025 #define OSC_MESSAGE_QUEUE_SIZE 1023
00026
00027 #ifdef HAVE_LIBLO
00028
00029 void
00030 OSCQueue::oscError(int num, const char *msg, const char *path)
00031 {
00032 std::cerr << "ERROR: OSCQueue::oscError: liblo server error " << num
00033 << " in path " << path << ": " << msg << std::endl;
00034 }
00035
00036 int
00037 OSCQueue::oscMessageHandler(const char *path, const char *types, lo_arg **argv,
00038 int argc, lo_message, void *user_data)
00039 {
00040 OSCQueue *queue = static_cast<OSCQueue *>(user_data);
00041
00042 int target;
00043 int targetData;
00044 QString method;
00045
00046 if (!queue->parseOSCPath(path, target, targetData, method)) {
00047 return 1;
00048 }
00049
00050 OSCMessage message;
00051 message.setTarget(target);
00052 message.setTargetData(targetData);
00053 message.setMethod(method);
00054
00055 int i = 0;
00056
00057 while (types && i < argc && types[i]) {
00058
00059 char type = types[i];
00060 lo_arg *arg = argv[i];
00061
00062 switch (type) {
00063 case 'i': message.addArg(arg->i); break;
00064
00065
00066
00067
00068 case 'f': message.addArg(arg->f); break;
00069 case 'd': message.addArg(arg->d); break;
00070 case 'c': message.addArg(arg->c); break;
00071 case 't': message.addArg(arg->i); break;
00072 case 's': message.addArg(&arg->s); break;
00073 default: std::cerr << "WARNING: OSCQueue::oscMessageHandler: "
00074 << "Unsupported OSC type '" << type << "'"
00075 << std::endl;
00076 break;
00077 }
00078
00079 ++i;
00080 }
00081
00082 queue->postMessage(message);
00083 return 0;
00084 }
00085
00086 #endif
00087
00088 OSCQueue::OSCQueue() :
00089 #ifdef HAVE_LIBLO
00090 m_thread(0),
00091 #endif
00092 m_buffer(OSC_MESSAGE_QUEUE_SIZE)
00093 {
00094 #ifdef HAVE_LIBLO
00095 m_thread = lo_server_thread_new(NULL, oscError);
00096
00097 lo_server_thread_add_method(m_thread, NULL, NULL,
00098 oscMessageHandler, this);
00099
00100 lo_server_thread_start(m_thread);
00101
00102 std::cout << "OSCQueue::OSCQueue: Base OSC URL is "
00103 << lo_server_thread_get_url(m_thread) << std::endl;
00104 #endif
00105 }
00106
00107 OSCQueue::~OSCQueue()
00108 {
00109 #ifdef HAVE_LIBLO
00110 if (m_thread) {
00111 lo_server_thread_stop(m_thread);
00112 }
00113 #endif
00114
00115 while (m_buffer.getReadSpace() > 0) {
00116 delete m_buffer.readOne();
00117 }
00118 }
00119
00120 bool
00121 OSCQueue::isOK() const
00122 {
00123 #ifdef HAVE_LIBLO
00124 return (m_thread != 0);
00125 #else
00126 return false;
00127 #endif
00128 }
00129
00130 QString
00131 OSCQueue::getOSCURL() const
00132 {
00133 QString url = "";
00134 #ifdef HAVE_LIBLO
00135 url = lo_server_thread_get_url(m_thread);
00136 #endif
00137 return url;
00138 }
00139
00140 size_t
00141 OSCQueue::getMessagesAvailable() const
00142 {
00143 return m_buffer.getReadSpace();
00144 }
00145
00146 OSCMessage
00147 OSCQueue::readMessage()
00148 {
00149 OSCMessage *message = m_buffer.readOne();
00150 OSCMessage rmessage = *message;
00151 delete message;
00152 return rmessage;
00153 }
00154
00155 void
00156 OSCQueue::postMessage(OSCMessage message)
00157 {
00158 int count = 0, max = 5;
00159 while (m_buffer.getWriteSpace() == 0) {
00160 if (count == max) {
00161 std::cerr << "ERROR: OSCQueue::postMessage: OSC message queue is full and not clearing -- abandoning incoming message" << std::endl;
00162 return;
00163 }
00164 std::cerr << "WARNING: OSCQueue::postMessage: OSC message queue (capacity " << m_buffer.getSize() << " is full!" << std::endl;
00165 std::cerr << "Waiting for something to be processed" << std::endl;
00166 #ifdef _WIN32
00167 Sleep(1);
00168 #else
00169 sleep(1);
00170 #endif
00171 count++;
00172 }
00173
00174 OSCMessage *mp = new OSCMessage(message);
00175 m_buffer.write(&mp, 1);
00176 std::cerr << "OSCQueue::postMessage: Posted OSC message: target "
00177 << message.getTarget() << ", target data " << message.getTargetData()
00178 << ", method " << message.getMethod().toStdString() << std::endl;
00179 emit messagesAvailable();
00180 }
00181
00182 bool
00183 OSCQueue::parseOSCPath(QString path, int &target, int &targetData,
00184 QString &method)
00185 {
00186 while (path.startsWith("/")) {
00187 path = path.right(path.length()-1);
00188 }
00189
00190 int i = 0;
00191
00192 bool ok = false;
00193 target = path.section('/', i, i).toInt(&ok);
00194
00195 if (!ok) {
00196 target = 0;
00197 } else {
00198 ++i;
00199 targetData = path.section('/', i, i).toInt(&ok);
00200 if (!ok) {
00201 targetData = 0;
00202 } else {
00203 ++i;
00204 }
00205 }
00206
00207 method = path.section('/', i, -1);
00208
00209 if (method.contains('/')) {
00210 std::cerr << "ERROR: OSCQueue::parseOSCPath: malformed path \""
00211 << path.toStdString() << "\" (should be target/data/method or "
00212 << "target/method or method, where target and data "
00213 << "are numeric)" << std::endl;
00214 return false;
00215 }
00216
00217 std::cerr << "OSCQueue::parseOSCPath: good path \"" << path.toStdString()
00218 << "\"" << std::endl;
00219
00220 return true;
00221 }
00222