Subversion Repositories Kolibri OS

Rev

Rev 376 | 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 "string.h"
  18. #include "ac97wav.h"
  19. #include "mpg/mpg123.h"
  20. #include "sound.h"
  21.  
  22. #define MP3_ERROR_OUT_OF_BUFFER  5
  23. int m_last_error;
  24.  
  25. void _stdcall thread_proc(void *param);
  26. void _stdcall create_thread(void *proc, void *param, int stack_size);
  27. void _stdcall send_ipc(int dst, DWORD code);
  28.  
  29. void touch(char *buf, int size);
  30. int mp3FindSync(byte* buf, int size, int* sync);
  31. int stream_read_raw(struct reader *rd,unsigned char *buf, int size);
  32.  
  33. char *fname;
  34.  
  35. struct reader rd;
  36. struct frame fr;
  37.  
  38. DWORD hDrv;
  39. DWORD hSound;
  40. SNDBUF hBuff;
  41.  
  42. CTRL_INFO info;
  43.  
  44. FILEINFO   fileinfo;
  45.  
  46. int m_vol;
  47. int l_vol=-700;     //-7db
  48. int r_vol=-700;
  49. int pan =0;
  50.  
  51. DWORD status;
  52. DWORD offset;
  53. DWORD first_sync;
  54.  
  55. unsigned char *testbuff;
  56. unsigned char *outbuf;
  57. unsigned char *inpbuf;
  58. unsigned char *outPtr;
  59.  
  60. int inpsize;
  61. int outsize;
  62. int outremain;
  63. int totalout;
  64. int done;
  65.  
  66. char header[] = "AC97 MP3 player";
  67. char buttons_text[]=" Play    Stop     <<      >>     Vol-    Vol+";
  68.  
  69. void (*snd_play)();
  70.  
  71. void draw_window()
  72. {
  73.    BeginDraw();
  74.  
  75.    DrawWindow(100,100,299,72,0x404040,3,0,0,0);
  76.  
  77.    make_button(7,24,45,13, 0x10|BT_NORMAL,0x808080);
  78.    make_button(56,24,45,13, 0x11|BT_NORMAL,0x808080);
  79.    make_button(104,24,45,13, 0x12|BT_NORMAL,0x808080);
  80.    make_button(152,24,45,13, 0x13|BT_NORMAL,0x808080);
  81.    make_button(200,24,45,13, 0x14|BT_NORMAL,0x808080);
  82.    make_button(248,24,45,13, 0x15|BT_NORMAL,0x808080);
  83.  
  84.    make_button(7,41,286,11, 0x30|BT_HIDE|BT_NOFRAME,0x404040);
  85.    draw_bar(7,41,286,11,0x404040);
  86.  
  87.    draw_bar(7,55,286,11,0x404040);
  88.    write_text(12,58,0x004000|FONT0, fname, strlen(fname));
  89.    write_text(11,57,0x00FF20|FONT0, fname, strlen(fname));
  90.  
  91.    write_text(8,8,0xFFFFFF|FONT0, header, strlen(header));
  92.    write_text(12,28,0x404040|FONT0,buttons_text,strlen(buttons_text));
  93.    write_text(11,27,0xA0FFA0|FONT0,buttons_text,strlen(buttons_text));
  94.  
  95.    EndDraw();
  96. };
  97.  
  98. void draw_progress_bar()
  99. {  DWORD x;
  100.    x = 287.0f * (float)(rd.filepos-rd.strremain)/(float)fileinfo.size;
  101.    if(x==0) return;
  102.    draw_bar(7,41,x,11,0xA0A0A0);
  103.    draw_bar(x+7,41,287-x,11,0x404040);
  104. };
  105.  
  106. void debug_out_str(char* str)
  107. {
  108.   while (*str != 0)
  109.   {
  110.     debug_out(*str);
  111.     str++;
  112.   }
  113. }
  114.  
  115. int main(int argc, char *argv[])      //int argc, char *argv[])
  116. {
  117.    DWORD fmt;
  118.    DWORD r_bytes;
  119.    int retval;
  120.    int err;
  121.    int ver;
  122.    
  123.    fname = argv[1];
  124.    debug_out_str("\n\rPlay file ");
  125.    debug_out_str(fname);
  126.    debug_out_str("\n\r");
  127.    
  128.    InitHeap(1024*1024);
  129.    if(get_fileinfo(fname, &fileinfo)==FILE_NOT_FOUND)
  130.    {  debug_out_str("\n\rfile not found\n\r");
  131.       return 0;
  132.    };
  133.  
  134.    if(err = InitSound(&ver))
  135.    {  
  136.      debug_out_str("Sound service not installed\n\r");
  137.      return 0;
  138.    }
  139.    
  140.    if( (SOUND_VERSION>(ver&0xFFFF)) ||
  141.        (SOUND_VERSION<(ver >> 16)))
  142.    {  
  143.      debug_out_str("Sound service version mismatch\n\r");
  144.      return 0;
  145.    }
  146.    
  147.    testbuff = UserAlloc(4096);
  148.    get_fileinfo(fname, &fileinfo);
  149.    offset = 0;
  150.    retval=read_file (fname,testbuff,0,2048,&r_bytes);
  151.    if (retval) return 0;
  152.  
  153.    inpbuf = UserAlloc(0x10000);
  154.    touch(inpbuf, 0x10000);
  155.    
  156.    create_reader(&rd, inpbuf, 0x10000);
  157.    init_reader(&rd,fname);
  158.  
  159.    fmt = test_wav((WAVEHEADER*)testbuff);
  160.    if (fmt != 0)
  161.    {
  162.      snd_play = &play_wave;
  163.      set_reader(&rd, 44);
  164.      outbuf = UserAlloc(32*1024);
  165.      touch(outbuf, 32768);
  166.    }  
  167.    else  
  168.    { fmt = test_mp3(testbuff);
  169.      if(fmt ==0) return 0;
  170.      snd_play = &play_mp3;
  171.      
  172.      outremain = 0x40000 ;
  173.      outbuf = UserAlloc(outremain);
  174.      touch(outbuf, outremain);
  175.      make_decode_tables(32767);
  176.      init_layer2();
  177.      init_layer3(32);
  178.      fr.single = -1;
  179.    };
  180.  
  181.    status = ST_PLAY;
  182.    
  183.    if (err = CreateBuffer(fmt,0, &hBuff))
  184.    {
  185.      debug_out_str("create buffer return error\n\r");
  186.     ; return 0;
  187.    }
  188.        
  189.    SetVolume(hBuff,l_vol,r_vol);
  190.    GetVolume(hBuff,&l_vol,&r_vol);
  191.  
  192.    create_thread(thread_proc, 0, 4096);
  193.  
  194.    while(1)
  195.    {  delay(10);
  196.       switch(status)
  197.       {  case ST_PLAY:
  198.            snd_play();
  199.            continue;
  200.  
  201.          case ST_STOP:
  202.            StopBuffer(hBuff);
  203.            status = ST_DONE;
  204.            continue;
  205.  
  206.          case ST_EXIT:
  207.            StopBuffer(hBuff);
  208.            DestroyBuffer(hBuff);
  209.            return 0;
  210.       };
  211.    };
  212.    return 0;
  213. };
  214.  
  215. void touch(char *buf, int size)
  216. { int i;
  217.    char a;
  218.     for ( i = 0;i < size; i+=4096)
  219.       a = buf[i];
  220. };
  221.  
  222. DWORD test_mp3(char *buf)
  223. {  unsigned long hdr;
  224.     WAVEHEADER whdr;
  225.      
  226.     while (1)
  227.     {  if(rd.filepos > 102400)
  228.           return 0;
  229.         if(!rd.head_read(&rd,&hdr))
  230.                         return 0;
  231.         if(!decode_header(&fr,hdr))
  232.         {  rd.strpos-=3;
  233.             rd.stream-=3;
  234.             rd.strremain+=3;
  235.             continue;
  236.         };
  237.         break;
  238.           };
  239.          
  240.     first_sync = rd.filepos-rd.strremain-4;
  241.          
  242.     whdr.riff_id = 0x46464952;
  243.     whdr.riff_format = 0x45564157;
  244.     whdr.wFormatTag = 0x01;
  245.     whdr.nSamplesPerSec = freqs[fr.sampling_frequency];
  246.     whdr.nChannels = 2; //mpginfo.channels;
  247.     whdr.wBitsPerSample = 16;
  248.    
  249.     return test_wav(&whdr);
  250. };
  251.  
  252.  
  253. void play_mp3()
  254. {  char *outPtr;
  255.     int totalout;
  256.     int outcount;
  257.  
  258.  //   memset(&fr,0,sizeof(fr));
  259.     fr.down_sample_sblimit = 32;
  260.     fr.single = -1;
  261.     reset_mpg();
  262.  
  263.     outPtr = outbuf;
  264.     totalout=0;
  265.     done = 0;
  266.     outremain=0x40000;
  267.  
  268.     memset(outbuf,0,0x40000);
  269.     set_reader(&rd, 0);    //;first_sync);
  270.  
  271.     while(1)
  272.     { if(status!=ST_PLAY)
  273.              break;
  274.  
  275.      for(;;)
  276.      {   outcount = 0;                          
  277.           if( !read_frame(&rd, &fr))
  278.           {  done = 1;
  279.               break;
  280.           };
  281.           fr.do_layer(&fr, outPtr,&outcount);
  282.           outPtr+= outcount;
  283.           totalout+=outcount;
  284.           outremain-=outcount;
  285.           if(outremain < outcount*2)
  286.             break;  
  287.     };
  288.  
  289.     if(done)
  290.     { if(totalout < 4096)
  291.       {  memset(outPtr,0,4096-totalout);
  292.                 totalout = 4096;
  293.       };
  294.     }
  295.     else
  296.       if(totalout < 8192)
  297.         continue;
  298.     outPtr = outbuf;      
  299.     while (totalout >= 4096)
  300.     {
  301.    
  302.       WaveOut(hBuff,outPtr,4096);
  303.       if(status!=ST_PLAY)
  304.       { if(status != ST_EXIT)
  305.          status =  ST_STOP;
  306.         return;
  307.       };
  308.       totalout-=4096;
  309.       outPtr+=4096;
  310.       outremain+=4096;
  311.     };
  312.     if(done)
  313.       break;
  314.      
  315.     memmove(outbuf,outPtr, totalout);
  316.     outPtr = outbuf+totalout;
  317.    }
  318.  
  319.     if(status != ST_EXIT)
  320.     status =  ST_STOP;
  321. };
  322.  
  323. void play_wave()
  324. {  int retval;
  325.  
  326.    set_reader(&rd,44);
  327.    retval = 0;
  328.    while(1)
  329.    {
  330.       if(status!=ST_PLAY)
  331.         break;
  332.  
  333.       if( !stream_read_raw(&rd,outbuf,32768))
  334.       {  done = 1;
  335.           break;
  336.       };
  337.       WaveOut(hBuff,outbuf,32768);
  338.    };
  339.  
  340.    if(status != ST_EXIT)
  341.     status =  ST_STOP;
  342. };
  343.  
  344. void snd_stop()
  345. {
  346.   StopBuffer(hBuff);
  347. };
  348.  
  349. void _stdcall thread_proc(void *param)
  350. {  int evnt;
  351.    int pos;
  352.    int key;
  353.  
  354.   _asm
  355.   {
  356.     mov eax, 66
  357.     mov ebx, 1
  358.     mov ecx, 1
  359.     int 0x40
  360.   };
  361.    
  362.   draw_window();
  363.  
  364.   while(1)
  365.   {  if(status==ST_PLAY)
  366.      {  draw_progress_bar();
  367.         evnt = wait_for_event(80);
  368.      }
  369.      else
  370.         evnt = wait_for_event_infinite();
  371.  
  372.     switch(evnt)
  373.     {
  374.       case EV_REDRAW:
  375.         draw_window();
  376.         break;
  377.  
  378.       case EV_KEY:
  379.         if(!get_key(&key))
  380.         {
  381.        
  382.           switch(key)
  383.           {  case 0xE0:
  384.              case 0xE1:
  385.                break;
  386.              default:
  387.                switch (key)
  388.                {
  389.                  case 0x01:  //Esc
  390.                    status = ST_EXIT;
  391.                    exit();
  392.                    break;
  393.                
  394.                  case 0x47:  //Home
  395.                    if(l_vol < 0)
  396.                    { l_vol+=100;
  397.                      r_vol+=100;  
  398.                      SetVolume(hBuff,l_vol,r_vol);
  399.                    };
  400.                    break;
  401.                  case 0x4F:  //End                
  402.                    if(l_vol > -10000)
  403.                    { l_vol-=100;
  404.                      r_vol-=100;  
  405.                      SetVolume(hBuff,l_vol,r_vol);
  406.                    };
  407.                    break;
  408.                  case 0x53:
  409.                    if(pan > -10000)
  410.                    { pan -=100;
  411.                      SetPan(hBuff,pan);
  412.                    };
  413.                    break;  
  414.                  case 0x51:
  415.                    if(pan < 10000)
  416.                    { pan +=100;
  417.                      SetPan(hBuff,pan);
  418.                    };
  419.                    break;  
  420.                }
  421.           };    
  422.         };  
  423.         break;
  424.  
  425.       case EV_BUTTON:
  426.         switch(get_button_id())
  427.         {  case 1:
  428.              status = ST_EXIT;
  429.              exit();
  430.              break;
  431.              
  432.            case 0x10:
  433.              status = ST_PLAY;
  434.              continue;
  435.  
  436.            case 0x11:
  437.              status = ST_STOP;
  438.              break;
  439. //           case 0x12:
  440. //           case 0x13:
  441.            case 0x14:
  442.             if(l_vol > -10000)
  443.             {
  444.               l_vol-=100;
  445.               r_vol-=100;  
  446.               SetVolume(hBuff,l_vol,r_vol);
  447.             };
  448.             break;
  449.  
  450.            case 0x15:
  451.             if(l_vol < 0)
  452.             { l_vol+=100;
  453.               r_vol+=100;  
  454.               SetVolume(hBuff,l_vol,r_vol);
  455.             };
  456.             break;
  457.  
  458.            case 0x30:
  459.             if(status==ST_DONE)
  460.               break;
  461.             pos = (GetMousePos(REL_WINDOW)>>16)-7;
  462.             offset = ((fileinfo.size-44)/286*pos+44)&0xFFFFFFFC;
  463.             set_reader(&rd, offset);
  464.             draw_progress_bar();
  465.             break;
  466.         };
  467.     };
  468.   };
  469. };
  470.  
  471. void delay (int val)
  472. {
  473.   _asm
  474.  {   mov   eax,5
  475.       mov   ebx, [val]
  476.       int   0x40
  477.   };  
  478. }
  479.  
  480. int wait_for_event(int time)
  481. { int retval;
  482.   _asm
  483.  {  mov  eax,23
  484.      mov  ebx,[time]
  485.      int  0x40
  486.      mov [retval], eax
  487.  };
  488.  return retval;
  489. };
  490.  
  491. int wait_for_event_infinite()
  492. { int retval;
  493.   _asm
  494.   {  mov  eax,10
  495.       int  0x40
  496.       mov [retval], eax
  497.   };
  498.   return retval;
  499. };
  500.  
  501. void BeginDraw()
  502. {_asm
  503.  { mov   eax,12
  504.     mov   ebx, 1
  505.     int   0x40
  506.   };  
  507. };
  508.  
  509. void EndDraw()
  510. { _asm
  511.  { mov   eax,12
  512.     mov   ebx, 2
  513.     int   0x40
  514.   };  
  515. };
  516.  
  517. ///*********
  518. void *memmove ( void * dst, void * src, int count)
  519. { void *ret;
  520.   ret = dst;
  521.  
  522.   if (dst <= src || (char *)dst >= ((char *)src + count))
  523.   {
  524.       while (count--)
  525.       { *(char *)dst = *(char *)src;
  526.           dst = (char *)dst + 1;
  527.           src = (char *)src + 1;
  528.       }
  529.    }
  530.    else
  531.     {
  532.         dst = (char *)dst + count - 1;
  533.         src = (char *)src + count - 1;
  534.          while (count--)
  535.           {  *(char *)dst = *(char *)src;
  536.               dst = (char *)dst - 1;
  537.               src = (char *)src - 1;
  538.           }
  539.     }
  540.     return ret;
  541. };
  542. //**********/
  543.  
  544. void * __cdecl mem_cpy(void * dst,const void * src,size_t count)
  545. {    void * ret = dst;
  546.       while (count--)
  547.       {  *(char *)dst = *(char *)src;
  548.           dst = (char *)dst + 1;
  549.           src = (char *)src + 1;
  550.       };
  551.       return(ret);
  552. }
  553.  
  554. //   debug_out_str(formats[fmt]);
  555. //   debug_out_str("\x0D\x0A\x00");
  556.  
  557. //   debug_out_str("pci cmd: ");
  558. //   debug_out_hex(info.pci_cmd);
  559. //   debug_out_str("\x0D\x0A\x00");
  560.  
  561. //   debug_out_str("irq line: ");
  562. //   debug_out_hex(info.irq);
  563. //   debug_out_str("\x0D\x0A\x00");
  564.  
  565. //   debug_out_str("global control: ");
  566. //   debug_out_hex(info.glob_cntrl);
  567. //   debug_out_str("\x0D\x0A\x00");
  568.  
  569. //   debug_out_str("global status:  ");
  570. //   debug_out_hex(info.glob_sta);
  571. //   debug_out_str("\x0D\x0A\x00");
  572.  
  573.  
  574.   // call _print_volume
  575.  
  576. //   debug_out_hex(whdr.nChannels);
  577. //   debug_out_str("\x0D\x0A\x00");
  578. //   debug_out_hex(whdr.nSamplesPerSec);
  579. //   debug_out_str("\x0D\x0A\x00");
  580.  
  581. //   debug_out_hex(fmt);
  582. //   debug_out_str("\x0D\x0A\x00");
  583.  
  584.  
  585.  
  586.