Subversion Repositories Kolibri OS

Rev

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