/src/Mixer/Effects.xs

http://github.com/PerlGameDev/SDL · Unknown · 261 lines · 209 code · 52 blank · 0 comment · 0 complexity · 05d61bb59d08deb2a7b13731fa3d6ded MD5 · raw file

  1. #include "EXTERN.h"
  2. #include "perl.h"
  3. #include "XSUB.h"
  4. #include "ppport.h"
  5. #ifndef SDL_PERL_DEFINES_H
  6. #include "defines.h"
  7. #endif
  8. #include <SDL.h>
  9. #ifdef HAVE_SDL_MIXER
  10. #include <SDL_mixer.h>
  11. #define MAX_EFFECTS 31
  12. PerlInterpreter *context = NULL;
  13. int registered_effects = 0;
  14. void** effects = NULL;
  15. void** effects_done = NULL;
  16. char* effect_func_cb = NULL;
  17. char* effect_func_done_cb = NULL;
  18. void effect_func(int chan, void *stream, int len, void *udata)
  19. {
  20. ENTER_TLS_CONTEXT;
  21. Sint16 *buf = (Sint16 *)stream;
  22. len /= 2; /* 2 bytes ber sample */
  23. dSP; /* initialize stack pointer */
  24. ENTER; /* everything created after here */
  25. SAVETMPS; /* ...is a temporary variable. */
  26. PUSHMARK(SP); /* remember the stack pointer */
  27. XPUSHs(sv_2mortal(newSViv(chan)));
  28. XPUSHs(sv_2mortal(newSViv(len)));
  29. XPUSHs(sv_2mortal(newSVsv(udata))); /* push something onto the stack */
  30. int i;
  31. for(i = 0; i < len; i++)
  32. XPUSHs(sv_2mortal(newSViv(buf[i])));
  33. PUTBACK; /* make local stack pointer global */
  34. /*if(cb != (SV*)NULL) */
  35. {
  36. int count = call_pv(effect_func_cb, G_ARRAY); /* call the function */
  37. SPAGAIN; /* refresh stack pointer */
  38. if(count == len + 1)
  39. *(SV *)udata = *(newSVsv(POPs));
  40. if(count)
  41. {
  42. memset(buf, 0, len * 2); /* clear the buffer */
  43. for(i = len - 1; i >= 0; i--)
  44. {
  45. buf[i] = POPi;
  46. }
  47. }
  48. PUTBACK;
  49. }
  50. FREETMPS; /* free that return value */
  51. LEAVE; /* ...and the XPUSHed "mortal" args. */
  52. LEAVE_TLS_CONTEXT;
  53. }
  54. void effect_pm_func(void *udata, Uint8 *stream, int len)
  55. {
  56. effect_func(-2, (void *)stream, len, udata);
  57. }
  58. void effect_done(int chan, void *udata)
  59. {
  60. ENTER_TLS_CONTEXT;
  61. dSP; /* initialize stack pointer */
  62. PUSHMARK(SP); /* remember the stack pointer */
  63. /*if(fcb != (SV*)NULL) */
  64. /*warn ( "Called %s", effect_func_done_cb ); */
  65. call_pv(effect_func_done_cb, G_DISCARD|G_VOID); /* call the function */
  66. LEAVE_TLS_CONTEXT;
  67. }
  68. #endif
  69. MODULE = SDL::Mixer::Effects PACKAGE = SDL::Mixer::Effects PREFIX = mixeff_
  70. #ifdef HAVE_SDL_MIXER
  71. #ifdef USE_THREADS
  72. int
  73. mixeff_register(channel, func, done, arg)
  74. int channel
  75. char *func
  76. char *done
  77. SV *arg
  78. CODE:
  79. if(effects == NULL)
  80. {
  81. effects = safemalloc(MAX_EFFECTS* sizeof(void*));
  82. }
  83. if(effects_done == NULL)
  84. {
  85. effects_done = safemalloc(MAX_EFFECTS* sizeof(void*));
  86. }
  87. GET_TLS_CONTEXT;
  88. effect_func_cb = func;
  89. effect_func_done_cb = done;
  90. if(registered_effects <= MAX_EFFECTS )
  91. {
  92. effects[registered_effects] = (void*)&effect_func;
  93. effects_done[registered_effects] = (void*)&effect_done;
  94. if(0 != Mix_RegisterEffect(channel, effects[registered_effects], effects_done[registered_effects], arg))
  95. {
  96. /*warn( "Registered %d %p %p", registered_effects, effects[registered_effects], effects_done[registered_effects]); */
  97. RETVAL = registered_effects;
  98. registered_effects++;
  99. }
  100. else
  101. {
  102. warn( "Maximum effects allowed is 32 " );
  103. RETVAL = -1;
  104. }
  105. }
  106. else
  107. {
  108. RETVAL = -1;
  109. }
  110. OUTPUT:
  111. RETVAL
  112. #else
  113. int
  114. mixeff_register(channel, func, done, arg)
  115. int channel
  116. char *func
  117. char *done
  118. SV *arg
  119. CODE:
  120. warn("Perl need to be compiled with 'useithreads' for SDL::Mixer::Effects::register( channel, func, done, arg )");
  121. XSRETURN_UNDEF;
  122. OUTPUT:
  123. RETVAL
  124. #endif
  125. int
  126. mixeff_unregister( channel, func )
  127. int channel
  128. int func
  129. CODE:
  130. int check;
  131. if( func <= registered_effects)
  132. {
  133. check = Mix_UnregisterEffect(channel, effects[func]);
  134. if (check == 0 )
  135. {
  136. warn ("Error unregistering: %s", Mix_GetError() );
  137. }
  138. }
  139. else
  140. {
  141. warn (" Invalid effect id %d, currently %d effects registered", func, registered_effects);
  142. check = 0;
  143. }
  144. RETVAL = check;
  145. OUTPUT:
  146. RETVAL
  147. int
  148. mixeff_unregister_all( channel )
  149. int channel
  150. CODE:
  151. RETVAL = Mix_UnregisterAllEffects(channel);
  152. OUTPUT:
  153. RETVAL
  154. int
  155. mixeff_set_panning( channel, left, right )
  156. int channel
  157. int left
  158. int right
  159. CODE:
  160. RETVAL = Mix_SetPanning(channel, left, right);
  161. OUTPUT:
  162. RETVAL
  163. int
  164. mixeff_set_position( channel, angle, distance )
  165. int channel
  166. Sint16 angle
  167. Uint8 distance
  168. CODE:
  169. RETVAL = Mix_SetPosition(channel, angle, distance);
  170. OUTPUT:
  171. RETVAL
  172. int
  173. mixeff_set_distance( channel, distance )
  174. int channel
  175. Uint8 distance
  176. CODE:
  177. RETVAL = Mix_SetDistance(channel, distance);
  178. OUTPUT:
  179. RETVAL
  180. int
  181. mixeff_set_reverse_stereo( channel, flip )
  182. int channel
  183. Uint8 flip
  184. CODE:
  185. RETVAL = Mix_SetReverseStereo(channel, flip);
  186. OUTPUT:
  187. RETVAL
  188. #ifdef USE_THREADS
  189. void
  190. mixeff_set_post_mix(func = NULL, arg = NULL)
  191. SV *func
  192. SV *arg
  193. CODE:
  194. GET_TLS_CONTEXT;
  195. if(func != (SV *)NULL)
  196. {
  197. Mix_SetPostMix(&effect_pm_func, arg);
  198. }
  199. else
  200. Mix_SetPostMix(NULL, NULL);
  201. #else
  202. void
  203. mixeff_set_post_mix(func = NULL, arg = NULL)
  204. SV *func
  205. SV *arg
  206. CODE:
  207. warn("Perl need to be compiled with 'useithreads' for SDL::Mixer::Effects::set_post_mix( func, arg )");
  208. #endif
  209. #endif