1
2 /*
3 * Example Interface for libmodplug without using XMMS
4 **
5 commandline interface to modplugxmms library
6 gurkan@linuks.mine.nu www.linuks.mine.nu
7 Copyright (C) 2003 Gürkan Sengün
8
9 TODO
10 unlock /dev/dsp when in 'p'ause mode
11 and have a look at SNDCTL_DSP_GETxPTR
12 more functions
13 sig handling
14 12:23 < tp76> tarzeau: yes. I prefer `T *foo = malloc (N * sizeof *foo);'.
15 use stat() to get filesize
16 run indent -kr
17
18 14:08 < tarzeau> so the player isn't stuck when anotehr thing is using /dev/dsp
19 14:08 < tarzeau> if that works a msg is displayed
20 14:08 < tarzeau> later the song is tried to be opened
21 14:08 < tarzeau> then the soundcard settings are set
22 14:09 < tarzeau> the the module is load using libmodplug
23 14:09 < tarzeau> module settings being set
24 14:09 < tarzeau> keyboard handling set
25 14:09 < tarzeau> the status string set up
26 14:09 < tarzeau> time stuff and the main loop
27 14:09 < warp> ok.
28 14:09 < tarzeau> where keyboard input is handled
29 14:09 < tarzeau> that's more or less it
30 14:10 < warp> see, you've just described all the functions you could make.
31 14:10 < warp> so, start that for loop with a init_sound_device () or
32 something.
33 14:10 < warp> etc... make functions for all the things you just described.
34 14:10 < tarzeau> heh good idea, i'll copy paste this irc talk and do that for
35 the next version like 0.9 with the sighandler for people
36 trying to ctrl-c or ctlr-z
37
38 maybe add support for write a .wav file for later play or .ogg
39 and maybe add support for gzip -d some.mod.gz | modplugplay
40 add support to allow modplugplay *.IT *.it *.s3m *.xm (n)ext (N)ot next
41 and -r for random order (make a random played/unplayed (bit)list)
42 show file size
43
44 argument processing
45 if it's not a file, we check if it's an option if not we ignore it
46
47 action keys
48 -> like key (put in list/directory)
49 -> dislike key (remove)
50 -> show info
51
52 || [] >> << >| ()
53
54 TODO
55 or maybe just a $HOME/.modplugplay or /etc/modplugplay
56 command line option handling
57 -l --loop
58 -m --mono
59 -s --stereo (default)
60 -4 --44100 (default)
61 -2 --22050
62 -1 --11025
63 -8 --8bit (default is 16bit)
64 -h --help
65 -q --quiet
66 -v --version (head -c1080 module |strings)
67 -i --info don't play, only show module info (songname,length,size,type)
68 */
69
70 #include <stdio.h> /* printf */
71 #include <string.h> /* strcpy */
72 #include <stdlib.h> /* srand/rand */
73 #include <unistd.h>
74 #include <libmodplug/modplug.h> /* core */
75 #include <sys/ioctl.h> /* control device */
76 #include <fcntl.h>
77
78 #ifdef __NetBSD__
79 #include <soundcard.h>
80 #else
81 #include <sys/soundcard.h>
82 #endif
83
84 #include <sys/time.h> /* gettimeofday */
85 #include <time.h>
86 #include <sys/poll.h> /* poll for keyboard input */
87 #include <termios.h> /* needed to get terminal size */
88
89 #define VERSION "1.1"
90
91 #define BUF_SIZE 4096
92 #define DEVICE_NAME "/dev/dsp"
93
94 static struct termios stored_settings;
95 int audio_fd, mixer_fd;
96 unsigned char audio_buffer[BUF_SIZE];
97
98 typedef struct {
99 int x, y;
100 } term_size;
101
102 /* inquire actual terminal size */
get_term_size(int fd,term_size * t)103 static int get_term_size(int fd, term_size *t) {
104 #ifdef TIOCGSIZE
105 struct ttysize win;
106 #elif defined(TIOCGWINSZ)
107 struct winsize win;
108 #endif
109
110 #ifdef TIOCGSIZE
111 if (ioctl(fd,TIOCGSIZE,&win)) return 0;
112 if (t) {
113 t->y=win.ts_lines;
114 t->x=win.ts_cols;
115 }
116 #elif defined TIOCGWINSZ
117 if (ioctl(fd,TIOCGWINSZ,&win)) return 0;
118 if (t) {
119 t->y=win.ws_row;
120 t->x=win.ws_col;
121 }
122 #else
123 {
124 const char *s;
125 s=getenv("LINES"); if (s) t->y=strtol(s,NULL,10); else t->y=25;
126 s=getenv("COLUMNS"); if (s) t->x=strtol(s,NULL,10); else t->x=80;
127 }
128 #endif
129 return 1;
130 }
131
set_keypress(void)132 void set_keypress(void)
133 {
134 struct termios new_settings;
135 tcgetattr(0,&stored_settings);
136 new_settings=stored_settings;
137 new_settings.c_lflag &= (~ICANON);
138 new_settings.c_lflag &= (~ECHO);
139 new_settings.c_cc[VTIME] = 0;
140 new_settings.c_cc[VMIN] = 1;
141 tcsetattr(0,TCSANOW,&new_settings);
142 return;
143 }
144
reset_keypress(void)145 void reset_keypress(void)
146 {
147 tcsetattr(0,TCSANOW,&stored_settings);
148 return;
149 }
150
ansi_cursor(int visible)151 void ansi_cursor(int visible)
152 {
153 if (visible) {
154 printf("\033[?25h");
155 } else {
156 printf("\033[?25l");
157 }
158 }
159
versioninfo()160 void versioninfo()
161 {
162 printf("\nCopyright (C) 2003 Gürkan Sengün\n");
163 printf("Version %s compiled on %s at %s.\n",VERSION,__DATE__,__TIME__);
164 }
165
help(char * s,int exitcode)166 void help(char *s, int exitcode)
167 {
168 printf("Copyright (C) 2003 Gürkan Sengün\n");
169 printf("Version %s compiled on %s at %s.\n",VERSION,__DATE__,__TIME__);
170 printf("\n");
171 if (exitcode!=0)
172 printf("%s: too few arguments\n",s);
173 printf("Usage: %s" /*[OPTIONS]*/" [FILES]\n",s);
174 printf("\n");
175
176 printf(" -v/--version print version info\n");
177 printf(" -h/--help print help\n");
178 printf(" -l start in looping mode\n");
179 /*
180 printf(" -r randomize play sequence\n");
181 printf(" -c write to console instead of %s\n",DEVICE_NAME);
182 printf(" -i use stdin for file input\n");
183 printf(" -q be quiet\n");
184 */
185 exit(exitcode);
186 }
187
get_byteorder()188 int get_byteorder()
189 {
190 #define sz sizeof(int)
191 int ival;
192 int format;
193 char s[sz];
194 char t[sz];
195 int i, lit, big;
196
197 for (i=0; i<sz; i++) s[i] = i;
198 ival = *(int *)s;
199 big = lit = 0;
200
201 for (i=0; i<sz; i++) {
202 char c = ival&0xff;
203 ival >>= 8;
204 if (s[i] == c) lit++;
205 if (s[sz-i-1] == c) big++;
206 t[i] = c;
207 }
208 if (lit == sz && big == 0) {
209 /*printf("little endian\n");*/
210 format = AFMT_S16_LE;
211 } else if (big == sz && lit == 0) {
212 /*printf("big endian\n");*/
213 format = AFMT_S16_BE;
214 } else {
215 format = -1;
216 }
217 return(format);
218 }
219
getFileData(char * filename,long * size)220 char *getFileData(char *filename, long *size)
221 {
222 FILE *f;
223 char *data;
224
225 f = fopen(filename, "rb");
226 if (f == NULL) {
227 return NULL;
228 }
229 fseek(f, 0L, SEEK_END);
230 (*size) = ftell(f);
231 rewind(f);
232 data = (char*)malloc(*size);
233 fread(data, *size, sizeof(char), f);
234 fclose(f);
235
236 return(data);
237 }
238
getpcmvol()239 int getpcmvol()
240 /* get absolute pcm volume, 0 - 100 (for left+right) */
241 {
242 int vol;
243
244 if ((mixer_fd=open("/dev/mixer", O_RDONLY | O_NONBLOCK, 0)) == -1) {
245 printf("can't open mixer\n");
246 exit(1);
247 }
248 ioctl(mixer_fd,MIXER_READ(SOUND_MIXER_PCM),&vol);
249 close(mixer_fd);
250
251 vol=vol & 255;
252 if (vol==100) vol=99;
253 return(vol);
254 }
255
setrelpcmvol(int newvol)256 int setrelpcmvol(int newvol)
257 /* set relative pcm volume, -100 .. 100 */
258 {
259 int currentvol=getpcmvol();
260 currentvol+=newvol;
261 if (currentvol>100) currentvol=100;
262 if (currentvol<0) currentvol=0;
263 newvol=currentvol+(currentvol*256);
264
265 if ((mixer_fd=open("/dev/mixer", O_RDONLY | O_NONBLOCK, 0)) == -1) {
266 printf("can't open mixer\n");
267 exit(1);
268 }
269 ioctl(mixer_fd,MIXER_WRITE(SOUND_MIXER_PCM),&newvol);
270 close(mixer_fd);
271 }
272
main(int argc,char * argv[])273 int main(int argc, char* argv[])
274 {
275 long size;
276 char *d;
277 term_size terminal;
278 ModPlugFile *f2;
279 int mlen, len;
280 struct timeval tvstart;
281 struct timeval tv;
282 struct timeval tvpause;
283 struct timeval tvunpause;
284 struct timeval tvptotal;
285 char status[161];
286 char songname[41];
287 char notpaus[4];
288
289 int vol=getpcmvol();
290 int songsplayed = 0;
291
292 ModPlug_Settings settings;
293 ModPlug_GetSettings(&settings);
294
295 int format;
296 int channels = 2;
297 int speed = 44100;
298
299 int c; // kontest
300 char buffer[128];
301 int result, nread;
302 struct pollfd pollfds;
303 int timeout = 1; /* Timeout in msec. */
304 int loop=0; // kontest
305 int pause=0;
306 int mono=0;
307 int bits=0;
308 int song;
309 int millisecond;
310 char *randplayed; /* randomly played songs
311 songs that are n/N'd are done or not? */
312 /* what about N if the previous song is not playable? */
313 /* maybe mark it played in randplayed */
314
315 // [rev--dly--] [sur--dly--] [bas--rng--]
316 int rev=0; // a
317 int revdly=0; // s
318 int sur=0; // d
319 int surdly=0; // y
320 int bas=0; // x
321 int basrng=0; // c
322
323 if ((format = get_byteorder()) == -1) {
324 return 1;
325 }
326
327 /* Initialize pollfds; we're looking at input, stdin */
328 pollfds.fd = 0; /* stdin */
329 pollfds.events = POLLIN; /* Wait for input */
330
331 if (argc==1) {
332 help(argv[0],1);
333 }
334
335 if (!get_term_size(STDIN_FILENO,&terminal)) {
336 fprintf(stderr,"warning: failed to get terminal size\n");
337 }
338
339 srand(time(NULL));
340
341 for (song=1; song<argc; song++) {
342
343 /* check if arguments need to be parsed */
344 if (argv[song][0] == '-') {
345 if (!songsplayed && strstr(argv[song],"-h")) {
346 printf("\n");
347 help(argv[0],0);
348 } else if (!songsplayed && strstr(argv[song],"-v")) {
349 versioninfo();
350 exit(0);
351 } else if (strstr(argv[song],"-l")) {
352 loop=1;
353 continue;
354 }
355 if (argv[song][1] == '-') { // not a song
356 if (strstr(argv[song],"--help")) {
357 help(argv[0],0);
358 } else if (strstr(argv[song],"--version")) {
359 versioninfo();
360 exit(0);
361 }
362 continue;
363 }
364 }
365
366 /* O_NONBLOCK gave me the problem
367 that after about 5 seconds writing audiobuffer to DEVICE_NAME
368 was not completed, like 3072 bytes instead of the full buffer 4096
369 which made the sound get faster (and wrong)
370 */
371 if ((audio_fd=open(DEVICE_NAME, O_WRONLY | O_NONBLOCK, 0)) == -1) {
372 fprintf(stderr,"%s (%s): ",DEVICE_NAME,argv[song]);
373 perror("");
374 exit(1);
375 }
376 close(audio_fd);
377
378 if ((audio_fd=open(DEVICE_NAME, O_WRONLY /*| O_NONBLOCK*/, 0)) == -1) {
379 perror(DEVICE_NAME);
380 exit(1);
381 } else {
382 printf("opened %s for playing ",DEVICE_NAME);
383 }
384 printf("%s ",argv[song]);
385 printf("[%d/%d]",song,argc-1);
386
387 d = getFileData(argv[song], &size);
388 if (d == NULL) continue;
389 printf(" [%ld]\n",size);
390
391 if (ioctl(audio_fd,SNDCTL_DSP_SETFMT, &format) == -1) {
392 perror("SND_CTL_DSP_SETFMT");
393 exit(1);
394 }
395
396 if (ioctl(audio_fd, SNDCTL_DSP_CHANNELS, &channels) == -1) {
397 perror("SNDCTL_DSP_CHANNELS");
398 exit(1);
399 }
400 /* int mChannels; */ /* Number of channels - 1 for mono or 2 for stereo */
401 /* int mBits; */ /* Bits per sample - 8, 16, or 32 */
402 /* int mFrequency; */ /* Sampling rate - 11025, 22050, or 44100 */
403
404 if (ioctl(audio_fd,SNDCTL_DSP_SPEED,&speed) == -1) {
405 perror("SNDCTL_DSP_SPEED");
406 exit(1);
407 }
408
409 /* Note: Basic settings must be set BEFORE ModPlug_Load */
410 settings.mResamplingMode = MODPLUG_RESAMPLE_FIR; /* RESAMP */
411 settings.mChannels = 2;
412 settings.mBits = 16;
413 settings.mFrequency = 44100;
414 /* insert more setting changes here */
415 ModPlug_SetSettings(&settings);
416
417 f2 = ModPlug_Load(d, size);
418 if (!f2) {
419 printf("could not load %s\n", argv[song]);
420 close(audio_fd);
421 free(d); /* ? */
422 } else {
423 songsplayed++;
424 /* settings.mFlags=MODPLUG_ENABLE_OVERSAMPLING | \
425 MODPLUG_ENABLE_NOISE_REDUCTION | \
426 MODPLUG_ENABLE_REVERB | \
427 MODPLUG_ENABLE_MEGABASS | \
428 MODPLUG_ENABLE_SURROUND;*/
429
430 // settings.mReverbDepth = 100; /* 0 - 100 */ * [REV--DLY--]
431 // settings.mReverbDelay = 200; /* 40 - 200 ms 00-FF */
432 // settings.mSurroundDepth = 100; /* 0 - 100 */ [SUR--DLY--]
433 // settings.mSurroundDelay = 40; /* 5 - 40 ms */
434 // settings.mBassAmount = 100; /* 0 - 100 */ [BAS--RNG--]
435 // settings.mBassRange = 100; /* 10 - 100 hz */
436 // [REV--DLY--] [SUR--DLY--] [BAS--RNG--]
437 // [rev--dly--] [sur--dly--] [bas--rng--]
438
439 set_keypress();
440 strcpy(songname, ModPlug_GetName(f2));
441
442 /* if no modplug "name" - use last 41 characters of filename */
443 if (strlen(songname)==0) {
444 int l = strlen(argv[song]);
445 char *st = argv[song];
446 if (l >= 41) st = argv[song] + l - 41;
447 strncpy(songname,st,41);
448 songname[41] = 0;
449 }
450 sprintf(status,"[1Gplaying %s (%%d.%%d/%d\") (%%d/%%d/%%d%%s) \b\b\b\b",songname,ModPlug_GetLength(f2)/1000);
451 if (loop) sprintf(status,"[1Glooping %s (%%d.%%d/%d\") (%%d/%%d/%%d%%s) \b\b\b\b",songname,ModPlug_GetLength(f2)/1000);
452
453 gettimeofday(&tvstart,NULL);
454 tvptotal.tv_sec=tvptotal.tv_usec=0;
455 mlen=1;
456
457 while(mlen!=0) {
458 if (mlen==0) { break; }
459
460 if (!pause) {
461 gettimeofday(&tv,NULL);
462 mlen=ModPlug_Read(f2,audio_buffer,BUF_SIZE);
463 if ((len=write(audio_fd,audio_buffer,mlen)) == -1) {
464 perror("audio write");
465 exit(1);
466 }
467 /*printf("%d %d\n",mlen,len);*/
468 }
469 printf(status,tv.tv_sec-tvstart.tv_sec-tvptotal.tv_sec,tv.tv_usec/100000,speed,channels,settings.mBits/*,rev,revdly,sur,surdly,bas,basrng*/);
470 fflush(stdout);
471
472 if ((mlen==0) && (loop==1)) {
473 /*printf("LOOPING NOW\n");*/
474 ModPlug_Seek(f2,0);
475 gettimeofday(&tvstart,NULL);
476 mlen=ModPlug_Read(f2,audio_buffer,BUF_SIZE);
477 tvptotal.tv_sec=tvptotal.tv_usec=0;
478 }
479
480 result = poll(&pollfds, 1, timeout);
481 switch (result) {
482 case 0:
483 /*printf(".");*/
484 break;
485 case -1:
486 perror("select");
487 exit(1);
488
489 default:
490 if (pollfds.revents && POLLIN) {
491 nread = read(0, buffer, 1); /* s/nread/1/2 */
492 if (nread == 0) {
493 printf("keyboard done\n");
494 exit(0);
495 } else {
496 buffer[nread] = 0;
497 /* printf("%s", buffer); */
498
499 if (buffer[0]=='q') { mlen=0; song=argc; ioctl(audio_fd,SNDCTL_DSP_RESET,0); } /* quit */
500
501 if (buffer[0]=='f') {
502 if ((tv.tv_sec-tvstart.tv_sec-tvptotal.tv_sec+10) < (ModPlug_GetLength(f2)/1000)) {
503 ioctl(audio_fd,SNDCTL_DSP_RESET,0);
504 ModPlug_Seek(f2,(tv.tv_sec-tvstart.tv_sec-tvptotal.tv_sec)*1000+10000);
505 tvstart.tv_sec-=10;
506 }
507 } /* forward 10" */
508
509 if (buffer[0]=='b') {
510 if ((tv.tv_sec-tvstart.tv_sec-tvptotal.tv_sec-10) > 0) {
511 ioctl(audio_fd,SNDCTL_DSP_RESET,0);
512 ModPlug_Seek(f2,(tv.tv_sec-tvstart.tv_sec-tvptotal.tv_sec)*1000-10000);
513 tvstart.tv_sec+=10;
514 }
515 } /* backward 10" */
516
517 /*
518 if (buffer[0]=='i') {
519 printf("\n");
520 } */
521
522 /*
523 if (buffer[0]=='a') {
524 rev++; settings.mReverbDepth=rev;
525 ModPlug_SetSettings(&settings);
526 }
527 if (buffer[0]=='A') {
528 rev--; settings.mReverbDepth=rev;
529 ModPlug_SetSettings(&settings);
530 }
531 if (buffer[0]=='s') {
532 revdly++; settings.mReverbDelay=revdly;
533 ModPlug_SetSettings(&settings);
534 }
535 if (buffer[0]=='S') {
536 revdly--; settings.mReverbDelay=revdly;
537 ModPlug_SetSettings(&settings);
538 }
539 if (buffer[0]=='d') {
540 sur++; settings.mSurroundDepth=sur;
541 ModPlug_SetSettings(&settings);
542 }
543 if (buffer[0]=='D') {
544 sur--; settings.mSurroundDepth=sur;
545 ModPlug_SetSettings(&settings);
546 }
547 if (buffer[0]=='y') {
548 surdly++; settings.mSurroundDelay=surdly;
549 ModPlug_SetSettings(&settings);
550 }
551 if (buffer[0]=='Y') {
552 surdly--; settings.mSurroundDelay=surdly;
553 ModPlug_SetSettings(&settings);
554 }
555 if (buffer[0]=='x') {
556 bas++; settings.mBassAmount=bas;
557 ModPlug_SetSettings(&settings);
558 }
559 if (buffer[0]=='X') {
560 bas--; settings.mBassAmount=bas;
561 ModPlug_SetSettings(&settings);
562 }
563 if (buffer[0]=='c') {
564 basrng++; settings.mBassRange=basrng;
565 ModPlug_SetSettings(&settings);
566 }
567 if (buffer[0]=='C') {
568 basrng--; settings.mBassRange=basrng;
569 ModPlug_SetSettings(&settings);
570 }
571 */
572
573 if (buffer[0]=='n') {
574 if (song<argc) { mlen=0; pause=0; ioctl(audio_fd,SNDCTL_DSP_RESET,0); }
575 }
576
577 if (buffer[0]=='N') {
578 if (song>1) { song-=2; mlen=0; pause=0; ioctl(audio_fd,SNDCTL_DSP_RESET,0); }
579 }
580
581 if (buffer[0]=='r') {
582 song=(int) ((float)(argc-1)*rand()/(RAND_MAX+1.0));
583 mlen=0; pause=0;
584 ioctl(audio_fd,SNDCTL_DSP_RESET,0);
585 /* printf("\n[%d?]\n",song+1); */
586 }
587
588 /*if (buffer[0]=='R') {
589 song=(int) ((float)(argc-1)*rand()/(RAND_MAX+1.0));
590 mlen=0; pause=0;
591 }*/
592
593 if (buffer[0]=='1') {
594 /* 11025 hertz */
595 speed=11025;
596 ioctl(audio_fd,SNDCTL_DSP_RESET,0);
597 if (ioctl(audio_fd,SNDCTL_DSP_SPEED,&speed) == -1) {
598 perror("SNDCTL_DSP_SPEED");
599 exit(1);
600 }
601 settings.mFrequency = 11025;
602 ModPlug_SetSettings(&settings);
603 f2=ModPlug_Load(d,size);
604 ModPlug_Seek(f2,(tv.tv_sec-tvstart.tv_sec-tvptotal.tv_sec)*1000+10000);
605 }
606
607 if (buffer[0]=='2') {
608 /* 22050 hertz */
609 speed=22050;
610 ioctl(audio_fd,SNDCTL_DSP_RESET,0);
611 if (ioctl(audio_fd,SNDCTL_DSP_SPEED,&speed) == -1) {
612 perror("SNDCTL_DSP_SPEED");
613 exit(1);
614 }
615 settings.mFrequency = 22050;
616 ModPlug_SetSettings(&settings);
617 f2=ModPlug_Load(d,size);
618 ModPlug_Seek(f2,(tv.tv_sec-tvstart.tv_sec-tvptotal.tv_sec)*1000+10000);
619 }
620
621 if (buffer[0]=='4') {
622 /* 44100 hertz */
623 speed=44100;
624 ioctl(audio_fd,SNDCTL_DSP_RESET,0);
625 if (ioctl(audio_fd,SNDCTL_DSP_SPEED,&speed) == -1) {
626 perror("SNDCTL_DSP_SPEED");
627 exit(1);
628 }
629 settings.mFrequency = 44100;
630 ModPlug_SetSettings(&settings);
631 f2=ModPlug_Load(d,size);
632 ModPlug_Seek(f2,(tv.tv_sec-tvstart.tv_sec-tvptotal.tv_sec)*1000+10000);
633 }
634
635 if (buffer[0]=='8') {
636 /* 8/16 bit */
637 /*format=;*/
638 bits^=1;
639 if (bits) { format=AFMT_U8; } else {
640 switch (get_byteorder()) {
641 case 0: format=AFMT_S16_LE; break;
642 case 1: format=AFMT_S16_BE; break;
643 default:
644 printf("could not determine byte order.\n");
645 return 1;
646 }
647 }
648 ioctl(audio_fd,SNDCTL_DSP_RESET,0);
649 if (ioctl(audio_fd,SNDCTL_DSP_SETFMT, &format) == -1) {
650 perror("SND_CTL_DSP_SETFMT");
651 exit(1);
652 }
653 if (bits) settings.mBits=8; else settings.mBits=16;
654 ModPlug_SetSettings(&settings);
655 f2=ModPlug_Load(d,size);
656 ModPlug_Seek(f2,(tv.tv_sec-tvstart.tv_sec-tvptotal.tv_sec)*1000+10000);
657 }
658
659 if (buffer[0]=='m') {
660 /* mono/stereo */
661 mono^=1;
662 if (mono) channels=1; else channels=2;
663 ioctl(audio_fd,SNDCTL_DSP_RESET,0);
664 if (ioctl(audio_fd, SNDCTL_DSP_CHANNELS, &channels) == -1) {
665 perror("SNDCTL_DSP_CHANNELS");
666 exit(1);
667 }
668 if (mono) settings.mChannels=1; else settings.mChannels=2;
669 ModPlug_SetSettings(&settings);
670 f2=ModPlug_Load(d,size);
671 ModPlug_Seek(f2,(tv.tv_sec-tvstart.tv_sec-tvptotal.tv_sec)*1000+10000);
672 }
673
674 if (buffer[0]=='l') {
675 loop^=1;
676 if (loop) {
677 memcpy(status+4,"loop",4);
678 } else {
679 memcpy(status+4,"play",4);
680 }
681 } /* loop */
682
683 if (buffer[0]=='+') {
684 setrelpcmvol(4);
685 }
686
687 if (buffer[0]=='-') {
688 setrelpcmvol(-4);
689 }
690
691 if (buffer[0]=='p') {
692 pause^=1;
693 ioctl(audio_fd,SNDCTL_DSP_RESET,0);
694 if (pause) {
695 gettimeofday(&tvpause,NULL);
696 memcpy(notpaus,status+4,4);
697 memcpy(status+4,"paus",4);
698 } else {
699 gettimeofday(&tvunpause,NULL);
700 memcpy(status+4,notpaus,4);
701 tvptotal.tv_sec+=tvunpause.tv_sec-tvpause.tv_sec;
702 tvptotal.tv_usec+=tvunpause.tv_usec-tvpause.tv_usec;
703 /* printf(status,tv.tv_sec-tvstart.tv_sec,tv.tv_usec/100000); */
704 }
705 } /* pause */
706 }
707 }
708 }
709 }
710 printf("\n");
711
712 reset_keypress();
713 ModPlug_Unload(f2);
714 close(audio_fd);
715 free(d);
716 } /* valid module */
717
718 } /* for */
719
720 return 0;
721 }
722
723