102 private: |
104 private: |
103 |
105 |
104 static void writeRecord(std::shared_ptr<RelationalWriter> writer, |
106 static void writeRecord(std::shared_ptr<RelationalWriter> writer, |
105 string_t eventType, integer_t channel, |
107 string_t eventType, integer_t channel, |
106 boolean_t noteOn, integer_t pitch, integer_t velocity, |
108 boolean_t noteOn, integer_t pitch, integer_t velocity, |
107 integer_t controllerId, integer_t value) { |
109 integer_t controllerId, integer_t value, |
|
110 string_t raw) { |
108 writer->writeAttribute(eventType); |
111 writer->writeAttribute(eventType); |
109 writer->writeAttribute(&channel, typeid (channel)); |
112 writer->writeAttribute(&channel, typeid (channel)); |
110 writer->writeAttribute(¬eOn, typeid (noteOn)); |
113 writer->writeAttribute(¬eOn, typeid (noteOn)); |
111 writer->writeAttribute(&pitch, typeid (pitch)); |
114 writer->writeAttribute(&pitch, typeid (pitch)); |
112 writer->writeAttribute(&velocity, typeid (velocity)); |
115 writer->writeAttribute(&velocity, typeid (velocity)); |
113 writer->writeAttribute(&controllerId, typeid (controllerId)); |
116 writer->writeAttribute(&controllerId, typeid (controllerId)); |
114 writer->writeAttribute(&value, typeid (value)); |
117 writer->writeAttribute(&value, typeid (value)); |
|
118 writer->writeAttribute(&raw, typeid (raw)); |
115 } |
119 } |
116 |
120 |
117 void processMessage(std::shared_ptr<RelationalWriter> writer, MidiMessage* event) { |
121 void processMessage(std::shared_ptr<RelationalWriter> writer, MidiMessage* event) { |
118 if (event->size == 0) { |
122 if (event->size == 0) { |
119 return; |
123 return; |
120 } else { |
124 } else { |
121 uint8_t type = event->buffer[0] & 0xF0; |
125 uint8_t type = event->buffer[0] & 0xF0; |
122 uint8_t channel = event->buffer[0] & 0x0F; |
126 uint8_t channel = event->buffer[0] & 0x0F; |
123 |
127 |
124 // TODO: write timestamp, message number |
128 // TODO: write timestamp, message number |
125 // TODO: write raw buffer in hex |
|
126 |
129 |
127 if ((type == 0x90 || type == 0x80) && event->size == 3) { |
130 if ((type == 0x90 || type == 0x80) && event->size == 3) { |
128 writeRecord(writer, L"note", channel, type == 0x90, event->buffer[1], event->buffer[2], 0, 0); |
131 writeRecord(writer, L"note", channel, type == 0x90, event->buffer[1], event->buffer[2], 0, 0, toHex(event)); |
129 } else if (type == 0xB0 && event->size == 3) { |
132 } else if (type == 0xB0 && event->size == 3) { |
130 writeRecord(writer, L"control", channel, false, 0, 0, event->buffer[1], event->buffer[2]); |
133 writeRecord(writer, L"control", channel, false, 0, 0, event->buffer[1], event->buffer[2], toHex(event)); |
131 } else { |
134 } else { |
132 writeRecord(writer, L"unknown", channel, false, 0, 0, 0, 0); |
135 writeRecord(writer, L"unknown", channel, false, 0, 0, 0, 0, toHex(event)); |
133 } |
136 } |
134 } |
137 } |
|
138 } |
|
139 |
|
140 string_t toHex(MidiMessage* event) { |
|
141 std::wstringstream result; |
|
142 result << std::hex << std::setfill(L'0'); |
|
143 |
|
144 for (size_t i = 0; i < event->size && i < sizeof (event->buffer); i++) { |
|
145 if (i > 0) result << L' '; |
|
146 result << std::setw(2) << event->buffer[i]; |
|
147 // result << ("0123456789abcdef"[event->buffer[i] >> 4]); |
|
148 // result << ("0123456789abcdef"[event->buffer[i] & 0xf]); |
|
149 } |
|
150 |
|
151 return result.str(); |
135 } |
152 } |
136 |
153 |
137 public: |
154 public: |
138 |
155 |
139 void finish(int sig) { |
156 void finish(int sig) { |
148 metadata.push_back({L"note_on", TypeId::BOOLEAN}); |
165 metadata.push_back({L"note_on", TypeId::BOOLEAN}); |
149 metadata.push_back({L"note_pitch", TypeId::INTEGER}); |
166 metadata.push_back({L"note_pitch", TypeId::INTEGER}); |
150 metadata.push_back({L"note_velocity", TypeId::INTEGER}); |
167 metadata.push_back({L"note_velocity", TypeId::INTEGER}); |
151 metadata.push_back({L"controller_id", TypeId::INTEGER}); |
168 metadata.push_back({L"controller_id", TypeId::INTEGER}); |
152 metadata.push_back({L"controller_value", TypeId::INTEGER}); |
169 metadata.push_back({L"controller_value", TypeId::INTEGER}); |
|
170 metadata.push_back({L"raw", TypeId::STRING}); |
153 writer->startRelation(L"midi", metadata, true); |
171 writer->startRelation(L"midi", metadata, true); |
154 relationalWriterFlush(); |
172 relationalWriterFlush(); |
155 |
173 |
156 // Initialize JACK connection: |
174 // Initialize JACK connection: |
157 std::string clientName = "relpipe-in-jack"; |
175 std::string clientName = "relpipe-in-jack"; |