00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024 #ifdef HAVE_CONFIG_H
00025 # include <config.h>
00026 #endif
00027
00028 #include <sys/types.h>
00029 #include <sys/stat.h>
00030 #include <unistd.h>
00031 #include <string.h>
00032 #include <stdio.h>
00033 #include <stdint.h>
00034
00035 #include <gdk/gdkkeysyms.h>
00036 #include <gnome.h>
00037
00038 #include <malloc.h>
00039 #include <stdlib.h>
00040 #include <gdk/gdk.h>
00041 #include <glib.h>
00042
00043 #include "morse.h"
00044 #include "audio.h"
00045 #include "interface_il.h"
00046 #include "support.h"
00047
00048 #define STATUS_BAR_MESSAGE_LENGTH 25
00049 #define NUMBER_OF_STATUS_BARS 03
00050 #define MAX_SPACES_TO_APPEND 30
00051
00053 #define NUM_PLOTS 3
00054
00056 #define BW_WIDGET_NAME_PREFIX "bw"
00057
00058 #define BW_WIDGET_NAME_SUFFIX "_hz"
00059
00063 #define BW_WIDGET_NAME_LENGTH 16
00064
00065 static char name_buffer[BW_WIDGET_NAME_LENGTH];
00066
00068 GtkWidget* morse_stats = NULL;
00069
00071 static gfloat *y = NULL;
00072
00073 static char buffer[NUMBER_OF_STATUS_BARS][STATUS_BAR_MESSAGE_LENGTH];
00074 G_LOCK_DEFINE(y);
00075 G_LOCK_DEFINE(buffer);
00076
00077 static void update_status_bar(uint32_t ffts, uint32_t samples, double wpm);
00078 static void update_statistics_window(const morse_stats_ts* stats_t);
00079 static void gui_append_character_2_morse_text(char *character);
00080 static void scope_fft_plot(double *vector, uint32_t num_points);
00081 static void dialog_box(char *message);
00082
00083 #if DEBUG_GRAPH_INTERFACE == 1
00084
00085 #define DEBUG_PLOT_PRG "graph -T X -x 0 20"
00086 static void debug_plot(const int8_t *plot, int32_t y);
00087 static void open_plot_debug_pipe(void);
00088 #else
00089 #define open_plot_debug_pipe(void)
00090 #endif
00091
00092
00093
00094
00096
00099 static void gui_append_character_2_morse_text(char *character)
00100 {
00101 GtkTextMark *mark = NULL;
00102 GtkTextIter iter_start, iter_end;
00103
00104 gdk_threads_enter();
00105 gtk_text_buffer_insert_at_cursor(GTK_TEXT_VIEW(main_gui.decoded_text_v)->buffer, character, 1);
00106
00107 gtk_text_buffer_get_bounds(GTK_TEXT_VIEW(main_gui.decoded_text_v)->buffer, &iter_start, &iter_end);
00108 mark = gtk_text_buffer_create_mark(GTK_TEXT_VIEW(main_gui.decoded_text_v)->buffer, NULL, &iter_end, FALSE);
00109 gtk_text_view_scroll_mark_onscreen(GTK_TEXT_VIEW(main_gui.decoded_text_v), mark);
00110 gtk_text_buffer_delete_mark(GTK_TEXT_VIEW(main_gui.decoded_text_v)->buffer, mark);
00111
00112 gdk_flush();
00113 gdk_threads_leave();
00114 }
00115
00116
00117 int32_t plot_fft_data_array_create(uint32_t num_points)
00118 {
00119 if((y = malloc(num_points * sizeof(gfloat))) == NULL) {
00120 fprintf (stderr, "Unable to allocate fft plot buffer\n");
00121 return -1;
00122 }
00123 gtk_curve_set_vector(GTK_CURVE(main_gui.scope_v), num_points, y);
00124 gtk_curve_set_curve_type(GTK_CURVE(main_gui.scope_v), GTK_CURVE_TYPE_FREE);
00125 return 0;
00126 }
00127
00128 void plot_fft_data_array_destroy(void)
00129 {
00130 free(y);
00131 y = NULL;
00132 }
00133
00136 void statistics_window_deleted_handler(void)
00137 {
00138 GtkWidget *widget;
00139
00140 widget = lookup_widget(main_gui.main_window_v, "statistics");
00141 gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(widget), FALSE);
00142 morse_stats = NULL;
00143 }
00144
00146
00150 static void scope_fft_plot(double *vector, uint32_t num_points)
00151 {
00152 uint32_t i;
00153
00154 G_LOCK(y);
00155
00156 for(i = 0; i < num_points; i++) {
00157 y[i] = (gfloat)vector[i];
00158 }
00159
00160 gdk_threads_enter();
00161 gtk_curve_set_vector(GTK_CURVE(main_gui.scope_v), (int32_t)num_points, y);
00162 gdk_flush();
00163 gdk_threads_leave();
00164 G_UNLOCK(y);
00165 }
00166
00168
00172 static void update_status_bar(uint32_t ffts, uint32_t samples, double wpm)
00173 {
00174 G_LOCK(buffer);
00175
00176 g_snprintf(&buffer[0][0], STATUS_BAR_MESSAGE_LENGTH, "Samples: %d", samples);
00177 g_snprintf(&buffer[1][0], STATUS_BAR_MESSAGE_LENGTH, "FFT's: %d", ffts);
00178 g_snprintf(&buffer[2][0], STATUS_BAR_MESSAGE_LENGTH, "WPM: %2.1f", wpm);
00179
00180 gdk_threads_enter();
00181 gtk_statusbar_push(GTK_STATUSBAR(main_gui.samples_statusbar_v), 1, &buffer[0][0]);
00182 gtk_statusbar_push(GTK_STATUSBAR(main_gui.ffts_statusbar_v), 1, &buffer[1][0]);
00183 gtk_statusbar_push(GTK_STATUSBAR(main_gui.wpm_statusbar_v), 1, &buffer[2][0]);
00184 gdk_flush();
00185 gdk_threads_leave();
00186 G_UNLOCK(buffer);
00187 }
00188
00192 static void update_statistics_window(const morse_stats_ts* stats_t)
00193 {
00194 GtkWidget *widget;
00195
00196 gdk_threads_enter();
00197
00198 if(NULL != morse_stats)
00199 {
00200 widget = lookup_widget(morse_stats, "avg_dah_length_entry");
00201 snprintf(name_buffer, BW_WIDGET_NAME_LENGTH, "%6.3f", stats_t->avg_dah_dur);
00202 gtk_entry_set_text(GTK_ENTRY(widget), name_buffer);
00203
00204 widget = lookup_widget(morse_stats, "avg_dit_length_entry");
00205 snprintf(name_buffer, BW_WIDGET_NAME_LENGTH, "%6.3f", stats_t->avg_dit_dur);
00206 gtk_entry_set_text(GTK_ENTRY(widget), name_buffer);
00207
00208 widget = lookup_widget(morse_stats, "dah_dit_ratio_entry");
00209 snprintf(name_buffer, BW_WIDGET_NAME_LENGTH, "%6.3f", stats_t->dah_dit_ratio);
00210 gtk_entry_set_text(GTK_ENTRY(widget), name_buffer);
00211
00212 widget = lookup_widget(morse_stats, "words_per_minute_entry");
00213 snprintf(name_buffer, BW_WIDGET_NAME_LENGTH, "%3.0f", stats_t->wpm);
00214 gtk_entry_set_text(GTK_ENTRY(widget), name_buffer);
00215 }
00216
00217 gdk_flush();
00218 gdk_threads_leave();
00219 }
00220
00222 static void dialog_box(char *message)
00223 {
00224 GtkWidget* msg_box;
00225
00226 msg_box = gtk_message_dialog_new(main_gui.main_window_v, GTK_DIALOG_MODAL, GTK_MESSAGE_INFO, GTK_BUTTONS_OK, message);
00227 gtk_dialog_run (GTK_DIALOG (msg_box));
00228 gtk_widget_destroy (msg_box);
00229 }
00230
00231 void init_gui_interface_hooks(void)
00232 {
00233 set_update_status_hndlr(&update_status_bar);
00234 set_display_character_hndlr(&gui_append_character_2_morse_text);
00235 set_scope_plot_hndlr(&scope_fft_plot);
00236 register_error_message_handler(&dialog_box);
00237 set_Morse_statistics_display_hndlr(&update_statistics_window);
00238 register_debug_plot(&debug_plot);
00239 open_plot_debug_pipe();
00240 }
00241
00242 uint32_t get_fft_data_size(void) { return morse_get_fft_data_size(); }
00243 int32_t get_fft_graph_top(void) { return morse_get_fft_graph_top(); }
00244 uint32_t get_tone_packet_size(void) { return morse_get_tone_packet_size(); }
00245
00246 int32_t threads_stop(void)
00247 {
00248 morse_stop_threads();
00249 preferences_enabled(TRUE);
00250 plot_fft_data_array_destroy();
00251 return 0;
00252 }
00253
00254 void preferences_enabled(gboolean state)
00255 {
00256 GtkWidget *widget;
00257 widget = lookup_widget(main_gui.main_window_v, "preferences");
00258 gtk_widget_set_sensitive(GTK_WIDGET(widget), state);
00259 }
00260
00261 void interface_activate_bw_chk_item(const int32_t bw)
00262 {
00263 GtkWidget *widget;
00264
00265
00266 snprintf(name_buffer, BW_WIDGET_NAME_LENGTH, "%s%d%s", BW_WIDGET_NAME_PREFIX, bw, BW_WIDGET_NAME_SUFFIX);
00267 widget = lookup_widget(main_gui.main_window_v, name_buffer);
00268 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM(widget), TRUE);
00269 }
00270
00272 #if DEBUG_GRAPH_INTERFACE == 1
00273
00274
00275 static FILE *xpipe = NULL;
00276
00277 static void open_plot_debug_pipe(void)
00278 {
00279 if(NULL == (xpipe = popen(DEBUG_PLOT_PRG, "w"))) {
00280 fprintf(stderr, "Can't find %s.", DEBUG_PLOT_PRG);
00281 }
00282 }
00283
00284 static void debug_plot(const int8_t *plot, int32_t y)
00285 {
00286 static int32_t x[NUM_PLOTS];
00287 int32_t tmp;
00288
00289 tmp = atoi(plot);
00290 if( (NULL != xpipe) && (NUM_PLOTS > tmp) ) {
00291 gdk_threads_enter();
00292 fprintf(xpipe, "%s %i %i\n", plot, x[tmp]++, y);
00293 fflush(xpipe);
00294 gdk_threads_leave();
00295 }
00296 }
00297 #endif