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