Subversion Repositories Kolibri OS

Rev

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