refactor: move adbprocess to QtScrcpyCore

This commit is contained in:
Barry 2022-06-06 07:57:40 +08:00
commit 8f8e056dbb
15 changed files with 416 additions and 228 deletions

View file

@ -94,7 +94,8 @@ message(STATUS "[${PROJECT_NAME}] Qt version is: ${QT_VERSION_MAJOR}.${QT_VERSIO
# adb # adb
set(QC_ADB_SOURCES set(QC_ADB_SOURCES
QtScrcpyCore/src/adb/adbprocess.h QtScrcpyCore/src/adb/adbprocessimpl.h
QtScrcpyCore/src/adb/adbprocessimpl.cpp
QtScrcpyCore/src/adb/adbprocess.cpp QtScrcpyCore/src/adb/adbprocess.cpp
) )
source_group(QtScrcpyCore/src/adb FILES ${QC_ADB_SOURCES}) source_group(QtScrcpyCore/src/adb FILES ${QC_ADB_SOURCES})
@ -109,6 +110,7 @@ source_group(QtScrcpyCore/src/common FILES ${QC_COMMON_SOURCES})
set(QC_INCLUDE_SOURCES set(QC_INCLUDE_SOURCES
QtScrcpyCore/include/QtScrcpyCore.h QtScrcpyCore/include/QtScrcpyCore.h
QtScrcpyCore/include/QtScrcpyCoreDef.h QtScrcpyCore/include/QtScrcpyCoreDef.h
QtScrcpyCore/include/adbprocess.h
) )
source_group(QtScrcpyCore/include FILES ${QC_INCLUDE_SOURCES}) source_group(QtScrcpyCore/include FILES ${QC_INCLUDE_SOURCES})
@ -293,6 +295,7 @@ add_executable(${PROJECT_NAME} ${QC_RUNTIME_TYPE} ${QC_PROJECT_SOURCES})
# Internal include path (todo: remove this, use absolute path include) # Internal include path (todo: remove this, use absolute path include)
# #
target_include_directories(${PROJECT_NAME} PRIVATE QtScrcpyCore/include)
target_include_directories(${PROJECT_NAME} PRIVATE QtScrcpyCore/src/adb) target_include_directories(${PROJECT_NAME} PRIVATE QtScrcpyCore/src/adb)
target_include_directories(${PROJECT_NAME} PRIVATE QtScrcpyCore/src/common) target_include_directories(${PROJECT_NAME} PRIVATE QtScrcpyCore/src/common)
target_include_directories(${PROJECT_NAME} PRIVATE QtScrcpyCore/src/device) target_include_directories(${PROJECT_NAME} PRIVATE QtScrcpyCore/src/device)

View file

@ -17,6 +17,15 @@ struct DeviceParams {
bool useReverse = true; // true:先使用adb reverse失败后自动使用adb forwardfalse:直接使用adb forward bool useReverse = true; // true:先使用adb reverse失败后自动使用adb forwardfalse:直接使用adb forward
int lockVideoOrientation = -1; // 是否锁定视频方向 int lockVideoOrientation = -1; // 是否锁定视频方向
bool stayAwake = false; // 是否保持唤醒 bool stayAwake = false; // 是否保持唤醒
QString serverVersion = "1.21";// server版本
QString logLevel = "info"; // log级别 debug/info/warn/error
// 编码选项 ""表示默认
// 例如 CodecOptions="profile=1,level=2"
// 更多编码选项参考 https://d.android.com/reference/android/media/MediaFormat
QString codecOptions = "";
// 指定编码器名称(必须是H.264编码器)""表示默认
// 例如 CodecName="OMX.qcom.video.encoder.avc"
QString codecName = "";
QString recordPath = ""; // 视频保存路径 QString recordPath = ""; // 视频保存路径
QString recordFileFormat = "mp4"; // 视频保存格式 mp4/mkv QString recordFileFormat = "mp4"; // 视频保存格式 mp4/mkv

View file

@ -1,9 +1,12 @@
#ifndef ADBPROCESS_H #ifndef ADBPROCESS_H
#define ADBPROCESS_H #define ADBPROCESS_H
#include <QProcess> #include <QObject>
class AdbProcess : public QProcess class AdbProcessImpl;
namespace qsc {
class AdbProcess : public QObject
{ {
Q_OBJECT Q_OBJECT
@ -20,6 +23,8 @@ public:
explicit AdbProcess(QObject *parent = nullptr); explicit AdbProcess(QObject *parent = nullptr);
virtual ~AdbProcess(); virtual ~AdbProcess();
static void setAdbPath(const QString& adbPath);
void execute(const QString &serial, const QStringList &args); void execute(const QString &serial, const QStringList &args);
void forward(const QString &serial, quint16 localPort, const QString &deviceSocketName); void forward(const QString &serial, quint16 localPort, const QString &deviceSocketName);
void forwardRemove(const QString &serial, quint16 localPort); void forwardRemove(const QString &serial, quint16 localPort);
@ -30,24 +35,20 @@ public:
void removePath(const QString &serial, const QString &path); void removePath(const QString &serial, const QString &path);
bool isRuning(); bool isRuning();
void setShowTouchesEnabled(const QString &serial, bool enabled); void setShowTouchesEnabled(const QString &serial, bool enabled);
void kill();
QStringList arguments();
QStringList getDevicesSerialFromStdOut(); QStringList getDevicesSerialFromStdOut();
QString getDeviceIPFromStdOut(); QString getDeviceIPFromStdOut();
QString getDeviceIPByIpFromStdOut(); QString getDeviceIPByIpFromStdOut();
QString getStdOut(); QString getStdOut();
QString getErrorOut(); QString getErrorOut();
static const QString &getAdbPath();
signals: signals:
void adbProcessResult(ADB_EXEC_RESULT processResult); void adbProcessResult(ADB_EXEC_RESULT processResult);
private: private:
void initSignals(); AdbProcessImpl* m_adbImpl = nullptr;
private:
QString m_standardOutput = "";
QString m_errorOutput = "";
static QString s_adbPath;
}; };
}
#endif // ADBPROCESS_H #endif // ADBPROCESS_H

View file

@ -1,3 +0,0 @@
HEADERS += \
$$PWD/QtScrcpyCore.h \
$$PWD/QtScrcpyCoreDef.h

View file

@ -5,240 +5,112 @@
#include <QProcess> #include <QProcess>
#include "adbprocess.h" #include "adbprocess.h"
#include "config.h" #include "adbprocessimpl.h"
QString AdbProcess::s_adbPath = ""; QString g_adbPath;
AdbProcess::AdbProcess(QObject *parent) : QProcess(parent) namespace qsc {
AdbProcess::AdbProcess(QObject *parent)
: QObject(parent)
, m_adbImpl(new AdbProcessImpl())
{ {
initSignals(); connect(m_adbImpl, &AdbProcessImpl::adbProcessImplResult, this, &qsc::AdbProcess::adbProcessResult);
} }
AdbProcess::~AdbProcess() AdbProcess::~AdbProcess()
{ {
if (isRuning()) { delete m_adbImpl;
close();
}
} }
const QString &AdbProcess::getAdbPath() void AdbProcess::setAdbPath(const QString &adbPath)
{ {
if (s_adbPath.isEmpty()) { g_adbPath = adbPath;
s_adbPath = QString::fromLocal8Bit(qgetenv("QTSCRCPY_ADB_PATH"));
QFileInfo fileInfo(s_adbPath);
if (s_adbPath.isEmpty() || !fileInfo.isFile()) {
s_adbPath = Config::getInstance().getAdbPath();
}
fileInfo = s_adbPath;
if (s_adbPath.isEmpty() || !fileInfo.isFile()) {
s_adbPath = QCoreApplication::applicationDirPath() + "/adb";
}
qInfo("adb path: %s", QDir(s_adbPath).absolutePath().toUtf8().data());
}
return s_adbPath;
}
void AdbProcess::initSignals()
{
// aboutToQuit not exit event loop, so deletelater is ok
//connect(QCoreApplication::instance(), &QCoreApplication::aboutToQuit, this, &AdbProcess::deleteLater);
connect(this, static_cast<void (QProcess::*)(int, QProcess::ExitStatus)>(&QProcess::finished), this, [this](int exitCode, QProcess::ExitStatus exitStatus) {
if (NormalExit == exitStatus && 0 == exitCode) {
emit adbProcessResult(AER_SUCCESS_EXEC);
} else {
//P7C0218510000537 unauthorized ,手机端此时弹出调试认证,要允许调试
emit adbProcessResult(AER_ERROR_EXEC);
}
qDebug() << "adb return " << exitCode << "exit status " << exitStatus;
});
connect(this, &QProcess::errorOccurred, this, [this](QProcess::ProcessError error) {
if (QProcess::FailedToStart == error) {
emit adbProcessResult(AER_ERROR_MISSING_BINARY);
} else {
emit adbProcessResult(AER_ERROR_START);
QString err = QString("qprocess start error:%1 %2").arg(program()).arg(arguments().join(" "));
qCritical() << err.toStdString().c_str();
}
});
connect(this, &QProcess::readyReadStandardError, this, [this]() {
QString tmp = QString::fromUtf8(readAllStandardError()).trimmed();
m_errorOutput += tmp;
qWarning() << QString("AdbProcess::error:%1").arg(tmp).toStdString().data();
});
connect(this, &QProcess::readyReadStandardOutput, this, [this]() {
QString tmp = QString::fromUtf8(readAllStandardOutput()).trimmed();
m_standardOutput += tmp;
qInfo() << QString("AdbProcess::out:%1").arg(tmp).toStdString().data();
});
connect(this, &QProcess::started, this, [this]() { emit adbProcessResult(AER_SUCCESS_START); });
} }
void AdbProcess::execute(const QString &serial, const QStringList &args) void AdbProcess::execute(const QString &serial, const QStringList &args)
{ {
m_standardOutput = ""; m_adbImpl->execute(serial, args);
m_errorOutput = "";
QStringList adbArgs;
if (!serial.isEmpty()) {
adbArgs << "-s" << serial;
}
adbArgs << args;
qDebug() << getAdbPath() << adbArgs.join(" ");
start(getAdbPath(), adbArgs);
} }
bool AdbProcess::isRuning() bool AdbProcess::isRuning()
{ {
if (QProcess::NotRunning == state()) { return m_adbImpl->isRuning();
return false;
} else {
return true;
}
} }
void AdbProcess::setShowTouchesEnabled(const QString &serial, bool enabled) void AdbProcess::setShowTouchesEnabled(const QString &serial, bool enabled)
{ {
QStringList adbArgs; m_adbImpl->setShowTouchesEnabled(serial, enabled);
adbArgs << "shell" }
<< "settings"
<< "put" void AdbProcess::kill()
<< "system" {
<< "show_touches"; m_adbImpl->kill();
adbArgs << (enabled ? "1" : "0"); }
execute(serial, adbArgs);
QStringList AdbProcess::arguments()
{
return m_adbImpl->arguments();
} }
QStringList AdbProcess::getDevicesSerialFromStdOut() QStringList AdbProcess::getDevicesSerialFromStdOut()
{ {
// get devices serial by adb devices return m_adbImpl->getDevicesSerialFromStdOut();
QStringList serials;
#if QT_VERSION >= QT_VERSION_CHECK(5, 15, 0)
QStringList devicesInfoList = m_standardOutput.split(QRegExp("\r\n|\n"), Qt::SkipEmptyParts);
#else
QStringList devicesInfoList = m_standardOutput.split(QRegExp("\r\n|\n"), QString::SkipEmptyParts);
#endif
for (QString deviceInfo : devicesInfoList) {
#if QT_VERSION >= QT_VERSION_CHECK(5, 15, 0)
QStringList deviceInfos = deviceInfo.split(QRegExp("\t"), Qt::SkipEmptyParts);
#else
QStringList deviceInfos = deviceInfo.split(QRegExp("\t"), QString::SkipEmptyParts);
#endif
if (2 == deviceInfos.count() && 0 == deviceInfos[1].compare("device")) {
serials << deviceInfos[0];
}
}
return serials;
} }
QString AdbProcess::getDeviceIPFromStdOut() QString AdbProcess::getDeviceIPFromStdOut()
{ {
QString ip = ""; return m_adbImpl->getDeviceIPFromStdOut();
#if 0
QString strIPExp = "inet [\\d.]*";
QRegExp ipRegExp(strIPExp, Qt::CaseInsensitive);
if (ipRegExp.indexIn(m_standardOutput) != -1) {
ip = ipRegExp.cap(0);
ip = ip.right(ip.size() - 5);
}
#else
QString strIPExp = "inet addr:[\\d.]*";
QRegExp ipRegExp(strIPExp, Qt::CaseInsensitive);
if (ipRegExp.indexIn(m_standardOutput) != -1) {
ip = ipRegExp.cap(0);
ip = ip.right(ip.size() - 10);
}
#endif
return ip;
} }
QString AdbProcess::getDeviceIPByIpFromStdOut() QString AdbProcess::getDeviceIPByIpFromStdOut()
{ {
QString ip = ""; return m_adbImpl->getDeviceIPByIpFromStdOut();
QString strIPExp = "wlan0 inet [\\d.]*";
QRegExp ipRegExp(strIPExp, Qt::CaseInsensitive);
if (ipRegExp.indexIn(m_standardOutput) != -1) {
ip = ipRegExp.cap(0);
ip = ip.right(ip.size() - 14);
}
qDebug() << "get ip: " << ip;
return ip;
} }
QString AdbProcess::getStdOut() QString AdbProcess::getStdOut()
{ {
return m_standardOutput; return m_adbImpl->getStdOut();
} }
QString AdbProcess::getErrorOut() QString AdbProcess::getErrorOut()
{ {
return m_errorOutput; return m_adbImpl->getErrorOut();
} }
void AdbProcess::forward(const QString &serial, quint16 localPort, const QString &deviceSocketName) void AdbProcess::forward(const QString &serial, quint16 localPort, const QString &deviceSocketName)
{ {
QStringList adbArgs; m_adbImpl->forward(serial, localPort, deviceSocketName);
adbArgs << "forward";
adbArgs << QString("tcp:%1").arg(localPort);
adbArgs << QString("localabstract:%1").arg(deviceSocketName);
execute(serial, adbArgs);
} }
void AdbProcess::forwardRemove(const QString &serial, quint16 localPort) void AdbProcess::forwardRemove(const QString &serial, quint16 localPort)
{ {
QStringList adbArgs; m_adbImpl->forwardRemove(serial, localPort);
adbArgs << "forward";
adbArgs << "--remove";
adbArgs << QString("tcp:%1").arg(localPort);
execute(serial, adbArgs);
} }
void AdbProcess::reverse(const QString &serial, const QString &deviceSocketName, quint16 localPort) void AdbProcess::reverse(const QString &serial, const QString &deviceSocketName, quint16 localPort)
{ {
QStringList adbArgs; m_adbImpl->reverse(serial, deviceSocketName, localPort);
adbArgs << "reverse";
adbArgs << QString("localabstract:%1").arg(deviceSocketName);
adbArgs << QString("tcp:%1").arg(localPort);
execute(serial, adbArgs);
} }
void AdbProcess::reverseRemove(const QString &serial, const QString &deviceSocketName) void AdbProcess::reverseRemove(const QString &serial, const QString &deviceSocketName)
{ {
QStringList adbArgs; m_adbImpl->reverseRemove(serial, deviceSocketName);
adbArgs << "reverse";
adbArgs << "--remove";
adbArgs << QString("localabstract:%1").arg(deviceSocketName);
execute(serial, adbArgs);
} }
void AdbProcess::push(const QString &serial, const QString &local, const QString &remote) void AdbProcess::push(const QString &serial, const QString &local, const QString &remote)
{ {
QStringList adbArgs; m_adbImpl->push(serial, local, remote);
adbArgs << "push";
adbArgs << local;
adbArgs << remote;
execute(serial, adbArgs);
} }
void AdbProcess::install(const QString &serial, const QString &local) void AdbProcess::install(const QString &serial, const QString &local)
{ {
QStringList adbArgs; m_adbImpl->install(serial, local);
adbArgs << "install";
adbArgs << "-r";
adbArgs << local;
execute(serial, adbArgs);
} }
void AdbProcess::removePath(const QString &serial, const QString &path) void AdbProcess::removePath(const QString &serial, const QString &path)
{ {
QStringList adbArgs; m_adbImpl->removePath(serial, path);
adbArgs << "shell"; }
adbArgs << "rm";
adbArgs << path;
execute(serial, adbArgs);
} }

View file

@ -0,0 +1,244 @@
#include <QCoreApplication>
#include <QDebug>
#include <QDir>
#include <QFileInfo>
#include <QProcess>
#include "adbprocessimpl.h"
QString AdbProcessImpl::s_adbPath = "";
extern QString g_adbPath;
AdbProcessImpl::AdbProcessImpl(QObject *parent) : QProcess(parent)
{
initSignals();
}
AdbProcessImpl::~AdbProcessImpl()
{
if (isRuning()) {
close();
}
}
const QString &AdbProcessImpl::getAdbPath()
{
if (s_adbPath.isEmpty()) {
s_adbPath = QString::fromLocal8Bit(qgetenv("QTSCRCPY_ADB_PATH"));
QFileInfo fileInfo(s_adbPath);
if (s_adbPath.isEmpty() || !fileInfo.isFile()) {
s_adbPath = g_adbPath;
}
fileInfo = s_adbPath;
if (s_adbPath.isEmpty() || !fileInfo.isFile()) {
s_adbPath = QCoreApplication::applicationDirPath() + "/adb";
}
qInfo("adb path: %s", QDir(s_adbPath).absolutePath().toUtf8().data());
}
return s_adbPath;
}
void AdbProcessImpl::initSignals()
{
// aboutToQuit not exit event loop, so deletelater is ok
//connect(QCoreApplication::instance(), &QCoreApplication::aboutToQuit, this, &AdbProcessImpl::deleteLater);
connect(this, static_cast<void (QProcess::*)(int, QProcess::ExitStatus)>(&QProcess::finished), this, [this](int exitCode, QProcess::ExitStatus exitStatus) {
if (NormalExit == exitStatus && 0 == exitCode) {
emit adbProcessImplResult(qsc::AdbProcess::AER_SUCCESS_EXEC);
} else {
//P7C0218510000537 unauthorized ,手机端此时弹出调试认证,要允许调试
emit adbProcessImplResult(qsc::AdbProcess::AER_ERROR_EXEC);
}
qDebug() << "adb return " << exitCode << "exit status " << exitStatus;
});
connect(this, &QProcess::errorOccurred, this, [this](QProcess::ProcessError error) {
if (QProcess::FailedToStart == error) {
emit adbProcessImplResult(qsc::AdbProcess::AER_ERROR_MISSING_BINARY);
} else {
emit adbProcessImplResult(qsc::AdbProcess::AER_ERROR_START);
QString err = QString("qprocess start error:%1 %2").arg(program()).arg(arguments().join(" "));
qCritical() << err.toStdString().c_str();
}
});
connect(this, &QProcess::readyReadStandardError, this, [this]() {
QString tmp = QString::fromUtf8(readAllStandardError()).trimmed();
m_errorOutput += tmp;
qWarning() << QString("AdbProcessImpl::error:%1").arg(tmp).toStdString().data();
});
connect(this, &QProcess::readyReadStandardOutput, this, [this]() {
QString tmp = QString::fromUtf8(readAllStandardOutput()).trimmed();
m_standardOutput += tmp;
qInfo() << QString("AdbProcessImpl::out:%1").arg(tmp).toStdString().data();
});
connect(this, &QProcess::started, this, [this]() { emit adbProcessImplResult(qsc::AdbProcess::AER_SUCCESS_START); });
}
void AdbProcessImpl::execute(const QString &serial, const QStringList &args)
{
m_standardOutput = "";
m_errorOutput = "";
QStringList adbArgs;
if (!serial.isEmpty()) {
adbArgs << "-s" << serial;
}
adbArgs << args;
qDebug() << getAdbPath() << adbArgs.join(" ");
start(getAdbPath(), adbArgs);
}
bool AdbProcessImpl::isRuning()
{
if (QProcess::NotRunning == state()) {
return false;
} else {
return true;
}
}
void AdbProcessImpl::setShowTouchesEnabled(const QString &serial, bool enabled)
{
QStringList adbArgs;
adbArgs << "shell"
<< "settings"
<< "put"
<< "system"
<< "show_touches";
adbArgs << (enabled ? "1" : "0");
execute(serial, adbArgs);
}
QStringList AdbProcessImpl::getDevicesSerialFromStdOut()
{
// get devices serial by adb devices
QStringList serials;
#if QT_VERSION >= QT_VERSION_CHECK(5, 15, 0)
QStringList devicesInfoList = m_standardOutput.split(QRegExp("\r\n|\n"), Qt::SkipEmptyParts);
#else
QStringList devicesInfoList = m_standardOutput.split(QRegExp("\r\n|\n"), QString::SkipEmptyParts);
#endif
for (QString deviceInfo : devicesInfoList) {
#if QT_VERSION >= QT_VERSION_CHECK(5, 15, 0)
QStringList deviceInfos = deviceInfo.split(QRegExp("\t"), Qt::SkipEmptyParts);
#else
QStringList deviceInfos = deviceInfo.split(QRegExp("\t"), QString::SkipEmptyParts);
#endif
if (2 == deviceInfos.count() && 0 == deviceInfos[1].compare("device")) {
serials << deviceInfos[0];
}
}
return serials;
}
QString AdbProcessImpl::getDeviceIPFromStdOut()
{
QString ip = "";
#if 0
QString strIPExp = "inet [\\d.]*";
QRegExp ipRegExp(strIPExp, Qt::CaseInsensitive);
if (ipRegExp.indexIn(m_standardOutput) != -1) {
ip = ipRegExp.cap(0);
ip = ip.right(ip.size() - 5);
}
#else
QString strIPExp = "inet addr:[\\d.]*";
QRegExp ipRegExp(strIPExp, Qt::CaseInsensitive);
if (ipRegExp.indexIn(m_standardOutput) != -1) {
ip = ipRegExp.cap(0);
ip = ip.right(ip.size() - 10);
}
#endif
return ip;
}
QString AdbProcessImpl::getDeviceIPByIpFromStdOut()
{
QString ip = "";
QString strIPExp = "wlan0 inet [\\d.]*";
QRegExp ipRegExp(strIPExp, Qt::CaseInsensitive);
if (ipRegExp.indexIn(m_standardOutput) != -1) {
ip = ipRegExp.cap(0);
ip = ip.right(ip.size() - 14);
}
qDebug() << "get ip: " << ip;
return ip;
}
QString AdbProcessImpl::getStdOut()
{
return m_standardOutput;
}
QString AdbProcessImpl::getErrorOut()
{
return m_errorOutput;
}
void AdbProcessImpl::forward(const QString &serial, quint16 localPort, const QString &deviceSocketName)
{
QStringList adbArgs;
adbArgs << "forward";
adbArgs << QString("tcp:%1").arg(localPort);
adbArgs << QString("localabstract:%1").arg(deviceSocketName);
execute(serial, adbArgs);
}
void AdbProcessImpl::forwardRemove(const QString &serial, quint16 localPort)
{
QStringList adbArgs;
adbArgs << "forward";
adbArgs << "--remove";
adbArgs << QString("tcp:%1").arg(localPort);
execute(serial, adbArgs);
}
void AdbProcessImpl::reverse(const QString &serial, const QString &deviceSocketName, quint16 localPort)
{
QStringList adbArgs;
adbArgs << "reverse";
adbArgs << QString("localabstract:%1").arg(deviceSocketName);
adbArgs << QString("tcp:%1").arg(localPort);
execute(serial, adbArgs);
}
void AdbProcessImpl::reverseRemove(const QString &serial, const QString &deviceSocketName)
{
QStringList adbArgs;
adbArgs << "reverse";
adbArgs << "--remove";
adbArgs << QString("localabstract:%1").arg(deviceSocketName);
execute(serial, adbArgs);
}
void AdbProcessImpl::push(const QString &serial, const QString &local, const QString &remote)
{
QStringList adbArgs;
adbArgs << "push";
adbArgs << local;
adbArgs << remote;
execute(serial, adbArgs);
}
void AdbProcessImpl::install(const QString &serial, const QString &local)
{
QStringList adbArgs;
adbArgs << "install";
adbArgs << "-r";
adbArgs << local;
execute(serial, adbArgs);
}
void AdbProcessImpl::removePath(const QString &serial, const QString &path)
{
QStringList adbArgs;
adbArgs << "shell";
adbArgs << "rm";
adbArgs << path;
execute(serial, adbArgs);
}

View file

@ -0,0 +1,42 @@
#pragma once
#include <QProcess>
#include "adbprocess.h"
class AdbProcessImpl : public QProcess
{
Q_OBJECT
public:
explicit AdbProcessImpl(QObject *parent = nullptr);
virtual ~AdbProcessImpl();
void execute(const QString &serial, const QStringList &args);
void forward(const QString &serial, quint16 localPort, const QString &deviceSocketName);
void forwardRemove(const QString &serial, quint16 localPort);
void reverse(const QString &serial, const QString &deviceSocketName, quint16 localPort);
void reverseRemove(const QString &serial, const QString &deviceSocketName);
void push(const QString &serial, const QString &local, const QString &remote);
void install(const QString &serial, const QString &local);
void removePath(const QString &serial, const QString &path);
bool isRuning();
void setShowTouchesEnabled(const QString &serial, bool enabled);
QStringList getDevicesSerialFromStdOut();
QString getDeviceIPFromStdOut();
QString getDeviceIPByIpFromStdOut();
QString getStdOut();
QString getErrorOut();
static const QString &getAdbPath();
signals:
void adbProcessImplResult(qsc::AdbProcess::ADB_EXEC_RESULT processResult);
private:
void initSignals();
private:
QString m_standardOutput = "";
QString m_errorOutput = "";
static QString s_adbPath;
};

View file

@ -113,11 +113,11 @@ void Device::screenshot()
void Device::showTouch(bool show) void Device::showTouch(bool show)
{ {
AdbProcess *adb = new AdbProcess(); AdbProcess *adb = new qsc::AdbProcess();
if (!adb) { if (!adb) {
return; return;
} }
connect(adb, &AdbProcess::adbProcessResult, this, [this](AdbProcess::ADB_EXEC_RESULT processResult) { connect(adb, &qsc::AdbProcess::adbProcessResult, this, [this](qsc::AdbProcess::ADB_EXEC_RESULT processResult) {
if (AdbProcess::AER_SUCCESS_START != processResult) { if (AdbProcess::AER_SUCCESS_START != processResult) {
sender()->deleteLater(); sender()->deleteLater();
} }
@ -282,6 +282,11 @@ bool Device::connectDevice()
params.useReverse = m_params.useReverse; params.useReverse = m_params.useReverse;
params.lockVideoOrientation = m_params.lockVideoOrientation; params.lockVideoOrientation = m_params.lockVideoOrientation;
params.stayAwake = m_params.stayAwake; params.stayAwake = m_params.stayAwake;
params.serverVersion = m_params.serverVersion;
params.logLevel = m_params.logLevel;
params.codecOptions = m_params.codecOptions;
params.codecName = m_params.codecName;
params.crop = ""; params.crop = "";
params.control = true; params.control = true;
m_server->start(params); m_server->start(params);

View file

@ -8,9 +8,9 @@ FileHandler::~FileHandler() {}
void FileHandler::onPushFileRequest(const QString &serial, const QString &file, const QString &devicePath) void FileHandler::onPushFileRequest(const QString &serial, const QString &file, const QString &devicePath)
{ {
AdbProcess* adb = new AdbProcess; qsc::AdbProcess* adb = new qsc::AdbProcess;
bool isApk = false; bool isApk = false;
connect(adb, &AdbProcess::adbProcessResult, this, [this, adb, isApk](AdbProcess::ADB_EXEC_RESULT processResult) { connect(adb, &qsc::AdbProcess::adbProcessResult, this, [this, adb, isApk](qsc::AdbProcess::ADB_EXEC_RESULT processResult) {
onAdbProcessResult(adb, isApk, processResult); onAdbProcessResult(adb, isApk, processResult);
}); });
@ -19,25 +19,25 @@ void FileHandler::onPushFileRequest(const QString &serial, const QString &file,
void FileHandler::onInstallApkRequest(const QString &serial, const QString &apkFile) void FileHandler::onInstallApkRequest(const QString &serial, const QString &apkFile)
{ {
AdbProcess* adb = new AdbProcess; qsc::AdbProcess* adb = new qsc::AdbProcess;
bool isApk = true; bool isApk = true;
connect(adb, &AdbProcess::adbProcessResult, this, [this, adb, isApk](AdbProcess::ADB_EXEC_RESULT processResult) { connect(adb, &qsc::AdbProcess::adbProcessResult, this, [this, adb, isApk](qsc::AdbProcess::ADB_EXEC_RESULT processResult) {
onAdbProcessResult(adb, isApk, processResult); onAdbProcessResult(adb, isApk, processResult);
}); });
adb->install(serial, apkFile); adb->install(serial, apkFile);
} }
void FileHandler::onAdbProcessResult(AdbProcess *adb, bool isApk, AdbProcess::ADB_EXEC_RESULT processResult) void FileHandler::onAdbProcessResult(qsc::AdbProcess *adb, bool isApk, qsc::AdbProcess::ADB_EXEC_RESULT processResult)
{ {
switch (processResult) { switch (processResult) {
case AdbProcess::AER_ERROR_START: case qsc::AdbProcess::AER_ERROR_START:
case AdbProcess::AER_ERROR_EXEC: case qsc::AdbProcess::AER_ERROR_EXEC:
case AdbProcess::AER_ERROR_MISSING_BINARY: case qsc::AdbProcess::AER_ERROR_MISSING_BINARY:
emit fileHandlerResult(FAR_ERROR_EXEC, isApk); emit fileHandlerResult(FAR_ERROR_EXEC, isApk);
adb->deleteLater(); adb->deleteLater();
break; break;
case AdbProcess::AER_SUCCESS_EXEC: case qsc::AdbProcess::AER_SUCCESS_EXEC:
emit fileHandlerResult(FAR_SUCCESS_EXEC, isApk); emit fileHandlerResult(FAR_SUCCESS_EXEC, isApk);
adb->deleteLater(); adb->deleteLater();
break; break;

View file

@ -25,7 +25,7 @@ public slots:
void onInstallApkRequest(const QString &serial, const QString &apkFile); void onInstallApkRequest(const QString &serial, const QString &apkFile);
protected: protected:
void onAdbProcessResult(AdbProcess* adb, bool isApk, AdbProcess::ADB_EXEC_RESULT processResult); void onAdbProcessResult(qsc::AdbProcess* adb, bool isApk, qsc::AdbProcess::ADB_EXEC_RESULT processResult);
signals: signals:
void fileHandlerResult(FILE_HANDLER_RESULT processResult, bool isApk = false); void fileHandlerResult(FILE_HANDLER_RESULT processResult, bool isApk = false);

View file

@ -5,7 +5,6 @@
#include <QTimer> #include <QTimer>
#include <QTimerEvent> #include <QTimerEvent>
#include "config.h"
#include "server.h" #include "server.h"
#define DEVICE_NAME_FIELD_LENGTH 64 #define DEVICE_NAME_FIELD_LENGTH 64
@ -15,8 +14,8 @@
Server::Server(QObject *parent) : QObject(parent) Server::Server(QObject *parent) : QObject(parent)
{ {
connect(&m_workProcess, &AdbProcess::adbProcessResult, this, &Server::onWorkProcessResult); connect(&m_workProcess, &qsc::AdbProcess::adbProcessResult, this, &Server::onWorkProcessResult);
connect(&m_serverProcess, &AdbProcess::adbProcessResult, this, &Server::onWorkProcessResult); connect(&m_serverProcess, &qsc::AdbProcess::adbProcessResult, this, &Server::onWorkProcessResult);
connect(&m_serverSocket, &QTcpServer::newConnection, this, [this]() { connect(&m_serverSocket, &QTcpServer::newConnection, this, [this]() {
QTcpSocket *tmp = m_serverSocket.nextPendingConnection(); QTcpSocket *tmp = m_serverSocket.nextPendingConnection();
@ -67,12 +66,12 @@ bool Server::enableTunnelReverse()
bool Server::disableTunnelReverse() bool Server::disableTunnelReverse()
{ {
AdbProcess *adb = new AdbProcess(); qsc::AdbProcess *adb = new qsc::AdbProcess();
if (!adb) { if (!adb) {
return false; return false;
} }
connect(adb, &AdbProcess::adbProcessResult, this, [this](AdbProcess::ADB_EXEC_RESULT processResult) { connect(adb, &qsc::AdbProcess::adbProcessResult, this, [this](qsc::AdbProcess::ADB_EXEC_RESULT processResult) {
if (AdbProcess::AER_SUCCESS_START != processResult) { if (qsc::AdbProcess::AER_SUCCESS_START != processResult) {
sender()->deleteLater(); sender()->deleteLater();
} }
}); });
@ -90,12 +89,12 @@ bool Server::enableTunnelForward()
} }
bool Server::disableTunnelForward() bool Server::disableTunnelForward()
{ {
AdbProcess *adb = new AdbProcess(); qsc::AdbProcess *adb = new qsc::AdbProcess();
if (!adb) { if (!adb) {
return false; return false;
} }
connect(adb, &AdbProcess::adbProcessResult, this, [this](AdbProcess::ADB_EXEC_RESULT processResult) { connect(adb, &qsc::AdbProcess::adbProcessResult, this, [this](qsc::AdbProcess::ADB_EXEC_RESULT processResult) {
if (AdbProcess::AER_SUCCESS_START != processResult) { if (qsc::AdbProcess::AER_SUCCESS_START != processResult) {
sender()->deleteLater(); sender()->deleteLater();
} }
}); });
@ -110,7 +109,7 @@ bool Server::execute()
} }
QStringList args; QStringList args;
args << "shell"; args << "shell";
args << QString("CLASSPATH=%1").arg(Config::getInstance().getServerPath()); args << QString("CLASSPATH=%1").arg(m_params.serverRemotePath);
args << "app_process"; args << "app_process";
#ifdef SERVER_DEBUGGER #ifdef SERVER_DEBUGGER
@ -129,10 +128,10 @@ bool Server::execute()
args << "/"; // unused; args << "/"; // unused;
args << "com.genymobile.scrcpy.Server"; args << "com.genymobile.scrcpy.Server";
args << Config::getInstance().getServerVersion(); args << m_params.serverVersion;
if (!Config::getInstance().getLogLevel().isEmpty()) { if (!m_params.logLevel.isEmpty()) {
args << QString("log_level=%1").arg(Config::getInstance().getLogLevel()); args << QString("log_level=%1").arg(m_params.logLevel);
} }
args << QString("max_size=%1").arg(QString::number(m_params.maxSize)); args << QString("max_size=%1").arg(QString::number(m_params.maxSize));
args << QString("bit_rate=%1").arg(QString::number(m_params.bitRate)); args << QString("bit_rate=%1").arg(QString::number(m_params.bitRate));
@ -149,11 +148,11 @@ bool Server::execute()
// code option // code option
// https://github.com/Genymobile/scrcpy/commit/080a4ee3654a9b7e96c8ffe37474b5c21c02852a // https://github.com/Genymobile/scrcpy/commit/080a4ee3654a9b7e96c8ffe37474b5c21c02852a
// <https://d.android.com/reference/android/media/MediaFormat> // <https://d.android.com/reference/android/media/MediaFormat>
if (Config::getInstance().getCodecOptions() != "") { if (!m_params.codecOptions.isEmpty()) {
args << QString("codec_options=%1").arg(Config::getInstance().getCodecOptions()); args << QString("codec_options=%1").arg(m_params.codecOptions);
} }
if (Config::getInstance().getCodecName() != "") { if (!m_params.codecName.isEmpty()) {
args << QString("encoder_name=%1").arg(Config::getInstance().getCodecName()); args << QString("encoder_name=%1").arg(m_params.codecName);
} }
#ifdef SERVER_DEBUGGER #ifdef SERVER_DEBUGGER
@ -417,13 +416,13 @@ result:
} }
} }
void Server::onWorkProcessResult(AdbProcess::ADB_EXEC_RESULT processResult) void Server::onWorkProcessResult(qsc::AdbProcess::ADB_EXEC_RESULT processResult)
{ {
if (sender() == &m_workProcess) { if (sender() == &m_workProcess) {
if (SSS_NULL != m_serverStartStep) { if (SSS_NULL != m_serverStartStep) {
switch (m_serverStartStep) { switch (m_serverStartStep) {
case SSS_PUSH: case SSS_PUSH:
if (AdbProcess::AER_SUCCESS_EXEC == processResult) { if (qsc::AdbProcess::AER_SUCCESS_EXEC == processResult) {
if (m_params.useReverse) { if (m_params.useReverse) {
m_serverStartStep = SSS_ENABLE_TUNNEL_REVERSE; m_serverStartStep = SSS_ENABLE_TUNNEL_REVERSE;
} else { } else {
@ -431,14 +430,14 @@ void Server::onWorkProcessResult(AdbProcess::ADB_EXEC_RESULT processResult)
m_serverStartStep = SSS_ENABLE_TUNNEL_FORWARD; m_serverStartStep = SSS_ENABLE_TUNNEL_FORWARD;
} }
startServerByStep(); startServerByStep();
} else if (AdbProcess::AER_SUCCESS_START != processResult) { } else if (qsc::AdbProcess::AER_SUCCESS_START != processResult) {
qCritical("adb push failed"); qCritical("adb push failed");
m_serverStartStep = SSS_NULL; m_serverStartStep = SSS_NULL;
emit serverStarted(false); emit serverStarted(false);
} }
break; break;
case SSS_ENABLE_TUNNEL_REVERSE: case SSS_ENABLE_TUNNEL_REVERSE:
if (AdbProcess::AER_SUCCESS_EXEC == processResult) { if (qsc::AdbProcess::AER_SUCCESS_EXEC == processResult) {
// At the application level, the device part is "the server" because it // At the application level, the device part is "the server" because it
// serves video stream and control. However, at the network level, the // serves video stream and control. However, at the network level, the
// client listens and the server connects to the client. That way, the // client listens and the server connects to the client. That way, the
@ -455,7 +454,7 @@ void Server::onWorkProcessResult(AdbProcess::ADB_EXEC_RESULT processResult)
m_serverStartStep = SSS_EXECUTE_SERVER; m_serverStartStep = SSS_EXECUTE_SERVER;
startServerByStep(); startServerByStep();
} else if (AdbProcess::AER_SUCCESS_START != processResult) { } else if (qsc::AdbProcess::AER_SUCCESS_START != processResult) {
// 有一些设备reverse会报错more than o'ne deviceadb的bug // 有一些设备reverse会报错more than o'ne deviceadb的bug
// https://github.com/Genymobile/scrcpy/issues/5 // https://github.com/Genymobile/scrcpy/issues/5
qCritical("adb reverse failed"); qCritical("adb reverse failed");
@ -465,10 +464,10 @@ void Server::onWorkProcessResult(AdbProcess::ADB_EXEC_RESULT processResult)
} }
break; break;
case SSS_ENABLE_TUNNEL_FORWARD: case SSS_ENABLE_TUNNEL_FORWARD:
if (AdbProcess::AER_SUCCESS_EXEC == processResult) { if (qsc::AdbProcess::AER_SUCCESS_EXEC == processResult) {
m_serverStartStep = SSS_EXECUTE_SERVER; m_serverStartStep = SSS_EXECUTE_SERVER;
startServerByStep(); startServerByStep();
} else if (AdbProcess::AER_SUCCESS_START != processResult) { } else if (qsc::AdbProcess::AER_SUCCESS_START != processResult) {
qCritical("adb forward failed"); qCritical("adb forward failed");
m_serverStartStep = SSS_NULL; m_serverStartStep = SSS_NULL;
emit serverStarted(false); emit serverStarted(false);
@ -481,11 +480,11 @@ void Server::onWorkProcessResult(AdbProcess::ADB_EXEC_RESULT processResult)
} }
if (sender() == &m_serverProcess) { if (sender() == &m_serverProcess) {
if (SSS_EXECUTE_SERVER == m_serverStartStep) { if (SSS_EXECUTE_SERVER == m_serverStartStep) {
if (AdbProcess::AER_SUCCESS_START == processResult) { if (qsc::AdbProcess::AER_SUCCESS_START == processResult) {
m_serverStartStep = SSS_RUNNING; m_serverStartStep = SSS_RUNNING;
m_tunnelEnabled = true; m_tunnelEnabled = true;
connectTo(); connectTo();
} else if (AdbProcess::AER_ERROR_START == processResult) { } else if (qsc::AdbProcess::AER_ERROR_START == processResult) {
if (!m_tunnelForward) { if (!m_tunnelForward) {
m_serverSocket.close(); m_serverSocket.close();
disableTunnelReverse(); disableTunnelReverse();

View file

@ -39,6 +39,16 @@ public:
bool useReverse = true; // true:先使用adb reverse失败后自动使用adb forwardfalse:直接使用adb forward bool useReverse = true; // true:先使用adb reverse失败后自动使用adb forwardfalse:直接使用adb forward
int lockVideoOrientation = -1; // 是否锁定视频方向 int lockVideoOrientation = -1; // 是否锁定视频方向
int stayAwake = false; // 是否保持唤醒 int stayAwake = false; // 是否保持唤醒
QString serverVersion = "1.21";// server版本
QString logLevel = "info"; // log级别 debug/info/warn/error
// 编码选项 ""表示默认
// 例如 CodecOptions="profile=1,level=2"
// 更多编码选项参考 https://d.android.com/reference/android/media/MediaFormat
QString codecOptions = "";
// 指定编码器名称(必须是H.264编码器)""表示默认
// 例如 CodecName="OMX.qcom.video.encoder.avc"
QString codecName = "";
QString crop = ""; // 视频裁剪 QString crop = ""; // 视频裁剪
bool control = true; // 安卓端是否接收键鼠控制 bool control = true; // 安卓端是否接收键鼠控制
}; };
@ -58,7 +68,7 @@ signals:
void serverStoped(); void serverStoped();
private slots: private slots:
void onWorkProcessResult(AdbProcess::ADB_EXEC_RESULT processResult); void onWorkProcessResult(qsc::AdbProcess::ADB_EXEC_RESULT processResult);
protected: protected:
void timerEvent(QTimerEvent *event); void timerEvent(QTimerEvent *event);
@ -80,8 +90,8 @@ private:
void onConnectTimer(); void onConnectTimer();
private: private:
AdbProcess m_workProcess; qsc::AdbProcess m_workProcess;
AdbProcess m_serverProcess; qsc::AdbProcess m_serverProcess;
TcpServer m_serverSocket; // only used if !tunnel_forward TcpServer m_serverSocket; // only used if !tunnel_forward
QPointer<VideoSocket> m_videoSocket = Q_NULLPTR; QPointer<VideoSocket> m_videoSocket = Q_NULLPTR;
QPointer<QTcpSocket> m_controlSocket = Q_NULLPTR; QPointer<QTcpSocket> m_controlSocket = Q_NULLPTR;

View file

@ -103,6 +103,8 @@ int main(int argc, char *argv[])
file.close(); file.close();
} }
qsc::AdbProcess::setAdbPath(Config::getInstance().getAdbPath());
g_mainDlg = new Dialog {}; g_mainDlg = new Dialog {};
g_mainDlg->show(); g_mainDlg->show();

View file

@ -17,28 +17,28 @@ Dialog::Dialog(QWidget *parent) : QDialog(parent), ui(new Ui::Dialog)
ui->setupUi(this); ui->setupUi(this);
initUI(); initUI();
connect(&m_adb, &AdbProcess::adbProcessResult, this, [this](AdbProcess::ADB_EXEC_RESULT processResult) { connect(&m_adb, &qsc::AdbProcess::adbProcessResult, this, [this](qsc::AdbProcess::ADB_EXEC_RESULT processResult) {
QString log = ""; QString log = "";
bool newLine = true; bool newLine = true;
QStringList args = m_adb.arguments(); QStringList args = m_adb.arguments();
switch (processResult) { switch (processResult) {
case AdbProcess::AER_ERROR_START: case qsc::AdbProcess::AER_ERROR_START:
break; break;
case AdbProcess::AER_SUCCESS_START: case qsc::AdbProcess::AER_SUCCESS_START:
log = "adb run"; log = "adb run";
newLine = false; newLine = false;
break; break;
case AdbProcess::AER_ERROR_EXEC: case qsc::AdbProcess::AER_ERROR_EXEC:
//log = m_adb.getErrorOut(); //log = m_adb.getErrorOut();
if (args.contains("ifconfig") && args.contains("wlan0")) { if (args.contains("ifconfig") && args.contains("wlan0")) {
getIPbyIp(); getIPbyIp();
} }
break; break;
case AdbProcess::AER_ERROR_MISSING_BINARY: case qsc::AdbProcess::AER_ERROR_MISSING_BINARY:
log = "adb not found"; log = "adb not found";
break; break;
case AdbProcess::AER_SUCCESS_EXEC: case qsc::AdbProcess::AER_SUCCESS_EXEC:
//log = m_adb.getStdOut(); //log = m_adb.getStdOut();
if (args.contains("devices")) { if (args.contains("devices")) {
QStringList devices = m_adb.getDevicesSerialFromStdOut(); QStringList devices = m_adb.getDevicesSerialFromStdOut();
@ -285,6 +285,10 @@ void Dialog::on_startServerBtn_clicked()
params.serverRemotePath = Config::getInstance().getServerPath(); params.serverRemotePath = Config::getInstance().getServerPath();
params.pushFilePath = Config::getInstance().getPushFilePath(); params.pushFilePath = Config::getInstance().getPushFilePath();
params.gameScript = getGameScript(ui->gameBox->currentText()); params.gameScript = getGameScript(ui->gameBox->currentText());
params.serverVersion = Config::getInstance().getServerVersion();
params.logLevel = Config::getInstance().getLogLevel();
params.codecOptions = Config::getInstance().getCodecOptions();
params.codecName = Config::getInstance().getCodecName();
qsc::IDeviceManage::getInstance().connectDevice(params); qsc::IDeviceManage::getInstance().connectDevice(params);
} }

View file

@ -75,7 +75,7 @@ protected:
private: private:
Ui::Dialog *ui; Ui::Dialog *ui;
AdbProcess m_adb; qsc::AdbProcess m_adb;
QSystemTrayIcon *m_hideIcon; QSystemTrayIcon *m_hideIcon;
QMenu *m_menu; QMenu *m_menu;
QAction *m_showWindow; QAction *m_showWindow;