julius/visual.c

Go to the documentation of this file.
00001 
00026 /*
00027  * Copyright (c) 2003-2005 Shikano Lab., Nara Institute of Science and Technology
00028  * Copyright (c) 2005-2006 Julius project team, Nagoya Institute of Technology
00029  * All rights reserved
00030  */
00031 
00032 #include <julius.h>
00033 
00034 #ifdef VISUALIZE
00035 
00036 #include <gtk/gtk.h>
00037 
00038 /* Window constant properties */
00039 #define WINTITLE "Julius word trellis viewer" 
00040 #define DEFAULT_WINDOW_WIDTH 800 
00041 #define DEFAULT_WINDOW_HEIGHT 600 
00042 #define CANVAS_MARGIN 16 
00043 #define WAVE_HEIGHT 48 
00044 #define WAVE_MARGIN 6 
00045 #define RESULT_HEIGHT 0 
00046 #define FONTSET "-*-fixed-medium-r-normal--10-*-*-*-*-*-*-*" 
00047 
00048 /* global valuables for window handling */
00049 static GdkFont *fontset;        
00050 static GdkPixmap *pixmap = NULL; 
00051 static gint canvas_width;       
00052 static gint canvas_height;      
00053 
00054 
00055 /**********************************************************************/
00056 /* view configuration switches */
00057 /**********************************************************************/
00058 static boolean sw_wid_axis = TRUE; 
00059 static boolean sw_score_beam = FALSE; 
00060 static boolean sw_text = TRUE;  
00061 static boolean sw_line = TRUE;  
00062 static boolean sw_level_thres = FALSE; 
00063 static boolean sw_hypo = FALSE;         
00064 
00065 /**********************************************************************/
00066 /* data to plot (1st pass / 2nd pass) */
00067 /**********************************************************************/
00068 /* data to plot on 1st pass */
00069 static BACKTRELLIS *btlocal = NULL; 
00070 /* data to plot on 2nd pass */
00071 static POPNODE *popped = NULL;  
00072 static int pnum;                
00073 static POPNODE *lastpop = NULL; 
00074 
00075 
00076 /**********************************************************************/
00077 /* GTK color allocation */
00078 /**********************************************************************/
00079 
00080 #define NCOLS 15
00081 static GdkColor cols[NCOLS] = {
00082   {0, 63000, 63000, 63000},     /* background */
00083   {0,     0,     0, 40000},     /* waveform */
00084   {0, 50000, 20000,     0},     /* waveform level threshold line */
00085   {0,     0,     0, 65535},     /* begin node of word arc */
00086   {0, 60000, 60000,     0},     /* end node of word arc */
00087   {0, 24000, 32000, 24000},     /* line (context word / word graph) */
00088   {0, 10000, 10000, 40000},     /* text (context word / word graph) */
00089   {0, 50000, 54000, 50000},     /* line (word indexed trellis = all survived words) */
00090   {0, 50000, 30000,     0},     /* line (best path) */
00091   {0, 55535,     0,     0},     /* end node (best path) */
00092   {0, 50000, 30000,     0},     /* text (best path) */
00093   {0, 12000, 20000, 12000},     /* line and text (2nd pass) */
00094   {0, 50000, 50000, 12000},     /* line and text (2nd pass popped) */
00095   {0, 50000,     0,     0},     /* 2nd pass best */
00096   {0,     0,     0,     0}      /* shadow for text decoration */
00097 };
00098 typedef enum {C_BG, C_WAVEFORM, C_LEVELTHRES, C_BGN, C_END, C_LINE, C_TEXT, C_LINE_FAINT, C_LINE_BEST, C_END_BEST, C_TEXT_BEST, C_PASS2_NEXT, C_PASS2, C_PASS2_BEST, C_SHADOW} UserColors;
00099 
00100 static GdkGC *dgc = NULL;               
00101 
00110 static void
00111 color_init()
00112 {
00113   GdkColormap *defcolmap;
00114   gboolean success[NCOLS];
00115   
00116   defcolmap = gdk_colormap_get_system();
00117   if (gdk_colormap_alloc_colors(defcolmap, cols, NCOLS, FALSE, TRUE, success) > 0) {
00118     j_printerr("Warning: some colors are not allocated\n");
00119   }
00120 
00121 }
00122 
00123 
00124 /**********************************************************************/
00125 /* graph scaling */
00126 /**********************************************************************/
00127 
00128 static LOGPROB *ftop = NULL;    
00129 static LOGPROB *fbottom = NULL; 
00130 static LOGPROB lowest;          
00131 static LOGPROB maxrange;        
00132 static LOGPROB maxrange2;       
00133 
00146 static void
00147 get_max_frame_score(BACKTRELLIS *bt)
00148 {
00149   int t, i;
00150   TRELLIS_ATOM *tre;
00151   LOGPROB x,y;
00152 
00153   /* allocate */
00154   if (ftop != NULL) free(ftop);
00155   ftop = mymalloc(sizeof(LOGPROB) * bt->framelen);
00156   if (fbottom != NULL) free(fbottom);
00157   fbottom = mymalloc(sizeof(LOGPROB) * bt->framelen);
00158 
00159   /* get maxrange, ftop[], fbottom[] */
00160   maxrange = 0.0;
00161   for (t=0;t<bt->framelen;t++) {
00162     x = LOG_ZERO;
00163     y = 0.0;
00164     for (i=0;i<bt->num[t];i++) {
00165       tre = bt->rw[t][i];
00166       if (x < tre->backscore) x = tre->backscore;
00167       if (y > tre->backscore) y = tre->backscore;
00168     }
00169     ftop[t] = x;
00170     fbottom[t] = y;
00171     if (maxrange < x - y) maxrange = x - y;
00172   }
00173 
00174   /* get the lowest score and range around y=(lowest/framelen)x */
00175   lowest = 0.0;
00176   for (t=0;t<bt->framelen;t++) {
00177     if (lowest > fbottom[t]) lowest = fbottom[t];
00178   }
00179   maxrange2 = 0.0;
00180   for (t=0;t<bt->framelen;t++) {
00181     x = lowest * (float)t / (float)bt->framelen;
00182     if (ftop[t] == LOG_ZERO) continue;
00183     if (maxrange2 < abs(ftop[t] - x)) maxrange2 = abs(ftop[t] - x);
00184     if (maxrange2 < abs(fbottom[t] - x)) maxrange2 = abs(fbottom[t] - x);
00185   }
00186 }
00187 
00204 static gint
00205 scale_x(int t)
00206 {
00207   return(t * (canvas_width - CANVAS_MARGIN * 2) / btlocal->framelen + CANVAS_MARGIN);
00208 }
00209 
00228 static gint
00229 scale_y(LOGPROB s, int t)
00230 {
00231   gint y;
00232   LOGPROB top, bottom;
00233   gint yoffset, height;
00234   
00235   if (sw_score_beam) {
00236     /* beam threshold-based: upper is the maximum score on the frame */
00237     top = ftop[t];
00238     if (top == LOG_ZERO) {      /* no token found on the time */
00239       bottom = top;
00240     } else {
00241       bottom = ftop[t] - maxrange;
00242     }
00243   } else {
00244     /* total score based: show around (lowest/framelen) x time */
00245     top = lowest * (float)t / (float)btlocal->framelen + maxrange2;
00246     bottom = lowest * (float)t / (float)btlocal->framelen - maxrange2;
00247   }
00248 
00249   yoffset = CANVAS_MARGIN + RESULT_HEIGHT + (speechlen != 0 ? (WAVE_MARGIN + WAVE_HEIGHT): 0);
00250   height = canvas_height - yoffset - CANVAS_MARGIN;
00251   if (top <= bottom) {  /* single or no token on the time */
00252     y = yoffset;
00253   } else {
00254     y = (top - s) * height / (top - bottom) + yoffset;
00255   }
00256   return(y);
00257 }
00258 
00275 static gint
00276 scale_y_wid(WORD_ID wid)
00277 {
00278   gint y;
00279   gint yoffset, height;
00280   
00281   yoffset = CANVAS_MARGIN + RESULT_HEIGHT + (speechlen != 0 ? (WAVE_MARGIN + WAVE_HEIGHT) : 0);
00282   height = canvas_height - yoffset - CANVAS_MARGIN;
00283   if (wid == WORD_INVALID) {
00284     y = yoffset;
00285   } else {
00286     y = wid * height / winfo->num + yoffset;
00287   }
00288   return(y);
00289 }
00290 
00291 
00292 /**********************************************************************/
00293 /* Draw wave data */
00294 /**********************************************************************/
00295 static SP16 max_level;          
00296 
00313 static gint
00314 scale_x_wave(int t)
00315 {
00316   return(t * (canvas_width - CANVAS_MARGIN * 2) / speechlen + CANVAS_MARGIN);
00317 }
00318 
00335 static gint
00336 scale_y_wave(SP16 x)
00337 {
00338   return(WAVE_HEIGHT / 2 + WAVE_MARGIN - (x * WAVE_HEIGHT / (max_level * 2)));
00339 }
00340 
00351 static void
00352 get_max_waveform_level()
00353 {
00354   int t;
00355   SP16 maxl;
00356   
00357   if (speechlen == 0) return;   /* no waveform data (MFCC) */
00358   
00359   maxl = 0;
00360   for(t=0;t<speechlen;t++) {
00361     if (maxl < abs(speech[t])) {
00362       maxl = abs(speech[t]);
00363     }
00364   }
00365 
00366   max_level = maxl;
00367   if (max_level < 3000) max_level = 3000;
00368 }
00369 
00382 static void
00383 draw_waveform(GtkWidget *widget)
00384 {
00385   int t;
00386   gint text_width;
00387   static char buf[20];
00388 
00389   if (speechlen == 0) return;   /* no waveform data (MFCC) */
00390 
00391   /* first time, make gc for drawing */
00392   if (dgc == NULL) {
00393     dgc = gdk_gc_new(widget->window);
00394     gdk_gc_copy(dgc, widget->style->fg_gc[GTK_STATE_NORMAL]);
00395   }
00396   
00397 
00398   /* draw frame */
00399   gdk_gc_set_foreground(dgc, &(cols[C_WAVEFORM]));
00400   gdk_draw_rectangle(pixmap, dgc, FALSE,
00401                      scale_x_wave(0), scale_y_wave(max_level),
00402                      scale_x_wave(speechlen-1) - scale_x_wave(0),
00403                      scale_y_wave(-max_level) - scale_y_wave(max_level));
00404 
00405   if (sw_level_thres) {
00406     /* draw level threshold line */
00407     gdk_gc_set_foreground(dgc, &(cols[C_LEVELTHRES]));
00408     gdk_draw_line(pixmap, dgc,
00409                   scale_x_wave(0), scale_y_wave(level_thres),
00410                   scale_x_wave(speechlen-1), scale_y_wave(level_thres));
00411     gdk_draw_line(pixmap, dgc,
00412                   scale_x_wave(0), scale_y_wave(-level_thres),
00413                   scale_x_wave(speechlen-1), scale_y_wave(-level_thres));
00414     snprintf(buf, 20, "-lv %d", level_thres);
00415     text_width = gdk_string_width(fontset, buf) + 1;
00416     gdk_draw_string(pixmap, fontset, dgc,
00417                     canvas_width - CANVAS_MARGIN - text_width - 2,
00418                     scale_y_wave(-max_level) - 2,
00419                     buf);
00420   }
00421   
00422   /* draw text */
00423   snprintf(buf, 20, "max: %d", max_level);
00424   text_width = gdk_string_width(fontset, buf) + 1;
00425   gdk_gc_set_foreground(dgc, &(cols[C_WAVEFORM]));
00426   gdk_draw_string(pixmap, fontset, dgc,
00427                   canvas_width - CANVAS_MARGIN - text_width - 2,
00428                   scale_y_wave(max_level) + 12,
00429                   buf);
00430 
00431   /* draw waveform */
00432   for(t=1;t<speechlen;t++) {
00433     gdk_gc_set_line_attributes(dgc, 1, GDK_LINE_SOLID, GDK_CAP_BUTT, GDK_JOIN_MITER);
00434     gdk_draw_line(pixmap, dgc,
00435                   scale_x_wave(t-1), scale_y_wave(speech[t-1]),
00436                   scale_x_wave(t), scale_y_wave(speech[t]));
00437   }
00438 }
00439 
00440 
00441 /**********************************************************************/
00442 /* GTK primitive functions to draw a trellis atom */
00443 /**********************************************************************/
00444 
00467 static void
00468 mygdk_draw_arc(GtkWidget *widget, int x1, int y1, int x2, int y2, int sw)
00469 {
00470   int width;
00471   UserColors c;
00472 
00473   /* first time, make gc for drawing */
00474   if (dgc == NULL) {
00475     dgc = gdk_gc_new(widget->window);
00476     gdk_gc_copy(dgc, widget->style->fg_gc[GTK_STATE_NORMAL]);
00477   }
00478 
00479   /* change arc style by sw */
00480   switch(sw) {
00481   case 0: c = C_LINE_FAINT; width = 1; break;
00482   case 1: c = C_LINE; width = 1; break;
00483   case 2: c = C_LINE_BEST; width = 3; break;
00484   case 3: c = C_PASS2_NEXT; width = 1; break; /* next */
00485   case 4: c = C_PASS2; width = 1; break; /* popper (realigned) */
00486   case 5: c = C_PASS2_NEXT; width = 2; break; /* popped (original) */
00487   case 6: c = C_PASS2_BEST; width = 3; break;
00488   default: c = C_LINE; width = 1; break;
00489   }
00490   
00491   /* draw arc line */
00492   if (sw_line) {
00493     gdk_gc_set_line_attributes(dgc, width, GDK_LINE_SOLID, GDK_CAP_BUTT, GDK_JOIN_MITER);
00494     gdk_gc_set_foreground(dgc, &(cols[c]));
00495     gdk_draw_line(pixmap, dgc, x1, y1, x2, y2);
00496     gdk_gc_set_line_attributes(dgc, 1, GDK_LINE_SOLID, GDK_CAP_BUTT, GDK_JOIN_MITER);
00497   }
00498 
00499   /* draw begin/end point rectangle */
00500   if (sw != 0 && sw != 5) {
00501     /* make edge */
00502     gdk_gc_set_foreground(dgc, &(cols[C_SHADOW]));
00503     gdk_draw_rectangle(pixmap, dgc,
00504                        TRUE,
00505                        x1 - width/2 - 2,
00506                        y1 - width/2 -2,
00507                        width+4,
00508                        width+4);
00509     gdk_draw_rectangle(pixmap, dgc,
00510                        TRUE,
00511                        x2 - width/2 - 2,
00512                        y2 - width/2 -2,
00513                        width+4,
00514                        width+4);
00515   }
00516   gdk_gc_set_foreground(dgc, &(cols[C_BGN]));
00517   gdk_draw_rectangle(pixmap, dgc,
00518                      TRUE,
00519                      x1 - width/2 - 1,
00520                      y1 - width/2 -1,
00521                      width+2,
00522                      width+2);
00523   if (c == C_LINE_BEST || c == C_PASS2_BEST) {
00524     gdk_gc_set_foreground(dgc, &(cols[C_END_BEST]));
00525   } else {
00526     gdk_gc_set_foreground(dgc, &(cols[C_END]));
00527   }
00528   gdk_draw_rectangle(pixmap, dgc,
00529                      TRUE,
00530                      x2 - width/2 - 1,
00531                      y2 - width/2 - 1,
00532                      width+2,
00533                      width+2);
00534   
00535 }
00536 
00555 static void
00556 draw_atom_sub(GtkWidget *widget, TRELLIS_ATOM *tre, TRELLIS_ATOM *last_tre, int sw)
00557 {
00558   int from_t;
00559   LOGPROB from_s;
00560   int from_w;
00561   
00562   /* draw word arc */
00563   if (sw_wid_axis) {
00564     if (tre->begintime <= 0) {
00565       from_t = 0;
00566       from_w = WORD_INVALID;
00567     } else {
00568       from_t = last_tre->endtime;
00569       from_w = last_tre->wid;
00570     }
00571     mygdk_draw_arc(widget,
00572                    scale_x(from_t),
00573                    scale_y_wid(from_w),
00574                    scale_x(tre->endtime),
00575                    scale_y_wid(tre->wid),
00576                    sw);
00577   } else {
00578     if (tre->begintime <= 0) {
00579       from_t = 0;
00580       from_s = 0.0;
00581     } else {
00582       from_t = last_tre->endtime;
00583       from_s = last_tre->backscore;
00584     }
00585     mygdk_draw_arc(widget,
00586                    scale_x(from_t),
00587                    scale_y(from_s, from_t),
00588                    scale_x(tre->endtime),
00589                    scale_y(tre->backscore, tre->endtime),
00590                    sw);
00591   }
00592 }
00593 
00610 static void
00611 draw_atom(GtkWidget *widget, TRELLIS_ATOM *tre, int sw)
00612 {
00613   draw_atom_sub(widget, tre, tre->last_tre, sw);
00614 }
00615 
00616 /* draw word output text */
00633 static void
00634 draw_atom_text(GtkWidget *widget, TRELLIS_ATOM *tre, int sw)
00635 {
00636   gint text_width;
00637   UserColors c;
00638   int style;
00639   int dx, dy, x, y;
00640   
00641   if (winfo->woutput[tre->wid] != NULL && strlen(winfo->woutput[tre->wid]) > 0) {
00642     switch(sw) {
00643     case 0: style = -1; break;
00644     case 1: c = C_TEXT; style = 0; break;
00645     case 2: c = C_TEXT_BEST; style = 1; break;
00646     case 3: c = C_PASS2_NEXT; style = 0; break;
00647     case 4: c = C_PASS2; style = 0; break;
00648     case 5: c = C_PASS2; style = 1; break;
00649     case 6: c = C_PASS2_BEST; style = 1; break;
00650     default: c = C_TEXT; style = 0; break;
00651     }
00652     if (style == -1) return;    /* do not draw text */
00653     
00654     text_width = gdk_string_width(fontset, winfo->woutput[tre->wid]) + 1;
00655     x = scale_x(tre->endtime) - text_width;
00656     if (sw_wid_axis) {
00657       y = scale_y_wid(tre->wid) - 4;
00658     } else {
00659       y = scale_y(tre->backscore, tre->endtime) - 4;
00660     }
00661     
00662     if (style == 1) {           /* make edge */
00663       gdk_gc_set_foreground(dgc, &cols[C_SHADOW]);
00664       for (dx = -1; dx <= 1; dx++) {
00665         for (dy = -1; dy <= 1; dy++) {
00666           if (dx == 0 && dy == 0) continue;
00667           gdk_draw_string(pixmap, fontset, dgc, x + dx, y + dy, 
00668                           winfo->woutput[tre->wid]);
00669         }
00670       }
00671     }
00672     gdk_gc_set_foreground(dgc, &cols[c]);
00673     gdk_draw_string(pixmap, fontset, dgc, x, y, 
00674                     winfo->woutput[tre->wid]);
00675   }
00676 }
00677 
00678 
00679 /**********************************************************************/
00680 /* wrapper for narrowing atoms to be drawn */
00681 /**********************************************************************/
00682 static WORD_ID *wordlist = NULL; 
00683 static WORD_ID wordlistnum = 0; 
00684 
00701 static boolean 
00702 wordlist_find(WORD_ID wid)
00703 {
00704   int left, right, mid;
00705   
00706   if (wordlistnum == 0) return FALSE;
00707 
00708   left = 0;
00709   right = wordlistnum - 1;
00710   while (left < right) {
00711     mid = (left + right) / 2;
00712     if (wordlist[mid] < wid) {
00713       left = mid + 1;
00714     } else {
00715       right = mid;
00716     }
00717   }
00718   if (wordlist[left] == wid) return TRUE;
00719   return FALSE;
00720 }
00721 
00722 
00723 /**********************************************************************/
00724 /* Top trellis atom drawing functions including wrapper */
00725 /* All functions below should call this */
00726 /**********************************************************************/
00727 
00744 static void
00745 draw_atom_top(GtkWidget *widget, TRELLIS_ATOM *tre, int sw)
00746 {
00747   if (wordlistnum == 0 || wordlist_find(tre->wid)) {
00748     draw_atom(widget, tre, sw);
00749   }
00750 }
00751 
00770 static void
00771 draw_atom_text_top(GtkWidget *widget, TRELLIS_ATOM *tre, int sw)
00772 {
00773   if (wordlistnum == 0 || wordlist_find(tre->wid)) {
00774     draw_atom_text(widget, tre, sw);
00775   }
00776 }
00777 
00778 
00779 /**********************************************************************/
00780 /* Draw a set of atom according to their properties */
00781 /**********************************************************************/
00782 
00795 static void
00796 draw_all_atom(GtkWidget *widget)
00797 {
00798   int t, i;
00799   TRELLIS_ATOM *tre;
00800   
00801   for (t=0;t<btlocal->framelen;t++) {
00802     for (i=0;i<btlocal->num[t];i++) {
00803       tre = btlocal->rw[t][i];
00804       draw_atom_top(widget, tre, 0);
00805     }
00806   }
00807   if (sw_text) {
00808     for (t=0;t<btlocal->framelen;t++) {
00809       for (i=0;i<btlocal->num[t];i++) {
00810         tre = btlocal->rw[t][i];
00811         draw_atom_text_top(widget, tre, 0);
00812       }
00813     }
00814   }
00815 }
00816 
00829 static void
00830 draw_context_valid_atom(GtkWidget *widget)
00831 {
00832   int t, i;
00833   TRELLIS_ATOM *tre;
00834 
00835   for (t=0;t<btlocal->framelen;t++) {
00836     for (i=0;i<btlocal->num[t];i++) {
00837       tre = btlocal->rw[t][i];
00838       if (tre->last_tre != NULL && tre->last_tre->wid != WORD_INVALID) {
00839         draw_atom_top(widget, tre->last_tre, 1);
00840       }
00841     }
00842   }
00843   if (sw_text) {
00844     for (t=0;t<btlocal->framelen;t++) {
00845       for (i=0;i<btlocal->num[t];i++) {
00846         tre = btlocal->rw[t][i];
00847         if (tre->last_tre != NULL && tre->last_tre->wid != WORD_INVALID) {
00848           draw_atom_text_top(widget, tre->last_tre, 1);
00849         }
00850       }
00851     }
00852   }
00853 }
00854 
00855 #ifdef WORD_GRAPH
00856 
00868 static void
00869 draw_word_graph(GtkWidget *widget)
00870 {
00871   int t, i;
00872   TRELLIS_ATOM *tre;
00873 
00874   /* assume (1)word atoms in word graph are already marked in
00875      generate_lattice() in beam.c, and (2) backtrellis is wid-sorted */
00876   for (t=0;t<btlocal->framelen;t++) {
00877     for (i=0;i<btlocal->num[t];i++) {
00878       tre = btlocal->rw[t][i];
00879       if (tre->within_wordgraph) {
00880         draw_atom_top(widget, tre, 1);
00881       }
00882     }
00883   }
00884   if (sw_text) {
00885     for (t=0;t<btlocal->framelen;t++) {
00886       for (i=0;i<btlocal->num[t];i++) {
00887         tre = btlocal->rw[t][i];
00888         if (tre->within_wordgraph) {
00889           draw_atom_text_top(widget, tre, 1);
00890         }
00891       }
00892     }
00893   }
00894   
00895 }
00896 #endif
00897 
00910 static void
00911 draw_best_path(GtkWidget *widget)
00912 {
00913   int last_time;
00914   LOGPROB maxscore;
00915   TRELLIS_ATOM *tre, *last_tre;
00916   int i;
00917 
00918   /* look for the beginning trellis word at end of speech */
00919   for (last_time = btlocal->framelen - 1; last_time >= 0; last_time--) {
00920 #ifdef USE_NGRAM
00921     /* it is fixed to the tail silence model (winfo->tail_silwid) */
00922     last_tre = bt_binsearch_atom(btlocal, last_time, winfo->tail_silwid);
00923     if (last_tre != NULL) break;
00924 #else /* USE_DFA */
00925     /* the best trellis word on the last frame (not use cp_end[]) */
00926     maxscore = LOG_ZERO;
00927     for (i=0;i<btlocal->num[last_time];i++) {
00928       tre = btlocal->rw[last_time][i];
00929       /*      if (dfa->cp_end[winfo->wton[tmp->wid]] == TRUE) {*/
00930         if (maxscore < tre->backscore) {
00931           maxscore = tre->backscore;
00932           last_tre = tre;
00933         }
00934         /*      }*/
00935     }
00936     if (maxscore != LOG_ZERO) break;
00937 #endif
00938   }
00939   if (last_time < 0) return;            /* last_tre not found */
00940 
00941   /* parse from the beginning word to find the best path */
00942   draw_atom_top(widget, last_tre, 2);
00943   tre = last_tre;
00944   while (tre->begintime > 0) {
00945     tre = tre->last_tre;
00946     draw_atom_top(widget, tre, 2);
00947   }
00948   if (sw_text) {
00949     draw_atom_text_top(widget, last_tre, 2);
00950     tre = last_tre;
00951     while (tre->begintime > 0) {
00952       tre = tre->last_tre;
00953       draw_atom_text_top(widget, tre, 2);
00954     }
00955   }
00956 }
00957 
00958 
00959 /**********************************************************************/
00960 /* 2nd pass drawing data collection functions */
00961 /* will be called from search_bestfirst_main.c to gather the atoms
00962    referred to in the search process of the 2nd pass */
00963 /**********************************************************************/
00964 
00977 void
00978 visual2_init(int maxhypo)
00979 {
00980   POPNODE *p, *ptmp;
00981   int i;
00982 
00983   if (popped == NULL) {
00984     popped = (POPNODE *)mymalloc(sizeof(POPNODE) * (maxhypo + 1));
00985   } else {
00986     for(i=0;i<pnum;i++) {
00987       p = popped[i].next;
00988       while(p) {
00989         ptmp = p->next;
00990         free(p);
00991         p = ptmp;
00992       }
00993     }
00994   }
00995   pnum = 1;
00996   /* for start words */
00997   popped[0].tre = NULL;
00998   popped[0].score = LOG_ZERO;
00999   popped[0].last = NULL;
01000   popped[0].next = NULL;
01001 
01002   /* for bests */
01003   p = lastpop;
01004   while(p) {
01005     ptmp = p->next;
01006     free(p);
01007     p = ptmp;
01008   }
01009   lastpop = NULL;
01010 }
01011 
01026 void
01027 visual2_popped(NODE *n, int popctr)
01028 {
01029   if (pnum < popctr + 1) pnum = popctr + 1;
01030   
01031   popped[popctr].tre = n->popnode->tre;
01032   popped[popctr].score = n->popnode->score;
01033   popped[popctr].last = n->popnode->last;
01034   popped[popctr].next = NULL;
01035 
01036   n->popnode = &(popped[popctr]);
01037 }
01038   
01055 void
01056 visual2_next_word(NODE *next, NODE *prev, int popctr)
01057 {
01058   POPNODE *new;
01059 
01060   /* allocate new popnode info */
01061   new = (POPNODE *)mymalloc(sizeof(POPNODE));
01062   new->tre = next->tre;
01063   new->score = next->score;
01064   /* link between previous POPNODE */
01065   new->last = (prev) ? prev->popnode : NULL;
01066   next->popnode = new;
01067   /* store */
01068   new->next = popped[popctr].next;
01069   popped[popctr].next = new;
01070 }
01071 
01086 void
01087 visual2_best(NODE *now, WORD_INFO *winfo)
01088 {
01089   POPNODE *new;
01090   
01091   new = (POPNODE *)mymalloc(sizeof(POPNODE));
01092   new->tre = now->popnode->tre;
01093   new->score = now->popnode->score;
01094   new->last = now->popnode->last;
01095   new->next = lastpop;
01096   lastpop = new;
01097 }
01098 
01099 /**********************************************************************/
01100 /* Draw atoms refered at the 2nd pass */
01101 /**********************************************************************/
01102 
01103 /* draw 2nd pass results */
01116 static void
01117 draw_final_results(GtkWidget *widget)
01118 {
01119   POPNODE *firstp, *lastp, *p;
01120 
01121   for(firstp = lastpop; firstp; firstp = firstp->next) {
01122     if (firstp->tre != NULL) {
01123       draw_atom(widget, firstp->tre, 6);
01124     }
01125     lastp = firstp;
01126     for(p = firstp->last; p; p = p->last) {
01127       if (p->tre != NULL) {
01128         draw_atom_sub(widget, p->tre, lastp->tre, 6);
01129         draw_atom_text_top(widget, p->tre, 6);
01130       }
01131       lastp = p;
01132     }
01133   }
01134 }
01135 
01136 static LOGPROB maxscore;        
01137 static LOGPROB minscore;        
01138 
01148 static void
01149 get_max_hypo_score()
01150 {
01151   POPNODE *p;
01152   int i;
01153 
01154   maxscore = LOG_ZERO;
01155   minscore = 0.0;
01156   for(i=1;i<pnum;i++) {
01157     if (maxscore < popped[i].score) maxscore = popped[i].score;
01158     if (minscore > popped[i].score) minscore = popped[i].score;
01159   }
01160 }
01161 
01178 static gint
01179 scale_hypo_y(LOGPROB s)
01180 {
01181   gint y;
01182   gint yoffset, height;
01183 
01184   yoffset = CANVAS_MARGIN + RESULT_HEIGHT + (speechlen != 0 ? (WAVE_MARGIN + WAVE_HEIGHT) : 0);
01185   height = canvas_height - yoffset - CANVAS_MARGIN;
01186   y = (maxscore - s) * height / (maxscore - minscore) + yoffset;
01187   return(y);
01188 }
01189 
01190 /* draw popped words */
01211 static void
01212 draw_popped(GtkWidget *widget, POPNODE *p, UserColors c, int width, int style)
01213 {
01214   int text_width;
01215   gint x, y;
01216 
01217   if (p->tre == NULL) return;
01218 
01219   if (p->last != NULL && p->last->tre != NULL) {
01220     gdk_gc_set_line_attributes(dgc, width, GDK_LINE_SOLID, GDK_CAP_BUTT, GDK_JOIN_MITER);
01221     gdk_gc_set_foreground(dgc, &(cols[c]));
01222     gdk_draw_line(pixmap, dgc,
01223                   scale_x(p->last->tre->endtime),
01224                   scale_hypo_y(p->last->score),
01225                   scale_x(p->tre->endtime),
01226                   scale_hypo_y(p->score));
01227     gdk_gc_set_line_attributes(dgc, 1, GDK_LINE_SOLID, GDK_CAP_BUTT, GDK_JOIN_MITER);
01228   }
01229   
01230   if (p->tre != NULL) {
01231     x = scale_x(p->tre->endtime);
01232     y = scale_hypo_y(p->score);
01233     if (style == 1) {
01234       gdk_gc_set_foreground(dgc, &(cols[C_SHADOW]));
01235       gdk_draw_rectangle(pixmap, dgc,
01236                          TRUE,
01237                          x - 3,
01238                          y - 3,
01239                          7,
01240                          7);
01241     } else if (style == 2) {
01242       gdk_gc_set_foreground(dgc, &(cols[c]));
01243       gdk_draw_rectangle(pixmap, dgc,
01244                          TRUE,
01245                          x - 3,
01246                          y - 3,
01247                          7,
01248                          7);
01249     }
01250     gdk_gc_set_foreground(dgc, &(cols[c]));
01251     gdk_draw_rectangle(pixmap, dgc,
01252                        TRUE,
01253                        x - 2,
01254                        y - 2,
01255                        5,
01256                        5);
01257     if (p->tre->wid != WORD_INVALID) {
01258       text_width = gdk_string_width(fontset, winfo->woutput[p->tre->wid]) + 1;
01259       gdk_draw_string(pixmap, fontset, dgc, x - text_width-1, y - 5, 
01260                       winfo->woutput[p->tre->wid]);
01261     }
01262   }
01263     
01264   
01265 }
01266 
01267 /* draw popped words at one hypothesis expantion */
01268 
01269 static int old_popctr;          
01270 
01285 static void
01286 draw_popnodes(GtkWidget *widget, int popctr)
01287 {
01288   POPNODE *p, *porg;
01289 
01290   if (popctr < 0 || popctr >= pnum) {
01291     j_printerr("invalid popctr (%d > %d)!\n", popctr, pnum);
01292     return;
01293   }
01294   
01295   porg = &(popped[popctr]);
01296 
01297   /* draw expanded atoms */
01298   for(p = porg->next; p; p = p->next) {
01299     draw_popped(widget, p, C_LINE_BEST, 1, 0);
01300   }
01301 
01302   /* draw hypothesis context */
01303   for(p = porg->last; p; p = p->last) {
01304     draw_popped(widget, p, C_PASS2_BEST, 2, 0);
01305   }
01306   draw_popped(widget, porg, C_PASS2_BEST, 3, 1);
01307 
01308   old_popctr = popctr;
01309 }
01322 static void
01323 draw_popnodes_old(GtkWidget *widget)
01324 {
01325   POPNODE *p, *porg;
01326 
01327   porg = &(popped[old_popctr]);
01328 
01329   /* draw expanded atoms */
01330   for(p = porg->next; p; p = p->next) {
01331     draw_popped(widget, p, C_LINE_FAINT, 1, 0);
01332   }
01333 
01334   /* draw hypothesis context */
01335   for(p = porg->last; p; p = p->last) {
01336     draw_popped(widget, p, C_PASS2, 2, 0);
01337   }
01338   draw_popped(widget, porg, C_PASS2, 3, 2);
01339 }
01340 
01341 /**********************************************************************/
01342 /* GTK TopLevel draw/redraw functions */
01343 /* will be called for each exposure/configure event */
01344 /**********************************************************************/
01345 static boolean fitscreen = TRUE; 
01346 
01359 static void
01360 draw_background(GtkWidget *widget)
01361 {
01362   static char buf[MAX_HMMNAME_LEN];
01363   
01364   /* first time, make gc for drawing */
01365   if (dgc == NULL) {
01366     dgc = gdk_gc_new(widget->window);
01367     gdk_gc_copy(dgc, widget->style->fg_gc[GTK_STATE_NORMAL]);
01368   }
01369   /* clear pixmap background */
01370   gdk_gc_set_foreground(dgc, &(cols[C_BG]));
01371   gdk_draw_rectangle(pixmap, dgc, TRUE,
01372                      0,0,canvas_width,canvas_height);
01373 
01374   /* display view mode and zoom status */
01375   gdk_gc_set_foreground(dgc, &(cols[C_TEXT]));
01376   if (sw_hypo) {
01377     gdk_draw_string(pixmap, fontset, dgc, 0, canvas_height - 16,
01378                     "Hypothesis score (2nd pass)");
01379   } else {
01380     gdk_draw_string(pixmap, fontset, dgc, 0, canvas_height - 16,
01381                     sw_wid_axis ? "Word ID" : (sw_score_beam ? "Beam score" : "Accumulated score (normalized by time)"));
01382   }
01383   snprintf(buf, 50, "x%3.1f", (float)canvas_width / (float)btlocal->framelen);
01384   gdk_draw_string(pixmap, fontset, dgc, 0, canvas_height - 3, buf);
01385 }
01386 
01399 static void
01400 drawarea_draw(GtkWidget *widget)
01401 {
01402   /* allocate (new) pixmap */
01403   if (pixmap) {
01404     gdk_pixmap_unref(pixmap);   /* destroy old one */
01405   }
01406   pixmap = gdk_pixmap_new(widget->window, canvas_width, canvas_height, -1);
01407   
01408   /* make background */
01409   draw_background(widget);
01410 
01411   if (speechlen != 0) {
01412     draw_waveform(widget);
01413   }
01414 
01415   if (!sw_hypo) {
01416     if (btlocal != NULL) {
01417       /* draw objects */
01418       draw_all_atom(widget);
01419 #ifdef WORD_GRAPH
01420       draw_word_graph(widget);
01421 #else
01422       draw_context_valid_atom(widget);
01423 #endif
01424       draw_best_path(widget);
01425     }
01426     if (popped != NULL) {
01427       /* draw 2nd pass objects */
01428       draw_final_results(widget);
01429     }
01430   }
01431 }
01432 
01445 static void
01446 drawarea_expose(GtkWidget *widget)
01447 {
01448   GdkRectangle r;
01449 
01450   r.x = 0;
01451   r.y = 0;
01452   r.width = canvas_width;
01453   r.height = canvas_height;
01454   gtk_widget_draw(widget, &r);
01455 }
01456 
01477 static gboolean
01478 event_drawarea_expose(GtkWidget *widget, GdkEventExpose *event, gpointer user_data)
01479 {
01480   if (pixmap != NULL) {
01481     gdk_draw_pixmap(widget->window,
01482                     widget->style->fg_gc[GTK_STATE_NORMAL],
01483                     pixmap,
01484                     event->area.x, event->area.y,
01485                     event->area.x, event->area.y,
01486                     event->area.width, event->area.height);
01487   }
01488 }
01489 
01510 static gboolean
01511 event_drawarea_configure(GtkWidget *widget, GdkEventExpose *event, gpointer user_data)
01512 {
01513   if (fitscreen) {              /* if in zoom mode, resizing window does not cause resize of the canvas */
01514     canvas_width = widget->allocation.width; /* get canvas size */
01515   }
01516   /* canvas height will be always automatically changed by resizing */
01517   canvas_height = widget->allocation.height;
01518 
01519   /* redraw objects to pixmap */
01520   drawarea_draw(widget);
01521 }
01522 
01523 
01524 /**********************************************************************/
01525 /* GTK callbacks for buttons */
01526 /**********************************************************************/
01527 
01542 static void
01543 action_toggle_thres(GtkWidget *widget)
01544 {
01545 
01546   if (speechlen == 0) return;
01547   /* toggle switch */
01548   if (sw_level_thres) sw_level_thres = FALSE;
01549   else sw_level_thres = TRUE;
01550 
01551   /* redraw objects to pixmap */
01552   drawarea_draw(widget);
01553 
01554   /* tell X to issue expose event on this window */
01555   drawarea_expose(widget);
01556 }
01557 
01558 #ifdef PLAYCOMMAND
01559 
01571 static void
01572 action_play_waveform(GtkWidget *widget)
01573 {
01574   char buf[80];
01575   static char command[250];
01576   int fd;
01577 
01578   if (speechlen == 0) return;
01579   
01580   /* play waveform */
01581   snprintf(buf, 250, "/var/tmp/julius_visual_play.%d", getpid());
01582   if ((fd = open(buf, O_CREAT | O_TRUNC | O_WRONLY, 0644)) < 0) {
01583     j_printerr("cannot open %s for writing\n", buf);
01584     return;
01585   }
01586   if (wrsamp(fd, speech, speechlen) < 0) {
01587     j_printerr("failed to write to %s for playing\n", buf);
01588     return;
01589   }
01590   close(fd);
01591   
01592   snprintf(command, 250, PLAYCOMMAND, para.smp_freq, buf);
01593   j_printf("play: [%s]\n", command);
01594   system(command);
01595 
01596   unlink(buf);
01597 }
01598 #endif
01599 
01614 static void
01615 action_view_wid(GtkWidget *button, GtkWidget *widget)
01616 {
01617   if (GTK_TOGGLE_BUTTON(button)->active) {
01618     /* set switch */
01619     sw_wid_axis = TRUE;
01620     sw_hypo = FALSE;
01621     /* redraw objects to pixmap */
01622     drawarea_draw(widget);
01623     /* tell X to issue expose event on this window */
01624     drawarea_expose(widget);
01625   } else {
01626     sw_wid_axis = FALSE;
01627   }
01628 }
01629 
01644 static void
01645 action_view_score(GtkWidget *button, GtkWidget *widget)
01646 {
01647   if (GTK_TOGGLE_BUTTON(button)->active) {
01648     /* set switch */
01649     sw_score_beam = FALSE;
01650     sw_hypo = FALSE;
01651     /* redraw objects to pixmap */
01652     drawarea_draw(widget);
01653     /* tell X to issue expose event on this window */
01654     drawarea_expose(widget);
01655   }
01656 }
01657 
01674 static void
01675 action_view_beam(GtkWidget *button, GtkWidget *widget)
01676 {
01677   if (GTK_TOGGLE_BUTTON(button)->active) {
01678     /* set switch */
01679     sw_score_beam = TRUE;
01680     sw_hypo = FALSE;
01681     /* redraw objects to pixmap */
01682     drawarea_draw(widget);
01683     /* tell X to issue expose event on this window */
01684     drawarea_expose(widget);
01685   }
01686 }
01687 
01704 static void
01705 action_toggle_arc(GtkWidget *button, GtkWidget *widget)
01706 {
01707   if (GTK_TOGGLE_BUTTON(button)->active) {
01708     sw_text = TRUE;
01709     sw_line = TRUE;
01710   } else {
01711     sw_text = FALSE;
01712     sw_line = FALSE;
01713   }
01714   /* redraw objects to pixmap */
01715   drawarea_draw(widget);
01716   /* tell X to issue expose event on this window */
01717   drawarea_expose(widget);
01718 }
01719 
01736 static void
01737 action_set_wid(GtkWidget *widget, GtkWidget *draw)
01738 {
01739   gchar *entry_text;
01740   WORD_ID i;
01741   
01742   entry_text = gtk_entry_get_text(GTK_ENTRY(widget));
01743 
01744   /* allocate */
01745   if (wordlist == NULL) {
01746     wordlist = mymalloc(sizeof(WORD_ID) * winfo->num);
01747   }
01748   wordlistnum = 0;
01749 
01750   /* pickup words with the specified output text and regiter them to the lsit */
01751   if (strlen(entry_text) == 0) {
01752     wordlistnum = 0;
01753   } else {
01754     for (i=0;i<winfo->num;i++) {
01755       if (strmatch(entry_text, winfo->woutput[i])) {
01756         wordlist[wordlistnum] = i;
01757         wordlistnum++;
01758       }
01759     }
01760     if (wordlistnum == 0) {
01761       j_printerr("word \"%s\" not found, show all\n", entry_text);
01762     } else {
01763       j_printerr("%d words found for \"%s\"\n", wordlistnum, entry_text);
01764     }
01765   }
01766   
01767   /* redraw objects to pixmap */
01768   drawarea_draw(draw);
01769   /* tell X to issue expose event on this window */
01770   drawarea_expose(draw);
01771 }
01772 
01787 static void
01788 action_zoom(GtkWidget *widget)
01789 {
01790   fitscreen = FALSE;
01791   if (btlocal != NULL) {
01792     canvas_width = btlocal->framelen * 2;
01793     gtk_drawing_area_size(GTK_DRAWING_AREA(widget), canvas_width, canvas_height);
01794 
01795   }
01796   drawarea_draw(widget);
01797   drawarea_expose(widget);
01798 }
01799 
01814 static void
01815 action_zoom_4(GtkWidget *widget)
01816 {
01817   fitscreen = FALSE;
01818   if (btlocal != NULL) {
01819     canvas_width = btlocal->framelen * 4;
01820     gtk_drawing_area_size(GTK_DRAWING_AREA(widget), canvas_width, canvas_height);
01821   }
01822  
01823   drawarea_draw(widget);
01824   drawarea_expose(widget);
01825 }
01826 
01841 static void
01842 action_zoom_8(GtkWidget *widget)
01843 {
01844   fitscreen = FALSE;
01845   if (btlocal != NULL) {
01846     canvas_width = btlocal->framelen * 8;
01847     gtk_drawing_area_size(GTK_DRAWING_AREA(widget), canvas_width, canvas_height);
01848   }
01849   
01850   drawarea_draw(widget);
01851   drawarea_expose(widget);
01852 }
01853 
01868 static void
01869 action_fit_screen(GtkWidget *widget)
01870 {
01871   fitscreen = TRUE;
01872   canvas_width = widget->parent->allocation.width;
01873   gtk_drawing_area_size(GTK_DRAWING_AREA(widget), canvas_width, canvas_height);
01874   
01875   drawarea_draw(widget);
01876   drawarea_expose(widget);
01877 }
01878 
01894 static void
01895 action_toggle_popctr(GtkWidget *button, GtkWidget *widget)
01896 {
01897   if (GTK_TOGGLE_BUTTON(button)->active) {
01898     sw_hypo = TRUE;
01899   } else {
01900     sw_hypo = FALSE;
01901   }
01902   drawarea_draw(widget);
01903   drawarea_expose(widget);
01904 }
01905 
01923 static void
01924 action_change_popctr(GtkAdjustment *adj, GtkWidget *widget)
01925 {
01926   int popctr;
01927 
01928   if (sw_hypo) {
01929     popctr = adj->value;
01930     draw_popnodes_old(widget);
01931     draw_popnodes(widget, popctr);
01932     drawarea_expose(widget);
01933   }
01934 }
01935 
01936 /**********************************************************************/
01937 /* GTK delete/destroy event handler */
01938 /**********************************************************************/
01939 
01960 static gint
01961 delete_event(GtkWidget *widget, GdkEvent *event, gpointer data)
01962 {
01963   return (FALSE);               /* emit destroy signal */
01964 }
01965 
01980 static void
01981 destroy(GtkWidget *widget, gpointer data)
01982 {
01983   gtk_main_quit();
01984 }
01985 
01986 /**********************************************************************/
01987 /* Main public functions for visualization */
01988 /**********************************************************************/
01989 
01998 void
01999 visual_init()
02000 {
02001   POPNODE *p;
02002 
02003   /* reset values */
02004   btlocal = NULL;
02005   
02006   /* initialize Gtk/Gdk libraries */
02007   /* no argument passed as gtk options */
02008   /*gtk_init (&argc, &argv);*/
02009   gtk_init(NULL, NULL);
02010 
02011   /* set locale */
02012   gtk_set_locale();
02013 
02014   /* load fontset */
02015   fontset = gdk_fontset_load(FONTSET);
02016   if (fontset == NULL) {
02017     j_error("cannot load X font \"%s\" for visualize\n", FONTSET);
02018   }
02019 
02020   /* initialize color */
02021   color_init();
02022 
02023   j_printerr("GTK initialized\n");
02024 
02025 }
02026 
02039 void
02040 visual_show(BACKTRELLIS *bt)
02041 {
02042   GtkWidget *window, *button, *draw, *entry, *scrolled_window, *scale;
02043   GtkWidget *box1, *box2, *label, *frame, *box3;
02044   GtkObject *adj;
02045   GSList *group;
02046   GList *glist;
02047 
02048   
02049   j_printerr("*** Showing word trellis view (close window to proceed)\n");
02050 
02051   /* store pointer to backtrellis data */
02052   btlocal = bt;
02053 
02054   /* prepare for Y axis score normalization */
02055   get_max_frame_score(bt);
02056 
02057   /* prepare for Y axis hypo score normalization */
02058   get_max_hypo_score();
02059 
02060   /* prepare for waveform */
02061   if (speechlen != 0) get_max_waveform_level();
02062 
02063   /* start with trellis view */
02064   sw_hypo = FALSE;
02065 
02066   /* reset value */
02067   fitscreen = TRUE;
02068   if (dgc != NULL) {
02069     gdk_gc_unref(dgc);
02070     dgc = NULL;
02071   }
02072 
02073   /* create main window */
02074   window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
02075   gtk_widget_set_usize(GTK_WIDGET(window), DEFAULT_WINDOW_WIDTH, DEFAULT_WINDOW_HEIGHT);
02076   gtk_window_set_title(GTK_WINDOW(window), WINTITLE);
02077   gtk_signal_connect(GTK_OBJECT(window), "delete_event",
02078                      GTK_SIGNAL_FUNC(delete_event), NULL);
02079   gtk_signal_connect(GTK_OBJECT(window), "destroy",
02080                      GTK_SIGNAL_FUNC(destroy), NULL);
02081   gtk_container_border_width(GTK_CONTAINER(window), 10);
02082 
02083   /* create horizontal packing box */
02084   box1 = gtk_hbox_new(FALSE, 5);
02085   gtk_container_add(GTK_CONTAINER(window), box1);
02086 
02087   /* create scrolled window */
02088   scrolled_window = gtk_scrolled_window_new(NULL, NULL);
02089   gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolled_window), GTK_POLICY_ALWAYS,GTK_POLICY_AUTOMATIC);
02090 
02091   /* create drawing area */
02092   draw = gtk_drawing_area_new();
02093   /*  gtk_drawing_area_size(GTK_DRAWING_AREA(draw), DEFAULT_CANVAS_WIDTH, DEFAULT_CANVAS_HEIGHT);*/
02094   gtk_signal_connect(GTK_OBJECT(draw), "expose-event", GTK_SIGNAL_FUNC(event_drawarea_expose), NULL);
02095   gtk_signal_connect(GTK_OBJECT(draw), "configure-event", GTK_SIGNAL_FUNC(event_drawarea_configure), NULL);
02096   gtk_scrolled_window_add_with_viewport(GTK_SCROLLED_WINDOW(scrolled_window), draw);
02097   gtk_box_pack_start(GTK_BOX(box1), scrolled_window, TRUE, TRUE, 0);
02098 
02099   /* create packing box for buttons */
02100   box2 = gtk_vbox_new(FALSE, 5);
02101   gtk_box_pack_start(GTK_BOX(box1), box2, FALSE, TRUE, 0);
02102 
02103   if (speechlen != 0) {
02104     /* create waveform related frame */
02105     frame = gtk_frame_new("waveform");
02106     gtk_box_pack_start(GTK_BOX(box2), frame, FALSE, FALSE, 0);
02107     box3 = gtk_hbox_new(FALSE, 5);
02108     gtk_container_set_border_width(GTK_CONTAINER(box3), 5);
02109     gtk_container_add(GTK_CONTAINER(frame), box3);
02110     
02111     /* create play button if supported */
02112 #ifdef PLAYCOMMAND
02113     button = gtk_button_new_with_label("play");
02114     gtk_signal_connect_object(GTK_OBJECT(button), "clicked",
02115                               GTK_SIGNAL_FUNC(action_play_waveform), GTK_OBJECT(draw));
02116     gtk_box_pack_start(GTK_BOX(box3), button, FALSE, FALSE, 0);
02117 #endif
02118     
02119     /* create level thres toggle button */
02120     button = gtk_button_new_with_label("thres");
02121     gtk_signal_connect_object(GTK_OBJECT(button), "clicked",
02122                               GTK_SIGNAL_FUNC(action_toggle_thres), GTK_OBJECT(draw));
02123     gtk_box_pack_start(GTK_BOX(box3), button, FALSE, FALSE, 0);
02124   }
02125     
02126   /* create scaling frame */
02127   frame = gtk_frame_new("change view");
02128   gtk_box_pack_start(GTK_BOX(box2), frame, FALSE, FALSE, 0);
02129   box3 = gtk_hbox_new(FALSE, 5);
02130   gtk_container_set_border_width(GTK_CONTAINER(box3), 5);
02131   gtk_container_add(GTK_CONTAINER(frame), box3);
02132 
02133   /* create word view button */
02134   button = gtk_radio_button_new_with_label(NULL, "word");
02135   gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(button), TRUE);
02136   gtk_signal_connect(GTK_OBJECT(button), "toggled",
02137                      GTK_SIGNAL_FUNC(action_view_wid), GTK_OBJECT(draw));
02138   gtk_box_pack_start(GTK_BOX(box3), button, FALSE, FALSE, 0);
02139 
02140   /* create score view button */
02141   group = gtk_radio_button_group(GTK_RADIO_BUTTON(button));
02142   button = gtk_radio_button_new_with_label(group, "score");
02143   gtk_signal_connect(GTK_OBJECT(button), "toggled",
02144                      GTK_SIGNAL_FUNC(action_view_score), GTK_OBJECT(draw));
02145   gtk_box_pack_start(GTK_BOX(box3), button, FALSE, FALSE, 0);
02146 
02147   /* create beam view button */
02148   group = gtk_radio_button_group(GTK_RADIO_BUTTON(button));
02149   button = gtk_radio_button_new_with_label(group, "beam");
02150   gtk_signal_connect(GTK_OBJECT(button), "toggled",
02151                      GTK_SIGNAL_FUNC(action_view_beam), GTK_OBJECT(draw));
02152   gtk_box_pack_start(GTK_BOX(box3), button, FALSE, FALSE, 0);
02153 
02154   /* create show/hide frame */
02155   frame = gtk_frame_new("show/hide");
02156   gtk_box_pack_start(GTK_BOX(box2), frame, FALSE, FALSE, 0);
02157   box3 = gtk_vbox_new(FALSE, 5);
02158   gtk_container_set_border_width(GTK_CONTAINER(box3), 5);
02159   gtk_container_add(GTK_CONTAINER(frame), box3);
02160 
02161   /* create text toggle button */
02162   button = gtk_toggle_button_new_with_label("arcs");
02163   gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(button), TRUE);
02164   gtk_signal_connect(GTK_OBJECT(button), "toggled",
02165                      GTK_SIGNAL_FUNC(action_toggle_arc), GTK_OBJECT(draw));
02166   gtk_box_pack_start(GTK_BOX(box3), button, FALSE, FALSE, 0);
02167 
02168   /* create word entry frame */
02169   frame = gtk_frame_new("view words");
02170   gtk_box_pack_start(GTK_BOX(box2), frame, FALSE, FALSE, 0);
02171   box3 = gtk_vbox_new(FALSE, 5);
02172   gtk_container_set_border_width(GTK_CONTAINER(box3), 5);
02173   gtk_container_add(GTK_CONTAINER(frame), box3);
02174 
02175   /* create word ID entry */
02176   entry = gtk_entry_new_with_max_length(16);
02177   gtk_signal_connect(GTK_OBJECT(entry), "activate",
02178                      GTK_SIGNAL_FUNC(action_set_wid), GTK_OBJECT(draw));
02179   gtk_box_pack_start(GTK_BOX(box3), entry, FALSE, FALSE, 0);
02180 
02181   /* create zoom frame */
02182   frame = gtk_frame_new("zoom");
02183   gtk_box_pack_start(GTK_BOX(box2), frame, FALSE, FALSE, 0);
02184   box3 = gtk_hbox_new(FALSE, 5);
02185   gtk_container_set_border_width(GTK_CONTAINER(box3), 5);
02186   gtk_container_add(GTK_CONTAINER(frame), box3);
02187 
02188   /* create x zoom button */
02189   button = gtk_button_new_with_label("x2");
02190   gtk_signal_connect_object(GTK_OBJECT(button), "clicked",
02191                             GTK_SIGNAL_FUNC(action_zoom), GTK_OBJECT(draw));
02192   gtk_box_pack_start(GTK_BOX(box3), button, FALSE, FALSE, 0);
02193 
02194   /* create x zoom button */
02195   button = gtk_button_new_with_label("x4");
02196   gtk_signal_connect_object(GTK_OBJECT(button), "clicked",
02197                             GTK_SIGNAL_FUNC(action_zoom_4), GTK_OBJECT(draw));
02198   gtk_box_pack_start(GTK_BOX(box3), button, FALSE, FALSE, 0);
02199 
02200   /* create x more zoom button */
02201   button = gtk_button_new_with_label("x8");
02202   gtk_signal_connect_object(GTK_OBJECT(button), "clicked",
02203                             GTK_SIGNAL_FUNC(action_zoom_8), GTK_OBJECT(draw));
02204   gtk_box_pack_start(GTK_BOX(box3), button, FALSE, FALSE, 0);
02205 
02206   /* create fit screen button */
02207   button = gtk_button_new_with_label("fit");
02208   gtk_signal_connect_object(GTK_OBJECT(button), "clicked",
02209                             GTK_SIGNAL_FUNC(action_fit_screen), GTK_OBJECT(draw));
02210   gtk_box_pack_start(GTK_BOX(box3), button, FALSE, FALSE, 0);
02211 
02212   /* create replay frame */
02213   frame = gtk_frame_new("pass2 replay");
02214   gtk_box_pack_start(GTK_BOX(box2), frame, FALSE, FALSE, 0);
02215   box3 = gtk_vbox_new(FALSE, 5);
02216   gtk_container_set_border_width(GTK_CONTAINER(box3), 5);
02217   gtk_container_add(GTK_CONTAINER(frame), box3);
02218 
02219   adj = gtk_adjustment_new(0.0, 0.0, (pnum-1) + 5, 1.0, 1.0, 5.0);
02220   gtk_signal_connect(GTK_OBJECT(adj), "value_changed",
02221                      GTK_SIGNAL_FUNC(action_change_popctr), GTK_OBJECT(draw));
02222 
02223   /* create replay start button */
02224   button = gtk_toggle_button_new_with_label("start");
02225   gtk_signal_connect(GTK_OBJECT(button), "toggled",
02226                      GTK_SIGNAL_FUNC(action_toggle_popctr), GTK_OBJECT(draw));
02227   gtk_box_pack_start(GTK_BOX(box3), button, FALSE, FALSE, 0);
02228   
02229   /* create replay scale widget */
02230   scale = gtk_hscale_new(GTK_ADJUSTMENT(adj));
02231   gtk_scale_set_digits(GTK_SCALE(scale), 0);
02232   gtk_box_pack_start(GTK_BOX(box3), scale, FALSE, FALSE, 0);
02233   
02234   /* create close button */
02235   button = gtk_button_new_with_label("close");
02236   /* connect click event to close the window */
02237   gtk_signal_connect_object(GTK_OBJECT(button), "clicked",
02238                             GTK_SIGNAL_FUNC(gtk_widget_destroy),
02239                             GTK_OBJECT(window));
02240   
02241   gtk_box_pack_start(GTK_BOX(box2), button, FALSE, FALSE, 0);
02242 
02243   /* show all the widget */
02244   gtk_widget_show_all(window);
02245 
02246   /* enter the gtk event routine */
02247   gtk_main();
02248 }
02249 
02250 #endif /* VISUALIZE */

Generated on Tue Dec 26 16:16:33 2006 for Julius by  doxygen 1.5.0