/** * Locates, basing on track->next_event_offset, the next event data in track->buffer, * interprets it, allocates smf_event_t and fills it properly. Returns smf_event_t * or NULL, if there was an error. Allocating event means adding it to the track; * see smf_event_new(). */ static smf_event_t * parse_next_event(smf_track_t *track) { uint32_t etime = 0; uint32_t len; size_t buffer_length; unsigned char *c, *start; smf_event_t *event = smf_event_new(); if (event == NULL) goto error; c = start = (unsigned char *)track->file_buffer + track->next_event_offset; assert(track->file_buffer != NULL); assert(track->file_buffer_length > 0); assert(track->next_event_offset > 0); buffer_length = track->file_buffer_length - track->next_event_offset; /* if there was no meta-EOT event, buffer_length can be zero. This is an error in the SMF file, but it shouldn't be treated as fatal. */ if (buffer_length == 0) { g_warning ("SMF warning: expected EOT at end of track, but none found"); goto error; } /* First, extract time offset from previous event. */ if (smf_extract_vlq(c, buffer_length, &etime, &len)) { goto error; } c += len; buffer_length -= len; if (buffer_length <= 0) goto error; /* Now, extract the actual event. */ if (extract_midi_event(c, buffer_length, event, &len, track->last_status)) { goto error; } c += len; buffer_length -= len; track->last_status = event->midi_buffer[0]; track->next_event_offset += c - start; smf_track_add_event_delta_pulses(track, event, etime); return (event); error: if (event != NULL) smf_event_delete(event); return (NULL); }
/** * Allocates an smf_event_t structure and fills it with "len" bytes copied * from "midi_data". * \param midi_data Pointer to MIDI data. It sill be copied to the newly allocated event->midi_buffer. * \param len Length of the buffer. It must be proper MIDI event length, e.g. 3 for Note On event. * \return Event containing MIDI data or NULL. */ smf_event_t * smf_event_new_from_pointer(void *midi_data, int len) { smf_event_t *event; event = smf_event_new(); if (event == NULL) return (NULL); event->midi_buffer_length = len; event->midi_buffer = malloc(event->midi_buffer_length); if (event->midi_buffer == NULL) { g_critical("Cannot allocate MIDI buffer structure: %s", strerror(errno)); smf_event_delete(event); return (NULL); } memcpy(event->midi_buffer, midi_data, len); return (event); }
static int cmd_eventadd(char *str) { int midi_buffer_length; double seconds; unsigned char *midi_buffer; char *time, *endtime; if (selected_track == NULL) { g_critical("Please select a track first, using 'track <number>' command."); return (-1); } if (str == NULL) { eventadd_usage(); return (-2); } /* Extract the time. Don't use strsep(3), it doesn't work on SunOS. */ time = str; str = strchr(str, ' '); if (str != NULL) { *str = '\0'; str++; } seconds = strtod(time, &endtime); if (endtime - time != strlen(time)) { g_critical("Time is supposed to be a number, without trailing characters."); return (-3); } /* Called with one parameter? */ if (str == NULL) { eventadd_usage(); return (-4); } if (decode_hex(str, &midi_buffer, &midi_buffer_length)) { eventadd_usage(); return (-5); } selected_event = smf_event_new(); if (selected_event == NULL) { g_critical("smf_event_new() failed, event not created."); return (-6); } selected_event->midi_buffer = midi_buffer; selected_event->midi_buffer_length = midi_buffer_length; if (smf_event_is_valid(selected_event) == 0) { g_critical("Event is invalid from the MIDI specification point of view, not created."); smf_event_delete(selected_event); selected_event = NULL; return (-7); } smf_track_add_event_seconds(selected_track, selected_event, seconds); g_message("Event created."); return (0); }
/** * Allocates an smf_event_t structure and fills it with at most three bytes of data. * For example, if you need to create Note On event, do something like this: * * smf_event_new_from_bytes(0x90, 0x3C, 0x7f); * * To create event for MIDI message that is shorter than three bytes, do something * like this: * * smf_event_new_from_bytes(0xC0, 0x42, -1); * * \param first_byte First byte of MIDI message. Must be valid status byte. * \param second_byte Second byte of MIDI message or -1, if message is one byte long. * \param third_byte Third byte of MIDI message or -1, if message is two bytes long. * \return Event containing MIDI data or NULL. */ smf_event_t * smf_event_new_from_bytes(int first_byte, int second_byte, int third_byte) { int len; smf_event_t *event; event = smf_event_new(); if (event == NULL) return (NULL); if (first_byte < 0) { g_critical("First byte of MIDI message cannot be < 0"); smf_event_delete(event); return (NULL); } if (first_byte > 255) { g_critical("smf_event_new_from_bytes: first byte is %d, which is larger than 255.", first_byte); return (NULL); } if (!is_status_byte(first_byte)) { g_critical("smf_event_new_from_bytes: first byte is not a valid status byte."); return (NULL); } if (second_byte < 0) len = 1; else if (third_byte < 0) len = 2; else len = 3; if (len > 1) { if (second_byte > 255) { g_critical("smf_event_new_from_bytes: second byte is %d, which is larger than 255.", second_byte); return (NULL); } if (is_status_byte(second_byte)) { g_critical("smf_event_new_from_bytes: second byte cannot be a status byte."); return (NULL); } } if (len > 2) { if (third_byte > 255) { g_critical("smf_event_new_from_bytes: third byte is %d, which is larger than 255.", third_byte); return (NULL); } if (is_status_byte(third_byte)) { g_critical("smf_event_new_from_bytes: third byte cannot be a status byte."); return (NULL); } } event->midi_buffer_length = len; event->midi_buffer = malloc(event->midi_buffer_length); if (event->midi_buffer == NULL) { g_critical("Cannot allocate MIDI buffer structure: %s", strerror(errno)); smf_event_delete(event); return (NULL); } event->midi_buffer[0] = first_byte; if (len > 1) event->midi_buffer[1] = second_byte; if (len > 2) event->midi_buffer[2] = third_byte; return (event); }