# HG changeset patch # User Chris Cannam # Date 1169746860 0 # Node ID 5828afd1d229de9a4f661f97a63e7e2f36314a45 # Parent 14cc0a78f3403c4449f6c2dbc316e33a7ba78f6c Fixes for Windows build diff -r 14cc0a78f340 -r 5828afd1d229 audioio/AudioPortAudioTarget.cpp --- a/audioio/AudioPortAudioTarget.cpp Thu Jan 25 16:26:49 2007 +0000 +++ b/audioio/AudioPortAudioTarget.cpp Thu Jan 25 17:41:00 2007 +0000 @@ -1,246 +1,250 @@ -/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */ - -/* - Sonic Visualiser - An audio file viewer and annotation editor. - Centre for Digital Music, Queen Mary, University of London. - This file copyright 2006 Chris Cannam. - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License as - published by the Free Software Foundation; either version 2 of the - License, or (at your option) any later version. See the file - COPYING included with this distribution for more information. -*/ - -#ifdef HAVE_PORTAUDIO - -#include "AudioPortAudioTarget.h" -#include "AudioCallbackPlaySource.h" - -#include -#include -#include - -//#define DEBUG_AUDIO_PORT_AUDIO_TARGET 1 - -AudioPortAudioTarget::AudioPortAudioTarget(AudioCallbackPlaySource *source) : - AudioCallbackPlayTarget(source), - m_stream(0), - m_bufferSize(0), - m_sampleRate(0), - m_latency(0) -{ - PaError err; - -#ifdef DEBUG_AUDIO_PORT_AUDIO_TARGET -#ifdef HAVE_PORTAUDIO_v18 - std::cerr << "AudioPortAudioTarget: Initialising for PortAudio v18" << std::endl; -#else - std::cerr << "AudioPortAudioTarget: Initialising for PortAudio v19" << std::endl; -#endif -#endif - - err = Pa_Initialize(); - if (err != paNoError) { - std::cerr << "ERROR: AudioPortAudioTarget: Failed to initialize PortAudio: " << Pa_GetErrorText(err) << std::endl; - return; - } - - m_bufferSize = 1024; - m_sampleRate = 44100; - if (m_source && (m_source->getSourceSampleRate() != 0)) { - m_sampleRate = m_source->getSourceSampleRate(); - } - -#ifdef HAVE_PORTAUDIO_v18 - m_latency = Pa_GetMinNumBuffers(m_bufferSize, m_sampleRate) * m_bufferSize; -#endif - -#ifdef HAVE_PORTAUDIO_v18 - err = Pa_OpenDefaultStream(&m_stream, 0, 2, paFloat32, - m_sampleRate, m_bufferSize, 0, - processStatic, this); -#else - err = Pa_OpenDefaultStream(&m_stream, 0, 2, paFloat32, - m_sampleRate, m_bufferSize, - processStatic, this); -#endif - - if (err != paNoError) { - std::cerr << "ERROR: AudioPortAudioTarget: Failed to open PortAudio stream: " << Pa_GetErrorText(err) << std::endl; - m_stream = 0; - Pa_Terminate(); - return; - } - -#ifndef HAVE_PORTAUDIO_v18 - const PaStreamInfo *info = Pa_GetStreamInfo(m_stream); - m_latency = int(info->outputLatency * m_sampleRate + 0.001); -#endif - - std::cerr << "PortAudio latency = " << m_latency << " frames" << std::endl; - - err = Pa_StartStream(m_stream); - - if (err != paNoError) { - std::cerr << "ERROR: AudioPortAudioTarget: Failed to start PortAudio stream: " << Pa_GetErrorText(err) << std::endl; - Pa_CloseStream(m_stream); - m_stream = 0; - Pa_Terminate(); - return; - } - - if (m_source) { - std::cerr << "AudioPortAudioTarget: block size " << m_bufferSize << std::endl; - m_source->setTargetBlockSize(m_bufferSize); - m_source->setTargetSampleRate(m_sampleRate); - m_source->setTargetPlayLatency(m_latency); - } -} - -AudioPortAudioTarget::~AudioPortAudioTarget() -{ - if (m_stream) { - PaError err; - err = Pa_CloseStream(m_stream); - if (err != paNoError) { - std::cerr << "ERROR: AudioPortAudioTarget: Failed to close PortAudio stream: " << Pa_GetErrorText(err) << std::endl; - } - err = Pa_Terminate(); - if (err != paNoError) { - std::cerr << "ERROR: AudioPortAudioTarget: Failed to terminate PortAudio: " << Pa_GetErrorText(err) << std::endl; - } - } -} - -bool -AudioPortAudioTarget::isOK() const -{ - return (m_stream != 0); -} - -#ifdef HAVE_PORTAUDIO_v18 -int -AudioPortAudioTarget::processStatic(void *input, void *output, - unsigned long nframes, - PaTimestamp outTime, void *data) -{ - return ((AudioPortAudioTarget *)data)->process(input, output, - nframes, outTime); -} -#else -int -AudioPortAudioTarget::processStatic(const void *input, void *output, - unsigned long nframes, - const PaStreamCallbackTimeInfo *timeInfo, - PaStreamCallbackFlags flags, void *data) -{ - return ((AudioPortAudioTarget *)data)->process(input, output, - nframes, timeInfo, - flags); -} -#endif - -void -AudioPortAudioTarget::sourceModelReplaced() -{ - m_source->setTargetSampleRate(m_sampleRate); -} - -#ifdef HAVE_PORTAUDIO_v18 -int -AudioPortAudioTarget::process(void *inputBuffer, void *outputBuffer, - unsigned long nframes, - PaTimestamp) -#else -int -AudioPortAudioTarget::process(const void *inputBuffer, void *outputBuffer, - unsigned long nframes, - const PaStreamCallbackTimeInfo *, - PaStreamCallbackFlags) -#endif -{ -#ifdef DEBUG_AUDIO_PORT_AUDIO_TARGET - std::cout << "AudioPortAudioTarget::process(" << nframes << ")" << std::endl; -#endif - - if (!m_source) return 0; - - float *output = (float *)outputBuffer; - - assert(nframes <= m_bufferSize); - - static float **tmpbuf = 0; - static size_t tmpbufch = 0; - static size_t tmpbufsz = 0; - - size_t sourceChannels = m_source->getSourceChannelCount(); - - // Because we offer pan, we always want at least 2 channels - if (sourceChannels < 2) sourceChannels = 2; - - if (!tmpbuf || tmpbufch != sourceChannels || tmpbufsz < m_bufferSize) { - - if (tmpbuf) { - for (size_t i = 0; i < tmpbufch; ++i) { - delete[] tmpbuf[i]; - } - delete[] tmpbuf; - } - - tmpbufch = sourceChannels; - tmpbufsz = m_bufferSize; - tmpbuf = new float *[tmpbufch]; - - for (size_t i = 0; i < tmpbufch; ++i) { - tmpbuf[i] = new float[tmpbufsz]; - } - } - - m_source->getSourceSamples(nframes, tmpbuf); - - float peakLeft = 0.0, peakRight = 0.0; - - for (size_t ch = 0; ch < 2; ++ch) { - - float peak = 0.0; - - if (ch < sourceChannels) { - - // PortAudio samples are interleaved - for (size_t i = 0; i < nframes; ++i) { - output[i * 2 + ch] = tmpbuf[ch][i] * m_outputGain; - float sample = fabsf(output[i * 2 + ch]); - if (sample > peak) peak = sample; - } - - } else if (ch == 1 && sourceChannels == 1) { - - for (size_t i = 0; i < nframes; ++i) { - output[i * 2 + ch] = tmpbuf[0][i] * m_outputGain; - float sample = fabsf(output[i * 2 + ch]); - if (sample > peak) peak = sample; - } - - } else { - for (size_t i = 0; i < nframes; ++i) { - output[i * 2 + ch] = 0; - } - } - - if (ch == 0) peakLeft = peak; - if (ch > 0 || sourceChannels == 1) peakRight = peak; - } - - m_source->setOutputLevels(peakLeft, peakRight); - - return 0; -} - -#ifdef INCLUDE_MOCFILES -#include "AudioPortAudioTarget.moc.cpp" -#endif - -#endif /* HAVE_PORTAUDIO */ - +/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */ + +/* + Sonic Visualiser + An audio file viewer and annotation editor. + Centre for Digital Music, Queen Mary, University of London. + This file copyright 2006 Chris Cannam. + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. See the file + COPYING included with this distribution for more information. +*/ + +#ifdef HAVE_PORTAUDIO + +#include "AudioPortAudioTarget.h" +#include "AudioCallbackPlaySource.h" + +#include +#include +#include + +#define DEBUG_AUDIO_PORT_AUDIO_TARGET 1 + +AudioPortAudioTarget::AudioPortAudioTarget(AudioCallbackPlaySource *source) : + AudioCallbackPlayTarget(source), + m_stream(0), + m_bufferSize(0), + m_sampleRate(0), + m_latency(0) +{ + PaError err; + +#ifdef DEBUG_AUDIO_PORT_AUDIO_TARGET +#ifdef HAVE_PORTAUDIO_v18 + std::cerr << "AudioPortAudioTarget: Initialising for PortAudio v18" << std::endl; +#else + std::cerr << "AudioPortAudioTarget: Initialising for PortAudio v19" << std::endl; +#endif +#endif + + err = Pa_Initialize(); + if (err != paNoError) { + std::cerr << "ERROR: AudioPortAudioTarget: Failed to initialize PortAudio: " << Pa_GetErrorText(err) << std::endl; + return; + } + + m_bufferSize = 1024; + m_sampleRate = 44100; + if (m_source && (m_source->getSourceSampleRate() != 0)) { + m_sampleRate = m_source->getSourceSampleRate(); + } + +#ifdef HAVE_PORTAUDIO_v18 + m_latency = Pa_GetMinNumBuffers(m_bufferSize, m_sampleRate) * m_bufferSize; +#endif + +#ifdef HAVE_PORTAUDIO_v18 + err = Pa_OpenDefaultStream(&m_stream, 0, 2, paFloat32, + m_sampleRate, m_bufferSize, 0, + processStatic, this); +#else + err = Pa_OpenDefaultStream(&m_stream, 0, 2, paFloat32, + m_sampleRate, m_bufferSize, + processStatic, this); +#endif + + if (err != paNoError) { + std::cerr << "ERROR: AudioPortAudioTarget: Failed to open PortAudio stream: " << Pa_GetErrorText(err) << std::endl; + m_stream = 0; + Pa_Terminate(); + return; + } + +#ifndef HAVE_PORTAUDIO_v18 + const PaStreamInfo *info = Pa_GetStreamInfo(m_stream); + m_latency = int(info->outputLatency * m_sampleRate + 0.001); +#endif + + std::cerr << "PortAudio latency = " << m_latency << " frames" << std::endl; + + err = Pa_StartStream(m_stream); + + if (err != paNoError) { + std::cerr << "ERROR: AudioPortAudioTarget: Failed to start PortAudio stream: " << Pa_GetErrorText(err) << std::endl; + Pa_CloseStream(m_stream); + m_stream = 0; + Pa_Terminate(); + return; + } + + if (m_source) { + std::cerr << "AudioPortAudioTarget: block size " << m_bufferSize << std::endl; + m_source->setTargetBlockSize(m_bufferSize); + m_source->setTargetSampleRate(m_sampleRate); + m_source->setTargetPlayLatency(m_latency); + } + +#ifdef DEBUG_PORT_AUDIO_TARGET + std::cerr << "AudioPortAudioTarget: initialised OK" << std::endl; +#endif +} + +AudioPortAudioTarget::~AudioPortAudioTarget() +{ + if (m_stream) { + PaError err; + err = Pa_CloseStream(m_stream); + if (err != paNoError) { + std::cerr << "ERROR: AudioPortAudioTarget: Failed to close PortAudio stream: " << Pa_GetErrorText(err) << std::endl; + } + err = Pa_Terminate(); + if (err != paNoError) { + std::cerr << "ERROR: AudioPortAudioTarget: Failed to terminate PortAudio: " << Pa_GetErrorText(err) << std::endl; + } + } +} + +bool +AudioPortAudioTarget::isOK() const +{ + return (m_stream != 0); +} + +#ifdef HAVE_PORTAUDIO_v18 +int +AudioPortAudioTarget::processStatic(void *input, void *output, + unsigned long nframes, + PaTimestamp outTime, void *data) +{ + return ((AudioPortAudioTarget *)data)->process(input, output, + nframes, outTime); +} +#else +int +AudioPortAudioTarget::processStatic(const void *input, void *output, + unsigned long nframes, + const PaStreamCallbackTimeInfo *timeInfo, + PaStreamCallbackFlags flags, void *data) +{ + return ((AudioPortAudioTarget *)data)->process(input, output, + nframes, timeInfo, + flags); +} +#endif + +void +AudioPortAudioTarget::sourceModelReplaced() +{ + m_source->setTargetSampleRate(m_sampleRate); +} + +#ifdef HAVE_PORTAUDIO_v18 +int +AudioPortAudioTarget::process(void *inputBuffer, void *outputBuffer, + unsigned long nframes, + PaTimestamp) +#else +int +AudioPortAudioTarget::process(const void *inputBuffer, void *outputBuffer, + unsigned long nframes, + const PaStreamCallbackTimeInfo *, + PaStreamCallbackFlags) +#endif +{ +#ifdef DEBUG_AUDIO_PORT_AUDIO_TARGET + std::cout << "AudioPortAudioTarget::process(" << nframes << ")" << std::endl; +#endif + + if (!m_source) return 0; + + float *output = (float *)outputBuffer; + + assert(nframes <= m_bufferSize); + + static float **tmpbuf = 0; + static size_t tmpbufch = 0; + static size_t tmpbufsz = 0; + + size_t sourceChannels = m_source->getSourceChannelCount(); + + // Because we offer pan, we always want at least 2 channels + if (sourceChannels < 2) sourceChannels = 2; + + if (!tmpbuf || tmpbufch != sourceChannels || tmpbufsz < m_bufferSize) { + + if (tmpbuf) { + for (size_t i = 0; i < tmpbufch; ++i) { + delete[] tmpbuf[i]; + } + delete[] tmpbuf; + } + + tmpbufch = sourceChannels; + tmpbufsz = m_bufferSize; + tmpbuf = new float *[tmpbufch]; + + for (size_t i = 0; i < tmpbufch; ++i) { + tmpbuf[i] = new float[tmpbufsz]; + } + } + + m_source->getSourceSamples(nframes, tmpbuf); + + float peakLeft = 0.0, peakRight = 0.0; + + for (size_t ch = 0; ch < 2; ++ch) { + + float peak = 0.0; + + if (ch < sourceChannels) { + + // PortAudio samples are interleaved + for (size_t i = 0; i < nframes; ++i) { + output[i * 2 + ch] = tmpbuf[ch][i] * m_outputGain; + float sample = fabsf(output[i * 2 + ch]); + if (sample > peak) peak = sample; + } + + } else if (ch == 1 && sourceChannels == 1) { + + for (size_t i = 0; i < nframes; ++i) { + output[i * 2 + ch] = tmpbuf[0][i] * m_outputGain; + float sample = fabsf(output[i * 2 + ch]); + if (sample > peak) peak = sample; + } + + } else { + for (size_t i = 0; i < nframes; ++i) { + output[i * 2 + ch] = 0; + } + } + + if (ch == 0) peakLeft = peak; + if (ch > 0 || sourceChannels == 1) peakRight = peak; + } + + m_source->setOutputLevels(peakLeft, peakRight); + + return 0; +} + +#ifdef INCLUDE_MOCFILES +#include "AudioPortAudioTarget.moc.cpp" +#endif + +#endif /* HAVE_PORTAUDIO */ + diff -r 14cc0a78f340 -r 5828afd1d229 osc/OSCQueue.cpp --- a/osc/OSCQueue.cpp Thu Jan 25 16:26:49 2007 +0000 +++ b/osc/OSCQueue.cpp Thu Jan 25 17:41:00 2007 +0000 @@ -1,215 +1,219 @@ -/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */ - -/* - Sonic Visualiser - An audio file viewer and annotation editor. - Centre for Digital Music, Queen Mary, University of London. - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License as - published by the Free Software Foundation; either version 2 of the - License, or (at your option) any later version. See the file - COPYING included with this distribution for more information. -*/ - -/* - This is a modified version of a source file from the - Rosegarden MIDI and audio sequencer and notation editor. - This file copyright 2000-2006 Chris Cannam and QMUL. -*/ - -#include "OSCQueue.h" - -#include - -#define OSC_MESSAGE_QUEUE_SIZE 1023 - -#ifdef HAVE_LIBLO - -void -OSCQueue::oscError(int num, const char *msg, const char *path) -{ - std::cerr << "ERROR: OSCQueue::oscError: liblo server error " << num - << " in path " << path << ": " << msg << std::endl; -} - -int -OSCQueue::oscMessageHandler(const char *path, const char *types, lo_arg **argv, - int argc, lo_message, void *user_data) -{ - OSCQueue *queue = static_cast(user_data); - - int target; - int targetData; - QString method; - - if (!queue->parseOSCPath(path, target, targetData, method)) { - return 1; - } - - OSCMessage message; - message.setTarget(target); - message.setTargetData(targetData); - message.setMethod(method); - - int i = 0; - - while (types && i < argc && types[i]) { - - char type = types[i]; - lo_arg *arg = argv[i]; - - switch (type) { - case 'i': message.addArg(arg->i); break; - case 'h': message.addArg(arg->h); break; - case 'f': message.addArg(arg->f); break; - case 'd': message.addArg(arg->d); break; - case 'c': message.addArg(arg->c); break; - case 't': message.addArg(arg->i); break; - case 's': message.addArg(&arg->s); break; - default: std::cerr << "WARNING: OSCQueue::oscMessageHandler: " - << "Unsupported OSC type '" << type << "'" - << std::endl; - break; - } - - ++i; - } - - queue->postMessage(message); - return 0; -} - -#endif - -OSCQueue::OSCQueue() : -#ifdef HAVE_LIBLO - m_thread(0), -#endif - m_buffer(OSC_MESSAGE_QUEUE_SIZE) -{ -#ifdef HAVE_LIBLO - m_thread = lo_server_thread_new(NULL, oscError); - - lo_server_thread_add_method(m_thread, NULL, NULL, - oscMessageHandler, this); - - lo_server_thread_start(m_thread); - - std::cout << "OSCQueue::OSCQueue: Base OSC URL is " - << lo_server_thread_get_url(m_thread) << std::endl; -#endif -} - -OSCQueue::~OSCQueue() -{ -#ifdef HAVE_LIBLO - if (m_thread) { - lo_server_thread_stop(m_thread); - } -#endif - - while (m_buffer.getReadSpace() > 0) { - delete m_buffer.readOne(); - } -} - -bool -OSCQueue::isOK() const -{ -#ifdef HAVE_LIBLO - return (m_thread != 0); -#else - return false; -#endif -} - -QString -OSCQueue::getOSCURL() const -{ - QString url = ""; -#ifdef HAVE_LIBLO - url = lo_server_thread_get_url(m_thread); -#endif - return url; -} - -size_t -OSCQueue::getMessagesAvailable() const -{ - return m_buffer.getReadSpace(); -} - -OSCMessage -OSCQueue::readMessage() -{ - OSCMessage *message = m_buffer.readOne(); - OSCMessage rmessage = *message; - delete message; - return rmessage; -} - -void -OSCQueue::postMessage(OSCMessage message) -{ - int count = 0, max = 5; - while (m_buffer.getWriteSpace() == 0) { - if (count == max) { - std::cerr << "ERROR: OSCQueue::postMessage: OSC message queue is full and not clearing -- abandoning incoming message" << std::endl; - return; - } - std::cerr << "WARNING: OSCQueue::postMessage: OSC message queue (capacity " << m_buffer.getSize() << " is full!" << std::endl; - std::cerr << "Waiting for something to be processed" << std::endl; - sleep(1); - count++; - } - - OSCMessage *mp = new OSCMessage(message); - m_buffer.write(&mp, 1); - std::cerr << "OSCQueue::postMessage: Posted OSC message: target " - << message.getTarget() << ", target data " << message.getTargetData() - << ", method " << message.getMethod().toStdString() << std::endl; - emit messagesAvailable(); -} - -bool -OSCQueue::parseOSCPath(QString path, int &target, int &targetData, - QString &method) -{ - while (path.startsWith("/")) { - path = path.right(path.length()-1); - } - - int i = 0; - - bool ok = false; - target = path.section('/', i, i).toInt(&ok); - - if (!ok) { - target = 0; - } else { - ++i; - targetData = path.section('/', i, i).toInt(&ok); - if (!ok) { - targetData = 0; - } else { - ++i; - } - } - - method = path.section('/', i, -1); - - if (method.contains('/')) { - std::cerr << "ERROR: OSCQueue::parseOSCPath: malformed path \"" - << path.toStdString() << "\" (should be target/data/method or " - << "target/method or method, where target and data " - << "are numeric)" << std::endl; - return false; - } - - std::cerr << "OSCQueue::parseOSCPath: good path \"" << path.toStdString() - << "\"" << std::endl; - - return true; -} - +/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */ + +/* + Sonic Visualiser + An audio file viewer and annotation editor. + Centre for Digital Music, Queen Mary, University of London. + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. See the file + COPYING included with this distribution for more information. +*/ + +/* + This is a modified version of a source file from the + Rosegarden MIDI and audio sequencer and notation editor. + This file copyright 2000-2006 Chris Cannam and QMUL. +*/ + +#include "OSCQueue.h" + +#include + +#define OSC_MESSAGE_QUEUE_SIZE 1023 + +#ifdef HAVE_LIBLO + +void +OSCQueue::oscError(int num, const char *msg, const char *path) +{ + std::cerr << "ERROR: OSCQueue::oscError: liblo server error " << num + << " in path " << path << ": " << msg << std::endl; +} + +int +OSCQueue::oscMessageHandler(const char *path, const char *types, lo_arg **argv, + int argc, lo_message, void *user_data) +{ + OSCQueue *queue = static_cast(user_data); + + int target; + int targetData; + QString method; + + if (!queue->parseOSCPath(path, target, targetData, method)) { + return 1; + } + + OSCMessage message; + message.setTarget(target); + message.setTargetData(targetData); + message.setMethod(method); + + int i = 0; + + while (types && i < argc && types[i]) { + + char type = types[i]; + lo_arg *arg = argv[i]; + + switch (type) { + case 'i': message.addArg(arg->i); break; + case 'h': message.addArg(arg->h); break; + case 'f': message.addArg(arg->f); break; + case 'd': message.addArg(arg->d); break; + case 'c': message.addArg(arg->c); break; + case 't': message.addArg(arg->i); break; + case 's': message.addArg(&arg->s); break; + default: std::cerr << "WARNING: OSCQueue::oscMessageHandler: " + << "Unsupported OSC type '" << type << "'" + << std::endl; + break; + } + + ++i; + } + + queue->postMessage(message); + return 0; +} + +#endif + +OSCQueue::OSCQueue() : +#ifdef HAVE_LIBLO + m_thread(0), +#endif + m_buffer(OSC_MESSAGE_QUEUE_SIZE) +{ +#ifdef HAVE_LIBLO + m_thread = lo_server_thread_new(NULL, oscError); + + lo_server_thread_add_method(m_thread, NULL, NULL, + oscMessageHandler, this); + + lo_server_thread_start(m_thread); + + std::cout << "OSCQueue::OSCQueue: Base OSC URL is " + << lo_server_thread_get_url(m_thread) << std::endl; +#endif +} + +OSCQueue::~OSCQueue() +{ +#ifdef HAVE_LIBLO + if (m_thread) { + lo_server_thread_stop(m_thread); + } +#endif + + while (m_buffer.getReadSpace() > 0) { + delete m_buffer.readOne(); + } +} + +bool +OSCQueue::isOK() const +{ +#ifdef HAVE_LIBLO + return (m_thread != 0); +#else + return false; +#endif +} + +QString +OSCQueue::getOSCURL() const +{ + QString url = ""; +#ifdef HAVE_LIBLO + url = lo_server_thread_get_url(m_thread); +#endif + return url; +} + +size_t +OSCQueue::getMessagesAvailable() const +{ + return m_buffer.getReadSpace(); +} + +OSCMessage +OSCQueue::readMessage() +{ + OSCMessage *message = m_buffer.readOne(); + OSCMessage rmessage = *message; + delete message; + return rmessage; +} + +void +OSCQueue::postMessage(OSCMessage message) +{ + int count = 0, max = 5; + while (m_buffer.getWriteSpace() == 0) { + if (count == max) { + std::cerr << "ERROR: OSCQueue::postMessage: OSC message queue is full and not clearing -- abandoning incoming message" << std::endl; + return; + } + std::cerr << "WARNING: OSCQueue::postMessage: OSC message queue (capacity " << m_buffer.getSize() << " is full!" << std::endl; + std::cerr << "Waiting for something to be processed" << std::endl; +#ifdef _WIN32 + Sleep(1); +#else + sleep(1); +#endif + count++; + } + + OSCMessage *mp = new OSCMessage(message); + m_buffer.write(&mp, 1); + std::cerr << "OSCQueue::postMessage: Posted OSC message: target " + << message.getTarget() << ", target data " << message.getTargetData() + << ", method " << message.getMethod().toStdString() << std::endl; + emit messagesAvailable(); +} + +bool +OSCQueue::parseOSCPath(QString path, int &target, int &targetData, + QString &method) +{ + while (path.startsWith("/")) { + path = path.right(path.length()-1); + } + + int i = 0; + + bool ok = false; + target = path.section('/', i, i).toInt(&ok); + + if (!ok) { + target = 0; + } else { + ++i; + targetData = path.section('/', i, i).toInt(&ok); + if (!ok) { + targetData = 0; + } else { + ++i; + } + } + + method = path.section('/', i, -1); + + if (method.contains('/')) { + std::cerr << "ERROR: OSCQueue::parseOSCPath: malformed path \"" + << path.toStdString() << "\" (should be target/data/method or " + << "target/method or method, where target and data " + << "are numeric)" << std::endl; + return false; + } + + std::cerr << "OSCQueue::parseOSCPath: good path \"" << path.toStdString() + << "\"" << std::endl; + + return true; +} +