BTRFS: Implement BTree::Path and change _Find.
[haiku.git] / src / apps / cortex / RouteApp / ConnectionIO.cpp
blob7f67dd9ddb71da85a684c842dc0cdb2cf0262686
1 /*
2 * Copyright (c) 1999-2000, Eric Moon.
3 * All rights reserved.
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions, and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions, and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
16 * 3. The name of the author may not be used to endorse or promote products
17 * derived from this software without specific prior written permission.
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR "AS IS" AND ANY EXPRESS OR
20 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
21 * OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
23 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
24 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
25 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
26 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
27 * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32 // ConnectionIO.cpp
34 #include "ConnectionIO.h"
35 #include "LiveNodeIO.h"
36 #include "NodeManager.h"
37 #include "NodeSetIOContext.h"
39 #include "MediaFormatIO.h"
40 #include "route_app_io.h"
42 #include <vector>
43 #include <Debug.h>
45 using namespace std;
47 __USE_CORTEX_NAMESPACE
49 // -------------------------------------------------------- //
50 // *** ctor/dtor
51 // -------------------------------------------------------- //
53 ConnectionIO::~ConnectionIO() {
54 if(m_inputNodeIO) delete m_inputNodeIO;
55 if(m_outputNodeIO) delete m_outputNodeIO;
58 // initialize for import
59 ConnectionIO::ConnectionIO() :
60 m_inputNodeIO(0),
61 m_outputNodeIO(0),
62 m_flags(0),
63 m_exportValid(false),
64 m_importState(IMPORT_NONE) {
66 m_outputFormat.type = B_MEDIA_NO_TYPE;
67 m_inputFormat.type = B_MEDIA_NO_TYPE;
68 m_requestedFormat.type = B_MEDIA_NO_TYPE;
71 // initialize for export
72 ConnectionIO::ConnectionIO(
73 const Connection* con,
74 const NodeManager* manager,
75 const NodeSetIOContext* context) :
77 m_inputNodeIO(0),
78 m_outputNodeIO(0),
79 m_exportValid(false),
80 m_importState(IMPORT_NONE) {
82 ASSERT(con);
83 ASSERT(manager);
84 ASSERT(context);
86 if(!con->isValid()) {
87 PRINT((
88 "!!! ConnectionIO(): invalid connection\n"));
89 return;
92 m_outputNodeIO = new LiveNodeIO(
93 manager,
94 context,
95 con->sourceNode());
97 // fetch output (connection-point) description
98 const char* name;
99 if(con->getOutputHint(
100 &name,
101 &m_outputFormat) == B_OK)
102 m_outputName = name;
103 else {
104 m_outputName = con->outputName();
107 m_inputNodeIO = new LiveNodeIO(
108 manager,
109 context,
110 con->destinationNode());
112 // fetch input (connection-point) description
113 if(con->getInputHint(
114 &name,
115 &m_inputFormat) == B_OK)
116 m_inputName = name;
118 else {
119 m_inputName = con->inputName();
122 m_requestedFormat = con->requestedFormat();
123 m_flags = con->flags();
125 m_exportValid = true;
128 // -------------------------------------------------------- //
129 // *** operations
130 // -------------------------------------------------------- //
132 // call when object imported to create the described
133 // connection
135 // +++++ to do
136 // smarter input/output matching -- if no name/format provided,
137 // pick the first available endpoint. otherwise, make two passes:
138 // 1) match all nodes w/ given name (pass wildcards through to roster)
139 // 2) filter by format
141 status_t ConnectionIO::instantiate(
142 NodeManager* manager,
143 const NodeSetIOContext* context,
144 Connection* outCon) {
146 // sanity checks
147 ASSERT(manager);
148 if(!m_inputNodeIO || !m_outputNodeIO)
149 return B_NOT_ALLOWED;
151 status_t err;
152 media_node_id node;
154 // find output node
155 NodeRef* outputRef;
156 err = m_outputNodeIO->getNode(manager, context, &node);
157 if(err < B_OK)
158 return err;
159 err = manager->getNodeRef(
160 node,
161 &outputRef);
162 if(err < B_OK)
163 return err;
165 // find output +++++ currently matches by name only
166 const int32 outputBufferSize = 16;
167 media_output outputs[outputBufferSize];
168 int32 count = outputBufferSize;
170 //vector<media_output> outputs;
171 // err = outputRef->getFreeOutputs(
172 // outputs/*,
173 // m_outputFormat.type*/);
175 err = outputRef->getFreeOutputs(
176 outputs,
177 outputBufferSize,
178 &count);
179 if(err < B_OK)
180 return err;
182 media_output output;
183 bool found = false;
184 for(int n = 0; n < count; ++n) {
185 if(m_outputName == outputs[n].name) {
186 output = outputs[n];
187 found = true;
188 break;
191 if(!found) {
192 PRINT(("!!! output '%s' of node '%s' not found\n",
193 m_outputName.String(),
194 outputRef->name()));
195 return B_NAME_NOT_FOUND;
198 // find input node
199 NodeRef* inputRef;
200 err = m_inputNodeIO->getNode(manager, context, &node);
201 if(err < B_OK)
202 return err;
203 err = manager->getNodeRef(
204 node,
205 &inputRef);
206 if(err < B_OK)
207 return err;
209 // find input +++++ currently matches by name only
210 vector<media_input> inputs;
211 err = inputRef->getFreeInputs(
212 inputs /*,
213 m_inputFormat.type*/);
214 if(err < B_OK)
215 return err;
217 media_input input;
218 found = false;
219 for(unsigned int n = 0; n < inputs.size(); ++n) {
220 if(m_inputName == inputs[n].name) {
221 input = inputs[n];
222 found = true;
223 break;
226 if(!found) {
227 PRINT(("!!! input '%s' of node '%s' not found\n",
228 m_inputName.String(),
229 inputRef->name()));
230 return B_NAME_NOT_FOUND;
233 // connect
234 Connection con;
235 if(m_requestedFormat.type != B_MEDIA_NO_TYPE)
236 err = manager->connect(
237 output,
238 input,
239 m_requestedFormat,
240 &con);
241 else
242 err = manager->connect(
243 output,
244 input,
245 &con);
247 if(err < B_OK)
248 return err;
250 if(outCon)
251 *outCon = con;
252 return B_OK;
255 // -------------------------------------------------------- //
256 // *** document-type setup
257 // -------------------------------------------------------- //
259 /*static*/
260 void ConnectionIO::AddTo(
261 XML::DocumentType* docType) {
263 // map self
264 docType->addMapping(new Mapping<ConnectionIO>(_CONNECTION_ELEMENT));
266 // map simple (content-only) elements
267 // +++++ should these be added at a higher level, since they're
268 // shared? no harm is done if one is added more than once,
269 // since they'll always map to StringContent -- but it's way
270 // messy!
271 // +++++
272 //docType->addMapping(new Mapping<StringContent>(_LIVE_NODE_ELEMENT));
273 // docType->addMapping(new Mapping<StringContent>(_NAME_ELEMENT));
274 // docType->addMapping(new Mapping<StringContent>(_KIND_ELEMENT));
275 // docType->addMapping(new Mapping<StringContent>(_FLAG_ELEMENT));
278 // -------------------------------------------------------- //
279 // *** IPersistent
280 // -------------------------------------------------------- //
282 // -------------------------------------------------------- //
283 // EXPORT:
284 // -------------------------------------------------------- //
287 // -------------------------------------------------------- //
288 void ConnectionIO::xmlExportBegin(
289 ExportContext& context) const {
291 if(!m_exportValid) {
292 context.reportError(
293 "ConnectionIO::xmlExportBegin():\n"
294 "*** invalid ***\n");
295 return;
298 context.beginElement(_CONNECTION_ELEMENT);
301 void ConnectionIO::xmlExportAttributes(
302 ExportContext& context) const { TOUCH(context); }
304 void ConnectionIO::xmlExportContent(
305 ExportContext& context) const {
307 context.beginContent();
309 // write output
311 context.beginElement(_OUTPUT_ELEMENT);
312 context.beginContent();
314 // describe the node
315 // LiveNodeIO nodeIO(
316 // m_manager,
317 // dynamic_cast<NodeSetIOContext*>(&context),
318 // m_outputNode);
319 context.writeObject(m_outputNodeIO);
321 // context.beginElement(_LIVE_NODE_ELEMENT);
322 // if(m_outputNodeKey.Length()) {
323 // context.writeAttr("key", m_outputNodeKey);
324 // }
325 // else {
326 // _write_simple("name", m_outputNodeName.String(), context);
327 // _write_node_kinds(m_outputNodeKind, context);
328 // }
329 // context.endElement(); // _LIVE_NODE_ELEMENT
331 // describe the output
333 _write_simple("name", m_outputName.String(), context);
335 if(m_outputFormat.type > B_MEDIA_UNKNOWN_TYPE) {
336 MediaFormatIO io(m_outputFormat);
337 context.writeObject(&io);
340 context.endElement(); // _OUTPUT_ELEMENT
343 // write input
345 context.beginElement(_INPUT_ELEMENT);
346 context.beginContent();
348 // describe the node
349 // LiveNodeIO nodeIO(
350 // m_manager,
351 // dynamic_cast<NodeSetIOContext*>(&context),
352 // m_inputNode);
353 context.writeObject(m_inputNodeIO);
355 // context.beginElement(_LIVE_NODE_ELEMENT);
356 // if(m_inputNodeKey.Length()) {
357 // context.writeAttr("key", m_inputNodeKey);
358 // }
359 // else {
360 // _write_simple("name", m_inputNodeName.String(), context);
361 // _write_node_kinds(m_inputNodeKind, context);
362 // }
363 // context.endElement(); // _LIVE_NODE_ELEMENT
365 // describe the input
367 _write_simple("name", m_inputName.String(), context);
369 if(m_inputFormat.type > B_MEDIA_UNKNOWN_TYPE) {
370 MediaFormatIO io(m_inputFormat);
371 context.writeObject(&io);
374 context.endElement(); // _INPUT_ELEMENT
377 // write requested format
378 if(m_requestedFormat.type > B_MEDIA_UNKNOWN_TYPE) {
379 MediaFormatIO io(m_requestedFormat);
380 BString comment = "\n";
381 comment << context.indentString();
382 comment << "<!-- initial requested format -->";
383 context.writeString(comment);
384 context.writeObject(&io);
388 void ConnectionIO::xmlExportEnd(
389 ExportContext& context) const {
391 context.endElement(); // _CONNECTION_ELEMENT
394 // -------------------------------------------------------- //
395 // IMPORT:
396 // -------------------------------------------------------- //
398 void ConnectionIO::xmlImportBegin(
399 ImportContext& context) { TOUCH(context); }
401 void ConnectionIO::xmlImportAttribute(
402 const char* key,
403 const char* value,
404 ImportContext& context) { TOUCH(key); TOUCH(value); TOUCH(context); }
406 void ConnectionIO::xmlImportContent(
407 const char* data,
408 uint32 length,
409 ImportContext& context) { TOUCH(data); TOUCH(length); TOUCH(context); }
411 void ConnectionIO::xmlImportChild(
412 IPersistent* child,
413 ImportContext& context) {
415 status_t err;
417 if(!strcmp(context.element(), _LIVE_NODE_ELEMENT)) {
418 LiveNodeIO* nodeIO = dynamic_cast<LiveNodeIO*>(child);
419 ASSERT(nodeIO);
421 // store the LiveNodeIO for now; it will be used in
422 // instantiate()
424 switch(m_importState) {
425 case IMPORT_OUTPUT:
426 m_outputNodeIO = nodeIO;
427 child = 0; // don't delete child object
428 break;
430 case IMPORT_INPUT:
431 m_inputNodeIO = nodeIO;
432 child = 0; // don't delete child object
433 break;
435 case IMPORT_NONE:
436 context.reportError("Unexpected node description.\n");
437 delete child;
438 return;
441 else if(!strcmp(context.element(), _NAME_ELEMENT)) {
442 StringContent* c = dynamic_cast<StringContent*>(child);
443 ASSERT(c);
445 switch(m_importState) {
446 case IMPORT_OUTPUT:
447 m_outputName = c->content;
448 break;
450 case IMPORT_INPUT:
451 m_inputName = c->content;
452 break;
454 case IMPORT_NONE:
455 context.reportError("Unexpected node name.\n");
456 delete child;
457 return;
460 else {
461 MediaFormatIO* io = dynamic_cast<MediaFormatIO*>(child);
462 if(!io) {
463 context.reportError("Unexpected element.\n");
464 delete child;
465 return;
468 media_format f;
469 err = io->getFormat(f);
470 if(err < B_OK) {
471 context.reportError("Malformed format.\n");
472 delete child;
473 return;
476 switch(m_importState) {
477 case IMPORT_OUTPUT:
478 m_outputFormat = f;
479 break;
481 case IMPORT_INPUT:
482 m_inputFormat = f;
483 break;
485 case IMPORT_NONE:
486 m_requestedFormat = f;
487 break;
491 if(child)
492 delete child;
495 void ConnectionIO::xmlImportComplete(
496 ImportContext& context) {
498 // +++++
501 void ConnectionIO::xmlImportChildBegin(
502 const char* name,
503 ImportContext& context) {
505 if(!strcmp(name, "input")) {
506 if(m_importState != IMPORT_NONE) {
507 context.reportError("ConnectionIO: unexpected nested child element\n");
508 return;
510 m_importState = IMPORT_INPUT;
512 else if(!strcmp(name, "output")) {
513 if(m_importState != IMPORT_NONE) {
514 context.reportError("ConnectionIO: unexpected nested child element\n");
515 return;
517 m_importState = IMPORT_OUTPUT;
519 else
520 context.reportError("ConnectionIO: unexpected child element\n");
523 void ConnectionIO::xmlImportChildComplete(
524 const char* name,
525 ImportContext& context) {
526 TOUCH(name); TOUCH(context);
528 m_importState = IMPORT_NONE;
531 // END -- ConnectionIO.cpp --