* Copyright (c) 1999-2000, Eric Moon.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions, and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions, and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR "AS IS" AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
* TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "DormantNodeIO.h"
#include "ImportContext.h"
#include "ExportContext.h"
#include "StringContent.h"
#include "NodeManager.h"
#include <Debug.h>
#include <MediaAddOn.h>
#include <MediaDefs.h>
#include <MediaRoster.h>
#include <Path.h>
#include <cstdlib>
#include "route_app_io.h"
__USE_CORTEX_NAMESPACE
DormantNodeIO::~DormantNodeIO() {}
DormantNodeIO::DormantNodeIO() :
m_kinds(0LL),
m_flavorID(0),
m_flags(0),
m_runMode(0),
m_recordingDelay(0),
m_cycle(false),
m_exportValid(false) {}
DormantNodeIO::DormantNodeIO(
NodeRef* ref,
const char* nodeKey) :
m_exportValid(false) {
ASSERT(ref);
ASSERT(nodeKey);
status_t err;
m_nodeKey = nodeKey;
dormant_node_info info;
err = ref->getDormantNodeInfo(&info);
if(err < B_OK) {
PRINT((
"!!! DormantNodeIO(): getDormantNodeInfo() failed:\n"
" %s\n",
strerror(err)));
return;
}
dormant_flavor_info flavorInfo;
err = BMediaRoster::Roster()->GetDormantFlavorInfoFor(
info, &flavorInfo);
if(err < B_OK) {
PRINT((
"!!! DormantNodeIO(): GetDormantFlavorInfoFor() failed:\n"
" %s\n",
strerror(err)));
return;
}
m_dormantName = flavorInfo.name;
m_flavorID = info.flavor_id;
m_kinds = flavorInfo.kinds;
m_flags = ref->flags();
entry_ref file;
if(ref->getFile(&file) == B_OK)
m_entry.SetTo(&file);
m_runMode = ref->runMode();
m_recordingDelay = ref->recordingDelay();
m_cycle = ref->isCycling();
m_exportValid = true;
}
void DormantNodeIO::AddTo(
XML::DocumentType* docType) {
docType->addMapping(new Mapping<DormantNodeIO>(_DORMANT_NODE_ELEMENT));
}
status_t DormantNodeIO::instantiate(
NodeManager* manager,
NodeRef** outRef) {
status_t err;
BPath p;
if(m_entry.InitCheck() == B_OK)
m_entry.GetPath(&p);
dormant_node_info info;
err = _matchDormantNode(&info);
if(err < B_OK) {
PRINT((
"!!! _matchDormantNode() failed: %s\n", strerror(err)));
return err;
}
err = manager->instantiate(
info,
outRef,
B_INFINITE_TIMEOUT,
m_flags);
if(err < B_OK) {
PRINT((
"!!! instantiate() failed: %s\n", strerror(err)));
return err;
}
entry_ref mediaRef;
if(m_entry.InitCheck() == B_OK && m_entry.GetRef(&mediaRef) == B_OK) {
err = (*outRef)->setFile(mediaRef);
if(err < B_OK) {
PRINT((
"!!! WARNING: setFile() failed: %s\n", strerror(err)));
}
}
if(m_runMode)
(*outRef)->setRunMode(m_runMode, m_recordingDelay);
if(m_cycle)
(*outRef)->setCycling(true);
return B_OK;
}
status_t DormantNodeIO::_matchDormantNode(
dormant_node_info* outInfo) {
status_t err;
const int32 bufferSize = 32;
dormant_node_info buffer[bufferSize];
int32 count = bufferSize;
err = BMediaRoster::Roster()->GetDormantNodes(
buffer,
&count,
0,
0,
m_dormantName.String(),
m_kinds,
0 );
if(err < B_OK)
return err;
if(!count)
return B_NAME_NOT_FOUND;
for(int32 n = 0; n < count; ++n) {
if(buffer[n].flavor_id == m_flavorID) {
*outInfo = buffer[n];
return B_OK;
}
}
return B_BAD_INDEX;
}
void DormantNodeIO::xmlExportBegin(
ExportContext& context) const {
if(!m_exportValid) {
context.reportError(
"DormantNodeIO::xmlExportBegin():\n"
"*** invalid ***\n");
return;
}
context.beginElement(_DORMANT_NODE_ELEMENT);
}
void DormantNodeIO::xmlExportAttributes(
ExportContext& context) const {
context.writeAttr("key", m_nodeKey);
}
void DormantNodeIO::xmlExportContent(
ExportContext& context) const {
context.beginContent();
BString buffer;
context.beginElement(_NAME_ELEMENT);
context.beginContent();
context.writeString(m_dormantName);
context.endElement();
if(m_flavorID > 0) {
buffer = "";
buffer << m_flavorID;
context.beginElement(_FLAVOR_ID_ELEMENT);
context.beginContent();
context.writeString(buffer);
context.endElement();
}
_write_node_kinds(m_kinds, context);
if(m_flags & NodeRef::NO_START_STOP)
_write_simple(_FLAG_ELEMENT, "NO_START_STOP", context);
if(m_flags & NodeRef::NO_SEEK)
_write_simple(_FLAG_ELEMENT, "NO_SEEK", context);
if(m_flags & NodeRef::NO_PREROLL)
_write_simple(_FLAG_ELEMENT, "NO_PREROLL", context);
if(m_flags & NodeRef::NO_STOP)
_write_simple(_FLAG_ELEMENT, "NO_STOP", context);
if(m_flags & NodeRef::NO_ROSTER_WATCH)
_write_simple(_FLAG_ELEMENT, "NO_ROSTER_WATCH", context);
if(m_flags & NodeRef::NO_POSITION_REPORTING)
_write_simple(_FLAG_ELEMENT, "NO_POSITION_REPORTING", context);
if(m_runMode > 0) {
switch(m_runMode) {
case BMediaNode::B_OFFLINE:
_write_simple(_RUN_MODE_ELEMENT, "B_OFFLINE", context);
break;
case BMediaNode::B_DECREASE_PRECISION:
_write_simple(_RUN_MODE_ELEMENT, "B_DECREASE_PRECISION", context);
break;
case BMediaNode::B_INCREASE_LATENCY:
_write_simple(_RUN_MODE_ELEMENT, "B_INCREASE_LATENCY", context);
break;
case BMediaNode::B_DROP_DATA:
_write_simple(_RUN_MODE_ELEMENT, "B_DROP_DATA", context);
break;
case BMediaNode::B_RECORDING:
_write_simple(_RUN_MODE_ELEMENT, "B_RECORDING", context);
buffer = "";
buffer << m_recordingDelay;
_write_simple(_RECORDING_DELAY_ELEMENT, buffer.String(), context);
break;
default:
buffer = "";
buffer << m_runMode;
_write_simple(_RUN_MODE_ELEMENT, buffer.String(), context);
}
}
if(m_cycle) {
context.beginElement(_CYCLE_ELEMENT);
context.endElement();
}
BPath p;
if(
m_entry.InitCheck() == B_OK &&
m_entry.GetPath(&p) == B_OK)
_write_simple(_REF_ELEMENT, p.Path(), context);
}
void DormantNodeIO::xmlExportEnd(
ExportContext& context) const {
context.endElement();
}
inline void _read_noderef_flag(
int32& ioFlags,
const char* data,
ImportContext& context) {
if(!strcmp(data, "NO_START_STOP"))
ioFlags |= NodeRef::NO_START_STOP;
else if(!strcmp(data, "NO_SEEK"))
ioFlags |= NodeRef::NO_SEEK;
else if(!strcmp(data, "NO_PREROLL"))
ioFlags |= NodeRef::NO_PREROLL;
else if(!strcmp(data, "NO_STOP"))
ioFlags |= NodeRef::NO_STOP;
else if(!strcmp(data, "NO_ROSTER_WATCH"))
ioFlags |= NodeRef::NO_ROSTER_WATCH;
else if(!strcmp(data, "NO_POSITION_REPORTING"))
ioFlags |= NodeRef::NO_POSITION_REPORTING;
else {
BString err;
err << "_read_noderef_flag(): unknown node flag '" << data << "'\n";
context.reportWarning(err.String());
}
}
inline void _read_run_mode(
int32& runMode,
const char* data,
ImportContext& context) {
if(!strcmp(data, "B_OFFLINE"))
runMode = BMediaNode::B_OFFLINE;
else if(!strcmp(data, "B_DECREASE_PRECISION"))
runMode = BMediaNode::B_DECREASE_PRECISION;
else if(!strcmp(data, "B_INCREASE_LATENCY"))
runMode = BMediaNode::B_INCREASE_LATENCY;
else if(!strcmp(data, "B_DROP_DATA"))
runMode = BMediaNode::B_DROP_DATA;
else if(!strcmp(data, "B_RECORDING"))
runMode = BMediaNode::B_RECORDING;
else {
BString err;
err << "_read_run_mode(): unknown run mode '" << data << "'\n";
context.reportWarning(err.String());
}
}
inline void _read_entry(
BEntry& entry,
const char* data,
ImportContext& context) {
entry_ref r;
status_t err = get_ref_for_path(data, &r);
if(err < B_OK) {
BString text;
text << "_read_entry_ref(): get_ref_for_path('" << data << "') failed:\n"
" " << strerror(err) << "\n";
context.reportWarning(text.String());
}
entry.SetTo(&r);
}
void DormantNodeIO::xmlImportBegin(
ImportContext& context) { TOUCH(context); }
void DormantNodeIO::xmlImportAttribute(
const char* key,
const char* value,
ImportContext& context) {
if(!strcmp(key, "key")) {
m_nodeKey = value;
}
else {
BString err;
err << "DormantNodeIO: unknown attribute '" << key << "'\n";
context.reportError(err.String());
}
}
void DormantNodeIO::xmlImportContent(
const char* data,
uint32 length,
ImportContext& context) { TOUCH(data); TOUCH(length); TOUCH(context); }
void DormantNodeIO::xmlImportChild(
IPersistent* child,
ImportContext& context) {
StringContent* obj = dynamic_cast<StringContent*>(child);
if(!obj) {
BString err;
err << "DormantNodeIO: unexpected element '" <<
context.element() << "'\n";
context.reportError(err.String());
return;
}
if(!strcmp(context.element(), _NAME_ELEMENT))
m_dormantName = obj->content;
else if(!strcmp(context.element(), _KIND_ELEMENT))
_read_node_kind(m_kinds, obj->content.String(), context);
else if(!strcmp(context.element(), _FLAVOR_ID_ELEMENT))
m_flavorID = atol(obj->content.String());
else if(!strcmp(context.element(), _FLAG_ELEMENT))
_read_noderef_flag(m_flags, obj->content.String(), context);
else if(!strcmp(context.element(), _RUN_MODE_ELEMENT))
_read_run_mode(m_runMode, obj->content.String(), context);
else if(!strcmp(context.element(), _RECORDING_DELAY_ELEMENT))
m_recordingDelay = strtoll(obj->content.String(), 0, 10);
else if(!strcmp(context.element(), _CYCLE_ELEMENT))
m_cycle = true;
else if(!strcmp(context.element(), _REF_ELEMENT))
_read_entry(m_entry, obj->content.String(), context);
else {
BString err;
err << "DormantNodeIO: unexpected element '" <<
context.element() << "'\n";
context.reportError(err.String());
}
delete child;
}
void DormantNodeIO::xmlImportComplete(
ImportContext& context) { TOUCH(context); }