aboutsummaryrefslogtreecommitdiffstats
path: root/ui/qt/voip_calls_dialog.cpp
diff options
context:
space:
mode:
authorGerald Combs <gerald@wireshark.org>2014-12-12 16:51:40 -0800
committerGerald Combs <gerald@wireshark.org>2015-10-02 18:26:05 +0000
commit3687d393040a40655d84e3e03417a474032bad86 (patch)
tree55f208b60abb59c5812bae2407a9b36dfdd2f09a /ui/qt/voip_calls_dialog.cpp
parentfd5eafa50a77bc319a240727600be38307e54f86 (diff)
Qt: Initial RTP playback.
Note the "initial". This is woefully incomplete. See the "to do" lists below and in the code. This differs a bit from the GTK+ version in that you specify one or more streams to be decoded. Instead of showing waveforms in individual widgets, add them all to a single QCustomPlot. This conserves screen real estate and lets us more easily take advantage of the QCP API. It also looks better IMHO. Change a bunch of checks for QtMultimediaWidgets to QtMultimedia. We probably won't use the widgets until we make 5.0 our minimum Qt version and plain old QtMultimedia lets us support Qt 4 more easily (in theory at least). Add resampling code from libspeex. I initially used this to resample each packet to match the preferred rate of our output device, but this resulted in poorer audio quality than expected. Leave it in and use to create visual samples for QCP and to match rates any time the rate changes. The latter is currently untested. Add some debugging macros. Note that both the RTP player and RTP analysis dialogs decode audio data using different code. Note that voip_calls_packet and voip_calls_init_tap appear to be dead code. To do: - Add silence frames where needed. - Implement the jitter buffer. - Implement the playback timing controls. - Tapping / scanning streams might be too slow. Change-Id: I20dd3b66d3df53c9b1f3501262dc01458849f6b4 Bug: 9007 Reviewed-on: https://code.wireshark.org/review/10458 Petri-Dish: Gerald Combs <gerald@wireshark.org> Reviewed-by: Gerald Combs <gerald@wireshark.org>
Diffstat (limited to 'ui/qt/voip_calls_dialog.cpp')
-rw-r--r--ui/qt/voip_calls_dialog.cpp116
1 files changed, 87 insertions, 29 deletions
diff --git a/ui/qt/voip_calls_dialog.cpp b/ui/qt/voip_calls_dialog.cpp
index e530993c56..b18fd91537 100644
--- a/ui/qt/voip_calls_dialog.cpp
+++ b/ui/qt/voip_calls_dialog.cpp
@@ -27,9 +27,11 @@
#include "epan/addr_resolv.h"
#include "epan/dissectors/packet-h225.h"
+#include "ui/rtp_stream.h"
#include "ui/utf8_entities.h"
#include "qt_ui_utils.h"
+#include "rtp_player_dialog.h"
#include "sequence_dialog.h"
#include "stock_icon.h"
#include "wireshark_application.h"
@@ -62,37 +64,47 @@ const int comments_col_ = 8;
Q_DECLARE_METATYPE(voip_calls_info_t*)
+enum { voip_calls_type_ = 1000 };
+
class VoipCallsTreeWidgetItem : public QTreeWidgetItem
{
public:
- VoipCallsTreeWidgetItem(QTreeWidget *tree, voip_calls_info_t *call_info) : QTreeWidgetItem(tree) {
- setData(0, Qt::UserRole, qVariantFromValue(call_info));
+ VoipCallsTreeWidgetItem(QTreeWidget *tree, voip_calls_info_t *call_info) :
+ QTreeWidgetItem(tree, voip_calls_type_),
+ call_info_(call_info)
+ {
drawData();
}
+ voip_calls_info_t *callInfo() {
+ // XXX Not needed? We explicitly pass selected conversations to RtpPlayerDialog.
+// call_info_->selected = isSelected() ? TRUE : FALSE;
+ return call_info_;
+ }
+
void drawData() {
- voip_calls_info_t *call_info = data(0, Qt::UserRole).value<voip_calls_info_t*>();
- if (!call_info) {
+ if (!call_info_) {
+ setText(start_time_col_, QObject::tr("Error"));
return;
}
// XXX Pull digit count from capture file precision
- setText(start_time_col_, QString::number(nstime_to_sec(&(call_info->start_rel_ts)), 'f', 6));
- setText(stop_time_col_, QString::number(nstime_to_sec(&(call_info->stop_rel_ts)), 'f', 6));
- setText(initial_speaker_col_, address_to_display_qstring(&(call_info->initial_speaker)));
- setText(from_col_, call_info->from_identity);
- setText(to_col_, call_info->to_identity);
- setText(protocol_col_, ((call_info->protocol == VOIP_COMMON) && call_info->protocol_name) ?
- call_info->protocol_name : voip_protocol_name[call_info->protocol]);
- setText(packets_col_, QString::number(call_info->npackets));
- setText(state_col_, voip_call_state_name[call_info->call_state]);
+ setText(start_time_col_, QString::number(nstime_to_sec(&(call_info_->start_rel_ts)), 'f', 6));
+ setText(stop_time_col_, QString::number(nstime_to_sec(&(call_info_->stop_rel_ts)), 'f', 6));
+ setText(initial_speaker_col_, address_to_display_qstring(&(call_info_->initial_speaker)));
+ setText(from_col_, call_info_->from_identity);
+ setText(to_col_, call_info_->to_identity);
+ setText(protocol_col_, ((call_info_->protocol == VOIP_COMMON) && call_info_->protocol_name) ?
+ call_info_->protocol_name : voip_protocol_name[call_info_->protocol]);
+ setText(packets_col_, QString::number(call_info_->npackets));
+ setText(state_col_, voip_call_state_name[call_info_->call_state]);
/* Add comments based on the protocol */
QString call_comments;
- switch (call_info->protocol) {
+ switch (call_info_->protocol) {
case VOIP_ISUP:
{
- isup_calls_info_t *isup_info = (isup_calls_info_t *)call_info->prot_info;
+ isup_calls_info_t *isup_info = (isup_calls_info_t *)call_info_->prot_info;
call_comments = QString("%1-%2 %3 %4-%5")
.arg(isup_info->ni)
.arg(isup_info->opc)
@@ -103,11 +115,11 @@ public:
break;
case VOIP_H323:
{
- h323_calls_info_t *h323_info = (h323_calls_info_t *)call_info->prot_info;
+ h323_calls_info_t *h323_info = (h323_calls_info_t *)call_info_->prot_info;
gboolean flag = FALSE;
static const QString on_str = QObject::tr("On");
static const QString off_str = QObject::tr("Off");
- if (call_info->call_state == VOIP_CALL_SETUP) {
+ if (call_info_->call_state == VOIP_CALL_SETUP) {
flag = h323_info->is_faststart_Setup;
} else {
if ((h323_info->is_faststart_Setup) && (h323_info->is_faststart_Proc)) {
@@ -121,7 +133,7 @@ public:
break;
case VOIP_COMMON:
default:
- call_comments = call_info->call_comment;
+ call_comments = call_info_->call_comment;
break;
}
setText(comments_col_, call_comments);
@@ -129,24 +141,25 @@ public:
bool operator< (const QTreeWidgetItem &other) const
{
- voip_calls_info_t *this_call_info = data(0, Qt::UserRole).value<voip_calls_info_t*>();
- voip_calls_info_t *other_call_info = other.data(0, Qt::UserRole).value<voip_calls_info_t*>();
- if (!this_call_info || !other_call_info) {
- return false;
+ if (other.type() != voip_calls_type_) return QTreeWidgetItem::operator< (other);
+ const VoipCallsTreeWidgetItem *other_row = static_cast<const VoipCallsTreeWidgetItem *>(&other);
+
+ if (!call_info_ || !other_row->call_info_) {
+ return QTreeWidgetItem::operator< (other);
}
switch (treeWidget()->sortColumn()) {
case start_time_col_:
- return nstime_cmp(&(this_call_info->start_rel_ts), &(other_call_info->start_rel_ts)) < 0;
+ return nstime_cmp(&(call_info_->start_rel_ts), &(other_row->call_info_->start_rel_ts)) < 0;
break;
case stop_time_col_:
- return nstime_cmp(&(this_call_info->stop_rel_ts), &(other_call_info->stop_rel_ts)) < 0;
+ return nstime_cmp(&(call_info_->stop_rel_ts), &(other_row->call_info_->stop_rel_ts)) < 0;
break;
case initial_speaker_col_:
- return cmp_address(&(this_call_info->initial_speaker), &(other_call_info->initial_speaker)) < 0;
+ return cmp_address(&(call_info_->initial_speaker), &(other_row->call_info_->initial_speaker)) < 0;
break;
case packets_col_:
- return this_call_info->npackets < other_call_info->npackets;
+ return call_info_->npackets < other_row->call_info_->npackets;
break;
default:
break;
@@ -155,7 +168,8 @@ public:
// Fall back to string comparison
return QTreeWidgetItem::operator <(other);
}
-
+private:
+ voip_calls_info_t *call_info_;
};
VoipCallsDialog::VoipCallsDialog(QWidget &parent, CaptureFile &cf, bool all_flows) :
@@ -240,7 +254,7 @@ void VoipCallsDialog::changeEvent(QEvent *event)
gboolean VoipCallsDialog::tapPacket(void *, packet_info *, epan_dissect_t *, const void *)
{
-#ifdef QT_MULTIMEDIAWIDGETS_LIB
+#ifdef QT_MULTIMEDIA_LIB
// voip_calls_tapinfo_t *tapinfo = (voip_calls_tapinfo_t *) tapinfo_ptr;
// add_rtp_packet for voip player.
// return TRUE;
@@ -256,6 +270,19 @@ void VoipCallsDialog::tapDraw(void *tapinfo_ptr)
return;
}
+ GList *graph_item = g_queue_peek_nth_link(tapinfo->graph_analysis->items, 0);
+ for (; graph_item; graph_item = g_list_next(graph_item)) {
+ for (GList *rsi_entry = g_list_first(tapinfo->rtp_stream_list); rsi_entry; rsi_entry = g_list_next(rsi_entry)) {
+ seq_analysis_item_t * sai = (seq_analysis_item_t *)graph_item->data;
+ rtp_stream_info_t *rsi = (rtp_stream_info_t *)rsi_entry->data;
+
+ if (rsi->start_fd->num == sai->fd->num) {
+ rsi->call_num = sai->conv_num;
+ // VOIP_CALLS_DEBUG("setting conv num %u for frame %u", sai->conv_num, sai->fd->num);
+ }
+ }
+ }
+
VoipCallsDialog *voip_calls_dialog = static_cast<VoipCallsDialog *>(tapinfo->tap_data);
if (voip_calls_dialog) {
voip_calls_dialog->updateCalls();
@@ -306,7 +333,7 @@ void VoipCallsDialog::updateWidgets()
}
prepare_button_->setEnabled(selected && have_ga_items);
sequence_button_->setEnabled(selected && have_ga_items);
-#if defined(QT_MULTIMEDIAWIDGETS_LIB) && 0 // We don't have a playback dialog yet.
+#if defined(QT_MULTIMEDIA_LIB)
player_button_->setEnabled(selected && have_ga_items);
#else
player_button_->setEnabled(false);
@@ -456,6 +483,35 @@ void VoipCallsDialog::showSequence()
sequence_dialog->show();
}
+void VoipCallsDialog::showPlayer()
+{
+#ifdef QT_MULTIMEDIA_LIB
+ RtpPlayerDialog rtp_player_dialog(*this, cap_file_);
+
+ foreach (QTreeWidgetItem *ti, ui->callTreeWidget->selectedItems()) {
+ VoipCallsTreeWidgetItem *vc_ti = static_cast<VoipCallsTreeWidgetItem *>(ti);
+ for (GList *rsi_entry = g_list_first(tapinfo_.rtp_stream_list); rsi_entry; rsi_entry = g_list_next(rsi_entry)) {
+ rtp_stream_info_t *rsi = (rtp_stream_info_t *)rsi_entry->data;
+ if (!rsi) continue;
+
+ //VOIP_CALLS_DEBUG("checking call %u, start frame %u == stream call %u, start frame %u, setup frame %u",
+ // vc_ti->callInfo()->call_num, vc_ti->callInfo()->start_fd->num,
+ // rsi->call_num, rsi->start_fd->num, rsi->setup_frame_number);
+ if (vc_ti->callInfo()->call_num == rsi->call_num) {
+ //VOIP_CALLS_DEBUG("adding call number %u", vc_ti->callInfo()->call_num);
+ rtp_player_dialog.addRtpStream(rsi);
+ }
+ }
+ }
+
+ connect(&rtp_player_dialog, SIGNAL(goToPacket(int)), this, SIGNAL(goToPacket(int)));
+
+ // XXX This retaps the packet list. We still have our own tap listener
+ // registered at this point.
+ rtp_player_dialog.exec();
+#endif // QT_MULTIMEDIA_LIB
+}
+
void VoipCallsDialog::on_callTreeWidget_itemActivated(QTreeWidgetItem *item, int)
{
voip_calls_info_t *call_info = item->data(0, Qt::UserRole).value<voip_calls_info_t*>();
@@ -481,6 +537,8 @@ void VoipCallsDialog::on_buttonBox_clicked(QAbstractButton *button)
prepareFilter();
} else if (button == sequence_button_) {
showSequence();
+ } else if (button == player_button_) {
+ showPlayer();
}
}