www.pudn.com > xvoice-0.8.1.rar > gnomeMainWin.cc
/** * gnomeMainWin.cc * * Description: gnome implementation of GUI main window * * Copyright (c) 1999, David Z. Creemer. * See the LICENSE file. All rights not granted therein are reserved. * * @author David Z. Creemer * @version 1.0 * * 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., 675 Mass Ave, Cambridge, MA 02139, USA. * */ #include "config.h" #include#include #include #include #include #include #include "Voice.h" #ifdef WINLIST #include "TargetList.h" #endif #include "MainWin.h" #include "Error.h" #include "xvoice.h" #include #ifdef WINLIST gint sel_row = -1; gint targ_row = -1; #endif static void dismiss(int ev, void * mw, const char *ph, int val); class gnomeMainWindow : public MainWindow { public: gnomeMainWindow(); ~gnomeMainWindow(); void micOff(); void micOn(); #ifdef WINLIST void selectPrevious(); void selectNext(); void selectNumber(int); #endif void targState(bool, bool); void reco(const char *text, bool firm); void errorMsg(int sev, const char* fn, const char* fmt, ...); void vocab(bool active, char *name); int notify ( int socket_handle, int ( * recv_fn ) ( ), void * recv_data, void * client_data ); void initVocabs(); Target* getTarget() { return _target; } Target* getNavTarget(); bool setTarget(); friend MainWindow *getGnomeMainWindow(int argc, char **argv); protected: void createMainWindow(int argc, char** argv); #ifdef WINLIST void updateTargetList(); void fillTargetList(); #endif friend void dismiss(int ev, void * mw, const char *ph, int val); protected: GtkWidget *_mainwin; GtkWidget *_targetWindow; GtkWidget *_textWindow; GtkWidget *_statusBar; GtkWidget *_micButton; GtkWidget *_vocabWindow; guint _mic_signal; stack _errStack; bool _errVocab; #ifdef WINLIST TargetList _targetList; #endif Target *_target; Target *_navtarget; }; gnomeMainWindow::gnomeMainWindow() : _mainwin( NULL ) { _target = new Target; _navtarget = new Target; } gnomeMainWindow::~gnomeMainWindow() { gint width,height; #if 0 /* * I would really like the hpaned to remember its position. * but there's no way to query it. I'd also like the main * window to remember its size, but all the docs claim that's * the responsibilty of the WM. */ if (_mainwin->window != NULL) { gdk_window_get_size(_mainwin->window, &width, &height); printf("width %d height %d\n",width, height); gnome_config_set_int("/xvoice/layout/width", width); gnome_config_set_int("/xvoice/layout/height", height); gnome_config_set_int("/xvoice/layout/hpan", height); } #endif delete _target; delete _navtarget; } static void CloseUpShop( GtkWidget * widget, gpointer data ) { //deallocate memory??? exitVoice(); gtk_main_quit(); } static defVocab msgVocab[] = { { 0, "dismiss" }, { -1, NULL } }; static void dismiss(int ev, void * mw, const char *ph, int val) { gnomeMainWindow *gmw = (gnomeMainWindow*)mw; GtkWidget *dialog = gmw->_errStack.top(); switch (ev) { case G_FAIL: break; case G_SUCCESS: break; case G_RECO: gtk_widget_destroy(dialog); gmw->_errStack.pop(); if (gmw->_errStack.size() == 0) disableVocab("msgVocab"); break; } } void gnomeMainWindow::initVocabs() { installVocab("msgVocab", dismiss, msgVocab, (void *)this); } void gnomeMainWindow::errorMsg(int sev, const char* fn, const char* fmt, ...) { GtkWidget *dialog; fstring msg; va_list ap; va_start(ap, fmt); msg.vappendf(fmt, ap); msg.appendf(" in %s", fn); dialog = gnome_warning_dialog_parented(msg.c_str(), GTK_WINDOW(_mainwin)); _errStack.push(dialog); if (_errStack.size() == 1) enableVocab("msgVocab"); va_end(ap); } void gnomeMainWindow::vocab(bool active, char *name) { if (active) { gtk_clist_append( GTK_CLIST(_vocabWindow), &name); } else { int i; char *text; /* * XXX - I'm breaking the clist API here, because it's * braindamaged that you can't get a row count out of it. */ for (i = 0; i < GTK_CLIST(_vocabWindow)->rows; ++i) { gtk_clist_get_text(GTK_CLIST(_vocabWindow), i, 0, &text); if (!strcmp(name, text)) { gtk_clist_remove(GTK_CLIST(_vocabWindow), i); break; } } } gtk_clist_moveto(GTK_CLIST(_vocabWindow), GTK_CLIST(_vocabWindow)->rows, 0, 1, 0); } Target* gnomeMainWindow::getNavTarget() { _navtarget->set(GDK_WINDOW_XWINDOW(_mainwin->window)); return _navtarget; } bool gnomeMainWindow::setTarget( ) { bool ret; const char *name; ret = _target->focusedTarget(); name = _target->name(); if (name == NULL) { gtk_clist_set_text( GTK_CLIST( _targetWindow ), 0, 2, "-" ); } else { gtk_clist_set_text( GTK_CLIST( _targetWindow ), 0, 2, name ); } return ret; } int gnomeMainWindow::notify ( int socket_handle, int ( * recv_fn ) ( ), void * recv_data, void * client_data ) { int * x_input_id = ( int * ) client_data; if ( recv_fn == NULL ) { gdk_input_remove ( * x_input_id ); return ( 0 ); } * x_input_id = gdk_input_add ( socket_handle, ( GdkInputCondition) 1, ( GdkInputFunction ) recv_fn, recv_data ); return ( 0) ; } #if 0 GtkWidget* get_widget( GtkWidget *widget, gchar* widget_name) { GtkWidget *parent, *found_widget; for (;;) { if (GTK_IS_MENU (widget)) parent = gtk_menu_get_attach_widget (GTK_MENU (widget)); else parent = widget->parent; if (parent == NULL) break; widget = parent; } found_widget = (GtkWidget*) gtk_object_get_data (GTK_OBJECT (widget), widget_name); if (!found_widget) g_warning ("Widget not found: %s", widget_name); return found_widget; } #endif gchar* testchars[3] = { "X", "Y", "Z" }; #ifdef WINLIST void gnomeMainWindow::fillTargetList() { GtkWidget* clist = get_widget( _mainwin, "targetList" ); gtk_clist_clear( GTK_CLIST( clist ) ); int count = _targetList.count(); for ( int i=0; i name() ); } gtk_clist_thaw( GTK_CLIST(clist) ); if ( rows > 0 ) gtk_clist_select_row( GTK_CLIST( clist ), 0, 0 ); } #endif void ToggleMic( GtkWidget * widget, gpointer data ) { dbgprintf(("state %d\n", (GTK_TOGGLE_BUTTON (widget)->active))); if (GTK_TOGGLE_BUTTON (widget)->active) { vCommand (CMICON); } else { vCommand (CMICOFF); } } void gnomeMainWindow::micOn() { gtk_signal_handler_block(GTK_OBJECT(_micButton), _mic_signal); gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON(_micButton), TRUE); gtk_signal_handler_unblock(GTK_OBJECT(_micButton), _mic_signal); gnome_appbar_set_status(GNOME_APPBAR(_statusBar), "Mic is on"); } void gnomeMainWindow::micOff() { gtk_signal_handler_block(GTK_OBJECT(_micButton), _mic_signal); gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON(_micButton), FALSE); gtk_signal_handler_unblock(GTK_OBJECT(_micButton), _mic_signal); gnome_appbar_set_status(GNOME_APPBAR(_statusBar), "Mic is off"); } #ifdef WINLIST void gnomeMainWindow::selectPrevious() { GtkWidget* clist = get_widget( _mainwin, "targetList" ); sel_row--; if ( sel_row < 0 ) sel_row = 0; gtk_clist_select_row( GTK_CLIST( clist ), sel_row, 0 ); } void gnomeMainWindow::selectNext() { //!? there has to be a better way to get the row count in a list GtkWidget* clist = get_widget( _mainwin, "targetList" ); int rows = gtk_clist_append( GTK_CLIST( clist ), testchars ); gtk_clist_remove( GTK_CLIST( clist ), rows ); sel_row++; if ( sel_row >= rows ) sel_row = rows - 1; if ( sel_row >= 0 ) gtk_clist_select_row( GTK_CLIST( clist ), sel_row, 0 ); } void gnomeMainWindow::selectNumber(int n){ //!? there has to be a better way to get the row count in a list GtkWidget* clist = get_widget( _mainwin, "targetList" ); int rows = gtk_clist_append( GTK_CLIST( clist ), testchars ); gtk_clist_remove( GTK_CLIST( clist ), rows ); sel_row=n; if ( sel_row >= rows ) sel_row = rows - 1; if ( sel_row >= 0 ) gtk_clist_select_row( GTK_CLIST( clist ), sel_row, 0 ); } void gnomeMainWindow::rescanTargets() { _targetList.scanForTargets(); fillTargetList(); //figure out the target app to dictate into: GtkWidget* statusBar = get_widget( _mainwin, "statusBar" ); GtkWidget* clist = get_widget( _mainwin, "targetList" ); targ_row = sel_row; //since the addition of the windowmanager shortcuts we need a valid target right from the //off : gMainWin->setTarget( (Target*) gtk_clist_get_row_data( GTK_CLIST( clist ), targ_row ) ); gMainWin->setTarget( (Target*) gtk_clist_get_row_data( GTK_CLIST( clist ), targ_row ) ); } #endif #ifdef WINLIST void RescanTargets( GtkWidget * widget, gpointer data ) { gMainWin->rescanTargets(); } void resetSelection( GtkWidget* clist ) { if ( targ_row > -1 ) gtk_clist_set_text( GTK_CLIST( clist ), targ_row, 1, "-" ); targ_row = -1; } /**This method is called after the user says 'stop dictation' */ void IdleTarget( GtkWidget * widget, gpointer data ) { GtkWidget* statusBar = get_widget( widget, "statusBar" ); GtkWidget* clist = get_widget( widget, "targetList" ); resetSelection( clist ); //SM_MSG reply; //SmSet(SM_SAVE_AUDIO,FALSE,&reply); // ensure xvoice vocabs //enableXVoiceVocabs(); char buffer[1024]; sprintf( buffer, "Command target is '%s'", XVOICE_APPNAME ); gtk_statusbar_push( GTK_STATUSBAR( statusBar ), sel_contextid, buffer ); } /**This method is called after the user says 'command' It checks what the currently selected target is and then attempts to load a grammar (.fsg file) with the same root as the app name e.g. if the target app was emacs it would try to load emacs.fsg */ void CommandTarget( GtkWidget * widget, gpointer data ) { GtkWidget* statusBar = get_widget( widget, "statusBar" ); GtkWidget* clist = get_widget( widget, "targetList" ); resetSelection( clist ); targ_row = sel_row; //figure out the target app to dictate into: gMainWin->setTarget( (Target*) gtk_clist_get_row_data( GTK_CLIST( clist ), targ_row ) ); gtk_clist_set_text( GTK_CLIST( clist ), targ_row, 1, "Command" ); ClearCorrections(); //****************** //Enable application specific grammar here: if(!enableCommandGrammar()){ gMainWin->idle(); return; } //****************** char buffer[1024]; sprintf( buffer, "Commanding '%s'", gMainWin->getTarget()->name() ); gtk_statusbar_push( GTK_STATUSBAR( statusBar ), sel_contextid, buffer ); } /** This method is eventually called after the user says "Dictate" */ void DictateTarget( GtkWidget * widget, gpointer data ) { int rc; GtkWidget* statusBar = get_widget( widget, "statusBar" ); GtkWidget* clist = get_widget( widget, "targetList" ); resetSelection( clist ); targ_row = sel_row; //figure out the target app to dictate into: gMainWin->setTarget( (Target*) gtk_clist_get_row_data( GTK_CLIST( clist ), targ_row ) ); gtk_clist_set_text( GTK_CLIST( clist ), targ_row, 1, "Dictate" ); ClearCorrections(); enableDictationVocabs(); //SM_MSG reply; //rc=SmSet(SM_SAVE_AUDIO,TRUE,&reply); //rc=SmQuery(SM_SAVE_AUDIO,&reply); // printf("Saving audio: rc=%d\n",rc); //TurnMicOff(); //the mic will be turned back on in the //utterance cb when the engine is ready. char buffer[1024]; sprintf( buffer, "Dictating to '%s'", gMainWin->getTarget()->name() ); gtk_statusbar_push( GTK_STATUSBAR( statusBar ), sel_contextid, buffer ); } #endif /* previously these were invoked by a menu button. * Now they are invoked by the voice module when the state changes. * The menu options (when they reappear) will call the Voice module to * change the state. */ void gnomeMainWindow::targState(bool command, bool dictate) { if (command && dictate) gtk_clist_set_text( GTK_CLIST( _targetWindow ), 0, 1, "Command/Dictate" ); else if (command) gtk_clist_set_text( GTK_CLIST( _targetWindow ), 0, 1, "Command" ); else if (dictate) gtk_clist_set_text( GTK_CLIST( _targetWindow ), 0, 1, "Dictate" ); else gtk_clist_set_text( GTK_CLIST( _targetWindow ), 0, 1, "Idle" ); } void gnomeMainWindow::reco(const char *text, bool firm) { if (firm) gtk_text_insert (GTK_TEXT (_textWindow), NULL, &_textWindow->style->black, NULL, text, -1); else gtk_text_insert (GTK_TEXT (_textWindow), NULL, &_textWindow->style->mid[0], NULL, text, -1); gtk_text_insert (GTK_TEXT (_textWindow), NULL, &_textWindow->style->black, NULL, ", ", -1); } #if WINLIST void handleTargetSelect( GtkWidget *clist, gint row, gint column, GdkEventButton *event, gpointer data ) { sel_row = row; } #endif void closeabout( GtkWidget *w, gpointer d ) { gtk_widget_destroy( (GTK_WIDGET( d ) ) ); } void rebuild_cb( GtkWidget *w, gpointer d ) { loadGrammars(); } void showabout( GtkWidget *w, gpointer d ) { const gchar *authors[] = { "David Z. Creemer", "Tom Doris", "Brian Craft", NULL }; GtkWidget* about = gnome_about_new(_(PACKAGE), VERSION, "(c) 1999, 2000", authors, _("Voice enabled X"), NULL); gtk_widget_show( about ); } static GnomeUIInfo file_menu[] = { GNOMEUIINFO_MENU_EXIT_ITEM(CloseUpShop, NULL), GNOMEUIINFO_END }; static GnomeUIInfo grammar_menu[] = { { GNOME_APP_UI_ITEM, N_("_Rebuild"), N_("Rebuild grammar files"), rebuild_cb, NULL, NULL, GNOME_APP_PIXMAP_NONE, NULL, 'r', GDK_CONTROL_MASK, NULL }, GNOMEUIINFO_END }; static GnomeUIInfo help_menu[] = { GNOMEUIINFO_MENU_ABOUT_ITEM(showabout, NULL), GNOMEUIINFO_END }; static GnomeUIInfo main_menu[] = { GNOMEUIINFO_SUBTREE(N_("_File"), file_menu), GNOMEUIINFO_SUBTREE(N_("_Grammars"), grammar_menu), GNOMEUIINFO_SUBTREE(N_("_Help"), help_menu), GNOMEUIINFO_END }; void gnomeMainWindow::createMainWindow(int argc, char** argv) { GtkWidget *mainWindow; GtkWidget *vbox3; GtkWidget *scrolledwindow1; GtkWidget *label; GtkWidget *hbox5; GtkWidget *hpaned; gnome_init(PACKAGE, VERSION, argc, argv); mainWindow = gnome_app_new(PACKAGE, PACKAGE); gtk_window_set_policy (GTK_WINDOW(mainWindow), TRUE, TRUE, TRUE); vbox3 = gtk_vbox_new (FALSE, 0); gnome_app_set_contents (GNOME_APP(mainWindow), vbox3); gtk_widget_show (vbox3); #ifdef WINLIST GtkWidget *Rescan = gtk_menu_item_new_with_label ("Rescan"); gtk_object_set_data(GTK_OBJECT (mainWindow), "Rescan", Rescan); gtk_widget_show (Rescan); gtk_container_add (GTK_CONTAINER (File_menu), Rescan); gtk_signal_connect (GTK_OBJECT (Rescan), "activate", GTK_SIGNAL_FUNC ( RescanTargets ), mainWindow); #endif #ifdef WINLIST GtkWidget* Target = gtk_menu_item_new_with_label ("Target"); gtk_object_set_data (GTK_OBJECT (mainWindow), "Target", Target); gtk_widget_show (Target); gtk_container_add (GTK_CONTAINER (menubar1), Target); GtkWidget *Target_menu = gtk_menu_new (); gtk_object_set_data (GTK_OBJECT (mainWindow), "Target_menu", Target_menu); gtk_menu_item_set_submenu (GTK_MENU_ITEM (Target), Target_menu); GtkWidget *Idle = gtk_menu_item_new_with_label ("Idle"); gtk_object_set_data(GTK_OBJECT (mainWindow), "Idle", Idle); gtk_widget_show (Idle); gtk_container_add (GTK_CONTAINER (Target_menu), Idle); gtk_signal_connect (GTK_OBJECT (Idle), "activate", GTK_SIGNAL_FUNC ( IdleTarget ), mainWindow); GtkWidget *Command = gtk_menu_item_new_with_label ("Command"); gtk_object_set_data(GTK_OBJECT (mainWindow), "Command", Command); gtk_widget_show (Command); gtk_container_add (GTK_CONTAINER (Target_menu), Command); gtk_signal_connect (GTK_OBJECT (Command), "activate", GTK_SIGNAL_FUNC ( CommandTarget ), mainWindow); GtkWidget *Dictate = gtk_menu_item_new_with_label ("Dictate"); gtk_object_set_data(GTK_OBJECT (mainWindow), "Dictate", Dictate); gtk_widget_show (Dictate); gtk_container_add (GTK_CONTAINER (Target_menu), Dictate); gtk_signal_connect (GTK_OBJECT (Dictate), "activate", GTK_SIGNAL_FUNC ( DictateTarget ), mainWindow); #endif gnome_app_create_menus(GNOME_APP(mainWindow), main_menu); scrolledwindow1 = gtk_scrolled_window_new (NULL, NULL); gtk_object_set_data (GTK_OBJECT (mainWindow), "scrolledwindow1", scrolledwindow1); gtk_widget_show (scrolledwindow1); gtk_box_pack_start (GTK_BOX (vbox3), scrolledwindow1, FALSE, TRUE, 2); gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolledwindow1), GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC); _targetWindow = gtk_clist_new (3); gtk_widget_show (_targetWindow); gtk_container_add (GTK_CONTAINER (scrolledwindow1), _targetWindow); gtk_container_border_width (GTK_CONTAINER (_targetWindow), 1); gtk_clist_set_column_width (GTK_CLIST (_targetWindow), 0, 23); gtk_clist_set_column_width (GTK_CLIST (_targetWindow), 1, 73); gtk_clist_set_column_width (GTK_CLIST (_targetWindow), 2, 80); gtk_clist_column_titles_show (GTK_CLIST (_targetWindow)); #ifdef WINLIST gtk_signal_connect (GTK_OBJECT( targetList ), "select_row", GTK_SIGNAL_FUNC( handleTargetSelect ), mainWindow); #endif label = gtk_label_new("#"); gtk_widget_show (label); gtk_clist_set_column_widget (GTK_CLIST (_targetWindow), 0, label); label = gtk_label_new("Status"); gtk_widget_show (label); gtk_clist_set_column_widget(GTK_CLIST (_targetWindow), 1, label); label = gtk_label_new("Application"); gtk_widget_show(label); gtk_clist_set_column_widget(GTK_CLIST (_targetWindow), 2, label); hpaned = gtk_hpaned_new(); gtk_widget_show(hpaned); gtk_box_pack_start (GTK_BOX (vbox3), hpaned, TRUE, TRUE, 0); /* Create the vocab list */ _vocabWindow = gtk_clist_new (1); GTK_CLIST_SET_FLAG(_vocabWindow, CLIST_SHOW_TITLES); gtk_widget_show (_vocabWindow); /* turns out this won't center the title. a label will. */ //gtk_clist_set_column_title(GTK_CLIST(_vocabWindow), 0, "Vocabularies"); label = gtk_label_new("Vocabularies"); gtk_paned_pack1 (GTK_PANED (hpaned), _vocabWindow, TRUE, TRUE); gtk_widget_show (label); gtk_clist_set_column_widget (GTK_CLIST (_vocabWindow), 0, label); /* Create the GtkText widget */ _textWindow = gtk_text_new (NULL, NULL); gtk_text_set_editable (GTK_TEXT (_textWindow), FALSE); gtk_text_set_word_wrap(GTK_TEXT(_textWindow), TRUE); gtk_paned_pack2 (GTK_PANED (hpaned), _textWindow, TRUE, TRUE); gtk_widget_show (_textWindow); gtk_widget_set_usize(_textWindow, -1, 50); /* Realizing a widget creates a window for it, * ready for us to insert some text */ gtk_widget_realize (_textWindow); hbox5 = gtk_hbox_new(FALSE, 0); gtk_widget_show (hbox5); gtk_box_pack_start (GTK_BOX (vbox3), hbox5, FALSE, FALSE, 0); label = gtk_label_new(" Microphone: "); gtk_widget_show(label); gtk_box_pack_start(GTK_BOX (hbox5), label, FALSE, FALSE, 3); gtk_label_set_justify(GTK_LABEL (label), GTK_JUSTIFY_RIGHT); _micButton = gtk_toggle_button_new_with_label ("Push To Talk"); gtk_widget_show (_micButton); gtk_box_pack_start (GTK_BOX (hbox5), _micButton, FALSE, FALSE, 0); _mic_signal = gtk_signal_connect ( GTK_OBJECT ( _micButton ), "toggled", GTK_SIGNAL_FUNC ( ToggleMic ), NULL ); _statusBar = gnome_appbar_new (FALSE, TRUE, GNOME_PREFERENCES_USER); gnome_app_set_statusbar (GNOME_APP(mainWindow), _statusBar); gtk_widget_show (_statusBar); gnome_app_install_menu_hints(GNOME_APP(mainWindow), main_menu); #ifndef WINLIST char *initial_clist[] = { "0", "Idle", "-" }; gtk_clist_append( GTK_CLIST( _targetWindow ), initial_clist ); #endif gtk_signal_connect ( GTK_OBJECT ( mainWindow ), "destroy", GTK_SIGNAL_FUNC ( CloseUpShop ), NULL ); _mainwin = mainWindow; gtk_widget_show( _mainwin ); } MainWindow *getGnomeMainWindow(int argc, char **argv) { gnomeMainWindow *mw = new gnomeMainWindow(); mw->createMainWindow(argc, argv); return mw; }