mirror of
https://github.com/Ardour/ardour.git
synced 2025-12-11 00:56:33 +01:00
* added midnam test file for xpath
* added to_string() to MIDI::Event * added XMLNode::attribute_value for attribute nodes * debugging output in MidiModel (incorrect rendering of Pitchbender events: Notes lost * added xpath tests for midnam files git-svn-id: svn://localhost/ardour2/branches/3.0@3406 d708f5d6-7413-0410-9779-e7cbd77b26cf
This commit is contained in:
parent
5e856e94ac
commit
4aa9d17ab1
7 changed files with 11816 additions and 10 deletions
|
|
@ -180,9 +180,7 @@ const MidiModel::const_iterator& MidiModel::const_iterator::operator++()
|
||||||
|
|
||||||
assert(_event->buffer() && _event->buffer()[0] != '\0');
|
assert(_event->buffer() && _event->buffer()[0] != '\0');
|
||||||
|
|
||||||
/*cerr << "const_iterator::operator++: _event type:" << hex << "0x" << int(_event->type())
|
/*cerr << "const_iterator::operator++: " << _event->to_string() << endl;*/
|
||||||
<< " buffer: 0x" << int(_event->buffer()[0]) << " 0x" << int(_event->buffer()[1])
|
|
||||||
<< " 0x" << int(_event->buffer()[2]) << endl;*/
|
|
||||||
|
|
||||||
if (! (_event->is_note() || _event->is_cc() || _event->is_pgm_change() || _event->is_pitch_bender() || _event->is_channel_aftertouch()) ) {
|
if (! (_event->is_note() || _event->is_cc() || _event->is_pgm_change() || _event->is_pitch_bender() || _event->is_channel_aftertouch()) ) {
|
||||||
cerr << "FAILED event buffer: " << hex << int(_event->buffer()[0]) << int(_event->buffer()[1]) << int(_event->buffer()[2]) << endl;
|
cerr << "FAILED event buffer: " << hex << int(_event->buffer()[0]) << int(_event->buffer()[1]) << int(_event->buffer()[2]) << endl;
|
||||||
|
|
@ -244,6 +242,7 @@ const MidiModel::const_iterator& MidiModel::const_iterator::operator++()
|
||||||
if (type == NOTE_ON) {
|
if (type == NOTE_ON) {
|
||||||
//cerr << "********** MIDI Iterator = note on" << endl;
|
//cerr << "********** MIDI Iterator = note on" << endl;
|
||||||
*_event = (*_note_iter)->on_event();
|
*_event = (*_note_iter)->on_event();
|
||||||
|
cerr << "Event contents on note on: " << _event->to_string() << endl;
|
||||||
_active_notes.push(*_note_iter);
|
_active_notes.push(*_note_iter);
|
||||||
++_note_iter;
|
++_note_iter;
|
||||||
} else if (type == NOTE_OFF) {
|
} else if (type == NOTE_OFF) {
|
||||||
|
|
@ -401,6 +400,7 @@ MidiModel::control_to_midi_event(boost::shared_ptr<MIDI::Event>& ev, const MidiC
|
||||||
ev->buffer()[0] = MIDI_CMD_BENDER + iter.automation_list->parameter().channel();
|
ev->buffer()[0] = MIDI_CMD_BENDER + iter.automation_list->parameter().channel();
|
||||||
ev->buffer()[1] = uint16_t(iter.y) & 0x7F; // LSB
|
ev->buffer()[1] = uint16_t(iter.y) & 0x7F; // LSB
|
||||||
ev->buffer()[2] = (uint16_t(iter.y) >> 7) & 0x7F; // MSB
|
ev->buffer()[2] = (uint16_t(iter.y) >> 7) & 0x7F; // MSB
|
||||||
|
//cerr << "Pitch bender event: " << ev->to_string() << " value: " << ev->pitch_bender_value() << " original value: " << iter.y << std::endl;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case MidiChannelAftertouchAutomation:
|
case MidiChannelAftertouchAutomation:
|
||||||
|
|
|
||||||
|
|
@ -24,6 +24,7 @@
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <cstdlib>
|
#include <cstdlib>
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
|
#include <sstream>
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
|
|
||||||
#include <midi++/types.h>
|
#include <midi++/types.h>
|
||||||
|
|
@ -93,8 +94,9 @@ struct Event {
|
||||||
_time = copy._time;
|
_time = copy._time;
|
||||||
if (_owns_buffer) {
|
if (_owns_buffer) {
|
||||||
if (copy._buffer) {
|
if (copy._buffer) {
|
||||||
if (copy._size > _size)
|
if (copy._size > _size) {
|
||||||
_buffer = (uint8_t*)::realloc(_buffer, copy._size);
|
_buffer = (uint8_t*)::realloc(_buffer, copy._size);
|
||||||
|
}
|
||||||
memcpy(_buffer, copy._buffer, copy._size);
|
memcpy(_buffer, copy._buffer, copy._size);
|
||||||
} else {
|
} else {
|
||||||
free(_buffer);
|
free(_buffer);
|
||||||
|
|
@ -216,6 +218,15 @@ 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]);
|
||||||
|
}
|
||||||
|
return result.str();
|
||||||
|
}
|
||||||
|
|
||||||
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,7 +96,8 @@ public:
|
||||||
void add_child_nocopy (XMLNode&);
|
void add_child_nocopy (XMLNode&);
|
||||||
|
|
||||||
boost::shared_ptr<XMLSharedNodeList> find(const std::string xpath) const;
|
boost::shared_ptr<XMLSharedNodeList> find(const std::string xpath) const;
|
||||||
|
std::string attribute_value();
|
||||||
|
|
||||||
const XMLPropertyList & properties() const { return _proplist; };
|
const XMLPropertyList & properties() const { return _proplist; };
|
||||||
XMLProperty *property(const char * );
|
XMLProperty *property(const char * );
|
||||||
XMLProperty *property(const std::string&);
|
XMLProperty *property(const std::string&);
|
||||||
|
|
|
||||||
11756
libs/pbd/tests/ProtoolsPatchFile.midnam
Executable file
11756
libs/pbd/tests/ProtoolsPatchFile.midnam
Executable file
File diff suppressed because it is too large
Load diff
|
|
@ -7,8 +7,8 @@ using namespace std;
|
||||||
|
|
||||||
int main()
|
int main()
|
||||||
{
|
{
|
||||||
cout << "Test 1: Find all banks in the file" << endl;
|
cout << "Test 1: RosegardenPatchFile.xml: Find all banks in the file" << endl;
|
||||||
XMLTree doc("./rosegardenpatchfile.xml");
|
XMLTree doc("./RosegardenPatchFile.xml");
|
||||||
// "//bank" gives as last element an empty element libxml bug????
|
// "//bank" gives as last element an empty element libxml bug????
|
||||||
boost::shared_ptr<XMLSharedNodeList> result = doc.root()->find("//bank[@name]");
|
boost::shared_ptr<XMLSharedNodeList> result = doc.root()->find("//bank[@name]");
|
||||||
|
|
||||||
|
|
@ -25,7 +25,7 @@ int main()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
cout << endl << endl << "Test 2: Find all programs whose program name contains 'Latin'" << endl;
|
cout << endl << endl << "Test 2: RosegardenPatchFile.xml: Find all programs whose program name contains 'Latin'" << endl;
|
||||||
|
|
||||||
result = doc.root()->find("/rosegarden-data/studio/device/bank/program[contains(@name, 'Latin')]");
|
result = doc.root()->find("/rosegarden-data/studio/device/bank/program[contains(@name, 'Latin')]");
|
||||||
assert(result->size() == 5);
|
assert(result->size() == 5);
|
||||||
|
|
@ -35,8 +35,9 @@ int main()
|
||||||
" with name: " << (*i)->property("name")->value() << endl;
|
" with name: " << (*i)->property("name")->value() << endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
cout << endl << endl << "Test 3: find all Sources where captured-for contains the string 'Guitar'" << endl;
|
cout << endl << endl << "Test 3: TestSession.ardour: find all Sources where captured-for contains the string 'Guitar'" << endl;
|
||||||
|
|
||||||
|
// We have to allocate a new document here, or we get segfaults
|
||||||
XMLTree doc2("./TestSession.ardour");
|
XMLTree doc2("./TestSession.ardour");
|
||||||
result = doc2.root()->find("/Session/Sources/Source[contains(@captured-for, 'Guitar')]");
|
result = doc2.root()->find("/Session/Sources/Source[contains(@captured-for, 'Guitar')]");
|
||||||
assert(result->size() == 16);
|
assert(result->size() == 16);
|
||||||
|
|
@ -46,7 +47,7 @@ int main()
|
||||||
"' with id: " << (*i)->property("id")->value() << endl;
|
"' with id: " << (*i)->property("id")->value() << endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
cout << endl << endl << "Test 4: Find all elements with an 'id' and 'name' attribute" << endl;
|
cout << endl << endl << "Test 4: TestSession.ardour: Find all elements with an 'id' and 'name' attribute" << endl;
|
||||||
|
|
||||||
result = doc2.root()->find("//*[@id and @name]");
|
result = doc2.root()->find("//*[@id and @name]");
|
||||||
|
|
||||||
|
|
@ -57,4 +58,29 @@ int main()
|
||||||
"' with id: " << (*i)->property("id")->value() <<
|
"' with id: " << (*i)->property("id")->value() <<
|
||||||
"' and name: " << (*i)->property("name")->value() << endl;
|
"' and name: " << (*i)->property("name")->value() << endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
cout << endl << endl << "Test 5: ProtoolsPatchFile.midnam: Get Banks and Patches for 'Name Set 1'" << endl;
|
||||||
|
|
||||||
|
// We have to allocate a new document here, or we get segfaults
|
||||||
|
XMLTree doc3("./ProtoolsPatchFile.midnam");
|
||||||
|
result = doc3.root()->find("/MIDINameDocument/MasterDeviceNames/ChannelNameSet[@Name='Name Set 1']/PatchBank");
|
||||||
|
assert(result->size() == 16);
|
||||||
|
|
||||||
|
for(XMLSharedNodeList::const_iterator i = result->begin(); i != result->end(); ++i) {
|
||||||
|
cout << "\t found Patchbank " << (*i)->property("Name")->value() << endl;
|
||||||
|
boost::shared_ptr<XMLSharedNodeList> patches = (*i)->find("//Patch[@Name]");
|
||||||
|
for(XMLSharedNodeList::const_iterator p = patches->begin(); p != patches->end(); ++p) {
|
||||||
|
cout << "\t\t found patch number " << (*p)->property("Number")->value()
|
||||||
|
<< " with name: " << (*p)->property("Name")->value() << endl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
cout << endl << endl << "Test 5: ProtoolsPatchFile.midnam: Find attribute nodes" << endl;
|
||||||
|
result = doc3.root()->find("//@Value");
|
||||||
|
|
||||||
|
for(XMLSharedNodeList::const_iterator i = result->begin(); i != result->end(); ++i) {
|
||||||
|
boost::shared_ptr<XMLNode> node = (*i);
|
||||||
|
cout << "\t found attribute node: " << node->name()
|
||||||
|
<< " value: " << node->attribute_value() << endl;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -301,6 +301,17 @@ XMLNode::find(const string xpath) const
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::string
|
||||||
|
XMLNode::attribute_value()
|
||||||
|
{
|
||||||
|
XMLNodeList children = this->children();
|
||||||
|
assert(!_is_content);
|
||||||
|
assert(children.size() == 1);
|
||||||
|
XMLNode* child = *(children.begin());
|
||||||
|
assert(child->is_content());
|
||||||
|
return child->content();
|
||||||
|
}
|
||||||
|
|
||||||
XMLNode *
|
XMLNode *
|
||||||
XMLNode::add_content(const string & c)
|
XMLNode::add_content(const string & c)
|
||||||
{
|
{
|
||||||
|
|
@ -537,3 +548,4 @@ static XMLSharedNodeList* find_impl(xmlXPathContext* ctxt, const string xpath)
|
||||||
|
|
||||||
return nodes;
|
return nodes;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue