midifile: fix header writes on close

When writing a midifile, update the pos with each write so that the seek
back to 0 when updating the headers actually does something.
This commit is contained in:
Wim Taymans 2026-05-21 14:04:19 +02:00
parent 26a2467e7b
commit 7614a2a5d6

View file

@ -218,21 +218,24 @@ exit:
return res; return res;
} }
static inline int write_n(FILE *file, const void *buf, int count) static inline int write_n(struct midi_file *mf, const void *buf, int count)
{ {
return fwrite(buf, 1, count, file) == (size_t)count ? count : -errno; if (fwrite(buf, 1, count, mf->file) != (size_t)count)
return -errno;
mf->pos += count;
return count;
} }
static inline int write_be16(FILE *file, uint16_t val) static inline int write_be16(struct midi_file *mf, uint16_t val)
{ {
uint8_t buf[2] = { val >> 8, val }; uint8_t buf[2] = { val >> 8, val };
return write_n(file, buf, 2); return write_n(mf, buf, 2);
} }
static inline int write_be32(FILE *file, uint32_t val) static inline int write_be32(struct midi_file *mf, uint32_t val)
{ {
uint8_t buf[4] = { val >> 24, val >> 16, val >> 8, val }; uint8_t buf[4] = { val >> 24, val >> 16, val >> 8, val };
return write_n(file, buf, 4); return write_n(mf, buf, 4);
} }
#define CHECK_RES(expr) if ((res = (expr)) < 0) return res #define CHECK_RES(expr) if ((res = (expr)) < 0) return res
@ -242,17 +245,18 @@ static int write_headers(struct midi_file *mf)
struct midi_track *tr = &mf->tracks[0]; struct midi_track *tr = &mf->tracks[0];
int res; int res;
mf_seek(mf, 0); if ((res = mf_seek(mf, 0)) < 0)
return -res;
mf->length = 6; mf->length = 6;
CHECK_RES(write_n(mf->file, "MThd", 4)); CHECK_RES(write_n(mf, "MThd", 4));
CHECK_RES(write_be32(mf->file, mf->length)); CHECK_RES(write_be32(mf, mf->length));
CHECK_RES(write_be16(mf->file, mf->info.format)); CHECK_RES(write_be16(mf, mf->info.format));
CHECK_RES(write_be16(mf->file, mf->info.ntracks)); CHECK_RES(write_be16(mf, mf->info.ntracks));
CHECK_RES(write_be16(mf->file, mf->info.division)); CHECK_RES(write_be16(mf, mf->info.division));
CHECK_RES(write_n(mf->file, "MTrk", 4)); CHECK_RES(write_n(mf, "MTrk", 4));
CHECK_RES(write_be32(mf->file, tr->size)); CHECK_RES(write_be32(mf, tr->size));
return 0; return 0;
} }
@ -323,7 +327,7 @@ int midi_file_close(struct midi_file *mf)
if (mf->mode == 2) { if (mf->mode == 2) {
uint8_t buf[4] = { 0x00, 0xff, 0x2f, 0x00 }; uint8_t buf[4] = { 0x00, 0xff, 0x2f, 0x00 };
CHECK_RES(write_n(mf->file, buf, 4)); CHECK_RES(write_n(mf, buf, 4));
mf->tracks[0].size += 4; mf->tracks[0].size += 4;
CHECK_RES(write_headers(mf)); CHECK_RES(write_headers(mf));
} else if (mf->mode != 1) } else if (mf->mode != 1)
@ -501,7 +505,7 @@ static int write_varlen(struct midi_file *mf, struct midi_track *tr, uint32_t va
} }
do { do {
b = buffer & 0xff; b = buffer & 0xff;
CHECK_RES(write_n(mf->file, &b, 1)); CHECK_RES(write_n(mf, &b, 1));
tr->size++; tr->size++;
buffer >>= 8; buffer >>= 8;
} while (b & 0x80); } while (b & 0x80);
@ -552,7 +556,7 @@ int midi_file_write_event(struct midi_file *mf, const struct midi_event *event)
if (ev_size > 0 && if (ev_size > 0 &&
(ev_data[0] == 0xf0 || ev_data[0] == 0xf7)) { (ev_data[0] == 0xf0 || ev_data[0] == 0xf7)) {
CHECK_RES(write_n(mf->file, ev_data, 1)); CHECK_RES(write_n(mf, ev_data, 1));
ev_size -= 1; ev_size -= 1;
ev_data += 1; ev_data += 1;
@ -561,7 +565,7 @@ int midi_file_write_event(struct midi_file *mf, const struct midi_event *event)
tr->size += 1; tr->size += 1;
} }
CHECK_RES(write_n(mf->file, ev_data, ev_size)); CHECK_RES(write_n(mf, ev_data, ev_size));
tr->size += ev_size; tr->size += ev_size;
} }
return 0; return 0;