gtkanal.c 57 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645
  1. /*
  2. * GTK plotting routines source file
  3. *
  4. * Copyright (c) 1999 Mark Taylor
  5. *
  6. * This library is free software; you can redistribute it and/or
  7. * modify it under the terms of the GNU Library General Public
  8. * License as published by the Free Software Foundation; either
  9. * version 2 of the License, or (at your option) any later version.
  10. *
  11. * This library is distributed in the hope that it will be useful,
  12. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  14. * Library General Public License for more details.
  15. *
  16. * You should have received a copy of the GNU Library General Public
  17. * License along with this library; if not, write to the
  18. * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
  19. * Boston, MA 02111-1307, USA.
  20. */
  21. /* $Id$ */
  22. #ifdef HAVE_CONFIG_H
  23. # include <config.h>
  24. #endif
  25. #include <gtk/gtk.h>
  26. #include "main.h"
  27. #include "lame.h"
  28. #include "machine.h"
  29. #include "encoder.h"
  30. #include "lame-analysis.h"
  31. #include "get_audio.h"
  32. #include "gtkanal.h"
  33. #include "gpkplotting.h"
  34. #include "lame_global_flags.h"
  35. /* this file should be removed. The few data items accessed in 'gfc'
  36. should be made accessable by writing a lame_set_variable() function */
  37. #include "util.h"
  38. #include "console.h"
  39. #ifdef _WIN32
  40. # include <windows.h>
  41. # define msleep(t) Sleep(t)
  42. #else
  43. # include <unistd.h>
  44. # define msleep(t) usleep((t) * 1000)
  45. #endif
  46. /*! Stringify \a x. */
  47. #define STR(x) #x
  48. /*! Stringify \a x, perform macro expansion. */
  49. #define XSTR(x) STR(x)
  50. #define MP3X_MAJOR_VERSION 0 /* Major version number */
  51. #define MP3X_MINOR_VERSION 82 /* Minor version number */
  52. #define MP3X_ALPHA_VERSION 0 /* Set number if this is an alpha version, otherwise zero */
  53. #define MP3X_BETA_VERSION 0 /* Set number if this is a beta version, otherwise zero */
  54. plotting_data *pinfo;
  55. plotting_data *pplot;
  56. plotting_data Pinfo[NUMPINFO];
  57. /* global variables for the state of the system */
  58. static gint idle_keepgoing; /* processing of frames is ON */
  59. static gint idle_count_max; /* number of frames to process before plotting */
  60. static gint idle_count; /* pause & plot when idle_count=idel_count_max */
  61. static gint idle_end = 0; /* process all frames, stop at last frame */
  62. static gint idle_back = 0; /* set when we are displaying the old data */
  63. static int mp3done = 0; /* last frame has been read */
  64. static GtkWidget *frameprogress; /* progress bar */
  65. static GtkWidget *framecounter; /* progress counter */
  66. static int subblock_draw[3] = { 1, 1, 1 };
  67. /* main window */
  68. GtkWidget *window;
  69. /* Backing pixmap for drawing areas */
  70. GtkWidget *pcmbox; /* PCM data plotted here */
  71. GtkWidget *winbox; /* mpg123 synthesis data plotted here */
  72. GtkWidget *enerbox[2]; /* spectrum, gr=0,1 plotted here */
  73. GtkWidget *mdctbox[2]; /* mdct coefficients gr=0,1 plotted here */
  74. GtkWidget *sfbbox[2]; /* scalefactors gr=0,1 plotted here */
  75. GtkWidget *headerbox; /* mpg123 header info shown here */
  76. struct gtkinfostruct {
  77. int filetype; /* input file type 0=WAV, 1=MP3 */
  78. int msflag; /* toggle between L&R vs M&S PCM data display */
  79. int chflag; /* toggle between L & R channels */
  80. int kbflag; /* toggle between wave # and barks */
  81. int flag123; /* show mpg123 frame info, OR ISO encoder frame info */
  82. double avebits; /* running average bits per frame */
  83. int approxbits; /* (approx) bits per frame */
  84. int maxbits; /* max bits per frame used so far */
  85. int totemph; /* total of frames with de-emphasis */
  86. int totms; /* total frames with ms_stereo */
  87. int totis; /* total frames with i_stereo */
  88. int totshort; /* total granules with short blocks */
  89. int totmix; /* total granules with mixed blocks */
  90. int totpreflag; /* total granules with preflag */
  91. int pupdate; /* plot while processing, or only when needed */
  92. int sfblines; /* plot scalefactor bands in MDCT plot */
  93. int difference; /* plot original - decoded instead of orig vs. decoded */
  94. int totalframes;
  95. } gtkinfo;
  96. static lame_global_flags *gfp;
  97. lame_internal_flags *gfc;
  98. hip_t hip; /* decoder handle of just encoded data */
  99. /**********************************************************************
  100. * read one frame and encode it
  101. **********************************************************************/
  102. int
  103. gtkmakeframe(void)
  104. {
  105. int iread = 0;
  106. static int init = 0;
  107. static int mpglag;
  108. static short int Buffer[2][1152];
  109. short int mpg123pcm[2][1152];
  110. int ch, j;
  111. int mp3count = 0;
  112. int mp3out = 0;
  113. int channels_out;
  114. unsigned char mp3buffer[LAME_MAXMP3BUFFER];
  115. static int frameNum = 0;
  116. int framesize = lame_get_framesize(gfp);
  117. channels_out = (lame_get_mode(gfp) == MONO) ? 1 : 2;
  118. pinfo->frameNum = frameNum;
  119. pinfo->sampfreq = lame_get_out_samplerate(gfp);
  120. pinfo->framesize = framesize;
  121. pinfo->stereo = channels_out;
  122. /* If the analsys code is enabled, lame will writes data into gfc->pinfo,
  123. * and mpg123 will write data into pinfo. Set these so
  124. * the libraries put this data in the right place: */
  125. gfc->pinfo = pinfo;
  126. hip_set_pinfo(hip, pinfo);
  127. if (is_mpeg_file_format(global_reader.input_format)) {
  128. hip_set_pinfo(get_hip(), pplot);
  129. iread = get_audio16(gfp, Buffer);
  130. /* add a delay of framesize-DECDELAY, which will make the total delay
  131. * exactly one frame, so we can sync MP3 output with WAV input */
  132. for (ch = 0; ch < channels_out; ch++) {
  133. for (j = 0; j < framesize - DECDELAY; j++)
  134. pinfo->pcmdata2[ch][j] = pinfo->pcmdata2[ch][j + framesize];
  135. for (j = 0; j < framesize; j++) /*rescale from int to short int */
  136. pinfo->pcmdata2[ch][j + framesize - DECDELAY] = Buffer[ch][j];
  137. }
  138. pinfo->frameNum123 = frameNum - 1;
  139. ++frameNum;
  140. }
  141. else {
  142. /* feed data to encoder until encoder produces some output */
  143. while (lame_get_frameNum(gfp) == pinfo->frameNum) {
  144. if (!init) {
  145. init = 1;
  146. mpglag = 1;
  147. if (hip) {
  148. hip_decode_exit(hip);
  149. }
  150. hip = hip_decode_init();
  151. hip_set_pinfo(hip, pinfo);
  152. }
  153. iread = get_audio16(gfp, Buffer);
  154. if (iread > framesize) {
  155. /* NOTE: frame analyzer requires that we encode one frame
  156. * for each pass through this loop. If lame_encode_buffer()
  157. * is feed data too quickly, it will sometimes encode multiple frames
  158. * breaking this loop.
  159. */
  160. error_printf("Warning: get_audio is returning too much data.\n");
  161. }
  162. if (iread <= 0)
  163. break; /* eof */
  164. mp3count = lame_encode_buffer(gfp, Buffer[0], Buffer[1], iread,
  165. mp3buffer, sizeof(mp3buffer));
  166. assert(!(mp3count > 0 && lame_get_frameNum(gfp) == pinfo->frameNum));
  167. /* not possible to produce mp3 data without encoding at least
  168. * one frame of data which would increment frameNum */
  169. }
  170. frameNum = lame_get_frameNum(gfp); /* use the internal MP3 frame counter */
  171. /* decode one frame of output */
  172. mp3out = hip_decode1(hip, mp3buffer, mp3count, mpg123pcm[0], mpg123pcm[1]); /* re-synthesis to pcm */
  173. /* mp3out = 0: need more data to decode */
  174. /* mp3out = -1: error. Lets assume 0 pcm output */
  175. /* mp3out = number of samples output */
  176. if (mp3out > 0)
  177. assert(mp3out == pinfo->framesize);
  178. if (mp3out != 0) {
  179. /* decoded output is for frame pinfo->frameNum123
  180. * add a delay of framesize-DECDELAY, which will make the total delay
  181. * exactly one frame */
  182. pinfo->frameNum123 = pinfo->frameNum - mpglag;
  183. for (ch = 0; ch < pinfo->stereo; ch++) {
  184. for (j = 0; j < pinfo->framesize - DECDELAY; j++)
  185. pinfo->pcmdata2[ch][j] = pinfo->pcmdata2[ch][j + pinfo->framesize];
  186. for (j = 0; j < pinfo->framesize; j++) {
  187. pinfo->pcmdata2[ch][j + pinfo->framesize - DECDELAY] =
  188. (mp3out == -1) ? 0 : mpg123pcm[ch][j];
  189. }
  190. }
  191. }
  192. else {
  193. if (mpglag == MAXMPGLAG) {
  194. error_printf("READ_AHEAD set too low - not enough frame buffering.\n"
  195. "MP3x display of input and output PCM data out of sync.\n");
  196. error_flush();
  197. }
  198. else
  199. mpglag++;
  200. pinfo->frameNum123 = -1; /* no frame output */
  201. }
  202. }
  203. return iread;
  204. }
  205. void
  206. plot_frame(void)
  207. {
  208. int i, j, n, ch, gr;
  209. gdouble *xcord, *ycord;
  210. gdouble xmx, xmn, ymx, ymn;
  211. double *data, *data2, *data3;
  212. char title2[80];
  213. char label[80], label2[80];
  214. char *title;
  215. plotting_data *pplot1;
  216. plotting_data *pplot2 = NULL;
  217. double en, samp;
  218. /*int sampindex, version = 0;*/
  219. int barthick;
  220. static int firstcall = 1;
  221. static GdkColor *barcolor, *color, *grcolor[2];
  222. static GdkColor yellow, gray, cyan, magenta, orange, pink, red, green, blue, black, oncolor,
  223. offcolor;
  224. int blocktype[2][2];
  225. int headbits;
  226. int mode_gr = 2;
  227. /* find the frame where mpg123 produced output coming from input frame
  228. * pinfo. i.e.: out_frame + out_frame_lag = input_frame */
  229. for (i = 1; i <= MAXMPGLAG; i++) {
  230. if ((pplot - i)->frameNum123 == pplot->frameNum) {
  231. pplot2 = pplot - i;
  232. break;
  233. }
  234. }
  235. if (i > MAXMPGLAG) {
  236. error_printf("input/output pcm syncing problem. should not happen!\n");
  237. pplot2 = pplot - 1;
  238. }
  239. /* however, the PCM data is delayed by 528 samples in the encoder filterbanks.
  240. * We added another 1152-528 delay to this so the PCM data is *exactly* one
  241. * frame behind the header & MDCT information */
  242. pplot1 = pplot2 + 1; /* back one frame for header info, MDCT */
  243. /* allocate these GC's only once */
  244. if (firstcall) {
  245. firstcall = 0;
  246. /* grcolor[0] = &magenta; */
  247. grcolor[0] = &blue;
  248. grcolor[1] = &green;
  249. barcolor = &gray;
  250. setcolor(headerbox, &oncolor, 255, 0, 0);
  251. setcolor(headerbox, &offcolor, 175, 175, 175);
  252. setcolor(pcmbox, &red, 255, 0, 0);
  253. setcolor(pcmbox, &pink, 255, 0, 255);
  254. setcolor(pcmbox, &magenta, 255, 0, 100);
  255. setcolor(pcmbox, &orange, 255, 127, 0);
  256. setcolor(pcmbox, &cyan, 0, 255, 255);
  257. setcolor(pcmbox, &green, 0, 255, 0);
  258. setcolor(pcmbox, &blue, 0, 0, 255);
  259. setcolor(pcmbox, &black, 0, 0, 0);
  260. setcolor(pcmbox, &gray, 100, 100, 100);
  261. setcolor(pcmbox, &yellow, 255, 255, 0);
  262. }
  263. /*******************************************************************
  264. * frame header info
  265. *******************************************************************/
  266. if (pplot1->sampfreq)
  267. samp = pplot1->sampfreq;
  268. else
  269. samp = 1;
  270. /*sampindex = SmpFrqIndex((long) samp, &version);*/
  271. ch = gtkinfo.chflag;
  272. headbits = 32 + ((pplot1->stereo == 2) ? 256 : 136);
  273. gtkinfo.approxbits = (pplot1->bitrate * 1000 * 1152.0 / samp) - headbits;
  274. sprintf(title2, "%3.1fkHz %ikbs ", samp / 1000, pplot1->bitrate);
  275. gtk_text_freeze(GTK_TEXT(headerbox));
  276. gtk_text_backward_delete(GTK_TEXT(headerbox), gtk_text_get_length(GTK_TEXT(headerbox)));
  277. gtk_text_set_point(GTK_TEXT(headerbox), 0);
  278. gtk_text_insert(GTK_TEXT(headerbox), NULL, &oncolor, NULL, title2, -1);
  279. title = " mono ";
  280. if (2 == pplot1->stereo)
  281. title = pplot1->js ? " js " : " s ";
  282. gtk_text_insert(GTK_TEXT(headerbox), NULL, &oncolor, NULL, title, -1);
  283. color = pplot1->ms_stereo ? &oncolor : &offcolor;
  284. gtk_text_insert(GTK_TEXT(headerbox), NULL, color, NULL, "ms ", -1);
  285. color = pplot1->i_stereo ? &oncolor : &offcolor;
  286. gtk_text_insert(GTK_TEXT(headerbox), NULL, color, NULL, "is ", -1);
  287. color = pplot1->crc ? &oncolor : &offcolor;
  288. gtk_text_insert(GTK_TEXT(headerbox), NULL, color, NULL, "crc ", -1);
  289. color = pplot1->padding ? &oncolor : &offcolor;
  290. gtk_text_insert(GTK_TEXT(headerbox), NULL, color, NULL, "pad ", -1);
  291. color = pplot1->emph ? &oncolor : &offcolor;
  292. gtk_text_insert(GTK_TEXT(headerbox), NULL, color, NULL, "em ", -1);
  293. sprintf(title2, "bv=%i,%i ", pplot1->big_values[0][ch], pplot1->big_values[1][ch]);
  294. gtk_text_insert(GTK_TEXT(headerbox), NULL, &black, NULL, title2, -1);
  295. color = pplot1->scfsi[ch] ? &oncolor : &offcolor;
  296. sprintf(title2, "scfsi=%i ", pplot1->scfsi[ch]);
  297. gtk_text_insert(GTK_TEXT(headerbox), NULL, color, NULL, title2, -1);
  298. if (gtkinfo.filetype)
  299. sprintf(title2, " mdb=%i %i/NA", pplot1->maindata, pplot1->totbits);
  300. else
  301. sprintf(title2, " mdb=%i %i/%i",
  302. pplot1->maindata, pplot1->totbits, pplot1->totbits + pplot->resvsize);
  303. gtk_text_insert(GTK_TEXT(headerbox), NULL, &oncolor, NULL, title2, -1);
  304. gtk_text_thaw(GTK_TEXT(headerbox));
  305. /*******************************************************************
  306. * block type
  307. *******************************************************************/
  308. for (gr = 0; gr < mode_gr; gr++)
  309. if (gtkinfo.flag123)
  310. blocktype[gr][ch] = pplot1->mpg123blocktype[gr][ch];
  311. else
  312. blocktype[gr][ch] = pplot->blocktype[gr][ch];
  313. /*******************************************************************
  314. * draw the PCM data *
  315. *******************************************************************/
  316. n = 1600; /* PCM frame + FFT window: 224 + 1152 + 224 */
  317. xcord = g_malloc(n * sizeof(gdouble));
  318. ycord = g_malloc(n * sizeof(gdouble));
  319. if (gtkinfo.msflag)
  320. title = ch ? "Side Channel" : "Mid Channel";
  321. else
  322. title = ch ? "Right Channel" : "Left Channel";
  323. sprintf(title2, "%s mask_ratio=%3.2f %3.2f ener_ratio=%3.2f %3.2f",
  324. title,
  325. pplot->ms_ratio[0], pplot->ms_ratio[1],
  326. pplot->ms_ener_ratio[0], pplot->ms_ener_ratio[1]);
  327. ymn = -32767;
  328. ymx = 32767;
  329. xmn = 0;
  330. xmx = 1600 - 1;
  331. /* 0 ... 224 draw in black, connecting to 224 pixel
  332. * 1375 .. 1599 draw in black connecting to 1375 pixel
  333. * 224 ... 1375 MP3 frame. draw in blue
  334. */
  335. /* draw the title */
  336. gpk_graph_draw(pcmbox, 0, xcord, ycord, xmn, ymn, xmx, ymx, 1, title2, &black);
  337. /* draw some hash marks dividing the frames */
  338. ycord[0] = ymx * .8;
  339. ycord[1] = ymn * .8;
  340. for (gr = 0; gr <= 2; gr++) {
  341. xcord[0] = 223.5 + gr * 576;
  342. xcord[1] = 223.5 + gr * 576;
  343. gpk_rectangle_draw(pcmbox, xcord, ycord, xmn, ymn, xmx, ymx, &yellow);
  344. }
  345. for (gr = 0; gr < mode_gr; gr++) {
  346. if (blocktype[gr][ch] == 2)
  347. for (i = 1; i <= 2; i++) {
  348. xcord[0] = 223.5 + gr * 576 + i * 192;
  349. xcord[1] = 223.5 + gr * 576 + i * 192;
  350. gpk_rectangle_draw(pcmbox, xcord, ycord, xmn, ymn, xmx, ymx, &yellow);
  351. }
  352. }
  353. /* bars representing FFT windows */
  354. xcord[0] = 0;
  355. ycord[0] = ymn + 3000;
  356. xcord[1] = 1024 - 1;
  357. ycord[1] = ymn + 1000;
  358. gpk_rectangle_draw(pcmbox, xcord, ycord, xmn, ymn, xmx, ymx, grcolor[0]);
  359. xcord[0] = 576;
  360. ycord[0] = ymn + 2000;
  361. xcord[1] = 576 + 1024 - 1;
  362. ycord[1] = ymn;
  363. gpk_rectangle_draw(pcmbox, xcord, ycord, xmn, ymn, xmx, ymx, grcolor[1]);
  364. /* plot PCM data */
  365. for (i = 0; i < n; i++) {
  366. xcord[i] = i;
  367. if (gtkinfo.msflag)
  368. ycord[i] = ch ? .5 * (pplot->pcmdata[0][i] - pplot->pcmdata[1][i]) :
  369. .5 * (pplot->pcmdata[0][i] + pplot->pcmdata[1][i]);
  370. else
  371. ycord[i] = pplot->pcmdata[ch][i];
  372. }
  373. /* skip plot if we are doing an mp3 file */
  374. if (!gtkinfo.filetype) {
  375. gpk_graph_draw(pcmbox, n, xcord, ycord, xmn, ymn, xmx, ymx, 0, title2, &black);
  376. }
  377. /*******************************************************************/
  378. /* draw the PCM re-synthesis data */
  379. /*******************************************************************/
  380. n = 1152;
  381. /*
  382. sprintf(title2,"Re-synthesis mask_ratio=%3.2f %3.2f ener_ratio=%3.2f %3.2f",
  383. pplot->ms_ratio[0],pplot->ms_ratio[1],
  384. pplot->ms_ener_ratio[0],pplot->ms_ener_ratio[1]);
  385. */
  386. title = "Re-synthesis";
  387. if (gtkinfo.difference)
  388. title = "Re-synthesis difference (amplified 20db)";
  389. ymn = -32767;
  390. ymx = 32767;
  391. xmn = 0;
  392. xmx = 1600 - 1;
  393. gpk_graph_draw(winbox, 0, xcord, ycord, xmn, ymn, xmx, ymx, 1, title, &black);
  394. /* draw some hash marks dividing the frames */
  395. ycord[0] = ymx * .8;
  396. ycord[1] = ymn * .8;
  397. for (gr = 0; gr <= 2; gr++) {
  398. xcord[0] = 223.5 + gr * 576;
  399. xcord[1] = 223.5 + gr * 576;
  400. gpk_rectangle_draw(winbox, xcord, ycord, xmn, ymn, xmx, ymx, &yellow);
  401. }
  402. for (gr = 0; gr < 2; gr++) {
  403. if (blocktype[gr][ch] == 2)
  404. for (i = 1; i <= 2; i++) {
  405. xcord[0] = 223.5 + gr * 576 + i * 192;
  406. xcord[1] = 223.5 + gr * 576 + i * 192;
  407. gpk_rectangle_draw(winbox, xcord, ycord, xmn, ymn, xmx, ymx, &yellow);
  408. }
  409. }
  410. /* this piece of PCM data from previous frame */
  411. n = 224;
  412. for (j = 1152 - n, i = 0; i < n; i++, j++) {
  413. xcord[i] = i;
  414. if (gtkinfo.msflag)
  415. ycord[i] = ch ? .5 * (pplot1->pcmdata2[0][j] -
  416. pplot1->pcmdata2[1][j]) :
  417. .5 * (pplot1->pcmdata2[0][j] + pplot1->pcmdata2[1][j]);
  418. else
  419. ycord[i] = pplot1->pcmdata2[ch][j];
  420. }
  421. /* this piece of PCM data from current frame */
  422. n = 1152;
  423. for (i = 0; i < n; i++) {
  424. xcord[i + 224] = i + 224;
  425. if (gtkinfo.msflag)
  426. ycord[i + 224] = ch ? .5 * (pplot2->pcmdata2[0][i] - pplot2->pcmdata2[1][i]) :
  427. .5 * (pplot2->pcmdata2[0][i] + pplot2->pcmdata2[1][i]);
  428. else
  429. ycord[i + 224] = pplot2->pcmdata2[ch][i];
  430. }
  431. n = 1152 + 224;
  432. if (gtkinfo.difference) {
  433. for (i = 0; i < n; i++) {
  434. if (gtkinfo.msflag)
  435. ycord[i] -= ch ? .5 * (pplot->pcmdata[0][i] - pplot->pcmdata[1][i]) :
  436. .5 * (pplot->pcmdata[0][i] + pplot->pcmdata[1][i]);
  437. else
  438. ycord[i] -= pplot->pcmdata[ch][i];
  439. }
  440. ycord[i] *= 100;
  441. }
  442. gpk_graph_draw(winbox, n, xcord, ycord, xmn, ymn, xmx, ymx, 0, title, &black);
  443. /*******************************************************************/
  444. /* draw the MDCT energy spectrum */
  445. /*******************************************************************/
  446. for (gr = 0; gr < mode_gr; gr++) {
  447. int bits, bits2;
  448. char *blockname = "";
  449. switch (blocktype[gr][ch]) {
  450. case 0:
  451. blockname = "normal";
  452. break;
  453. case 1:
  454. blockname = "start";
  455. break;
  456. case 2:
  457. blockname = "short";
  458. break;
  459. case 3:
  460. blockname = "end";
  461. break;
  462. }
  463. strcpy(label, blockname);
  464. if (pplot1->mixed[gr][ch])
  465. strcat(label, "(mixed)");
  466. n = 576;
  467. if (gtkinfo.flag123) {
  468. data = pplot1->mpg123xr[gr][0];
  469. data2 = pplot1->mpg123xr[gr][1];
  470. }
  471. else {
  472. data = pplot->xr[gr][0];
  473. data2 = pplot->xr[gr][1];
  474. }
  475. xmn = 0;
  476. xmx = n - 1;
  477. ymn = 0;
  478. ymx = 11;
  479. /* draw title, erase old plot */
  480. if (gtkinfo.flag123) {
  481. bits = pplot1->mainbits[gr][ch];
  482. bits2 = pplot1->sfbits[gr][ch];
  483. }
  484. else {
  485. bits = pplot->LAMEmainbits[gr][ch];
  486. bits2 = pplot->LAMEsfbits[gr][ch];
  487. }
  488. sprintf(title2, "MDCT%1i(%s) bits=%i/%i ", gr, label, bits, bits2);
  489. gpk_bargraph_draw(mdctbox[gr], 0, xcord, ycord, xmn, ymn, xmx, ymx, 1, title2, 0, barcolor);
  490. /* draw some hash marks showing scalefactor bands */
  491. if (gtkinfo.sfblines) {
  492. int fac, nsfb, *scalefac;
  493. if (blocktype[gr][ch] == SHORT_TYPE) {
  494. nsfb = SBMAX_s;
  495. i = nsfb - 7;
  496. fac = 3;
  497. scalefac = gfc->scalefac_band.s;
  498. }
  499. else {
  500. nsfb = SBMAX_l;
  501. i = nsfb - 10;
  502. fac = 1;
  503. scalefac = gfc->scalefac_band.l;
  504. }
  505. for (; i < nsfb; i++) {
  506. ycord[0] = .8 * ymx;
  507. ycord[1] = ymn;
  508. xcord[0] = fac * scalefac[i];
  509. xcord[1] = xcord[0];
  510. gpk_rectangle_draw(mdctbox[gr], xcord, ycord, xmn, ymn, xmx, ymx, &yellow);
  511. }
  512. }
  513. ymn = 9e20;
  514. ymx = -9e20;
  515. for (i = 0; i < n; i++) {
  516. double coeff;
  517. xcord[i] = i;
  518. if (gtkinfo.msflag) {
  519. coeff = ch ? .5 * (data[i] - data2[i]) : .5 * (data[i] + data2[i]);
  520. }
  521. else {
  522. coeff = ch ? data2[i] : data[i];
  523. }
  524. if (blocktype[gr][ch] == SHORT_TYPE && !subblock_draw[i % 3])
  525. coeff = 0;
  526. ycord[i] = coeff * coeff * 1e10;
  527. ycord[i] = log10(MAX(ycord[i], (double) 1));
  528. #if 0
  529. if (ch == 0)
  530. if (i == 26)
  531. if (data[i] != 0)
  532. console_printf("%i %i i=%i mdct: (db) %f %f \n", pplot->frameNum, gr, i,
  533. 10 * log10(data[i] * data[i]),
  534. 10 * log10(.33 *
  535. (data[i - 1] * data[i - 1] + data[i] * data[i] +
  536. data[i + 1] * data[i + 1]))
  537. );
  538. #endif
  539. ymx = (ycord[i] > ymx) ? ycord[i] : ymx;
  540. ymn = (ycord[i] < ymn) ? ycord[i] : ymn;
  541. }
  542. /* print the min/max
  543. sprintf(title2,"MDCT%1i %5.2f %5.2f bits=%i",gr,ymn,ymx,
  544. pplot1->mainbits[gr][ch]);
  545. */
  546. if (gtkinfo.flag123)
  547. bits = pplot1->mainbits[gr][ch];
  548. else
  549. bits = pplot->LAMEmainbits[gr][ch];
  550. sprintf(title2, "MDCT%1i(%s) bits=%i ", gr, label, bits);
  551. xmn = 0;
  552. xmx = n - 1;
  553. ymn = 0;
  554. ymx = 11;
  555. gpk_bargraph_draw(mdctbox[gr], n, xcord, ycord, xmn, ymn, xmx, ymx, 0, title2, 0, barcolor);
  556. }
  557. /*******************************************************************
  558. * draw the psy model energy spectrum (k space)
  559. * l3psy.c computes pe, en, thm for THIS granule.
  560. *******************************************************************/
  561. if (gtkinfo.kbflag) {
  562. for (gr = 0; gr < mode_gr; gr++) {
  563. n = HBLKSIZE; /* only show half the spectrum */
  564. data = &pplot->energy[gr][ch][0];
  565. ymn = 9e20;
  566. ymx = -9e20;
  567. for (i = 0; i < n; i++) {
  568. xcord[i] = i + 1;
  569. if (blocktype[gr][ch] == SHORT_TYPE && !subblock_draw[i % 3])
  570. ycord[i] = 0;
  571. else
  572. ycord[i] = log10(MAX(data[i], (double) 1));
  573. ymx = (ycord[i] > ymx) ? ycord[i] : ymx;
  574. ymn = (ycord[i] < ymn) ? ycord[i] : ymn;
  575. }
  576. for (en = 0, j = 0; j < BLKSIZE; j++)
  577. en += pplot->energy[gr][ch][j];
  578. sprintf(title2, "FFT%1i pe=%5.2fK en=%5.2e ", gr, pplot->pe[gr][ch] / 1000, en);
  579. ymn = 3;
  580. ymx = 15;
  581. xmn = 1;
  582. xmx = n;
  583. gpk_bargraph_draw(enerbox[gr], n, xcord, ycord,
  584. xmn, ymn, xmx, ymx, 1, title2, 0, barcolor);
  585. }
  586. }
  587. else {
  588. /*******************************************************************
  589. * draw the psy model energy spectrum (scalefactor bands)
  590. *******************************************************************/
  591. for (gr = 0; gr < mode_gr; gr++) {
  592. if (blocktype[gr][ch] == 2) {
  593. n = 3 * SBMAX_s;
  594. data = &pplot->en_s[gr][ch][0];
  595. data2 = &pplot->thr_s[gr][ch][0];
  596. data3 = &pplot->xfsf_s[gr][ch][0];
  597. }
  598. else {
  599. n = SBMAX_l;
  600. data = &pplot->en[gr][ch][0];
  601. data2 = &pplot->thr[gr][ch][0];
  602. data3 = &pplot->xfsf[gr][ch][0];
  603. }
  604. ymn = 9e20;
  605. ymx = -9e20;
  606. for (i = 0; i < n; i++) {
  607. xcord[i] = i + 1;
  608. if (blocktype[gr][ch] == SHORT_TYPE && !subblock_draw[i % 3])
  609. ycord[i] = 0;
  610. else
  611. ycord[i] = log10(MAX(data[i], (double) 1));
  612. /*
  613. ymx=(ycord[i] > ymx) ? ycord[i] : ymx;
  614. ymn=(ycord[i] < ymn) ? ycord[i] : ymn;
  615. */
  616. }
  617. /* en = max energy difference amoung the 3 short FFTs for this granule */
  618. en = pplot->ers[gr][ch];
  619. if (en > 999)
  620. en = 999;
  621. sprintf(title2,
  622. "FFT%1i pe=%5.2fK/%3.1f \nnoise ovr_b:%i/max:%3.1f/ovr:%3.1f/tot:%3.1f/ssd:%i",
  623. gr, pplot->pe[gr][ch] / 1000, en, pplot->over[gr][ch], pplot->max_noise[gr][ch],
  624. pplot->over_noise[gr][ch], pplot->tot_noise[gr][ch], pplot->over_SSD[gr][ch]);
  625. barthick = 3;
  626. if (blocktype[gr][ch] == SHORT_TYPE)
  627. barthick = 2;
  628. if (!(subblock_draw[0] && subblock_draw[1] && subblock_draw[2]))
  629. barthick = 3;
  630. ymn = 3;
  631. ymx = 15;
  632. xmn = 1;
  633. xmx = n + 1; /* a little extra because of the bar thickness */
  634. gpk_bargraph_draw(enerbox[gr], n, xcord, ycord,
  635. xmn, ymn, xmx, ymx, 1, title2, barthick, barcolor);
  636. for (i = 0; i < n; i++) {
  637. xcord[i] = i + 1 + .20;
  638. if (blocktype[gr][ch] == SHORT_TYPE && !subblock_draw[i % 3])
  639. ycord[i] = 0;
  640. else
  641. ycord[i] = log10(MAX(data2[i], (double) 1));
  642. }
  643. gpk_bargraph_draw(enerbox[gr], n, xcord, ycord,
  644. xmn, ymn, xmx, ymx, 0, title2, barthick, grcolor[gr]);
  645. for (i = 0; i < n; i++) {
  646. xcord[i] = i + 1 + .40;
  647. if (blocktype[gr][ch] == SHORT_TYPE && !subblock_draw[i % 3])
  648. ycord[i] = 0;
  649. else
  650. ycord[i] = log10(MAX(data3[i], (double) 1));
  651. }
  652. gpk_bargraph_draw(enerbox[gr], n, xcord, ycord,
  653. xmn, ymn, xmx, ymx, 0, title2, barthick, &red);
  654. }
  655. }
  656. /*******************************************************************
  657. * draw scalefactors
  658. *******************************************************************/
  659. for (gr = 0; gr < mode_gr; gr++) {
  660. int ggain;
  661. if (blocktype[gr][ch] == 2) {
  662. n = 3 * SBMAX_s;
  663. if (gtkinfo.flag123)
  664. data = pplot1->sfb_s[gr][ch];
  665. else
  666. data = pplot->LAMEsfb_s[gr][ch];
  667. }
  668. else {
  669. n = SBMAX_l;
  670. if (gtkinfo.flag123)
  671. data = pplot1->sfb[gr][ch];
  672. else
  673. data = pplot->LAMEsfb[gr][ch];
  674. }
  675. ymn = -1;
  676. ymx = 10;
  677. for (i = 0; i < n; i++) {
  678. xcord[i] = i + 1;
  679. if (blocktype[gr][ch] == SHORT_TYPE && !subblock_draw[i % 3])
  680. ycord[i] = 0;
  681. else
  682. ycord[i] = -data[i];
  683. ymx = (ycord[i] > ymx - 2) ? ycord[i] + 2 : ymx;
  684. ymn = (ycord[i] < ymn) ? ycord[i] - 1 : ymn;
  685. }
  686. if (blocktype[gr][ch] == 2) {
  687. sprintf(label2,
  688. "SFB scale=%i preflag=%i %i%i%i",
  689. pplot1->scalefac_scale[gr][ch],
  690. pplot1->preflag[gr][ch],
  691. pplot1->sub_gain[gr][ch][0],
  692. pplot1->sub_gain[gr][ch][1], pplot1->sub_gain[gr][ch][2]);
  693. }
  694. else {
  695. sprintf(label2, "SFB scale=%i preflag=%i", pplot1->scalefac_scale[gr][ch],
  696. pplot1->preflag[gr][ch]);
  697. }
  698. if (gtkinfo.flag123)
  699. ggain = (pplot1->qss[gr][ch]);
  700. else
  701. ggain = (pplot->LAMEqss[gr][ch]);
  702. sprintf(title2, " ggain=%i", ggain);
  703. strcat(label2, title2);
  704. xmn = 1;
  705. xmx = n + 1;
  706. gpk_bargraph_draw(sfbbox[gr], n, xcord, ycord,
  707. xmn, ymn, xmx, ymx, 1, label2, 0, grcolor[gr]);
  708. ycord[0] = ycord[1] = 0;
  709. xcord[0] = 1;
  710. xcord[1] = n + 1;
  711. gpk_rectangle_draw(sfbbox[gr], xcord, ycord, xmn, ymn, xmx, ymx, &yellow);
  712. }
  713. }
  714. static void
  715. update_progress(void)
  716. {
  717. char label[80];
  718. int tf = lame_get_totalframes(gfp);
  719. if (gtkinfo.totalframes > 0)
  720. tf = gtkinfo.totalframes;
  721. sprintf(label, "Frame:%4i/%4i %6.2fs", pplot->frameNum, (int) tf - 1, pplot->frametime);
  722. gtk_progress_set_value(GTK_PROGRESS(frameprogress), (gdouble) pplot->frameNum);
  723. gtk_label_set_text(GTK_LABEL(framecounter), label);
  724. }
  725. static void
  726. analyze(void)
  727. {
  728. if (idle_keepgoing) {
  729. idle_count = 0;
  730. idle_count_max = 0;
  731. idle_keepgoing = 0;
  732. idle_end = 0;
  733. }
  734. plot_frame();
  735. update_progress();
  736. }
  737. static void
  738. plotclick(GtkWidget * widget, gpointer data)
  739. {
  740. analyze();
  741. }
  742. static int
  743. frameadv1(GtkWidget * widget, gpointer data)
  744. {
  745. int i;
  746. if (idle_keepgoing) {
  747. if (idle_back) {
  748. /* frame displayed is the old frame. to advance, just swap in new frame */
  749. idle_back--;
  750. pplot = &Pinfo[READ_AHEAD + idle_back];
  751. }
  752. else {
  753. /* advance the frame by reading in a new frame */
  754. pplot = &Pinfo[READ_AHEAD];
  755. if (mp3done) {
  756. /* dont try to read any more frames, and quit if "finish MP3" was selected */
  757. /* if (idle_finish) gtk_main_quit(); */
  758. idle_count_max = 0;
  759. idle_end = 0;
  760. }
  761. else {
  762. /* read in the next frame */
  763. for (i = NUMPINFO - 1; i > 0; i--)
  764. memcpy(&Pinfo[i], &Pinfo[i - 1], sizeof(plotting_data));
  765. pinfo = &Pinfo[0];
  766. pinfo->num_samples = gtkmakeframe();
  767. if (pinfo->num_samples == 0 && gtkinfo.totalframes == 0)
  768. /* allow an extra frame to flush decoder buffers */
  769. gtkinfo.totalframes = pinfo->frameNum + 2;
  770. if (pinfo->sampfreq)
  771. pinfo->frametime = (pinfo->frameNum) * 1152.0 / pinfo->sampfreq;
  772. else
  773. pinfo->frametime = 0;
  774. /* eof?
  775. if (!pinfo->num_samples) if (idle_finish) gtk_main_quit();
  776. */
  777. pinfo->totbits = 0;
  778. {
  779. int gr, ch;
  780. for (gr = 0; gr < 2; gr++)
  781. for (ch = 0; ch < 2; ch++) {
  782. gtkinfo.totshort += (pinfo->mpg123blocktype[gr][ch] == 2);
  783. gtkinfo.totmix += !(pinfo->mixed[gr][ch] == 0);
  784. gtkinfo.totpreflag += (pinfo->preflag[gr][ch] == 1);
  785. pinfo->totbits += pinfo->mainbits[gr][ch];
  786. }
  787. }
  788. if (pinfo->frameNum > 0) /* start averaging at second frame */
  789. gtkinfo.avebits = (gtkinfo.avebits * ((pinfo->frameNum) - 1)
  790. + pinfo->totbits) / (pinfo->frameNum);
  791. gtkinfo.maxbits = MAX(gtkinfo.maxbits, pinfo->totbits);
  792. gtkinfo.totemph += !(pinfo->emph == 0);
  793. gtkinfo.totms += !(pinfo->ms_stereo == 0);
  794. gtkinfo.totis += !(pinfo->i_stereo == 0);
  795. if (gtkinfo.totalframes > 0)
  796. if (pplot->frameNum >= gtkinfo.totalframes - 1)
  797. mp3done = 1;
  798. }
  799. }
  800. idle_count++;
  801. if (gtkinfo.pupdate)
  802. plot_frame();
  803. update_progress();
  804. if ((idle_count >= idle_count_max) && (!idle_end))
  805. analyze();
  806. }
  807. else {
  808. /*no processing to do, sleep in order to not monopolize CPU */
  809. msleep(10);
  810. }
  811. return 1;
  812. }
  813. static void
  814. frameadv(GtkWidget * widget, gpointer data)
  815. {
  816. int adv;
  817. if (!strcmp((char *) data, "-1")) {
  818. /* ignore if we've already gone back as far as possible */
  819. if (pplot->frameNum == 0 || (idle_back == NUMBACK))
  820. return;
  821. idle_back++;
  822. pplot = &Pinfo[READ_AHEAD + idle_back];
  823. analyze();
  824. return;
  825. }
  826. adv = 1;
  827. if (!strcmp((char *) data, "1"))
  828. adv = 1;
  829. if (!strcmp((char *) data, "10"))
  830. adv = 10;
  831. if (!strcmp((char *) data, "100"))
  832. adv = 100;
  833. if (!strcmp((char *) data, "finish"))
  834. idle_end = 1;
  835. if (idle_keepgoing) {
  836. /* already running - que up additional frame advance requests */
  837. idle_count_max += adv;
  838. }
  839. else {
  840. /* turn on idleing */
  841. idle_count_max = adv;
  842. idle_count = 0;
  843. idle_keepgoing = 1;
  844. }
  845. }
  846. /* another callback */
  847. static void
  848. delete_event(GtkWidget * widget, GdkEvent * event, gpointer data)
  849. {
  850. /* set MP3 done flag in case the File/Quit menu item has been selected */
  851. mp3done = 1;
  852. if (hip) {
  853. hip_decode_exit(hip);
  854. hip = 0;
  855. }
  856. gtk_main_quit();
  857. }
  858. static void
  859. channel_option(GtkWidget * widget, gpointer data)
  860. {
  861. long option;
  862. option = (long) data;
  863. switch (option) {
  864. case 1:
  865. gtkinfo.msflag = 0;
  866. gtkinfo.chflag = 0;
  867. break;
  868. case 2:
  869. gtkinfo.msflag = 0;
  870. gtkinfo.chflag = 1;
  871. break;
  872. case 3:
  873. gtkinfo.msflag = 1;
  874. gtkinfo.chflag = 0;
  875. break;
  876. case 4:
  877. gtkinfo.msflag = 1;
  878. gtkinfo.chflag = 1;
  879. }
  880. analyze();
  881. }
  882. static void
  883. spec_option(GtkWidget * widget, gpointer data)
  884. {
  885. long option;
  886. option = (long) data;
  887. switch (option) {
  888. case 1:
  889. gtkinfo.kbflag = 0;
  890. break;
  891. case 2:
  892. gtkinfo.kbflag = 1;
  893. break;
  894. case 3:
  895. gtkinfo.flag123 = 0;
  896. break;
  897. case 4:
  898. gtkinfo.flag123 = 1;
  899. break;
  900. case 5:
  901. gtkinfo.pupdate = 1;
  902. break;
  903. case 6:
  904. gtkinfo.pupdate = 0;
  905. break;
  906. case 7:
  907. gtkinfo.sfblines = !gtkinfo.sfblines;
  908. break;
  909. case 8:
  910. gtkinfo.difference = !gtkinfo.difference;
  911. break;
  912. }
  913. analyze();
  914. }
  915. static gint
  916. key_press_event(GtkWidget * widget, GdkEventKey * event)
  917. {
  918. /* is a switch() statement in lame forbidden? */
  919. if (event->keyval == '1') {
  920. subblock_draw[0] = 1;
  921. subblock_draw[1] = 0;
  922. subblock_draw[2] = 0;
  923. analyze();
  924. }
  925. else if (event->keyval == '2') {
  926. subblock_draw[0] = 0;
  927. subblock_draw[1] = 1;
  928. subblock_draw[2] = 0;
  929. analyze();
  930. }
  931. else if (event->keyval == '3') {
  932. subblock_draw[0] = 0;
  933. subblock_draw[1] = 0;
  934. subblock_draw[2] = 1;
  935. analyze();
  936. }
  937. else if (event->keyval == '0') {
  938. subblock_draw[0] = 1;
  939. subblock_draw[1] = 1;
  940. subblock_draw[2] = 1;
  941. analyze();
  942. }
  943. /* analyze(); */ /* dont redraw entire window for every key! */
  944. return 0;
  945. }
  946. /*! Get the mp3x version string. */
  947. /*!
  948. \param void
  949. \return a pointer to a string which describes the version of mp3x.
  950. */
  951. const char *
  952. get_mp3x_version(void)
  953. {
  954. #if MP3X_ALPHA_VERSION > 0
  955. static /*@observer@ */ const char *const str =
  956. XSTR(MP3X_MAJOR_VERSION) "." XSTR(MP3X_MINOR_VERSION)
  957. " (alpha " XSTR(MP3X_ALPHA_VERSION) ", " __DATE__ " " __TIME__ ")";
  958. #elif MP3X_BETA_VERSION > 0
  959. static /*@observer@ */ const char *const str =
  960. XSTR(MP3X_MAJOR_VERSION) "." XSTR(MP3X_MINOR_VERSION)
  961. " (beta " XSTR(MP3X_BETA_VERSION) ", " __DATE__ ")";
  962. #else
  963. static /*@observer@ */ const char *const str =
  964. XSTR(MP3X_MAJOR_VERSION) "." XSTR(MP3X_MINOR_VERSION);
  965. #endif
  966. return str;
  967. }
  968. static void
  969. text_window(GtkWidget * widget, gpointer data)
  970. {
  971. long option;
  972. GtkWidget *hbox, *vbox, *button, *box;
  973. GtkWidget *textwindow, *vscrollbar;
  974. char text[256];
  975. option = (long) data;
  976. textwindow = gtk_window_new(GTK_WINDOW_DIALOG);
  977. gtk_signal_connect_object(GTK_OBJECT(window), "delete_event",
  978. GTK_SIGNAL_FUNC(gtk_widget_destroy), GTK_OBJECT(textwindow));
  979. gtk_container_set_border_width(GTK_CONTAINER(textwindow), 0);
  980. vbox = gtk_vbox_new(FALSE, 0);
  981. hbox = gtk_hbox_new(FALSE, 0);
  982. button = gtk_button_new_with_label("close");
  983. gtk_signal_connect_object(GTK_OBJECT(button), "clicked",
  984. GTK_SIGNAL_FUNC(gtk_widget_destroy), GTK_OBJECT(textwindow));
  985. box = gtk_text_new(NULL, NULL);
  986. gtk_text_set_editable(GTK_TEXT(box), FALSE);
  987. vscrollbar = gtk_vscrollbar_new(GTK_TEXT(box)->vadj);
  988. switch (option) {
  989. case 0:
  990. gtk_window_set_title(GTK_WINDOW(textwindow), "Documentation");
  991. gtk_widget_set_usize(box, 450, 500);
  992. gtk_text_set_word_wrap(GTK_TEXT(box), TRUE);
  993. /* text should be moved outside this function, may be in a separate file */
  994. gtk_text_insert(GTK_TEXT(box), NULL, NULL, NULL,
  995. "Frame header information: "
  996. "First the bitrate, sampling frequency and mono, stereo or jstereo "
  997. "indicators are displayed . If the bitstream is jstereo, then mid/side "
  998. "stereo or intensity stereo may be on (indicated in red). If "
  999. "de-emphasis is used, this is also indicated in red. The mdb value is "
  1000. "main_data_begin. The encoded data starts this many bytes *before* the "
  1001. "frame header. A large value of mdb means the bitstream has saved some "
  1002. "bits into the reservoir, which it may allocate for some future frame. "
  1003. "The two numbers after mdb are the size (in bits) used to encode the "
  1004. "MDCT coefficients for this frame, followed byt the size of the bit "
  1005. "resevoir before encoding this frame. The maximum frame size and a "
  1006. "running average are given in the Stats pull down menu. A large "
  1007. "maximum frame size indicates the bitstream has made use of the bit "
  1008. "reservoir. \n\n", -1);
  1009. gtk_text_insert(GTK_TEXT(box), NULL, NULL, NULL,
  1010. "PCM data (top graph): "
  1011. "The PCM data is plotted in black. The layer3 frame is divided into 2 "
  1012. "granules of 576 samples (marked with yellow vertical lines). In the "
  1013. "case of normal, start and stop blocks, the MDCT coefficients for each "
  1014. "granule are computed using a 1152 sample window centered over the "
  1015. "granule. In the case of short blocks, the granule is further divided "
  1016. "into 3 blocks of 192 samples (also marked with yellow vertical lines)."
  1017. "The MDCT coefficients for these blocks are computed using 384 sample "
  1018. "windows centered over the 192 sample window. (This info not available "
  1019. "when analyzing .mp3 files.) For the psycho-acoustic model, a windowed "
  1020. "FFT is computed for each granule. The range of these windows "
  1021. "is denoted by the blue and green bars.\n\n", -1);
  1022. gtk_text_insert(GTK_TEXT(box), NULL, NULL, NULL,
  1023. "PCM re-synthesis data (second graph): "
  1024. "Same as the PCM window described above. The data displayed is the "
  1025. "result of encoding and then decoding the original sample. \n\n", -1);
  1026. gtk_text_insert(GTK_TEXT(box), NULL, NULL, NULL,
  1027. "MDCT windows: "
  1028. "Shows the energy in the MDCT spectrum for granule 0 (left window) "
  1029. "and granule 1 (right window). The text also shows the blocktype "
  1030. "used, the number of bits used to encode the coefficients and the "
  1031. "number of extra bits allocated from the reservoir. The MDCT pull down "
  1032. "window will toggle between the original unquantized MDCT coefficients "
  1033. "and the compressed (quantized) coefficients.\n\n", -1);
  1034. gtk_text_insert(GTK_TEXT(box), NULL, NULL, NULL,
  1035. "FFT window: "
  1036. "The gray bars show the energy in the FFT spectrum used by the "
  1037. "psycho-acoustic model. Granule 0 is in the left window, granule 1 in "
  1038. "the right window. The green and blue bars show how much distortion is "
  1039. "allowable, as computed by the psycho-acoustic model. The red bars show "
  1040. "the actual distortion after encoding. There is one FFT for each "
  1041. "granule, computed with a 1024 Hann window centered over the "
  1042. "appropriate granule. (the range of this 1024 sample window is shown "
  1043. "by the blue and green bars in the PCM data window). The Spectrum pull "
  1044. "down window will toggle between showing the energy in equally spaced "
  1045. "frequency domain and the scale factor bands used by layer3. Finally, "
  1046. "the perceptual entropy, total energy and number of scalefactor bands "
  1047. "with audible distortion is shown. (This info not available when "
  1048. "analyzing .mp3 files.)", -1);
  1049. break;
  1050. case 1:
  1051. /* Set the about box information */
  1052. gtk_window_set_title(GTK_WINDOW(textwindow), "About");
  1053. gtk_widget_set_usize(box, 350, 260);
  1054. sprintf(text, "LAME version %s \n%s\n\n", get_lame_version(), get_lame_url());
  1055. gtk_text_insert(GTK_TEXT(box), NULL, NULL, NULL, text, -1);
  1056. sprintf(text, "psycho-acoustic model: GPSYCHO version %s\n", get_psy_version());
  1057. gtk_text_insert(GTK_TEXT(box), NULL, NULL, NULL, text, -1);
  1058. sprintf(text, "frame analyzer: MP3x version %s\n\n", get_mp3x_version());
  1059. gtk_text_insert(GTK_TEXT(box), NULL, NULL, NULL, text, -1);
  1060. gtk_text_insert(GTK_TEXT(box), NULL, NULL, NULL,
  1061. "decoder: mpg123/mpglib .59q \nMichael Hipp (www.mpg123.de)\n\n", -1);
  1062. gtk_text_insert(GTK_TEXT(box), NULL, NULL, NULL,
  1063. "Encoder, decoder & psy-models based on ISO\ndemonstration source. ", -1);
  1064. break;
  1065. case 2:
  1066. gtk_window_set_title(GTK_WINDOW(textwindow), "Statistics");
  1067. gtk_widget_set_usize(box, 350, 260);
  1068. sprintf(text, "frames processed so far: %i \n", Pinfo[0].frameNum + 1);
  1069. gtk_text_insert(GTK_TEXT(box), NULL, NULL, NULL, text, -1);
  1070. sprintf(text, "granules processed so far: %i \n\n", 4 * (Pinfo[0].frameNum + 1));
  1071. gtk_text_insert(GTK_TEXT(box), NULL, NULL, NULL, text, -1);
  1072. sprintf(text, "mean bits/frame (approximate): %i\n", gtkinfo.approxbits);
  1073. gtk_text_insert(GTK_TEXT(box), NULL, NULL, NULL, text, -1);
  1074. sprintf(text, "mean bits/frame (from LAME): %i\n", 4 * Pinfo[0].mean_bits);
  1075. gtk_text_insert(GTK_TEXT(box), NULL, NULL, NULL, text, -1);
  1076. sprintf(text, "bitsize of largest frame: %i \n", gtkinfo.maxbits);
  1077. gtk_text_insert(GTK_TEXT(box), NULL, NULL, NULL, text, -1);
  1078. sprintf(text, "average bits/frame: %3.1f \n\n", gtkinfo.avebits);
  1079. gtk_text_insert(GTK_TEXT(box), NULL, NULL, NULL, text, -1);
  1080. sprintf(text, "ms_stereo frames: %i \n", gtkinfo.totms);
  1081. gtk_text_insert(GTK_TEXT(box), NULL, NULL, NULL, text, -1);
  1082. sprintf(text, "i_stereo frames: %i \n", gtkinfo.totis);
  1083. gtk_text_insert(GTK_TEXT(box), NULL, NULL, NULL, text, -1);
  1084. sprintf(text, "de-emphasis frames: %i \n", gtkinfo.totemph);
  1085. gtk_text_insert(GTK_TEXT(box), NULL, NULL, NULL, text, -1);
  1086. sprintf(text, "short block granules: %i \n", gtkinfo.totshort);
  1087. gtk_text_insert(GTK_TEXT(box), NULL, NULL, NULL, text, -1);
  1088. sprintf(text, "mixed block granules: %i \n", gtkinfo.totmix);
  1089. gtk_text_insert(GTK_TEXT(box), NULL, NULL, NULL, text, -1);
  1090. sprintf(text, "preflag granules: %i \n", gtkinfo.totpreflag);
  1091. gtk_text_insert(GTK_TEXT(box), NULL, NULL, NULL, text, -1);
  1092. break;
  1093. }
  1094. gtk_widget_show(vscrollbar);
  1095. gtk_widget_show(box);
  1096. gtk_widget_show(vbox);
  1097. gtk_widget_show(hbox);
  1098. gtk_widget_show(button);
  1099. gtk_box_pack_start(GTK_BOX(hbox), box, FALSE, TRUE, 0);
  1100. gtk_box_pack_start(GTK_BOX(hbox), vscrollbar, FALSE, FALSE, 0);
  1101. gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, TRUE, 0);
  1102. gtk_box_pack_end(GTK_BOX(vbox), button, FALSE, TRUE, 0);
  1103. gtk_container_add(GTK_CONTAINER(textwindow), vbox);
  1104. gtk_widget_show(textwindow);
  1105. }
  1106. /* #include <strings.h>*/
  1107. /* This is the GtkItemFactoryEntry structure used to generate new menus.
  1108. Item 1: The menu path. The letter after the underscore indicates an
  1109. accelerator key once the menu is open.
  1110. Item 2: The accelerator key for the entry
  1111. Item 3: The callback function.
  1112. Item 4: The callback action. This changes the parameters with
  1113. which the function is called. The default is 0.
  1114. Item 5: The item type, used to define what kind of an item it is.
  1115. Here are the possible values:
  1116. NULL -> "<Item>"
  1117. "" -> "<Item>"
  1118. "<Title>" -> create a title item
  1119. "<Item>" -> create a simple item
  1120. "<CheckItem>" -> create a check item
  1121. "<ToggleItem>" -> create a toggle item
  1122. "<RadioItem>" -> create a radio item
  1123. <path> -> path of a radio item to link against
  1124. "<Separator>" -> create a separator
  1125. "<Branch>" -> create an item to hold sub items
  1126. "<LastBranch>" -> create a right justified branch
  1127. */
  1128. #define C(chr) "<control>" #chr
  1129. #define func(name) (GtkItemFactoryCallback) (name)
  1130. static const GtkItemFactoryEntry menu_items[] = {
  1131. {"/_File", NULL, NULL, 0, "<Branch>"},
  1132. #if 0
  1133. {"/File/_New", C(N), func(print_hello), 0, NULL},
  1134. {"/File/_Open", C(O), func(print_hello), 0, NULL},
  1135. {"/File/_Save", C(S), func(print_hello), 0, NULL},
  1136. {"/File/Save _As", NULL, NULL, 0, NULL},
  1137. {"/File/sep1", NULL, NULL, 0, "<Separator>"},
  1138. {"/File/Quit", C(Q), func(gtk_main_quit), 0, NULL},
  1139. #endif
  1140. {"/File/_Quit", C(Q), func(delete_event), 0, NULL},
  1141. {"/_Plotting", NULL, NULL, 0, "<Branch>"},
  1142. {"/Plotting/_While advancing", NULL, func(spec_option), 5, NULL},
  1143. {"/Plotting/_After advancing", NULL, func(spec_option), 6, NULL},
  1144. {"/Plotting/Toggle SFB lines", NULL, func(spec_option), 7, NULL},
  1145. {"/Plotting/Toggle orig-diff", NULL, func(spec_option), 8, NULL},
  1146. {"/_Channel", NULL, NULL, 0, "<Branch>"},
  1147. {"/Channel/show _Left", NULL, func(channel_option), 1, NULL},
  1148. {"/Channel/show _Right", NULL, func(channel_option), 2, NULL},
  1149. {"/Channel/show _Mid", NULL, func(channel_option), 3, NULL},
  1150. {"/Channel/show _Side", NULL, func(channel_option), 4, NULL},
  1151. {"/_Spectrum", NULL, NULL, 0, "<Branch>"},
  1152. {"/Spectrum/_Scalefactor bands", NULL, func(spec_option), 1, NULL},
  1153. {"/Spectrum/_Wave number", NULL, func(spec_option), 2, NULL},
  1154. {"/_MDCT", NULL, NULL, 0, "<Branch>"},
  1155. {"/MDCT/_Original", NULL, func(spec_option), 3, NULL},
  1156. {"/MDCT/_Compressed", NULL, func(spec_option), 4, NULL},
  1157. {"/MDCT/_Toggle SFB lines", NULL, func(spec_option), 7, NULL},
  1158. {"/_Stats", NULL, NULL, 0, "<Branch>"},
  1159. {"/Stats/_Show", NULL, func(text_window), 2, NULL},
  1160. {"/_Help", NULL, NULL, 0, "<LastBranch>"},
  1161. {"/_Help/_Documentation", NULL, func(text_window), 0, NULL},
  1162. {"/_Help/_About", NULL, func(text_window), 1, NULL},
  1163. };
  1164. #undef C
  1165. #undef func
  1166. static void
  1167. get_main_menu(GtkWidget * windows, GtkWidget ** menubar)
  1168. {
  1169. unsigned int nmenu_items = sizeof(menu_items) / sizeof(menu_items[0]);
  1170. GtkItemFactory *item_factory;
  1171. GtkAccelGroup *accel_group;
  1172. accel_group = gtk_accel_group_new();
  1173. /* This function initializes the item factory.
  1174. Param 1: The type of menu - can be GTK_TYPE_MENU_BAR, GTK_TYPE_MENU,
  1175. or GTK_TYPE_OPTION_MENU.
  1176. Param 2: The path of the menu.
  1177. Param 3: A pointer to a gtk_accel_group. The item factory sets up
  1178. the accelerator table while generating menus.
  1179. */
  1180. item_factory = gtk_item_factory_new(GTK_TYPE_MENU_BAR, "<main>", accel_group);
  1181. /* This function generates the menu items. Pass the item factory,
  1182. the number of items in the array, the array itself, and any
  1183. callback data for the the menu items. */
  1184. gtk_item_factory_create_items(item_factory, nmenu_items, (GtkItemFactoryEntry *) menu_items,
  1185. NULL);
  1186. /* Attach the new accelerator group to the window. */
  1187. gtk_accel_group_attach(accel_group, GTK_OBJECT(windows));
  1188. if (menubar)
  1189. /* Finally, return the actual menu bar created by the item factory. */
  1190. *menubar = gtk_item_factory_get_widget(item_factory, "<main>");
  1191. }
  1192. int
  1193. gtkcontrol(lame_global_flags * gfp2, char *inPath)
  1194. {
  1195. /* GtkWidget is the storage type for widgets */
  1196. GtkWidget *button;
  1197. GtkAdjustment *adj;
  1198. GtkWidget *mbox; /* main box */
  1199. GtkWidget *box1; /* frame control buttons go */
  1200. GtkWidget *box2; /* frame counters */
  1201. GtkWidget *box3; /* frame header info */
  1202. GtkWidget *table; /* table for all the plotting areas */
  1203. GtkWidget *menubar;
  1204. gint tableops, graphx, graphy;
  1205. char frameinfo[80];
  1206. graphx = 600; /* minimum allowed size of pixmap */
  1207. graphy = 95;
  1208. gfp = gfp2;
  1209. gfc = gfp->internal_flags;
  1210. /* set some global defaults/variables */
  1211. gtkinfo.filetype = is_mpeg_file_format(global_reader.input_format) ? 1 : 0;
  1212. gtkinfo.msflag = 0;
  1213. gtkinfo.chflag = 0;
  1214. gtkinfo.kbflag = 0;
  1215. gtkinfo.flag123 = is_mpeg_file_format(global_reader.input_format) ? 1 : 0; /* MP3 file=use mpg123 output */
  1216. gtkinfo.pupdate = 0;
  1217. gtkinfo.avebits = 0;
  1218. gtkinfo.maxbits = 0;
  1219. gtkinfo.approxbits = 0;
  1220. gtkinfo.totemph = 0;
  1221. gtkinfo.totms = 0;
  1222. gtkinfo.totis = 0;
  1223. gtkinfo.totshort = 0;
  1224. gtkinfo.totmix = 0;
  1225. gtkinfo.sfblines = 1;
  1226. gtkinfo.difference = 0;
  1227. gtkinfo.totalframes = 0;
  1228. memset((char *) Pinfo, 0, sizeof(Pinfo));
  1229. pplot = &Pinfo[READ_AHEAD];
  1230. strcpy(frameinfo, "MP3x: ");
  1231. strncat(frameinfo, inPath, 70);
  1232. window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
  1233. gtk_window_set_title(GTK_WINDOW(window), frameinfo);
  1234. gtk_signal_connect(GTK_OBJECT(window), "delete_event", GTK_SIGNAL_FUNC(delete_event), NULL);
  1235. gtk_signal_connect_object(GTK_OBJECT(window), "key_press_event",
  1236. GTK_SIGNAL_FUNC(key_press_event), GTK_OBJECT(window));
  1237. gtk_container_set_border_width(GTK_CONTAINER(window), 0);
  1238. mbox = gtk_vbox_new(FALSE, 0);
  1239. /* layout of mbox */
  1240. box1 = gtk_hbox_new(FALSE, 0);
  1241. box2 = gtk_hbox_new(FALSE, 0);
  1242. box3 = gtk_hbox_new(FALSE, 0);
  1243. table = gtk_table_new(5, 2, FALSE);
  1244. tableops = GTK_FILL | GTK_EXPAND | GTK_SHRINK;
  1245. get_main_menu(window, &menubar);
  1246. gtk_box_pack_start(GTK_BOX(mbox), menubar, FALSE, TRUE, 0);
  1247. gtk_box_pack_end(GTK_BOX(mbox), box1, FALSE, TRUE, 0);
  1248. gtk_box_pack_end(GTK_BOX(mbox), box2, FALSE, TRUE, 0);
  1249. gtk_box_pack_start(GTK_BOX(mbox), box3, FALSE, TRUE, 0);
  1250. gtk_box_pack_start(GTK_BOX(mbox), table, TRUE, TRUE, 0);
  1251. gtk_container_add(GTK_CONTAINER(window), mbox);
  1252. /*********************************************************************/
  1253. /* stuff in box3 frame header info */
  1254. /*********************************************************************/
  1255. /*
  1256. headerbox = gtk_label_new(" ");
  1257. gtk_label_set_justify(GTK_LABEL(headerbox),GTK_JUSTIFY_LEFT);
  1258. */
  1259. headerbox = gtk_text_new(NULL, NULL);
  1260. gtk_text_set_editable(GTK_TEXT(headerbox), FALSE);
  1261. gtk_widget_set_usize(headerbox, 200, 20);
  1262. gtk_widget_show(headerbox);
  1263. gtk_box_pack_start(GTK_BOX(box3), headerbox, TRUE, TRUE, 0);
  1264. /*********************************************************************/
  1265. /* stuff in box2 frame counters */
  1266. /*********************************************************************/
  1267. framecounter = gtk_label_new("");
  1268. gtk_widget_show(framecounter);
  1269. gtk_box_pack_start(GTK_BOX(box2), framecounter, FALSE, TRUE, 0);
  1270. adj = (GtkAdjustment *) gtk_adjustment_new(0, 0, (gint) lame_get_totalframes(gfp) - 1, 0, 0, 0);
  1271. frameprogress = gtk_progress_bar_new_with_adjustment(adj);
  1272. /* Set the format of the string that can be displayed in the
  1273. * trough of the progress bar:
  1274. * %p - percentage
  1275. * %v - value
  1276. * %l - lower range value
  1277. * %u - upper range value */
  1278. gtk_progress_set_format_string(GTK_PROGRESS(frameprogress), "%p%%");
  1279. gtk_progress_set_value(GTK_PROGRESS(frameprogress), (gdouble) 0);
  1280. gtk_progress_set_show_text(GTK_PROGRESS(frameprogress), TRUE);
  1281. gtk_widget_show(frameprogress);
  1282. gtk_box_pack_end(GTK_BOX(box2), frameprogress, FALSE, TRUE, 0);
  1283. /*********************************************************************/
  1284. /* stuff in box1 buttons along bottom */
  1285. /*********************************************************************/
  1286. button = gtk_button_new_with_label("-1");
  1287. gtk_signal_connect(GTK_OBJECT(button), "clicked", GTK_SIGNAL_FUNC(frameadv), (gpointer) "-1");
  1288. gtk_box_pack_start(GTK_BOX(box1), button, TRUE, TRUE, 0);
  1289. gtk_widget_show(button);
  1290. button = gtk_button_new_with_label("+1");
  1291. gtk_signal_connect(GTK_OBJECT(button), "clicked", GTK_SIGNAL_FUNC(frameadv), (gpointer) "1");
  1292. gtk_box_pack_start(GTK_BOX(box1), button, TRUE, TRUE, 0);
  1293. gtk_widget_show(button);
  1294. button = gtk_button_new_with_label("+10");
  1295. gtk_signal_connect(GTK_OBJECT(button), "clicked", GTK_SIGNAL_FUNC(frameadv), (gpointer) "10");
  1296. gtk_box_pack_start(GTK_BOX(box1), button, TRUE, TRUE, 0);
  1297. gtk_widget_show(button);
  1298. button = gtk_button_new_with_label("+100");
  1299. gtk_signal_connect(GTK_OBJECT(button), "clicked", GTK_SIGNAL_FUNC(frameadv), (gpointer) "100");
  1300. gtk_box_pack_start(GTK_BOX(box1), button, TRUE, TRUE, 0);
  1301. gtk_widget_show(button);
  1302. button = gtk_button_new_with_label("last frame");
  1303. gtk_signal_connect(GTK_OBJECT(button), "clicked",
  1304. GTK_SIGNAL_FUNC(frameadv), (gpointer) "finish");
  1305. gtk_box_pack_start(GTK_BOX(box1), button, TRUE, TRUE, 0);
  1306. gtk_widget_show(button);
  1307. button = gtk_button_new_with_label("stop/plot");
  1308. gtk_signal_connect(GTK_OBJECT(button), "clicked", GTK_SIGNAL_FUNC(plotclick), NULL);
  1309. gtk_box_pack_start(GTK_BOX(box1), button, TRUE, TRUE, 0);
  1310. gtk_widget_show(button);
  1311. /*********************************************************************/
  1312. /* stuff in table. all the plotting windows */
  1313. /*********************************************************************/
  1314. pcmbox = gpk_plot_new(graphx, graphy);
  1315. gtk_table_attach(GTK_TABLE(table), pcmbox, 0, 2, 0, 1, tableops, tableops, 2, 2);
  1316. gtk_widget_show(pcmbox);
  1317. winbox = gpk_plot_new(graphy, graphy);
  1318. gtk_table_attach(GTK_TABLE(table), winbox, 0, 2, 1, 2, tableops, tableops, 2, 2);
  1319. gtk_widget_show(winbox);
  1320. mdctbox[0] = gpk_plot_new(graphy, graphy);
  1321. gtk_table_attach(GTK_TABLE(table), mdctbox[0], 0, 1, 2, 3, tableops, tableops, 2, 2);
  1322. gtk_widget_show(mdctbox[0]);
  1323. mdctbox[1] = gpk_plot_new(graphy, graphy);
  1324. gtk_table_attach(GTK_TABLE(table), mdctbox[1], 1, 2, 2, 3, tableops, tableops, 2, 2);
  1325. gtk_widget_show(mdctbox[1]);
  1326. enerbox[0] = gpk_plot_new(graphy, graphy);
  1327. gtk_table_attach(GTK_TABLE(table), enerbox[0], 0, 1, 3, 4, tableops, tableops, 2, 2);
  1328. gtk_widget_show(enerbox[0]);
  1329. enerbox[1] = gpk_plot_new(graphy, graphy);
  1330. gtk_table_attach(GTK_TABLE(table), enerbox[1], 1, 2, 3, 4, tableops, tableops, 2, 2);
  1331. gtk_widget_show(enerbox[1]);
  1332. sfbbox[0] = gpk_plot_new(graphy, graphy);
  1333. gtk_table_attach(GTK_TABLE(table), sfbbox[0], 0, 1, 4, 5, tableops, tableops, 2, 2);
  1334. gtk_widget_show(sfbbox[0]);
  1335. sfbbox[1] = gpk_plot_new(graphy, graphy);
  1336. gtk_table_attach(GTK_TABLE(table), sfbbox[1], 1, 2, 4, 5, tableops, tableops, 2, 2);
  1337. gtk_widget_show(sfbbox[1]);
  1338. gtk_idle_add((GtkFunction) frameadv1, NULL);
  1339. gtk_widget_show(menubar);
  1340. gtk_widget_show(box2);
  1341. gtk_widget_show(box3);
  1342. gtk_widget_show(table);
  1343. gtk_widget_show(box1);
  1344. gtk_widget_show(mbox);
  1345. gtk_widget_show(window); /* show smallest allowed window */
  1346. /* make window bigger. */
  1347. /* now the user will be able to shrink it, if desired */
  1348. /* gtk_widget_set_usize(mbox,500,500); */
  1349. /* gtk_widget_show (window); */ /* show smallest allowed window */
  1350. idle_keepgoing = 1; /* processing of frames is ON */
  1351. idle_count_max = READ_AHEAD + 1; /* number of frames to process before plotting */
  1352. idle_count = 0; /* pause & plot when idle_count=idle_count_max */
  1353. gtk_main();
  1354. assert(mp3done);
  1355. return (0);
  1356. }