home *** CD-ROM | disk | FTP | other *** search
/ AmigActive 4 / AACD04.ISO / AACD / Sound / LAME / Source / gtkanal.c < prev    next >
C/C++ Source or Header  |  1999-06-01  |  39KB  |  1,162 lines

  1. #ifdef HAVEGTK
  2. #include <math.h>
  3. #include <gtk/gtk.h>
  4. #include "gpkplotting.h"
  5. #include "common.h"
  6. #include "encoder.h"
  7. #include "l3psy.h"
  8. #include "gtkanal.h"
  9. #include "version.h"
  10.  
  11. /* global variables for the state of the system */
  12. static gint idle_keepgoing;        /* processing of frames is ON */
  13. static gint idle_count_max;   /* number of frames to process before plotting */
  14. static gint idle_count;       /* pause & plot when idle_count=idel_count_max */
  15. static gint idle_finish=0;      /* process all frames, finish mp3 file and exit */
  16. static gint idle_back = 0;     /* set when we are displaying the old data */
  17. static int mp3done = 0;         /* last frame has been read */
  18. static GtkWidget *frameprogress; /* progress bar */ 
  19. static GtkWidget *framecounter;  /* progress counter */ 
  20.  
  21. /* main window */
  22. GtkWidget *window;
  23. /* Backing pixmap for drawing areas */
  24. GtkWidget *pcmbox;       /* PCM data plotted here */
  25. GtkWidget *winbox;       /* mpg123 synthesis data plotted here */
  26. GtkWidget *enerbox[2];   /* spectrum, gr=0,1 plotted here */
  27. GtkWidget *mdctbox[2];   /* mdct coefficients gr=0,1 plotted here */
  28. GtkWidget *headerbox;    /* mpg123 header info shown here */
  29.  
  30. plotting_data *pinfo;
  31. plotting_data Pinfo[NUMPINFO];
  32.  
  33. struct gtkinfostruct {
  34.   int totalframes;        /* total number of frames in mp3 file */
  35.   int filetype;           /* input file type 0=WAV, 1=MP3 */
  36.   int msflag;             /* toggle between L&R vs M&S PCM data display */
  37.   int chflag;             /* toggle between L & R channels */
  38.   int kbflag;             /* toggle between wave # and barks */
  39.   int flag123;            /* show mpg123 frame info, OR ISO encoder frame info */
  40.   int gpsycho;            /* TRUE if using gpsycho model */
  41.   double avebits;         /* running average bits per frame */
  42.   int approxbits;         /* (approx) bits per frame */
  43.   int maxbits;            /* max bits per frame used so far*/
  44.   int totemph;            /* total of frames with de-emphasis */
  45.   int totms;              /* total frames with ms_stereo */
  46.   int totis;              /* total frames with i_stereo */
  47.   int totshort;           /* total granules with short blocks */
  48.   int totmix;             /* total granules with mixed blocks */
  49.   int pupdate;            /* plot while processing, or only when needed */
  50. } gtkinfo;
  51.  
  52.  
  53.  
  54.  
  55.  
  56. void plot_frame()
  57. {
  58.   int i,j,n,ch,gr,grtemp;
  59.   gdouble *xcord,*ycord;
  60.   gdouble xmx,xmn,ymx,ymn;
  61.   double *data,*data2,*data3;
  62.   char title2[80];
  63.   char *title;
  64.   plotting_data *pplot;
  65.   plotting_data *pplot1;
  66.   plotting_data *pplot2;
  67.   plotting_data *ptemp;
  68.  
  69.   double en,samp;
  70.   static int firstcall=1;
  71.   static GdkColor *barcolor,*color,*grcolor[2];
  72.   static GdkColor yellow,gray,cyan,magenta,orange,pink,red,green,blue,black,oncolor,offcolor;
  73.   int blocktype[2][2];
  74.   int headbits;
  75.  
  76.   /* find the delay between the frame we are plotting and the frame for
  77.    * which MPG123 finally produced some output.  */
  78.   { int mpglag=0;
  79.   for (i=0; i<=(pinfo->mpglag); i++ ) 
  80.     if ((pinfo-i)->mpglag > mpglag ) mpglag = (pinfo-i)->mpglag;
  81.   pplot2 = pinfo-mpglag;
  82.   }
  83.   /* however, the PCM data is delayed by 528 samples in the encoder filterbanks.
  84.    * We added another 1152-528 delay to this so the PCM data is *exactly* one 
  85.    * frame behind the header & MDCT information */
  86.   pplot1 =pplot2 +1;                   /* back one frame for header info, MDCT */
  87.   pplot = pinfo;                       /* reference frame pcm input, FFT's */
  88.  
  89.   /* allocate these GC's only once */
  90.   if (firstcall) {
  91.     firstcall=0;
  92.     /*    grcolor[0]=&magenta; */
  93.     grcolor[0]=&blue;
  94.     grcolor[1]=&green;
  95.     barcolor = &gray;
  96.  
  97.     setcolor(headerbox,&oncolor,255,0,0);
  98.     setcolor(headerbox,&offcolor,175,175,175);
  99.     setcolor(pcmbox,&red,255,0,0);
  100.     setcolor(pcmbox,&pink,255,0,255);
  101.     setcolor(pcmbox,&magenta,255,0,100);
  102.     setcolor(pcmbox,&orange,255,127,0);
  103.     setcolor(pcmbox,&cyan,0,255,255);
  104.     setcolor(pcmbox,&green,0,255,0);
  105.     setcolor(pcmbox,&blue,0,0,255);
  106.     setcolor(pcmbox,&black,0,0,0);
  107.     setcolor(pcmbox,&gray,100,100,100);
  108.     setcolor(pcmbox,&yellow,255,255,0);
  109.  
  110.   }
  111.  
  112.   /*******************************************************************
  113.    * frame header info
  114.    *******************************************************************/
  115.   if (pplot1->sampfreq)
  116.     samp=pplot1->sampfreq;
  117.   else samp=1;
  118.   
  119.   headbits = 32 + ((pplot1->stereo==2) ? 256 : 136);
  120.   gtkinfo.approxbits = (pplot1->bitrate*1000*1152.0/samp) - headbits;
  121.   /*font = gdk_font_load ("-misc-fixed-medium-r-*-*-*-100-*-*-*-*-*-*");*/
  122.   sprintf(title2,"%3.1fkHz %ikbs ",samp/1000,pplot1->bitrate);
  123.   gtk_text_freeze (GTK_TEXT(headerbox));
  124.   gtk_text_backward_delete(GTK_TEXT(headerbox),
  125.                 gtk_text_get_length(GTK_TEXT(headerbox)));
  126.   gtk_text_set_point(GTK_TEXT(headerbox),0);
  127.   gtk_text_insert(GTK_TEXT(headerbox),NULL,&oncolor,NULL,title2, -1);
  128.   title = " mono ";
  129.   if (2==pplot1->stereo) title = pplot1->js ? " jstereo " : " stereo ";
  130.   gtk_text_insert (GTK_TEXT(headerbox), NULL, &oncolor, NULL,title, -1);
  131.   color = pplot1->ms_stereo ? &oncolor : &offcolor ; 
  132.   gtk_text_insert (GTK_TEXT(headerbox), NULL, color, NULL,"ms_stereo ", -1);
  133.   color = pplot1->i_stereo ? &oncolor : &offcolor ; 
  134.   gtk_text_insert (GTK_TEXT(headerbox), NULL, color, NULL,"i_stereo ", -1);
  135.   color = pplot1->emph ? &oncolor : &offcolor ; 
  136.   gtk_text_insert (GTK_TEXT(headerbox), NULL, color, NULL,"emph ", -1);
  137.   color = pplot1->scfsi ? &oncolor : &offcolor ; 
  138.   gtk_text_insert (GTK_TEXT(headerbox), NULL, color, NULL,"scfsi ", -1);
  139.   if (gtkinfo.filetype) 
  140.     sprintf(title2," mdb=%i %i/NA",pplot1->maindata,pplot1->totbits);
  141.   else
  142.     sprintf(title2," mdb=%i   %i/%i",
  143.       pplot1->maindata,pplot1->totbits,pplot->resvsize);
  144.   gtk_text_insert (GTK_TEXT(headerbox), NULL, &oncolor, NULL,title2, -1);
  145.   gtk_text_thaw (GTK_TEXT(headerbox));
  146.  
  147.  
  148.   ch = gtkinfo.chflag;
  149.   /*******************************************************************
  150.    * block type
  151.    *******************************************************************/
  152.   for (gr = 0 ; gr < 2 ; gr ++) 
  153.     if (gtkinfo.flag123) 
  154.       blocktype[gr][ch]=pplot1->mpg123blocktype[gr][ch];
  155.     else blocktype[gr][ch]=pplot->blocktype[gr][ch]; 
  156.  
  157.   
  158.   /*******************************************************************
  159.    * draw the PCM data *
  160.    *******************************************************************/
  161.   n = 1600;  /* PCM frame + FFT window:   224 + 1152 + 224  */
  162.   xcord = g_malloc(n*sizeof(gdouble));
  163.   ycord = g_malloc(n*sizeof(gdouble));
  164.  
  165.  
  166.   if (gtkinfo.msflag) 
  167.     title=ch ? "Side Channel" :  "Mid Channel";
  168.   else 
  169.     title=ch ? "Right Channel" : "Left Channel";
  170.  
  171.   ymn = -32767 ; 
  172.   ymx =  32767;
  173.   xmn = 0;
  174.   xmx = 1600-1;
  175.  
  176.   /*  0  ... 224      draw in black, connecting to 224 pixel
  177.    * 1375 .. 1599     draw in black  connecting to 1375 pixel
  178.    * 224 ... 1375     MP3 frame.  draw in blue
  179.    */
  180.  
  181.   /* draw the title */
  182.   gpk_graph_draw(pcmbox,0,xcord,ycord,xmn,ymn,xmx,ymx,1,title,
  183.          &black);
  184.  
  185.  
  186.   /* draw some hash marks dividing the frames */
  187.   ycord[0] = ymx*.8;  ycord[1] = ymn*.8;
  188.   for (gr=0 ; gr<=2; gr++) {
  189.     xcord[0] = 223.5 + gr*576;   xcord[1] = 223.5 +gr*576;  
  190.     gpk_rectangle_draw(pcmbox,xcord,ycord,xmn,ymn,xmx,ymx,&yellow);
  191.   }
  192.   for (gr = 0 ; gr < 2 ; gr++) {
  193.     if (blocktype[gr][ch]==2) 
  194.       for (i=1 ; i<=2; i++) {
  195.     xcord[0] = 223.5+gr*576 + i*192; 
  196.     xcord[1] = 223.5+gr*576 + i*192; 
  197.     gpk_rectangle_draw(pcmbox,xcord,ycord,xmn,ymn,xmx,ymx,&yellow);
  198.       }
  199.   }
  200.   /* bars representing FFT windows */
  201.   xcord[0] = 0;       ycord[0] = ymn+3000;
  202.   xcord[1] = 1024-1;  ycord[1] = ymn+1000;
  203.   gpk_rectangle_draw(pcmbox,xcord,ycord,xmn,ymn,xmx,ymx,grcolor[0]);
  204.   xcord[0] = 576;          ycord[0] = ymn+2000;
  205.   xcord[1] = 576+1024-1;   ycord[1] = ymn;
  206.   gpk_rectangle_draw(pcmbox,xcord,ycord,xmn,ymn,xmx,ymx,grcolor[1]);
  207.  
  208.  
  209.   /* plot PCM data */
  210.   for (i=0; i<n; i++) {
  211.     xcord[i] = i;
  212.     if (gtkinfo.msflag) 
  213.       ycord[i] = ch ? .5*(pplot->pcmdata[0][i]-pplot->pcmdata[1][i]) : 
  214.       .5*(pplot->pcmdata[0][i]+pplot->pcmdata[1][i]);
  215.     else 
  216.       ycord[i]=pplot->pcmdata[ch][i];
  217.   }
  218.  
  219.   /* skip plot if we are doing an mp3 file */
  220.   if (!gtkinfo.filetype) {
  221.   n = 224;    /* number of points on end of blue part */
  222.   /* data left of frame */
  223.   gpk_graph_draw(pcmbox,n+1,xcord,ycord,xmn,ymn,xmx,ymx,0,title,&black);
  224.   /* data right of frame */
  225.   gpk_graph_draw(pcmbox,n+1,&xcord[1152+n-1],&ycord[1152+n-1],
  226.          xmn,ymn,xmx,ymx,0,title,&black);
  227.   /* the actual frame */
  228.   gpk_graph_draw(pcmbox,1152,&xcord[n],&ycord[n],xmn,ymn,xmx,ymx,0,title,&black);
  229.   }
  230.  
  231.  
  232.   /*******************************************************************/
  233.   /* draw the PCM re-synthesis data */
  234.   /*******************************************************************/
  235.   n = 1152;
  236.  
  237.   sprintf(title2,"Re-synthesis  ms_ratio=%3.2f  %3.2f",
  238.       pplot->ms_ratio[0],pplot->ms_ratio[1]);
  239.   title=title2;
  240.  
  241.  
  242.   ymn = -32767 ; 
  243.   ymx =  32767;
  244.   xmn = 0;
  245.   xmx = 1600-1; 
  246.   gpk_graph_draw(winbox,0,xcord,ycord,
  247.          xmn,ymn,xmx,ymx,1,title,&black);
  248.   /* draw some hash marks dividing the frames */
  249.   ycord[0] = ymx*.8;  ycord[1] = ymn*.8;
  250.   for (gr=0 ; gr<=2; gr++) {
  251.     xcord[0] = 223.5 + gr*576;   xcord[1] = 223.5 +gr*576;  
  252.     gpk_rectangle_draw(winbox,xcord,ycord,xmn,ymn,xmx,ymx,&yellow);
  253.   }
  254.   for (gr = 0 ; gr < 2 ; gr++) {
  255.     if (blocktype[gr][ch]==2) 
  256.       for (i=1 ; i<=2; i++) {
  257.     xcord[0] = 223.5+gr*576 + i*192; 
  258.     xcord[1] = 223.5+gr*576 + i*192; 
  259.     gpk_rectangle_draw(winbox,xcord,ycord,xmn,ymn,xmx,ymx,&yellow);
  260.       }
  261.   }
  262.  
  263.  
  264.  
  265.   n = 224;
  266.   for (j=1152-n,i=0; i<=n; i++,j++) {
  267.     xcord[i] = i;
  268.     if (gtkinfo.msflag) 
  269.       ycord[i] = ch ? .5*(pplot1->pcmdata2[0][j]-
  270.                           pplot1->pcmdata2[1][j]) : 
  271.       .5*(pplot1->pcmdata2[0][j]+pplot1->pcmdata2[1][j]);
  272.     else 
  273.       ycord[i]=pplot1->pcmdata2[ch][j];
  274.   }
  275.   gpk_graph_draw(winbox,n+1,xcord,ycord,
  276.          xmn,ymn,xmx,ymx,0,title,&black);
  277.  
  278.   n = 1152;
  279.   for (i=0; i<n; i++) {
  280.     xcord[i] = i+224;
  281.     if (gtkinfo.msflag) 
  282.       ycord[i] = ch ? .5*(pplot2->pcmdata2[0][i]-pplot2->pcmdata2[1][i]) : 
  283.       .5*(pplot2->pcmdata2[0][i]+pplot2->pcmdata2[1][i]);
  284.     else 
  285.       ycord[i]=pplot2->pcmdata2[ch][i];
  286.   }
  287.   gpk_graph_draw(winbox,n,xcord,ycord,
  288.          xmn,ymn,xmx,ymx,0,title,&black);
  289.  
  290.  
  291.  
  292.  
  293.  
  294.   /*******************************************************************/
  295.   /* draw the MDCT energy spectrum */
  296.   /*******************************************************************/
  297.   for (gr = 0 ; gr < 2 ; gr ++) {
  298.     int bits;
  299.     char *blockname;
  300.     char label[80],label2[80];
  301.     switch (blocktype[gr][ch]) {
  302.     case 0: blockname = "normal";     break;
  303.     case 1:      blockname = "start";    break;
  304.     case 2:     blockname = "short";     break;
  305.     case 3:     blockname = "end";     break;
  306.     }
  307.     strcpy(label,blockname);
  308.     if (pplot1->mixed[gr][ch]) strcat(label,"(mixed)");
  309.     if (blocktype[gr][ch]==2) {
  310.       sprintf(label2,
  311.           " %i %i %i",pplot1->sub_gain[gr][ch][0],
  312.           pplot1->sub_gain[gr][ch][1],
  313.           pplot1->sub_gain[gr][ch][2]);
  314.       strcat(label,label2);
  315.     }
  316.  
  317.     
  318.     
  319.     
  320.     n = 576;
  321.     if (gtkinfo.flag123) {
  322.       data = pplot1->mpg123xr[gr][0];
  323.       data2 = pplot1->mpg123xr[gr][1];
  324.     }else{
  325.       data = pplot->xr[gr][0];
  326.       data2 = pplot->xr[gr][1];
  327.     }
  328.     
  329.  
  330.  
  331.     ymn=9e20;
  332.     ymx=-9e20;
  333.     for (i=0; i<n; i++) {
  334.       double coeff;
  335.       xcord[i] = i+1;
  336.       if (gtkinfo.msflag){
  337.     coeff = ch ?  .5*(data[i]-data2[i]) : .5*(data[i]+data2[i]) ;
  338.       }else{
  339.     coeff = ch ? data2[i] : data[i];
  340.       }
  341.       ycord[i]=coeff*coeff*1e10;
  342.       ycord[i] = log10( MAX( ycord[i],(double) 1)); 
  343.       ymx=(ycord[i] > ymx) ? ycord[i] : ymx;
  344.       ymn=(ycord[i] < ymn) ? ycord[i] : ymn;
  345.     }
  346.     /*  print the min/max
  347.     sprintf(title2,"MDCT%1i %5.2f %5.2f  bits=%i",gr,ymn,ymx,
  348.     pplot1->mainbits[gr][ch]);
  349.     */
  350.     if (gtkinfo.flag123) bits=pplot1->mainbits[gr][ch];
  351.     else bits=pplot->LAMEmainbits[gr][ch];
  352.     
  353.     
  354.     sprintf(title2,"MDCT%1i(%s) bits=%i q=%i n=%3.1f",gr,label,bits,
  355.           pplot1->qss[gr][ch]-210,pplot->noise[gr][ch]*1e6);
  356.     
  357.     xmn = 1;
  358.     xmx = n;
  359.     ymn=0;
  360.     ymx=11;
  361.     gpk_bargraph_draw(mdctbox[gr],n,xcord,ycord,
  362.               xmn,ymn,xmx,ymx,1,title2,0,barcolor);
  363.   }
  364.   
  365.  
  366.  
  367.   
  368.   /*******************************************************************
  369.    * draw the psy model energy spectrum (k space) 
  370.    * l3psy.c computes pe, en, thm for THIS granule.  
  371.    * To encode, ISO uses (bug): en,thm from last granule.  
  372.    *                            pe from this granule
  373.    * gpsycho model corrects this
  374.    *******************************************************************/
  375.   if (gtkinfo.msflag || gtkinfo.filetype) {
  376.     /* erase everything */
  377.     gpk_bargraph_draw(enerbox[0],0,xcord,ycord,
  378.               xmn,ymn,xmx,ymx,1," ",0,barcolor);
  379.     gpk_bargraph_draw(enerbox[1],0,xcord,ycord,
  380.               xmn,ymn,xmx,ymx,1," ",0,barcolor);
  381.   }
  382.   else if (gtkinfo.kbflag){
  383.     for (gr = 0 ; gr < 2 ; gr ++) {
  384.       n = HBLKSIZE; /* only show half the spectrum */
  385.       if (gtkinfo.gpsycho)
  386.     {ptemp=pplot;  grtemp=gr;}
  387.       else {
  388.     /* display info from one granule behind */
  389.     if (gr==0) {ptemp=(pplot+1); grtemp=1;}
  390.     if (gr==1) {ptemp=pplot;  grtemp=0;}
  391.       }
  392.       data = &ptemp->energy[grtemp][ch][0];
  393.       
  394.       ymn=9e20;
  395.       ymx=-9e20;
  396.       for (i=0; i<n; i++) {
  397.     xcord[i] = i+1;
  398.     ycord[i] = log10( MAX( data[i],(double) 1));
  399.     ymx=(ycord[i] > ymx) ? ycord[i] : ymx;
  400.     ymn=(ycord[i] < ymn) ? ycord[i] : ymn;
  401.       }
  402.       for (en=0 , j=0; j<BLKSIZE ; j++) 
  403.     en += ptemp->energy[grtemp][ch][j];
  404.  
  405.       sprintf(title2,"FFT%1i  pe=%4.1fK  en=%5.2e ",gr,
  406.           ptemp->pe[grtemp][ch]/1000,en);
  407.  
  408.       ymn = 3;
  409.       ymx = 15;
  410.       xmn = 1;
  411.       xmx = n;
  412.       gpk_bargraph_draw(enerbox[gr],n,xcord,ycord,
  413.             xmn,ymn,xmx,ymx,1,title2,0,barcolor);
  414.       
  415.     }
  416.   }else{
  417.     /*******************************************************************
  418.      * draw the psy model energy spectrum (scalefactor bands)
  419.      * ISO model (because of bugs) uses:  
  420.      *        pe,en,thm,energy delayed 1 granule
  421.      *******************************************************************/
  422.     for (gr = 0 ; gr < 2 ; gr ++) {
  423.       if (gtkinfo.gpsycho)
  424.     { ptemp=pplot;  grtemp=gr;}
  425.       else {
  426.     if (gr==0) {ptemp=(pplot+1); grtemp=1;}
  427.     if (gr==1) {ptemp=pplot;  grtemp=0;}
  428.       }
  429.       
  430.       if (blocktype[gr][ch]==2) {
  431.     n = 3*SBMAX_s; 
  432.     data = &ptemp->en_s[grtemp][ch][0];
  433.     data2 = &ptemp->thr_s[grtemp][ch][0];
  434.     data3 = &pplot->xfsf_s[grtemp][ch][0];
  435.       } else {
  436.     n = SBMAX_l; 
  437.     data = &ptemp->en[grtemp][ch][0];
  438.     data2 = &ptemp->thr[grtemp][ch][0];
  439.     data3 = &pplot->xfsf[grtemp][ch][0];
  440.       }
  441.       ymn=9e20;
  442.       ymx=-9e20;
  443.       for (i=0; i<n; i++) {
  444.     xcord[i] = i+1;
  445.     ycord[i] = log10( MAX( data[i],(double) 1));
  446.     ymx=(ycord[i] > ymx) ? ycord[i] : ymx;
  447.     ymn=(ycord[i] < ymn) ? ycord[i] : ymn;
  448.       }
  449.  
  450.  
  451.  
  452.  
  453.       /* en = max energy difference amoung the 3 short FFTs for this granule */
  454.       en = pplot->ers[gr][ch];
  455.       sprintf(title2,"FFT%1i pe=%4.1fK del_en=%3.1f over=%i",gr,
  456.           ptemp->pe[grtemp][ch]/1000,en,pplot->over[gr][ch]);
  457.  
  458.  
  459.       ymn = 3;
  460.       ymx = 15;
  461.       xmn = 1;
  462.       xmx = n+1; /* a little extra because of the bar thickness */
  463.       gpk_bargraph_draw(enerbox[gr],n,xcord,ycord,
  464.             xmn,ymn,xmx,ymx,1,title2,0,barcolor);
  465.  
  466.  
  467.       for (i=0; i<n; i++) {
  468.     xcord[i] = i+1;
  469.     ycord[i] = log10( MAX( data3[i], (double) 1));
  470.     ymx=(ycord[i] > ymx) ? ycord[i] : ymx;
  471.     ymn=(ycord[i] < ymn) ? ycord[i] : ymn;
  472.       }
  473.       gpk_bargraph_draw(enerbox[gr],n,xcord,ycord,
  474.             xmn,ymn,xmx,ymx,0,title2,3,&red);  
  475.  
  476.       
  477.       for (i=0; i<n; i++) {
  478.     xcord[i] = i+1 + (.25*n)/SBMAX_l;
  479.     ycord[i] = log10( MAX( data2[i], (double) 1));
  480.     ymx=(ycord[i] > ymx) ? ycord[i] : ymx;
  481.     ymn=(ycord[i] < ymn) ? ycord[i] : ymn;
  482.       }
  483.       gpk_bargraph_draw(enerbox[gr],n,xcord,ycord,
  484.             xmn,ymn,xmx,ymx,0,title2,3,grcolor[gr]);
  485.     }
  486.   }
  487. }
  488.  
  489.  
  490.  
  491. static void update_progress()
  492. {    
  493.   char label[80];
  494.   sprintf(label,"Frame:%4i/%4i  %6.2fs",
  495.      pinfo->frameNum,gtkinfo.totalframes, pinfo->frametime);
  496.   gtk_progress_set_value (GTK_PROGRESS (frameprogress), (gdouble) pinfo->frameNum);
  497.   gtk_label_set_text(GTK_LABEL(framecounter),label);
  498. }
  499.  
  500.  
  501.  
  502. static void analyze()
  503. {
  504.     if ( idle_keepgoing) {
  505.       idle_count = 0;
  506.       idle_count_max=0;
  507.       idle_keepgoing=0;
  508.       idle_finish=0;
  509.     }
  510.     plot_frame();   
  511.     update_progress(); 
  512. }
  513.  
  514. static void plotclick( GtkWidget *widget, gpointer   data )
  515. {   analyze(); }
  516.  
  517.  
  518.  
  519.  
  520. static int frameadv1( GtkWidget *widget, gpointer   data )
  521. {
  522.   int i;
  523.   if (idle_keepgoing ){
  524.     if (idle_back) {
  525.       /* frame displayed is the old frame.  to advance, just swap in new frame */
  526.       idle_back--;
  527.       pinfo = &Pinfo[READ_AHEAD+idle_back];
  528.     }else{
  529.       /* advance the frame by reading in a new frame */
  530.       if (mp3done) { 
  531.     /* dont try to read any more frames, and quit if "finish MP3" was selected */
  532.     if (idle_finish) gtk_main_quit();
  533.     idle_count_max=0; 
  534.       } else {
  535.     /* read in the next frame */
  536.     for (i=NUMPINFO-1 ; i>0 ; i--)
  537.       memcpy(&Pinfo[i],&Pinfo[i-1],sizeof(plotting_data));
  538.     pinfo = &Pinfo[0];
  539.     pinfo->num_samples = gtkinfo.filetype ? readframe() : makeframe();
  540.     if (pinfo->sampfreq) 
  541.       pinfo->frametime = (pinfo->frameNum-1)*1152.0/pinfo->sampfreq;
  542.     else pinfo->frametime=0;
  543.     if (!pinfo->num_samples) {
  544.       mp3done = 1; 
  545.       if (idle_finish) gtk_main_quit();
  546.     }
  547.  
  548.     pinfo->totbits = 0;
  549.     { int gr,ch;
  550.     for (gr = 0 ; gr < 2 ; gr ++) 
  551.       for (ch = 0 ; ch < 2 ; ch ++) {
  552.         gtkinfo.totshort += (pinfo->mpg123blocktype[gr][ch]==2);
  553.         gtkinfo.totmix  += !(pinfo->mixed[gr][ch]==0);
  554.         pinfo->totbits += pinfo->mainbits[gr][ch];
  555.       }
  556.     }
  557.     if (pinfo->frameNum > 1) /* start averaging at frame = 2*/
  558.       gtkinfo.avebits = (gtkinfo.avebits*((pinfo->frameNum)-2)
  559.       + pinfo->totbits ) /(pinfo->frameNum-1);
  560.  
  561.     gtkinfo.maxbits=MAX(gtkinfo.maxbits,pinfo->totbits);
  562.     gtkinfo.totemph += !(pinfo->emph==0);
  563.     gtkinfo.totms   += !(pinfo->ms_stereo==0);
  564.     gtkinfo.totis   += !(pinfo->i_stereo==0);
  565.  
  566.     pinfo = &Pinfo[READ_AHEAD];
  567.       }
  568.     }
  569.  
  570.     idle_count++;
  571.     if (gtkinfo.pupdate) plot_frame();
  572.     update_progress();
  573.     if ((idle_count>=idle_count_max) && (! idle_finish)) analyze();
  574.   }
  575.   return 1;
  576. }
  577.  
  578.  
  579. static void frameadv( GtkWidget *widget, gpointer   data )
  580. {
  581.     int adv;
  582.  
  583.     if (!strcmp((char *) data,"-1")) {
  584.       /* ignore if we've already gone back as far as possible */
  585.       if (pinfo->frameNum==1 || (idle_back==NUMBACK)) return;  
  586.       idle_back++;
  587.       pinfo = &Pinfo[READ_AHEAD+idle_back];
  588.       analyze();
  589.       return;
  590.     }
  591.  
  592.  
  593.     adv = 1;
  594.     if (!strcmp((char *) data,"1")) adv = 1;
  595.     if (!strcmp((char *) data,"10")) adv = 10;
  596.     if (!strcmp((char *) data,"100")) adv = 100;
  597.     if (!strcmp((char *) data,"finish")) idle_finish = 1;
  598.  
  599.  
  600.     if (idle_keepgoing) {
  601.       /* already running - que up additional frame advance requests */
  602.       idle_count_max += adv; 
  603.     }
  604.     else {
  605.       /* turn on idleing */
  606.       idle_count_max = adv;
  607.       idle_count = 0;
  608.       idle_keepgoing = 1;
  609.     }
  610. }
  611.  
  612.  
  613.  
  614.  
  615. /* another callback */
  616. static void delete_event( GtkWidget *widget,
  617.                    GdkEvent  *event,
  618.            gpointer   data )
  619. {
  620.     gtk_main_quit ();
  621. }
  622.  
  623.  
  624.  
  625.  
  626.  
  627.  
  628.  
  629. static void channel_option (GtkWidget *widget, gpointer data)
  630. {
  631.   int option;
  632.   option = (int) data;
  633.   switch (option) {
  634.   case 1:
  635.     gtkinfo.msflag=0;
  636.     gtkinfo.chflag=0; 
  637.     break;
  638.   case 2:
  639.     gtkinfo.msflag=0;
  640.     gtkinfo.chflag=1; 
  641.     break;
  642.   case 3:
  643.     gtkinfo.msflag=1;
  644.     gtkinfo.chflag=0; 
  645.     break;
  646.   case 4:
  647.     gtkinfo.msflag=1;
  648.     gtkinfo.chflag=1; 
  649.   }
  650.   analyze();
  651. }
  652. static void spec_option (GtkWidget *widget, gpointer data)
  653. {
  654.   int option;
  655.   option = (int) data;
  656.   switch (option) {
  657.   case 1:
  658.     gtkinfo.kbflag=0;
  659.     break;
  660.   case 2:
  661.     gtkinfo.kbflag=1;
  662.     break;
  663.   case 3:
  664.     gtkinfo.flag123=0;
  665.     break;
  666.   case 4:
  667.     gtkinfo.flag123=1;
  668.     break;
  669.   case 5:
  670.     gtkinfo.pupdate=1;
  671.     break;
  672.   case 6:
  673.     gtkinfo.pupdate=0;
  674.     break;
  675.   }
  676.   analyze();
  677. }
  678.  
  679.  
  680.  
  681. static void text_window (GtkWidget *widget, gpointer data)
  682. {
  683.   int option;
  684.   GtkWidget *hbox,*vbox,*button,*box;
  685.   GtkWidget *textwindow,*vscrollbar;
  686.   char text[80];
  687.  
  688.   option = (int) data;
  689.   
  690.   textwindow = gtk_window_new(GTK_WINDOW_DIALOG);
  691.   gtk_signal_connect_object (GTK_OBJECT (window), "delete_event",
  692.               GTK_SIGNAL_FUNC(gtk_widget_destroy),
  693.               GTK_OBJECT (textwindow));
  694.  
  695.   gtk_container_set_border_width (GTK_CONTAINER (textwindow), 0);
  696.   vbox = gtk_vbox_new(FALSE,0);
  697.   hbox = gtk_hbox_new(FALSE,0);
  698.  
  699.   button = gtk_button_new_with_label ("close");
  700.   gtk_signal_connect_object (GTK_OBJECT (button), "clicked",
  701.                  GTK_SIGNAL_FUNC(gtk_widget_destroy),
  702.                  GTK_OBJECT (textwindow));
  703.  
  704.   box = gtk_text_new (NULL, NULL);
  705.   gtk_text_set_editable (GTK_TEXT (box), FALSE);
  706.   vscrollbar = gtk_vscrollbar_new (GTK_TEXT(box)->vadj);
  707.  
  708.  
  709.   switch (option) {
  710.   case 0: 
  711.     gtk_window_set_title (GTK_WINDOW (textwindow), "Documentation");
  712.     gtk_widget_set_usize(box,450,500); 
  713.     gtk_text_set_word_wrap(GTK_TEXT(box),TRUE);
  714.     gtk_text_insert(GTK_TEXT(box),NULL,NULL,NULL,
  715.         "Frame header information: "\
  716.         "First the bitrate, sampling frequency and mono, stereo or jstereo "\
  717.         "indicators are displayed .  If the bitstream is jstereo, then mid/side "\
  718.         "stereo or intensity stereo may be on (indicated in red).  If "\
  719.         "de-emphasis is used, this is also indicated in red.  The mdb value is "\
  720.         "main_data_begin.  The encoded data starts this many bytes *before* the "\
  721.         "frame header.  A large value of mdb means the bitstream has saved some "\
  722.         "bits into the reservoir, which it may allocate for some future frame. "\
  723.         "The two numbers after mdb are the size (in bits) used to encode the "\
  724.         "MDCT coefficients for this frame, followed byt the size of the bit "\
  725.         "resevoir before encoding this frame.  The maximum frame size and a "\
  726.         "running average are given in the Stats pull down menu.  A large "\
  727.         "maximum frame size indicates the bitstream has made use of the bit "\
  728.         "reservoir. \n\n",-1);
  729.  
  730.     gtk_text_insert(GTK_TEXT(box),NULL,NULL,NULL,
  731.         "PCM data (top graph): "\
  732.         "The PCM data is plotted in black.  The layer3 frame is divided into 2 "\
  733.         "granules of 576 samples (marked with yellow vertical lines).  In the "\
  734.         "case of normal, start and stop blocks, the MDCT coefficients for each "\
  735.         "granule are computed using a 1152 sample window centered over the "\
  736.         "granule.  In the case of short blocks, the granule is further divided "\
  737.         "into 3 blocks of 192 samples (also marked with yellow vertical lines)."\
  738.         "The MDCT coefficients for these blocks are computed using 384 sample "\
  739.         "windows centered over the 192 sample window.  (This info not available "\
  740.         "when analyzing .mp3 files.)  For the psycho-acoustic model, a windowed "\
  741.         "FFT is computed for each granule.  The range of these windows "\
  742.         "is denoted by the blue and green bars.\n\n",-1);
  743.  
  744.         gtk_text_insert(GTK_TEXT(box),NULL,NULL,NULL,
  745.         "PCM re-synthesis data (second graph): "\
  746.         "Same as the PCM window described above.  The data displayed is the "\
  747.         "result of encoding and then decoding the original sample. \n\n",-1);
  748.  
  749.         gtk_text_insert(GTK_TEXT(box),NULL,NULL,NULL,
  750.         "MDCT windows: "\
  751.         "Shows the energy in the MDCT spectrum for granule 0 (left window) "\
  752.         "and granule 1 (right window).  The text also shows the blocktype "\
  753.         "used, the number of bits used to encode the coefficients and the "\
  754.         "number of extra bits allocated from the reservoir.  The MDCT pull down "\
  755.         "window will toggle between the original unquantized MDCT coefficients "\
  756.         "and the compressed (quantized) coefficients.\n\n",-1); 
  757.  
  758.         gtk_text_insert(GTK_TEXT(box),NULL,NULL,NULL,
  759.         "FFT window: "\
  760.         "The gray bars show the energy in the FFT spectrum used by the "\
  761.         "psycho-acoustic model.  Granule 0 is in the left window, granule 1 in "\
  762.         "the right window.  The green and blue bars show how much distortion is "\
  763.         "allowable, as computed by the psycho-acoustic model. The red bars show "\
  764.         "the actual distortion after encoding.  There is one FFT for each "\
  765.         "granule, computed with a 1024 Hann window centered over the "\
  766.         "appropriate granule.  (the range of this 1024 sample window is shown "\
  767.         "by the blue and green bars in the PCM data window).  The Spectrum pull "\
  768.         "down window will toggle between showing the energy in equally spaced "\
  769.         "frequency domain and the scale factor bands used by layer3.  Finally, "\
  770.         "the perceptual entropy, total energy and number of scalefactor bands "\
  771.         "with audible distortion is shown.  (This info not available when "\
  772.         "analyzing .mp3 files.)",-1);
  773.  
  774.     break;
  775.   case 1:
  776.     /* Set the about box information */
  777.     gtk_window_set_title (GTK_WINDOW (textwindow), "About");
  778.     gtk_widget_set_usize(box,350,260);
  779.  
  780.     sprintf(text,"LAME version %s \nwww.sulaco.org/mp3\n\n",get_lame_version());
  781.     gtk_text_insert(GTK_TEXT(box),NULL,NULL,NULL,text,-1);
  782.  
  783.     sprintf(text,"psycho-acoustic model:  GPSYCHO version %s \nMark Taylor\n\n",get_psy_version());
  784.     gtk_text_insert(GTK_TEXT(box),NULL,NULL,NULL,text,-1);
  785.     
  786.     sprintf(text,"frame analyzer: MP3x version %s  \nMark Taylor\n\n",get_mp3x_version());
  787.     gtk_text_insert(GTK_TEXT(box),NULL,NULL,NULL,text,-1);
  788.     
  789.     gtk_text_insert(GTK_TEXT(box),NULL,NULL,NULL,
  790.             "decoder:  mpg123/mpglib  .59q  \nMichael Hipp \nwww-ti.informatik.uni-tuebingen.de/~hippm/mpg123.html\n\n",-1);
  791.     
  792.     gtk_text_insert(GTK_TEXT(box),NULL,NULL,NULL,
  793.     "Encoder, decoder & psy-models based on ISO\ndemonstration source. ",-1);
  794.     break;
  795.  
  796.   case 2:
  797.     gtk_window_set_title (GTK_WINDOW (textwindow), "Statistics");
  798.     gtk_widget_set_usize(box,350,260);
  799.     sprintf(text,"frames processed so far: %i \n",Pinfo[0].frameNum);
  800.     gtk_text_insert(GTK_TEXT(box),NULL,NULL,NULL,text,-1);
  801.     sprintf(text,"granules processed so far: %i \n\n",4*Pinfo[0].frameNum);
  802.     gtk_text_insert(GTK_TEXT(box),NULL,NULL,NULL,text,-1);
  803.     sprintf(text,"mean bits/frame (approximate): %i\n",
  804.         gtkinfo.approxbits);
  805.     gtk_text_insert(GTK_TEXT(box),NULL,NULL,NULL,text,-1);
  806.     sprintf(text,"mean bits/frame (from LAME): %i\n",
  807.         4*Pinfo[0].mean_bits);
  808.     gtk_text_insert(GTK_TEXT(box),NULL,NULL,NULL,text,-1);
  809.     sprintf(text,"bitsize of largest frame: %i \n",gtkinfo.maxbits);
  810.     gtk_text_insert(GTK_TEXT(box),NULL,NULL,NULL,text,-1);
  811.     sprintf(text,"average bits/frame: %3.1f \n\n",gtkinfo.avebits);
  812.     gtk_text_insert(GTK_TEXT(box),NULL,NULL,NULL,text,-1);
  813.     sprintf(text,"ms_stereo frames: %i \n",gtkinfo.totms);
  814.     gtk_text_insert(GTK_TEXT(box),NULL,NULL,NULL,text,-1);
  815.     sprintf(text,"i_stereo frames: %i \n",gtkinfo.totis);
  816.     gtk_text_insert(GTK_TEXT(box),NULL,NULL,NULL,text,-1);
  817.     sprintf(text,"de-emphasis frames: %i \n",gtkinfo.totemph);
  818.     gtk_text_insert(GTK_TEXT(box),NULL,NULL,NULL,text,-1);
  819.     sprintf(text,"short block granules: %i \n",gtkinfo.totshort);
  820.     gtk_text_insert(GTK_TEXT(box),NULL,NULL,NULL,text,-1);
  821.     sprintf(text,"mixed block granules: %i \n",gtkinfo.totmix);
  822.     gtk_text_insert(GTK_TEXT(box),NULL,NULL,NULL,text,-1);
  823.     break;
  824.   }
  825.  
  826.  
  827.  
  828.   gtk_widget_show (vscrollbar);
  829.   gtk_widget_show (box);
  830.   gtk_widget_show (vbox);
  831.   gtk_widget_show (hbox);
  832.   gtk_widget_show (button);
  833.  
  834.   gtk_box_pack_start (GTK_BOX(hbox), box, FALSE, TRUE, 0);
  835.   gtk_box_pack_start(GTK_BOX(hbox), vscrollbar, FALSE, FALSE, 0);
  836.   gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, TRUE, 0);
  837.   gtk_box_pack_end (GTK_BOX (vbox), button, FALSE, TRUE, 0);
  838.   gtk_container_add (GTK_CONTAINER (textwindow), vbox); 
  839.   gtk_widget_show(textwindow);
  840.  
  841. }
  842.  
  843.  
  844.  
  845.  
  846. /* #include <strings.h>*/
  847.  
  848.  
  849. /* This is the GtkItemFactoryEntry structure used to generate new menus.
  850.    Item 1: The menu path. The letter after the underscore indicates an
  851.            accelerator key once the menu is open.
  852.    Item 2: The accelerator key for the entry
  853.    Item 3: The callback function.
  854.    Item 4: The callback action.  This changes the parameters with
  855.            which the function is called.  The default is 0.
  856.    Item 5: The item type, used to define what kind of an item it is.
  857.            Here are the possible values:
  858.  
  859.            NULL               -> "<Item>"
  860.            ""                 -> "<Item>"
  861.            "<Title>"          -> create a title item
  862.            "<Item>"           -> create a simple item
  863.            "<CheckItem>"      -> create a check item
  864.            "<ToggleItem>"     -> create a toggle item
  865.            "<RadioItem>"      -> create a radio item
  866.            <path>             -> path of a radio item to link against
  867.            "<Separator>"      -> create a separator
  868.            "<Branch>"         -> create an item to hold sub items
  869.            "<LastBranch>"     -> create a right justified branch 
  870. */
  871.  
  872. static GtkItemFactoryEntry menu_items[] = {
  873.   {"/_File",         NULL,         NULL, 0, "<Branch>"},
  874.   /*
  875.   {"/File/_New",     "<control>N", print_hello, 0, NULL},
  876.   {"/File/_Open",    "<control>O", print_hello, 0, NULL},
  877.   {"/File/_Save",    "<control>S", print_hello, 0, NULL},
  878.   {"/File/Save _As", NULL,         NULL, 0, NULL},
  879.   {"/File/sep1",     NULL,         NULL, 0, "<Separator>"},
  880.   {"/File/Quit",     "<control>Q", gtk_main_quit, 0, NULL}, 
  881.   */
  882.   {"/File/_Quit",     "<control>Q", delete_event, 0, NULL}, 
  883.  
  884.   {"/_Plotting",            NULL,         NULL,   0,    "<Branch>"},
  885.   {"/Plotting/_While advancing" ,  NULL,  spec_option, 5, NULL},
  886.   {"/Plotting/_After advancing",  NULL,  spec_option, 6, NULL},
  887.  
  888.   {"/_Channel",            NULL,         NULL,   0,    "<Branch>"},
  889.   {"/Channel/show _Left" ,  NULL,  channel_option, 1, NULL},
  890.   {"/Channel/show _Right",  NULL,  channel_option, 2, NULL},
  891.   {"/Channel/show _Mid" ,   NULL,  channel_option, 3, NULL},
  892.   {"/Channel/show _Side",   NULL,  channel_option, 4, NULL},
  893.  
  894.   {"/_Spectrum",                   NULL,  NULL, 0, "<Branch>"},
  895.   {"/Spectrum/_Scalefactor bands",  NULL,  spec_option, 1, NULL},
  896.   {"/Spectrum/_Wave number",        NULL,  spec_option, 2, NULL},
  897.  
  898.   {"/_MDCT",                         NULL,  NULL, 0, "<Branch>"},
  899.   {"/MDCT/_Original",               NULL,  spec_option, 3, NULL},
  900.   {"/MDCT/_Compressed",             NULL,  spec_option, 4, NULL},
  901.  
  902.   {"/_Stats",                         NULL,  NULL, 0, "<Branch>"},
  903.   {"/Stats/_Show",               NULL,  text_window, 2, NULL},
  904.  
  905.   {"/_Help",         NULL,         NULL, 0, "<LastBranch>"},
  906.   {"/_Help/_Documentation",   NULL,   text_window, 0, NULL},
  907.   {"/_Help/_About",           NULL,   text_window, 1, NULL},
  908. };
  909.  
  910.  
  911. static void get_main_menu(GtkWidget *window, GtkWidget ** menubar) {
  912.   int nmenu_items = sizeof(menu_items) / sizeof(menu_items[0]);
  913.   GtkItemFactory *item_factory;
  914.   GtkAccelGroup *accel_group;
  915.  
  916.   accel_group = gtk_accel_group_new();
  917.  
  918.   /* This function initializes the item factory.
  919.      Param 1: The type of menu - can be GTK_TYPE_MENU_BAR, GTK_TYPE_MENU,
  920.               or GTK_TYPE_OPTION_MENU.
  921.      Param 2: The path of the menu.
  922.      Param 3: A pointer to a gtk_accel_group.  The item factory sets up
  923.               the accelerator table while generating menus.
  924.   */
  925.  
  926.   item_factory = gtk_item_factory_new(GTK_TYPE_MENU_BAR, "<main>", 
  927.                        accel_group);
  928.  
  929.   /* This function generates the menu items. Pass the item factory,
  930.      the number of items in the array, the array itself, and any
  931.      callback data for the the menu items. */
  932.   gtk_item_factory_create_items(item_factory, nmenu_items, menu_items, NULL);
  933.  
  934.   /* Attach the new accelerator group to the window. */
  935.   gtk_accel_group_attach (accel_group, GTK_OBJECT (window));
  936.  
  937.   if (menubar)
  938.     /* Finally, return the actual menu bar created by the item factory. */ 
  939.     *menubar = gtk_item_factory_get_widget(item_factory, "<main>");
  940. }
  941.  
  942.  
  943.  
  944.  
  945. int gtkcontrol(int totalframes,int filetype,char *infile, int gpsycho)
  946. {
  947.     /* GtkWidget is the storage type for widgets */
  948.     GtkWidget *button;
  949.     GtkAdjustment *adj;
  950.     GtkWidget *mbox;        /* main box */
  951.     GtkWidget *box1;        /* frame control buttons go */
  952.     GtkWidget *box2;        /* frame counters */
  953.     GtkWidget *box3;        /* frame header info */
  954.     GtkWidget *table;       /* table for all the plotting areas */
  955.     GtkWidget *menubar;
  956.  
  957.     gint tableops,graphx,graphy;
  958.     char frameinfo[80];
  959.  
  960.     graphx = 500;  /* minimum allowed size of pixmap */
  961.     graphy = 100;
  962.  
  963.  
  964.     /* set some global defaults/variables */
  965.     gtkinfo.totalframes = totalframes; 
  966.     gtkinfo.filetype = filetype;
  967.     gtkinfo.msflag=0;
  968.     gtkinfo.chflag=0;
  969.     gtkinfo.kbflag=0;
  970.     gtkinfo.flag123=filetype;
  971.     gtkinfo.pupdate=0;
  972.     gtkinfo.avebits = 0;
  973.     gtkinfo.maxbits = 0;
  974.     gtkinfo.approxbits = 0;
  975.     gtkinfo.totemph = 0;
  976.     gtkinfo.totms = 0;
  977.     gtkinfo.totis = 0;
  978.     gtkinfo.totshort = 0;
  979.     gtkinfo.totmix = 0;
  980.  
  981.     gtkinfo.gpsycho=gpsycho;
  982.     memset((char *) Pinfo, 0, sizeof(Pinfo));
  983.     pinfo = &Pinfo[READ_AHEAD];
  984.  
  985.     strcpy(frameinfo,"MP3x: ");
  986.     strncat(frameinfo,infile,70);
  987.  
  988.     window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
  989.     gtk_window_set_title (GTK_WINDOW (window), frameinfo);
  990.     gtk_signal_connect (GTK_OBJECT (window), "delete_event",
  991.             GTK_SIGNAL_FUNC (delete_event), NULL);
  992.     gtk_container_set_border_width (GTK_CONTAINER (window), 0);
  993.  
  994.  
  995.     mbox = gtk_vbox_new(FALSE, 0);
  996.  
  997.  
  998.     /* layout of mbox */
  999.     box1 = gtk_hbox_new(FALSE, 0);
  1000.     box2 = gtk_hbox_new(FALSE, 0);
  1001.     box3 = gtk_hbox_new(FALSE, 0);
  1002.     table = gtk_table_new (4, 2, FALSE);
  1003.     tableops = GTK_FILL | GTK_EXPAND | GTK_SHRINK;
  1004.     get_main_menu(window, &menubar);
  1005.  
  1006.     gtk_box_pack_start(GTK_BOX(mbox), menubar, FALSE, TRUE, 0);
  1007.     gtk_box_pack_end (GTK_BOX (mbox), box1, FALSE, TRUE, 0);
  1008.     gtk_box_pack_end(GTK_BOX (mbox),box2, FALSE, TRUE, 0);
  1009.     gtk_box_pack_start(GTK_BOX (mbox),box3, FALSE, TRUE, 0);
  1010.     gtk_box_pack_start (GTK_BOX (mbox), table, TRUE, TRUE, 0);
  1011.     gtk_container_add (GTK_CONTAINER (window), mbox); 
  1012.  
  1013.  
  1014.     /*********************************************************************/
  1015.     /* stuff in box3  frame header info */
  1016.     /*********************************************************************/
  1017.     /*
  1018.     headerbox = gtk_label_new(" ");
  1019.     gtk_label_set_justify(GTK_LABEL(headerbox),GTK_JUSTIFY_LEFT); 
  1020.     */
  1021.     headerbox = gtk_text_new (NULL, NULL);
  1022.     gtk_text_set_editable (GTK_TEXT (headerbox), FALSE);
  1023.     gtk_widget_set_usize(headerbox,200,20);
  1024.     gtk_widget_show (headerbox);
  1025.     gtk_box_pack_start(GTK_BOX (box3),headerbox, TRUE, TRUE, 0);
  1026.     
  1027.  
  1028.  
  1029.     /*********************************************************************/
  1030.     /* stuff in box2   frame counters  */
  1031.     /*********************************************************************/
  1032.     framecounter = gtk_label_new("");
  1033.     gtk_widget_show(framecounter);
  1034.     gtk_box_pack_start(GTK_BOX (box2),framecounter, FALSE, TRUE, 0);
  1035.  
  1036.     adj = (GtkAdjustment *) gtk_adjustment_new (0, 1,(gint) totalframes, 0, 0, 0);
  1037.     frameprogress = gtk_progress_bar_new_with_adjustment (adj);
  1038.     /* Set the format of the string that can be displayed in the
  1039.      * trough of the progress bar:
  1040.      * %p - percentage
  1041.      * %v - value
  1042.      * %l - lower range value
  1043.      * %u - upper range value */
  1044.     gtk_progress_set_format_string (GTK_PROGRESS (frameprogress),
  1045.                                 "%p%%");
  1046.     gtk_progress_set_value (GTK_PROGRESS (frameprogress), (gdouble) 0);
  1047.     gtk_progress_set_show_text (GTK_PROGRESS (frameprogress),TRUE);
  1048.     gtk_widget_show (frameprogress);
  1049.     gtk_box_pack_end (GTK_BOX (box2), frameprogress, FALSE, TRUE, 0);
  1050.  
  1051.  
  1052.  
  1053.     /*********************************************************************/
  1054.     /* stuff in box1  buttons along bottom */
  1055.     /*********************************************************************/
  1056.     button = gtk_button_new_with_label ("-1");
  1057.     gtk_signal_connect (GTK_OBJECT (button), "clicked",
  1058.             GTK_SIGNAL_FUNC (frameadv), (gpointer) "-1");
  1059.     gtk_box_pack_start(GTK_BOX(box1), button, TRUE, TRUE, 0);
  1060.     gtk_widget_show(button);
  1061.  
  1062.     button = gtk_button_new_with_label ("+1");
  1063.     gtk_signal_connect (GTK_OBJECT (button), "clicked",
  1064.             GTK_SIGNAL_FUNC (frameadv), (gpointer) "1");
  1065.     gtk_box_pack_start(GTK_BOX(box1), button, TRUE, TRUE, 0);
  1066.     gtk_widget_show(button);
  1067.  
  1068.     button = gtk_button_new_with_label ("+10");
  1069.     gtk_signal_connect (GTK_OBJECT (button), "clicked",
  1070.             GTK_SIGNAL_FUNC (frameadv), (gpointer) "10");
  1071.     gtk_box_pack_start(GTK_BOX(box1), button, TRUE, TRUE, 0);
  1072.     gtk_widget_show(button);
  1073.  
  1074.     button = gtk_button_new_with_label ("+100");
  1075.     gtk_signal_connect (GTK_OBJECT (button), "clicked",
  1076.             GTK_SIGNAL_FUNC (frameadv), (gpointer) "100");
  1077.     gtk_box_pack_start(GTK_BOX(box1), button, TRUE, TRUE, 0);
  1078.     gtk_widget_show(button);
  1079.  
  1080.     button = gtk_button_new_with_label ("finish mp3");
  1081.     gtk_signal_connect (GTK_OBJECT (button), "clicked",
  1082.             GTK_SIGNAL_FUNC (frameadv), (gpointer) "finish");
  1083.     gtk_box_pack_start(GTK_BOX(box1), button, TRUE, TRUE, 0);
  1084.     gtk_widget_show(button);
  1085.  
  1086.     button = gtk_button_new_with_label ("stop/plot");
  1087.     gtk_signal_connect (GTK_OBJECT (button), "clicked",
  1088.             GTK_SIGNAL_FUNC (plotclick), NULL);
  1089.     gtk_box_pack_start(GTK_BOX(box1), button, TRUE, TRUE, 0);
  1090.     gtk_widget_show(button);
  1091.  
  1092.  
  1093.     /*********************************************************************/
  1094.     /* stuff in table.  all the plotting windows */
  1095.     /*********************************************************************/
  1096.     pcmbox = gpk_plot_new(graphx,graphy);
  1097.     gtk_table_attach (GTK_TABLE(table),pcmbox,0,2,0,1,tableops,tableops,2,2 );
  1098.     gtk_widget_show (pcmbox);
  1099.  
  1100.     winbox = gpk_plot_new(graphy,graphy);
  1101.     gtk_table_attach(GTK_TABLE(table),winbox,0,2,1,2,tableops,tableops,2,2);
  1102.     gtk_widget_show (winbox);
  1103.  
  1104.  
  1105.     mdctbox[0] = gpk_plot_new(graphy,graphy);
  1106.     gtk_table_attach(GTK_TABLE(table),mdctbox[0],0,1,2,3,tableops,tableops,2,2);
  1107.     gtk_widget_show (mdctbox[0]);
  1108.  
  1109.     mdctbox[1] = gpk_plot_new(graphy,graphy);
  1110.     gtk_table_attach (GTK_TABLE(table),mdctbox[1],1,2,2,3,tableops,tableops,2,2);
  1111.     gtk_widget_show (mdctbox[1]);
  1112.  
  1113.     enerbox[0] = gpk_plot_new(graphy,graphy);
  1114.     gtk_table_attach(GTK_TABLE(table),enerbox[0],0,1,3,4,tableops,tableops,2,2);
  1115.     gtk_widget_show (enerbox[0]);
  1116.  
  1117.     enerbox[1] = gpk_plot_new(graphy,graphy);
  1118.     gtk_table_attach (GTK_TABLE(table),enerbox[1],1,2,3,4,tableops,tableops,2,2);
  1119.     gtk_widget_show (enerbox[1]);
  1120.  
  1121.  
  1122.  
  1123.  
  1124.     gtk_idle_add((GtkFunction) frameadv1, NULL);
  1125.     gtk_widget_show(menubar); 
  1126.     gtk_widget_show(box2); 
  1127.     gtk_widget_show(box3); 
  1128.     gtk_widget_show(table);
  1129.     gtk_widget_show(box1);
  1130.     gtk_widget_show (mbox);
  1131.     gtk_widget_show (window);     /* show smallest allowed window */
  1132.  
  1133.     /* make window bigger.   */ 
  1134.     /* now the user will be able to shrink it, if desired */
  1135.     /* gtk_widget_set_usize(mbox,500,500);  */
  1136.     /* gtk_widget_show (window); */     /* show smallest allowed window */
  1137.  
  1138.  
  1139.     
  1140.     idle_keepgoing=1;             /* processing of frames is ON */
  1141.     idle_count_max=READ_AHEAD+1;  /* number of frames to process before plotting */
  1142.     idle_count=0;                 /* pause & plot when idle_count=idle_count_max */
  1143.  
  1144.  
  1145.  
  1146.     gtk_main ();
  1147.     if (!mp3done) exit(2);
  1148.     return(0);
  1149. }
  1150.  
  1151. #endif
  1152.  
  1153.  
  1154.  
  1155.  
  1156.  
  1157.  
  1158.  
  1159.  
  1160.  
  1161.  
  1162.