Commits

pygame  committed b1fa454

mixer enhancements

  • Participants
  • Parent commits 1784d58

Comments (0)

Files changed (4)

 # BREAK = change breaks existing code
 # BUG	= fixed a bug that was (or could have been) crashing
 
+April 16, 2002
+        mixer keeps a reference to playing Sound objects
+        channel.set_volume() can take 2 volumes for panning
+        music.play() can take a starting position for the song
+
 April 14, 2002
 	bug when re-initializing pygame.display [BUG]
 

File docs/ref/Channel.html

 
 <a name=set_volume><font size=+2><b>set_volume
 </b></font><br><font size=+1><tt>
-Channel.set_volume(val) -> None
+Channel.set_volume(val, [stereoval]) -> None
 </tt></font><ul>
 Sets the volume for the channel. The channel's volume level is
 mixed with the volume for the active sound object. The value is
 between 0.0 and 1.0.
+<br>&nbsp;<br>
+If mixer is using stereo, you can set the panning for audio
+by supplying a volume for the left and right channels. If
+SDL_mixer cannot set the panning, it will average the two
+volumes. Panning requires SDL_mixer-1.2.1.
 </ul><br>&nbsp;<br>
 
 <a name=stop><font size=+2><b>stop
 static int request_stereo = MIX_DEFAULT_CHANNELS;
 static int request_chunksize = MIX_DEFAULT_CHUNKSIZE;
 
+static PyObject **channelsounds = NULL;
+static int numchannelsounds = 0;
+
 Mix_Music** current_music;
 
 
 static void autoquit(void)
 {
+        int i;
 	if(SDL_WasInit(SDL_INIT_AUDIO))
 	{
 		Mix_HaltMusic();
 
+                if(channelsounds)
+                {
+/*printf("FREE CHANNELSOUNDS, %p\n", channelsounds);*/
+                    for(i=0; i<numchannelsounds; ++i)
+                        Py_XDECREF(channelsounds[i]);
+                    free(channelsounds);
+                    channelsounds = NULL;
+                    numchannelsounds = 0;
+                }
+
 		if(current_music)
 		{
 			if(*current_music)
 	if(!SDL_WasInit(SDL_INIT_AUDIO))
 	{
 		PyGame_RegisterQuit(autoquit);
+                
+                if(!channelsounds) /*should always be null*/
+                {
+                    channelsounds = (PyObject**)malloc(sizeof(PyObject*)*8);
+                    numchannelsounds = 8;
+                    for(i=0; i < numchannelsounds; ++i)
+                        channelsounds[i] = NULL;
+/*printf("ALLOC CHANNELSOUNDS, %p\n", channelsounds);*/
+                }
 
 		if(SDL_InitSubSystem(SDL_INIT_AUDIO) == -1)
 			return PyInt_FromLong(0);
 			SDL_QuitSubSystem(SDL_INIT_AUDIO);
 			return PyInt_FromLong(0);
 		}
+#if MIX_MAJOR_VERSION>=1 && MIX_MINOR_VERSION>=2 && MIX_PATCHLEVEL>=4
+                /*Mix_ChannelFinished(some_callback);*/
+#endif
 	}
 	return PyInt_FromLong(1);
 }
 	if(channelnum == -1)
 		RETURN_NONE
 
+        Py_XDECREF(channelsounds[channelnum]);
+        channelsounds[channelnum] = self;
+        Py_INCREF(self);
+                    
 	//make sure volume on this arbitrary channel is set to full
 	Mix_Volume(channelnum, 128);
 
     /*DOC*/    "Set the play volume for this sound. This will effect any channels\n"
     /*DOC*/    "currently playing this sound, along with all subsequent calls to\n"
     /*DOC*/    "play. The value is 0.0 to 1.0.\n"
+
     /*DOC*/ ;
 
 static PyObject* snd_set_volume(PyObject* self, PyObject* args)
 
 static void sound_dealloc(PyObject* self)
 {
-	Mix_Chunk* chunk = PySound_AsChunk(self);
+    	Mix_Chunk* chunk = PySound_AsChunk(self);
+/*printf("DELETE SOUND\n");*/
 	Mix_FreeChunk(chunk);
 	PyObject_DEL(self);
 }
 	channelnum = Mix_PlayChannelTimed(channelnum, chunk, loops, playtime);
 	if(channelnum != -1)
 		Mix_GroupChannel(channelnum, (int)chunk);
-	
+
+        Py_XDECREF(channelsounds[channelnum]);
+        channelsounds[channelnum] = sound;
+        Py_INCREF(sound);
+
+        	
 	RETURN_NONE
 }
 
 
 
     /*DOC*/ static char doc_chan_set_volume[] =
-    /*DOC*/    "Channel.set_volume(val) -> None\n"
+    /*DOC*/    "Channel.set_volume(val, [stereoval]) -> None\n"
     /*DOC*/    "set volume for channel\n"
     /*DOC*/    "\n"
     /*DOC*/    "Sets the volume for the channel. The channel's volume level is\n"
     /*DOC*/    "mixed with the volume for the active sound object. The value is\n"
     /*DOC*/    "between 0.0 and 1.0.\n"
+    /*DOC*/    "\n"
+    /*DOC*/    "If mixer is using stereo, you can set the panning for audio\n"
+    /*DOC*/    "by supplying a volume for the left and right channels. If\n"
+    /*DOC*/    "SDL_mixer cannot set the panning, it will average the two\n"
+    /*DOC*/    "volumes. Panning requires SDL_mixer-1.2.1.\n"
     /*DOC*/ ;
 
 static PyObject* chan_set_volume(PyObject* self, PyObject* args)
 {
 	int channelnum = PyChannel_AsInt(self);
-	float volume;
+	float volume, stereovolume=-1.11f;
 
-	if(!PyArg_ParseTuple(args, "f", &volume))
+	if(!PyArg_ParseTuple(args, "f|f", &volume, &stereovolume))
 		return NULL;
 
 	MIXER_INIT_CHECK();
-
+#if MIX_MAJOR_VERSION>=1 && MIX_MINOR_VERSION>=2 && MIX_PATCHLEVEL>=1
+        if(stereovolume != -1.11f)
+            Mix_SetPanning(channelnum, (Uint8)(volume*255), (Uint8)(stereovolume*255));
+        else
+            Mix_SetPanning(channelnum, (Uint8)255, (Uint8)255);
+        volume = 1.0f;
+#else
+        if(stereovolume != -1.11f)
+            volume = (volume + stereovolume) * 0.5f;
+#endif
 	Mix_Volume(channelnum, (int)(volume*128));
 	RETURN_NONE
 }
 
 static PyObject* set_num_channels(PyObject* self, PyObject* args)
 {
-	int numchans;
+	int numchans, i;
 	if(!PyArg_ParseTuple(args, "i", &numchans))
 		return NULL;
 
 	MIXER_INIT_CHECK();
 
+        if(numchans > numchannelsounds)
+        {
+            channelsounds = (PyObject**)realloc(channelsounds, sizeof(PyObject*)*numchans);
+            for(i = numchannelsounds; i < numchans; ++i)
+                channelsounds[i] = NULL;
+            numchannelsounds = numchans;
+        }
+        
 	Mix_AllocateChannels(numchans);
 	RETURN_NONE
 }
 /*music module methods*/
 
     /*DOC*/ static char doc_play[] =
-    /*DOC*/    "pygame.mixer.music.play([loops]) -> None\n"
+    /*DOC*/    "pygame.mixer.music.play(loops=0, starttime=0) -> None\n"
     /*DOC*/    "play the current loaded music\n"
     /*DOC*/    "\n"
     /*DOC*/    "Starts playing the current loaded music. This will restart the\n"
     /*DOC*/    "sound if it is playing. Loops controls how many extra time the\n"
     /*DOC*/    "sound will play, a negative loop will play indefinitely, it\n"
     /*DOC*/    "defaults to 0.\n"
+    /*DOC*/    "\n"
+    /*DOC*/    "The starting time argument is given in milliseconds, and controls\n"
+    /*DOC*/    "the offset to start playing the music. Setting the starting time\n"
+    /*DOC*/    "is only available on SDL_mixer-1.2.4, otherwise it will raise a\n"
+    /*DOC*/    "NotImplementedError\n"
     /*DOC*/ ;
 
 static PyObject* music_play(PyObject* self, PyObject* args)
 {
-	int loops = 0;
+	int loops=0, starttime=0;
 	int val;
 
-	if(!PyArg_ParseTuple(args, "|i", &loops))
+	if(!PyArg_ParseTuple(args, "|ii", &loops, &starttime))
 		return NULL;
 
 	MIXER_INIT_CHECK();
 	music_pos = 0;
 	music_pos_time = SDL_GetTicks();
 
+#if MIX_MAJOR_VERSION>=1 && MIX_MINOR_VERSION>=2 && MIX_PATCHLEVEL>=4
+/*printf("Starting Music At Offset %d\n", starttime);*/
+        val = Mix_FadeInMusicPos(current_music, loops, 0, starttime/1000.0);
+#else
+        if(starttime)
+            return RAISE(PyExc_NotImplementedError, "music start time requires SDL_mixer-1.2.4");
 	val = Mix_PlayMusic(current_music, loops);
-	if(val == -1)
+#endif
+     	if(val == -1)
 		return RAISE(PyExc_SDLError, SDL_GetError());
 
 	RETURN_NONE