Subversion Repositories Kolibri OS

Rev

Rev 3495 | Rev 5485 | 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
 
1842 clevermous 24
#define DOCKABLE_WINDOW
576 serge 25
#define MP3_ERROR_OUT_OF_BUFFER  5
26
int m_last_error;
27
 
28
void _stdcall thread_proc(void *param);
1842 clevermous 29
int _stdcall create_thread(void *proc, void *param, int stack_size);
576 serge 30
 
1842 clevermous 31
#ifdef DOCKABLE_WINDOW
32
void GetThreadInfo (char *info, int slot); //Asper+
33
#endif
34
 
576 serge 35
void touch(char *buf, int size);
36
int mp3FindSync(byte* buf, int size, int* sync);
646 serge 37
int stream_read_raw(struct reader *rd,unsigned char *buf, int size);
576 serge 38
 
646 serge 39
int __cdecl _stricmp (const char * dst, const char * src);
40
char *__cdecl strrchr (const char * string,int ch);
1842 clevermous 41
int _strncmp(char *src, char *dst, DWORD n); //Asper+
42
int _strncpy (char *dst, char *src, int n); //Asper+
43
void uint2str(unsigned int value, char *string); //Asper+
646 serge 44
 
576 serge 45
struct reader rd;
46
struct frame fr;
47
 
48
DWORD hDrv;
49
DWORD hSound;
50
SNDBUF hBuff;
51
 
52
CTRL_INFO info;
53
 
54
FILEINFO   fileinfo;
1842 clevermous 55
const char filename[256];
646 serge 56
const char *fileext;
1842 clevermous 57
char full_filename[4096];
576 serge 58
 
59
int m_vol;
60
int l_vol=-700;     //-7db
61
int r_vol=-700;
62
int pan =0;
63
 
64
DWORD status;
65
DWORD first_sync;
1842 clevermous 66
DWORD PLStatus=0; //Asper+
3495 yogev_ezra 67
byte replay=0;
68
byte hidden=0;
576 serge 69
 
1842 clevermous 70
#ifdef DOCKABLE_WINDOW
71
byte thread_info[1024]; //Asper+
72
#endif
73
 
74
int tid, pl_tid;
75
const DWORD main_wh=92, pl_ww=300, pl_wh=382; //Asper+
76
DWORD pl_wx=100, pl_wy=101+92;  //Asper+
77
//DWORD main_wc=0x404040, main_bc=0x808080;  //Asper+ ac97snd Classic style
78
//DWORD main_wc=0x002040, main_bc=0x008080, main_ic=0x002040, selected_ic=0x1010F0;  //Asper+
79
DWORD main_wc=0x101030, main_bc=0x008080, main_ic=0x000000, selected_ic=0x1010F0;  //Asper+
80
 
576 serge 81
unsigned char *testbuff;
82
unsigned char *outbuf;
83
unsigned char *inpbuf;
84
unsigned char *outPtr;
85
 
86
int inpsize;
87
int outsize;
88
int outremain;
89
int totalout;
90
int done;
646 serge 91
 
576 serge 92
char header[] = "AC97 MP3 player";
1842 clevermous 93
char header_PL[] = "PLAYLIST";
646 serge 94
char buttons_xm[]  = " Play    Stop                    Vol-    Vol+"; /* uFMOD integration */
95
char buttons_wav[] = " Play    Stop     <<      >>     Vol-    Vol+"; /* uFMOD integration */
1842 clevermous 96
char button_PL[] = "PL"; //Asper+
3495 yogev_ezra 97
char button_R[] = "R"; //Asper+
646 serge 98
char *buttons_text = buttons_wav;                                     /* uFMOD integration */
576 serge 99
 
646 serge 100
void play_xm();                                                       /* uFMOD integration */
576 serge 101
void (*snd_play)();
102
 
1842 clevermous 103
 
104
//Asper_____________________Play List code start_____________________________
105
#define PLI_BUTTON_HEIGHT    13
106
#define PL_MAX_SHOWN_ITEMS   (pl_wh-PLI_BUTTON_HEIGHT-40)/PLI_BUTTON_HEIGHT
107
#define MAX_TEXT_WIDTH       46
108
 
109
int currSelected, currActive, currFirstShowed;
110
unsigned char *pl_buff;
111
char pl_path[4096];
112
int pl_items_number;
113
 
114
int ShowPLContent(char *filebuffer);
115
int GetFileNameFromPL(const char *fbuff, int index, char *name);
116
void Win2Dos (char *st, int len);
117
 
118
void HidePLWindow()
119
{
120
   BeginDraw();
121
   ResizeReplaceWindow(pl_wx,pl_wy,0,0);
122
   EndDraw();
123
}
124
 
125
void ShowPLWindow()
126
{
127
   unsigned int i;
128
 
129
   BeginDraw();
130
   DrawWindow(pl_wx,pl_wy,pl_ww,pl_wh,main_ic,4,0,0,0);
131
 
132
   for (i=0; i
133
	   make_button(7,24+i*(PLI_BUTTON_HEIGHT+1),285,PLI_BUTTON_HEIGHT, (0x10+i)|BT_NORMAL|BT_NOFRAME, main_ic);
134
 
135
   write_text(8,8,FONT0, header_PL, sizeof(header_PL)-1);
136
   ShowPLContent(pl_buff);
137
   EndDraw();
138
}
139
 
140
int LoadTrack(int i)
141
{
142
	if (GetFileNameFromPL(pl_buff, i, filename))
143
	{
144
		strcpy (full_filename, pl_path);
145
		strcat (full_filename, filename);
146
		return 1;
147
	}
148
	return 0;
149
}
150
 
151
void _stdcall pl_thread_proc(void *param)
152
{  int evnt;
153
   int key, button;
154
   DWORD tmp_x, tmp_y, i; //Asper+
155
   char ipc_buff[16]="";
156
 
157
   set_event_mask(0x47); //Asper + IPC event
158
   ipc_init(ipc_buff, 16);
159
 
160
  _asm
161
  {
162
    mov eax, 66
163
    mov ebx, 1
164
    mov ecx, 1
165
    int 0x40
166
  };
167
 
168
  ShowPLWindow();
169
 
170
  while(1)
171
  {
172
	if (PLStatus&0xF0)
173
    {
174
		switch(PLStatus)
175
		{
176
			case 0x11:
177
				HidePLWindow();
178
			break;
179
			case 0x12:
180
				ResizeReplaceWindow(pl_wx,pl_wy,pl_ww,pl_wh);
181
			break;
182
		}
183
		PLStatus&=0x0F;
184
	}
185
	switch (status)
186
	{
187
		case ST_TRACK:
188
			break;
189
		case ST_EXIT:
190
			PLStatus=0x00;
191
			exit();
192
	}
193
 
194
#ifdef DOCKABLE_WINDOW
195
	tmp_x = (DWORD)thread_info[35]*0x100+(DWORD)thread_info[34];
196
	tmp_y = (DWORD)thread_info[38]+main_wh+1;
197
	if (pl_wx!= tmp_x || pl_wy!=tmp_y)
198
	{
199
		pl_wx=tmp_x;
200
		pl_wy=tmp_y;
201
		ResizeReplaceWindow(pl_wx,pl_wy,-1,-1);
202
	}
203
#endif
204
 
205
    evnt = wait_for_event(20);
206
 
207
    switch(evnt)
208
    {
209
      case EV_REDRAW:
210
			  ShowPLWindow();
211
        break;
212
 
213
      case EV_KEY:
214
        if(!get_key(&key))
215
        {
216
 
217
          switch(key)
218
          {  case 0xE0:
219
             case 0xE1:
220
               break;
221
             default:
222
               switch (key)
223
               {
224
                 case 0x01:  //Esc
225
					 PLStatus=0x00;
226
					 exit();
227
					 break;
228
 
3495 yogev_ezra 229
				 case 0x19: //P - playlist
230
				   switch (PLStatus)
231
				   {    case 0x00: //PL not started.
232
							pl_tid=create_thread(pl_thread_proc, 0, 4096);
233
							PLStatus=0x12;
234
						break;
235
						case 0x01: //PL started, but hidden.
236
							PLStatus=0x12;
237
						break;
238
						case 0x02: //PL started and showed.
239
							PLStatus=0x11;
240
						break;
241
				   }
242
				   break;
243
 
1842 clevermous 244
				 case 0x1C:  //Enter
245
					 currActive=currFirstShowed+currSelected-1;
246
					 status = ST_TRACK;
247
					 break;
3495 yogev_ezra 248
 
249
				 case 0x2C: //Z - previous
250
				   currActive-=2;
251
				   status = ST_TRACK;
252
				   break;
253
 
254
				 case 0x2D: //X - play
255
				   status = ST_PLAY;
256
				   break;
257
 
258
				 case 0x2E: //C - pause
259
				   break;
260
 
261
				 case 0x2F: //V - stop
262
                   status = ST_STOP;
263
				   break;
264
 
265
				 case 0x30: //B - next
266
				   status = ST_TRACK;
267
				   break;
268
 
1842 clevermous 269
                 case 0x47:  //Home
270
					 if(l_vol < 0)
271
					 { l_vol+=100;
272
					   r_vol+=100;
273
					   SetVolume(hBuff,l_vol,r_vol);
274
					 };
275
				   break;
276
                 case 0x48:  //Up
277
					 if (currSelected==0)
278
					 {
279
						 if (currFirstShowed>0)
280
							 currFirstShowed--;
3495 yogev_ezra 281
						 else break;
1842 clevermous 282
						 ShowPLContent(pl_buff);
283
						 break;
284
					 }
285
					 currSelected--;
286
					 ShowPLContent(pl_buff);
287
					 break;
288
                 case 0x50:  //Down
289
					 if (currSelected+currFirstShowed > pl_items_number-2) break;
290
					 if (currSelected==PL_MAX_SHOWN_ITEMS-1)
291
					 {
292
						 //if (currFirstShowed
293
							 currFirstShowed++;
294
						 ShowPLContent(pl_buff);
295
						 break;
296
					 }
297
					 //if (currSelected
298
					 currSelected++;
299
					 ShowPLContent(pl_buff);
300
					 break;
301
                 case 0x4F:  //End
302
					 if(l_vol > -10000)
303
					 { l_vol-=100;
304
					   r_vol-=100;
305
					   SetVolume(hBuff,l_vol,r_vol);
306
					 };
307
					 break;
308
                 case 0x53:
309
					 if(pan > -10000)
310
					 { pan -=100;
311
					   SetPan(hBuff,pan);
312
					 };
313
					 break;
314
                 case 0x51:
315
					 if(pan < 10000)
316
					 { pan +=100;
317
					   SetPan(hBuff,pan);
318
					 };
319
					 break;
320
			   }
321
		  };
322
		};
323
		break;
324
 
325
      case EV_BUTTON:
326
		  button=get_button_id();
327
		  if (button==1)
328
		  {
329
			  PLStatus=0x00;
330
			  exit();
331
		  }
3495 yogev_ezra 332
		  currActive=currFirstShowed+button-0x10-1;
333
		  status = ST_TRACK;
1842 clevermous 334
		  break;
335
	  case EV_IPC:
336
  		  *ipc_buff='\0';
337
		  ShowPLContent(pl_buff);
338
		  break;
339
 
340
	}
341
  }
342
}
343
 
344
void Win2Dos (char *st, int len)
345
{
346
	int i;
347
	unsigned char ch;
348
 
349
	for (i=0; i
350
	{
351
		ch = st[i];
352
		if (ch>=192)
353
		{
354
			if (ch>=240) ch-=16;
355
			else ch-=64;
356
		}
357
		else
358
		{
359
			if (ch==168) ch = 240;
360
			if (ch==184) ch = 241;
361
			if (ch==185) ch = 252;
362
			if ((ch==147) || (ch==148) || (ch==171) || (ch==187)) ch = 34;
363
			if ((ch==150) || (ch==151)) ch = 45;
364
		}
365
		st[i]=ch;
366
	}
367
}
368
 
369
int GetFileNameFromPL(const char *plbuff, int index, char *name)
370
{
371
	int count=0,i=0,j=0;
372
	char ch;
373
 
374
	do{
375
		ch=plbuff[i];
376
		if (ch!='#' && i && plbuff[i-1]=='\n')
377
			count++;
3495 yogev_ezra 378
		if (count-1==index)
1842 clevermous 379
		{
3495 yogev_ezra 380
			if (j>MAX_TEXT_WIDTH || ch=='\r' || ch=='\n')
1842 clevermous 381
			{
3495 yogev_ezra 382
				name[j]='\0';
1842 clevermous 383
				break;
384
			}
385
			if (ch=='\\') ch='/';
386
			name[j++]=ch;
387
		}
388
		else if (count-1>index) break;
389
		i++;
390
	}while (ch);
391
	if (!ch) return 0;
392
	return j;
393
}
394
 
395
int CountFileNamesInPL(const char *plbuff)
396
{
397
	int count=0,i=0;
398
	char ch;
399
 
400
	do{
401
		ch=plbuff[i];
402
		if (ch!='#' && i && plbuff[i-1]=='\n')
403
			count++;
404
		i++;
405
	}while (ch);
406
	if (count) count--;
407
	return count;
408
}
409
 
410
int ShowPLContent(char *filebuffer)
411
{
412
	char st[MAX_TEXT_WIDTH+10]="", tmp[MAX_TEXT_WIDTH+1]="";
413
	unsigned int len=8,i;
414
	DWORD text_color;
415
 
416
	draw_bar(7,24,285,PLI_BUTTON_HEIGHT*(PL_MAX_SHOWN_ITEMS+2), main_ic);
417
	draw_bar(7,24+currSelected*(PLI_BUTTON_HEIGHT+1),285,PLI_BUTTON_HEIGHT, selected_ic);
418
	for (i=0; i
419
	{
420
		text_color = (currFirstShowed+i==currActive?0xFFFFFF|FONT0:0x00FF20|FONT0);
421
		if (!GetFileNameFromPL(filebuffer, i+currFirstShowed, tmp)) break;
422
		uint2str(currFirstShowed+i+1, st);
423
		strcat(st, ". ");
424
		strcat(st, tmp);
425
		len = strlen(st);
426
		if (len > MAX_TEXT_WIDTH)
427
			len = MAX_TEXT_WIDTH;
428
		write_text(11,i*(PLI_BUTTON_HEIGHT+1)+27,text_color, st, len);
429
	}
430
	return 1;
431
}
432
//Asper_____________________Play List code end_____________________________
3495 yogev_ezra 433
void redraw_R_button() //Asper +
434
{
435
	DWORD rc = 0xA0FFA0; //R button text color
436
	if (!replay) rc = 0x404040;
437
	write_text(14,74,rc|FONT0,button_R,sizeof(button_R)-1);
438
}
1842 clevermous 439
 
440
void update_dinamic_content() //Asper +
441
{
3495 yogev_ezra 442
	int len = strlen(filename);
443
	if (len > 47) len = 47;
1842 clevermous 444
	draw_bar(7,41,286,11,main_wc);
445
	draw_bar(7,55,286,11,main_wc);
3495 yogev_ezra 446
	write_text(11,57,0x00FF20|FONT0, filename, len);
1842 clevermous 447
}
448
 
576 serge 449
void draw_window()
450
{
451
   BeginDraw();
3495 yogev_ezra 452
   if (!hidden)
453
   {
454
      DrawWindow(100,100,299,main_wh,main_wc,4,0,0,0); //Asper+
576 serge 455
 
3495 yogev_ezra 456
      make_button(7,24,45,13, 0x10|BT_NORMAL,main_bc);
457
      make_button(56,24,45,13, 0x11|BT_NORMAL,main_bc);
458
      make_button(104,24,45,13, 0x12|BT_NORMAL,main_bc);
459
      make_button(152,24,45,13, 0x13|BT_NORMAL,main_bc);
460
      make_button(200,24,45,13, 0x14|BT_NORMAL,main_bc);
461
      make_button(248,24,45,13, 0x15|BT_NORMAL,main_bc);
576 serge 462
 
3495 yogev_ezra 463
      make_button(268,70,25,13, 0x16|BT_NORMAL,main_bc); //Asper+ PL button
464
      make_button(10,70,12,13, 0x17|BT_NORMAL,main_wc); //Asper+ R button
576 serge 465
 
3495 yogev_ezra 466
      make_button(7,41,286,11, 0x30|BT_HIDE|BT_NOFRAME,main_wc);
576 serge 467
 
3495 yogev_ezra 468
      update_dinamic_content();
469
      write_text(8,8,FONT0, header, sizeof(header)-1);                     /* uFMOD integration */
470
      write_text(12,28,main_wc|FONT0,buttons_text,sizeof(buttons_wav)-1); /* uFMOD integration */
471
      write_text(11,27,0xA0FFA0|FONT0,buttons_text,sizeof(buttons_wav)-1); /* uFMOD integration */
576 serge 472
 
3495 yogev_ezra 473
      write_text(276,74,main_wc|FONT0,button_PL,sizeof(button_PL)-1); //Asper+ PL button text
474
      write_text(275,73,0xA0FFA0|FONT0,button_PL,sizeof(button_PL)-1); //Asper+
475
      redraw_R_button();
476
   }
576 serge 477
   EndDraw();
478
};
479
 
480
void draw_progress_bar()
481
{  DWORD x;
646 serge 482
   x = (DWORD)(287.0f * (float)(rd.filepos-rd.strremain)/(float)fileinfo.size); /* uFMOD integration */
576 serge 483
   if(x==0) return;
484
   draw_bar(7,41,x,11,0xA0A0A0);
1842 clevermous 485
   draw_bar(x+7,41,287-x,11,main_wc);
576 serge 486
};
487
 
1842 clevermous 488
void debug_out_str(const char* str)
576 serge 489
{
490
  while (*str != 0)
491
  {
492
    debug_out(*str);
493
    str++;
494
  }
495
}
496
 
1842 clevermous 497
int LoadPL(char *fname)
577 serge 498
{
1842 clevermous 499
	DWORD fmt;
500
	DWORD r_bytes;
501
	int retval;
502
	int i;
503
//		char st[100]="";
504
 
505
	char *pch;
506
 
507
	r_bytes=0;
508
	pch=strrchr(fname, '/');
509
	if (pch)
510
		i=pch-fname+1;
511
	else
512
		i=strlen(fname);
513
 
514
	_strncpy (pl_path, fname, i);
515
	pl_path[i]='\0';
516
 
517
	if (!pl_buff)
518
		pl_buff = UserAlloc(0x40000);
519
	retval=read_file (fname,pl_buff,0,0x40000,&r_bytes);
520
 
521
	if ( retval && (r_bytes==0))
522
		return 0;
523
 
524
	Win2Dos(pl_buff, r_bytes);
525
	pl_items_number=CountFileNamesInPL(pl_buff);
526
/*
527
	debug_out_str("\n\rPlay List files number = ");
528
	itoa(pl_items_number, st, 10);
529
	debug_out_str(st);
530
*/
531
	fmt = test_m3u(pl_buff);
532
 
533
	if(!fmt)
534
	{
535
		debug_out_str("\n\rInvalid M3U file");
536
		return 0;
537
	}
538
	debug_out_str("\n\rValid M3U file");
539
	currSelected=currFirstShowed=0;
540
	currActive=-1;
541
	return 1;
542
}
543
 
544
int LoadFile(char *fname)
545
{
577 serge 546
   DWORD fmt;
547
   DWORD r_bytes;
548
   int retval;
549
   int err;
646 serge 550
   unsigned char *ttl, *cur;               /* uFMOD integration */
1842 clevermous 551
 
577 serge 552
   debug_out_str("\n\rPlay file ");
553
   debug_out_str(fname);
554
   debug_out_str("\n\r");
1842 clevermous 555
 
577 serge 556
   if(get_fileinfo(fname, &fileinfo)==FILE_NOT_FOUND)
1842 clevermous 557
   {  debug_out_str("\n\rfile not found\n\r");
577 serge 558
      return 0;
559
   }
1842 clevermous 560
 
561
   r_bytes=0;
562
   strcpy(filename, strrchr(fname,'/')+1);
563
   if( !(fileext = strrchr(filename,'.')))
564
	   return 0;
565
 
566
   if(!_stricmp(fileext,".m3u"))
567
   {
568
	   LoadPL(fname);
569
	   status=ST_TRACK;
570
	   return 1;
577 serge 571
   }
1842 clevermous 572
 
573
   if (!testbuff)
574
	   testbuff = UserAlloc(4096);
575
 
577 serge 576
   retval=read_file (fname,testbuff,0,2048,&r_bytes);
1842 clevermous 577
   if ( retval && (r_bytes==0))
578
	   return 0;
579
 
580
   if (!inpbuf)
581
   {
582
	   inpbuf = UserAlloc(0x10000);
583
	   touch(inpbuf, 0x10000);
584
   }
577 serge 585
   create_reader(&rd, inpbuf, 0x10000);
586
   init_reader(&rd,fname);
1842 clevermous 587
 
646 serge 588
   if(!_stricmp(fileext,".mp3"))
1842 clevermous 589
   {
646 serge 590
			fmt = test_mp3(testbuff);
591
			if(!fmt)
592
			{
1842 clevermous 593
			  debug_out_str("\n\rInvalid MP3 file");
646 serge 594
			  return 0;
595
			};
1842 clevermous 596
			snd_play = &play_mp3;
597
			outremain = 0x40000;
598
			if (!outbuf)
599
			{
600
				outbuf = UserAlloc(outremain);
601
				touch(outbuf, outremain);
602
			}
603
			make_decode_tables(32767);
604
			init_layer2();
605
			init_layer3(32);
646 serge 606
			fr.single = -1;
1842 clevermous 607
			goto play;
577 serge 608
   };
3495 yogev_ezra 609
 
646 serge 610
   if(!_stricmp(fileext,".xm"))
611
   {
612
	   if(uFMOD_LoadSong(fname))
3495 yogev_ezra 613
	   {
646 serge 614
	      buttons_text = buttons_xm;               /* uFMOD integration */
615
	      fmt = PCM_2_16_48;                       /* uFMOD integration */
616
	      snd_play = &play_xm;                     /* uFMOD integration */
617
	      ttl = uFMOD_GetTitle();                  /* uFMOD integration */
618
	      cur = ttl;                               /* uFMOD integration */
619
	      err = 0;                                 /* uFMOD integration */
620
	      while(*cur && *cur++ != ' ') err++;      /* uFMOD integration */
621
	      if(err){                                 /* uFMOD integration */
622
	 	      cur = fname;                             /* uFMOD integration */
623
			     while(*cur) cur++;                       /* uFMOD integration */
624
			     *cur++ = ' ';                            /* uFMOD integration */
625
			     *cur++ = '|';                            /* uFMOD integration */
626
			     *cur++ = ' ';                            /* uFMOD integration */
627
			     while(*ttl) *cur++ = *ttl++;             /* uFMOD integration */
628
		    }
629
		    goto play;
630
		 }
631
		 debug_out_str("\n\rInvalid XM file");
632
     return 0;
633
	 };
634
 
635
	 if(!_stricmp(fileext, ".wav"))
636
	 {
1842 clevermous 637
       fmt = test_wav((WAVEHEADER*)testbuff);
646 serge 638
	   if(fmt)
639
		 {
640
		   snd_play = &play_wave;
641
		   set_reader(&rd, 44);
642
		   outbuf = UserAlloc(32*1024);
643
		   touch(outbuf, 32768);
1842 clevermous 644
		   goto play;
646 serge 645
		 }
646
     debug_out_str("\n\rInvalid WAV file");
647
     return 0;
648
	 };
577 serge 649
 
1842 clevermous 650
   debug_out_str("\n\rUnsupported file");
646 serge 651
   return 0;
652
 
653
play:
654
 
577 serge 655
   status = ST_PLAY;
1842 clevermous 656
   SetFormat(hBuff, fmt);
657
   SetVolume(hBuff,l_vol,r_vol);
658
   GetVolume(hBuff,&l_vol,&r_vol);
659
 
660
   return 1;
661
}
662
 
663
int main(int argc, char *argv[])
664
{
665
   int err, ver;
666
   int i;
667
   char ipc_msg[2]="\0\0";
3495 yogev_ezra 668
   pl_items_number=0;
669
 
670
   if (argv[1][0]=='-' && argv[1][1]=='h')
671
   {
672
      hidden = 1;
673
	  argv[1]+=3;
674
   }
1842 clevermous 675
   strcpy (full_filename, argv[1]);
3495 yogev_ezra 676
 
1842 clevermous 677
   InitHeap(1024*1024);
577 serge 678
 
1842 clevermous 679
   if(err = InitSound(&ver))
680
   {
681
     debug_out_str("Sound service not installed\n\r");
682
     return 0;
683
   }
684
 
685
   if( (SOUND_VERSION>(ver&0xFFFF)) ||
686
       (SOUND_VERSION<(ver >> 16)))
687
   {
688
     debug_out_str("Sound service version mismatch\n\r");
689
     return 0;
690
   }
691
 
692
   if (err = CreateBuffer(PCM_2_16_48, 0, &hBuff))
577 serge 693
   {
694
     debug_out_str("create buffer return error\n\r");
1842 clevermous 695
     return 0;
577 serge 696
   }
1842 clevermous 697
 
698
   if (!LoadFile(full_filename))
699
	   return 0;
700
   tid=create_thread(thread_proc, 0, 4096);
577 serge 701
 
702
   while(1)
703
   {  delay(10);
704
      switch(status)
1842 clevermous 705
      {  case ST_TRACK:
706
			StopBuffer(hBuff);
707
			if (LoadTrack(++currActive))
708
			{
709
				if (LoadFile(full_filename))
710
					status = ST_PLAY;
711
			}
3495 yogev_ezra 712
			else
713
			{
714
				currSelected=currFirstShowed=0;
715
				currActive=-1;
716
				if (!replay) status = ST_STOP;
717
				continue;
718
			}
577 serge 719
 
1842 clevermous 720
			//Update ac97snd and PL windows
721
			i=currActive-currFirstShowed;
722
			if (i>PL_MAX_SHOWN_ITEMS-1)
723
				currFirstShowed = currActive - PL_MAX_SHOWN_ITEMS/2;
724
			ipc_send_msg(tid, ipc_msg);
725
			ipc_send_msg(pl_tid, ipc_msg);
726
			continue;
727
 
728
	  case ST_PLAY:
729
		  snd_play();
730
		  continue;
577 serge 731
 
1842 clevermous 732
	  case ST_STOP:
733
		  StopBuffer(hBuff);
734
		  status = ST_DONE;
735
		  continue;
736
 
737
	  case ST_EXIT:
738
		  uFMOD_StopSong();          /* uFMOD integration */
739
		  StopBuffer(hBuff);
740
		  DestroyBuffer(hBuff);
741
		  return 0;
742
	  };
577 serge 743
   };
744
   return 0;
745
};
746
 
576 serge 747
void touch(char *buf, int size)
748
{ int i;
749
   char a;
646 serge 750
    for ( i = 0;i < size; i+=4096)     //alloc all pages
576 serge 751
      a = buf[i];
752
};
753
 
1842 clevermous 754
DWORD test_m3u(char *buf) //Asper+
755
{
756
	char  *sign="#EXTM3U";
757
	return _strncmp(buf, sign, 7);
758
}
759
 
576 serge 760
DWORD test_mp3(char *buf)
761
{  unsigned long hdr;
762
    WAVEHEADER whdr;
763
 
764
    while (1)
765
    {  if(rd.filepos > 102400)
766
          return 0;
767
        if(!rd.head_read(&rd,&hdr))
577 serge 768
                        return 0;
576 serge 769
        if(!decode_header(&fr,hdr))
646 serge 770
        {
771
         if((hdr & 0xffffff00) == 0x49443300)
772
 	      {
773
 		    int id3length = 0;
774
		    id3length = parse_new_id3(&rd, hdr);
775
		    continue;
776
	      };
777
          rd.strpos-=3;
778
          rd.stream-=3;
779
          rd.strremain+=3;
780
          continue;
576 serge 781
        };
782
        break;
646 serge 783
    };
576 serge 784
 
785
    first_sync = rd.filepos-rd.strremain-4;
786
 
787
    whdr.riff_id = 0x46464952;
788
    whdr.riff_format = 0x45564157;
789
    whdr.wFormatTag = 0x01;
790
    whdr.nSamplesPerSec = freqs[fr.sampling_frequency];
646 serge 791
    whdr.nChannels = 2;
576 serge 792
    whdr.wBitsPerSample = 16;
793
 
794
    return test_wav(&whdr);
795
};
796
 
797
 
798
void play_mp3()
799
{  char *outPtr;
800
    int totalout;
801
    int outcount;
802
 
577 serge 803
 //   memset(&fr,0,sizeof(fr));
804
    fr.down_sample_sblimit = 32;
576 serge 805
    fr.single = -1;
806
    reset_mpg();
807
 
808
    outPtr = outbuf;
809
    totalout=0;
810
    done = 0;
811
    outremain=0x40000;
812
 
813
    memset(outbuf,0,0x40000);
814
    set_reader(&rd, 0);    //;first_sync);
815
 
816
    while(1)
817
    { if(status!=ST_PLAY)
818
             break;
819
 
577 serge 820
     for(;;)
821
     {   outcount = 0;
576 serge 822
          if( !read_frame(&rd, &fr))
823
          {  done = 1;
824
              break;
825
          };
826
          fr.do_layer(&fr, outPtr,&outcount);
827
          outPtr+= outcount;
828
          totalout+=outcount;
829
          outremain-=outcount;
830
          if(outremain < outcount*2)
831
            break;
577 serge 832
    };
576 serge 833
 
577 serge 834
    if(done)
835
    { if(totalout < 4096)
836
      {  memset(outPtr,0,4096-totalout);
837
                totalout = 4096;
576 serge 838
      };
577 serge 839
    }
840
    else
841
      if(totalout < 8192)
842
        continue;
576 serge 843
 
577 serge 844
    outPtr = outbuf;
845
    while (totalout >= 4096)
846
    {
847
 
848
      WaveOut(hBuff,outPtr,4096);
849
      if(status!=ST_PLAY)
1842 clevermous 850
      { if ((status != ST_EXIT) && (status != ST_STOP))
851
         status = ST_TRACK;
577 serge 852
        return;
853
      };
854
      totalout-=4096;
855
      outPtr+=4096;
856
      outremain+=4096;
857
    };
858
    if(done)
859
      break;
860
 
861
    memmove(outbuf,outPtr, totalout);
862
    outPtr = outbuf+totalout;
863
   }
864
 
1842 clevermous 865
    if ((status != ST_EXIT) && (status != ST_STOP))
866
      status =  ST_TRACK;
576 serge 867
};
868
 
869
void play_wave()
646 serge 870
{  int count;
576 serge 871
 
872
   set_reader(&rd,44);
873
   while(1)
874
   {
875
      if(status!=ST_PLAY)
876
        break;
877
 
646 serge 878
      if( count=stream_read_raw(&rd,outbuf,32768))
879
      {
880
        WaveOut(hBuff,outbuf,count);
881
        continue;
882
      }
883
      done = 1;
884
      break;
576 serge 885
   };
886
 
1842 clevermous 887
   if ((status != ST_EXIT) && (status != ST_STOP))
888
     status =  ST_TRACK;
576 serge 889
};
890
 
646 serge 891
void play_xm(){                             /* uFMOD integration */
892
	while(status == ST_PLAY){                 /* uFMOD integration */
893
		uFMOD_WaveOut(hBuff);                   /* uFMOD integration */
894
		delay(8);                               /* uFMOD integration */
895
	}                                         /* uFMOD integration */
1842 clevermous 896
	if ((status != ST_EXIT) && (status != ST_STOP)) status = ST_TRACK;   /* uFMOD integration */
646 serge 897
}                                           /* uFMOD integration */
898
 
576 serge 899
void snd_stop()
900
{
901
  StopBuffer(hBuff);
902
};
903
 
577 serge 904
void _stdcall thread_proc(void *param)
905
{  int evnt;
906
   int pos;
907
   int key;
908
   DWORD offset;
1842 clevermous 909
   char ipc_buff[16];
799 serge 910
 
1842 clevermous 911
   set_event_mask(0x47); //Asper + IPC event
912
   ipc_init(ipc_buff, 16);
913
 
577 serge 914
  _asm
576 serge 915
  {
577 serge 916
    mov eax, 66
917
    mov ebx, 1
918
    mov ecx, 1
919
    int 0x40
576 serge 920
  };
577 serge 921
 
922
  draw_window();
576 serge 923
 
577 serge 924
  while(1)
1842 clevermous 925
  {
926
	 if(status==ST_PLAY)
577 serge 927
     {  draw_progress_bar();
1842 clevermous 928
        evnt = wait_for_event(80);
577 serge 929
     }
930
     else
1842 clevermous 931
		 evnt = wait_for_event_infinite();
576 serge 932
 
1842 clevermous 933
#ifdef DOCKABLE_WINDOW
934
     GetThreadInfo(thread_info, -1);
935
#endif
936
 
577 serge 937
    switch(evnt)
938
    {
939
      case EV_REDRAW:
1842 clevermous 940
		  draw_window();
941
		  break;
576 serge 942
 
577 serge 943
      case EV_KEY:
944
        if(!get_key(&key))
945
        {
946
 
947
          switch(key)
948
          {  case 0xE0:
949
             case 0xE1:
950
               break;
951
             default:
952
               switch (key)
953
               {
954
                 case 0x01:  //Esc
955
                   status = ST_EXIT;
956
                   exit();
1842 clevermous 957
                   break;
577 serge 958
 
3495 yogev_ezra 959
				 case 0x13: //R - repeat on/off
960
				   replay=!replay;
961
				   redraw_R_button();
962
				   break;
963
 
964
				 case 0x19: //P - playlist
965
				   switch (PLStatus)
966
				   {    case 0x00: //PL not started.
967
							pl_tid=create_thread(pl_thread_proc, 0, 4096);
968
							PLStatus=0x12;
969
						break;
970
						case 0x01: //PL started, but hidden.
971
							PLStatus=0x12;
972
						break;
973
						case 0x02: //PL started and showed.
974
							PLStatus=0x11;
975
						break;
976
				   }
977
				   break;
978
 
979
				 case 0x2C: //Z - previous
980
				   currActive-=2;
981
				   status = ST_TRACK;
982
				   break;
983
 
984
				 case 0x2D: //X - play
985
				   status = ST_PLAY;
986
				   break;
987
 
988
				 case 0x2E: //C - pause
989
				   break;
990
 
991
				 case 0x2F: //V - stop
992
                   status = ST_STOP;
993
				   break;
994
 
995
				 case 0x30: //B - next
996
				   status = ST_TRACK;
997
				   break;
998
 
999
				 case 0x47:  //Home
577 serge 1000
                   if(l_vol < 0)
1001
                   { l_vol+=100;
1002
                     r_vol+=100;
1003
                     SetVolume(hBuff,l_vol,r_vol);
1004
                   };
1005
                   break;
1006
                 case 0x4F:  //End
1007
                   if(l_vol > -10000)
1008
                   { l_vol-=100;
1009
                     r_vol-=100;
1010
                     SetVolume(hBuff,l_vol,r_vol);
1011
                   };
1012
                   break;
1013
                 case 0x53:
1014
                   if(pan > -10000)
1015
                   { pan -=100;
1016
                     SetPan(hBuff,pan);
1017
                   };
1018
                   break;
1019
                 case 0x51:
1020
                   if(pan < 10000)
1021
                   { pan +=100;
1022
                     SetPan(hBuff,pan);
1023
                   };
1024
                   break;
1025
               }
1026
          };
1027
        };
1028
        break;
576 serge 1029
 
577 serge 1030
      case EV_BUTTON:
1031
        switch(get_button_id())
1032
        {  case 1:
1033
             status = ST_EXIT;
1034
             exit();
1035
             break;
1036
 
1037
           case 0x10:
1038
             status = ST_PLAY;
3495 yogev_ezra 1039
             break;//continue;
576 serge 1040
 
577 serge 1041
           case 0x11:
1042
             status = ST_STOP;
1043
             break;
1842 clevermous 1044
           case 0x12:
3495 yogev_ezra 1045
			 currActive-=2;
1046
			 status = ST_TRACK;
1047
			 break;
1842 clevermous 1048
           case 0x13:
3495 yogev_ezra 1049
			 status = ST_TRACK;
1050
			 break;
577 serge 1051
           case 0x14:
1052
            if(l_vol > -10000)
1053
            {
1054
              l_vol-=100;
1055
              r_vol-=100;
1056
              SetVolume(hBuff,l_vol,r_vol);
1057
            };
1058
            break;
576 serge 1059
 
577 serge 1060
           case 0x15:
1061
            if(l_vol < 0)
1062
            { l_vol+=100;
1063
              r_vol+=100;
1064
              SetVolume(hBuff,l_vol,r_vol);
1065
            };
1066
            break;
576 serge 1067
 
1842 clevermous 1068
           case 0x16: //Asper+ PL button action
1069
			   switch (PLStatus)
1070
			   {    case 0x00: //PL not started.
1071
						pl_tid=create_thread(pl_thread_proc, 0, 4096);
1072
						PLStatus=0x12;
1073
				    break;
1074
					case 0x01: //PL started, but hidden.
1075
						PLStatus=0x12;
1076
				    break;
1077
					case 0x02: //PL started and showed.
1078
						PLStatus=0x11;
1079
					break;
1080
			   }
1081
            break;
3495 yogev_ezra 1082
           case 0x17: //Asper+ PL button action
1083
			   replay=!replay;
1084
			   redraw_R_button();
1085
            break;
1842 clevermous 1086
 
577 serge 1087
           case 0x30:
1088
            if(status==ST_DONE)
1089
              break;
1090
            pos = (GetMousePos(REL_WINDOW)>>16)-7;
1091
            offset = ((fileinfo.size-44)/286*pos+44)&0xFFFFFFFC;
1092
            set_reader(&rd, offset);
1093
            draw_progress_bar();
1094
            break;
1095
        };
1842 clevermous 1096
		break;
1097
 
1098
	  case EV_IPC:
1099
		  *ipc_buff='\0';
1100
		  update_dinamic_content();
1101
		  break;
1102
 
577 serge 1103
    };
1104
  };
576 serge 1105
};
1106
 
1107
void delay (int val)
1108
{
1109
  _asm
799 serge 1110
 {
1111
      mov   eax,5
576 serge 1112
      mov   ebx, [val]
1113
      int   0x40
1114
  };
1115
}
1116
 
1117
int wait_for_event(int time)
1118
{ int retval;
1119
  _asm
799 serge 1120
 {
1121
     mov  eax,23
576 serge 1122
     mov  ebx,[time]
1123
     int  0x40
1124
     mov [retval], eax
1125
 };
1126
 return retval;
1127
};
1128
 
1129
int wait_for_event_infinite()
1130
{ int retval;
1131
  _asm
799 serge 1132
  {
1133
      mov  eax,10
576 serge 1134
      int  0x40
1135
      mov [retval], eax
1136
  };
1137
  return retval;
1138
};
1139
 
1140
void BeginDraw()
1141
{_asm
799 serge 1142
 {
1143
    mov   eax,12
576 serge 1144
    mov   ebx, 1
1145
    int   0x40
1146
  };
1147
};
1148
 
1149
void EndDraw()
1150
{ _asm
799 serge 1151
 {
1152
    mov   eax,12
576 serge 1153
    mov   ebx, 2
1154
    int   0x40
1155
  };
1156
};
1157
 
1842 clevermous 1158
//Asper+_______start KolibriOS sys functions___________________
1159
void ResizeReplaceWindow (DWORD x, DWORD y, DWORD w, DWORD h) //Asper+
1160
{
1161
  _asm
1162
 {
1163
      mov   eax, 67
1164
      mov   ebx, [x]
1165
      mov   ecx, [y]
1166
      mov   edx, [w]
1167
      mov   esi, [h]
1168
      int   0x40
1169
  };
1170
}
1171
 
1172
#ifdef DOCKABLE_WINDOW
1173
void GetThreadInfo (char *info, int slot) //Asper+
1174
{
1175
	_asm
1176
	{
1177
		mov   eax, 9
1178
		mov   ebx, [info]
1179
		mov   ecx, [slot]
1180
		int   0x40
1181
	}
1182
}
1183
#endif
1184
 
1185
void set_event_mask(int mask)
1186
{
1187
	_asm
1188
	{
1189
		mov  eax, 40
1190
		mov  ebx, [mask]
1191
		int  0x40
1192
	}
1193
}
1194
 
1195
void ipc_init(char *buf, int bufsize)
1196
{
1197
	_asm
1198
	{
1199
		mov  eax, 60
1200
		mov  ebx, 1
1201
		mov  ecx, [buf]
1202
		mov  edx, [bufsize]
1203
		int  0x40
1204
	}
1205
}
1206
 
1207
int ipc_send_msg(int PID, char *msg)
1208
{
1209
	int len = strlen(msg);
1210
	int retval;
1211
	_asm
1212
	{
1213
		mov  eax, 60
1214
		mov  ebx, 2
1215
		mov  ecx, [PID]
1216
		mov  edx, [msg]
1217
		mov  esi, [len]
1218
		int  0x40
1219
		mov [retval], eax
1220
	}
1221
}
1222
//Asper+_______end KolibriOS sys functions___________________
1223
 
1224
//Asper+_______start strings routines___________________
1225
int _strncmp(char *src, char *dst, DWORD n)
1226
{
1227
	_asm{
1228
		mov		esi, src
1229
		mov		edi, dst
1230
		mov		ecx, n
1231
	}
1232
 l1:
1233
	_asm{
1234
		cmpsb
1235
		jne 	err
1236
		loop 	l1
1237
	}
1238
	return 1;
1239
 err:
1240
	return 0;
1241
}
1242
 
1243
int _strncpy (char *dst, char *src, int n)
1244
{
1245
	int  i;
1246
	for (i=0; i
1247
	{
1248
		dst[i]=src[i];
1249
		if (src[i]=='\0') break;
1250
	}
1251
	return 0;
1252
}
1253
 
1254
void uint2str(unsigned int value, char *string)
1255
{
1256
  char tmp[33];
1257
  int i, j;
1258
  unsigned v;
1259
 
1260
  v = (unsigned)value;
1261
  j = 0;
1262
  do{
1263
    i = v % 10;
1264
    v = v / 10;
1265
    if (i < 10)
1266
      tmp[j] = i+'0';
1267
    else
1268
      tmp[j] = i + 'a' - 10;
1269
	j++;
1270
  }while (v);
1271
 
1272
  for (i=0; i
1273
    string[i] = tmp[j-i-1];
1274
  string[i] = '\0';
1275
}
1276
 
1277
//Asper+_______end strings routines___________________
1278
 
1279
 
576 serge 1280
///*********
3533 yogev_ezra 1281
void *__cdecl memmove ( void * dst, const void * src, unsigned int count)  /* uFMOD integration */
576 serge 1282
{ void *ret;
1283
  ret = dst;
1284
 
1285
  if (dst <= src || (char *)dst >= ((char *)src + count))
1286
  {
1287
      while (count--)
1288
      { *(char *)dst = *(char *)src;
1289
          dst = (char *)dst + 1;
1290
          src = (char *)src + 1;
1291
      }
1292
   }
1293
   else
1294
    {
1295
        dst = (char *)dst + count - 1;
1296
        src = (char *)src + count - 1;
1297
         while (count--)
1298
          {  *(char *)dst = *(char *)src;
1299
              dst = (char *)dst - 1;
1300
              src = (char *)src - 1;
1301
          }
1302
    }
1303
    return ret;
1304
};
1305
//**********/
1306
 
1307
void * __cdecl mem_cpy(void * dst,const void * src,size_t count)
1308
{    void * ret = dst;
1309
      while (count--)
1310
      {  *(char *)dst = *(char *)src;
1311
          dst = (char *)dst + 1;
1312
          src = (char *)src + 1;
1313
      };
1314
      return(ret);
1315
}
1316
 
646 serge 1317
char * __cdecl strrchr (const char * string,int ch)
1318
{
1319
        char *start = (char *)string;
1320
 
1321
        while (*string++)                       /* find end of string */
1322
                ;
1323
                                                /* search towards front */
1324
        while (--string != start && *string != (char)ch)
1325
                ;
1326
 
1327
        if (*string == (char)ch)                /* char found ? */
1328
                return( (char *)string );
1329
 
1330
        return(NULL);
1331
}
1332
 
1333
int __cdecl _stricmp (const char * dst, const char * src)
1334
{
1335
    int f, l;
1336
 
1337
    do
1338
    {
1339
        if ( ((f = (unsigned char)(*(dst++))) >= 'A') && (f <= 'Z') )
1340
            f -= 'A' - 'a';
1341
        if ( ((l = (unsigned char)(*(src++))) >= 'A') && (l <= 'Z') )
1342
            l -= 'A' - 'a';
1343
    }
1344
    while ( f && (f == l) );
1345
 
1346
    return(f - l);
1347
}
1348
 
1349