From b8d85227f6cfacb66237a6399f28cef0e94d1cb1 Mon Sep 17 00:00:00 2001 From: Gerald Combs Date: Mon, 23 May 2022 18:59:35 -0700 Subject: [PATCH] Qt: Update the RTP stream UI to support Qt6Multimedia. Fixes #18115 --- CMakeLists.txt | 12 +++- ui/qt/rtp_audio_stream.cpp | 90 ++++++++++++++++++++++++--- ui/qt/rtp_audio_stream.h | 30 +++++++-- ui/qt/rtp_player_dialog.cpp | 120 ++++++++++++++++++++++++++++++++---- ui/qt/rtp_player_dialog.h | 24 +++++++- 5 files changed, 242 insertions(+), 34 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 25d4f40a87..627d96849b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1210,12 +1210,13 @@ if(BUILD_wireshark OR BUILD_logray) Qt${qtver}Core Qt${qtver}Gui Qt${qtver}LinguistTools - # Our code currently does not compile with Qt6Multimedia - # Qt${qtver}Multimedia Qt${qtver}PrintSupport Qt${qtver}Widgets Qt${qtver}Concurrent ) + set(QT_OPTIONAL_PACKAGELIST + Qt${qtver}Multimedia + ) if(USE_qt6) set(CMAKE_CXX_STANDARD 17) # Setting CMAKE_CXX_STANDARD is not sufficient with MSVC, see @@ -1226,7 +1227,6 @@ if(BUILD_wireshark OR BUILD_logray) endif() list(APPEND QT_PACKAGELIST Qt6Core5Compat) else() - list(APPEND QT_PACKAGELIST Qt5Multimedia) if(WIN32) list(APPEND QT_PACKAGELIST Qt5WinExtras) endif() @@ -1237,6 +1237,12 @@ if(BUILD_wireshark OR BUILD_logray) list(APPEND QT_INCLUDE_DIRS ${${_qt_package}_INCLUDE_DIRS}) list(APPEND QT_COMPILE_DEFINITIONS ${${_qt_package}_COMPILE_DEFINITIONS}) endforeach() + foreach(_qt_package IN LISTS QT_OPTIONAL_PACKAGELIST) + find_package(${_qt_package} ${QT_FIND_PACKAGE_OPTIONS}) + list(APPEND QT_LIBRARIES ${${_qt_package}_LIBRARIES}) + list(APPEND QT_INCLUDE_DIRS ${${_qt_package}_INCLUDE_DIRS}) + list(APPEND QT_COMPILE_DEFINITIONS ${${_qt_package}_COMPILE_DEFINITIONS}) + endforeach() if(APPLE AND "/usr/local/opt/qt5/lib/QtCore.framework" IN_LIST Qt5Core_INCLUDE_DIRS) # When qt@6 and qt@5 are both installed via Homebrew, # /usr/local/include/QtCore/qvariant.h points to Qt 6 headers. diff --git a/ui/qt/rtp_audio_stream.cpp b/ui/qt/rtp_audio_stream.cpp index 83b3c248ea..a1cb42c2f9 100644 --- a/ui/qt/rtp_audio_stream.cpp +++ b/ui/qt/rtp_audio_stream.cpp @@ -31,6 +31,10 @@ #include #include +#if (QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)) +#include +#include +#endif #include #include #include @@ -54,13 +58,13 @@ RtpAudioStream::RtpAudioStream(QObject *parent, rtpstream_id_t *id, bool stereo_ , audio_out_rate_(0) , audio_requested_out_rate_(0) , audio_resampler_(0) - , audio_output_(NULL) , max_sample_val_(1) , max_sample_val_used_(1) , color_(0) , jitter_buffer_size_(50) , timing_mode_(RtpAudioStream::JitterBuffer) , start_play_time_(0) + , audio_output_(NULL) { rtpstream_id_copy(id, &id_); memset(&rtpstream_, 0, sizeof(rtpstream_)); @@ -181,7 +185,11 @@ void RtpAudioStream::setAudioRouting(AudioRouting audio_routing) audio_routing_ = audio_routing; } +#if (QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)) +void RtpAudioStream::decode(QAudioDevice out_device) +#else void RtpAudioStream::decode(QAudioDeviceInfo out_device) +#endif { if (rtp_packets_.size() < 1) return; @@ -200,7 +208,11 @@ void RtpAudioStream::decode(QAudioDeviceInfo out_device) } // Side effect: it creates and initiates resampler if needed +#if (QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)) +quint32 RtpAudioStream::calculateAudioOutRate(QAudioDevice out_device, unsigned int sample_rate, unsigned int requested_out_rate) +#else quint32 RtpAudioStream::calculateAudioOutRate(QAudioDeviceInfo out_device, unsigned int sample_rate, unsigned int requested_out_rate) +#endif { quint32 out_rate; @@ -208,19 +220,30 @@ quint32 RtpAudioStream::calculateAudioOutRate(QAudioDeviceInfo out_device, unsig // our audio hardware. QAudioFormat format; format.setSampleRate(sample_rate); +#if (QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)) + // Must match rtp_media.h. + format.setSampleFormat(QAudioFormat::Int16); +#else format.setSampleSize(SAMPLE_BYTES * 8); // bits format.setSampleType(QAudioFormat::SignedInt); +#endif if (stereo_required_) { format.setChannelCount(2); } else { format.setChannelCount(1); } +#if (QT_VERSION < QT_VERSION_CHECK(6, 0, 0)) format.setCodec("audio/pcm"); +#endif if (!out_device.isFormatSupported(format) && (requested_out_rate==0) ) { +#if (QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)) + out_rate = out_device.preferredFormat().sampleRate(); +#else out_rate = out_device.nearestFormat(format).sampleRate(); +#endif audio_resampler_ = speex_resampler_init(1, sample_rate, out_rate, 10, NULL); RTP_STREAM_DEBUG("Started resampling from %u to (out) %u Hz.", sample_rate, out_rate); } else { @@ -240,7 +263,11 @@ quint32 RtpAudioStream::calculateAudioOutRate(QAudioDeviceInfo out_device, unsig return out_rate; } +#if (QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)) +void RtpAudioStream::decodeAudio(QAudioDevice out_device) +#else void RtpAudioStream::decodeAudio(QAudioDeviceInfo out_device) +#endif { // XXX This is more messy than it should be. @@ -607,10 +634,10 @@ const QVector RtpAudioStream::insertedSilenceSamples(int y_offset) quint32 RtpAudioStream::nearestPacket(double timestamp, bool is_relative) { - if (packet_timestamps_.keys().count() < 1) return 0; + if (packet_timestamps_.size() < 1) return 0; if (!is_relative) timestamp -= start_abs_offset_; - QMap::const_iterator it = packet_timestamps_.lowerBound(timestamp); + QMap::iterator it = packet_timestamps_.lowerBound(timestamp); if (it == packet_timestamps_.end()) return 0; return it.value(); } @@ -624,12 +651,16 @@ QAudio::State RtpAudioStream::outputState() const const QString RtpAudioStream::formatDescription(const QAudioFormat &format) { QString fmt_descr = QString("%1 Hz, ").arg(format.sampleRate()); - switch (format.sampleType()) { - case QAudioFormat::SignedInt: - fmt_descr += "Int"; +#if (QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)) + switch (format.sampleFormat()) { + case QAudioFormat::UInt8: + fmt_descr += "UInt8"; break; - case QAudioFormat::UnSignedInt: - fmt_descr += "UInt"; + case QAudioFormat::Int16: + fmt_descr += "Int16"; + break; + case QAudioFormat::Int32: + fmt_descr += "Int32"; break; case QAudioFormat::Float: fmt_descr += "Float"; @@ -638,8 +669,26 @@ const QString RtpAudioStream::formatDescription(const QAudioFormat &format) fmt_descr += "Unknown"; break; } - fmt_descr += QString::number(format.sampleSize()); - fmt_descr += format.byteOrder() == QAudioFormat::BigEndian ? "BE" : "LE"; +#else + switch (format.sampleType()) { + case QAudioFormat::SignedInt: + fmt_descr += "Int"; + fmt_descr += QString::number(format.sampleSize()); + fmt_descr += format.byteOrder() == QAudioFormat::BigEndian ? "BE" : "LE"; + break; + case QAudioFormat::UnSignedInt: + fmt_descr += "UInt"; + fmt_descr += QString::number(format.sampleSize()); + fmt_descr += format.byteOrder() == QAudioFormat::BigEndian ? "BE" : "LE"; + break; + case QAudioFormat::Float: + fmt_descr += "Float"; + break; + default: + fmt_descr += "Unknown"; + break; + } +#endif return fmt_descr; } @@ -660,7 +709,11 @@ QString RtpAudioStream::getIDAsQString() return str; } +#if (QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)) +bool RtpAudioStream::prepareForPlay(QAudioDevice out_device) +#else bool RtpAudioStream::prepareForPlay(QAudioDeviceInfo out_device) +#endif { qint64 start_pos; qint64 size; @@ -683,24 +736,36 @@ bool RtpAudioStream::prepareForPlay(QAudioDeviceInfo out_device) QAudioFormat format; format.setSampleRate(audio_out_rate_); +#if (QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)) + // Must match rtp_media.h. + format.setSampleFormat(QAudioFormat::Int16); +#else format.setSampleSize(SAMPLE_BYTES * 8); // bits format.setSampleType(QAudioFormat::SignedInt); +#endif if (stereo_required_) { format.setChannelCount(2); } else { format.setChannelCount(1); } +#if (QT_VERSION < QT_VERSION_CHECK(6, 0, 0)) format.setCodec("audio/pcm"); +#endif // RTP_STREAM_DEBUG("playing %s %d samples @ %u Hz", // sample_file_->fileName().toUtf8().constData(), // (int) sample_file_->size(), audio_out_rate_); if (!out_device.isFormatSupported(format)) { +#if (QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)) + QString playback_error = tr("%1 does not support PCM at %2. Preferred format is %3") + .arg(out_device.description(), formatDescription(format), formatDescription(out_device.preferredFormat())); +#else QString playback_error = tr("%1 does not support PCM at %2. Preferred format is %3") .arg(out_device.deviceName()) .arg(formatDescription(format)) .arg(formatDescription(out_device.nearestFormat(format))); +#endif emit playbackError(playback_error); } @@ -718,8 +783,13 @@ bool RtpAudioStream::prepareForPlay(QAudioDeviceInfo out_device) temp_file_ = new AudioRoutingFilter(audio_file_, stereo_required_, audio_routing_); temp_file_->seek(start_pos); if (audio_output_) delete audio_output_; +#if (QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)) + audio_output_ = new QAudioSink(out_device, format, this); + connect(audio_output_, &QAudioSink::stateChanged, this, &RtpAudioStream::outputStateChanged); +#else audio_output_ = new QAudioOutput(out_device, format, this); connect(audio_output_, &QAudioOutput::stateChanged, this, &RtpAudioStream::outputStateChanged); +#endif return true; } else { // Report stopped audio if start position is later than stream ends diff --git a/ui/qt/rtp_audio_stream.h b/ui/qt/rtp_audio_stream.h index 9cf24fa2be..0279a6d9f2 100644 --- a/ui/qt/rtp_audio_stream.h +++ b/ui/qt/rtp_audio_stream.h @@ -32,7 +32,11 @@ #include class QAudioFormat; +#if (QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)) +class QAudioSink; +#else class QAudioOutput; +#endif class QIODevice; @@ -51,7 +55,11 @@ public: void reset(double global_start_time); AudioRouting getAudioRouting(); void setAudioRouting(AudioRouting audio_routing); +#if (QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)) + void decode(QAudioDevice out_device); +#else void decode(QAudioDeviceInfo out_device); +#endif double startRelTime() const { return start_rel_time_; } double stopRelTime() const { return stop_rel_time_; } @@ -78,7 +86,7 @@ public: * @return A set of timestamps suitable for passing to QCPGraph::setData. */ const QVector outOfSequenceTimestamps(bool relative = true); - int outOfSequence() { return out_of_seq_timestamps_.size(); } + int outOfSequence() { return static_cast(out_of_seq_timestamps_.size()); } /** * @brief Return a list of out-of-sequence samples. Y value is constant. * @param y_offset Y axis offset to be used for stacking graphs. @@ -91,7 +99,7 @@ public: * @return A set of timestamps suitable for passing to QCPGraph::setData. */ const QVector jitterDroppedTimestamps(bool relative = true); - int jitterDropped() { return jitter_drop_timestamps_.size(); } + int jitterDropped() { return static_cast(jitter_drop_timestamps_.size()); } /** * @brief Return a list of jitter dropped samples. Y value is constant. * @param y_offset Y axis offset to be used for stacking graphs. @@ -104,7 +112,7 @@ public: * @return A set of timestamps suitable for passing to QCPGraph::setData. */ const QVector wrongTimestampTimestamps(bool relative = true); - int wrongTimestamps() { return wrong_timestamp_timestamps_.size(); } + int wrongTimestamps() { return static_cast(wrong_timestamp_timestamps_.size()); } /** * @brief Return a list of wrong timestamp samples. Y value is constant. * @param y_offset Y axis offset to be used for stacking graphs. @@ -117,7 +125,7 @@ public: * @return A set of timestamps suitable for passing to QCPGraph::setData. */ const QVector insertedSilenceTimestamps(bool relative = true); - int insertedSilences() { return silence_timestamps_.size(); } + int insertedSilences() { return static_cast(silence_timestamps_.size()); } /** * @brief Return a list of wrong timestamp samples. Y value is constant. * @param y_offset Y axis offset to be used for stacking graphs. @@ -135,7 +143,11 @@ public: void setJitterBufferSize(int jitter_buffer_size) { jitter_buffer_size_ = jitter_buffer_size; } void setTimingMode(TimingMode timing_mode) { timing_mode_ = timing_mode; } void setStartPlayTime(double start_play_time) { start_play_time_ = start_play_time; } +#if (QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)) + bool prepareForPlay(QAudioDevice out_device); +#else bool prepareForPlay(QAudioDeviceInfo out_device); +#endif void startPlaying(); void pausePlaying(); void stopPlaying(); @@ -185,7 +197,6 @@ private: QSet payload_names_; struct SpeexResamplerState_ *audio_resampler_; struct SpeexResamplerState_ *visual_resampler_; - QAudioOutput *audio_output_; QMap packet_timestamps_; QVector visual_samples_; QVector out_of_seq_timestamps_; @@ -203,9 +214,16 @@ private: const QString formatDescription(const QAudioFormat & format); QString currentOutputDevice(); +#if (QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)) + QAudioSink *audio_output_; + void decodeAudio(QAudioDevice out_device); + quint32 calculateAudioOutRate(QAudioDevice out_device, unsigned int sample_rate, unsigned int requested_out_rate); +#else + QAudioOutput *audio_output_; void decodeAudio(QAudioDeviceInfo out_device); - void decodeVisual(); quint32 calculateAudioOutRate(QAudioDeviceInfo out_device, unsigned int sample_rate, unsigned int requested_out_rate); +#endif + void decodeVisual(); SAMPLE *resizeBufferIfNeeded(SAMPLE *buff, gint32 *buff_bytes, qint64 requested_size); private slots: diff --git a/ui/qt/rtp_player_dialog.cpp b/ui/qt/rtp_player_dialog.cpp index 651c32e7e1..47a38205af 100644 --- a/ui/qt/rtp_player_dialog.cpp +++ b/ui/qt/rtp_player_dialog.cpp @@ -39,7 +39,13 @@ #include "ui/qt/widgets/wireshark_file_dialog.h" #include +#if (QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)) +#include +#include +#include +#else #include +#endif #include #include #include @@ -216,6 +222,11 @@ RtpPlayerDialog::RtpPlayerDialog(QWidget &parent, CaptureFile &cf, bool capture_ drawStartPlayMarker(); start_marker_pos_->setVisible(true); +#if (QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)) + notify_timer_.setInterval(100); // ~15 fps + connect(¬ify_timer_, &QTimer::timeout, this, &RtpPlayerDialog::outputNotify); +#endif + datetime_ticker_->setDateTimeFormat("yyyy-MM-dd\nhh:mm:ss.zzz"); ui->audioPlot->xAxis->setNumberFormat("gb"); @@ -264,12 +275,21 @@ RtpPlayerDialog::RtpPlayerDialog(QWidget &parent, CaptureFile &cf, bool capture_ // Ordered, unique device names starting with the system default QMap out_device_map; // true == default device +#if (QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)) + out_device_map.insert(QMediaDevices::defaultAudioOutput().description(), true); + foreach (QAudioDevice out_device, QMediaDevices::audioOutputs()) { + if (!out_device_map.contains(out_device.description())) { + out_device_map.insert(out_device.description(), false); + } + } +#else out_device_map.insert(QAudioDeviceInfo::defaultOutputDevice().deviceName(), true); foreach (QAudioDeviceInfo out_device, QAudioDeviceInfo::availableDevices(QAudio::AudioOutput)) { if (!out_device_map.contains(out_device.deviceName())) { out_device_map.insert(out_device.deviceName(), false); } } +#endif ui->outputDeviceComboBox->blockSignals(true); foreach (QString out_name, out_device_map.keys()) { @@ -460,7 +480,11 @@ void RtpPlayerDialog::rescanPackets(bool rescale_axes) ui->hintLabel->setText("" + tr("Decoding streams...") + ""); mainApp->processEvents(); +#if (QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)) + QAudioDevice cur_out_device = getCurrentDeviceInfo(); +#else QAudioDeviceInfo cur_out_device = getCurrentDeviceInfo(); +#endif int row_count = ui->streamTreeWidget->topLevelItemCount(); // Reset stream values @@ -1000,7 +1024,7 @@ void RtpPlayerDialog::updateWidgets() bool enable_stop = false; bool enable_timing = true; int count = ui->streamTreeWidget->topLevelItemCount(); - int selected = ui->streamTreeWidget->selectedItems().count(); + qsizetype selected = ui->streamTreeWidget->selectedItems().count(); if (count < 1) { enable_play = false; @@ -1177,7 +1201,7 @@ void RtpPlayerDialog::updateHintLabel() QString hint = ""; double start_pos = getStartPlayMarker(); int row_count = ui->streamTreeWidget->topLevelItemCount(); - int selected = ui->streamTreeWidget->selectedItems().count(); + qsizetype selected = ui->streamTreeWidget->selectedItems().count(); int not_muted = 0; hint += tr("%1 streams").arg(row_count); @@ -1368,7 +1392,11 @@ void RtpPlayerDialog::on_playButton_clicked() start_time = start_marker_time_play_ - first_stream_rel_start_time_; } +#if (QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)) + QAudioDevice cur_out_device = getCurrentDeviceInfo(); +#else QAudioDeviceInfo cur_out_device = getCurrentDeviceInfo(); +#endif playing_streams_.clear(); int row_count = ui->streamTreeWidget->topLevelItemCount(); for (int row = 0; row < row_count; row++) { @@ -1397,6 +1425,29 @@ void RtpPlayerDialog::on_playButton_clicked() updateWidgets(); } +#if (QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)) +QAudioDevice RtpPlayerDialog::getCurrentDeviceInfo() +{ + QAudioDevice cur_out_device = QMediaDevices::defaultAudioOutput(); + QString cur_out_name = currentOutputDeviceName(); + foreach (QAudioDevice out_device, QMediaDevices::audioOutputs()) { + if (cur_out_name == out_device.description()) { + cur_out_device = out_device; + } + } + + return cur_out_device; +} + +void RtpPlayerDialog::sinkStateChanged() +{ + if (marker_stream_->state() == QAudio::ActiveState) { + notify_timer_.start(); + } else { + notify_timer_.stop(); + } +} +#else QAudioDeviceInfo RtpPlayerDialog::getCurrentDeviceInfo() { QAudioDeviceInfo cur_out_device = QAudioDeviceInfo::defaultOutputDevice(); @@ -1409,7 +1460,31 @@ QAudioDeviceInfo RtpPlayerDialog::getCurrentDeviceInfo() return cur_out_device; } +#endif +#if (QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)) +QAudioSink *RtpPlayerDialog::getSilenceAudioOutput() +{ + QAudioDevice cur_out_device = getCurrentDeviceInfo(); + + QAudioFormat format; + if (marker_stream_requested_out_rate_ > 0) { + format.setSampleRate(marker_stream_requested_out_rate_); + } else { + format.setSampleRate(8000); + } + // Must match rtp_media.h. + format.setSampleFormat(QAudioFormat::Int16); + format.setChannelCount(1); + if (!cur_out_device.isFormatSupported(format)) { + format = cur_out_device.preferredFormat(); + } + + QAudioSink *sink = new QAudioSink(cur_out_device, format, this); + connect(sink, &QAudioSink::stateChanged, this, &RtpPlayerDialog::sinkStateChanged); + return sink; +} +#else QAudioOutput *RtpPlayerDialog::getSilenceAudioOutput() { QAudioOutput *o; @@ -1431,10 +1506,11 @@ QAudioOutput *RtpPlayerDialog::getSilenceAudioOutput() o = new QAudioOutput(cur_out_device, format, this); o->setNotifyInterval(100); // ~15 fps - connect(o, SIGNAL(notify()), this, SLOT(outputNotify())); + connect(o, &QAudioOutput::notify, this, &RtpPlayerDialog::outputNotify); return o; } +#endif void RtpPlayerDialog::outputNotify() { @@ -1591,7 +1667,7 @@ void RtpPlayerDialog::on_streamTreeWidget_itemSelectionChanged() } } - int selected = ui->streamTreeWidget->selectedItems().count(); + qsizetype selected = ui->streamTreeWidget->selectedItems().count(); if (selected == 0) { analyze_btn_->setEnabled(false); prepare_btn_->setEnabled(false); @@ -1682,7 +1758,7 @@ void RtpPlayerDialog::on_actionRemoveStream_triggered() QList items = ui->streamTreeWidget->selectedItems(); block_redraw_ = true; - for(int i = items.count() - 1; i>=0; i-- ) { + for(int i = static_cast(items.count()) - 1; i>=0; i-- ) { removeRow(items[i]); } block_redraw_ = false; @@ -1859,9 +1935,22 @@ void RtpPlayerDialog::fillAudioRateMenu() ui->outputAudioRate->blockSignals(true); ui->outputAudioRate->clear(); ui->outputAudioRate->addItem(tr("Automatic")); +#if (QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)) + // XXX QAudioDevice doesn't provide supportedSampleRates(). Fake it with + // what's available. + QAudioDevice cur_out_device = getCurrentDeviceInfo(); + QSetsample_rates; + sample_rates.insert(cur_out_device.minimumSampleRate()); + sample_rates.insert(cur_out_device.preferredFormat().sampleRate()); + sample_rates.insert(cur_out_device.maximumSampleRate()); + for (auto rate : sample_rates) { + ui->outputAudioRate->addItem(QString::number(rate)); + } +#else foreach (int rate, getCurrentDeviceInfo().supportedSampleRates()) { ui->outputAudioRate->addItem(QString::number(rate)); } +#endif ui->outputAudioRate->blockSignals(false); } @@ -2017,12 +2106,19 @@ void RtpPlayerDialog::formatAudioRouting(QTreeWidgetItem *ti, AudioRouting audio bool RtpPlayerDialog::isStereoAvailable() { +#if (QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)) + QAudioDevice cur_out_device = getCurrentDeviceInfo(); + if (cur_out_device.maximumChannelCount() > 1) { + return true; + } +#else QAudioDeviceInfo cur_out_device = getCurrentDeviceInfo(); foreach(int count, cur_out_device.supportedChannelCounts()) { - if (count>1) { + if (count > 1) { return true; } } +#endif return false; } @@ -2075,7 +2171,7 @@ void RtpPlayerDialog::on_actionStop_triggered() } } -qint64 RtpPlayerDialog::saveAudioHeaderAU(QFile *save_file, int channels, unsigned audio_rate) +qint64 RtpPlayerDialog::saveAudioHeaderAU(QFile *save_file, quint32 channels, unsigned audio_rate) { uint8_t pd[4]; int64_t nchars; @@ -2131,7 +2227,7 @@ qint64 RtpPlayerDialog::saveAudioHeaderAU(QFile *save_file, int channels, unsign return save_file->pos(); } -qint64 RtpPlayerDialog::saveAudioHeaderWAV(QFile *save_file, int channels, unsigned audio_rate, qint64 samples) +qint64 RtpPlayerDialog::saveAudioHeaderWAV(QFile *save_file, quint32 channels, unsigned audio_rate, qint64 samples) { uint8_t pd[4]; int64_t nchars; @@ -2464,12 +2560,12 @@ void RtpPlayerDialog::saveAudio(save_mode_t save_mode) } else { switch (format) { case save_audio_au: - if (-1 == saveAudioHeaderAU(&file, streams.count(), save_audio_rate)) { + if (-1 == saveAudioHeaderAU(&file, static_cast(streams.count()), save_audio_rate)) { QMessageBox::warning(this, tr("Error"), tr("Can't write header of AU file")); return; } if (lead_silence_samples > 0) { - if (!writeAudioSilenceSamples(&file, lead_silence_samples, streams.count())) { + if (!writeAudioSilenceSamples(&file, lead_silence_samples, static_cast(streams.count()))) { QMessageBox::warning(this, tr("Warning"), tr("Save failed!")); } } @@ -2478,12 +2574,12 @@ void RtpPlayerDialog::saveAudio(save_mode_t save_mode) } break; case save_audio_wav: - if (-1 == saveAudioHeaderWAV(&file, streams.count(), save_audio_rate, (maxSample - startSample) + lead_silence_samples)) { + if (-1 == saveAudioHeaderWAV(&file, static_cast(streams.count()), save_audio_rate, (maxSample - startSample) + lead_silence_samples)) { QMessageBox::warning(this, tr("Error"), tr("Can't write header of WAV file")); return; } if (lead_silence_samples > 0) { - if (!writeAudioSilenceSamples(&file, lead_silence_samples, streams.count())) { + if (!writeAudioSilenceSamples(&file, lead_silence_samples, static_cast(streams.count()))) { QMessageBox::warning(this, tr("Warning"), tr("Save failed!")); } } diff --git a/ui/qt/rtp_player_dialog.h b/ui/qt/rtp_player_dialog.h index b7593e6262..dd6970b6f5 100644 --- a/ui/qt/rtp_player_dialog.h +++ b/ui/qt/rtp_player_dialog.h @@ -28,7 +28,11 @@ #include #ifdef QT_MULTIMEDIA_LIB -#include +# if (QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)) +# include +# else +# include +# endif #endif namespace Ui { @@ -199,6 +203,10 @@ private slots: void on_actionPrepareFilter_triggered(); void on_actionReadCapture_triggered(); +#if (QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)) + void sinkStateChanged(); +#endif + #endif private: static RtpPlayerDialog *pinstance_; @@ -222,7 +230,12 @@ private: QSharedPointer datetime_ticker_; bool stereo_available_; QList playing_streams_; +#if (QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)) + QAudioSink *marker_stream_; + QTimer notify_timer_; +#else QAudioOutput *marker_stream_; +#endif quint32 marker_stream_requested_out_rate_; QTreeWidgetItem *last_ti_; bool listener_removed_; @@ -258,8 +271,13 @@ private: void updateStartStopTime(rtpstream_info_t *rtpstream, bool is_first); void formatAudioRouting(QTreeWidgetItem *ti, AudioRouting audio_routing); bool isStereoAvailable(); +#if (QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)) + QAudioSink *getSilenceAudioOutput(); + QAudioDevice getCurrentDeviceInfo(); +#else QAudioOutput *getSilenceAudioOutput(); QAudioDeviceInfo getCurrentDeviceInfo(); +#endif QTreeWidgetItem *findItemByCoords(QPoint point); QTreeWidgetItem *findItem(QCPAbstractPlottable *plottable); void handleItemHighlight(QTreeWidgetItem *ti, bool scroll); @@ -271,8 +289,8 @@ private: void fillAudioRateMenu(); void cleanupMarkerStream(); - qint64 saveAudioHeaderAU(QFile *save_file, int channels, unsigned audio_rate); - qint64 saveAudioHeaderWAV(QFile *save_file, int channels, unsigned audio_rate, qint64 samples); + qint64 saveAudioHeaderAU(QFile *save_file, quint32 channels, unsigned audio_rate); + qint64 saveAudioHeaderWAV(QFile *save_file, quint32 channels, unsigned audio_rate, qint64 samples); bool writeAudioSilenceSamples(QFile *out_file, qint64 samples, int stream_count); bool writeAudioStreamsSamples(QFile *out_file, QVector streams, bool swap_bytes); save_audio_t selectFileAudioFormatAndName(QString *file_path);