misc/libopenalbridge/commands.c
author nemo
Sat, 27 Apr 2013 16:56:50 -0400
changeset 8939 b26aaf28c920
parent 3697 d5b30d6373fc
permissions -rw-r--r--
So. First pass. Add secondary explosions to RateExplosion and RateShotgun. Not yet added to shoves. This is of limited utility at present since the dX has to be small since we can't bother tracing all hog motion. But, should be more useful once shove is added, and tracking of explosives and mines.

/*
 *  commands.c
 *  Hedgewars
 *
 *  Created by Vittorio on 13/06/10.
 *  Copyright 2010 __MyCompanyName__. All rights reserved.
 *
 */

#include "commands.h"
#include "wrappers.h"

ALfloat old_gain;
extern ALuint *Sources;
extern ALuint cache_size, cache_index, sources_number;
extern ALboolean instances_number;
extern al_sound_t *the_sounds;

void openal_pausesound (uint32_t index) {
    if (openal_ready() == AL_TRUE && index < cache_size)
        alSourcePause(Sources[the_sounds[index].source_index]);
}


void openal_stopsound (uint32_t index) {
    if (openal_ready() == AL_TRUE && index < cache_size)
        alSourceStop(Sources[the_sounds[index].source_index]);
}


void openal_playsound (unsigned int index) {
    ALboolean needsSource = AL_TRUE;
    ALfloat SourcePosition[] = { 0.0, 0.0, 0.0 };
    ALfloat SourceVelocity[] = { 0.0, 0.0, 0.0 };
    ALint state;
    int i, j;

    if (openal_ready() == AL_TRUE && index < cache_size) {
        // check if sound has already a source
        if (the_sounds[index].source_index != -1) {
            // it has a source, check it's not playing
            alGetSourcei(Sources[the_sounds[index].source_index], AL_SOURCE_STATE, &state);
            if (state != AL_PLAYING && state != AL_PAUSED) {
                // it is not being played, so we can use it safely
	            needsSource = AL_FALSE;
            }
            // else it is being played, so we have to allocate a new source for this buffer
        }

        if (needsSource) {
#ifdef DEBUG
            fprintf(stderr,"(Bridge Debug) - looking for a source for sound %d\n", index);
#endif
            for (i = 0; i < sources_number; i++) {
                // let's iterate on Sources until we find a source that is not playing
                alGetSourcei(Sources[i], AL_SOURCE_STATE, &state);
                if (state != AL_PLAYING && state != AL_PAUSED) {
                    // let's iterate on the_sounds until we find the sound using that source
                    for (j = 0; j < cache_size; j++) {
                        if (the_sounds[j].source_index == i) {
                            the_sounds[j].source_index = -1;
                            break;
                        }
                    }
                    // here we know that no-one is using that source so we can use it
                    break;
                }
            }

            if (i == sources_number) {
                // this means all sources are busy
            }

            // set source properties that it will use when it's in playback
            alSourcei (Sources[i], AL_BUFFER,   the_sounds[index].buffer);
            alSourcef (Sources[i], AL_PITCH,    1.0f);
            alSourcef (Sources[i], AL_GAIN,     1.0f);
            alSourcefv(Sources[i], AL_POSITION, SourcePosition);
            alSourcefv(Sources[i], AL_VELOCITY, SourceVelocity);
            alSourcei (Sources[i], AL_LOOPING,  0);

            if (AL_NO_ERROR != alGetError()) {
                fprintf(stderr,"(Bridge ERROR) - failed to set Source properties\n");
                return;
            }
            the_sounds[index].source_index = i;
        }

        alSourcePlay(Sources[the_sounds[index].source_index]);

        if (AL_NO_ERROR != alGetError()) {
            fprintf(stderr,"(Bridge Warning) - failed to play sound %d\n", index);
            return;
        }
    }
}

void openal_toggleloop (uint32_t index) {
    ALint loop;

    if (openal_ready() == AL_TRUE && index < cache_size) {
        alGetSourcei (Sources[the_sounds[index].source_index], AL_LOOPING, &loop);
        alSourcei (Sources[the_sounds[index].source_index], AL_LOOPING, !((uint8_t) loop) & 0x00000001);
    }
}


void openal_setvolume (uint32_t index, float gain) {
    if (openal_ready() == AL_TRUE && index < cache_size)
        alSourcef (Sources[the_sounds[index].source_index], AL_GAIN, gain);
}


void openal_setglobalvolume (float gain) {
    if (openal_ready() == AL_TRUE)
        alListenerf (AL_GAIN, gain);
}

void openal_togglemute () {
    ALfloat gain;

    if (openal_ready() == AL_TRUE) {
        alGetListenerf (AL_GAIN, &gain);
        if (gain > 0) {
            old_gain = gain;
            gain = 0;
        } else
            gain = old_gain;

        alListenerf (AL_GAIN, gain);
    }
}

// Fade in or out by calling a helper thread
void openal_fade (uint32_t index, uint16_t quantity, al_fade_t direction) {
#ifndef _WIN32
    pthread_t thread;
#else
    HANDLE Thread;
#endif
    fade_t *fade;

    if (openal_ready() == AL_TRUE && index < cache_size) {
        fade = (fade_t*) Malloc(sizeof(fade_t));
        fade->index = index;
        fade->quantity = quantity;
        fade->type = direction;

#ifndef _WIN32
        pthread_create(&thread, NULL, (void *)helper_fade, (void *)fade);
        pthread_detach(thread);
#else
        Thread = (HANDLE) _beginthread((void *)helper_fade, 0, (void *)fade);
#endif
    }
}

void openal_setposition (uint32_t index, float x, float y, float z) {
    if (openal_ready() == AL_TRUE && index < cache_size)
        alSource3f(Sources[the_sounds[index].source_index], AL_POSITION, x, y, z);;
}

void helper_fade(void *tmp) {
    ALfloat gain;
    ALfloat target_gain;
    fade_t *fade;
    uint32_t index;
    uint16_t quantity;
    al_fade_t type;

    fade = tmp;
    index = fade->index;
    quantity = fade->quantity;
    type = fade->type;
    free (fade);

    if (type == AL_FADE_IN) {
#ifdef DEBUG
        fprintf(stderr,"(Bridge Info) - Fade-in in progress [index %d quantity %d]", index, quantity);
#endif

        // save the volume desired after the fade
        alGetSourcef(Sources[the_sounds[index].source_index], AL_GAIN, &target_gain);
        if (target_gain > 1.0f || target_gain <= 0.0f)
            target_gain = 1.0f;

        for (gain = 0.0f ; gain <= target_gain; gain += (float) quantity/10000) {
#ifdef TRACE
            fprintf(stderr,"(Bridge Debug) - Fade-in set gain to %f\n", gain);
#endif
            alSourcef(Sources[the_sounds[index].source_index], AL_GAIN, gain);
            usleep(10000);
        }
    } else {
        alGetSourcef(Sources[the_sounds[index].source_index], AL_GAIN, &target_gain);

        for (gain = target_gain; gain >= 0.00f; gain -= (float) quantity/10000) {
#ifdef TRACE
            fprintf(stderr,"(Bridge Debug) - Fade-out set gain to %f\n", gain);
#endif
            alSourcef(Sources[the_sounds[index].source_index], AL_GAIN, gain);
            usleep(10000);
        }

        if (AL_NO_ERROR != alGetError())
            fprintf(stderr,"(Bridge Warning) - Failed to set fade-out effect\n");

        // stop that sound and reset its volume
        alSourceStop (Sources[the_sounds[index].source_index]);
        alSourcef (Sources[the_sounds[index].source_index], AL_GAIN, target_gain);
    }

    if (AL_NO_ERROR != alGetError())
        fprintf(stderr,"(Bridge Warning) - Failed to set fade effect\n");

#ifndef _WIN32
    pthread_exit(NULL);
#else
    _endthread();
#endif
}