Merge r14152 from theora-exp.
[xiph/unicode.git] / postfish / mainpanel.c
blob3e2fafb3a0e1b30afdc75cc3c2828c765fd847a4
1 /*
3 * postfish
4 *
5 * Copyright (C) 2002-2005 Monty
7 * Postfish is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2, or (at your option)
10 * any later version.
12 * Postfish is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with Postfish; see the file COPYING. If not, write to the
19 * Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
24 #include "postfish.h"
25 #include <gtk/gtk.h>
26 #include <gdk/gdkkeysyms.h>
27 #include "fisharray.h"
28 #include "buttonicons.h"
29 #include "multibar.h"
30 #include "readout.h"
31 #include "input.h"
32 #include "output.h"
33 #include "mainpanel.h"
34 #include "windowbutton.h"
35 #include "config.h"
37 static postfish_mainpanel p;
38 extern char *configfile;
39 extern sig_atomic_t main_looping;
41 static void action_setb_to(postfish_mainpanel *p,const char *time);
42 static void action_seta_to(postfish_mainpanel *p,const char *time);
45 static void mainpanel_state_to_config(int bank){
46 int i;
47 float f;
49 f=multibar_get_value(MULTIBAR(p.masterdB_s),0);
50 i=gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(p.masterdB_a));
52 config_set_integer("mainpanel_master_att",bank,0,0,0,0,rint(f*10));
53 config_set_integer("mainpanel_master_att_active",bank,0,0,0,0,i);
55 config_set_string("mainpanel_cue_A",0,0,0,0,gtk_entry_get_text(GTK_ENTRY(p.entry_a)));
56 config_set_string("mainpanel_cue_B",0,0,0,0,gtk_entry_get_text(GTK_ENTRY(p.entry_b)));
57 config_set_integer("mainpanel_loop",0,0,0,0,0,
58 gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(p.cue_b)));
60 for(i=0;i<input_ch || i<OUTPUT_CHANNELS;i++)
61 config_set_integer("mainpanel_VU_show",0,0,0,0,i,
62 gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(p.channelshow[i])));
64 clippanel_state_to_config(bank);
65 compandpanel_state_to_config(bank);
66 singlepanel_state_to_config(bank);
67 deverbpanel_state_to_config(bank);
68 eqpanel_state_to_config(bank);
69 reverbpanel_state_to_config(bank);
70 limitpanel_state_to_config(bank);
71 outpanel_state_to_config(bank);
72 mixpanel_state_to_config(bank);
76 static void mainpanel_state_from_config(int bank){
78 int val,i;
79 const char *string;
81 if(!config_get_integer("mainpanel_master_att",bank,0,0,0,0,&val))
82 multibar_thumb_set(MULTIBAR(p.masterdB_s),val*.1,0);
84 if(!config_get_integer("mainpanel_master_att_active",bank,0,0,0,0,&val))
85 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(p.masterdB_a),val);
87 /* A/B state are saved but *not* banked */
88 if((string=config_get_string("mainpanel_cue_A",0,0,0,0)))
89 action_seta_to(&p,string);
90 if((string=config_get_string("mainpanel_cue_B",0,0,0,0)))
91 action_setb_to(&p,string);
92 if(!config_get_integer("mainpanel_loop",0,0,0,0,0,&val))
93 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(p.cue_b),val);
95 for(i=0;i<input_ch || i<OUTPUT_CHANNELS;i++)
96 if(!config_get_integer("mainpanel_VU_show",0,0,0,0,i,&val))
97 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(p.channelshow[i]),val);
99 clippanel_state_from_config(bank);
100 compandpanel_state_from_config(bank);
101 singlepanel_state_from_config(bank);
102 deverbpanel_state_from_config(bank);
103 eqpanel_state_from_config(bank);
104 reverbpanel_state_from_config(bank);
105 limitpanel_state_from_config(bank);
106 outpanel_state_from_config(bank);
107 mixpanel_state_from_config(bank);
111 void save_state(){
112 mainpanel_state_to_config(0);
113 config_save(configfile);
116 static void savestatei(GtkWidget *dummy, gpointer in){
117 save_state();
120 static void meterhold_reset(postfish_mainpanel *p){
121 p->inpeak=-200;
122 p->outpeak=-200;
124 readout_set(READOUT(p->inreadout),"------");
125 readout_set(READOUT(p->outreadout),"------");
128 static void action_zero(GtkWidget *widget,postfish_mainpanel *p){
129 char buf[14];
130 off_t cursor;
132 output_halt_playback();
133 cursor=input_seek(0);
134 input_cursor_to_time(cursor,buf);
135 readout_set(READOUT(p->cue),buf);
136 multibar_reset(MULTIBAR(p->inbar));
137 multibar_reset(MULTIBAR(p->outbar));
138 clippanel_reset();
139 eqpanel_reset();
140 compandpanel_reset();
141 singlepanel_reset();
142 limitpanel_reset();
143 mixpanel_reset();
144 meterhold_reset(p);
147 static void action_end(GtkWidget *widget,postfish_mainpanel *p){
148 char buf[14];
149 off_t cursor=input_time_to_cursor("9999:59:59.99");
151 output_halt_playback();
152 cursor=input_seek(cursor);
153 input_cursor_to_time(cursor,buf);
154 readout_set(READOUT(p->cue),(char *)buf);
155 multibar_reset(MULTIBAR(p->inbar));
156 multibar_reset(MULTIBAR(p->outbar));
157 clippanel_reset();
158 eqpanel_reset();
159 compandpanel_reset();
160 singlepanel_reset();
161 limitpanel_reset();
162 mixpanel_reset();
163 meterhold_reset(p);
166 static void action_bb(GtkWidget *widget,postfish_mainpanel *p){
167 off_t cursor=input_time_seek_rel(-60);
168 char time[14];
169 input_cursor_to_time(cursor,time);
170 readout_set(READOUT(p->cue),(char *)time);
173 static void action_b(GtkWidget *widget,postfish_mainpanel *p){
174 off_t cursor=input_time_seek_rel(-5);
175 char time[14];
176 input_cursor_to_time(cursor,time);
177 readout_set(READOUT(p->cue),(char *)time);
180 static void action_f(GtkWidget *widget,postfish_mainpanel *p){
181 off_t cursor=input_time_seek_rel(5);
182 char time[14];
183 input_cursor_to_time(cursor,time);
184 readout_set(READOUT(p->cue),(char *)time);
187 static void action_ff(GtkWidget *widget,postfish_mainpanel *p){
188 off_t cursor=input_time_seek_rel(60);
189 char time[14];
190 input_cursor_to_time(cursor,time);
191 readout_set(READOUT(p->cue),(char *)time);
194 /* gotta have the Fucking Fish */
195 static int reanimate_fish(postfish_mainpanel *p){
196 if(playback_active || (p->fishframe>0 && p->fishframe<12)){
197 /* continue spinning */
198 p->fishframe++;
199 if(p->fishframe>=12)p->fishframe=0;
201 gtk_image_set_from_pixmap(GTK_IMAGE(p->twirlimage),
202 p->ff[p->fishframe],
203 p->fb[p->fishframe]);
205 if(p->fishframe==0 && !playback_active){
206 /* reschedule to blink */
207 p->fishframe_timer=
208 g_timeout_add(rand()%1000*30,(GSourceFunc)reanimate_fish,p);
209 return FALSE;
211 }else{
212 p->fishframe++;
213 if(p->fishframe<=1)p->fishframe=12;
214 if(p->fishframe>=19)p->fishframe=0;
216 gtk_image_set_from_pixmap(GTK_IMAGE(p->twirlimage),
217 p->ff[p->fishframe],
218 p->fb[p->fishframe]);
221 if(p->fishframe==12){
222 /* reschedule to animate */
223 p->fishframe_timer=
224 g_timeout_add(10,(GSourceFunc)reanimate_fish,p);
225 return FALSE;
227 if(p->fishframe==0){
228 /* reschedule to blink */
229 p->fishframe_timer=
230 g_timeout_add(rand()%1000*30,(GSourceFunc)reanimate_fish,p);
231 return FALSE;
234 return TRUE;
237 static void animate_fish(postfish_mainpanel *p){
238 if(p->fishframe_init){
239 g_source_remove(p->fishframe_timer);
240 p->fishframe_timer=
241 g_timeout_add(80,(GSourceFunc)reanimate_fish,p);
242 }else{
243 p->fishframe_init=1;
244 p->fishframe_timer=
245 g_timeout_add(rand()%1000*30,(GSourceFunc)reanimate_fish,p);
249 static void action_play(GtkWidget *widget,postfish_mainpanel *p){
250 if(gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget))){
251 if(!playback_active){
252 pthread_t playback_thread_id;
253 playback_active=1;
254 meterhold_reset(p);
255 animate_fish(p);
256 pthread_create(&playback_thread_id,NULL,&playback_thread,NULL);
258 }else{
259 output_halt_playback();
263 static void action_entrya(GtkWidget *widget,postfish_mainpanel *p){
264 const char *time=gtk_entry_get_text(GTK_ENTRY(p->entry_a));
265 off_t cursor=input_time_to_cursor(time);
267 input_seek(cursor);
268 readout_set(READOUT(p->cue),(char *)time);
272 static void action_entryb(GtkWidget *widget,postfish_mainpanel *p){
273 if(gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget))){
275 const char *time=gtk_entry_get_text(GTK_ENTRY(p->entry_b));
276 off_t cursora,cursorb=input_time_to_cursor(time);
277 time=gtk_entry_get_text(GTK_ENTRY(p->entry_a));
278 cursora=input_time_to_cursor(time);
280 if(cursora<cursorb){
281 input_Acursor_set(cursora);
282 input_Bcursor_set(cursorb);
283 loop_active=1;
284 }else{
285 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(widget),0);
287 }else
288 loop_active=0;
290 gtk_image_set_from_pixmap(GTK_IMAGE(p->playimage),
291 p->pf[loop_active],
292 p->pb[loop_active]);
296 static void action_seta_to(postfish_mainpanel *p,const char *time){
297 gtk_entry_set_text(GTK_ENTRY(p->entry_a),time);
300 const char *time=gtk_entry_get_text(GTK_ENTRY(p->entry_a));
301 off_t cursora=input_time_to_cursor(time),cursorb;
302 time=gtk_entry_get_text(GTK_ENTRY(p->entry_b));
303 cursorb=input_time_to_cursor(time);
305 if(cursora>=cursorb && loop_active){
306 loop_active=0;
307 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(p->cue_b),0);
309 input_Acursor_set(cursora);
314 static void action_seta(GtkWidget *widget,postfish_mainpanel *p){
315 const char *time=readout_get(READOUT(p->cue));
316 action_seta_to(p,time);
319 static void action_setb_to(postfish_mainpanel *p,const char *time){
320 off_t cursora,cursorb;
322 cursorb=input_time_to_cursor(time);
323 gtk_entry_set_text(GTK_ENTRY(p->entry_b),time);
325 time=gtk_entry_get_text(GTK_ENTRY(p->entry_a));
326 cursora=input_time_to_cursor(time);
328 if(cursora>=cursorb && loop_active){
329 loop_active=0;
330 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(p->cue_b),0);
332 input_Bcursor_set(cursorb);
336 static void action_setb(GtkWidget *widget,postfish_mainpanel *p){
337 const char *time= time=readout_get(READOUT(p->cue));
338 action_setb_to(p,time);
341 static void shutdown(void){
342 output_halt_playback();
343 save_state();
344 main_looping=0;
345 gtk_main_quit();
348 static void masterdB_change(GtkWidget *dummy, gpointer in){
349 postfish_mainpanel *p=in;
350 char buf[80];
351 float val=multibar_get_value(MULTIBAR(p->masterdB_s),0);
352 sprintf(buf,"%+5.1fdB",val);
353 readout_set(READOUT(p->masterdB_r),buf);
355 if(gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(p->masterdB_a)))
356 master_att=rint(val*10);
357 else
358 master_att=0;
361 static gboolean timeevent_unselect(GtkWidget *widget,
362 gpointer dummy){
364 gtk_editable_select_region(GTK_EDITABLE(widget),0,0);
365 return FALSE;
368 static gboolean channel_keybinding(GtkWidget *widget,
369 GdkEventKey *event,
370 gpointer in){
371 postfish_mainpanel *p=in;
372 int keych=event->keyval-GDK_0;
373 int actualch,widgetnum;
375 if(keych==0)
376 keych=9;
377 else
378 keych--;
380 if(keych<0 || keych>9)return FALSE;
381 actualch=keych;
383 widgetnum=p->channelrotate[keych];
385 while(widgetnum>=p->channeleffects){
386 widgetnum-=p->channeleffects;
387 actualch+=10;
390 gtk_widget_grab_focus(p->channel_wa[widgetnum][actualch]);
392 widgetnum=++p->channelrotate[keych];
394 actualch=keych;
395 while(widgetnum>=p->channeleffects){
396 widgetnum-=p->channeleffects;
397 actualch+=10;
399 if(actualch>=input_ch)p->channelrotate[keych]=0;
401 return TRUE;
404 static gboolean timeevent_keybinding(GtkWidget *widget,
405 GdkEventKey *event,
406 gpointer in){
407 GtkWidget *toplevel=GTK_WIDGET(in);
408 GtkEntry *e=GTK_ENTRY(widget);
409 gint pos=gtk_editable_get_position(GTK_EDITABLE(widget));
410 const gchar *text=gtk_entry_get_text(e);
412 /* we accept only numerals, forward arrow keys, Enter, tab, alt-tab,
413 block all else */
414 switch(event->keyval){
415 case GDK_6:
416 case GDK_7:
417 case GDK_8:
418 case GDK_9:
419 if(pos==5 || pos==8)return TRUE;
420 case GDK_0:
421 case GDK_1:
422 case GDK_2:
423 case GDK_3:
424 case GDK_4:
425 case GDK_5:
426 if(pos==4 || pos==7 || pos==10)pos++;
428 if(pos>12)return TRUE;
430 char buffer[15];
431 strncpy(buffer,text,15);
432 if(pos>13)pos=13;
433 buffer[pos]=event->keyval;
435 time_fix(buffer);
437 pos++;
438 if(pos==4 || pos==7 || pos==10)pos++;
439 gtk_entry_set_text(e,buffer);
440 gtk_editable_set_position(GTK_EDITABLE(widget),pos);
441 return TRUE;
443 break;
444 case GDK_BackSpace:
445 /* rewrite to left arrow */
446 case GDK_Left:
447 if(pos==0){
448 /* back up focus */
449 gtk_widget_child_focus(toplevel,GTK_DIR_LEFT);
450 return TRUE;
453 pos--;
454 if(pos==4 || pos==7 || pos==10)pos--;
455 gtk_editable_set_position(GTK_EDITABLE(widget),pos);
456 return TRUE;
458 case GDK_Right:
459 if(pos>=12){
460 /* advance focus */
461 gtk_widget_child_focus(toplevel,GTK_DIR_RIGHT);
462 return TRUE;
465 pos++;
466 if(pos==4 || pos==7 || pos==10)pos++;
467 gtk_editable_set_position(GTK_EDITABLE(widget),pos);
468 return TRUE;
470 case GDK_Tab:
471 case GDK_ISO_Left_Tab:
472 case GDK_Up:
473 case GDK_Down:
474 return FALSE;
476 default:
477 return TRUE;
481 static gboolean mainpanel_keybinding(GtkWidget *widget,
482 GdkEventKey *event,
483 gpointer in){
484 postfish_mainpanel *p=in;
487 #if 0
488 fprintf(stderr,"keypress: M%d C%d S%d L%d '%x'\n",
489 event->state&GDK_MOD1_MASK,
490 event->state&GDK_CONTROL_MASK,
491 event->state&GDK_SHIFT_MASK,
492 event->state&GDK_LOCK_MASK,
493 event->keyval);
494 #endif
496 if(event->state&GDK_MOD1_MASK) return FALSE;
497 if(event->state&GDK_CONTROL_MASK)return FALSE;
499 /* non-control keypresses */
500 switch(event->keyval){
501 case GDK_less:
502 case GDK_comma:
503 case GDK_period:
504 case GDK_greater:
506 /* GTK has one unfortunate bit of hardwiring; if a key is held down
507 and autorepeats, the default pushbutton widget-unactivate timeout
508 is 250 ms, far slower than autorepeat. We must defeat this to
509 have autorepeat accellerators function at full speed. */
512 GdkEventKey copy=*event;
513 copy.type=GDK_KEY_RELEASE;
514 gtk_main_do_event((GdkEvent *)(&copy));
516 while (gtk_events_pending ()) gtk_main_iteration ();
520 switch(event->keyval){
521 case GDK_minus:
522 multibar_thumb_set(MULTIBAR(p->masterdB_s),
523 multibar_get_value(MULTIBAR(p->masterdB_s),0)-.1,0);
524 break;
525 case GDK_underscore:
526 multibar_thumb_set(MULTIBAR(p->masterdB_s),
527 multibar_get_value(MULTIBAR(p->masterdB_s),0)-1.,0);
528 break;
529 case GDK_equal:
530 multibar_thumb_set(MULTIBAR(p->masterdB_s),
531 multibar_get_value(MULTIBAR(p->masterdB_s),0)+.1,0);
532 break;
533 case GDK_plus:
534 multibar_thumb_set(MULTIBAR(p->masterdB_s),
535 multibar_get_value(MULTIBAR(p->masterdB_s),0)+1.,0);
536 break;
537 default:
538 return FALSE;
541 return TRUE;
544 static void mainpanel_chentry(postfish_mainpanel *p,
545 GtkWidget *table,
546 char *label,
547 int i,
548 void (*single_create)
549 (postfish_mainpanel *,
550 GtkWidget **, GtkWidget **),
551 void (*multi_create)
552 (postfish_mainpanel *,
553 GtkWidget **, GtkWidget **)){
555 int j;
556 GtkWidget *wm[input_ch+1];
557 GtkWidget *wa[input_ch];
559 for(j=0;j<input_ch;j++){
560 char buffer[80];
561 sprintf(buffer," %d ",j+1);
562 p->channel_wa[i][j]=wa[j]=gtk_toggle_button_new_with_label(buffer);
564 if(multi_create){
565 /* a panel button per channel, multiple accellerated labels */
566 GtkWidget *l=gtk_label_new_with_mnemonic(label);
567 GtkWidget *a=gtk_alignment_new(0,.5,0,0);
568 gtk_widget_set_name(l,"windowbuttonlike");
569 gtk_misc_set_alignment(GTK_MISC(l),0,.5);
570 wm[j]=windowbutton_new(NULL);
571 gtk_container_add(GTK_CONTAINER(a),wm[j]);
572 gtk_table_attach_defaults(GTK_TABLE(table),a,2+j*2,4+j*2,i+1,i+2);
573 gtk_table_attach(GTK_TABLE(table),l,1,2,i+1,i+2,GTK_FILL,0,0,0);
574 if(j>0 || single_create)gtk_widget_set_size_request(l,0,0);
575 gtk_label_set_mnemonic_widget(GTK_LABEL(l),wm[j]);
578 GtkRequisition requisition;
579 GtkWidget *label=gtk_label_new(NULL);
580 gtk_widget_size_request(wm[j],&requisition);
581 gtk_widget_set_size_request(label,requisition.width/2,1);
582 gtk_table_attach_defaults(GTK_TABLE(table),label,2+j*2,3+j*2,i+1,i+2);
583 gtk_table_attach_defaults(GTK_TABLE(table),wa[j],3+j*2,4+j*2,i+1,i+2);
586 }else{
587 gtk_table_attach_defaults(GTK_TABLE(table),wa[j],3+j*2,4+j*2,i+1,i+2);
591 if(single_create){
592 /* one master windowbutton, one label */
593 wm[input_ch]=windowbutton_new(label);
594 gtk_table_attach_defaults(GTK_TABLE(table),wm[input_ch],0,2,i+1,i+2);
596 (*single_create)(p,wm+input_ch,wa);
597 }else{
598 GtkWidget *b=windowbutton_new(NULL);
600 gtk_widget_set_sensitive(b,FALSE);
601 gtk_table_attach_defaults(GTK_TABLE(table),b,0,1,i+1,i+2);
604 if(multi_create)
605 (*multi_create)(p,wm,wa);
607 if (!single_create && !multi_create){
608 GtkWidget *l=gtk_label_new(label);
610 gtk_widget_set_name(l,"windowbuttonlike");
611 gtk_misc_set_alignment(GTK_MISC(l),0,.5);
612 gtk_table_attach_defaults(GTK_TABLE(table),l,1,2,i+1,i+2);
617 static void mainpanel_masterentry(postfish_mainpanel *p,
618 GtkWidget *table,
619 char *label,
620 char *shortcut,
621 guint key,
622 int i,
623 void (*panel_create)
624 (postfish_mainpanel *,
625 GtkWidget *, GtkWidget *)){
627 GtkWidget *ww=windowbutton_new(label);
628 GtkWidget *wa=(shortcut?
629 gtk_toggle_button_new_with_label(shortcut):
630 gtk_frame_new(shortcut));
632 gtk_table_attach_defaults(GTK_TABLE(table),ww,0,1,i+1,i+2);
633 gtk_table_attach_defaults(GTK_TABLE(table),wa,1,2,i+1,i+2);
634 if(shortcut)
635 gtk_widget_add_accelerator (wa, "activate", p->group, key, 0, 0);
636 else{
637 gtk_frame_set_shadow_type(GTK_FRAME(wa),GTK_SHADOW_ETCHED_IN);
640 if(panel_create)(*panel_create)(p,ww,(shortcut?wa:0));
643 #define CHANNEL_EFFECTS 7
644 #define MASTER_EFFECTS 7
645 extern char *version;
646 void mainpanel_create(postfish_mainpanel *panel,char **chlabels){
647 char *text_bar[7]={"[bksp]","[<]","[,]","[space]","[.]","[>]","[end]"};
649 int i;
650 GdkPixmap *xpm_bar[7];
651 GdkBitmap *xbm_bar[7];
652 GtkWidget *gim_bar[7];
654 GtkWidget *topplace,*topal,*topalb;
656 GtkWidget *topframe=gtk_frame_new (NULL);
657 GtkWidget *toplabel=gtk_label_new (NULL);
659 GtkWidget *quitbutton=gtk_button_new_with_mnemonic("_quit");
660 GtkWidget *savebutton=gtk_button_new_with_label("^save");
662 GtkWidget *mainbox=gtk_hbox_new(0,6);
663 GtkWidget *masterback=gtk_event_box_new();
664 GtkWidget *channelback=gtk_event_box_new();
665 GtkWidget *masterframe=gtk_frame_new(" Master ");
666 GtkWidget *channelframe=gtk_frame_new(" Channel ");
668 GtkWidget *deckbox=gtk_vbox_new(0,0);
669 GtkWidget *channelbox=gtk_vbox_new(0,0);
670 GtkWidget *masterbox=gtk_vbox_new(0,6);
672 GtkWidget *channeltable=gtk_table_new(CHANNEL_EFFECTS+1,input_ch*2+2,0);
673 GtkWidget *mastertable=gtk_table_new(MASTER_EFFECTS+1,2,0);
675 GdkWindow *root=gdk_get_default_root_window();
677 panel->toplevel=gtk_window_new (GTK_WINDOW_TOPLEVEL);
678 panel->group = gtk_accel_group_new ();
679 gtk_window_add_accel_group (GTK_WINDOW(panel->toplevel), panel->group);
681 panel->channel_wa=malloc(CHANNEL_EFFECTS*sizeof(*panel->channel_wa));
682 for(i=0;i<CHANNEL_EFFECTS;i++)
683 panel->channel_wa[i]=malloc(input_ch*sizeof(**panel->channel_wa));
684 panel->channeleffects=CHANNEL_EFFECTS;
686 char versionmarkup[240];
687 snprintf(versionmarkup,240," <span size=\"large\" weight=\"bold\" "
688 "style=\"italic\" foreground=\"dark blue\">"
689 "Postfish</span> <span size=\"small\" foreground=\"#606060\">"
690 "revision %s</span> ",
691 version);
694 topplace=gtk_table_new(1,1,0);
695 topalb=gtk_hbox_new(0,0);
696 topal=gtk_alignment_new(1,0,0,0);
698 gtk_widget_set_name(quitbutton,"quitbutton");
700 gtk_box_pack_start(GTK_BOX(topalb),savebutton,0,0,0);
701 gtk_box_pack_start(GTK_BOX(topalb),quitbutton,0,0,0);
702 gtk_container_add (GTK_CONTAINER(topal),topalb);
705 gtk_table_attach_defaults(GTK_TABLE(topplace),
706 topal,0,1,0,1);
707 gtk_table_attach_defaults(GTK_TABLE(topplace),
708 topframe,0,1,0,1);
710 gtk_container_add (GTK_CONTAINER (panel->toplevel), topplace);
711 gtk_container_set_border_width (GTK_CONTAINER (quitbutton), 3);
712 gtk_container_set_border_width (GTK_CONTAINER (savebutton), 3);
714 g_signal_connect (G_OBJECT (quitbutton), "clicked",
715 G_CALLBACK (shutdown), NULL);
717 g_signal_connect (G_OBJECT (savebutton), "clicked",
718 G_CALLBACK (savestatei), 0);
720 gtk_widget_add_accelerator (savebutton, "activate", panel->group, GDK_s, GDK_CONTROL_MASK, 0);
723 g_signal_connect (G_OBJECT (panel->toplevel), "key-press-event",
724 G_CALLBACK (mainpanel_keybinding), panel);
726 g_signal_connect_after (G_OBJECT (panel->toplevel), "key-press-event",
727 G_CALLBACK (channel_keybinding), panel);
730 for(i=0;i<19;i++)
731 panel->ff[i]=gdk_pixmap_create_from_xpm_d(root,
732 panel->fb+i,NULL,ff_xpm[i]);
734 xpm_bar[0]=gdk_pixmap_create_from_xpm_d(root,
735 xbm_bar,NULL,bar_home_xpm);
736 xpm_bar[1]=gdk_pixmap_create_from_xpm_d(root,
737 xbm_bar+1,NULL,bar_bb_xpm);
738 xpm_bar[2]=gdk_pixmap_create_from_xpm_d(root,
739 xbm_bar+2,NULL,bar_b_xpm);
740 xpm_bar[3]=gdk_pixmap_create_from_xpm_d(root,
741 xbm_bar+3,NULL,bar_p_xpm);
742 xpm_bar[4]=gdk_pixmap_create_from_xpm_d(root,
743 xbm_bar+4,NULL,bar_f_xpm);
744 xpm_bar[5]=gdk_pixmap_create_from_xpm_d(root,
745 xbm_bar+5,NULL,bar_ff_xpm);
746 xpm_bar[6]=gdk_pixmap_create_from_xpm_d(root,
747 xbm_bar+6,NULL,bar_end_xpm);
750 panel->pf[0]=xpm_bar[3];
751 panel->pb[0]=xbm_bar[3];
752 panel->pf[1]=gdk_pixmap_create_from_xpm_d(root,
753 panel->pb+1,NULL,bar_l_xpm);
755 for(i=0;i<7;i++)
756 gim_bar[i]=gtk_image_new_from_pixmap(xpm_bar[i],xbm_bar[i]);
757 panel->playimage=gim_bar[3];
759 panel->twirlimage=gtk_image_new_from_pixmap(panel->ff[0],panel->fb[0]);
761 gtk_container_set_border_width (GTK_CONTAINER (topframe), 3);
762 gtk_container_set_border_width (GTK_CONTAINER (mainbox), 3);
763 gtk_container_set_border_width (GTK_CONTAINER (masterbox), 3);
764 gtk_container_set_border_width (GTK_CONTAINER (channelbox), 3);
765 gtk_frame_set_shadow_type(GTK_FRAME(topframe),GTK_SHADOW_ETCHED_IN);
766 gtk_frame_set_label_widget(GTK_FRAME(topframe),toplabel);
767 gtk_label_set_markup(GTK_LABEL(toplabel),versionmarkup);
769 gtk_container_add (GTK_CONTAINER(topframe), mainbox);
770 gtk_box_pack_end(GTK_BOX(mainbox),masterbox,0,0,0);
771 gtk_box_pack_end(GTK_BOX(mainbox),channelbox,0,0,0);
772 gtk_box_pack_start(GTK_BOX(masterbox),masterback,1,1,0);
773 gtk_box_pack_start(GTK_BOX(channelbox),channelback,1,1,0);
774 gtk_container_add (GTK_CONTAINER(masterback), masterframe);
775 gtk_container_add (GTK_CONTAINER(channelback), channelframe);
776 gtk_box_pack_start(GTK_BOX(mainbox),deckbox,0,0,0);
777 gtk_widget_set_name(masterback,"winpanel");
778 gtk_widget_set_name(channelback,"winpanel");
780 gtk_frame_set_label_align(GTK_FRAME(channelframe),.5,0.);
781 gtk_frame_set_label_align(GTK_FRAME(masterframe),.5,0.);
783 /* left side of main panel */
785 char *labels[13]={"","-96","-72","-60","-48","-36","-24",
786 "-16","-8","-3","0","+3","+6"};
787 float levels[13]={-140.,-96.,-72.,-60.,-48.,-36.,-24.,
788 -16.,-8.,-3.,0.,+3.,+6.};
790 GtkWidget *ttable=gtk_table_new(7,2,0);
791 GtkWidget *togglebox=gtk_hbox_new(0,0);
792 GtkWidget *in=gtk_label_new("in:");
793 GtkWidget *out=gtk_label_new("out:");
794 GtkWidget *show=gtk_label_new("show:");
795 GtkWidget *inbox=gtk_hbox_new(0,0);
796 GtkWidget *outbox=gtk_hbox_new(0,0);
798 panel->inbar=multibar_new(13,labels,levels, 0,
799 LO_ATTACK|LO_DECAY|HI_DECAY|PEAK_FOLLOW );
800 panel->outbar=multibar_new(13,labels,levels, 0,
801 LO_ATTACK|LO_DECAY|HI_DECAY|PEAK_FOLLOW );
802 panel->inreadout=readout_new("------");
803 panel->outreadout=readout_new("------");
805 gtk_widget_set_name(panel->inreadout,"smallreadout");
806 gtk_widget_set_name(panel->outreadout,"smallreadout");
808 gtk_box_pack_start(GTK_BOX(inbox),panel->inbar,1,1,0);
809 gtk_box_pack_end(GTK_BOX(inbox),panel->inreadout,0,1,0);
810 gtk_box_pack_start(GTK_BOX(outbox),panel->outbar,1,1,0);
811 gtk_box_pack_end(GTK_BOX(outbox),panel->outreadout,0,1,0);
813 gtk_container_set_border_width(GTK_CONTAINER (ttable), 3);
814 gtk_table_set_col_spacings(GTK_TABLE(ttable),5);
815 gtk_misc_set_alignment(GTK_MISC(show),1,.5);
816 gtk_misc_set_alignment(GTK_MISC(in),1,.5);
817 gtk_misc_set_alignment(GTK_MISC(out),1,.5);
818 gtk_box_set_spacing(GTK_BOX(togglebox),5);
820 for(i=0;;i++){
821 if(!chlabels[i])break;
823 GtkWidget *button=gtk_check_button_new_with_mnemonic(chlabels[i]);
824 if(i<input_ch)gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(button),TRUE);
825 gtk_box_pack_start(GTK_BOX(togglebox),button,0,0,0);
827 char buffer[]="color\0\0";
828 buffer[5]= (i%10)+48;
829 gtk_widget_set_name(button,buffer);
831 panel->channelshow[i]=button;
834 gtk_table_attach_defaults(GTK_TABLE(ttable),togglebox,1,3,0,1);
835 gtk_table_attach(GTK_TABLE(ttable),show,0,1,0,1,GTK_FILL|GTK_SHRINK,GTK_FILL|GTK_SHRINK,0,0);
836 gtk_table_attach(GTK_TABLE(ttable),in,0,1,1,2,GTK_FILL|GTK_SHRINK,GTK_FILL|GTK_SHRINK,0,0);
837 gtk_table_attach(GTK_TABLE(ttable),out,0,1,2,3,GTK_FILL|GTK_SHRINK,GTK_FILL|GTK_SHRINK,0,0);
838 gtk_table_attach(GTK_TABLE(ttable),inbox,1,3,1,2,GTK_EXPAND|GTK_FILL,GTK_EXPAND|GTK_FILL,0,0);
839 gtk_table_attach(GTK_TABLE(ttable),outbox,1,3,2,3,GTK_EXPAND|GTK_FILL,GTK_EXPAND|GTK_FILL,0,0);
841 gtk_table_set_row_spacing(GTK_TABLE(ttable),1,1);
842 gtk_table_set_row_spacing(GTK_TABLE(ttable),2,2);
844 /* master dB slider */
846 char *sliderlabels[11]={"","-40","-30","-20","-10","0","+10","+20","+30","+40","+50"};
847 float sliderlevels[11]={-50,-40,-30,-20,-10,0,10,20,30,40,50};
849 GtkWidget *box=gtk_hbox_new(0,0);
851 GtkWidget *masterlabel=gtk_label_new("master:");
852 panel->masterdB_a=gtk_toggle_button_new_with_label("a[t]ten");
853 panel->masterdB_r=readout_new(" 0.0dB");
854 panel->masterdB_s=multibar_slider_new(11,sliderlabels,sliderlevels,1);
856 multibar_thumb_set(MULTIBAR(panel->masterdB_s),0.,0);
857 multibar_thumb_increment(MULTIBAR(panel->masterdB_s),.1,1.);
859 gtk_misc_set_alignment(GTK_MISC(masterlabel),1,.5);
861 gtk_table_attach(GTK_TABLE(ttable),masterlabel,0,1,3,4,
862 GTK_FILL,GTK_FILL,0,0);
864 gtk_box_pack_start(GTK_BOX(box),panel->masterdB_s,1,1,0);
865 gtk_box_pack_start(GTK_BOX(box),panel->masterdB_r,0,0,0);
866 gtk_box_pack_start(GTK_BOX(box),panel->masterdB_a,0,0,0);
868 gtk_table_attach_defaults(GTK_TABLE(ttable),box,1,3,3,4);
870 multibar_callback(MULTIBAR(panel->masterdB_s),
871 masterdB_change,(gpointer)panel);
873 gtk_widget_add_accelerator (panel->masterdB_a, "activate", panel->group, GDK_t, 0, 0);
874 g_signal_connect_after (G_OBJECT(panel->masterdB_a), "clicked",
875 G_CALLBACK(masterdB_change), (gpointer)panel);
876 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(panel->masterdB_a),1);
879 /* master action bar */
881 GtkWidget *bar_table=gtk_table_new(1,8,1);
882 for(i=0;i<7;i++){
883 GtkWidget *box=gtk_vbox_new(0,3);
884 GtkWidget *label=gtk_label_new(text_bar[i]);
886 if(i==3)
887 panel->deckactive[i]=gtk_toggle_button_new();
888 else
889 panel->deckactive[i]=gtk_button_new();
891 gtk_box_pack_start(GTK_BOX(box),gim_bar[i],0,0,0);
892 gtk_box_pack_start(GTK_BOX(box),label,0,0,0);
893 gtk_container_add (GTK_CONTAINER(panel->deckactive[i]), box);
896 gtk_table_attach_defaults(GTK_TABLE(bar_table),panel->deckactive[0],0,1,0,1);
897 gtk_table_attach_defaults(GTK_TABLE(bar_table),panel->deckactive[1],1,2,0,1);
898 gtk_table_attach_defaults(GTK_TABLE(bar_table),panel->deckactive[2],2,3,0,1);
899 gtk_table_attach_defaults(GTK_TABLE(bar_table),panel->deckactive[3],3,5,0,1);
900 gtk_table_attach_defaults(GTK_TABLE(bar_table),panel->deckactive[4],5,6,0,1);
901 gtk_table_attach_defaults(GTK_TABLE(bar_table),panel->deckactive[5],6,7,0,1);
902 gtk_table_attach_defaults(GTK_TABLE(bar_table),panel->deckactive[6],7,8,0,1);
904 gtk_table_attach(GTK_TABLE(ttable),bar_table,1,3,4,5,
905 GTK_EXPAND|GTK_FILL,GTK_EXPAND|GTK_FILL,
906 0,8);
908 gtk_table_attach(GTK_TABLE(ttable),panel->twirlimage,0,1,4,5,
909 0,0,
910 0,0);
913 g_signal_connect (G_OBJECT (panel->deckactive[0]), "clicked",
914 G_CALLBACK (action_zero), panel);
915 g_signal_connect (G_OBJECT (panel->deckactive[1]), "clicked",
916 G_CALLBACK (action_bb), panel);
917 g_signal_connect (G_OBJECT (panel->deckactive[2]), "clicked",
918 G_CALLBACK (action_b), panel);
919 g_signal_connect (G_OBJECT (panel->deckactive[3]), "clicked",
920 G_CALLBACK (action_play), panel);
921 g_signal_connect (G_OBJECT (panel->deckactive[4]), "clicked",
922 G_CALLBACK (action_f), panel);
923 g_signal_connect (G_OBJECT (panel->deckactive[5]), "clicked",
924 G_CALLBACK (action_ff), panel);
925 g_signal_connect (G_OBJECT (panel->deckactive[6]), "clicked",
926 G_CALLBACK (action_end), panel);
928 gtk_widget_add_accelerator (panel->deckactive[3], "activate", panel->group, GDK_space, 0, 0);
930 if(!input_seekable){
931 gtk_widget_set_sensitive(panel->deckactive[0],FALSE);
932 gtk_widget_set_sensitive(panel->deckactive[1],FALSE);
933 gtk_widget_set_sensitive(panel->deckactive[2],FALSE);
934 gtk_widget_set_sensitive(panel->deckactive[4],FALSE);
935 gtk_widget_set_sensitive(panel->deckactive[5],FALSE);
936 gtk_widget_set_sensitive(panel->deckactive[6],FALSE);
937 }else{
938 gtk_widget_add_accelerator (panel->deckactive[0], "activate", panel->group, GDK_BackSpace, 0, 0);
939 gtk_widget_add_accelerator (panel->deckactive[1], "activate", panel->group, GDK_less, 0, 0);
940 gtk_widget_add_accelerator (panel->deckactive[2], "activate", panel->group, GDK_comma, 0, 0);
941 gtk_widget_add_accelerator (panel->deckactive[4], "activate", panel->group, GDK_period, 0, 0);
942 gtk_widget_add_accelerator (panel->deckactive[5], "activate", panel->group, GDK_greater, 0, 0);
943 gtk_widget_add_accelerator (panel->deckactive[6], "activate", panel->group, GDK_End, 0, 0);
948 /* cue bar */
950 GtkWidget *cuebox=gtk_hbox_new(0,0);
951 GtkWidget *cuelabel=gtk_label_new("cue:");
953 GtkWidget *framea=gtk_vseparator_new();
954 GtkWidget *frameb=gtk_vseparator_new();
956 GtkWidget *panelb=windowbutton_new("c_ue list");
957 GtkWidget *temp;
959 panel->entry_a=gtk_entry_new();
960 panel->entry_b=gtk_entry_new();
962 panel->cue=readout_new(" : :00.00");
964 temp=gtk_button_new_with_label(" a ");
965 gtk_widget_add_accelerator (temp, "activate", panel->group, GDK_a, 0, 0);
966 g_signal_connect (G_OBJECT (temp), "clicked",
967 G_CALLBACK (action_entrya), panel);
968 gtk_box_pack_start(GTK_BOX(cuebox),panel->cue,0,0,0);
969 gtk_box_pack_start(GTK_BOX(cuebox),framea,1,1,3);
970 gtk_box_pack_start(GTK_BOX(cuebox),temp,0,0,0);
971 gtk_box_pack_start(GTK_BOX(cuebox),panel->entry_a,0,0,0);
972 if(!input_seekable)gtk_widget_set_sensitive(temp,FALSE);
974 temp=gtk_button_new_with_label(" A ");
975 gtk_widget_add_accelerator (temp, "activate", panel->group, GDK_A, GDK_SHIFT_MASK, 0);
976 g_signal_connect (G_OBJECT (temp), "clicked",
977 G_CALLBACK (action_seta), panel);
978 gtk_box_pack_start(GTK_BOX(cuebox),temp,0,0,0);
980 panel->cue_b=temp=gtk_toggle_button_new_with_label(" b ");
981 gtk_widget_add_accelerator (temp, "activate", panel->group, GDK_b, 0, 0);
982 g_signal_connect (G_OBJECT (temp), "clicked",
983 G_CALLBACK (action_entryb), panel);
984 gtk_box_pack_start(GTK_BOX(cuebox),frameb,1,1,3);
985 gtk_box_pack_start(GTK_BOX(cuebox),temp,0,0,0);
986 if(!input_seekable)gtk_widget_set_sensitive(temp,FALSE);
988 temp=gtk_button_new_with_label(" B ");
989 gtk_widget_add_accelerator (temp, "activate", panel->group, GDK_B, GDK_SHIFT_MASK, 0);
990 g_signal_connect (G_OBJECT (temp), "clicked",
991 G_CALLBACK (action_setb), panel);
992 gtk_box_pack_start(GTK_BOX(cuebox),panel->entry_b,0,0,0);
993 gtk_box_pack_start(GTK_BOX(cuebox),temp,0,0,0);
995 gtk_entry_set_width_chars(GTK_ENTRY(panel->entry_a),13);
996 gtk_entry_set_width_chars(GTK_ENTRY(panel->entry_b),13);
997 gtk_entry_set_text(GTK_ENTRY(panel->entry_a)," : :00.00");
998 gtk_entry_set_text(GTK_ENTRY(panel->entry_b)," : :00.00");
1001 g_signal_connect (G_OBJECT (panel->entry_a), "key-press-event",
1002 G_CALLBACK (timeevent_keybinding), panel->toplevel);
1003 g_signal_connect (G_OBJECT (panel->entry_b), "key-press-event",
1004 G_CALLBACK (timeevent_keybinding), panel->toplevel);
1006 g_signal_connect_after(G_OBJECT (panel->entry_a), "grab_focus",
1007 G_CALLBACK (timeevent_unselect), NULL);
1008 g_signal_connect_after(G_OBJECT (panel->entry_b), "grab_focus",
1009 G_CALLBACK (timeevent_unselect), NULL);
1011 gtk_misc_set_alignment(GTK_MISC(cuelabel),1,.5);
1013 gtk_table_attach_defaults(GTK_TABLE(ttable),cuelabel,0,1,5,6);
1014 gtk_table_attach_defaults(GTK_TABLE(ttable),cuebox,1,2,5,6);
1015 gtk_table_attach_defaults(GTK_TABLE(ttable),panelb,2,3,5,6);
1019 /* config bar */
1021 GtkWidget *confbox=gtk_hbox_new(0,0);
1022 GtkWidget *conflabel=gtk_label_new("setting:");
1023 GtkWidget *conf=readout_new("");
1024 GtkWidget *panel=windowbutton_new("_setting list");
1025 gtk_misc_set_alignment(GTK_MISC(conflabel),1,.5);
1027 gtk_table_attach_defaults(GTK_TABLE(ttable),conflabel,0,1,6,7);
1028 gtk_table_attach(GTK_TABLE(ttable),confbox,1,2,6,7,
1029 GTK_EXPAND|GTK_FILL,GTK_EXPAND|GTK_FILL,0,3);
1030 gtk_table_attach_defaults(GTK_TABLE(ttable),panel,2,3,6,7);
1032 gtk_box_pack_start(GTK_BOX(confbox),conf,1,1,0);
1036 gtk_box_pack_end(GTK_BOX(deckbox),ttable,0,0,0);
1041 /* channel panel */
1044 GtkWidget *temp=gtk_label_new(NULL);
1045 GtkWidget *alignbox=gtk_vbox_new(0,0);
1046 gtk_container_set_border_width (GTK_CONTAINER (channeltable), 3);
1047 gtk_frame_set_shadow_type(GTK_FRAME(channelframe),GTK_SHADOW_ETCHED_IN);
1048 gtk_box_pack_start(GTK_BOX(alignbox),channeltable,0,0,0);
1049 gtk_container_add(GTK_CONTAINER(channelframe),alignbox);
1050 gtk_table_set_row_spacings(GTK_TABLE(channeltable),1);
1052 gtk_label_set_markup(GTK_LABEL(temp),"<span size=\"x-small\">visible</span>");
1053 gtk_misc_set_alignment(GTK_MISC(temp),0,.5);
1054 gtk_table_attach_defaults(GTK_TABLE(channeltable),temp,0,2,0,1);
1056 temp=gtk_label_new(NULL);
1057 gtk_label_set_markup(GTK_LABEL(temp),"<span size=\"x-small\">active</span>");
1058 gtk_misc_set_alignment(GTK_MISC(temp),1,.5);
1059 gtk_table_attach_defaults(GTK_TABLE(channeltable),temp,1,2+input_ch*2,0,1);
1062 mainpanel_chentry(panel,channeltable,"_Declip ",0,clippanel_create,0);
1063 mainpanel_chentry(panel,channeltable,"De_verb ",1,deverbpanel_create_channel,0);
1064 mainpanel_chentry(panel,channeltable,"_Multicomp ",2,0,compandpanel_create_channel);
1065 mainpanel_chentry(panel,channeltable,"_Singlecomp ",3,0,singlepanel_create_channel);
1066 mainpanel_chentry(panel,channeltable,"_EQ ",4,0,eqpanel_create_channel);
1067 mainpanel_chentry(panel,channeltable,"_Reverb ",5,0,reverbpanel_create_channel);
1068 mainpanel_chentry(panel,channeltable,"Atten/Mi_x ",6,attenpanel_create,
1069 mixpanel_create_channel);
1071 /* master panel */
1073 GtkWidget *temp=gtk_label_new(NULL);
1074 GtkWidget *alignbox=gtk_vbox_new(0,0);
1075 gtk_container_set_border_width (GTK_CONTAINER (mastertable), 3);
1076 gtk_frame_set_shadow_type(GTK_FRAME(masterframe),GTK_SHADOW_ETCHED_IN);
1077 gtk_box_pack_start(GTK_BOX(alignbox),mastertable,0,0,0);
1078 gtk_container_add(GTK_CONTAINER(masterframe),alignbox);
1079 gtk_table_set_row_spacings(GTK_TABLE(mastertable),1);
1082 gtk_label_set_markup(GTK_LABEL(temp),"<span size=\"x-small\">visible</span>");
1083 gtk_misc_set_alignment(GTK_MISC(temp),0,.5);
1084 gtk_table_attach_defaults(GTK_TABLE(mastertable),temp,0,1,0,1);
1086 temp=gtk_label_new(NULL);
1087 gtk_label_set_markup(GTK_LABEL(temp),"<span size=\"x-small\">active</span>");
1088 gtk_misc_set_alignment(GTK_MISC(temp),1,.5);
1089 gtk_table_attach_defaults(GTK_TABLE(mastertable),temp,1,2,0,1);
1092 mainpanel_masterentry(panel,mastertable,"_Multicomp "," m ",GDK_m,0,compandpanel_create_master);
1093 mainpanel_masterentry(panel,mastertable,"_Singlecomp "," s ",GDK_s,1,singlepanel_create_master);
1094 mainpanel_masterentry(panel,mastertable,"_EQ "," e ",GDK_e,2,eqpanel_create_master);
1095 mainpanel_masterentry(panel,mastertable,"_Reverb "," r ",GDK_r,3,reverbpanel_create_master);
1096 mainpanel_masterentry(panel,mastertable,"_Limit "," l ",GDK_l,4,limitpanel_create);
1098 /* output has three activity buttons not in the main grid */
1100 GtkWidget *ww=windowbutton_new("_Output ");
1102 GtkWidget *std=gtk_toggle_button_new_with_label(" o ");
1103 GtkWidget *ply=gtk_toggle_button_new_with_label("mOn");
1104 GtkWidget *box=gtk_hbox_new(0,0);
1105 GtkWidget *box2=gtk_hbox_new(1,0);
1107 GtkWidget *fw=windowbutton_new(NULL);
1108 GtkWidget *fr=gtk_frame_new(NULL);
1110 gtk_frame_set_shadow_type(GTK_FRAME(fr),GTK_SHADOW_ETCHED_IN);
1111 gtk_widget_set_sensitive(fw,FALSE);
1113 gtk_widget_add_accelerator (std, "activate", panel->group, GDK_o, 0, 0);
1114 gtk_widget_add_accelerator (ply, "activate", panel->group, GDK_O,
1115 GDK_SHIFT_MASK, 0);
1117 gtk_box_pack_start(GTK_BOX(box),ww,0,0,0);
1118 gtk_box_pack_start(GTK_BOX(box),box2,1,1,2);
1119 gtk_box_pack_start(GTK_BOX(box2),ply,1,1,0);
1122 gtk_table_attach_defaults(GTK_TABLE(mastertable),fw,0,1,6,7);
1123 gtk_table_attach_defaults(GTK_TABLE(mastertable),fr,1,2,6,7);
1125 gtk_table_attach_defaults(GTK_TABLE(mastertable),box,0,1,7,8);
1126 gtk_table_attach_defaults(GTK_TABLE(mastertable),std,1,2,7,8);
1129 GtkWidget *active[2]={ply,std};
1130 outpanel_create(panel,ww,active);
1134 g_signal_connect (G_OBJECT (panel->toplevel), "delete_event",
1135 G_CALLBACK (shutdown), NULL);
1138 gtk_widget_show_all(panel->toplevel);
1139 gtk_window_set_resizable(GTK_WINDOW(panel->toplevel),0);
1143 static void feedback_process(postfish_mainpanel *panel){
1145 /* first order of business: release the play button if playback is
1146 no longer in progress */
1148 if(gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(panel->deckactive[3])))
1149 if(!playback_active)
1150 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(panel->deckactive[3]),0);
1152 /* second order of business; update the input meter if data is
1153 available and not dirtied by a seek */
1154 if(!playback_seeking){
1155 int current_p=!output_feedback_deep();
1156 off_t time_cursor;
1157 float *rms=alloca(sizeof(*rms)*(input_ch+OUTPUT_CHANNELS));
1158 float *peak=alloca(sizeof(*peak)*(input_ch+OUTPUT_CHANNELS));
1160 if(pull_output_feedback(peak,rms)){
1161 char buffer[14];
1162 int i;
1164 for(i=0;i<OUTPUT_CHANNELS;i++){
1165 if(peak[i]>=1.)
1166 multibar_setwarn(MULTIBAR(panel->outbar),current_p);
1168 if(gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(panel->channelshow[i]))){
1169 peak[i]=todB(peak[i])*.5;
1170 rms[i]=todB(rms[i])*.5;
1172 if(peak[i]>panel->outpeak){
1173 panel->outpeak=ceil(peak[i]);
1174 sprintf(buffer,"%+4.0fdB",panel->outpeak);
1175 readout_set(READOUT(panel->outreadout),buffer);
1178 }else{
1179 peak[i]=-400;
1180 rms[i]=-400;
1185 multibar_set(MULTIBAR(panel->outbar),rms,peak,OUTPUT_CHANNELS,current_p);
1187 if(pull_input_feedback(peak,rms,&time_cursor)){
1188 for(i=0;i<input_ch;i++){
1189 if(gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(panel->channelshow[i]))){
1190 peak[i]=todB(peak[i])*.5;
1191 rms[i]=todB(rms[i])*.5;
1193 if(peak[i]>panel->inpeak){
1194 panel->inpeak=ceil(peak[i]);
1195 sprintf(buffer,"%+4.0fdB",panel->inpeak);
1196 readout_set(READOUT(panel->inreadout),buffer);
1199 }else{
1200 peak[i]=-400;
1201 rms[i]=-400;
1205 multibar_set(MULTIBAR(panel->inbar),rms,peak,input_ch,current_p);
1206 input_cursor_to_time(time_cursor,buffer);
1207 readout_set(READOUT(panel->cue),buffer);
1210 clippanel_feedback(current_p);
1211 eqpanel_feedback(current_p);
1212 compandpanel_feedback(current_p);
1213 singlepanel_feedback(current_p);
1214 limitpanel_feedback(current_p);
1215 mixpanel_feedback(current_p);
1221 static gboolean async_event_handle(GIOChannel *channel,
1222 GIOCondition condition,
1223 gpointer data){
1224 postfish_mainpanel *panel=data;
1225 char buf[1];
1226 read(eventpipe[0],buf,1);
1228 switch(buf[0]){
1229 case 0:
1230 feedback_process(panel);
1231 break;
1232 case 1:
1233 shutdown();
1234 break;
1237 return TRUE;
1240 static int look_for_gtkrc(char *filename){
1241 FILE *f=fopen(filename,"r");
1242 if(!f)return 0;
1243 fprintf(stderr,"Loading postfish-gtkrc file found at %s\n",filename);
1244 gtk_rc_add_default_file(filename);
1245 return 1;
1248 #include <stdlib.h>
1249 void mainpanel_go(int argc,char *argv[], int ch){
1250 char *homedir=getenv("HOME");
1251 char *labels[33];
1252 char buffer[20];
1253 int i;
1254 int found=0;
1255 memset(&p,0,sizeof(p));
1257 found|=look_for_gtkrc(ETCDIR"/postfish-gtkrc");
1259 char *rcdir=getenv("HOME");
1260 if(rcdir){
1261 char *rcfile="/.postfish/postfish-gtkrc";
1262 char *homerc=calloc(1,strlen(rcdir)+strlen(rcfile)+1);
1263 strcat(homerc,homedir);
1264 strcat(homerc,rcfile);
1265 found|=look_for_gtkrc(homerc);
1269 char *rcdir=getenv("POSTFISH_RCDIR");
1270 if(rcdir){
1271 char *rcfile="/postfish-gtkrc";
1272 char *homerc=calloc(1,strlen(rcdir)+strlen(rcfile)+1);
1273 strcat(homerc,homedir);
1274 strcat(homerc,rcfile);
1275 found|=look_for_gtkrc(homerc);
1278 found|=look_for_gtkrc("./postfish-gtkrc");
1280 if(!found){
1282 fprintf(stderr,"Postfish could not find the postfish-gtkrc configuration file normally\n"
1283 "installed with Postfish and located in one of the following places:\n"
1285 "\t./postfish-gtkrc\n"
1286 "\t$(POSTFISHDIR)/postfish-gtkrc\n"
1287 "\t~/.postfish/postfish-gtkrc\n\t"
1288 ETCDIR"/postfish-gtkrc\n"
1289 "This configuration file is used to tune the color, font and other detail aspects\n"
1290 "of the Postfish user interface. Although Postfish will work without it, the UI\n"
1291 "appearence will likely make the application harder to use due to missing visual\n"
1292 "cues.\n");
1295 gtk_rc_add_default_file(ETCDIR"/postfish-gtkrc");
1296 if(homedir){
1297 char *rcfile="/.postfish-gtkrc";
1298 char *homerc=calloc(1,strlen(homedir)+strlen(rcfile)+1);
1299 strcat(homerc,homedir);
1300 strcat(homerc,rcfile);
1301 gtk_rc_add_default_file(homerc);
1303 gtk_rc_add_default_file(".postfish-gtkrc");
1304 gtk_rc_add_default_file("postfish-gtkrc");
1305 gtk_init (&argc, &argv);
1307 memset(labels,0,sizeof(labels));
1308 if(ch==1){
1309 labels[0]="_1 mono";
1311 for(i=1;i<OUTPUT_CHANNELS;i++){
1312 sprintf(buffer,"_%d",i+1);
1313 labels[i]=strdup(buffer);
1315 }else if (ch==2){
1316 labels[0]="_1 left";
1317 labels[1]="_2 right";
1318 for(i=2;i<OUTPUT_CHANNELS;i++){
1319 sprintf(buffer,"_%d",i+1);
1320 labels[i]=strdup(buffer);
1322 }else if (ch>0 && ch<=MAX_INPUT_CHANNELS){
1323 for(i=0;i<ch && i<9;i++){
1324 sprintf(buffer,"_%d",i+1);
1325 labels[i]=strdup(buffer);
1327 for(;i<ch;i++){
1328 sprintf(buffer,"%d_%d",(i+1)/10,(i+1)%10);
1329 labels[i]=strdup(buffer);
1331 for(;i<OUTPUT_CHANNELS;i++){
1332 sprintf(buffer,"_%d",i+1);
1333 labels[i]=strdup(buffer);
1336 }else{
1337 fprintf(stderr,"\nPostfish currently supports inputs of 1 to %d\n"
1338 "channels (current input request: %d channels)\n\n",(int)MAX_INPUT_CHANNELS,ch);
1339 exit(1);
1342 mainpanel_create(&p,labels);
1343 mainpanel_state_from_config(0);
1344 animate_fish(&p);
1346 /* set up watching the event pipe */
1348 GIOChannel *channel = g_io_channel_unix_new (eventpipe[0]);
1349 guint id;
1351 g_io_channel_set_encoding (channel, NULL, NULL);
1352 g_io_channel_set_buffered (channel, FALSE);
1353 g_io_channel_set_close_on_unref (channel, TRUE);
1355 id = g_io_add_watch (channel, G_IO_IN, async_event_handle, &p);
1357 g_io_channel_unref (channel);
1361 /* the slight race here is cosmetic, so I'm not worrying about it */
1362 main_looping=1;
1363 gtk_main ();