From Lars Ruoff:
[obnox/wireshark/wip.git] / gtk / rtp_analysis.c
index eba7d33d3731d91d3451dd8c1a9f126270e6bc44..ebaf6273b947c8e58652f7449ff100750a0eabaa 100644 (file)
@@ -1,7 +1,7 @@
 /* rtp_analysis.c
  * RTP analysis addition for ethereal
  *
- * $Id: rtp_analysis.c,v 1.16 2003/12/28 12:43:40 ulfl Exp $
+ * $Id: rtp_analysis.c,v 1.28 2004/01/27 18:05:32 obiot Exp $
  *
  * Copyright 2003, Alcatel Business Systems
  * By Lars Ruoff <lars.ruoff@gmx.net>
@@ -44,6 +44,7 @@
 #include "../graph/graph.h"
 #endif
 
+#include "util.h"
 #include "epan/epan_dissect.h"
 #include "epan/filesystem.h"
 #include "tap.h"
@@ -65,6 +66,9 @@
 #include "progress_dlg.h"
 #include "compat_macros.h"
 
+#include "image/clist_ascend.xpm"
+#include "image/clist_descend.xpm"
+
 #include <math.h>
 #include <fcntl.h>
 #include <string.h>
 
 /****************************************************************************/
 
+typedef struct column_arrows {
+       GtkWidget *table;
+       GtkWidget *ascend_pm;
+       GtkWidget *descend_pm;
+} column_arrows;
+
 typedef struct _dialog_data_t {
        GtkWidget *window;
        GtkCList *clist_fwd;
        GtkCList *clist_rev;
        GtkWidget *label_stats_fwd;
        GtkWidget *label_stats_rev;
+       column_arrows *col_arrows_fwd;
+       column_arrows *col_arrows_rev;
        GtkWidget *notebook;
        GtkCList *selected_clist;
        GtkWidget *save_voice_as_w;
@@ -99,7 +111,8 @@ typedef struct _dialog_data_t {
 #endif
 } dialog_data_t;
 
-#define OK_TEXT "Ok"
+#define OK_TEXT "[ Ok ]"
+#define PT_UNDEFINED -1
 
 /* type of error when saving voice in a file didn't succeed */
 typedef enum {
@@ -135,6 +148,7 @@ typedef struct _tap_rtp_stat_t {
        gboolean under;
        gint cycles;
        guint16 pt;
+       int reg_pt;
 } tap_rtp_stat_t;
 
 /* status flags for the flags parameter in tap_rtp_stat_t */
@@ -143,6 +157,8 @@ typedef struct _tap_rtp_stat_t {
 #define STAT_FLAG_WRONG_SEQ   0x04
 #define STAT_FLAG_PT_CHANGE   0x08
 #define STAT_FLAG_PT_CN       0x10
+#define STAT_FLAG_FOLLOW_PT_CN  0x20
+#define STAT_FLAG_REG_PT_CHANGE  0x40
 
 typedef struct _tap_rtp_save_info_t {
        FILE *fp;
@@ -191,6 +207,19 @@ typedef struct _user_data_t {
 } user_data_t;
 
 
+/* Column titles. */
+static gchar *titles[8] =  {
+       "Packet",
+       "Sequence",
+       "Delay (s)",
+       "Jitter (s)",
+       "Marker",
+       "Status",
+       "Date",
+       "Length"
+};
+
+
 typedef const guint8 * ip_addr_p;
 
 
@@ -200,8 +229,10 @@ typedef const guint8 * ip_addr_p;
 /****************************************************************************/
 /* when there is a [re]reading of packet's */
 static void
-rtp_reset(user_data_t *user_data _U_)
+rtp_reset(void *user_data_arg)
 {
+       user_data_t *user_data = user_data_arg;
+
        user_data->forward.statinfo.first_packet = TRUE;
        user_data->reversed.statinfo.first_packet = TRUE;
        user_data->forward.statinfo.max_delay = 0;
@@ -230,6 +261,8 @@ rtp_reset(user_data_t *user_data _U_)
        user_data->reversed.statinfo.start_time = 0;
        user_data->forward.statinfo.time = 0;
        user_data->reversed.statinfo.time = 0;
+       user_data->forward.statinfo.reg_pt = PT_UNDEFINED;
+       user_data->reversed.statinfo.reg_pt = PT_UNDEFINED;
 
        user_data->forward.saveinfo.count = 0;
        user_data->reversed.saveinfo.count = 0;
@@ -285,8 +318,10 @@ static int rtp_packet_save_payload(tap_rtp_save_info_t *saveinfo,
 
 /****************************************************************************/
 /* whenever a RTP packet is seen by the tap listener */
-static int rtp_packet(user_data_t *user_data, packet_info *pinfo, epan_dissect_t *edt _U_, struct _rtp_info *rtpinfo)
+static int rtp_packet(void *user_data_arg, packet_info *pinfo, epan_dissect_t *edt _U_, void *rtpinfo_arg)
 {
+       user_data_t *user_data = user_data_arg;
+       struct _rtp_info *rtpinfo = rtpinfo_arg;
 #ifdef USE_CONVERSATION_GRAPH
        value_pair_t vp;
 #endif
@@ -339,11 +374,14 @@ static int rtp_packet_analyse(tap_rtp_stat_t *statinfo,
        if (rtpinfo->info_payload_type == PT_CN
                || rtpinfo->info_payload_type == PT_CN_OLD)
                statinfo->flags |= STAT_FLAG_PT_CN;
+       if (statinfo->pt == PT_CN
+               || statinfo->pt == PT_CN_OLD)
+               statinfo->flags |= STAT_FLAG_FOLLOW_PT_CN;
        if (rtpinfo->info_payload_type != statinfo->pt)
                statinfo->flags |= STAT_FLAG_PT_CHANGE;
 
        statinfo->pt = rtpinfo->info_payload_type;
-       
+
        /* store the current time and calculate the current jitter */
        current_time = (double)pinfo->fd->rel_secs + (double) pinfo->fd->rel_usecs/1000000;
        current_jitter = statinfo->jitter + ( fabs (current_time - (statinfo->time) -
@@ -365,13 +403,31 @@ static int rtp_packet_analyse(tap_rtp_stat_t *statinfo,
                statinfo->delta_timestamp = rtpinfo->info_timestamp - statinfo->timestamp;
                statinfo->flags |= STAT_FLAG_MARKER;
        }
-       /* if neither then it is a normal packet */
-       if (!(statinfo->first_packet) && !(rtpinfo->info_marker_set)) {
+       /* is it a regular packet? */
+       if (!(statinfo->flags & STAT_FLAG_FIRST)
+               && !(statinfo->flags & STAT_FLAG_MARKER)
+               && !(statinfo->flags & STAT_FLAG_PT_CN)
+               && !(statinfo->flags & STAT_FLAG_FOLLOW_PT_CN)) {
+               /* include it in maximum delay calculation */
                if (statinfo->delay > statinfo->max_delay) {
                        statinfo->max_delay = statinfo->delay;
                        statinfo->max_nr = pinfo->fd->num;
                }
        }
+       /* regular payload change? (CN ignored) */
+       if (!(statinfo->flags & STAT_FLAG_FIRST)
+               && !(statinfo->flags & STAT_FLAG_PT_CN)) {
+               if ((statinfo->pt != statinfo->reg_pt)
+                       && (statinfo->reg_pt != PT_UNDEFINED)) {
+                       statinfo->flags |= STAT_FLAG_REG_PT_CHANGE;
+               }
+       }
+
+       /* set regular payload*/
+       if (!(statinfo->flags & STAT_FLAG_PT_CN)) {
+               statinfo->reg_pt = statinfo->pt;
+       }
+
 
        /* When calculating expected rtp packets the seq number can wrap around
        * so we have to count the number of cycles
@@ -437,6 +493,11 @@ static int rtp_packet_analyse(tap_rtp_stat_t *statinfo,
 }
 
 
+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};
+
 /****************************************************************************/
 /* adds statistics information from the packet to the clist */
 static int rtp_packet_add_info(GtkCList *clist,
@@ -447,7 +508,7 @@ static int rtp_packet_add_info(GtkCList *clist,
        struct tm *tm_tmp;
        time_t then;
        gchar status[40];
-       GdkColor color = {0, 0xffff, 0xffff, 0xffff};
+       GdkColor color = COLOR_DEFAULT;
 
        then = pinfo->fd->abs_secs;
        msecs = (guint16)(pinfo->fd->abs_usecs/1000);
@@ -463,35 +524,32 @@ static int rtp_packet_add_info(GtkCList *clist,
 
        if (statinfo->pt == PT_CN) {
                snprintf(status,40,"Comfort noise (PT=13, RFC 3389)");
-               color.pixel = 0;
-               color.red = 0x7fff;
-               color.green = 0x7fff;
-               color.blue = 0xffff;
+               color = COLOR_CN;
        }
        else if (statinfo->pt == PT_CN_OLD) {
                snprintf(status,40,"Comfort noise (PT=19, reserved)");
-               color.pixel = 0;
-               color.red = 0x7fff;
-               color.green = 0x7fff;
-               color.blue = 0xffff;
+               color = COLOR_CN;
        }
        else if (statinfo->flags & STAT_FLAG_WRONG_SEQ) {
                snprintf(status,40,"Wrong sequence nr.");
-               color.pixel = 0;
-               color.red = 0xffff;
-               color.green = 0x7fff;
-               color.blue = 0x7fff;
+               color = COLOR_ERROR;
+       }
+       else if (statinfo->flags & STAT_FLAG_REG_PT_CHANGE) {
+               snprintf(status,40,"Payload changed to PT=%u", statinfo->pt);
+               color = COLOR_WARNING;
        }
        else if ((statinfo->flags & STAT_FLAG_PT_CHANGE)
                &&  !(statinfo->flags & STAT_FLAG_FIRST)
-               &&  !(statinfo->flags & STAT_FLAG_PT_CN)) {
-               snprintf(status,40,"Payload type changed to PT=%u", statinfo->pt);
-               color.pixel = 0;
-               color.red = 0xffff;
-               color.green = 0x7fff;
-               color.blue = 0x7fff;
+               &&  !(statinfo->flags & STAT_FLAG_PT_CN)
+               &&  (statinfo->flags & STAT_FLAG_FOLLOW_PT_CN)
+               &&  !(statinfo->flags & STAT_FLAG_MARKER)) {
+               snprintf(status,40,"Marker missing?");
+               color = COLOR_WARNING;
        }
        else {
+               if (statinfo->flags & STAT_FLAG_MARKER) {
+                       color = COLOR_WARNING;
+               }
                snprintf(status,40,OK_TEXT);
        }
 
@@ -635,27 +693,27 @@ void unprotect_thread_critical_region(void);
 /* close the dialog window and remove the tap listener */
 static void on_destroy(GtkWidget *win _U_, user_data_t *user_data _U_)
 {
-       protect_thread_critical_region();
-       remove_tap_listener(user_data);
-       unprotect_thread_critical_region();
-
+       /* close and remove temporary files */
        if (user_data->forward.saveinfo.fp != NULL)
                fclose(user_data->forward.saveinfo.fp);
        if (user_data->reversed.saveinfo.fp != NULL)
                fclose(user_data->reversed.saveinfo.fp);
+       /*XXX: test for error **/
        remove(user_data->f_tempname);
        remove(user_data->r_tempname);
 
-       /* Is there a save voice window open? */
+       /* destroy save_voice_as window if open */
        if (user_data->dlg.save_voice_as_w != NULL)
                gtk_widget_destroy(user_data->dlg.save_voice_as_w);
 
 #ifdef USE_CONVERSATION_GRAPH
-       /* Is there a graph window open? */
+       /* destroy graph window if open */
        if (user_data->dlg.graph_window != NULL)
                gtk_widget_destroy(user_data->dlg.graph_window);
 #endif
 
+       g_free(user_data->dlg.col_arrows_fwd);
+       g_free(user_data->dlg.col_arrows_rev);
        g_free(user_data);
 }
 
@@ -785,10 +843,54 @@ 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_)
 {
+       gchar filter_text[256];
+       dfilter_t *sfcode;
+       GString *error_string;
+
+       /* clear the dialog box clists */
        gtk_clist_clear(GTK_CLIST(user_data->dlg.clist_fwd));
        gtk_clist_clear(GTK_CLIST(user_data->dlg.clist_rev));
-       redissect_packets(&cfile);
+
+       /* try to compile the filter. */
+       strcpy(filter_text,"rtp && ip");
+       if (!dfilter_compile(filter_text, &sfcode)) {
+               simple_dialog(ESD_TYPE_WARN | ESD_TYPE_MODAL, NULL, dfilter_error_msg);
+               return;
+       }
+
+       sprintf(filter_text,"rtp && (( ip.src==%s && udp.srcport==%u && ip.dst==%s && udp.dstport==%u ) || ( ip.src==%s && udp.srcport==%u && ip.dst==%s && udp.dstport==%u ))",
+               ip_to_str((ip_addr_p)&(user_data->ip_src_fwd)),
+               user_data->port_src_fwd,
+               ip_to_str((ip_addr_p)&(user_data->ip_dst_fwd)),
+               user_data->port_dst_fwd,
+               ip_to_str((ip_addr_p)&(user_data->ip_src_rev)),
+               user_data->port_src_rev,
+               ip_to_str((ip_addr_p)&(user_data->ip_dst_rev)),
+               user_data->port_dst_rev
+               );
+
+       /* register tap listener */
+       error_string = register_tap_listener("rtp", user_data, filter_text,
+               rtp_reset, rtp_packet, rtp_draw);
+       if (error_string != NULL) {
+               simple_dialog(ESD_TYPE_WARN | ESD_TYPE_MODAL, NULL, error_string->str);
+                       g_string_free(error_string, TRUE);
+               return;
+       }
+
+       /* retap all packets */
+       retap_packets(&cfile);
+
+       /* remove tap listener again */
+       protect_thread_critical_region();
+       remove_tap_listener(user_data);
+       unprotect_thread_critical_region();
+
+       /* draw statistics info */
        draw_stat(user_data);
+
+       gtk_clist_sort(user_data->dlg.clist_fwd);
+       gtk_clist_sort(user_data->dlg.clist_rev);
 }
 
 /****************************************************************************/
@@ -807,10 +909,7 @@ static void on_next_bt_clicked(GtkWidget *bt _U_, user_data_t *user_data _U_)
        gint row;
        if (user_data->dlg.selected_clist==NULL)
                return;
-/*
-       if (user_data->dlg.selected_row==-1)
-               user_data->dlg.selected_row = 0;
-*/
+
        clist = user_data->dlg.selected_clist;
        row = user_data->dlg.selected_row + 1;
 
@@ -866,19 +965,36 @@ static void save_csv_as_ok_cb(GtkWidget *bt _U_, gpointer fs /*user_data_t *user
        
        if (GTK_TOGGLE_BUTTON(forw)->active || GTK_TOGGLE_BUTTON(both)->active) {
                fp = fopen(g_dest, "w");
+               if (fp == NULL) {
+                       simple_dialog(ESD_TYPE_CRIT, NULL,
+                           file_open_error_message(errno, TRUE), g_dest);
+                       return;
+               }
                
                if (GTK_TOGGLE_BUTTON(both)->active) {
                        fprintf(fp, "Forward\n");
+                       if (ferror(fp)) {
+                               simple_dialog(ESD_TYPE_CRIT, NULL,
+                                   file_write_error_message(errno), g_dest);
+                               fclose(fp);
+                               return;
+                       }
                }
                
-               for(j = 0; j < GTK_CLIST(user_data->dlg.clist_fwd)->columns; j++) {
+               for(j = 0; j < 8; j++) {
                        if (j == 0) {
-                               fprintf(fp,"%s",GTK_CLIST(user_data->dlg.clist_fwd)->column[j].title);
+                               fprintf(fp,"%s",titles[j]);
                        } else {
-                               fprintf(fp,",%s",GTK_CLIST(user_data->dlg.clist_fwd)->column[j].title);
+                               fprintf(fp,",%s",titles[j]);
                        }
                }
                fprintf(fp,"\n");
+               if (ferror(fp)) {
+                       simple_dialog(ESD_TYPE_CRIT, NULL,
+                           file_write_error_message(errno), g_dest);
+                       fclose(fp);
+                       return;
+               }
                for (i = 0; i < GTK_CLIST(user_data->dlg.clist_fwd)->rows; i++) {
                        for(j = 0; j < GTK_CLIST(user_data->dlg.clist_fwd)->columns; j++) {
                                gtk_clist_get_text(GTK_CLIST(user_data->dlg.clist_fwd),i,j,&columnText);
@@ -889,27 +1005,61 @@ static void save_csv_as_ok_cb(GtkWidget *bt _U_, gpointer fs /*user_data_t *user
                                }
                        }
                        fprintf(fp,"\n");
+                       if (ferror(fp)) {
+                               simple_dialog(ESD_TYPE_CRIT, NULL,
+                                   file_write_error_message(errno), g_dest);
+                               fclose(fp);
+                               return;
+                       }
                }
                
-               fclose(fp);
+               if (fclose(fp) == EOF) {
+                       simple_dialog(ESD_TYPE_CRIT, NULL,
+                           file_write_error_message(errno), g_dest);
+                       return;
+               }
        }
        
        if (GTK_TOGGLE_BUTTON(rev)->active || GTK_TOGGLE_BUTTON(both)->active) {
                
                if (GTK_TOGGLE_BUTTON(both)->active) {
                        fp = fopen(g_dest, "a");
+                       if (fp == NULL) {
+                               simple_dialog(ESD_TYPE_CRIT, NULL,
+                                   file_open_error_message(errno, TRUE),
+                                   g_dest);
+                               return;
+                       }
                        fprintf(fp, "\nReverse\n");
+                       if (ferror(fp)) {
+                               simple_dialog(ESD_TYPE_CRIT, NULL,
+                                   file_write_error_message(errno), g_dest);
+                               fclose(fp);
+                               return;
+                       }
                } else {
                        fp = fopen(g_dest, "w");
+                       if (fp == NULL) {
+                               simple_dialog(ESD_TYPE_CRIT, NULL,
+                                   file_open_error_message(errno, TRUE),
+                                   g_dest);
+                               return;
+                       }
                }
-               for(j = 0; j < GTK_CLIST(user_data->dlg.clist_rev)->columns; j++) {
+               for(j = 0; j < 8; j++) {
                        if (j == 0) {
-                               fprintf(fp,"%s",GTK_CLIST(user_data->dlg.clist_rev)->column[j].title);
+                               fprintf(fp,"%s",titles[j]);
                        } else {
-                               fprintf(fp,",%s",GTK_CLIST(user_data->dlg.clist_rev)->column[j].title);
+                               fprintf(fp,",%s",titles[j]);
                        }
                }
                fprintf(fp,"\n");
+               if (ferror(fp)) {
+                       simple_dialog(ESD_TYPE_CRIT, NULL,
+                           file_write_error_message(errno), g_dest);
+                       fclose(fp);
+                       return;
+               }
                for (i = 0; i < GTK_CLIST(user_data->dlg.clist_rev)->rows; i++) {
                        for(j = 0; j < GTK_CLIST(user_data->dlg.clist_rev)->columns; j++) {
                                gtk_clist_get_text(GTK_CLIST(user_data->dlg.clist_rev),i,j,&columnText);
@@ -920,8 +1070,18 @@ static void save_csv_as_ok_cb(GtkWidget *bt _U_, gpointer fs /*user_data_t *user
                                }
                        }
                        fprintf(fp,"\n");
+                       if (ferror(fp)) {
+                               simple_dialog(ESD_TYPE_CRIT, NULL,
+                                   file_write_error_message(errno), g_dest);
+                               fclose(fp);
+                               return;
+                       }
+               }
+               if (fclose(fp) == EOF) {
+                       simple_dialog(ESD_TYPE_CRIT, NULL,
+                           file_write_error_message(errno), g_dest);
+                       return;
                }
-               fclose(fp);
        }
 
        gtk_widget_destroy(GTK_WIDGET(user_data->dlg.save_csv_as_w));
@@ -1067,7 +1227,7 @@ static gboolean copy_file(gchar *dest, gint channels, /*gint format,*/ user_data
                return FALSE;
        }
 
-       progbar = create_progress_dlg("Saving voice in a file", dest, "Stop", &stop_flag);
+       progbar = create_progress_dlg("Saving voice in a file", dest, &stop_flag);
 
        /* First we write the .au header. XXX Hope this is endian independant */
        /* the magic word 0x2e736e64 == .snd */
@@ -1490,18 +1650,20 @@ static void draw_stat(user_data_t *user_data)
        gint32 f_lost = f_expected - user_data->forward.statinfo.total_nr;
        gint32 r_lost = r_expected - user_data->reversed.statinfo.total_nr;
 
-       g_snprintf(label_max, 199, "Max delay = %f sec at packet no. %u \n\n"
+       g_snprintf(label_max, 199, "Max delay = %f sec at packet no. %u \n"
                "Total RTP packets = %u   (expected %u)   Lost RTP packets = %d"
                "   Sequence errors = %u",
-               user_data->forward.statinfo.max_delay, user_data->forward.statinfo.max_nr, user_data->forward.statinfo.total_nr,
+               user_data->forward.statinfo.max_delay, user_data->forward.statinfo.max_nr,
+               user_data->forward.statinfo.total_nr,
                f_expected, f_lost, user_data->forward.statinfo.sequence);
 
        gtk_label_set_text(GTK_LABEL(user_data->dlg.label_stats_fwd), label_max);
 
-       g_snprintf(label_max, 199, "Max delay = %f sec at packet no. %u \n\n"
+       g_snprintf(label_max, 199, "Max delay = %f sec at packet no. %u \n"
                "Total RTP packets = %u   (expected %u)   Lost RTP packets = %d"
                "   Sequence errors = %u",
-               user_data->reversed.statinfo.max_delay, user_data->reversed.statinfo.max_nr, user_data->reversed.statinfo.total_nr,
+               user_data->reversed.statinfo.max_delay, user_data->reversed.statinfo.max_nr,
+               user_data->reversed.statinfo.total_nr,
                r_expected, r_lost, user_data->reversed.statinfo.sequence);
 
        gtk_label_set_text(GTK_LABEL(user_data->dlg.label_stats_rev), label_max);
@@ -1509,6 +1671,9 @@ static void draw_stat(user_data_t *user_data)
        return ;
 }
 
+
+#define NUM_COLS 8
+
 /****************************************************************************/
 /* append a line to clist */
 static void add_to_clist(GtkCList *clist, guint32 number, guint16 seq_num,
@@ -1542,6 +1707,170 @@ static void add_to_clist(GtkCList *clist, guint32 number, guint16 seq_num,
        gtk_clist_set_background(GTK_CLIST(clist), added_row, color);
 }
 
+
+/****************************************************************************/
+/* callback for sorting columns of clist */
+static gint rtp_sort_column(GtkCList *clist, gconstpointer ptr1, gconstpointer ptr2)
+{
+       char *text1 = NULL;
+       char *text2 = NULL;
+       int i1, i2;
+       double f1, f2;
+
+       const GtkCListRow *row1 = (GtkCListRow *) ptr1;
+       const GtkCListRow *row2 = (GtkCListRow *) ptr2;
+
+       text1 = GTK_CELL_TEXT (row1->cell[clist->sort_column])->text;
+       text2 = GTK_CELL_TEXT (row2->cell[clist->sort_column])->text;
+
+       switch(clist->sort_column){
+       /* columns representing strings */
+       case 4:
+       case 5:
+       case 6:
+               return strcmp (text1, text2);
+       /* columns representing ints */
+       case 0:
+       case 1:
+       case 7:
+               i1=atoi(text1);
+               i2=atoi(text2);
+               return i1-i2;
+       /* columns representing floats */
+       case 2:
+       case 3:
+               f1=atof(text1);
+               f2=atof(text2);
+               if (fabs(f1-f2)<0.0000005)
+                       return 0;
+               if (f1<f2)
+                       return -1;
+               return 1;
+       }
+       g_assert_not_reached();
+       return 0;
+}
+
+
+/****************************************************************************/
+static void
+click_column_cb(GtkCList *clist, gint column, gpointer data)
+{
+       column_arrows *col_arrows = (column_arrows *) data;
+       int i;
+
+       gtk_clist_freeze(clist);
+
+       for (i = 0; i < NUM_COLS; i++) {
+               gtk_widget_hide(col_arrows[i].ascend_pm);
+               gtk_widget_hide(col_arrows[i].descend_pm);
+       }
+
+       if (column == clist->sort_column) {
+               if (clist->sort_type == GTK_SORT_ASCENDING) {
+                       clist->sort_type = GTK_SORT_DESCENDING;
+                       gtk_widget_show(col_arrows[column].descend_pm);
+               } else {
+                       clist->sort_type = GTK_SORT_ASCENDING;
+                       gtk_widget_show(col_arrows[column].ascend_pm);
+               }
+       } else {
+               clist->sort_type = GTK_SORT_ASCENDING;
+               gtk_widget_show(col_arrows[column].ascend_pm);
+               gtk_clist_set_sort_column(clist, column);
+       }
+       gtk_clist_thaw(clist);
+
+       gtk_clist_sort(clist);
+}
+
+
+/****************************************************************************/
+/* Add the packet list */
+static
+GtkWidget* create_clist(user_data_t* user_data)
+{
+       GtkWidget* clist_fwd;
+
+       /* clist for the information */
+       clist_fwd = gtk_clist_new(8);
+       gtk_widget_show(clist_fwd);
+       SIGNAL_CONNECT(clist_fwd, "select_row", on_clist_select_row, user_data);
+
+       gtk_clist_column_titles_show(GTK_CLIST(clist_fwd));
+       gtk_clist_set_compare_func(GTK_CLIST(clist_fwd), rtp_sort_column);
+       gtk_clist_set_sort_column(GTK_CLIST(clist_fwd), 0);
+       gtk_clist_set_sort_type(GTK_CLIST(clist_fwd), GTK_SORT_ASCENDING);
+
+       /* hide date and length column */
+       gtk_clist_set_column_visibility(GTK_CLIST(clist_fwd), 6, FALSE);
+       gtk_clist_set_column_visibility(GTK_CLIST(clist_fwd), 7, FALSE);
+
+       /* column widths and justification */
+       gtk_clist_set_column_width(GTK_CLIST(clist_fwd), 0, 60);
+       gtk_clist_set_column_width(GTK_CLIST(clist_fwd), 1, 75);
+       gtk_clist_set_column_width(GTK_CLIST(clist_fwd), 2, 75);
+       gtk_clist_set_column_width(GTK_CLIST(clist_fwd), 3, 75);
+       gtk_clist_set_column_width(GTK_CLIST(clist_fwd), 4, 50);
+       gtk_clist_set_column_justification(GTK_CLIST(clist_fwd), 0, GTK_JUSTIFY_RIGHT);
+       gtk_clist_set_column_justification(GTK_CLIST(clist_fwd), 1, GTK_JUSTIFY_RIGHT);
+       gtk_clist_set_column_justification(GTK_CLIST(clist_fwd), 2, GTK_JUSTIFY_CENTER);
+       gtk_clist_set_column_justification(GTK_CLIST(clist_fwd), 3, GTK_JUSTIFY_CENTER);
+       gtk_clist_set_column_justification(GTK_CLIST(clist_fwd), 4, GTK_JUSTIFY_CENTER);
+       gtk_clist_set_column_justification(GTK_CLIST(clist_fwd), 5, GTK_JUSTIFY_CENTER);
+
+       return clist_fwd;
+}
+
+
+/****************************************************************************/
+/* Add the sort by column feature for a packet clist */
+static
+column_arrows* add_sort_by_column(GtkWidget* window, GtkWidget* clist,
+                                                                 user_data_t* user_data _U_)
+{
+       column_arrows *col_arrows;
+       GdkBitmap *ascend_bm, *descend_bm;
+       GdkPixmap *ascend_pm, *descend_pm;
+       GtkStyle *win_style;
+       GtkWidget *column_lb;
+       int i;
+
+       col_arrows = (column_arrows *) g_malloc(sizeof(column_arrows) * NUM_COLS);
+       win_style = gtk_widget_get_style(window);
+       ascend_pm = gdk_pixmap_create_from_xpm_d(window->window,
+                       &ascend_bm,
+                       &win_style->bg[GTK_STATE_NORMAL],
+                       (gchar **)clist_ascend_xpm);
+       descend_pm = gdk_pixmap_create_from_xpm_d(window->window,
+                       &descend_bm,
+                       &win_style->bg[GTK_STATE_NORMAL],
+                       (gchar **)clist_descend_xpm);
+
+       for (i=0; i<NUM_COLS; i++) {
+               col_arrows[i].table = gtk_table_new(2, 2, FALSE);
+               gtk_table_set_col_spacings(GTK_TABLE(col_arrows[i].table), 5);
+               column_lb = gtk_label_new(titles[i]);
+               gtk_table_attach(GTK_TABLE(col_arrows[i].table), column_lb, 0, 1, 0, 2, GTK_SHRINK, GTK_SHRINK, 0, 0);
+               gtk_widget_show(column_lb);
+
+               col_arrows[i].ascend_pm = gtk_pixmap_new(ascend_pm, ascend_bm);
+               gtk_table_attach(GTK_TABLE(col_arrows[i].table), col_arrows[i].ascend_pm, 1, 2, 1, 2, GTK_SHRINK, GTK_SHRINK, 0, 0);
+               col_arrows[i].descend_pm = gtk_pixmap_new(descend_pm, descend_bm);
+               gtk_table_attach(GTK_TABLE(col_arrows[i].table), col_arrows[i].descend_pm, 1, 2, 0, 1, GTK_SHRINK, GTK_SHRINK, 0, 0);
+               /* make packet-nr be the default sort order */
+               if (i == 0) {
+                       gtk_widget_show(col_arrows[i].ascend_pm);
+               }
+               gtk_clist_set_column_widget(GTK_CLIST(clist), i, col_arrows[i].table);
+               gtk_widget_show(col_arrows[i].table);
+       }
+
+       SIGNAL_CONNECT(clist, "click-column", click_column_cb, col_arrows);
+
+       return col_arrows;
+}
+
 /****************************************************************************/
 /* Create the dialog box with all widgets */
 void create_rtp_dialog(user_data_t* user_data)
@@ -1553,19 +1882,21 @@ void create_rtp_dialog(user_data_t* user_data)
        GtkWidget *label_stats_rev;
        GtkWidget *notebook;
 
-       GtkWidget *main_vb, *page, *page_r, *label, *label1, *label2, *label3;
+       GtkWidget *main_vb, *page, *page_r;
+       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
 
-       gchar *titles[8] =  {"Packet", "Sequence",  "Delay (s)", "Jitter (s)", "Marker", "Status", "Date", "Length"};
        gchar label_forward[150];
        gchar label_reverse[150];
 
        gchar str_ip_src[16];
        gchar str_ip_dst[16];
+       column_arrows *col_arrows_fwd;
+       column_arrows *col_arrows_rev;
        
 
        window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
@@ -1574,25 +1905,24 @@ void create_rtp_dialog(user_data_t* user_data)
        SIGNAL_CONNECT(window, "destroy", on_destroy, user_data);
 
        /* Container for each row of widgets */
-       main_vb = gtk_vbox_new(FALSE, 3);
-       gtk_container_border_width(GTK_CONTAINER(main_vb), 5);
+       main_vb = gtk_vbox_new(FALSE, 2);
+       gtk_container_border_width(GTK_CONTAINER(main_vb), 2);
        gtk_container_add(GTK_CONTAINER(window), main_vb);
        gtk_widget_show(main_vb);
 
-
        /* Notebooks... */
        strcpy(str_ip_src, ip_to_str((ip_addr_p)&user_data->ip_src_fwd));
        strcpy(str_ip_dst, ip_to_str((ip_addr_p)&user_data->ip_dst_fwd));
 
        g_snprintf(label_forward, 149, 
-               "Analysing connection from  %s port %u  to  %s port %u   SSRC = %u\n", 
+               "Analysing stream from  %s port %u  to  %s port %u   SSRC = %u", 
                str_ip_src, user_data->port_src_fwd, str_ip_dst, user_data->port_dst_fwd, user_data->ssrc_fwd);
 
        strcpy(str_ip_src, ip_to_str((ip_addr_p)&user_data->ip_src_rev));
        strcpy(str_ip_dst, ip_to_str((ip_addr_p)&user_data->ip_dst_rev));
 
        g_snprintf(label_reverse, 149,
-               "Analysing connection from  %s port %u  to  %s port %u   SSRC = %u\n", 
+               "Analysing stream from  %s port %u  to  %s port %u   SSRC = %u", 
                str_ip_src, user_data->port_src_rev, str_ip_dst, user_data->port_dst_rev, user_data->ssrc_rev);
 
        /* Start a notebook for flipping between sets of changes */
@@ -1603,89 +1933,60 @@ void create_rtp_dialog(user_data_t* user_data)
                        user_data);
 
        /* page for forward connection */
-       page = gtk_vbox_new(FALSE, 5);
-       gtk_container_set_border_width(GTK_CONTAINER(page), 20);
+       page = gtk_vbox_new(FALSE, 8);
+       gtk_container_set_border_width(GTK_CONTAINER(page), 8);
+
+       /* direction label */
+       label = gtk_label_new(label_forward);
+       gtk_box_pack_start(GTK_BOX(page), label, FALSE, FALSE, 0);
+
+       /* place for some statistics */
+       label_stats_fwd = gtk_label_new("\n");
+       gtk_box_pack_end(GTK_BOX(page), label_stats_fwd, FALSE, FALSE, 0);
 
        /* scrolled window */
        scrolled_window = gtk_scrolled_window_new(NULL, NULL);
-       WIDGET_SET_SIZE(scrolled_window, 600, 200);
+       WIDGET_SET_SIZE(scrolled_window, 560, 200);
        gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolled_window), 
                GTK_POLICY_AUTOMATIC, GTK_POLICY_ALWAYS);
 
-       /* direction label */
-       label1 = gtk_label_new(label_forward);
-       gtk_box_pack_start(GTK_BOX(page), label1, FALSE, FALSE, 0);
-
-       /* place for some statistics */
-       label_stats_fwd = gtk_label_new("\n\n");
-       gtk_box_pack_end(GTK_BOX(page), label_stats_fwd, FALSE, FALSE, 5);
-
-       /* clist for the information */
-       clist_fwd = gtk_clist_new_with_titles(8, titles);
+       /* packet clist */
+       clist_fwd = create_clist(user_data);
        gtk_widget_show(clist_fwd);
        gtk_container_add(GTK_CONTAINER(scrolled_window), clist_fwd);
        gtk_box_pack_start(GTK_BOX(page), scrolled_window, TRUE, TRUE, 0);
-       SIGNAL_CONNECT(clist_fwd, "select_row", on_clist_select_row, user_data);
-       /* Hide date and length column */
-       gtk_clist_set_column_visibility(GTK_CLIST(clist_fwd), 6, FALSE);
-       gtk_clist_set_column_visibility(GTK_CLIST(clist_fwd), 7, FALSE);
+       gtk_widget_show(scrolled_window);
 
-       /* label */
-       label = gtk_label_new("     Forward Direction     ");
+       /* tab */
+       label = gtk_label_new("  Forward Direction  ");
        gtk_notebook_append_page(GTK_NOTEBOOK(notebook), page, label);
 
-       /* column width and justification */
-       gtk_clist_set_column_width(GTK_CLIST(clist_fwd), 0, 80);
-       gtk_clist_set_column_width(GTK_CLIST(clist_fwd), 1, 80);
-       gtk_clist_set_column_width(GTK_CLIST(clist_fwd), 2, 80);
-       gtk_clist_set_column_width(GTK_CLIST(clist_fwd), 3, 80);
-       gtk_clist_set_column_width(GTK_CLIST(clist_fwd), 4, 40);
-       gtk_clist_set_column_justification(GTK_CLIST(clist_fwd), 0, GTK_JUSTIFY_CENTER);
-       gtk_clist_set_column_justification(GTK_CLIST(clist_fwd), 1, GTK_JUSTIFY_CENTER);
-       gtk_clist_set_column_justification(GTK_CLIST(clist_fwd), 2, GTK_JUSTIFY_CENTER);
-       gtk_clist_set_column_justification(GTK_CLIST(clist_fwd), 3, GTK_JUSTIFY_CENTER);
-       gtk_clist_set_column_justification(GTK_CLIST(clist_fwd), 4, GTK_JUSTIFY_CENTER);
-       gtk_clist_set_column_justification(GTK_CLIST(clist_fwd), 5, GTK_JUSTIFY_CENTER);
-
        /* same page for reversed connection */
-       page_r = gtk_vbox_new(FALSE, 5);
-       gtk_container_set_border_width(GTK_CONTAINER(page_r), 20);
+       page_r = gtk_vbox_new(FALSE, 8);
+       gtk_container_set_border_width(GTK_CONTAINER(page_r), 8);
+       label = gtk_label_new(label_reverse);
+       gtk_box_pack_start(GTK_BOX(page_r), label, FALSE, FALSE, 0);
+       label_stats_rev = gtk_label_new("\n");
+       gtk_box_pack_end(GTK_BOX(page_r), label_stats_rev, FALSE, FALSE, 0);
+
        scrolled_window_r = gtk_scrolled_window_new(NULL, NULL);
-       WIDGET_SET_SIZE(scrolled_window_r, 600, 200);
+       WIDGET_SET_SIZE(scrolled_window_r, 560, 200);
        gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolled_window_r), 
                GTK_POLICY_AUTOMATIC, GTK_POLICY_ALWAYS);
-       label3 = gtk_label_new(label_reverse);
-       gtk_box_pack_start(GTK_BOX(page_r), label3, FALSE, FALSE, 0);
-       label_stats_rev = gtk_label_new("\n\n");
-       gtk_box_pack_end(GTK_BOX(page_r), label_stats_rev, FALSE, FALSE, 5);
-       clist_rev = gtk_clist_new_with_titles(8, titles);
-       gtk_widget_show(clist_rev);
-       gtk_clist_set_column_visibility(GTK_CLIST(clist_rev), 6, FALSE);
-       gtk_clist_set_column_visibility(GTK_CLIST(clist_rev), 7, FALSE);
-
-       SIGNAL_CONNECT(clist_rev, "select_row", on_clist_select_row, user_data);
 
+       clist_rev = create_clist(user_data);
+       gtk_widget_show(clist_rev);
        gtk_container_add(GTK_CONTAINER(scrolled_window_r), clist_rev);
        gtk_box_pack_start(GTK_BOX(page_r), scrolled_window_r, TRUE, TRUE, 0);
-       label2 = gtk_label_new("     Reversed Direction     ");
-       gtk_notebook_append_page(GTK_NOTEBOOK(notebook), page_r, label2);
-
-       gtk_clist_set_column_width(GTK_CLIST(clist_rev), 0, 80);
-       gtk_clist_set_column_width(GTK_CLIST(clist_rev), 1, 80);
-       gtk_clist_set_column_width(GTK_CLIST(clist_rev), 2, 80);
-       gtk_clist_set_column_width(GTK_CLIST(clist_rev), 3, 80);
-       gtk_clist_set_column_width(GTK_CLIST(clist_rev), 4, 40);
-       gtk_clist_set_column_justification(GTK_CLIST(clist_rev), 0, GTK_JUSTIFY_CENTER);
-       gtk_clist_set_column_justification(GTK_CLIST(clist_rev), 1, GTK_JUSTIFY_CENTER);
-       gtk_clist_set_column_justification(GTK_CLIST(clist_rev), 2, GTK_JUSTIFY_CENTER);
-       gtk_clist_set_column_justification(GTK_CLIST(clist_rev), 3, GTK_JUSTIFY_CENTER);
-       gtk_clist_set_column_justification(GTK_CLIST(clist_rev), 4, GTK_JUSTIFY_CENTER);
-       gtk_clist_set_column_justification(GTK_CLIST(clist_rev), 5, GTK_JUSTIFY_CENTER);
+       gtk_widget_show(scrolled_window_r);
+
+       label = gtk_label_new("  Reversed Direction  ");
+       gtk_notebook_append_page(GTK_NOTEBOOK(notebook), page_r, label);
 
        /* page for help&about or future
        page_help = gtk_hbox_new(FALSE, 5);
-       label4 = gtk_label_new("     Future    ");
-       gtk_notebook_append_page(GTK_NOTEBOOK(notebook), page_help, label4);
+       label = gtk_label_new("     Future    ");
+       gtk_notebook_append_page(GTK_NOTEBOOK(notebook), page_help, label);
        frame = gtk_frame_new("");
        text = gtk_label_new("\n\nMaybe some more statistics: delay and jitter distribution,...");
        gtk_label_set_justify(GTK_LABEL(text), GTK_JUSTIFY_LEFT);
@@ -1716,12 +2017,12 @@ void create_rtp_dialog(user_data_t* user_data)
        gtk_widget_show(csv_bt);
        SIGNAL_CONNECT(csv_bt, "clicked", save_csv_as_cb, user_data);
 
-       refresh_bt = gtk_button_new_with_label("Refresh");
+       refresh_bt = BUTTON_NEW_FROM_STOCK(GTK_STOCK_REFRESH);
        gtk_container_add(GTK_CONTAINER(box4), refresh_bt);
        gtk_widget_show(refresh_bt);
        SIGNAL_CONNECT(refresh_bt, "clicked", on_refresh_bt_clicked, user_data);
 
-       goto_bt = gtk_button_new_with_label("Go to frame");
+       goto_bt = BUTTON_NEW_FROM_STOCK(GTK_STOCK_JUMP_TO);
        gtk_container_add(GTK_CONTAINER(box4), goto_bt);
        gtk_widget_show(goto_bt);
        SIGNAL_CONNECT(goto_bt, "clicked", on_goto_bt_clicked, user_data);
@@ -1733,18 +2034,23 @@ void create_rtp_dialog(user_data_t* user_data)
        SIGNAL_CONNECT(graph_bt, "clicked", on_graph_bt_clicked, user_data);
 #endif
 
-       next_bt = gtk_button_new_with_label("Next");
+       next_bt = gtk_button_new_with_label("Next non-Ok");
        gtk_container_add(GTK_CONTAINER(box4), next_bt);
        gtk_widget_show(next_bt);
        SIGNAL_CONNECT(next_bt, "clicked", on_next_bt_clicked, user_data);
 
-       close_bt = gtk_button_new_with_label("Close");
+       close_bt = BUTTON_NEW_FROM_STOCK(GTK_STOCK_CLOSE);
        gtk_container_add(GTK_CONTAINER(box4), close_bt);
        gtk_widget_show(close_bt);
        SIGNAL_CONNECT(close_bt, "clicked", on_close_bt_clicked, user_data);
 
        gtk_widget_show(window);
 
+       /* sort by column feature */
+       col_arrows_fwd = add_sort_by_column(window, clist_fwd, user_data);
+       col_arrows_rev = add_sort_by_column(window, clist_rev, user_data);
+
+       /* some widget references need to be saved for outside use */
        user_data->dlg.window = window;
        user_data->dlg.clist_fwd = GTK_CLIST(clist_fwd);
        user_data->dlg.clist_rev = GTK_CLIST(clist_rev);
@@ -1753,12 +2059,14 @@ void create_rtp_dialog(user_data_t* user_data)
        user_data->dlg.notebook = notebook;
        user_data->dlg.selected_clist = GTK_CLIST(clist_fwd);
        user_data->dlg.selected_row = 0;
+       user_data->dlg.col_arrows_fwd = col_arrows_fwd;
+       user_data->dlg.col_arrows_rev = col_arrows_rev;
 }
 
 
 /****************************************************************************/
 static gboolean process_node(proto_node *ptree_node, header_field_info *hfinformation,
-                                                       const gchar* proto_field, guint32* p_result)
+                                                       gchar* proto_field, guint32* p_result)
 {
        field_info            *finfo;
        proto_node            *proto_sibling_node;
@@ -1768,7 +2076,7 @@ static gboolean process_node(proto_node *ptree_node, header_field_info *hfinform
        finfo = PITEM_FINFO(ptree_node);
 
        if (hfinformation==(finfo->hfinfo)) {
-               hfssrc = proto_registrar_get_byname((gchar*) proto_field);
+               hfssrc = proto_registrar_get_byname(proto_field);
                if (hfssrc == NULL)
                        return FALSE;
                for(ptree_node=ptree_node->first_child; ptree_node!=NULL; 
@@ -1798,14 +2106,14 @@ static gboolean process_node(proto_node *ptree_node, header_field_info *hfinform
 
 /****************************************************************************/
 static gboolean get_int_value_from_proto_tree(proto_tree *protocol_tree,
-                                                                                        const gchar* proto_name,
-                                                                                        const gchar* proto_field,
+                                                                                        gchar* proto_name,
+                                                                                        gchar* proto_field,
                                                                                         guint32* p_result)
 {
        proto_node      *ptree_node;
        header_field_info     *hfinformation;
 
-       hfinformation = proto_registrar_get_byname((gchar*) proto_name);
+       hfinformation = proto_registrar_get_byname(proto_name);
        if (hfinformation == NULL)
                return FALSE;
 
@@ -1817,6 +2125,10 @@ static gboolean get_int_value_from_proto_tree(proto_tree *protocol_tree,
 }
 
 
+/* XXX just copied from gtk/rpc_stat.c */
+void protect_thread_critical_region(void);
+void unprotect_thread_critical_region(void);
+
 /****************************************************************************/
 /* XXX only handles RTP over IPv4, should add IPv6 support */
 void rtp_analysis(
@@ -1833,10 +2145,9 @@ void rtp_analysis(
                )
 {
        user_data_t *user_data;
-       gchar filter_text[256];
-       dfilter_t *sfcode;
-       GString *error_string;
+       int fd;
 
+       /* init */
        user_data = g_malloc(sizeof(user_data_t));
 
        user_data->ip_src_fwd = ip_src_fwd;
@@ -1850,41 +2161,14 @@ void rtp_analysis(
        user_data->port_dst_rev = port_dst_rev;
        user_data->ssrc_rev = ssrc_rev;
 
-       create_rtp_dialog(user_data);
-
-       /* Try to compile the filter. */
-       strcpy(filter_text,"rtp && ip");
-       if (!dfilter_compile(filter_text, &sfcode)) {
-               simple_dialog(ESD_TYPE_WARN | ESD_TYPE_MODAL, NULL, dfilter_error_msg);
-               return;
-       }
-
-       sprintf(filter_text,"rtp && ip && !icmp && (( ip.src==%s && udp.srcport==%u && ip.dst==%s && udp.dstport==%u ) || ( ip.src==%s && udp.srcport==%u && ip.dst==%s && udp.dstport==%u ))",
-               ip_to_str((ip_addr_p)&ip_src_fwd),
-               port_src_fwd,
-               ip_to_str((ip_addr_p)&ip_dst_fwd),
-               port_dst_fwd,
-               ip_to_str((ip_addr_p)&ip_src_rev),
-               port_src_rev,
-               ip_to_str((ip_addr_p)&ip_dst_rev),
-               port_dst_rev
-               );
-
-       error_string = register_tap_listener("rtp", user_data, filter_text,
-               (void*)rtp_reset, (void*)rtp_packet, (void*)rtp_draw);
-       if (error_string != NULL) {
-               simple_dialog(ESD_TYPE_WARN | ESD_TYPE_MODAL, NULL, error_string->str);
-                       g_string_free(error_string, TRUE);
-               g_free(user_data);
-               return;
-               /*exit(1);*/
-       }
-
        /* file names for storing sound data */
-       strncpy(user_data->f_tempname, "f_tempnameXXXXXX", TMPNAMSIZE);
-       strncpy(user_data->r_tempname, "r_tempnameXXXXXX", TMPNAMSIZE);
-       mkstemp(user_data->f_tempname);
-       mkstemp(user_data->r_tempname);
+       /*XXX: check for errors*/
+       fd = create_tempfile(user_data->f_tempname, sizeof(user_data->f_tempname),
+               "ether_rtp_f");
+       close(fd);
+       fd = create_tempfile(user_data->r_tempname, sizeof(user_data->r_tempname),
+               "ether_rtp_r");
+       close(fd);
        user_data->forward.saveinfo.fp = NULL;
        user_data->reversed.saveinfo.fp = NULL;
        user_data->dlg.save_voice_as_w = NULL;
@@ -1895,9 +2179,11 @@ void rtp_analysis(
        user_data->series_rev.value_pairs = NULL;
 #endif
 
-       redissect_packets(&cfile);
+       /* create the dialog box */
+       create_rtp_dialog(user_data);
 
-       draw_stat(user_data);
+       /* proceed as if the Refresh button would have been pressed */
+       on_refresh_bt_clicked(NULL, user_data);
 }
 
 /****************************************************************************/
@@ -1920,6 +2206,7 @@ void rtp_analysis_cb(GtkWidget *w _U_, gpointer data _U_)
        capture_file *cf;
        epan_dissect_t *edt;
        gint err;
+       gchar *err_info;
        gboolean frame_matched;
        frame_data *fdata;
        GList *strinfo_list;
@@ -1942,9 +2229,10 @@ 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)) {
+       if (!wtap_seek_read(cf->wth, fdata->file_off, &cf->pseudo_header,
+           cf->pd, fdata->cap_len, &err, &err_info)) {
                simple_dialog(ESD_TYPE_WARN | ESD_TYPE_MODAL, NULL,
-                       file_read_error_message(err), cf->filename);
+                       cf_read_error_message(err, err_info), cf->filename);
                return;
        }
        edt = epan_dissect_new(TRUE, FALSE);
@@ -1955,13 +2243,9 @@ void rtp_analysis_cb(GtkWidget *w _U_, gpointer data _U_)
        /* if it is not an rtp frame, show the rtpstream dialog */
        frame_matched = dfilter_apply_edt(sfcode, edt);
        if (frame_matched != 1) {
-               rtpstream_dlg_show(rtpstream_get_info()->strinfo_list);
-               return;
-/*
                epan_dissect_free(edt);
                simple_dialog(ESD_TYPE_WARN | ESD_TYPE_MODAL, NULL, "You didn't choose a RTP packet!");
                return;
-*/
        }
 
        /* ok, it is a RTP frame, so let's get the ip and port values */
@@ -2048,6 +2332,6 @@ register_tap_listener_rtp_analysis(void)
 void
 register_tap_menu_rtp_analysis(void)
 {
-       register_tap_menu_item("Statistics/RTP Streams/Analyse...",
+       register_tap_menu_item("_Statistics/RTP Streams/Analyse...",
            rtp_analysis_cb, NULL, NULL, NULL);
 }