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