25 #include <glibmm/miscutils.h>
35 template<
typename Time>
45 template<
typename Time>
58 template<
typename Time>
64 _fd = fopen(path.c_str(),
"r+");
68 fseek(_fd, _header_size - 4, 0);
69 uint32_t track_size_be = 0;
70 fread(&track_size_be, 4, 1, _fd);
71 _track_size = GUINT32_FROM_BE(track_size_be);
72 _empty = _track_size > 4;
77 _fd = fopen(path.c_str(),
"w+");
79 cerr <<
"ERROR: Can not open SMF file " << path <<
" for writing: " <<
80 strerror(errno) << endl;
91 return (_fd == 0) ? -1 : 0;
94 template<
typename Time>
106 template<
typename Time>
110 fseek(_fd, _header_size, SEEK_SET);
113 template<
typename Time>
120 fseek(_fd, -4, SEEK_END);
121 size_t read_bytes = fread(buffer,
sizeof(uint8_t), 4, _fd);
123 if ((read_bytes == 4)
127 && buffer[3] == 0x00) {
129 fseek(_fd, -4, SEEK_END);
132 fseek(_fd, 0, SEEK_END);
136 template<
typename Time>
143 template<
typename Time>
153 const uint16_t type = GUINT16_TO_BE(0);
154 const uint16_t ntracks = GUINT16_TO_BE(1);
155 const uint16_t division = GUINT16_TO_BE(_ppqn);
158 memcpy(data, &type, 2);
159 memcpy(data+2, &ntracks, 2);
160 memcpy(data+4, &division, 2);
164 fseek(_fd, 0, SEEK_SET);
165 write_chunk(
"MThd", 6, data);
166 write_chunk_header(
"MTrk", _track_size);
173 template<
typename Time>
178 seek_to_footer_position();
180 seek_to_footer_position();
185 template<
typename Time>
190 char eot[3] = { 0xFF, 0x2F, 0x00 };
191 fwrite(eot, 1, 3, _fd);
210 template<
typename Time>
232 const int status = fgetc(_fd);
240 if (status == 0xFF) {
244 const int type = fgetc(_fd);
245 if ((
unsigned char)type == 0x2F) {
254 if (event_size <= 0) {
264 if (*size < (
unsigned)event_size)
265 *buf = (uint8_t*)realloc(*buf, event_size);
269 (*buf)[0] = (
unsigned char)status;
271 fread((*buf) + 1, 1, *size - 1, _fd);
282 template<
typename Time>
289 size_t stamp_size = write_var_len(delta_t);
292 stamp_size += write_var_len(ev.
size() - 1);
293 fwrite(ev.
buffer() + 1, 1, ev.
size() - 1, _fd);
298 _track_size += stamp_size + ev.
size();
299 _last_ev_time = ev.
time();
305 template<
typename Time>
310 fseek(_fd, _header_size, SEEK_SET);
313 template<
typename Time>
321 template<
typename Time>
325 const uint32_t length_be = GUINT32_TO_BE(length);
327 fwrite(
id, 1, 4, _fd);
328 fwrite(&length_be, 4, 1, _fd);
331 template<
typename Time>
335 write_chunk_header(
id, length);
337 fwrite(data, 1, length, _fd);
341 template<
typename Time>
347 uint32_t buffer = value & 0x7F;
349 while ( (value >>= 7) ) {
351 buffer |= ((value & 0x7F) | 0x80);
static int midi_event_size(uint8_t status)
int read_event(uint32_t *delta_t, uint32_t *size, uint8_t **buf) const
void end_write() THROW_FILE_ERROR
int open(const std::string &path) THROW_FILE_ERROR
size_t write_var_len(uint32_t val)
void close() THROW_FILE_ERROR
void write_chunk_header(const char id[4], uint32_t length)
#define MIDI_CMD_COMMON_SYSEX
void write_chunk(const char id[4], uint32_t length, void *data)
void seek_to_start() const
void seek_to_footer_position()
void append_event_delta(uint32_t delta_t, const Event< Time > &ev)
static uint32_t read_var_len(FILE *fd)
const uint8_t * buffer() const
LIBARDOUR_API PBD::PropertyDescriptor< framecnt_t > length