2 * Copyright (c) 1999-2000, Eric Moon.
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
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.
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"
47 __USE_CORTEX_NAMESPACE
49 // -------------------------------------------------------- //
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() :
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
) :
80 m_importState(IMPORT_NONE
) {
88 "!!! ConnectionIO(): invalid connection\n"));
92 m_outputNodeIO
= new LiveNodeIO(
97 // fetch output (connection-point) description
99 if(con
->getOutputHint(
101 &m_outputFormat
) == B_OK
)
104 m_outputName
= con
->outputName();
107 m_inputNodeIO
= new LiveNodeIO(
110 con
->destinationNode());
112 // fetch input (connection-point) description
113 if(con
->getInputHint(
115 &m_inputFormat
) == B_OK
)
119 m_inputName
= con
->inputName();
122 m_requestedFormat
= con
->requestedFormat();
123 m_flags
= con
->flags();
125 m_exportValid
= true;
128 // -------------------------------------------------------- //
130 // -------------------------------------------------------- //
132 // call when object imported to create the described
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
) {
148 if(!m_inputNodeIO
|| !m_outputNodeIO
)
149 return B_NOT_ALLOWED
;
156 err
= m_outputNodeIO
->getNode(manager
, context
, &node
);
159 err
= manager
->getNodeRef(
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(
173 // m_outputFormat.type*/);
175 err
= outputRef
->getFreeOutputs(
184 for(int n
= 0; n
< count
; ++n
) {
185 if(m_outputName
== outputs
[n
].name
) {
192 PRINT(("!!! output '%s' of node '%s' not found\n",
193 m_outputName
.String(),
195 return B_NAME_NOT_FOUND
;
200 err
= m_inputNodeIO
->getNode(manager
, context
, &node
);
203 err
= manager
->getNodeRef(
209 // find input +++++ currently matches by name only
210 vector
<media_input
> inputs
;
211 err
= inputRef
->getFreeInputs(
213 m_inputFormat.type*/);
219 for(unsigned int n
= 0; n
< inputs
.size(); ++n
) {
220 if(m_inputName
== inputs
[n
].name
) {
227 PRINT(("!!! input '%s' of node '%s' not found\n",
228 m_inputName
.String(),
230 return B_NAME_NOT_FOUND
;
235 if(m_requestedFormat
.type
!= B_MEDIA_NO_TYPE
)
236 err
= manager
->connect(
242 err
= manager
->connect(
255 // -------------------------------------------------------- //
256 // *** document-type setup
257 // -------------------------------------------------------- //
260 void ConnectionIO::AddTo(
261 XML::DocumentType
* docType
) {
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
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 // -------------------------------------------------------- //
280 // -------------------------------------------------------- //
282 // -------------------------------------------------------- //
284 // -------------------------------------------------------- //
287 // -------------------------------------------------------- //
288 void ConnectionIO::xmlExportBegin(
289 ExportContext
& context
) const {
293 "ConnectionIO::xmlExportBegin():\n"
294 "*** invalid ***\n");
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();
311 context
.beginElement(_OUTPUT_ELEMENT
);
312 context
.beginContent();
315 // LiveNodeIO nodeIO(
317 // dynamic_cast<NodeSetIOContext*>(&context),
319 context
.writeObject(m_outputNodeIO
);
321 // context.beginElement(_LIVE_NODE_ELEMENT);
322 // if(m_outputNodeKey.Length()) {
323 // context.writeAttr("key", m_outputNodeKey);
326 // _write_simple("name", m_outputNodeName.String(), context);
327 // _write_node_kinds(m_outputNodeKind, context);
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
345 context
.beginElement(_INPUT_ELEMENT
);
346 context
.beginContent();
349 // LiveNodeIO nodeIO(
351 // dynamic_cast<NodeSetIOContext*>(&context),
353 context
.writeObject(m_inputNodeIO
);
355 // context.beginElement(_LIVE_NODE_ELEMENT);
356 // if(m_inputNodeKey.Length()) {
357 // context.writeAttr("key", m_inputNodeKey);
360 // _write_simple("name", m_inputNodeName.String(), context);
361 // _write_node_kinds(m_inputNodeKind, context);
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 // -------------------------------------------------------- //
396 // -------------------------------------------------------- //
398 void ConnectionIO::xmlImportBegin(
399 ImportContext
& context
) { TOUCH(context
); }
401 void ConnectionIO::xmlImportAttribute(
404 ImportContext
& context
) { TOUCH(key
); TOUCH(value
); TOUCH(context
); }
406 void ConnectionIO::xmlImportContent(
409 ImportContext
& context
) { TOUCH(data
); TOUCH(length
); TOUCH(context
); }
411 void ConnectionIO::xmlImportChild(
413 ImportContext
& context
) {
417 if(!strcmp(context
.element(), _LIVE_NODE_ELEMENT
)) {
418 LiveNodeIO
* nodeIO
= dynamic_cast<LiveNodeIO
*>(child
);
421 // store the LiveNodeIO for now; it will be used in
424 switch(m_importState
) {
426 m_outputNodeIO
= nodeIO
;
427 child
= 0; // don't delete child object
431 m_inputNodeIO
= nodeIO
;
432 child
= 0; // don't delete child object
436 context
.reportError("Unexpected node description.\n");
441 else if(!strcmp(context
.element(), _NAME_ELEMENT
)) {
442 StringContent
* c
= dynamic_cast<StringContent
*>(child
);
445 switch(m_importState
) {
447 m_outputName
= c
->content
;
451 m_inputName
= c
->content
;
455 context
.reportError("Unexpected node name.\n");
461 MediaFormatIO
* io
= dynamic_cast<MediaFormatIO
*>(child
);
463 context
.reportError("Unexpected element.\n");
469 err
= io
->getFormat(f
);
471 context
.reportError("Malformed format.\n");
476 switch(m_importState
) {
486 m_requestedFormat
= f
;
495 void ConnectionIO::xmlImportComplete(
496 ImportContext
& context
) {
501 void ConnectionIO::xmlImportChildBegin(
503 ImportContext
& context
) {
505 if(!strcmp(name
, "input")) {
506 if(m_importState
!= IMPORT_NONE
) {
507 context
.reportError("ConnectionIO: unexpected nested child element\n");
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");
517 m_importState
= IMPORT_OUTPUT
;
520 context
.reportError("ConnectionIO: unexpected child element\n");
523 void ConnectionIO::xmlImportChildComplete(
525 ImportContext
& context
) {
526 TOUCH(name
); TOUCH(context
);
528 m_importState
= IMPORT_NONE
;
531 // END -- ConnectionIO.cpp --