2011-09-14 6 views
0

GTKを使用して非常に簡単なバッテリーステータスアイコンを書いています。 GtkStatusIconは、ツールチップの現在のバッテリステータスを表示します。 私は、通常類似したコマンドacpiの出力を解析バッテリー情報を得るために:私のバッテリステータスアイコンがうまく動作しますが、私は自分のコンピュータを中断し、その後、私はそれを再開したとき、私のプログラムがでクラッシュ サスペンドからの再開時のセグメンテーションフォルト

Battery 0: Discharging, 70%, 01:00:00 remaining

セグメンテーション障害。

全体のコードは、(私はそれをコメントしました)これです:

#include <gtk/gtk.h> 
#include <unistd.h> 
#include <string.h> 
#include <stdlib.h> 

#define DEFAULT_ARRAY_SIZE 3 
#define DEFAULT_TIME_UPDATE 5 

const gchar * acpi_command = "acpi"; 

typedef enum batteryState{ 
    CHARGING, 
    DISCHARGING, 
} BatteryState; 

typedef struct batteryTray { 
    GtkStatusIcon * tray_icon; 
    gchar * tooltip; 
    gchar * icon; 
} BatteryTray; 

typedef struct battery { 
    gchar * status; 
    gint percentage; 
    gchar * extra; 
     BatteryTray batteryTray; 
    BatteryState batteryState; 
} Battery; 

static void update_status_battery(Battery * battery); 
static gboolean update_status_tray(Battery * battery); 
static gchar * get_status_icon_name(Battery * battery); 
static void create_tray_icon(Battery * battery); 
static void parse_acpi_output(Battery * battery, gchar * acpi_output); 
static char * get_acpi_output(const gchar * acpi_command); 

static void update_status_battery(Battery * battery) 
{ 
    if(strcmp(battery->status, "Charging") == 0) 
     battery->batteryState = CHARGING; 
    else if(strcmp(battery->status, "Discharging") == 0) 
     battery->batteryState = DISCHARGING; 
} 

static gboolean update_status_tray(Battery * battery) 
{ 
    gchar * icon_name = get_status_icon_name(battery); 
    gchar * acpi_out = get_acpi_output(acpi_command); 

    parse_acpi_output(battery, acpi_out); 
    update_status_battery(battery); 

    battery->batteryTray.tooltip = g_strdup_printf("%s (%d%%) %s", 
     battery->status, 
     battery->percentage, 
     battery->extra); 

    gtk_status_icon_set_tooltip_text(battery->batteryTray.tray_icon, 
     battery->batteryTray.tooltip); 

    gtk_status_icon_set_from_icon_name(battery->batteryTray.tray_icon, 
     icon_name); 

    return TRUE; 
} 

static gchar * get_status_icon_name(Battery * battery) 
{ 

    GString * icon_name = g_string_new("notification-battery"); 

    if (battery->percentage < 20) 
     g_string_append(icon_name, "-low"); 
    else if (battery->percentage < 40) 
     g_string_append(icon_name, "-020"); 
    else if (battery->percentage < 80) 
     g_string_append(icon_name, "-060"); 
    else 
     g_string_append(icon_name, "-100"); 

    if(battery->batteryState == CHARGING) { 
     g_string_append(icon_name, "-plugged"); 
    } 

    return icon_name->str; 
} 

static void create_tray_icon(Battery * battery) 
{ 
     /* create the gtkstatusicon and call the function 
      `update_status_tray` every 5 seconds */ 

    battery->batteryTray.tray_icon = gtk_status_icon_new(); 
    battery->batteryTray.tooltip = "battery"; 
    gtk_status_icon_set_tooltip(battery->batteryTray.tray_icon, 
     battery->batteryTray.tooltip); 
    gtk_status_icon_set_visible(battery->batteryTray.tray_icon, 
     TRUE); 

    update_status_tray(battery); 
    g_timeout_add_seconds(DEFAULT_TIME_UPDATE, (GSourceFunc) update_status_tray, battery); 
} 

static void parse_acpi_output(Battery * battery, gchar * acpi_output) 
{ 
    /* acpi output is like: 
     Battery 0: Discharging, 70%, 01:00:00 remaining 

     In this function I assign "Discharging" to battery->status 
     70 to battery->percentage 
     and "01:00:00 remaining" to battery->extra 

     I use strtok to split the acpi output into tokens delimited by ',' and 
     then, if there's a blank character ' ' in front of a token, i 'remove' it. 
    */ 

    gint i = 0; 
    gchar * t; 
    gchar ** values_array; 

    /* find the position of ':' in the string */ 
    int pos = strchr(acpi_output, ':') - acpi_output; 
    t = strtok(acpi_output + pos + 1, ","); 

    values_array = malloc(DEFAULT_ARRAY_SIZE * sizeof(gchar)); 

    while(t != NULL) { 
     /* 'remove' the blank character */ 
     values_array[i++] = t[0] == ' ' ? t + 1 : t; 
     t = strtok(NULL, ","); 
    } 

    /* remove newline */ 
    if(values_array[2][strlen(values_array[2]) - 1] == '\n') { 
     values_array[2][strlen(values_array[2]) - 1] = '\0'; 
    } 

    battery->status = values_array[0]; 
    battery->percentage = atoi(values_array[1]); 
    battery->extra = values_array[2]; 

    free(values_array); 
} 

static gchar * get_acpi_output(const gchar * acpi_command) 
{ 
    gchar * output; 
    GError * error = NULL; 

    /* assign the output of the acpi command to 'output' */ 
    g_spawn_command_line_sync(acpi_command, &output, NULL, NULL, &error); 
    return output; 
} 

int main(int argc, char ** argv) 
{ 
    Battery battery; 

    gtk_init(&argc, &argv); 
    create_tray_icon(&battery); 
    gtk_main(); 

    return 0; 
} 

私は私は本当に理解できないので、誰かが私を助けることができることを願っています。

+0

これは大量のコードです。少なくとも、自分自身でいくつかの作業を行います。コアダンプを作成し、デバッガでクラッシュ時の動作を確認します。 –

答えて

1

さらに多くのエラーチェックができる場所があります。おそらくあなたのコードの外の何かが起床中に失敗します。たとえば、g_spawn_command_line_syncの結果を確認しないでください。outputが有効な文字列を指していると仮定していますが、必ずしもそうとは限りません。実行するツールの出力には一定の数のトークンが含まれていると想定していますが、実際には確認していないと思いますが、必ずしもそうではありません。

関連する問題