Add another DL CRC error - Duplicate NonZero RV.
[obnox/wireshark/wip.git] / gtk / rtp_analysis.c
index 5bbd869f3dcb208227ea451a7c7d42699443d9e2..49d97440cda931ca1c31a9306b74f7907007fc1a 100644 (file)
@@ -36,6 +36,8 @@
 #ifdef HAVE_CONFIG_H
 #include "config.h"
 #endif
+
+#include <stdio.h>
 #include <math.h>
 #include <string.h>
 #include <locale.h>
 #include <epan/strutil.h>
 
 #include "../util.h"
-#include "../register.h"
 #include "../g711.h"
 #include "../alert_box.h"
 #include "../simple_dialog.h"
 #include "../stat_menu.h"
 #include "../progress_dlg.h"
-#include "../color.h"
 #include "../tempfile.h"
 #include <wsutil/file_util.h>
 
 #include "gtk/file_dlg.h"
 #include "gtk/gui_utils.h"
 #include "gtk/gui_stat_menu.h"
+#include "gtk/pixmap_save.h"
 #include "gtk/main.h"
 #include "gtk/rtp_analysis.h"
 #include "gtk/rtp_stream.h"
 #include "gtk/rtp_stream_dlg.h"
+#include "gtk/stock_icons.h"
+#include "gtk/utf8_entities.h"
+
+#ifdef HAVE_LIBPORTAUDIO
+#include "gtk/graph_analysis.h"
+#include "gtk/voip_calls.h"
+#include "gtk/rtp_player.h"
+#endif /* HAVE_LIBPORTAUDIO */
+
+#include "gtk/old-gtk-compat.h"
 
 enum
 {
-   PACKET_COLUMN,
-   SEQUENCE_COLUMN,
-   DELTA_COLUMN,
-   JITTER_COLUMN,
-   IPBW_COLUMN,
-   MARKER_COLUMN,
-   STATUS_COLUMN,
-   DATE_COLUMN,
-   LENGTH_COLUMN,
-   FOREGROUND_COLOR_COL,
-   BACKGROUND_COLOR_COL,
-   N_COLUMN /* The number of columns */
+       PACKET_COLUMN,
+       SEQUENCE_COLUMN,
+       TIMESTAMP_COLUMN,
+       DELTA_COLUMN,
+       JITTER_COLUMN,
+       SKEW_COLUMN,
+       IPBW_COLUMN,
+       MARKER_COLUMN,
+       STATUS_COLUMN,
+       DATE_COLUMN,
+       LENGTH_COLUMN,
+       FOREGROUND_COLOR_COL,
+       BACKGROUND_COLOR_COL,
+       N_COLUMN /* The number of columns */
 };
 /****************************************************************************/
 
 #define NUM_COLS 9
 #define NUM_GRAPH_ITEMS 100000
 #define MAX_YSCALE 16
+#define AUTO_MAX_YSCALE_INDEX 0
 #define AUTO_MAX_YSCALE 0
-#define MAX_GRAPHS 4
+#define MAX_GRAPHS 6
 #define GRAPH_FWD_JITTER 0
 #define GRAPH_FWD_DIFF 1
-#define GRAPH_REV_JITTER 2
-#define GRAPH_REV_DIFF 3
+#define GRAPH_FWD_DELTA 2
+#define GRAPH_REV_JITTER 3
+#define GRAPH_REV_DIFF 4
+#define GRAPH_REV_DELTA 5
 static guint32 yscale_max[MAX_YSCALE] = {AUTO_MAX_YSCALE, 1000, 2000, 5000, 10000, 20000, 50000, 100000, 200000, 500000, 1000000, 2000000, 5000000, 10000000, 20000000, 50000000};
 
 #define MAX_PIXELS_PER_TICK 4
-#define DEFAULT_PIXELS_PER_TICK 1
+#define DEFAULT_PIXELS_PER_TICK_INDEX 2
 static guint32 pixels_per_tick[MAX_PIXELS_PER_TICK] = {1, 2, 5, 10};
-static const char *graph_descr[4] = {"Fwd Jitter", "Fwd Difference", "Rvr Jitter", "Rvr Difference"};
+static const char *graph_descr[MAX_GRAPHS] = {"Fwd Jitter", "Fwd Difference", "Fwd Delta", "Rvr Jitter", "Rvr Difference", "Rvr Delta"};
 /* unit is in ms */
 #define MAX_TICK_VALUES 5
-#define DEFAULT_TICK_VALUE 1
+#define DEFAULT_TICK_INTERVAL_VALUES_INDEX 1
 static guint tick_interval_values[MAX_TICK_VALUES] = { 1, 10, 100, 1000, 10000 };
 typedef struct _dialog_graph_graph_item_t {
        guint32 value;
@@ -124,33 +140,42 @@ typedef struct _dialog_graph_graph_item_t {
 
 typedef struct _dialog_graph_graph_t {
        struct _user_data_t *ud;
-        dialog_graph_graph_item_t items[NUM_GRAPH_ITEMS];
-        int plot_style;
-        gboolean display;
-        GtkWidget *display_button;
-        int hf_index;
-        GdkColor color;
-        GdkGC *gc;
+       dialog_graph_graph_item_t items[NUM_GRAPH_ITEMS];
+       int plot_style;
+       gboolean display;
+       GtkWidget *display_button;
+       int hf_index;
+#if GTK_CHECK_VERSION(3,0,0)
+       GdkRGBA rgba_color;
+#endif
+       GdkColor color;
        gchar title[100];
 } dialog_graph_graph_t;
 
 
 typedef struct _dialog_graph_t {
        gboolean needs_redraw;
-        gint32 interval;    /* measurement interval in ms */
-        guint32 last_interval;
-        guint32 max_interval; /* XXX max_interval and num_items are redundant */
-        guint32 num_items;
+       gint32 interval_index;  /* index into tick_interval_values_array */
+       gint32 interval;        /* measurement interval in ms */
+       guint32 last_interval;
+       guint32 max_interval;  /* XXX max_interval and num_items are redundant */
+       guint32 num_items;
        struct _dialog_graph_graph_t graph[MAX_GRAPHS];
-        GtkWidget *window;
-        GtkWidget *draw_area;
-        GdkPixmap *pixmap;
-        GtkAdjustment *scrollbar_adjustment;
-        GtkWidget *scrollbar;
-        int pixmap_width;
-        int pixmap_height;
-        int pixels_per_tick;
-        int max_y_units;
+       GtkWidget *window;
+       GtkWidget *draw_area;
+#if GTK_CHECK_VERSION(2,22,0)
+       cairo_surface_t *surface;
+#else
+       GdkPixmap *pixmap;
+#endif
+       GtkAdjustment *scrollbar_adjustment;
+       GtkWidget *scrollbar;
+       int surface_width;
+       int surface_height;
+       int pixels_per_tick_index; /* index into pixels_per_tick array */
+       int pixels_per_tick;
+       int max_y_units_index;     /* index into yscale_max array      */
+       int max_y_units;
        double start_time;
 } dialog_graph_t;
 
@@ -169,10 +194,7 @@ typedef struct _dialog_data_t {
        GtkWidget *save_voice_as_w;
        GtkWidget *save_csv_as_w;
        gint notebook_signal_id;
-    dialog_graph_t dialog_graph;
-#ifdef USE_CONVERSATION_GRAPH
-       GtkWidget *graph_window;
-#endif
+       dialog_graph_t dialog_graph;
 } dialog_data_t;
 
 #define OK_TEXT "[ Ok ]"
@@ -184,6 +206,7 @@ typedef enum {
        TAP_RTP_PADDING_ERROR,
        TAP_RTP_SHORT_FRAME,
        TAP_RTP_FILE_OPEN_ERROR,
+       TAP_RTP_FILE_WRITE_ERROR,
        TAP_RTP_NO_DATA
 } error_type_t;
 
@@ -201,8 +224,6 @@ struct _info_direction {
        tap_rtp_save_info_t saveinfo;
 };
 
-#define TMPNAMSIZE 100
-
 #define SILENCE_PCMU   (guint8)0xFF
 #define SILENCE_PCMA   (guint8)0x55
 
@@ -224,25 +245,23 @@ typedef struct _user_data_t {
        struct _info_direction forward;
        struct _info_direction reversed;
 
-       char f_tempname[TMPNAMSIZE];
-       char r_tempname[TMPNAMSIZE];
+       char *f_tempname;
+       char *r_tempname;
 
        /* dialog associated data */
        dialog_data_t dlg;
 
-#ifdef USE_CONVERSATION_GRAPH
-       time_series_t series_fwd;
-       time_series_t series_rev;
-#endif
 } user_data_t;
 
 
 /* Column titles. */
-static const gchar *titles[9] =  {
+static const gchar *titles[11] =  {
        "Packet",
        "Sequence",
+       "Time stamp",
        "Delta (ms)",
        "Jitter (ms)",
+       "Skew(ms)",
        "IP BW (kbps)",
        "Marker",
        "Status",
@@ -261,12 +280,12 @@ static const gchar *titles[9] =  {
 #define SAVE_RAW_FORMAT        4
 
 
-static void on_refresh_bt_clicked(GtkWidget *bt _U_, user_data_t *user_data _U_);
+static void on_refresh_bt_clicked(GtkWidget *bt _U_, user_data_t *user_data);
 /****************************************************************************/
 static void enable_graph(dialog_graph_graph_t *dgg)
 {
 
-        dgg->display=TRUE;
+       dgg->display=TRUE;
 
 }
 
@@ -289,6 +308,8 @@ rtp_reset(void *user_data_arg)
        user_data->reversed.statinfo.max_delta = 0;
        user_data->forward.statinfo.max_jitter = 0;
        user_data->reversed.statinfo.max_jitter = 0;
+       user_data->forward.statinfo.max_skew = 0;
+       user_data->reversed.statinfo.max_skew = 0;
        user_data->forward.statinfo.mean_jitter = 0;
        user_data->reversed.statinfo.mean_jitter = 0;
        user_data->forward.statinfo.delta = 0;
@@ -297,6 +318,16 @@ rtp_reset(void *user_data_arg)
        user_data->reversed.statinfo.diff = 0;
        user_data->forward.statinfo.jitter = 0;
        user_data->reversed.statinfo.jitter = 0;
+       user_data->forward.statinfo.skew = 0;
+       user_data->reversed.statinfo.skew = 0;
+       user_data->forward.statinfo.sumt = 0;
+       user_data->reversed.statinfo.sumt = 0;
+       user_data->forward.statinfo.sumTS = 0;
+       user_data->reversed.statinfo.sumTS = 0;
+       user_data->forward.statinfo.sumt2 = 0;
+       user_data->reversed.statinfo.sumt2 = 0;
+       user_data->forward.statinfo.sumtTS = 0;
+       user_data->reversed.statinfo.sumtTS = 0;
        user_data->forward.statinfo.bandwidth = 0;
        user_data->reversed.statinfo.bandwidth = 0;
        user_data->forward.statinfo.total_bytes = 0;
@@ -340,17 +371,10 @@ rtp_reset(void *user_data_arg)
        /* reset graph info */
        dialog_graph_reset(user_data);
 
-#ifdef USE_CONVERSATION_GRAPH
-       if (user_data->dlg.graph_window != NULL)
-               window_destroy(user_data->dlg.graph_window);
-
-       g_array_free(user_data->series_fwd.value_pairs, TRUE);
-       user_data->series_fwd.value_pairs = g_array_new(FALSE, FALSE, sizeof(value_pair_t));
-
-       g_array_free(user_data->series_rev.value_pairs, TRUE);
-       user_data->series_rev.value_pairs = g_array_new(FALSE, FALSE, sizeof(value_pair_t));
+#ifdef HAVE_LIBPORTAUDIO
+       /* reset the RTP player */
+       reset_rtp_player();
 #endif
-
        /* XXX check for error at fclose? */
        if (user_data->forward.saveinfo.fp != NULL)
                fclose(user_data->forward.saveinfo.fp);
@@ -366,40 +390,42 @@ rtp_reset(void *user_data_arg)
 }
 
 /****************************************************************************/
-static int rtp_packet_add_graph(dialog_graph_graph_t *dgg, tap_rtp_stat_t *statinfo, packet_info *pinfo, guint32 value)
+static gboolean rtp_packet_add_graph(dialog_graph_graph_t *dgg, tap_rtp_stat_t *statinfo, packet_info *pinfo, guint32 value)
 {
        dialog_graph_graph_item_t *it;
-       int idx;
+       guint32 idx;
        double rtp_time;
 
-       /* we sometimes get called when dgg is disabled.
-       this is a bug since the tap listener should be removed first */
+       /*
+       * We sometimes get called when dgg is disabled.
+       * This is a bug since the tap listener should be removed first
+       */
        if(!dgg->display){
-               return 0;
+               return FALSE;
        }
 
        dgg->ud->dlg.dialog_graph.needs_redraw=TRUE;
 
        /*
-       * Find which interval this is supposed to to in and store the
+       * Find which interval this is supposed to go in and store the
        * interval index as idx
        */
        if (dgg->ud->dlg.dialog_graph.start_time == -1){ /* it is the first */
                dgg->ud->dlg.dialog_graph.start_time = statinfo->start_time;
        }
-       rtp_time = nstime_to_sec(&pinfo->fd->rel_ts) - dgg->ud->dlg.dialog_graph.start_time;
+       rtp_time = nstime_to_msec(&pinfo->fd->rel_ts) - dgg->ud->dlg.dialog_graph.start_time;
        if(rtp_time<0){
                return FALSE;
        }
-       idx = (guint32)(rtp_time*1000)/dgg->ud->dlg.dialog_graph.interval;
+       idx = (guint32)(rtp_time)/dgg->ud->dlg.dialog_graph.interval;
 
        /* some sanity checks */
-       if((idx<0)||(idx>=NUM_GRAPH_ITEMS)){
+       if(idx>=NUM_GRAPH_ITEMS){
                return FALSE;
        }
 
        /* update num_items */
-       if((guint32)idx > dgg->ud->dlg.dialog_graph.num_items){
+       if(idx > dgg->ud->dlg.dialog_graph.num_items){
                dgg->ud->dlg.dialog_graph.num_items=idx;
                dgg->ud->dlg.dialog_graph.max_interval=idx*dgg->ud->dlg.dialog_graph.interval;
        }
@@ -429,18 +455,18 @@ static void rtp_draw(void *prs _U_)
 }
 
 /* forward declarations */
-static void add_to_list(GtkWidget *list, user_data_t * user_data, guint32 number, guint16 seq_num,
-                         double delta, double jitter, double bandwidth, gchar *status, gboolean marker,
-                         gchar *timeStr, guint32 pkt_len,gchar *color_str, guint32 flags);
+static void add_to_list(GtkWidget *list, user_data_t * user_data, guint32 number, guint16 seq_num, guint32 timestamp,
+                       double delta, double jitter, double skew ,double bandwidth, gchar *status, gboolean marker,
+                       gchar *timeStr, guint32 pkt_len,gchar *color_str, guint32 flags);
 
 static int rtp_packet_add_info(GtkWidget *list, user_data_t * user_data,
        tap_rtp_stat_t *statinfo, packet_info *pinfo,
        const struct _rtp_info *rtpinfo);
 
 static int rtp_packet_save_payload(tap_rtp_save_info_t *saveinfo,
-                                   tap_rtp_stat_t *statinfo,
-                                   packet_info *pinfo,
-                                   const struct _rtp_info *rtpinfo);
+                                  tap_rtp_stat_t *statinfo,
+                                  packet_info *pinfo,
+                                  const struct _rtp_info *rtpinfo);
 
 
 /****************************************************************************/
@@ -449,9 +475,8 @@ static int rtp_packet(void *user_data_arg, packet_info *pinfo, epan_dissect_t *e
 {
        user_data_t *user_data = user_data_arg;
        const struct _rtp_info *rtpinfo = rtpinfo_arg;
-#ifdef USE_CONVERSATION_GRAPH
-       value_pair_t vp;
-#endif
+       gboolean rtp_selected = FALSE;
+
        /* we ignore packets that are not displayed */
        if (pinfo->fd->flags.passed_dfilter == 0)
                return 0;
@@ -464,18 +489,21 @@ static int rtp_packet(void *user_data_arg, packet_info *pinfo, epan_dissect_t *e
                && user_data->port_src_fwd == pinfo->srcport
                && CMP_ADDRESS(&(user_data->ip_dst_fwd), &(pinfo->net_dst)) == 0
                && user_data->port_dst_fwd == pinfo->destport)  {
-#ifdef USE_CONVERSATION_GRAPH
-               vp.time = ((double)pinfo->fd->rel_secs + (double)pinfo->fd->rel_usecs/1000000);
-               vp.fnumber = pinfo->fd->num;
-               g_array_append_val(user_data->series_fwd.value_pairs, vp);
-#endif
                rtp_packet_analyse(&(user_data->forward.statinfo), pinfo, rtpinfo);
-               rtp_packet_add_graph(&(user_data->dlg.dialog_graph.graph[GRAPH_FWD_JITTER]), &(user_data->forward.statinfo), pinfo, (guint32)(user_data->forward.statinfo.jitter*1000000));
-               rtp_packet_add_graph(&(user_data->dlg.dialog_graph.graph[GRAPH_FWD_DIFF]), &(user_data->forward.statinfo), pinfo, (guint32)(user_data->forward.statinfo.diff*1000000));
+               rtp_packet_add_graph(&(user_data->dlg.dialog_graph.graph[GRAPH_FWD_JITTER]),
+                       &(user_data->forward.statinfo), pinfo,
+                       (guint32)(user_data->forward.statinfo.jitter*1000));
+               rtp_packet_add_graph(&(user_data->dlg.dialog_graph.graph[GRAPH_FWD_DIFF]),
+                       &(user_data->forward.statinfo), pinfo,
+                       (guint32)(user_data->forward.statinfo.diff*1000));
+               rtp_packet_add_graph(&(user_data->dlg.dialog_graph.graph[GRAPH_FWD_DELTA]),
+                       &(user_data->forward.statinfo), pinfo,
+                       (guint32)(user_data->forward.statinfo.delta*1000));
                rtp_packet_add_info(user_data->dlg.list_fwd, user_data,
                        &(user_data->forward.statinfo), pinfo, rtpinfo);
                rtp_packet_save_payload(&(user_data->forward.saveinfo),
                        &(user_data->forward.statinfo), pinfo, rtpinfo);
+               rtp_selected = TRUE;
        }
        /* is it the reversed direction? */
        else if (user_data->ssrc_rev == rtpinfo->info_sync_src
@@ -483,19 +511,27 @@ static int rtp_packet(void *user_data_arg, packet_info *pinfo, epan_dissect_t *e
                && user_data->port_src_rev == pinfo->srcport
                && CMP_ADDRESS(&(user_data->ip_dst_rev), &(pinfo->net_dst)) == 0
                && user_data->port_dst_rev == pinfo->destport)  {
-#ifdef USE_CONVERSATION_GRAPH
-               vp.time = ((double)pinfo->fd->rel_secs + (double)pinfo->fd->rel_usecs/1000000);
-               vp.fnumber = pinfo->fd->num;
-               g_array_append_val(user_data->series_rev.value_pairs, vp);
-#endif
                rtp_packet_analyse(&(user_data->reversed.statinfo), pinfo, rtpinfo);
-               rtp_packet_add_graph(&(user_data->dlg.dialog_graph.graph[GRAPH_REV_JITTER]), &(user_data->reversed.statinfo), pinfo, (guint32)(user_data->reversed.statinfo.jitter*1000000));
-               rtp_packet_add_graph(&(user_data->dlg.dialog_graph.graph[GRAPH_REV_DIFF]), &(user_data->reversed.statinfo), pinfo, (guint32)(user_data->reversed.statinfo.diff*1000000));
+               rtp_packet_add_graph(&(user_data->dlg.dialog_graph.graph[GRAPH_REV_JITTER]),
+                       &(user_data->reversed.statinfo), pinfo,
+                       (guint32)(user_data->reversed.statinfo.jitter*1000));
+               rtp_packet_add_graph(&(user_data->dlg.dialog_graph.graph[GRAPH_REV_DIFF]),
+                       &(user_data->reversed.statinfo), pinfo,
+                       (guint32)(user_data->reversed.statinfo.diff*1000));
+               rtp_packet_add_graph(&(user_data->dlg.dialog_graph.graph[GRAPH_REV_DELTA]),
+                       &(user_data->reversed.statinfo), pinfo,
+                       (guint32)(user_data->reversed.statinfo.delta*1000));
                rtp_packet_add_info(user_data->dlg.list_rev, user_data,
                        &(user_data->reversed.statinfo), pinfo, rtpinfo);
                rtp_packet_save_payload(&(user_data->reversed.saveinfo),
                        &(user_data->reversed.statinfo), pinfo, rtpinfo);
+               rtp_selected = TRUE;
        }
+       /* add this RTP for future listening using the RTP Player*/
+#ifdef HAVE_LIBPORTAUDIO
+       if (rtp_selected)
+               add_rtp_packet(rtpinfo, pinfo);
+#endif
 
        return 0;
 }
@@ -506,6 +542,7 @@ static const GdkColor COLOR_DEFAULT = {0, 0xffff, 0xffff, 0xffff};
 static const GdkColor COLOR_ERROR = {0, 0xffff, 0xbfff, 0xbfff};
 static const GdkColor COLOR_WARNING = {0, 0xffff, 0xdfff, 0xbfff};
 static const GdkColor COLOR_CN = {0, 0xbfff, 0xbfff, 0xffff};
+COLOR_T_EVENT g_snprintf(color_str,sizeof(color_str),"#ef8c bfff ffff");
 static const GdkColor COLOR_FOREGROUND = {0, 0x0000, 0x0000, 0x0000};
 */
 /****************************************************************************/
@@ -547,11 +584,15 @@ static int rtp_packet_add_info(GtkWidget *list, user_data_t * user_data,
        }
        else if (statinfo->flags & STAT_FLAG_WRONG_SEQ) {
                g_snprintf(status,sizeof(status),"Wrong sequence nr.");
-               /* color = COLOR_ERROR; */ 
+               /* color = COLOR_ERROR; */
                g_snprintf(color_str,sizeof(color_str),"#ffffbfffbfff");
        }
        else if (statinfo->flags & STAT_FLAG_REG_PT_CHANGE) {
-               g_snprintf(status,sizeof(status),"Payload changed to PT=%u", statinfo->pt);
+               if (statinfo->flags & STAT_FLAG_PT_T_EVENT){
+                       g_snprintf(status,sizeof(status),"Payload changed to PT=%u telephone/event", statinfo->pt);
+               }else{
+                       g_snprintf(status,sizeof(status),"Payload changed to PT=%u", statinfo->pt);
+               }
                /* color = COLOR_WARNING; */
                g_snprintf(color_str,sizeof(color_str),"#ffffdfffbfff");
        }
@@ -568,8 +609,12 @@ static int rtp_packet_add_info(GtkWidget *list, user_data_t * user_data,
                g_snprintf(status,sizeof(status),"Marker missing?");
                /* color = COLOR_WARNING; */
                g_snprintf(color_str,sizeof(color_str),"#ffffdfffbfff");
-       }
-       else {
+       }else if (statinfo->flags & STAT_FLAG_PT_T_EVENT){
+               g_snprintf(status,sizeof(status),"PT=%u telephone/event", statinfo->pt);
+               /* XXX add color? */
+               /* color = COLOR_T_EVENT; */
+               g_snprintf(color_str,sizeof(color_str),"#ef8cbfffffff");
+       }else {
                if (statinfo->flags & STAT_FLAG_MARKER) {
                        /* color = COLOR_WARNING; */
                        g_snprintf(color_str,sizeof(color_str),"#ffffdfffbfff");
@@ -580,6 +625,8 @@ static int rtp_packet_add_info(GtkWidget *list, user_data_t * user_data,
        if (statinfo->flags & STAT_FLAG_FIRST) {
                add_to_list(list, user_data,
                        pinfo->fd->num, rtpinfo->info_seq_num,
+                       statinfo->timestamp,
+                       0,
                        0,
                        0,
                        statinfo->bandwidth,
@@ -592,8 +639,10 @@ static int rtp_packet_add_info(GtkWidget *list, user_data_t * user_data,
        else {
                add_to_list(list, user_data,
                        pinfo->fd->num, rtpinfo->info_seq_num,
-                       statinfo->delta*1000,
-                       statinfo->jitter*1000,
+                       statinfo->timestamp,
+                       statinfo->delta,
+                       statinfo->jitter,
+                       statinfo->skew,
                        statinfo->bandwidth,
                        status,
                        rtpinfo->info_marker_set,
@@ -607,9 +656,9 @@ static int rtp_packet_add_info(GtkWidget *list, user_data_t * user_data,
 #define MAX_SILENCE_TICKS 1000000
 /****************************************************************************/
 static int rtp_packet_save_payload(tap_rtp_save_info_t *saveinfo,
-                                   tap_rtp_stat_t *statinfo,
-                                   packet_info *pinfo,
-                                   const struct _rtp_info *rtpinfo)
+                                  tap_rtp_stat_t *statinfo,
+                                  packet_info *pinfo,
+                                  const struct _rtp_info *rtpinfo)
 {
        guint i;
        const guint8 *data;
@@ -671,7 +720,13 @@ static int rtp_packet_save_payload(tap_rtp_save_info_t *saveinfo,
                                tmp = 0;
                                break;
                        }
-                       nchars=fwrite(&tmp, 1, 1, saveinfo->fp);
+                       nchars = fwrite(&tmp, 1, 1, saveinfo->fp);
+                       if (nchars != 1) {
+                               /* Write error or short write */
+                               saveinfo->saved = FALSE;
+                               saveinfo->error_type = TAP_RTP_FILE_WRITE_ERROR;
+                               return 0;
+                       }
                        saveinfo->count++;
                }
                fflush(saveinfo->fp);
@@ -695,7 +750,13 @@ static int rtp_packet_save_payload(tap_rtp_save_info_t *saveinfo,
                * plus the offset of the payload from the beginning
                * of the RTP data */
                data = rtpinfo->info_data + rtpinfo->info_payload_offset;
-               nchars=fwrite(data, sizeof(unsigned char), (rtpinfo->info_payload_len - rtpinfo->info_padding_count), saveinfo->fp);
+               nchars = fwrite(data, sizeof(unsigned char), (rtpinfo->info_payload_len - rtpinfo->info_padding_count), saveinfo->fp);
+               if (nchars != (rtpinfo->info_payload_len - rtpinfo->info_padding_count)) {
+                       /* Write error or short write */
+                       saveinfo->saved = FALSE;
+                       saveinfo->error_type = TAP_RTP_FILE_WRITE_ERROR;
+                       return 0;
+               }
                saveinfo->count+=(rtpinfo->info_payload_len - rtpinfo->info_padding_count);
 
                fflush(saveinfo->fp);
@@ -714,7 +775,7 @@ static int rtp_packet_save_payload(tap_rtp_save_info_t *saveinfo,
 
 /****************************************************************************/
 /* close the dialog window and remove the tap listener */
-static void on_destroy(GtkWidget *win _U_, user_data_t *user_data _U_)
+static void on_destroy(GtkWidget *win _U_, user_data_t *user_data)
 {
        /* remove tap listener */
        protect_thread_critical_region();
@@ -730,32 +791,29 @@ static void on_destroy(GtkWidget *win _U_, user_data_t *user_data _U_)
        ws_remove(user_data->f_tempname);
        ws_remove(user_data->r_tempname);
 
+#if 0  /* XXX: GtkFileChooserDialog/gtk_dialog_run currently being used is effectively modal so this is not req'd */
        /* destroy save_voice_as window if open */
        if (user_data->dlg.save_voice_as_w != NULL)
                window_destroy(user_data->dlg.save_voice_as_w);
-
+#endif
        /* destroy graph window if open */
        if (user_data->dlg.dialog_graph.window != NULL)
                window_destroy(user_data->dlg.dialog_graph.window);
 
-#ifdef USE_CONVERSATION_GRAPH
-       /* destroy graph window if open */
-       if (user_data->dlg.graph_window != NULL)
-               window_destroy(user_data->dlg.graph_window);
-#endif
-
        /* disable the "switch_page" signal in the dlg, otherwise will be called when the windows is destroy and cause an exception using GTK1*/
        g_signal_handler_disconnect(user_data->dlg.notebook, user_data->dlg.notebook_signal_id);
 
+       g_free(user_data->f_tempname);
+       g_free(user_data->r_tempname);
        g_free(user_data);
 }
 
 
 /****************************************************************************/
 static void on_notebook_switch_page(GtkNotebook *notebook _U_,
-                                    GtkNotebookPage *page _U_,
-                                    gint page_num _U_,
-                                    user_data_t *user_data _U_)
+                                   gpointer *page _U_,
+                                   gint page_num _U_,
+                                   user_data_t *user_data _U_)
 {
        user_data->dlg.selected_list =
                (page_num==0) ? user_data->dlg.list_fwd : user_data->dlg.list_rev ;
@@ -765,93 +823,12 @@ static void on_notebook_switch_page(GtkNotebook *notebook _U_,
 
 /****************************************************************************/
 
-static void on_list_select_row(GtkTreeSelection *selection, 
-                                                          user_data_t *user_data _U_/*gpointer data */)
+static void on_list_select_row(GtkTreeSelection *selection,
+                                                          user_data_t *user_data/*gpointer data */)
 {
        user_data->dlg.selected_list_sel = selection;
 }
 
-#ifdef USE_CONVERSATION_GRAPH
-Note this will not work any more as clist is removed.
-/****************************************************************************/
-/* when the graph window gets destroyed */
-static void on_destroy_graph(GtkWidget *win _U_, user_data_t *user_data _U_)
-{
-       /* note that graph window has been destroyed */
-       user_data->dlg.graph_window = NULL;
-}
-
-/****************************************************************************/
-static void graph_selection_callback(value_pair_t vp, user_data_t *user_data)
-{
-       guint row;
-       GtkCList *clist = NULL;
-       if (vp.fnumber != 0) {
-               clist = GTK_CLIST(user_data->dlg.clist_fwd);
-               row = gtk_clist_find_row_from_data(clist,
-                               GUINT_TO_POINTER(vp.fnumber));
-               if (row==-1) {
-                       clist = GTK_CLIST(user_data->dlg.clist_rev);
-                       row = gtk_clist_find_row_from_data(clist,
-                                       GUINT_TO_POINTER(vp.fnumber));
-               }
-               if (row!=-1) {
-                       gtk_notebook_set_current_page(GTK_NOTEBOOK(user_data->dlg.notebook),
-                               (clist == GTK_CLIST(user_data->dlg.clist_fwd)) ? 0 : 1);
-                       gtk_clist_select_row(clist, row, 0);
-                       gtk_clist_moveto(clist, row, 0, 0.5, 0);
-               }
-       }
-}
-
-
-/****************************************************************************/
-static void on_graph_bt_clicked(GtkWidget *bt _U_, user_data_t *user_data _U_)
-{
-       gchar title1[80];
-       gchar title2[80];
-       GList *list = NULL;
-
-       if (user_data->dlg.graph_window != NULL) {
-               /* There's already a graph window; reactivate it. */
-               reactivate_window(user_data->dlg.graph_window);
-               return;
-       }
-       list = g_list_append(list, &(user_data->series_fwd));
-       list = g_list_append(list, &(user_data->series_rev));
-
-       user_data->series_fwd.color.pixel = 0;
-       user_data->series_fwd.color.red = 0x80ff;
-       user_data->series_fwd.color.green = 0xe0ff;
-       user_data->series_fwd.color.blue = 0xffff;
-       user_data->series_fwd.yvalue = 0.5;
-
-       user_data->series_rev.color.pixel = 0;
-       user_data->series_rev.color.red = 0x60ff;
-       user_data->series_rev.color.green = 0xc0ff;
-       user_data->series_rev.color.blue = 0xffff;
-       user_data->series_rev.yvalue = -0.5;
-
-       g_snprintf(title1, 80, "Forward: %s:%u to %s:%u (SSRC=0x%X)",
-               get_addr_name(&(user_data->ip_src_fwd)),
-               user_data->port_src_fwd,
-               get_addr_name(&(user_data->ip_dst_fwd)),
-               user_data->port_dst_fwd,
-               user_data->ssrc_fwd);
-
-       g_snprintf(title2, 80, "Reverse: %s:%u to %s:%u (SSRC=0x%X)",
-               get_addr_name(&(user_data->ip_src_rev)),
-               user_data->port_src_rev,
-               get_addr_name(&(user_data->ip_dst_rev)),
-               user_data->port_dst_rev,
-               user_data->ssrc_rev);
-
-       user_data->dlg.graph_window = show_conversation_graph(list, title1, title2,
-               &graph_selection_callback, user_data);
-       g_signal_connect(user_data->dlg.graph_window, "destroy",
-                       G_CALLBACK(on_destroy_graph), user_data);
-}
-#endif /*USE_CONVERSATION_GRAPH*/
 
 /****************************************************************************/
 static void dialog_graph_set_title(user_data_t* user_data)
@@ -883,13 +860,13 @@ static void dialog_graph_reset(user_data_t* user_data)
 
        user_data->dlg.dialog_graph.needs_redraw=TRUE;
        for(i=0;i<MAX_GRAPHS;i++){
-                for(j=0;j<NUM_GRAPH_ITEMS;j++){
-                        dialog_graph_graph_item_t *dggi;
-                        dggi=&user_data->dlg.dialog_graph.graph[i].items[j];
+               for(j=0;j<NUM_GRAPH_ITEMS;j++){
+                       dialog_graph_graph_item_t *dggi;
+                       dggi=&user_data->dlg.dialog_graph.graph[i].items[j];
                        dggi->value=0;
                        dggi->flags=0;
-                }
-        }
+               }
+       }
        user_data->dlg.dialog_graph.last_interval=0xffffffff;
        user_data->dlg.dialog_graph.max_interval=0;
        user_data->dlg.dialog_graph.num_items=0;
@@ -897,23 +874,27 @@ static void dialog_graph_reset(user_data_t* user_data)
        /* create the color titles near the filter buttons */
        for(i=0;i<MAX_GRAPHS;i++){
                /* it is forward */
-               if (i<2){
-                               g_snprintf(user_data->dlg.dialog_graph.graph[i].title, 100, "%s: %s:%u to %s:%u (SSRC=0x%X)",
-                                       graph_descr[i],
-                       get_addr_name(&(user_data->ip_src_fwd)),
-                       user_data->port_src_fwd,
-                       get_addr_name(&(user_data->ip_dst_fwd)),
-                       user_data->port_dst_fwd,
-                       user_data->ssrc_fwd);
+               if (i<(MAX_GRAPHS/2)){
+                       g_snprintf(user_data->dlg.dialog_graph.graph[i].title,
+                                  sizeof(user_data->dlg.dialog_graph.graph[0].title),
+                                  "%s: %s:%u to %s:%u (SSRC=0x%X)",
+                                  graph_descr[i],
+                                  get_addr_name(&(user_data->ip_src_fwd)),
+                                  user_data->port_src_fwd,
+                                  get_addr_name(&(user_data->ip_dst_fwd)),
+                                  user_data->port_dst_fwd,
+                                  user_data->ssrc_fwd);
                /* it is reverse */
                } else {
-                       g_snprintf(user_data->dlg.dialog_graph.graph[i].title, 100, "%s: %s:%u to %s:%u (SSRC=0x%X)",
-                                       graph_descr[i],
-                       get_addr_name(&(user_data->ip_src_rev)),
-                       user_data->port_src_rev,
-                       get_addr_name(&(user_data->ip_dst_rev)),
-                       user_data->port_dst_rev,
-                       user_data->ssrc_rev);
+                       g_snprintf(user_data->dlg.dialog_graph.graph[i].title,
+                                  sizeof(user_data->dlg.dialog_graph.graph[0].title),
+                                  "%s: %s:%u to %s:%u (SSRC=0x%X)",
+                                  graph_descr[i],
+                                  get_addr_name(&(user_data->ip_src_rev)),
+                                  user_data->port_src_rev,
+                                  get_addr_name(&(user_data->ip_dst_rev)),
+                                  user_data->port_dst_rev,
+                                  user_data->ssrc_rev);
                }
        }
 
@@ -923,9 +904,9 @@ static void dialog_graph_reset(user_data_t* user_data)
 /****************************************************************************/
 static guint32 get_it_value(dialog_graph_graph_t *dgg, int idx)
 {
-        dialog_graph_graph_item_t *it;
+       dialog_graph_graph_item_t *it;
 
-        it=&dgg->items[idx];
+       it=&dgg->items[idx];
 
        return it->value;
 }
@@ -933,342 +914,431 @@ static guint32 get_it_value(dialog_graph_graph_t *dgg, int idx)
 /****************************************************************************/
 static void print_time_scale_string(char *buf, int buf_len, guint32 t)
 {
-        if(t>=10000000){
-                g_snprintf(buf, buf_len, "%ds",t/1000000);
-        } else if(t>=1000000){
-                g_snprintf(buf, buf_len, "%d.%03ds",t/1000000,(t%1000000)/1000);
-        } else if(t>=10000){
-                g_snprintf(buf, buf_len, "%dms",t/1000);
-        } else if(t>=1000){
-                g_snprintf(buf, buf_len, "%d.%03dms",t/1000,t%1000);
-        } else {
-                g_snprintf(buf, buf_len, "%dus",t);
-        }
+       if(t>=10000000){
+               g_snprintf(buf, buf_len, "%ds",t/1000000);
+       } else if(t>=1000000){
+               g_snprintf(buf, buf_len, "%d.%03ds",t/1000000,(t%1000000)/1000);
+       } else if(t>=10000){
+               g_snprintf(buf, buf_len, "%dms",t/1000);
+       } else if(t>=1000){
+               g_snprintf(buf, buf_len, "%d.%03dms",t/1000,t%1000);
+       } else {
+               g_snprintf(buf, buf_len, "%dus",t);
+       }
 }
 
 /****************************************************************************/
 static void dialog_graph_draw(user_data_t* user_data)
 {
-        int i, lwidth;
-        guint32 last_interval, first_interval, interval_delta, delta_multiplier;
-        gint32 current_interval;
-        guint32 left_x_border;
-        guint32 right_x_border;
-        guint32 top_y_border;
-        guint32 bottom_y_border;
-        PangoLayout  *layout;
-        int label_width, label_height;
-        guint32 draw_width, draw_height;
-        char label_string[15];
-
-        /* new variables */
-        guint32 num_time_intervals;
-        guint32 max_value;              /* max value of seen data */
-        guint32 max_y;                  /* max value of the Y scale */
-
-        if(!user_data->dlg.dialog_graph.needs_redraw){
-                return;
-        }
-        user_data->dlg.dialog_graph.needs_redraw=FALSE;
-
-        /*
-         * Find the length of the intervals we have data for
-         * so we know how large arrays we need to malloc()
-         */
-        num_time_intervals=user_data->dlg.dialog_graph.num_items;
-        /* if there isnt anything to do, just return */
-        if(num_time_intervals==0){
-                return;
-        }
-        num_time_intervals+=1;
-        /* XXX move this check to _packet() */
-        if(num_time_intervals>NUM_GRAPH_ITEMS){
-                simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, "RTP Graph error. There are too many entries, bailing out");
-                return;
-        }
-
-        /*
-         * find the max value so we can autoscale the y axis
-         */
-        max_value=0;
-        for(i=0;i<MAX_GRAPHS;i++){
-                int idx;
-
-                if(!user_data->dlg.dialog_graph.graph[i].display){
-                        continue;
-                }
-                for(idx=0;(guint32) (idx) < num_time_intervals;idx++){
-                        guint32 val;
-
-                        val=get_it_value(&user_data->dlg.dialog_graph.graph[i], idx);
-
-                        /* keep track of the max value we have encountered */
-                        if(val>max_value){
-                                max_value=val;
-                        }
-                }
-        }
-
-        /*
-         * Clear out old plot
-         */
-        gdk_draw_rectangle(user_data->dlg.dialog_graph.pixmap,
-                           user_data->dlg.dialog_graph.draw_area->style->white_gc,
-                           TRUE,
-                           0, 0,
-                           user_data->dlg.dialog_graph.draw_area->allocation.width,
-                           user_data->dlg.dialog_graph.draw_area->allocation.height);
-
-
-        /*
-         * Calculate the y scale we should use
-         */
-        if(user_data->dlg.dialog_graph.max_y_units==AUTO_MAX_YSCALE){
-                max_y=yscale_max[MAX_YSCALE-1];
-                for(i=MAX_YSCALE-1;i>0;i--){
-                        if(max_value<yscale_max[i]){
-                                max_y=yscale_max[i];
-                        }
-                }
-        } else {
-                /* the user had specified an explicit y scale to use */
-                max_y=user_data->dlg.dialog_graph.max_y_units;
-        }
-
-        /*
-         * Calculate size of borders surrounding the plot
-         * The border on the right side needs to be adjusted depending
-         * on the width of the text labels. For simplicity we assume that the
-         * top y scale label will be the widest one
-         */
-         print_time_scale_string(label_string, 15, max_y);
-        layout = gtk_widget_create_pango_layout(user_data->dlg.dialog_graph.draw_area, label_string);
-        pango_layout_get_pixel_size(layout, &label_width, &label_height);
-        left_x_border=10;
-        right_x_border=label_width+20;
-        top_y_border=10;
-        bottom_y_border=label_height+20;
-
-
-        /*
-         * Calculate the size of the drawing area for the actual plot
-         */
-        draw_width=user_data->dlg.dialog_graph.pixmap_width-right_x_border-left_x_border;
-        draw_height=user_data->dlg.dialog_graph.pixmap_height-top_y_border-bottom_y_border;
-
-
-        /*
-         * Draw the y axis and labels
-         * (we always draw the y scale with 11 ticks along the axis)
-         */
-        gdk_draw_line(user_data->dlg.dialog_graph.pixmap, user_data->dlg.dialog_graph.draw_area->style->black_gc,
-                user_data->dlg.dialog_graph.pixmap_width-right_x_border+1,
-                top_y_border,
-                user_data->dlg.dialog_graph.pixmap_width-right_x_border+1,
-                user_data->dlg.dialog_graph.pixmap_height-bottom_y_border);
-        for(i=0;i<=10;i++){
-                int xwidth, lwidth;
-
-                xwidth=5;
-                if(!(i%5)){
-                        /* first, middle and last tick are slightly longer */
-                        xwidth=10;
-                }
-                /* draw the tick */
-                gdk_draw_line(user_data->dlg.dialog_graph.pixmap, user_data->dlg.dialog_graph.draw_area->style->black_gc,
-                        user_data->dlg.dialog_graph.pixmap_width-right_x_border+1,
-                        user_data->dlg.dialog_graph.pixmap_height-bottom_y_border-draw_height*i/10,
-                        user_data->dlg.dialog_graph.pixmap_width-right_x_border+1+xwidth,
-                        user_data->dlg.dialog_graph.pixmap_height-bottom_y_border-draw_height*i/10);
-                /* draw the labels */
-                if(i==0){
-                        print_time_scale_string(label_string, 15, (max_y*i/10));
-                        pango_layout_set_text(layout, label_string, -1);
-                        pango_layout_get_pixel_size(layout, &lwidth, NULL);
-                        gdk_draw_layout(user_data->dlg.dialog_graph.pixmap,
-                                        user_data->dlg.dialog_graph.draw_area->style->black_gc,
-                                        user_data->dlg.dialog_graph.pixmap_width-right_x_border+15+label_width-lwidth,
-                                        user_data->dlg.dialog_graph.pixmap_height-bottom_y_border-draw_height*i/10-label_height/2,
-                                        layout);
-                }
-                if(i==5){
-                        print_time_scale_string(label_string, 15, (max_y*i/10));
-                        pango_layout_set_text(layout, label_string, -1);
-                        pango_layout_get_pixel_size(layout, &lwidth, NULL);
-                        gdk_draw_layout(user_data->dlg.dialog_graph.pixmap,
-                                        user_data->dlg.dialog_graph.draw_area->style->black_gc,
-                                        user_data->dlg.dialog_graph.pixmap_width-right_x_border+15+label_width-lwidth,
-                                        user_data->dlg.dialog_graph.pixmap_height-bottom_y_border-draw_height*i/10-label_height/2,
-                                        layout);
-                }
-                if(i==10){
-                        print_time_scale_string(label_string, 15, (max_y*i/10));
-                        pango_layout_set_text(layout, label_string, -1);
-                        pango_layout_get_pixel_size(layout, &lwidth, NULL);
-                        gdk_draw_layout(user_data->dlg.dialog_graph.pixmap,
-                                        user_data->dlg.dialog_graph.draw_area->style->black_gc,
-                                        user_data->dlg.dialog_graph.pixmap_width-right_x_border+15+label_width-lwidth,
-                                        user_data->dlg.dialog_graph.pixmap_height-bottom_y_border-draw_height*i/10-label_height/2,
-                                        layout);
-                }
-        }
-
-
-
-        /*
-         * if we have not specified the last_interval via the gui,
-         * then just pick the current end of the capture so that is scrolls
-         * nicely when doing live captures
-         */
-        if(user_data->dlg.dialog_graph.last_interval==0xffffffff){
-                last_interval=user_data->dlg.dialog_graph.max_interval;
-        } else {
-                last_interval=user_data->dlg.dialog_graph.last_interval;
-        }
+       int i, lwidth;
+       guint32 last_interval, first_interval, interval_delta, delta_multiplier;
+       gint32 current_interval;
+       guint32 left_x_border;
+       guint32 right_x_border;
+       guint32 top_y_border;
+       guint32 bottom_y_border;
+       PangoLayout  *layout;
+       int label_width, label_height;
+       int label_width_mid, label_height_mid;
+       guint32 draw_width, draw_height;
+       char label_string[15];
+       GtkAllocation widget_alloc;
+       cairo_t *cr;
+
+       /* new variables */
+       guint32 num_time_intervals;
+       guint32 max_value;              /* max value of seen data */
+       guint32 max_y;                  /* max value of the Y scale */
+
+       if(!user_data->dlg.dialog_graph.needs_redraw){
+               return;
+       }
+       user_data->dlg.dialog_graph.needs_redraw=FALSE;
+
+       /*
+        * Find the length of the intervals we have data for
+        * so we know how large arrays we need to malloc()
+        */
+       num_time_intervals=user_data->dlg.dialog_graph.num_items;
+       /* if there isnt anything to do, just return */
+       if(num_time_intervals==0){
+               return;
+       }
+       num_time_intervals+=1;
+       /* XXX move this check to _packet() */
+       if(num_time_intervals>NUM_GRAPH_ITEMS){
+               simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, "RTP Graph error. There are too many entries, bailing out");
+               return;
+       }
+
+       /*
+        * find the max value so we can autoscale the y axis
+        */
+       max_value=0;
+       for(i=0;i<MAX_GRAPHS;i++){
+               int idx;
+
+               if(!user_data->dlg.dialog_graph.graph[i].display){
+                       continue;
+               }
+               for(idx=0;(guint32) (idx) < num_time_intervals;idx++){
+                       guint32 val;
+
+                       val=get_it_value(&user_data->dlg.dialog_graph.graph[i], idx);
+
+                       /* keep track of the max value we have encountered */
+                       if(val>max_value){
+                               max_value=val;
+                       }
+               }
+       }
+
+       /*
+        * Clear out old plot
+        */
+#if GTK_CHECK_VERSION(2,22,0)
+       cr = cairo_create (user_data->dlg.dialog_graph.surface);
+#else
+       cr = gdk_cairo_create (user_data->dlg.dialog_graph.pixmap);
+#endif
+       cairo_set_source_rgb (cr, 1, 1, 1);
+       gtk_widget_get_allocation(user_data->dlg.dialog_graph.draw_area, &widget_alloc);
+       cairo_rectangle (cr,
+               0,
+               0,
+               widget_alloc.width,
+               widget_alloc.height);
+       cairo_fill (cr);
+       cairo_destroy (cr);
+
+       /*
+        * Calculate the y scale we should use
+        */
+       if(user_data->dlg.dialog_graph.max_y_units==AUTO_MAX_YSCALE){
+               max_y=yscale_max[MAX_YSCALE-1];
+               for(i=MAX_YSCALE-1;i>0;i--){
+                       if(max_value<yscale_max[i]){
+                               max_y=yscale_max[i];
+                       }
+               }
+       } else {
+               /* the user had specified an explicit y scale to use */
+               max_y=user_data->dlg.dialog_graph.max_y_units;
+       }
+
+       /*
+        * Calculate size of borders surrounding the plot
+        * The border on the right side needs to be adjusted depending
+        * on the width of the text labels.
+        */
+       print_time_scale_string(label_string, sizeof(label_string), max_y);
+       layout = gtk_widget_create_pango_layout(user_data->dlg.dialog_graph.draw_area, label_string);
+       pango_layout_get_pixel_size(layout, &label_width, &label_height);
+       print_time_scale_string(label_string, sizeof(label_string), max_y*5/10);
+       layout = gtk_widget_create_pango_layout(user_data->dlg.dialog_graph.draw_area, label_string);
+       pango_layout_get_pixel_size(layout, &label_width_mid, &label_height_mid);
+       if (label_width_mid > label_width) {
+               label_width = label_width_mid;
+               label_height = label_height_mid;
+       }
+
+       left_x_border=10;
+       right_x_border=label_width+20;
+       top_y_border=10;
+       bottom_y_border=label_height+20;
+
+
+       /*
+        * Calculate the size of the drawing area for the actual plot
+        */
+       draw_width=user_data->dlg.dialog_graph.surface_width-right_x_border-left_x_border;
+       draw_height=user_data->dlg.dialog_graph.surface_height-top_y_border-bottom_y_border;
+
+
+       /*
+        * Draw the y axis and labels
+        * (we always draw the y scale with 11 ticks along the axis)
+        */
+#if GTK_CHECK_VERSION(2,22,0)
+       cr = cairo_create (user_data->dlg.dialog_graph.surface);
+#else
+       cr = gdk_cairo_create (user_data->dlg.dialog_graph.pixmap);
+#endif
+       cairo_set_line_width (cr, 1.0);
+       cairo_move_to(cr, user_data->dlg.dialog_graph.surface_width-right_x_border+1.5, top_y_border+0.5);
+       cairo_line_to(cr, user_data->dlg.dialog_graph.surface_width-right_x_border+1.5, user_data->dlg.dialog_graph.surface_height-bottom_y_border+0.5);
+       cairo_stroke(cr);
+       cairo_destroy(cr);
+
+       for(i=0;i<=10;i++){
+               int xwidth;
+
+               xwidth=5;
+               if(!(i%5)){
+                       /* first, middle and last tick are slightly longer */
+                       xwidth=10;
+               }
+               /* draw the tick */
+#if GTK_CHECK_VERSION(2,22,0)
+               cr = cairo_create (user_data->dlg.dialog_graph.surface);
+#else
+               cr = gdk_cairo_create (user_data->dlg.dialog_graph.pixmap);
+#endif
+               cairo_set_line_width (cr, 1.0);
+               cairo_move_to(cr,
+                       user_data->dlg.dialog_graph.surface_width-right_x_border+1.5,
+                       user_data->dlg.dialog_graph.surface_height-bottom_y_border-draw_height*i/10+0.5);
+               
+               cairo_line_to(cr,
+                       user_data->dlg.dialog_graph.surface_width-right_x_border+1.5+xwidth,
+                       user_data->dlg.dialog_graph.surface_height-bottom_y_border-draw_height*i/10+0.5);
+               cairo_stroke(cr);
+               cairo_destroy(cr);
+               /* draw the labels */
+               if(i==0){
+                       print_time_scale_string(label_string, sizeof(label_string), (max_y*i/10));
+                       pango_layout_set_text(layout, label_string, -1);
+                       pango_layout_get_pixel_size(layout, &lwidth, NULL);
+#if GTK_CHECK_VERSION(2,22,0)
+                       cr = cairo_create (user_data->dlg.dialog_graph.surface);
+#else
+                       cr = gdk_cairo_create (user_data->dlg.dialog_graph.pixmap);
+#endif
+                       cairo_move_to (cr,
+                               user_data->dlg.dialog_graph.surface_width-right_x_border+15+label_width-lwidth,
+                               user_data->dlg.dialog_graph.surface_height-bottom_y_border-draw_height*i/10-label_height/2);
+                       pango_cairo_show_layout (cr, layout);
+                       cairo_destroy (cr);
+                       cr = NULL;
+               }
+               if(i==5){
+                       print_time_scale_string(label_string, sizeof(label_string), (max_y*i/10));
+                       pango_layout_set_text(layout, label_string, -1);
+                       pango_layout_get_pixel_size(layout, &lwidth, NULL);
+#if GTK_CHECK_VERSION(2,22,0)
+                       cr = cairo_create (user_data->dlg.dialog_graph.surface);
+#else
+                       cr = gdk_cairo_create (user_data->dlg.dialog_graph.pixmap);
+#endif
+                       cairo_move_to (cr,
+                               user_data->dlg.dialog_graph.surface_width-right_x_border+15+label_width-lwidth,
+                               user_data->dlg.dialog_graph.surface_height-bottom_y_border-draw_height*i/10-label_height/2);
+                       pango_cairo_show_layout (cr, layout);
+                       cairo_destroy (cr);
+                       cr = NULL;
+               }
+               if(i==10){
+                       print_time_scale_string(label_string, sizeof(label_string), (max_y*i/10));
+                       pango_layout_set_text(layout, label_string, -1);
+                       pango_layout_get_pixel_size(layout, &lwidth, NULL);
+#if GTK_CHECK_VERSION(2,22,0)
+                       cr = cairo_create (user_data->dlg.dialog_graph.surface);
+#else
+                       cr = gdk_cairo_create (user_data->dlg.dialog_graph.pixmap);
+#endif
+                       cairo_move_to (cr,
+                               user_data->dlg.dialog_graph.surface_width-right_x_border+15+label_width-lwidth,
+                               user_data->dlg.dialog_graph.surface_height-bottom_y_border-draw_height*i/10-label_height/2);
+                       pango_cairo_show_layout (cr, layout);
+                       cairo_destroy (cr);
+                       cr = NULL;
+               }
+       }
+
+
+
+       /*
+        * if we have not specified the last_interval via the gui,
+        * then just pick the current end of the capture so that is scrolls
+        * nicely when doing live captures
+        */
+       if(user_data->dlg.dialog_graph.last_interval==0xffffffff){
+               last_interval=user_data->dlg.dialog_graph.max_interval;
+       } else {
+               last_interval=user_data->dlg.dialog_graph.last_interval;
+       }
 
 
 
 
 /*XXX*/
-        /* plot the x-scale */
-        gdk_draw_line(user_data->dlg.dialog_graph.pixmap, user_data->dlg.dialog_graph.draw_area->style->black_gc, left_x_border, user_data->dlg.dialog_graph.pixmap_height-bottom_y_border+1, user_data->dlg.dialog_graph.pixmap_width-right_x_border+1, user_data->dlg.dialog_graph.pixmap_height-bottom_y_border+1);
-
-        if((last_interval/user_data->dlg.dialog_graph.interval)>draw_width/user_data->dlg.dialog_graph.pixels_per_tick+1){
-                first_interval=(last_interval/user_data->dlg.dialog_graph.interval)-draw_width/user_data->dlg.dialog_graph.pixels_per_tick+1;
-                first_interval*=user_data->dlg.dialog_graph.interval;
-        } else {
-                first_interval=0;
-        }
-
-        interval_delta=1;
-        delta_multiplier=5;
-        while(interval_delta<((last_interval-first_interval)/10)){
-                interval_delta*=delta_multiplier;
-                if(delta_multiplier==5){
-                        delta_multiplier=2;
-                } else {
-                        delta_multiplier=5;
-                }
-        }
-
-        for(current_interval=last_interval;current_interval>(gint32)first_interval;current_interval=current_interval-user_data->dlg.dialog_graph.interval){
-                int x, xlen;
-
-                /* if pixels_per_tick is <5, only draw every 10 ticks */
-                if((user_data->dlg.dialog_graph.pixels_per_tick<10) && (current_interval%(10*user_data->dlg.dialog_graph.interval))){
-                        continue;
-                }
-
-                if(current_interval%interval_delta){
-                        xlen=5;
-                } else {
-                        xlen=17;
-                }
-
-                x=draw_width+left_x_border-((last_interval-current_interval)/user_data->dlg.dialog_graph.interval)*user_data->dlg.dialog_graph.pixels_per_tick;
-                gdk_draw_line(user_data->dlg.dialog_graph.pixmap, user_data->dlg.dialog_graph.draw_area->style->black_gc,
-                        x-1-user_data->dlg.dialog_graph.pixels_per_tick/2,
-                        user_data->dlg.dialog_graph.pixmap_height-bottom_y_border+1,
-                        x-1-user_data->dlg.dialog_graph.pixels_per_tick/2,
-                        user_data->dlg.dialog_graph.pixmap_height-bottom_y_border+xlen+1);
-
-                if(xlen==17){
-                        int lwidth;
-                        if(user_data->dlg.dialog_graph.interval>=1000){
-                                g_snprintf(label_string, 15, "%ds", current_interval/1000);
-                        } else if(user_data->dlg.dialog_graph.interval>=100){
-                                g_snprintf(label_string, 15, "%d.%1ds", current_interval/1000,(current_interval/100)%10);
-                        } else if(user_data->dlg.dialog_graph.interval>=10){
-                                g_snprintf(label_string, 15, "%d.%2ds", current_interval/1000,(current_interval/10)%100);
-                        } else {
-                                g_snprintf(label_string, 15, "%d.%3ds", current_interval/1000,current_interval%1000);
-                        }
-                        pango_layout_set_text(layout, label_string, -1);
-                        pango_layout_get_pixel_size(layout, &lwidth, NULL);
-                        gdk_draw_layout(user_data->dlg.dialog_graph.pixmap,
-                                        user_data->dlg.dialog_graph.draw_area->style->black_gc,
-                                        x-1-user_data->dlg.dialog_graph.pixels_per_tick/2-lwidth/2,
-                                        user_data->dlg.dialog_graph.pixmap_height-bottom_y_border+20,
-                                        layout);
-                }
-
-        }
-
-
-
-
-
-
-        /*
-         * Draw "x" for Sequence Errors and "m" for Marks
-         */
+       /* plot the x-scale */
+#if GTK_CHECK_VERSION(2,22,0)
+       cr = cairo_create (user_data->dlg.dialog_graph.surface);
+#else
+       cr = gdk_cairo_create (user_data->dlg.dialog_graph.pixmap);
+#endif
+       cairo_set_line_width (cr, 1.0);
+       cairo_move_to(cr, left_x_border+0.5, user_data->dlg.dialog_graph.surface_height-bottom_y_border+1.5);
+       cairo_line_to(cr, user_data->dlg.dialog_graph.surface_width-right_x_border+1.5,user_data->dlg.dialog_graph.surface_height-bottom_y_border+1.5);
+       cairo_stroke(cr);
+       cairo_destroy(cr);
+
+       if((last_interval/user_data->dlg.dialog_graph.interval)>draw_width/user_data->dlg.dialog_graph.pixels_per_tick+1){
+               first_interval=(last_interval/user_data->dlg.dialog_graph.interval)-draw_width/user_data->dlg.dialog_graph.pixels_per_tick+1;
+               first_interval*=user_data->dlg.dialog_graph.interval;
+       } else {
+               first_interval=0;
+       }
+
+       interval_delta=1;
+       delta_multiplier=5;
+       while(interval_delta<((last_interval-first_interval)/10)){
+               interval_delta*=delta_multiplier;
+               if(delta_multiplier==5){
+                       delta_multiplier=2;
+               } else {
+                       delta_multiplier=5;
+               }
+       }
+
+       for(current_interval=last_interval;current_interval>(gint32)first_interval;current_interval=current_interval-user_data->dlg.dialog_graph.interval){
+               int x, xlen;
+
+               /* if pixels_per_tick is <5, only draw every 10 ticks */
+               if((user_data->dlg.dialog_graph.pixels_per_tick<10) && (current_interval%(10*user_data->dlg.dialog_graph.interval))){
+                       continue;
+               }
+
+               if(current_interval%interval_delta){
+                       xlen=5;
+               } else {
+                       xlen=17;
+               }
+
+               x=draw_width+left_x_border-((last_interval-current_interval)/user_data->dlg.dialog_graph.interval)*user_data->dlg.dialog_graph.pixels_per_tick;
+#if GTK_CHECK_VERSION(2,22,0)
+               cr = cairo_create (user_data->dlg.dialog_graph.surface);
+#else
+               cr = gdk_cairo_create (user_data->dlg.dialog_graph.pixmap);
+#endif
+               cairo_set_line_width (cr, 1.0);
+               cairo_move_to(cr, x-1-user_data->dlg.dialog_graph.pixels_per_tick/2+0.5, user_data->dlg.dialog_graph.surface_height-bottom_y_border+1.5);
+               cairo_line_to(cr, x-1-user_data->dlg.dialog_graph.pixels_per_tick/2+0.5, user_data->dlg.dialog_graph.surface_height-bottom_y_border+xlen+1.5);
+               cairo_stroke(cr);
+               cairo_destroy(cr);
+
+               if(xlen==17){
+                       if(user_data->dlg.dialog_graph.interval>=1000){
+                               g_snprintf(label_string, sizeof(label_string), "%ds", current_interval/1000);
+                       } else if(user_data->dlg.dialog_graph.interval>=100){
+                               g_snprintf(label_string, sizeof(label_string), "%d.%1ds", current_interval/1000,(current_interval/100)%10);
+                       } else if(user_data->dlg.dialog_graph.interval>=10){
+                               g_snprintf(label_string, sizeof(label_string), "%d.%2ds", current_interval/1000,(current_interval/10)%100);
+                       } else {
+                               g_snprintf(label_string, sizeof(label_string), "%d.%3ds", current_interval/1000,current_interval%1000);
+                       }
+                       pango_layout_set_text(layout, label_string, -1);
+                       pango_layout_get_pixel_size(layout, &lwidth, NULL);
+#if GTK_CHECK_VERSION(2,22,0)
+                       cr = cairo_create (user_data->dlg.dialog_graph.surface);
+#else
+                       cr = gdk_cairo_create (user_data->dlg.dialog_graph.pixmap);
+#endif
+                       cairo_move_to (cr,
+                               x-1-user_data->dlg.dialog_graph.pixels_per_tick/2-lwidth/2,
+                               user_data->dlg.dialog_graph.surface_height-bottom_y_border+20);
+                       pango_cairo_show_layout (cr, layout);
+                       cairo_destroy (cr);
+                       cr = NULL;
+               }
+
+       }
+
+
+
+
+
+
+       /*
+        * Draw "x" for Sequence Errors and "m" for Marks
+        */
        /* Draw the labels Fwd and Rev */
-       g_strlcpy(label_string,"<-Fwd",15);
+       g_strlcpy(label_string, UTF8_LEFTWARDS_ARROW "Fwd",sizeof(label_string));
+       pango_layout_set_text(layout, label_string, -1);
+       pango_layout_get_pixel_size(layout, &lwidth, NULL);
+#if GTK_CHECK_VERSION(2,22,0)
+       cr = cairo_create (user_data->dlg.dialog_graph.surface);
+#else
+       cr = gdk_cairo_create (user_data->dlg.dialog_graph.pixmap);
+#endif
+       cairo_move_to (cr,
+               user_data->dlg.dialog_graph.surface_width-right_x_border+33-lwidth,
+               user_data->dlg.dialog_graph.surface_height-bottom_y_border+3);
+       pango_cairo_show_layout (cr, layout);
+       cairo_destroy (cr);
+       cr = NULL;
+
+       g_strlcpy(label_string, UTF8_LEFTWARDS_ARROW "Rev",sizeof(label_string));
        pango_layout_set_text(layout, label_string, -1);
        pango_layout_get_pixel_size(layout, &lwidth, NULL);
-       gdk_draw_layout(user_data->dlg.dialog_graph.pixmap,
-               user_data->dlg.dialog_graph.draw_area->style->black_gc,
-               user_data->dlg.dialog_graph.pixmap_width-right_x_border+33-lwidth,
-               user_data->dlg.dialog_graph.pixmap_height-bottom_y_border+3,
-               layout);
-        g_strlcpy(label_string,"<-Rev",15);
-        pango_layout_set_text(layout, label_string, -1);
-        pango_layout_get_pixel_size(layout, &lwidth, NULL);
-        gdk_draw_layout(user_data->dlg.dialog_graph.pixmap,
-                user_data->dlg.dialog_graph.draw_area->style->black_gc,
-                user_data->dlg.dialog_graph.pixmap_width-right_x_border+33-lwidth,
-                user_data->dlg.dialog_graph.pixmap_height-bottom_y_border+3+9,
-                layout);
+#if GTK_CHECK_VERSION(2,22,0)
+       cr = cairo_create (user_data->dlg.dialog_graph.surface);
+#else
+       cr = gdk_cairo_create (user_data->dlg.dialog_graph.pixmap);
+#endif
+       cairo_move_to (cr,
+               user_data->dlg.dialog_graph.surface_width-right_x_border+33-lwidth,
+               user_data->dlg.dialog_graph.surface_height-bottom_y_border+3+9);
+       pango_cairo_show_layout (cr, layout);
+       cairo_destroy (cr);
+       cr = NULL;
 
        /* Draw the marks */
        for(i=MAX_GRAPHS-1;i>=0;i--){
                guint32 interval;
-               guint32 x_pos, prev_x_pos;
+               guint32 x_pos/*, prev_x_pos*/;
 
                /* XXX for fwd or rev, the flag info for jitter and diff is the same, and here I loop twice */
                if (!user_data->dlg.dialog_graph.graph[i].display){
                        continue;
                }
                /* initialize prev x/y to the low left corner of the graph */
-               prev_x_pos=draw_width-1-user_data->dlg.dialog_graph.pixels_per_tick*((last_interval-first_interval)/user_data->dlg.dialog_graph.interval+1)+left_x_border;
+               /*prev_x_pos=draw_width-1-user_data->dlg.dialog_graph.pixels_per_tick*((last_interval-first_interval)/user_data->dlg.dialog_graph.interval+1)+left_x_border;*/
 
                for(interval=first_interval+user_data->dlg.dialog_graph.interval;interval<=last_interval;interval+=user_data->dlg.dialog_graph.interval){
                        x_pos=draw_width-1-user_data->dlg.dialog_graph.pixels_per_tick*((last_interval-interval)/user_data->dlg.dialog_graph.interval+1)+left_x_border;
 
                        if(user_data->dlg.dialog_graph.graph[i].items[interval/user_data->dlg.dialog_graph.interval].flags & (STAT_FLAG_WRONG_SEQ|STAT_FLAG_MARKER)){
-                               int lwidth;
                                if (user_data->dlg.dialog_graph.graph[i].items[interval/user_data->dlg.dialog_graph.interval].flags & STAT_FLAG_WRONG_SEQ){
-                                       g_strlcpy(label_string,"x",15);
+                                       g_strlcpy(label_string,"x",sizeof(label_string));
                                } else {
-                                       g_strlcpy(label_string,"m",15);
+                                       g_strlcpy(label_string,"m",sizeof(label_string));
                                }
 
-                               pango_layout_set_text(layout, label_string, -1);
-                                pango_layout_get_pixel_size(layout, &lwidth, NULL);
-                                gdk_draw_layout(user_data->dlg.dialog_graph.pixmap,
-                                        user_data->dlg.dialog_graph.draw_area->style->black_gc,
-                                        x_pos-1-lwidth/2,
-                                        user_data->dlg.dialog_graph.pixmap_height-bottom_y_border+3+7*(i/2),
-                                        layout);
-                        }
+                               pango_layout_set_text(layout, label_string, -1);
+                               pango_layout_get_pixel_size(layout, &lwidth, NULL);
+#if GTK_CHECK_VERSION(2,22,0)
+                               cr = cairo_create (user_data->dlg.dialog_graph.surface);
+#else
+                               cr = gdk_cairo_create (user_data->dlg.dialog_graph.pixmap);
+#endif
+                               cairo_move_to (cr,
+                                       x_pos-1-lwidth/2,
+                                       user_data->dlg.dialog_graph.surface_height-bottom_y_border+3+7*(i/2));
+                               pango_cairo_show_layout (cr, layout);
+                               cairo_destroy (cr);
+                               cr = NULL;
 
-                        prev_x_pos=x_pos;
-                }
-        }
+                       }
 
-        g_object_unref(G_OBJECT(layout));
+                       /*prev_x_pos=x_pos;*/
+               }
+       }
 
-        /*
-         * Loop over all graphs and draw them
-         */
+       g_object_unref(G_OBJECT(layout));
+
+       /*
+        * Loop over all graphs and draw them
+        */
        for(i=MAX_GRAPHS-1;i>=0;i--){
                guint32 interval;
-               guint32 x_pos, y_pos, prev_x_pos, prev_y_pos;
+               guint32 x_pos, y_pos, /*prev_x_pos,*/ prev_y_pos;
                if (!user_data->dlg.dialog_graph.graph[i].display){
-                        continue;
-                }
+                       continue;
+               }
                /* initialize prev x/y to the low left corner of the graph */
-               prev_x_pos=draw_width-1-user_data->dlg.dialog_graph.pixels_per_tick*((last_interval-first_interval)/user_data->dlg.dialog_graph.interval+1)+left_x_border;
+               /*prev_x_pos=draw_width-1-user_data->dlg.dialog_graph.pixels_per_tick*((last_interval-first_interval)/user_data->dlg.dialog_graph.interval+1)+left_x_border;*/
                prev_y_pos=draw_height-1+top_y_border;
 
                for(interval=first_interval+user_data->dlg.dialog_graph.interval;interval<=last_interval;interval+=user_data->dlg.dialog_graph.interval){
@@ -1276,256 +1346,315 @@ static void dialog_graph_draw(user_data_t* user_data)
                        x_pos=draw_width-1-user_data->dlg.dialog_graph.pixels_per_tick*((last_interval-interval)/user_data->dlg.dialog_graph.interval+1)+left_x_border;
                        val=get_it_value(&user_data->dlg.dialog_graph.graph[i], interval/user_data->dlg.dialog_graph.interval);
                        if(val>max_y){
-                                y_pos=0;
-                        } else {
-                                y_pos=draw_height-1-(val*draw_height)/max_y+top_y_border;
-                        }
-
-                        /* dont need to draw anything if the segment
-                         * is entirely above the top of the graph
-                         */
-                        if( (prev_y_pos==0) && (y_pos==0) ){
-                                prev_y_pos=y_pos;
-                                prev_x_pos=x_pos;
-                                continue;
-                        }
-
-                        if(val){
-                               gdk_draw_line(user_data->dlg.dialog_graph.pixmap, user_data->dlg.dialog_graph.graph[i].gc,
-                                x_pos, draw_height-1+top_y_border,
-                                x_pos, y_pos);
-                       }
-
-                        prev_y_pos=y_pos;
-                        prev_x_pos=x_pos;
-                }
-        }
-
-
-        gdk_draw_pixmap(user_data->dlg.dialog_graph.draw_area->window,
-                        user_data->dlg.dialog_graph.draw_area->style->fg_gc[GTK_WIDGET_STATE(user_data->dlg.dialog_graph.draw_area)],
-                        user_data->dlg.dialog_graph.pixmap,
-                        0, 0,
-                        0, 0,
-                        user_data->dlg.dialog_graph.pixmap_width, user_data->dlg.dialog_graph.pixmap_height);
-
-
-        /* update the scrollbar */
-        user_data->dlg.dialog_graph.scrollbar_adjustment->upper=(gfloat) user_data->dlg.dialog_graph.max_interval;
-        user_data->dlg.dialog_graph.scrollbar_adjustment->step_increment=(gfloat) ((last_interval-first_interval)/10);
-        user_data->dlg.dialog_graph.scrollbar_adjustment->page_increment=(gfloat) (last_interval-first_interval);
-        if((last_interval-first_interval)*100 < user_data->dlg.dialog_graph.max_interval){
-                user_data->dlg.dialog_graph.scrollbar_adjustment->page_size=(gfloat) (user_data->dlg.dialog_graph.max_interval/100);
-        } else {
-                user_data->dlg.dialog_graph.scrollbar_adjustment->page_size=(gfloat) (last_interval-first_interval);
-        }
-        user_data->dlg.dialog_graph.scrollbar_adjustment->value=last_interval-user_data->dlg.dialog_graph.scrollbar_adjustment->page_size;
-        gtk_adjustment_changed(user_data->dlg.dialog_graph.scrollbar_adjustment);
-        gtk_adjustment_value_changed(user_data->dlg.dialog_graph.scrollbar_adjustment);
+                               y_pos=0;
+                       } else {
+                               y_pos=draw_height-1-(val*draw_height)/max_y+top_y_border;
+                       }
+
+                       /* dont need to draw anything if the segment
+                        * is entirely above the top of the graph
+                        */
+                       if( (prev_y_pos==0) && (y_pos==0) ){
+                               prev_y_pos=y_pos;
+                               /*prev_x_pos=x_pos;*/
+                               continue;
+                       }
+
+                       if(val){
+#if GTK_CHECK_VERSION(2,22,0)
+                               cr = cairo_create (user_data->dlg.dialog_graph.surface);
+#else
+                               cr = gdk_cairo_create (user_data->dlg.dialog_graph.pixmap);
+#endif
+                               gdk_cairo_set_source_color (cr, &user_data->dlg.dialog_graph.graph[i].color);
+                               cairo_set_line_width (cr, 1.0);
+                               cairo_move_to(cr, x_pos+0.5, draw_height-1+top_y_border+0.5);
+                               cairo_line_to(cr, x_pos+0.5, y_pos+0.5);
+                               cairo_stroke(cr);
+                               cairo_destroy(cr);
+                       }
+
+                       prev_y_pos=y_pos;
+                       /*prev_x_pos=x_pos;*/
+               }
+       }
+
+       cr = gdk_cairo_create (gtk_widget_get_window(user_data->dlg.dialog_graph.draw_area));
+
+#if GTK_CHECK_VERSION(2,22,0)
+       cairo_set_source_surface (cr, user_data->dlg.dialog_graph.surface, 0, 0);
+#else
+       gdk_cairo_set_source_pixmap (cr, user_data->dlg.dialog_graph.pixmap, 0, 0);
+#endif
+       cairo_rectangle (cr, 0, 0, user_data->dlg.dialog_graph.surface_width, user_data->dlg.dialog_graph.surface_height);
+       cairo_fill (cr);
+
+       cairo_destroy (cr);
+
+       /* update the scrollbar */
+       gtk_adjustment_set_upper(user_data->dlg.dialog_graph.scrollbar_adjustment, (gfloat) user_data->dlg.dialog_graph.max_interval);
+       gtk_adjustment_set_step_increment(user_data->dlg.dialog_graph.scrollbar_adjustment, (gfloat) ((last_interval-first_interval)/10));
+       gtk_adjustment_set_page_increment(user_data->dlg.dialog_graph.scrollbar_adjustment, (gfloat) (last_interval-first_interval));
+       if((last_interval-first_interval)*100 < user_data->dlg.dialog_graph.max_interval){
+               gtk_adjustment_set_page_size(user_data->dlg.dialog_graph.scrollbar_adjustment, (gfloat) (user_data->dlg.dialog_graph.max_interval/100));
+       } else {
+               gtk_adjustment_set_page_size(user_data->dlg.dialog_graph.scrollbar_adjustment, (gfloat) (last_interval-first_interval));
+       }
+       gtk_adjustment_set_value(user_data->dlg.dialog_graph.scrollbar_adjustment, last_interval - gtk_adjustment_get_page_size(user_data->dlg.dialog_graph.scrollbar_adjustment));
+       gtk_adjustment_changed(user_data->dlg.dialog_graph.scrollbar_adjustment);
+       gtk_adjustment_value_changed(user_data->dlg.dialog_graph.scrollbar_adjustment);
 
 }
 
 /****************************************************************************/
 static void dialog_graph_redraw(user_data_t* user_data)
 {
-        user_data->dlg.dialog_graph.needs_redraw=TRUE;
-        dialog_graph_draw(user_data);
+       user_data->dlg.dialog_graph.needs_redraw=TRUE;
+       dialog_graph_draw(user_data);
 }
 
 /****************************************************************************/
-static gint quit(GtkWidget *widget, GdkEventExpose *event _U_)
+static void quit(GtkWidget *widget _U_, user_data_t *user_data)
 {
-       user_data_t *user_data;
-
-       user_data=(user_data_t *)g_object_get_data(G_OBJECT(widget), "user_data_t");
+       GtkWidget *bt_save = g_object_get_data(G_OBJECT(user_data->dlg.dialog_graph.window), "bt_save");
+       surface_info_t *surface_info = g_object_get_data(G_OBJECT(bt_save), "surface-info");
 
+       g_free(surface_info);
        user_data->dlg.dialog_graph.window = NULL;
-       return TRUE;
 }
 
 /****************************************************************************/
-static gint expose_event(GtkWidget *widget, GdkEventExpose *event)
+#if GTK_CHECK_VERSION(3,0,0)
+static gboolean draw_area_draw(GtkWidget *widget, cairo_t *cr, gpointer data)
 {
-       user_data_t *user_data;
-
-       user_data=(user_data_t *)g_object_get_data(G_OBJECT(widget), "user_data_t");
-    if(!user_data){
-               exit(10);
-    }
+       user_data_t *user_data = data;
+       GtkAllocation allocation;
 
+       gtk_widget_get_allocation (widget, &allocation);
 
-        gdk_draw_pixmap(widget->window,
-                        widget->style->fg_gc[GTK_WIDGET_STATE(widget)],
-                        user_data->dlg.dialog_graph.pixmap,
-                        event->area.x, event->area.y,
-                        event->area.x, event->area.y,
-                        event->area.width, event->area.height);
+       cairo_set_source_surface (cr, user_data->dlg.dialog_graph.surface, 0, 0);
+       cairo_rectangle (cr, 0, 0, allocation.width, allocation.height);
+       cairo_fill (cr);
 
-        return FALSE;
+       return FALSE;
 }
+#else
+static gint expose_event(GtkWidget *widget, GdkEventExpose *event, gpointer data)
+{
+       user_data_t *user_data = data;
+       cairo_t *cr = gdk_cairo_create (gtk_widget_get_window(widget));
+
 
+#if GTK_CHECK_VERSION(2,22,0)
+       cairo_set_source_surface (cr, user_data->dlg.dialog_graph.surface, 0, 0);
+#else
+       gdk_cairo_set_source_pixmap (cr, user_data->dlg.dialog_graph.pixmap, 0, 0);
+#endif
+       cairo_rectangle (cr, event->area.x, event->area.y, event->area.width, event->area.height);
+       cairo_fill (cr);
+
+       cairo_destroy (cr);
+
+       return FALSE;
+}
+#endif
 /****************************************************************************/
 static gint configure_event(GtkWidget *widget, GdkEventConfigure *event _U_)
 {
-        user_data_t *user_data;
-       int i;
-
-        user_data=(user_data_t *)g_object_get_data(G_OBJECT(widget), "user_data_t");
+       user_data_t *user_data;
+       GtkWidget *bt_save;
+       GtkAllocation widget_alloc;
+       cairo_t *cr;
+#if GTK_CHECK_VERSION(2,22,0)
+       surface_info_t *surface_info = g_new(surface_info_t, 1);
+#endif
 
-        if(!user_data){
-                exit(10);
-        }
+       user_data=(user_data_t *)g_object_get_data(G_OBJECT(widget), "user_data_t");
 
-        if(user_data->dlg.dialog_graph.pixmap){
-                gdk_pixmap_unref(user_data->dlg.dialog_graph.pixmap);
-                user_data->dlg.dialog_graph.pixmap=NULL;
-        }
+       if(!user_data){
+               exit(10);
+       }
 
-        user_data->dlg.dialog_graph.pixmap=gdk_pixmap_new(widget->window,
-                        widget->allocation.width,
-                        widget->allocation.height,
-                        -1);
-        user_data->dlg.dialog_graph.pixmap_width=widget->allocation.width;
-        user_data->dlg.dialog_graph.pixmap_height=widget->allocation.height;
+#if GTK_CHECK_VERSION(2,22,0)
+       if(user_data->dlg.dialog_graph.surface){
+               g_object_unref(user_data->dlg.dialog_graph.surface);
+               user_data->dlg.dialog_graph.surface=NULL;
+       }
+       gtk_widget_get_allocation(widget, &widget_alloc);
+       user_data->dlg.dialog_graph.surface = gdk_window_create_similar_surface (gtk_widget_get_window(widget),
+                       CAIRO_CONTENT_COLOR,
+                       widget_alloc.width,
+                       widget_alloc.height);
+#else
+       if(user_data->dlg.dialog_graph.pixmap){
+               g_object_unref(user_data->dlg.dialog_graph.pixmap);
+               user_data->dlg.dialog_graph.pixmap=NULL;
+       }
 
-        gdk_draw_rectangle(user_data->dlg.dialog_graph.pixmap,
-                        widget->style->white_gc,
-                        TRUE,
-                        0, 0,
-                        widget->allocation.width,
-                        widget->allocation.height);
+       gtk_widget_get_allocation(widget, &widget_alloc);
+       user_data->dlg.dialog_graph.pixmap=gdk_pixmap_new(gtk_widget_get_window(widget),
+                                                         widget_alloc.width,
+                                                         widget_alloc.height,
+                                                         -1);
+#endif
+       user_data->dlg.dialog_graph.surface_width=widget_alloc.width;
+       user_data->dlg.dialog_graph.surface_height=widget_alloc.height;
+
+       bt_save = g_object_get_data(G_OBJECT(user_data->dlg.dialog_graph.window), "bt_save");
+#if GTK_CHECK_VERSION(2,22,0)
+       surface_info->surface = user_data->dlg.dialog_graph.surface;
+       surface_info->width = widget_alloc.width;
+       surface_info->height = widget_alloc.height;
+       g_object_set_data(G_OBJECT(bt_save), "surface-info", surface_info);
+       gtk_widget_set_sensitive(bt_save, TRUE);
+
+       cr = cairo_create (user_data->dlg.dialog_graph.surface);
+#else
+       g_object_set_data(G_OBJECT(bt_save), "pixmap", user_data->dlg.dialog_graph.pixmap);
+       gtk_widget_set_sensitive(bt_save, TRUE);
 
-        /* set up the colors and the GC structs for this pixmap */
-       for(i=0;i<MAX_GRAPHS;i++){
-               user_data->dlg.dialog_graph.graph[i].gc=gdk_gc_new(user_data->dlg.dialog_graph.pixmap);
-                gdk_gc_set_rgb_fg_color(user_data->dlg.dialog_graph.graph[i].gc, &user_data->dlg.dialog_graph.graph[i].color);
-       }
+       cr = gdk_cairo_create (user_data->dlg.dialog_graph.pixmap);
+#endif
+       cairo_rectangle (cr, 0, 0, widget_alloc.width, widget_alloc.height);
+       cairo_set_source_rgb (cr, 1, 1, 1);
+       cairo_fill (cr);
+       cairo_destroy (cr);
 
        dialog_graph_redraw(user_data);
-        return TRUE;
+       return TRUE;
 }
 
 /****************************************************************************/
 static gint scrollbar_changed(GtkWidget *widget _U_, gpointer data)
 {
-        user_data_t *user_data=(user_data_t *)data;
-        guint32 mi;
+       user_data_t *user_data=(user_data_t *)data;
+       guint32 mi;
 
-        mi=(guint32) (user_data->dlg.dialog_graph.scrollbar_adjustment->value+user_data->dlg.dialog_graph.scrollbar_adjustment->page_size);
-        if(user_data->dlg.dialog_graph.last_interval==mi){
-                return TRUE;
-        }
-        if( (user_data->dlg.dialog_graph.last_interval==0xffffffff)
-        &&  (mi==user_data->dlg.dialog_graph.max_interval) ){
-                return TRUE;
-        }
+       mi=(guint32) (gtk_adjustment_get_value(user_data->dlg.dialog_graph.scrollbar_adjustment) + gtk_adjustment_get_page_size(user_data->dlg.dialog_graph.scrollbar_adjustment));
+       if(user_data->dlg.dialog_graph.last_interval==mi){
+               return TRUE;
+       }
+       if( (user_data->dlg.dialog_graph.last_interval==0xffffffff)
+           &&  (mi==user_data->dlg.dialog_graph.max_interval) ){
+               return TRUE;
+       }
 
-        user_data->dlg.dialog_graph.last_interval=(mi/user_data->dlg.dialog_graph.interval)*user_data->dlg.dialog_graph.interval;
+       user_data->dlg.dialog_graph.last_interval=(mi/user_data->dlg.dialog_graph.interval)*user_data->dlg.dialog_graph.interval;
 
        dialog_graph_redraw(user_data);
-        return TRUE;
+       return TRUE;
 }
 
 /****************************************************************************/
 static void create_draw_area(user_data_t* user_data, GtkWidget *box)
 {
-        user_data->dlg.dialog_graph.draw_area=gtk_drawing_area_new();
-        g_signal_connect(user_data->dlg.dialog_graph.draw_area, "destroy", G_CALLBACK(quit), user_data);
-        g_object_set_data(G_OBJECT(user_data->dlg.dialog_graph.draw_area), "user_data_t", user_data);
+       user_data->dlg.dialog_graph.draw_area=gtk_drawing_area_new();
+       g_signal_connect(user_data->dlg.dialog_graph.draw_area, "destroy", G_CALLBACK(quit), user_data);
 
-        gtk_widget_set_size_request(user_data->dlg.dialog_graph.draw_area, user_data->dlg.dialog_graph.pixmap_width, user_data->dlg.dialog_graph.pixmap_height);
+       gtk_widget_set_size_request(user_data->dlg.dialog_graph.draw_area, user_data->dlg.dialog_graph.surface_width, user_data->dlg.dialog_graph.surface_height);
 
-        /* signals needed to handle backing pixmap */
-        g_signal_connect(user_data->dlg.dialog_graph.draw_area, "expose_event", G_CALLBACK(expose_event), NULL);
-        g_signal_connect(user_data->dlg.dialog_graph.draw_area, "configure_event", G_CALLBACK(configure_event), user_data);
+       /* signals needed to handle backing pixmap */
+#if GTK_CHECK_VERSION(3,0,0)
+       g_signal_connect(user_data->dlg.dialog_graph.draw_area, "draw", G_CALLBACK(draw_area_draw), user_data);
+#else
+       g_signal_connect(user_data->dlg.dialog_graph.draw_area, "expose_event", G_CALLBACK(expose_event), user_data);
+#endif
+       g_signal_connect(user_data->dlg.dialog_graph.draw_area, "configure_event", G_CALLBACK(configure_event), user_data);
 
-        gtk_widget_show(user_data->dlg.dialog_graph.draw_area);
-        gtk_box_pack_start(GTK_BOX(box), user_data->dlg.dialog_graph.draw_area, TRUE, TRUE, 0);
+       gtk_widget_show(user_data->dlg.dialog_graph.draw_area);
+       gtk_box_pack_start(GTK_BOX(box), user_data->dlg.dialog_graph.draw_area, TRUE, TRUE, 0);
 
-        /* create the associated scrollbar */
-        user_data->dlg.dialog_graph.scrollbar_adjustment=(GtkAdjustment *)gtk_adjustment_new(0,0,0,0,0,0);
-        user_data->dlg.dialog_graph.scrollbar=gtk_hscrollbar_new(user_data->dlg.dialog_graph.scrollbar_adjustment);
-        gtk_widget_show(user_data->dlg.dialog_graph.scrollbar);
-        gtk_box_pack_start(GTK_BOX(box), user_data->dlg.dialog_graph.scrollbar, FALSE, FALSE, 0);
-        g_signal_connect(user_data->dlg.dialog_graph.scrollbar_adjustment, "value_changed", G_CALLBACK(scrollbar_changed), user_data);
+       /* create the associated scrollbar */
+       user_data->dlg.dialog_graph.scrollbar_adjustment=(GtkAdjustment *)gtk_adjustment_new(0,0,0,0,0,0);
+       user_data->dlg.dialog_graph.scrollbar=gtk_hscrollbar_new(user_data->dlg.dialog_graph.scrollbar_adjustment);
+       gtk_widget_show(user_data->dlg.dialog_graph.scrollbar);
+       gtk_box_pack_start(GTK_BOX(box), user_data->dlg.dialog_graph.scrollbar, FALSE, FALSE, 0);
+       g_signal_connect(user_data->dlg.dialog_graph.scrollbar_adjustment, "value_changed", G_CALLBACK(scrollbar_changed), user_data);
 }
 
 /****************************************************************************/
 static void disable_graph(dialog_graph_graph_t *dgg)
 {
-        if (dgg->display) {
-                dgg->display=FALSE;
-                gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(dgg->display_button),
-                    FALSE);
-        }
+       if (dgg->display) {
+               dgg->display=FALSE;
+               gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(dgg->display_button),
+                                            FALSE);
+       }
 }
 
 /****************************************************************************/
 static gint filter_callback(GtkWidget *widget _U_, dialog_graph_graph_t *dgg)
 {
-        /* this graph is not active, just update display and redraw */
-        if(!gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(dgg->display_button))){
-                disable_graph(dgg);
-                dialog_graph_redraw(dgg->ud);
+       /* this graph is not active, just update display and redraw */
+       if(!gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(dgg->display_button))){
+               disable_graph(dgg);
+               dialog_graph_redraw(dgg->ud);
                return 0;
-        }
+       }
 
-               enable_graph(dgg);
-        cf_retap_packets(&cfile, FALSE);
-        dialog_graph_redraw(dgg->ud);
+       enable_graph(dgg);
+       cf_retap_packets(&cfile);
+       dialog_graph_redraw(dgg->ud);
 
-        return 0;
+       return 0;
 }
 
 /****************************************************************************/
 static void create_filter_box(dialog_graph_graph_t *dgg, GtkWidget *box, int num)
 {
-        GtkWidget *hbox;
-        GtkWidget *label;
-        char str[256];
+       GtkWidget *hbox;
+       GtkWidget *label;
+       char str[256];
 
-        hbox=gtk_hbox_new(FALSE, 3);
-        gtk_container_add(GTK_CONTAINER(box), hbox);
-        gtk_box_set_child_packing(GTK_BOX(box), hbox, FALSE, FALSE, 0, GTK_PACK_START);
-        gtk_widget_show(hbox);
+       hbox=gtk_hbox_new(FALSE, 3);
+       gtk_container_add(GTK_CONTAINER(box), hbox);
+       gtk_box_set_child_packing(GTK_BOX(box), hbox, FALSE, FALSE, 0, GTK_PACK_START);
+       gtk_widget_show(hbox);
 
-       g_snprintf(str, 256, "Graph %d", num);
+       g_snprintf(str, sizeof(str), "Graph %d", num);
        dgg->display_button=gtk_toggle_button_new_with_label(str);
-        gtk_box_pack_start(GTK_BOX(hbox), dgg->display_button, FALSE, FALSE, 0);
-        gtk_widget_show(dgg->display_button);
-        gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(dgg->display_button), dgg->display);
-        g_signal_connect(dgg->display_button, "toggled", G_CALLBACK(filter_callback), dgg);
+       gtk_box_pack_start(GTK_BOX(hbox), dgg->display_button, FALSE, FALSE, 0);
+       gtk_widget_show(dgg->display_button);
+       gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(dgg->display_button), dgg->display);
+       g_signal_connect(dgg->display_button, "toggled", G_CALLBACK(filter_callback), dgg);
 
        label=gtk_label_new(dgg->title);
-        gtk_widget_show(label);
-        gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 0);
-
-        gtk_widget_modify_fg(label, GTK_STATE_NORMAL, &dgg->color);
-        gtk_widget_modify_fg(label, GTK_STATE_ACTIVE, &dgg->color);
-        gtk_widget_modify_fg(label, GTK_STATE_PRELIGHT, &dgg->color);
-        gtk_widget_modify_fg(label, GTK_STATE_SELECTED, &dgg->color);
-        gtk_widget_modify_fg(label, GTK_STATE_INSENSITIVE, &dgg->color);
-
-        return;
+       gtk_widget_show(label);
+       gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 0);
+
+#if GTK_CHECK_VERSION(3,0,0)
+       gtk_widget_override_color(label, GTK_STATE_NORMAL, &dgg->rgba_color);
+       gtk_widget_override_color(label, GTK_STATE_ACTIVE, &dgg->rgba_color);
+       gtk_widget_override_color(label, GTK_STATE_PRELIGHT, &dgg->rgba_color);
+       gtk_widget_override_color(label, GTK_STATE_SELECTED, &dgg->rgba_color);
+       gtk_widget_override_color(label, GTK_STATE_INSENSITIVE, &dgg->rgba_color);
+#else  
+       gtk_widget_modify_fg(label, GTK_STATE_NORMAL, &dgg->color);
+       gtk_widget_modify_fg(label, GTK_STATE_ACTIVE, &dgg->color);
+       gtk_widget_modify_fg(label, GTK_STATE_PRELIGHT, &dgg->color);
+       gtk_widget_modify_fg(label, GTK_STATE_SELECTED, &dgg->color);
+       gtk_widget_modify_fg(label, GTK_STATE_INSENSITIVE, &dgg->color);
+#endif
+       return;
 }
 
 /****************************************************************************/
 static void create_filter_area(user_data_t* user_data, GtkWidget *box)
 {
-        GtkWidget *frame;
-        GtkWidget *vbox;
+       GtkWidget *frame;
+       GtkWidget *vbox;
        int i;
        GtkWidget *label;
 
-       frame=gtk_frame_new("Graphs");
-        gtk_container_add(GTK_CONTAINER(box), frame);
-        gtk_widget_show(frame);
+       frame=gtk_frame_new("Graphs");
+       gtk_container_add(GTK_CONTAINER(box), frame);
+       gtk_widget_show(frame);
 
-        vbox=gtk_vbox_new(FALSE, 1);
-        gtk_container_add(GTK_CONTAINER(frame), vbox);
-       gtk_container_set_border_width(GTK_CONTAINER(vbox), 3);
-        gtk_box_set_child_packing(GTK_BOX(box), vbox, FALSE, FALSE, 0, GTK_PACK_START);
-        gtk_widget_show(vbox);
+       vbox=gtk_vbox_new(FALSE, 1);
+       gtk_container_add(GTK_CONTAINER(frame), vbox);
+       gtk_container_set_border_width(GTK_CONTAINER(vbox), 3);
+       gtk_box_set_child_packing(GTK_BOX(box), vbox, FALSE, FALSE, 0, GTK_PACK_START);
+       gtk_widget_show(vbox);
 
        for(i=0;i<MAX_GRAPHS;i++){
                create_filter_box(&user_data->dlg.dialog_graph.graph[i], vbox, i+1);
@@ -1535,236 +1664,244 @@ static void create_filter_area(user_data_t* user_data, GtkWidget *box)
        gtk_widget_show(label);
        gtk_box_pack_start(GTK_BOX(vbox), label, FALSE, FALSE, 0);
 
-        return;
+       return;
 }
 
 /****************************************************************************/
 static void yscale_select(GtkWidget *item, gpointer key)
 {
-        int val;
+       int i;
        user_data_t *user_data;
 
-        user_data=(user_data_t *)key;
-        val=(long)g_object_get_data(G_OBJECT(item), "yscale_max");
+       user_data=(user_data_t *)key;
+       i = gtk_combo_box_get_active (GTK_COMBO_BOX(item));
 
-        user_data->dlg.dialog_graph.max_y_units=val;
-        dialog_graph_redraw(user_data);
+       user_data->dlg.dialog_graph.max_y_units_index=i;
+       user_data->dlg.dialog_graph.max_y_units=yscale_max[i];
+       dialog_graph_redraw(user_data);
 }
 
 /****************************************************************************/
 static void pixels_per_tick_select(GtkWidget *item, gpointer key)
 {
-        int val;
-        user_data_t *user_data;
+       int i;
+       user_data_t *user_data;
+
+       user_data=(user_data_t *)key;
+       i = gtk_combo_box_get_active (GTK_COMBO_BOX(item));
 
-        user_data=(user_data_t *)key;
-        val=(long)g_object_get_data(G_OBJECT(item), "pixels_per_tick");
-        user_data->dlg.dialog_graph.pixels_per_tick=val;
-        dialog_graph_redraw(user_data);
+       user_data->dlg.dialog_graph.pixels_per_tick_index=i;
+       user_data->dlg.dialog_graph.pixels_per_tick=pixels_per_tick[i];
+       dialog_graph_redraw(user_data);
 }
 
 /****************************************************************************/
 static void tick_interval_select(GtkWidget *item, gpointer key)
 {
-        int val;
-        user_data_t *user_data;
+       int i;
+       user_data_t *user_data;
 
-        user_data=(user_data_t *)key;
-        val=(long)g_object_get_data(G_OBJECT(item), "tick_interval");
+       user_data=(user_data_t *)key;
+       i = gtk_combo_box_get_active (GTK_COMBO_BOX(item));
 
-        user_data->dlg.dialog_graph.interval=val;
-        cf_retap_packets(&cfile, FALSE);
-        dialog_graph_redraw(user_data);
+       user_data->dlg.dialog_graph.interval_index=i;
+       user_data->dlg.dialog_graph.interval=tick_interval_values[i];
+       cf_retap_packets(&cfile);
+       dialog_graph_redraw(user_data);
 }
 
 /****************************************************************************/
-static void create_yscale_max_menu_items(user_data_t* user_data, GtkWidget *menu)
+static GtkWidget *
+create_yscale_max_menu_items(user_data_t* user_data)
 {
-        char str[15];
-        GtkWidget *menu_item;
-        int i;
-
-        for(i=0;i<MAX_YSCALE;i++){
-                if(yscale_max[i]==AUTO_MAX_YSCALE){
-                       g_strlcpy(str,"Auto",15);
-                } else {
-                        g_snprintf(str, 15, "%u ms", yscale_max[i]/1000);
-                }
-                menu_item=gtk_menu_item_new_with_label(str);
-                g_object_set_data(G_OBJECT(menu_item), "yscale_max",
-                                GUINT_TO_POINTER(yscale_max[i]));
-                g_signal_connect(menu_item, "activate", G_CALLBACK(yscale_select), user_data);
-                gtk_widget_show(menu_item);
-                gtk_menu_shell_append(GTK_MENU_SHELL(menu), menu_item);
-        }
-        return;
+       char str[15];
+       GtkWidget *combo_box;
+       int i;
+
+       combo_box = gtk_combo_box_text_new();
+
+       for(i=0;i<MAX_YSCALE;i++){
+               if(yscale_max[i]==AUTO_MAX_YSCALE){
+                       g_strlcpy(str,"Auto",sizeof(str));
+               } else if (yscale_max[i] < 1000000) {
+                       g_snprintf(str, sizeof(str), "%u ms", yscale_max[i]/1000);
+               } else {
+                       g_snprintf(str, sizeof(str), "%u s", yscale_max[i]/1000000);
+               }
+                gtk_combo_box_text_append_text (GTK_COMBO_BOX_TEXT (combo_box), str);
+       }
+       gtk_combo_box_set_active(GTK_COMBO_BOX(combo_box), user_data->dlg.dialog_graph.max_y_units_index);
+       g_signal_connect(combo_box, "changed", G_CALLBACK(yscale_select), (gpointer)user_data);
+
+       return combo_box;
 }
 
 /****************************************************************************/
-static void create_pixels_per_tick_menu_items(user_data_t* user_data, GtkWidget *menu)
+static GtkWidget *
+create_pixels_per_tick_menu_items(user_data_t *user_data)
 {
-        char str[5];
-        GtkWidget *menu_item;
-        int i;
-
-        for(i=0;i<MAX_PIXELS_PER_TICK;i++){
-                g_snprintf(str, 5, "%u", pixels_per_tick[i]);
-                menu_item=gtk_menu_item_new_with_label(str);
-
-                g_object_set_data(G_OBJECT(menu_item), "pixels_per_tick",
-                                GUINT_TO_POINTER(pixels_per_tick[i]));
-                g_signal_connect(menu_item, "activate", G_CALLBACK(pixels_per_tick_select), user_data);
-                gtk_widget_show(menu_item);
-                gtk_menu_shell_append(GTK_MENU_SHELL(menu), menu_item);
-        }
-        gtk_menu_set_active(GTK_MENU(menu), DEFAULT_PIXELS_PER_TICK);
-        return;
-}
+       char str[5];
+       GtkWidget *combo_box;
+       int i;
+
+       combo_box = gtk_combo_box_text_new();
 
+       for(i=0;i<MAX_PIXELS_PER_TICK;i++){
+               g_snprintf(str, sizeof(str), "%u", pixels_per_tick[i]);
+                gtk_combo_box_text_append_text (GTK_COMBO_BOX_TEXT (combo_box), str);
+       }
+       gtk_combo_box_set_active(GTK_COMBO_BOX(combo_box), user_data->dlg.dialog_graph.pixels_per_tick_index);
+
+       g_signal_connect(combo_box, "changed", G_CALLBACK(pixels_per_tick_select), (gpointer)user_data);
+
+       return combo_box;
+}
 
 /****************************************************************************/
-static void create_tick_interval_menu_items(user_data_t* user_data, GtkWidget *menu)
+static GtkWidget *
+create_tick_interval_menu_items(user_data_t *user_data)
 {
-        char str[15];
-        GtkWidget *menu_item;
-        int i;
-
-        for(i=0;i<MAX_TICK_VALUES;i++){
-                if(tick_interval_values[i]>=1000){
-                        g_snprintf(str, 15, "%u sec", tick_interval_values[i]/1000);
-                } else if(tick_interval_values[i]>=100){
-                        g_snprintf(str, 15, "0.%1u sec", (tick_interval_values[i]/100)%10);
-                } else if(tick_interval_values[i]>=10){
-                        g_snprintf(str, 15, "0.%02u sec", (tick_interval_values[i]/10)%10);
-                } else {
-                        g_snprintf(str, 15, "0.%03u sec", (tick_interval_values[i])%10);
-                }
-
-                menu_item=gtk_menu_item_new_with_label(str);
-                g_object_set_data(G_OBJECT(menu_item), "tick_interval",
-                                GUINT_TO_POINTER(tick_interval_values[i]));
-                g_signal_connect(menu_item, "activate", G_CALLBACK(tick_interval_select), (gpointer)user_data);
-                gtk_widget_show(menu_item);
-                gtk_menu_shell_append(GTK_MENU_SHELL(menu), menu_item);
-        }
-        gtk_menu_set_active(GTK_MENU(menu), DEFAULT_TICK_VALUE);
-        return;
+       GtkWidget *combo_box;
+       char str[15];
+       int i;
+
+       combo_box = gtk_combo_box_text_new();
+
+       for(i=0;i<MAX_TICK_VALUES;i++){
+               if(tick_interval_values[i]>=1000){
+                       g_snprintf(str, sizeof(str), "%u sec", tick_interval_values[i]/1000);
+               } else if(tick_interval_values[i]>=100){
+                       g_snprintf(str, sizeof(str), "0.%1u sec", (tick_interval_values[i]/100)%10);
+               } else if(tick_interval_values[i]>=10){
+                       g_snprintf(str, sizeof(str), "0.%02u sec", (tick_interval_values[i]/10)%10);
+               } else {
+                       g_snprintf(str, sizeof(str), "0.%03u sec", (tick_interval_values[i])%10);
+               }
+                gtk_combo_box_text_append_text (GTK_COMBO_BOX_TEXT (combo_box), str);
+       }
+       gtk_combo_box_set_active(GTK_COMBO_BOX(combo_box), user_data->dlg.dialog_graph.interval_index);
+       g_signal_connect(combo_box, "changed", G_CALLBACK(tick_interval_select), (gpointer)user_data);
+
+       return combo_box;
 }
 
 /****************************************************************************/
-static void create_ctrl_menu(user_data_t* user_data, GtkWidget *box, const char *name, void (*func)(user_data_t* user_data, GtkWidget *menu))
+static void create_ctrl_menu(user_data_t* user_data, GtkWidget *box, const char *name, GtkWidget *(*func)(user_data_t* user_data))
 {
-        GtkWidget *hbox;
-        GtkWidget *label;
-        GtkWidget *option_menu;
-        GtkWidget *menu;
-
-        hbox=gtk_hbox_new(FALSE, 0);
-        gtk_container_add(GTK_CONTAINER(box), hbox);
-        gtk_box_set_child_packing(GTK_BOX(box), hbox, FALSE, FALSE, 0, GTK_PACK_START);
-        gtk_widget_show(hbox);
-
-        label=gtk_label_new(name);
-        gtk_widget_show(label);
-        gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 0);
-
-        option_menu=gtk_option_menu_new();
-        menu=gtk_menu_new();
-        (*func)(user_data, menu);
-        gtk_option_menu_set_menu(GTK_OPTION_MENU(option_menu), menu);
-        gtk_box_pack_end(GTK_BOX(hbox), option_menu, FALSE, FALSE, 0);
-        gtk_widget_show(option_menu);
+       GtkWidget *hbox;
+       GtkWidget *label;
+       GtkWidget *combo_box;
+
+       hbox=gtk_hbox_new(FALSE, 0);
+       gtk_container_add(GTK_CONTAINER(box), hbox);
+       gtk_box_set_child_packing(GTK_BOX(box), hbox, FALSE, FALSE, 0, GTK_PACK_START);
+       gtk_widget_show(hbox);
+
+       label=gtk_label_new(name);
+       gtk_widget_show(label);
+       gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 0);
+
+       combo_box = (*func)(user_data);
+       gtk_box_pack_end(GTK_BOX(hbox), combo_box, FALSE, FALSE, 0);
+       gtk_widget_show(combo_box);
 }
 
 /****************************************************************************/
 static void create_ctrl_area(user_data_t* user_data, GtkWidget *box)
 {
        GtkWidget *frame_vbox;
-       GtkWidget *frame;
-        GtkWidget *vbox;
+       GtkWidget *frame;
+       GtkWidget *vbox;
 
-        frame_vbox=gtk_vbox_new(FALSE, 0);
-        gtk_container_add(GTK_CONTAINER(box), frame_vbox);
-        gtk_widget_show(frame_vbox);
+       frame_vbox=gtk_vbox_new(FALSE, 0);
+       gtk_container_add(GTK_CONTAINER(box), frame_vbox);
+       gtk_widget_show(frame_vbox);
 
        frame = gtk_frame_new("X Axis");
-        gtk_container_add(GTK_CONTAINER(frame_vbox), frame);
-        gtk_widget_show(frame);
+       gtk_container_add(GTK_CONTAINER(frame_vbox), frame);
+       gtk_widget_show(frame);
 
-        vbox=gtk_vbox_new(FALSE, 0);
-        gtk_container_add(GTK_CONTAINER(frame), vbox);
+       vbox=gtk_vbox_new(FALSE, 0);
+       gtk_container_add(GTK_CONTAINER(frame), vbox);
        gtk_container_set_border_width(GTK_CONTAINER(vbox), 3);
-        gtk_box_set_child_packing(GTK_BOX(box), vbox, FALSE, FALSE, 0, GTK_PACK_END);
-        gtk_widget_show(vbox);
+       gtk_box_set_child_packing(GTK_BOX(box), vbox, FALSE, FALSE, 0, GTK_PACK_END);
+       gtk_widget_show(vbox);
 
-        create_ctrl_menu(user_data, vbox, "Tick interval:", create_tick_interval_menu_items);
-        create_ctrl_menu(user_data, vbox, "Pixels per tick:", create_pixels_per_tick_menu_items);
+       create_ctrl_menu(user_data, vbox, "Tick interval:", create_tick_interval_menu_items);
+       create_ctrl_menu(user_data, vbox, "Pixels per tick:", create_pixels_per_tick_menu_items);
 
-       frame = gtk_frame_new("Y Axis");
-        gtk_container_add(GTK_CONTAINER(frame_vbox), frame);
-        gtk_widget_show(frame);
+       frame = gtk_frame_new("Y Axis");
+       gtk_container_add(GTK_CONTAINER(frame_vbox), frame);
+       gtk_widget_show(frame);
 
-        vbox=gtk_vbox_new(FALSE, 0);
-        gtk_container_add(GTK_CONTAINER(frame), vbox);
-       gtk_container_set_border_width(GTK_CONTAINER(vbox), 3);
-        gtk_box_set_child_packing(GTK_BOX(box), vbox, FALSE, FALSE, 0, GTK_PACK_END);
-        gtk_widget_show(vbox);
+       vbox=gtk_vbox_new(FALSE, 0);
+       gtk_container_add(GTK_CONTAINER(frame), vbox);
+       gtk_container_set_border_width(GTK_CONTAINER(vbox), 3);
+       gtk_box_set_child_packing(GTK_BOX(box), vbox, FALSE, FALSE, 0, GTK_PACK_END);
+       gtk_widget_show(vbox);
 
-        create_ctrl_menu(user_data, vbox, "Scale:", create_yscale_max_menu_items);
+       create_ctrl_menu(user_data, vbox, "Scale:", create_yscale_max_menu_items);
 
-        return;
+       return;
 }
 
 /****************************************************************************/
 static void dialog_graph_init_window(user_data_t* user_data)
 {
-        GtkWidget *vbox;
-        GtkWidget *hbox;
-       GtkWidget *bt_close;
+       GtkWidget *vbox;
+       GtkWidget *hbox;
+       GtkWidget *bt_close;
+       GtkWidget *bt_save;
 
-        /* create the main window */
-        user_data->dlg.dialog_graph.window=window_new(GTK_WINDOW_TOPLEVEL, "I/O Graphs");
+       /* create the main window */
+       user_data->dlg.dialog_graph.window=dlg_window_new("I/O Graphs");   /* transient_for top_level */
 
-        vbox=gtk_vbox_new(FALSE, 0);
-        gtk_container_add(GTK_CONTAINER(user_data->dlg.dialog_graph.window), vbox);
-        gtk_widget_show(vbox);
+       vbox=gtk_vbox_new(FALSE, 0);
+       gtk_container_add(GTK_CONTAINER(user_data->dlg.dialog_graph.window), vbox);
+       gtk_widget_show(vbox);
 
-        create_draw_area(user_data, vbox);
+       create_draw_area(user_data, vbox);
 
-        hbox=gtk_hbox_new(FALSE, 3);
-        gtk_box_pack_end(GTK_BOX(vbox), hbox, FALSE, FALSE, 5);
-       gtk_container_set_border_width(GTK_CONTAINER(hbox), 3);
-        gtk_box_set_child_packing(GTK_BOX(vbox), hbox, FALSE, FALSE, 0, GTK_PACK_START);
-        gtk_widget_show(hbox);
+       hbox=gtk_hbox_new(FALSE, 3);
+       gtk_box_pack_end(GTK_BOX(vbox), hbox, FALSE, FALSE, 5);
+       gtk_container_set_border_width(GTK_CONTAINER(hbox), 3);
+       gtk_box_set_child_packing(GTK_BOX(vbox), hbox, FALSE, FALSE, 0, GTK_PACK_START);
+       gtk_widget_show(hbox);
 
-        create_filter_area(user_data, hbox);
-        create_ctrl_area(user_data, hbox);
+       create_filter_area(user_data, hbox);
+       create_ctrl_area(user_data, hbox);
 
-        dialog_graph_set_title(user_data);
+       dialog_graph_set_title(user_data);
+
+       hbox = dlg_button_row_new(GTK_STOCK_CLOSE, GTK_STOCK_SAVE, NULL);
+       gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 0);
+       gtk_widget_show(hbox);
 
-    hbox = dlg_button_row_new(GTK_STOCK_CLOSE, NULL);
-        gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 0);
-    gtk_widget_show(hbox);
+       bt_close = g_object_get_data(G_OBJECT(hbox), GTK_STOCK_CLOSE);
+       window_set_cancel_button(user_data->dlg.dialog_graph.window, bt_close, window_cancel_button_cb);
 
-    bt_close = g_object_get_data(G_OBJECT(hbox), GTK_STOCK_CLOSE);
-    window_set_cancel_button(user_data->dlg.dialog_graph.window, bt_close, window_cancel_button_cb);
+       bt_save = g_object_get_data(G_OBJECT(hbox), GTK_STOCK_SAVE);
+       gtk_widget_set_sensitive(bt_save, FALSE);
+       gtk_widget_set_tooltip_text(bt_save, "Save the displayed graph to a file");
+       g_signal_connect(bt_save, "clicked", G_CALLBACK(pixmap_save_cb), NULL);
+       g_object_set_data(G_OBJECT(user_data->dlg.dialog_graph.window), "bt_save", bt_save);
 
-    g_signal_connect(user_data->dlg.dialog_graph.window, "delete_event", G_CALLBACK(window_delete_event_cb), NULL);
+       g_signal_connect(user_data->dlg.dialog_graph.window, "delete_event", G_CALLBACK(window_delete_event_cb), NULL);
 
-    gtk_widget_show(user_data->dlg.dialog_graph.window);
-    window_present(user_data->dlg.dialog_graph.window);
+       gtk_widget_show(user_data->dlg.dialog_graph.window);
+       window_present(user_data->dlg.dialog_graph.window);
 
 }
 
 
 /****************************************************************************/
-static void on_graph_bt_clicked(GtkWidget *bt _U_, user_data_t *user_data _U_)
+static void on_graph_bt_clicked(GtkWidget *bt _U_, user_data_t *user_data)
 {
-        if (user_data->dlg.dialog_graph.window != NULL) {
-                /* There's already a graph window; reactivate it. */
-                reactivate_window(user_data->dlg.dialog_graph.window);
-                return;
-        }
+       if (user_data->dlg.dialog_graph.window != NULL) {
+               /* There's already a graph window; reactivate it. */
+               reactivate_window(user_data->dlg.dialog_graph.window);
+               return;
+       }
 
        dialog_graph_init_window(user_data);
 
@@ -1783,7 +1920,7 @@ static void on_goto_bt_clicked_lst(GtkWidget *bt _U_, user_data_t *user_data _U_
 
        if (selection==NULL)
                return;
-       
+
        if (gtk_tree_selection_get_selected (selection, &model, &iter)){
                gtk_tree_model_get (model, &iter, PACKET_COLUMN, &fnumber, -1);
                cf_goto_frame(&cfile, fnumber);
@@ -1795,7 +1932,7 @@ static void draw_stat(user_data_t *user_data);
 
 /****************************************************************************/
 /* re-dissects all packets */
-static void on_refresh_bt_clicked(GtkWidget *bt _U_, user_data_t *user_data _U_)
+static void on_refresh_bt_clicked(GtkWidget *bt _U_, user_data_t *user_data)
 {
        GString *error_string;
 
@@ -1805,7 +1942,7 @@ static void on_refresh_bt_clicked(GtkWidget *bt _U_, user_data_t *user_data _U_)
        unprotect_thread_critical_region();
 
        /* register tap listener */
-       error_string = register_tap_listener("rtp", user_data, NULL,
+       error_string = register_tap_listener("rtp", user_data, NULL, 0,
                rtp_reset, rtp_packet, rtp_draw);
        if (error_string != NULL) {
                simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, "%s", error_string->str);
@@ -1814,13 +1951,23 @@ static void on_refresh_bt_clicked(GtkWidget *bt _U_, user_data_t *user_data _U_)
        }
 
        /* retap all packets */
-       cf_retap_packets(&cfile, FALSE);
+       cf_retap_packets(&cfile);
 
        /* draw statistics info */
        draw_stat(user_data);
 
 }
 
+#ifdef HAVE_LIBPORTAUDIO
+/****************************************************************************/
+static void
+on_player_bt_clicked(GtkButton *button _U_, gpointer user_data _U_)
+{
+       /*rtp_player_init(voip_calls_get_info());*/
+       rtp_player_init(NULL);
+}
+#endif /* HAVE_LIBPORTAUDIO */
+
 static void on_next_bt_clicked_list(GtkWidget *bt _U_, user_data_t *user_data _U_)
 {
        GtkTreeIter iter;
@@ -1863,7 +2010,7 @@ try_again:
 
 /****************************************************************************/
 /* when we want to save the information */
-static void save_csv_as_ok_cb(GtkWidget *bt _U_, gpointer fs /*user_data_t *user_data*/ _U_)
+static gboolean save_csv_as_ok_cb(GtkWidget *w _U_, gpointer fc /*user_data_t *user_data*/)
 {
        gchar *g_dest;
        GtkWidget *rev, *forw, *both;
@@ -1871,25 +2018,27 @@ static void save_csv_as_ok_cb(GtkWidget *bt _U_, gpointer fs /*user_data_t *user
 
        GtkListStore *store;
        GtkTreeIter iter;
-       GtkTreeSelection *selection;
        GtkTreeModel *model;
+       gboolean more_items = TRUE;
 
        /* To Hold data from the list row */
-       guint                   packet;         /* Packet                               */
-       guint                   sequence;       /* Sequence                             */
+       guint32                 packet;         /* Packet                       */
+       guint16                 sequence;       /* Sequence                     */
+       guint32                 timestamp;      /* timestamp                    */
        gfloat                  delta;          /* Delta(ms)                    */
        gfloat                  jitter;         /* Jitter(ms)                   */
+       gfloat                  skew;           /* Skew(ms)                     */
        gfloat                  ipbw;           /* IP BW(kbps)                  */
-       gboolean                marker;         /* Marker                               */
-       char *                  status_str;     /* Status                               */
-       char *                  date_str;       /* Date                                 */
-       guint                   length;         /* Length                               */
+       gboolean                marker;         /* Marker                       */
+       char *                  status_str;     /* Status                       */
+       char *                  date_str;       /* Date                         */
+       guint                   length;         /* Length                       */
 
 
        FILE *fp;
        int j;
 
-       g_dest = g_strdup(gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(fs)));
+       g_dest = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(fc));
 
        /* Perhaps the user specified a directory instead of a file.
         * Check whether they did.
@@ -1898,191 +2047,222 @@ static void save_csv_as_ok_cb(GtkWidget *bt _U_, gpointer fs /*user_data_t *user
                /* It's a directory - set the file selection box to display it. */
                set_last_open_dir(g_dest);
                g_free(g_dest);
-               file_selection_set_current_folder(fs, get_last_open_dir());
-               return;
+               file_selection_set_current_folder(fc, get_last_open_dir());
+               gtk_file_chooser_set_current_name(fc, "");
+               return FALSE; /* run the dialog again */
        }
 
-       rev = (GtkWidget*)g_object_get_data(G_OBJECT(bt), "reversed_rb");
-       forw = (GtkWidget*)g_object_get_data(G_OBJECT(bt), "forward_rb");
-       both = (GtkWidget*)g_object_get_data(G_OBJECT(bt), "both_rb");
-       user_data = (user_data_t*)g_object_get_data(G_OBJECT(bt), "user_data");
+       rev  = (GtkWidget*)g_object_get_data(G_OBJECT(fc), "reversed_rb");
+       forw = (GtkWidget*)g_object_get_data(G_OBJECT(fc), "forward_rb");
+       both = (GtkWidget*)g_object_get_data(G_OBJECT(fc), "both_rb");
+       user_data = (user_data_t*)g_object_get_data(G_OBJECT(fc), "user_data");
 
-       if (GTK_TOGGLE_BUTTON(forw)->active || GTK_TOGGLE_BUTTON(both)->active) {
+       if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(forw)) || gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(both))) {
                fp = ws_fopen(g_dest, "w");
                if (fp == NULL) {
                        open_failure_alert_box(g_dest, errno, TRUE);
-                       return;
+                       g_free(g_dest);
+                       return TRUE; /* we're done */
                }
 
-               if (GTK_TOGGLE_BUTTON(both)->active) {
+               if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(both))) {
                        fprintf(fp, "Forward\n");
                        if (ferror(fp)) {
                                write_failure_alert_box(g_dest, errno);
                                fclose(fp);
-                               return;
+                               g_free(g_dest);
+                               return TRUE; /* we're done */
                        }
                }
 
                for(j = 0; j < NUM_COLS; j++) {
                        if (j == 0) {
-                               fprintf(fp,"%s",titles[j]);
+                               fprintf(fp,"\"%s\"",titles[j]);
                        } else {
-                               fprintf(fp,",%s",titles[j]);
+                               fprintf(fp,",\"%s\"",titles[j]);
                        }
                }
                fprintf(fp,"\n");
                if (ferror(fp)) {
                        write_failure_alert_box(g_dest, errno);
                        fclose(fp);
-                       return;
+                       g_free(g_dest);
+                       return TRUE;
                }
                model = gtk_tree_view_get_model(GTK_TREE_VIEW(user_data->dlg.list_fwd));
                store = GTK_LIST_STORE(model);
                if( gtk_tree_model_get_iter_first(GTK_TREE_MODEL(store), &iter) ) {
-                        
-                        selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(user_data->dlg.list_fwd));
-                       
-                        while (gtk_tree_model_iter_next (model,&iter)) {
-                                gtk_tree_model_get(GTK_TREE_MODEL(store), &iter, 
-                                        0, &packet,
-                                        1, &sequence,
-                                        2, &delta,
-                                        3, &jitter,
-                                        4, &ipbw,
-                                        5, &marker,
-                                        6, &status_str,
-                                        7, &date_str,
-                                        8, &length,
+
+                        while (more_items){
+                                gtk_tree_model_get(GTK_TREE_MODEL(store), &iter,
+                                                   PACKET_COLUMN,    &packet,
+                                                   SEQUENCE_COLUMN,  &sequence,
+                                                   TIMESTAMP_COLUMN, &timestamp,
+                                                   DELTA_COLUMN,     &delta,
+                                                   JITTER_COLUMN,    &jitter,
+                                                   SKEW_COLUMN,      &skew,
+                                                   IPBW_COLUMN,      &ipbw,
+                                                   MARKER_COLUMN,    &marker,
+                                                   STATUS_COLUMN,    &status_str,
+                                                   DATE_COLUMN,      &date_str,
+                                                   LENGTH_COLUMN,    &length,
                                         -1);
-                                fprintf(fp, "%u",packet);
-                                fprintf(fp, ",%u", sequence);
-                                fprintf(fp, ",%.2f", delta);
-                                fprintf(fp, ",%.2f", jitter);
-                                fprintf(fp, ",%.2f", ipbw);
-                                fprintf(fp, ",%s", marker? "SET" : "");
-                                fprintf(fp, ",%s", status_str);
-                                fprintf(fp, ",%s", date_str);
-                                fprintf(fp, ",%u", length);
+                                fprintf(fp, "\"%u\"",    packet);
+                                fprintf(fp, ",\"%u\"",   sequence);
+                                fprintf(fp, ",\"%u\"",   timestamp);
+                                fprintf(fp, ",\"%.2f\"", delta);
+                                fprintf(fp, ",\"%.2f\"", jitter);
+                                fprintf(fp, ",\"%.2f\"", skew);
+                                fprintf(fp, ",\"%.2f\"", ipbw);
+                                fprintf(fp, ",\"%s\"",   marker? "SET" : "");
+                                fprintf(fp, ",\"%s\"",   status_str);
+                                fprintf(fp, ",\"%s\"",   date_str);
+                                fprintf(fp, ",\"%u\"",   length);
                                 fprintf(fp,"\n");
-                        }
-                        if (ferror(fp)) {
-                                write_failure_alert_box(g_dest, errno);
-                                fclose(fp);
-                                return;
+                                g_free(status_str);
+                                g_free(date_str);
+                                if (ferror(fp)) {
+                                        write_failure_alert_box(g_dest, errno);
+                                        fclose(fp);
+                                        g_free(g_dest);
+                                        return TRUE; /* we're done */
+                                }
+
+                                more_items = gtk_tree_model_iter_next (model,&iter);
                         }
                 }
 
                if (fclose(fp) == EOF) {
                        write_failure_alert_box(g_dest, errno);
-                       return;
+                       g_free(g_dest);
+                       return TRUE; /* we're done */
                }
        }
 
-       if (GTK_TOGGLE_BUTTON(rev)->active || GTK_TOGGLE_BUTTON(both)->active) {
+       if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(rev)) || gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(both))) {
 
-               if (GTK_TOGGLE_BUTTON(both)->active) {
+               if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(both))) {
                        fp = ws_fopen(g_dest, "a");
                        if (fp == NULL) {
                                open_failure_alert_box(g_dest, errno, TRUE);
-                               return;
+                               g_free(g_dest);
+                               return TRUE; /* we're done */
                        }
                        fprintf(fp, "\nReverse\n");
                        if (ferror(fp)) {
                                write_failure_alert_box(g_dest, errno);
                                fclose(fp);
-                               return;
+                               g_free(g_dest);
+                               return TRUE; /* we're done */
                        }
                } else {
                        fp = ws_fopen(g_dest, "w");
                        if (fp == NULL) {
                                open_failure_alert_box(g_dest, errno, TRUE);
-                               return;
+                               g_free(g_dest);
+                               return TRUE; /* we're done */
                        }
                }
                for(j = 0; j < NUM_COLS; j++) {
                        if (j == 0) {
-                               fprintf(fp,"%s",titles[j]);
+                               fprintf(fp,"\"%s\"",titles[j]);
                        } else {
-                               fprintf(fp,",%s",titles[j]);
+                               fprintf(fp,",\"%s\"",titles[j]);
                        }
                }
                fprintf(fp,"\n");
                if (ferror(fp)) {
                        write_failure_alert_box(g_dest, errno);
                        fclose(fp);
-                       return;
+                       g_free(g_dest);
+                       return TRUE; /* we're done */
                }
                model = gtk_tree_view_get_model(GTK_TREE_VIEW(user_data->dlg.list_rev));
                store = GTK_LIST_STORE(model);
                if( gtk_tree_model_get_iter_first(GTK_TREE_MODEL(store), &iter) ) {
-                        
-                        selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(user_data->dlg.list_rev));
-                       
-                        while (gtk_tree_model_iter_next (model,&iter)) {
-                                gtk_tree_model_get(GTK_TREE_MODEL(store), &iter, 
-                                        0, &packet,
-                                        1, &sequence,
-                                        2, &delta,
-                                        3, &jitter,
-                                        4, &ipbw,
-                                        5, &marker,
-                                        6, &status_str,
-                                        7, &date_str,
-                                        8, &length,
+
+                       more_items = TRUE;
+
+                        while (more_items){
+                                gtk_tree_model_get(GTK_TREE_MODEL(store), &iter,
+                                        PACKET_COLUMN,    &packet,
+                                        SEQUENCE_COLUMN,  &sequence,
+                                        TIMESTAMP_COLUMN, &timestamp,
+                                        DELTA_COLUMN,     &delta,
+                                        JITTER_COLUMN,    &jitter,
+                                        SKEW_COLUMN,      &skew,
+                                        IPBW_COLUMN,      &ipbw,
+                                        MARKER_COLUMN,    &marker,
+                                        STATUS_COLUMN,    &status_str,
+                                        DATE_COLUMN,      &date_str,
+                                        LENGTH_COLUMN,    &length,
                                         -1);
-                                fprintf(fp, "%u",packet);
-                                fprintf(fp, ",%u", sequence);
-                                fprintf(fp, ",%.2f", delta);
-                                fprintf(fp, ",%.2f", jitter);
-                                fprintf(fp, ",%.2f", ipbw);
-                                fprintf(fp, ",%s", marker? "SET" : "");
-                                fprintf(fp, ",%s", status_str);
-                                fprintf(fp, ",%s", date_str);
-                                fprintf(fp, ",%u", length);
+                                fprintf(fp, "\"%u\"",    packet);
+                                fprintf(fp, ",\"%u\"",   sequence);
+                                fprintf(fp, ",\"%u\"",   timestamp);
+                                fprintf(fp, ",\"%.2f\"", delta);
+                                fprintf(fp, ",\"%.2f\"", jitter);
+                                fprintf(fp, ",\"%.2f\"", skew);
+                                fprintf(fp, ",\"%.2f\"", ipbw);
+                                fprintf(fp, ",\"%s\"",   marker? "SET" : "");
+                                fprintf(fp, ",\"%s\"",   status_str);
+                                fprintf(fp, ",\"%s\"",   date_str);
+                                fprintf(fp, ",\"%u\"",   length);
                                 fprintf(fp,"\n");
-                        }
-                        if (ferror(fp)) {
-                                write_failure_alert_box(g_dest, errno);
-                                fclose(fp);
-                                return;
+                                g_free(status_str);
+                                g_free(date_str);
+                                if (ferror(fp)) {
+                                        write_failure_alert_box(g_dest, errno);
+                                        fclose(fp);
+                                        g_free(g_dest);
+                                        return TRUE; /* we're done */
+                                }
+
+                                more_items = gtk_tree_model_iter_next (model,&iter);
                         }
                 }
                if (fclose(fp) == EOF) {
                        write_failure_alert_box(g_dest, errno);
-                       return;
+                       g_free(g_dest);
+                       return TRUE; /* we're done */
                }
        }
 
-       window_destroy(GTK_WIDGET(user_data->dlg.save_csv_as_w));
+       g_free(g_dest);
+       return TRUE; /* we're done */
 }
 
-static void save_csv_as_destroy_cb(GtkWidget *win _U_, user_data_t *user_data _U_)
+static void save_csv_as_destroy_cb(GtkWidget *win _U_, user_data_t *user_data)
 {
        user_data->dlg.save_csv_as_w = NULL;
 }
 
 /* when the user wants to save the csv information in a file */
-static void save_csv_as_cb(GtkWidget *bt _U_, user_data_t *user_data _U_)
+static void save_csv_as_cb(GtkWidget *bt _U_, user_data_t *user_data)
 {
        GtkWidget *vertb;
        GtkWidget *table1;
        GtkWidget *label_format;
        GtkWidget *channels_label;
-       GSList *channels_group = NULL;
        GtkWidget *forward_rb;
        GtkWidget *reversed_rb;
        GtkWidget *both_rb;
 
+#if 0  /* XXX: GtkFileChooserDialog/gtk_dialog_run currently being used is effectively modal so this is not req'd */
        if (user_data->dlg.save_csv_as_w != NULL) {
                /* There's already a Save CSV info dialog box; reactivate it. */
                reactivate_window(user_data->dlg.save_csv_as_w);
                return;
        }
-
-       user_data->dlg.save_csv_as_w = gtk_file_chooser_dialog_new("Wireshark: Save Data As CSV", GTK_WINDOW(user_data->dlg.notebook), GTK_FILE_CHOOSER_ACTION_SAVE,
-                                    GTK_STOCK_OK, GTK_RESPONSE_ACCEPT,
-                                    GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
-                                    NULL);
+#endif
+       user_data->dlg.save_csv_as_w = gtk_file_chooser_dialog_new("Wireshark: Save Data As CSV",
+                                                                  GTK_WINDOW(user_data->dlg.notebook),
+                                                                  GTK_FILE_CHOOSER_ACTION_SAVE,
+                                                                  GTK_STOCK_OK, GTK_RESPONSE_ACCEPT,
+                                                                  GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
+                                                                  NULL);
+       gtk_file_chooser_set_do_overwrite_confirmation(GTK_FILE_CHOOSER(user_data->dlg.save_csv_as_w), TRUE);
+       gtk_window_set_transient_for(GTK_WINDOW(user_data->dlg.save_csv_as_w),GTK_WINDOW(user_data->dlg.window));
 
        /* Container for each row of widgets */
        vertb = gtk_vbox_new(FALSE, 0);
@@ -2102,30 +2282,29 @@ static void save_csv_as_cb(GtkWidget *bt _U_, user_data_t *user_data _U_)
                (GtkAttachOptions) (GTK_FILL),
                (GtkAttachOptions) (0), 0, 0);
 
+       gtk_misc_set_alignment (GTK_MISC (label_format), 0, 0.5f);
 
-       channels_label = gtk_label_new ("Channels:");
+
+       channels_label = gtk_label_new ("Channels:    ");
        gtk_widget_show (channels_label);
        gtk_table_attach (GTK_TABLE (table1), channels_label, 0, 1, 1, 2,
                (GtkAttachOptions) (GTK_FILL),
                (GtkAttachOptions) (0), 0, 0);
-       gtk_misc_set_alignment (GTK_MISC (channels_label), 0, 0.5);
+       gtk_misc_set_alignment (GTK_MISC (channels_label), 0, 0.5f);
 
-       forward_rb = gtk_radio_button_new_with_label (channels_group, "forward  ");
-       channels_group = gtk_radio_button_get_group (GTK_RADIO_BUTTON (forward_rb));
+       forward_rb = gtk_radio_button_new_with_label (NULL, "forward  ");
        gtk_widget_show (forward_rb);
        gtk_table_attach (GTK_TABLE (table1), forward_rb, 1, 2, 1, 2,
                (GtkAttachOptions) (GTK_FILL),
                (GtkAttachOptions) (0), 0, 0);
 
-       reversed_rb = gtk_radio_button_new_with_label (channels_group, "reversed");
-       channels_group = gtk_radio_button_get_group (GTK_RADIO_BUTTON (reversed_rb));
+       reversed_rb = gtk_radio_button_new_with_label_from_widget (GTK_RADIO_BUTTON(forward_rb), "reversed    ");
        gtk_widget_show (reversed_rb);
        gtk_table_attach (GTK_TABLE (table1), reversed_rb, 2, 3, 1, 2,
                (GtkAttachOptions) (GTK_FILL),
                (GtkAttachOptions) (0), 0, 0);
 
-       both_rb = gtk_radio_button_new_with_label (channels_group, "both");
-       channels_group = gtk_radio_button_get_group (GTK_RADIO_BUTTON (both_rb));
+       both_rb = gtk_radio_button_new_with_label_from_widget (GTK_RADIO_BUTTON(forward_rb), "both");
        gtk_widget_show (both_rb);
        gtk_table_attach (GTK_TABLE (table1), both_rb, 3, 4, 1, 2,
                (GtkAttachOptions) (GTK_FILL),
@@ -2138,7 +2317,7 @@ static void save_csv_as_cb(GtkWidget *bt _U_, user_data_t *user_data _U_)
        g_object_set_data(G_OBJECT(user_data->dlg.save_csv_as_w), "both_rb", both_rb);
        g_object_set_data(G_OBJECT(user_data->dlg.save_csv_as_w), "user_data", user_data);
 
-       g_signal_connect(user_data->dlg.save_csv_as_w, "delete_event", 
+       g_signal_connect(user_data->dlg.save_csv_as_w, "delete_event",
                G_CALLBACK(window_delete_event_cb), NULL);
        g_signal_connect(user_data->dlg.save_csv_as_w, "destroy",
                G_CALLBACK(save_csv_as_destroy_cb), user_data);
@@ -2146,17 +2325,30 @@ static void save_csv_as_cb(GtkWidget *bt _U_, user_data_t *user_data _U_)
        gtk_widget_show(user_data->dlg.save_csv_as_w);
        window_present(user_data->dlg.save_csv_as_w);
 
-       if (gtk_dialog_run(GTK_DIALOG(user_data->dlg.save_csv_as_w)) == GTK_RESPONSE_ACCEPT){
-               save_csv_as_ok_cb(user_data->dlg.save_csv_as_w, user_data->dlg.save_csv_as_w);
-       }else{
-               window_destroy(user_data->dlg.save_csv_as_w);
+       /* "Run" the GtkFileChooserDialog.                                              */
+       /* Upon exit: If "Accept" run the OK callback.                                  */
+       /*            If the OK callback returns with a FALSE status, re-run the dialog.*/
+       /*            Destroy the window.                                               */
+       /* XXX: If the OK callback pops up an alert box (eg: for an error) it *must*    */
+       /*      return with a TRUE status so that the dialog window will be destroyed.  */
+       /*      Trying to re-run the dialog after popping up an alert box will not work */
+       /*       since the user will not be able to dismiss the alert box.              */
+       /*      The (somewhat unfriendly) effect: the user must re-invoke the           */
+       /*      GtkFileChooserDialog whenever the OK callback pops up an alert box.     */
+       /*                                                                              */
+       /*      ToDo: use GtkFileChooserWidget in a dialog window instead of            */
+       /*            GtkFileChooserDialog.                                             */
+       while (gtk_dialog_run(GTK_DIALOG(user_data->dlg.save_csv_as_w)) == GTK_RESPONSE_ACCEPT) {
+               if (save_csv_as_ok_cb(NULL, user_data->dlg.save_csv_as_w)) {
+                       break; /* we're done */
+               }
        }
-
+       window_destroy(user_data->dlg.save_csv_as_w);
 }
 
 
 /****************************************************************************/
-static void save_voice_as_destroy_cb(GtkWidget *win _U_, user_data_t *user_data _U_)
+static void save_voice_as_destroy_cb(GtkWidget *win _U_, user_data_t *user_data)
 {
        /* Note that we no longer have a Save voice info dialog box. */
        user_data->dlg.save_voice_as_w = NULL;
@@ -2165,6 +2357,7 @@ static void save_voice_as_destroy_cb(GtkWidget *win _U_, user_data_t *user_data
 /****************************************************************************/
 /* here we save it into a file that user specified */
 /* XXX what about endians here? could go something wrong? */
+
 static gboolean copy_file(gchar *dest, gint channels, gint format, user_data_t *user_data)
 {
        FILE *to_stream, *forw_stream, *rev_stream;
@@ -2178,6 +2371,7 @@ static gboolean copy_file(gchar *dest, gint channels, gint format, user_data_t *
        guint32 progbar_count, progbar_quantum, progbar_nextstep = 0, count = 0;
        gboolean stop_flag = FALSE;
        size_t nchars;
+       gboolean ret_val;
 
        forw_stream = ws_fopen(user_data->f_tempname, "rb");
        if (forw_stream == NULL)
@@ -2200,25 +2394,37 @@ static gboolean copy_file(gchar *dest, gint channels, gint format, user_data_t *
 
        if      (format == SAVE_AU_FORMAT) /* au format */
        {
-               /* First we write the .au header. XXX Hope this is endian independant */
+               /* First we write the .au header. XXX Hope this is endian independent */
                /* the magic word 0x2e736e64 == .snd */
                phtonl(pd, 0x2e736e64);
-               nchars=fwrite(pd, 1, 4, to_stream);
+               nchars = fwrite(pd, 1, 4, to_stream);
+               if (nchars != 4)
+                       goto copy_file_err;
                /* header offset == 24 bytes */
                phtonl(pd, 24);
-               nchars=fwrite(pd, 1, 4, to_stream);
+               nchars = fwrite(pd, 1, 4, to_stream);
+               if (nchars != 4)
+                       goto copy_file_err;
                /* total length; it is permitted to set this to 0xffffffff */
                phtonl(pd, -1);
-               nchars=fwrite(pd, 1, 4, to_stream);
+               nchars = fwrite(pd, 1, 4, to_stream);
+               if (nchars != 4)
+                       goto copy_file_err;
                /* encoding format == 16-bit linear PCM */
                phtonl(pd, 3);
-               nchars=fwrite(pd, 1, 4, to_stream);
+               nchars = fwrite(pd, 1, 4, to_stream);
+               if (nchars != 4)
+                       goto copy_file_err;
                /* sample rate == 8000 Hz */
                phtonl(pd, 8000);
-               nchars=fwrite(pd, 1, 4, to_stream);
+               nchars = fwrite(pd, 1, 4, to_stream);
+               if (nchars != 4)
+                       goto copy_file_err;
                /* channels == 1 */
                phtonl(pd, 1);
-               nchars=fwrite(pd, 1, 4, to_stream);
+               nchars = fwrite(pd, 1, 4, to_stream);
+               if (nchars != 4)
+                       goto copy_file_err;
 
 
                switch (channels) {
@@ -2245,20 +2451,12 @@ static gboolean copy_file(gchar *dest, gint channels, gint format, user_data_t *
                                                phtons(pd, sample);
                                        }
                                        else{
-                                               fclose(forw_stream);
-                                               fclose(rev_stream);
-                                               fclose(to_stream);
-                                               destroy_progress_dlg(progbar);
-                                               return FALSE;
+                                               goto copy_file_err;
                                        }
 
                                        fwritten = fwrite(pd, 1, 2, to_stream);
                                        if (fwritten < 2) {
-                                               fclose(forw_stream);
-                                               fclose(rev_stream);
-                                               fclose(to_stream);
-                                               destroy_progress_dlg(progbar);
-                                               return FALSE;
+                                               goto copy_file_err;
                                        }
                                }
                                break;
@@ -2286,20 +2484,12 @@ static gboolean copy_file(gchar *dest, gint channels, gint format, user_data_t *
                                                phtons(pd, sample);
                                        }
                                        else{
-                                               fclose(forw_stream);
-                                               fclose(rev_stream);
-                                               fclose(to_stream);
-                                               destroy_progress_dlg(progbar);
-                                               return FALSE;
+                                               goto copy_file_err;
                                        }
 
                                        rwritten = fwrite(pd, 1, 2, to_stream);
                                        if (rwritten < 2) {
-                                               fclose(forw_stream);
-                                               fclose(rev_stream);
-                                               fclose(to_stream);
-                                               destroy_progress_dlg(progbar);
-                                               return FALSE;
+                                               goto copy_file_err;
                                        }
                                }
                                break;
@@ -2314,11 +2504,11 @@ static gboolean copy_file(gchar *dest, gint channels, gint format, user_data_t *
                                 * we have to write some silence information for one channel */
                                if (user_data->forward.statinfo.start_time > user_data->reversed.statinfo.start_time) {
                                        f_write_silence = (guint32)
-                                               ((user_data->forward.statinfo.start_time-user_data->reversed.statinfo.start_time)*8000);
+                                               ((user_data->forward.statinfo.start_time-user_data->reversed.statinfo.start_time)*(8000/1000));
                                }
                                else if (user_data->forward.statinfo.start_time < user_data->reversed.statinfo.start_time) {
                                        r_write_silence = (guint32)
-                                               ((user_data->reversed.statinfo.start_time-user_data->forward.statinfo.start_time)*8000);
+                                               ((user_data->reversed.statinfo.start_time-user_data->forward.statinfo.start_time)*(8000/1000));
                                }
                                for(;;) {
                                        if(stop_flag)
@@ -2375,21 +2565,13 @@ static gboolean copy_file(gchar *dest, gint channels, gint format, user_data_t *
                                        }
                                        else
                                        {
-                                               fclose(forw_stream);
-                                               fclose(rev_stream);
-                                               fclose(to_stream);
-                                               destroy_progress_dlg(progbar);
-                                               return FALSE;
+                                               goto copy_file_err;
                                        }
 
 
                                        rwritten = fwrite(pd, 1, 2, to_stream);
                                        if (rwritten < 2) {
-                                               fclose(forw_stream);
-                                               fclose(rev_stream);
-                                               fclose(to_stream);
-                                               destroy_progress_dlg(progbar);
-                                               return FALSE;
+                                               goto copy_file_err;
                                        }
                                }
                        }
@@ -2414,11 +2596,7 @@ static gboolean copy_file(gchar *dest, gint channels, gint format, user_data_t *
                                break;
                        }
                        default: {
-                               fclose(forw_stream);
-                               fclose(rev_stream);
-                               fclose(to_stream);
-                               destroy_progress_dlg(progbar);
-                               return FALSE;
+                               goto copy_file_err;
                        }
                }
 
@@ -2436,55 +2614,63 @@ static gboolean copy_file(gchar *dest, gint channels, gint format, user_data_t *
                        count++;
 
                        if (putc(rawvalue, to_stream) == EOF) {
-                               fclose(forw_stream);
-                               fclose(rev_stream);
-                               fclose(to_stream);
-                               destroy_progress_dlg(progbar);
-                               return FALSE;
+                               goto copy_file_err;
                        }
                }
        }
 
+       ret_val = TRUE;
+       goto copy_file_xit;
+
+copy_file_err:
+       ret_val = FALSE;
+       goto copy_file_xit;
+
+copy_file_xit:
        destroy_progress_dlg(progbar);
        fclose(forw_stream);
        fclose(rev_stream);
        fclose(to_stream);
-       return TRUE;
+       return ret_val;
 }
 
 
 /****************************************************************************/
 /* the user wants to save in a file */
 /* XXX support for different formats is currently commented out */
-static void save_voice_as_ok_cb(GtkWidget *ok_bt _U_, gpointer fs _U_)
+static gboolean save_voice_as_ok_cb(GtkWidget *w _U_, gpointer fc)
 {
        gchar *g_dest;
        /*GtkWidget *wav, *sw;*/
        GtkWidget *au, *raw;
        GtkWidget *rev, *forw, *both;
        user_data_t *user_data;
-       gint channels , format;
+       gint channels, format;
 
-       g_dest = g_strdup(gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(fs)));
+       g_dest = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(fc));
 
        /* Perhaps the user specified a directory instead of a file.
-       Check whether they did. */
+        * Check whether they did.
+        */
        if (test_for_directory(g_dest) == EISDIR) {
                /* It's a directory - set the file selection box to display it. */
                set_last_open_dir(g_dest);
                g_free(g_dest);
-               file_selection_set_current_folder(fs, get_last_open_dir());
-               return;
+               file_selection_set_current_folder(fc, get_last_open_dir());
+               gtk_file_chooser_set_current_name(fc, "");
+               return FALSE; /* run the dialog again */
        }
 
-       /*wav = (GtkWidget *)g_object_get_data(G_OBJECT(ok_bt), "wav_rb");
-       sw = (GtkWidget *)g_object_get_data(G_OBJECT(ok_bt), "sw_rb");*/
-       au = (GtkWidget *)g_object_get_data(G_OBJECT(ok_bt), "au_rb");
-       raw = (GtkWidget *)g_object_get_data(G_OBJECT(ok_bt), "raw_rb");
-       rev = (GtkWidget *)g_object_get_data(G_OBJECT(ok_bt), "reversed_rb");
-       forw = (GtkWidget *)g_object_get_data(G_OBJECT(ok_bt), "forward_rb");
-       both = (GtkWidget *)g_object_get_data(G_OBJECT(ok_bt), "both_rb");
-       user_data = (user_data_t *)g_object_get_data(G_OBJECT(ok_bt), "user_data");
+#if 0
+       wav  = (GtkWidget *)g_object_get_data(G_OBJECT(fc), "wav_rb");
+       sw   = (GtkWidget *)g_object_get_data(G_OBJECT(fc), "sw_rb");
+#endif
+       au   = (GtkWidget *)g_object_get_data(G_OBJECT(fc), "au_rb");
+       raw  = (GtkWidget *)g_object_get_data(G_OBJECT(fc), "raw_rb");
+       rev  = (GtkWidget *)g_object_get_data(G_OBJECT(fc), "reversed_rb");
+       forw = (GtkWidget *)g_object_get_data(G_OBJECT(fc), "forward_rb");
+       both = (GtkWidget *)g_object_get_data(G_OBJECT(fc), "both_rb");
+       user_data = (user_data_t *)g_object_get_data(G_OBJECT(fc), "user_data");
 
        /* XXX user clicks the ok button, but we know we can't save the voice info because f.e.
        * we don't support that codec. So we pop up a warning. Maybe it would be better to
@@ -2495,7 +2681,7 @@ static void save_voice_as_ok_cb(GtkWidget *ok_bt _U_, gpointer fs _U_)
        */
 
        /* we can not save in both directions */
-       if ((user_data->forward.saveinfo.saved == FALSE) && (user_data->reversed.saveinfo.saved == FALSE) && (GTK_TOGGLE_BUTTON (both)->active)) {
+       if ((user_data->forward.saveinfo.saved == FALSE) && (user_data->reversed.saveinfo.saved == FALSE) && (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON (both)))) {
                /* there are many combinations here, we just exit when first matches */
                if ((user_data->forward.saveinfo.error_type == TAP_RTP_WRONG_CODEC) ||
                        (user_data->reversed.saveinfo.error_type == TAP_RTP_WRONG_CODEC))
@@ -2516,11 +2702,12 @@ static void save_voice_as_ok_cb(GtkWidget *ok_bt _U_, gpointer fs _U_)
                else
                        simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
                        "Can't save in a file: File I/O problem!");
-               return;
+               g_free(g_dest);
+               return TRUE; /* we're done */
        }
        /* we can not save forward direction */
-       else if ((user_data->forward.saveinfo.saved == FALSE) && ((GTK_TOGGLE_BUTTON (forw)->active) ||
-               (GTK_TOGGLE_BUTTON (both)->active))) {
+       else if ((user_data->forward.saveinfo.saved == FALSE) && ((gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON (forw))) ||
+               (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON (both))))) {
                if (user_data->forward.saveinfo.error_type == TAP_RTP_WRONG_CODEC)
                        simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
                        "Can't save forward direction in a file: Unsupported codec!");
@@ -2536,11 +2723,12 @@ static void save_voice_as_ok_cb(GtkWidget *ok_bt _U_, gpointer fs _U_)
                else
                        simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
                        "Can't save forward direction in a file: File I/O problem!");
-               return;
+               g_free(g_dest);
+               return TRUE; /* we're done */
        }
        /* we can not save reversed direction */
-       else if ((user_data->reversed.saveinfo.saved == FALSE) && ((GTK_TOGGLE_BUTTON (rev)->active) ||
-               (GTK_TOGGLE_BUTTON (both)->active))) {
+       else if ((user_data->reversed.saveinfo.saved == FALSE) && ((gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON (rev))) ||
+               (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON (both))))) {
                if (user_data->reversed.saveinfo.error_type == TAP_RTP_WRONG_CODEC)
                        simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
                        "Can't save reversed direction in a file: Unsupported codec!");
@@ -2559,23 +2747,29 @@ static void save_voice_as_ok_cb(GtkWidget *ok_bt _U_, gpointer fs _U_)
                else
                        simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
                        "Can't save reversed direction in a file: File I/O problem!");
-               return;
+               g_free(g_dest);
+               return TRUE; /* we're done */
        }
 
-       /*if (GTK_TOGGLE_BUTTON (wav)->active)
-       format = SAVE_WAV_FORMAT;
-       else */if (GTK_TOGGLE_BUTTON (au)->active)
-       format = SAVE_AU_FORMAT;
-       /*else if (GTK_TOGGLE_BUTTON (sw)->active)
-       format = SAVE_SW_FORMAT;*/
-       else if (GTK_TOGGLE_BUTTON (raw)->active)
-       format = SAVE_RAW_FORMAT;
+#if 0
+       if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON (wav)))
+               format = SAVE_WAV_FORMAT;
        else
-       format = SAVE_NONE_FORMAT;
+#endif
+       if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON (au)))
+               format = SAVE_AU_FORMAT;
+#if 0
+       else if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON (sw)))
+               format = SAVE_SW_FORMAT;
+#endif
+       else if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON (raw)))
+               format = SAVE_RAW_FORMAT;
+       else
+               format = SAVE_NONE_FORMAT;
 
-       if (GTK_TOGGLE_BUTTON (rev)->active)
+       if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON (rev)))
                channels = SAVE_REVERSE_DIRECTION_MASK;
-       else if (GTK_TOGGLE_BUTTON (both)->active)
+       else if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON (both)))
                channels = SAVE_BOTH_DIRECTION_MASK;
        else
                channels = SAVE_FORWARD_DIRECTION_MASK;
@@ -2587,18 +2781,21 @@ static void save_voice_as_ok_cb(GtkWidget *ok_bt _U_, gpointer fs _U_)
                if ((channels & SAVE_FORWARD_DIRECTION_MASK) && (user_data->forward.statinfo.pt != PT_PCMA) && (user_data->forward.statinfo.pt != PT_PCMU)){
                        simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
                                "Can't save in a file: saving in au format supported only for alaw/ulaw streams");
-                       return;
+                       g_free(g_dest);
+                       return TRUE; /* we're done */
                }
                if ((channels & SAVE_REVERSE_DIRECTION_MASK) && (user_data->reversed.statinfo.pt != PT_PCMA) && (user_data->reversed.statinfo.pt != PT_PCMU)){
                        simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
                                "Can't save in a file: saving in au format supported only for alaw/ulaw streams");
-                       return;
+                       g_free(g_dest);
+                       return TRUE; /* we're done */
                }
                /* make sure pt's don't differ */
                if ((channels == SAVE_BOTH_DIRECTION_MASK) && (user_data->forward.statinfo.pt != user_data->reversed.statinfo.pt)){
                        simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
                                "Can't save in a file: Forward and reverse direction differ in type");
-                       return;
+                       g_free(g_dest);
+                       return TRUE; /* we're done */
                }
        }
        else if (format == SAVE_RAW_FORMAT)
@@ -2607,37 +2804,39 @@ static void save_voice_as_ok_cb(GtkWidget *ok_bt _U_, gpointer fs _U_)
                if (channels == SAVE_BOTH_DIRECTION_MASK){
                        simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
                                "Can't save in a file: Unable to save raw data in both directions");
-                       return;
+                       g_free(g_dest);
+                       return TRUE; /* we're done */
                }
        }
        else
        {
                simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
                        "Can't save in a file: Invalid save format");
-               return;
+               g_free(g_dest);
+               return TRUE; /* we're done */
        }
 
        if(!copy_file(g_dest, channels, format, user_data)) {
                /* XXX - report the error type! */
                simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
                        "An error occurred while saving voice in a file!");
-               return;
+               g_free(g_dest);
+               return TRUE; /* we're done */
        }
 
-       window_destroy(GTK_WIDGET(user_data->dlg.save_voice_as_w));
+       g_free(g_dest);
+       return TRUE; /* we're done */
 }
 
 /****************************************************************************/
 /* when the user wants to save the voice information in a file */
 /* XXX support for different formats is currently commented out */
-static void on_save_bt_clicked(GtkWidget *bt _U_, user_data_t *user_data _U_)
+static void on_save_bt_clicked(GtkWidget *bt _U_, user_data_t *user_data)
 {
        GtkWidget *vertb;
        GtkWidget *table1;
        GtkWidget *label_format;
        GtkWidget *channels_label;
-       GSList *format_group = NULL;
-       GSList *channels_group = NULL;
        GtkWidget *forward_rb;
        GtkWidget *reversed_rb;
        GtkWidget *both_rb;
@@ -2646,21 +2845,26 @@ static void on_save_bt_clicked(GtkWidget *bt _U_, user_data_t *user_data _U_)
        GtkWidget *raw_rb;
 
        /* if we can't save in a file: wrong codec, cut packets or other errors */
-       /* shold the error arise here or later when you click ok button ?
-       * if we do it here, then we must disable the refresh button, so we don't do it here */
+       /* Should the error arise here or later when you click ok button ?
+        * if we do it here, then we must disable the refresh button, so we don't do it here
+        */
 
+#if 0  /* XXX: GtkFileChooserDialog/gtk_dialog_run currently being used is effectively modal so this is not req'd */
        if (user_data->dlg.save_voice_as_w != NULL) {
                /* There's already a Save voice info dialog box; reactivate it. */
                reactivate_window(user_data->dlg.save_voice_as_w);
                return;
        }
-
-    /* XXX - use file_selection from dlg_utils instead! */
-       user_data->dlg.save_voice_as_w = gtk_file_chooser_dialog_new("Wireshark: Save Payload As ...", GTK_WINDOW(user_data->dlg.notebook), GTK_FILE_CHOOSER_ACTION_SAVE,
-                                    GTK_STOCK_OK, GTK_RESPONSE_ACCEPT,
-                                    GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
-                                    NULL);
-
+#endif
+       /* XXX - use file_selection from dlg_utils instead! */
+       user_data->dlg.save_voice_as_w = gtk_file_chooser_dialog_new("Wireshark: Save Payload As ...",
+                                                                    GTK_WINDOW(user_data->dlg.notebook),
+                                                                    GTK_FILE_CHOOSER_ACTION_SAVE,
+                                                                    GTK_STOCK_OK, GTK_RESPONSE_ACCEPT,
+                                                                    GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
+                                                                    NULL);
+       gtk_file_chooser_set_do_overwrite_confirmation(GTK_FILE_CHOOSER(user_data->dlg.save_voice_as_w), TRUE);
+       gtk_window_set_transient_for(GTK_WINDOW(user_data->dlg.save_voice_as_w),GTK_WINDOW(user_data->dlg.window));
 
        /* Container for each row of widgets */
        vertb = gtk_vbox_new(FALSE, 0);
@@ -2686,80 +2890,75 @@ static void on_save_bt_clicked(GtkWidget *bt _U_, user_data_t *user_data _U_)
                (GtkAttachOptions) (GTK_FILL),
                (GtkAttachOptions) (0), 0, 0);
 
-       gtk_misc_set_alignment (GTK_MISC (label_format), 0, 0.5);
+       gtk_misc_set_alignment (GTK_MISC (label_format), 0, 0.5f);
 
-       raw_rb = gtk_radio_button_new_with_label (format_group, ".raw");
-       format_group = gtk_radio_button_get_group (GTK_RADIO_BUTTON (raw_rb));
+       raw_rb = gtk_radio_button_new_with_label (NULL, ".raw");
        gtk_widget_show (raw_rb);
        gtk_table_attach (GTK_TABLE (table1), raw_rb, 1, 2, 0, 1,
        (GtkAttachOptions) (GTK_FILL),
        (GtkAttachOptions) (0), 0, 0);
 
 
-       au_rb = gtk_radio_button_new_with_label (format_group, ".au");
-       format_group = gtk_radio_button_get_group (GTK_RADIO_BUTTON (au_rb));
+       au_rb = gtk_radio_button_new_with_label_from_widget (GTK_RADIO_BUTTON(raw_rb), ".au");
        gtk_widget_show (au_rb);
        gtk_table_attach (GTK_TABLE (table1), au_rb, 3, 4, 0, 1,
        (GtkAttachOptions) (GTK_FILL),
        (GtkAttachOptions) (0), 0, 0);
 
+#if 0
        /* we support .au - ulaw*/
-       /*      wav_rb = gtk_radio_button_new_with_label (format_group, ".wav");
-       format_group = gtk_radio_button_get_group (GTK_RADIO_BUTTON (wav_rb));
+       wav_rb = gtk_radio_button_new_with_label_from_widget (GTK_RADIO_BUTTON(raw_rb), ".wav");
        gtk_widget_show (wav_rb);
        gtk_table_attach (GTK_TABLE (table1), wav_rb, 1, 2, 0, 1,
        (GtkAttachOptions) (GTK_FILL),
        (GtkAttachOptions) (0), 0, 0);
 
-         sw_rb = gtk_radio_button_new_with_label (format_group, "8 kHz, 16 bit  ");
-         format_group = gtk_radio_button_get_group (GTK_RADIO_BUTTON (sw_rb));
-         gtk_widget_show (sw_rb);
-         gtk_table_attach (GTK_TABLE (table1), sw_rb, 2, 3, 0, 1,
-         (GtkAttachOptions) (GTK_FILL),
-         (GtkAttachOptions) (0), 0, 0);
-         au_rb = gtk_radio_button_new_with_label (format_group, ".au");
-         format_group = gtk_radio_button_get_group (GTK_RADIO_BUTTON (au_rb));
-         gtk_widget_show (au_rb);
-         gtk_table_attach (GTK_TABLE (table1), au_rb, 3, 4, 0, 1,
-         (GtkAttachOptions) (GTK_FILL),
-         (GtkAttachOptions) (0), 0, 0);
-       */
-
+       sw_rb = gtk_radio_button_new_with_label_from_widget (GTK_RADIO_BUTTON(raw_rb), "8 kHz, 16 bit  ");
+       gtk_widget_show (sw_rb);
+       gtk_table_attach (GTK_TABLE (table1), sw_rb, 2, 3, 0, 1,
+                         (GtkAttachOptions) (GTK_FILL),
+                         (GtkAttachOptions) (0), 0, 0);
+       au_rb = gtk_radio_button_new_with_label_from_widget (GTK_RADIO_BUTTON(raw_rb), ".au");
+       gtk_widget_show (au_rb);
+       gtk_table_attach (GTK_TABLE (table1), au_rb, 3, 4, 0, 1,
+                         (GtkAttachOptions) (GTK_FILL),
+                         (GtkAttachOptions) (0), 0, 0);
+#endif
 
-       channels_label = gtk_label_new ("Channels:");
+       channels_label = gtk_label_new ("Channels:    ");
        gtk_widget_show (channels_label);
        gtk_table_attach (GTK_TABLE (table1), channels_label, 0, 1, 1, 2,
                (GtkAttachOptions) (GTK_FILL),
                (GtkAttachOptions) (0), 0, 0);
-       gtk_misc_set_alignment (GTK_MISC (channels_label), 0, 0.5);
+       gtk_misc_set_alignment (GTK_MISC (channels_label), 0, 0.5f);
 
-       forward_rb = gtk_radio_button_new_with_label (channels_group, "forward  ");
-       channels_group = gtk_radio_button_get_group (GTK_RADIO_BUTTON (forward_rb));
+       forward_rb = gtk_radio_button_new_with_label (NULL, "forward    ");
        gtk_widget_show (forward_rb);
        gtk_table_attach (GTK_TABLE (table1), forward_rb, 1, 2, 1, 2,
                (GtkAttachOptions) (GTK_FILL),
                (GtkAttachOptions) (0), 0, 0);
 
-       reversed_rb = gtk_radio_button_new_with_label (channels_group, "reversed");
-       channels_group = gtk_radio_button_get_group (GTK_RADIO_BUTTON (reversed_rb));
+       reversed_rb = gtk_radio_button_new_with_label_from_widget (GTK_RADIO_BUTTON(forward_rb), "reversed    ");
        gtk_widget_show (reversed_rb);
        gtk_table_attach (GTK_TABLE (table1), reversed_rb, 2, 3, 1, 2,
-               (GtkAttachOptions) (GTK_FILL),
-               (GtkAttachOptions) (0), 0, 0);
+                         (GtkAttachOptions) (GTK_FILL),
+                         (GtkAttachOptions) (0), 0, 0);
 
-       both_rb = gtk_radio_button_new_with_label (channels_group, "both");
-       channels_group = gtk_radio_button_get_group (GTK_RADIO_BUTTON (both_rb));
+       both_rb = gtk_radio_button_new_with_label_from_widget (GTK_RADIO_BUTTON(forward_rb), "both");
        gtk_widget_show (both_rb);
        gtk_table_attach (GTK_TABLE (table1), both_rb, 3, 4, 1, 2,
-               (GtkAttachOptions) (GTK_FILL),
-               (GtkAttachOptions) (0), 0, 0);
+                         (GtkAttachOptions) (GTK_FILL),
+                         (GtkAttachOptions) (0), 0, 0);
 
-       gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(both_rb), TRUE);
 
+       gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(forward_rb), TRUE);
+
+#if 0
        /* if one direction is nok we don't allow saving
        XXX this is not ok since the user can click the refresh button and cause changes
        but we can not update this window. So we move all the decision on the time the ok
        button is clicked
+       */
        if (user_data->forward.saved == FALSE) {
        gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(reversed_rb), TRUE);
        gtk_widget_set_sensitive(forward_rb, FALSE);
@@ -2769,30 +2968,44 @@ static void on_save_bt_clicked(GtkWidget *bt _U_, user_data_t *user_data _U_)
        gtk_widget_set_sensitive(reversed_rb, FALSE);
        gtk_widget_set_sensitive(both_rb, FALSE);
        }
-       */
+ #endif
 
-       /*g_object_set_data(G_OBJECT(ok_bt), "wav_rb", wav_rb);*/
+       /*g_object_set_data(G_OBJECT(user_data->dlg.save_voice_as_w), "wav_rb", wav_rb);*/
        g_object_set_data(G_OBJECT(user_data->dlg.save_voice_as_w), "au_rb", au_rb);
-       /*g_object_set_data(G_OBJECT(ok_bt), "sw_rb", sw_rb);*/
+       /*g_object_set_data(G_OBJECT(user_data->dlg.save_voice_as_w), "sw_rb", sw_rb);*/
        g_object_set_data(G_OBJECT(user_data->dlg.save_voice_as_w), "raw_rb", raw_rb);
        g_object_set_data(G_OBJECT(user_data->dlg.save_voice_as_w), "forward_rb", forward_rb);
        g_object_set_data(G_OBJECT(user_data->dlg.save_voice_as_w), "reversed_rb", reversed_rb);
        g_object_set_data(G_OBJECT(user_data->dlg.save_voice_as_w), "both_rb", both_rb);
        g_object_set_data(G_OBJECT(user_data->dlg.save_voice_as_w), "user_data", user_data);
 
-    g_signal_connect(user_data->dlg.save_voice_as_w, "delete_event",
-                        G_CALLBACK(window_delete_event_cb), NULL);
+       g_signal_connect(user_data->dlg.save_voice_as_w, "delete_event",
+                        G_CALLBACK(window_delete_event_cb), NULL);
        g_signal_connect(user_data->dlg.save_voice_as_w, "destroy",
-                        G_CALLBACK(save_voice_as_destroy_cb), user_data);
+                        G_CALLBACK(save_voice_as_destroy_cb), user_data);
 
        gtk_widget_show(user_data->dlg.save_voice_as_w);
-    window_present(user_data->dlg.save_voice_as_w);
-
-       if (gtk_dialog_run(GTK_DIALOG(user_data->dlg.save_voice_as_w)) == GTK_RESPONSE_ACCEPT){
-               save_voice_as_ok_cb(user_data->dlg.save_voice_as_w, user_data->dlg.save_voice_as_w);
-       }else{
-               window_destroy(user_data->dlg.save_voice_as_w);
+       window_present(user_data->dlg.save_voice_as_w);
+
+       /* "Run" the GtkFileChooserDialog.                                              */
+       /* Upon exit: If "Accept" run the OK callback.                                  */
+       /*            If the OK callback returns with a FALSE status, re-run the dialog.*/
+       /*            Destroy the window.                                               */
+       /* XXX: If the OK callback pops up an alert box (eg: for an error) it *must*    */
+       /*      return with a TRUE status so that the dialog window will be destroyed.  */
+       /*      Trying to re-run the dialog after popping up an alert box will not work */
+       /*       since the user will not be able to dismiss the alert box.              */
+       /*      The (somewhat unfriendly) effect: the user must re-invoke the           */
+       /*      GtkFileChooserDialog whenever the OK callback pops up an alert box.     */
+       /*                                                                              */
+       /*      ToDo: use GtkFileChooserWidget in a dialog window instead of            */
+       /*            GtkFileChooserDialog.                                             */
+       while (gtk_dialog_run(GTK_DIALOG(user_data->dlg.save_voice_as_w)) == GTK_RESPONSE_ACCEPT) {
+               if (save_voice_as_ok_cb(NULL, user_data->dlg.save_voice_as_w)) {
+                       break;  /* we're done */
+               }
        }
+       window_destroy(user_data->dlg.save_voice_as_w);
 
 }
 
@@ -2801,42 +3014,88 @@ static void on_save_bt_clicked(GtkWidget *bt _U_, user_data_t *user_data _U_)
 /* when we are finished with redisection, we add the label for the statistic */
 static void draw_stat(user_data_t *user_data)
 {
-       gchar label_max[200];
+       gchar label_max[300];
        guint32 f_expected = (user_data->forward.statinfo.stop_seq_nr + user_data->forward.statinfo.cycles*65536)
                - user_data->forward.statinfo.start_seq_nr + 1;
        guint32 r_expected = (user_data->reversed.statinfo.stop_seq_nr + user_data->reversed.statinfo.cycles*65536)
                - user_data->reversed.statinfo.start_seq_nr + 1;
-       gint32 f_lost = f_expected - user_data->forward.statinfo.total_nr;
-       gint32 r_lost = r_expected - user_data->reversed.statinfo.total_nr;
+       guint32 f_total_nr = user_data->forward.statinfo.total_nr;
+       guint32 r_total_nr = user_data->reversed.statinfo.total_nr;
+       gint32 f_lost = f_expected - f_total_nr;
+       gint32 r_lost = r_expected - r_total_nr;
+       double f_sumt = user_data->forward.statinfo.sumt;
+       double f_sumTS = user_data->forward.statinfo.sumTS;
+       double f_sumt2 = user_data->forward.statinfo.sumt2;
+       double f_sumtTS = user_data->forward.statinfo.sumtTS;
+
+       double r_sumt = user_data->reversed.statinfo.sumt;
+       double r_sumTS = user_data->reversed.statinfo.sumTS;
+       double r_sumt2 = user_data->reversed.statinfo.sumt2;
+       double r_sumtTS = user_data->reversed.statinfo.sumtTS;
        double f_perc, r_perc;
+       double f_clock_drift = 1.0;
+       double r_clock_drift = 1.0;
+       double f_duration = user_data->forward.statinfo.time - user_data->forward.statinfo.start_time;
+       double r_duration = user_data->reversed.statinfo.time - user_data->reversed.statinfo.start_time;
+       guint32 f_clock_rate = user_data->forward.statinfo.clock_rate;
+       guint32 r_clock_rate = user_data->reversed.statinfo.clock_rate;
+
+       if (f_clock_rate == 0){
+               f_clock_rate = 1;
+       }
+
+       if (r_clock_rate == 0){
+               r_clock_rate = 1;
+       }
+
        if (f_expected){
                f_perc = (double)(f_lost*100)/(double)f_expected;
        } else {
                f_perc = 0;
        }
-        if (r_expected){
-                r_perc = (double)(r_lost*100)/(double)r_expected;
-        } else {
-                r_perc = 0;
-        }
+       if (r_expected){
+               r_perc = (double)(r_lost*100)/(double)r_expected;
+       } else {
+               r_perc = 0;
+       }
 
-       g_snprintf(label_max, 199, "Max delta = %f sec at packet no. %u \n"
+       if ((f_total_nr >0)&&(f_sumt2 > 0)){
+               f_clock_drift = (f_total_nr * f_sumtTS - f_sumt * f_sumTS) / (f_total_nr * f_sumt2 - f_sumt * f_sumt);
+       }
+       if ((r_total_nr >0)&&(r_sumt2 > 0)){
+               r_clock_drift = (r_total_nr * r_sumtTS - r_sumt * r_sumTS) / (r_total_nr * r_sumt2 - r_sumt * r_sumt);
+       }
+       g_snprintf(label_max, sizeof(label_max), "Max delta = %.2f ms at packet no. %u \n"
+               "Max jitter = %.2f ms. Mean jitter = %.2f ms.\n"
+               "Max skew = %.2f ms.\n"
                "Total RTP packets = %u   (expected %u)   Lost RTP packets = %d (%.2f%%)"
-               "   Sequence errors = %u",
+               "   Sequence errors = %u \n"
+               "Duration %.2f s (%.0f ms clock drift, corresponding to %.0f Hz (%+.2f%%)",
                user_data->forward.statinfo.max_delta, user_data->forward.statinfo.max_nr,
-               user_data->forward.statinfo.total_nr,
-               f_expected, f_lost, f_perc, user_data->forward.statinfo.sequence);
+               user_data->forward.statinfo.max_jitter,user_data->forward.statinfo.mean_jitter,
+               user_data->forward.statinfo.max_skew,
+               f_expected, f_expected, f_lost, f_perc,
+               user_data->forward.statinfo.sequence,
+               f_duration/1000,f_duration*(f_clock_drift-1.0),f_clock_drift*f_clock_rate,100.0*(f_clock_drift-1.0));
 
        gtk_label_set_text(GTK_LABEL(user_data->dlg.label_stats_fwd), label_max);
+       gtk_label_set_selectable (GTK_LABEL(user_data->dlg.label_stats_fwd),TRUE);
 
-       g_snprintf(label_max, 199, "Max delta = %f sec at packet no. %u \n"
+       g_snprintf(label_max, sizeof(label_max), "Max delta = %.2f ms at packet no. %u \n"
+               "Max jitter = %.2f ms. Mean jitter = %.2f ms.\n"
+               "Max skew = %.2f ms.\n"
                "Total RTP packets = %u   (expected %u)   Lost RTP packets = %d (%.2f%%)"
-               "   Sequence errors = %u",
+               "   Sequence errors = %u \n"
+               "Duration %.2f s (%.0f ms clock drift, corresponding to %.0f Hz (%+.2f%%)",
                user_data->reversed.statinfo.max_delta, user_data->reversed.statinfo.max_nr,
-               user_data->reversed.statinfo.total_nr,
-               r_expected, r_lost, r_perc, user_data->reversed.statinfo.sequence);
+               user_data->reversed.statinfo.max_jitter,user_data->reversed.statinfo.mean_jitter,
+               user_data->reversed.statinfo.max_skew,
+               r_expected, r_expected, r_lost, r_perc,
+               user_data->reversed.statinfo.sequence,
+               r_duration/1000,r_duration*(r_clock_drift-1.0),r_clock_drift*r_clock_rate,100.0*(r_clock_drift-1.0));
 
        gtk_label_set_text(GTK_LABEL(user_data->dlg.label_stats_rev), label_max);
+       gtk_label_set_selectable (GTK_LABEL(user_data->dlg.label_stats_rev),TRUE);
 
        return ;
 }
@@ -2845,42 +3104,39 @@ static void draw_stat(user_data_t *user_data)
 
 /****************************************************************************/
 /* append a line to list */
-static void add_to_list(GtkWidget *list, user_data_t * user_data, guint32 number, guint16 seq_num,
-                         double delta, double jitter, double bandwidth, gchar *status, gboolean marker,
-                         gchar *timeStr, guint32 pkt_len, gchar *color_str, guint32 flags)
+static void add_to_list(GtkWidget *list, user_data_t * user_data, guint32 number, guint16 seq_num, guint32 timestamp,
+                       double delta, double jitter,double skew, double bandwidth, gchar *status, gboolean marker,
+                       gchar *timeStr, guint32 pkt_len, gchar *color_str, guint32 flags)
 {
-    GtkListStore *list_store;
+       GtkListStore *list_store;
 
        if (strcmp(status, OK_TEXT) != 0) {
                user_data->dlg.number_of_nok++;
        }
 
-    list_store = GTK_LIST_STORE(gtk_tree_view_get_model(GTK_TREE_VIEW (list))); /* Get store */
+       list_store = GTK_LIST_STORE(gtk_tree_view_get_model(GTK_TREE_VIEW (list))); /* Get store */
 
-       /* Creates a new row at position. iter will be changed to point to this new row. 
+       /* Creates a new row at position. iter will be changed to point to this new row.
         * If position is larger than the number of rows on the list, then the new row will be appended to the list.
         * The row will be filled with the values given to this function.
         * :
         * should generally be preferred when inserting rows in a sorted list store.
         */
-#if GTK_CHECK_VERSION(2,6,0)
        gtk_list_store_insert_with_values( list_store , &user_data->dlg.iter, G_MAXINT,
-#else
-       gtk_list_store_append  (list_store, &user_data->dlg.iter);
-       gtk_list_store_set  (list_store, &user_data->dlg.iter,
-#endif
-                PACKET_COLUMN, number,
-                SEQUENCE_COLUMN, seq_num,
-                               DELTA_COLUMN, delta,
-                               JITTER_COLUMN, jitter,
-                               IPBW_COLUMN, bandwidth,
-                               MARKER_COLUMN, marker,
-                               STATUS_COLUMN, (char *)status,
-                               DATE_COLUMN,  (char *)timeStr,
-                               LENGTH_COLUMN,  pkt_len,
-                               FOREGROUND_COLOR_COL, NULL,
-                               BACKGROUND_COLOR_COL, (char *)color_str,
-                               -1);
+                            PACKET_COLUMN,        number,
+                            SEQUENCE_COLUMN,      seq_num,
+                            TIMESTAMP_COLUMN,     timestamp,
+                            DELTA_COLUMN,         delta,
+                            JITTER_COLUMN,        jitter,
+                            SKEW_COLUMN,          skew,
+                            IPBW_COLUMN,          bandwidth,
+                            MARKER_COLUMN,        marker,
+                            STATUS_COLUMN,        (char *)status,
+                            DATE_COLUMN,          (char *)timeStr,
+                            LENGTH_COLUMN,        pkt_len,
+                            FOREGROUND_COLOR_COL, NULL,
+                            BACKGROUND_COLOR_COL, (char *)color_str,
+                            -1);
 
        if(flags & STAT_FLAG_FIRST){
                /* Set first row as active */
@@ -2892,231 +3148,233 @@ static void add_to_list(GtkWidget *list, user_data_t * user_data, guint32 number
 * Functions needed to present values from the list
 */
 
-/* Present floats with two decimals */
-static void
-rtp_float_data_func (GtkTreeViewColumn *column _U_,
-                           GtkCellRenderer   *renderer,
-                           GtkTreeModel      *model,
-                           GtkTreeIter       *iter,
-                           gpointer           user_data)
-   {
-     gfloat  float_val;
-     gchar   buf[20];
-        char *savelocale;
-
-        /* the col to get data from is in userdata */
-        gint float_col = GPOINTER_TO_INT(user_data);
-
-     gtk_tree_model_get(model, iter, float_col, &float_val, -1);
-
-        /* save the current locale */
-        savelocale = setlocale(LC_NUMERIC, NULL);
-        /* switch to "C" locale to avoid problems with localized decimal separators
-         * in g_snprintf("%f") functions
-         */
-        setlocale(LC_NUMERIC, "C");
-
-     g_snprintf(buf, sizeof(buf), "%.2f", float_val);
-        /* restore previous locale setting */
-        setlocale(LC_NUMERIC, savelocale);
-
-     g_object_set(renderer, "text", buf, NULL);
-   }
 
 /* Present boolean value */
-void
+static void
 rtp_boolean_data_func (GtkTreeViewColumn *column _U_,
-                           GtkCellRenderer   *renderer,
-                           GtkTreeModel      *model,
-                           GtkTreeIter       *iter,
-                           gpointer           user_data)
-   {
-     gboolean  bool_val;
-     gchar   buf[20];
-        /* the col to get data from is in userdata */
-        gint bool_col = GPOINTER_TO_INT(user_data);
-
-     gtk_tree_model_get(model, iter, bool_col, &bool_val, -1);
-
-        switch(bool_col){
-                case MARKER_COLUMN:
-                        g_snprintf(buf, sizeof(buf), "%s", bool_val? "SET" : "");
-                        break;
-                default:
-                        g_assert_not_reached();
-                        break;
-        }
-     g_object_set(renderer, "text", buf, NULL);
-   }
+                      GtkCellRenderer   *renderer,
+                      GtkTreeModel      *model,
+                      GtkTreeIter       *iter,
+                      gpointer           user_data)
+{
+       gboolean  bool_val;
+       gchar   buf[20];
+       /* the col to get data from is in userdata */
+       gint bool_col = GPOINTER_TO_INT(user_data);
+
+       gtk_tree_model_get(model, iter, bool_col, &bool_val, -1);
+
+       switch(bool_col){
+       case MARKER_COLUMN:
+               g_strlcpy(buf, bool_val ? "SET" : "", sizeof(buf));
+               break;
+       default:
+               g_assert_not_reached();
+               break;
+       }
+       g_object_set(renderer, "text", buf, NULL);
+}
 
 /* Create list */
 static
 GtkWidget* create_list(user_data_t* user_data)
 {
 
-    GtkListStore *list_store;
-    GtkWidget *list;
-    GtkTreeViewColumn *column;
-    GtkCellRenderer *renderer;
-    GtkTreeSortable *sortable;
+       GtkListStore *list_store;
+       GtkWidget *list;
+       GtkTreeViewColumn *column;
+       GtkCellRenderer *renderer;
+       GtkTreeSortable *sortable;
        GtkTreeView     *list_view;
        GtkTreeSelection  *selection;
 
        /* Create the store */
-    list_store = gtk_list_store_new(N_COLUMN,  /* Total number of columns XXX*/
-                               G_TYPE_UINT,            /* Packet                               */
-                               G_TYPE_UINT,            /* Sequence                             */
-                               G_TYPE_FLOAT,   /* Delta(ms)                    */
-                               G_TYPE_FLOAT,   /* Jitter(ms)                   */
-                               G_TYPE_FLOAT,   /* IP BW(kbps)                  */
-                               G_TYPE_BOOLEAN,  /* Marker                              */
-                               G_TYPE_STRING,   /* Status                              */
-                               G_TYPE_STRING,  /* Date                                 */
-                               G_TYPE_UINT,            /* Length                               */
-                                                          G_TYPE_STRING,   /* Foreground color         */
-                                                          G_TYPE_STRING);  /* Background color         */
-
-    /* Create a view */
-    list = gtk_tree_view_new_with_model (GTK_TREE_MODEL (list_store));
+       list_store = gtk_list_store_new(N_COLUMN,       /* Total number of columns XXX  */
+                                       G_TYPE_UINT,    /* Packet                       */
+                                       G_TYPE_UINT,    /* Sequence                     */
+                                       G_TYPE_UINT,    /* Time stamp                   */
+                                       G_TYPE_FLOAT,   /* Delta(ms)                    */
+                                       G_TYPE_FLOAT,   /* Filtered Jitter(ms)          */
+                                       G_TYPE_FLOAT,   /* Skew(ms)                     */
+                                       G_TYPE_FLOAT,   /* IP BW(kbps)                  */
+                                       G_TYPE_BOOLEAN, /* Marker                       */
+                                       G_TYPE_STRING,  /* Status                       */
+                                       G_TYPE_STRING,  /* Date                         */
+                                       G_TYPE_UINT,    /* Length                       */
+                                       G_TYPE_STRING,  /* Foreground color             */
+                                       G_TYPE_STRING); /* Background color             */
+
+       /* Create a view */
+       list = gtk_tree_view_new_with_model (GTK_TREE_MODEL (list_store));
 
        list_view = GTK_TREE_VIEW(list);
        sortable = GTK_TREE_SORTABLE(list_store);
 
-#if GTK_CHECK_VERSION(2,6,0)
        /* Speed up the list display */
        gtk_tree_view_set_fixed_height_mode(list_view, TRUE);
-#endif
 
-    /* Setup the sortable columns */
-    gtk_tree_sortable_set_sort_column_id(sortable, PACKET_COLUMN, GTK_SORT_ASCENDING);
-    gtk_tree_view_set_headers_clickable(list_view, FALSE);
+       /* Setup the sortable columns */
+       gtk_tree_sortable_set_sort_column_id(sortable, PACKET_COLUMN, GTK_SORT_ASCENDING);
+       gtk_tree_view_set_headers_clickable(list_view, FALSE);
 
-    /* The view now holds a reference.  We can get rid of our own reference */
-    g_object_unref (G_OBJECT (list_store));
+       /* The view now holds a reference.  We can get rid of our own reference */
+       g_object_unref (G_OBJECT (list_store));
 
-    /* 
+       /*
         * Create the first column packet, associating the "text" attribute of the
-     * cell_renderer to the first column of the model 
+        * cell_renderer to the first column of the model
         */
-    renderer = gtk_cell_renderer_text_new ();
-    column = gtk_tree_view_column_new_with_attributes ("Packet", renderer, 
-               "text", PACKET_COLUMN, 
-        "foreground", FOREGROUND_COLOR_COL,
-        "background", BACKGROUND_COLOR_COL,
-               NULL);
-    gtk_tree_view_column_set_sort_column_id(column, PACKET_COLUMN);
-    gtk_tree_view_column_set_resizable(column, TRUE);
-    gtk_tree_view_column_set_sizing(column, GTK_TREE_VIEW_COLUMN_FIXED);
-    gtk_tree_view_column_set_min_width(column, 100);
+       renderer = gtk_cell_renderer_text_new ();
+       column = gtk_tree_view_column_new_with_attributes ("Packet", renderer,
+                                                          "text",      PACKET_COLUMN,
+                                                          "foreground", FOREGROUND_COLOR_COL,
+                                                          "background", BACKGROUND_COLOR_COL,
+                                                          NULL);
+       gtk_tree_view_column_set_sort_column_id(column, PACKET_COLUMN);
+       gtk_tree_view_column_set_resizable(column, TRUE);
+       gtk_tree_view_column_set_sizing(column, GTK_TREE_VIEW_COLUMN_FIXED);
+       gtk_tree_view_column_set_min_width(column, 55);
 
        /* Add the column to the view. */
-    gtk_tree_view_append_column (list_view, column);
-
-    /* Second column.. Sequence. */
-    renderer = gtk_cell_renderer_text_new ();
-    column = gtk_tree_view_column_new_with_attributes ("Sequence", renderer, 
-               "text", SEQUENCE_COLUMN,
-        "foreground", FOREGROUND_COLOR_COL,
-        "background", BACKGROUND_COLOR_COL,
-               NULL);
-    gtk_tree_view_column_set_sort_column_id(column, SEQUENCE_COLUMN);
-    gtk_tree_view_column_set_resizable(column, TRUE);
-    gtk_tree_view_column_set_sizing(column, GTK_TREE_VIEW_COLUMN_FIXED);
-    gtk_tree_view_column_set_min_width(column, 100);
-    gtk_tree_view_append_column (list_view, column);
-
-    /* Third column.. Delta(ms). */
-    renderer = gtk_cell_renderer_text_new ();
-       column = gtk_tree_view_column_new_with_attributes ("Delta(ms)", renderer, 
-               "text", DELTA_COLUMN, 
-        "foreground", FOREGROUND_COLOR_COL,
-        "background", BACKGROUND_COLOR_COL,
-               NULL);
-       
-       gtk_tree_view_column_set_cell_data_func(column, renderer, rtp_float_data_func, 
-               GINT_TO_POINTER(DELTA_COLUMN), NULL);
-
-    gtk_tree_view_column_set_sort_column_id(column, DELTA_COLUMN);
-    gtk_tree_view_column_set_resizable(column, TRUE);
-    gtk_tree_view_column_set_sizing(column, GTK_TREE_VIEW_COLUMN_FIXED);
-    gtk_tree_view_column_set_min_width(column, 100);
-    gtk_tree_view_append_column (list_view, column);
-
-    /* Forth column.. Jitter(ms). */
-    renderer = gtk_cell_renderer_text_new ();
-    column = gtk_tree_view_column_new_with_attributes ("Jitter(ms)", renderer, 
-               "text", JITTER_COLUMN, 
-        "foreground", FOREGROUND_COLOR_COL,
-        "background", BACKGROUND_COLOR_COL,
-               NULL);
-
-       gtk_tree_view_column_set_cell_data_func(column, renderer, rtp_float_data_func, 
-               GINT_TO_POINTER(JITTER_COLUMN), NULL);
-
-    gtk_tree_view_column_set_sort_column_id(column, JITTER_COLUMN);
-    gtk_tree_view_column_set_resizable(column, TRUE);
-    gtk_tree_view_column_set_sizing(column, GTK_TREE_VIEW_COLUMN_FIXED);
-    gtk_tree_view_column_set_min_width(column, 100);
-    gtk_tree_view_append_column (list_view, column);
-
-    /* Fifth column.. IP BW(kbps). */
-    renderer = gtk_cell_renderer_text_new ();
-    column = gtk_tree_view_column_new_with_attributes ("IP BW(kbps)", renderer, 
-               "text", IPBW_COLUMN, 
-        "foreground", FOREGROUND_COLOR_COL,
-        "background", BACKGROUND_COLOR_COL,
-               NULL);
-
-       gtk_tree_view_column_set_cell_data_func(column, renderer, rtp_float_data_func, 
-               GINT_TO_POINTER(IPBW_COLUMN), NULL);
-
-    gtk_tree_view_column_set_sort_column_id(column, IPBW_COLUMN);
-    gtk_tree_view_column_set_resizable(column, TRUE);
-    gtk_tree_view_column_set_sizing(column, GTK_TREE_VIEW_COLUMN_FIXED);
-    gtk_tree_view_column_set_min_width(column, 100);
-    gtk_tree_view_append_column (list_view, column);
-
-    /* Sixth column.. Marker. */
-    renderer = gtk_cell_renderer_text_new ();
-    column = gtk_tree_view_column_new_with_attributes ("Marker", renderer, 
-               "text", MARKER_COLUMN, 
-        "foreground", FOREGROUND_COLOR_COL,
-        "background", BACKGROUND_COLOR_COL,
-               NULL);
-
-       gtk_tree_view_column_set_cell_data_func(column, renderer, rtp_boolean_data_func, 
-               GINT_TO_POINTER(MARKER_COLUMN), NULL);
-
-    gtk_tree_view_column_set_sort_column_id(column, MARKER_COLUMN);
-    gtk_tree_view_column_set_resizable(column, TRUE);
-    gtk_tree_view_column_set_sizing(column, GTK_TREE_VIEW_COLUMN_FIXED);
-    gtk_tree_view_column_set_min_width(column, 75);
-    gtk_tree_view_append_column (list_view, column);
-
-        /* Seventh column.. Status. */
-    renderer = gtk_cell_renderer_text_new ();
-    column = gtk_tree_view_column_new_with_attributes ( "Status", renderer, 
-               "text", STATUS_COLUMN,
-        "foreground", FOREGROUND_COLOR_COL,
-        "background", BACKGROUND_COLOR_COL,
-               NULL);
-    gtk_tree_view_column_set_sort_column_id(column, STATUS_COLUMN);
-    gtk_tree_view_column_set_resizable(column, TRUE);
-    gtk_tree_view_column_set_sizing(column, GTK_TREE_VIEW_COLUMN_FIXED);
-    gtk_tree_view_column_set_min_width(column, 100);
-    gtk_tree_view_append_column (list_view, column);
-
-    /* Now enable the sorting of each column */
-    gtk_tree_view_set_rules_hint(GTK_TREE_VIEW(list_view), TRUE);
-    gtk_tree_view_set_headers_clickable(GTK_TREE_VIEW(list_view), TRUE);
+       gtk_tree_view_append_column (list_view, column);
+
+       /* Sequence. */
+       renderer = gtk_cell_renderer_text_new ();
+       column = gtk_tree_view_column_new_with_attributes ("Sequence", renderer,
+                                                          "text", SEQUENCE_COLUMN,
+                                                          "foreground", FOREGROUND_COLOR_COL,
+                                                          "background", BACKGROUND_COLOR_COL,
+                                                          NULL);
+       gtk_tree_view_column_set_sort_column_id(column, SEQUENCE_COLUMN);
+       gtk_tree_view_column_set_resizable(column, TRUE);
+       gtk_tree_view_column_set_sizing(column, GTK_TREE_VIEW_COLUMN_FIXED);
+       gtk_tree_view_column_set_min_width(column, 75);
+       gtk_tree_view_append_column (list_view, column);
+
+#if 0
+       Currently not visible
+               /* Time stamp. */
+               renderer = gtk_cell_renderer_text_new ();
+       column = gtk_tree_view_column_new_with_attributes ("Time stamp", renderer,
+                                                          "text", TIMESTAMP_COLUMN,
+                                                          "foreground", FOREGROUND_COLOR_COL,
+                                                          "background", BACKGROUND_COLOR_COL,
+                                                          NULL);
+       gtk_tree_view_column_set_sort_column_id(column, TIMESTAMP_COLUMN);
+       gtk_tree_view_column_set_resizable(column, TRUE);
+       gtk_tree_view_column_set_sizing(column, GTK_TREE_VIEW_COLUMN_FIXED);
+       gtk_tree_view_column_set_min_width(column, 75);
+       gtk_tree_view_append_column (list_view, column);
+#endif
+       /* Delta(ms). */
+       renderer = gtk_cell_renderer_text_new ();
+       column = gtk_tree_view_column_new_with_attributes ("Delta(ms)", renderer,
+                                                          "text", DELTA_COLUMN,
+                                                          "foreground", FOREGROUND_COLOR_COL,
+                                                          "background", BACKGROUND_COLOR_COL,
+                                                          NULL);
+
+       gtk_tree_view_column_set_cell_data_func(column, renderer, float_data_func,
+                                               GINT_TO_POINTER(DELTA_COLUMN), NULL);
+
+       gtk_tree_view_column_set_sort_column_id(column, DELTA_COLUMN);
+       gtk_tree_view_column_set_resizable(column, TRUE);
+       gtk_tree_view_column_set_sizing(column, GTK_TREE_VIEW_COLUMN_FIXED);
+       gtk_tree_view_column_set_min_width(column, 75);
+       gtk_tree_view_append_column (list_view, column);
+
+       /* Jitter(ms). */
+       renderer = gtk_cell_renderer_text_new ();
+       column = gtk_tree_view_column_new_with_attributes ("Filtered Jitter(ms)", renderer,
+                                                          "text", JITTER_COLUMN,
+                                                          "foreground", FOREGROUND_COLOR_COL,
+                                                          "background", BACKGROUND_COLOR_COL,
+                                                          NULL);
+
+       gtk_tree_view_column_set_cell_data_func(column, renderer, float_data_func,
+                                               GINT_TO_POINTER(JITTER_COLUMN), NULL);
+
+       gtk_tree_view_column_set_sort_column_id(column, JITTER_COLUMN);
+       gtk_tree_view_column_set_resizable(column, TRUE);
+       gtk_tree_view_column_set_sizing(column, GTK_TREE_VIEW_COLUMN_FIXED);
+       gtk_tree_view_column_set_min_width(column, 110);
+       gtk_tree_view_append_column (list_view, column);
+
+       /* Skew(ms). */
+       renderer = gtk_cell_renderer_text_new ();
+       column = gtk_tree_view_column_new_with_attributes ("Skew(ms)", renderer,
+                                                          "text", SKEW_COLUMN,
+                                                          "foreground", FOREGROUND_COLOR_COL,
+                                                          "background", BACKGROUND_COLOR_COL,
+                                                          NULL);
+
+       gtk_tree_view_column_set_cell_data_func(column, renderer, float_data_func,
+                                               GINT_TO_POINTER(SKEW_COLUMN), NULL);
+
+       gtk_tree_view_column_set_sort_column_id(column, SKEW_COLUMN);
+       gtk_tree_view_column_set_resizable(column, TRUE);
+       gtk_tree_view_column_set_sizing(column, GTK_TREE_VIEW_COLUMN_FIXED);
+       gtk_tree_view_column_set_min_width(column, 110);
+       gtk_tree_view_append_column (list_view, column);
+
+       /* IP BW(kbps). */
+       renderer = gtk_cell_renderer_text_new ();
+       column = gtk_tree_view_column_new_with_attributes ("IP BW(kbps)", renderer,
+                                                          "text", IPBW_COLUMN,
+                                                          "foreground", FOREGROUND_COLOR_COL,
+                                                          "background", BACKGROUND_COLOR_COL,
+                                                          NULL);
+
+       gtk_tree_view_column_set_cell_data_func(column, renderer, float_data_func,
+                                               GINT_TO_POINTER(IPBW_COLUMN), NULL);
+
+       gtk_tree_view_column_set_sort_column_id(column, IPBW_COLUMN);
+       gtk_tree_view_column_set_resizable(column, TRUE);
+       gtk_tree_view_column_set_sizing(column, GTK_TREE_VIEW_COLUMN_FIXED);
+       gtk_tree_view_column_set_min_width(column, 80);
+       gtk_tree_view_append_column (list_view, column);
+
+       /* Marker. */
+       renderer = gtk_cell_renderer_text_new ();
+       column = gtk_tree_view_column_new_with_attributes ("Marker", renderer,
+                                                          "text", MARKER_COLUMN,
+                                                          "foreground", FOREGROUND_COLOR_COL,
+                                                          "background", BACKGROUND_COLOR_COL,
+                                                          NULL);
+
+       gtk_tree_view_column_set_cell_data_func(column, renderer, rtp_boolean_data_func,
+                                               GINT_TO_POINTER(MARKER_COLUMN), NULL);
+
+       gtk_tree_view_column_set_sort_column_id(column, MARKER_COLUMN);
+       gtk_tree_view_column_set_resizable(column, TRUE);
+       gtk_tree_view_column_set_sizing(column, GTK_TREE_VIEW_COLUMN_FIXED);
+       gtk_tree_view_column_set_min_width(column, 60);
+       gtk_tree_view_append_column (list_view, column);
+
+       /* Status. */
+       renderer = gtk_cell_renderer_text_new ();
+       column = gtk_tree_view_column_new_with_attributes ( "Status", renderer,
+                                                           "text", STATUS_COLUMN,
+                                                           "foreground", FOREGROUND_COLOR_COL,
+                                                           "background", BACKGROUND_COLOR_COL,
+                                                           NULL);
+       gtk_tree_view_column_set_sort_column_id(column, STATUS_COLUMN);
+       gtk_tree_view_column_set_resizable(column, TRUE);
+       gtk_tree_view_column_set_sizing(column, GTK_TREE_VIEW_COLUMN_FIXED);
+       gtk_tree_view_column_set_min_width(column, 100);
+       gtk_tree_view_append_column (list_view, column);
+
+       /* Now enable the sorting of each column */
+       gtk_tree_view_set_rules_hint(GTK_TREE_VIEW(list_view), TRUE);
+       gtk_tree_view_set_headers_clickable(GTK_TREE_VIEW(list_view), TRUE);
 
        /* Setup the selection handler */
        selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(list));
        gtk_tree_selection_set_mode(selection, GTK_SELECTION_SINGLE);
 
        g_signal_connect (G_OBJECT (selection), "changed", /* select_row */
-                  G_CALLBACK (on_list_select_row),
-                  user_data);
+                         G_CALLBACK (on_list_select_row),
+                         user_data);
        return list;
 }
 
@@ -3135,9 +3393,9 @@ static void create_rtp_dialog(user_data_t* user_data)
        GtkWidget *label;
        GtkWidget *scrolled_window, *scrolled_window_r/*, *frame, *text, *label4, *page_help*/;
        GtkWidget *box4, *voice_bt, *refresh_bt, *goto_bt, *close_bt, *csv_bt, *next_bt;
-#ifdef USE_CONVERSATION_GRAPH
-       GtkWidget *graph_bt;
-#endif
+#ifdef HAVE_LIBPORTAUDIO
+       GtkWidget *player_bt = NULL;
+#endif /* HAVE_LIBPORTAUDIO */
        GtkWidget *graph_bt;
        gchar label_forward[150];
        gchar label_forward_tree[150];
@@ -3146,7 +3404,7 @@ static void create_rtp_dialog(user_data_t* user_data)
        gchar str_ip_src[16];
        gchar str_ip_dst[16];
 
-       window = window_new(GTK_WINDOW_TOPLEVEL, "Wireshark: RTP Stream Analysis");
+       window = dlg_window_new("Wireshark: RTP Stream Analysis");  /* transient_for top_level */
        gtk_window_set_default_size(GTK_WINDOW(window), 700, 400);
 
        /* Container for each row of widgets */
@@ -3156,22 +3414,22 @@ static void create_rtp_dialog(user_data_t* user_data)
        gtk_widget_show(main_vb);
 
        /* Notebooks... */
-       g_strlcpy(str_ip_src, get_addr_name(&(user_data->ip_src_fwd)), 16);
-       g_strlcpy(str_ip_dst, get_addr_name(&(user_data->ip_dst_fwd)), 16);
+       g_strlcpy(str_ip_src, get_addr_name(&(user_data->ip_src_fwd)), sizeof(str_ip_src));
+       g_strlcpy(str_ip_dst, get_addr_name(&(user_data->ip_dst_fwd)), sizeof(str_ip_dst));
 
-       g_snprintf(label_forward, 149,
+       g_snprintf(label_forward, sizeof(label_forward),
                "Analysing stream from  %s port %u  to  %s port %u   SSRC = 0x%X",
                str_ip_src, user_data->port_src_fwd, str_ip_dst, user_data->port_dst_fwd, user_data->ssrc_fwd);
 
-       g_snprintf(label_forward_tree, 149,
+       g_snprintf(label_forward_tree, sizeof(label_forward_tree),
                "Analysing stream from  %s port %u  to  %s port %u   SSRC = 0x%X",
                str_ip_src, user_data->port_src_fwd, str_ip_dst, user_data->port_dst_fwd, user_data->ssrc_fwd);
 
 
-       g_strlcpy(str_ip_src, get_addr_name(&(user_data->ip_src_rev)), 16);
-       g_strlcpy(str_ip_dst, get_addr_name(&(user_data->ip_dst_rev)), 16);
+       g_strlcpy(str_ip_src, get_addr_name(&(user_data->ip_src_rev)), sizeof(str_ip_src));
+       g_strlcpy(str_ip_dst, get_addr_name(&(user_data->ip_dst_rev)), sizeof(str_ip_dst));
 
-       g_snprintf(label_reverse, 149,
+       g_snprintf(label_reverse, sizeof(label_reverse),
                "Analysing stream from  %s port %u  to  %s port %u   SSRC = 0x%X",
                str_ip_src, user_data->port_src_rev, str_ip_dst, user_data->port_dst_rev, user_data->ssrc_rev);
 
@@ -3181,7 +3439,7 @@ static void create_rtp_dialog(user_data_t* user_data)
        g_object_set_data(G_OBJECT(window), "notebook", notebook);
 
        user_data->dlg.notebook_signal_id =
-        g_signal_connect(notebook, "switch_page", G_CALLBACK(on_notebook_switch_page), user_data);
+               g_signal_connect(notebook, "switch_page", G_CALLBACK(on_notebook_switch_page), user_data);
 
        /* page for forward connection */
        page = gtk_vbox_new(FALSE, 8);
@@ -3228,7 +3486,8 @@ static void create_rtp_dialog(user_data_t* user_data)
        label = gtk_label_new("  Reversed Direction  ");
        gtk_notebook_append_page(GTK_NOTEBOOK(notebook), page_r, label);
 
-       /* page for help&about or future
+       /* page for help&about or future */
+#if 0
        page_help = gtk_hbox_new(FALSE, 5);
        label = gtk_label_new("     Future    ");
        gtk_notebook_append_page(GTK_NOTEBOOK(notebook), page_help, label);
@@ -3238,7 +3497,7 @@ static void create_rtp_dialog(user_data_t* user_data)
        gtk_container_add(GTK_CONTAINER(frame), text);
        gtk_container_set_border_width(GTK_CONTAINER(frame), 20);
        gtk_box_pack_start(GTK_BOX(page_help), frame, TRUE, TRUE, 0);
-       */
+#endif
 
        /* show all notebooks */
        gtk_widget_show_all(notebook);
@@ -3249,7 +3508,6 @@ static void create_rtp_dialog(user_data_t* user_data)
        gtk_container_set_border_width(GTK_CONTAINER(box4), 10);
        gtk_button_box_set_layout(GTK_BUTTON_BOX (box4), GTK_BUTTONBOX_EDGE);
        gtk_box_set_spacing(GTK_BOX (box4), 0);
-       gtk_button_box_set_child_ipadding(GTK_BUTTON_BOX (box4), 4, 0);
        gtk_widget_show(box4);
 
        voice_bt = gtk_button_new_with_label("Save payload...");
@@ -3272,18 +3530,18 @@ static void create_rtp_dialog(user_data_t* user_data)
        gtk_widget_show(goto_bt);
        g_signal_connect(goto_bt, "clicked", G_CALLBACK(on_goto_bt_clicked_lst), user_data);
 
-    graph_bt = gtk_button_new_with_label("Graph");
-       gtk_container_add(GTK_CONTAINER(box4), graph_bt);
-       gtk_widget_show(graph_bt);
-       g_signal_connect(graph_bt, "clicked", G_CALLBACK(on_graph_bt_clicked), user_data);
-
-
-#ifdef USE_CONVERSATION_GRAPH
        graph_bt = gtk_button_new_with_label("Graph");
        gtk_container_add(GTK_CONTAINER(box4), graph_bt);
        gtk_widget_show(graph_bt);
        g_signal_connect(graph_bt, "clicked", G_CALLBACK(on_graph_bt_clicked), user_data);
-#endif
+
+#ifdef HAVE_LIBPORTAUDIO
+       player_bt = gtk_button_new_from_stock(WIRESHARK_STOCK_AUDIO_PLAYER);
+       gtk_container_add(GTK_CONTAINER(box4), player_bt);
+       gtk_widget_show(player_bt);
+       g_signal_connect(player_bt, "clicked", G_CALLBACK(on_player_bt_clicked), NULL);
+       /*gtk_widget_set_tooltip_text (player_bt, "Launch the RTP player to listen the audio stream");*/
+#endif /* HAVE_LIBPORTAUDIO */
 
        next_bt = gtk_button_new_with_label("Next non-Ok");
        gtk_container_add(GTK_CONTAINER(box4), next_bt);
@@ -3292,15 +3550,19 @@ static void create_rtp_dialog(user_data_t* user_data)
 
        close_bt = gtk_button_new_from_stock(GTK_STOCK_CLOSE);
        gtk_container_add(GTK_CONTAINER(box4), close_bt);
-    GTK_WIDGET_SET_FLAGS(close_bt, GTK_CAN_DEFAULT);
+#if GTK_CHECK_VERSION(2,18,0)
+       gtk_widget_set_can_default(close_bt, TRUE);
+#else
+       GTK_WIDGET_SET_FLAGS(close_bt, GTK_CAN_DEFAULT);
+#endif
        gtk_widget_show(close_bt);
-    window_set_cancel_button(window, close_bt, window_cancel_button_cb);
+       window_set_cancel_button(window, close_bt, window_cancel_button_cb);
 
-    g_signal_connect(window, "delete_event", G_CALLBACK(window_delete_event_cb), NULL);
+       g_signal_connect(window, "delete_event", G_CALLBACK(window_delete_event_cb), NULL);
        g_signal_connect(window, "destroy", G_CALLBACK(on_destroy), user_data);
 
-    gtk_widget_show(window);
-    window_present(window);
+       gtk_widget_show(window);
+       window_present(window);
 
 
        /* some widget references need to be saved for outside use */
@@ -3330,7 +3592,9 @@ static gboolean process_node(proto_node *ptree_node, header_field_info *hfinform
        header_field_info     *hfssrc;
        ipv4_addr             *ipv4;
 
-       finfo = PITEM_FINFO(ptree_node);
+       finfo = PNODE_FINFO(ptree_node);
+
+       g_assert(finfo && "Caller passed top of the protocol tree. Expected child node");
 
        if (hfinformation==(finfo->hfinfo)) {
                hfssrc = proto_registrar_get_byname(proto_field);
@@ -3338,7 +3602,7 @@ static gboolean process_node(proto_node *ptree_node, header_field_info *hfinform
                        return FALSE;
                for(ptree_node=ptree_node->first_child; ptree_node!=NULL;
                                        ptree_node=ptree_node->next) {
-                       finfo=PITEM_FINFO(ptree_node);
+                       finfo=PNODE_FINFO(ptree_node);
                        if (hfssrc==finfo->hfinfo) {
                                if (hfinformation->type==FT_IPv4) {
                                        ipv4 = fvalue_get(&finfo->value);
@@ -3401,12 +3665,26 @@ void rtp_analysis(
        user_data_t *user_data;
        int fd;
        int i;
-       static color_t col[MAX_GRAPHS] = {
-                       {0,     0x0000, 0x0000, 0x0000},
-               {0,     0xffff, 0x0000, 0x0000},
-               {0,     0x0000, 0xffff, 0x0000},
-               {0,     0x0000, 0x0000, 0xffff}
+       static GdkColor col[MAX_GRAPHS] = {
+               {0,     0x0000, 0x0000, 0x0000}, /* Black */
+               {0,     0xffff, 0x0000, 0x0000}, /* Red */
+               {0,     0x0000, 0xffff, 0x0000}, /* Green */
+               {0,             0xdddd, 0xcccc, 0x6666}, /* Light amber yellow */
+               {0,             0x6666, 0xcccc, 0xdddd}, /* Light bluish cyan */
+               {0,     0x0000, 0x0000, 0xffff}  /* Blue */
+       };
+#if GTK_CHECK_VERSION(3,0,0)
+       static GdkRGBA rgba_col[MAX_GRAPHS] = {
+               {0.0,   0.0,   0.0,   1.0}, /* Black */
+               {1.0,   0.0,   0.1,   1.0}, /* Red */
+               {0.0,   1.0,   0.0,   1.0}, /* Green */
+               {0.867, 0.800, 0.400, 1.0}, /* Light amber yellow */
+               {0.400, 0.800, 0.867, 1.0}, /* Light bluish cyan */
+               {0.0,   0.0,   1.0,   1.0}, /* Blue */
        };
+#endif
+
+       char *tempname;
 
        /* init */
        user_data = g_malloc(sizeof(user_data_t));
@@ -3425,49 +3703,55 @@ void rtp_analysis(
 
        /* file names for storing sound data */
        /*XXX: check for errors*/
-       fd = create_tempfile(user_data->f_tempname, sizeof(user_data->f_tempname),
-               "ether_rtp_f");
+       fd = create_tempfile(&tempname, "wireshark_rtp_f");
+       user_data->f_tempname = g_strdup(tempname);
        ws_close(fd);
-       fd = create_tempfile(user_data->r_tempname, sizeof(user_data->r_tempname),
-               "ether_rtp_r");
+       fd = create_tempfile(&tempname, "wireshark_rtp_r");
+       user_data->r_tempname = g_strdup(tempname);
        ws_close(fd);
        user_data->forward.saveinfo.fp = NULL;
        user_data->reversed.saveinfo.fp = NULL;
        user_data->dlg.save_voice_as_w = NULL;
        user_data->dlg.save_csv_as_w = NULL;
-    user_data->dlg.dialog_graph.window = NULL;
+       user_data->dlg.dialog_graph.window = NULL;
 
-#ifdef USE_CONVERSATION_GRAPH
-       user_data->dlg.graph_window = NULL;
-       user_data->series_fwd.value_pairs = NULL;
-       user_data->series_rev.value_pairs = NULL;
+       /* init dialog_graph */
+       user_data->dlg.dialog_graph.needs_redraw=TRUE;
+       user_data->dlg.dialog_graph.interval_index=DEFAULT_TICK_INTERVAL_VALUES_INDEX;
+       user_data->dlg.dialog_graph.interval=tick_interval_values[DEFAULT_TICK_INTERVAL_VALUES_INDEX];
+       user_data->dlg.dialog_graph.draw_area=NULL;
+#if GTK_CHECK_VERSION(2,22,0)
+       user_data->dlg.dialog_graph.surface=NULL;
+#else
+       user_data->dlg.dialog_graph.pixmap=NULL;
 #endif
-
-        /* init dialog_graph */
-        user_data->dlg.dialog_graph.needs_redraw=TRUE;
-        user_data->dlg.dialog_graph.interval=tick_interval_values[DEFAULT_TICK_VALUE];
-        user_data->dlg.dialog_graph.draw_area=NULL;
-        user_data->dlg.dialog_graph.pixmap=NULL;
-        user_data->dlg.dialog_graph.scrollbar=NULL;
-        user_data->dlg.dialog_graph.scrollbar_adjustment=NULL;
-        user_data->dlg.dialog_graph.pixmap_width=500;
-        user_data->dlg.dialog_graph.pixmap_height=200;
-        user_data->dlg.dialog_graph.pixels_per_tick=pixels_per_tick[DEFAULT_PIXELS_PER_TICK];
-        user_data->dlg.dialog_graph.max_y_units=AUTO_MAX_YSCALE;
-        user_data->dlg.dialog_graph.last_interval=0xffffffff;
-        user_data->dlg.dialog_graph.max_interval=0;
-        user_data->dlg.dialog_graph.num_items=0;
+       user_data->dlg.dialog_graph.scrollbar=NULL;
+       user_data->dlg.dialog_graph.scrollbar_adjustment=NULL;
+       user_data->dlg.dialog_graph.surface_width=500;
+       user_data->dlg.dialog_graph.surface_height=200;
+       user_data->dlg.dialog_graph.pixels_per_tick_index=DEFAULT_PIXELS_PER_TICK_INDEX;
+       user_data->dlg.dialog_graph.pixels_per_tick=pixels_per_tick[DEFAULT_PIXELS_PER_TICK_INDEX];
+       user_data->dlg.dialog_graph.max_y_units_index=AUTO_MAX_YSCALE_INDEX;
+       user_data->dlg.dialog_graph.max_y_units=AUTO_MAX_YSCALE;
+       user_data->dlg.dialog_graph.last_interval=0xffffffff;
+       user_data->dlg.dialog_graph.max_interval=0;
+       user_data->dlg.dialog_graph.num_items=0;
        user_data->dlg.dialog_graph.start_time = -1;
 
        for(i=0;i<MAX_GRAPHS;i++){
-               user_data->dlg.dialog_graph.graph[i].gc=NULL;
-               user_data->dlg.dialog_graph.graph[i].color.pixel=0;
-               user_data->dlg.dialog_graph.graph[i].color.red=col[i].red;
-               user_data->dlg.dialog_graph.graph[i].color.green=col[i].green;
-               user_data->dlg.dialog_graph.graph[i].color.blue=col[i].blue;
-               user_data->dlg.dialog_graph.graph[i].display=TRUE;
-               user_data->dlg.dialog_graph.graph[i].display_button=NULL;
-               user_data->dlg.dialog_graph.graph[i].ud=user_data;
+               user_data->dlg.dialog_graph.graph[i].color.pixel=0;
+               user_data->dlg.dialog_graph.graph[i].color.red=col[i].red;
+               user_data->dlg.dialog_graph.graph[i].color.green=col[i].green;
+               user_data->dlg.dialog_graph.graph[i].color.blue=col[i].blue;
+#if GTK_CHECK_VERSION(3,0,0)
+               user_data->dlg.dialog_graph.graph[i].rgba_color.red=rgba_col[i].red;
+               user_data->dlg.dialog_graph.graph[i].rgba_color.green=rgba_col[i].green;
+               user_data->dlg.dialog_graph.graph[i].rgba_color.blue=rgba_col[i].blue;
+               user_data->dlg.dialog_graph.graph[i].rgba_color.alpha=rgba_col[i].alpha;
+#endif
+               user_data->dlg.dialog_graph.graph[i].display=TRUE;
+               user_data->dlg.dialog_graph.graph[i].display_button=NULL;
+               user_data->dlg.dialog_graph.graph[i].ud=user_data;
        }
 
        /* create the dialog box */
@@ -3479,7 +3763,11 @@ void rtp_analysis(
 
 /****************************************************************************/
 /* entry point from main menu */
+#ifdef MAIN_MENU_USE_UIMANAGER
+void rtp_analysis_cb(GtkAction *action _U_, gpointer user_data _U_)
+#else
 static void rtp_analysis_cb(GtkWidget *w _U_, gpointer data _U_)
+#endif
 {
        address ip_src_fwd;
        guint16 port_src_fwd;
@@ -3496,9 +3784,7 @@ static void rtp_analysis_cb(GtkWidget *w _U_, gpointer data _U_)
        gchar filter_text[256];
        dfilter_t *sfcode;
        capture_file *cf;
-       epan_dissect_t *edt;
-       gint err;
-       gchar *err_info;
+       epan_dissect_t edt;
        gboolean frame_matched;
        frame_data *fdata;
        GList *strinfo_list;
@@ -3507,7 +3793,7 @@ static void rtp_analysis_cb(GtkWidget *w _U_, gpointer data _U_)
        guint nfound;
 
        /* Try to compile the filter. */
-       g_strlcpy(filter_text,"rtp && rtp.version && rtp.ssrc && (ip || ipv6)",256);
+       g_strlcpy(filter_text,"rtp && rtp.version && rtp.ssrc && (ip || ipv6)",sizeof(filter_text));
        if (!dfilter_compile(filter_text, &sfcode)) {
                simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, "%s", dfilter_error_msg);
                return;
@@ -3521,47 +3807,42 @@ static void rtp_analysis_cb(GtkWidget *w _U_, gpointer data _U_)
                return; /* if we exit here it's an error */
 
        /* dissect the current frame */
-       if (!wtap_seek_read(cf->wth, fdata->file_off, &cf->pseudo_header,
-           cf->pd, fdata->cap_len, &err, &err_info)) {
-               simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
-                       cf_read_error_message(err, err_info), cf->filename);
-               return;
-       }
-       edt = epan_dissect_new(TRUE, FALSE);
-       epan_dissect_prime_dfilter(edt, sfcode);
-       epan_dissect_run(edt, &cf->pseudo_header, cf->pd, fdata, NULL);
-       frame_matched = dfilter_apply_edt(sfcode, edt);
+       if (!cf_read_frame(cf, fdata))
+               return; /* error reading the frame */
+       epan_dissect_init(&edt, TRUE, FALSE);
+       epan_dissect_prime_dfilter(&edt, sfcode);
+       epan_dissect_run(&edt, &cf->pseudo_header, cf->pd, fdata, NULL);
 
        /* if it is not an rtp frame, show the rtpstream dialog */
-       frame_matched = dfilter_apply_edt(sfcode, edt);
-       if (frame_matched != 1) {
-               epan_dissect_free(edt);
+       frame_matched = dfilter_apply_edt(sfcode, &edt);
+       if (frame_matched != TRUE) {
+               epan_dissect_cleanup(&edt);
                simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
                    "You didn't choose a RTP packet!");
                return;
        }
 
        /* ok, it is a RTP frame, so let's get the ip and port values */
-       COPY_ADDRESS(&(ip_src_fwd), &(edt->pi.src))
-       COPY_ADDRESS(&(ip_dst_fwd), &(edt->pi.dst))
-       port_src_fwd = edt->pi.srcport;
-       port_dst_fwd = edt->pi.destport;
+       COPY_ADDRESS(&(ip_src_fwd), &(edt.pi.src))
+       COPY_ADDRESS(&(ip_dst_fwd), &(edt.pi.dst))
+       port_src_fwd = edt.pi.srcport;
+       port_dst_fwd = edt.pi.destport;
 
        /* assume the inverse ip/port combination for the reverse direction */
-       COPY_ADDRESS(&(ip_src_rev), &(edt->pi.dst))
-       COPY_ADDRESS(&(ip_dst_rev), &(edt->pi.src))
-       port_src_rev = edt->pi.destport;
-       port_dst_rev = edt->pi.srcport;
-
-        /* check if it is RTP Version 2 */
-        if (!get_int_value_from_proto_tree(edt->tree, "rtp", "rtp.version", &version_fwd) || version_fwd != 2) {
-                simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
-                    "RTP Version != 2 isn't supported!");
-                return;
-        }
+       COPY_ADDRESS(&(ip_src_rev), &(edt.pi.dst))
+       COPY_ADDRESS(&(ip_dst_rev), &(edt.pi.src))
+       port_src_rev = edt.pi.destport;
+       port_dst_rev = edt.pi.srcport;
+
+       /* check if it is RTP Version 2 */
+       if (!get_int_value_from_proto_tree(edt.tree, "rtp", "rtp.version", &version_fwd) || version_fwd != 2) {
+               simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
+                             "RTP Version != 2 isn't supported!");
+               return;
+       }
 
        /* now we need the SSRC value of the current frame */
-       if (!get_int_value_from_proto_tree(edt->tree, "rtp", "rtp.ssrc", &ssrc_fwd)) {
+       if (!get_int_value_from_proto_tree(edt.tree, "rtp", "rtp.ssrc", &ssrc_fwd)) {
                simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
                    "SSRC value couldn't be found!");
                return;
@@ -3629,8 +3910,11 @@ rtp_analysis_init(const char *dummy _U_,void* userdata _U_)
 void
 register_tap_listener_rtp_analysis(void)
 {
-       register_stat_cmd_arg("rtp", rtp_analysis_init,NULL);
+       register_stat_cmd_arg("rtp", rtp_analysis_init, NULL);
 
-       register_stat_menu_item("RTP/Stream Analysis...", REGISTER_STAT_GROUP_TELEPHONY,
+#ifdef MAIN_MENU_USE_UIMANAGER
+#else
+       register_stat_menu_item("_RTP/Stream Analysis...", REGISTER_STAT_GROUP_TELEPHONY,
            rtp_analysis_cb, NULL, NULL, NULL);
+#endif
 }