1 /*
2 * Copyright (C) 1990 Regents of the University of California.
3 *
4 * Permission to use, copy, modify, distribute, and sell this software and
5 * its documentation for any purpose is hereby granted without fee,
6 * provided that the above copyright notice appear in all copies and that
7 * both that copyright notice and this permission notice appear in
8 * supporting documentation, and that the name of the University of
9 * California not be used in advertising or publicity pertaining to
10 * distribution of the software without specific, written prior
11 * permission. the University of California makes no representations
12 * about the suitability of this software for any purpose. It is provided
13 * "as is" without express or implied warranty.
14 */
15
16 # include <X11/Intrinsic.h>
17 # include <X11/StringDefs.h>
18 # include <X11/Shell.h>
19 # include <X11/Xaw/Form.h>
20 # include <X11/Xaw/Label.h>
21 # include <X11/Xaw/List.h>
22 # include <X11/Xaw/Command.h>
23 # include <X11/Xaw/Toggle.h>
24 # include <X11/Xaw/Viewport.h>
25 # include <X11/Xaw/Dialog.h>
26
27
28 # include <stdio.h>
29 # include <string.h>
30 # include <stdlib.h>
31
32 # include "debug.h"
33 # include "cdrom_globs.h"
34 #if defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__NetBSD__) || defined(__DragonFly__)
35 # include "cdrom_freebsd.h"
36 #endif
37 #ifdef sun
38 # include "cdrom_sun.h"
39 #endif
40 #ifdef sgi
41 # include "cdrom_sgi.h"
42 #endif
43
44
45 /* externally manipulated vars: */
46 char program_str[100];
47 char *disc_title = NULL;
48
49 static Widget program_form;
50 static Widget program_display_form;
51 static Widget program_anchor;
52 static Widget trackbuttons[9];
53 static Widget plus10_button;
54 static Widget new_track_button;
55 static Boolean adding_to_new_track = False;
56 static struct prognode *current_node = NULL;
57
58 static void cb_move_program_ptr();
59 static void cb_clear_program();
60 static void cb_cancel_program();
61 static void cb_save_program();
62 static void cb_trackbuttons();
63 static void cb_add_10();
64 static void cb_new_track();
65 static void cb_program_all();
66
67 void
program_form_setup(parent_widget)68 program_form_setup (parent_widget)
69 Widget parent_widget;
70 {
71 Arg args[10];
72 char namestr[2];
73 int i;
74
75 Widget program_display_viewport;
76 Widget track_select_form;
77 Widget clear_button;
78 Widget cancel_button;
79 Widget save_button;
80 Widget all_button;
81
82 /*
83 * create program form as a non-managed widget, because this
84 * form "pops up" when requested, as part of the main form, and
85 * therefore moves along with the main form. (Pop-ups don't do this
86 * easily.)
87 */
88 program_form = XtCreateWidget("programForm",
89 formWidgetClass,
90 parent_widget,
91 (ArgList) NULL, 0);
92
93 program_display_viewport = XtCreateManagedWidget(
94 "programDisplayViewport",
95 viewportWidgetClass,
96 program_form,
97 (ArgList) NULL, 0);
98
99 program_display_form = XtCreateManagedWidget("programDisplayForm",
100 formWidgetClass,
101 program_display_viewport,
102 (ArgList) NULL, 0);
103
104
105 XtSetArg(args[0], XtNlabel, " ");
106 XtSetArg(args[1], XtNstate, TRUE);
107 program_anchor = XtCreateManagedWidget("programSelection",
108 toggleWidgetClass,
109 program_display_form,
110 (ArgList) args, 2);
111 XtAddCallback (program_anchor, XtNcallback, cb_move_program_ptr, NULL);
112
113
114 XtSetArg(args[0], XtNfromVert, program_display_viewport);
115 clear_button = XtCreateManagedWidget("Clear",
116 commandWidgetClass,
117 program_form,
118 (ArgList) args, 1);
119 XtAddCallback (clear_button, XtNcallback, cb_clear_program, NULL);
120
121 XtSetArg(args[0], XtNfromVert, program_display_viewport);
122 XtSetArg(args[1], XtNfromHoriz, clear_button);
123 cancel_button = XtCreateManagedWidget("Cancel",
124 commandWidgetClass,
125 program_form,
126 (ArgList) args, 2);
127 XtAddCallback (cancel_button, XtNcallback, cb_cancel_program, NULL);
128
129
130 XtSetArg(args[0], XtNfromVert, program_display_viewport);
131 XtSetArg(args[1], XtNfromHoriz, cancel_button);
132 save_button = XtCreateManagedWidget("Save",
133 commandWidgetClass,
134 program_form,
135 (ArgList) args, 2);
136 XtAddCallback (save_button, XtNcallback, cb_save_program, NULL);
137
138
139 XtSetArg(args[0], XtNfromVert, clear_button);
140 track_select_form = XtCreateManagedWidget("selectForm",
141 formWidgetClass,
142 program_form,
143 (ArgList) args, 1);
144
145
146 for (i = 1; i <= 9; i++)
147 {
148 sprintf(namestr, "%d",i);
149 trackbuttons[i-1] = XtCreateManagedWidget(namestr,
150 commandWidgetClass,
151 track_select_form,
152 (ArgList) NULL, 0);
153
154 }
155
156 XtAddCallback (trackbuttons[0], XtNcallback, cb_trackbuttons, NULL);
157
158 for (i = 1; i < 9; i++)
159 {
160 XtSetArg(args[0], XtNfromHoriz, trackbuttons[i-1]);
161 XtSetValues(trackbuttons[i], args, 1);
162 XtAddCallback (trackbuttons[i], XtNcallback, cb_trackbuttons, NULL);
163 }
164
165 XtSetArg(args[0], XtNfromVert, trackbuttons[0]);
166 plus10_button = XtCreateManagedWidget("+10",
167 commandWidgetClass,
168 track_select_form,
169 (ArgList) args, 1);
170 XtAddCallback (plus10_button, XtNcallback, cb_add_10, NULL);
171
172 XtSetArg(args[0], XtNfromVert, trackbuttons[0]);
173 XtSetArg(args[1], XtNfromHoriz, plus10_button);
174 new_track_button = XtCreateManagedWidget(" ",
175 commandWidgetClass,
176 track_select_form,
177 (ArgList) args, 2);
178 XtAddCallback (new_track_button, XtNcallback, cb_new_track, NULL);
179
180 XtSetArg(args[0], XtNfromVert, trackbuttons[0]);
181 XtSetArg(args[1], XtNfromHoriz, trackbuttons[6]);
182 all_button = XtCreateManagedWidget("All",
183 commandWidgetClass,
184 track_select_form,
185 (ArgList) args, 2);
186 XtAddCallback (all_button, XtNcallback, cb_program_all, NULL);
187
188 }
189
190 void
popup_program_form(widget,topLevel,call_data)191 popup_program_form (widget, topLevel, call_data)
192 Widget widget;
193 Widget topLevel;
194 XtPointer call_data;
195 {
196 Arg args[2];
197 int i;
198 char *progstr;
199 char *token;
200 int track;
201
202 extern FILE *disc_info;
203
204
205 cdi.selection = NULL;
206
207 /* load saved program (if any) */
208 if (disc_info != NULL)
209 {
210 /* copy "open" program str for tokenization */
211 progstr = strdup(program_str);
212 token = strtok(progstr, "-"); /* find 1st programmed track */
213 if (token != NULL)
214 {
215 debug_printf(1, "using stored program\n");
216 while (token != NULL)
217 {
218 sscanf(token, "%d",&track); /* convert to # */
219 program_add_track((unsigned char)track);
220 token = strtok(NULL,"-"); /* get next track str */
221 }
222 }
223 }
224
225 /* clear sensitivity for all */
226 for (i=0; i < 9; i++)
227 {
228 XtSetArg(args[0], XtNsensitive, FALSE);
229 XtSetValues(trackbuttons[i], args, 1);
230 }
231
232 XtSetArg(args[0], XtNsensitive, FALSE);
233 XtSetValues(plus10_button, args, 1);
234 XtSetValues(new_track_button, args, 1);
235
236 for (i = 0; (i < 9) && (i < cdi.maxtrack); i++)
237 {
238 /* set sensitivity for active buttons */
239 XtSetArg(args[0], XtNsensitive, TRUE);
240 XtSetValues(trackbuttons[i], args, 1);
241 }
242 if (cdi.maxtrack > 9)
243 {
244 XtSetArg(args[0], XtNsensitive, TRUE);
245 XtSetValues(plus10_button, args, 1);
246 }
247
248
249 XtManageChild(program_form);
250 }
251
252
253
254 void
make_program_button(node,next_to,label)255 make_program_button(node, next_to, label)
256 struct prognode *node;
257 Widget next_to;
258 char label[];
259 {
260 Arg args[10];
261 char name[2];
262 int i = 0;
263
264 XtSetArg(args[i], XtNfromHoriz, next_to); i++;
265 XtSetArg(args[i], XtNlabel, label); i++;
266 XtSetArg(args[i], XtNradioGroup, program_anchor); i++;
267 XtSetArg(args[i], XtNstate, TRUE); i++; /* activates *this* button */
268
269 node->button = XtCreateManagedWidget("programSelection",
270 toggleWidgetClass,
271 program_display_form,
272 (ArgList) args, i);
273 XtAddCallback(node->button, XtNcallback, cb_move_program_ptr,
274 (XtPointer) node);
275
276 if (node->next != NULL) /* then reposition widget following */
277 {
278 XtSetArg(args[0], XtNfromHoriz, node->button);
279 XtSetValues(node->next->button, args, 1);
280 }
281 }
282
283 void
program_add_track(track)284 program_add_track (track)
285 unsigned char track;
286 {
287 struct prognode *insert_point, *new, *next;
288 Arg args[10];
289 char *p;
290 char label[3];
291 int i;
292
293 XawFormDoLayout (program_display_form, FALSE);
294
295 if (cdi.program == NULL)
296 {
297 new = (struct prognode *) malloc(sizeof(struct prognode));
298 new->track = track;
299 new->next = NULL;
300 new->prev = NULL;
301 current_node = cdi.program = new;
302 cdi.lastprog = 1;
303
304 sprintf(label, "%d", track);
305 make_program_button(new, program_anchor, label);
306 }
307
308 else if (current_node == NULL) /* pre-insert */
309 {
310 new = (struct prognode *) malloc(sizeof(struct prognode));
311 new->track = track;
312 new->next = cdi.program;
313 new->prev = NULL;
314 current_node = cdi.program->prev = new;
315 cdi.program = cdi.program->prev;
316 cdi.lastprog++;
317
318 sprintf(label, "%d", track);
319 make_program_button(new, program_anchor, label);
320
321 sprintf(label, "-%d", new->next->track);
322 XtSetArg(args[0], XtNlabel, label);
323 XtSetValues(new->next->button, args, 1);
324 }
325 else
326 {
327 insert_point = cdi.program;
328
329 while ((insert_point->next != NULL) &&
330 (insert_point != current_node))
331 insert_point = insert_point->next;
332
333 new = (struct prognode *) malloc(sizeof(struct prognode));
334 new->track = track;
335 new->next = insert_point->next;
336 new->prev = insert_point;
337 if (new->next != NULL)
338 new->next->prev = new; /* complete link back */
339
340 cdi.lastprog++;
341 current_node = insert_point->next = new;
342
343 sprintf(label, "-%d", track);
344 make_program_button(new, insert_point->button, label);
345 }
346
347 next = cdi.program;
348 sprintf(program_str, "%d", next->track);
349 for (i = 1; i < cdi.lastprog; i++)
350 {
351 next = next->next;
352 sprintf(program_str, "%s-%d", program_str, next->track);
353 }
354
355
356 XawFormDoLayout (program_display_form, TRUE);
357
358
359 if (cdi.state & CDROM_STATE_PAUSE)
360 {
361 cdi.selection = new;
362 cdi.curtrack = new->track;
363 track_button_update();
364 timer_button_update();
365 }
366 }
367
368 void
program_delete_track(node)369 program_delete_track (node)
370 struct prognode *node;
371 {
372 int i;
373 Arg args[2];
374 char *p;
375 char label[3];
376
377 if (cdi.program == NULL)
378 return;
379
380 if (node->prev != NULL)
381 {
382 node->prev->next = node->next;
383 current_node = node->prev;
384 XtSetArg(args[0], XtNstate, True);
385 XtSetValues(current_node->button, args, 1);
386
387 XtSetArg(args[0], XtNfromHoriz, node->prev->button);
388 }
389 else
390 {
391 cdi.program = node->next;
392 current_node = cdi.program;
393 if (current_node != NULL)
394 {
395 sprintf(label, "%d", current_node->track);
396 XtSetArg(args[0], XtNlabel, label);
397 XtSetArg(args[1], XtNstate, True);
398 XtSetValues(current_node->button, args, 2);
399
400 XtSetArg(args[0], XtNfromHoriz, program_anchor);
401
402 }
403 else
404 {
405 XtSetArg(args[0], XtNstate, True);
406 XtSetValues(program_anchor, args, 1);
407 }
408 }
409
410 if (node->next != NULL)
411 {
412 node->next->prev = node->prev;
413 XtSetValues(node->next->button, args, 1);
414 }
415
416
417 XtDestroyWidget(node->button);
418 free(node);
419
420 cdi.lastprog--;
421
422 if (cdi.program == NULL)
423 {
424 program_str[0] = '\0';
425 cdi.selection = NULL;
426 }
427 else
428 {
429 cdi.selection = current_node;
430
431 if (cdi.state & CDROM_STATE_PAUSE)
432 {
433 cdi.curtrack = current_node->track;
434 track_button_update();
435 timer_button_update();
436 }
437
438 node = cdi.program;
439 sprintf(program_str, "%d", node->track);
440 for (i = 1; i < cdi.lastprog; i++)
441 {
442 node = node->next;
443 sprintf(program_str, "%s-%d", program_str, node->track);
444 }
445 }
446
447 }
448
449
450 int
program_time_remaining()451 program_time_remaining()
452 {
453 struct prognode *node;
454 int time_remaining = 0;
455
456 if ((cdi.program == NULL) || (cdi.selection == NULL))
457 return (0);
458
459 node = cdi.selection;
460 while (node != NULL)
461 {
462 time_remaining += cdi.times[node->track - 1];
463 node = node->next;
464 }
465 time_remaining -= cdi.duration;
466 return (time_remaining);
467 }
468
469
470 unsigned char
program_goto_next_track()471 program_goto_next_track()
472 {
473 Arg arg;
474 Boolean already_on;
475
476 if (cdi.program == NULL)
477 return (0);
478 else if (cdi.selection == NULL)
479 cdi.selection = cdi.program;
480 else if (cdi.selection->next == NULL)
481 {
482 cdi.selection = NULL;
483 return (0);
484 }
485 else
486 cdi.selection = cdi.selection->next;
487
488
489 XtSetArg(arg, XtNstate, &already_on);
490 XtGetValues(cdi.selection->button, &arg, 1);
491 if (already_on == FALSE)
492 {
493 XtSetArg(arg, XtNstate, TRUE);
494 XtSetValues(cdi.selection->button, &arg, 1);
495 }
496
497 pgm_button_set();
498 return(cdi.selection->track);
499 }
500
501 unsigned char
program_resume()502 program_resume()
503 {
504 unsigned char track;
505
506 if (cdi.program != NULL)
507 {
508 if (cdi.selection == NULL)
509 track = program_goto_next_track();
510 else
511 track = cdi.selection->track;
512 }
513 else
514 track = cdi.curtrack;
515 pgm_button_set();
516
517 return(track);
518 }
519
520
521 unsigned char
program_goto_prev_track()522 program_goto_prev_track()
523 {
524 Arg arg;
525 Boolean already_on;
526
527 if ((cdi.program == NULL) || (cdi.selection->prev == NULL))
528 return (0);
529
530 cdi.selection = cdi.selection->prev;
531
532 XtSetArg(arg, XtNstate, &already_on);
533 XtGetValues(cdi.selection->button, &arg, 1);
534 if (already_on == FALSE)
535 {
536 XtSetArg(arg, XtNstate, TRUE);
537 XtSetValues(cdi.selection->button, &arg, 1);
538 }
539
540 pgm_button_set();
541 return (cdi.selection->track);
542 }
543
544 unsigned char
program_next_track()545 program_next_track()
546 {
547 if (cdi.program == NULL)
548 return (0);
549
550 else if (cdi.selection == NULL)
551 return (cdi.program->track);
552
553 else if (cdi.selection->next == NULL)
554 return (0);
555 else
556 return (cdi.selection->next->track);
557
558 }
559
560 unsigned char
program_prev_track()561 program_prev_track()
562 {
563 if ((cdi.program == NULL) || (cdi.selection == NULL) ||
564 (cdi.selection->prev == NULL))
565 return (0);
566
567 else
568 return (cdi.selection->prev->track);
569
570 }
571
572 void
clear_program()573 clear_program()
574 {
575 Arg arg;
576
577 /* clear new_track button and deactivate */
578 XtSetArg(arg, XtNlabel, " ");
579 XtSetValues(new_track_button, &arg, 1);
580 XtSetArg(arg, XtNsensitive, False);
581 XtSetValues(new_track_button, &arg, 1);
582 adding_to_new_track = False;
583
584 if (cdi.program == NULL)
585 return;
586
587 cdi.selection = cdi.program;
588 while (cdi.selection->next != NULL)
589 {
590 cdi.program = cdi.program-> next;
591 XtDestroyWidget(cdi.selection->button);
592 free(cdi.selection);
593 cdi.selection = cdi.program;
594 }
595 XtDestroyWidget(cdi.selection->button);
596 free(cdi.selection);
597 cdi.selection = cdi.program = NULL;
598 cdi.lastprog = 0;
599 XtSetArg(arg, XtNstate, True);
600 XtSetValues(program_anchor, &arg, 1);
601
602 program_str[0]= '\0'; /* clear "store" string */
603
604 }
605
606 void
program_cancel()607 program_cancel()
608 {
609 debug_printf(1, "program mode cancelled\n");
610 clear_program();
611
612 XtUnmanageChild(program_form);
613 pgm_button_reset();
614 timer_button_reset();
615 timer_button_update();
616 cdi.state &= ~CDROM_STATE_PROGRAM;
617 }
618
619 void
cb_move_program_ptr(widget,node,call_data)620 cb_move_program_ptr(widget, node, call_data)
621 Widget widget;
622 struct prognode *node;
623 XtPointer call_data;
624 {
625 /*
626 * I cannot get XawToggleGetCurrent to work at all, so this
627 * is a bastardized way of doing this:
628 */
629
630 Arg arg;
631 Boolean state;
632
633 XtSetArg(arg, XtNstate, &state);
634 XtGetValues(widget, &arg, 1);
635
636 if (state == True)
637 {
638 if ((current_node == node) && (current_node != NULL))
639 {
640 debug_printf(1, "deleting selection from program\n");
641 program_delete_track(node);
642 }
643 else
644 {
645 current_node = node;
646
647 if ((current_node != NULL) &&
648 ((cdi.state & CDROM_STATE_PAUSE) ||
649 ((cdi.state & CDROM_STATE_PLAY) == 0)))
650 {
651 cdi.selection = node;
652 cdi.curtrack = node->track;
653 track_button_update();
654 timer_button_update();
655 }
656 }
657 }
658
659 }
660
661
662 static void
cb_program_all(widget,client_data,call_data)663 cb_program_all(widget, client_data, call_data)
664 Widget widget;
665 XtPointer client_data;
666 XtPointer call_data;
667 {
668 Arg arg;
669 int i;
670
671 clear_program();
672
673 debug_printf(1, "program replaced by in-sequence track list\n");
674 for (i = 1; i <= cdi.maxtrack; i++)
675 program_add_track ((unsigned char) i);
676 }
677
678 static void
cb_clear_program(widget,client_data,call_data)679 cb_clear_program (widget, client_data, call_data)
680 Widget widget;
681 XtPointer client_data;
682 XtPointer call_data;
683 {
684 clear_program(); /* get rid of program */
685 debug_printf(1, "program cleared\n");
686 }
687
688 static void
cb_cancel_program(widget,client_data,call_data)689 cb_cancel_program (widget, client_data, call_data)
690 Widget widget;
691 XtPointer client_data;
692 XtPointer call_data;
693 {
694 program_cancel(); /* get rid of program and form */
695 }
696
697 void
cb_save_program(widget,client_data,call_data)698 cb_save_program (widget, client_data, call_data)
699 Widget widget;
700 XtPointer client_data;
701 XtPointer call_data;
702 {
703 Arg arg;
704 char *progstr;
705 extern FILE *disc_info;
706
707 disc_info = fopen(info_filename, "w+"); /* open for r/w */
708 if (disc_info == NULL) {
709 fprintf(stderr,"Can't open save file %s\n",info_filename);
710 perror("cb_save_program");
711 return;
712 }
713 fprintf(disc_info, "Title:%s\nProgram: %s\n", disc_title, program_str);
714 fflush(disc_info);
715
716 debug_printf(1, "program saved to %s\n", info_filename);
717 }
718
719 void
add_to_new_track(number)720 add_to_new_track (number)
721 int number;
722 {
723 Arg arg;
724 char *namestr;
725 int track = 0;
726
727 /* an apparent bug in my system won't allow the auto-display of this
728 * label change without explicit forcing redraw via something other
729 * than the label itself
730 */
731 XtSetArg(arg, XtNsensitive, False);
732 XtSetValues(new_track_button, &arg, 1);
733
734 XtSetArg(arg, XtNlabel, &namestr);
735 XtGetValues(new_track_button, &arg, 1);
736 if (namestr[0] != ' ')
737 sscanf (namestr, "%d", &track);
738 track += number;
739 sprintf(namestr, "%d\n", track);
740 XtSetArg(arg, XtNlabel, namestr);
741 XtSetValues(new_track_button, &arg, 1);
742
743 /* reset the sensitive flage for redraw */
744 XtSetArg(arg, XtNsensitive, True);
745 XtSetValues(new_track_button, &arg, 1);
746 }
747
748 static void
cb_add_10(widget,client_data,call_data)749 cb_add_10(widget, client_data, call_data)
750 Widget widget;
751 XtPointer client_data;
752 XtPointer call_data;
753 {
754 Arg arg;
755 char *namestr;
756 int track = 0;
757
758 XtSetArg(arg, XtNsensitive, True);
759 XtSetValues(new_track_button, &arg, 1);
760 adding_to_new_track = True;
761 add_to_new_track(10);
762 }
763
764 static void
cb_new_track(widget,client_data,call_data)765 cb_new_track(widget, client_data, call_data)
766 Widget widget;
767 XtPointer client_data;
768 XtPointer call_data;
769 {
770 Arg arg;
771 char *namestr;
772 int track;
773
774 XtSetArg(arg, XtNlabel, &namestr);
775 XtGetValues(widget, &arg, 1);
776 sscanf (namestr, "%d", &track);
777
778 if ((track >= cdi.mintrack) && (track <= cdi.maxtrack))
779 {
780 debug_printf(1, "adding track %d to program\n", track);
781 program_add_track((unsigned char) track);
782 }
783 XtSetArg(arg, XtNlabel, " ");
784 XtSetValues(new_track_button, &arg, 1);
785 XtSetArg(arg, XtNsensitive, False);
786 XtSetValues(new_track_button, &arg, 1);
787 adding_to_new_track = False;
788 }
789
790
791 static void
cb_trackbuttons(widget,client_data,call_data)792 cb_trackbuttons(widget, client_data, call_data)
793 Widget widget;
794 XtPointer client_data;
795 XtPointer call_data;
796 {
797 Arg arg;
798 char *namestr;
799 int track;
800 Boolean state;
801
802 XtSetArg(arg, XtNlabel, &namestr);
803 XtGetValues(widget, &arg, 1);
804 sscanf (namestr, "%d", &track);
805
806 if (adding_to_new_track)
807 add_to_new_track(track);
808 else
809 {
810 debug_printf(1, "adding track %d to program\n", track);
811 program_add_track((unsigned char) track);
812 }
813
814 }
815