Subversion Repositories Kolibri OS

Rev

Rev 6347 | Blame | Compare with Previous | Last modification | View Log | RSS feed

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