--- /dev/null	Thu Nov  4 09:07:25 1999
+++ src/readsmp.c	Mon Jul 22 22:27:48 2002
@@ -0,0 +1,192 @@
+/*         ______   ___    ___
+ *        /\  _  \ /\_ \  /\_ \
+ *        \ \ \L\ \\//\ \ \//\ \      __     __   _ __   ___
+ *         \ \  __ \ \ \ \  \ \ \   /'__`\ /'_ `\/\`'__\/ __`\
+ *          \ \ \/\ \ \_\ \_ \_\ \_/\  __//\ \L\ \ \ \//\ \L\ \
+ *           \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/
+ *            \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/
+ *                                           /\____/
+ *                                           \_/__/
+ *
+ *      Top level sample reading routines.
+ *
+ *      By Shawn Hargreaves.
+ *
+ *      See readme.txt for copyright information.
+ */
+
+
+#include <string.h>
+
+#include "allegro.h"
+#include "allegro/internal/aintern.h"
+
+
+
+typedef struct SAMPLE_TYPE_INFO
+{
+   char *ext;
+   SAMPLE *(*load)(AL_CONST char *filename);
+   int (*save)(AL_CONST char *filename, SAMPLE *smp);
+   struct SAMPLE_TYPE_INFO *next;
+} SAMPLE_TYPE_INFO;
+
+static SAMPLE_TYPE_INFO *sample_type_list = NULL;
+
+
+
+/* register_sample_file_type:
+ *  Informs Allegro of a new sample file type, telling it how to load and
+ *  save files of this format (either function may be NULL).
+ */
+void register_sample_file_type(AL_CONST char *ext, SAMPLE *(*load)(AL_CONST char *filename), int (*save)(AL_CONST char *filename, SAMPLE *smp))
+{
+   char tmp[32], *aext;
+   SAMPLE_TYPE_INFO *iter = sample_type_list;
+
+   aext = uconvert_toascii(ext, tmp);
+   if (strlen(aext) == 0) return;
+
+   if (!iter) 
+      iter = sample_type_list = malloc(sizeof(struct SAMPLE_TYPE_INFO));
+   else {
+      for (iter = sample_type_list; iter->next; iter = iter->next);
+      iter = iter->next = malloc(sizeof(struct SAMPLE_TYPE_INFO));
+   }
+
+   if (iter) {
+      iter->load = load;
+      iter->save = save;
+      iter->ext = strdup(aext);
+      iter->next = NULL;
+   }
+}
+
+
+
+/* load_sample:
+ *  Loads a sample from disk.
+ */
+SAMPLE *load_sample(AL_CONST char *filename)
+{
+   char tmp[32], *aext;
+   SAMPLE_TYPE_INFO *iter;
+
+   aext = uconvert_toascii(get_extension(filename), tmp);
+   
+   for (iter = sample_type_list; iter; iter = iter->next) {
+      if (stricmp(iter->ext, aext) == 0) {
+	 if (iter->load)
+	    return iter->load(filename);
+	 return NULL;
+      }
+   }
+
+   return NULL;
+}
+
+
+
+/* save_sample:
+ *  Writes a sample to disk.
+ */
+int save_sample(AL_CONST char *filename, SAMPLE *smp)
+{
+   char tmp[32], *aext;
+   SAMPLE_TYPE_INFO *iter;
+
+   aext = uconvert_toascii(get_extension(filename), tmp);
+
+   for (iter = sample_type_list; iter; iter = iter->next) {
+      if (stricmp(iter->ext, aext) == 0) {
+	 if (iter->load)
+	    return iter->save(filename, smp);
+	 return 1;
+      }
+   }
+
+   return 1;
+}
+
+
+
+/* register_sample_file_type_exit:
+ *  Free list of registered sample file types.
+ */
+static void register_sample_file_type_exit(void)
+{
+   SAMPLE_TYPE_INFO *iter = sample_type_list, *next;
+
+   while (iter) {
+      next = iter->next;
+      free(iter->ext);
+      free(iter);
+      iter = next;
+   }
+   
+   sample_type_list = NULL;
+
+   /* If we are using a destructor, then we only want to prune the list
+    * down to valid modules. So we clean up as usual, but then reinstall
+    * the internal modules.
+    */
+   #if defined(CONSTRUCTOR_FUNCTION) && defined(DESTRUCTOR_FUNCTION)
+      _register_sample_file_type_init();
+   #endif
+
+   _remove_exit_func(register_sample_file_type_exit);
+}
+
+
+
+/* _register_sample_file_type_init:
+ *  Register built-in sample file types.
+ */
+void _register_sample_file_type_init(void)
+{
+   char buf[32];
+
+   _add_exit_func(register_sample_file_type_exit);
+
+   register_sample_file_type(uconvert_ascii("wav", buf), load_wav, NULL);
+   register_sample_file_type(uconvert_ascii("voc", buf), load_voc, NULL);
+}
+
+
+
+#if (defined CONSTRUCTOR_FUNCTION) && (defined DESTRUCTOR_FUNCTION)
+   CONSTRUCTOR_FUNCTION(static void sample_filetype_constructor());
+   DESTRUCTOR_FUNCTION(static void sample_filetype_destructor());
+
+   /* sample_filetype_constructor:
+    *  Register sample filetype functions if this object file is linked
+    *  in. This isn't called if the load_sample() and save_sample()
+    *  functions aren't used in a program, thus saving a little space
+    *  in statically linked programs.
+    */
+   static void sample_filetype_constructor()
+   {
+      _register_sample_file_type_init();
+   }
+
+   /* sample_filetype_destructor:
+    *  Since we only want to destroy the whole list when we *actually*
+    *  quit, not just when allegro_exit() is called, we need to use a
+    *  destructor to accomplish this.
+    */
+   static void sample_filetype_destructor()
+   {
+      SAMPLE_TYPE_INFO *iter = sample_type_list, *next;
+
+      while (iter) {
+         next = iter->next;
+         free(iter->ext);
+         free(iter);
+         iter = next;
+      }
+   
+      sample_type_list = NULL;
+
+      _remove_exit_func(register_sample_file_type_exit);
+   }
+#endif
--- ./include/allegro/internal/aintern.h.sample	Mon Jul 22 22:27:00 2002
+++ ./include/allegro/internal/aintern.h	Mon Jul 22 22:27:18 2002
@@ -1123,6 +1123,9 @@
 /* for readbmp.c */
 AL_FUNC(void, _register_bitmap_file_type_init, (void));
 
+/* for readsmp.c */
+AL_FUNC(void, _register_sample_file_type_init, (void));
+
 
 /* for module linking system; see comment in allegro.c */
 struct _AL_LINKER_MIDI
--- ./include/allegro/digi.h.sample	Mon Jul 22 22:05:29 2002
+++ ./include/allegro/digi.h	Mon Jul 22 22:05:31 2002
@@ -201,6 +201,8 @@
 
 AL_FUNC(void, lock_sample, (struct SAMPLE *spl));
 
+AL_FUNC(void, register_sample_file_type, (AL_CONST char *ext, AL_METHOD(struct SAMPLE *, load, (AL_CONST char *filename)), AL_METHOD(int, save, (AL_CONST char *filename, struct SAMPLE *smp))));
+
 #ifdef __cplusplus
    }
 #endif
--- ./src/allegro.c.sample	Mon Jul 22 22:08:27 2002
+++ ./src/allegro.c	Mon Jul 22 22:08:46 2002
@@ -282,8 +282,10 @@
       _midi_constructor();
       _mouse_constructor();
       _register_bitmap_file_type_init();
+      _register_sample_file_type_init();
    #else
       #ifndef DESTRUCTOR_FUNCTION
+         _register_sample_file_type_init();
          _register_bitmap_file_type_init();
       #endif
    #endif
--- ./src/sound.c.sample	Mon Jul 22 22:22:33 2002
+++ ./src/sound.c	Mon Jul 22 22:22:51 2002
@@ -772,23 +772,6 @@
 
 
 
-/* load_sample:
- *  Loads a sample from disk.
- */
-SAMPLE *load_sample(AL_CONST char *filename)
-{
-   char tmp[32];
-
-   if (ustricmp(get_extension(filename), uconvert_ascii("wav", tmp)) == 0)
-      return load_wav(filename);
-   else if (ustricmp(get_extension(filename), uconvert_ascii("voc", tmp)) == 0)
-      return load_voc(filename);
-   else
-      return NULL;
-}
-
-
-
 /* load_voc:
  *  Reads a mono VOC format sample file, returning a SAMPLE structure, 
  *  or NULL on error.
--- ./makefile.lst.sample	Mon Jul 22 22:23:05 2002
+++ ./makefile.lst	Mon Jul 22 22:23:12 2002
@@ -44,6 +44,7 @@
 	src/quantize.c \
 	src/quat.c \
 	src/readbmp.c \
+	src/readsmp.c \
 	src/rgblp15.c \
 	src/rgblp16.c \
 	src/rgblp24.c \
