bd69d06f783f3a5feeb24d14a090e585a9aa0719
[melted] / src / humperdink / client.c
1 /*
2 * client.c -- Valerie client demo
3 * Copyright (C) 2002-2003 Ushodaya Enterprises Limited
4 * Author: Charles Yates <charles.yates@pandora.be>
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 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software Foundation,
18 * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
19 */
20
21 /* System header files */
22 #include <stdio.h>
23 #include <stdlib.h>
24 #include <string.h>
25
26 /* Application header files */
27 #include "client.h"
28 #include "io.h"
29
30 /** Clip navigation enumeration.
31 */
32
33 typedef enum
34 {
35 absolute,
36 relative
37 }
38 dv_demo_whence;
39
40 /** Function prototype for menu handling.
41 */
42
43 typedef valerie_error_code (*demo_function)( dv_demo );
44
45 /** The menu structure.
46 */
47
48 typedef struct
49 {
50 char *description;
51 struct menu_item
52 {
53 char *option;
54 demo_function function;
55 }
56 array[ 50 ];
57 }
58 *dv_demo_menu, dv_demo_menu_t;
59
60 /** Forward reference to menu runner.
61 */
62
63 extern valerie_error_code dv_demo_run_menu( dv_demo, dv_demo_menu );
64
65 /** Foward references.
66 */
67
68 extern valerie_error_code dv_demo_list_nodes( dv_demo );
69 extern valerie_error_code dv_demo_add_unit( dv_demo );
70 extern valerie_error_code dv_demo_select_unit( dv_demo );
71 extern valerie_error_code dv_demo_execute( dv_demo );
72 extern valerie_error_code dv_demo_load( dv_demo );
73 extern valerie_error_code dv_demo_transport( dv_demo );
74 static void *dv_demo_status_thread( void * );
75
76 /** Connected menu definition.
77 */
78
79 dv_demo_menu_t connected_menu =
80 {
81 "Connected Menu",
82 {
83 { "Add Unit", dv_demo_add_unit },
84 { "Select Unit", dv_demo_select_unit },
85 { "Command Shell", dv_demo_execute },
86 { NULL, NULL }
87 }
88 };
89
90 /** Initialise the demo structure.
91 */
92
93 dv_demo dv_demo_init( valerie_parser parser )
94 {
95 dv_demo this = malloc( sizeof( dv_demo_t ) );
96 if ( this != NULL )
97 {
98 int index = 0;
99 memset( this, 0, sizeof( dv_demo_t ) );
100 strcpy( this->last_directory, "/" );
101 for ( index = 0; index < 4; index ++ )
102 {
103 this->queues[ index ].unit = index;
104 this->queues[ index ].position = -1;
105 }
106 this->parser = parser;
107 }
108 return this;
109 }
110
111 /** Display a status record.
112 */
113
114 void dv_demo_show_status( dv_demo demo, valerie_status status )
115 {
116 if ( status->unit == demo->selected_unit && demo->showing )
117 {
118 char temp[ 1024 ] = "";
119
120 sprintf( temp, "U%d ", demo->selected_unit );
121
122 switch( status->status )
123 {
124 case unit_offline:
125 strcat( temp, "offline " );
126 break;
127 case unit_undefined:
128 strcat( temp, "undefined " );
129 break;
130 case unit_not_loaded:
131 strcat( temp, "unloaded " );
132 break;
133 case unit_stopped:
134 strcat( temp, "stopped " );
135 break;
136 case unit_playing:
137 strcat( temp, "playing " );
138 break;
139 case unit_paused:
140 strcat( temp, "paused " );
141 break;
142 case unit_disconnected:
143 strcat( temp, "disconnect" );
144 break;
145 default:
146 strcat( temp, "unknown " );
147 break;
148 }
149
150 sprintf( temp + strlen( temp ), " %9d %9d %9d ", status->in, status->position, status->out );
151 strcat( temp, status->clip );
152
153 printf( "%-80.80s\r", temp );
154 fflush( stdout );
155 }
156 }
157
158 /** Determine action to carry out as dictated by the client unit queue.
159 */
160
161 void dv_demo_queue_action( dv_demo demo, valerie_status status )
162 {
163 dv_demo_queue queue = &demo->queues[ status->unit ];
164
165 /* SPECIAL CASE STATUS NOTIFICATIONS TO IGNORE */
166
167 /* When we've issued a LOAD on the previous notification, then ignore this one. */
168 if ( queue->ignore )
169 {
170 queue->ignore --;
171 return;
172 }
173
174 if ( queue->mode && status->status != unit_offline && queue->head != queue->tail )
175 {
176 if ( ( status->position >= status->out && status->speed > 0 ) || status->status == unit_not_loaded )
177 {
178 queue->position = ( queue->position + 1 ) % 50;
179 if ( queue->position == queue->tail )
180 queue->position = queue->head;
181 valerie_unit_load( demo->dv_status, status->unit, queue->list[ queue->position ] );
182 if ( status->status == unit_not_loaded )
183 valerie_unit_play( demo->dv, queue->unit );
184 queue->ignore = 1;
185 }
186 else if ( ( status->position <= status->in && status->speed < 0 ) || status->status == unit_not_loaded )
187 {
188 if ( queue->position == -1 )
189 queue->position = queue->head;
190 valerie_unit_load( demo->dv_status, status->unit, queue->list[ queue->position ] );
191 if ( status->status == unit_not_loaded )
192 valerie_unit_play( demo->dv, queue->unit );
193 queue->position = ( queue->position - 1 ) % 50;
194 queue->ignore = 1;
195 }
196 }
197 }
198
199 /** Status thread.
200 */
201
202 static void *dv_demo_status_thread( void *arg )
203 {
204 dv_demo demo = arg;
205 valerie_status_t status;
206 valerie_notifier notifier = valerie_get_notifier( demo->dv_status );
207
208 while ( !demo->terminated )
209 {
210 if ( valerie_notifier_wait( notifier, &status ) != -1 )
211 {
212 dv_demo_queue_action( demo, &status );
213 dv_demo_show_status( demo, &status );
214 if ( status.status == unit_disconnected )
215 demo->disconnected = 1;
216 }
217 }
218
219 return NULL;
220 }
221
222 /** Turn on/off status display.
223 */
224
225 void dv_demo_change_status( dv_demo demo, int flag )
226 {
227 if ( demo->disconnected && flag )
228 {
229 valerie_error_code error = valerie_connect( demo->dv );
230 if ( error == valerie_ok )
231 demo->disconnected = 0;
232 else
233 beep();
234 }
235
236 if ( flag )
237 {
238 valerie_status_t status;
239 valerie_notifier notifier = valerie_get_notifier( demo->dv );
240 valerie_notifier_get( notifier, &status, demo->selected_unit );
241 demo->showing = 1;
242 dv_demo_show_status( demo, &status );
243 }
244 else
245 {
246 demo->showing = 0;
247 printf( "%-80.80s\r", " " );
248 fflush( stdout );
249 }
250 }
251
252 /** Add a unit.
253 */
254
255 valerie_error_code dv_demo_add_unit( dv_demo demo )
256 {
257 valerie_error_code error = valerie_ok;
258 valerie_nodes nodes = valerie_nodes_init( demo->dv );
259 valerie_units units = valerie_units_init( demo->dv );
260
261 if ( valerie_nodes_count( nodes ) != -1 && valerie_units_count( units ) != -1 )
262 {
263 char pressed;
264 valerie_node_entry_t node;
265 valerie_unit_entry_t unit;
266 int node_index = 0;
267 int unit_index = 0;
268
269 printf( "Select a Node\n\n" );
270
271 for ( node_index = 0; node_index < valerie_nodes_count( nodes ); node_index ++ )
272 {
273 valerie_nodes_get( nodes, node_index, &node );
274 printf( "%d: %s - %s ", node_index + 1, node.guid, node.name );
275 for ( unit_index = 0; unit_index < valerie_units_count( units ); unit_index ++ )
276 {
277 valerie_units_get( units, unit_index, &unit );
278 if ( !strcmp( unit.guid, node.guid ) )
279 printf( "[U%d] ", unit.unit );
280 }
281 printf( "\n" );
282 }
283
284 printf( "0. Exit\n\n" );
285
286 printf( "Node: " );
287
288 while ( ( pressed = get_keypress( ) ) != '0' )
289 {
290 node_index = pressed - '1';
291 if ( node_index >= 0 && node_index < valerie_nodes_count( nodes ) )
292 {
293 int unit;
294 printf( "%c\n\n", pressed );
295 valerie_nodes_get( nodes, node_index, &node );
296 if ( valerie_unit_add( demo->dv, node.guid, &unit ) == valerie_ok )
297 {
298 printf( "Unit added as U%d\n", unit );
299 demo->selected_unit = unit;
300 }
301 else
302 {
303 int index = 0;
304 valerie_response response = valerie_get_last_response( demo->dv );
305 printf( "Failed to add unit:\n\n" );
306 for( index = 1; index < valerie_response_count( response ) - 1; index ++ )
307 printf( "%s\n", valerie_response_get_line( response, index ) );
308 }
309 printf( "\n" );
310 wait_for_any_key( NULL );
311 break;
312 }
313 else
314 {
315 beep( );
316 }
317 }
318 }
319 else
320 {
321 printf( "Invalid response from the server.\n\n" );
322 wait_for_any_key( NULL );
323 }
324
325 valerie_nodes_close( nodes );
326 valerie_units_close( units );
327
328 return error;
329 }
330
331 /** Select a unit.
332 */
333
334 valerie_error_code dv_demo_select_unit( dv_demo demo )
335 {
336 int terminated = 0;
337 int refresh = 1;
338
339 while ( !terminated )
340 {
341 valerie_units units = valerie_units_init( demo->dv );
342
343 if ( valerie_units_count( units ) > 0 )
344 {
345 valerie_unit_entry_t unit;
346 int index = 0;
347 char key = '\0';
348
349 if ( refresh )
350 {
351 printf( "Select a Unit\n\n" );
352
353 for ( index = 0; index < valerie_units_count( units ); index ++ )
354 {
355 valerie_units_get( units, index, &unit );
356 printf( "%d: U%d - %s [%s]\n", index + 1,
357 unit.unit,
358 unit.guid,
359 unit.online ? "online" : "offline" );
360 }
361 printf( "0: Exit\n\n" );
362
363 printf( "Unit [%d]: ", demo->selected_unit + 1 );
364 refresh = 0;
365 }
366
367 key = get_keypress( );
368
369 if ( key == '\r' )
370 key = demo->selected_unit + '1';
371
372 if ( key != '0' )
373 {
374 if ( key >= '1' && key < '1' + valerie_units_count( units ) )
375 {
376 demo->selected_unit = key - '1';
377 printf( "%c\n\n", key );
378 dv_demo_load( demo );
379 refresh = 1;
380 }
381 else
382 {
383 beep( );
384 }
385 }
386 else
387 {
388 printf( "0\n\n" );
389 terminated = 1;
390 }
391 }
392 else if ( valerie_units_count( units ) == 0 )
393 {
394 printf( "No units added - add a unit first\n\n" );
395 dv_demo_add_unit( demo );
396 }
397 else
398 {
399 printf( "Unable to obtain Unit List.\n" );
400 terminated = 1;
401 }
402
403 valerie_units_close( units );
404 }
405
406 return valerie_ok;
407 }
408
409 /** Execute an arbitrary command.
410 */
411
412 valerie_error_code dv_demo_execute( dv_demo demo )
413 {
414 valerie_error_code error = valerie_ok;
415 char command[ 10240 ];
416 int terminated = 0;
417
418 printf( "Miracle Shell\n" );
419 printf( "Enter an empty command to exit.\n\n" );
420
421 while ( !terminated )
422 {
423 terminated = 1;
424 printf( "Command> " );
425
426 if ( chomp( io_get_string( command, 10240, "" ) ) != NULL )
427 {
428 if ( strcmp( command, "" ) )
429 {
430 int index = 0;
431 valerie_response response = NULL;
432 error = valerie_execute( demo->dv, 10240, command );
433 printf( "\n" );
434 response = valerie_get_last_response( demo->dv );
435 for ( index = 0; index < valerie_response_count( response ); index ++ )
436 {
437 char *line = valerie_response_get_line( response, index );
438 printf( "%4d: %s\n", index, line );
439 }
440 printf( "\n" );
441 terminated = 0;
442 }
443 }
444 }
445
446 printf( "\n" );
447
448 return error;
449 }
450
451 /** Add a file to the queue.
452 */
453
454 valerie_error_code dv_demo_queue_add( dv_demo demo, dv_demo_queue queue, char *file )
455 {
456 valerie_status_t status;
457 valerie_notifier notifier = valerie_get_notifier( demo->dv );
458
459 if ( ( queue->tail + 1 ) % 50 == queue->head )
460 queue->head = ( queue->head + 1 ) % 50;
461 strcpy( queue->list[ queue->tail ], file );
462 queue->tail = ( queue->tail + 1 ) % 50;
463
464 valerie_notifier_get( notifier, &status, queue->unit );
465 valerie_notifier_put( notifier, &status );
466
467 return valerie_ok;
468 }
469
470 /** Basic queue maintenance and status reports.
471 */
472
473 valerie_error_code dv_demo_queue_maintenance( dv_demo demo, dv_demo_queue queue )
474 {
475 printf( "Queue Maintenance for Unit %d\n\n", queue->unit );
476
477 if ( !queue->mode )
478 {
479 char ch;
480 printf( "Activate queueing? [Y] " );
481 ch = get_keypress( );
482 if ( ch == 'y' || ch == 'Y' || ch == '\r' )
483 queue->mode = 1;
484 printf( "\n\n" );
485 }
486
487 if ( queue->mode )
488 {
489 int terminated = 0;
490 int last_position = -2;
491
492 term_init( );
493
494 while ( !terminated )
495 {
496 int first = ( queue->position + 1 ) % 50;
497 int index = first;
498
499 if ( first == queue->tail )
500 index = first = queue->head;
501
502 if ( queue->head == queue->tail )
503 {
504 if ( last_position == -2 )
505 {
506 printf( "Queue is empty\n" );
507 printf( "\n" );
508 printf( "0 = exit, t = turn off queueing\n\n" );
509 last_position = -1;
510 }
511 }
512 else if ( last_position != queue->position )
513 {
514 printf( "Order of play\n\n" );
515
516 do
517 {
518 printf( "%c%02d: %s\n", index == first ? '*' : ' ', index, queue->list[ index ] + 1 );
519 index = ( index + 1 ) % 50;
520 if ( index == queue->tail )
521 index = queue->head;
522 }
523 while( index != first );
524
525 printf( "\n" );
526 printf( "0 = exit, t = turn off queueing, c = clear queue\n\n" );
527 last_position = queue->position;
528 }
529
530 dv_demo_change_status( demo, 1 );
531
532 switch( term_read( ) )
533 {
534 case -1:
535 break;
536 case '0':
537 terminated = 1;
538 break;
539 case 't':
540 terminated = 1;
541 queue->mode = 0;
542 break;
543 case 'c':
544 queue->head = queue->tail = 0;
545 queue->position = -1;
546 last_position = -2;
547 break;
548 }
549
550 dv_demo_change_status( demo, 0 );
551 }
552
553 term_exit( );
554 }
555
556 return valerie_ok;
557 }
558
559 /** Load a file to the selected unit. Horrible function - sorry :-/. Not a good
560 demo....
561 */
562
563 valerie_error_code dv_demo_load( dv_demo demo )
564 {
565 valerie_error_code error = valerie_ok;
566 int terminated = 0;
567 int refresh = 1;
568 int start = 0;
569
570 strcpy( demo->current_directory, demo->last_directory );
571
572 term_init( );
573
574 while ( !terminated )
575 {
576 valerie_dir dir = valerie_dir_init( demo->dv, demo->current_directory );
577
578 if ( valerie_dir_count( dir ) == -1 )
579 {
580 printf( "Invalid directory - retrying %s\n", demo->last_directory );
581 valerie_dir_close( dir );
582 dir = valerie_dir_init( demo->dv, demo->last_directory );
583 if ( valerie_dir_count( dir ) == -1 )
584 {
585 printf( "Invalid directory - going back to /\n" );
586 valerie_dir_close( dir );
587 dir = valerie_dir_init( demo->dv, "/" );
588 strcpy( demo->current_directory, "/" );
589 }
590 else
591 {
592 strcpy( demo->current_directory, demo->last_directory );
593 }
594 }
595
596 terminated = valerie_dir_count( dir ) == -1;
597
598 if ( !terminated )
599 {
600 int index = 0;
601 int selected = 0;
602 int max = 9;
603 int end = 0;
604
605 end = valerie_dir_count( dir );
606
607 strcpy( demo->last_directory, demo->current_directory );
608
609 while ( !selected && !terminated )
610 {
611 valerie_dir_entry_t entry;
612 int pressed;
613
614 if ( refresh )
615 {
616 char *action = "Load & Play";
617 if ( demo->queues[ demo->selected_unit ].mode )
618 action = "Queue";
619 printf( "%s from %s\n\n", action, demo->current_directory );
620 if ( strcmp( demo->current_directory, "/" ) )
621 printf( "-: Parent directory\n" );
622 for ( index = start; index < end && ( index - start ) < max; index ++ )
623 {
624 valerie_dir_get( dir, index, &entry );
625 printf( "%d: %s\n", index - start + 1, entry.name );
626 }
627 while ( ( index ++ % 9 ) != 0 )
628 printf( "\n" );
629 printf( "\n" );
630 if ( start + max < end )
631 printf( "space = more files" );
632 else if ( end > max )
633 printf( "space = return to start of list" );
634 if ( start > 0 )
635 printf( ", b = previous files" );
636 printf( "\n" );
637 printf( "0 = abort, t = transport, x = execute command, q = queue maintenance\n\n" );
638 refresh = 0;
639 }
640
641 dv_demo_change_status( demo, 1 );
642
643 pressed = term_read( );
644 switch( pressed )
645 {
646 case -1:
647 break;
648 case '0':
649 terminated = 1;
650 break;
651 case 'b':
652 refresh = start - max >= 0;
653 if ( refresh )
654 start = start - max;
655 break;
656 case ' ':
657 refresh = start + max < end;
658 if ( refresh )
659 {
660 start = start + max;
661 }
662 else if ( end > max )
663 {
664 start = 0;
665 refresh = 1;
666 }
667 break;
668 case '-':
669 if ( strcmp( demo->current_directory, "/" ) )
670 {
671 selected = 1;
672 ( *strrchr( demo->current_directory, '/' ) ) = '\0';
673 ( *( strrchr( demo->current_directory, '/' ) + 1 ) ) = '\0';
674 }
675 break;
676 case 't':
677 dv_demo_change_status( demo, 0 );
678 term_exit( );
679 dv_demo_transport( demo );
680 term_init( );
681 selected = 1;
682 break;
683 case 'x':
684 dv_demo_change_status( demo, 0 );
685 term_exit( );
686 dv_demo_execute( demo );
687 term_init( );
688 selected = 1;
689 break;
690 case 'q':
691 dv_demo_change_status( demo, 0 );
692 term_exit( );
693 dv_demo_queue_maintenance( demo, &demo->queues[ demo->selected_unit ] );
694 term_init( );
695 selected = 1;
696 break;
697 default:
698 if ( pressed >= '1' && pressed <= '9' )
699 {
700 if ( ( start + pressed - '1' ) < end )
701 {
702 valerie_dir_get( dir, start + pressed - '1', &entry );
703 selected = 1;
704 strcat( demo->current_directory, entry.name );
705 }
706 }
707 break;
708 }
709
710 dv_demo_change_status( demo, 0 );
711 }
712
713 valerie_dir_close( dir );
714 }
715
716 if ( !terminated && demo->current_directory[ strlen( demo->current_directory ) - 1 ] != '/' )
717 {
718 if ( demo->queues[ demo->selected_unit ].mode == 0 )
719 {
720 error = valerie_unit_load( demo->dv, demo->selected_unit, demo->current_directory );
721 valerie_unit_play( demo->dv, demo->selected_unit );
722 }
723 else
724 {
725 dv_demo_queue_add( demo, &demo->queues[ demo->selected_unit ], demo->current_directory );
726 printf( "File %s added to queue.\n", demo->current_directory );
727 }
728 strcpy( demo->current_directory, demo->last_directory );
729 refresh = 0;
730 }
731 else
732 {
733 refresh = 1;
734 start = 0;
735 }
736 }
737
738 term_exit( );
739
740 return error;
741 }
742
743 /** Set the in point of the clip on the select unit.
744 */
745
746 valerie_error_code dv_demo_set_in( dv_demo demo )
747 {
748 int position = 0;
749 valerie_status_t status;
750 valerie_notifier notifier = valerie_parser_get_notifier( demo->parser );
751 valerie_notifier_get( notifier, &status, demo->selected_unit );
752 position = status.position;
753 return valerie_unit_set_in( demo->dv, demo->selected_unit, position );
754 }
755
756 /** Set the out point of the clip on the selected unit.
757 */
758
759 valerie_error_code dv_demo_set_out( dv_demo demo )
760 {
761 int position = 0;
762 valerie_status_t status;
763 valerie_notifier notifier = valerie_parser_get_notifier( demo->parser );
764 valerie_notifier_get( notifier, &status, demo->selected_unit );
765 position = status.position;
766 return valerie_unit_set_out( demo->dv, demo->selected_unit, position );
767 }
768
769 /** Clear the in and out points on the selected unit.
770 */
771
772 valerie_error_code dv_demo_clear_in_out( dv_demo demo )
773 {
774 return valerie_unit_clear_in_out( demo->dv, demo->selected_unit );
775 }
776
777 /** Goto a user specified frame on the selected unit.
778 */
779
780 valerie_error_code dv_demo_goto( dv_demo demo )
781 {
782 int frame = 0;
783 printf( "Frame: " );
784 if ( get_int( &frame, 0 ) )
785 return valerie_unit_goto( demo->dv, demo->selected_unit, frame );
786 return valerie_ok;
787 }
788
789 /** Manipulate playback on the selected unit.
790 */
791
792 valerie_error_code dv_demo_transport( dv_demo demo )
793 {
794 valerie_error_code error = valerie_ok;
795 int refresh = 1;
796 int terminated = 0;
797 valerie_status_t status;
798 valerie_notifier notifier = valerie_get_notifier( demo->dv );
799
800 while ( !terminated )
801 {
802 if ( refresh )
803 {
804 printf( " +----+ +------+ +----+ +------+ +---+ +-----+ +------+ +-----+ +---+ \n" );
805 printf( " |1=-5| |2=-2.5| |3=-1| |4=-0.5| |5=1| |6=0.5| |7=1.25| |8=2.5| |9=5| \n" );
806 printf( " +----+ +------+ +----+ +------+ +---+ +-----+ +------+ +-----+ +---+ \n" );
807 printf( "\n" );
808 printf( "+----------------------------------------------------------------------+\n" );
809 printf( "| 0 = quit, x = eXecute, 'space' = pause |\n" );
810 printf( "| g = goto a frame, q = queue maintenance |\n" );
811 printf( "| h = step -1, j = end of clip, k = start of clip, l = step 1 |\n" );
812 printf( "| eof handling: p = pause, r = repeat, t = terminate |\n" );
813 printf( "| i = set in point, o = set out point, c = clear in/out |\n" );
814 printf( "| u = use point settings, d = don't use point settings |\n" );
815 printf( "+----------------------------------------------------------------------+\n" );
816 printf( "\n" );
817 term_init( );
818 refresh = 0;
819 }
820
821 dv_demo_change_status( demo, 1 );
822
823 switch( term_read( ) )
824 {
825 case '0':
826 terminated = 1;
827 break;
828 case -1:
829 break;
830 case ' ':
831 error = valerie_unit_pause( demo->dv, demo->selected_unit );
832 break;
833 case '1':
834 error = valerie_unit_play_at_speed( demo->dv, demo->selected_unit, -5000 );
835 break;
836 case '2':
837 error = valerie_unit_play_at_speed( demo->dv, demo->selected_unit, -2500 );
838 break;
839 case '3':
840 error = valerie_unit_play_at_speed( demo->dv, demo->selected_unit, -1000 );
841 break;
842 case '4':
843 error = valerie_unit_play_at_speed( demo->dv, demo->selected_unit, -500 );
844 break;
845 case '5':
846 error = valerie_unit_play( demo->dv, demo->selected_unit );
847 break;
848 case '6':
849 error = valerie_unit_play_at_speed( demo->dv, demo->selected_unit, 500 );
850 break;
851 case '7':
852 error = valerie_unit_play_at_speed( demo->dv, demo->selected_unit, 1250 );
853 break;
854 case '8':
855 error = valerie_unit_play_at_speed( demo->dv, demo->selected_unit, 2500 );
856 break;
857 case '9':
858 error = valerie_unit_play_at_speed( demo->dv, demo->selected_unit, 5000 );
859 break;
860 case 's':
861 error = valerie_unit_goto( demo->dv, demo->selected_unit, 0 );
862 break;
863 case 'h':
864 error = valerie_unit_step( demo->dv, demo->selected_unit, -1 );
865 break;
866 case 'j':
867 valerie_notifier_get( notifier, &status, demo->selected_unit );
868 error = valerie_unit_goto( demo->dv, demo->selected_unit, status.tail_out );
869 break;
870 case 'k':
871 valerie_notifier_get( notifier, &status, demo->selected_unit );
872 error = valerie_unit_goto( demo->dv, demo->selected_unit, status.in );
873 break;
874 case 'l':
875 error = valerie_unit_step( demo->dv, demo->selected_unit, 1 );
876 break;
877 case 'p':
878 error = valerie_unit_set( demo->dv, demo->selected_unit, "eof", "pause" );
879 break;
880 case 'r':
881 error = valerie_unit_set( demo->dv, demo->selected_unit, "eof", "loop" );
882 break;
883 case 't':
884 error = valerie_unit_set( demo->dv, demo->selected_unit, "eof", "stop" );
885 break;
886 case 'i':
887 error = dv_demo_set_in( demo );
888 break;
889 case 'o':
890 error = dv_demo_set_out( demo );
891 break;
892 case 'g':
893 dv_demo_change_status( demo, 0 );
894 term_exit( );
895 error = dv_demo_goto( demo );
896 refresh = 1;
897 break;
898 case 'c':
899 error = dv_demo_clear_in_out( demo );
900 break;
901 case 'u':
902 error = valerie_unit_set( demo->dv, demo->selected_unit, "points", "use" );
903 break;
904 case 'd':
905 error = valerie_unit_set( demo->dv, demo->selected_unit, "points", "ignore" );
906 break;
907 case 'x':
908 dv_demo_change_status( demo, 0 );
909 term_exit( );
910 dv_demo_execute( demo );
911 refresh = 1;
912 break;
913 case 'q':
914 dv_demo_change_status( demo, 0 );
915 term_exit( );
916 dv_demo_queue_maintenance( demo, &demo->queues[ demo->selected_unit ] );
917 refresh = 1;
918 break;
919 }
920
921 dv_demo_change_status( demo, 0 );
922 }
923
924 term_exit( );
925
926 return error;
927 }
928
929 /** Recursive menu execution.
930 */
931
932 valerie_error_code dv_demo_run_menu( dv_demo demo, dv_demo_menu menu )
933 {
934 char *items = "123456789abcdefghijklmnopqrstuvwxyz";
935 int refresh_menu = 1;
936 int terminated = 0;
937 int item_count = 0;
938 int item_selected = 0;
939 int index = 0;
940 char key;
941
942 while( !terminated )
943 {
944
945 if ( refresh_menu )
946 {
947 printf( "%s\n\n", menu->description );
948 for ( index = 0; menu->array[ index ].option != NULL; index ++ )
949 printf( "%c: %s\n", items[ index ], menu->array[ index ].option );
950 printf( "0: Exit\n\n" );
951 printf( "Select Option: " );
952 refresh_menu = 0;
953 item_count = index;
954 }
955
956 key = get_keypress( );
957
958 if ( demo->disconnected && key != '0' )
959 {
960 valerie_error_code error = valerie_connect( demo->dv );
961 if ( error == valerie_ok )
962 demo->disconnected = 0;
963 else
964 beep();
965 }
966
967 if ( !demo->disconnected || key == '0' )
968 {
969 item_selected = strchr( items, key ) - items;
970
971 if ( key == '0' )
972 {
973 printf( "%c\n\n", key );
974 terminated = 1;
975 }
976 else if ( item_selected >= 0 && item_selected < item_count )
977 {
978 printf( "%c\n\n", key );
979 menu->array[ item_selected ].function( demo );
980 refresh_menu = 1;
981 }
982 else
983 {
984 beep( );
985 }
986 }
987 }
988
989 return valerie_ok;
990 }
991
992 /** Entry point for main menu.
993 */
994
995 void dv_demo_run( dv_demo this )
996 {
997 this->dv = valerie_init( this->parser );
998 this->dv_status = valerie_init( this->parser );
999 if ( valerie_connect( this->dv ) == valerie_ok )
1000 {
1001 pthread_create( &this->thread, NULL, dv_demo_status_thread, this );
1002 dv_demo_run_menu( this, &connected_menu );
1003 this->terminated = 1;
1004 pthread_join( this->thread, NULL );
1005 this->terminated = 0;
1006 }
1007 else
1008 {
1009 printf( "Unable to connect." );
1010 wait_for_any_key( "" );
1011 }
1012
1013 valerie_close( this->dv_status );
1014 valerie_close( this->dv );
1015
1016 printf( "Demo Exit.\n" );
1017 }
1018
1019 /** Close the demo structure.
1020 */
1021
1022 void dv_demo_close( dv_demo demo )
1023 {
1024 free( demo );
1025 }