Mercurial > hg > easaier-soundaccess
comparison sv/osc/OSCQueue.cpp @ 0:fc9323a41f5a
start base : Sonic Visualiser sv1-1.0rc1
author | lbajardsilogic |
---|---|
date | Fri, 11 May 2007 09:08:14 +0000 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
-1:000000000000 | 0:fc9323a41f5a |
---|---|
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 and QMUL. | |
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 #ifdef _WIN32 | |
164 Sleep(1); | |
165 #else | |
166 sleep(1); | |
167 #endif | |
168 count++; | |
169 } | |
170 | |
171 OSCMessage *mp = new OSCMessage(message); | |
172 m_buffer.write(&mp, 1); | |
173 std::cerr << "OSCQueue::postMessage: Posted OSC message: target " | |
174 << message.getTarget() << ", target data " << message.getTargetData() | |
175 << ", method " << message.getMethod().toStdString() << std::endl; | |
176 emit messagesAvailable(); | |
177 } | |
178 | |
179 bool | |
180 OSCQueue::parseOSCPath(QString path, int &target, int &targetData, | |
181 QString &method) | |
182 { | |
183 while (path.startsWith("/")) { | |
184 path = path.right(path.length()-1); | |
185 } | |
186 | |
187 int i = 0; | |
188 | |
189 bool ok = false; | |
190 target = path.section('/', i, i).toInt(&ok); | |
191 | |
192 if (!ok) { | |
193 target = 0; | |
194 } else { | |
195 ++i; | |
196 targetData = path.section('/', i, i).toInt(&ok); | |
197 if (!ok) { | |
198 targetData = 0; | |
199 } else { | |
200 ++i; | |
201 } | |
202 } | |
203 | |
204 method = path.section('/', i, -1); | |
205 | |
206 if (method.contains('/')) { | |
207 std::cerr << "ERROR: OSCQueue::parseOSCPath: malformed path \"" | |
208 << path.toStdString() << "\" (should be target/data/method or " | |
209 << "target/method or method, where target and data " | |
210 << "are numeric)" << std::endl; | |
211 return false; | |
212 } | |
213 | |
214 std::cerr << "OSCQueue::parseOSCPath: good path \"" << path.toStdString() | |
215 << "\"" << std::endl; | |
216 | |
217 return true; | |
218 } | |
219 |