# HG changeset patch # User Eric Wing # Date 1289283587 28800 # Node ID 9365e714fc4bf8f02169ab2730574c7b9b1ec615 # Parent a8d96c934e77a165939b375e331e221ef8ab7652 Added SeekChannel, SeekSource. Fixed a return value bug in RewindSource. diff -r a8d96c934e77 -r 9365e714fc4b ALmixer.c --- a/ALmixer.c Sun Nov 07 05:20:21 2010 -0800 +++ b/ALmixer.c Mon Nov 08 22:19:47 2010 -0800 @@ -2330,7 +2330,7 @@ ALint channel; if(0 == source) { - return Internal_RewindChannel(-1) + 1; + return Internal_RewindChannel(-1); } channel = Internal_GetChannel(source); @@ -2339,7 +2339,7 @@ ALmixer_SetError("Cannot rewind source: %s", ALmixer_GetError()); return 0; } - return Internal_RewindChannel(channel) + 1; + return Internal_RewindChannel(channel); } @@ -3220,6 +3220,219 @@ } +static ALint Internal_SeekChannel(ALint channel, ALuint msec) +{ + ALint retval = 0; + ALenum error; + ALint state; + ALint running_count = 0; + + if(0 == msec) + { + return Internal_RewindChannel(channel); + } + + if(channel >= Number_of_Channels_global) + { + ALmixer_SetError("Cannot seek channel %d because it exceeds maximum number of channels (%d)\n", channel, Number_of_Channels_global); + return -1; + } + + if((error = alGetError()) != AL_NO_ERROR) + { + fprintf(stderr, "24Testing error: %s\n", + alGetString(error)); + } + /* Clear error */ + alGetError(); + + /* If the user specified a specific channel */ + if(channel >= 0) + { + /* only need to process channel if in use */ + if(ALmixer_Channel_List[channel].channel_in_use) + { + + /* What should I do? Do I just rewind the channel + * or also rewind the data? Since the data is + * shared, let's make it the user's responsibility + * to rewind the data. + */ + if(ALmixer_Channel_List[channel].almixer_data->decoded_all) + { + /* convert milliseconds to seconds */ + ALfloat sec_offset = msec / 1000.0f; + + alGetSourcei( + ALmixer_Channel_List[channel].alsource, + AL_SOURCE_STATE, &state + ); + if((error = alGetError()) != AL_NO_ERROR) + { + fprintf(stderr, "25Testing error: %s\n", + alGetString(error)); + } + /* OpenAL seek */ + alSourcef(ALmixer_Channel_List[channel].alsource, AL_SEC_OFFSET, sec_offset); + if((error = alGetError()) != AL_NO_ERROR) + { + ALmixer_SetError("%s", + alGetString(error) ); + retval = -1; + } + /* Need to resume playback if it was originally playing */ + if(AL_PLAYING == state) + { + alSourcePlay(ALmixer_Channel_List[channel].alsource); + if((error = alGetError()) != AL_NO_ERROR) + { + ALmixer_SetError("%s", + alGetString(error) ); + retval = -1; + } + } + else if(AL_PAUSED == state) + { + /* HACK: The problem is that when paused, after + * the Rewind, I can't get it off the INITIAL + * state without restarting + */ + alSourcePlay(ALmixer_Channel_List[channel].alsource); + if((error = alGetError()) != AL_NO_ERROR) + { + fprintf(stderr, "25Testing error: %s\n", + alGetString(error)); + } + alSourcePause(ALmixer_Channel_List[channel].alsource); + if((error = alGetError()) != AL_NO_ERROR) + { + ALmixer_SetError("%s", + alGetString(error) ); + retval = -1; + } + } + } + else + { + /* Streamed data is different. Rewinding the channel + * does no good. Rewinding the data will have an + * effect, but it will be lagged based on how + * much data is queued. Recommend users call Halt + * before rewind if they want immediate results. + */ + retval = Internal_SeekData(ALmixer_Channel_List[channel].almixer_data, msec); + } + } + } + /* The user wants to rewind all channels */ + else + { + ALint i; + ALfloat sec_offset = msec / 1000.0f; + + for(i=0; idecoded_all) + { + alGetSourcei( + ALmixer_Channel_List[i].alsource, + AL_SOURCE_STATE, &state + ); + if((error = alGetError()) != AL_NO_ERROR) + { + fprintf(stderr, "26Testing error: %s\n", + alGetString(error)); + } + + alSourcef(ALmixer_Channel_List[channel].alsource, AL_SEC_OFFSET, sec_offset); + if((error = alGetError()) != AL_NO_ERROR) + { + ALmixer_SetError("%s", + alGetString(error) ); + retval = -1; + } + /* Need to resume playback if it was originally playing */ + if(AL_PLAYING == state) + { + alSourcePlay(ALmixer_Channel_List[i].alsource); + if((error = alGetError()) != AL_NO_ERROR) + { + ALmixer_SetError("%s", + alGetString(error) ); + retval = -1; + } + } + else if(AL_PAUSED == state) + { + /* HACK: The problem is that when paused, after + * the Rewind, I can't get it off the INITIAL + * state without restarting + */ + alSourcePlay(ALmixer_Channel_List[i].alsource); + if((error = alGetError()) != AL_NO_ERROR) + { + fprintf(stderr, "27Testing error: %s\n", + alGetString(error)); + } + alSourcePause(ALmixer_Channel_List[i].alsource); + if((error = alGetError()) != AL_NO_ERROR) + { + ALmixer_SetError("%s", + alGetString(error) ); + retval = -1; + } + } + } + else + { + /* Streamed data is different. Rewinding the channel + * does no good. Rewinding the data will have an + * effect, but it will be lagged based on how + * much data is queued. Recommend users call Halt + * before rewind if they want immediate results. + */ + running_count += Internal_SeekData(ALmixer_Channel_List[i].almixer_data, msec); + } + } + } + } + if(-1 == retval) + { + return -1; + } + else + { + return running_count; + } + +} + +static ALint Internal_SeekSource(ALuint source, ALuint msec) +{ + ALint channel; + if(0 == source) + { + return Internal_SeekChannel(-1, msec); + } + + channel = Internal_GetChannel(source); + if(-1 == channel) + { + ALmixer_SetError("Cannot seek source: %s", ALmixer_GetError()); + return 0; + } + return Internal_SeekChannel(channel, msec); +} + + static ALint Internal_FadeInChannelTimed(ALint channel, ALmixer_Data* data, ALint loops, ALuint fade_ticks, ALint expire_ticks) { @@ -4701,8 +4914,9 @@ t = (ALfloat) delta_time * ALmixer_Channel_List[i].fade_inv_time; current_volume = (1.0f-t) * ALmixer_Channel_List[i].fade_start_volume + t * ALmixer_Channel_List[i].fade_end_volume; + /* fprintf(stderr, "start_vol=%f, end_vol:%f, current_volume: %f\n", ALmixer_Channel_List[i].fade_start_volume, ALmixer_Channel_List[i].fade_end_volume, current_volume); - + */ /* Set the volume */ alSourcef(ALmixer_Channel_List[i].alsource, AL_GAIN, current_volume); @@ -8502,6 +8716,32 @@ return retval; } +ALint ALmixer_SeekChannel(ALint channel, ALuint msec) +{ + ALint retval; +#ifdef ENABLE_ALMIXER_THREADS + SDL_LockMutex(s_simpleLock); +#endif + retval = Internal_SeekChannel(channel, msec); +#ifdef ENABLE_ALMIXER_THREADS + SDL_UnlockMutex(s_simpleLock); +#endif + return retval; +} + +ALint ALmixer_SeekSource(ALuint source, ALuint msec) +{ + ALint retval; +#ifdef ENABLE_ALMIXER_THREADS + SDL_LockMutex(s_simpleLock); +#endif + retval = Internal_SeekSource(source, msec); +#ifdef ENABLE_ALMIXER_THREADS + SDL_UnlockMutex(s_simpleLock); +#endif + return retval; +} + ALint ALmixer_FadeInChannelTimed(ALint channel, ALmixer_Data* data, ALint loops, ALuint fade_ticks, ALint expire_ticks) { ALint retval; diff -r a8d96c934e77 -r 9365e714fc4b ALmixer.h --- a/ALmixer.h Sun Nov 07 05:20:21 2010 -0800 +++ b/ALmixer.h Mon Nov 08 22:19:47 2010 -0800 @@ -1077,6 +1077,27 @@ extern ALMIXER_DECLSPEC ALboolean ALMIXER_CALL ALmixer_SeekData(ALmixer_Data* almixer_data, ALuint msec_pos); /** + * Seeks the sound to the beginning that is playing on a specific channel. + * If decoded all, seek will instantly seek it. Data is not + * affected, so it will start at the "Seek"'ed positiond. + * Streamed data will seek the actual data, but the effect + * may not be noticed until the currently buffered data is played. + * @param which_channel The channel to seek or -1 to seek all channels. + * @return The actual number of channels rewound on success or -1 on error. + */ +extern ALMIXER_DECLSPEC ALint ALMIXER_CALL ALmixer_SeekChannel(ALint which_channel, ALuint msec_pos); +/** + * Seeks the sound to the beginning that is playing on a specific source. + * If decoded all, seek will instantly seek it. Data is not + * affected, so it will start at the "Seek"'ed positiond. + * Streamed data will seek the actual data, but the effect + * may not be noticed until the currently buffered data is played. + * @param al_source The source to seek or 0 to seek all sources. + * @return The actual number of sources rewound on success or -1 on error. + */ +extern ALMIXER_DECLSPEC ALint ALMIXER_CALL ALmixer_SeekSource(ALuint al_source, ALuint msec_pos); + +/** * Pauses playback on a channel. * Pauses playback on a channel. Should have no effect on channels that aren't playing. * @param which_channel The channel to pause or -1 to pause all channels. @@ -1440,8 +1461,7 @@ extern ALMIXER_DECLSPEC ALuint ALMIXER_CALL ALmixer_CountUnreservedFreeChannels(void); /** - * Returns the number of channels that are currently in use (playing/paused), - * excluding the channels that have been reserved. + * Returns the number of channels that are currently in use (playing/paused). * @return The number of channels that are currently in use. * @see ALmixer_ReserveChannels */