-
-
Notifications
You must be signed in to change notification settings - Fork 2.8k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #628 from barry-ran/dev
sync
- Loading branch information
Showing
30 changed files
with
757 additions
and
257 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Submodule QtScrcpyCore
updated
108 files
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,197 @@ | ||
#include <QTcpSocket> | ||
#include <QHostAddress> | ||
#include <QAudioOutput> | ||
#include <QTime> | ||
#include <QElapsedTimer> | ||
|
||
#include "audiooutput.h" | ||
|
||
AudioOutput::AudioOutput(QObject *parent) | ||
: QObject(parent) | ||
{ | ||
connect(&m_sndcpy, &QProcess::readyReadStandardOutput, this, [this]() { | ||
qInfo() << QString("AudioOutput::") << QString(m_sndcpy.readAllStandardOutput()); | ||
}); | ||
connect(&m_sndcpy, &QProcess::readyReadStandardError, this, [this]() { | ||
qInfo() << QString("AudioOutput::") << QString(m_sndcpy.readAllStandardError()); | ||
}); | ||
} | ||
|
||
AudioOutput::~AudioOutput() | ||
{ | ||
if (QProcess::NotRunning != m_sndcpy.state()) { | ||
m_sndcpy.kill(); | ||
} | ||
stop(); | ||
} | ||
|
||
bool AudioOutput::start(const QString& serial, int port) | ||
{ | ||
if (m_running) { | ||
stop(); | ||
} | ||
|
||
QElapsedTimer timeConsumeCount; | ||
timeConsumeCount.start(); | ||
bool ret = runSndcpyProcess(serial, port); | ||
qInfo() << "AudioOutput::run sndcpy cost:" << timeConsumeCount.elapsed() << "milliseconds"; | ||
if (!ret) { | ||
return ret; | ||
} | ||
|
||
startAudioOutput(); | ||
startRecvData(port); | ||
|
||
m_running = true; | ||
return true; | ||
} | ||
|
||
void AudioOutput::stop() | ||
{ | ||
if (!m_running) { | ||
return; | ||
} | ||
m_running = false; | ||
|
||
stopRecvData(); | ||
stopAudioOutput(); | ||
} | ||
|
||
void AudioOutput::installonly(const QString &serial, int port) | ||
{ | ||
runSndcpyProcess(serial, port, false); | ||
} | ||
|
||
bool AudioOutput::runSndcpyProcess(const QString &serial, int port, bool wait) | ||
{ | ||
if (QProcess::NotRunning != m_sndcpy.state()) { | ||
m_sndcpy.kill(); | ||
} | ||
|
||
#ifdef Q_OS_WIN32 | ||
QStringList params; | ||
params << serial; | ||
params << QString("%1").arg(port); | ||
m_sndcpy.start("sndcpy.bat", params); | ||
#else | ||
QStringList params; | ||
params << "sndcpy.sh"; | ||
params << serial; | ||
params << QString("%1").arg(port); | ||
m_sndcpy.start("bash", params); | ||
#endif | ||
|
||
if (!wait) { | ||
return true; | ||
} | ||
|
||
if (!m_sndcpy.waitForStarted()) { | ||
qWarning() << "AudioOutput::start sndcpy.bat failed"; | ||
return false; | ||
} | ||
if (!m_sndcpy.waitForFinished()) { | ||
qWarning() << "AudioOutput::sndcpy.bat crashed"; | ||
return false; | ||
} | ||
|
||
return true; | ||
} | ||
|
||
void AudioOutput::startAudioOutput() | ||
{ | ||
if (m_audioOutput) { | ||
return; | ||
} | ||
|
||
QAudioFormat format; | ||
format.setSampleRate(48000); | ||
format.setChannelCount(2); | ||
format.setSampleSize(16); | ||
format.setCodec("audio/pcm"); | ||
format.setByteOrder(QAudioFormat::LittleEndian); | ||
format.setSampleType(QAudioFormat::SignedInt); | ||
|
||
QAudioDeviceInfo info(QAudioDeviceInfo::defaultOutputDevice()); | ||
if (!info.isFormatSupported(format)) { | ||
qWarning() << "AudioOutput::audio format not supported, cannot play audio."; | ||
return; | ||
} | ||
|
||
m_audioOutput = new QAudioOutput(format, this); | ||
connect(m_audioOutput, &QAudioOutput::stateChanged, this, [](QAudio::State state) { | ||
qInfo() << "AudioOutput::audio state changed:" << state; | ||
}); | ||
m_audioOutput->setBufferSize(48000*2*15/1000 * 20); | ||
m_outputDevice = m_audioOutput->start(); | ||
} | ||
|
||
void AudioOutput::stopAudioOutput() | ||
{ | ||
if (!m_audioOutput) { | ||
return; | ||
} | ||
|
||
m_audioOutput->stop(); | ||
delete m_audioOutput; | ||
m_audioOutput = nullptr; | ||
} | ||
|
||
void AudioOutput::startRecvData(int port) | ||
{ | ||
if (m_workerThread.isRunning()) { | ||
stopRecvData(); | ||
} | ||
|
||
auto audioSocket = new QTcpSocket(); | ||
audioSocket->moveToThread(&m_workerThread); | ||
connect(&m_workerThread, &QThread::finished, audioSocket, &QObject::deleteLater); | ||
|
||
connect(this, &AudioOutput::connectTo, audioSocket, [audioSocket](int port) { | ||
audioSocket->connectToHost(QHostAddress::LocalHost, port); | ||
if (!audioSocket->waitForConnected(500)) { | ||
qWarning("AudioOutput::audio socket connect failed"); | ||
return; | ||
} | ||
qInfo("AudioOutput::audio socket connect success"); | ||
}); | ||
connect(audioSocket, &QIODevice::readyRead, audioSocket, [this, audioSocket]() { | ||
qint64 recv = audioSocket->bytesAvailable(); | ||
//qDebug() << "AudioOutput::recv data:" << recv; | ||
|
||
if (!m_outputDevice) { | ||
return; | ||
} | ||
if (m_buffer.capacity() < recv) { | ||
m_buffer.reserve(recv); | ||
} | ||
|
||
qint64 count = audioSocket->read(m_buffer.data(), audioSocket->bytesAvailable()); | ||
m_outputDevice->write(m_buffer.data(), count); | ||
}); | ||
connect(audioSocket, &QTcpSocket::stateChanged, audioSocket, [](QAbstractSocket::SocketState state) { | ||
qInfo() << "AudioOutput::audio socket state changed:" << state; | ||
|
||
}); | ||
#if QT_VERSION >= QT_VERSION_CHECK(5, 15, 0) | ||
connect(audioSocket, &QTcpSocket::errorOccurred, audioSocket, [](QAbstractSocket::SocketError error) { | ||
qInfo() << "AudioOutput::audio socket error occurred:" << error; | ||
}); | ||
#else | ||
connect(audioSocket, QOverload<QAbstractSocket::SocketError>::of(&QAbstractSocket::error), audioSocket, [](QAbstractSocket::SocketError error) { | ||
qInfo() << "AudioOutput::audio socket error occurred:" << error; | ||
}); | ||
#endif | ||
|
||
m_workerThread.start(); | ||
emit connectTo(port); | ||
} | ||
|
||
void AudioOutput::stopRecvData() | ||
{ | ||
if (!m_workerThread.isRunning()) { | ||
return; | ||
} | ||
|
||
m_workerThread.quit(); | ||
m_workerThread.wait(); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,41 @@ | ||
#ifndef AUDIOOUTPUT_H | ||
#define AUDIOOUTPUT_H | ||
|
||
#include <QThread> | ||
#include <QProcess> | ||
#include <QPointer> | ||
#include <QVector> | ||
|
||
class QAudioOutput; | ||
class QIODevice; | ||
class AudioOutput : public QObject | ||
{ | ||
Q_OBJECT | ||
public: | ||
explicit AudioOutput(QObject *parent = nullptr); | ||
~AudioOutput(); | ||
|
||
bool start(const QString& serial, int port); | ||
void stop(); | ||
void installonly(const QString& serial, int port); | ||
|
||
private: | ||
bool runSndcpyProcess(const QString& serial, int port, bool wait = true); | ||
void startAudioOutput(); | ||
void stopAudioOutput(); | ||
void startRecvData(int port); | ||
void stopRecvData(); | ||
|
||
signals: | ||
void connectTo(int port); | ||
|
||
private: | ||
QAudioOutput* m_audioOutput = nullptr; | ||
QPointer<QIODevice> m_outputDevice; | ||
QThread m_workerThread; | ||
QProcess m_sndcpy; | ||
QVector<char> m_buffer; | ||
bool m_running = false; | ||
}; | ||
|
||
#endif // AUDIOOUTPUT_H |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Binary file not shown.
Oops, something went wrong.