annotate osc/OSCQueue.cpp @ 139:ee977f93f66c

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