Subversion Repositories Kolibri OS

Rev

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