3 * gtk2 spectrum analyzer
5 * Copyright (C) 2004 Monty
7 * This analyzer 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)
12 * The analyzer 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.
26 #include <gdk/gdkkeysyms.h>
27 #include "fisharray.h"
30 sig_atomic_t increment_fish
=0;
33 GtkWidget
*twirlimage
;
41 guint fishframe_timer
;
47 GtkWidget
**chbuttons
;
58 int plot_last_update
=0;
61 static void replot(struct panel
*p
){
62 int i
,lactive
[total_ch
];
63 for(i
=0;i
<total_ch
;i
++)
64 lactive
[i
]=gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(p
->chbuttons
[i
]));
66 /* update the spectral display; send new data */
68 pthread_mutex_lock(&feedback_mutex
);
69 plot_refresh(PLOT(p
->plot
),lactive
);
70 plot_last_update
=feedback_increment
;
71 pthread_mutex_unlock(&feedback_mutex
);
75 static void shutdown(void){
79 /* gotta have the Fucking Fish */
80 static int reanimate_fish(struct panel
*p
){
81 if(process_active
|| (p
->fishframe
>0 && p
->fishframe
<12)){
82 /* continue spinning */
83 if(increment_fish
)p
->fishframe
++;
84 if(p
->fishframe
>=12)p
->fishframe
=0;
86 gtk_image_set_from_pixmap(GTK_IMAGE(p
->twirlimage
),
90 if(p
->fishframe
==0 && !process_active
){
91 /* reschedule to blink */
93 g_timeout_add(rand()%1000*30,(GSourceFunc
)reanimate_fish
,p
);
99 if(p
->fishframe
<=1)p
->fishframe
=12;
100 if(p
->fishframe
>=19)p
->fishframe
=0;
102 gtk_image_set_from_pixmap(GTK_IMAGE(p
->twirlimage
),
104 p
->fb
[p
->fishframe
]);
107 if(p
->fishframe
==12){
108 /* reschedule to animate */
110 g_timeout_add(10,(GSourceFunc
)reanimate_fish
,p
);
114 /* reschedule to blink */
116 g_timeout_add(rand()%1000*30,(GSourceFunc
)reanimate_fish
,p
);
123 static void animate_fish(struct panel
*p
){
124 if(p
->fishframe_init
){
125 g_source_remove(p
->fishframe_timer
);
127 g_timeout_add(80,(GSourceFunc
)reanimate_fish
,p
);
131 g_timeout_add(rand()%1000*30,(GSourceFunc
)reanimate_fish
,p
);
135 static void dump(GtkWidget
*widget
,struct panel
*p
){
136 process_dump(plot_mode
);
139 static void noise(GtkWidget
*widget
,struct panel
*p
){
140 if(gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget
))){
143 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(widget
),0);
145 plot_setting(PLOT(p
->plot
),plot_res
,plot_scale
,plot_mode
,plot_link
,plot_depth
,0);
148 plot_setting(PLOT(p
->plot
),plot_res
,plot_scale
,plot_mode
,plot_link
,plot_depth
,0);
152 gtk_button_set_label(GTK_BUTTON(widget
),"clear _noise floor");
154 plot_setting(PLOT(p
->plot
),plot_res
,plot_scale
,plot_mode
,plot_link
,plot_depth
,1);
156 gtk_button_set_label(GTK_BUTTON(widget
),"sample _noise floor");
161 static void depthchange(GtkWidget
*widget
,struct panel
*p
){
162 int choice
=gtk_combo_box_get_active(GTK_COMBO_BOX(widget
));
180 plot_setting(PLOT(p
->plot
),plot_res
,plot_scale
,plot_mode
,plot_link
,plot_depth
,plot_noise
);
183 static void set_fg(GtkWidget
*c
, gpointer in
){
185 gtk_widget_modify_fg(c
,GTK_STATE_NORMAL
,rgb
);
186 gtk_widget_modify_fg(c
,GTK_STATE_ACTIVE
,rgb
);
187 gtk_widget_modify_fg(c
,GTK_STATE_PRELIGHT
,rgb
);
188 gtk_widget_modify_fg(c
,GTK_STATE_SELECTED
,rgb
);
190 /* buttons usually have internal labels */
191 if(GTK_IS_CONTAINER(c
))
192 gtk_container_forall (GTK_CONTAINER(c
),set_fg
,in
);
195 static void set_via_active(struct panel
*p
, int *active
, int *bactive
){
198 for(fi
=0;fi
<inputs
;fi
++){
199 for(i
=ch
;i
<ch
+channels
[fi
];i
++)
200 gtk_widget_set_sensitive(p
->chbuttons
[i
],1);
203 plot_set_active(PLOT(p
->plot
),active
,bactive
);
206 static void chlabels(GtkWidget
*widget
,struct panel
*p
){
207 /* scan state, update labels on channel buttons, set sensitivity
208 based on grouping and mode */
211 int bactive
[total_ch
];
213 for(i
=0;i
<total_ch
;i
++)
214 bactive
[i
]=active
[i
]=gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(p
->chbuttons
[i
]));
216 /* set sensitivity */
218 case LINK_IMPEDENCE_p1
:
219 case LINK_IMPEDENCE_1
:
220 case LINK_IMPEDENCE_10
:
227 /* first channel in each group insensitive/inactive, used as a reference */
229 for(fi
=0;fi
<inputs
;fi
++){
230 for(i
=ch
;i
<ch
+channels
[fi
];i
++){
232 gtk_widget_set_sensitive(p
->chbuttons
[i
],0);
233 active
[i
]=0; /* do not frob widget, only plot settings */
235 gtk_widget_set_sensitive(p
->chbuttons
[i
],1);
241 plot_set_active(PLOT(p
->plot
),active
,bactive
);
244 case LINK_SUMMED
: /* summing mode */
245 case LINK_SUB_FROM
: /* subtract channels from reference */
247 for(fi
=0;fi
<inputs
;fi
++){
249 for(i
=ch
;i
<ch
+channels
[fi
];i
++){
257 set_via_active(p
,active
,bactive
);
260 case LINK_INDEPENDENT
: /* normal/independent mode */
261 set_via_active(p
,active
,bactive
);
264 case LINK_PHASE
: /* response/phase */
266 for(fi
=0;fi
<inputs
;fi
++){
267 for(i
=ch
;i
<ch
+channels
[fi
];i
++)
269 gtk_widget_set_sensitive(p
->chbuttons
[i
],0);
273 gtk_widget_set_sensitive(p
->chbuttons
[i
],1);
275 gtk_widget_set_sensitive(p
->chbuttons
[i
],0);
281 plot_set_active(PLOT(p
->plot
),active
,bactive
);
291 case LINK_IMPEDENCE_p1
:
292 case LINK_IMPEDENCE_1
:
293 case LINK_IMPEDENCE_10
:
296 for(fi
=0;fi
<inputs
;fi
++){
297 for(i
=ch
;i
<ch
+channels
[fi
];i
++){
299 gtk_button_set_label(GTK_BUTTON(p
->chbuttons
[i
]),"reference");
301 sprintf(buf
,"channel %d", i
-ch
);
302 gtk_button_set_label(GTK_BUTTON(p
->chbuttons
[i
]),buf
);
310 for(fi
=0;fi
<inputs
;fi
++){
311 for(i
=ch
;i
<ch
+channels
[fi
];i
++){
313 gtk_button_set_label(GTK_BUTTON(p
->chbuttons
[i
]),"output");
315 sprintf(buf
,"channel %d", i
-ch
);
316 gtk_button_set_label(GTK_BUTTON(p
->chbuttons
[i
]),buf
);
323 case LINK_INDEPENDENT
:
327 for(fi
=0;fi
<inputs
;fi
++){
328 for(i
=ch
;i
<ch
+channels
[fi
];i
++){
329 sprintf(buf
,"channel %d", i
-ch
);
330 gtk_button_set_label(GTK_BUTTON(p
->chbuttons
[i
]),buf
);
339 for(fi
=0;fi
<inputs
;fi
++){
340 for(i
=ch
;i
<ch
+channels
[fi
];i
++){
342 gtk_button_set_label(GTK_BUTTON(p
->chbuttons
[i
]),"unused");
344 gtk_button_set_label(GTK_BUTTON(p
->chbuttons
[i
]),"response");
346 gtk_button_set_label(GTK_BUTTON(p
->chbuttons
[i
]),"phase");
348 gtk_button_set_label(GTK_BUTTON(p
->chbuttons
[i
]),"unused");
361 for(fi
=0;fi
<inputs
;fi
++){
362 GdkColor rgb
= chcolor(ch
);
364 for(i
=ch
;i
<ch
+channels
[fi
];i
++){
365 GtkWidget
*button
=p
->chbuttons
[i
];
374 for(fi
=0;fi
<inputs
;fi
++){
375 for(i
=ch
;i
<ch
+channels
[fi
];i
++){
376 GdkColor rgb
= chcolor(i
);
377 GtkWidget
*button
=p
->chbuttons
[i
];
387 static void reschange(GtkWidget
*widget
,struct panel
*p
){
388 plot_res
=gtk_combo_box_get_active(GTK_COMBO_BOX(widget
));
389 plot_setting(PLOT(p
->plot
),plot_res
,plot_scale
,plot_mode
,plot_link
,plot_depth
,plot_noise
);
392 static void scalechange(GtkWidget
*widget
,struct panel
*p
){
393 plot_scale
=gtk_combo_box_get_active(GTK_COMBO_BOX(widget
));
394 plot_setting(PLOT(p
->plot
),plot_res
,plot_scale
,plot_mode
,plot_link
,plot_depth
,plot_noise
);
397 static void modechange(GtkWidget
*widget
,struct panel
*p
){
398 plot_mode
=gtk_combo_box_get_active(GTK_COMBO_BOX(widget
));
400 plot_setting(PLOT(p
->plot
),plot_res
,plot_scale
,plot_mode
,plot_link
,plot_depth
,plot_noise
);
403 static void linkchange(GtkWidget
*widget
,struct panel
*p
){
404 plot_link
=gtk_combo_box_get_active(GTK_COMBO_BOX(widget
));
406 plot_setting(PLOT(p
->plot
),plot_res
,plot_scale
,plot_mode
,plot_link
,plot_depth
,plot_noise
);
410 static void runchange(GtkWidget
*widget
,struct panel
*p
){
411 if(gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget
))){
417 pthread_create(&thread_id
,NULL
,&process_thread
,NULL
);
421 while(process_active
)sched_yield();
425 static void holdchange(GtkWidget
*widget
,struct panel
*p
){
426 plot_hold
=gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget
));
428 plot_draw(PLOT(p
->plot
));
431 static void loopchange(GtkWidget
*widget
,struct panel
*p
){
432 acc_loop
=gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget
));
435 static void clearchange(GtkWidget
*widget
,struct panel
*p
){
437 plot_clear(PLOT(p
->plot
));
443 static void rewindchange(GtkWidget
*widget
,struct panel
*p
){
447 extern char *version
;
448 void panel_create(struct panel
*panel
){
451 GtkWidget
*topplace
,*topal
,*topalb
;
453 GtkWidget
*topframe
=gtk_frame_new (NULL
);
454 GtkWidget
*toplabel
=gtk_label_new (NULL
);
455 GtkWidget
*quitbutton
=gtk_button_new_with_mnemonic("_quit");
456 GtkWidget
*mainbox
=gtk_hbox_new(0,6);
457 GdkWindow
*root
=gdk_get_default_root_window();
458 GtkWidget
*rightbox
=gtk_vbox_new(0,0);
459 GtkWidget
*leftbox
=gtk_vbox_new(0,6);
461 panel
->toplevel
=gtk_window_new (GTK_WINDOW_TOPLEVEL
);
462 panel
->group
= gtk_accel_group_new ();
463 gtk_window_add_accel_group (GTK_WINDOW(panel
->toplevel
), panel
->group
);
465 char versionmarkup
[240];
466 snprintf(versionmarkup
,240," <span size=\"large\" weight=\"bold\" "
467 "style=\"italic\" foreground=\"dark blue\">"
468 "Spectrum Analyzer</span> <span size=\"small\" foreground=\"#606060\">"
469 "revision %s</span> ",
472 /* the Fucking Fish */
474 panel
->ff
[i
]=gdk_pixmap_create_from_xpm_d(root
,
475 panel
->fb
+i
,NULL
,ff_xpm
[i
]);
476 panel
->twirlimage
=gtk_image_new_from_pixmap(panel
->ff
[0],panel
->fb
[0]);
478 active
= calloc(total_ch
,sizeof(*active
));
480 topplace
=gtk_table_new(1,1,0);
481 topalb
=gtk_hbox_new(0,0);
482 topal
=gtk_alignment_new(1,0,0,0);
484 gtk_widget_set_name(quitbutton
,"quitbutton");
486 gtk_box_pack_start(GTK_BOX(topalb
),quitbutton
,0,0,0);
487 gtk_container_add (GTK_CONTAINER(topal
),topalb
);
489 gtk_table_attach_defaults(GTK_TABLE(topplace
),
491 gtk_table_attach_defaults(GTK_TABLE(topplace
),
494 gtk_container_add (GTK_CONTAINER (panel
->toplevel
), topplace
);
495 gtk_container_set_border_width (GTK_CONTAINER (quitbutton
), 3);
497 g_signal_connect (G_OBJECT (quitbutton
), "clicked",
498 G_CALLBACK (shutdown
), NULL
);
499 gtk_widget_add_accelerator (quitbutton
, "activate", panel
->group
, GDK_q
, 0, 0);
501 gtk_container_set_border_width (GTK_CONTAINER (topframe
), 3);
502 gtk_container_set_border_width (GTK_CONTAINER (mainbox
), 3);
503 gtk_frame_set_shadow_type(GTK_FRAME(topframe
),GTK_SHADOW_ETCHED_IN
);
504 gtk_frame_set_label_widget(GTK_FRAME(topframe
),toplabel
);
505 gtk_label_set_markup(GTK_LABEL(toplabel
),versionmarkup
);
507 gtk_container_add (GTK_CONTAINER(topframe
), mainbox
);
509 g_signal_connect (G_OBJECT (panel
->toplevel
), "delete_event",
510 G_CALLBACK (shutdown
), NULL
);
512 /* add the spectrum plot box */
513 panel
->plot
=plot_new(blocksize
/2+1,inputs
,channels
,rate
);
514 gtk_box_pack_end(GTK_BOX(leftbox
),panel
->plot
,1,1,0);
515 gtk_box_pack_start(GTK_BOX(mainbox
),leftbox
,1,1,0);
519 GtkWidget
*box
=gtk_hbox_new(1,1);
520 GtkWidget
*fishbox
=gtk_hbox_new(0,0);
521 gtk_box_pack_end(GTK_BOX(fishbox
),panel
->twirlimage
,0,0,0);
522 gtk_container_set_border_width (GTK_CONTAINER (fishbox
), 3);
524 gtk_box_pack_start(GTK_BOX(box
),fishbox
,0,0,0);
525 gtk_box_pack_start(GTK_BOX(rightbox
),box
,0,0,0);
536 //GtkWidget *vbox=gtk_vbox_new(1,1);
538 GtkWidget
*sep
=gtk_hseparator_new();
539 gtk_box_pack_start(GTK_BOX(rightbox
),sep
,0,0,6);
541 panel
->chbuttons
= calloc(total_ch
,sizeof(*panel
->chbuttons
));
542 for(fi
=0;fi
<inputs
;fi
++){
544 char *lastslash
= strrchr(inputname
[fi
],'/');
545 sprintf(buffer
,"%s",(lastslash
?lastslash
+1:inputname
[fi
]));
546 label
=gtk_label_new(buffer
);
547 gtk_widget_set_name(label
,"readout");
548 gtk_box_pack_start(GTK_BOX(rightbox
),label
,0,0,0);
550 sprintf(buffer
,"%dHz %dbit",rate
[fi
],bits
[fi
]);
551 label
=gtk_label_new(buffer
);
552 gtk_widget_set_name(label
,"readout");
553 gtk_box_pack_start(GTK_BOX(rightbox
),label
,0,0,0);
555 for(i
=ch
;i
<ch
+channels
[fi
];i
++){
556 GtkWidget
*button
=panel
->chbuttons
[i
]=gtk_toggle_button_new();
558 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(button
),1);
559 g_signal_connect (G_OBJECT (button
), "clicked", G_CALLBACK (chlabels
), panel
);
560 gtk_box_pack_start(GTK_BOX(rightbox
),button
,0,0,0);
563 GtkWidget
*sep
=gtk_hseparator_new();
564 gtk_box_pack_start(GTK_BOX(rightbox
),sep
,0,0,6);
569 chlabels(NULL
,panel
);
572 GtkWidget
*bbox
=gtk_vbox_new(0,0);
574 /* add the action buttons */
577 GtkWidget
*menu
=gtk_combo_box_new_text();
578 char *entries
[]={"single-pixel","1/24th octave","1/12th octave","1/3 octave"};
580 gtk_combo_box_append_text (GTK_COMBO_BOX (menu
), entries
[i
]);
581 gtk_combo_box_set_active(GTK_COMBO_BOX(menu
),plot_res
);
582 gtk_box_pack_start(GTK_BOX(bbox
),menu
,0,0,0);
583 g_signal_connect (G_OBJECT (menu
), "changed",
584 G_CALLBACK (reschange
), panel
);
588 GtkWidget
*menu
=gtk_combo_box_new_text();
589 char *entries
[]={"log scale","ISO log scale","linear scale"};
591 gtk_combo_box_append_text (GTK_COMBO_BOX (menu
), entries
[i
]);
592 gtk_combo_box_set_active(GTK_COMBO_BOX(menu
),plot_scale
);
593 plot_setting(PLOT(panel
->plot
),plot_res
,plot_scale
,plot_mode
,plot_link
,plot_depth
,plot_noise
);
594 gtk_box_pack_start(GTK_BOX(bbox
),menu
,0,0,0);
596 g_signal_connect (G_OBJECT (menu
), "changed",
597 G_CALLBACK (scalechange
), panel
);
602 GtkWidget
*menu
=gtk_combo_box_new_text();
603 char *entries
[]={"10dB","20dB","45dB","90dB","140dB"};
605 gtk_combo_box_append_text (GTK_COMBO_BOX (menu
), entries
[i
]);
606 gtk_combo_box_set_active(GTK_COMBO_BOX(menu
),3);
607 gtk_box_pack_start(GTK_BOX(bbox
),menu
,0,0,0);
609 g_signal_connect (G_OBJECT (menu
), "changed",
610 G_CALLBACK (depthchange
), panel
);
615 GtkWidget
*menu
=gtk_combo_box_new_text();
616 char *entries
[]={"realtime","maximum","accumulate"};
618 gtk_combo_box_append_text (GTK_COMBO_BOX (menu
), entries
[i
]);
619 gtk_combo_box_set_active(GTK_COMBO_BOX(menu
),plot_mode
);
620 gtk_box_pack_start(GTK_BOX(bbox
),menu
,0,0,0);
622 g_signal_connect (G_OBJECT (menu
), "changed",
623 G_CALLBACK (modechange
), panel
);
628 GtkWidget
*menu
=gtk_combo_box_new_text();
630 gtk_combo_box_append_text (GTK_COMBO_BOX (menu
), link_entries
[i
]);
631 gtk_combo_box_set_active(GTK_COMBO_BOX(menu
),0);
632 gtk_box_pack_start(GTK_BOX(bbox
),menu
,0,0,0);
634 g_signal_connect (G_OBJECT (menu
), "changed",
635 G_CALLBACK (linkchange
), panel
);
639 GtkWidget
*sep
=gtk_hseparator_new();
640 gtk_box_pack_start(GTK_BOX(bbox
),sep
,0,0,4);
645 GtkWidget
*button
=gtk_toggle_button_new_with_mnemonic("_run");
646 gtk_widget_add_accelerator (button
, "activate", panel
->group
, GDK_space
, 0, 0);
647 gtk_widget_add_accelerator (button
, "activate", panel
->group
, GDK_r
, 0, 0);
648 g_signal_connect (G_OBJECT (button
), "clicked", G_CALLBACK (runchange
), panel
);
649 gtk_box_pack_start(GTK_BOX(bbox
),button
,0,0,0);
656 GtkWidget
*box
=gtk_hbox_new(1,1);
657 GtkWidget
*button
=gtk_toggle_button_new_with_mnemonic("_hold");
658 gtk_widget_add_accelerator (button
, "activate", panel
->group
, GDK_h
, 0, 0);
659 g_signal_connect (G_OBJECT (button
), "clicked", G_CALLBACK (holdchange
), panel
);
660 gtk_box_pack_start(GTK_BOX(box
),button
,1,1,0);
662 button
=gtk_toggle_button_new_with_mnemonic("_loop");
663 gtk_widget_add_accelerator (button
, "activate", panel
->group
, GDK_l
, 0, 0);
664 g_signal_connect (G_OBJECT (button
), "clicked", G_CALLBACK (loopchange
), panel
);
665 gtk_box_pack_start(GTK_BOX(box
),button
,1,1,0);
666 gtk_widget_set_sensitive(button
,global_seekable
);
668 gtk_box_pack_start(GTK_BOX(bbox
),box
,0,0,0);
674 GtkWidget
*box
=gtk_hbox_new(1,1);
675 GtkWidget
*button
=gtk_button_new_with_mnemonic("_clear");
676 gtk_widget_add_accelerator (button
, "activate", panel
->group
, GDK_c
, 0, 0);
677 g_signal_connect (G_OBJECT (button
), "clicked", G_CALLBACK (clearchange
), panel
);
678 gtk_box_pack_start(GTK_BOX(box
),button
,1,1,0);
680 button
=gtk_button_new_with_mnemonic("re_wind");
681 gtk_widget_add_accelerator (button
, "activate", panel
->group
, GDK_w
, 0, 0);
682 g_signal_connect (G_OBJECT (button
), "clicked", G_CALLBACK (rewindchange
), panel
);
683 gtk_widget_set_sensitive(button
,global_seekable
);
684 gtk_box_pack_start(GTK_BOX(box
),button
,1,1,0);
686 gtk_box_pack_start(GTK_BOX(bbox
),box
,0,0,0);
691 GtkWidget
*button
=gtk_button_new_with_mnemonic("_dump data");
692 gtk_widget_add_accelerator (button
, "activate", panel
->group
, GDK_d
, 0, 0);
693 g_signal_connect (G_OBJECT (button
), "clicked", G_CALLBACK (dump
), panel
);
694 gtk_box_pack_start(GTK_BOX(bbox
),button
,0,0,0);
699 GtkWidget
*button
=gtk_toggle_button_new_with_mnemonic("sample _noise floor");
700 gtk_widget_add_accelerator (button
, "activate", panel
->group
, GDK_n
, 0, 0);
701 g_signal_connect (G_OBJECT (button
), "toggled", G_CALLBACK (noise
), panel
);
702 gtk_box_pack_start(GTK_BOX(bbox
),button
,0,0,0);
705 gtk_box_pack_end(GTK_BOX(rightbox
),bbox
,0,0,0);
706 gtk_box_pack_start(GTK_BOX(mainbox
),rightbox
,0,0,0);
709 gtk_widget_show_all(panel
->toplevel
);
710 //gtk_window_set_resizable(GTK_WINDOW(panel->toplevel),0);
714 static gboolean
async_event_handle(GIOChannel
*channel
,
715 GIOCondition condition
,
717 struct panel
*panel
=data
;
720 /* read all pending */
721 while(read(eventpipe
[0],buf
,1)>0);
725 /* check playback status and update the run button if needed */
726 if(process_active
&& panel
->run
&&
727 !gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(panel
->run
)))
728 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(panel
->run
),1);
729 if(!process_active
&& panel
->run
&&
730 gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(panel
->run
)))
731 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(panel
->run
),0);
733 /* update the spectral display; send new data */
734 pthread_mutex_lock(&feedback_mutex
);
735 if(plot_last_update
!=feedback_increment
){
736 pthread_mutex_unlock(&feedback_mutex
);
738 plot_draw(PLOT(panel
->plot
));
740 while (gtk_events_pending())
741 gtk_main_iteration();
743 pthread_mutex_unlock(&feedback_mutex
);
748 static int look_for_gtkrc(char *filename
){
749 FILE *f
=fopen(filename
,"r");
751 fprintf(stderr
,"Loading spectrum-gtkrc file found at %s\n",filename
);
752 gtk_rc_add_default_file(filename
);
756 void panel_go(int argc
,char *argv
[]){
757 char *homedir
=getenv("HOME");
759 memset(&p
,0,sizeof(p
));
761 found
|=look_for_gtkrc(ETCDIR
"/spectrum-gtkrc");
763 char *rcdir
=getenv("HOME");
765 char *rcfile
="/.spectrum/spectrum-gtkrc";
766 char *homerc
=calloc(1,strlen(rcdir
)+strlen(rcfile
)+1);
767 strcat(homerc
,homedir
);
768 strcat(homerc
,rcfile
);
769 found
|=look_for_gtkrc(homerc
);
773 char *rcdir
=getenv("SPECTRUM_RCDIR");
775 char *rcfile
="/spectrum-gtkrc";
776 char *homerc
=calloc(1,strlen(rcdir
)+strlen(rcfile
)+1);
777 strcat(homerc
,homedir
);
778 strcat(homerc
,rcfile
);
779 found
|=look_for_gtkrc(homerc
);
782 found
|=look_for_gtkrc("./spectrum-gtkrc");
786 fprintf(stderr
,"Could not find the spectrum-gtkrc configuration file normally\n"
787 "installed in one of the following places:\n"
789 "\t./spectrum-gtkrc\n"
790 "\t$(SPECTRUM_RCDIR)/spectrum-gtkrc\n"
791 "\t~/.spectrum/spectrum-gtkrc\n\t"
792 ETCDIR
"/spectrum-gtkrc\n"
793 "This configuration file is used to tune the color, font and other detail aspects\n"
794 "of the user interface. Although the analyzer will work without it, the UI\n"
795 "appearence will likely make the application harder to use due to missing visual\n"
799 gtk_rc_add_default_file(ETCDIR
"/spectrum-gtkrc");
801 char *rcfile
="/.spectrum-gtkrc";
802 char *homerc
=calloc(1,strlen(homedir
)+strlen(rcfile
)+1);
803 strcat(homerc
,homedir
);
804 strcat(homerc
,rcfile
);
805 gtk_rc_add_default_file(homerc
);
807 gtk_rc_add_default_file(".spectrum-gtkrc");
808 gtk_rc_add_default_file("spectrum-gtkrc");
809 gtk_init (&argc
, &argv
);
814 /* set up watching the event pipe */
816 GIOChannel
*channel
= g_io_channel_unix_new (eventpipe
[0]);
819 g_io_channel_set_encoding (channel
, NULL
, NULL
);
820 g_io_channel_set_buffered (channel
, FALSE
);
821 g_io_channel_set_close_on_unref (channel
, TRUE
);
823 id
= g_io_add_watch (channel
, G_IO_IN
, async_event_handle
, &p
);
825 g_io_channel_unref (channel
);
829 /* we want to be running by default */
834 pthread_create(&thread_id
,NULL
,&process_thread
,NULL
);