1 /*
2  *  This program is free software; you can redistribute it and/or
3  *  modify it under the terms of the GNU General Public License as
4  *  published by the Free Software Foundation; either version 3 of
5  *  the License, or (at your option) any later version.
6  *
7  *  This program is distributed in the hope that it will be useful,
8  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
9  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
10  *  GNU General Public License for more details:
11  *
12  *  http://www.gnu.org/copyleft/gpl.txt
13  */
14 
15 #include "callbacks.h"
16 #include "shared.h"
17 
18 /* Pop up error dialog */
19 static GtkWidget *error_dialog = NULL;
20 
21 /*------------------------------------------------------------------------*/
22 
23 /*  Error_Dialog()
24  *
25  *  Opens an error dialog box
26  */
27 
28   void
Error_Dialog(char * message)29 Error_Dialog( char *message )
30 {
31   GtkWidget *label;
32   GtkBuilder *builder;
33 
34   if( !error_dialog )
35   {
36     error_dialog = create_error_dialog( &builder );
37     label = Builder_Get_Object( builder, "error_message" );
38     gtk_label_set_text( GTK_LABEL(label), (const gchar *)message );
39     gtk_widget_show( error_dialog );
40     g_object_unref( builder );
41   }
42 }
43 
44 
45   void
on_main_window_destroy(GObject * object,gpointer user_data)46 on_main_window_destroy(
47     GObject *object,
48     gpointer user_data)
49 {
50   gtk_main_quit();
51 }
52 
53 
54   gboolean
on_main_window_delete_event(GtkWidget * widget,GdkEvent * event,gpointer user_data)55 on_main_window_delete_event(
56     GtkWidget *widget,
57     GdkEvent  *event,
58     gpointer   user_data)
59 {
60   Cleanup();
61   g_object_unref( main_builder );
62   return( FALSE );
63 }
64 
65 
66   gboolean
on_scope_drawingarea_draw(GtkWidget * widget,cairo_t * cr,gpointer user_data)67 on_scope_drawingarea_draw(
68     GtkWidget *widget,
69     cairo_t   *cr,
70     gpointer  user_data)
71 {
72   Display_Scope( cr );
73   return( TRUE );
74 }
75 
76   void
on_receiver_combobox_changed(GtkComboBox * combobox,gpointer user_data)77 on_receiver_combobox_changed(
78     GtkComboBox     *combobox,
79     gpointer         user_data)
80 {
81   GtkWidget *toggle = Builder_Get_Object( main_builder, "receive_togglebutton" );
82   gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON(toggle), FALSE );
83 
84   gchar *txt = gtk_combo_box_text_get_active_text( receiver_combobox );
85   if( strcmp(txt, "FT847") == 0 )
86     rc_data.receiver_type = FT847;
87   else if( strcmp(txt, "FT857") == 0 )
88     rc_data.receiver_type = FT857;
89   else if( strcmp(txt, "K2") == 0 )
90     rc_data.receiver_type = K2;
91   else if( strcmp(txt, "K3") == 0 )
92     rc_data.receiver_type = K3;
93   else if( strcmp(txt, "PERSEUS") == 0 )
94     rc_data.receiver_type = PERSEUS;
95   else if( strcmp(txt, "-- NONE --") == 0 )
96     rc_data.receiver_type = NONE;
97 
98   if( rc_data.receiver_type == PERSEUS )
99     rc_data.open_type = SND_OPEN_PLAYBACK;
100   else
101     rc_data.open_type = SND_OPEN_CAPTURE;
102 
103   /* Enable Transceiver CAT */
104   if( rc_data.receiver_type == NONE )
105     Clear_Flag( ENABLE_CAT );
106   else
107     Set_Flag( ENABLE_CAT );
108 }
109 
110 
111   void
on_frequency_spinbutton_value_changed(GtkSpinButton * spin_button,gpointer user_data)112 on_frequency_spinbutton_value_changed(
113     GtkSpinButton *spin_button,
114     gpointer       user_data)
115 {
116   rc_data.receiver_freq = gtk_spin_button_get_value_as_int( spin_button );
117   Write_Rx_Freq( rc_data.receiver_freq );
118 }
119 
120 
121   gboolean
on_frequency_spinbutton_scroll_event(GtkWidget * widget,GdkEvent * event,gpointer user_data)122 on_frequency_spinbutton_scroll_event(
123     GtkWidget *widget,
124     GdkEvent  *event,
125     gpointer   user_data)
126 {
127   if( event->scroll.direction == GDK_SCROLL_UP )
128     rc_data.receiver_freq++;
129   else if( event->scroll.direction == GDK_SCROLL_DOWN )
130     rc_data.receiver_freq--;
131   gtk_spin_button_set_value( frequency, (double)rc_data.receiver_freq );
132   return( TRUE );
133 }
134 
135 
136   void
on_wpm_spinbutton_value_changed(GtkSpinButton * spin_button,gpointer user_data)137 on_wpm_spinbutton_value_changed(
138     GtkSpinButton *spin_button,
139     gpointer       user_data)
140 {
141   rc_data.unit_elem = gtk_spin_button_get_value_as_int( spin_button );
142   rc_data.unit_elem =
143     (60 * rc_data.tone_freq) /
144     (50 * CYCLES_PER_FRAG * rc_data.unit_elem);
145 }
146 
147 
148   void
on_squelch_spinbutton_value_changed(GtkSpinButton * spin_button,gpointer user_data)149 on_squelch_spinbutton_value_changed(
150     GtkSpinButton *spin_button,
151     gpointer       user_data)
152 {
153   rc_data.det_squelch =
154     gtk_spin_button_get_value_as_int( spin_button );
155 }
156 
157 
158   void
on_ratio_spinbutton_value_changed(GtkSpinButton * spin_button,gpointer user_data)159 on_ratio_spinbutton_value_changed(
160     GtkSpinButton *spin_button,
161     gpointer       user_data)
162 {
163   rc_data.det_ratio =
164     gtk_spin_button_get_value( spin_button );
165 }
166 
167 
168   void
on_error_quit_button_clicked(GtkButton * button,gpointer user_data)169 on_error_quit_button_clicked(
170     GtkButton *button,
171     gpointer   user_data)
172 {
173   Cleanup();
174   gtk_main_quit();
175 }
176 
177 
178   void
on_clear_button_clicked(GtkButton * button,gpointer user_data)179 on_clear_button_clicked(
180     GtkButton *button,
181     gpointer   user_data)
182 {
183   gtk_text_buffer_set_text( rx_text_buffer, "", -1 );
184 }
185 
186 
187   gboolean
on_waterfall_drawingarea_draw(GtkWidget * widget,cairo_t * cr,gpointer user_data)188 on_waterfall_drawingarea_draw(
189     GtkWidget *widget,
190     cairo_t   *cr,
191     gpointer   user_data)
192 {
193   if( wfall_pixbuf != NULL )
194   {
195     gdk_cairo_set_source_pixbuf( cr, wfall_pixbuf, 0.0, 0.0 );
196     cairo_paint( cr );
197   }
198   return( TRUE );
199 }
200 
201 
202   gboolean
on_waterfall_drawingarea_button_press_event(GtkWidget * widget,GdkEventButton * event,gpointer user_data)203 on_waterfall_drawingarea_button_press_event(
204     GtkWidget      *widget,
205     GdkEventButton *event,
206     gpointer        user_data)
207 {
208   if( event->button == 1 )
209   {
210     if( isFlagSet(CAT_SETUP) )
211       Tune_Tcvr( event->x );
212   }
213   return( TRUE );
214 }
215 
216 
217   void
on_error_ok_button_clicked(GtkButton * button,gpointer user_data)218 on_error_ok_button_clicked(
219     GtkButton *button,
220     gpointer   user_data)
221 {
222   gtk_widget_destroy( error_dialog );
223 }
224 
225 
226   void
on_error_dialog_destroy(GObject * object,gpointer user_data)227 on_error_dialog_destroy(
228     GObject  *object,
229     gpointer  user_data)
230 {
231   error_dialog = NULL;
232 }
233 
234 
235   gboolean
on_error_dialog_delete_event(GtkWidget * widget,GdkEvent * event,gpointer user_data)236 on_error_dialog_delete_event(
237     GtkWidget *widget,
238     GdkEvent  *event,
239     gpointer   user_data)
240 {
241   return( TRUE );
242 }
243 
244 
245   void
on_auto_checkbutton_toggled(GtkToggleButton * togglebutton,gpointer user_data)246 on_auto_checkbutton_toggled(
247     GtkToggleButton *togglebutton,
248     gpointer         user_data)
249 {
250   if( gtk_toggle_button_get_active(togglebutton) )
251     Set_Flag( ADAPT_SPEED );
252   else
253     Clear_Flag( ADAPT_SPEED );
254 }
255 
256 
257   void
on_waterfall_drawingarea_configure_event(GtkWidget * widget,GdkEventConfigure * event,gpointer user_data)258 on_waterfall_drawingarea_configure_event(
259     GtkWidget    *widget,
260     GdkEventConfigure *event,
261     gpointer     user_data )
262 {
263   Waterfall_Configure_Event( event->width, event->height );
264 }
265 
266 
267   void
on_receive_togglebutton_toggled(GtkToggleButton * togglebutton,gpointer user_data)268 on_receive_togglebutton_toggled(
269     GtkToggleButton *togglebutton,
270     gpointer         user_data)
271 {
272   if( gtk_toggle_button_get_active(togglebutton) &&
273       isFlagSet(RCCONFIG_OK) )
274   {
275     char mesg[MESG_SIZE];
276     int error = 0;
277     mesg[0]   = '\0';
278 
279     /* Enable receiving Morse code */
280     if( !Setup_Sound_Card(mesg, &error) )
281     {
282       if( error )
283       {
284         Strlcat( mesg, _("\nError: "), sizeof(mesg) );
285         Strlcat( mesg, snd_strerror(error), sizeof(mesg) );
286       }
287       Cleanup();
288       Error_Dialog( mesg );
289     }
290     else if( isFlagSet(ENABLE_RECEIVE) ) /* Detector initialiazed OK */
291     {
292       if( isFlagSet(ENABLE_CAT) ) /* Valid receiver specified */
293       {
294 #ifdef HAVE_LIBPERSEUS_SDR
295         if( rc_data.receiver_type == PERSEUS )
296         {
297           if( !Perseus_Initialize() ) return;
298         }
299         else
300 #endif
301           Open_Tcvr_Serial();
302       }
303 
304       /* Start receiving and decoding signals */
305       g_idle_add( Print_Character, "RX" );
306     }
307     else
308       Error_Dialog( _("Failed to initialize signal detector") );
309   } /* if( gtk_toggle_button_get_active(togglebutton) */
310   else
311   {
312     if( isFlagSet(ENABLE_RECEIVE) )
313     {
314       g_idle_remove_by_data( "RX" );
315 
316 #ifdef HAVE_LIBPERSEUS_SDR
317       if( rc_data.receiver_type == PERSEUS )
318         Perseus_Close_Device();
319       else
320 #endif
321         if( isFlagSet(ENABLE_CAT) )
322           Close_Tcvr_Serial();
323 
324       Close_PCM_Handle();
325     } /* if( isFlagSet(ENABLE_RECEIVE) ) */
326   } /* else of if( gtk_toggle_button_get_active(togglebutton) */
327 }
328 
329 
330   void
on_ratio_radiobutton_toggled(GtkToggleButton * togglebutton,gpointer user_data)331 on_ratio_radiobutton_toggled(
332     GtkToggleButton *togglebutton,
333     gpointer         user_data)
334 {
335   if( gtk_toggle_button_get_active(togglebutton) )
336   {
337     gtk_label_set_text( GTK_LABEL(scope_label), _("Lead/Trail Ratio") );
338     Clear_Flag(
339         SELECT_LEVEL   |
340         DISPLAY_LEVEL  |
341         DISPLAY_SIGNAL);
342     Set_Flag( DISPLAY_RATIO );
343   }
344 }
345 
346 
347   void
on_level_radiobutton_toggled(GtkToggleButton * togglebutton,gpointer user_data)348 on_level_radiobutton_toggled(
349     GtkToggleButton *togglebutton,
350     gpointer         user_data)
351 {
352   if( gtk_toggle_button_get_active(togglebutton) )
353   {
354     gtk_label_set_text( GTK_LABEL(scope_label), _("Squelch Level") );
355     Set_Flag( SELECT_LEVEL );
356     Set_Flag( DISPLAY_LEVEL );
357     Clear_Flag( DISPLAY_RATIO | DISPLAY_SIGNAL );
358   }
359 }
360 
361 
362   void
on_stop_radiobutton_toggled(GtkToggleButton * togglebutton,gpointer user_data)363 on_stop_radiobutton_toggled(
364     GtkToggleButton *togglebutton,
365     gpointer         user_data)
366 {
367   if( gtk_toggle_button_get_active(togglebutton) )
368   {
369     gtk_label_set_text( GTK_LABEL(scope_label), _("Hold Display") );
370     Clear_Flag(
371         DISPLAY_SIGNAL |
372         SELECT_LEVEL   |
373         DISPLAY_LEVEL  |
374         DISPLAY_RATIO );
375     Set_Flag( SCOPE_HOLD );
376   }
377   else Clear_Flag( SCOPE_HOLD );
378 }
379 
380 
381   void
on_signal_radiobutton_toggled(GtkToggleButton * togglebutton,gpointer user_data)382 on_signal_radiobutton_toggled(
383     GtkToggleButton *togglebutton,
384     gpointer         user_data)
385 {
386   if( gtk_toggle_button_get_active(togglebutton) )
387   {
388     gtk_label_set_text( GTK_LABEL(scope_label), _("Signal Detector") );
389     Clear_Flag(
390         SELECT_LEVEL  |
391         DISPLAY_LEVEL |
392         DISPLAY_RATIO );
393     Set_Flag( DISPLAY_SIGNAL );
394   }
395 }
396 
397