Subversion Repositories Kolibri OS

Rev

Rev 577 | Go to most recent revision | Details | 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
typedef struct
23
{
24
  int sender;
25
  int size;
26
  int code;
27
  char data[1];
28
} IPC;
29
 
30
int ipc_client = 0;
31
 
32
#define MP3_ERROR_OUT_OF_BUFFER  5
33
int m_last_error;
34
 
35
void _stdcall thread_proc(void *param);
36
void _stdcall create_thread(void *proc, void *param, int stack_size);
37
void _stdcall init_ipc(void);
38
void _stdcall send_ipc(int dst, DWORD code);
39
IPC * _stdcall recieve_ipc(void);
40
 
41
void touch(char *buf, int size);
42
int mp3FindSync(byte* buf, int size, int* sync);
43
int stream_read_raw(struct reader *rd,unsigned char *buf, int size);
44
 
45
char *fname;
46
 
47
struct reader rd;
48
struct frame fr;
49
 
50
void draw_window();
51
void draw_progress_bar();
52
void do_ipc();
53
void exit();
54
 
55
 
56
DWORD hDrv;
57
DWORD hSound;
58
SNDBUF hBuff;
59
volatile int snd_init=0;
60
 
61
CTRL_INFO info;
62
 
63
FILEINFO   fileinfo;
64
 
65
int m_vol;
66
int l_vol=-700;     //-7db
67
int r_vol=-700;
68
int pan =0;
69
 
70
DWORD status;
71
DWORD offset;
72
DWORD first_sync;
73
 
74
unsigned char *testbuff;
75
unsigned char *outbuf;
76
unsigned char *inpbuf;
77
unsigned char *outPtr;
78
 
79
int inpsize;
80
int outsize;
81
int outremain;
82
int totalout;
83
int done;
84
char path[1024];
85
char header[] = "AC97 MP3 player";
86
char buttons_text[]=" Play    Stop     <<      >>     Vol-    Vol+";
87
 
88
void (*snd_play)();
89
 
90
 
91
int main(int argc, char *argv[])      //int argc, char *argv[])
92
{
93
   int err;
94
   int ver;
95
   int evnt;
96
   int key;
97
   int pos;
98
   int msg;
99
   int cnt;
100
   IPC *incom;
101
 
102
   _asm
103
   {
104
     mov eax, 40
105
     mov ebx, 0x47  ;recieve ipc
106
     int 0x40
107
     mov eax, 66
108
     mov ebx, 1
109
     mov ecx, 1
110
     int 0x40
111
   };
112
   init_ipc();
113
   InitHeap(0);
114
 
115
   if(err = InitSound(&ver))
116
   { debug_out_str("Sound service not installed\n\r");
117
     return 0;
118
   }
119
 
120
   if( (SOUND_VERSION>(ver&0xFFFF)) ||
121
       (SOUND_VERSION<(ver >> 16)))
122
   { debug_out_str("Sound service version mismatch\n\r");
123
     return 0;
124
   }
125
 
126
   make_decode_tables(32767);
127
   init_layer2();
128
   init_layer3(32);
129
   fr.single = -1;
130
 
131
   outremain = 0x40000 ;
132
   if( !(outbuf=UserAlloc(outremain)))
133
     return 0;
134
 
135
   touch(outbuf, outremain);
136
 
137
   if ( !(testbuff=UserAlloc(4096)))
138
     return 0;
139
 
140
   if (! (inpbuf=UserAlloc(0x10000)))
141
     return 0;
142
 
143
   touch(inpbuf, 0x10000);
144
   create_reader(&rd, inpbuf, 0x10000);
145
 
146
   fname = argv[1];
147
 
148
   if(get_fileinfo(fname, &fileinfo)==FILE_NOT_FOUND)
149
   {
150
     _asm
151
     {
152
       mov eax, 23
153
       mov ebx, 100
154
       int 0x40
155
       mov [msg], eax
156
     }
157
     if (msg != 7)
158
     {
159
       debug_out_str("\n\rfile not found\n\r");
160
       return 0;
161
     };
162
     incom = recieve_ipc();
163
     if(incom->code != 'CNCT')
164
     {
165
       debug_out_str("\n\rinvalid ipc code\n\r");
166
       status = ST_EXIT;
167
       return 0;
168
     };
169
     ipc_client = incom->sender;
170
     send_ipc(ipc_client,'CNCT');
171
   };
172
 
173
 
174
   snd_init=0;
175
   create_thread(thread_proc, 0, 4096);
176
 
177
   for(snd_init=0,cnt=100; (snd_init==0)&&(cnt!=0); cnt--)
178
     delay(10);
179
 
180
   if (!snd_init)
181
     return 0;
182
 
183
   draw_window();
184
 
185
   while(1)
186
  {  if(status==ST_PLAY)
187
     {  draw_progress_bar();
188
        evnt = wait_for_event(80);
189
     }
190
     else
191
        evnt = wait_for_event_infinite();
192
 
193
    switch(evnt)
194
    {
195
      case EV_REDRAW:
196
        draw_window();
197
        break;
198
 
199
      case EV_KEY:
200
        if(!get_key(&key))
201
        {
202
 
203
          switch(key)
204
          {  case 0xE0:
205
             case 0xE1:
206
               break;
207
             default:
208
               switch (key)
209
               {
210
                 case 0x01:  //Esc
211
                   status = ST_EXIT;
212
                   exit();
213
                   break;
214
 
215
                 case 0x47:  //Home
216
                   if(l_vol < 0)
217
                   { l_vol+=100;
218
                     r_vol+=100;
219
                     SetVolume(hBuff,l_vol,r_vol);
220
                   };
221
                   break;
222
                 case 0x4F:  //End
223
                   if(l_vol > -10000)
224
                   { l_vol-=100;
225
                     r_vol-=100;
226
                     SetVolume(hBuff,l_vol,r_vol);
227
                   };
228
                   break;
229
                 case 0x53:
230
                   if(pan > -10000)
231
                   { pan -=100;
232
                     SetPan(hBuff,pan);
233
                   };
234
                   break;
235
                 case 0x51:
236
                   if(pan < 10000)
237
                   { pan +=100;
238
                     SetPan(hBuff,pan);
239
                   };
240
                   break;
241
               }
242
          };
243
        };
244
        break;
245
 
246
      case EV_BUTTON:
247
        switch(get_button_id())
248
        {  case 1:
249
             status = ST_EXIT;
250
             exit();
251
             break;
252
 
253
           case 0x10:
254
             status = ST_PLAY;
255
             continue;
256
 
257
           case 0x11:
258
             status = ST_STOP;
259
             break;
260
//           case 0x12:
261
//           case 0x13:
262
           case 0x14:
263
            if(l_vol > -10000)
264
            {
265
              l_vol-=100;
266
              r_vol-=100;
267
              SetVolume(hBuff,l_vol,r_vol);
268
            };
269
            break;
270
 
271
           case 0x15:
272
            if(l_vol < 0)
273
            { l_vol+=100;
274
              r_vol+=100;
275
              SetVolume(hBuff,l_vol,r_vol);
276
            };
277
            break;
278
 
279
           case 0x30:
280
            if(status==ST_DONE)
281
              break;
282
            pos = (GetMousePos(REL_WINDOW)>>16)-7;
283
            offset = ((fileinfo.size-44)/286*pos+44)&0xFFFFFFFC;
284
            set_reader(&rd, offset);
285
            draw_progress_bar();
286
            break;
287
        };
288
        break;
289
      case EV_IPC:
290
        do_ipc();
291
        break;
292
    };
293
  };
294
 
295
 
296
 
297
 
298
   return 0;
299
};
300
 
301
 
302
void draw_window()
303
{
304
   BeginDraw();
305
 
306
   DrawWindow(100,100,299,72,0x404040,3,0,0,0);
307
 
308
   make_button(7,24,45,13, 0x10|BT_NORMAL,0x808080);
309
   make_button(56,24,45,13, 0x11|BT_NORMAL,0x808080);
310
   make_button(104,24,45,13, 0x12|BT_NORMAL,0x808080);
311
   make_button(152,24,45,13, 0x13|BT_NORMAL,0x808080);
312
   make_button(200,24,45,13, 0x14|BT_NORMAL,0x808080);
313
   make_button(248,24,45,13, 0x15|BT_NORMAL,0x808080);
314
 
315
   make_button(7,41,286,11, 0x30|BT_HIDE|BT_NOFRAME,0x404040);
316
   draw_bar(7,41,286,11,0x404040);
317
 
318
   draw_bar(7,55,286,11,0x404040);
319
   write_text(12,58,0x004000|FONT0, fname, strlen(fname));
320
   write_text(11,57,0x00FF20|FONT0, fname, strlen(fname));
321
 
322
   write_text(8,8,0xFFFFFF|FONT0, header, strlen(header));
323
   write_text(12,28,0x404040|FONT0,buttons_text,strlen(buttons_text));
324
   write_text(11,27,0xA0FFA0|FONT0,buttons_text,strlen(buttons_text));
325
 
326
   EndDraw();
327
};
328
 
329
void draw_progress_bar()
330
{  DWORD x;
331
   x = 287.0f * (float)(rd.filepos-rd.strremain)/(float)fileinfo.size;
332
   if(x==0) return;
333
   draw_bar(7,41,x,11,0xA0A0A0);
334
   draw_bar(x+7,41,287-x,11,0x404040);
335
};
336
 
337
void debug_out_str(char* str)
338
{
339
  while (*str != 0)
340
  {
341
    debug_out(*str);
342
    str++;
343
  }
344
}
345
 
346
 
347
void touch(char *buf, int size)
348
{ int i;
349
   char a;
350
    for ( i = 0;i < size; i+=4096)
351
      a = buf[i];
352
};
353
 
354
DWORD test_mp3(char *buf)
355
{  unsigned long hdr;
356
    WAVEHEADER whdr;
357
 
358
    while (1)
359
    {  if(rd.filepos > 102400)
360
          return 0;
361
        if(!rd.head_read(&rd,&hdr))
362
           return 0;
363
        if(!decode_header(&fr,hdr))
364
        {
365
           if((hdr & 0xffffff00) == 0x49443300)
366
 	       {
367
 		     int id3length = 0;
368
		     id3length = parse_new_id3(&rd, hdr);
369
		     continue;
370
	       };
371
 
372
           rd.strpos-=3;
373
           rd.stream-=3;
374
           rd.strremain+=3;
375
           continue;
376
        };
377
        break;
378
    };
379
 
380
    first_sync = rd.filepos-rd.strremain-4;
381
 
382
    whdr.riff_id = 0x46464952;
383
    whdr.riff_format = 0x45564157;
384
    whdr.wFormatTag = 0x01;
385
    whdr.nSamplesPerSec = freqs[fr.sampling_frequency];
386
    whdr.nChannels = 2; //mpginfo.channels;
387
    whdr.wBitsPerSample = 16;
388
 
389
    return test_wav(&whdr);
390
};
391
 
392
 
393
void play_mp3()
394
{  char *outPtr;
395
    int totalout;
396
    int outcount;
397
 
398
    fr.down_sample_sblimit = 32;
399
    fr.single = -1;
400
    reset_mpg();
401
 
402
    outPtr = outbuf;
403
    totalout=0;
404
    done = 0;
405
    outremain=0x40000;
406
 
407
    memset(outbuf,0,0x40000);
408
    set_reader(&rd, 0);    //;first_sync);
409
 
410
    while(1)
411
    { if(status!=ST_PLAY)
412
             break;
413
 
414
      for(;;)
415
      {   outcount = 0;
416
          if( !read_frame(&rd, &fr))
417
          {  done = 1;
418
              break;
419
          };
420
          fr.do_layer(&fr, outPtr,&outcount);
421
          outPtr+= outcount;
422
          totalout+=outcount;
423
          outremain-=outcount;
424
          if(outremain < outcount*2)
425
            break;
426
      };
427
 
428
      if(done)
429
      { if(totalout < 4096)
430
        {  memset(outPtr,0,4096-totalout);
431
           totalout = 4096;
432
        };
433
      }
434
      else if(totalout < 8192) continue;
435
 
436
      outPtr = outbuf;
437
      while (totalout >= 4096)
438
      {
439
        WaveOut(hBuff,outPtr,4096);
440
        if(status!=ST_PLAY)
441
        { StopBuffer(hBuff);
442
          return;
443
        };
444
        totalout-=4096;
445
        outPtr+=4096;
446
        outremain+=4096;
447
      };
448
 
449
      if(done)
450
      { status = ST_STOP;
451
 
452
        if( ipc_client)
453
          send_ipc(ipc_client,'DONE');
454
        return;
455
      }
456
      memmove(outbuf,outPtr, totalout);
457
      outPtr = outbuf+totalout;
458
    };
459
};
460
 
461
 
462
int play_track(char *path)
463
{
464
   DWORD fmt;
465
   DWORD r_bytes;
466
   int retval;
467
   int err;
468
//   int err;
469
 
470
   retval = ST_DONE;
471
 
472
   get_fileinfo(path, &fileinfo);
473
   offset = 0;
474
   err=read_file (path,testbuff,0,2048,&r_bytes);
475
   if (err)
476
     return ST_DONE;
477
 
478
   init_reader(&rd,path);
479
 
480
   fmt = test_wav((WAVEHEADER*)testbuff);
481
   if (fmt != 0)
482
   {
483
     snd_play = &play_wave;
484
     set_reader(&rd, 44);
485
     retval = ST_PLAY;
486
   }
487
   else
488
   { fmt = test_mp3(testbuff);
489
     if(fmt ==0)
490
       return ST_DONE;
491
 
492
     snd_play = &play_mp3;
493
     outremain = 0x40000;
494
     retval = ST_PLAY;
495
   };
496
 
497
   SetFormat(hBuff, fmt);
498
   return retval;
499
};
500
 
501
 
502
void play_wave()
503
{  int retval;
504
 
505
   set_reader(&rd,44);
506
   retval = 0;
507
   while(1)
508
   {
509
      if(status!=ST_PLAY)
510
        break;
511
 
512
      if( !stream_read_raw(&rd,outbuf,32768))
513
      {  done = 1;
514
          break;
515
      };
516
      WaveOut(hBuff,outbuf,32768);
517
   };
518
 
519
   if(status != ST_EXIT)
520
    status =  ST_STOP;
521
};
522
 
523
void snd_stop()
524
{
525
  StopBuffer(hBuff);
526
};
527
 
528
void do_ipc()
529
{
530
  IPC *incom;
531
  incom = recieve_ipc();
532
  switch(incom->code)
533
  {
534
    case 'PLAY':
535
      fname = incom->data;
536
      status = ST_TRACK;
537
      return;
538
 
539
    case 'STOP':
540
      status = ST_STOP;
541
      return;
542
 
543
    case 'EXIT':
544
      status = ST_EXIT;
545
      exit();
546
  };
547
};
548
 
549
void _stdcall thread_proc(void *param)
550
{
551
   int err;
552
 
553
   if (err = CreateBuffer(PCM_ALL|PCM_OUT,0, &hBuff))
554
   {
555
     debug_out_str("create buffer return error\n\r");
556
     exit();
557
   };
558
 
559
   SetVolume(hBuff,l_vol,r_vol);
560
   GetVolume(hBuff,&l_vol,&r_vol);
561
//   debug_out_hex(l_vol);
562
//   debug_out_str("\n\r");
563
//   debug_out_hex(r_vol);
564
//   debug_out_str("\n\r");
565
 
566
   if(fname[0] !='/0')
567
     status = play_track(fname);
568
 
569
   debug_out_str("\n\rPlay file ");
570
   debug_out_str(fname);
571
   debug_out_str("\n\r");
572
 
573
   snd_init = 1;
574
 
575
   while(1)
576
   {  delay(10);
577
      switch(status)
578
      {
579
         case ST_TRACK:
580
           strcpy(path, fname);
581
           status = play_track(fname);
582
           if( ipc_client & (status == ST_DONE))
583
           { send_ipc(ipc_client,'DONE');
584
             continue;
585
           };
586
 
587
         case ST_PLAY:
588
           snd_play();
589
           continue;
590
 
591
         case ST_STOP:
592
           StopBuffer(hBuff);
593
           status = ST_DONE;
594
           continue;
595
 
596
         case ST_EXIT:
597
           StopBuffer(hBuff);
598
           DestroyBuffer(hBuff);
599
           if (ipc_client)
600
             send_ipc(ipc_client,'EXIT');
601
           return;
602
      };
603
   };
604
 
605
 
606
};
607
 
608
void delay (int val)
609
{
610
  _asm
611
  {   mov   eax,5
612
      mov   ebx, [val]
613
      int   0x40
614
  };
615
}
616
 
617
int wait_for_event(int time)
618
{ int retval;
619
  _asm
620
 {  mov  eax,23
621
     mov  ebx,[time]
622
     int  0x40
623
     mov [retval], eax
624
 };
625
 return retval;
626
};
627
 
628
int wait_for_event_infinite()
629
{ int retval;
630
  _asm
631
  {  mov  eax,10
632
      int  0x40
633
      mov [retval], eax
634
  };
635
  return retval;
636
};
637
 
638
void BeginDraw()
639
{_asm
640
 { mov   eax,12
641
    mov   ebx, 1
642
    int   0x40
643
  };
644
};
645
 
646
void EndDraw()
647
{ _asm
648
 { mov   eax,12
649
    mov   ebx, 2
650
    int   0x40
651
  };
652
};
653
 
654
///*********
655
void *memmove ( void * dst, void * src, int count)
656
{ void *ret;
657
  ret = dst;
658
 
659
  if (dst <= src || (char *)dst >= ((char *)src + count))
660
  {
661
      while (count--)
662
      { *(char *)dst = *(char *)src;
663
          dst = (char *)dst + 1;
664
          src = (char *)src + 1;
665
      }
666
   }
667
   else
668
    {
669
        dst = (char *)dst + count - 1;
670
        src = (char *)src + count - 1;
671
         while (count--)
672
          {  *(char *)dst = *(char *)src;
673
              dst = (char *)dst - 1;
674
              src = (char *)src - 1;
675
          }
676
    }
677
    return ret;
678
};
679
//**********/
680
 
681
void * __cdecl mem_cpy(void * dst,const void * src,size_t count)
682
{    void * ret = dst;
683
      while (count--)
684
      {  *(char *)dst = *(char *)src;
685
          dst = (char *)dst + 1;
686
          src = (char *)src + 1;
687
      };
688
      return(ret);
689
}
690
 
691
//   debug_out_str(formats[fmt]);
692
//   debug_out_str("\x0D\x0A\x00");
693
 
694
//   debug_out_str("pci cmd: ");
695
//   debug_out_hex(info.pci_cmd);
696
//   debug_out_str("\x0D\x0A\x00");
697
 
698
//   debug_out_str("irq line: ");
699
//   debug_out_hex(info.irq);
700
//   debug_out_str("\x0D\x0A\x00");
701
 
702
//   debug_out_str("global control: ");
703
//   debug_out_hex(info.glob_cntrl);
704
//   debug_out_str("\x0D\x0A\x00");
705
 
706
//   debug_out_str("global status:  ");
707
//   debug_out_hex(info.glob_sta);
708
//   debug_out_str("\x0D\x0A\x00");
709
 
710
 
711
  // call _print_volume
712
 
713
//   debug_out_hex(whdr.nChannels);
714
//   debug_out_str("\x0D\x0A\x00");
715
//   debug_out_hex(whdr.nSamplesPerSec);
716
//   debug_out_str("\x0D\x0A\x00");
717
 
718
//   debug_out_hex(fmt);
719
//   debug_out_str("\x0D\x0A\x00");
720