root/trunk/libffado/src/libosc/OscNode.cpp

Revision 445, 7.9 kB (checked in by pieterpalmers, 15 years ago)

* name change from FreeBoB to FFADO
* replaced tabs by 4 spaces
* got rid of end-of-line spaces
* made all license and copyrights conform

library becomes LGPL, apps become GPL
explicitly state LGPL v2.1 and GPL v2 (don't like v3 draft)

copyrights are 2005-2007 Daniel & Pieter
except for the MotU stuff (C) Jonathan, Pieter

Line 
1 /*
2  * Copyright (C) 2005-2007 by Pieter Palmers
3  *
4  * This file is part of FFADO
5  * FFADO = Free Firewire (pro-)audio drivers for linux
6  *
7  * FFADO is based upon FreeBoB
8  *
9  * This library is free software; you can redistribute it and/or
10  * modify it under the terms of the GNU Lesser General Public
11  * License version 2.1, as published by the Free Software Foundation;
12  *
13  * This library is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16  * Lesser General Public License for more details.
17  *
18  * You should have received a copy of the GNU Lesser General Public
19  * License along with this library; if not, write to the Free Software
20  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
21  * MA 02110-1301 USA
22  */
23
24 #include "OscNode.h"
25 #include "OscMessage.h"
26 #include "OscResponse.h"
27 #include <assert.h>
28
29 namespace OSC {
30
31 IMPL_DEBUG_MODULE( OscNode, OscNode, DEBUG_LEVEL_VERBOSE );
32
33 OscNode::OscNode()
34     : m_oscBase("")
35     , m_oscAutoDelete(false)
36 {}
37
38 OscNode::OscNode(string b)
39     : m_oscBase(b)
40     , m_oscAutoDelete(false)
41 {}
42
43 OscNode::OscNode(string b, bool autodelete)
44     : m_oscBase(b)
45     , m_oscAutoDelete(autodelete)
46 {}
47
48 OscNode::~OscNode() {
49     debugOutput( DEBUG_LEVEL_VERY_VERBOSE, "Removing child nodes\n");
50
51     for ( OscNodeVectorIterator it = m_ChildNodes.begin();
52       it != m_ChildNodes.end();
53       ++it )
54     {
55         if((*it)->doOscNodeAutoDelete()) {
56             debugOutput( DEBUG_LEVEL_VERY_VERBOSE, " Auto-deleting child node %s\n",
57                          (*it)->getOscBase().c_str());
58             delete (*it);
59         }
60     }
61 }
62
63 void
64 OscNode::setVerboseLevel(int l) {
65     setDebugLevel(l);
66     for ( OscNodeVectorIterator it = m_ChildNodes.begin();
67       it != m_ChildNodes.end();
68       ++it )
69     {
70         (*it)->setVerboseLevel(l);
71     }
72 }
73
74 // generic message processing
75 OscResponse
76 OscNode::processOscMessage(string path, OscMessage *m)
77 {
78     debugOutput( DEBUG_LEVEL_VERBOSE, "(%p) MSG: %s\n",this, path.c_str());
79
80     // delete leading slash
81     if(path.find_first_of('/')==0) path=path.substr(1,path.size());
82
83     // delete trailing slash
84     if(path.find_last_of('/')==path.size()-1) path=path.substr(0,path.size()-1);
85
86     // continue processing
87     int firstsep=path.find_first_of('/');
88
89     if (firstsep == -1) {
90         OscResponse retVal;
91
92         // process the message
93         retVal=processOscMessage(m);
94
95         if(retVal.isHandled()) {
96             return retVal; // completely handled
97         } else { // (partially) unhandled
98             return processOscMessageDefault(m, retVal);
99         }
100
101     } else { // it targets a deeper node
102         string newpath=path.substr(firstsep+1);
103         int secondsep=newpath.find_first_of('/');
104         string newbase;
105         if (secondsep==-1) {
106             newbase=newpath;
107         } else {
108             newbase=path.substr(firstsep+1,secondsep);
109         }
110
111         for ( OscNodeVectorIterator it = m_ChildNodes.begin();
112           it != m_ChildNodes.end();
113           ++it )
114         {
115             if((*it)->getOscBase() == newbase) {
116                 return (*it)->processOscMessage(newpath,m);
117             }
118         }
119         debugOutput( DEBUG_LEVEL_VERBOSE, "Child node %s not found \n",newbase.c_str());
120
121         return OscResponse(OscResponse::eError);
122     }
123     return OscResponse(OscResponse::eError);
124 }
125
126 // default handlers
127
128 // overload this to make a node process a message
129 OscResponse
130 OscNode::processOscMessage(OscMessage *m)
131 {
132     debugOutput( DEBUG_LEVEL_VERBOSE, "(%p) MSG PROCESS: %s\n", this, m->getPath().c_str());
133     m->print();
134     return OscResponse(OscResponse::eUnhandled); // handled but no response
135 }
136
137 // this provides support for messages that are
138 // supported by all nodes
139 OscResponse
140 OscNode::processOscMessageDefault(OscMessage *m, OscResponse r)
141 {
142     unsigned int nbArgs=m->nbArguments();
143     if (nbArgs>=1) {
144         OscArgument arg0=m->getArgument(0);
145         if(arg0.isString()) { // first argument should be a string command
146             string cmd=arg0.getString();
147             debugOutput( DEBUG_LEVEL_VERBOSE, "(%p) CMD? %s\n", this, cmd.c_str());
148             if(cmd == "list") {
149                 debugOutput( DEBUG_LEVEL_VERBOSE, "Listing node children...\n");
150                 OscMessage rm=oscListChildren(r.getMessage());
151                 return OscResponse(rm);
152             }
153         }
154     }
155     // default action: don't change response
156     return r;
157 }
158
159 OscMessage
160 OscNode::oscListChildren(OscMessage m) {
161
162     for ( OscNodeVectorIterator it = m_ChildNodes.begin();
163       it != m_ChildNodes.end();
164       ++it )
165     {
166         m.addArgument((*it)->getOscBase());
167     }
168     m.print();
169     return m;
170 }
171
172 // child management
173
174 bool
175 OscNode::addChildOscNode(OscNode *n)
176 {
177     assert(n);
178
179     debugOutput( DEBUG_LEVEL_VERBOSE, "Adding child node %s\n",n->getOscBase().c_str());
180     for ( OscNodeVectorIterator it = m_ChildNodes.begin();
181       it != m_ChildNodes.end();
182       ++it )
183     {
184         if(*it == n) {
185             debugOutput( DEBUG_LEVEL_VERBOSE,
186                 "Child node %s already registered\n",
187                 n->getOscBase().c_str());
188             return false;
189         }
190     }
191     m_ChildNodes.push_back(n);
192     return true;
193 }
194
195 /**
196  * Add a child node under a certain path.
197  * e.g. if you have a node with base 'X' and
198  * you want it to be at /base/level1/level2/X
199  * you would add it using this function, by
200  *  addChildOscNode(n, "/base/level1/level2")
201  *
202  * @param n
203  * @param
204  * @return
205  */
206 bool
207 OscNode::addChildOscNode(OscNode *n, string path)
208 {
209     debugOutput( DEBUG_LEVEL_VERBOSE, "add node to: %s\n",path.c_str());
210
211     // delete leading slashes
212     if(path.find_first_of('/')==0) path=path.substr(1,path.size());
213
214     // delete trailing slashes
215     if(path.find_last_of('/')==path.size()-1) path=path.substr(0,path.size()-1);
216
217     // continue processing
218     int firstsep=path.find_first_of('/');
219
220     if (firstsep == -1) {
221         return addChildOscNode(n);
222     } else { // it targets a deeper node
223         string newpath=path.substr(firstsep+1);
224         int secondsep=newpath.find_first_of('/');
225         string newbase;
226         if (secondsep==-1) {
227             newbase=newpath;
228         } else {
229             newbase=path.substr(firstsep+1,secondsep);
230         }
231
232         // if the path is already present, find it
233         for ( OscNodeVectorIterator it = m_ChildNodes.begin();
234           it != m_ChildNodes.end();
235           ++it )
236         {
237             if((*it)->getOscBase() == newbase) {
238                 return (*it)->addChildOscNode(n,newpath);
239             }
240         }
241         debugOutput( DEBUG_LEVEL_VERBOSE, "node %s not found, creating auto-node\n",newbase.c_str());
242
243         OscNode *autoNode=new OscNode(newbase,true);
244
245         // add the auto-node to this node
246         m_ChildNodes.push_back(autoNode);
247
248         // add the child to the node
249         return autoNode->addChildOscNode(n,newpath);
250     }
251     return false;
252 }
253
254 bool
255 OscNode::removeChildOscNode(OscNode *n)
256 {
257     assert(n);
258     debugOutput( DEBUG_LEVEL_VERBOSE, "Removing child node %s\n",n->getOscBase().c_str());
259
260     for ( OscNodeVectorIterator it = m_ChildNodes.begin();
261       it != m_ChildNodes.end();
262       ++it )
263     {
264         if(*it == n) {
265             m_ChildNodes.erase(it);
266             if((*it)->doOscNodeAutoDelete()) {
267                 debugOutput( DEBUG_LEVEL_VERBOSE, " Auto-deleting child node %s\n",n->getOscBase().c_str());
268                 delete (*it);
269             }
270             return true;
271         }
272     }
273
274     debugOutput( DEBUG_LEVEL_VERBOSE, "Child node %s not found \n",n->getOscBase().c_str());
275
276     return false; //not found
277 }
278
279 void
280 OscNode::printOscNode()
281 {
282     printOscNode("");
283 }
284
285 void
286 OscNode::printOscNode(string path)
287 {
288     debugOutput( DEBUG_LEVEL_NORMAL, "%s/%s\n",
289                  path.c_str(),getOscBase().c_str());
290
291     for ( OscNodeVectorIterator it = m_ChildNodes.begin();
292       it != m_ChildNodes.end();
293       ++it )
294     {
295         (*it)->printOscNode(path+"/"+getOscBase());
296     }
297 }
298
299 } // end of namespace OSC
Note: See TracBrowser for help on using the browser.