Subversion Repositories Kolibri OS

Rev

Rev 799 | Rev 1842 | 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.
650 serge 3
//   (C) copyright Serge 2006-2007 infinity_sound@mail.ru
4
//   (C) copyright Quantum 2007    ufmod@users.sf.net
576 serge 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;
799 serge 432
 
577 serge 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
799 serge 553
 {
554
      mov   eax,5
576 serge 555
      mov   ebx, [val]
556
      int   0x40
557
  };
558
}
559
 
560
int wait_for_event(int time)
561
{ int retval;
562
  _asm
799 serge 563
 {
564
     mov  eax,23
576 serge 565
     mov  ebx,[time]
566
     int  0x40
567
     mov [retval], eax
568
 };
569
 return retval;
570
};
571
 
572
int wait_for_event_infinite()
573
{ int retval;
574
  _asm
799 serge 575
  {
576
      mov  eax,10
576 serge 577
      int  0x40
578
      mov [retval], eax
579
  };
580
  return retval;
581
};
582
 
583
void BeginDraw()
584
{_asm
799 serge 585
 {
586
    mov   eax,12
576 serge 587
    mov   ebx, 1
588
    int   0x40
589
  };
590
};
591
 
592
void EndDraw()
593
{ _asm
799 serge 594
 {
595
    mov   eax,12
576 serge 596
    mov   ebx, 2
597
    int   0x40
598
  };
599
};
600
 
601
///*********
646 serge 602
void *memmove ( void * dst, void * src, unsigned int count)  /* uFMOD integration */
576 serge 603
{ void *ret;
604
  ret = dst;
605
 
606
  if (dst <= src || (char *)dst >= ((char *)src + count))
607
  {
608
      while (count--)
609
      { *(char *)dst = *(char *)src;
610
          dst = (char *)dst + 1;
611
          src = (char *)src + 1;
612
      }
613
   }
614
   else
615
    {
616
        dst = (char *)dst + count - 1;
617
        src = (char *)src + count - 1;
618
         while (count--)
619
          {  *(char *)dst = *(char *)src;
620
              dst = (char *)dst - 1;
621
              src = (char *)src - 1;
622
          }
623
    }
624
    return ret;
625
};
626
//**********/
627
 
628
void * __cdecl mem_cpy(void * dst,const void * src,size_t count)
629
{    void * ret = dst;
630
      while (count--)
631
      {  *(char *)dst = *(char *)src;
632
          dst = (char *)dst + 1;
633
          src = (char *)src + 1;
634
      };
635
      return(ret);
636
}
637
 
646 serge 638
char * __cdecl strrchr (const char * string,int ch)
639
{
640
        char *start = (char *)string;
641
 
642
        while (*string++)                       /* find end of string */
643
                ;
644
                                                /* search towards front */
645
        while (--string != start && *string != (char)ch)
646
                ;
647
 
648
        if (*string == (char)ch)                /* char found ? */
649
                return( (char *)string );
650
 
651
        return(NULL);
652
}
653
 
654
int __cdecl _stricmp (const char * dst, const char * src)
655
{
656
    int f, l;
657
 
658
    do
659
    {
660
        if ( ((f = (unsigned char)(*(dst++))) >= 'A') && (f <= 'Z') )
661
            f -= 'A' - 'a';
662
        if ( ((l = (unsigned char)(*(src++))) >= 'A') && (l <= 'Z') )
663
            l -= 'A' - 'a';
664
    }
665
    while ( f && (f == l) );
666
 
667
    return(f - l);
668
}
669