Subversion Repositories Kolibri OS

Rev

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

Rev Author Line No. Line
165 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"
228 serge 19
#include "mpg/mpg123.h"
376 serge 20
#include "sound.h"
165 serge 21
 
376 serge 22
#define MP3_ERROR_OUT_OF_BUFFER  5
228 serge 23
int m_last_error;
24
 
165 serge 25
void thread_proc();
26
void touch(char *buf, int size);
228 serge 27
int mp3FindSync(byte* buf, int size, int* sync);
28
int stream_read_raw(struct reader *rd,unsigned char *buf, int size);
165 serge 29
 
228 serge 30
char *fname;
165 serge 31
 
228 serge 32
struct reader rd;
33
struct frame fr;
165 serge 34
 
35
DWORD hDrv;
36
DWORD hSound;
376 serge 37
SNDBUF hBuff;
165 serge 38
 
39
CTRL_INFO info;
40
 
41
FILEINFO   fileinfo;
42
 
43
int m_vol;
376 serge 44
int l_vol=-500;
45
int r_vol=-500;
46
int pan =0;
47
 
165 serge 48
DWORD status;
49
DWORD offset;
50
DWORD first_sync;
51
 
228 serge 52
unsigned char *testbuff;
53
unsigned char *outbuf;
54
unsigned char *inpbuf;
55
unsigned char *outPtr;
56
 
165 serge 57
int inpsize;
58
int outsize;
228 serge 59
int outremain;
60
int totalout;
61
int done;
376 serge 62
 
165 serge 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);
228 serge 85
   write_text(12,58,0x004000|FONT0, fname, strlen(fname));
86
   write_text(11,57,0x00FF20|FONT0, fname, strlen(fname));
165 serge 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;
376 serge 97
   x = 287.0f * (float)(rd.filepos-rd.strremain)/(float)fileinfo.size;
165 serge 98
   if(x==0) return;
99
   draw_bar(7,41,x,11,0xA0A0A0);
376 serge 100
   draw_bar(x+7,41,287-x,11,0x404040);
165 serge 101
};
102
 
103
void debug_out_str(char* str)
104
{
105
  while (*str != 0)
106
  {
107
    debug_out(*str);
108
    str++;
109
  }
110
}
111
 
228 serge 112
int main(int argc, char *argv[])      //int argc, char *argv[])
165 serge 113
{ DWORD fmt;
114
   char *thread_stack;
115
   DWORD r_bytes;
116
   int retval;
376 serge 117
   int err;
118
   int ver;
119
 
228 serge 120
   fname = argv[1];
121
   //debug_out_str(fname);
122
 
165 serge 123
   InitHeap(1024*1024);
228 serge 124
   if(get_fileinfo(fname, &fileinfo)==FILE_NOT_FOUND)
165 serge 125
      return 0;
126
 
376 serge 127
 
128
   if(err = InitSound(&ver))
129
   {
130
     debug_out_str("Sound service not installed\n\r");
165 serge 131
     return 0;
376 serge 132
   }
133
 
134
   if( ver != SOUND_VERSION)
135
   {
136
     debug_out_str("Sound service version mismatch\n\r");
137
     return 0;
138
   }
139
 
165 serge 140
   testbuff = UserAlloc(4096);
228 serge 141
   get_fileinfo(fname, &fileinfo);
165 serge 142
   offset = 0;
228 serge 143
   retval=read_file (fname,testbuff,0,2048,&r_bytes);
165 serge 144
   if (retval) return 0;
228 serge 145
 
146
   inpbuf = UserAlloc(0x10000);
147
   touch(inpbuf, 0x10000);
165 serge 148
 
228 serge 149
   create_reader(&rd, inpbuf, 0x10000);
150
   init_reader(&rd,fname);
151
 
165 serge 152
   fmt = test_wav((WAVEHEADER*)testbuff);
153
   if (fmt != 0)
154
   {
155
     snd_play = &play_wave;
228 serge 156
     set_reader(&rd, 44);
165 serge 157
     outbuf = UserAlloc(32*1024);
158
     touch(outbuf, 32768);
159
   }
160
   else
376 serge 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;
165 serge 172
   };
173
 
174
   status = ST_PLAY;
175
 
376 serge 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);
165 serge 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:
376 serge 196
           StopBuffer(hBuff);
165 serge 197
           status = ST_DONE;
198
           continue;
199
 
200
         case ST_EXIT:
376 serge 201
           StopBuffer(hBuff);
202
           DestroyBuffer(hBuff);
165 serge 203
           return 0;
204
      };
205
   };
206
   return 0;
207
};
208
 
209
void touch(char *buf, int size)
210
{ int i;
228 serge 211
   char a;
165 serge 212
    for ( i = 0;i < size; i+=4096)
228 serge 213
      a = buf[i];
165 serge 214
};
215
 
216
DWORD test_mp3(char *buf)
228 serge 217
{  unsigned long hdr;
165 serge 218
    WAVEHEADER whdr;
219
 
228 serge 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
 
165 serge 236
    whdr.riff_id = 0x46464952;
237
    whdr.riff_format = 0x45564157;
238
    whdr.wFormatTag = 0x01;
228 serge 239
    whdr.nSamplesPerSec = freqs[fr.sampling_frequency];
240
    whdr.nChannels = 2; //mpginfo.channels;
241
    whdr.wBitsPerSample = 16;
165 serge 242
 
243
    return test_wav(&whdr);
244
};
228 serge 245
 
165 serge 246
 
247
void play_mp3()
228 serge 248
{  char *outPtr;
165 serge 249
    int totalout;
228 serge 250
    int outcount;
165 serge 251
 
286 serge 252
 //   memset(&fr,0,sizeof(fr));
253
    fr.down_sample_sblimit = 32;
254
    fr.single = -1;
255
    reset_mpg();
228 serge 256
 
165 serge 257
    outPtr = outbuf;
258
    totalout=0;
228 serge 259
    done = 0;
286 serge 260
    outremain=0x40000;
228 serge 261
 
286 serge 262
    memset(outbuf,0,0x40000);
263
    set_reader(&rd, 0);    //;first_sync);
165 serge 264
 
265
    while(1)
266
    { if(status!=ST_PLAY)
267
             break;
268
 
228 serge 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)
376 serge 284
    { if(totalout < 4096)
285
      {  memset(outPtr,0,4096-totalout);
286
                totalout = 4096;
165 serge 287
      };
376 serge 288
    }
289
    else
290
      if(totalout < 8192)
291
        continue;
228 serge 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;
376 serge 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;
228 serge 316
    };
376 serge 317
    if(done)
318
      break;
319
 
228 serge 320
    memmove(outbuf,outPtr, totalout);
321
    outPtr = outbuf+totalout;
322
   }
323
 
165 serge 324
    if(status != ST_EXIT)
325
    status =  ST_STOP;
326
};
327
 
328
void play_wave()
376 serge 329
{  int retval;
165 serge 330
 
286 serge 331
   set_reader(&rd,44);
165 serge 332
   retval = 0;
333
   while(1)
334
   {
228 serge 335
      if(status!=ST_PLAY)
336
        break;
165 serge 337
 
228 serge 338
      if( !stream_read_raw(&rd,outbuf,32768))
339
      {  done = 1;
340
          break;
341
      };
376 serge 342
      WaveOut(hBuff,outbuf,32768);
165 serge 343
   };
344
 
345
   if(status != ST_EXIT)
346
    status =  ST_STOP;
347
};
348
 
349
void snd_stop()
350
{
376 serge 351
  StopBuffer(hBuff);
165 serge 352
};
353
 
354
void thread_proc()
228 serge 355
{  int evnt;
165 serge 356
   int pos;
357
   int key;
358
 
376 serge 359
  _asm
360
  {
361
    mov eax, 66
362
    mov ebx, 1
363
    mov ecx, 1
364
    int 0x40
365
  };
165 serge 366
 
367
  draw_window();
368
 
369
  while(1)
370
  {  if(status==ST_PLAY)
376 serge 371
     {  draw_progress_bar();
372
        evnt = wait_for_event(80);
373
     }
165 serge 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:
376 serge 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
        };
165 serge 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:
376 serge 447
            if(l_vol > -10000)
448
            {
449
              l_vol-=100;
450
              r_vol-=100;
451
              SetVolume(hBuff,l_vol,r_vol);
452
            };
453
            break;
165 serge 454
 
455
           case 0x15:
376 serge 456
            if(l_vol < 0)
457
            { l_vol+=100;
458
              r_vol+=100;
459
              SetVolume(hBuff,l_vol,r_vol);
460
            };
461
            break;
165 serge 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;
228 serge 468
            set_reader(&rd, offset);
165 serge 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()
376 serge 497
{ int retval;
165 serge 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
 
228 serge 522
///*********
523
void *memmove ( void * dst, void * src, int count)
524
{ void *ret;
525
  ret = dst;
165 serge 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
    }
228 serge 545
    return ret;
165 serge 546
};
228 serge 547
//**********/
165 serge 548
 
228 serge 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
}
165 serge 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