OSDN Git Service

afbee9e1c6c199dc0c058802259132e952a9e36c
[android-x86/external-alsa-utils.git] / xamixer2 / display.c
1 /*****************************************************************************
2    xamixer.c - an Alsa based gtk mixer
3    Written by Raistlinn (lansdoct@cs.alfred.edu)
4    Copyright (C) 1998 by Christopher Lansdown
5    
6    This program is free software; you can redistribute it and/or
7    modify it under the terms of the GNU General Public License
8    as published by the Free Software Foundation; either version 2
9    of the License, or (at your option) any later version.
10    
11    This program 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
14    GNU General Public License for more details.
15    
16    You should have received a copy of the GNU General Public License
17    along with this program; if not, write to the Free Software
18    Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
19 ******************************************************************************/
20
21 /*****************************************************************************/
22 /* Begin #include's */
23
24 #include "main.h"
25
26 /* End #include's */
27 /*****************************************************************************/
28
29 /*****************************************************************************/
30 /* Begin Global Variables */
31
32 extern GtkWidget *window;
33 extern Card *card; /* And array of the cards */
34 extern int cards; /* The number of cards in the system. */
35 extern Config config; /* The system config */
36
37 /* End Global Variables */
38 /*****************************************************************************/ 
39
40 /*****************************************************************************/ 
41 /* Begin function prototypes */
42
43 GtkWidget *group_elements(int card, int mixer, Group *group);
44 GtkWidget *display_volume1(Group *group, int element, void *handle, char *route);
45 GtkWidget *display_switch2(Group *group, int element, void *handle, char *route);
46 GtkWidget *display_switch1(Group *group, int element, void *handle, char *route);
47 GtkWidget *display_3deffect1(Group *group, int element, void *handle, char *route);
48
49 /* End function protoypes */
50 /*****************************************************************************/ 
51
52 GtkWidget *create_mixer_page(int card_num, int mixer_num) 
53 {
54         GtkWidget *vbox;
55         GtkWidget *hbox;
56         GtkWidget *frame;
57         int i=card_num, j=mixer_num, k=0, l, m;
58         int w=1, col;
59         
60         /* Compute the number of culumns to use */
61         //      w = (int)sqrt((double)card[i].mixer[j].info.elements);
62         w = (int)(1.5 * 
63                   (float)card[i].mixer[j].info.elements / 
64                   (float)card[i].mixer[j].info.groups);
65         if (w == 0)
66                 col = 0;
67         else
68                 /* Compute the number of groups in a column */
69                 col = (card[i].mixer[j].info.groups + w - 1)/ w;
70
71         /* Create the main bounding box */
72         hbox = gtk_hbox_new(FALSE, 0);
73         gtk_widget_show(hbox);
74
75
76         /* Make a vertical box for each column, then put that column's worth
77            of mixer groups into the column */
78         for(l = 0; l < w; l++) {
79                 /* Make the vertical box to pack it in */
80                 vbox = gtk_vbox_new(FALSE, 0);
81                 gtk_widget_show(vbox);
82                 gtk_box_pack_start(GTK_BOX(hbox), vbox, FALSE, FALSE, 0);
83
84                 for(m = 0; m < col && k < card[i].mixer[j].info.groups; m++) {
85                         /* Make the group frame */
86                         frame = gtk_frame_new(card[i].mixer[j].group[k].group.gid.name);
87                         gtk_widget_show(frame);
88                         gtk_box_pack_start(GTK_BOX(vbox), frame, FALSE, FALSE, 0);
89                         
90                         gtk_container_add(GTK_CONTAINER(frame),
91                                           group_elements(card_num, 
92                                                          mixer_num,
93                                                          &card[i].mixer[j].group[k]));
94
95
96                         /* Now increment the count of which mixer group we're on */
97                         k++;
98                 }
99         }
100
101         return hbox;
102 }
103
104
105 GtkWidget *group_elements(int card_num, int mixer, Group *group)
106 {
107         GtkWidget *vbox;
108         GtkWidget *hbox;
109         GtkWidget *label;
110         GtkWidget *box;
111         GtkWidget *widget;
112         char thor[128];
113         int i, j;
114         snd_mixer_element_t test;
115
116         vbox = gtk_vbox_new(FALSE, 0);
117         gtk_widget_show(vbox);
118
119         for(i = 0; i < group->group.elements; i++) {
120                 /* Each element gets its own horizontal box */
121                 hbox=gtk_hbox_new(FALSE, 0);
122                 gtk_widget_show(hbox);
123                 gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 0);
124                 
125                 snprintf(thor, 128, "%s routed to the %s", 
126                          group->group.pelements[i].name, 
127                          group->routes[i].proutes[0].name);
128
129 /*              label = gtk_label_new(thor); */
130 /*              gtk_widget_show(label); */
131 /*              gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 0); */
132
133
134                 switch(group->group.pelements[i].type){
135
136                 case SND_MIXER_ETYPE_VOLUME1:
137                         gtk_box_pack_end(GTK_BOX(hbox), 
138                                          display_volume1(group, i, 
139                                                          card[card_num].mixer[mixer].handle,
140                                                          thor), 
141                                          FALSE, FALSE, 0);
142                         break;
143
144                 case SND_MIXER_ETYPE_SWITCH1:
145                         gtk_box_pack_end(GTK_BOX(hbox),
146                                          display_switch1(group, i, 
147                                                          card[card_num].mixer[mixer].handle,
148                                                          thor),
149                                          FALSE, FALSE, 0);
150                         break;
151
152                 case SND_MIXER_ETYPE_SWITCH2:
153                         gtk_box_pack_end(GTK_BOX(hbox),
154                                          display_switch2(group, i, 
155                                                          card[card_num].mixer[mixer].handle,
156                                                          thor),
157                                          FALSE, FALSE, 0);
158                         break;
159
160                 case SND_MIXER_ETYPE_3D_EFFECT1:
161                         gtk_box_pack_end(GTK_BOX(hbox),
162                                          display_3deffect1(group, i, 
163                                                          card[card_num].mixer[mixer].handle,
164                                                          thor),
165                                          FALSE, FALSE, 0);
166                         break;  
167                 }
168         }
169
170
171
172         return vbox;
173 }
174
175 GtkWidget *display_3deffect1(Group *group, int element, void *handle, char *route)
176 {
177         GtkWidget *vbox;
178         GtkWidget *box;
179         GtkTooltips *tooltips;
180         GtkWidget *widget;
181         GtkWidget *label;
182         int i=element;
183         GtkObject *adj;
184
185         vbox = gtk_vbox_new(FALSE, 0);
186         gtk_widget_show(vbox);
187
188         group->gtk[i].interface = calloc(10, sizeof(GtkWidget *));
189         group->gtk[i].adjust = calloc(10, sizeof(GtkWidget *));
190
191         /* The on/off switch */
192         if(group->einfo[i].data.teffect1.effect & SND_MIXER_EFF1_SW) {
193                 box = gtk_hbox_new(FALSE, 0);
194                 gtk_widget_show(box);
195                 gtk_box_pack_start(GTK_BOX(vbox), box, FALSE, FALSE, 0);
196                 
197                 label = gtk_label_new("3D Effect");
198                 gtk_widget_show(label);
199                 gtk_box_pack_start(GTK_BOX(box), label, FALSE, FALSE, 0);
200                 
201                 widget = gtk_check_button_new();
202                 if(group->element[i].data.teffect1.sw)
203                         gtk_toggle_button_set_state(GTK_TOGGLE_BUTTON(widget), TRUE);
204                 
205                 gtk_widget_show(widget);
206                 gtk_box_pack_end(GTK_BOX(box), widget, FALSE, FALSE, 0);
207                 /* Connect it to the callback */
208                 gtk_signal_connect(GTK_OBJECT(widget), "toggled", 
209                                    GTK_SIGNAL_FUNC(adjust_teffect1),
210                                    create_cb_data(group, handle, i, TYPE_SW));
211         }
212
213
214
215         /* The mono switch */
216         if(group->einfo[i].data.teffect1.effect & SND_MIXER_EFF1_MONO_SW) {
217                 box = gtk_hbox_new(FALSE, 0);
218                 gtk_widget_show(box);
219                 gtk_box_pack_start(GTK_BOX(vbox), box, FALSE, FALSE, 0);
220                 
221                 label = gtk_label_new("3D Effect Mono");
222                 gtk_widget_show(label);
223                 gtk_box_pack_start(GTK_BOX(box), label, FALSE, FALSE, 0);
224                 
225                 widget = gtk_check_button_new();
226                 if(group->element[i].data.teffect1.sw)
227                         gtk_toggle_button_set_state(GTK_TOGGLE_BUTTON(widget), TRUE);
228                 gtk_widget_show(widget);
229                 gtk_box_pack_end(GTK_BOX(box), widget, FALSE, FALSE, 0);
230                 /* Connect it to the callback */
231                 gtk_signal_connect(GTK_OBJECT(widget), "toggled", 
232                                    GTK_SIGNAL_FUNC(adjust_teffect1),
233                                    create_cb_data(group, handle, i, TYPE_MONO_SW));
234         }
235
236
237         /* the wide control */
238         if(group->einfo[i].data.teffect1.effect & SND_MIXER_EFF1_WIDE) {
239                 box = gtk_hbox_new(FALSE, 0);
240                 gtk_widget_show(box);
241                 gtk_box_pack_start(GTK_BOX(vbox), box, FALSE, FALSE, 0);
242                 
243                 label = gtk_label_new("3D Effect Width");
244                 gtk_widget_show(label);
245                 gtk_box_pack_start(GTK_BOX(box), label, FALSE, FALSE, 0);
246                 
247                 
248                 adj = gtk_adjustment_new(group->element[i].data.teffect1.wide,
249                                          group->einfo[i].data.teffect1.min_wide,
250                                          group->einfo[i].data.teffect1.max_wide,
251                                          1.0,
252                                          3.0,
253                                          0.0);
254                 widget = gtk_hscale_new(GTK_ADJUSTMENT(adj));
255                 gtk_scale_set_value_pos(GTK_SCALE(widget), 
256                                         GTK_POS_RIGHT);
257                 gtk_widget_set_usize(widget, 100, -1);
258                 gtk_widget_show(widget);
259                 gtk_box_pack_end(GTK_BOX(box), widget, FALSE, FALSE, 0);
260
261                 /* connect the signal */
262                 gtk_signal_connect(GTK_OBJECT(adj),
263                                    "value_changed", 
264                                    GTK_SIGNAL_FUNC (adjust_teffect1),
265                                    create_cb_data(group, handle, i, TYPE_WIDE));
266         }
267
268         /* the volume widget */
269         if(group->einfo[i].data.teffect1.effect & SND_MIXER_EFF1_VOLUME) {
270                 box = gtk_hbox_new(FALSE, 0);
271                 gtk_widget_show(box);
272                 gtk_box_pack_start(GTK_BOX(vbox), box, FALSE, FALSE, 0);
273                 
274                 label = gtk_label_new("3D Effect Volume");
275                 gtk_widget_show(label);
276                 gtk_box_pack_start(GTK_BOX(box), label, FALSE, FALSE, 0);
277                 
278                 
279                 adj = gtk_adjustment_new(group->element[i].data.teffect1.volume,
280                                          group->einfo[i].data.teffect1.min_volume,
281                                          group->einfo[i].data.teffect1.max_volume,
282                                          1.0,
283                                          3.0,
284                                          0.0);
285                 widget = gtk_hscale_new(GTK_ADJUSTMENT(adj));
286                 gtk_scale_set_value_pos(GTK_SCALE(widget), 
287                                         GTK_POS_RIGHT);
288                 gtk_widget_set_usize(widget, 100, -1);
289                 gtk_widget_show(widget);
290                 gtk_box_pack_end(GTK_BOX(box), widget, FALSE, FALSE, 0);
291                 /* connect the signal */
292                 gtk_signal_connect(GTK_OBJECT(adj),
293                                    "value_changed", 
294                                    GTK_SIGNAL_FUNC (adjust_teffect1),
295                                    create_cb_data(group, handle, i, TYPE_VOLUME));
296         }
297
298
299         /* The center widget */
300         if(group->einfo[i].data.teffect1.effect & SND_MIXER_EFF1_CENTER) {
301                 box = gtk_hbox_new(FALSE, 0);
302                 gtk_widget_show(box);
303                 gtk_box_pack_start(GTK_BOX(vbox), box, FALSE, FALSE, 0);
304                 
305                 label = gtk_label_new("3D Effect Center");
306                 gtk_widget_show(label);
307                 gtk_box_pack_start(GTK_BOX(box), label, FALSE, FALSE, 0);
308                 
309                 
310                 adj = gtk_adjustment_new(group->element[i].data.teffect1.center,
311                                          group->einfo[i].data.teffect1.min_center,
312                                          group->einfo[i].data.teffect1.max_center,
313                                          1.0,
314                                          3.0,
315                                          0.0);
316                 widget = gtk_hscale_new(GTK_ADJUSTMENT(adj));
317                 gtk_scale_set_value_pos(GTK_SCALE(widget), 
318                                         GTK_POS_RIGHT);
319                 gtk_widget_set_usize(widget, 100, -1);
320                 gtk_widget_show(widget);
321                 gtk_box_pack_end(GTK_BOX(box), widget, FALSE, FALSE, 0);
322                 gtk_signal_connect(GTK_OBJECT(adj),
323                                    "value_changed", 
324                                    GTK_SIGNAL_FUNC (adjust_teffect1),
325                                    create_cb_data(group, handle, i, TYPE_CENTER));
326         }
327
328
329         /* The Space widget */
330         if(group->einfo[i].data.teffect1.effect & SND_MIXER_EFF1_SPACE) {
331                 box = gtk_hbox_new(FALSE, 0);
332                 gtk_widget_show(box);
333                 gtk_box_pack_start(GTK_BOX(vbox), box, FALSE, FALSE, 0);
334                 
335                 label = gtk_label_new("3D Effect Space");
336                 gtk_widget_show(label);
337                 gtk_box_pack_start(GTK_BOX(box), label, FALSE, FALSE, 0);
338                 
339                 
340                 adj = gtk_adjustment_new(group->element[i].data.teffect1.space,
341                                          group->einfo[i].data.teffect1.min_space,
342                                          group->einfo[i].data.teffect1.max_space,
343                                          1.0,
344                                          3.0,
345                                          0.0);
346                 widget = gtk_hscale_new(GTK_ADJUSTMENT(adj));
347                 gtk_scale_set_value_pos(GTK_SCALE(widget), 
348                                         GTK_POS_RIGHT);
349                 gtk_widget_set_usize(widget, 100, -1);
350                 gtk_widget_show(widget);
351                 gtk_box_pack_end(GTK_BOX(box), widget, FALSE, FALSE, 0);
352                 gtk_signal_connect(GTK_OBJECT(adj),
353                                    "value_changed", 
354                                    GTK_SIGNAL_FUNC (adjust_teffect1),
355                                    create_cb_data(group, handle, i, TYPE_SPACE));
356         }
357
358         /* The depth widget */
359         if(group->einfo[i].data.teffect1.effect & SND_MIXER_EFF1_DEPTH) {
360                 box = gtk_hbox_new(FALSE, 0);
361                 gtk_widget_show(box);
362                 gtk_box_pack_start(GTK_BOX(vbox), box, FALSE, FALSE, 0);
363                 
364                 label = gtk_label_new("3D Effect Depth");
365                 gtk_widget_show(label);
366                 gtk_box_pack_start(GTK_BOX(box), label, FALSE, FALSE, 0);
367                 
368                 
369                 adj = gtk_adjustment_new(group->element[i].data.teffect1.depth,
370                                          group->einfo[i].data.teffect1.min_depth,
371                                          group->einfo[i].data.teffect1.max_depth,
372                                          1.0,
373                                          3.0,
374                                          0.0);
375                 widget = gtk_hscale_new(GTK_ADJUSTMENT(adj));
376                 gtk_scale_set_value_pos(GTK_SCALE(widget), 
377                                         GTK_POS_RIGHT);
378                 gtk_widget_set_usize(widget, 100, -1);
379                 gtk_widget_show(widget);
380                 gtk_box_pack_end(GTK_BOX(box), widget, FALSE, FALSE, 0);
381                 gtk_signal_connect(GTK_OBJECT(adj),
382                                    "value_changed", 
383                                    GTK_SIGNAL_FUNC (adjust_teffect1),
384                                    create_cb_data(group, handle, i, TYPE_DEPTH));
385         }
386
387         /* The delay widget */
388         if(group->einfo[i].data.teffect1.effect & SND_MIXER_EFF1_DELAY) {
389                 box = gtk_hbox_new(FALSE, 0);
390                 gtk_widget_show(box);
391                 gtk_box_pack_start(GTK_BOX(vbox), box, FALSE, FALSE, 0);
392                 
393                 label = gtk_label_new("3D Effect Delay");
394                 gtk_widget_show(label);
395                 gtk_box_pack_start(GTK_BOX(box), label, FALSE, FALSE, 0);
396                 
397                 
398                 adj = gtk_adjustment_new(group->element[i].data.teffect1.delay,
399                                          group->einfo[i].data.teffect1.min_delay,
400                                          group->einfo[i].data.teffect1.max_delay,
401                                          1.0,
402                                          3.0,
403                                          0.0);
404                 widget = gtk_hscale_new(GTK_ADJUSTMENT(adj));
405                 gtk_scale_set_value_pos(GTK_SCALE(widget), 
406                                         GTK_POS_RIGHT);
407                 gtk_widget_set_usize(widget, 100, -1);
408                 gtk_widget_show(widget);
409                 gtk_box_pack_end(GTK_BOX(box), widget, FALSE, FALSE, 0);
410                 gtk_signal_connect(GTK_OBJECT(adj),
411                                    "value_changed", 
412                                    GTK_SIGNAL_FUNC (adjust_teffect1),
413                                    create_cb_data(group, handle, i, TYPE_DELAY));
414         }
415
416
417         /* The feedback widget */
418         if(group->einfo[i].data.teffect1.effect & SND_MIXER_EFF1_FEEDBACK) {
419                 box = gtk_hbox_new(FALSE, 0);
420                 gtk_widget_show(box);
421                 gtk_box_pack_start(GTK_BOX(vbox), box, FALSE, FALSE, 0);
422                 
423                 label = gtk_label_new("3D Effect Feedback");
424                 gtk_widget_show(label);
425                 gtk_box_pack_start(GTK_BOX(box), label, FALSE, FALSE, 0);
426                 
427                 
428                 adj = gtk_adjustment_new(group->element[i].data.teffect1.feedback,
429                                          group->einfo[i].data.teffect1.min_feedback,
430                                          group->einfo[i].data.teffect1.max_feedback,
431                                          1.0,
432                                          3.0,
433                                          0.0);
434                 widget = gtk_hscale_new(GTK_ADJUSTMENT(adj));
435                 gtk_scale_set_value_pos(GTK_SCALE(widget), 
436                                         GTK_POS_RIGHT);
437                 gtk_widget_set_usize(widget, 100, -1);
438                 gtk_widget_show(widget);
439                 gtk_box_pack_end(GTK_BOX(box), widget, FALSE, FALSE, 0);
440                 gtk_signal_connect(GTK_OBJECT(adj),
441                                    "value_changed", 
442                                    GTK_SIGNAL_FUNC (adjust_teffect1),
443                                    create_cb_data(group, handle, i, TYPE_FEEDBACK));
444         }
445
446
447
448         return vbox;
449 }
450
451 GtkWidget *display_switch1(Group *group, int element, void *handle, char *route)
452 {
453         GtkWidget *box;
454         GtkTooltips *tooltips;
455         GtkWidget *button;
456         int i, j;
457
458         i = element;
459
460         box = gtk_hbox_new(FALSE, 0);
461         gtk_widget_show(box);
462
463         /* Allocate the widget array */
464         group->gtk[i].interface = calloc(group->element[i].data.switch1.sw, sizeof(GtkWidget *));
465
466         for(j = 0; j < group->element[i].data.switch1.sw; j++) {
467                 button = gtk_check_button_new();
468                 /* looks painful, doesn't it?  It's checking the state of the appropriate bit */
469                 if(group->element[i].data.switch1.psw[j / sizeof(unsigned int)] & 
470                    (1 << (j % sizeof(unsigned int))))
471                         gtk_toggle_button_set_state(GTK_TOGGLE_BUTTON (button), TRUE);
472                 gtk_widget_show(button);
473
474                 /* Set up the tooltips */
475                 tooltips = gtk_tooltips_new();
476                 gtk_tooltips_set_tip (tooltips, button, route, NULL);
477
478
479                 gtk_box_pack_start(GTK_BOX (box), button, FALSE, FALSE, 0);
480
481                 /* Connect it to the callback */
482                 gtk_signal_connect(GTK_OBJECT(button), "toggled", 
483                                    GTK_SIGNAL_FUNC(adjust_switch1),
484                                    create_cb_data(group, handle, i, j));
485
486                 /* Store the widget */
487                 group->gtk[i].interface[j] = button;
488         }
489
490
491         return box;
492 }
493
494
495 GtkWidget *display_switch2(Group *group, int element, void *handle, char *route)
496 {
497         GtkWidget *button;
498         GtkTooltips *tooltips;
499         int i, j=0;
500
501         i = element;
502
503         if(!group) {
504                 printf("Group isn't initialized!\n");
505                 return NULL;
506         }
507
508         button = gtk_check_button_new();
509
510         if(group->element)
511                 if(group->element[i].data.switch2.sw) {
512                         gtk_toggle_button_set_state(GTK_TOGGLE_BUTTON(button), TRUE);
513                 }
514
515         gtk_widget_show(button);
516
517         /* Set up the tooltip */
518         tooltips = gtk_tooltips_new();
519         gtk_tooltips_set_tip (tooltips, button, route, NULL);
520
521         if(group->gtk) {
522                 group->gtk[i].interface = calloc(1, sizeof(GtkWidget *));
523                 group->gtk[i].interface[j] = button;
524         } else {
525                 printf("Something wasn't initialized properly.\n");
526         }
527
528         /* Connect it to the callback */
529         gtk_signal_connect(GTK_OBJECT(group->gtk[i].interface[j]),
530                            "toggled", 
531                            GTK_SIGNAL_FUNC (adjust_switch2),
532                            create_cb_data(group, handle, element, j));
533         
534         return button;
535 }
536
537 GtkWidget *display_volume1(Group *group, int element, void *handle, char *route)
538 {
539         GtkWidget *box;
540         GtkTooltips *tooltips;
541         int i,j;
542
543         i = element;
544
545         box = gtk_vbox_new(FALSE, 0);
546         gtk_widget_show(box);
547
548         group->gtk[i].adjust = calloc(group->element[i].data.volume1.voices, 
549                                       sizeof(GtkObject *));
550         group->gtk[i].interface = calloc(group->element[i].data.volume1.voices, 
551                                          sizeof(GtkWidget *));
552         
553         for(j=0; j < group->element[i].data.volume1.voices; j++) {
554                 group->gtk[i].adjust[j] = 
555                         gtk_adjustment_new(group->element[i].data.volume1.pvoices[j],
556                                            group->einfo[i].data.volume1.prange[0].min,
557                                            group->einfo[i].data.volume1.prange[0].max,
558                                            1.0,
559                                            3.0,
560                                            0.0);
561                 
562                 group->gtk[i].interface[j] = 
563                         gtk_hscale_new(GTK_ADJUSTMENT(group->gtk[i].adjust[j]));
564
565                 gtk_signal_connect(GTK_OBJECT(group->gtk[i].adjust[j]),
566                                    "value_changed", 
567                                    GTK_SIGNAL_FUNC (adjust_volume1),
568                                    create_cb_data(group, handle, element, j));
569
570 /*              gtk_scale_set_draw_value(GTK_SCALE(group->gtk[i].interface[j]), */
571 /*                                       FALSE); */
572
573                 gtk_scale_set_value_pos(GTK_SCALE(group->gtk[i].interface[j]), 
574                                         GTK_POS_RIGHT);
575
576                 gtk_widget_set_usize(group->gtk[i].interface[j], 100, -1);
577
578                 gtk_widget_show(group->gtk[i].interface[j]);
579                 gtk_box_pack_start(GTK_BOX(box), 
580                                    group->gtk[i].interface[j], 
581                                    FALSE, FALSE, 0);
582
583                 /* Set up the tooltip */
584                 tooltips = gtk_tooltips_new();
585                 gtk_tooltips_set_tip (tooltips, group->gtk[i].interface[j], route, NULL);
586
587         }
588         
589
590
591         return box;
592 }