⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 callbacks.c

📁 linux下的FFT 频谱分析
💻 C
📖 第 1 页 / 共 2 页
字号:
#ifdef HAVE_CONFIG_H#  include <config.h>#endif#include <gdk/gdkkeysyms.h>#include <gdk/gdkrgb.h>#include <stdlib.h>#include <stdio.h>#include <glib.h>#include "callbacks.h"#include "interface.h"#include "support.h"#include "fft-spectra.h"/* Refresh intervals: times per second. */#define REFRESH_RATE 20int refresh_status = REFRESH_NONE;int mode = MODE_FOURIER;int view_grid        = 1; int view_custom_grid = 1;char *settings = NULL;GdkGC *gc_select = NULL;PangoLayout *pango_layout=NULL;         /* Pango for rendering text */GHashTable *rgb_gc_hash=NULL;           /* Reuse the GdkGCs */static GtkWidget     *main_window=NULL,                  /* The main window widget. */    *darea=NULL;                        /* Drawing area - here will be drawn everyhing - main display area                                            and scalebars. */static GdkPixmap     *main_pixmap=NULL,                  /* The pixmap of the main display area */    *side_scalebar_pixmap=NULL,         /* The side scalebar pixmap */    *scalebar_pixmap=NULL,              /* The scalebar pixmap */    *cached_scalebar_pixmap=NULL;       /* The scalebar is cached - it does not change very often and we can                                            save some work creating it */int main_width=0,     main_height=0,     scalebar_height=0,    scalebar_width=0,    side_scalebar_width=0,    side_scalebar_height=0; float *data=NULL;int ndata_out;float dfreq;static int refresh_handler_id = 0;      /* ID of handler which is periodically called to display sampled data */int refresh_rate = REFRESH_RATE;static float button_pressed_x = -1,     /* Every time a mouse button is pressed, the position is saved to be */            button_pressed_y  = -1;     /* able to draw the selection rectabgle. Value of -1 means "not pressed". */static float button_current_x,          /* With every movement, position of mouse is saved for the selection rectangle */            button_current_y;#define pixmap_display(pixmap,x,y,w,h) gdk_draw_pixmap(darea->window, darea->style->bg_gc[GTK_WIDGET_STATE(darea)], pixmap, x,y,x,y,w,h);gint expose_event(GtkWidget *widget, GdkEventExpose *event);gboolean button_press_event(GtkWidget *widget, GdkEventButton *event);gboolean motion_notify_event(GtkWidget *widget, GdkEventMotion *event);gboolean button_release_event(GtkWidget *widget, GdkEventButton *event);gint key_press_event (GtkWidget *widget, GdkEventKey *event);void configure_event (GtkWidget *widget, GdkEventConfigure *event);int refresh_handler(gpointer user_data);void draw(void);void selection_rectangle_draw(GdkPixmap *pixmap, int width,int height);/* Do not create a new GdkGC with the same color, if    it is already in use and we need only the color    with all other attributes set to default.    Q: Do we really need to allocate for every color    a new GdkGC?*/GdkGC *get_gc(const char *color_string){    GdkGC *gc;    if ( !rgb_gc_hash )         rgb_gc_hash = g_hash_table_new(g_str_hash, g_str_equal);    gc = g_hash_table_lookup(rgb_gc_hash,color_string);    if (gc)        return gc;    gc = get_gc_new(color_string);    g_hash_table_insert(rgb_gc_hash,color_string,gc);    return gc;}/* Get a private instance of GdkGC, so that line type etc. can be changed */GdkGC *get_gc_new(const char *color_string){    GdkColor color;    GdkGC *gc;    gc = gdk_gc_new(darea->window);    gdk_color_parse(color_string, &color);    gdk_colormap_alloc_color (gdk_colormap_get_system(), &color, FALSE, FALSE);    gdk_gc_set_foreground(gc, &color);    gdk_gc_set_background(gc, &color);    return gc;}/* What gets changed when switching between PROFILES:    does change:        - colors        - custom line tags        - window dimensions        - display ranges           What gets changed when switching between DISPLAY MODES:    does change:        - colors        - window dimensions*/void read_profile(void){    int width,height;    if ( mode==MODE_FOURIER )        fourier_read_profile(&width,&height);    else if ( mode==MODE_SPECTROGRAM )        spectrogram_read_profile(&width,&height);    else if ( mode==MODE_WAVES )        waves_read_profile(&width,&height);    gc_select = get_gc( sconf_get_string_or_die(settings,"select_color") );    if (width>0 && height>0)        gtk_window_resize(GTK_WINDOW(main_window),width,height);}void switch_profile(void *ignore,char *custom_settings){    if ( custom_settings )        settings = custom_settings;    read_profile();    default_zoom_restore();    refresh_status |= REFRESH_ALL;}/* On resize we need to reallocate pixmaps. Routines specific to a    display mode are called to determine dimensions of the main pixmap,    scalebars etc.*/void configure_event (GtkWidget *widget, GdkEventConfigure *event){    static int text_width, text_height;    static int first_run=1;    char buf[BUFLEN];    if ( first_run )    {        /* To determine the height of the scalebar, first find out the height             of the text. Run it only once.        */        snprintf(buf,50,"%d",ndata_out);        pango_layout = gtk_widget_create_pango_layout(widget,buf);        pango_layout_get_pixel_size(pango_layout, &text_width,&text_height);        first_run = 0;    }    /* Free existing pixmaps */    if (main_pixmap)    {        g_object_unref(main_pixmap);        main_pixmap = NULL;    }    if (scalebar_pixmap)    {        g_object_unref(scalebar_pixmap);        scalebar_pixmap = NULL;    }    if (cached_scalebar_pixmap)    {        g_object_unref(cached_scalebar_pixmap);        cached_scalebar_pixmap = NULL;    }    if (side_scalebar_pixmap)    {        g_object_unref(side_scalebar_pixmap);        side_scalebar_pixmap = NULL;    }    /* Call routines specific to each display mode */    if ( mode==MODE_FOURIER )    {        scalebar_height      = 2*SB_MARGIN + text_height;        scalebar_width       = widget->allocation.width;        main_width           = widget->allocation.width;        main_height          = widget->allocation.height - scalebar_height;        side_scalebar_width  = 0;        side_scalebar_height = 0;        fourier_gtk_configure();     }    else if ( mode==MODE_SPECTROGRAM )    {        side_scalebar_height = widget->allocation.height;        side_scalebar_width  = 5*SB_MARGIN;        scalebar_height      = 2*SB_MARGIN + text_height;        scalebar_width       = widget->allocation.width - side_scalebar_width;        main_width           = widget->allocation.width - side_scalebar_width;        main_height          = widget->allocation.height - scalebar_height;        spectrogram_gtk_configure(widget);     }    else if ( mode==MODE_WAVES )    {        side_scalebar_height = 0;        side_scalebar_width  = 0;        scalebar_height      = 0;        scalebar_width       = 0;        main_width           = widget->allocation.width;        main_height          = widget->allocation.height;        waves_gtk_configure();     }    /* Allocate the pixmaps and give the display modes pointers.        Currently only the spectrogram mode does need this for clearing        the screen on various events. Other display modes do not need it,        because they refresh the main_pixmap ALWAYS, not just a single line        as spectrogram does.    */    main_pixmap = gdk_pixmap_new(widget->window,main_width,main_height,-1);    spectrogram_set_main_pixmap(main_pixmap);    if ( scalebar_height )    {        scalebar_pixmap = gdk_pixmap_new(widget->window,scalebar_width,scalebar_height,-1);        cached_scalebar_pixmap = gdk_pixmap_new(widget->window,scalebar_width,scalebar_height,-1);    }    if ( side_scalebar_width )        side_scalebar_pixmap = gdk_pixmap_new(widget->window,side_scalebar_width,side_scalebar_height,-1);        if ( mode==MODE_SPECTROGRAM )        spectrogram_clean_screen();            if ( !refresh_handler_id )        refresh_handler_id = g_timeout_add(1000/refresh_rate, refresh_handler, NULL);    refresh_status |= REFRESH_ALL|REFRESH_SIDE_SCALEBAR;}/* The main drawing function - takes care of what is going to be redrawn    and what routines will take care of it.*/void draw(void){    int width, height;    int sb_width,sb_height;    if ( refresh_status==REFRESH_NONE || refresh_status==REFRESH_FFT_STOP) return;    gdk_drawable_get_size(main_pixmap,&width,&height);    /* The side scalebar for spectrogram mode */    if ( mode==MODE_SPECTROGRAM && refresh_status&REFRESH_SIDE_SCALEBAR )        spectrogram_draw_side_scalebar(side_scalebar_pixmap,side_scalebar_width,side_scalebar_height);    if ( mode==MODE_FOURIER || mode==MODE_SPECTROGRAM )    {        gdk_drawable_get_size(scalebar_pixmap,&sb_width,&sb_height);        /* Scalebar needs refresh. */        if ( refresh_status&REFRESH_SCALEBAR )            default_scalebar_draw(cached_scalebar_pixmap,sb_width,sb_height);        /* Update of data and fft is needed. */        if ( refresh_status&REFRESH_FFT_SAMPLE )        {            if ( mode==MODE_FOURIER )                fourier_main_draw(main_pixmap, width,height);            else                spectrogram_main_draw(main_pixmap, width,height);        }        /* The selection rectangle is being drawn.  */        if ( refresh_status&REFRESH_SELECTION )             selection_rectangle_draw(main_pixmap, width,height);        /* The screen needs refresh - when copying pixmaps, it should not matter            what GdkGC is used. */        if ( refresh_status&(REFRESH_FFT_SAMPLE|REFRESH_SELECTION) )            gdk_draw_drawable(darea->window, gc_select, main_pixmap, 0,0,0,0,-1,-1);        /* Motion pointer needs refresh */        if ( refresh_status&(REFRESH_POINTER_SCALEBAR|REFRESH_SCALEBAR) )        {            gdk_draw_drawable(scalebar_pixmap, gc_select, cached_scalebar_pixmap, 0,0,0,0,-1,-1);            default_scalebar_pointer_draw(scalebar_pixmap,sb_width,sb_height,button_current_x);            gdk_draw_drawable(darea->window, gc_select, scalebar_pixmap, 0,0,0,height,-1,-1);        }        if (side_scalebar_pixmap && refresh_status&(REFRESH_SCALEBAR))            gdk_draw_drawable(darea->window, gc_select, side_scalebar_pixmap,0,0,main_width,0,-1,-1);    }    else if ( mode==MODE_WAVES )    {        waves_main_draw(main_pixmap, width,height);        gdk_draw_drawable(darea->window, gc_select, main_pixmap, 0,0,0,0,-1,-1);    }    if ( refresh_status&REFRESH_FFT_STOP )        refresh_status=REFRESH_FFT_STOP;    else        refresh_status=REFRESH_NONE;}/* This routine is called only ones from main() to init GTK stuff. */void init(char *custom_settings){    GSList *l;    GtkWidget *settings_menu, *submenu, *item;    char *str;        fprintf(stderr,"bps=%d esd_rate=%d channels=%d refresh_rate=%d nsamples=%d signed=%d\n",        bps,esd_rate,channels,refresh_rate,ndata_in,signed_data);    MALLOC(data,float,ndata_in);    init_fft(ndata_in);    ndata_out = ndata_in/2+1;    dfreq = esd_rate*0.5/ndata_out;     /* A frequency difference between two consecutive data points */        main_window = create_window1();    darea = lookup_widget(main_window, "drawingarea1");    gtk_signal_connect(GTK_OBJECT(darea),"configure_event",(GtkSignalFunc)configure_event, NULL);    gtk_signal_connect (GTK_OBJECT(darea),"expose_event",(GtkSignalFunc)expose_event, NULL);    gtk_signal_connect (GTK_OBJECT(darea),"button_press_event",(GtkSignalFunc)button_press_event, NULL);    gtk_signal_connect (GTK_OBJECT(darea),"button_release_event",(GtkSignalFunc)button_release_event, NULL);    gtk_signal_connect (GTK_OBJECT(darea),"motion_notify_event",(GtkSignalFunc)motion_notify_event, NULL);    gtk_signal_connect (GTK_OBJECT(main_window),"key_press_event", (GtkSignalFunc) key_press_event, NULL);    gtk_widget_add_events(darea, GDK_BUTTON_PRESS_MASK|GDK_BUTTON_RELEASE_MASK|GDK_POINTER_MOTION_MASK);    gtk_window_set_title(GTK_WINDOW(main_window),"FFT Spectra");    gtk_widget_show (main_window);    if ( !conf_read(config_file) )        exit_nicely("Error: The config file \"%s\" could not be read.\n", config_file);    l = conf_get_gslist("default/profiles");    if (l)    {        settings_menu = lookup_widget(main_window, "settings1");        submenu = gtk_menu_new();        gtk_menu_item_set_submenu(GTK_MENU_ITEM(settings_menu), submenu);        while (l)

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -