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