Subversion Repositories Kolibri OS

Rev

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