1 /* Playing a sound file
2
3 * Copyright (C) 1998 J.A. Bezemer
4 *
5 * Licensed under the terms of the GNU General Public License.
6 * ABSOLUTELY NO WARRANTY.
7 * See the file `COPYING' in this directory.
8 */
9
10 #include "playwav.h"
11 #include "scrollmenu.h"
12 #include "stringinput.h"
13 #include "buttons.h"
14 #include "boxes.h"
15 #include "dirfilemenu.h"
16 #include "errorwindow.h"
17 #include "textwindow.h"
18 #include "checkfile.h"
19 #include "yesnowindow.h"
20 #include "helpline.h"
21 #include "clrscr.h"
22 #include "secshms.h"
23 #include "fmtheaders.h"
24 #include "signpr_main.h"
25
26 #include <stdlib.h>
27 #include <sys/stat.h>
28 #include <string.h>
29 #ifndef OLD_CURSES
30 #include <ncurses.h>
31 #else
32 #include <curses.h>
33 #endif
34
35 #define BPLAYCMD "bplay_gramo"
36
37 void
playwav_playit(char * filename,int usebeginendtime,double begintime,double endtime)38 playwav_playit (char *filename, int usebeginendtime, double begintime,
39 double endtime)
40 {
41 char shellcmd[500], *tmp;
42 int len, ret;
43
44 switch (checkfile (filename))
45 {
46 case FILE_EXISTS:
47
48 tmp = shellcmd;
49 len = 500;
50 retry:
51 if (usebeginendtime)
52 ret = snprintf (tmp, len,
53 BPLAYCMD " -S -s 44100 -b 16 -J %ld -T %ld \"%s\"",
54 (long) (begintime * 44100),
55 (long) ((endtime - begintime) * 44100), filename);
56 else
57 ret = snprintf (tmp, len,
58 BPLAYCMD " -S -s 44100 -b 16 \"%s\"", filename);
59
60 if (ret > len)
61 {
62 tmp = alloca(ret);
63 len = ret;
64 if (tmp)
65 goto retry;
66 error_window ("The system ran out of memory");
67 break;
68 }
69
70 if (ret == -1)
71 {
72 error_window ("Cannot handle file names this long. Sorry.");
73 break;
74 }
75
76 /* defaults for raw files (but no -r, so .wav's supply their own
77 parameters) - you can even listen to executables in CD quality (: */
78
79 def_prog_mode (); /* save terminal state */
80
81 system (shellcmd);
82
83 reset_prog_mode (); /* reset terminal state */
84 clear ();
85
86 break;
87
88 case DIR_EXISTS:
89 error_window ("The specified name is of a directory. A \
90 file name must be specified.");
91 break;
92
93 case DIR_OK_NEW_FILE:
94 case DIR_WRONG:
95 error_window ("The specified file does not exist.");
96 break;
97
98 default:
99 error_window ("Fell out of switch, playwav #2");
100 break;
101 }
102 }
103
104 #define PLAY_TRACK 1
105 #define PLAY_BEGINNING 2
106 #define PLAY_END 3
107 #define PLAY_BEFORE 4
108 #define PLAY_AFTER 5
109
110 /* These may be fractional, like 5.2, if you like that better. */
111 #define BEGINNING_SECS 5
112 #define END_SECS 4
113 #define BEFORE_SECS 3
114 #define AFTER_SECS 3
115
116 void
playwav_track(char * filename,int track,int action)117 playwav_track (char *filename, int track, int action)
118 {
119 beginendsample_t tracktimes[100];
120 int number_of_tracks;
121 double begintime, endtime;
122 char helpstring[200];
123
124 if (!load_track_times (filename, tracktimes, &number_of_tracks))
125 return;
126
127 if (track > number_of_tracks || track < 1)
128 {
129 sprintf (helpstring, "There are only %d tracks.", number_of_tracks);
130 error_window (helpstring);
131 return;
132 }
133
134 switch (action)
135 {
136 case PLAY_TRACK:
137 begintime = tracktimes[track].begin;
138 endtime = tracktimes[track].end;
139 /* use samples here, convert to seconds after switch */
140 break;
141
142 case PLAY_BEGINNING:
143 begintime = tracktimes[track].begin;
144 endtime = tracktimes[track].begin + BEGINNING_SECS * 44100;
145 break;
146
147 case PLAY_END:
148 begintime = tracktimes[track].end - END_SECS * 44100;
149 endtime = tracktimes[track].end;
150 break;
151
152 case PLAY_BEFORE:
153 begintime = tracktimes[track].begin - BEFORE_SECS * 44100;
154 endtime = tracktimes[track].begin;
155 break;
156
157 case PLAY_AFTER:
158 begintime = tracktimes[track].end;
159 endtime = tracktimes[track].end + AFTER_SECS * 44100;
160 break;
161
162 default:
163 error_window ("Fell out of switch, playwav #3");
164 return;
165 }
166
167 if (begintime < 0)
168 begintime = 0;
169 if (endtime < 0)
170 endtime = 0;
171 if (begintime >= endtime)
172 return;
173
174 /* samples -> seconds here */
175 playwav_playit (filename, 1, begintime / 44100, endtime / 44100);
176 }
177
178
179 int
playwav_select_file(char * startdir,char * selectedfile,int * usebeginendtime,double * begintime,double * endtime)180 playwav_select_file (char *startdir, char *selectedfile,
181 int *usebeginendtime, double *begintime,
182 double *endtime)
183 /* Returns 0: canceled, 1: OK */
184 {
185 scrollmenu_t dirfilelist;
186 stringinput_t string;
187 button_t ok_button, cancel_button;
188 int dont_stop = TRUE;
189 int returnval = 0;
190 int focus;
191 int in_ch;
192 int i;
193 char helpstring[500];
194 char *charpointer;
195 struct stat filestats;
196 int oldselected;
197 double tempdouble = 0;
198 long templong;
199 char tempstring[250];
200 stringinput_t trackstring, begintimestring, endtimestring;
201 button_t beginend_check;
202 struct stat buf;
203
204 char *helplines[8] =
205 {
206 " Select name of sound file to be played. TAB: Next field",
207 " Enter: Play track B/E: Beginning/End F/A: beFore/After +/-: Prev/Next",
208 " Play only a part of the sound file. TAB: Next field",
209 " Enter begin time of part to be played. TAB: Next field",
210 " Enter end time of part to be played. TAB: Next field",
211 " Enter name of sound file to be played. TAB: Next field",
212 " Back to main menu. TAB: Next field",
213 " Play the specified (part of the) sound file. TAB: Next field"};
214
215 dirfilelist.y = 3;
216 dirfilelist.x = 5;
217 dirfilelist.h = 12;
218 dirfilelist.w = 32;
219 dirfilelist.firstonscreen = 0;
220 dirfilemenu (startdir, &dirfilelist);
221 dirfilelist.selected = dirfilelist.last_of_1st_part + 1;
222
223 string.maxlen = 500;
224 string.string = (char *) malloc (string.maxlen * sizeof (char));
225 if (selectedfile[0] == '\0')
226 strcpy (string.string, startdir);
227 else
228 strcpy (string.string, selectedfile);
229 string.y = 17;
230 string.x = 5;
231 string.w = 70;
232 string.cursorpos = strlen (string.string);
233 string.firstcharonscreen = strlen (string.string) - string.w + 2;
234 if (string.firstcharonscreen < 0)
235 string.firstcharonscreen = 0;
236
237 ok_button.text = " Play ";
238 ok_button.y = 20;
239 ok_button.x = 69;
240 ok_button.selected = FALSE;
241
242 cancel_button.text = " Cancel ";
243 cancel_button.y = 20;
244 cancel_button.x = 5;
245 cancel_button.selected = FALSE;
246
247 trackstring.maxlen = 500;
248 trackstring.string = (char *) malloc (
249 trackstring.maxlen * sizeof (char));
250 strcpy (trackstring.string, "1");
251 trackstring.y = 11;
252 trackstring.x = 54;
253 trackstring.w = 10;
254 trackstring.cursorpos = strlen (trackstring.string);
255 trackstring.firstcharonscreen = 0;
256
257 begintimestring.maxlen = 500;
258 begintimestring.string = (char *) malloc (
259 begintimestring.maxlen * sizeof (char));
260 fsec2hmsf (*begintime, begintimestring.string);
261 begintimestring.y = 14;
262 begintimestring.x = 59;
263 begintimestring.w = 18;
264 begintimestring.cursorpos = strlen (begintimestring.string);
265 begintimestring.firstcharonscreen = 0;
266
267 endtimestring.maxlen = 500;
268 endtimestring.string = (char *) malloc (
269 endtimestring.maxlen * sizeof (char));
270 fsec2hmsf (*endtime, endtimestring.string);
271 endtimestring.y = 15;
272 endtimestring.x = 59;
273 endtimestring.w = 18;
274 endtimestring.cursorpos = strlen (endtimestring.string);
275 endtimestring.firstcharonscreen = 0;
276
277 beginend_check.text = ""; /* see below */
278 beginend_check.y = 13;
279 beginend_check.x = 42;
280 beginend_check.selected = FALSE;
281
282 clearscreen (PLAYWAV_HEADERTEXT);
283
284 if (selectedfile[0] == '\0')
285 focus = 0;
286 else
287 focus = 5;
288
289 do
290 {
291 if (*usebeginendtime)
292 beginend_check.text = "[X] Use begin and end times";
293 else
294 beginend_check.text = "[ ] Use begin and end times";
295
296 if (focus == 2)
297 beginend_check.selected = TRUE;
298 else
299 beginend_check.selected = FALSE;
300
301 if (focus == 6)
302 cancel_button.selected = TRUE;
303 else
304 cancel_button.selected = FALSE;
305
306 if (focus == 7)
307 ok_button.selected = TRUE;
308 else
309 ok_button.selected = FALSE;
310
311 dirfilelist.hasfocus = (focus == 0);
312
313 scrollmenu_display (&dirfilelist);
314 mybox (dirfilelist.y - 1, dirfilelist.x - 1,
315 dirfilelist.h + 2, dirfilelist.w + 2);
316 mvprintw (dirfilelist.y - 1, dirfilelist.x + 1,
317 "Files and directories:");
318
319 button_display (&beginend_check);
320
321 stringinput_display (&trackstring);
322 mvprintw (trackstring.y, trackstring.x - 7,
323 "Track:");
324
325 stringinput_display (&begintimestring);
326 mvprintw (begintimestring.y, begintimestring.x - 12,
327 "Begin time:");
328
329 stringinput_display (&endtimestring);
330 mvprintw (endtimestring.y, endtimestring.x - 12,
331 "End time :");
332
333 stringinput_display (&string);
334 mybox (string.y - 1, string.x - 1, 3, string.w + 2);
335 mvprintw (string.y - 1, string.x + 1, "File name:");
336
337 button_display (&cancel_button);
338 mybox (cancel_button.y - 1, cancel_button.x - 1,
339 3, strlen (cancel_button.text) + 2);
340 button_display (&ok_button);
341 mybox (ok_button.y - 1, ok_button.x - 1,
342 3, strlen (ok_button.text) + 2);
343
344 header (PLAYWAV_HEADERTEXT);
345 helpline (helplines[focus]);
346
347 /* this really should be a switch... */
348 if (focus == 1)
349 stringinput_display (&trackstring);
350 else if (focus == 3)
351 stringinput_display (&begintimestring);
352 else if (focus == 4)
353 stringinput_display (&endtimestring);
354 else if (focus == 5)
355 stringinput_display (&string);
356 else
357 move (0, 79);
358
359 refresh ();
360
361 in_ch = getch ();
362
363 switch (focus)
364 {
365 case 0: /* dirfilelist */
366 if (scrollmenu_stdkeys (in_ch, &dirfilelist) >= 0)
367 {
368 oldselected = dirfilelist.selected;
369 i = dirfilemenu_process_select (&dirfilelist,
370 helpstring);
371 if (i == 0) /* filename in helpstring */
372 {
373 strcpy (string.string, helpstring);
374 focus = 7;
375 string.cursorpos = strlen (string.string);
376 string.firstcharonscreen = 0;
377
378 if (!stat (helpstring, &buf))
379 {
380 *begintime = 0;
381 if (buf.st_size < sizeof (wavhead))
382 *endtime = 0;
383 else
384 *endtime = (buf.st_size - sizeof (wavhead))
385 / (2 * 2 * 44100.);
386
387 fsec2hmsf (*begintime, begintimestring.string);
388 begintimestring.cursorpos =
389 strlen (begintimestring.string);
390 begintimestring.firstcharonscreen = 0;
391
392 fsec2hmsf (*endtime, endtimestring.string);
393 endtimestring.cursorpos = strlen (endtimestring.string);
394 endtimestring.firstcharonscreen = 0;
395 }
396 }
397 else
398 /* dir in helpstring */
399 {
400 scrollmenu_delete_menu (&dirfilelist);
401 dirfilemenu (helpstring, &dirfilelist);
402 if (dirfilelist.number == 0)
403 {
404 error_window (
405 "No permission to read this directory.");
406 scrollmenu_delete_menu (&dirfilelist);
407 dirfilemenu (startdir, &dirfilelist);
408 dirfilelist.selected = oldselected;
409 }
410 else
411 {
412 strcpy (startdir, helpstring);
413 dirfilelist.firstonscreen = 0;
414
415 charpointer = strrchr (string.string, '/');
416 if (charpointer != NULL)
417 strcat (helpstring, charpointer + 1);
418 else
419 strcat (helpstring, string.string);
420 strcpy (string.string, helpstring);
421 }
422 }
423 }
424 else
425 switch (in_ch)
426 {
427 case KEY_LEFT:
428 focus--;
429 break;
430 case KEY_RIGHT:
431 focus++;
432 break;
433 }
434 break;
435
436 case 1: /* tracks */
437 /* exclude keys like b,e,f,a,+,- */
438 if ((in_ch >= '0' && in_ch <= '9') || in_ch > 127)
439 stringinput_stdkeys (in_ch, &trackstring);
440
441 templong = atol (trackstring.string);
442
443 switch (in_ch)
444 {
445 case KEY_ENTER:
446 case 13:
447 playwav_track (string.string, templong, PLAY_TRACK);
448 break;
449
450 case 'b':
451 case 'B':
452 playwav_track (string.string, templong, PLAY_BEGINNING);
453 break;
454
455 case 'e':
456 case 'E':
457 playwav_track (string.string, templong, PLAY_END);
458 break;
459
460 case 'f':
461 case 'F':
462 playwav_track (string.string, templong, PLAY_BEFORE);
463 break;
464
465 case 'a':
466 case 'A':
467 playwav_track (string.string, templong, PLAY_AFTER);
468 break;
469
470 case '+':
471 case '=':
472 if (templong < 99)
473 templong++;
474 sprintf (trackstring.string, "%ld", templong);
475 trackstring.cursorpos = strlen (trackstring.string);
476 trackstring.firstcharonscreen = 0;
477 break;
478
479 case '-':
480 case '_':
481 if (templong > 1)
482 templong--;
483 sprintf (trackstring.string, "%ld", templong);
484 trackstring.cursorpos = strlen (trackstring.string);
485 trackstring.firstcharonscreen = 0;
486 break;
487
488 case KEY_UP:
489 focus--;
490 break;
491 case KEY_DOWN:
492 focus++;
493 break;
494 }
495
496 break;
497
498 case 2: /* Use begin/end times */
499 switch (in_ch)
500 {
501 case KEY_ENTER:
502 case 13:
503 case ' ':
504 case 'x':
505 case 'X':
506 *usebeginendtime = 1 - *usebeginendtime;
507 break;
508
509 case KEY_LEFT:
510 case KEY_UP:
511 focus--;
512 break;
513 case KEY_RIGHT:
514 case KEY_DOWN:
515 focus++;
516 break;
517 }
518 break;
519
520 case 3: /* begin time */
521 stringinput_stdkeys (in_ch, &begintimestring);
522 switch (in_ch)
523 {
524 case KEY_ENTER:
525 case 13:
526 strcpy (tempstring, begintimestring.string);
527 if (!hmsf2fsec (tempstring, &tempdouble))
528 {
529 error_window ("Enter the time in the format hours:\
530 minutes:seconds.fractions, for example 0:04:26.740");
531 begintimestring.cursorpos =
532 strlen (begintimestring.string);
533 }
534 else
535 {
536 *begintime = tempdouble;
537 fsec2hmsf (tempdouble, begintimestring.string);
538 begintimestring.cursorpos =
539 strlen (begintimestring.string);
540 focus++;
541 }
542 break;
543
544 case KEY_UP:
545 focus--;
546 break;
547 case KEY_DOWN:
548 focus++;
549 break;
550 }
551 break;
552
553 case 4: /* end time */
554 stringinput_stdkeys (in_ch, &endtimestring);
555 switch (in_ch)
556 {
557 case KEY_ENTER:
558 case 13:
559 strcpy (tempstring, endtimestring.string);
560 if (!hmsf2fsec (tempstring, &tempdouble))
561 {
562 error_window ("Enter the time in the format hours:\
563 minutes:seconds.fractions, for example 0:04:26.740");
564 endtimestring.cursorpos =
565 strlen (endtimestring.string);
566 }
567 else
568 {
569 *endtime = tempdouble;
570 fsec2hmsf (tempdouble, endtimestring.string);
571 endtimestring.cursorpos =
572 strlen (endtimestring.string);
573 focus = 5;
574 }
575 break;
576
577 case KEY_UP:
578 focus--;
579 break;
580 case KEY_DOWN:
581 focus++;
582 break;
583 }
584 break;
585
586
587 case 5: /* string */
588 stringinput_stdkeys (in_ch, &string);
589 if (in_ch == KEY_ENTER || in_ch == 13)
590 {
591 strcpy (helpstring, string.string);
592
593 /* cut away last '/'-s */
594 while (strlen (helpstring) > 0 &&
595 helpstring[strlen (helpstring) - 1] == '/')
596 helpstring[strlen (helpstring) - 1] = '\0';
597
598 strcat (helpstring, "/");
599
600 if (!stat (helpstring, &filestats) &&
601 S_ISDIR (filestats.st_mode))
602 {
603 strcpy (startdir, helpstring);
604 scrollmenu_delete_menu (&dirfilelist);
605 dirfilemenu (startdir, &dirfilelist);
606 dirfilelist.firstonscreen = 0;
607 dirfilelist.selected =
608 dirfilelist.last_of_1st_part + 1;
609 strcpy (string.string, startdir);
610 string.cursorpos = strlen (string.string);
611 focus = 0;
612 }
613 else
614 /* it's a file */
615 {
616 focus = 7;
617
618 if (!stat (string.string, &buf))
619 {
620 *begintime = 0;
621 if (buf.st_size < sizeof (wavhead))
622 *endtime = 0;
623 else
624 *endtime = (buf.st_size - sizeof (wavhead))
625 / (2 * 2 * 44100.);
626
627 fsec2hmsf (*begintime, begintimestring.string);
628 begintimestring.cursorpos =
629 strlen (begintimestring.string);
630 begintimestring.firstcharonscreen = 0;
631
632 fsec2hmsf (*endtime, endtimestring.string);
633 endtimestring.cursorpos = strlen (endtimestring.string);
634 endtimestring.firstcharonscreen = 0;
635 }
636 }
637 }
638 else
639 switch (in_ch)
640 {
641 case KEY_UP:
642 focus--;
643 break;
644 case KEY_DOWN:
645 focus++;
646 break;
647 }
648 break;
649
650 case 6: /* Cancel */
651 if (in_ch == KEY_ENTER || in_ch == 13)
652 {
653 returnval = 0;
654 dont_stop = FALSE;
655 }
656 else
657 switch (in_ch)
658 {
659 case KEY_LEFT:
660 case KEY_UP:
661 focus--;
662 break;
663 case KEY_RIGHT:
664 case KEY_DOWN:
665 focus++;
666 break;
667 }
668 break;
669
670 case 7: /* OK */
671 if (in_ch == KEY_ENTER || in_ch == 13)
672 {
673 strcpy (tempstring, begintimestring.string);
674 if (!hmsf2fsec (tempstring, &tempdouble))
675 {
676 error_window ("Enter the begin time in the format hours:\
677 minutes:seconds.fractions, for example 0:04:26.740");
678 begintimestring.cursorpos =
679 strlen (begintimestring.string);
680 focus = 3;
681 break;
682 }
683
684 *begintime = tempdouble;
685
686 strcpy (tempstring, endtimestring.string);
687 if (!hmsf2fsec (tempstring, &tempdouble))
688 {
689 error_window ("Enter the end time in the format hours:\
690 minutes:seconds.fractions, for example 0:04:26.740");
691 endtimestring.cursorpos =
692 strlen (endtimestring.string);
693 focus = 4;
694 break;
695 }
696
697 *endtime = tempdouble;
698
699 if (*begintime > *endtime)
700 {
701 error_window ("The begin time is larger than the end time.");
702 fsec2hmsf (*begintime, begintimestring.string);
703 begintimestring.cursorpos =
704 strlen (begintimestring.string);
705 fsec2hmsf (*endtime, endtimestring.string);
706 endtimestring.cursorpos =
707 strlen (endtimestring.string);
708 focus = 3;
709 break;
710 }
711
712 switch (checkfile (string.string))
713 {
714 case FILE_EXISTS:
715 /* strcpy (selectedfile, string.string);
716 returnval = 1;
717 dont_stop = FALSE; */
718
719 playwav_playit (string.string, *usebeginendtime, *begintime,
720 *endtime);
721 break;
722
723 case DIR_EXISTS:
724 error_window ("The specified name is of a directory. A \
725 file name must be specified.");
726 string.cursorpos = strlen (string.string);
727 focus = 5;
728 break;
729
730 case DIR_OK_NEW_FILE:
731 case DIR_WRONG:
732 error_window ("The specified file does not exist.");
733 string.cursorpos = strlen (string.string);
734 focus = 5;
735 break;
736
737 default:
738 error_window ("Fell out of switch, playwav #1");
739 break;
740 }
741
742 } /* if ENTER */
743 else
744 switch (in_ch)
745 {
746 case KEY_LEFT:
747 case KEY_UP:
748 focus--;
749 break;
750 case KEY_RIGHT:
751 case KEY_DOWN:
752 focus++;
753 break;
754 }
755 break;
756 }
757
758 if (in_ch == 9) /* TAB */
759 focus++;
760
761 if (in_ch == 27)
762 dont_stop = FALSE;
763
764 if (focus > 7)
765 focus = 0;
766 if (focus < 0)
767 focus = 7;
768 }
769 while (dont_stop);
770
771 scrollmenu_delete_menu (&dirfilelist);
772 free (string.string);
773
774 return returnval;
775 }
776
777 void
playwav_main(char * startdir)778 playwav_main (char *startdir)
779 {
780 char filename[250];
781 /* char shellcmd[500]; */
782 int usebeginendtime = 0;
783 double begintime = 0, endtime = 0;
784
785 filename[0] = '\0';
786
787 while (1)
788 {
789 if (!playwav_select_file (startdir, filename, &usebeginendtime,
790 &begintime, &endtime))
791 return;
792
793 #if 0
794 /* not used any more - integrated in select_file */
795 def_prog_mode (); /* save terminal state */
796
797 if (usebeginendtime)
798 sprintf (shellcmd, "bplay_gramo -S -s 44100 -b 16 -J %ld -T %ld \"%s\"",
799 (long) (begintime * 44100),
800 (long) ((endtime - begintime) * 44100), filename);
801 else
802 sprintf (shellcmd, "bplay_gramo -S -s 44100 -b 16 \"%s\"", filename);
803 /* defaults for raw files (but no -r, so .wav's supply their own
804 parameters */
805
806 system (shellcmd);
807
808 reset_prog_mode (); /* reset terminal state */
809 #endif /* 0 */
810
811 }
812 }
813