mirror of
https://github.com/Ardour/ardour.git
synced 2025-12-09 16:24:57 +01:00
* splitted midi++/event.h in header and implementation
* added to_string(), to_xml() and from_xml() to MIDI::Event * added partial support for midnam-Patchfiles (http://www.sonosphere.com/dtds/MIDINameDocument.dtd): midnam_patch.h/.cc * added validation support to xml++.cc/.h * added XMLNode::add_property(const char *name, const long value) * added test to pbd/tests/xpath.cc git-svn-id: svn://localhost/ardour2/branches/3.0@3412 d708f5d6-7413-0410-9779-e7cbd77b26cf
This commit is contained in:
parent
5c60257b4a
commit
911c5717bc
9 changed files with 445 additions and 82 deletions
|
|
@ -25,12 +25,14 @@ midi2.Append(DOMAIN=domain,MAJOR=2,MINOR=1,MICRO=1)
|
||||||
sources = Split("""
|
sources = Split("""
|
||||||
fd_midiport.cc
|
fd_midiport.cc
|
||||||
fifomidi.cc
|
fifomidi.cc
|
||||||
|
event.cc
|
||||||
midi.cc
|
midi.cc
|
||||||
midichannel.cc
|
midichannel.cc
|
||||||
midifactory.cc
|
midifactory.cc
|
||||||
midimanager.cc
|
midimanager.cc
|
||||||
midiparser.cc
|
midiparser.cc
|
||||||
midiport.cc
|
midiport.cc
|
||||||
|
midnam_patch.cc
|
||||||
mmc.cc
|
mmc.cc
|
||||||
mtc.cc
|
mtc.cc
|
||||||
version.cc
|
version.cc
|
||||||
|
|
|
||||||
97
libs/midi++2/event.cc
Normal file
97
libs/midi++2/event.cc
Normal file
|
|
@ -0,0 +1,97 @@
|
||||||
|
#include "midi++/event.h"
|
||||||
|
|
||||||
|
namespace MIDI {
|
||||||
|
|
||||||
|
#ifdef MIDI_EVENT_ALLOW_ALLOC
|
||||||
|
Event::Event(double t, uint32_t s, uint8_t* b, bool owns_buffer)
|
||||||
|
: _time(t)
|
||||||
|
, _size(s)
|
||||||
|
, _buffer(b)
|
||||||
|
, _owns_buffer(owns_buffer)
|
||||||
|
{
|
||||||
|
if (owns_buffer) {
|
||||||
|
_buffer = (uint8_t*)malloc(_size);
|
||||||
|
if (b) {
|
||||||
|
memcpy(_buffer, b, _size);
|
||||||
|
} else {
|
||||||
|
memset(_buffer, 0, _size);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Event::Event(const XMLNode& event)
|
||||||
|
{
|
||||||
|
string name = event.name();
|
||||||
|
|
||||||
|
if (name == "ControlChange") {
|
||||||
|
|
||||||
|
} else if (name == "ProgramChange") {
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Event::Event(const Event& copy, bool owns_buffer)
|
||||||
|
: _time(copy._time)
|
||||||
|
, _size(copy._size)
|
||||||
|
, _buffer(copy._buffer)
|
||||||
|
, _owns_buffer(owns_buffer)
|
||||||
|
{
|
||||||
|
if (owns_buffer) {
|
||||||
|
_buffer = (uint8_t*)malloc(_size);
|
||||||
|
if (copy._buffer) {
|
||||||
|
memcpy(_buffer, copy._buffer, _size);
|
||||||
|
} else {
|
||||||
|
memset(_buffer, 0, _size);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Event::~Event() {
|
||||||
|
if (_owns_buffer) {
|
||||||
|
free(_buffer);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#endif // MIDI_EVENT_ALLOW_ALLOC
|
||||||
|
|
||||||
|
std::string
|
||||||
|
Event::to_string() const
|
||||||
|
{
|
||||||
|
std::ostringstream result(std::ios::ate);
|
||||||
|
result << "MIDI::Event type:" << std::hex << "0x" << int(type()) << " buffer: ";
|
||||||
|
|
||||||
|
for(uint32_t i = 0; i < size(); ++i) {
|
||||||
|
result << " 0x" << int(_buffer[i]);
|
||||||
|
}
|
||||||
|
return result.str();
|
||||||
|
}
|
||||||
|
|
||||||
|
boost::shared_ptr<XMLNode>
|
||||||
|
Event::to_xml() const
|
||||||
|
{
|
||||||
|
XMLNode *result = 0;
|
||||||
|
|
||||||
|
switch (type()) {
|
||||||
|
case MIDI_CMD_CONTROL:
|
||||||
|
result = new XMLNode("ControlChange");
|
||||||
|
result->add_property("Channel", channel());
|
||||||
|
result->add_property("Control", cc_number());
|
||||||
|
result->add_property("Value", cc_value());
|
||||||
|
break;
|
||||||
|
|
||||||
|
case MIDI_CMD_PGM_CHANGE:
|
||||||
|
result = new XMLNode("ProgramChange");
|
||||||
|
result->add_property("Channel", channel());
|
||||||
|
result->add_property("number", pgm_number());
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
// The implementation is continued as needed
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return boost::shared_ptr<XMLNode>(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace MIDI
|
||||||
|
|
@ -29,6 +29,7 @@
|
||||||
|
|
||||||
#include <midi++/types.h>
|
#include <midi++/types.h>
|
||||||
#include <midi++/events.h>
|
#include <midi++/events.h>
|
||||||
|
#include <pbd/xml++.h>
|
||||||
|
|
||||||
/** If this is not defined, all methods of MidiEvent are RT safe
|
/** If this is not defined, all methods of MidiEvent are RT safe
|
||||||
* but MidiEvent will never deep copy and (depending on the scenario)
|
* but MidiEvent will never deep copy and (depending on the scenario)
|
||||||
|
|
@ -46,21 +47,7 @@ namespace MIDI {
|
||||||
*/
|
*/
|
||||||
struct Event {
|
struct Event {
|
||||||
#ifdef MIDI_EVENT_ALLOW_ALLOC
|
#ifdef MIDI_EVENT_ALLOW_ALLOC
|
||||||
Event(double t=0, uint32_t s=0, uint8_t* b=NULL, bool owns_buffer=false)
|
Event(double t=0, uint32_t s=0, uint8_t* b=NULL, bool owns_buffer=false);
|
||||||
: _time(t)
|
|
||||||
, _size(s)
|
|
||||||
, _buffer(b)
|
|
||||||
, _owns_buffer(owns_buffer)
|
|
||||||
{
|
|
||||||
if (owns_buffer) {
|
|
||||||
_buffer = (uint8_t*)malloc(_size);
|
|
||||||
if (b) {
|
|
||||||
memcpy(_buffer, b, _size);
|
|
||||||
} else {
|
|
||||||
memset(_buffer, 0, _size);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Copy \a copy.
|
/** Copy \a copy.
|
||||||
*
|
*
|
||||||
|
|
@ -68,27 +55,14 @@ struct Event {
|
||||||
* is NOT REALTIME SAFE. Otherwise both events share a buffer and
|
* is NOT REALTIME SAFE. Otherwise both events share a buffer and
|
||||||
* memory management semantics are the caller's problem.
|
* memory management semantics are the caller's problem.
|
||||||
*/
|
*/
|
||||||
Event(const Event& copy, bool owns_buffer)
|
Event(const Event& copy, bool owns_buffer);
|
||||||
: _time(copy._time)
|
|
||||||
, _size(copy._size)
|
|
||||||
, _buffer(copy._buffer)
|
|
||||||
, _owns_buffer(owns_buffer)
|
|
||||||
{
|
|
||||||
if (owns_buffer) {
|
|
||||||
_buffer = (uint8_t*)malloc(_size);
|
|
||||||
if (copy._buffer) {
|
|
||||||
memcpy(_buffer, copy._buffer, _size);
|
|
||||||
} else {
|
|
||||||
memset(_buffer, 0, _size);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
~Event() {
|
/**
|
||||||
if (_owns_buffer) {
|
* see the MIDI XML specification: http://www.midi.org/dtds/MIDIEvents10.dtd
|
||||||
free(_buffer);
|
*/
|
||||||
}
|
Event(const XMLNode &event);
|
||||||
}
|
|
||||||
|
~Event();
|
||||||
|
|
||||||
inline const Event& operator=(const Event& copy) {
|
inline const Event& operator=(const Event& copy) {
|
||||||
_time = copy._time;
|
_time = copy._time;
|
||||||
|
|
@ -179,6 +153,7 @@ struct Event {
|
||||||
_size = size;
|
_size = size;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#else
|
#else
|
||||||
|
|
||||||
inline void set_buffer(uint8_t* buf) { _buffer = buf; }
|
inline void set_buffer(uint8_t* buf) { _buffer = buf; }
|
||||||
|
|
@ -218,15 +193,16 @@ struct Event {
|
||||||
inline bool is_sysex() const { return _buffer[0] == 0xF0 || _buffer[0] == 0xF7; }
|
inline bool is_sysex() const { return _buffer[0] == 0xF0 || _buffer[0] == 0xF7; }
|
||||||
inline const uint8_t* buffer() const { return _buffer; }
|
inline const uint8_t* buffer() const { return _buffer; }
|
||||||
inline uint8_t*& buffer() { return _buffer; }
|
inline uint8_t*& buffer() { return _buffer; }
|
||||||
inline std::string to_string() const {
|
|
||||||
std::ostringstream result(std::ios::ate);
|
|
||||||
result << "MIDI::Event type:" << std::hex << "0x" << int(type()) << " buffer: ";
|
|
||||||
|
|
||||||
for(uint32_t i = 0; i < size(); ++i) {
|
/**
|
||||||
result << " 0x" << int(_buffer[i]);
|
* mainly used for debugging purposes
|
||||||
}
|
*/
|
||||||
return result.str();
|
std::string to_string() const;
|
||||||
}
|
|
||||||
|
/**
|
||||||
|
* see the MIDI XML specification: http://www.midi.org/dtds/MIDIEvents10.dtd
|
||||||
|
*/
|
||||||
|
boost::shared_ptr<XMLNode> to_xml() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
double _time; /**< Sample index (or beat time) at which event is valid */
|
double _time; /**< Sample index (or beat time) at which event is valid */
|
||||||
|
|
|
||||||
96
libs/midi++2/midi++/midnam_patch.h
Normal file
96
libs/midi++2/midi++/midnam_patch.h
Normal file
|
|
@ -0,0 +1,96 @@
|
||||||
|
#ifndef MIDNAM_PATCH_H_
|
||||||
|
#define MIDNAM_PATCH_H_
|
||||||
|
|
||||||
|
#include "pbd/stateful.h"
|
||||||
|
#include "midi++/event.h"
|
||||||
|
#include "pbd/xml++.h"
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
#include <list>
|
||||||
|
#include <set>
|
||||||
|
|
||||||
|
namespace MIDI
|
||||||
|
{
|
||||||
|
|
||||||
|
namespace Name
|
||||||
|
{
|
||||||
|
|
||||||
|
class Patch : public PBD::Stateful
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
typedef std::list<MIDI::Event> PatchMidiCommands;
|
||||||
|
|
||||||
|
Patch() {};
|
||||||
|
Patch(string a_number, string a_name) : _number(a_number), _name(a_name) {};
|
||||||
|
~Patch() {};
|
||||||
|
|
||||||
|
const string& name() const { return _name; }
|
||||||
|
void set_name(const string a_name) { _name = a_name; }
|
||||||
|
|
||||||
|
const string& number() const { return _number; }
|
||||||
|
void set_number(const string a_number) { _number = a_number; }
|
||||||
|
|
||||||
|
const PatchMidiCommands& patch_midi_commands() const { return _patch_midi_commands; }
|
||||||
|
|
||||||
|
XMLNode& get_state (void);
|
||||||
|
int set_state (const XMLNode& a_node);
|
||||||
|
|
||||||
|
private:
|
||||||
|
string _number;
|
||||||
|
string _name;
|
||||||
|
PatchMidiCommands _patch_midi_commands;
|
||||||
|
};
|
||||||
|
|
||||||
|
class PatchBank : public PBD::Stateful
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
typedef std::list<Patch> PatchNameList;
|
||||||
|
|
||||||
|
PatchBank() {};
|
||||||
|
virtual ~PatchBank() {};
|
||||||
|
PatchBank(string a_name) : _name(a_name) {};
|
||||||
|
|
||||||
|
const string& name() const { return _name; }
|
||||||
|
void set_name(const string a_name) { _name = a_name; }
|
||||||
|
|
||||||
|
const PatchNameList& patch_name_list() const { return _patch_name_list; }
|
||||||
|
|
||||||
|
XMLNode& get_state (void);
|
||||||
|
int set_state (const XMLNode& a_node);
|
||||||
|
|
||||||
|
private:
|
||||||
|
string _name;
|
||||||
|
PatchNameList _patch_name_list;
|
||||||
|
};
|
||||||
|
|
||||||
|
class ChannelNameSet : public PBD::Stateful
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
typedef std::set<uint8_t> AvailableForChannels;
|
||||||
|
typedef std::list<PatchBank> PatchBanks;
|
||||||
|
|
||||||
|
ChannelNameSet() {};
|
||||||
|
virtual ~ChannelNameSet() {};
|
||||||
|
ChannelNameSet(string a_name) : _name(a_name) {};
|
||||||
|
|
||||||
|
const string& name() const { return _name; }
|
||||||
|
void set_name(const string a_name) { _name = a_name; }
|
||||||
|
|
||||||
|
const AvailableForChannels& available_for_channels() const { return _available_for_channels; }
|
||||||
|
const PatchBanks& patch_banks() const { return _patch_banks; }
|
||||||
|
|
||||||
|
XMLNode& get_state (void);
|
||||||
|
int set_state (const XMLNode& a_node);
|
||||||
|
|
||||||
|
private:
|
||||||
|
string _name;
|
||||||
|
AvailableForChannels _available_for_channels;
|
||||||
|
PatchBanks _patch_banks;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /*MIDNAM_PATCH_H_*/
|
||||||
137
libs/midi++2/midnam_patch.cc
Normal file
137
libs/midi++2/midnam_patch.cc
Normal file
|
|
@ -0,0 +1,137 @@
|
||||||
|
#include "midi++/midnam_patch.h"
|
||||||
|
#include <algorithm>
|
||||||
|
|
||||||
|
namespace MIDI
|
||||||
|
{
|
||||||
|
|
||||||
|
namespace Name
|
||||||
|
{
|
||||||
|
|
||||||
|
XMLNode&
|
||||||
|
Patch::get_state (void)
|
||||||
|
{
|
||||||
|
XMLNode* node = new XMLNode("Patch");
|
||||||
|
node->add_property("Number", _number);
|
||||||
|
node->add_property("Name", _name);
|
||||||
|
XMLNode* commands = node->add_child("PatchMIDICommands");
|
||||||
|
for (PatchMidiCommands::const_iterator event = _patch_midi_commands.begin();
|
||||||
|
event != _patch_midi_commands.end();
|
||||||
|
++event) {
|
||||||
|
commands->add_child_copy(*(event->to_xml()));
|
||||||
|
}
|
||||||
|
|
||||||
|
return *node;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
Patch::set_state (const XMLNode& node)
|
||||||
|
{
|
||||||
|
assert(node.name() == "Patch");
|
||||||
|
_number = node.property("Number")->value();
|
||||||
|
_name = node.property("Name")->value();
|
||||||
|
XMLNode* commands = node.child("PatchMIDICommands");
|
||||||
|
assert(commands);
|
||||||
|
const XMLNodeList events = commands->children();
|
||||||
|
for (XMLNodeList::const_iterator i = events.begin(); i != events.end(); ++i) {
|
||||||
|
_patch_midi_commands.push_back(*(new Event(*(*i))));
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
XMLNode&
|
||||||
|
PatchBank::get_state (void)
|
||||||
|
{
|
||||||
|
XMLNode* node = new XMLNode("PatchBank");
|
||||||
|
node->add_property("Name", _name);
|
||||||
|
XMLNode* patch_name_list = node->add_child("PatchNameList");
|
||||||
|
for (PatchNameList::iterator patch = _patch_name_list.begin();
|
||||||
|
patch != _patch_name_list.end();
|
||||||
|
++patch) {
|
||||||
|
patch_name_list->add_child_nocopy(patch->get_state());
|
||||||
|
}
|
||||||
|
|
||||||
|
return *node;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
PatchBank::set_state (const XMLNode& node)
|
||||||
|
{
|
||||||
|
assert(node.name() == "PatchBank");
|
||||||
|
_name = node.property("Name")->value();
|
||||||
|
XMLNode* patch_name_list = node.child("PatchNameList");
|
||||||
|
assert(patch_name_list);
|
||||||
|
const XMLNodeList patches = patch_name_list->children();
|
||||||
|
for (XMLNodeList::const_iterator i = patches.begin(); i != patches.end(); ++i) {
|
||||||
|
Patch patch;
|
||||||
|
patch.set_state(*(*i));
|
||||||
|
_patch_name_list.push_back(patch);
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
XMLNode&
|
||||||
|
ChannelNameSet::get_state (void)
|
||||||
|
{
|
||||||
|
XMLNode* node = new XMLNode("ChannelNameSet");
|
||||||
|
node->add_property("Name", _name);
|
||||||
|
|
||||||
|
XMLNode* available_for_channels = node->add_child("AvailableForChannels");
|
||||||
|
assert(available_for_channels);
|
||||||
|
|
||||||
|
for (uint8_t channel = 0; channel < 16; ++channel) {
|
||||||
|
XMLNode* available_channel = available_for_channels->add_child("AvailableChannel");
|
||||||
|
assert(available_channel);
|
||||||
|
|
||||||
|
available_channel->add_property("Channel", (long) channel);
|
||||||
|
|
||||||
|
if (_available_for_channels.find(channel) != _available_for_channels.end()) {
|
||||||
|
available_channel->add_property("Available", "true");
|
||||||
|
} else {
|
||||||
|
available_channel->add_property("Available", "false");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (PatchBanks::iterator patch_bank = _patch_banks.begin();
|
||||||
|
patch_bank != _patch_banks.end();
|
||||||
|
++patch_bank) {
|
||||||
|
node->add_child_nocopy(patch_bank->get_state());
|
||||||
|
}
|
||||||
|
|
||||||
|
return *node;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
ChannelNameSet::set_state (const XMLNode& node)
|
||||||
|
{
|
||||||
|
assert(node.name() == "ChannelNameSet");
|
||||||
|
_name = node.property("Name")->value();
|
||||||
|
const XMLNodeList children = node.children();
|
||||||
|
for (XMLNodeList::const_iterator i = children.begin(); i != children.end(); ++i) {
|
||||||
|
XMLNode* node = *i;
|
||||||
|
assert(node);
|
||||||
|
if (node->name() == "AvailableForChannels") {
|
||||||
|
boost::shared_ptr<XMLSharedNodeList> channels =
|
||||||
|
node->find("//AvailableChannel[@Available = 'true']/@Channel");
|
||||||
|
for(XMLSharedNodeList::const_iterator i = channels->begin();
|
||||||
|
i != channels->end();
|
||||||
|
++i) {
|
||||||
|
_available_for_channels.insert(atoi((*i)->attribute_value().c_str()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (node->name() == "PatchBank") {
|
||||||
|
PatchBank bank;
|
||||||
|
bank.set_state(*node);
|
||||||
|
_patch_banks.push_back(bank);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
} //namespace Name
|
||||||
|
|
||||||
|
} //namespace MIDI
|
||||||
|
|
||||||
|
|
@ -39,10 +39,11 @@ private:
|
||||||
string _filename;
|
string _filename;
|
||||||
XMLNode *_root;
|
XMLNode *_root;
|
||||||
int _compression;
|
int _compression;
|
||||||
|
bool read_internal(bool validate);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
XMLTree();
|
XMLTree();
|
||||||
XMLTree(const string &fn);
|
XMLTree(const string &fn, bool validate = false);
|
||||||
XMLTree(const XMLTree *);
|
XMLTree(const XMLTree *);
|
||||||
~XMLTree();
|
~XMLTree();
|
||||||
|
|
||||||
|
|
@ -55,8 +56,10 @@ public:
|
||||||
int compression() const { return _compression; };
|
int compression() const { return _compression; };
|
||||||
int set_compression(int);
|
int set_compression(int);
|
||||||
|
|
||||||
bool read();
|
bool read() { return read_internal(false); };
|
||||||
bool read(const string &fn) { set_filename(fn); return read(); };
|
bool read(const string &fn) { set_filename(fn); return read_internal(false); };
|
||||||
|
bool read_and_validate() { return read_internal(true); };
|
||||||
|
bool read_and_validate(const string &fn) { set_filename(fn); return read_internal(true); };
|
||||||
bool read_buffer(const string &);
|
bool read_buffer(const string &);
|
||||||
|
|
||||||
bool write() const;
|
bool write() const;
|
||||||
|
|
@ -77,9 +80,9 @@ private:
|
||||||
XMLPropertyMap _propmap;
|
XMLPropertyMap _propmap;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
XMLNode(const string &);
|
XMLNode(const string& name);
|
||||||
XMLNode(const string &, const string &);
|
XMLNode(const string& name, const string& content);
|
||||||
XMLNode(const XMLNode&);
|
XMLNode(const XMLNode& other);
|
||||||
~XMLNode();
|
~XMLNode();
|
||||||
|
|
||||||
const string name() const { return _name; };
|
const string name() const { return _name; };
|
||||||
|
|
@ -105,8 +108,9 @@ public:
|
||||||
{ return ((XMLNode *) this)->property(n); };
|
{ return ((XMLNode *) this)->property(n); };
|
||||||
const XMLProperty *property(const std::string& ns) const
|
const XMLProperty *property(const std::string& ns) const
|
||||||
{ return ((XMLNode *) this)->property(ns); };
|
{ return ((XMLNode *) this)->property(ns); };
|
||||||
XMLProperty *add_property(const char *, const string &);
|
XMLProperty *add_property(const char *name, const string& value);
|
||||||
XMLProperty *add_property(const char *, const char * = "");
|
XMLProperty *add_property(const char *name, const char *value = "");
|
||||||
|
XMLProperty *add_property(const char *name, const long value);
|
||||||
|
|
||||||
void remove_property(const string &);
|
void remove_property(const string &);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
test: xpath
|
test: xpath
|
||||||
LD_LIBRARY_PATH=..:../../sigc++2:../../glibmm2 ./xpath
|
LD_LIBRARY_PATH=..:../../sigc++2:../../glibmm2 ./xpath
|
||||||
LD_LIBRARY_PATH=..:../../sigc++2:../../glibmm2 gprof ./xpath
|
LD_LIBRARY_PATH=..:../../sigc++2:../../glibmm2 gprof ./xpath > gprof.out
|
||||||
|
|
||||||
xpath: xpath.cc
|
xpath: xpath.cc
|
||||||
gcc -o $@ -g -pg -I.. `xml2-config --libs --cflags` -L.. -L../../sigc++2 -L../../glibmm2 -lstdc++ -lpbd -lglibmm2 -lsigc++2 $<
|
gcc -o $@ -g -pg -I.. `xml2-config --libs --cflags` -L.. -L../../sigc++2 -L../../glibmm2 -lstdc++ -lpbd -lglibmm2 -lsigc++2 $<
|
||||||
|
|
@ -83,4 +83,16 @@ int main()
|
||||||
cout << "\t found attribute node: " << node->name()
|
cout << "\t found attribute node: " << node->name()
|
||||||
<< " value: " << node->attribute_value() << endl;
|
<< " value: " << node->attribute_value() << endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
cout << endl << endl << "Test 6: ProtoolsPatchFile.midnam: Find available channels on 'Name Set 1'" << endl;
|
||||||
|
result = doc3.root()->find(
|
||||||
|
"//ChannelNameSet[@Name = 'Name Set 1']//AvailableChannel[@Available = 'true']/@Channel");
|
||||||
|
|
||||||
|
assert(result->size() == 15);
|
||||||
|
for(XMLSharedNodeList::const_iterator i = result->begin(); i != result->end(); ++i) {
|
||||||
|
boost::shared_ptr<XMLNode> node = (*i);
|
||||||
|
cout << "\t found available Channel: " << node->name()
|
||||||
|
<< " value: " << node->attribute_value() << endl;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -22,12 +22,12 @@ XMLTree::XMLTree()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
XMLTree::XMLTree(const string &fn)
|
XMLTree::XMLTree(const string &fn, bool validate)
|
||||||
: _filename(fn),
|
: _filename(fn),
|
||||||
_root(0),
|
_root(0),
|
||||||
_compression(0)
|
_compression(0)
|
||||||
{
|
{
|
||||||
read();
|
read_internal(validate);
|
||||||
}
|
}
|
||||||
|
|
||||||
XMLTree::XMLTree(const XMLTree * from)
|
XMLTree::XMLTree(const XMLTree * from)
|
||||||
|
|
@ -59,24 +59,55 @@ XMLTree::set_compression(int c)
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
XMLTree::read(void)
|
XMLTree::read_internal(bool validate)
|
||||||
{
|
{
|
||||||
xmlDocPtr doc;
|
//shouldnt be used anywhere ATM, remove if so!
|
||||||
|
assert(!validate);
|
||||||
if (_root) {
|
if (_root) {
|
||||||
delete _root;
|
delete _root;
|
||||||
_root = 0;
|
_root = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
xmlKeepBlanksDefault(0);
|
xmlParserCtxtPtr ctxt; /* the parser context */
|
||||||
|
xmlDocPtr doc; /* the resulting document tree */
|
||||||
|
|
||||||
doc = xmlParseFile(_filename.c_str());
|
xmlKeepBlanksDefault(0);
|
||||||
if (!doc) {
|
/* parse the file, activating the DTD validation option */
|
||||||
|
if(validate) {
|
||||||
|
/* create a parser context */
|
||||||
|
ctxt = xmlNewParserCtxt();
|
||||||
|
if (ctxt == NULL) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
doc = xmlCtxtReadFile(ctxt, _filename.c_str(), NULL, XML_PARSE_DTDVALID);
|
||||||
|
} else {
|
||||||
|
doc = xmlParseFile(_filename.c_str());
|
||||||
|
}
|
||||||
|
|
||||||
|
/* check if parsing suceeded */
|
||||||
|
if (doc == NULL) {
|
||||||
|
if(validate) {
|
||||||
|
xmlFreeParserCtxt(ctxt);
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
} else {
|
||||||
|
/* check if validation suceeded */
|
||||||
|
if (validate && ctxt->valid == 0) {
|
||||||
|
xmlFreeParserCtxt(ctxt);
|
||||||
|
xmlFreeDoc(doc);
|
||||||
|
xmlCleanupParser();
|
||||||
|
throw XMLException("Failed to validate document " + _filename);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
_root = readnode(xmlDocGetRootElement(doc));
|
_root = readnode(xmlDocGetRootElement(doc));
|
||||||
|
|
||||||
|
/* free up the parser context */
|
||||||
|
if(validate) {
|
||||||
|
xmlFreeParserCtxt(ctxt);
|
||||||
|
}
|
||||||
xmlFreeDoc(doc);
|
xmlFreeDoc(doc);
|
||||||
|
xmlCleanupParser();
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
@ -370,6 +401,14 @@ XMLNode::add_property(const char * n, const char * v)
|
||||||
return add_property(n, vs);
|
return add_property(n, vs);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
XMLProperty *
|
||||||
|
XMLNode::add_property(const char *name, const long value)
|
||||||
|
{
|
||||||
|
static char str[1024];
|
||||||
|
snprintf(str, 1024, "%ld", value);
|
||||||
|
return add_property(name, str);
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
XMLNode::remove_property(const string & n)
|
XMLNode::remove_property(const string & n)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue