Subversion Repositories Kolibri OS

Rev

Rev 577 | Rev 650 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
576 serge 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"
646 serge 21
#include "../ufmod-codec.h"                   /* uFMOD integration */
22
void exit();                                  /* uFMOD integration */
576 serge 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);
646 serge 33
int stream_read_raw(struct reader *rd,unsigned char *buf, int size);
576 serge 34
 
646 serge 35
int __cdecl _stricmp (const char * dst, const char * src);
36
char *__cdecl strrchr (const char * string,int ch);
37
 
576 serge 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;
646 serge 50
const char *filename;
51
const char *fileext;
576 serge 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;
646 serge 71
 
576 serge 72
char header[] = "AC97 MP3 player";
646 serge 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 */
576 serge 76
 
646 serge 77
void play_xm();                                                       /* uFMOD integration */
576 serge 78
void (*snd_play)();
79
 
80
void draw_window()
81
{
646 serge 82
	int len;                                                          /* uFMOD integration */
576 serge 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);
646 serge 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 */
576 serge 101
 
646 serge 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 */
576 serge 105
 
106
   EndDraw();
107
};
108
 
109
void draw_progress_bar()
110
{  DWORD x;
646 serge 111
   x = (DWORD)(287.0f * (float)(rd.filepos-rd.strremain)/(float)fileinfo.size); /* uFMOD integration */
576 serge 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
 
577 serge 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;
646 serge 133
   unsigned char *ttl, *cur;               /* uFMOD integration */
577 serge 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);
646 serge 172
 
173
   filename = strrchr(fname,'/')+1;
174
   if( !(fileext = strrchr(filename,'.')))
175
     return 0;
176
 
177
   if(!_stricmp(fileext,".mp3"))
577 serge 178
   {
646 serge 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;
577 serge 194
   };
646 serge 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
	 };
577 serge 235
 
646 serge 236
   debug_out_str("\n\rUsupported file");
237
   return 0;
238
 
239
play:
240
 
577 serge 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:
646 serge 267
           uFMOD_StopSong();          /* uFMOD integration */
577 serge 268
           StopBuffer(hBuff);
269
           DestroyBuffer(hBuff);
270
           return 0;
271
      };
272
   };
273
   return 0;
274
};
275
 
576 serge 276
void touch(char *buf, int size)
277
{ int i;
278
   char a;
646 serge 279
    for ( i = 0;i < size; i+=4096)     //alloc all pages
576 serge 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))
577 serge 291
                        return 0;
576 serge 292
        if(!decode_header(&fr,hdr))
646 serge 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;
576 serge 304
        };
305
        break;
646 serge 306
    };
576 serge 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];
646 serge 314
    whdr.nChannels = 2;
576 serge 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
 
577 serge 326
 //   memset(&fr,0,sizeof(fr));
327
    fr.down_sample_sblimit = 32;
576 serge 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
 
577 serge 343
     for(;;)
344
     {   outcount = 0;
576 serge 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;
577 serge 355
    };
576 serge 356
 
577 serge 357
    if(done)
358
    { if(totalout < 4096)
359
      {  memset(outPtr,0,4096-totalout);
360
                totalout = 4096;
576 serge 361
      };
577 serge 362
    }
363
    else
364
      if(totalout < 8192)
365
        continue;
576 serge 366
 
577 serge 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;
576 serge 390
};
391
 
392
void play_wave()
646 serge 393
{  int count;
576 serge 394
 
395
   set_reader(&rd,44);
396
   while(1)
397
   {
398
      if(status!=ST_PLAY)
399
        break;
400
 
646 serge 401
      if( count=stream_read_raw(&rd,outbuf,32768))
402
      {
403
        WaveOut(hBuff,outbuf,count);
404
        continue;
405
      }
406
      done = 1;
407
      break;
576 serge 408
   };
409
 
410
   if(status != ST_EXIT)
646 serge 411
     status =  ST_STOP;
576 serge 412
};
413
 
646 serge 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
 
576 serge 422
void snd_stop()
423
{
424
  StopBuffer(hBuff);
425
};
426
 
577 serge 427
void _stdcall thread_proc(void *param)
428
{  int evnt;
429
   int pos;
430
   int key;
431
   DWORD offset;
432
 
433
  _asm
576 serge 434
  {
577 serge 435
    mov eax, 66
436
    mov ebx, 1
437
    mov ecx, 1
438
    int 0x40
576 serge 439
  };
577 serge 440
 
441
  draw_window();
576 serge 442
 
577 serge 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();
576 serge 450
 
577 serge 451
    switch(evnt)
452
    {
453
      case EV_REDRAW:
454
        draw_window();
455
        break;
576 serge 456
 
577 serge 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;
576 serge 503
 
577 serge 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;
576 serge 513
             continue;
514
 
577 serge 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;
576 serge 528
 
577 serge 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;
576 serge 536
 
577 serge 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
  };
576 serge 548
};
549
 
550
void delay (int val)
551
{
552
  _asm
577 serge 553
 {   mov   eax,5
576 serge 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
///*********
646 serge 597
void *memmove ( void * dst, void * src, unsigned int count)  /* uFMOD integration */
576 serge 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
 
646 serge 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
 
576 serge 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");