X-Git-Url: http://research.m1stereo.tv/gitweb?a=blobdiff_plain;f=src%2Fmvcp-client%2Fclient.c;fp=src%2Fmvcp-client%2Fclient.c;h=afd2bbda7205dc6f0aead2921ce59551dab72b29;hb=27f0329aa8f434794f1f18e018fc3221e58b77a4;hp=0000000000000000000000000000000000000000;hpb=f5a43889f0ea29962f2d32b5dab0fcd25bebb945;p=melted diff --git a/src/mvcp-client/client.c b/src/mvcp-client/client.c new file mode 100644 index 0000000..afd2bbd --- /dev/null +++ b/src/mvcp-client/client.c @@ -0,0 +1,1025 @@ +/* + * client.c -- Valerie client demo + * Copyright (C) 2002-2003 Ushodaya Enterprises Limited + * Author: Charles Yates + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +/* System header files */ +#include +#include +#include + +/* Application header files */ +#include "client.h" +#include "io.h" + +/** Clip navigation enumeration. +*/ + +typedef enum +{ + absolute, + relative +} +dv_demo_whence; + +/** Function prototype for menu handling. +*/ + +typedef valerie_error_code (*demo_function)( dv_demo ); + +/** The menu structure. +*/ + +typedef struct +{ + const char *description; + struct menu_item + { + const char *option; + demo_function function; + } + array[ 50 ]; +} +*dv_demo_menu, dv_demo_menu_t; + +/** Forward reference to menu runner. +*/ + +extern valerie_error_code dv_demo_run_menu( dv_demo, dv_demo_menu ); + +/** Foward references. +*/ + +extern valerie_error_code dv_demo_list_nodes( dv_demo ); +extern valerie_error_code dv_demo_add_unit( dv_demo ); +extern valerie_error_code dv_demo_select_unit( dv_demo ); +extern valerie_error_code dv_demo_execute( dv_demo ); +extern valerie_error_code dv_demo_load( dv_demo ); +extern valerie_error_code dv_demo_transport( dv_demo ); +static void *dv_demo_status_thread( void * ); + +/** Connected menu definition. +*/ + +dv_demo_menu_t connected_menu = +{ + "Connected Menu", + { + { "Add Unit", dv_demo_add_unit }, + { "Select Unit", dv_demo_select_unit }, + { "Command Shell", dv_demo_execute }, + { NULL, NULL } + } +}; + +/** Initialise the demo structure. +*/ + +dv_demo dv_demo_init( valerie_parser parser ) +{ + dv_demo this = malloc( sizeof( dv_demo_t ) ); + if ( this != NULL ) + { + int index = 0; + memset( this, 0, sizeof( dv_demo_t ) ); + strcpy( this->last_directory, "/" ); + for ( index = 0; index < 4; index ++ ) + { + this->queues[ index ].unit = index; + this->queues[ index ].position = -1; + } + this->parser = parser; + } + return this; +} + +/** Display a status record. +*/ + +void dv_demo_show_status( dv_demo demo, valerie_status status ) +{ + if ( status->unit == demo->selected_unit && demo->showing ) + { + char temp[ 1024 ] = ""; + + sprintf( temp, "U%d ", demo->selected_unit ); + + switch( status->status ) + { + case unit_offline: + strcat( temp, "offline " ); + break; + case unit_undefined: + strcat( temp, "undefined " ); + break; + case unit_not_loaded: + strcat( temp, "unloaded " ); + break; + case unit_stopped: + strcat( temp, "stopped " ); + break; + case unit_playing: + strcat( temp, "playing " ); + break; + case unit_paused: + strcat( temp, "paused " ); + break; + case unit_disconnected: + strcat( temp, "disconnect" ); + break; + default: + strcat( temp, "unknown " ); + break; + } + + sprintf( temp + strlen( temp ), " %9d %9d %9d ", status->in, status->position, status->out ); + strcat( temp, status->clip ); + + printf( "%-80.80s\r", temp ); + fflush( stdout ); + } +} + +/** Determine action to carry out as dictated by the client unit queue. +*/ + +void dv_demo_queue_action( dv_demo demo, valerie_status status ) +{ + dv_demo_queue queue = &demo->queues[ status->unit ]; + + /* SPECIAL CASE STATUS NOTIFICATIONS TO IGNORE */ + + /* When we've issued a LOAD on the previous notification, then ignore this one. */ + if ( queue->ignore ) + { + queue->ignore --; + return; + } + + if ( queue->mode && status->status != unit_offline && queue->head != queue->tail ) + { + if ( ( status->position >= status->out && status->speed > 0 ) || status->status == unit_not_loaded ) + { + queue->position = ( queue->position + 1 ) % 50; + if ( queue->position == queue->tail ) + queue->position = queue->head; + valerie_unit_load( demo->dv_status, status->unit, queue->list[ queue->position ] ); + if ( status->status == unit_not_loaded ) + valerie_unit_play( demo->dv, queue->unit ); + queue->ignore = 1; + } + else if ( ( status->position <= status->in && status->speed < 0 ) || status->status == unit_not_loaded ) + { + if ( queue->position == -1 ) + queue->position = queue->head; + valerie_unit_load( demo->dv_status, status->unit, queue->list[ queue->position ] ); + if ( status->status == unit_not_loaded ) + valerie_unit_play( demo->dv, queue->unit ); + queue->position = ( queue->position - 1 ) % 50; + queue->ignore = 1; + } + } +} + +/** Status thread. +*/ + +static void *dv_demo_status_thread( void *arg ) +{ + dv_demo demo = arg; + valerie_status_t status; + valerie_notifier notifier = valerie_get_notifier( demo->dv_status ); + + while ( !demo->terminated ) + { + if ( valerie_notifier_wait( notifier, &status ) != -1 ) + { + dv_demo_queue_action( demo, &status ); + dv_demo_show_status( demo, &status ); + if ( status.status == unit_disconnected ) + demo->disconnected = 1; + } + } + + return NULL; +} + +/** Turn on/off status display. +*/ + +void dv_demo_change_status( dv_demo demo, int flag ) +{ + if ( demo->disconnected && flag ) + { + valerie_error_code error = valerie_connect( demo->dv ); + if ( error == valerie_ok ) + demo->disconnected = 0; + else + beep(); + } + + if ( flag ) + { + valerie_status_t status; + valerie_notifier notifier = valerie_get_notifier( demo->dv ); + valerie_notifier_get( notifier, &status, demo->selected_unit ); + demo->showing = 1; + dv_demo_show_status( demo, &status ); + } + else + { + demo->showing = 0; + printf( "%-80.80s\r", " " ); + fflush( stdout ); + } +} + +/** Add a unit. +*/ + +valerie_error_code dv_demo_add_unit( dv_demo demo ) +{ + valerie_error_code error = valerie_ok; + valerie_nodes nodes = valerie_nodes_init( demo->dv ); + valerie_units units = valerie_units_init( demo->dv ); + + if ( valerie_nodes_count( nodes ) != -1 && valerie_units_count( units ) != -1 ) + { + char pressed; + valerie_node_entry_t node; + valerie_unit_entry_t unit; + int node_index = 0; + int unit_index = 0; + + printf( "Select a Node\n\n" ); + + for ( node_index = 0; node_index < valerie_nodes_count( nodes ); node_index ++ ) + { + valerie_nodes_get( nodes, node_index, &node ); + printf( "%d: %s - %s ", node_index + 1, node.guid, node.name ); + for ( unit_index = 0; unit_index < valerie_units_count( units ); unit_index ++ ) + { + valerie_units_get( units, unit_index, &unit ); + if ( !strcmp( unit.guid, node.guid ) ) + printf( "[U%d] ", unit.unit ); + } + printf( "\n" ); + } + + printf( "0. Exit\n\n" ); + + printf( "Node: " ); + + while ( ( pressed = get_keypress( ) ) != '0' ) + { + node_index = pressed - '1'; + if ( node_index >= 0 && node_index < valerie_nodes_count( nodes ) ) + { + int unit; + printf( "%c\n\n", pressed ); + valerie_nodes_get( nodes, node_index, &node ); + if ( valerie_unit_add( demo->dv, node.guid, &unit ) == valerie_ok ) + { + printf( "Unit added as U%d\n", unit ); + demo->selected_unit = unit; + } + else + { + int index = 0; + valerie_response response = valerie_get_last_response( demo->dv ); + printf( "Failed to add unit:\n\n" ); + for( index = 1; index < valerie_response_count( response ) - 1; index ++ ) + printf( "%s\n", valerie_response_get_line( response, index ) ); + } + printf( "\n" ); + wait_for_any_key( NULL ); + break; + } + else + { + beep( ); + } + } + } + else + { + printf( "Invalid response from the server.\n\n" ); + wait_for_any_key( NULL ); + } + + valerie_nodes_close( nodes ); + valerie_units_close( units ); + + return error; +} + +/** Select a unit. +*/ + +valerie_error_code dv_demo_select_unit( dv_demo demo ) +{ + int terminated = 0; + int refresh = 1; + + while ( !terminated ) + { + valerie_units units = valerie_units_init( demo->dv ); + + if ( valerie_units_count( units ) > 0 ) + { + valerie_unit_entry_t unit; + int index = 0; + char key = '\0'; + + if ( refresh ) + { + printf( "Select a Unit\n\n" ); + + for ( index = 0; index < valerie_units_count( units ); index ++ ) + { + valerie_units_get( units, index, &unit ); + printf( "%d: U%d - %s [%s]\n", index + 1, + unit.unit, + unit.guid, + unit.online ? "online" : "offline" ); + } + printf( "0: Exit\n\n" ); + + printf( "Unit [%d]: ", demo->selected_unit + 1 ); + refresh = 0; + } + + key = get_keypress( ); + + if ( key == '\r' ) + key = demo->selected_unit + '1'; + + if ( key != '0' ) + { + if ( key >= '1' && key < '1' + valerie_units_count( units ) ) + { + demo->selected_unit = key - '1'; + printf( "%c\n\n", key ); + dv_demo_load( demo ); + refresh = 1; + } + else + { + beep( ); + } + } + else + { + printf( "0\n\n" ); + terminated = 1; + } + } + else if ( valerie_units_count( units ) == 0 ) + { + printf( "No units added - add a unit first\n\n" ); + dv_demo_add_unit( demo ); + } + else + { + printf( "Unable to obtain Unit List.\n" ); + terminated = 1; + } + + valerie_units_close( units ); + } + + return valerie_ok; +} + +/** Execute an arbitrary command. +*/ + +valerie_error_code dv_demo_execute( dv_demo demo ) +{ + valerie_error_code error = valerie_ok; + char command[ 10240 ]; + int terminated = 0; + + printf( "Miracle Shell\n" ); + printf( "Enter an empty command to exit.\n\n" ); + + while ( !terminated ) + { + terminated = 1; + printf( "Command> " ); + + if ( chomp( io_get_string( command, 10240, "" ) ) != NULL ) + { + if ( strcmp( command, "" ) ) + { + int index = 0; + valerie_response response = NULL; + error = valerie_execute( demo->dv, 10240, command ); + printf( "\n" ); + response = valerie_get_last_response( demo->dv ); + for ( index = 0; index < valerie_response_count( response ); index ++ ) + { + char *line = valerie_response_get_line( response, index ); + printf( "%4d: %s\n", index, line ); + } + printf( "\n" ); + terminated = 0; + } + } + } + + printf( "\n" ); + + return error; +} + +/** Add a file to the queue. +*/ + +valerie_error_code dv_demo_queue_add( dv_demo demo, dv_demo_queue queue, char *file ) +{ + valerie_status_t status; + valerie_notifier notifier = valerie_get_notifier( demo->dv ); + + if ( ( queue->tail + 1 ) % 50 == queue->head ) + queue->head = ( queue->head + 1 ) % 50; + strcpy( queue->list[ queue->tail ], file ); + queue->tail = ( queue->tail + 1 ) % 50; + + valerie_notifier_get( notifier, &status, queue->unit ); + valerie_notifier_put( notifier, &status ); + + return valerie_ok; +} + +/** Basic queue maintenance and status reports. +*/ + +valerie_error_code dv_demo_queue_maintenance( dv_demo demo, dv_demo_queue queue ) +{ + printf( "Queue Maintenance for Unit %d\n\n", queue->unit ); + + if ( !queue->mode ) + { + char ch; + printf( "Activate queueing? [Y] " ); + ch = get_keypress( ); + if ( ch == 'y' || ch == 'Y' || ch == '\r' ) + queue->mode = 1; + printf( "\n\n" ); + } + + if ( queue->mode ) + { + int terminated = 0; + int last_position = -2; + + term_init( ); + + while ( !terminated ) + { + int first = ( queue->position + 1 ) % 50; + int index = first; + + if ( first == queue->tail ) + index = first = queue->head; + + if ( queue->head == queue->tail ) + { + if ( last_position == -2 ) + { + printf( "Queue is empty\n" ); + printf( "\n" ); + printf( "0 = exit, t = turn off queueing\n\n" ); + last_position = -1; + } + } + else if ( last_position != queue->position ) + { + printf( "Order of play\n\n" ); + + do + { + printf( "%c%02d: %s\n", index == first ? '*' : ' ', index, queue->list[ index ] + 1 ); + index = ( index + 1 ) % 50; + if ( index == queue->tail ) + index = queue->head; + } + while( index != first ); + + printf( "\n" ); + printf( "0 = exit, t = turn off queueing, c = clear queue\n\n" ); + last_position = queue->position; + } + + dv_demo_change_status( demo, 1 ); + + switch( term_read( ) ) + { + case -1: + break; + case '0': + terminated = 1; + break; + case 't': + terminated = 1; + queue->mode = 0; + break; + case 'c': + queue->head = queue->tail = 0; + queue->position = -1; + last_position = -2; + break; + } + + dv_demo_change_status( demo, 0 ); + } + + term_exit( ); + } + + return valerie_ok; +} + +/** Load a file to the selected unit. Horrible function - sorry :-/. Not a good + demo.... +*/ + +valerie_error_code dv_demo_load( dv_demo demo ) +{ + valerie_error_code error = valerie_ok; + int terminated = 0; + int refresh = 1; + int start = 0; + + strcpy( demo->current_directory, demo->last_directory ); + + term_init( ); + + while ( !terminated ) + { + valerie_dir dir = valerie_dir_init( demo->dv, demo->current_directory ); + + if ( valerie_dir_count( dir ) == -1 ) + { + printf( "Invalid directory - retrying %s\n", demo->last_directory ); + valerie_dir_close( dir ); + dir = valerie_dir_init( demo->dv, demo->last_directory ); + if ( valerie_dir_count( dir ) == -1 ) + { + printf( "Invalid directory - going back to /\n" ); + valerie_dir_close( dir ); + dir = valerie_dir_init( demo->dv, "/" ); + strcpy( demo->current_directory, "/" ); + } + else + { + strcpy( demo->current_directory, demo->last_directory ); + } + } + + terminated = valerie_dir_count( dir ) == -1; + + if ( !terminated ) + { + int index = 0; + int selected = 0; + int max = 9; + int end = 0; + + end = valerie_dir_count( dir ); + + strcpy( demo->last_directory, demo->current_directory ); + + while ( !selected && !terminated ) + { + valerie_dir_entry_t entry; + int pressed; + + if ( refresh ) + { + const char *action = "Load & Play"; + if ( demo->queues[ demo->selected_unit ].mode ) + action = "Queue"; + printf( "%s from %s\n\n", action, demo->current_directory ); + if ( strcmp( demo->current_directory, "/" ) ) + printf( "-: Parent directory\n" ); + for ( index = start; index < end && ( index - start ) < max; index ++ ) + { + valerie_dir_get( dir, index, &entry ); + printf( "%d: %s\n", index - start + 1, entry.name ); + } + while ( ( index ++ % 9 ) != 0 ) + printf( "\n" ); + printf( "\n" ); + if ( start + max < end ) + printf( "space = more files" ); + else if ( end > max ) + printf( "space = return to start of list" ); + if ( start > 0 ) + printf( ", b = previous files" ); + printf( "\n" ); + printf( "0 = abort, t = transport, x = execute command, q = queue maintenance\n\n" ); + refresh = 0; + } + + dv_demo_change_status( demo, 1 ); + + pressed = term_read( ); + switch( pressed ) + { + case -1: + break; + case '0': + terminated = 1; + break; + case 'b': + refresh = start - max >= 0; + if ( refresh ) + start = start - max; + break; + case ' ': + refresh = start + max < end; + if ( refresh ) + { + start = start + max; + } + else if ( end > max ) + { + start = 0; + refresh = 1; + } + break; + case '-': + if ( strcmp( demo->current_directory, "/" ) ) + { + selected = 1; + ( *strrchr( demo->current_directory, '/' ) ) = '\0'; + ( *( strrchr( demo->current_directory, '/' ) + 1 ) ) = '\0'; + } + break; + case 't': + dv_demo_change_status( demo, 0 ); + term_exit( ); + dv_demo_transport( demo ); + term_init( ); + selected = 1; + break; + case 'x': + dv_demo_change_status( demo, 0 ); + term_exit( ); + dv_demo_execute( demo ); + term_init( ); + selected = 1; + break; + case 'q': + dv_demo_change_status( demo, 0 ); + term_exit( ); + dv_demo_queue_maintenance( demo, &demo->queues[ demo->selected_unit ] ); + term_init( ); + selected = 1; + break; + default: + if ( pressed >= '1' && pressed <= '9' ) + { + if ( ( start + pressed - '1' ) < end ) + { + valerie_dir_get( dir, start + pressed - '1', &entry ); + selected = 1; + strcat( demo->current_directory, entry.name ); + } + } + break; + } + + dv_demo_change_status( demo, 0 ); + } + + valerie_dir_close( dir ); + } + + if ( !terminated && demo->current_directory[ strlen( demo->current_directory ) - 1 ] != '/' ) + { + if ( demo->queues[ demo->selected_unit ].mode == 0 ) + { + error = valerie_unit_load( demo->dv, demo->selected_unit, demo->current_directory ); + valerie_unit_play( demo->dv, demo->selected_unit ); + } + else + { + dv_demo_queue_add( demo, &demo->queues[ demo->selected_unit ], demo->current_directory ); + printf( "File %s added to queue.\n", demo->current_directory ); + } + strcpy( demo->current_directory, demo->last_directory ); + refresh = 0; + } + else + { + refresh = 1; + start = 0; + } + } + + term_exit( ); + + return error; +} + +/** Set the in point of the clip on the select unit. +*/ + +valerie_error_code dv_demo_set_in( dv_demo demo ) +{ + int position = 0; + valerie_status_t status; + valerie_notifier notifier = valerie_parser_get_notifier( demo->parser ); + valerie_notifier_get( notifier, &status, demo->selected_unit ); + position = status.position; + return valerie_unit_set_in( demo->dv, demo->selected_unit, position ); +} + +/** Set the out point of the clip on the selected unit. +*/ + +valerie_error_code dv_demo_set_out( dv_demo demo ) +{ + int position = 0; + valerie_status_t status; + valerie_notifier notifier = valerie_parser_get_notifier( demo->parser ); + valerie_notifier_get( notifier, &status, demo->selected_unit ); + position = status.position; + return valerie_unit_set_out( demo->dv, demo->selected_unit, position ); +} + +/** Clear the in and out points on the selected unit. +*/ + +valerie_error_code dv_demo_clear_in_out( dv_demo demo ) +{ + return valerie_unit_clear_in_out( demo->dv, demo->selected_unit ); +} + +/** Goto a user specified frame on the selected unit. +*/ + +valerie_error_code dv_demo_goto( dv_demo demo ) +{ + int frame = 0; + printf( "Frame: " ); + if ( get_int( &frame, 0 ) ) + return valerie_unit_goto( demo->dv, demo->selected_unit, frame ); + return valerie_ok; +} + +/** Manipulate playback on the selected unit. +*/ + +valerie_error_code dv_demo_transport( dv_demo demo ) +{ + valerie_error_code error = valerie_ok; + int refresh = 1; + int terminated = 0; + valerie_status_t status; + valerie_notifier notifier = valerie_get_notifier( demo->dv ); + + while ( !terminated ) + { + if ( refresh ) + { + printf( " +----+ +------+ +----+ +------+ +---+ +-----+ +------+ +-----+ +---+ \n" ); + 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" ); + printf( " +----+ +------+ +----+ +------+ +---+ +-----+ +------+ +-----+ +---+ \n" ); + printf( "\n" ); + printf( "+----------------------------------------------------------------------+\n" ); + printf( "| 0 = quit, x = eXecute, 'space' = pause |\n" ); + printf( "| g = goto a frame, q = queue maintenance |\n" ); + printf( "| h = step -1, j = end of clip, k = start of clip, l = step 1 |\n" ); + printf( "| eof handling: p = pause, r = repeat, t = terminate |\n" ); + printf( "| i = set in point, o = set out point, c = clear in/out |\n" ); + printf( "| u = use point settings, d = don't use point settings |\n" ); + printf( "+----------------------------------------------------------------------+\n" ); + printf( "\n" ); + term_init( ); + refresh = 0; + } + + dv_demo_change_status( demo, 1 ); + + switch( term_read( ) ) + { + case '0': + terminated = 1; + break; + case -1: + break; + case ' ': + error = valerie_unit_pause( demo->dv, demo->selected_unit ); + break; + case '1': + error = valerie_unit_play_at_speed( demo->dv, demo->selected_unit, -5000 ); + break; + case '2': + error = valerie_unit_play_at_speed( demo->dv, demo->selected_unit, -2500 ); + break; + case '3': + error = valerie_unit_play_at_speed( demo->dv, demo->selected_unit, -1000 ); + break; + case '4': + error = valerie_unit_play_at_speed( demo->dv, demo->selected_unit, -500 ); + break; + case '5': + error = valerie_unit_play( demo->dv, demo->selected_unit ); + break; + case '6': + error = valerie_unit_play_at_speed( demo->dv, demo->selected_unit, 500 ); + break; + case '7': + error = valerie_unit_play_at_speed( demo->dv, demo->selected_unit, 1250 ); + break; + case '8': + error = valerie_unit_play_at_speed( demo->dv, demo->selected_unit, 2500 ); + break; + case '9': + error = valerie_unit_play_at_speed( demo->dv, demo->selected_unit, 5000 ); + break; + case 's': + error = valerie_unit_goto( demo->dv, demo->selected_unit, 0 ); + break; + case 'h': + error = valerie_unit_step( demo->dv, demo->selected_unit, -1 ); + break; + case 'j': + valerie_notifier_get( notifier, &status, demo->selected_unit ); + error = valerie_unit_goto( demo->dv, demo->selected_unit, status.tail_out ); + break; + case 'k': + valerie_notifier_get( notifier, &status, demo->selected_unit ); + error = valerie_unit_goto( demo->dv, demo->selected_unit, status.in ); + break; + case 'l': + error = valerie_unit_step( demo->dv, demo->selected_unit, 1 ); + break; + case 'p': + error = valerie_unit_set( demo->dv, demo->selected_unit, "eof", "pause" ); + break; + case 'r': + error = valerie_unit_set( demo->dv, demo->selected_unit, "eof", "loop" ); + break; + case 't': + error = valerie_unit_set( demo->dv, demo->selected_unit, "eof", "stop" ); + break; + case 'i': + error = dv_demo_set_in( demo ); + break; + case 'o': + error = dv_demo_set_out( demo ); + break; + case 'g': + dv_demo_change_status( demo, 0 ); + term_exit( ); + error = dv_demo_goto( demo ); + refresh = 1; + break; + case 'c': + error = dv_demo_clear_in_out( demo ); + break; + case 'u': + error = valerie_unit_set( demo->dv, demo->selected_unit, "points", "use" ); + break; + case 'd': + error = valerie_unit_set( demo->dv, demo->selected_unit, "points", "ignore" ); + break; + case 'x': + dv_demo_change_status( demo, 0 ); + term_exit( ); + dv_demo_execute( demo ); + refresh = 1; + break; + case 'q': + dv_demo_change_status( demo, 0 ); + term_exit( ); + dv_demo_queue_maintenance( demo, &demo->queues[ demo->selected_unit ] ); + refresh = 1; + break; + } + + dv_demo_change_status( demo, 0 ); + } + + term_exit( ); + + return error; +} + +/** Recursive menu execution. +*/ + +valerie_error_code dv_demo_run_menu( dv_demo demo, dv_demo_menu menu ) +{ + const char *items = "123456789abcdefghijklmnopqrstuvwxyz"; + int refresh_menu = 1; + int terminated = 0; + int item_count = 0; + int item_selected = 0; + int index = 0; + char key; + + while( !terminated ) + { + + if ( refresh_menu ) + { + printf( "%s\n\n", menu->description ); + for ( index = 0; menu->array[ index ].option != NULL; index ++ ) + printf( "%c: %s\n", items[ index ], menu->array[ index ].option ); + printf( "0: Exit\n\n" ); + printf( "Select Option: " ); + refresh_menu = 0; + item_count = index; + } + + key = get_keypress( ); + + if ( demo->disconnected && key != '0' ) + { + valerie_error_code error = valerie_connect( demo->dv ); + if ( error == valerie_ok ) + demo->disconnected = 0; + else + beep(); + } + + if ( !demo->disconnected || key == '0' ) + { + item_selected = strchr( items, key ) - items; + + if ( key == '0' ) + { + printf( "%c\n\n", key ); + terminated = 1; + } + else if ( item_selected >= 0 && item_selected < item_count ) + { + printf( "%c\n\n", key ); + menu->array[ item_selected ].function( demo ); + refresh_menu = 1; + } + else + { + beep( ); + } + } + } + + return valerie_ok; +} + +/** Entry point for main menu. +*/ + +void dv_demo_run( dv_demo this ) +{ + this->dv = valerie_init( this->parser ); + this->dv_status = valerie_init( this->parser ); + if ( valerie_connect( this->dv ) == valerie_ok ) + { + pthread_create( &this->thread, NULL, dv_demo_status_thread, this ); + dv_demo_run_menu( this, &connected_menu ); + this->terminated = 1; + pthread_join( this->thread, NULL ); + this->terminated = 0; + } + else + { + printf( "Unable to connect." ); + wait_for_any_key( "" ); + } + + valerie_close( this->dv_status ); + valerie_close( this->dv ); + + printf( "Demo Exit.\n" ); +} + +/** Close the demo structure. +*/ + +void dv_demo_close( dv_demo demo ) +{ + free( demo ); +}