Merge branch 'master' into cairocanvas
[ardour.git] / libs / evoral / src / libsmf / smf_load.c
index 71ad02498e0cc710065ca4364230791bc54ee385..98d5ea8cfff656619eb8db53289e815d1c84882e 100644 (file)
@@ -206,8 +206,8 @@ parse_mthd_chunk(smf_t *smf)
  * 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 size_t buffer_length, uint32_t *value, uint32_t *len)
+int
+smf_extract_vlq(const unsigned char *buf, const size_t buffer_length, uint32_t *value, uint32_t *len)
 {
        uint32_t val = 0;
        const unsigned char *c = buf;
@@ -275,16 +275,21 @@ is_escape_byte(const unsigned char status)
 static int32_t
 expected_sysex_length(const unsigned char status, const unsigned char *second_byte, const size_t buffer_length, int32_t *consumed_bytes)
 {
-       uint32_t sysex_length, len;
+       uint32_t sysex_length = 0;
+       uint32_t len = 0;
 
+#ifndef NDEBUG
+       (void) status;
+#else
        assert(status == 0xF0);
+#endif
 
        if (buffer_length < 3) {
                g_critical("SMF error: end of buffer in expected_sysex_length().");
                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;
@@ -424,7 +429,8 @@ extract_escaped_event(const unsigned char *buf, const size_t buffer_length, smf_
        (void) last_status;
        
        int status;
-       int32_t message_length, vlq_length;
+       int32_t message_length = 0;
+       int32_t vlq_length = 0;
        const unsigned char *c = buf;
 
        status = *buf;
@@ -539,7 +545,7 @@ extract_midi_event(const unsigned char *buf, const size_t buffer_length, smf_eve
 static smf_event_t *
 parse_next_event(smf_track_t *track)
 {
-       uint32_t time = 0;
+       uint32_t etime = 0;
        uint32_t len;
        size_t buffer_length;
        unsigned char *c, *start;
@@ -558,7 +564,7 @@ parse_next_event(smf_track_t *track)
        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, &etime, &len))
                goto error;
 
        c += len;
@@ -576,7 +582,7 @@ parse_next_event(smf_track_t *track)
        track->last_status = event->midi_buffer[0];
        track->next_event_offset += c - start;
 
-       smf_track_add_event_delta_pulses(track, event, time);
+       smf_track_add_event_delta_pulses(track, event, etime);
 
        return (event);
 
@@ -631,7 +637,7 @@ smf_event_is_textual(const smf_event_t *event)
        if (event->midi_buffer_length < 4)
                return (0);
 
-       if (event->midi_buffer[3] < 1 && event->midi_buffer[3] > 9)
+       if (event->midi_buffer[3] < 1 || event->midi_buffer[3] > 9)
                return (0);
 
        return (1);
@@ -645,7 +651,8 @@ smf_event_is_textual(const smf_event_t *event)
 char *
 smf_event_extract_text(const smf_event_t *event)
 {
-       uint32_t string_length, length_length;
+       uint32_t string_length = 0;
+       uint32_t length_length = 0;
 
        if (!smf_event_is_textual(event))
                return (NULL);
@@ -655,7 +662,7 @@ smf_event_extract_text(const smf_event_t *event)
                return (NULL);
        }
 
-       extract_vlq((void *)&(event->midi_buffer[2]), event->midi_buffer_length - 2, &string_length, &length_length);
+       smf_extract_vlq((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.");
@@ -794,12 +801,11 @@ parse_mtrk_chunk(smf_track_t *track)
 }
 
 /**
- * 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, size_t *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) {
@@ -831,22 +837,17 @@ load_file_into_buffer(void **file_buffer, size_t *file_buffer_length, const char
        *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);
 }
 
@@ -879,6 +880,7 @@ smf_load_from_memory(const void *buffer, const size_t buffer_length)
                if (parse_mtrk_chunk(track)) {
                        g_warning("SMF warning: Cannot load track.");
                        smf_track_delete(track);
+                       continue;
                }
 
                track->file_buffer = NULL;
@@ -903,17 +905,17 @@ smf_load_from_memory(const void *buffer, const size_t buffer_length)
 /**
  * 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)
 {
        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);