Sona 0.50 Source

Sona 0.50/tools/mml2sona/stream.c

#include <stdio.h>
#include <stdlib.h>
#include "main.h"
#include "stream.h"

// Default amount of events allocated for a stream
#define DEFAULT_EVENT_ALLOC 0x10

//***************************************************************************
// create_stream
// Allocates a new empty stream and returns it.
//---------------------------------------------------------------------------
// return: pointer to stream
//***************************************************************************

Stream *create_stream(void)
{
   // Allocate stream structure
   Stream *stream = (Stream*) malloc(sizeof(Stream));
   if (stream == NULL) {
      fputs(ERRORMSG_NOMEMORY, stderr);
      exit(EXIT_FAILURE);
   }
   
   // Set up stream
   stream->num_events = 0;
   stream->allocated_events = DEFAULT_EVENT_ALLOC;
   stream->timestamp = 0;
   stream->end_timestamp = 0;
   stream->looped = 0;
   
   // Allocate initial event array
   stream->events = (Event*) malloc(sizeof(Event) *
      stream->allocated_events);
   if (stream->events == NULL) {
      fputs(ERRORMSG_NOMEMORY, stderr);
      exit(EXIT_FAILURE);
   }
   
   // Return new stream
   return stream;
}

//***************************************************************************
// create_event
// Allocates a new event into a stream and returns it.
//---------------------------------------------------------------------------
// param stream: pointer to stream
//---------------------------------------------------------------------------
// return: pointer to event
//***************************************************************************

Event *create_event(Stream *stream)
{
   // Make room for the new event
   stream->num_events++;
   
   if (stream->num_events > stream->allocated_events) {
      stream->allocated_events *= 2;
      stream->events = (Event*) realloc(stream->events,
         sizeof(Event) * stream->allocated_events);
      if (stream->events == NULL) {
         fputs(ERRORMSG_NOMEMORY, stderr);
         exit(EXIT_FAILURE);
      }
   }
   
   // Set up event with default values
   Event *event = &stream->events[stream->num_events - 1];
   event->type = EVENT_NONE;
   event->timestamp = stream->timestamp;
   event->sort_priority = stream->num_events;
   
   // Return new event
   return event;
}

//***************************************************************************
// sort_stream
// Sorts the events within a stream by timestamp. This is required in order
// for save_sona() to work properly.
//---------------------------------------------------------------------------
// param stream: pointer to stream
//***************************************************************************

static int sort_func(const void *, const void *);

void sort_stream(Stream *stream)
{
   qsort(stream->events, stream->num_events, sizeof(Event), sort_func);
}

static int sort_func(const void *ptr1, const void *ptr2)
{
   const Event *event1 = (Event*)(ptr1);
   const Event *event2 = (Event*)(ptr2);
   
   if (event1->timestamp < event2->timestamp) return -1;
   if (event1->timestamp > event2->timestamp) return +1;
   if (event1->sort_priority < event2->sort_priority) return -1;
   if (event1->sort_priority > event2->sort_priority) return +1;
   return 0;
}

//***************************************************************************
// delete_stream
// Deallocates a stream.
//---------------------------------------------------------------------------
// param stream: pointer to stream
//---------------------------------------------------------------------------
// note: the pointer to the stream becomes invalid after calling this.
//***************************************************************************

void delete_stream(Stream *stream)
{
   if (stream == NULL) return;
   free(stream->events);
   free(stream);
}