Qt: Update the RTP stream UI to support Qt6Multimedia.

Fixes #18115
This commit is contained in:
Gerald Combs 2022-05-23 18:59:35 -07:00
parent d2b6b89b94
commit b8d85227f6
5 changed files with 242 additions and 34 deletions

View File

@ -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.

View File

@ -31,6 +31,10 @@
#include <ui/qt/utils/rtp_audio_routing_filter.h>
#include <ui/qt/utils/rtp_audio_file.h>
#if (QT_VERSION >= QT_VERSION_CHECK(6, 0, 0))
#include <QAudioDevice>
#include <QAudioSink>
#endif
#include <QAudioFormat>
#include <QAudioOutput>
#include <QVariant>
@ -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<double> 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<double, quint32>::const_iterator it = packet_timestamps_.lowerBound(timestamp);
QMap<double, quint32>::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

View File

@ -32,7 +32,11 @@
#include <QAudioOutput>
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<double> outOfSequenceTimestamps(bool relative = true);
int outOfSequence() { return out_of_seq_timestamps_.size(); }
int outOfSequence() { return static_cast<int>(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<double> jitterDroppedTimestamps(bool relative = true);
int jitterDropped() { return jitter_drop_timestamps_.size(); }
int jitterDropped() { return static_cast<int>(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<double> wrongTimestampTimestamps(bool relative = true);
int wrongTimestamps() { return wrong_timestamp_timestamps_.size(); }
int wrongTimestamps() { return static_cast<int>(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<double> insertedSilenceTimestamps(bool relative = true);
int insertedSilences() { return silence_timestamps_.size(); }
int insertedSilences() { return static_cast<int>(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<QString> payload_names_;
struct SpeexResamplerState_ *audio_resampler_;
struct SpeexResamplerState_ *visual_resampler_;
QAudioOutput *audio_output_;
QMap<double, quint32> packet_timestamps_;
QVector<qint16> visual_samples_;
QVector<double> 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:

View File

@ -39,7 +39,13 @@
#include "ui/qt/widgets/wireshark_file_dialog.h"
#include <QAudio>
#if (QT_VERSION >= QT_VERSION_CHECK(6, 0, 0))
#include <QAudioDevice>
#include <QAudioSink>
#include <QMediaDevices>
#else
#include <QAudioDeviceInfo>
#endif
#include <QFrame>
#include <QMenu>
#include <QVBoxLayout>
@ -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(&notify_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<QString, bool> 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("<i><small>" + tr("Decoding streams...") + "</i></small>");
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 = "<small><i>";
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<QTreeWidgetItem *> items = ui->streamTreeWidget->selectedItems();
block_redraw_ = true;
for(int i = items.count() - 1; i>=0; i-- ) {
for(int i = static_cast<int>(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();
QSet<int>sample_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<quint32>(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<int>(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<quint32>(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<int>(streams.count()))) {
QMessageBox::warning(this, tr("Warning"), tr("Save failed!"));
}
}

View File

@ -28,7 +28,11 @@
#include <ui/qt/widgets/qcustomplot.h>
#ifdef QT_MULTIMEDIA_LIB
#include <QAudioDeviceInfo>
# if (QT_VERSION >= QT_VERSION_CHECK(6, 0, 0))
# include <QAudioDevice>
# else
# include <QAudioDeviceInfo>
# 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<QCPAxisTickerDateTime> datetime_ticker_;
bool stereo_available_;
QList<RtpAudioStream *> 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<RtpAudioStream *> streams, bool swap_bytes);
save_audio_t selectFileAudioFormatAndName(QString *file_path);