Browse Source

integrated linux support

Cary Sandvig 25 years ago
parent
commit
c29cd37138

+ 14 - 9
panda/src/audio/Sources.pp

@@ -45,18 +45,23 @@
 
 
 #end lib_target
 #end lib_target
 
 
-// #begin lib_target
-//   #define TARGET audio_load_st
-//   #define LOCAL_LIBS \
-//     audio
-// 
-//   #define SOURCES \
-//     audio_load_st.cxx
-// 
-// #end lib_target
+#begin lib_target
+  #define TARGET audio_load_st
+  #define USE_SOXST yes
+  #define LOCAL_LIBS \
+    audio
+
+  #define SOURCES \
+    audio_load_st.cxx
+
+#end lib_target
 
 
 #begin test_bin_target
 #begin test_bin_target
   #define TARGET test_audio
   #define TARGET test_audio
+  #define LOCAL_LIBS \
+    audio
+  #define OTHER_LIBS \
+    $[OTHER_LIBS] pystub
 
 
   #define SOURCES \
   #define SOURCES \
     test_audio.cxx
     test_audio.cxx

+ 14 - 8
panda/src/audio/audio_linux_traits.cxx

@@ -12,6 +12,9 @@
 #include <ipc_thread.h>
 #include <ipc_thread.h>
 #include <ipc_mutex.h>
 #include <ipc_mutex.h>
 #include <set>
 #include <set>
+#include <fcntl.h>
+#include <sys/soundcard.h>
+#include <sys/ioctl.h>
 
 
 typedef set<Buffer*> BufferSet;
 typedef set<Buffer*> BufferSet;
 
 
@@ -21,11 +24,11 @@ static byte* buffer1;
 static byte* buffer2;
 static byte* buffer2;
 static byte* current_buffer;
 static byte* current_buffer;
 static byte* back_buffer;
 static byte* back_buffer;
-static byte* zero_buffer;
+byte* zero_buffer;
 static byte* scratch_buffer;
 static byte* scratch_buffer;
 static byte* fetch_buffer;
 static byte* fetch_buffer;
-static int want_buffers, have_buffers;
-static bool initializing = false;
+static int want_buffers = 0, have_buffers = 0;
+static bool initializing = true;
 static int output_fd;
 static int output_fd;
 static thread* update_thread;
 static thread* update_thread;
 static int sample_size = sizeof(short);
 static int sample_size = sizeof(short);
@@ -98,8 +101,8 @@ static void mix_in(byte* buf, byte* from, float vol, float pan) {
     signed short in_right = read_buffer(from, i+1);
     signed short in_right = read_buffer(from, i+1);
 
 
     // figure out panning at some point
     // figure out panning at some point
-    in_left *= vol;
-    in_right *= vol;
+    in_left = (short int)(in_left * vol);
+    in_right = (short int)(in_right * vol);
 
 
     // compute mixed values
     // compute mixed values
     left = sound_clamp(left+in_left);
     left = sound_clamp(left+in_left);
@@ -115,7 +118,7 @@ static void mix_buffer(byte* buf) {
   memcpy(scratch_buffer, zero_buffer, audio_buffer_size);
   memcpy(scratch_buffer, zero_buffer, audio_buffer_size);
   // do stuff
   // do stuff
   for (BufferSet::iterator i=buffers.begin(); i!=buffers.end(); ++i)
   for (BufferSet::iterator i=buffers.begin(); i!=buffers.end(); ++i)
-    min_in(scratch, (*i)->get_buffer(fetch_buffer), 1., 0.);
+    mix_in(scratch_buffer, (*i)->get_buffer(fetch_buffer), 1., 0.);
   BufferSet to_del;
   BufferSet to_del;
   for (BufferSet::iterator j=buffers.begin(); j!=buffers.end(); ++j)
   for (BufferSet::iterator j=buffers.begin(); j!=buffers.end(); ++j)
     if ((*j)->is_done())
     if ((*j)->is_done())
@@ -149,6 +152,9 @@ static void update_linux(void) {
     // mix 2 buffers and put them in place.
     // mix 2 buffers and put them in place.
     mix_buffer(current_buffer);
     mix_buffer(current_buffer);
     mix_buffer(back_buffer);
     mix_buffer(back_buffer);
+    if (initializing)
+      audio_cat->debug() << "mixed 2 buffers, want is currently at ("
+			 << want_buffers << ")" << endl;
     initializing = false;
     initializing = false;
     break;
     break;
   default:
   default:
@@ -157,7 +163,7 @@ static void update_linux(void) {
 }
 }
 
 
 static void internal_update(void*) {
 static void internal_update(void*) {
-  if ((output_fd = open(audio_device, O_WRONLY, 0)) == -1) {
+  if ((output_fd = open(audio_device->c_str(), O_WRONLY, 0)) == -1) {
     audio_cat->error() << "could not open '" << audio_device << "'" << endl;
     audio_cat->error() << "could not open '" << audio_device << "'" << endl;
     return;
     return;
   }
   }
@@ -221,7 +227,7 @@ static void initialize(void) {
 
 
   audio_cat->info() << "spawning internal update thread" << endl;
   audio_cat->info() << "spawning internal update thread" << endl;
   update_thread = thread::create(internal_update, (void*)0L,
   update_thread = thread::create(internal_update, (void*)0L,
-				 thread_PRIORITY_NORMAL);
+				 thread::PRIORITY_NORMAL);
 
 
   AudioManager::set_update_func(update_linux);
   AudioManager::set_update_func(update_linux);
   have_initialized = true;
   have_initialized = true;

+ 19 - 6
panda/src/audio/audio_linux_traits.h

@@ -11,7 +11,14 @@
 #ifndef __AUDIO_LINUX_TRAITS_H__
 #ifndef __AUDIO_LINUX_TRAITS_H__
 #define __AUDIO_LINUX_TRAITS_H__
 #define __AUDIO_LINUX_TRAITS_H__
 
 
+#include "config_audio.h"
+
+#ifndef HAVE_DEFINED_BYTE
 typedef unsigned char byte;
 typedef unsigned char byte;
+#define HAVE_DEFINED_BYTE
+#endif /* HAVE_DEFINED_BYTE */
+
+extern byte* zero_buffer;
 
 
 class EXPCL_PANDA Buffer {
 class EXPCL_PANDA Buffer {
 private:
 private:
@@ -19,15 +26,21 @@ private:
   unsigned long _size;
   unsigned long _size;
   unsigned long _pos;
   unsigned long _pos;
   bool _done;
   bool _done;
+
+  INLINE unsigned long buffer_min(unsigned long a, unsigned long b) {
+    return (a<b)?a:b;
+  }
 public:
 public:
   INLINE Buffer(byte* data, unsigned long size) : _data(data), _size(size),
   INLINE Buffer(byte* data, unsigned long size) : _data(data), _size(size),
 						  _pos(0), _done(false) {}
 						  _pos(0), _done(false) {}
   INLINE byte* get_buffer(byte* buf) {
   INLINE byte* get_buffer(byte* buf) {
-    memcpy(buf, &_data[_pos], audio_buffer_size);
-    _pos += audio_buffer_size;
-    if (_pos > _size) {
+    unsigned long copy_size = buffer_min(_size-_pos, audio_buffer_size);
+    unsigned long residue = audio_buffer_size - copy_size;
+    memcpy(buf, &_data[_pos], copy_size);
+    _pos += copy_size;
+    if (residue != 0) {
       _pos -= _size;
       _pos -= _size;
-      memcpy(&buf[audio_buffer_size-_pos-1], zero_buffer, _pos);
+      memcpy(&buf[copy_size], zero_buffer, residue);
       _done = true;
       _done = true;
     }
     }
     return buf;
     return buf;
@@ -36,7 +49,7 @@ public:
     return _done;
     return _done;
   }
   }
   INLINE unsigned long get_size(void) const {
   INLINE unsigned long get_size(void) const {
-    return _size
+    return _size;
   }
   }
   INLINE void reset(void) {
   INLINE void reset(void) {
     _done = false;
     _done = false;
@@ -57,7 +70,7 @@ public:
   static void destroy(AudioTraits::SampleClass*);
   static void destroy(AudioTraits::SampleClass*);
 public:
 public:
   // used by the loader
   // used by the loader
-  static LinuxSample* load_raw(byte*, unsigned long)
+  static LinuxSample* load_raw(byte*, unsigned long);
   // used by the players
   // used by the players
   INLINE Buffer* get_data(void);
   INLINE Buffer* get_data(void);
 };
 };

+ 237 - 74
panda/src/audio/audio_load_st.cxx

@@ -8,11 +8,16 @@
 #include "config_audio.h"
 #include "config_audio.h"
 #include "audio_trait.h"
 #include "audio_trait.h"
 
 
+#ifdef HAVE_SOXST
+
+extern "C" {
 #include <sox/st.h>
 #include <sox/st.h>
 #include <sox/patchlvl.h>
 #include <sox/patchlvl.h>
+}
 
 
 #if (PATCHLEVEL == 16)
 #if (PATCHLEVEL == 16)
 #define FORMATS formats
 #define FORMATS formats
+#define ENCODEFIELD style
 #define EFFECTS_TYPE struct effect
 #define EFFECTS_TYPE struct effect
 #define STREAM_TYPE struct soundstream
 #define STREAM_TYPE struct soundstream
 #define GETTYPE gettype
 #define GETTYPE gettype
@@ -21,10 +26,12 @@
 #define SIZES sizes
 #define SIZES sizes
 #define ENCODING styles
 #define ENCODING styles
 #define COPYFORMAT copyformat
 #define COPYFORMAT copyformat
-#define GETEFFECT geteffect
-#define UPDATEEFFECT(a, b, c, d)
+#define UPDATEEFFECT(a, b, c, d) \
+  (a)->ininfo.channels = (b)->info.channels; \
+  (a)->outinfo.channels = (c)->info.channels;
 #else /* PATCHLEVEL != 16 */
 #else /* PATCHLEVEL != 16 */
 #define FORMATS st_formats
 #define FORMATS st_formats
+#define ENCODEFIELD encoding
 #define EFFECTS_TYPE struct st_effect
 #define EFFECTS_TYPE struct st_effect
 #define STREAM_TYPE struct st_soundstream
 #define STREAM_TYPE struct st_soundstream
 #define GETTYPE st_gettype
 #define GETTYPE st_gettype
@@ -33,45 +40,64 @@
 #define SIZES st_sizes_str
 #define SIZES st_sizes_str
 #define ENCODING st_encodings_str
 #define ENCODING st_encodings_str
 #define COPYFORMAT st_copyformat
 #define COPYFORMAT st_copyformat
-#define GETEFFECT st_geteffect
 #define UPDATEEFFECT st_updateeffect
 #define UPDATEEFFECT st_updateeffect
 #endif /* PATCHLEVEL */
 #endif /* PATCHLEVEL */
 
 
+#endif /* HAVE_SOXST */
+
 Configure(audio_load_st);
 Configure(audio_load_st);
 
 
+#ifdef HAVE_SOXST
+
 // the effects we will be using are to change the rate and number of channels
 // the effects we will be using are to change the rate and number of channels
 static EFFECTS_TYPE efftab[5];  // left/mono channel effects
 static EFFECTS_TYPE efftab[5];  // left/mono channel effects
 static EFFECTS_TYPE efftabR[5]; // right channel effects
 static EFFECTS_TYPE efftabR[5]; // right channel effects
 static int neffects;            // how many effects are in action
 static int neffects;            // how many effects are in action
 
 
-static STREAM_TYPE informat;    // holder for the input
-static STREAM_TYPE outformat;   // holder for fake output;
+static STREAM_TYPE iformat;    // holder for the input
+static STREAM_TYPE oformat;   // holder for fake output;
 
 
 INLINE static void init_stream(void) {
 INLINE static void init_stream(void) {
-  informat.info.rate = 0;
-  informat.info.size = -1;
-  informat.info.encoding = -1;
-  informat.info.channels = -1;
-  informat.comment = (char*)0L;
-  informat.swap = 0;
-  informat.filetype = (char*)0L;
-  informat.fp = stdin;
-  informat.filename = "input";
-
-  outformat.info.rate = audio_mix_freq;
-  outformat.info.size = -1;
-  outformat.info.encoding = -1;
-  outformat.info.channels = 2;
-  outformat.comment = (char*)0L;
-  outformat.swap = 0;
-  outformat.filetype = (char*)0L;
-  outformat.fp = stdout;
-  outformat.filename = "output";
+  iformat.info.rate = 0;
+  iformat.info.size = -1;
+  iformat.info.ENCODEFIELD = -1;
+  iformat.info.channels = -1;
+  iformat.comment = (char*)0L;
+  iformat.swap = 0;
+  iformat.filetype = (char*)0L;
+  iformat.fp = stdin;
+  iformat.filename = "input";
+
+  oformat.info.rate = audio_mix_freq;
+  oformat.info.size = -1;
+  oformat.info.ENCODEFIELD = -1;
+  oformat.info.channels = 2;
+  oformat.comment = (char*)0L;
+  oformat.swap = 0;
+  oformat.filetype = (char*)0L;
+  oformat.fp = stdout;
+  oformat.filename = "output";
 }
 }
 
 
+INLINE static void compat_geteffect(EFFECTS_TYPE* eff, const char* name) {
+#if (PATCHLEVEL == 16)
+  eff->name = (char*)name;
+  geteffect(eff);
+#else /* PATCHLEVEL == 16 */
+  st_geteffect(eff, name);
+#endif /* PATCHLEVEL == 16 */
+}
+
+typedef void effOptFunc(EFFECTS_TYPE*, int, char**);
+#ifndef HAVE_DEFINED_BYTE
+typedef unsigned char byte;
+#define HAVE_DEFINED_BYTE
+#endif /* HAVE_DEFINED_BYTE */
+
 INLINE static void check_effects(void) {
 INLINE static void check_effects(void) {
-  bool needchan = (informat.info.rate != audio_mix_freq);
-  bool needrate = (informat.info.channels != 2);
+  bool needrate = (iformat.info.rate != audio_mix_freq);
+  bool needchan = (iformat.info.channels != 2);
+  effOptFunc* func;
 
 
   // efftab[0] is always the input stream and always exists
   // efftab[0] is always the input stream and always exists
   neffects = 1;
   neffects = 1;
@@ -79,11 +105,12 @@ INLINE static void check_effects(void) {
   // if reducing the number of samples, it is faster to run all effects
   // if reducing the number of samples, it is faster to run all effects
   // after the resample effect
   // after the resample effect
   if (needrate) {
   if (needrate) {
-    GETEFFECT(&efftab[neffects], "resample");
+    compat_geteffect(&efftab[neffects], "resample");
     // setup and give default opts
     // setup and give default opts
-    (*efftab[neffects].h->getopts)(&efftab[neffects],(int)0,(char**)0L);
+    func = (effOptFunc*)(efftab[neffects].h->getopts);
+    (*func)(&efftab[neffects],(int)0,(char**)0L);
     // copy format info to effect table
     // copy format info to effect table
-    UPDATEEFFECT(&efftab[neffects], &informat, &outformat, 0);
+    UPDATEEFFECT(&efftab[neffects], &iformat, &oformat, 0);
     // rate can't handle multiple channels so be sure and account for that
     // rate can't handle multiple channels so be sure and account for that
     if (efftab[neffects].ininfo.channels > 1)
     if (efftab[neffects].ininfo.channels > 1)
       memcpy(&efftabR[neffects], &efftab[neffects], sizeof(EFFECTS_TYPE));
       memcpy(&efftabR[neffects], &efftab[neffects], sizeof(EFFECTS_TYPE));
@@ -92,53 +119,169 @@ INLINE static void check_effects(void) {
   // if we ever have more then 2 channels in an input file, we will need to
   // if we ever have more then 2 channels in an input file, we will need to
   // deal with that somewhere here
   // deal with that somewhere here
   if (needchan) {
   if (needchan) {
-    GETEFFECT(&efftab[neffects], "avg");
+    compat_geteffect(&efftab[neffects], "avg");
     //setup and give default opts
     //setup and give default opts
-    (*efftab[neffects].h->getopts)(&efftab[neffects],(int)0,(char**)0L);
+    func = (effOptFunc*)(efftab[neffects].h->getopts);
+    (*func)(&efftab[neffects],(int)0,(char**)0L);
     // copy format info to effect table
     // copy format info to effect table
-    UPDATEEFFECT(&efftab[neffects], &informat, &outformat, 0);
+    UPDATEEFFECT(&efftab[neffects], &iformat, &oformat, 0);
     ++neffects;
     ++neffects;
   }
   }
 }
 }
 
 
-static byte* read_file(Filename filename) {
+typedef void effFlowFunc(EFFECTS_TYPE*, LONG*, LONG*, LONG*, LONG*);
+
+static LONG ibufl[BUFSIZ/2];
+static LONG ibufr[BUFSIZ/2];
+static LONG obufl[BUFSIZ/2];
+static LONG obufr[BUFSIZ/2];
+
+static int flow_effect(int e) {
+  LONG i, done, idone, odone, idonel, odonel, idoner, odoner;
+  LONG *ibuf, *obuf;
+  effFlowFunc* eflow;
+
+  // is there any input data?
+  if (efftab[e-1].odone == efftab[e-1].olen)
+    return 0;
+  if (!efftabR[e].name) {
+    // no stereo data, or effect can handle stereo data.  so run effect
+    // over the entire buffer
+    idone = efftab[e-1].olen - efftab[e-1].odone;
+    odone = BUFSIZ;
+    eflow = (effFlowFunc*)(efftab[e].h->flow);
+    (*eflow)(&efftab[e], &efftab[e-1].obuf[efftab[e-1].odone], efftab[e].obuf,
+	     &idone, &odone);
+    efftab[e-1].odone += idone;
+    efftab[e].odone = 0;
+    efftab[e].olen = odone;
+    done = idone + odone;
+  } else {
+    // put stereo data in two seperate buffers and run effect on each of them
+    idone = efftab[e-1].olen - efftab[e-1].odone;
+    odone = BUFSIZ;
+    ibuf = &efftab[e-1].obuf[efftab[e-1].odone];
+    for (i=0; i<idone; i+=2) {
+      ibufl[i/2] = *ibuf++;
+      ibufr[i/2] = *ibuf++;
+    }
+    // left
+    idonel = (idone + 1)/2; // odd-length logic
+    odonel = odone / 2;
+    eflow = (effFlowFunc*)(efftab[e].h->flow);
+    (*eflow)(&efftab[e], ibufl, obufl, &idonel, &odonel);
+    // right
+    idoner = idone/2;  // odd-length logic
+    odoner = odone/2;
+    eflow = (effFlowFunc*)(efftabR[e].h->flow);
+    (*eflow)(&efftabR[e], ibufr, obufr, &idoner, &odoner);
+    obuf = efftab[e].obuf;
+    // this loop implies that left and right effects will always output
+    // the same amount of data
+    for (i=0; i<odoner; i++) {
+      *obuf++ = obufl[i];
+      *obuf++ = obufr[i];
+    }
+    efftab[e-1].odone += idonel + idoner;
+    efftab[e].odone = 0;
+    efftab[e].olen = odonel + odoner;
+    done = idonel + idoner + odonel + odoner;
+  }
+  if (done == 0)
+    audio_cat->error() << "Effect took & gave no samples!" << endl;
+  return 1;
+}
+
+typedef void effDrainFunc(EFFECTS_TYPE*, LONG*, LONG*);
+
+static int drain_effect(int e) {
+  LONG i, olen, olenl, olenr;
+  LONG *obuf;
+  effDrainFunc* edrain;
+
+  if (!efftabR[e].name) {
+    efftab[e].olen = BUFSIZ;
+    edrain = (effDrainFunc*)(efftab[e].h->drain);
+    (*edrain)(&efftab[e], efftab[e].obuf, &efftab[e].olen);
+  } else {
+    olen = BUFSIZ;
+    // left
+    olenl = olen / 2;
+    edrain = (effDrainFunc*)(efftab[e].h->drain);
+    (*edrain)(&efftab[e], obufl, &olenl);
+    // right
+    olenr = olen / 2;
+    edrain = (effDrainFunc*)(efftab[e].h->drain);
+    (*edrain)(&efftabR[e], obufr, &olenr);
+    obuf = efftab[e].obuf;
+    // this loop implies left and right effect will always output the same
+    // amount of data
+    for (i=0; i<olenr; ++i) {
+      *obuf++ = obufl[i];
+      *obuf++ = obufr[i];
+    }
+    efftab[e].olen = olenl + olenr;
+  }
+  return (efftab[e].olen);
+}
+
+typedef int formatSReadFunc(STREAM_TYPE*);
+typedef LONG formatReadFunc(STREAM_TYPE*, LONG*, LONG);
+typedef int formatStopReadFunc(STREAM_TYPE*);
+typedef void effStartFunc(EFFECTS_TYPE*);
+typedef void effStopFunc(EFFECTS_TYPE*);
+
+static void read_file(Filename filename, byte** buf, unsigned long& slen) {
   int e, havedata;
   int e, havedata;
   ostringstream out;
   ostringstream out;
+  formatSReadFunc* srfunc;
+  formatReadFunc* rfunc;
+  formatStopReadFunc* strfunc;
+  effStartFunc* esfunc;
+  effStopFunc* estfunc;
 
 
   init_stream();
   init_stream();
-  if ((informat.fp = fopen(filename.c_str(), READBINARY)) == NULL) {
+  if ((iformat.fp = fopen(filename.c_str(), READBINARY)) == NULL) {
     audio_cat->error() << "could not open '" << filename << "'" << endl;
     audio_cat->error() << "could not open '" << filename << "'" << endl;
-    return (byte*)0L;
+    *buf = (byte*)0L;
+    slen = 0;
+    return;
   }
   }
-  informat.filname = filename.c_str();
-  informat.filetype = filename.get_extension();
-  informat.comment = filename.c_str();  // for lack of anything better
+  iformat.filename = (char*)filename.c_str();
+  iformat.filetype = (char*)filename.get_extension().c_str();
+  iformat.comment = (char*)filename.c_str();  // for lack of anything better
   // now we start some more real work
   // now we start some more real work
-  GETTYPE(&informat);
+  GETTYPE(&iformat);
   // read and write starters can change their formats
   // read and write starters can change their formats
-  if ((*informat.h->startread)(&informat) == COMPAT_EOF) {
+  srfunc = (formatSReadFunc*)(iformat.h->startread);
+  if ((*srfunc)(&iformat) == COMPAT_EOF) {
     audio_cat->error() << "failed to start read" << endl;
     audio_cat->error() << "failed to start read" << endl;
-    return (byte*)0L;
+    *buf = (byte*)0L;
+    slen = 0;
+    return;
   }
   }
-  CHECKFORMAT(&informat);
+  CHECKFORMAT(&iformat);
   if (audio_cat->is_debug())
   if (audio_cat->is_debug())
-    audio_cat->debug() << "Input file '" << informat.filename
-		       << "': sample rate = " << informat.info.rate
-		       << "  size = " << SIZES[informat.info.size]
-		       << "  encoding = " << ENCODING[informat.info.encoding]
-		       << "  " << informat.info.channels
-		       << (informat.info.channels > 1)?"channels":"channel"
+    audio_cat->debug() << "Input file '" << iformat.filename
+		       << "': sample rate = " << iformat.info.rate
+		       << "  size = " << SIZES[iformat.info.size]
+		       << "  encoding = " << ENCODING[iformat.info.ENCODEFIELD]
+		       << "  " << iformat.info.channels
+		       << ((iformat.info.channels > 1)?"channels":"channel")
 		       << endl;
 		       << endl;
   if (audio_cat->is_debug())
   if (audio_cat->is_debug())
-    audio_cat->debug() << "Input file comment: '" << informat.comment << "'"
+    audio_cat->debug() << "Input file comment: '" << iformat.comment << "'"
 		       << endl;
 		       << endl;
-  COPYFORMAT(&informat, &outformat);
+  COPYFORMAT(&iformat, &oformat);
   check_effects();
   check_effects();
   // start all effects
   // start all effects
   for (e=1; e<neffects; ++e) {
   for (e=1; e<neffects; ++e) {
-    (*efftab[e].h->start)(&efftab[e]);
-    if (efftabR[e].name)
-      (*efftabR[e].h->start)(&efftabR[e]);
+    esfunc = (effStartFunc*)(efftab[e].h->start);
+    (*esfunc)(&efftab[e]);
+    if (efftabR[e].name) {
+      esfunc = (effStartFunc*)(efftabR[e].h->start);
+      (*esfunc)(&efftabR[e]);
+    }
   }
   }
   // reserve output buffers for all effects
   // reserve output buffers for all effects
   for (e=0; e<neffects; e++) {
   for (e=0; e<neffects; e++) {
@@ -147,8 +290,8 @@ static byte* read_file(Filename filename) {
       efftabR[e].obuf = new LONG[BUFSIZ*sizeof(LONG)];
       efftabR[e].obuf = new LONG[BUFSIZ*sizeof(LONG)];
   }
   }
   // get the main while loop ready, have some data for it to start on
   // get the main while loop ready, have some data for it to start on
-  efftab[0].olen = (*informat.h->read)(&informat, efftab[0].obuf,
-				       (LONG)BUFSIZ);
+  rfunc = (formatReadFunc*)(iformat.h->read);
+  efftab[0].olen = (*rfunc)(&iformat, efftab[0].obuf, (LONG)BUFSIZ);
   efftab[0].odone = 0;
   efftab[0].odone = 0;
   // run input data thru effects and get more until olen == 0
   // run input data thru effects and get more until olen == 0
   while (efftab[0].olen > 0) {
   while (efftab[0].olen > 0) {
@@ -167,7 +310,7 @@ static byte* read_file(Filename filename) {
 	for (LONG i=0; i<efftab[neffects-1].olen; ++i) {
 	for (LONG i=0; i<efftab[neffects-1].olen; ++i) {
 	  LONG foo = efftab[neffects-1].obuf[i];
 	  LONG foo = efftab[neffects-1].obuf[i];
 	  signed short bar = (foo >> 16);
 	  signed short bar = (foo >> 16);
-	  unsigned char *b = &bar;
+	  unsigned char *b = (unsigned char*)&bar;
 	  out << *b << *(++b);
 	  out << *b << *(++b);
 	}
 	}
 	efftab[neffects-1].odone = efftab[neffects-1].olen;
 	efftab[neffects-1].odone = efftab[neffects-1].olen;
@@ -181,8 +324,8 @@ static byte* read_file(Filename filename) {
 	}
 	}
     } while (havedata);
     } while (havedata);
     // read another chunk
     // read another chunk
-    efftab[0].olen = (*informat.h->read)(&informat, efftab[0].obuf,
-					 (LONG)BUFSIZ);
+    rfunc = (formatReadFunc*)(iformat.h->read);
+    efftab[0].olen = (*rfunc)(&iformat, efftab[0].obuf, (LONG)BUFSIZ);
     efftab[0].odone = 0;
     efftab[0].odone = 0;
   }
   }
   // drain the effects out first to last.  push the residue thru subsequent
   // drain the effects out first to last.  push the residue thru subsequent
@@ -195,7 +338,7 @@ static byte* read_file(Filename filename) {
 	for (LONG i=0; i<efftab[neffects-1].olen; ++i) {
 	for (LONG i=0; i<efftab[neffects-1].olen; ++i) {
 	  LONG foo = efftab[neffects-1].obuf[i];
 	  LONG foo = efftab[neffects-1].obuf[i];
 	  signed short bar = (foo >> 16);
 	  signed short bar = (foo >> 16);
-	  unsigned char *b = &bar;
+	  unsigned char *b = (unsigned char*)&bar;
 	  out << *b << *(++b);
 	  out << *b << *(++b);
 	}
 	}
       }
       }
@@ -204,23 +347,36 @@ static byte* read_file(Filename filename) {
     }
     }
   // stop all effects.  In so doing, some may generate more data
   // stop all effects.  In so doing, some may generate more data
   for (e=1; e<neffects; ++e) {
   for (e=1; e<neffects; ++e) {
-    (*efftab[e].h->stop)(&efftab[e]);
-    if (efftabR[e].name)
-      (*efftabR[e].h->stop)(&efftabR[e]);
+    estfunc = (effStopFunc*)(efftab[e].h->stop);
+    (*estfunc)(&efftab[e]);
+    if (efftabR[e].name) {
+      estfunc = (effStopFunc*)(efftabR[e].h->stop);
+      (*estfunc)(&efftabR[e]);
+    }
   }
   }
   // stop reading the file
   // stop reading the file
-  if ((*informat.h->stopread)(&informat) == COMPAT_EOF) {
+  strfunc = (formatStopReadFunc*)(iformat.h->stopread);
+  if ((*strfunc)(&iformat) == COMPAT_EOF) {
     audio_cat->error() << "error stoping input file" << endl;
     audio_cat->error() << "error stoping input file" << endl;
   }
   }
-  fclose(informat.fp);
+  fclose(iformat.fp);
   // generate output
   // generate output
   string s = out.str();
   string s = out.str();
-  int slen = s.length();
-  byte* ret = new byte[slen];
-  memcpy(ret, s.data(), slen);
-  return ret;
+  slen = s.length();
+  *buf = new byte[slen];
+  memcpy(*buf, s.data(), slen);
+}
+
+extern "C" {
+void cleanup(void) {
+  // make sure everything is shut down
+  if (iformat.fp)
+    fclose(iformat.fp);
+}
 }
 }
 
 
+#endif /* HAVE_SOXST */
+
 #ifdef AUDIO_USE_MIKMOD
 #ifdef AUDIO_USE_MIKMOD
 
 
 void AudioDestroySt(AudioTraits::SampleClass* sample) {
 void AudioDestroySt(AudioTraits::SampleClass* sample) {
@@ -259,18 +415,23 @@ void AudioLoadSt(AudioTraits::SampleClass** sample,
 
 
 #ifdef AUDIO_USE_LINUX
 #ifdef AUDIO_USE_LINUX
 
 
+#include "audio_linux_traits.h"
+
 void AudioDestroySt(AudioTraits::SampleClass* sample) {
 void AudioDestroySt(AudioTraits::SampleClass* sample) {
   delete sample;
   delete sample;
 }
 }
 
 
 void AudioLoadSt(AudioTraits::SampleClass** sample,
 void AudioLoadSt(AudioTraits::SampleClass** sample,
 		 AudioTraits::PlayerClass** player,
 		 AudioTraits::PlayerClass** player,
-		 AudioTraits::DeleteSampleFunc** destroy, Filename) {
-  audio_cat->warning() << "linux doesn't support reading raw data yet"
-		       << endl;
-  *sample = (AudioTraits::SampleClass*)0L;
-  *player = (AudioTraits::PlayerClass*)0L;
-  *destroy = AudioDestroySt;
+		 AudioTraits::DeleteSampleFunc** destroy, Filename filename) {
+  byte* buf;
+  unsigned long len;
+  read_file(filename, &buf, len);
+  if (buf != (byte*)0L) {
+    *sample = LinuxSample::load_raw(buf, len);
+    *player = LinuxPlayer::get_instance();
+    *destroy = AudioDestroySt;
+  }
 }
 }
 
 
 #else /* AUDIO_USE_LINUX */
 #else /* AUDIO_USE_LINUX */
@@ -302,6 +463,7 @@ void AudioLoadSt(AudioTraits::SampleClass** sample,
 #endif /* AUDIO_USE_MIKMOD */
 #endif /* AUDIO_USE_MIKMOD */
 
 
 ConfigureFn(audio_load_st) {
 ConfigureFn(audio_load_st) {
+#ifdef HAVE_SOXST
   for (int i=0; FORMATS[i].names != (char**)0L; ++i)
   for (int i=0; FORMATS[i].names != (char**)0L; ++i)
     for (int j=0; FORMATS[i].names[j] != (char*)0L; ++j) {
     for (int j=0; FORMATS[i].names[j] != (char*)0L; ++j) {
       if (audio_cat->is_debug())
       if (audio_cat->is_debug())
@@ -309,4 +471,5 @@ ConfigureFn(audio_load_st) {
 			   << "'" << endl;
 			   << "'" << endl;
       AudioPool::register_sample_loader(FORMATS[i].names[j], AudioLoadSt);
       AudioPool::register_sample_loader(FORMATS[i].names[j], AudioLoadSt);
     }
     }
+#endif /* HAVE_SOXST */
 }
 }

+ 1 - 1
panda/src/audio/audio_load_wav.cxx

@@ -60,7 +60,7 @@ void AudioLoadWav(AudioTraits::SampleClass** sample,
 		  AudioTraits::PlayerClass** player,
 		  AudioTraits::PlayerClass** player,
 		  AudioTraits::DeleteSampleFunc** destroy, Filename) {
 		  AudioTraits::DeleteSampleFunc** destroy, Filename) {
   *sample = (AudioTraits::SampleClass*)0L;
   *sample = (AudioTraits::SampleClass*)0L;
-  *player = (audioTraits::PlayerClass*)0L;
+  *player = (AudioTraits::PlayerClass*)0L;
   *destroy = AudioDestroyWav;
   *destroy = AudioDestroyWav;
 }
 }
 
 

+ 2 - 6
panda/src/audio/audio_trait.h

@@ -55,15 +55,11 @@ public:
 #ifdef PENV_WIN32
 #ifdef PENV_WIN32
 #define AUDIO_USE_WIN32
 #define AUDIO_USE_WIN32
 #else /* PENV_WIN32 */
 #else /* PENV_WIN32 */
-/*
 #ifdef PENV_LINUX
 #ifdef PENV_LINUX
 #define AUDIO_USE_LINUX
 #define AUDIO_USE_LINUX
-#else /* PENV_LINUX *
-*/
+#else /* PENV_LINUX */
 #define AUDIO_USE_NULL
 #define AUDIO_USE_NULL
-/*
-#endif /* PENV_LINUX *
-*/
+#endif /* PENV_LINUX */
 #endif /* PENV_WIN32 */
 #endif /* PENV_WIN32 */
 #endif /* HAVE_MIKMOD */
 #endif /* HAVE_MIKMOD */