1 /* rtp_player_dialog.h 2 * 3 * Wireshark - Network traffic analyzer 4 * By Gerald Combs <gerald@wireshark.org> 5 * Copyright 1998 Gerald Combs 6 * 7 * SPDX-License-Identifier: GPL-2.0-or-later 8 */ 9 10 #ifndef RTP_PLAYER_DIALOG_H 11 #define RTP_PLAYER_DIALOG_H 12 13 #include "config.h" 14 15 #include <glib.h> 16 #include <mutex> 17 18 #include "ui/rtp_stream.h" 19 20 #include "wireshark_dialog.h" 21 #include "rtp_audio_stream.h" 22 23 #include <QWidget> 24 #include <QMap> 25 #include <QMultiHash> 26 #include <QTreeWidgetItem> 27 #include <QMetaType> 28 #include <ui/qt/widgets/qcustomplot.h> 29 #include <QAudioDeviceInfo> 30 31 namespace Ui { 32 class RtpPlayerDialog; 33 } 34 35 class QCPItemStraightLine; 36 class QDialogButtonBox; 37 class QMenu; 38 class RtpAudioStream; 39 class QCPAxisTicker; 40 class QCPAxisTickerDateTime; 41 42 typedef enum { 43 save_audio_none, 44 save_audio_au, 45 save_audio_wav 46 } save_audio_t; 47 48 typedef enum { 49 save_payload_none, 50 save_payload_data 51 } save_payload_t; 52 53 typedef enum { 54 save_mode_from_cursor, 55 save_mode_sync_stream, 56 save_mode_sync_file 57 } save_mode_t; 58 59 // Singleton by https://refactoring.guru/design-patterns/singleton/cpp/example#example-1 60 class RtpPlayerDialog : public WiresharkDialog 61 { 62 Q_OBJECT 63 #ifdef QT_MULTIMEDIA_LIB 64 Q_PROPERTY(QString currentOutputDeviceName READ currentOutputDeviceName) 65 #endif 66 67 public: 68 /** 69 * Returns singleton 70 */ 71 static RtpPlayerDialog *openRtpPlayerDialog(QWidget &parent, CaptureFile &cf, QObject *packet_list, bool capture_running); 72 73 /** 74 * Should not be clonnable and assignable 75 */ 76 RtpPlayerDialog(RtpPlayerDialog &other) = delete; 77 void operator=(const RtpPlayerDialog &) = delete; 78 79 /** 80 * @brief Common routine to add a "Play call" button to a QDialogButtonBox. 81 * @param button_box Caller's QDialogButtonBox. 82 * @return The new "Play call" button. 83 */ 84 static QToolButton *addPlayerButton(QDialogButtonBox *button_box, QDialog *dialog); 85 86 #ifdef QT_MULTIMEDIA_LIB 87 void accept(); 88 void reject(); 89 90 void setMarkers(); 91 92 /** Replace/Add/Remove an RTP streams to play. 93 * Requires array of rtpstream_info_t. 94 * Each item must have filled items: src_addr, src_port, dest_addr, 95 * dest_port, ssrc, packet_count, setup_frame_number, and start_rel_time. 96 * 97 * @param stream_ids struct with rtpstream info 98 */ 99 void replaceRtpStreams(QVector<rtpstream_id_t *> stream_ids); 100 void addRtpStreams(QVector<rtpstream_id_t *> stream_ids); 101 void removeRtpStreams(QVector<rtpstream_id_t *> stream_ids); 102 103 signals: 104 // Tells the packet list to redraw. An alternative might be to add a 105 // cf_packet_marked callback to file.[ch] but that's synchronous and 106 // might incur too much overhead. 107 void packetsMarked(); 108 void updateFilter(QString filter, bool force = false); 109 void goToPacket(int packet_num); 110 void rtpAnalysisDialogReplaceRtpStreams(QVector<rtpstream_id_t *> stream_infos); 111 void rtpAnalysisDialogAddRtpStreams(QVector<rtpstream_id_t *> stream_infos); 112 void rtpAnalysisDialogRemoveRtpStreams(QVector<rtpstream_id_t *> stream_infos); 113 114 public slots: 115 void rtpAnalysisReplace(); 116 void rtpAnalysisAdd(); 117 void rtpAnalysisRemove(); 118 119 protected: 120 explicit RtpPlayerDialog(QWidget &parent, CaptureFile &cf, bool capture_running); 121 ~RtpPlayerDialog(); 122 123 virtual void showEvent(QShowEvent *); 124 void contextMenuEvent(QContextMenuEvent *event); 125 bool eventFilter(QObject *obj, QEvent *event); 126 127 private slots: 128 /** Retap the capture file, reading RTP packets that match the 129 * streams added using ::addRtpStream. 130 */ 131 void retapPackets(); 132 void captureEvent(CaptureEvent e); 133 /** Clear, decode, and redraw each stream. 134 */ 135 void rescanPackets(bool rescale_axes = false); 136 void createPlot(bool rescale_axes = false); 137 void updateWidgets(); 138 void itemEntered(QTreeWidgetItem *item, int column); 139 void mouseMovePlot(QMouseEvent *event); 140 void graphClicked(QMouseEvent *event); 141 void graphDoubleClicked(QMouseEvent *event); 142 void plotClicked(QCPAbstractPlottable *plottable, int dataIndex, QMouseEvent *event); 143 void updateHintLabel(); 144 void resetXAxis(); 145 void updateGraphs(); 146 void playFinished(RtpAudioStream *stream, QAudio::Error error); 147 148 void setPlayPosition(double secs); 149 void setPlaybackError(const QString playback_error); 150 void changeAudioRoutingOnItem(QTreeWidgetItem *ti, AudioRouting new_audio_routing); 151 void changeAudioRouting(AudioRouting new_audio_routing); 152 void invertAudioMutingOnItem(QTreeWidgetItem *ti); 153 void on_playButton_clicked(); 154 void on_pauseButton_clicked(); 155 void on_stopButton_clicked(); 156 void on_actionReset_triggered(); 157 void on_actionZoomIn_triggered(); 158 void on_actionZoomOut_triggered(); 159 void on_actionMoveLeft10_triggered(); 160 void on_actionMoveRight10_triggered(); 161 void on_actionMoveLeft1_triggered(); 162 void on_actionMoveRight1_triggered(); 163 void on_actionGoToPacket_triggered(); 164 void on_actionGoToSetupPacketPlot_triggered(); 165 void on_actionGoToSetupPacketTree_triggered(); 166 void on_actionRemoveStream_triggered(); 167 void on_actionAudioRoutingP_triggered(); 168 void on_actionAudioRoutingL_triggered(); 169 void on_actionAudioRoutingLR_triggered(); 170 void on_actionAudioRoutingR_triggered(); 171 void on_actionAudioRoutingMute_triggered(); 172 void on_actionAudioRoutingUnmute_triggered(); 173 void on_actionAudioRoutingMuteInvert_triggered(); 174 void on_streamTreeWidget_itemSelectionChanged(); 175 void on_streamTreeWidget_itemDoubleClicked(QTreeWidgetItem *item, const int column); 176 void on_outputDeviceComboBox_currentIndexChanged(const QString &); 177 void on_outputAudioRate_currentIndexChanged(const QString &); 178 void on_jitterSpinBox_valueChanged(double); 179 void on_timingComboBox_currentIndexChanged(int); 180 void on_todCheckBox_toggled(bool checked); 181 void on_buttonBox_helpRequested(); 182 void on_actionSelectAll_triggered(); 183 void on_actionSelectInvert_triggered(); 184 void on_actionSelectNone_triggered(); 185 void outputNotify(); 186 void on_actionPlay_triggered(); 187 void on_actionStop_triggered(); 188 void on_actionSaveAudioFromCursor_triggered(); 189 void on_actionSaveAudioSyncStream_triggered(); 190 void on_actionSaveAudioSyncFile_triggered(); 191 void on_actionSavePayload_triggered(); 192 void on_actionSelectInaudible_triggered(); 193 void on_actionDeselectInaudible_triggered(); 194 void on_actionPrepareFilter_triggered(); 195 void on_actionReadCapture_triggered(); 196 197 private: 198 static RtpPlayerDialog *pinstance_; 199 static std::mutex mutex_; 200 201 Ui::RtpPlayerDialog *ui; 202 QMenu *graph_ctx_menu_; 203 QMenu *list_ctx_menu_; 204 double first_stream_rel_start_time_; // Relative start time of first stream 205 double first_stream_abs_start_time_; // Absolute start time of first stream 206 double first_stream_rel_stop_time_; // Relative end time of first stream (ued for streams_length_ calculation 207 double streams_length_; // Difference between start of first stream and end of last stream 208 double start_marker_time_; // Always relative time to start of the capture 209 double start_marker_time_play_; // Copy when play started 210 QCPItemStraightLine *cur_play_pos_; 211 QCPItemStraightLine *start_marker_pos_; 212 QString playback_error_; 213 QSharedPointer<QCPAxisTicker> number_ticker_; 214 QSharedPointer<QCPAxisTickerDateTime> datetime_ticker_; 215 bool stereo_available_; 216 QList<RtpAudioStream *> playing_streams_; 217 QAudioOutput *marker_stream_; 218 quint32 marker_stream_requested_out_rate_; 219 QTreeWidgetItem *last_ti_; 220 bool listener_removed_; 221 QPushButton *read_btn_; 222 QToolButton *inaudible_btn_; 223 QToolButton *analyze_btn_; 224 QPushButton *prepare_btn_; 225 QPushButton *export_btn_; 226 QMultiHash<guint, RtpAudioStream *> stream_hash_; 227 bool block_redraw_; 228 int lock_ui_; 229 bool read_capture_enabled_; 230 double silence_skipped_time_; 231 232 // const QString streamKey(const rtpstream_info_t *rtpstream); 233 // const QString streamKey(const packet_info *pinfo, const struct _rtp_info *rtpinfo); 234 235 // Tap callbacks 236 // static void tapReset(void *tapinfo_ptr); 237 static tap_packet_status tapPacket(void *tapinfo_ptr, packet_info *pinfo, epan_dissect_t *, const void *rtpinfo_ptr); 238 static void tapDraw(void *tapinfo_ptr); 239 240 void addPacket(packet_info *pinfo, const struct _rtp_info *rtpinfo); 241 void zoomXAxis(bool in); 242 void panXAxis(int x_pixels); 243 const QString getFormatedTime(double f_time); 244 const QString getFormatedHoveredTime(); 245 int getHoveredPacket(); 246 QString currentOutputDeviceName(); 247 double getStartPlayMarker(); 248 void drawStartPlayMarker(); 249 void setStartPlayMarker(double new_time); 250 void updateStartStopTime(rtpstream_info_t *rtpstream, bool is_first); 251 void formatAudioRouting(QTreeWidgetItem *ti, AudioRouting audio_routing); 252 bool isStereoAvailable(); 253 QAudioOutput *getSilenceAudioOutput(); 254 QAudioDeviceInfo getCurrentDeviceInfo(); 255 QTreeWidgetItem *findItemByCoords(QPoint point); 256 QTreeWidgetItem *findItem(QCPAbstractPlottable *plottable); 257 void handleItemHighlight(QTreeWidgetItem *ti, bool scroll); 258 void highlightItem(QTreeWidgetItem *ti, bool highlight); 259 void invertSelection(); 260 void handleGoToSetupPacket(QTreeWidgetItem *ti); 261 void addSingleRtpStream(rtpstream_id_t *id); 262 void removeRow(QTreeWidgetItem *ti); 263 void fillAudioRateMenu(); 264 void cleanupMarkerStream(); 265 266 qint64 saveAudioHeaderAU(QFile *save_file, int channels, unsigned audio_rate); 267 qint64 saveAudioHeaderWAV(QFile *save_file, int channels, unsigned audio_rate, qint64 samples); 268 bool writeAudioSilenceSamples(QFile *out_file, qint64 samples, int stream_count); 269 bool writeAudioStreamsSamples(QFile *out_file, QVector<RtpAudioStream *> streams, bool swap_bytes); 270 save_audio_t selectFileAudioFormatAndName(QString *file_path); 271 save_payload_t selectFilePayloadFormatAndName(QString *file_path); 272 QVector<RtpAudioStream *>getSelectedAudibleNonmutedAudioStreams(); 273 void saveAudio(save_mode_t save_mode); 274 void savePayload(); 275 void lockUI(); 276 void unlockUI(); 277 void selectInaudible(bool select); 278 QVector<rtpstream_id_t *>getSelectedRtpStreamIDs(); 279 void fillTappedColumns(); 280 281 #else // QT_MULTIMEDIA_LIB 282 private: 283 Ui::RtpPlayerDialog *ui; 284 #endif // QT_MULTIMEDIA_LIB 285 }; 286 287 #endif // RTP_PLAYER_DIALOG_H 288