2
.github/workflows/ubuntu.yml
vendored
|
@ -18,7 +18,7 @@ jobs:
|
|||
runs-on: ${{ matrix.os }}
|
||||
strategy:
|
||||
matrix:
|
||||
os: [ubuntu-18.04]
|
||||
os: [ubuntu-22.04]
|
||||
qt-ver: [5.15.1]
|
||||
qt-arch-install: [gcc_64]
|
||||
gcc-arch: [x64]
|
||||
|
|
|
@ -79,8 +79,8 @@ set(CMAKE_AUTOUIC ON)
|
|||
set(CMAKE_AUTOMOC ON)
|
||||
set(CMAKE_AUTORCC ON)
|
||||
|
||||
find_package(QT NAMES Qt6 Qt5 COMPONENTS Widgets Network REQUIRED)
|
||||
find_package(Qt${QT_VERSION_MAJOR} COMPONENTS Widgets Network REQUIRED)
|
||||
find_package(QT NAMES Qt6 Qt5 COMPONENTS Widgets Network Multimedia REQUIRED)
|
||||
find_package(Qt${QT_VERSION_MAJOR} COMPONENTS Widgets Network Multimedia REQUIRED)
|
||||
if(CMAKE_SYSTEM_NAME STREQUAL "Linux")
|
||||
find_package(QT NAMES Qt6 Qt5 COMPONENTS X11Extras REQUIRED)
|
||||
find_package(Qt${QT_VERSION_MAJOR} COMPONENTS X11Extras REQUIRED)
|
||||
|
@ -108,6 +108,13 @@ set(QC_UIBASE_SOURCES
|
|||
)
|
||||
source_group(uibase FILES ${QC_UIBASE_SOURCES})
|
||||
|
||||
# audio
|
||||
set(QC_AUDIO_SOURCES
|
||||
audio/audiooutput.h
|
||||
audio/audiooutput.cpp
|
||||
)
|
||||
source_group(audio FILES ${QC_AUDIO_SOURCES})
|
||||
|
||||
# ui
|
||||
set(QC_UI_SOURCES
|
||||
ui/toolform.h
|
||||
|
@ -199,6 +206,7 @@ set(QC_PROJECT_SOURCES
|
|||
${QC_MAIN_SOURCES}
|
||||
${QC_GROUP_CONTROLLER}
|
||||
${QC_PLANTFORM_SOURCES}
|
||||
${QC_AUDIO_SOURCES}
|
||||
)
|
||||
|
||||
if(CMAKE_SYSTEM_NAME STREQUAL "Darwin")
|
||||
|
@ -242,6 +250,11 @@ set_target_properties(${PROJECT_NAME} PROPERTIES
|
|||
if(CMAKE_SYSTEM_NAME STREQUAL "Windows")
|
||||
get_target_property(QSC_BIN_OUTPUT_PATH ${PROJECT_NAME} RUNTIME_OUTPUT_DIRECTORY)
|
||||
set(QSC_DEPLOY_PATH ${QSC_BIN_OUTPUT_PATH})
|
||||
|
||||
add_custom_command(TARGET ${PROJECT_NAME} POST_BUILD
|
||||
COMMAND ${CMAKE_COMMAND} -E copy_if_different "${CMAKE_CURRENT_SOURCE_DIR}/sndcpy/sndcpy.bat" "${QSC_BIN_OUTPUT_PATH}"
|
||||
COMMAND ${CMAKE_COMMAND} -E copy_if_different "${CMAKE_CURRENT_SOURCE_DIR}/sndcpy/sndcpy.apk" "${QSC_BIN_OUTPUT_PATH}"
|
||||
)
|
||||
endif()
|
||||
|
||||
# MacOS
|
||||
|
@ -255,6 +268,8 @@ if(CMAKE_SYSTEM_NAME STREQUAL "Darwin")
|
|||
add_custom_command(TARGET ${PROJECT_NAME} POST_BUILD
|
||||
# config file copy to Contents/MacOS/config
|
||||
COMMAND ${CMAKE_COMMAND} -E copy_if_different "${CMAKE_CURRENT_SOURCE_DIR}/../config/config.ini" "${MACOS_BUNDLE_PATH}/MacOS/config/config.ini"
|
||||
COMMAND ${CMAKE_COMMAND} -E copy_if_different "${CMAKE_CURRENT_SOURCE_DIR}/sndcpy/sndcpy.sh" "${MACOS_BUNDLE_PATH}/MacOS"
|
||||
COMMAND ${CMAKE_COMMAND} -E copy_if_different "${CMAKE_CURRENT_SOURCE_DIR}/sndcpy/sndcpy.apk" "${MACOS_BUNDLE_PATH}/MacOS"
|
||||
)
|
||||
|
||||
# Step 2. ues MACOSX_PACKAGE_LOCATION copy icns to Resources
|
||||
|
@ -284,6 +299,11 @@ if(CMAKE_SYSTEM_NAME STREQUAL "Linux")
|
|||
get_target_property(QSC_BIN_OUTPUT_PATH ${PROJECT_NAME} RUNTIME_OUTPUT_DIRECTORY)
|
||||
set(QSC_DEPLOY_PATH ${QSC_BIN_OUTPUT_PATH})
|
||||
|
||||
add_custom_command(TARGET ${PROJECT_NAME} POST_BUILD
|
||||
COMMAND ${CMAKE_COMMAND} -E copy_if_different "${CMAKE_CURRENT_SOURCE_DIR}/sndcpy/sndcpy.sh" "${QSC_BIN_OUTPUT_PATH}"
|
||||
COMMAND ${CMAKE_COMMAND} -E copy_if_different "${CMAKE_CURRENT_SOURCE_DIR}/sndcpy/sndcpy.apk" "${QSC_BIN_OUTPUT_PATH}"
|
||||
)
|
||||
|
||||
set(THREADS_PREFER_PTHREAD_FLAG ON)
|
||||
find_package(Threads REQUIRED)
|
||||
|
||||
|
@ -309,5 +329,6 @@ add_subdirectory(QtScrcpyCore)
|
|||
target_link_libraries(${PROJECT_NAME} PRIVATE
|
||||
Qt${QT_VERSION_MAJOR}::Widgets
|
||||
Qt${QT_VERSION_MAJOR}::Network
|
||||
Qt${QT_VERSION_MAJOR}::Multimedia
|
||||
QtScrcpyCore
|
||||
)
|
||||
|
|
|
@ -1 +1 @@
|
|||
Subproject commit 7ac8571daadf5af9b548a4c02eb7c6d504af6a97
|
||||
Subproject commit 3004e63935fe8a3e57b91e117a91c1a6aa68ae42
|
197
QtScrcpy/audio/audiooutput.cpp
Normal file
|
@ -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();
|
||||
}
|
41
QtScrcpy/audio/audiooutput.h
Normal file
|
@ -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
|
|
@ -22,21 +22,24 @@ int main(int argc, char *argv[])
|
|||
{
|
||||
// set env
|
||||
#ifdef Q_OS_WIN32
|
||||
qputenv("QTSCRCPY_ADB_PATH", "D:/android/sdk/platform-tools/adb.exe");
|
||||
qputenv("QTSCRCPY_ADB_PATH", "../../../QtScrcpy/QtScrcpyCore/src/third_party/adb/win/adb.exe");
|
||||
qputenv("QTSCRCPY_SERVER_PATH", "../../../QtScrcpy/QtScrcpyCore/src/third_party/scrcpy-server");
|
||||
qputenv("QTSCRCPY_KEYMAP_PATH", "../../../keymap");
|
||||
qputenv("QTSCRCPY_CONFIG_PATH", "../../../config");
|
||||
#endif
|
||||
|
||||
#ifdef Q_OS_OSX
|
||||
qputenv("QTSCRCPY_KEYMAP_PATH", "../../../../../keymap");
|
||||
qputenv("QTSCRCPY_ADB_PATH", "../../../../../../QtScrcpy/QtScrcpyCore/src/third_party/adb/mac/adb");
|
||||
qputenv("QTSCRCPY_SERVER_PATH", "../../../../../../QtScrcpy/QtScrcpyCore/src/third_party/scrcpy-server");
|
||||
qputenv("QTSCRCPY_KEYMAP_PATH", "../../../../../../keymap");
|
||||
qputenv("QTSCRCPY_CONFIG_PATH", "../../../../../../config");
|
||||
#endif
|
||||
|
||||
#ifdef Q_OS_LINUX
|
||||
qputenv("QTSCRCPY_ADB_PATH", "../../QtScrcpy/QtScrcpyCore/src/third_party/adb/linux/adb");
|
||||
qputenv("QTSCRCPY_SERVER_PATH", "../../QtScrcpy/QtScrcpyCore/src/third_party/scrcpy-server");
|
||||
qputenv("QTSCRCPY_CONFIG_PATH", "../../config");
|
||||
qputenv("QTSCRCPY_KEYMAP_PATH", "../../keymap");
|
||||
qputenv("QTSCRCPY_ADB_PATH", "../../../QtScrcpy/QtScrcpyCore/src/third_party/adb/linux/adb");
|
||||
qputenv("QTSCRCPY_SERVER_PATH", "../../../QtScrcpy/QtScrcpyCore/src/third_party/scrcpy-server");
|
||||
qputenv("QTSCRCPY_KEYMAP_PATH", "../../../keymap");
|
||||
qputenv("QTSCRCPY_CONFIG_PATH", "../../../config");
|
||||
#endif
|
||||
|
||||
g_msgType = covertLogLevel(Config::getInstance().getLogLevel());
|
||||
|
|
|
@ -3,6 +3,114 @@
|
|||
<TS version="2.1" language="en_US">
|
||||
<context>
|
||||
<name>Dialog</name>
|
||||
<message>
|
||||
<source>show</source>
|
||||
<translation>show</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>quit</source>
|
||||
<translation>quit</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>original</source>
|
||||
<translation>original</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>no lock</source>
|
||||
<translation>no lock</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Notice</source>
|
||||
<translation>Notice</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Hidden here!</source>
|
||||
<translation>Hidden here!</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>select path</source>
|
||||
<translation>select path</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>QObject</name>
|
||||
<message>
|
||||
<source>This software is completely open source and free. Use it at your own risk. You can download it at the following address:</source>
|
||||
<translation>This software is completely open source and free. Use it at your own risk. You can download it at the following address:</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>ToolForm</name>
|
||||
<message>
|
||||
<source>Tool</source>
|
||||
<translation>Tool</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>full screen</source>
|
||||
<translation>full screen</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>expand notify</source>
|
||||
<translation>expand notify</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>touch switch</source>
|
||||
<translation>touch switch</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>close screen</source>
|
||||
<translation>close screen</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>power</source>
|
||||
<translation>power</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>volume up</source>
|
||||
<translation>volume up</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>volume down</source>
|
||||
<translation>volume down</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>app switch</source>
|
||||
<translation>app switch</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>menu</source>
|
||||
<translation>menu</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>home</source>
|
||||
<translation>home</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>return</source>
|
||||
<translation>return</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>screen shot</source>
|
||||
<translation>screen shot</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>open screen</source>
|
||||
<translation>open screen</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>group control</source>
|
||||
<translation>group control</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>VideoForm</name>
|
||||
<message>
|
||||
<source>file does not exist</source>
|
||||
<translation>file does not exist</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>Widget</name>
|
||||
<message>
|
||||
<source>Wireless</source>
|
||||
<translation>Wireless</translation>
|
||||
|
@ -166,109 +274,20 @@
|
|||
<translation>refresh devices</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>show</source>
|
||||
<translatorcomment>show</translatorcomment>
|
||||
<translation>show</translation>
|
||||
<source>install sndcpy</source>
|
||||
<translation>install sndcpy</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>quit</source>
|
||||
<translatorcomment>quit</translatorcomment>
|
||||
<translation>quit</translation>
|
||||
<source>start audio</source>
|
||||
<translation>start audio</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>original</source>
|
||||
<translation>original</translation>
|
||||
<source>stop audio</source>
|
||||
<translation>stop audio</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>no lock</source>
|
||||
<translation>no lock</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Notice</source>
|
||||
<translatorcomment>Notice</translatorcomment>
|
||||
<translation>Notice</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Hidden here!</source>
|
||||
<translatorcomment>Hidden here!</translatorcomment>
|
||||
<translation>Hidden here!</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>QObject</name>
|
||||
<message>
|
||||
<source>This software is completely open source and free. Use it at your own risk. You can download it at the following address:</source>
|
||||
<translation>This software is completely open source and free. Use it at your own risk. You can download it at the following address:</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>ToolForm</name>
|
||||
<message>
|
||||
<source>Tool</source>
|
||||
<translation>Tool</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>full screen</source>
|
||||
<translation>full screen</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>expand notify</source>
|
||||
<translation>expand notify</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>touch switch</source>
|
||||
<translation>touch switch</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>close screen</source>
|
||||
<translation>close screen</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>power</source>
|
||||
<translation>power</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>volume up</source>
|
||||
<translation>volume up</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>volume down</source>
|
||||
<translation>volume down</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>app switch</source>
|
||||
<translation>app switch</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>menu</source>
|
||||
<translation>menu</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>home</source>
|
||||
<translation>home</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>return</source>
|
||||
<translation>return</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>screen shot</source>
|
||||
<translation>screen shot</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>open screen</source>
|
||||
<translation>open screen</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>group control</source>
|
||||
<translation>group control</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>VideoForm</name>
|
||||
<message>
|
||||
<source>file does not exist</source>
|
||||
<translation>file does not exist</translation>
|
||||
<source>auto update</source>
|
||||
<translation>autp update</translation>
|
||||
</message>
|
||||
</context>
|
||||
</TS>
|
||||
|
|
|
@ -3,6 +3,114 @@
|
|||
<TS version="2.1" language="zh_CN">
|
||||
<context>
|
||||
<name>Dialog</name>
|
||||
<message>
|
||||
<source>show</source>
|
||||
<translation>显示</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>quit</source>
|
||||
<translation>退出</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>original</source>
|
||||
<translation>原始</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>no lock</source>
|
||||
<translation>不锁定</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Notice</source>
|
||||
<translation>提示</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Hidden here!</source>
|
||||
<translation>安卓录屏程序隐藏在这!</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>select path</source>
|
||||
<translation>选择路径</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>QObject</name>
|
||||
<message>
|
||||
<source>This software is completely open source and free. Use it at your own risk. You can download it at the following address:</source>
|
||||
<translation>本软件完全开源免费,作者不对使用该软件产生的一切后果负责。你可以在以下地址下载:</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>ToolForm</name>
|
||||
<message>
|
||||
<source>Tool</source>
|
||||
<translation>工具</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>full screen</source>
|
||||
<translation>全屏</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>expand notify</source>
|
||||
<translation>下拉通知</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>touch switch</source>
|
||||
<translation>触摸显示开关</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>close screen</source>
|
||||
<translation>关闭屏幕</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>power</source>
|
||||
<translation>电源</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>volume up</source>
|
||||
<translation>音量加</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>volume down</source>
|
||||
<translation>音量减</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>app switch</source>
|
||||
<translation>切换应用</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>menu</source>
|
||||
<translation>菜单</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>home</source>
|
||||
<translation>主界面</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>return</source>
|
||||
<translation>返回</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>screen shot</source>
|
||||
<translation>截图</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>open screen</source>
|
||||
<translation>打开屏幕</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>group control</source>
|
||||
<translation>群控</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>VideoForm</name>
|
||||
<message>
|
||||
<source>file does not exist</source>
|
||||
<translation>文件不存在</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>Widget</name>
|
||||
<message>
|
||||
<source>Wireless</source>
|
||||
<translation>无线</translation>
|
||||
|
@ -166,109 +274,20 @@
|
|||
<translation>刷新设备列表</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>show</source>
|
||||
<translatorcomment>显示</translatorcomment>
|
||||
<translation>显示</translation>
|
||||
<source>install sndcpy</source>
|
||||
<translation>安装sndcpy</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>quit</source>
|
||||
<translatorcomment>退出</translatorcomment>
|
||||
<translation>退出</translation>
|
||||
<source>start audio</source>
|
||||
<translation>开始音频</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>original</source>
|
||||
<translation>原始</translation>
|
||||
<source>stop audio</source>
|
||||
<translation>停止音频</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>no lock</source>
|
||||
<translation>不锁定</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Notice</source>
|
||||
<translatorcomment>提示</translatorcomment>
|
||||
<translation>提示</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Hidden here!</source>
|
||||
<translatorcomment>安卓录屏程序隐藏在这!</translatorcomment>
|
||||
<translation>安卓录屏程序隐藏在这!</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>QObject</name>
|
||||
<message>
|
||||
<source>This software is completely open source and free. Use it at your own risk. You can download it at the following address:</source>
|
||||
<translation>本软件完全开源免费,作者不对使用该软件产生的一切后果负责。你可以在以下地址下载:</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>ToolForm</name>
|
||||
<message>
|
||||
<source>Tool</source>
|
||||
<translation>工具</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>full screen</source>
|
||||
<translation>全屏</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>expand notify</source>
|
||||
<translation>下拉通知</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>touch switch</source>
|
||||
<translation>触摸显示开关</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>close screen</source>
|
||||
<translation>关闭屏幕</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>power</source>
|
||||
<translation>电源</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>volume up</source>
|
||||
<translation>音量加</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>volume down</source>
|
||||
<translation>音量减</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>app switch</source>
|
||||
<translation>切换应用</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>menu</source>
|
||||
<translation>菜单</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>home</source>
|
||||
<translation>主界面</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>return</source>
|
||||
<translation>返回</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>screen shot</source>
|
||||
<translation>截图</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>open screen</source>
|
||||
<translation>打开屏幕</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>group control</source>
|
||||
<translation>群控</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>VideoForm</name>
|
||||
<message>
|
||||
<source>file does not exist</source>
|
||||
<translation>文件不存在</translation>
|
||||
<source>auto update</source>
|
||||
<translation>自动刷新</translation>
|
||||
</message>
|
||||
</context>
|
||||
</TS>
|
||||
|
|
BIN
QtScrcpy/sndcpy/sndcpy.apk
Normal file
53
QtScrcpy/sndcpy/sndcpy.bat
Normal file
|
@ -0,0 +1,53 @@
|
|||
@echo off
|
||||
|
||||
echo Begin Runing...
|
||||
set SNDCPY_PORT=28200
|
||||
set SNDCPY_APK=sndcpy.apk
|
||||
set ADB=adb.exe
|
||||
|
||||
if not "%1"=="" (
|
||||
set serial=-s %1
|
||||
)
|
||||
if not "%2"=="" (
|
||||
set SNDCPY_PORT=%2
|
||||
)
|
||||
|
||||
echo Waiting for device %1...
|
||||
%ADB% %serial% wait-for-device || goto :error
|
||||
echo Find device %1
|
||||
|
||||
for /f "delims=" %%i in ('%ADB% %serial% shell pm path com.rom1v.sndcpy') do set sndcpy_installed=%%i
|
||||
if "%sndcpy_installed%"=="" (
|
||||
echo Install %SNDCPY_APK%...
|
||||
%ADB% %serial% uninstall com.rom1v.sndcpy || goto :error
|
||||
%ADB% %serial% install -t -r -g %SNDCPY_APK% || goto :error
|
||||
echo Install %SNDCPY_APK% success
|
||||
)
|
||||
|
||||
echo Request PROJECT_MEDIA permission...
|
||||
%ADB% %serial% shell appops set com.rom1v.sndcpy PROJECT_MEDIA allow
|
||||
|
||||
echo Forward port %SNDCPY_PORT%...
|
||||
%ADB% %serial% forward tcp:%SNDCPY_PORT% localabstract:sndcpy || goto :error
|
||||
|
||||
echo Start %SNDCPY_APK%...
|
||||
%ADB% %serial% shell am start com.rom1v.sndcpy/.MainActivity || goto :error
|
||||
|
||||
:check_start
|
||||
echo Waiting %SNDCPY_APK% start...
|
||||
::timeout /T 1 /NOBREAK > nul
|
||||
%ADB% %serial% shell sleep 0.1
|
||||
for /f "delims=" %%i in ("%ADB% shell 'ps | grep com.rom1v.sndcpy'") do set sndcpy_started=%%i
|
||||
if "%sndcpy_started%"=="" (
|
||||
goto :check_start
|
||||
)
|
||||
echo %SNDCPY_APK% started...
|
||||
|
||||
echo Ready playing...
|
||||
::vlc.exe -Idummy --demux rawaud --network-caching=0 --play-and-exit tcp://localhost:%SNDCPY_PORT%
|
||||
::ffplay.exe -nodisp -autoexit -probesize 32 -sync ext -f s16le -ar 48k -ac 2 tcp://localhost:%SNDCPY_PORT%
|
||||
goto :EOF
|
||||
|
||||
:error
|
||||
echo Failed with error #%errorlevel%.
|
||||
exit /b %errorlevel%
|
46
QtScrcpy/sndcpy/sndcpy.sh
Executable file
|
@ -0,0 +1,46 @@
|
|||
#!/bin/bash
|
||||
|
||||
echo Begin Runing...
|
||||
SNDCPY_PORT=28200
|
||||
SNDCPY_APK=sndcpy.apk
|
||||
ADB=./adb
|
||||
|
||||
serial=
|
||||
if [[ $# -ge 2 ]]
|
||||
then
|
||||
serial="-s $1"
|
||||
SNDCPY_PORT=$2
|
||||
fi
|
||||
|
||||
echo "Waiting for device $1..."
|
||||
$ADB $serial wait-for-device
|
||||
echo "Find device $1"
|
||||
|
||||
sndcpy_installed=$($ADB $serial shell pm path com.rom1v.sndcpy)
|
||||
if [[ $sndcpy_installed == "" ]]; then
|
||||
echo Install $SNDCPY_APK...
|
||||
$ADB $serial uninstall com.rom1v.sndcpy
|
||||
$ADB $serial install -t -r -g $SNDCPY_APK
|
||||
echo Install $SNDCPY_APK success
|
||||
fi
|
||||
|
||||
echo Request PROJECT_MEDIA permission...
|
||||
$ADB $serial shell appops set com.rom1v.sndcpy PROJECT_MEDIA allow
|
||||
|
||||
echo Forward port $SNDCPY_PORT...
|
||||
$ADB $serial forward tcp:$SNDCPY_PORT localabstract:sndcpy
|
||||
|
||||
echo Start $SNDCPY_APK...
|
||||
$ADB $serial shell am start com.rom1v.sndcpy/.MainActivity
|
||||
|
||||
while ((1))
|
||||
do
|
||||
echo Waiting $SNDCPY_APK start...
|
||||
sleep 0.1
|
||||
sndcpy_started=$($ADB shell 'ps | grep com.rom1v.sndcpy')
|
||||
if [[ $sndcpy_started != "" ]]; then
|
||||
break
|
||||
fi
|
||||
done
|
||||
|
||||
echo Ready playing...
|
|
@ -25,11 +25,21 @@ const QString &getKeyMapPath()
|
|||
return s_keyMapPath;
|
||||
}
|
||||
|
||||
Dialog::Dialog(QWidget *parent) : QDialog(parent), ui(new Ui::Dialog)
|
||||
Dialog::Dialog(QWidget *parent) : QWidget(parent), ui(new Ui::Widget)
|
||||
{
|
||||
ui->setupUi(this);
|
||||
initUI();
|
||||
|
||||
updateBootConfig(true);
|
||||
|
||||
on_useSingleModeCheck_clicked();
|
||||
on_updateDevice_clicked();
|
||||
|
||||
connect(&m_autoUpdatetimer, &QTimer::timeout, this, &Dialog::on_updateDevice_clicked);
|
||||
if (ui->autoUpdatecheckBox->isChecked()) {
|
||||
m_autoUpdatetimer.start(5000);
|
||||
}
|
||||
|
||||
connect(&m_adb, &qsc::AdbProcess::adbProcessResult, this, [this](qsc::AdbProcess::ADB_EXEC_RESULT processResult) {
|
||||
QString log = "";
|
||||
bool newLine = true;
|
||||
|
@ -101,7 +111,7 @@ Dialog::Dialog(QWidget *parent) : QDialog(parent), ui(new Ui::Dialog)
|
|||
m_menu->addAction(m_quit);
|
||||
m_hideIcon->setContextMenu(m_menu);
|
||||
m_hideIcon->show();
|
||||
connect(m_showWindow, &QAction::triggered, this, &Dialog::slotShow);
|
||||
connect(m_showWindow, &QAction::triggered, this, &Dialog::show);
|
||||
connect(m_quit, &QAction::triggered, this, [this]() {
|
||||
m_hideIcon->hide();
|
||||
qApp->quit();
|
||||
|
@ -123,7 +133,7 @@ Dialog::~Dialog()
|
|||
void Dialog::initUI()
|
||||
{
|
||||
setAttribute(Qt::WA_DeleteOnClose);
|
||||
setWindowFlags(windowFlags() | Qt::WindowMinimizeButtonHint | Qt::WindowCloseButtonHint | Qt::CustomizeWindowHint);
|
||||
//setWindowFlags(windowFlags() | Qt::WindowMinimizeButtonHint | Qt::WindowCloseButtonHint | Qt::CustomizeWindowHint);
|
||||
|
||||
setWindowTitle(Config::getInstance().getTitle());
|
||||
|
||||
|
@ -145,12 +155,6 @@ void Dialog::initUI()
|
|||
ui->lockOrientationBox->addItem("180");
|
||||
ui->lockOrientationBox->addItem("270");
|
||||
ui->lockOrientationBox->setCurrentIndex(0);
|
||||
|
||||
updateBootConfig(true);
|
||||
|
||||
on_useSingleModeCheck_clicked();
|
||||
|
||||
on_updateDevice_clicked();
|
||||
}
|
||||
|
||||
void Dialog::updateBootConfig(bool toView)
|
||||
|
@ -181,6 +185,7 @@ void Dialog::updateBootConfig(bool toView)
|
|||
ui->closeScreenCheck->setChecked(config.autoOffScreen);
|
||||
ui->stayAwakeCheck->setChecked(config.keepAlive);
|
||||
ui->useSingleModeCheck->setChecked(config.simpleMode);
|
||||
ui->autoUpdatecheckBox->setChecked(config.autoUpdateDevice);
|
||||
} else {
|
||||
UserBootConfig config;
|
||||
|
||||
|
@ -198,6 +203,7 @@ void Dialog::updateBootConfig(bool toView)
|
|||
config.framelessWindow = ui->framelessCheck->isChecked();
|
||||
config.keepAlive = ui->stayAwakeCheck->isChecked();
|
||||
config.simpleMode = ui->useSingleModeCheck->isChecked();
|
||||
config.autoUpdateDevice = ui->autoUpdatecheckBox->isChecked();
|
||||
Config::getInstance().setUserBootConfig(config);
|
||||
}
|
||||
}
|
||||
|
@ -238,17 +244,13 @@ QString Dialog::getGameScript(const QString &fileName)
|
|||
return ret;
|
||||
}
|
||||
|
||||
void Dialog::slotShow()
|
||||
{
|
||||
this->show();
|
||||
m_hideIcon->hide();
|
||||
}
|
||||
|
||||
void Dialog::slotActivated(QSystemTrayIcon::ActivationReason reason)
|
||||
{
|
||||
switch (reason) {
|
||||
case QSystemTrayIcon::Trigger:
|
||||
#ifdef Q_OS_WIN32
|
||||
this->show();
|
||||
#endif
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
|
@ -464,8 +466,11 @@ void Dialog::onDeviceConnected(bool success, const QString &serial, const QStrin
|
|||
void Dialog::onDeviceDisconnected(QString serial)
|
||||
{
|
||||
GroupController::instance().removeDevice(serial);
|
||||
|
||||
auto data = qsc::IDeviceManage::getInstance().getDevice(serial)->getUserData();
|
||||
auto device = qsc::IDeviceManage::getInstance().getDevice(serial);
|
||||
if (!device) {
|
||||
return;
|
||||
}
|
||||
auto data = device->getUserData();
|
||||
if (data) {
|
||||
VideoForm* vf = static_cast<VideoForm*>(data);
|
||||
qsc::IDeviceManage::getInstance().getDevice(serial)->deRegisterDeviceObserver(vf);
|
||||
|
@ -688,3 +693,36 @@ const QString &Dialog::getServerPath()
|
|||
}
|
||||
return serverPath;
|
||||
}
|
||||
|
||||
void Dialog::on_startAudioBtn_clicked()
|
||||
{
|
||||
if (ui->serialBox->count() == 0) {
|
||||
qWarning() << "No device is connected!";
|
||||
return;
|
||||
}
|
||||
|
||||
m_audioOutput.start(ui->serialBox->currentText(), 28200);
|
||||
}
|
||||
|
||||
void Dialog::on_stopAudioBtn_clicked()
|
||||
{
|
||||
m_audioOutput.stop();
|
||||
}
|
||||
|
||||
void Dialog::on_installSndcpyBtn_clicked()
|
||||
{
|
||||
if (ui->serialBox->count() == 0) {
|
||||
qWarning() << "No device is connected!";
|
||||
return;
|
||||
}
|
||||
m_audioOutput.installonly(ui->serialBox->currentText(), 28200);
|
||||
}
|
||||
|
||||
void Dialog::on_autoUpdatecheckBox_toggled(bool checked)
|
||||
{
|
||||
if (checked) {
|
||||
m_autoUpdatetimer.start(5000);
|
||||
} else {
|
||||
m_autoUpdatetimer.stop();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,24 +1,26 @@
|
|||
#ifndef DIALOG_H
|
||||
#define DIALOG_H
|
||||
|
||||
#include <QDialog>
|
||||
#include <QWidget>
|
||||
#include <QPointer>
|
||||
#include <QMessageBox>
|
||||
#include <QMenu>
|
||||
#include <QSystemTrayIcon>
|
||||
#include <QListWidget>
|
||||
#include <QTimer>
|
||||
|
||||
|
||||
#include "adbprocess.h"
|
||||
#include "../QtScrcpyCore/include/QtScrcpyCore.h"
|
||||
#include "audio/audiooutput.h"
|
||||
|
||||
namespace Ui
|
||||
{
|
||||
class Dialog;
|
||||
class Widget;
|
||||
}
|
||||
|
||||
class QYUVOpenGLWidget;
|
||||
class Dialog : public QDialog
|
||||
class Dialog : public QWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
|
@ -57,6 +59,14 @@ private slots:
|
|||
void on_useSingleModeCheck_clicked();
|
||||
void on_serialBox_currentIndexChanged(const QString &arg1);
|
||||
|
||||
void on_startAudioBtn_clicked();
|
||||
|
||||
void on_stopAudioBtn_clicked();
|
||||
|
||||
void on_installSndcpyBtn_clicked();
|
||||
|
||||
void on_autoUpdatecheckBox_toggled(bool checked);
|
||||
|
||||
private:
|
||||
bool checkAdbRun();
|
||||
void initUI();
|
||||
|
@ -64,7 +74,6 @@ private:
|
|||
void execAdbCmd();
|
||||
void delayMs(int ms);
|
||||
QString getGameScript(const QString &fileName);
|
||||
void slotShow();
|
||||
void slotActivated(QSystemTrayIcon::ActivationReason reason);
|
||||
int findDeviceFromeSerialBox(bool wifi);
|
||||
quint32 getBitRate();
|
||||
|
@ -74,12 +83,14 @@ protected:
|
|||
void closeEvent(QCloseEvent *event);
|
||||
|
||||
private:
|
||||
Ui::Dialog *ui;
|
||||
Ui::Widget *ui;
|
||||
qsc::AdbProcess m_adb;
|
||||
QSystemTrayIcon *m_hideIcon;
|
||||
QMenu *m_menu;
|
||||
QAction *m_showWindow;
|
||||
QAction *m_quit;
|
||||
AudioOutput m_audioOutput;
|
||||
QTimer m_autoUpdatetimer;
|
||||
};
|
||||
|
||||
#endif // DIALOG_H
|
||||
|
|
|
@ -1,13 +1,13 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>Dialog</class>
|
||||
<widget class="QDialog" name="Dialog">
|
||||
<class>Widget</class>
|
||||
<widget class="QWidget" name="Widget">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>1293</width>
|
||||
<height>419</height>
|
||||
<height>454</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
|
@ -100,17 +100,34 @@
|
|||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="label_10">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_13">
|
||||
<property name="topMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Double click to connect:</string>
|
||||
</property>
|
||||
</widget>
|
||||
<item>
|
||||
<widget class="QLabel" name="label_10">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Double click to connect:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QCheckBox" name="autoUpdatecheckBox">
|
||||
<property name="text">
|
||||
<string>auto update</string>
|
||||
</property>
|
||||
<property name="checked">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QListWidget" name="connectedPhoneList">
|
||||
|
@ -941,6 +958,45 @@
|
|||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QWidget" name="usbWidget3" native="true">
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_12">
|
||||
<property name="leftMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QPushButton" name="installSndcpyBtn">
|
||||
<property name="text">
|
||||
<string>install sndcpy</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="startAudioBtn">
|
||||
<property name="text">
|
||||
<string>start audio</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="stopAudioBtn">
|
||||
<property name="text">
|
||||
<string>stop audio</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
|
|
|
@ -87,6 +87,9 @@
|
|||
#define COMMON_SIMPLE_MODE_KEY "SimpleMode"
|
||||
#define COMMON_SIMPLE_MODE_DEF false
|
||||
|
||||
#define COMMON_AUTO_UPDATE_DEVICE_KEY "AutoUpdateDevice"
|
||||
#define COMMON_AUTO_UPDATE_DEVICE_DEF true
|
||||
|
||||
// device config
|
||||
#define SERIAL_WINDOW_RECT_KEY_X "WindowRectX"
|
||||
#define SERIAL_WINDOW_RECT_KEY_Y "WindowRectY"
|
||||
|
@ -145,6 +148,7 @@ void Config::setUserBootConfig(const UserBootConfig &config)
|
|||
m_userData->setValue(COMMON_AUTO_OFF_SCREEN_KEY, config.autoOffScreen);
|
||||
m_userData->setValue(COMMON_KEEP_ALIVE_KEY, config.keepAlive);
|
||||
m_userData->setValue(COMMON_SIMPLE_MODE_KEY, config.simpleMode);
|
||||
m_userData->setValue(COMMON_AUTO_UPDATE_DEVICE_KEY, config.autoUpdateDevice);
|
||||
m_userData->endGroup();
|
||||
m_userData->sync();
|
||||
}
|
||||
|
@ -167,6 +171,7 @@ UserBootConfig Config::getUserBootConfig()
|
|||
config.autoOffScreen = m_userData->value(COMMON_AUTO_OFF_SCREEN_KEY, COMMON_AUTO_OFF_SCREEN_DEF).toBool();
|
||||
config.keepAlive = m_userData->value(COMMON_KEEP_ALIVE_KEY, COMMON_KEEP_ALIVE_DEF).toBool();
|
||||
config.simpleMode = m_userData->value(COMMON_SIMPLE_MODE_KEY, COMMON_SIMPLE_MODE_DEF).toBool();
|
||||
config.autoUpdateDevice = m_userData->value(COMMON_AUTO_UPDATE_DEVICE_KEY, COMMON_AUTO_UPDATE_DEVICE_DEF).toBool();
|
||||
m_userData->endGroup();
|
||||
return config;
|
||||
}
|
||||
|
|
|
@ -21,6 +21,7 @@ struct UserBootConfig
|
|||
bool framelessWindow = false;
|
||||
bool keepAlive = false;
|
||||
bool simpleMode = false;
|
||||
bool autoUpdateDevice = true;
|
||||
};
|
||||
|
||||
class QSettings;
|
||||
|
|
13
README.md
|
@ -25,11 +25,11 @@ It focuses on:
|
|||
|
||||
[lowlatency]: https://github.com/Genymobile/scrcpy/pull/646
|
||||
|
||||

|
||||

|
||||
|
||||

|
||||

|
||||
|
||||

|
||||

|
||||
|
||||
## Customized key mapping
|
||||
You can write your own script to map keyboard and mouse actions to touches and clicks of the mobile phone according to your needs. [Here](docs/KeyMapDes.md) are the rules.
|
||||
|
@ -122,12 +122,7 @@ you can [build it by yourself](##Build)(just ubuntu test)
|
|||
|
||||
|
||||
## Run
|
||||
### Simple Mode
|
||||
Connect to your Android device on your computer, then run the program and click `USB connect` or `WiFi connect`
|
||||
### Not Simple Mode
|
||||
Connect to your Android device on your computer, then run the program and click the button below to connect to the Android device.
|
||||
|
||||

|
||||
|
||||
### Wireless connection steps (ensure that the mobile phone and PC are in the same LAN):
|
||||
1. Enable USB debugging in developer options on the Android device
|
||||
|
@ -139,7 +134,6 @@ Connect to your Android device on your computer, then run the program and click
|
|||
7. Click update device again, and another device with IP address will be found. Select this device.
|
||||
8. Click start service
|
||||
|
||||
|
||||
|
||||
Note: it is not necessary to keep you Android device connected via USB after you start adbd.
|
||||
|
||||
|
@ -187,6 +181,7 @@ Note: it is not necessary to keep you Android device connected via USB after you
|
|||
- `Ctrl`+`v` _pastes_ the computer clipboard as a sequence of text events (but
|
||||
breaks non-ASCII characters).
|
||||
- Group control
|
||||
- Sync device speaker sound to the computer (based on [sndcpy](https://github.com/rom1v/sndcpy), Android 10+ only)
|
||||
|
||||
## Shortcuts
|
||||
|
||||
|
|
13
README_zh.md
|
@ -24,12 +24,11 @@ QtScrcpy可以通过USB(或通过TCP/IP)连接Android设备,并进行显示和
|
|||
|
||||
[低延迟]: https://github.com/Genymobile/scrcpy/pull/646
|
||||
|
||||

|
||||
|
||||

|
||||

|
||||
|
||||

|
||||
|
||||

|
||||

|
||||
|
||||
## 自定义按键映射
|
||||
可以根据需要,自己编写脚本将PC键盘按键映射为手机的触摸点击,编写规则在[这里](docs/KeyMapDes_zh.md)。
|
||||
|
@ -126,12 +125,7 @@ Mac OS平台,你可以直接使用我编译好的可执行程序:
|
|||
目前只在ubuntu上测试过
|
||||
|
||||
## 运行
|
||||
### 精简模式
|
||||
在你的电脑上接入Android设备,然后运行程序,点击`一键USB连接`或者`一键WIFI连接`
|
||||
### 非精简模式
|
||||
在你的电脑上接入Android设备,然后运行程序,按顺序点击如下按钮即可连接到Android设备
|
||||
|
||||

|
||||
|
||||
### 无线连接步骤(保证手机和电脑在同一个局域网):
|
||||
1. 安卓手机端在开发者选项中打开usb调试
|
||||
|
@ -186,6 +180,7 @@ Mac OS平台,你可以直接使用我编译好的可执行程序:
|
|||
- `Ctrl` + `Shift` + `v`将计算机剪贴板复制到设备剪贴板;
|
||||
- `Ctrl` +`v` 将计算机剪贴板作为一系列文本事件发送到设备(不支持非ASCII字符)。
|
||||
- 群控
|
||||
- 同步设备扬声器声音到电脑(基于[sndcpy](https://github.com/rom1v/sndcpy),仅支持安卓10+)
|
||||
|
||||
## 快捷键
|
||||
|
||||
|
|
BIN
screenshot/linux-en.png
Normal file
After Width: | Height: | Size: 1.5 MiB |
BIN
screenshot/linux-zh.png
Normal file
After Width: | Height: | Size: 1.7 MiB |
BIN
screenshot/mac-en.png
Normal file
After Width: | Height: | Size: 9.8 MiB |
BIN
screenshot/mac-zh.png
Normal file
After Width: | Height: | Size: 10 MiB |
Before Width: | Height: | Size: 769 KiB |
Before Width: | Height: | Size: 32 KiB |
Before Width: | Height: | Size: 911 KiB |
BIN
screenshot/win-en.png
Normal file
After Width: | Height: | Size: 919 KiB |
BIN
screenshot/win-zh.png
Normal file
After Width: | Height: | Size: 1.3 MiB |
Before Width: | Height: | Size: 1.2 MiB |