annotate data/osc/OSCQueue.cpp @ 1346:75ad55315db4 3.0-integration

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