#include <math.h>
#include <errno.h>
#include <ctype.h>
+#ifdef PLATFORM_WINDOWS
+#include <winsock2.h>
+#else
#include <arpa/inet.h>
+#endif
#include "smf.h"
#include "smf_private.h"
assert(smf->file_buffer != NULL);
assert(smf->file_buffer_length > 0);
- assert(smf->next_chunk_offset >= 0);
if (smf->next_chunk_offset + sizeof(struct chunk_header_struct) >= smf->file_buffer_length) {
g_critical("SMF warning: no more chunks left.");
return (-1);
}
- tmp_mthd = smf->file_buffer;
+ tmp_mthd = (struct chunk_header_struct*)smf->file_buffer;
if (!chunk_signature_matches(tmp_mthd, "MThd")) {
g_critical("SMF error: MThd signature not found, is that a MIDI file?");
* Explanation of Variable Length Quantities is here: http://www.borg.com/~jglatt/tech/midifile/vari.htm
* Returns 0 iff everything went OK, different value in case of error.
*/
-static int
-extract_vlq(const unsigned char *buf, const int buffer_length, int *value, int *len)
+int
+smf_extract_vlq(const unsigned char *buf, const size_t buffer_length, uint32_t *value, uint32_t *len)
{
- int val = 0;
+ uint32_t val = 0;
const unsigned char *c = buf;
- assert(buffer_length > 0);
-
for (;;) {
if (c >= buf + buffer_length) {
g_critical("End of buffer in extract_vlq().");
break;
};
+ assert(c >= buf);
*value = val;
*len = c - buf + 1;
* contains VLQ telling how many bytes it takes, "on the wire" format does not have
* this.
*/
-static int
-expected_sysex_length(const unsigned char status, const unsigned char *second_byte, const int buffer_length, int *consumed_bytes)
+static int32_t
+expected_sysex_length(const unsigned char status, const unsigned char *second_byte, const size_t buffer_length, int32_t *consumed_bytes)
{
- int sysex_length, len;
+ uint32_t sysex_length = 0;
+ uint32_t len = 0;
assert(status == 0xF0);
return (-1);
}
- extract_vlq(second_byte, buffer_length, &sysex_length, &len);
+ smf_extract_vlq(second_byte, buffer_length, &sysex_length, &len);
if (consumed_bytes != NULL)
*consumed_bytes = len;
return (sysex_length + 1);
}
-static int
-expected_escaped_length(const unsigned char status, const unsigned char *second_byte, const int buffer_length, int *consumed_bytes)
+static int32_t
+expected_escaped_length(const unsigned char status, const unsigned char *second_byte, const size_t buffer_length, int32_t *consumed_bytes)
{
/* -1, because we do not want to account for 0x7F status. */
return (expected_sysex_length(status, second_byte, buffer_length, consumed_bytes) - 1);
* The "second_byte" points to the expected second byte of the MIDI message. "buffer_length" is the buffer
* length limit, counting from "second_byte". Returns value < 0 iff there was an error.
*/
-static int
-expected_message_length(unsigned char status, const unsigned char *second_byte, const int buffer_length)
+static int32_t
+expected_message_length(unsigned char status, const unsigned char *second_byte, const size_t buffer_length)
{
/* Make sure this really is a valid status byte. */
assert(is_status_byte(status));
/* We cannot use this routine for escaped events. */
assert(!is_escape_byte(status));
- /* Buffer length may be zero, for e.g. realtime messages. */
- assert(buffer_length >= 0);
-
/* Is this a metamessage? */
if (status == 0xFF) {
if (buffer_length < 2) {
}
static int
-extract_sysex_event(const unsigned char *buf, const int buffer_length, smf_event_t *event, int *len, int last_status)
+extract_sysex_event(const unsigned char *buf, const size_t buffer_length, smf_event_t *event, uint32_t *len, int last_status)
{
- int status, message_length, vlq_length;
+ (void) last_status;
+
+ int status;
+ int32_t vlq_length, message_length;
const unsigned char *c = buf;
status = *buf;
c += vlq_length;
- if (vlq_length + message_length >= buffer_length) {
+ if (vlq_length + (size_t)message_length >= buffer_length) {
g_critical("End of buffer in extract_sysex_event().");
return (-5);
}
event->midi_buffer_length = message_length;
- event->midi_buffer = malloc(event->midi_buffer_length);
+ event->midi_buffer = (uint8_t*)malloc(event->midi_buffer_length);
if (event->midi_buffer == NULL) {
g_critical("Cannot allocate memory in extract_sysex_event(): %s", strerror(errno));
return (-4);
}
static int
-extract_escaped_event(const unsigned char *buf, const int buffer_length, smf_event_t *event, int *len, int last_status)
+extract_escaped_event(const unsigned char *buf, const size_t buffer_length, smf_event_t *event, uint32_t *len, int last_status)
{
- int status, message_length, vlq_length;
+ (void) last_status;
+
+ int status;
+ int32_t message_length = 0;
+ int32_t vlq_length = 0;
const unsigned char *c = buf;
status = *buf;
c += vlq_length;
- if (vlq_length + message_length >= buffer_length) {
+ if (vlq_length + (size_t)message_length >= buffer_length) {
g_critical("End of buffer in extract_escaped_event().");
return (-5);
}
event->midi_buffer_length = message_length;
- event->midi_buffer = malloc(event->midi_buffer_length);
+ event->midi_buffer = (uint8_t*)malloc(event->midi_buffer_length);
if (event->midi_buffer == NULL) {
g_critical("Cannot allocate memory in extract_escaped_event(): %s", strerror(errno));
return (-4);
* Returns 0 iff everything went OK, value < 0 in case of error.
*/
static int
-extract_midi_event(const unsigned char *buf, const int buffer_length, smf_event_t *event, int *len, int last_status)
+extract_midi_event(const unsigned char *buf, const size_t buffer_length, smf_event_t *event, uint32_t *len, int last_status)
{
- int status, message_length;
+ int status;
+ int32_t message_length;
const unsigned char *c = buf;
assert(buffer_length > 0);
if (message_length < 0)
return (-3);
- if (message_length - 1 > buffer_length - (c - buf)) {
+ if ((size_t)message_length > buffer_length - (c - buf) + 1) {
g_critical("End of buffer in extract_midi_event().");
return (-5);
}
event->midi_buffer_length = message_length;
- event->midi_buffer = malloc(event->midi_buffer_length);
+ event->midi_buffer = (uint8_t*)malloc(event->midi_buffer_length);
if (event->midi_buffer == NULL) {
g_critical("Cannot allocate memory in extract_midi_event(): %s", strerror(errno));
return (-4);
static smf_event_t *
parse_next_event(smf_track_t *track)
{
- int time = 0, len, buffer_length;
+ uint32_t time = 0;
+ uint32_t len;
+ size_t buffer_length;
unsigned char *c, *start;
smf_event_t *event = smf_event_new();
assert(buffer_length > 0);
/* First, extract time offset from previous event. */
- if (extract_vlq(c, buffer_length, &time, &len))
+ if (smf_extract_vlq(c, buffer_length, &time, &len))
goto error;
c += len;
* and makes ordinary, zero-terminated string from it. May return NULL if there was any problem.
*/
static char *
-make_string(const unsigned char *buf, const int buffer_length, int len)
+make_string(const unsigned char *buf, const size_t buffer_length, uint32_t len)
{
char *str;
len = buffer_length;
}
- str = malloc(len + 1);
+ str = (char*)malloc(len + 1);
if (str == NULL) {
g_critical("Cannot allocate memory in make_string().");
return (NULL);
char *
smf_event_extract_text(const smf_event_t *event)
{
- int string_length = -1, length_length = -1;
+ uint32_t string_length = 0;
+ uint32_t length_length = 0;
if (!smf_event_is_textual(event))
return (NULL);
return (NULL);
}
- extract_vlq((void *)&(event->midi_buffer[2]), event->midi_buffer_length - 2, &string_length, &length_length);
+ smf_extract_vlq((const unsigned char*)(void *)&(event->midi_buffer[2]), event->midi_buffer_length - 2, &string_length, &length_length);
if (string_length <= 0) {
g_critical("smf_event_extract_text: truncated MIDI message.");
return (NULL);
}
- return (make_string((void *)(&event->midi_buffer[2] + length_length), event->midi_buffer_length - 2 - length_length, string_length));
+ return (make_string((const unsigned char*)(void *)(&event->midi_buffer[2] + length_length), event->midi_buffer_length - 2 - length_length, string_length));
}
/**
{
assert(event);
assert(event->midi_buffer);
+
+ int32_t expected;
if (event->midi_buffer_length < 1)
return (0);
if (smf_event_is_sysex(event))
return (1);
- if (event->midi_buffer_length != expected_message_length(event->midi_buffer[0],
- &(event->midi_buffer[1]), event->midi_buffer_length - 1)) {
+ expected = expected_message_length(event->midi_buffer[0],
+ &(event->midi_buffer[1]), event->midi_buffer_length - 1);
+ if (expected < 0 || event->midi_buffer_length != (size_t)expected) {
return (0);
}
}
/**
- * Allocate buffer of proper size and read file contents into it. Close file afterwards.
+ * Allocate buffer of proper size and read file contents into it.
*/
static int
-load_file_into_buffer(void **file_buffer, int *file_buffer_length, const char *file_name)
+load_file_into_buffer(void **file_buffer, size_t *file_buffer_length, FILE* stream)
{
- FILE *stream = fopen(file_name, "r");
+ long offset;
if (stream == NULL) {
g_critical("Cannot open input file: %s", strerror(errno));
return (-2);
}
- *file_buffer_length = ftell(stream);
- if (*file_buffer_length == -1) {
+ offset = ftell(stream);
+ if (offset < 0) {
g_critical("ftell(3) failed: %s", strerror(errno));
return (-3);
}
+ *file_buffer_length = (size_t)offset;
if (fseek(stream, 0, SEEK_SET)) {
g_critical("fseek(3) failed: %s", strerror(errno));
*file_buffer = malloc(*file_buffer_length);
if (*file_buffer == NULL) {
g_critical("malloc(3) failed: %s", strerror(errno));
-
+
return (-5);
}
if (fread(*file_buffer, 1, *file_buffer_length, stream) != *file_buffer_length) {
g_critical("fread(3) failed: %s", strerror(errno));
-
+ free (*file_buffer);
+ *file_buffer = NULL;
return (-6);
}
- if (fclose(stream)) {
- g_critical("fclose(3) failed: %s", strerror(errno));
-
- return (-7);
- }
-
return (0);
}
* \return SMF or NULL, if loading failed.
*/
smf_t *
-smf_load_from_memory(const void *buffer, const int buffer_length)
+smf_load_from_memory(const void *buffer, const size_t buffer_length)
{
int i;
if (parse_mtrk_chunk(track)) {
g_warning("SMF warning: Cannot load track.");
smf_track_delete(track);
+ continue;
}
track->file_buffer = NULL;
smf->file_buffer = NULL;
smf->file_buffer_length = 0;
- smf->next_chunk_offset = -1;
+ smf->next_chunk_offset = 0;
return (smf);
}
/**
* Loads SMF file.
*
- * \param file_name Path to the file.
+ * \param file Open file.
* \return SMF or NULL, if loading failed.
*/
smf_t *
-smf_load(const char *file_name)
+smf_load(FILE *file)
{
- int file_buffer_length;
+ size_t file_buffer_length;
void *file_buffer;
smf_t *smf;
- if (load_file_into_buffer(&file_buffer, &file_buffer_length, file_name))
+ if (load_file_into_buffer(&file_buffer, &file_buffer_length, file))
return (NULL);
smf = smf_load_from_memory(file_buffer, file_buffer_length);