Subversion Repositories Kolibri OS

Rev

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

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