annotate sv/osc/OSCQueue.cpp @ 282:d9319859a4cf tip

(none)
author benoitrigolleau
date Fri, 31 Oct 2008 11:00:24 +0000
parents fc9323a41f5a
children
rev   line source
lbajardsilogic@0 1 /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */
lbajardsilogic@0 2
lbajardsilogic@0 3 /*
lbajardsilogic@0 4 Sonic Visualiser
lbajardsilogic@0 5 An audio file viewer and annotation editor.
lbajardsilogic@0 6 Centre for Digital Music, Queen Mary, University of London.
lbajardsilogic@0 7
lbajardsilogic@0 8 This program is free software; you can redistribute it and/or
lbajardsilogic@0 9 modify it under the terms of the GNU General Public License as
lbajardsilogic@0 10 published by the Free Software Foundation; either version 2 of the
lbajardsilogic@0 11 License, or (at your option) any later version. See the file
lbajardsilogic@0 12 COPYING included with this distribution for more information.
lbajardsilogic@0 13 */
lbajardsilogic@0 14
lbajardsilogic@0 15 /*
lbajardsilogic@0 16 This is a modified version of a source file from the
lbajardsilogic@0 17 Rosegarden MIDI and audio sequencer and notation editor.
lbajardsilogic@0 18 This file copyright 2000-2006 Chris Cannam and QMUL.
lbajardsilogic@0 19 */
lbajardsilogic@0 20
lbajardsilogic@0 21 #include "OSCQueue.h"
lbajardsilogic@0 22
lbajardsilogic@0 23 #include <iostream>
lbajardsilogic@0 24
lbajardsilogic@0 25 #define OSC_MESSAGE_QUEUE_SIZE 1023
lbajardsilogic@0 26
lbajardsilogic@0 27 #ifdef HAVE_LIBLO
lbajardsilogic@0 28
lbajardsilogic@0 29 void
lbajardsilogic@0 30 OSCQueue::oscError(int num, const char *msg, const char *path)
lbajardsilogic@0 31 {
lbajardsilogic@0 32 std::cerr << "ERROR: OSCQueue::oscError: liblo server error " << num
lbajardsilogic@0 33 << " in path " << path << ": " << msg << std::endl;
lbajardsilogic@0 34 }
lbajardsilogic@0 35
lbajardsilogic@0 36 int
lbajardsilogic@0 37 OSCQueue::oscMessageHandler(const char *path, const char *types, lo_arg **argv,
lbajardsilogic@0 38 int argc, lo_message, void *user_data)
lbajardsilogic@0 39 {
lbajardsilogic@0 40 OSCQueue *queue = static_cast<OSCQueue *>(user_data);
lbajardsilogic@0 41
lbajardsilogic@0 42 int target;
lbajardsilogic@0 43 int targetData;
lbajardsilogic@0 44 QString method;
lbajardsilogic@0 45
lbajardsilogic@0 46 if (!queue->parseOSCPath(path, target, targetData, method)) {
lbajardsilogic@0 47 return 1;
lbajardsilogic@0 48 }
lbajardsilogic@0 49
lbajardsilogic@0 50 OSCMessage message;
lbajardsilogic@0 51 message.setTarget(target);
lbajardsilogic@0 52 message.setTargetData(targetData);
lbajardsilogic@0 53 message.setMethod(method);
lbajardsilogic@0 54
lbajardsilogic@0 55 int i = 0;
lbajardsilogic@0 56
lbajardsilogic@0 57 while (types && i < argc && types[i]) {
lbajardsilogic@0 58
lbajardsilogic@0 59 char type = types[i];
lbajardsilogic@0 60 lo_arg *arg = argv[i];
lbajardsilogic@0 61
lbajardsilogic@0 62 switch (type) {
lbajardsilogic@0 63 case 'i': message.addArg(arg->i); break;
lbajardsilogic@0 64 case 'h': message.addArg(arg->h); break;
lbajardsilogic@0 65 case 'f': message.addArg(arg->f); break;
lbajardsilogic@0 66 case 'd': message.addArg(arg->d); break;
lbajardsilogic@0 67 case 'c': message.addArg(arg->c); break;
lbajardsilogic@0 68 case 't': message.addArg(arg->i); break;
lbajardsilogic@0 69 case 's': message.addArg(&arg->s); break;
lbajardsilogic@0 70 default: std::cerr << "WARNING: OSCQueue::oscMessageHandler: "
lbajardsilogic@0 71 << "Unsupported OSC type '" << type << "'"
lbajardsilogic@0 72 << std::endl;
lbajardsilogic@0 73 break;
lbajardsilogic@0 74 }
lbajardsilogic@0 75
lbajardsilogic@0 76 ++i;
lbajardsilogic@0 77 }
lbajardsilogic@0 78
lbajardsilogic@0 79 queue->postMessage(message);
lbajardsilogic@0 80 return 0;
lbajardsilogic@0 81 }
lbajardsilogic@0 82
lbajardsilogic@0 83 #endif
lbajardsilogic@0 84
lbajardsilogic@0 85 OSCQueue::OSCQueue() :
lbajardsilogic@0 86 #ifdef HAVE_LIBLO
lbajardsilogic@0 87 m_thread(0),
lbajardsilogic@0 88 #endif
lbajardsilogic@0 89 m_buffer(OSC_MESSAGE_QUEUE_SIZE)
lbajardsilogic@0 90 {
lbajardsilogic@0 91 #ifdef HAVE_LIBLO
lbajardsilogic@0 92 m_thread = lo_server_thread_new(NULL, oscError);
lbajardsilogic@0 93
lbajardsilogic@0 94 lo_server_thread_add_method(m_thread, NULL, NULL,
lbajardsilogic@0 95 oscMessageHandler, this);
lbajardsilogic@0 96
lbajardsilogic@0 97 lo_server_thread_start(m_thread);
lbajardsilogic@0 98
lbajardsilogic@0 99 std::cout << "OSCQueue::OSCQueue: Base OSC URL is "
lbajardsilogic@0 100 << lo_server_thread_get_url(m_thread) << std::endl;
lbajardsilogic@0 101 #endif
lbajardsilogic@0 102 }
lbajardsilogic@0 103
lbajardsilogic@0 104 OSCQueue::~OSCQueue()
lbajardsilogic@0 105 {
lbajardsilogic@0 106 #ifdef HAVE_LIBLO
lbajardsilogic@0 107 if (m_thread) {
lbajardsilogic@0 108 lo_server_thread_stop(m_thread);
lbajardsilogic@0 109 }
lbajardsilogic@0 110 #endif
lbajardsilogic@0 111
lbajardsilogic@0 112 while (m_buffer.getReadSpace() > 0) {
lbajardsilogic@0 113 delete m_buffer.readOne();
lbajardsilogic@0 114 }
lbajardsilogic@0 115 }
lbajardsilogic@0 116
lbajardsilogic@0 117 bool
lbajardsilogic@0 118 OSCQueue::isOK() const
lbajardsilogic@0 119 {
lbajardsilogic@0 120 #ifdef HAVE_LIBLO
lbajardsilogic@0 121 return (m_thread != 0);
lbajardsilogic@0 122 #else
lbajardsilogic@0 123 return false;
lbajardsilogic@0 124 #endif
lbajardsilogic@0 125 }
lbajardsilogic@0 126
lbajardsilogic@0 127 QString
lbajardsilogic@0 128 OSCQueue::getOSCURL() const
lbajardsilogic@0 129 {
lbajardsilogic@0 130 QString url = "";
lbajardsilogic@0 131 #ifdef HAVE_LIBLO
lbajardsilogic@0 132 url = lo_server_thread_get_url(m_thread);
lbajardsilogic@0 133 #endif
lbajardsilogic@0 134 return url;
lbajardsilogic@0 135 }
lbajardsilogic@0 136
lbajardsilogic@0 137 size_t
lbajardsilogic@0 138 OSCQueue::getMessagesAvailable() const
lbajardsilogic@0 139 {
lbajardsilogic@0 140 return m_buffer.getReadSpace();
lbajardsilogic@0 141 }
lbajardsilogic@0 142
lbajardsilogic@0 143 OSCMessage
lbajardsilogic@0 144 OSCQueue::readMessage()
lbajardsilogic@0 145 {
lbajardsilogic@0 146 OSCMessage *message = m_buffer.readOne();
lbajardsilogic@0 147 OSCMessage rmessage = *message;
lbajardsilogic@0 148 delete message;
lbajardsilogic@0 149 return rmessage;
lbajardsilogic@0 150 }
lbajardsilogic@0 151
lbajardsilogic@0 152 void
lbajardsilogic@0 153 OSCQueue::postMessage(OSCMessage message)
lbajardsilogic@0 154 {
lbajardsilogic@0 155 int count = 0, max = 5;
lbajardsilogic@0 156 while (m_buffer.getWriteSpace() == 0) {
lbajardsilogic@0 157 if (count == max) {
lbajardsilogic@0 158 std::cerr << "ERROR: OSCQueue::postMessage: OSC message queue is full and not clearing -- abandoning incoming message" << std::endl;
lbajardsilogic@0 159 return;
lbajardsilogic@0 160 }
lbajardsilogic@0 161 std::cerr << "WARNING: OSCQueue::postMessage: OSC message queue (capacity " << m_buffer.getSize() << " is full!" << std::endl;
lbajardsilogic@0 162 std::cerr << "Waiting for something to be processed" << std::endl;
lbajardsilogic@0 163 #ifdef _WIN32
lbajardsilogic@0 164 Sleep(1);
lbajardsilogic@0 165 #else
lbajardsilogic@0 166 sleep(1);
lbajardsilogic@0 167 #endif
lbajardsilogic@0 168 count++;
lbajardsilogic@0 169 }
lbajardsilogic@0 170
lbajardsilogic@0 171 OSCMessage *mp = new OSCMessage(message);
lbajardsilogic@0 172 m_buffer.write(&mp, 1);
lbajardsilogic@0 173 std::cerr << "OSCQueue::postMessage: Posted OSC message: target "
lbajardsilogic@0 174 << message.getTarget() << ", target data " << message.getTargetData()
lbajardsilogic@0 175 << ", method " << message.getMethod().toStdString() << std::endl;
lbajardsilogic@0 176 emit messagesAvailable();
lbajardsilogic@0 177 }
lbajardsilogic@0 178
lbajardsilogic@0 179 bool
lbajardsilogic@0 180 OSCQueue::parseOSCPath(QString path, int &target, int &targetData,
lbajardsilogic@0 181 QString &method)
lbajardsilogic@0 182 {
lbajardsilogic@0 183 while (path.startsWith("/")) {
lbajardsilogic@0 184 path = path.right(path.length()-1);
lbajardsilogic@0 185 }
lbajardsilogic@0 186
lbajardsilogic@0 187 int i = 0;
lbajardsilogic@0 188
lbajardsilogic@0 189 bool ok = false;
lbajardsilogic@0 190 target = path.section('/', i, i).toInt(&ok);
lbajardsilogic@0 191
lbajardsilogic@0 192 if (!ok) {
lbajardsilogic@0 193 target = 0;
lbajardsilogic@0 194 } else {
lbajardsilogic@0 195 ++i;
lbajardsilogic@0 196 targetData = path.section('/', i, i).toInt(&ok);
lbajardsilogic@0 197 if (!ok) {
lbajardsilogic@0 198 targetData = 0;
lbajardsilogic@0 199 } else {
lbajardsilogic@0 200 ++i;
lbajardsilogic@0 201 }
lbajardsilogic@0 202 }
lbajardsilogic@0 203
lbajardsilogic@0 204 method = path.section('/', i, -1);
lbajardsilogic@0 205
lbajardsilogic@0 206 if (method.contains('/')) {
lbajardsilogic@0 207 std::cerr << "ERROR: OSCQueue::parseOSCPath: malformed path \""
lbajardsilogic@0 208 << path.toStdString() << "\" (should be target/data/method or "
lbajardsilogic@0 209 << "target/method or method, where target and data "
lbajardsilogic@0 210 << "are numeric)" << std::endl;
lbajardsilogic@0 211 return false;
lbajardsilogic@0 212 }
lbajardsilogic@0 213
lbajardsilogic@0 214 std::cerr << "OSCQueue::parseOSCPath: good path \"" << path.toStdString()
lbajardsilogic@0 215 << "\"" << std::endl;
lbajardsilogic@0 216
lbajardsilogic@0 217 return true;
lbajardsilogic@0 218 }
lbajardsilogic@0 219