Index: ode.c
===================================================================
--- ode.c	(revision 1149)
+++ ode.c	(revision 1150)
@@ -1310,12 +1310,13 @@
      strcpy(raydium_ode_element[i].name,name);
      raydium_ode_element[i].object=group;
      raydium_ode_element[i].user_tag=tag;
-     if(strlen(mesh))
-      {
-      raydium_ode_element[i].mesh=raydium_object_find_load(mesh);
-      if(radius<0) // AUTODETECT
-         radius=raydium_object_find_dist_max(raydium_ode_element[i].mesh)*-radius;
-      }
+     if(mesh!=NULL)
+         if(strlen(mesh))
+          {
+          raydium_ode_element[i].mesh=raydium_object_find_load(mesh);
+          if(radius<0) // AUTODETECT
+             radius=raydium_object_find_dist_max(raydium_ode_element[i].mesh)*-radius;
+          }
 
      if(type==RAYDIUM_ODE_STANDARD)
         {
@@ -1390,18 +1391,19 @@
      strcpy(raydium_ode_element[i].name,name);
      raydium_ode_element[i].object=group;
      raydium_ode_element[i].user_tag=tag;
-     if(strlen(mesh))
-     {
-      raydium_ode_element[i].mesh=raydium_object_find_load(mesh);
-      if(tx<0) // AUTODETECT
+     if(mesh!=NULL)
+         if(strlen(mesh))
          {
-         dReal ratio=tx;
-         raydium_object_find_axes_max(raydium_ode_element[i].mesh,&tx,&ty,&tz);
-         tx*=(-ratio);
-         ty*=(-ratio);
-         tz*=(-ratio);
+          raydium_ode_element[i].mesh=raydium_object_find_load(mesh);
+          if(tx<0) // AUTODETECT
+             {
+             dReal ratio=tx;
+             raydium_object_find_axes_max(raydium_ode_element[i].mesh,&tx,&ty,&tz);
+             tx*=(-ratio);
+             ty*=(-ratio);
+             tz*=(-ratio);
+             }
          }
-     }
 
      if(type==RAYDIUM_ODE_STANDARD)
      {
@@ -1479,31 +1481,32 @@
         strcpy(raydium_ode_element[i].name,name);
         raydium_ode_element[i].object=group;
         raydium_ode_element[i].user_tag=tag;
-        if(strlen(mesh))
-        {
-            raydium_ode_element[i].mesh=raydium_object_find_load(mesh);
-            if(radius<0) // AUTODETECT
+        if(mesh!=NULL)
+            if(strlen(mesh))
             {
-                dReal ratio=radius;
-                GLfloat tx,ty,tz;
-                raydium_object_find_axes_max(raydium_ode_element[i].mesh,&tx,&ty,&tz);
-                if(tz<tx || tz<ty)
-                    {
-                    raydium_log("ODE: Error: cannot create capsule: autodetect failed: longest side of the mesh should be Z !");
-                    return -1;
-                    }
-                radius=(raydium_math_max(tx,ty)*(-ratio))/2.f;
-                length=tz*(-ratio);
-            }
-        // ODE: "cylinder's length is not counting the caps (half-spheres)"
-        length-=(radius*2.f);
+                raydium_ode_element[i].mesh=raydium_object_find_load(mesh);
+                if(radius<0) // AUTODETECT
+                {
+                    dReal ratio=radius;
+                    GLfloat tx,ty,tz;
+                    raydium_object_find_axes_max(raydium_ode_element[i].mesh,&tx,&ty,&tz);
+                    if(tz<tx || tz<ty)
+                        {
+                        raydium_log("ODE: Error: cannot create capsule: autodetect failed: longest side of the mesh should be Z !");
+                        return -1;
+                        }
+                    radius=(raydium_math_max(tx,ty)*(-ratio))/2.f;
+                    length=tz*(-ratio);
+                }
+            // ODE: "cylinder's length is not counting the caps (half-spheres)"
+            length-=(radius*2.f);
 
-        if(radius<=0 || length<=0)
-            {
-            raydium_log("ODE: Error: cannot create capsule: invalid size: The full lenght has to be at least twice the radius (Z aligned)");
-            return -1;
+            if(radius<=0 || length<=0)
+                {
+                raydium_log("ODE: Error: cannot create capsule: invalid size: The full lenght has to be at least twice the radius (Z aligned)");
+                return -1;
+                }
             }
-        }
 
     if(type==RAYDIUM_ODE_STANDARD)
     {
tSourcePitch(int src, ALfloat *p)
+{
+ int result=raydium_sound_SourceVerify(src);
+ if(result==0)
+ {
+  alGetSourcef(raydium_sound_source[src],AL_PITCH,p);
+  raydium_sound_verify("getting source pitch");
+ }
+ return(result);
+}
+
+
+//SETS SOURCE PITCH
+//TAKES A SOURCE NUMBER AND AN ALfloat
+int raydium_sound_SetSourcePitch(int src, ALfloat p)
+{
+ int result=raydium_sound_SourceVerify(src);
+ if(result==0)
+ {
+  if(p>2.0)
+  {
+   p=2.0;//CLIPPING
+   raydium_log("sound: Pitch Overflow , clipped to 2");
+  }
+  if(p<=0.0)
+  {
+   p=0.1; // Seems ok :)
+   raydium_log("sound: Tried to set negative or 0 Pitch , clipped to 0.1");
+  }
+  alSourcef(raydium_sound_source[src],AL_PITCH,p);
+  raydium_sound_verify("setting source pitch");
+ }
+ return(result);
+}
+
+
+//GETS SOURCE GAIN
+//TAKES A SOURCE NUMBER
+//GIVES AN ALfloat
+int raydium_sound_GetSourceGain(int src, ALfloat *g)
+{
+ int result=raydium_sound_SourceVerify(src);
+ if(result==0)
+ {
+  alGetSourcef(raydium_sound_source[src],AL_GAIN,g);
+  raydium_sound_verify("getting source gain");
+ }
+ return(result);
+}
+
+
+//SETS SOURCE GAIN
+//TAKES A SOURCE NUMBER AND AN ALfloat
+int raydium_sound_SetSourceGain(int src, ALfloat g)
+{
+ int result=raydium_sound_SourceVerify(src);
+ if(result==0)
+ {
+  if(g<0.0)
+  {
+   g=0.0;
+   raydium_log("sound: Tried to set negative Gain , clipped to 0");
+  }
+  alSourcef(raydium_sound_source[src],AL_GAIN,g);
+  raydium_sound_verify("setting source gain");
+ }
+ return(result);
+}
+
+//SETS SOURCE POSITION
+//TAKES A SOURCE NUMBER AND AN ALfloat ARRAY {x,y,z}
+int raydium_sound_SetSourcePos(int src, ALfloat Pos[])
+{
+ int result=raydium_sound_SourceVerify(src);
+ if(result==0 && raydium_sound_Array3IsValid(Pos))
+ {
+  alSourcefv(raydium_sound_source[src],AL_POSITION,Pos);
+  raydium_sound_verify("setting source position");
+ }
+ return(result);
+}
+
+
+int raydium_sound_SetSourcePosCamera(int src)
+{
+ALfloat p[3];
+p[0]=raydium_camera_x;
+p[1]=raydium_camera_y;
+p[2]=raydium_camera_z;
+return raydium_sound_SetSourcePos(src,p);
+}
+
+//GETS SOURCE POSITION
+//TAKES A SOURCE NUMBER
+//GIVES AN ALfloat ARRAY {x,y,z}
+int raydium_sound_GetSourcePos(int src, ALfloat *Pos[] )
+{
+ int result=raydium_sound_SourceVerify(src);
+ if(result==0)
+ {
+  alGetSourcefv(raydium_sound_source[src],AL_POSITION,(ALfloat *)&(*Pos));
+  raydium_sound_verify("getting source position");
+ }
+ return(result);
+}
+
+
+//SETS SOURCE DIRECTION
+//TAKES A SOURCE NUMBER AND AN ALfloat ARRAY {x,y,z}
+int raydium_sound_SetSourceDir(int src, ALfloat Dir[])
+{
+ int result=raydium_sound_SourceVerify(src);
+ if(result==0 && raydium_sound_Array3IsValid(Dir))
+ {
+  alSourcefv(raydium_sound_source[src],AL_DIRECTION,Dir);
+  raydium_sound_verify("setting source direction");
+ }
+ return(result);
+}
+
+//GETS SOURCE DIRECTION
+//TAKES A SOURCE NUMBER
+//GIVES AN ALfloat ARRAY {x,y,z}
+int raydium_sound_GetSourceDir(int src, ALfloat *Dir[] )
+{
+ int result=raydium_sound_SourceVerify(src);
+ if(result==0)
+ {
+  alGetSourcefv(raydium_sound_source[src],AL_DIRECTION,(ALfloat *)&(*Dir));
+  raydium_sound_verify("getting source direction");
+ }
+ return(result);
+}
+
+
+//SETS SOURCE VELOCITY
+//TAKES A SOURCE NUMBER AND AN ALfloat ARRAY {x,y,z}
+int raydium_sound_SetSourceVel(int src, ALfloat Vel[])
+{
+ int result=raydium_sound_SourceVerify(src);
+ if(result==0 && raydium_sound_Array3IsValid(Vel))
+ {
+  alSourcefv(raydium_sound_source[src],AL_VELOCITY,Vel);
+  raydium_sound_verify("setting source velocity");
+ }
+ return(result);
+}
+
+//GETS SOURCE VELOCITY
+//TAKES A SOURCE NUMBER
+//GIVES AN ALfloat ARRAY {x,y,z}
+int raydium_sound_GetSourceVel(int src, ALfloat *Vel[] )
+{
+ int result=raydium_sound_SourceVerify(src);
+ if(result==0)
+ {
+  alGetSourcefv(raydium_sound_source[src],AL_VELOCITY,(ALfloat *)&(*Vel));
+  raydium_sound_verify("getting source velocity");
+ }
+ return(result);
+}
+
+
+
+//SETS LISTENER POSITION
+//TAKES AN ALfloat ARRAY {x,y,z}
+void raydium_sound_SetListenerPos(ALfloat Pos[])
+{
+ if(!raydium_sound_Array3IsValid(Pos)) return;
+ 
+ alListenerfv(AL_POSITION,Pos);
+   raydium_sound_verify("setting listener position");
+}
+
+//GETS LISTENER POSITION
+//GIVES AN ALfloat ARRAY {x,y,z}
+void raydium_sound_GetListenerPos(ALfloat *Pos[] )
+{
+ alGetListenerfv(AL_POSITION,(ALfloat *)&(*Pos));
+   raydium_sound_verify("getting listener position");
+}
+
+//SETS LISTENER ORIENTATION
+//TAKES AN ALfloat ARRAY {x,y,z,x2,y2,z2}
+//                        ATvector UPvector
+void raydium_sound_SetListenerOr(ALfloat Or[])
+{
+ if(!raydium_sound_Array3IsValid(Or)) return;
+ if(!raydium_sound_Array3IsValid(Or+3)) return;
+ 
+ alListenerfv(AL_ORIENTATION,Or);
+   raydium_sound_verify("setting listener orientation");
+}
+
+//GETS LISTENER ORIENTATION
+//GIVES AN ALfloat ARRAY {x,y,z,x2,y2,z2}
+//                        ATvector UPvector
+void raydium_sound_GetListenerOr(ALfloat *Or[] )
+{
+ 
+ alGetListenerfv(AL_ORIENTATION,(ALfloat *)&(*Or));
+   raydium_sound_verify("getting listener orientation");
+}
+
+//SETS LISTENER VELOCITY
+//TAKES AN ALfloat ARRAY {x,y,z}
+void raydium_sound_SetListenerVel(ALfloat Vel[])
+{
+if(!raydium_sound_Array3IsValid(Vel)) return;
+
+ alListenerfv(AL_VELOCITY,Vel);
+   raydium_sound_verify("setting listener velocity");
+}
+
+//GETS LISTENER VELOCITY
+//GIVES AN ALfloat ARRAY {x,y,z}
+void raydium_sound_GetListenerVel(ALfloat *Vel[] )
+{
+ alGetListenerfv(AL_VELOCITY,(ALfloat *)&(*Vel));
+   raydium_sound_verify("getting listener velocity");
+}
+
+
+//INITIALISATION
+void raydium_sound_init(void)
+{
+ ALfloat listenerPos[]={-10.0,0.0,0.0};
+ ALfloat listenerVel[]={0.0,0.0,0.0};
+// ALfloat back[] ={ 0.0f, 0.0f, -1.0f, 0.0f, 1.0f, 0.0f };
+ ALfloat front[]={ 1.0f, 0.0f,  1.0f, 0.0f, 0.0f, 1.0f };
+
+#ifdef NO_SOUND_DEBUG
+return;
+#endif
+
+ alutInit(&raydium_init_argc, raydium_init_argv);
+//alutInit(0, NULL) ;
+ alGetError();
+
+ alListenerfv(AL_POSITION,listenerPos);
+ alListenerfv(AL_VELOCITY,listenerVel);
+ alListenerfv(AL_ORIENTATION,front);
+ alDistanceModel(AL_INVERSE_DISTANCE);
+//#ifdef __linux
+ alGetError(); /* clear error */
+ alGenBuffers(RAYDIUM_SOUND_NUM_BUFFERS, raydium_sound_buffer);
+ raydium_sound_verify("alGenBuffers");
+//#else
+//alGenBuffers(RAYDIUM_SOUND_NUM_BUFFERS,raydium_sound_buffer);
+// if (!raydium_sound_buffer)
+// {
+//  raydium_log("sound: Error creating buffers !!");
+//  exit(1);
+// }
+//#endif
+
+ raydium_log("sound: Buffer creation successfull");
+
+//#ifdef __linux
+ alGetError(); /* clear error */
+ alGenSources(RAYDIUM_SOUND_NUM_SOURCES, raydium_sound_source);
+ raydium_sound_verify("alGenSources");
+//#else
+// raydium_sound_verify("alGenSources");
+//#endif
+ raydium_sound_top_buffer=2; //first available buffer (2 first are used by music)
+ raydium_sound=1;
+ raydium_sound_music_file=NULL;
+ raydium_sound_DefaultReferenceDistance=50.f; // default distance where the source sound is half volume
+ raydium_sound_music_eof_callback=NULL;
+ raydium_log("sound: OK");
+ 
+}
+
+//PLAYS A SOURCE
+int raydium_sound_SourcePlay(int src)
+{
+ int result=raydium_sound_SourceVerify(src);
+ if(result==0)
+ {
+  alSourcePlay(raydium_sound_source[src]);
+ }
+ return(result);
+}
+
+//STOPS A SOURCE
+int raydium_sound_SourceStop(int src)
+{
+ int result=raydium_sound_SourceVerify(src);
+ if(result==0)
+ {
+  alSourceStop(raydium_sound_source[src]);
+ }
+ return(result);
+}
+
+//PAUSE A SOURCE
+int raydium_sound_SourcePause(int src)
+{
+ int result=raydium_sound_SourceVerify(src);
+ if(result==0)
+ {
+  alSourcePause(raydium_sound_source[src]);
+ }
+ return(result);
+}
+
+//UNPAUSE A SOURCE
+int raydium_sound_SourceUnpause(int src)
+{
+ int result;
+ int state;
+ result=raydium_sound_SourceVerify(src);
+ if(result==0)
+ {
+  alGetSourcei(raydium_sound_source[src], AL_SOURCE_STATE, &state);
+  if(state==AL_PAUSED)
+    alSourcePlay(raydium_sound_source[src]);
+ }
+ return(result);
+}
+
+
+//THINGS TO DO WHEN EXITING
+void raydium_sound_close(void)
+{
+int i;
+ if(raydium_sound==1) // WE DO THESE THINGS ONLY IF OPEN AL INIT WAS OK
+ {
+  for(i=0;i<raydium_sound_top_buffer;i++)
+    raydium_sound_SourceStop(i);
+  raydium_log("sound: Deleting sources");
+   alDeleteSources(RAYDIUM_SOUND_NUM_SOURCES,raydium_sound_source);
+  raydium_log("sound: Deleting buffers");
+   alDeleteBuffers(RAYDIUM_SOUND_NUM_BUFFERS,raydium_sound_buffer);
+  raydium_log("sound: Releasing OpenAL");
+   alutExit();
+ }
+}
+
+
+int BufferData(ALuint buffer,OggVorbis_File *file,vorbis_info *ogginfo) 
+{
+  unsigned int count=0;
+  int stream;
+  int amt;
+  ALint format;
+
+  while(count<SOUNDDATASIZE)
+  {
+    amt=ov_read(file,&(raydium_sound_music_buf[count]),
+          SOUNDDATASIZE-count,
+          0,2,1,&stream);
+    if(amt<=0)
+    {
+//      if(amt<0)fprintf(stderr,"ov_read error: ");
+      raydium_log("sound: ov_read error");
+      break;
+    }
+    count+=amt;
+  }
+
+  if(!count)
+    return 0;
+
+  if(ogginfo->channels==1)
+    format=AL_FORMAT_MONO16;
+  else
+    format=AL_FORMAT_STEREO16;
+
+  alBufferData(buffer,format,raydium_sound_music_buf,count,ogginfo->rate);
+  return 1;
+}
+
+void raydium_sound_internal_cleanstreambuffs(void)
+{
+  ALint format;
+  vorbis_info *ogginfo;
+  
+  ogginfo=raydium_sound_ogginfo;
+  memset(raydium_sound_music_buf,0,SOUNDDATASIZE);
+
+  if(ogginfo->channels==1)
+    format=AL_FORMAT_MONO16;
+  else
+    format=AL_FORMAT_STEREO16;
+
+  alBufferData(raydium_sound_buffer[0],format,raydium_sound_music_buf,SOUNDDATASIZE,ogginfo->rate);
+  alBufferData(raydium_sound_buffer[1],format,raydium_sound_music_buf,SOUNDDATASIZE,ogginfo->rate);
+}
+
+
+int StartMusic(ALuint musicsource,ALuint *buffers,OggVorbis_File *file,
+      vorbis_info *ogginfo)
+{
+  int ok;
+  alSourceStop(musicsource);
+  memset(raydium_sound_music_buf,0,SOUNDDATASIZE);
+  ok=BufferData(raydium_sound_buffer[0],file,ogginfo) 
+     && BufferData(raydium_sound_buffer[1],file,ogginfo);
+  alSourceQueueBuffers(musicsource,2,raydium_sound_buffer);
+  alSourcePlay(musicsource);
+  return ok;
+} 
+
+
+
+//try to open music
+int raydium_sound_load_music(char *fname)
+{
+#ifdef NO_SOUND_DEBUG
+return -1;
+#endif
+
+ if(raydium_sound_music_file) fclose(raydium_sound_music_file);
+ raydium_sound_music_file=NULL;
+ 
+ if(fname==NULL || strlen(fname)==0)
+    return 0;
+ 
+ raydium_sound_music_file = raydium_file_fopen( fname, "rb" );
+ if(raydium_sound_music_file == NULL)
+ {
+  raydium_log("sound: Could not open %s", fname);
+  perror("raydium_sound_load_music");
+  return(-1);
+ }
+
+ alSourcei( raydium_sound_source[0], AL_SOURCE_RELATIVE, AL_TRUE );
+ alSourcei( raydium_sound_source[0], AL_LOOPING, AL_FALSE );
+
+ if(ov_open(raydium_sound_music_file, &raydium_sound_vf, NULL, 0) < 0)
+ {
+  raydium_log("ERROR: Failed to open %s as vorbis",fname);
+  return(-1);
+ }
+ raydium_sound_ogginfo=ov_info(&raydium_sound_vf,-1);
+ 
+// size = bits/8 * ov_info(&raydium_sound_vf, 0)->channels; 
+StartMusic(raydium_sound_source[0],raydium_sound_buffer,
+           &raydium_sound_vf,raydium_sound_ogginfo);
+ 
+return(0);
+}
+
+
+void raydium_sound_music_callback(void)
+{
+ALuint nprocessed;
+ALuint buffer;
+ALint sourcestate;
+char newfile[RAYDIUM_MAX_NAME_LEN];
+
+ if(raydium_sound_music_file==NULL) return;
+
+ if(feof(raydium_sound_music_file))
+    {
+    fseek(raydium_sound_music_file,0,SEEK_SET);//rewind in the file if we hit the end
+    raydium_log("sound: end of file reached");
+    if(raydium_sound_music_eof_callback && raydium_sound_music_eof_callback(newfile)>0)
+	{
+	if(strlen(newfile)) 
+	    raydium_sound_load_music(newfile);
+	else
+	    {
+	    // may cause glitches on next music.. ?
+	    //fclose(raydium_sound_music_file);
+	    //raydium_sound_music_file=NULL;
+	    raydium_sound_load_music(NULL);
+	    }
+	return ;
+	}
+    }
+
+ alGetSourcei(raydium_sound_source[0],AL_BUFFERS_PROCESSED,&nprocessed);
+ if(nprocessed) // or while...
+ {
+  static int last;
+  alSourceUnqueueBuffers(raydium_sound_source[0],1,&buffer);
+  if(buffer==last)
+    {
+    raydium_log("sound: OpenAL internal buffer mistake: cleaning buffers");
+    alSourceStop(raydium_sound_source[0]);
+    raydium_sound_internal_cleanstreambuffs();
+    alSourcePlay(raydium_sound_source[0]);
+    }
+    else  
+    {
+    last=buffer;
+    BufferData(buffer,&raydium_sound_vf,raydium_sound_ogginfo);
+    alSourceQueueBuffers(raydium_sound_source[0],1,&buffer);
+    nprocessed--;
+    }
+ } 
+
+ //restart playing if needed
+ alGetSourcei(raydium_sound_source[0],AL_SOURCE_STATE,&sourcestate);
+ if(sourcestate!=AL_PLAYING)
+ {
+  raydium_log("sound: music source stopped, back to play");
+  StartMusic(raydium_sound_source[0],raydium_sound_buffer,
+             &raydium_sound_vf,raydium_sound_ogginfo);
+ } 
+
+}
+
+//THINGS TO DO
+void raydium_sound_callback(void)
+{
+raydium_sound_music_callback();
+}
+