Subversion Repositories Kolibri OS

Rev

Go to most recent revision | Blame | Last modification | View Log | Download | RSS feed

  1. //
  2. //   This file is part of the AC97 mp3 player.
  3. //   (C) copyright Serge 2006
  4. //   email: infinity_sound@mail.ru
  5. //
  6. //   This program is free software; you can redistribute it and/or modify
  7. //   it under the terms of the GNU General Public License as published by
  8. //   the Free Software Foundation; either version 2 of the License, or
  9. //   (at your option) any later version.
  10. //
  11. //   This program is distributed in the hope that it will be useful,
  12. //   but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. //   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  14. //   GNU General Public License for more details.
  15.  
  16. #include "kolibri.h"
  17. #include "stdio.h"
  18. #include "string.h"
  19. #include "ac97wav.h"
  20. #include "mp3dec/mp3dec.h"
  21.  
  22. void thread_proc();
  23. void touch(char *buf, int size);
  24.  
  25. extern char *__argv;
  26.  
  27. //extern char __path;
  28.  
  29. /*****      for debug output only
  30. char formats[37][12] =
  31. { "PCM_ALL",
  32.   "PCM_2_16_48","PCM_1_16_48","PCM_2_16_44","PCM_1_16_44",
  33.   "PCM_2_16_32","PCM_1_16_32","PCM_2_16_24","PCM_1_16_24",
  34.   "PCM_2_16_22","PCM_1_16_22","PCM_2_16_16","PCM_1_16_16",
  35.   "PCM_2_16_12","PCM_1_16_12","PCM_2_16_11","PCM_1_16_11",
  36.   "PCM_2_16_8","PCM_1_16_8","PCM_2_8_48","PCM_1_8_48",
  37.   "PCM_2_8_44","PCM_1_8_44","PCM_2_8_32","PCM_1_8_32",
  38.   "PCM_2_8_24","PCM_1_8_24","PCM_2_8_22","PCM_1_8_22",
  39.   "PCM_2_8_16","PCM_1_8_16","PCM_2_8_12","PCM_1_8_12",
  40.   "PCM_2_8_11","PCM_1_8_11","PCM_2_8_8","PCM_1_8_8"
  41. };
  42. *******/
  43.  
  44. DWORD hDrv;
  45. DWORD hSound;
  46. DWORD hBuff;
  47. DWORD event[2];
  48.  
  49. CTRL_INFO info;
  50.  
  51. FILEINFO   fileinfo;
  52.  
  53. int m_vol;
  54. DWORD status;
  55. DWORD offset;
  56. DWORD first_sync;
  57.  
  58. char *testbuff;
  59. char *outbuf;
  60. char *inpbuf;
  61. int inpsize;
  62. int outsize;
  63.  
  64. char srv_name[] = "INFINITY";
  65. char srv_intel[] = "SOUND";
  66. char header[] = "AC97 MP3 player";
  67. char buttons_text[]=" Play    Stop     <<      >>     Vol-    Vol+";
  68.  
  69. MPEG_DECODE_INFO mpginfo;
  70. MPEG_DECODE_PARAM param;
  71.  
  72. void (*snd_play)();
  73.  
  74. void draw_window()
  75. {
  76.    BeginDraw();
  77.  
  78.    DrawWindow(100,100,299,72,0x404040,3,0,0,0);
  79.  
  80.    make_button(7,24,45,13, 0x10|BT_NORMAL,0x808080);
  81.    make_button(56,24,45,13, 0x11|BT_NORMAL,0x808080);
  82.    make_button(104,24,45,13, 0x12|BT_NORMAL,0x808080);
  83.    make_button(152,24,45,13, 0x13|BT_NORMAL,0x808080);
  84.    make_button(200,24,45,13, 0x14|BT_NORMAL,0x808080);
  85.    make_button(248,24,45,13, 0x15|BT_NORMAL,0x808080);
  86.  
  87.    make_button(7,41,286,11, 0x30|BT_HIDE|BT_NOFRAME,0x404040);
  88.    draw_bar(7,41,286,11,0x404040);
  89.  
  90.    draw_bar(7,55,286,11,0x404040);
  91.    write_text(12,58,0x004000|FONT0, __argv, strlen(__argv));
  92.    write_text(11,57,0x00FF20|FONT0, __argv, strlen(__argv));
  93.  
  94.    write_text(8,8,0xFFFFFF|FONT0, header, strlen(header));
  95.    write_text(12,28,0x404040|FONT0,buttons_text,strlen(buttons_text));
  96.    write_text(11,27,0xA0FFA0|FONT0,buttons_text,strlen(buttons_text));
  97.  
  98.    EndDraw();
  99. };
  100.  
  101. void draw_progress_bar()
  102. {  DWORD x;
  103.    x = 286.0f * (float)offset/(float)fileinfo.size;
  104.    if(x==0) return;
  105.    draw_bar(7,41,x,11,0xA0A0A0);
  106.    draw_bar(x+7,41,286-x,11,0x404040);
  107. };
  108.  
  109. void debug_out_str(char* str)
  110. {
  111.   while (*str != 0)
  112.   {
  113.     debug_out(*str);
  114.     str++;
  115.   }
  116. }
  117.  
  118. int main()      //int argc, char *argv[])
  119. { DWORD fmt;
  120.    char *thread_stack;
  121.    DWORD r_bytes;
  122.    int retval;
  123.  
  124.    InitHeap(1024*1024);
  125.    if(get_fileinfo(__argv, &fileinfo)==FILE_NOT_FOUND)
  126.       return 0;
  127.  
  128.    if((hDrv=GetService(srv_intel))==0)
  129.      return 0;
  130.  
  131.    if ((hSound=GetService(srv_name))==0)
  132.      return 0;
  133.  
  134.    GetDevInfo(hDrv, &info);
  135.  
  136.    m_vol = GetMasterVol(hDrv,&m_vol);
  137.    if (m_vol > 85)
  138.    { m_vol = 85;
  139.       SetMasterVol(hDrv,m_vol);
  140.    };
  141.  
  142.    _asm {fninit};
  143.    mp3DecodeInit();
  144.      
  145.    testbuff = UserAlloc(4096);
  146.    get_fileinfo(__argv, &fileinfo);
  147.    offset = 0;
  148.    retval=read_file (__argv,testbuff,0,2048,&r_bytes);
  149.    if (retval) return 0;
  150.    
  151.    fmt = test_wav((WAVEHEADER*)testbuff);
  152.    if (fmt != 0)
  153.    {
  154.      snd_play = &play_wave;
  155.      outbuf = UserAlloc(32*1024);
  156.      touch(outbuf, 32768);
  157.      offset = 44;
  158.    }  
  159.    else  
  160.    {  fmt = test_mp3(testbuff);
  161.        if(fmt ==0) return 0;
  162.        snd_play = &play_mp3;
  163.        
  164.        inpsize = mpginfo.maxInputSize*30;
  165.        inpbuf =  UserAlloc(inpsize);
  166.        touch(inpbuf, inpsize);
  167.        outsize = mpginfo.outputSize*30+0x10000;
  168.        outbuf = UserAlloc(outsize);
  169.        touch(outbuf, outsize);
  170.        first_sync = offset;
  171.    };
  172.  
  173.    status = ST_PLAY;
  174.    
  175.    hBuff = CreateBuffer(hSound,fmt);
  176.    if (hBuff == 0) return 0;
  177.    thread_stack = UserAlloc(4096);
  178.    thread_stack+=4092;
  179.  
  180.    CreateThread(thread_proc, thread_stack);
  181.  
  182.    while(1)
  183.    {  delay(10);
  184.       switch(status)
  185.       {  case ST_PLAY:
  186.            snd_play();
  187.            continue;
  188.  
  189.          case ST_STOP:
  190.            StopBuffer(hSound, hBuff);
  191.            status = ST_DONE;
  192.            continue;
  193.  
  194.          case ST_EXIT:
  195.            StopBuffer(hSound, hBuff);
  196.            DestroyBuffer(hSound, hBuff);
  197.            return 0;
  198.       };
  199.    };
  200.    return 0;
  201. };
  202.  
  203. void touch(char *buf, int size)
  204. { int i;
  205.     for ( i = 0;i < size; i+=4096)
  206.       buf[i] = 0;
  207. };
  208.  
  209. DWORD test_mp3(char *buf)
  210. {  int retval;
  211.     int sync;
  212.     WAVEHEADER whdr;
  213.     DWORD r_bytes=2048;
  214.      
  215.     for (;;)
  216.     {
  217.           if (!mp3FindSync(buf, 2048, &sync))
  218.             offset+= 2048;
  219.         else break;
  220.        
  221.         if (offset >= fileinfo.size || offset >= 102400)
  222.             return 0;
  223.  
  224.         retval = read_file (__argv,buf,offset,2048,&r_bytes);
  225.           if(retval != 0)  return 0;
  226.           };
  227.     offset+=sync;
  228.     retval = read_file (__argv,buf,offset,2048,&r_bytes);
  229.           if(retval != 0) return 0;
  230.          
  231.         mp3GetDecodeInfo(buf, r_bytes, &mpginfo, 1);
  232.     whdr.riff_id = 0x46464952;
  233.     whdr.riff_format = 0x45564157;
  234.     whdr.wFormatTag = 0x01;
  235.     whdr.nSamplesPerSec = mpginfo.frequency;
  236.     whdr.nChannels = mpginfo.channels;
  237.     whdr.wBitsPerSample = mpginfo.bitsPerSample;
  238.    
  239.     return test_wav(&whdr);
  240. };
  241. void wave_out(char* buff)
  242. { DWORD ev[2];
  243.  
  244.    GetNotify(&ev[0]);
  245.    SetBuffer(hSound,hBuff,buff,ev[1],0x8000);
  246. }
  247.  
  248. void play_mp3()
  249. {  int retval;
  250.     DWORD r_bytes;
  251.     char *inpPtr;
  252.     char *outPtr;
  253.     int inpBytes;
  254.     int totalout;
  255.    
  256.     offset = first_sync;
  257.    
  258.     retval = read_file (__argv,inpbuf,offset,inpsize,&r_bytes);
  259.           if(retval != 0)
  260.           {  status =  ST_STOP;
  261.               return ;
  262.     };
  263.     offset+=inpsize;
  264.  
  265.     mp3DecodeStart(inpbuf, inpsize);
  266.  
  267.     inpPtr = inpbuf+mpginfo.skipSize;
  268.     inpBytes = inpsize-mpginfo.skipSize;
  269.     outPtr = outbuf;
  270.     totalout=0;
  271.    
  272.     memset(outbuf,0,0x10000);
  273.     SetBuffer(hSound,hBuff,outbuf,0,0x10000);
  274.     PlayBuffer(hSound, hBuff);
  275.  
  276.     _asm { fninit }
  277.    
  278.     while(1)
  279.     { if(status!=ST_PLAY)
  280.              break;
  281.  
  282.       for(;;)
  283.       { param.inputBuf  = inpPtr;
  284.                param.inputSize  = inpBytes;
  285.            param.outputBuf      = outPtr;
  286.  
  287.            if(!mp3DecodeFrame(&param))
  288.             if( mp3GetLastError()== MP3_ERROR_OUT_OF_BUFFER)
  289.               break;            
  290.  
  291.          inpPtr += param.inputSize;
  292.                      inpBytes -= param.inputSize;
  293.          outPtr+=param.outputSize;
  294.          totalout+=param.outputSize;
  295.       };
  296.                   memmove(inpbuf, inpPtr, inpBytes);
  297.           retval = read_file(__argv, &inpbuf[inpBytes],offset, inpsize-inpBytes, &r_bytes);
  298.       offset+=r_bytes; 
  299.  
  300.             if (r_bytes== 0)  break;   
  301.            
  302.                   inpPtr = inpbuf;
  303.                   inpBytes += r_bytes;
  304.             if(totalout < 32768) continue;
  305.          
  306.             outPtr = outbuf;           
  307.             while (totalout > 32768)
  308.      { wave_out(outPtr);
  309.               totalout-=0x8000;
  310.               outPtr+=0x8000;  
  311.       };
  312.       memmove(outbuf,outPtr, totalout);
  313.       outPtr = outbuf+totalout;
  314.     };
  315.     if(status != ST_EXIT)
  316.     status =  ST_STOP;
  317. };
  318.  
  319. void play_wave()
  320. {
  321.    int retval;
  322.    int remain;
  323.    int i;
  324.  
  325.    offset = 44;
  326.  
  327.    read_file (__argv,outbuf,offset,32*1024,0);
  328.    offset+=32*1024;
  329.    SetBuffer(hSound,hBuff,outbuf,0,0x8000);
  330.  
  331.    read_file (__argv,outbuf,offset,32*1024,0);
  332.    offset+=32*1024;
  333.    SetBuffer(hSound,hBuff,outbuf,0x8000,0x8000);
  334.  
  335.    PlayBuffer(hSound, hBuff);
  336.  
  337.    retval = 0;
  338.    while(1)
  339.    {
  340.      if(status!=ST_PLAY)
  341.        break;
  342.  
  343.      GetNotify(&event[0]);
  344.      if(retval == FILE_EOF)
  345.        break;
  346.      remain = fileinfo.size-offset;
  347.      if(remain >=32768)
  348.      { retval = read_file (__argv,outbuf,offset,32*1024,0);
  349.        offset+=32*1024;
  350.        SetBuffer(hSound,hBuff,outbuf,event[1],0x8000);
  351.        continue;
  352.      };
  353.      if(remain == 0)
  354.      { retval = FILE_EOF;
  355.        continue;
  356.      };
  357.      read_file (__argv,outbuf,offset,remain,0);
  358.      for(i=remain;i<32768;i++)
  359.        outbuf[i] = 0;
  360.      SetBuffer(hSound,hBuff,outbuf,event[1],0x8000);
  361.      retval= FILE_EOF;
  362.    };
  363.  
  364.    if(status != ST_EXIT)
  365.     status =  ST_STOP;
  366. };
  367.  
  368. void snd_stop()
  369. {
  370.   StopBuffer(hSound, hBuff);
  371. };
  372.  
  373. void thread_proc()
  374. { int evnt;
  375.    int pos;
  376.    int key;
  377.  
  378.   _asm { fninit };
  379.  
  380.    
  381.   draw_window();
  382.  
  383.   while(1)
  384.   {  if(status==ST_PLAY)
  385.       {  draw_progress_bar();
  386.           evnt = wait_for_event(80);
  387.        //   debug_out_str("BIG ERROR...\x0D\x0A\x00");          
  388.       }
  389.      else
  390.         evnt = wait_for_event_infinite();
  391.  
  392.     switch(evnt)
  393.     {
  394.       case EV_REDRAW:
  395.         draw_window();
  396.         break;
  397.  
  398.       case EV_KEY:
  399.         key = get_key();
  400.         if(key==27)
  401.         {   status = ST_EXIT;
  402.             exit();
  403.         };
  404.         if((key==45)||key==54)
  405.         { if(m_vol > 0)
  406.           { m_vol--;
  407.             SetMasterVol(hDrv,m_vol);
  408.           };
  409.           break;
  410.         };
  411.         if((key==61)||key==56)
  412.         { if(m_vol < 90)
  413.           { m_vol++;
  414.             SetMasterVol(hDrv,m_vol);
  415.           };
  416.         };
  417.         break;
  418.  
  419.       case EV_BUTTON:
  420.         switch(get_button_id())
  421.         {  case 1:
  422.              status = ST_EXIT;
  423.              exit();
  424.              break;
  425.              
  426.            case 0x10:
  427.              status = ST_PLAY;
  428.              continue;
  429.  
  430.            case 0x11:
  431.              status = ST_STOP;
  432.              break;
  433. //           case 0x12:
  434. //           case 0x13:
  435.            case 0x14:
  436.              if(m_vol > 0)
  437.              { m_vol--;
  438.                SetMasterVol(hDrv,m_vol);
  439.              };
  440.              break;
  441.  
  442.            case 0x15:
  443.              if(m_vol < 90)
  444.              { m_vol++;
  445.                SetMasterVol(hDrv,m_vol);
  446.              };
  447.              break;
  448.  
  449.            case 0x30:
  450.             if(status==ST_DONE)
  451.               break;
  452.             if(snd_play == play_mp3)
  453.               continue;  
  454.             pos = (GetMousePos(REL_WINDOW)>>16)-7;
  455.             offset = ((fileinfo.size-44)/286*pos+44)&0xFFFFFFFC;
  456.             draw_progress_bar();
  457.             break;
  458.         };
  459.     };
  460.   };
  461. };
  462.  
  463. DWORD test_wav(WAVEHEADER *hdr)
  464. {
  465.   if(hdr->riff_id != 0x46464952)
  466.     return 0;
  467.  
  468.   if(hdr->riff_format != 0x45564157)
  469.     return 0;
  470.  
  471.   if (hdr->wFormatTag != 0x01)
  472.     return 0;
  473.  
  474.   switch(hdr->nSamplesPerSec)
  475.   { case 48000:
  476.       switch (hdr->nChannels)
  477.       {  case 1:
  478.            if(hdr->wBitsPerSample == 16)
  479.              return PCM_1_16_48;
  480.            else
  481.              return PCM_1_8_48;
  482.  
  483.          case 2:
  484.            if(hdr->wBitsPerSample == 16)
  485.              return PCM_2_16_48;
  486.            else
  487.              return PCM_2_8_48;
  488.       };
  489.  
  490.     case 44100:
  491.       switch (hdr->nChannels)
  492.       {  case 1:
  493.            if(hdr->wBitsPerSample == 16)
  494.              return PCM_1_16_44;
  495.            else
  496.              return PCM_1_8_44;
  497.  
  498.          case 2:
  499.            if(hdr->wBitsPerSample == 16)
  500.              return PCM_2_16_44;
  501.            else
  502.              return PCM_2_8_44;
  503.       };
  504.  
  505.     case 32000:
  506.       switch (hdr->nChannels)
  507.       {  case 1:
  508.            if(hdr->wBitsPerSample == 16)
  509.              return PCM_1_16_32;
  510.            else
  511.              return PCM_1_8_32;
  512.  
  513.          case 2:
  514.            if(hdr->wBitsPerSample == 16)
  515.              return PCM_2_16_32;
  516.            else
  517.              return PCM_2_8_32;
  518.       };
  519.  
  520.     case 24000:
  521.       switch (hdr->nChannels)
  522.       {  case 1:
  523.            if(hdr->wBitsPerSample == 16)
  524.              return PCM_1_16_24;
  525.            else
  526.              return PCM_1_8_24;
  527.  
  528.          case 2:
  529.            if(hdr->wBitsPerSample == 16)
  530.              return PCM_2_16_24;
  531.            else
  532.              return PCM_2_8_24;
  533.       };
  534.  
  535.     case 22050:
  536.       switch (hdr->nChannels)
  537.       {  case 1:
  538.            if(hdr->wBitsPerSample == 16)
  539.              return PCM_1_16_22;
  540.            else
  541.              return PCM_1_8_22;
  542.  
  543.          case 2:
  544.            if(hdr->wBitsPerSample == 16)
  545.              return PCM_2_16_22;
  546.            else
  547.              return PCM_2_8_22;
  548.       };
  549.  
  550.     case 16000:
  551.       switch (hdr->nChannels)
  552.       {  case 1:
  553.            if(hdr->wBitsPerSample == 16)
  554.              return PCM_1_16_16;
  555.            else
  556.              return PCM_1_8_16;
  557.  
  558.          case 2:
  559.            if(hdr->wBitsPerSample == 16)
  560.              return PCM_2_16_16;
  561.            else
  562.              return PCM_2_8_16;
  563.       };
  564.  
  565.     case 12000:
  566.       switch (hdr->nChannels)
  567.       {  case 1:
  568.            if(hdr->wBitsPerSample == 16)
  569.              return PCM_1_16_12;
  570.            else
  571.              return PCM_1_8_12;
  572.  
  573.          case 2:
  574.            if(hdr->wBitsPerSample == 16)
  575.              return PCM_2_16_12;
  576.            else
  577.              return PCM_2_8_12;
  578.       };
  579.  
  580.     case 11025:
  581.       switch (hdr->nChannels)
  582.       {  case 1:
  583.            if(hdr->wBitsPerSample == 16)
  584.              return PCM_1_16_11;
  585.            else
  586.              return PCM_1_8_11;
  587.  
  588.          case 2:
  589.            if(hdr->wBitsPerSample == 16)
  590.              return PCM_2_16_11;
  591.            else
  592.              return PCM_2_8_11;
  593.       };
  594.  
  595.     case 8000:
  596.       switch (hdr->nChannels)
  597.       {  case 1:
  598.            if(hdr->wBitsPerSample == 16)
  599.              return PCM_1_16_8;
  600.            else
  601.              return PCM_1_8_8;
  602.  
  603.          case 2:
  604.            if(hdr->wBitsPerSample == 16)
  605.              return PCM_2_16_8;
  606.            else
  607.              return PCM_2_8_8;
  608.       };
  609.       default:
  610.         return 0;
  611.   };
  612. };
  613.  
  614. void delay (int val)
  615. {
  616.   _asm
  617.  {   mov   eax,5
  618.       mov   ebx, [val]
  619.       int   0x40
  620.   };  
  621. }
  622.  
  623. int wait_for_event(int time)
  624. { int retval;
  625.   _asm
  626.  {  mov  eax,23
  627.      mov  ebx,[time]
  628.      int  0x40
  629.      mov [retval], eax
  630.  };
  631.  return retval;
  632. };
  633.  
  634. int wait_for_event_infinite()
  635. { int retval;
  636.   _asm
  637.   {  mov  eax,10
  638.       int  0x40
  639.       mov [retval], eax
  640.   };
  641.   return retval;
  642. };
  643.  
  644. void BeginDraw()
  645. {_asm
  646.  { mov   eax,12
  647.     mov   ebx, 1
  648.     int   0x40
  649.   };  
  650. };
  651.  
  652. void EndDraw()
  653. { _asm
  654.  { mov   eax,12
  655.     mov   ebx, 2
  656.     int   0x40
  657.   };  
  658. };
  659.  
  660. void * __cdecl memmove ( void * dst, const void * src, size_t count)
  661. { void * ret = dst;
  662.  
  663.   if (dst <= src || (char *)dst >= ((char *)src + count))
  664.   {
  665.       while (count--)
  666.       { *(char *)dst = *(char *)src;
  667.           dst = (char *)dst + 1;
  668.           src = (char *)src + 1;
  669.       }
  670.    }
  671.    else
  672.     {
  673.         dst = (char *)dst + count - 1;
  674.         src = (char *)src + count - 1;
  675.          while (count--)
  676.           {  *(char *)dst = *(char *)src;
  677.               dst = (char *)dst - 1;
  678.               src = (char *)src - 1;
  679.           }
  680.     }
  681.     return(ret);
  682. };
  683.  
  684.  
  685.  
  686.  
  687. //   debug_out_str(formats[fmt]);
  688. //   debug_out_str("\x0D\x0A\x00");
  689.  
  690. //   debug_out_str("pci cmd: ");
  691. //   debug_out_hex(info.pci_cmd);
  692. //   debug_out_str("\x0D\x0A\x00");
  693.  
  694. //   debug_out_str("irq line: ");
  695. //   debug_out_hex(info.irq);
  696. //   debug_out_str("\x0D\x0A\x00");
  697.  
  698. //   debug_out_str("global control: ");
  699. //   debug_out_hex(info.glob_cntrl);
  700. //   debug_out_str("\x0D\x0A\x00");
  701.  
  702. //   debug_out_str("global status:  ");
  703. //   debug_out_hex(info.glob_sta);
  704. //   debug_out_str("\x0D\x0A\x00");
  705.  
  706.  
  707.   // call _print_volume
  708.  
  709. //   debug_out_hex(whdr.nChannels);
  710. //   debug_out_str("\x0D\x0A\x00");
  711. //   debug_out_hex(whdr.nSamplesPerSec);
  712. //   debug_out_str("\x0D\x0A\x00");
  713.  
  714. //   debug_out_hex(fmt);
  715. //   debug_out_str("\x0D\x0A\x00");
  716.  
  717.  
  718.  
  719.