Subversion Repositories Kolibri OS

Rev

Rev 8494 | Rev 9288 | Go to most recent revision | Blame | Compare with Previous | Last modification | View Log | RSS feed

  1. #include "SDL_audio.h"
  2. #include <SDL_kos.h>
  3. #include <stdlib.h>
  4. #include <string.h>
  5. #include <sound.h>
  6. #include <stdio.h>
  7.  
  8. extern void SDL_printf(const char * fmt,...);
  9.  
  10. static void GetNotify(__u32* event)
  11. {
  12.         __asm__("int $0x40" :: "a"(68),"b"(14),"c"(event));
  13. }
  14. static int CreateThread(void* fn, char* p_stack)
  15. {
  16.         int res;
  17.         __asm__("int $0x40" : "=a"(res) : "a"(51),"b"(1),"c"(fn),"d"(p_stack));
  18.         return res;
  19. }
  20. static char pinfo[1024];
  21. static int GetProcessInfo(int slot)
  22. {
  23.         int res;
  24.         __asm__("int $0x40" : "=a"(res) : "a"(9),"b"(pinfo),"c"(slot));
  25.         return res;
  26. }
  27. static void ActivateWnd(int slot)
  28. {
  29.         __asm__("int $0x40" :: "a"(18),"b"(3),"c"(slot));
  30. }
  31. static void Yield(void)
  32. {
  33.         __asm__("int $0x40" :: "a"(68),"b"(1));
  34. }
  35.  
  36. static int bInitialized=0;
  37. static SNDBUF hBuff=0;
  38. static char* data=NULL;
  39. static int audio_tid=0;
  40. static int main_slot;
  41. static __u32 main_tid;
  42. static char audio_thread_stack[40960];
  43. static __u32 used_format=0;
  44. static volatile int mix_size=0;
  45.  
  46. static void (*callback)(void* userdata, Uint8* stream, int len);
  47. static void* userdata;
  48.  
  49. int SDL_AudioInit(const char* driver_name)
  50. {
  51.         if (bInitialized)
  52.         {
  53.                 SDL_SetError("audio already initialized");
  54.                 return -1;
  55.         }
  56.         int ver;
  57.         if (InitSound(&ver))
  58.         {
  59.                 SDL_printf("Warning: cannot load drivers, sound output will be disabled\n");
  60.                 return 0;
  61.         }
  62.         bInitialized = 1;
  63.         return 0;
  64. }
  65.  
  66. void SDL_AudioQuit(void)
  67. {
  68. }
  69.  
  70. char* SDL_AudioDriverName(char* namebuf, int maxlen)
  71. {
  72.         if (!bInitialized)
  73.                 return NULL;
  74.         strncpy(namebuf,"KolibriAudio",maxlen);
  75.         return namebuf;
  76. }
  77.  
  78. #define AUDIO_SUSPEND 1
  79. #define AUDIO_RESUME 2
  80. #define AUDIO_DIE 3
  81. static volatile int audio_command=0,audio_response=0,bLocked=0,bInCallback=0;
  82. static void audio_thread(void)
  83. {
  84.         SDL_printf("audio_thread created\n");
  85.         int bPaused;
  86.         __u32 event[6];
  87.         // initialize
  88.         if (CreateBuffer(used_format|PCM_RING, 0, &hBuff))
  89.         {
  90.                 audio_response=1;
  91.                 exit(0);
  92.         }
  93.         GetBufferSize(hBuff, &mix_size);
  94.         SDL_printf("buffer created, size is %d\n",mix_size);
  95.         mix_size >>= 1;
  96.         data = malloc(mix_size);
  97.         audio_response=1;
  98.         if (!data) exit(0);
  99.         // wait for resume
  100.         while (audio_command!=AUDIO_RESUME)
  101.                 Yield();
  102.         // initialize
  103. /*        bInCallback=1;
  104.         callback(userdata,data,mix_size);
  105.         SetBuffer(hBuff,data,0,mix_size);
  106.         callback(userdata,data,mix_size);
  107.         SetBuffer(hBuff,data,mix_size,mix_size);
  108.         bInCallback=0;*/
  109.         audio_command=0;
  110.         bPaused=0;
  111.         audio_response=1;
  112.         PlayBuffer(hBuff,0);
  113.         // main loop
  114.         for (;;)
  115.         {
  116.                 if (audio_command==AUDIO_RESUME)
  117.                 {
  118.                         PlayBuffer(hBuff,0);
  119.                         audio_command = 0;
  120.                         bPaused = 0;
  121.                         audio_response = 1;
  122.                 }
  123.                 else if (audio_command==AUDIO_SUSPEND)
  124.                 {
  125.                         StopBuffer(hBuff);
  126.                         audio_command = 0;
  127.                         bPaused = 1;
  128.                         audio_response = 1;
  129.                 }
  130.                 else if (audio_command==AUDIO_DIE)
  131.                 {
  132.                         audio_response = 1;
  133.                         StopBuffer(hBuff);
  134.                         DestroyBuffer(hBuff);
  135.                         exit(0);
  136.                 }
  137.                 else
  138.                 {
  139.                         GetProcessInfo(main_slot);
  140.                         if (pinfo[0x32]==9 || *(__u32*)(pinfo+0x1E)!=main_tid)
  141.                         {
  142.                                 audio_command = AUDIO_DIE;
  143.                                 continue;
  144.                         }
  145.                 }
  146.                 if (bPaused)
  147.                         __kos__delay100(5);
  148.                 else
  149.                 {
  150.                         GetNotify(event);
  151.                         if (event[0] != 0xFF000001)
  152.                                 continue;
  153.                         while (bLocked)
  154.                                 Yield();
  155.                         bInCallback=1;
  156.                         callback(userdata,data,mix_size);
  157.                         bInCallback=0;
  158.                         SetBuffer(hBuff,data,event[3],mix_size);
  159.                 }
  160.         }
  161. }
  162.  
  163. int SDL_OpenAudio(SDL_AudioSpec* desired, SDL_AudioSpec* obtained)
  164. {
  165.         if (!bInitialized)
  166.         {
  167.                 SDL_SetError("Audio device was not initialized");
  168.                 return -1;
  169.         }
  170.         if (!obtained)
  171.         {
  172.                 SDL_SetError("Audio format: software emulation is not supported");
  173.                 return -1;
  174.         }
  175.         if (used_format)
  176.         {
  177.                 SDL_SetError("Audio device was already opened");
  178.                 return -1;
  179.         }
  180.         memcpy(obtained,desired,sizeof(SDL_AudioSpec));
  181.         switch (desired->freq)
  182.         {
  183.  
  184. #define HANDLE_FREQ(freq,symb)                          \
  185.         case freq:                                      \
  186.                 switch (desired->channels)              \
  187.                 {                                       \
  188.                 case 1:                                 \
  189.                         switch (desired->format)        \
  190.                         {                               \
  191.                         case AUDIO_U8:                  \
  192.                         case AUDIO_S8:                  \
  193.                                 used_format = PCM_1_8_##symb;   \
  194.                                 break;                  \
  195.                         case AUDIO_U16SYS:              \
  196.                         case AUDIO_S16SYS:              \
  197.                                 used_format = PCM_1_16_##symb;  \
  198.                                 break;                  \
  199.                         }                               \
  200.                         break;                          \
  201.                 case 2:                                 \
  202.                         switch (desired->format)        \
  203.                         {                               \
  204.                         case AUDIO_U8:                  \
  205.                         case AUDIO_S8:                  \
  206.                                 used_format = PCM_2_8_##symb;   \
  207.                                 break;                  \
  208.                         case AUDIO_U16SYS:              \
  209.                         case AUDIO_S16SYS:              \
  210.                                 used_format = PCM_2_16_##symb;  \
  211.                                 break;                  \
  212.                         }                               \
  213.                         break;                          \
  214.                 }                                       \
  215.                 break;
  216.  
  217.         HANDLE_FREQ(48000,48);
  218.         HANDLE_FREQ(44100,44);
  219.         HANDLE_FREQ(32000,32);
  220.         HANDLE_FREQ(24000,24);
  221.         HANDLE_FREQ(22050,22);
  222.         HANDLE_FREQ(16000,16);
  223.         HANDLE_FREQ(12000,12);
  224.         HANDLE_FREQ(11025,11);
  225.         HANDLE_FREQ(8000,8);
  226.         }
  227.         if (!used_format)
  228.         {
  229.                 SDL_SetError("Unknown audio format");
  230.                 return -1;
  231.         }
  232.         callback=desired->callback;
  233.         userdata=desired->userdata;
  234.         GetProcessInfo(-1);
  235.         main_tid = *(__u32*)(pinfo+0x1E);
  236.         for (main_slot=0;;main_slot++)
  237.         {
  238.                 GetProcessInfo(main_slot);
  239.                 if (pinfo[0x32]!=9 && *(__u32*)(pinfo+0x1E)==main_tid)
  240.                         break;
  241.         }
  242.         audio_tid=CreateThread(audio_thread,audio_thread_stack+40960);
  243.         if (audio_tid<0)
  244.         {
  245.                 SDL_SetError("Cannot create audio thread");
  246.                 return -1;
  247.         }
  248.         ActivateWnd(main_slot);
  249.         while (!audio_response)
  250.                 Yield();
  251.         if (!hBuff)
  252.         {
  253.                 SDL_SetError("Cannot create audio buffer");
  254.                 return -1;
  255.         }
  256.         if (!data)
  257.         {
  258.                 SDL_SetError("Cannot allocate audio buffer");
  259.                 return -1;
  260.         }
  261.         obtained->silence = (desired->format == AUDIO_U8 ? 0x80 : 0);
  262.         obtained->size = mix_size;
  263.         obtained->samples = obtained->size / obtained->channels;
  264.         if (desired->format == AUDIO_U16SYS || desired->format == AUDIO_S16SYS)
  265.                 obtained->samples /= 2;
  266.         SDL_printf("obtained size is %d, samples %d\n",obtained->size,
  267.         obtained->samples);
  268.         return 0;
  269. }
  270. void SDL_CloseAudio(void)
  271. {
  272.         if (!audio_tid) return;
  273.         audio_response = 0;
  274.         audio_command = AUDIO_DIE;
  275.         while (!audio_response)
  276.                 Yield();
  277.         free(data);
  278.         used_format = 0;
  279. }
  280.  
  281. void SDL_PauseAudio(int pause_on)
  282. {
  283.         if (!audio_tid) return;
  284.         audio_response = 0;
  285.         audio_command = pause_on?AUDIO_SUSPEND:AUDIO_RESUME;
  286.         while (!audio_response)
  287.                 Yield();
  288. }
  289. void SDL_LockAudio(void)
  290. {
  291.         if (!audio_tid) return;
  292.         bLocked = 1;
  293.         while (bInCallback)
  294.                 Yield();
  295. }
  296. void SDL_UnlockAudio(void)
  297. {
  298.         bLocked = 0;
  299. }
  300.