annotate data/osc/OSCQueue.cpp @ 335:02d2ad95ea52 spectrogram-cache-rejig

* Get storage advice for each cache in an FFT data server. Allows us to be more confident about the actual memory situation and cut over from memory to disc part way through an FFT calculation if necessary. StorageAdviser is now a bit too optimistic though (it's too keen to allocate large numbers of small blocks in memory).
author Chris Cannam
date Tue, 13 Nov 2007 13:54:10 +0000
parents 32e50b620a6c
children 115f60df1e4d
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@320 23 #include <iostream>
Chris@320 24
Chris@320 25 #define OSC_MESSAGE_QUEUE_SIZE 1023
Chris@320 26
Chris@320 27 #ifdef HAVE_LIBLO
Chris@320 28
Chris@320 29 void
Chris@320 30 OSCQueue::oscError(int num, const char *msg, const char *path)
Chris@320 31 {
Chris@320 32 std::cerr << "ERROR: OSCQueue::oscError: liblo server error " << num
Chris@320 33 << " in path " << path << ": " << msg << std::endl;
Chris@320 34 }
Chris@320 35
Chris@320 36 int
Chris@320 37 OSCQueue::oscMessageHandler(const char *path, const char *types, lo_arg **argv,
Chris@320 38 int argc, lo_message, void *user_data)
Chris@320 39 {
Chris@320 40 OSCQueue *queue = static_cast<OSCQueue *>(user_data);
Chris@320 41
Chris@320 42 int target;
Chris@320 43 int targetData;
Chris@320 44 QString method;
Chris@320 45
Chris@320 46 if (!queue->parseOSCPath(path, target, targetData, method)) {
Chris@320 47 return 1;
Chris@320 48 }
Chris@320 49
Chris@320 50 OSCMessage message;
Chris@320 51 message.setTarget(target);
Chris@320 52 message.setTargetData(targetData);
Chris@320 53 message.setMethod(method);
Chris@320 54
Chris@320 55 int i = 0;
Chris@320 56
Chris@320 57 while (types && i < argc && types[i]) {
Chris@320 58
Chris@320 59 char type = types[i];
Chris@320 60 lo_arg *arg = argv[i];
Chris@320 61
Chris@320 62 switch (type) {
Chris@320 63 case 'i': message.addArg(arg->i); break;
Chris@320 64 // This conversion fails to compile in 64-bit environments
Chris@320 65 // at present, and we don't use the h type anyway so we
Chris@320 66 // can safely omit it
Chris@320 67 // case 'h': message.addArg(arg->h); break;
Chris@320 68 case 'f': message.addArg(arg->f); break;
Chris@320 69 case 'd': message.addArg(arg->d); break;
Chris@320 70 case 'c': message.addArg(arg->c); break;
Chris@320 71 case 't': message.addArg(arg->i); break;
Chris@320 72 case 's': message.addArg(&arg->s); break;
Chris@320 73 default: std::cerr << "WARNING: OSCQueue::oscMessageHandler: "
Chris@320 74 << "Unsupported OSC type '" << type << "'"
Chris@320 75 << std::endl;
Chris@320 76 break;
Chris@320 77 }
Chris@320 78
Chris@320 79 ++i;
Chris@320 80 }
Chris@320 81
Chris@320 82 queue->postMessage(message);
Chris@320 83 return 0;
Chris@320 84 }
Chris@320 85
Chris@320 86 #endif
Chris@320 87
Chris@320 88 OSCQueue::OSCQueue() :
Chris@320 89 #ifdef HAVE_LIBLO
Chris@320 90 m_thread(0),
Chris@320 91 #endif
Chris@320 92 m_buffer(OSC_MESSAGE_QUEUE_SIZE)
Chris@320 93 {
Chris@320 94 #ifdef HAVE_LIBLO
Chris@320 95 m_thread = lo_server_thread_new(NULL, oscError);
Chris@320 96
Chris@320 97 lo_server_thread_add_method(m_thread, NULL, NULL,
Chris@320 98 oscMessageHandler, this);
Chris@320 99
Chris@320 100 lo_server_thread_start(m_thread);
Chris@320 101
Chris@320 102 std::cout << "OSCQueue::OSCQueue: Base OSC URL is "
Chris@320 103 << lo_server_thread_get_url(m_thread) << std::endl;
Chris@320 104 #endif
Chris@320 105 }
Chris@320 106
Chris@320 107 OSCQueue::~OSCQueue()
Chris@320 108 {
Chris@320 109 #ifdef HAVE_LIBLO
Chris@320 110 if (m_thread) {
Chris@320 111 lo_server_thread_stop(m_thread);
Chris@320 112 }
Chris@320 113 #endif
Chris@320 114
Chris@320 115 while (m_buffer.getReadSpace() > 0) {
Chris@320 116 delete m_buffer.readOne();
Chris@320 117 }
Chris@320 118 }
Chris@320 119
Chris@320 120 bool
Chris@320 121 OSCQueue::isOK() const
Chris@320 122 {
Chris@320 123 #ifdef HAVE_LIBLO
Chris@320 124 return (m_thread != 0);
Chris@320 125 #else
Chris@320 126 return false;
Chris@320 127 #endif
Chris@320 128 }
Chris@320 129
Chris@320 130 QString
Chris@320 131 OSCQueue::getOSCURL() const
Chris@320 132 {
Chris@320 133 QString url = "";
Chris@320 134 #ifdef HAVE_LIBLO
Chris@320 135 url = lo_server_thread_get_url(m_thread);
Chris@320 136 #endif
Chris@320 137 return url;
Chris@320 138 }
Chris@320 139
Chris@320 140 size_t
Chris@320 141 OSCQueue::getMessagesAvailable() const
Chris@320 142 {
Chris@320 143 return m_buffer.getReadSpace();
Chris@320 144 }
Chris@320 145
Chris@320 146 OSCMessage
Chris@320 147 OSCQueue::readMessage()
Chris@320 148 {
Chris@320 149 OSCMessage *message = m_buffer.readOne();
Chris@320 150 OSCMessage rmessage = *message;
Chris@320 151 delete message;
Chris@320 152 return rmessage;
Chris@320 153 }
Chris@320 154
Chris@320 155 void
Chris@320 156 OSCQueue::postMessage(OSCMessage message)
Chris@320 157 {
Chris@320 158 int count = 0, max = 5;
Chris@320 159 while (m_buffer.getWriteSpace() == 0) {
Chris@320 160 if (count == max) {
Chris@320 161 std::cerr << "ERROR: OSCQueue::postMessage: OSC message queue is full and not clearing -- abandoning incoming message" << std::endl;
Chris@320 162 return;
Chris@320 163 }
Chris@320 164 std::cerr << "WARNING: OSCQueue::postMessage: OSC message queue (capacity " << m_buffer.getSize() << " is full!" << std::endl;
Chris@320 165 std::cerr << "Waiting for something to be processed" << std::endl;
Chris@320 166 #ifdef _WIN32
Chris@320 167 Sleep(1);
Chris@320 168 #else
Chris@320 169 sleep(1);
Chris@320 170 #endif
Chris@320 171 count++;
Chris@320 172 }
Chris@320 173
Chris@320 174 OSCMessage *mp = new OSCMessage(message);
Chris@320 175 m_buffer.write(&mp, 1);
Chris@320 176 std::cerr << "OSCQueue::postMessage: Posted OSC message: target "
Chris@320 177 << message.getTarget() << ", target data " << message.getTargetData()
Chris@320 178 << ", method " << message.getMethod().toStdString() << std::endl;
Chris@320 179 emit messagesAvailable();
Chris@320 180 }
Chris@320 181
Chris@320 182 bool
Chris@320 183 OSCQueue::parseOSCPath(QString path, int &target, int &targetData,
Chris@320 184 QString &method)
Chris@320 185 {
Chris@320 186 while (path.startsWith("/")) {
Chris@320 187 path = path.right(path.length()-1);
Chris@320 188 }
Chris@320 189
Chris@320 190 int i = 0;
Chris@320 191
Chris@320 192 bool ok = false;
Chris@320 193 target = path.section('/', i, i).toInt(&ok);
Chris@320 194
Chris@320 195 if (!ok) {
Chris@320 196 target = 0;
Chris@320 197 } else {
Chris@320 198 ++i;
Chris@320 199 targetData = path.section('/', i, i).toInt(&ok);
Chris@320 200 if (!ok) {
Chris@320 201 targetData = 0;
Chris@320 202 } else {
Chris@320 203 ++i;
Chris@320 204 }
Chris@320 205 }
Chris@320 206
Chris@320 207 method = path.section('/', i, -1);
Chris@320 208
Chris@320 209 if (method.contains('/')) {
Chris@320 210 std::cerr << "ERROR: OSCQueue::parseOSCPath: malformed path \""
Chris@320 211 << path.toStdString() << "\" (should be target/data/method or "
Chris@320 212 << "target/method or method, where target and data "
Chris@320 213 << "are numeric)" << std::endl;
Chris@320 214 return false;
Chris@320 215 }
Chris@320 216
Chris@320 217 std::cerr << "OSCQueue::parseOSCPath: good path \"" << path.toStdString()
Chris@320 218 << "\"" << std::endl;
Chris@320 219
Chris@320 220 return true;
Chris@320 221 }
Chris@320 222