aboutsummaryrefslogtreecommitdiff
path: root/engines/sci/sfx/songlib.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'engines/sci/sfx/songlib.cpp')
-rw-r--r--engines/sci/sfx/songlib.cpp282
1 files changed, 282 insertions, 0 deletions
diff --git a/engines/sci/sfx/songlib.cpp b/engines/sci/sfx/songlib.cpp
new file mode 100644
index 0000000000..57475e82db
--- /dev/null
+++ b/engines/sci/sfx/songlib.cpp
@@ -0,0 +1,282 @@
+/***************************************************************************
+ songlib.c Copyright (C) 2002 Christoph Reichenbach
+
+ This program may be modified and copied freely according to the terms of
+ the GNU general public license (GPL), as long as the above copyright
+ notice and the licensing information contained herein are preserved.
+
+ Please refer to www.gnu.org for licensing details.
+
+ This work is provided AS IS, without warranty of any kind, expressed or
+ implied, including but not limited to the warranties of merchantibility,
+ noninfringement, and fitness for a specific purpose. The author will not
+ be held liable for any damage caused by this work or derivatives of it.
+
+ By using this source code, you agree to the licensing terms as stated
+ above.
+
+
+ Please contact the maintainer for bug reports or inquiries.
+
+ Current Maintainer:
+
+ Christoph Reichenbach (CJR) <reichenb@colorado.edu>
+
+***************************************************************************/
+
+#include <stdio.h>
+#include "sci/include/sfx_engine.h"
+#include "sci/include/sci_memory.h"
+
+#define debug_stream stderr
+
+GTimeVal
+song_sleep_time(GTimeVal *lastslept, long ticks)
+{
+ GTimeVal tv;
+ long timetosleep;
+ long timeslept; /* Time already slept */
+ timetosleep = ticks * SOUND_TICK; /* Time to sleep in us */
+
+ sci_get_current_time(&tv);
+ timeslept = 1000000 * (tv.tv_sec - lastslept->tv_sec) +
+ tv.tv_usec - lastslept->tv_usec;
+
+ timetosleep -= timeslept;
+
+ if (timetosleep < 0)
+ timetosleep = 0;
+
+ tv.tv_sec = timetosleep / 1000000;
+ tv.tv_usec = timetosleep % 1000000;
+
+ return tv;
+}
+
+
+GTimeVal
+song_next_wakeup_time(GTimeVal *lastslept, long ticks)
+{
+ GTimeVal retval;
+
+ retval.tv_sec = lastslept->tv_sec + (ticks / 60);
+ retval.tv_usec = lastslept->tv_usec + ((ticks % 60) * SOUND_TICK);
+
+ if (retval.tv_usec >= 1000000) {
+ retval.tv_usec -= 1000000;
+ ++retval.tv_sec;
+ }
+
+ return retval;
+}
+
+
+song_t *
+song_new(song_handle_t handle, song_iterator_t *it, int priority)
+{
+ song_t *retval;
+ retval = (song_t*) sci_malloc(sizeof(song_t));
+
+#ifdef SATISFY_PURIFY
+ memset(retval, 0, sizeof(song_t));
+#endif
+
+ retval->handle = handle;
+ retval->priority = priority;
+ retval->next = NULL;
+ retval->delay = 0;
+ retval->it = it;
+ retval->status = SOUND_STATUS_STOPPED;
+ retval->next_playing = NULL;
+ retval->next_stopping = NULL;
+ retval->restore_behavior = RESTORE_BEHAVIOR_CONTINUE;
+ retval->restore_time = 0;
+
+ return retval;
+}
+
+
+void
+song_lib_add(songlib_t songlib, song_t *song)
+{
+ song_t **seeker = NULL;
+ int pri = song->priority;
+
+ if (NULL == song) {
+ sciprintf("song_lib_add(): NULL passed for song\n");
+ return;
+ }
+
+ if (*(songlib.lib) == NULL) {
+ *(songlib.lib) = song;
+ song->next = NULL;
+
+ return;
+ }
+
+ seeker = (songlib.lib);
+ while (*seeker && ((*seeker)->priority > pri))
+ seeker = &((*seeker)->next);
+
+ song->next = *seeker;
+ *seeker = song;
+}
+
+static void /* Recursively free a chain of songs */
+_songfree_chain(song_t *song)
+{
+ if (song) {
+ _songfree_chain(song->next);
+ songit_free(song->it);
+ song->it = NULL;
+ free(song);
+ }
+}
+
+
+void
+song_lib_init(songlib_t *songlib)
+{
+ songlib->lib = &(songlib->_s);
+ songlib->_s = NULL;
+}
+
+void
+song_lib_free(songlib_t songlib)
+{
+ _songfree_chain(*(songlib.lib));
+ *(songlib.lib) = NULL;
+}
+
+
+song_t *
+song_lib_find(songlib_t songlib, song_handle_t handle)
+{
+ song_t *seeker = *(songlib.lib);
+
+ while (seeker) {
+ if (seeker->handle == handle)
+ break;
+ seeker = seeker->next;
+ }
+
+ return seeker;
+}
+
+
+song_t *
+song_lib_find_next_active(songlib_t songlib, song_t *other)
+{
+ song_t *seeker = other? other->next : *(songlib.lib);
+
+ while (seeker) {
+ if ((seeker->status == SOUND_STATUS_WAITING) ||
+ (seeker->status == SOUND_STATUS_PLAYING))
+ break;
+ seeker = seeker->next;
+ }
+
+ /* Only return songs that have equal priority */
+ if (other && seeker && other->priority > seeker->priority)
+ return NULL;
+
+ return seeker;
+}
+
+song_t *
+song_lib_find_active(songlib_t songlib)
+{
+ return song_lib_find_next_active(songlib, NULL);
+}
+
+int
+song_lib_remove(songlib_t songlib, song_handle_t handle)
+{
+ int retval;
+ song_t *goner = *(songlib.lib);
+
+ if (!goner)
+ return -1;
+
+ if (goner->handle == handle)
+ *(songlib.lib) = goner->next;
+
+ else {
+ while ((goner->next) && (goner->next->handle != handle))
+ goner = goner->next;
+
+ if (goner->next) { /* Found him? */
+ song_t *oldnext = goner->next;
+
+ goner->next = goner->next->next;
+ goner = oldnext;
+ } else return -1; /* No. */
+ }
+
+ retval = goner->status;
+
+ songit_free(goner->it);
+ free(goner);
+
+ return retval;
+}
+
+void
+song_lib_resort(songlib_t songlib, song_t *song)
+{
+ if (*(songlib.lib) == song)
+ *(songlib.lib) = song->next;
+ else {
+ song_t *seeker = *(songlib.lib);
+
+ while (seeker->next && (seeker->next != song))
+ seeker = seeker->next;
+
+ if (seeker->next)
+ seeker->next = seeker->next->next;
+ }
+
+ song_lib_add(songlib, song);
+}
+
+int
+song_lib_count(songlib_t songlib)
+{
+ song_t *seeker = *(songlib.lib);
+ int retval = 0;
+
+ while (seeker) {
+ retval++;
+ seeker = seeker->next;
+ }
+
+ return retval;
+}
+
+void
+song_lib_set_restore_behavior(songlib_t songlib, song_handle_t handle, RESTORE_BEHAVIOR action)
+{
+ song_t *seeker = song_lib_find(songlib, handle);
+
+ seeker->restore_behavior = action;
+}
+
+void
+song_lib_dump(songlib_t songlib, int line)
+{
+ song_t *seeker = *(songlib.lib);
+
+ fprintf(debug_stream,"L%d:", line);
+ do {
+ fprintf(debug_stream," %p", (void *)seeker);
+
+ if (seeker) {
+ fprintf(debug_stream,"[%04lx,p=%d,s=%d]->", seeker->handle, seeker->priority,seeker->status);
+ seeker = seeker->next;
+ }
+ fprintf(debug_stream,"\n");
+ } while (seeker);
+ fprintf(debug_stream,"\n");
+
+}
+