Subversion Repositories Kolibri OS

Rev

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