#include "EXTERN.h" #include "perl.h" #include "XSUB.h" #include "ppport.h" #ifndef SDL_PERL_DEFINES_H #include "defines.h" #endif #include #ifdef HAVE_SDL_MIXER #include #define MAX_EFFECTS 31 PerlInterpreter *context = NULL; int registered_effects = 0; void** effects = NULL; void** effects_done = NULL; char* effect_func_cb = NULL; char* effect_func_done_cb = NULL; void effect_func(int chan, void *stream, int len, void *udata) { ENTER_TLS_CONTEXT; { dSP; /* initialize stack pointer */ int i; Sint16 *buf = (Sint16 *)stream; len /= 2; /* 2 bytes ber sample */ ENTER; /* everything created after here */ SAVETMPS; /* ...is a temporary variable. */ PUSHMARK(SP); /* remember the stack pointer */ XPUSHs(sv_2mortal(newSViv(chan))); XPUSHs(sv_2mortal(newSViv(len))); XPUSHs(sv_2mortal(newSVsv(udata))); /* push something onto the stack */ for(i = 0; i < len; i++) XPUSHs(sv_2mortal(newSViv(buf[i]))); PUTBACK; /* make local stack pointer global */ /*if(cb != (SV*)NULL) */ { int count = call_pv(effect_func_cb, G_ARRAY); /* call the function */ SPAGAIN; /* refresh stack pointer */ if(count == len + 1) *(SV *)udata = *(newSVsv(POPs)); if(count) { memset(buf, 0, len * 2); /* clear the buffer */ for(i = len - 1; i >= 0; i--) buf[i] = POPi; } PUTBACK; } FREETMPS; /* free that return value */ LEAVE; /* ...and the XPUSHed "mortal" args. */ } LEAVE_TLS_CONTEXT; } void effect_pm_func(void *udata, Uint8 *stream, int len) { effect_func(-2, (void *)stream, len, udata); } void effect_done(int chan, void *udata) { ENTER_TLS_CONTEXT; { dSP; /* initialize stack pointer */ PUSHMARK(SP); /* remember the stack pointer */ call_pv(effect_func_done_cb, G_DISCARD|G_VOID); /* call the function */ } LEAVE_TLS_CONTEXT; } #endif MODULE = SDL::Mixer::Effects PACKAGE = SDL::Mixer::Effects PREFIX = mixeff_ #ifdef HAVE_SDL_MIXER #ifdef USE_THREADS int mixeff_register(channel, func, done, arg) int channel char *func char *done SV *arg CODE: if(effects == NULL) effects = safemalloc(MAX_EFFECTS* sizeof(void*)); if(effects_done == NULL) effects_done = safemalloc(MAX_EFFECTS* sizeof(void*)); GET_TLS_CONTEXT; effect_func_cb = func; effect_func_done_cb = done; if(registered_effects <= MAX_EFFECTS ) { effects[registered_effects] = (void *)&effect_func; effects_done[registered_effects] = (void *)&effect_done; if(0 != Mix_RegisterEffect(channel, effects[registered_effects], effects_done[registered_effects], arg)) { /*warn( "Registered %d %p %p", registered_effects, effects[registered_effects], effects_done[registered_effects]); */ RETVAL = registered_effects; registered_effects++; } else { warn( "Maximum effects allowed is 32 " ); RETVAL = -1; } } else RETVAL = -1; OUTPUT: RETVAL #else int mixeff_register(channel, func, done, arg) int channel char *func char *done SV *arg CODE: warn("Perl need to be compiled with 'useithreads' for SDL::Mixer::Effects::register( channel, func, done, arg )"); XSRETURN_UNDEF; OUTPUT: RETVAL #endif int mixeff_unregister( channel, func ) int channel int func PREINIT: int check; CODE: if( func <= registered_effects) { check = Mix_UnregisterEffect(channel, effects[func]); if( check == 0 ) warn ("Error unregistering: %s", Mix_GetError() ); } else { warn (" Invalid effect id %d, currently %d effects registered", func, registered_effects); check = 0; } RETVAL = check; OUTPUT: RETVAL int mixeff_unregister_all( channel ) int channel CODE: RETVAL = Mix_UnregisterAllEffects(channel); OUTPUT: RETVAL int mixeff_set_panning( channel, left, right ) int channel int left int right CODE: RETVAL = Mix_SetPanning(channel, left, right); OUTPUT: RETVAL int mixeff_set_position( channel, angle, distance ) int channel Sint16 angle Uint8 distance CODE: RETVAL = Mix_SetPosition(channel, angle, distance); OUTPUT: RETVAL int mixeff_set_distance( channel, distance ) int channel Uint8 distance CODE: RETVAL = Mix_SetDistance(channel, distance); OUTPUT: RETVAL int mixeff_set_reverse_stereo( channel, flip ) int channel Uint8 flip CODE: RETVAL = Mix_SetReverseStereo(channel, flip); OUTPUT: RETVAL #ifdef USE_THREADS void mixeff_set_post_mix(func = NULL, arg = NULL) SV *func SV *arg CODE: GET_TLS_CONTEXT; if(func != (SV *)NULL) Mix_SetPostMix(&effect_pm_func, arg); else Mix_SetPostMix(NULL, NULL); #else void mixeff_set_post_mix(func = NULL, arg = NULL) SV *func SV *arg CODE: warn("Perl need to be compiled with 'useithreads' for SDL::Mixer::Effects::set_post_mix( func, arg )"); #endif #endif