Alejandro Vaquero:
[obnox/wireshark/wip.git] / gtk / rtp_player.c
1  /* rtp_player.c
2  *
3  * $Id$
4  *
5  *  Copyright 2006, Alejandro Vaquero <alejandrovaquero@yahoo.com>
6  *
7  * Wireshark - Network traffic analyzer
8  * By Gerald Combs <gerald@wireshark.org>
9  * Copyright 1999 Gerald Combs
10  *
11  * This program is free software; you can redistribute it and/or
12  * modify it under the terms of the GNU General Public License
13  * as published by the Free Software Foundation; either version 2
14  * of the License, or (at your option) any later version.
15  *
16  * This program is distributed in the hope that it will be useful,
17  * but WITHOUT ANY WARRANTY; without even the implied warranty of
18  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19  * GNU General Public License for more details.
20  *
21  * You should have received a copy of the GNU General Public License
22  * along with this program; if not, write to the Free Software
23  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
24  */
25
26 /*
27  * Here is a summary on how this works:
28  *  - The VoipCalls will call add_rtp_packet() every time there is an RTP
29  *    packet
30  *  - add_rtp_packet() will add the RTP packet in a RTP stream struct, and
31  *    create the RTP stream if it is the  first RTP in the stream.
32  *  - Each new RTP stream will be added to a list of RTP stream, called
33  *    rtp_streams_list
34  *  - When the user clicks "Player" in the VoipCall dialogue,
35  *    rtp_player_init() is called.
36  *  - rtp_player_init() create the main dialog, and it calls:
37  *    + mark_rtp_stream_to_play() to mark the RTP streams that needs to be
38  *      displayed. These are the RTP stream that match the selected calls in
39  *      the VoipCall dlg.
40  *    + decode_rtp_stream() this will decode the RTP packets in each RTP
41  *      stream, and will also create  the RTP channles. An RTP channel is a
42  *      group of RTP stream that have in common the source and destination
43  *      IP and UPD ports. The RTP channels is what the user will listen in
44  *      one of the two Audio channles. 
45  *      The RTP channels are stored in the hash table rtp_channels_hash
46  *    + add_channel_to_window() will create and add the Audio graphic
47  *      representation in the main window
48  *  - When the user click the check box to listen one of the Audio channels,
49  *    the structure rtp_channels is filled  to play one or two RTP channels
50  *    (a max of two channels can be listened at a given moment)
51  */
52
53
54 #ifdef HAVE_CONFIG_H
55 #include "config.h"
56 #endif
57
58 #ifdef HAVE_LIBPORTAUDIO
59
60 #include <epan/stats_tree.h>
61 #include <epan/addr_resolv.h>
62 #include <string.h>
63 #include <glib.h>
64 #include <gtk/gtk.h>
65 #include "globals.h"
66 #include "portaudio.h"
67 #include "simple_dialog.h"
68 #include "gui_utils.h"
69 #include "dlg_utils.h"
70 #include "compat_macros.h"
71
72 #include "graph_analysis.h"
73 #include "voip_calls_dlg.h"
74 #include "voip_calls.h"
75 #include "gtkglobals.h"
76
77
78 #include <epan/dissectors/packet-rtp.h>
79
80 #include "rtp_player.h"
81 #include "codecs/G711a/G711adecode.h"
82 #include "codecs/G711u/G711udecode.h"
83 #include <math.h>
84
85 #ifndef min
86 #define min(a,b) (((a)<(b))?(a):(b))
87 #endif
88 #ifndef max
89 #define max(a,b) (((a)>(b))?(a):(b))
90 #endif
91
92 /*define this symbol to compile with G729 and G723 codecs*/
93 /*#define HAVE_G729_G723 1*/
94
95 #ifdef HAVE_G729_G723
96 #include "codecs/G729/G729decode.h"
97 #include "codecs/G723/G723decode.h"
98 #endif /* HAVE_G729_G723 */
99
100 static gboolean initialized = FALSE;
101
102 voip_calls_tapinfo_t *voip_calls = NULL;
103
104 /* Hash table with all the RTP streams */
105 static GHashTable*  rtp_streams_hash = NULL;
106
107 /* List with all the RTP streams (this is used to decode them as it is sorted)*/
108 static GList*  rtp_streams_list = NULL;
109
110 /* the window */
111 static GtkWidget *rtp_player_dlg_w;
112 static GtkWidget *channels_vb;
113 static GtkWidget *main_scrolled_window = NULL;
114 static GtkWidget *jitter_spinner;
115 static GtkWidget *bt_decode;
116 static GtkWidget *bt_play;
117 static GtkWidget *bt_pause;
118 static GtkWidget *bt_stop;
119 static GtkWidget *progress_bar;
120 static GtkWidget *info_bar;
121 static GtkWidget *stat_hbox;
122
123 static guint32 total_packets;
124 static guint32 total_frames;
125 static guint32 progbar_count;
126
127 static int new_jitter_buff;
128
129 /* a hash table with the RTP streams to play per audio channel */
130 static GHashTable *rtp_channels_hash = NULL;
131
132 /* Port Audio staff */
133 #define SAMPLE_RATE  (8000)
134 #define NUM_CHANNELS    (2)
135
136 #define PA_SAMPLE_TYPE  paInt16
137 typedef gint16 SAMPLE;
138 #define SAMPLE_SILENCE  (0)
139 #define FRAMES_PER_BUFFER  (512)
140
141 typedef struct _sample_t {
142         SAMPLE val;
143         guint8 status;
144 } sample_t;
145
146 #define S_NORMAL 0
147 #define S_DROP_BY_JITT 1
148 #define S_WRONG_SEQ 2
149
150 /* Display channels constants */
151 #define MULT 80
152 #define CHANNEL_WIDTH 500
153 #define CHANNEL_HEIGHT 100
154 #define MAX_TIME_LABEL 10
155 #define HEIGHT_TIME_LABEL 18
156 #define MAX_NUM_COL_CONV 10
157
158 #if PORTAUDIO_API_1
159 PortAudioStream *pa_stream;
160 #else /* PORTAUDIO_API_1 */
161 PaStream *pa_stream;
162 #endif /* PORTAUDIO_API_1 */
163
164 /* TODO: The RTP Player it is only supported for GTK >=2 */
165 #if GTK_MAJOR_VERSION >= 2
166
167 /* defines a RTP stream */
168 typedef struct _rtp_stream_info {
169         address src_addr;
170         guint16 src_port;
171         address dest_addr;
172         guint16 dest_port;
173         guint32 ssrc;
174         guint32 first_frame_number; /* first RTP frame for the stream */
175         double start_time;                      /* RTP stream start time in ms */
176         gboolean play;
177         guint16 call_num;
178         GList*  rtp_packets_list; /* List of RTP packets in the stream */
179         guint32 num_packets;
180 } rtp_stream_info_t;
181
182
183 /* defines the RTP streams to be played in an audio channel */
184 typedef struct _rtp_channel_info {
185         double start_time;                      /* RTP stream start time in ms */
186         double end_time;                        /* RTP stream end time in ms */
187         GArray *samples;                        /* the array with decoded audio */
188         guint16 call_num;
189         gboolean selected;
190         guint32 frame_index;
191         guint32 drop_by_jitter_buff;
192         guint32 out_of_seq;
193         guint32 max_frame_index;
194         GtkWidget *check_bt;
195         GtkWidget *separator;
196         GtkWidget *scroll_window;
197         GtkWidget *draw_area;
198         GdkPixmap *pixmap;
199         GtkAdjustment *h_scrollbar_adjustment;
200         GdkPixbuf* cursor_pixbuf;
201 #if PORTAUDIO_API_1
202         PaTimestamp cursor_prev;
203 #else /* PORTAUDIO_API_1 */
204         PaTime cursor_prev;
205 #endif /* PORTAUDIO_API_1 */
206         GdkGC *bg_gc[MAX_NUM_COL_CONV+1];
207         gboolean cursor_catch;
208         rtp_stream_info_t *first_stream;        /* This is the first RTP stream in the channel */
209         guint32 num_packets;
210 } rtp_channel_info_t;
211
212 /* defines a RTP packet */
213 typedef struct _rtp_packet {
214         struct _rtp_info *info; /* the RTP dissected info */
215         double arrive_offset;   /* arrive offset time since the begining of the stream in ms */
216         guint8* payload_data;
217 } rtp_packet_t;
218
219 /* defines the two RTP channels to be played */
220 typedef struct _rtp_play_channles {
221         rtp_channel_info_t* rci[2]; /* Channels to be played */
222         guint32 start_index[2];
223         guint32 end_index[2];
224         int channel;
225         guint32 max_frame_index;
226         guint32 frame_index;
227         gboolean pause;
228         gboolean stop;
229         gint32 pause_duration;
230 #if PORTAUDIO_API_1
231         PaTimestamp out_diff_time;
232 #else /* PORTAUDIO_API_1 */
233         PaTime out_diff_time;
234         PaTime pa_start_time;
235 #endif /* PORTAUDIO_API_1 */
236 } rtp_play_channles_t;
237
238 /* The two RTP channles to play */
239 static rtp_play_channles_t *rtp_channels = NULL;
240
241
242 /****************************************************************************/
243 static void 
244 rtp_key_destroy(gpointer key)
245 {
246         g_free(key);
247         key = NULL;
248 }
249
250 /****************************************************************************/
251 static void 
252 rtp_channel_value_destroy(gpointer rci_arg)
253 {
254         rtp_channel_info_t *rci = rci_arg;
255
256         g_array_free(rci->samples, TRUE);
257         g_free(rci);
258         rci = NULL;
259 }
260
261 /****************************************************************************/
262 static void 
263 rtp_stream_value_destroy(gpointer rsi_arg)
264 {
265         rtp_stream_info_t *rsi = rsi_arg;
266         GList*  rtp_packets_list;
267         rtp_packet_t *rp;
268
269         rtp_packets_list = g_list_first(rsi->rtp_packets_list);
270         while (rtp_packets_list)
271         {
272                 rp = rtp_packets_list->data;
273
274                 g_free(rp->info);
275                 g_free(rp->payload_data);
276                 g_free(rp);
277                 rp = NULL;
278         
279                 rtp_packets_list = g_list_next(rtp_packets_list);
280         }
281         g_free(rsi);
282         rsi = NULL;
283 }
284
285 /****************************************************************************/
286 static void
287 set_sensitive_check_bt(gchar *key _U_ , rtp_channel_info_t *rci, guint *stop _U_ ) 
288 {
289         gtk_widget_set_sensitive(rci->check_bt, !(*stop));      
290 }
291
292 /****************************************************************************/
293 static void 
294 bt_state(gboolean decode, gboolean play, gboolean pause, gboolean stop)
295 {
296         gboolean new_jitter_value = FALSE;
297         gboolean false_val = FALSE;
298
299         gtk_widget_set_sensitive(bt_decode, decode);
300         gtk_widget_set_sensitive(jitter_spinner, decode);
301                 
302         if (new_jitter_buff != (int) gtk_spin_button_get_value((GtkSpinButton * )jitter_spinner)) {
303                 new_jitter_value = TRUE;
304         }
305
306         /* set the sensitive state of play only if there is a channel selected */
307         if ( play && (rtp_channels->rci[0] || rtp_channels->rci[1]) && !new_jitter_value) {             
308                 gtk_widget_set_sensitive(bt_play, TRUE);
309         } else {
310                 gtk_widget_set_sensitive(bt_play, FALSE);
311         }
312         
313         if (!new_jitter_value) {
314                 gtk_widget_set_sensitive(bt_pause, pause);
315                 gtk_widget_set_sensitive(bt_stop, stop);
316
317                 /* Set sensitive to the check buttons based on the STOP state */
318                 g_hash_table_foreach( rtp_channels_hash, (GHFunc)set_sensitive_check_bt, &stop);        
319         } else {
320                 gtk_widget_set_sensitive(bt_pause, FALSE);
321                 gtk_widget_set_sensitive(bt_stop, FALSE);
322
323                 g_hash_table_foreach( rtp_channels_hash, (GHFunc)set_sensitive_check_bt, &false_val);   
324         }
325 }
326
327 /****************************************************************************/
328 void 
329 add_rtp_packet(const struct _rtp_info *rtp_info, packet_info *pinfo)
330 {
331         rtp_stream_info_t *stream_info = NULL;
332         rtp_packet_t *new_rtp_packet;
333         GString *key_str = NULL;
334
335         /* create the the streams hash if it doen't exist */
336         if (!rtp_streams_hash)
337                 rtp_streams_hash = g_hash_table_new_full( g_str_hash, g_str_equal, rtp_key_destroy, rtp_stream_value_destroy);
338
339         /* Create a hash key to lookup in the RTP streams hash table
340          * uses: src_ip:src_port dst_ip:dst_port ssrc
341          */
342         key_str = g_string_new("");
343         g_string_printf(key_str, "%s:%d %s:%d %d", get_addr_name(&(pinfo->src)),
344                 pinfo->srcport, get_addr_name(&(pinfo->dst)),
345                 pinfo->destport, rtp_info->info_sync_src );
346
347         /* lookup for this rtp packet in the stream hash table*/
348         stream_info =  g_hash_table_lookup( rtp_streams_hash, key_str->str);
349
350         /* if it is not in the hash table, create a new stream */
351         if (stream_info==NULL) {
352                 stream_info = g_malloc(sizeof(rtp_stream_info_t));
353                 COPY_ADDRESS(&(stream_info->src_addr), &(pinfo->src));
354                 stream_info->src_port = pinfo->srcport;
355                 COPY_ADDRESS(&(stream_info->dest_addr), &(pinfo->dst));
356                 stream_info->dest_port = pinfo->destport;
357                 stream_info->ssrc = rtp_info->info_sync_src;
358                 stream_info->rtp_packets_list = NULL;
359                 stream_info->first_frame_number = pinfo->fd->num;
360                 stream_info->start_time = nstime_to_msec(&pinfo->fd->rel_ts);
361                 stream_info->call_num = 0;
362                 stream_info->play = FALSE;
363                 stream_info->num_packets = 0;
364
365                 g_hash_table_insert(rtp_streams_hash, g_strdup(key_str->str), stream_info);
366
367                 /* Add the element to the List too. The List is used to decode the packets because it is sordted */
368                 rtp_streams_list = g_list_append(rtp_streams_list, stream_info);
369         }
370
371         /* increment the number of packets in this stream, this is used for the progress bar and statistics*/
372         stream_info->num_packets++;
373
374         /* Add the RTP packet to the list */
375         new_rtp_packet = g_malloc(sizeof(rtp_packet_t));
376         new_rtp_packet->info = g_malloc(sizeof(struct _rtp_info));
377
378         memcpy(new_rtp_packet->info, rtp_info, sizeof(struct _rtp_info));
379         new_rtp_packet->arrive_offset = nstime_to_msec(&pinfo->fd->rel_ts) - stream_info->start_time;
380         /* copy the RTP payload to the rtp_packet to be decoded later */
381         if (rtp_info->info_payload_len) {
382                 new_rtp_packet->payload_data = g_malloc(rtp_info->info_payload_len);
383                 memcpy(new_rtp_packet->payload_data, &(rtp_info->info_data[rtp_info->info_payload_offset]), rtp_info->info_payload_len);
384         } else {
385                 new_rtp_packet->payload_data = NULL;
386         }
387
388         stream_info->rtp_packets_list = g_list_append(stream_info->rtp_packets_list, new_rtp_packet);
389
390         g_string_free(key_str, TRUE);
391 }
392
393 /****************************************************************************/
394 /* Mark the RTP stream to be played. Use the voip_calls graph to see if the 
395  * setup_frame is there and then if the associated voip_call is selected.
396  */
397 static void 
398 mark_rtp_stream_to_play(gchar *key _U_ , rtp_stream_info_t *rsi, gpointer ptr _U_)
399 {
400         GList*  graph_list;
401         graph_analysis_item_t *graph_item;
402         GList*  voip_calls_list;
403         voip_calls_info_t *tmp_voip_call;
404
405         /* Reset the "to be play" value because the user can close and reopen the RTP Player window
406          * and the streams are nor reset in that case
407          */
408         rsi->play = FALSE;
409
410         /* and associate the RTP stream with a call using the first RTP in the stream*/
411         graph_list = g_list_first(voip_calls->graph_analysis->list);
412         while (graph_list)
413         {
414                 graph_item = graph_list->data;
415                 if (rsi->first_frame_number == graph_item->frame_num) {
416                         rsi->call_num = graph_item->conv_num;
417                         /* if it is in the graph list, then check if the voip_call is selected */
418                         voip_calls_list = g_list_first(voip_calls->strinfo_list);
419                         while (voip_calls_list)
420                         {
421                                 tmp_voip_call = voip_calls_list->data;
422                                 if ( (tmp_voip_call->call_num == rsi->call_num) && (tmp_voip_call->selected == TRUE) ) {
423                                         rsi->play = TRUE;
424                                         total_packets += rsi->num_packets;
425                                         break;
426                                 }
427                                 voip_calls_list = g_list_next(voip_calls_list);
428                         }
429                         break;
430                 }
431                 graph_list = g_list_next(graph_list);
432         }
433 }
434
435
436 /****************************************************************************/
437 /* Decode a RTP packet 
438  * Return the number of decoded bytes
439  */
440 static int 
441 decode_rtp_packet(rtp_packet_t *rp, rtp_channel_info_t *rci, SAMPLE **out_buff)
442 {
443         unsigned int  payload_type;
444         SAMPLE *tmp_buff = NULL;
445         int decoded_bytes = 0;
446
447         if ((rp->payload_data == NULL) || (rp->info->info_payload_len == 0) ) {
448                 return 0;
449         }
450
451         payload_type = rp->info->info_payload_type;
452         switch (payload_type) {
453         case 0: /* G711 Ulaw */
454                 tmp_buff = malloc(sizeof(SAMPLE) * rp->info->info_payload_len * 1);
455                 decodeG711u(rp->payload_data, rp->info->info_payload_len,
456                           tmp_buff, &decoded_bytes);
457                 break; 
458         case 8: /* G711 Alaw */
459                 tmp_buff = malloc(sizeof(SAMPLE) * rp->info->info_payload_len * 1);
460                 decodeG711a(rp->payload_data, rp->info->info_payload_len,
461                           tmp_buff, &decoded_bytes);
462                 break; 
463 #ifdef HAVE_G729_G723
464         case 18:        /* G729 */
465                 tmp_buff = malloc(sizeof(SAMPLE) * rp->info->info_payload_len * 8); /* G729 8kbps => 64kbps/8kbps = 8  */
466                 decodeG729(rp->payload_data, rp->info->info_payload_len,
467                           tmp_buff, &decoded_bytes);
468                 break; 
469         case 4: /* G723 */
470
471                 if (rp->info->info_payload_len%24 == 0) /* G723 High 6.4kbps */
472                         tmp_buff = malloc(sizeof(SAMPLE) * rp->info->info_payload_len * 10); /* G723 High 64kbps/6.4kbps = 10  */       
473                 else if (rp->info->info_payload_len%20 == 0)    /* G723 Low 5.3kbps */
474                         tmp_buff = malloc(sizeof(SAMPLE) * rp->info->info_payload_len * 13); /* G723 High 64kbps/5.3kbps = 13  */       
475                 else {
476                   return 0;
477                 }
478                 decodeG723(rp->payload_data, rp->info->info_payload_len,
479                           tmp_buff, &decoded_bytes);
480                 break;
481 #endif /* HAVE_G729_G723 */
482         } 
483
484         *out_buff = tmp_buff;
485         return decoded_bytes;
486 }
487
488 /****************************************************************************/
489 void
490 update_progress_bar(gfloat percentage)
491 {
492
493         gtk_progress_bar_update(GTK_PROGRESS_BAR(progress_bar), percentage);
494
495         /* Force gtk to redraw the window before starting decoding the packet */
496         while (gtk_events_pending())
497                 gtk_main_iteration();
498 }
499
500 /****************************************************************************/
501 /* Decode the RTP streams and add them to the RTP channels struct
502  */
503 static void 
504 decode_rtp_stream(rtp_stream_info_t *rsi, gpointer ptr _U_)
505 {
506         GString *key_str = NULL;
507         rtp_channel_info_t *rci;
508         gboolean first = TRUE;
509         GList*  rtp_packets_list;
510         rtp_packet_t *rp;
511
512         int i;
513         double rtp_time;
514         double rtp_time_prev;
515         double arrive_time;
516         double arrive_time_prev;
517         double start_time;
518         double start_rtp_time;
519         double diff;
520         double pack_period;
521         double total_time;
522         double total_time_prev;
523         gint32 silence_frames;
524         int seq;
525         double delay;
526         double prev_diff;
527         double mean_delay;
528         double variation;
529         int decoded_bytes;
530         int decoded_bytes_prev;
531         int jitter_buff;
532         SAMPLE *out_buff = NULL;
533         sample_t silence;
534         sample_t sample;
535         guint8 status;
536         guint32 start_timestamp; 
537
538         guint32 progbar_nextstep;
539         int progbar_quantum;
540         gfloat progbar_val;
541
542         silence.val = 0;
543         silence.status = S_NORMAL;
544
545         /* skip it if we are not going to play it */ 
546         if (rsi->play == FALSE) {
547                 return;
548         }
549
550         /* get the static jitter buffer from the spinner gui */
551         jitter_buff = (int) gtk_spin_button_get_value((GtkSpinButton * )jitter_spinner);
552
553         /* Create a hash key to lookup in the RTP channels hash
554          * uses: src_ip:src_port dst_ip:dst_port call_num
555          */
556         key_str = g_string_new("");
557         g_string_printf(key_str, "%s:%d %s:%d %d", get_addr_name(&(rsi->src_addr)),
558                 rsi->src_port, get_addr_name(&(rsi->dest_addr)),
559                 rsi->dest_port, rsi->call_num );
560
561         /* create the rtp_channels_hash table if it doesn't exist */
562         if (!rtp_channels_hash) {
563                 rtp_channels_hash = g_hash_table_new_full( g_str_hash, g_str_equal, rtp_key_destroy, rtp_channel_value_destroy);
564         }
565
566         /* lookup for this stream in the channel hash table */
567         rci =  g_hash_table_lookup( rtp_channels_hash, key_str->str);
568
569         /* ..if it is not in the hash, create an entry */
570         if (rci == NULL) {
571                 rci = malloc(sizeof(rtp_channel_info_t));
572                 rci->call_num = rsi->call_num;
573                 rci->start_time = rsi->start_time;
574                 rci->end_time = rsi->start_time;                
575                 rci->selected = FALSE;
576                 rci->frame_index = 0;
577                 rci->drop_by_jitter_buff = 0;
578                 rci->out_of_seq = 0;
579                 rci->max_frame_index = 0;
580                 rci->samples = g_array_new (FALSE, FALSE, sizeof(sample_t));
581                 rci->check_bt = NULL;
582                 rci->separator = NULL;
583                 rci->draw_area = NULL;
584                 rci->pixmap = NULL;
585                 rci->h_scrollbar_adjustment = NULL;
586                 rci->cursor_pixbuf = NULL;
587                 rci->cursor_prev = 0;
588                 rci->cursor_catch = FALSE;
589                 rci->first_stream = rsi;
590                 rci->num_packets = rsi->num_packets;
591                 g_hash_table_insert(rtp_channels_hash, g_strdup(key_str->str), rci);
592         } else {
593                 /* Add silence between the two streams if needed */
594                 silence_frames = (gint32)( ((rsi->start_time - rci->end_time)/1000)*SAMPLE_RATE );
595                 for (i = 0; i< silence_frames; i++) {
596                         g_array_append_val(rci->samples, silence);
597                 }
598                 rci->num_packets += rsi->num_packets;
599         }
600
601         /* decode the RTP stream */
602         first = TRUE;
603         rtp_time = 0;
604         decoded_bytes = 0;
605         decoded_bytes_prev = 0;
606         silence_frames = 0;
607         arrive_time = start_time = 0;
608         arrive_time_prev = 0;
609         pack_period = 0;
610         total_time = 0;
611         total_time_prev = 0;
612         seq = 0;
613         delay = 0;
614         prev_diff = 0;
615         mean_delay = 0;
616         variation = 0;
617         start_timestamp = 0;
618
619         /* we update the progress bar 100 times */
620         progbar_quantum = total_packets/100;
621         progbar_nextstep = progbar_count;
622
623         status = S_NORMAL;
624
625         rtp_packets_list = g_list_first(rsi->rtp_packets_list);
626         while (rtp_packets_list)
627         {
628
629                 if (progbar_count >= progbar_nextstep) {
630                         g_assert(total_packets > 0);
631
632                         progbar_val = (gfloat) progbar_count / total_packets;
633
634                         update_progress_bar(progbar_val);
635
636                         progbar_nextstep += progbar_quantum;
637                 }
638                 
639
640                 rp = rtp_packets_list->data;
641                 if (first == TRUE) {
642                         start_timestamp = rp->info->info_timestamp; /* defined start_timestmp to avoid overflow in timestamp. TODO: handle the timestamp correctly */
643                         start_rtp_time = 0;
644                         rtp_time_prev = start_rtp_time;
645                         first = FALSE;
646                         seq = rp->info->info_seq_num - 1;
647                 }
648
649                 decoded_bytes = decode_rtp_packet(rp, rci, &out_buff);
650                 if (decoded_bytes == 0) {
651                         seq = rp->info->info_seq_num;
652                 }
653
654                 rtp_time = (double)(rp->info->info_timestamp-start_timestamp)/SAMPLE_RATE - start_rtp_time;
655                 arrive_time = (double)rp->arrive_offset/1000 - start_time;
656
657                 if (rp->info->info_seq_num != seq+1){
658                         rci->out_of_seq++;
659                         status = S_WRONG_SEQ;
660                 }
661                 seq = rp->info->info_seq_num;
662
663                 diff = arrive_time - rtp_time;
664
665                 delay = diff - prev_diff;
666                 prev_diff = diff;
667                 if (delay<0) delay = -delay;
668
669                 if (diff<0) diff = -diff;
670   
671                 total_time = (double)rp->arrive_offset/1000;
672                 
673                 printf("seq = %d arr = %f abs_diff = %f index = %d tim = %f ji=%d jb=%f\n",rp->info->info_seq_num, 
674                         total_time, diff, rci->samples->len, ((double)rci->samples->len/8000 - total_time)*1000, 0,
675                                 (mean_delay + 4*variation)*1000);
676                 fflush(stdout);
677
678                 /* if the jitter buffer was exceded */  
679                 if ( diff*1000 > jitter_buff ) {
680                         printf("Packet drop by jitter buffer exceded\n");
681                         rci->drop_by_jitter_buff++;
682                         status = S_DROP_BY_JITT;
683
684                         /* if there was a silence period (more than two packetization period) resync the source */
685                         if ( (rtp_time - rtp_time_prev) > pack_period*2 ){
686                                 printf("Resync...\n");
687
688                                 silence_frames = (gint32)((arrive_time - arrive_time_prev)*SAMPLE_RATE - decoded_bytes_prev/2);
689                                 for (i = 0; i< silence_frames; i++) {
690                                         silence.status = status;
691                                         g_array_append_val(rci->samples, silence);
692
693                                         /* only mark the fisrt in the silence that has the previos problem (S_DROP_BY_JITT  or S_WRONG_SEQ ) */
694                                         status = S_NORMAL;
695                                 }
696
697                                 decoded_bytes_prev = 0;
698                                 start_timestamp = rp->info->info_timestamp; /* defined start_timestmp to avoid overflow in timestamp. TODO: handle the timestamp correctly */
699                                 start_rtp_time = 0;
700                                 start_time = (double)rp->arrive_offset/1000;
701                                 rtp_time_prev = 0;
702                         }
703                 } else {
704                         /* Add silence if it is necessary */
705                         silence_frames = (gint32)((rtp_time - rtp_time_prev)*SAMPLE_RATE - decoded_bytes_prev/2);
706                         for (i = 0; i< silence_frames; i++) {
707                                 silence.status = status;
708                                 g_array_append_val(rci->samples, silence);
709
710                                 /* only mark the fisrt in the silence that has the previos problem (S_DROP_BY_JITT  or S_WRONG_SEQ ) */
711                                 status = S_NORMAL;
712                         }
713
714                         status = S_NORMAL;
715
716                         /* Add the audio */
717                         for (i = 0; i< (decoded_bytes/2); i++) {
718                                 sample.val = out_buff[i];
719                                 sample.status = status;
720                                 g_array_append_val(rci->samples, sample);
721                         }
722         
723                         rtp_time_prev = rtp_time;
724                         pack_period = (double)(decoded_bytes/2)/SAMPLE_RATE;
725                         decoded_bytes_prev = decoded_bytes;
726                         arrive_time_prev = arrive_time;
727
728                 }
729
730                 rtp_packets_list = g_list_next (rtp_packets_list);
731                 progbar_count++;
732         }
733         rci->max_frame_index = rci->samples->len;
734         rci->end_time = rci->start_time + ((double)rci->samples->len/SAMPLE_RATE)*1000;
735
736         g_string_free(key_str, TRUE);
737 }
738
739 /****************************************************************************/
740 static gint 
741 h_scrollbar_changed(GtkWidget *widget _U_, gpointer user_data)
742 {
743         rtp_channel_info_t *rci = (rtp_channel_info_t *)user_data;
744         rci->cursor_catch = TRUE;
745         return TRUE;
746 }
747
748 static gboolean draw_cursors(gpointer data);
749
750 /****************************************************************************/
751 static void
752 stop_channels(void) 
753 {       
754         PaError err;
755         GtkWidget *dialog;
756
757         /* we should never be here if we are already in STOP */
758         if(rtp_channels->stop){
759                 exit(10);
760         }
761
762         rtp_channels->stop = TRUE;
763         /* force a draw_cursor to stop it */
764         draw_cursors(NULL);
765
766         err = Pa_StopStream(pa_stream);
767
768         if( err != paNoError ) {
769                 dialog = gtk_message_dialog_new ((GtkWindow *) rtp_player_dlg_w,
770                                                           GTK_DIALOG_DESTROY_WITH_PARENT, GTK_MESSAGE_ERROR,GTK_BUTTONS_CLOSE,
771                                                           "Can not Stop Stream in PortAduio Library.\n Error: %s", Pa_GetErrorText( err ));
772                 gtk_dialog_run (GTK_DIALOG (dialog));
773                 gtk_widget_destroy (dialog);
774                 return;
775         }
776
777         err = Pa_CloseStream(pa_stream);
778         if( err != paNoError ) {
779                 dialog = gtk_message_dialog_new ((GtkWindow *) rtp_player_dlg_w,
780                                                           GTK_DIALOG_DESTROY_WITH_PARENT, GTK_MESSAGE_ERROR,GTK_BUTTONS_CLOSE,
781                                                           "Can not Close Stream in PortAduio Library.\n Error: %s", Pa_GetErrorText( err ));
782                 gtk_dialog_run (GTK_DIALOG (dialog));
783                 gtk_widget_destroy (dialog);
784                 return;
785         }
786
787         rtp_channels->start_index[0] = 0;
788         rtp_channels->start_index[1] = 0;
789         rtp_channels->end_index[0] = 0;
790         rtp_channels->end_index[1] = 0;
791         rtp_channels->max_frame_index = 0;
792         rtp_channels->frame_index = 0;
793         rtp_channels->pause = FALSE;
794         rtp_channels->pause_duration = 0;
795         rtp_channels->stop = TRUE;
796         rtp_channels->out_diff_time = 10000;
797
798         if (rtp_channels->rci[0]) rtp_channels->rci[0]->frame_index = 0;
799         if (rtp_channels->rci[1]) rtp_channels->rci[1]->frame_index = 0;
800
801         /* set the sensitive state of the buttons (decode, play, pause, stop) */
802         bt_state(TRUE, TRUE, FALSE, FALSE);
803
804 }
805
806 /****************************************************************************/
807 /* Draw a cursor in a channel graph 
808  */
809 static void 
810 draw_channel_cursor(rtp_channel_info_t *rci, guint32 start_index)
811 {
812 #if PORTAUDIO_API_1
813         PaTimestamp index;
814 #else /* PORTAUDIO_API_1 */
815         PaTime index;
816 #endif /* PORTAUDIO_API_1 */
817         int i;
818
819         if (!rci) return;
820
821 #if PORTAUDIO_API_1
822         index = Pa_StreamTime( pa_stream ) - rtp_channels->pause_duration - rtp_channels->out_diff_time - start_index;
823 #else  /* PORTAUDIO_API_1 */
824         index = ((guint32)(SAMPLE_RATE) * (Pa_GetStreamTime(pa_stream)-rtp_channels->pa_start_time))- rtp_channels->pause_duration - rtp_channels->out_diff_time - start_index;
825 #endif  /* PORTAUDIO_API_1 */
826
827
828         /* If we finished playing both channels, then stop them */
829         if ( (rtp_channels && (!rtp_channels->stop) && (!rtp_channels->pause)) && (index > rtp_channels->max_frame_index) ) {
830                 stop_channels();
831                 return;
832         }
833
834         /* If only this channel finished, then return */
835         if (index > rci->max_frame_index) {
836                 return;
837         }
838
839         /* draw the previous saved pixbuf line */
840         if (rci->cursor_pixbuf && (rci->cursor_prev>=0)) {
841
842                 gdk_draw_pixbuf(rci->pixmap, NULL, rci->cursor_pixbuf, 0, 0, (int) (rci->cursor_prev/MULT), 0, -1, -1, GDK_RGB_DITHER_NONE, 0 ,0);
843
844                 gdk_draw_drawable(rci->draw_area->window,
845                         rci->draw_area->style->fg_gc[GTK_WIDGET_STATE(rci->draw_area)],
846                         rci->pixmap,
847                         (int) (rci->cursor_prev/MULT), 0,
848                         (int) (rci->cursor_prev/MULT), 0,
849                         1, rci->draw_area->allocation.height-HEIGHT_TIME_LABEL);
850
851                 g_object_unref(rci->cursor_pixbuf);
852         }
853
854         if (index>0 && (rci->cursor_prev>=0)) {
855                 rci->cursor_pixbuf = gdk_pixbuf_get_from_drawable(NULL, rci->pixmap, NULL, (int) (index/MULT), 0, 0, 0, 1, rci->draw_area->allocation.height-HEIGHT_TIME_LABEL);
856
857                 gdk_draw_line(rci->pixmap, rci->draw_area->style->black_gc,
858                         (int) (index/MULT),
859                         0,
860                         (int) (index/MULT),
861                         rci->draw_area->allocation.height-HEIGHT_TIME_LABEL);
862
863                 gdk_draw_drawable(rci->draw_area->window,
864                         rci->draw_area->style->fg_gc[GTK_WIDGET_STATE(rci->draw_area)], 
865                         rci->pixmap,
866                         (int) (index/MULT), 0,
867                         (int) (index/MULT), 0,
868                         1, rci->draw_area->allocation.height-HEIGHT_TIME_LABEL);
869         }
870
871         /* Disconnect the scroll bar "value" signal to not be called */
872         SIGNAL_DISCONNECT_BY_FUNC(rci->h_scrollbar_adjustment, h_scrollbar_changed, rci);
873
874         /* Move the horizontal scroll bar */
875 /*      if ( (rci->cursor_prev/MULT < (rci->h_scrollbar_adjustment->value+rci->h_scrollbar_adjustment->page_increment)) && 
876                 (index/MULT >= (rci->h_scrollbar_adjustment->value+rci->h_scrollbar_adjustment->page_increment)) ){             
877                 for (i=1; i<10; i++) {
878                         rci->h_scrollbar_adjustment->value += rci->h_scrollbar_adjustment->page_size/10;
879                         gtk_adjustment_value_changed(rci->h_scrollbar_adjustment);
880                 }
881
882         }
883  */
884         if (!rci->cursor_catch) {
885                 if (index/MULT < rci->h_scrollbar_adjustment->page_size/2) {
886                         rci->h_scrollbar_adjustment->value = rci->h_scrollbar_adjustment->lower;
887                 } else if (index/MULT > (rci->h_scrollbar_adjustment->upper - rci->h_scrollbar_adjustment->page_size/2)) {
888                         rci->h_scrollbar_adjustment->value = rci->h_scrollbar_adjustment->upper - rci->h_scrollbar_adjustment->page_size;
889                 } else {
890                         rci->h_scrollbar_adjustment->value = index/MULT - rci->h_scrollbar_adjustment->page_size/2;
891                 }
892
893                 gtk_adjustment_value_changed(rci->h_scrollbar_adjustment);
894         } else if ( (rci->cursor_prev/MULT < (rci->h_scrollbar_adjustment->value+rci->h_scrollbar_adjustment->page_increment)) && 
895                 (index/MULT >= (rci->h_scrollbar_adjustment->value+rci->h_scrollbar_adjustment->page_increment)) ){     
896                 rci->cursor_catch = FALSE;
897                 for (i=1; i<10; i++) {
898                         rci->h_scrollbar_adjustment->value = min(rci->h_scrollbar_adjustment->upper-rci->h_scrollbar_adjustment->page_size, rci->h_scrollbar_adjustment->value + (rci->h_scrollbar_adjustment->page_size/20));
899                         gtk_adjustment_value_changed(rci->h_scrollbar_adjustment);
900                 }
901
902         }
903
904
905         /* Connect back the "value" scroll signal */
906         SIGNAL_CONNECT(rci->h_scrollbar_adjustment, "value_changed", h_scrollbar_changed, rci);
907
908
909 /*      if (index/MULT < rci->h_scrollbar_adjustment->page_increment) {
910                 rci->h_scrollbar_adjustment->value = rci->h_scrollbar_adjustment->lower;
911         } else if (index/MULT > (rci->h_scrollbar_adjustment->upper - rci->h_scrollbar_adjustment->page_size + rci->h_scrollbar_adjustment->page_increment)) {
912                 rci->h_scrollbar_adjustment->value = rci->h_scrollbar_adjustment->upper - rci->h_scrollbar_adjustment->page_size;
913         } else {
914                 if ( (index/MULT < rci->h_scrollbar_adjustment->value) || (index/MULT > (rci->h_scrollbar_adjustment->value+rci->h_scrollbar_adjustment->page_increment)) ){
915                         rci->h_scrollbar_adjustment->value = index/MULT;
916                 }
917         }
918  */
919
920 /*      if (index/MULT < rci->h_scrollbar_adjustment->page_size/2) {
921                 rci->h_scrollbar_adjustment->value = rci->h_scrollbar_adjustment->lower;
922         } else if (index/MULT > (rci->h_scrollbar_adjustment->upper - rci->h_scrollbar_adjustment->page_size/2)) {
923                 rci->h_scrollbar_adjustment->value = rci->h_scrollbar_adjustment->upper - rci->h_scrollbar_adjustment->page_size;
924         } else {
925                 rci->h_scrollbar_adjustment->value = index/MULT - rci->h_scrollbar_adjustment->page_size/2;
926         }
927  */
928 /*      gtk_adjustment_value_changed(rci->h_scrollbar_adjustment);
929  */
930         rci->cursor_prev = index;
931 }
932
933 /****************************************************************************/
934 /* Move and draw the cursor in the graph 
935  */
936 static gboolean 
937 draw_cursors(gpointer data)
938 {
939         if (!rtp_channels) return FALSE;
940
941         /* Draw and move each of the two channels */
942         draw_channel_cursor(rtp_channels->rci[0], rtp_channels->start_index[0]);
943         draw_channel_cursor(rtp_channels->rci[1], rtp_channels->start_index[1]);
944
945         if ((rtp_channels->stop) || (rtp_channels->pause)) return FALSE;
946
947         return TRUE;
948 }
949
950 /****************************************************************************/
951 static void
952 init_rtp_channels_vals(void)
953 {
954         rtp_play_channles_t *rpci = rtp_channels; 
955         
956         /* if we only have one channel to play, we just use the info from that channel */
957         if (rpci->rci[0] == NULL) {
958                 rpci->max_frame_index = rpci->rci[1]->max_frame_index;
959                 rpci->start_index[0] = rpci->max_frame_index;
960                 rpci->start_index[1] = 0;
961                 rpci->end_index[0] = rpci->max_frame_index;
962                 rpci->end_index[1] = rpci->max_frame_index;
963         } else if (rpci->rci[1] == NULL) {
964                 rpci->max_frame_index = rpci->rci[0]->max_frame_index;
965                 rpci->start_index[1] = rpci->max_frame_index;
966                 rpci->start_index[0] = 0;
967                 rpci->end_index[0] = rpci->max_frame_index;
968                 rpci->end_index[1] = rpci->max_frame_index;
969
970         /* if the two channels are to be played, then we need to sync both based on the start/end time of each one */
971         } else {
972                 rpci->max_frame_index = (guint32)(SAMPLE_RATE/1000) * (guint32)(max(rpci->rci[0]->end_time, rpci->rci[1]->end_time) -
973                                                         (guint32)min(rpci->rci[0]->start_time, rpci->rci[1]->start_time));
974
975                 if (rpci->rci[0]->start_time < rpci->rci[1]->start_time) {
976                         rpci->start_index[0] = 0;
977                         rpci->start_index[1] = (guint32)(SAMPLE_RATE/1000) * (guint32)(rpci->rci[1]->start_time - rpci->rci[0]->start_time);
978                 } else {
979                         rpci->start_index[1] = 0;
980                         rpci->start_index[0] = (guint32)(SAMPLE_RATE/1000) * (guint32)(rpci->rci[0]->start_time - rpci->rci[1]->start_time);
981                 } 
982
983                 if (rpci->rci[0]->end_time < rpci->rci[1]->end_time) {
984                         rpci->end_index[0] = rpci->max_frame_index - ((guint32)(SAMPLE_RATE/1000) * (guint32)(rpci->rci[1]->end_time - rpci->rci[0]->end_time));
985                         rpci->end_index[1] = rpci->max_frame_index;
986                 } else {
987                         rpci->end_index[1] = rpci->max_frame_index - ((guint32)(SAMPLE_RATE/1000) * (guint32)(rpci->rci[0]->end_time - rpci->rci[1]->end_time));
988                         rpci->end_index[0] = rpci->max_frame_index;
989                 } 
990         }
991 }
992
993
994 /****************************************************************************/
995 /* This routine will be called by the PortAudio engine when audio is needed.
996  * It may called at interrupt level on some machines so don't do anything
997  * that could mess up the system like calling malloc() or free().
998  */
999 #if PORTAUDIO_API_1
1000
1001 static int paCallback(   void *inputBuffer, void *outputBuffer,
1002                              unsigned long framesPerBuffer,
1003                              PaTimestamp outTime, void *userData)
1004 {
1005 #else /* PORTAUDIO_API_1 */
1006 static int paCallback( void *inputBuffer, void *outputBuffer,
1007                              unsigned long framesPerBuffer,
1008                                                          const PaStreamCallbackTimeInfo* outTime,
1009                                                          PaStreamCallbackFlags statusFlags,
1010                              void *userData)
1011 {
1012 /*      (void) statusFlags;*/
1013 #endif /* PORTAUDIO_API_1 */
1014     rtp_play_channles_t *rpci = (rtp_play_channles_t*)userData;
1015     SAMPLE *wptr = (SAMPLE*)outputBuffer;
1016     sample_t sample;
1017     unsigned int i;
1018     int finished;
1019     unsigned int framesLeft;
1020     int framesToPlay;
1021
1022         /* if it is pasued, we keep the stream running but with silence only */
1023         if (rtp_channels->pause) {
1024                 for(i=0; i<framesPerBuffer; i++ ) {
1025                         *wptr++ = 0;
1026                         *wptr++ = 0;
1027                 }
1028                 rtp_channels->pause_duration += framesPerBuffer;
1029                 return 0;
1030         }
1031
1032 #if PORTAUDIO_API_1
1033         rpci->out_diff_time = outTime -  Pa_StreamTime(pa_stream) ;
1034 #else /* PORTAUDIO_API_1 */
1035         rpci->out_diff_time = (guint32)(SAMPLE_RATE) * (outTime->outputBufferDacTime - Pa_GetStreamTime(pa_stream)) ; 
1036 #endif /* PORTAUDIO_API_1 */
1037
1038
1039         /* set the values if this is the first time */
1040         if (rpci->max_frame_index == 0) {
1041                 init_rtp_channels_vals();
1042
1043         }
1044
1045         framesLeft = rpci->max_frame_index - rpci->frame_index;
1046
1047     (void) inputBuffer; /* Prevent unused variable warnings. */
1048     (void) outTime;
1049
1050     if( framesLeft < framesPerBuffer )
1051     {
1052         framesToPlay = framesLeft;
1053         finished = 1;
1054     }
1055     else
1056     {
1057         framesToPlay = framesPerBuffer;
1058         finished = 0;
1059     }
1060
1061     for( i=0; i<(unsigned int)framesToPlay; i++ )
1062     {
1063                 if (rpci->rci[0] && ( (rpci->frame_index >= rpci->start_index[0]) && (rpci->frame_index <= rpci->end_index[0]) )) {
1064                         sample = g_array_index(rpci->rci[0]->samples, sample_t, rpci->rci[0]->frame_index++);
1065                         *wptr++ = sample.val;
1066                 } else {
1067                         *wptr++ = 0;
1068                 }
1069
1070                 if (rpci->rci[1] && ( (rpci->frame_index >= rpci->start_index[1]) && (rpci->frame_index <= rpci->end_index[1]) )) {
1071                         sample = g_array_index(rpci->rci[1]->samples, sample_t, rpci->rci[1]->frame_index++);
1072                         *wptr++ = sample.val;
1073                 } else {
1074                         *wptr++ = 0;
1075                 }
1076     }
1077     for( ; i<framesPerBuffer; i++ )
1078     {
1079         *wptr++ = 0;
1080                 *wptr++ = 0;
1081     }
1082         rpci->frame_index += framesToPlay;
1083
1084     return finished;
1085 }
1086
1087 /****************************************************************************/
1088 static void 
1089 on_bt_check_clicked(GtkButton *button _U_, gpointer user_data _U_)
1090 {
1091         rtp_channel_info_t *rci = user_data;
1092
1093         if (rci->selected) {
1094                 if (rtp_channels->rci[0] == rci) {
1095                         rtp_channels->rci[0] = NULL;
1096                         rtp_channels->channel = 0;
1097                 } else {
1098                         rtp_channels->rci[1] = NULL;
1099                         rtp_channels->channel = 1;
1100                 }
1101         } else {
1102                 /* if there are already both channels selected, unselect the old one */
1103                 if (rtp_channels->rci[rtp_channels->channel]) {
1104                         /* we disconnect the signal temporarly to avoid been called back */
1105                         SIGNAL_DISCONNECT_BY_FUNC(rtp_channels->rci[rtp_channels->channel]->check_bt, on_bt_check_clicked, rtp_channels->rci[rtp_channels->channel]);
1106                         gtk_toggle_button_set_active((GtkToggleButton *)rtp_channels->rci[rtp_channels->channel]->check_bt, FALSE);
1107                         SIGNAL_CONNECT(rtp_channels->rci[rtp_channels->channel]->check_bt, "clicked", on_bt_check_clicked, rtp_channels->rci[rtp_channels->channel]);
1108                         rtp_channels->rci[rtp_channels->channel]->selected = FALSE;
1109                 }
1110
1111                 rtp_channels->rci[rtp_channels->channel] = rci;
1112                 rtp_channels->channel = !(rtp_channels->channel);
1113         }
1114
1115         rci->selected = !(rci->selected);
1116
1117         /* set the sensitive state of the buttons (decode, play, pause, stop) */
1118         bt_state(TRUE, TRUE, FALSE, FALSE);
1119 }
1120
1121 /****************************************************************************/
1122 static void channel_draw(rtp_channel_info_t* rci)
1123 {
1124         int i,j;
1125         sample_t sample;
1126         SAMPLE min, max;
1127         PangoLayout  *small_layout;
1128         guint32 label_width, label_height;
1129         char label_string[MAX_TIME_LABEL];
1130         double offset;
1131         guint32 progbar_nextstep;
1132         int progbar_quantum;
1133         gfloat progbar_val;
1134         guint status;
1135         GdkGC *gc;
1136         GdkGC *red_gc;
1137         GdkColor red_color = {0, 65535, 0, 0};
1138         
1139         if (GDK_IS_DRAWABLE(rci->pixmap)) {
1140                 /* Clear out old plot */
1141                 gdk_draw_rectangle(rci->pixmap,
1142                         rci->bg_gc[1+rci->call_num%MAX_NUM_COL_CONV],
1143                         TRUE,
1144                         0, 0,
1145                         rci->draw_area->allocation.width,
1146                         rci->draw_area->allocation.height);
1147
1148                 small_layout = gtk_widget_create_pango_layout(rci->draw_area, label_string);
1149                 pango_layout_set_font_description(small_layout, pango_font_description_from_string("Helvetica,Sans,Bold 7"));
1150
1151                 /* calculated the pixel offset to display integer seconds */
1152                 offset = ((double)rci->start_time/1000 - floor((double)rci->start_time/1000))*SAMPLE_RATE/MULT;
1153
1154                 gdk_draw_line(rci->pixmap, rci->draw_area->style->black_gc,
1155                                 0,
1156                                 rci->draw_area->allocation.height-HEIGHT_TIME_LABEL,
1157                                 rci->draw_area->allocation.width,
1158                                 rci->draw_area->allocation.height-HEIGHT_TIME_LABEL);
1159
1160                 /* we update the progress bar 100 times */
1161                 progbar_quantum = (total_frames/MULT)/100;
1162                 progbar_nextstep = progbar_count;
1163
1164                 red_gc = gdk_gc_new(rci->draw_area->window);
1165                 gdk_gc_set_rgb_fg_color(red_gc, &red_color);
1166
1167                 for (i=0; i< min(rci->draw_area->allocation.width,(gint)(rci->samples->len/MULT)); i++) {
1168                         sample.val = 0;
1169                         status = S_NORMAL;
1170                         max=(SAMPLE)0xFFFF;
1171                         min=(SAMPLE)0x7FFF;
1172
1173                         if (progbar_count >= progbar_nextstep) {
1174                                 g_assert(total_frames > 0);
1175
1176                                 progbar_val = (gfloat) progbar_count / (total_frames/MULT);
1177
1178                                 update_progress_bar(progbar_val);
1179
1180                                 progbar_nextstep += progbar_quantum;
1181                         }
1182
1183                         for (j=0; j<MULT; j++) {
1184                                 sample = g_array_index(rci->samples, sample_t, i*MULT+j);
1185                                 max = max(max, sample.val);
1186                                 min = min(min, sample.val);
1187                                 if (sample.status == S_DROP_BY_JITT) status = S_DROP_BY_JITT;
1188                         }
1189
1190                         if (status == S_DROP_BY_JITT) {
1191                                 gc = red_gc;
1192                         } else {
1193                                 gc = rci->draw_area->style->black_gc;
1194                         }
1195
1196                         gdk_draw_line(rci->pixmap, gc,
1197                                 i,
1198                                 (gint)(( (0x7FFF+min) * (rci->draw_area->allocation.height-HEIGHT_TIME_LABEL))/0xFFFF),
1199                                 i,
1200                                 (gint)(( (0x7FFF+max) * (rci->draw_area->allocation.height-HEIGHT_TIME_LABEL))/0xFFFF));
1201
1202                         /*draw the time label and grid */
1203                         if ( !((i*MULT)%(SAMPLE_RATE)) ) {
1204                                 gdk_draw_line(rci->pixmap, rci->draw_area->style->black_gc,
1205                                         (int) (i - offset),
1206                                         rci->draw_area->allocation.height-HEIGHT_TIME_LABEL,
1207                                         (int) (i - offset),
1208                                         rci->draw_area->allocation.height-HEIGHT_TIME_LABEL+4);
1209
1210                                 g_snprintf(label_string, MAX_TIME_LABEL, "%.0f", floor(rci->start_time/1000) + i*MULT/SAMPLE_RATE);
1211
1212                                 pango_layout_set_text(small_layout, label_string, -1);
1213                                 pango_layout_get_pixel_size(small_layout, &label_width, &label_height);
1214                                 gdk_draw_layout(rci->pixmap,
1215                                         rci->draw_area->style->black_gc,
1216                                         (int) (i - offset - label_width/2),
1217                                         rci->draw_area->allocation.height - label_height,
1218                                         small_layout);
1219                         /* draw the 1/2 sec grid */
1220                         } else if ( !((i*MULT)%(SAMPLE_RATE/2)) ) {
1221                                 gdk_draw_line(rci->pixmap, rci->draw_area->style->black_gc,
1222                                         (int) (i - offset),
1223                                         rci->draw_area->allocation.height-HEIGHT_TIME_LABEL,
1224                                         (int) (i - offset),
1225                                         rci->draw_area->allocation.height-HEIGHT_TIME_LABEL+2);
1226
1227                         }
1228
1229                         progbar_count++;
1230                 }
1231         }
1232
1233 }
1234 /****************************************************************************/
1235 static gint expose_event_channels(GtkWidget *widget, GdkEventExpose *event)
1236 {
1237         rtp_channel_info_t *rci;
1238
1239         rci=(rtp_channel_info_t *)OBJECT_GET_DATA(widget, "rtp_channel_info_t");
1240         if(!rci){
1241                 exit(10);
1242         }
1243
1244         if (GDK_IS_DRAWABLE(widget->window))
1245                 gdk_draw_drawable(widget->window,
1246                         widget->style->fg_gc[GTK_WIDGET_STATE(widget)],
1247                         rci->pixmap,
1248                         event->area.x, event->area.y,
1249                         event->area.x, event->area.y,
1250                         event->area.width, event->area.height);
1251
1252         return FALSE;
1253 }
1254
1255 /****************************************************************************/
1256 static gint 
1257 configure_event_channels(GtkWidget *widget, GdkEventConfigure *event _U_)
1258 {
1259         rtp_channel_info_t *rci;
1260         int i;
1261
1262         /* the first calor is blue to highlight the selected item 
1263          * the other collors are the same as in the Voip Graph analysys
1264          * to match the same calls 
1265          */
1266         static GdkColor col[MAX_NUM_COL_CONV+1] = {
1267                 {0,     0x00FF, 0x00FF, 0xFFFF},
1268                 {0,     0x33FF, 0xFFFF, 0x33FF},
1269                 {0,     0x00FF, 0xCCFF, 0xCCFF},
1270                 {0,     0x66FF, 0xFFFF, 0xFFFF},
1271                 {0,     0x99FF, 0x66FF, 0xFFFF},
1272                 {0,     0xFFFF, 0xFFFF, 0x33FF},
1273                 {0,     0xCCFF, 0x99FF, 0xFFFF},
1274                 {0,     0xCCFF, 0xFFFF, 0x33FF},
1275                 {0,     0xFFFF, 0xCCFF, 0xCCFF},
1276                 {0,     0xFFFF, 0x99FF, 0x66FF},
1277                 {0,     0xFFFF, 0xFFFF, 0x99FF}
1278         };
1279
1280         rci=(rtp_channel_info_t *)OBJECT_GET_DATA(widget, "rtp_channel_info_t");
1281         if(!rci){
1282                 exit(10);
1283         }
1284
1285         if(rci->pixmap){
1286                 g_object_unref(rci->pixmap);
1287                 rci->pixmap=NULL;
1288         }
1289
1290         rci->pixmap = gdk_pixmap_new(widget->window,
1291                                         widget->allocation.width,
1292                                         widget->allocation.height,
1293                                         -1);
1294
1295         if ( GDK_IS_DRAWABLE(rci->pixmap) )
1296                 gdk_draw_rectangle(rci->pixmap,
1297                         widget->style->white_gc,
1298                         TRUE,
1299                         0, 0,
1300                         widget->allocation.width,
1301                         widget->allocation.height);
1302
1303         /* create gcs for the background color of each channel */
1304         for (i=0; i<MAX_NUM_COL_CONV+1; i++){
1305                 rci->bg_gc[i]=gdk_gc_new(rci->pixmap);
1306                 gdk_gc_set_rgb_fg_color(rci->bg_gc[i], &col[i]);
1307         }
1308
1309         channel_draw(rci);
1310
1311         return TRUE;
1312 }
1313
1314 /****************************************************************************/
1315 static gint 
1316 button_press_event_channel(GtkWidget *widget, GdkEventButton *event _U_)
1317 {
1318         rtp_channel_info_t *rci;
1319         int this_channel;
1320         guint32 prev_index;
1321
1322         rci=(rtp_channel_info_t *)OBJECT_GET_DATA(widget, "rtp_channel_info_t");
1323         if(!rci){
1324                 exit(10);
1325         }
1326
1327         if (!rci->selected) {
1328
1329                 /* only select a new channels if we are in STOP */
1330                 if (!rtp_channels->stop) return 0;
1331
1332                 /* if there are already both channels selected, unselect the old one */
1333                 if (rtp_channels->rci[rtp_channels->channel]) {
1334                         /* we disconnect the signal temporarly to avoid been called back */
1335                         SIGNAL_DISCONNECT_BY_FUNC(rtp_channels->rci[rtp_channels->channel]->check_bt, on_bt_check_clicked, rtp_channels->rci[rtp_channels->channel]);
1336                         gtk_toggle_button_set_active((GtkToggleButton *) rtp_channels->rci[rtp_channels->channel]->check_bt, FALSE);
1337                         SIGNAL_CONNECT(rtp_channels->rci[rtp_channels->channel]->check_bt, "clicked", on_bt_check_clicked, rtp_channels->rci[rtp_channels->channel]);
1338                         rtp_channels->rci[rtp_channels->channel]->selected = FALSE;
1339                 }
1340
1341                 /* we disconnect the signal temporarly to avoid been called back */
1342                 SIGNAL_DISCONNECT_BY_FUNC(rci->check_bt, on_bt_check_clicked, rci);
1343                 gtk_toggle_button_set_active((GtkToggleButton *) rci->check_bt, TRUE);
1344                 SIGNAL_CONNECT(rci->check_bt, "clicked", on_bt_check_clicked, rci);
1345
1346                 rtp_channels->rci[rtp_channels->channel] = rci;
1347                 rtp_channels->channel = !(rtp_channels->channel);
1348                 rci->selected = TRUE;
1349
1350                 /* set the sensitive state of the buttons (decode, play, pause, stop) */                
1351                 bt_state(TRUE, TRUE, FALSE, FALSE);
1352         }
1353
1354         if (rci == rtp_channels->rci[0]) {
1355                 this_channel = 0;
1356         } else {
1357                 this_channel = 1;
1358         }
1359
1360         rci->frame_index = (unsigned int) (event->x * MULT);
1361         
1362         prev_index = rtp_channels->frame_index;
1363         rtp_channels->frame_index = rtp_channels->start_index[this_channel] + rci->frame_index;
1364         rtp_channels->pause_duration += prev_index - rtp_channels->frame_index;
1365
1366
1367
1368         /* change the index in the other channel if selected, according with the index position */
1369         if (rtp_channels->rci[!this_channel]) {
1370                 init_rtp_channels_vals();
1371
1372                 if (rtp_channels->frame_index < rtp_channels->start_index[!this_channel]) {
1373                         rtp_channels->rci[!this_channel]->frame_index = 0;
1374                 } else if (rtp_channels->frame_index > rtp_channels->end_index[!this_channel]) {
1375                         rtp_channels->rci[!this_channel]->frame_index = rtp_channels->rci[!this_channel]->max_frame_index;
1376                 } else {
1377                         rtp_channels->rci[!this_channel]->frame_index = rtp_channels->frame_index - rtp_channels->start_index[!this_channel];
1378                 }
1379         } else {
1380                 init_rtp_channels_vals();
1381         }
1382
1383         rtp_channels->out_diff_time = 0;
1384
1385         rci->cursor_catch = TRUE;
1386
1387         /* redraw the cusrsor */
1388         draw_cursors(NULL);
1389
1390         return TRUE;
1391 }
1392
1393 /****************************************************************************/
1394 static void
1395 add_channel_to_window(gchar *key _U_ , rtp_channel_info_t *rci, guint *counter _U_ )
1396 {
1397         GString *label = NULL;
1398         GtkWidget *viewport;
1399
1400
1401         /* create the channel draw area */
1402         rci->draw_area=gtk_drawing_area_new();
1403         
1404         rci->scroll_window=gtk_scrolled_window_new(NULL, NULL);
1405
1406         gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (rci->scroll_window), GTK_POLICY_ALWAYS, GTK_POLICY_NEVER);
1407         rci->h_scrollbar_adjustment = gtk_scrolled_window_get_hadjustment(GTK_SCROLLED_WINDOW(rci->scroll_window));
1408
1409         
1410         gtk_widget_set_size_request(rci->draw_area, (gint)(rci->samples->len/MULT), CHANNEL_HEIGHT);
1411
1412
1413         viewport = gtk_viewport_new(rci->h_scrollbar_adjustment, gtk_scrolled_window_get_vadjustment(GTK_SCROLLED_WINDOW(rci->scroll_window)));
1414         gtk_container_add(GTK_CONTAINER(viewport), rci->draw_area);
1415         gtk_container_add(GTK_CONTAINER(rci->scroll_window), viewport);
1416         gtk_viewport_set_shadow_type(GTK_VIEWPORT(viewport), GTK_SHADOW_NONE);
1417         OBJECT_SET_DATA(rci->draw_area, "rtp_channel_info_t", rci);
1418         gtk_widget_add_events (rci->draw_area, GDK_BUTTON_PRESS_MASK);
1419         GTK_WIDGET_SET_FLAGS(rci->draw_area, GTK_CAN_FOCUS);
1420         gtk_widget_grab_focus(rci->draw_area);
1421
1422         gtk_box_pack_start(GTK_BOX (channels_vb), rci->scroll_window, FALSE, FALSE, 0);
1423
1424         /* signals needed to handle backing pixmap */
1425         SIGNAL_CONNECT(rci->draw_area, "expose_event", expose_event_channels, NULL);
1426         SIGNAL_CONNECT(rci->draw_area, "configure_event", configure_event_channels, rci);
1427         gtk_widget_add_events (rci->draw_area, GDK_BUTTON_PRESS_MASK);
1428         SIGNAL_CONNECT(rci->draw_area, "button_press_event", button_press_event_channel, rci);
1429         SIGNAL_CONNECT(rci->h_scrollbar_adjustment, "value_changed", h_scrollbar_changed, rci);
1430
1431
1432         label = g_string_new("");
1433         g_string_printf(label, "From %s:%d to %s:%d   Duration:%.2f   Drop by Jitter Buff:%d(%.1f%%)   Out of Seq: %d(%.1f%%)", get_addr_name(&(rci->first_stream->src_addr)), 
1434                 rci->first_stream->src_port, get_addr_name(&(rci->first_stream->dest_addr)), rci->first_stream->dest_port, 
1435                 (double)rci->samples->len/SAMPLE_RATE, rci->drop_by_jitter_buff, (double)rci->drop_by_jitter_buff * 100 / (double)rci->num_packets
1436                 , rci->out_of_seq, (double)rci->out_of_seq * 100 / (double)rci->num_packets);
1437
1438         rci->check_bt = gtk_check_button_new_with_label(label->str);
1439         gtk_box_pack_start(GTK_BOX (channels_vb), rci->check_bt, FALSE, FALSE, 1);
1440         
1441         /* Create the Separator if it is not the last one */
1442         (*counter)++;
1443         if (*counter < g_hash_table_size(rtp_channels_hash)) {
1444             rci->separator = gtk_hseparator_new();
1445                 gtk_box_pack_start(GTK_BOX (channels_vb), rci->separator, FALSE, FALSE, 5);
1446         }
1447
1448         SIGNAL_CONNECT(rci->check_bt, "clicked", on_bt_check_clicked, rci);
1449
1450         g_string_free(label, TRUE);
1451 }
1452
1453 /****************************************************************************/
1454 static void
1455 count_channel_frames(gchar *key _U_ , rtp_channel_info_t *rci, gpointer ptr _U_ ) 
1456 {
1457         total_frames += rci->samples->len;
1458 }
1459
1460 /****************************************************************************/
1461 static void
1462 play_channels(void) 
1463 {       
1464         PaError err;
1465         GtkWidget *dialog;
1466
1467         /* we should never be here if we are in PLAY and !PAUSE */
1468         if(!rtp_channels->stop && !rtp_channels->pause){
1469                 exit(10);
1470         }
1471
1472         /* if we are in PAUSE change the sate */
1473         if (rtp_channels->pause) {
1474                 rtp_channels->pause = FALSE;
1475                 /* set the sensitive state of the buttons (decode, play, pause, stop) */
1476                 bt_state(FALSE, FALSE, TRUE, TRUE);
1477
1478         /* if not PAUSE, then start to PLAY */
1479         } else {
1480 #if PORTAUDIO_API_1
1481                 err = Pa_OpenStream(
1482                           &pa_stream,
1483                           paNoDevice,     /* default input device */
1484                           0,              /* no input */
1485                           PA_SAMPLE_TYPE, /* 16 bit Integer input */
1486                           NULL,
1487                           Pa_GetDefaultOutputDeviceID(),
1488                           NUM_CHANNELS,   /* Stereo output */
1489                           PA_SAMPLE_TYPE, /* 16 bit Integer output */
1490                           NULL,
1491                           SAMPLE_RATE,
1492                           FRAMES_PER_BUFFER,
1493                           0,              /* number of buffers, if zero then use default minimum */
1494                           paClipOff,      /* we won't output out of range samples so don't bother clipping them */
1495                           paCallback,
1496                           rtp_channels );
1497 #else /* PORTAUDIO_API_1 */
1498                 err = Pa_OpenDefaultStream( 
1499                                 &pa_stream,
1500                 0,
1501                 NUM_CHANNELS,
1502                 PA_SAMPLE_TYPE,
1503                 SAMPLE_RATE,
1504                 FRAMES_PER_BUFFER,
1505                 paCallback,
1506                 rtp_channels );
1507 #endif /* PORTAUDIO_API_1 */
1508
1509                 if( err != paNoError ) {
1510                         dialog = gtk_message_dialog_new ((GtkWindow *) rtp_player_dlg_w,
1511                                                                   GTK_DIALOG_DESTROY_WITH_PARENT, GTK_MESSAGE_ERROR,GTK_BUTTONS_CLOSE,
1512                                                                   "Can not Open Stream in PortAduio Library.\n Error: %s", Pa_GetErrorText( err ));
1513                         gtk_dialog_run (GTK_DIALOG (dialog));
1514                         gtk_widget_destroy (dialog);
1515                         return;
1516                 }
1517
1518                 err = Pa_StartStream( pa_stream );
1519                 if( err != paNoError ) {
1520                         dialog = gtk_message_dialog_new ((GtkWindow *) rtp_player_dlg_w,
1521                                                                   GTK_DIALOG_DESTROY_WITH_PARENT, GTK_MESSAGE_ERROR,GTK_BUTTONS_CLOSE,
1522                                                                   "Can not Start Stream in PortAudio Library.\n Error: %s", Pa_GetErrorText( err ));
1523                         gtk_dialog_run (GTK_DIALOG (dialog));
1524                         gtk_widget_destroy (dialog);
1525                         return;
1526                 }
1527 #if !PORTAUDIO_API_1
1528                 rtp_channels->pa_start_time = Pa_GetStreamTime(pa_stream);
1529 #endif /* PORTAUDIO_API_1 */
1530
1531                 rtp_channels->stop = FALSE;
1532
1533                 /* set the sensitive state of the buttons (decode, play, pause, stop) */
1534                 bt_state(FALSE, FALSE, TRUE, TRUE);
1535         }
1536
1537         /* Draw the cursor in the graph */
1538         g_timeout_add_full(G_PRIORITY_DEFAULT_IDLE, MULT*1000/SAMPLE_RATE, draw_cursors, NULL, NULL);
1539
1540 }
1541
1542 /****************************************************************************/
1543 static void
1544 pause_channels(void) 
1545 {       
1546         rtp_channels->pause = !(rtp_channels->pause);
1547
1548         /* reactivate the cusrosr display if no in pause */
1549         if (!rtp_channels->pause) {
1550                 /* Draw the cursor in the graph */
1551                 g_timeout_add_full(G_PRIORITY_DEFAULT_IDLE, MULT*1000/SAMPLE_RATE, draw_cursors, NULL, NULL);
1552         }
1553
1554         /* set the sensitive state of the buttons (decode, play, pause, stop) */        
1555         bt_state(FALSE, TRUE, FALSE, TRUE);
1556 }
1557
1558 /****************************************************************************/
1559 static void 
1560 reset_rtp_channels(void)
1561 {
1562         rtp_channels->channel = 0;
1563         rtp_channels->rci[0] = NULL;
1564         rtp_channels->rci[1] = NULL;
1565         rtp_channels->start_index[0] = 0;
1566         rtp_channels->start_index[1] = 0;
1567         rtp_channels->end_index[0] = 0;
1568         rtp_channels->end_index[1] = 0;
1569         rtp_channels->max_frame_index = 0;
1570         rtp_channels->frame_index = 0;
1571         rtp_channels->pause = FALSE;
1572         rtp_channels->pause_duration = 0;
1573         rtp_channels->stop = TRUE;
1574         rtp_channels->out_diff_time = 10000;
1575 }
1576
1577 /****************************************************************************/
1578 static void
1579 remove_channel_to_window(gchar *key _U_ , rtp_channel_info_t *rci, gpointer ptr _U_ ) 
1580 {
1581         g_object_unref(rci->pixmap);
1582         gtk_widget_destroy(rci->draw_area);
1583         gtk_widget_destroy(rci->scroll_window);
1584         gtk_widget_destroy(rci->check_bt);
1585         gtk_widget_destroy(rci->separator);
1586 }
1587
1588 /****************************************************************************/
1589 static void
1590 reset_channels(void)
1591 {
1592
1593         /* Remove the channels from the main window if there are there */
1594         g_hash_table_foreach( rtp_channels_hash, (GHFunc)remove_channel_to_window, NULL);
1595
1596
1597         /* destroy the rtp channels hash table */
1598         if (rtp_channels_hash) {
1599                 g_hash_table_destroy(rtp_channels_hash);
1600                 rtp_channels_hash = NULL;
1601         }
1602
1603         if (rtp_channels) {
1604                 reset_rtp_channels();
1605         }
1606 }
1607
1608 /****************************************************************************/
1609 void
1610 reset_rtp_player(void)
1611 {
1612         /* Destroy the rtp channels */
1613         reset_channels();
1614
1615         /* destroy the rtp streams hash table */
1616         if (rtp_streams_hash) {
1617                 g_hash_table_destroy(rtp_streams_hash);
1618                 rtp_streams_hash = NULL;
1619         }
1620
1621         /* destroy the rtp streams list */
1622         if (rtp_streams_list) {
1623                 g_list_free (rtp_streams_list);
1624                 rtp_streams_list = NULL;
1625         }
1626
1627 }
1628
1629 /****************************************************************************/
1630 static void
1631 decode_streams(void) 
1632 {       
1633         guint statusbar_context;
1634         guint counter;
1635
1636         /* set the sensitive state of the buttons (decode, play, pause, stop) */
1637         bt_state(FALSE, FALSE, FALSE, FALSE);
1638
1639         reset_channels();
1640
1641         progress_bar = gtk_progress_bar_new();
1642         WIDGET_SET_SIZE(progress_bar, 100, -1);
1643         gtk_box_pack_start(GTK_BOX (stat_hbox), progress_bar, FALSE, FALSE, 2);
1644         gtk_widget_show(progress_bar);
1645         statusbar_context = gtk_statusbar_get_context_id((GtkStatusbar *) info_bar, "main");
1646         gtk_statusbar_push((GtkStatusbar *) info_bar, statusbar_context, "  Decoding RTP packets...");
1647
1648         gtk_statusbar_set_has_resize_grip(GTK_STATUSBAR(info_bar), FALSE);
1649
1650         /* reset the number of packet to be decoded, this is used for the progress bar */
1651         total_packets = 0;
1652         /* reset the Progress Bar count */
1653         progbar_count = 0;
1654
1655         /* Mark the RTP streams to be played using the selected VoipCalls*/
1656         g_hash_table_foreach( rtp_streams_hash, (GHFunc)mark_rtp_stream_to_play, NULL);
1657
1658         /* Decode the RTP streams and add them to the RTP channels to be played */
1659         g_list_foreach( rtp_streams_list, (GFunc)decode_rtp_stream, NULL);
1660
1661         /* reset the number of frames to be displayed, this is used for the progress bar */
1662         total_frames = 0;
1663         /* Count the frames in all the RTP channels */
1664         g_hash_table_foreach( rtp_channels_hash, (GHFunc)count_channel_frames, NULL);   
1665
1666         /* reset the Progress Bar count again for the progress of creating the channels view */
1667         progbar_count = 0;
1668         gtk_statusbar_pop((GtkStatusbar *) info_bar, statusbar_context);
1669         gtk_statusbar_push((GtkStatusbar *) info_bar, statusbar_context, "  Creating channels view...");
1670
1671         /* Display the RTP channels in the window */
1672         counter = 0;
1673         g_hash_table_foreach( rtp_channels_hash, (GHFunc)add_channel_to_window, &counter);      
1674
1675         /* Resize the main scroll window to display no more than 5 channels, otherwise the scroll bar need to be used */
1676         WIDGET_SET_SIZE(main_scrolled_window, CHANNEL_WIDTH, 
1677                 min(g_hash_table_size(rtp_channels_hash), 5) * (CHANNEL_HEIGHT+60));
1678
1679         gtk_widget_show_all(main_scrolled_window);
1680
1681         gtk_widget_destroy(progress_bar);
1682         gtk_statusbar_set_has_resize_grip(GTK_STATUSBAR(info_bar), TRUE);
1683         gtk_statusbar_pop((GtkStatusbar *) info_bar, statusbar_context);
1684
1685         /* blank the status label */
1686         gtk_statusbar_pop((GtkStatusbar *) info_bar, statusbar_context);
1687
1688         /* set the sensitive state of the buttons (decode, play, pause, stop) */
1689         bt_state(TRUE, FALSE, FALSE, FALSE);
1690
1691         /* get the static jitter buffer from the spinner gui */
1692         new_jitter_buff = (int) gtk_spin_button_get_value((GtkSpinButton * )jitter_spinner);
1693
1694 }
1695
1696 /****************************************************************************/
1697 static void 
1698 on_bt_decode_clicked(GtkButton *button _U_, gpointer user_data _U_)
1699 {
1700         decode_streams();
1701 }
1702
1703 /****************************************************************************/
1704 static void 
1705 on_bt_play_clicked(GtkButton *button _U_, gpointer user_data _U_)
1706 {
1707         play_channels();
1708 }
1709
1710 /****************************************************************************/
1711 static void 
1712 on_bt_pause_clicked(GtkButton *button _U_, gpointer user_data _U_)
1713 {
1714         pause_channels();
1715 }
1716
1717 /****************************************************************************/
1718 static void 
1719 on_bt_stop_clicked(GtkButton *button _U_, gpointer user_data _U_)
1720 {
1721         stop_channels();
1722 }
1723
1724 /****************************************************************************/
1725 static void
1726 rtp_player_on_destroy(GtkObject *object _U_, gpointer user_data _U_)
1727 {
1728         /* Stop the channels if necesary */
1729         if(rtp_channels && (!rtp_channels->stop)){
1730                 stop_channels();
1731         }
1732
1733         /* Destroy the rtp channels */
1734         reset_channels();
1735
1736         g_free(rtp_channels);
1737         rtp_channels = NULL;
1738
1739         initialized = FALSE;
1740
1741         gtk_widget_destroy(rtp_player_dlg_w);
1742         main_scrolled_window = NULL;
1743         rtp_player_dlg_w = NULL;
1744 }
1745
1746 /****************************************************************************/
1747 static void
1748 jitter_spinner_value_changed (GtkSpinButton *spinner, gpointer user_data _U_)
1749 {
1750         /* set the sensitive state of the buttons (decode, play, pause, stop) */
1751         bt_state(TRUE, TRUE, FALSE, FALSE);
1752 }
1753
1754 /****************************************************************************/
1755 static void
1756 rtp_player_dlg_create(void)
1757 {
1758         GtkWidget *main_vb;
1759         GtkWidget *hbuttonbox;
1760         GtkWidget *h_jitter_buttons_box;
1761         GtkWidget *bt_close;
1762         GtkAdjustment *jitter_spinner_adj;
1763         GtkWidget *label;
1764
1765         GtkTooltips *tooltips = gtk_tooltips_new();
1766
1767         rtp_player_dlg_w=gtk_window_new(GTK_WINDOW_TOPLEVEL);
1768         
1769         gtk_window_set_title(GTK_WINDOW(rtp_player_dlg_w), "Wireshark: RTP Player");
1770         gtk_window_set_position(GTK_WINDOW(rtp_player_dlg_w), GTK_WIN_POS_NONE);
1771
1772         gtk_window_set_default_size(GTK_WINDOW(rtp_player_dlg_w), 400, 50);
1773
1774         main_vb = gtk_vbox_new (FALSE, 0);
1775         gtk_container_add(GTK_CONTAINER(rtp_player_dlg_w), main_vb);
1776         gtk_container_set_border_width (GTK_CONTAINER (main_vb), 2);
1777         
1778         main_scrolled_window=gtk_scrolled_window_new(NULL, NULL);
1779         gtk_container_set_border_width (GTK_CONTAINER (main_scrolled_window), 4);
1780         WIDGET_SET_SIZE(main_scrolled_window, CHANNEL_WIDTH, 0);
1781
1782         gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (main_scrolled_window), GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC);
1783         gtk_container_add(GTK_CONTAINER(main_vb), main_scrolled_window);
1784
1785         channels_vb = gtk_vbox_new (FALSE, 0);
1786         gtk_container_set_border_width (GTK_CONTAINER (channels_vb), 2);
1787         gtk_scrolled_window_add_with_viewport((GtkScrolledWindow *) main_scrolled_window, channels_vb);
1788
1789         h_jitter_buttons_box = gtk_hbox_new (FALSE, 0);
1790         gtk_container_set_border_width (GTK_CONTAINER (h_jitter_buttons_box), 10);
1791         gtk_box_pack_start (GTK_BOX(main_vb), h_jitter_buttons_box, FALSE, FALSE, 0);
1792         label = gtk_label_new("Jitter buffer [ms] ");
1793         gtk_box_pack_start(GTK_BOX(h_jitter_buttons_box), label, FALSE, FALSE, 0);
1794         
1795         jitter_spinner_adj = (GtkAdjustment *) gtk_adjustment_new (50, 0, 500, 5, 10, 10);
1796         jitter_spinner = gtk_spin_button_new (jitter_spinner_adj, 5, 0);
1797         gtk_box_pack_start(GTK_BOX(h_jitter_buttons_box), jitter_spinner, FALSE, FALSE, 0);
1798         gtk_tooltips_set_tip (tooltips, jitter_spinner, "The simulated jitter buffer in [ms]", NULL);
1799         SIGNAL_CONNECT(GTK_OBJECT (jitter_spinner_adj), "value_changed", (GtkSignalFunc) jitter_spinner_value_changed, NULL);
1800
1801         /* button row */
1802         hbuttonbox = gtk_hbutton_box_new ();
1803         gtk_box_pack_start (GTK_BOX (h_jitter_buttons_box), hbuttonbox, TRUE, TRUE, 0);
1804         gtk_button_box_set_layout (GTK_BUTTON_BOX (hbuttonbox), GTK_BUTTONBOX_SPREAD);
1805         gtk_button_box_set_spacing (GTK_BUTTON_BOX (hbuttonbox), 30);
1806
1807         bt_decode = gtk_button_new_with_label("Decode");
1808         gtk_container_add(GTK_CONTAINER(hbuttonbox), bt_decode);
1809         SIGNAL_CONNECT(bt_decode, "clicked", on_bt_decode_clicked, NULL);
1810         gtk_tooltips_set_tip (tooltips, bt_decode, "Decode the RTP stream(s)", NULL);
1811
1812         bt_play = gtk_button_new_with_label("Play");
1813         gtk_container_add(GTK_CONTAINER(hbuttonbox), bt_play);
1814         SIGNAL_CONNECT(bt_play, "clicked", on_bt_play_clicked, NULL);
1815         gtk_tooltips_set_tip (tooltips, bt_play, "Play the RTP channel(s)", NULL);
1816
1817         bt_pause = gtk_button_new_with_label("Pause");
1818         gtk_container_add(GTK_CONTAINER(hbuttonbox), bt_pause);
1819         SIGNAL_CONNECT(bt_pause, "clicked", on_bt_pause_clicked, NULL);
1820         gtk_tooltips_set_tip (tooltips, bt_pause, "Pause the RTP channel(s)", NULL);
1821
1822         bt_stop = gtk_button_new_with_label("Stop");
1823         gtk_container_add(GTK_CONTAINER(hbuttonbox), bt_stop);
1824         SIGNAL_CONNECT(bt_stop, "clicked", on_bt_stop_clicked, NULL);
1825         gtk_tooltips_set_tip (tooltips, bt_stop, "Stop the RTP channel(s)", NULL);
1826
1827         bt_close = BUTTON_NEW_FROM_STOCK(GTK_STOCK_CLOSE);
1828         gtk_container_add (GTK_CONTAINER (hbuttonbox), bt_close);
1829         GTK_WIDGET_SET_FLAGS(bt_close, GTK_CAN_DEFAULT);
1830         gtk_tooltips_set_tip (tooltips, bt_close, "Close this dialog", NULL);
1831
1832         SIGNAL_CONNECT(bt_close, "clicked", rtp_player_on_destroy, NULL);
1833         SIGNAL_CONNECT(rtp_player_dlg_w, "destroy", rtp_player_on_destroy, NULL);
1834
1835         /* button row */
1836         hbuttonbox = gtk_hbutton_box_new ();
1837
1838         /* Filter/status hbox */
1839         stat_hbox = gtk_hbox_new(FALSE, 1);
1840         gtk_container_border_width(GTK_CONTAINER(stat_hbox), 0);
1841
1842         /* statusbar */
1843         info_bar = gtk_statusbar_new();
1844         gtk_statusbar_set_has_resize_grip(GTK_STATUSBAR(info_bar), TRUE);
1845
1846         gtk_box_pack_start(GTK_BOX(stat_hbox), info_bar, TRUE, TRUE, 0);
1847
1848         /* statusbar hbox */
1849         gtk_box_pack_start(GTK_BOX(main_vb), stat_hbox, FALSE, TRUE, 0);
1850
1851         /* set the sensitive state of the buttons (decode, play, pause, stop) */
1852         bt_state(TRUE, FALSE, FALSE, FALSE);
1853         
1854         gtk_widget_show_all(rtp_player_dlg_w);
1855
1856         /* Force gtk to redraw the window before starting decoding the packet */
1857         while (g_main_context_iteration(NULL, FALSE));
1858 }
1859
1860 /****************************************************************************/
1861 void
1862 rtp_player_init(voip_calls_tapinfo_t *voip_calls_tap)
1863 {
1864         PaError err;
1865         GtkWidget *dialog;
1866
1867         if (initialized) return;
1868         initialized = TRUE;
1869
1870         voip_calls = voip_calls_tap;
1871         err = Pa_Initialize();
1872         if( err != paNoError ) {
1873                 dialog = gtk_message_dialog_new ((GtkWindow *) rtp_player_dlg_w,
1874                                   GTK_DIALOG_DESTROY_WITH_PARENT, GTK_MESSAGE_ERROR,GTK_BUTTONS_CLOSE,
1875                                   "Can not Initialize the PortAduio Library.\n Error: %s", Pa_GetErrorText( err ));
1876                 gtk_dialog_run (GTK_DIALOG (dialog));
1877                 gtk_widget_destroy (dialog);
1878                 initialized = FALSE;
1879                 return;
1880         }
1881
1882         new_jitter_buff = -1;
1883
1884 #ifdef HAVE_G729_G723
1885         /* Initialize the G729 and G723 decoders */
1886         initG723();
1887         initG729();
1888 #endif /* HAVE_G729_G723 */
1889
1890         if (!rtp_channels) {
1891                 rtp_channels = g_malloc(sizeof(rtp_play_channles_t));
1892         }
1893
1894         reset_rtp_channels();
1895
1896         /* create the dialog window */
1897         rtp_player_dlg_create();
1898         
1899 }
1900
1901 #endif /* GTK_MAJOR_VERSION >= 2 */
1902  
1903 #endif /* HAVE_LIBPORTAUDIO */