Subversion Repositories Kolibri OS

Rev

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