Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Minimal qt6 support #1100

Merged
merged 1 commit into from
Jan 10, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion .github/workflows/macos.yml
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ jobs:
runs-on: macos-14
strategy:
matrix:
qt-ver: [5.15.2]
qt-ver: [6.5.3]
qt-arch-install: [clang_64]
clang-arch: [x64]
env:
Expand All @@ -34,6 +34,7 @@ jobs:
uses: jurplel/[email protected]
with:
version: ${{ matrix.qt-ver }}
modules: qtmultimedia
cached: ${{ steps.cache-qt.outputs.cache-hit }}
- uses: actions/checkout@v2
with:
Expand Down
5 changes: 3 additions & 2 deletions .github/workflows/ubuntu.yml
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ jobs:
strategy:
matrix:
os: [ubuntu-22.04]
qt-ver: [5.15.2]
qt-ver: [6.5.3]
qt-arch-install: [gcc_64]
gcc-arch: [x64]
env:
Expand All @@ -30,6 +30,7 @@ jobs:
uses: jurplel/[email protected]
with:
version: ${{ matrix.qt-ver }}
modules: qtmultimedia
cached: ${{ steps.cache-qt.outputs.cache-hit }}
- name: Cache Qt
id: cache-qt
Expand All @@ -38,7 +39,7 @@ jobs:
path: ${{ env.qt-install-path }}/${{ matrix.qt-arch-install }}
key: ${{ runner.os }}/${{ matrix.qt-ver }}/${{ matrix.qt-arch-install }}
- name: Install GL library
run: sudo apt-get install -y libglew-dev libglfw3-dev
run: sudo apt-get install -y libglew-dev libglfw3-dev libopengl-dev libx11-dev libxtst-dev
- uses: actions/checkout@v2
with:
fetch-depth: 0
Expand Down
8 changes: 3 additions & 5 deletions .github/workflows/windows.yml
Original file line number Diff line number Diff line change
Expand Up @@ -24,16 +24,13 @@ jobs:
# 矩阵配置 https://help.github.com/en/actions/reference/workflow-syntax-for-github-actions#jobsjob_idstrategymatrix
strategy:
matrix:
qt-ver: [5.15.2]
qt-arch: [win64_msvc2019_64, win32_msvc2019]
qt-ver: [6.5.3]
qt-arch: [win64_msvc2019_64]
# 配置qt-arch的额外设置msvc-arch,qt-arch-install
include:
- qt-arch: win64_msvc2019_64
msvc-arch: x64
qt-arch-install: msvc2019_64
- qt-arch: win32_msvc2019
msvc-arch: x86
qt-arch-install: msvc2019
# job env,所有steps都可以访问
# 不同级别env详解 https://help.github.com/en/actions/reference/workflow-syntax-for-github-actions#env
# 使用表达式语法${{}}访问上下文 https://help.github.com/en/actions/reference/context-and-expression-syntax-for-github-actions
Expand Down Expand Up @@ -62,6 +59,7 @@ jobs:
target: desktop
# Architecture for Windows/Android
arch: ${{ matrix.qt-arch }}
modules: qtmultimedia
cached: ${{ steps.cache-qt.outputs.cache-hit }}
# 拉取代码
- uses: actions/checkout@v2
Expand Down
31 changes: 19 additions & 12 deletions QtScrcpy/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,9 @@ cmake_minimum_required(VERSION 3.19 FATAL_ERROR)
# QC Custom config
set(QC_PROJECT_NAME "QtScrcpy")
# Read version numbers from file
file(STRINGS ${CMAKE_CURRENT_SOURCE_DIR}/appversion QC_FILE_VERSION)
file(STRINGS ${CMAKE_CURRENT_SOURCE_DIR}/appversion QC_FILE_VERSION_UNSTRIPPED)
string(STRIP "${QC_FILE_VERSION_UNSTRIPPED}" QC_FILE_VERSION)

set(QC_PROJECT_VERSION ${QC_FILE_VERSION})

# Project declare
Expand Down Expand Up @@ -52,13 +54,13 @@ if (MSVC)
add_compile_options(/W3 /WX /wd4566)

# avoid warning C4819
add_compile_options(-source-charset:utf-8)
#add_compile_options(-source-charset:utf-8)
#add_compile_options(/utf-8)

# ensure we use minimal "windows.h" lib without the crazy min max macros
add_compile_definitions(NOMINMAX WIN32_LEAN_AND_MEAN)
# disable SAFESEH - avoid "LNK2026: module unsafe"(Qt5.15&&vs2019)

# disable SAFESEH - avoid "LNK2026: module unsafe"(Qt5.15&&vs2019)
add_link_options(/SAFESEH:NO)
endif()

Expand All @@ -79,11 +81,10 @@ set(CMAKE_AUTOUIC ON)
set(CMAKE_AUTOMOC ON)
set(CMAKE_AUTORCC ON)

find_package(QT NAMES Qt6 Qt5 COMPONENTS Widgets Network Multimedia REQUIRED)
find_package(Qt${QT_VERSION_MAJOR} COMPONENTS Widgets Network Multimedia REQUIRED)
find_package(QT NAMES Qt6 Qt5 COMPONENTS Widgets Network Multimedia OpenGL OpenGLWidgets REQUIRED)
find_package(Qt${QT_VERSION_MAJOR} COMPONENTS Widgets Network Multimedia OpenGL OpenGLWidgets 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)
find_package(X11 REQUIRED)
endif()

message(STATUS "[${PROJECT_NAME}] Qt version is: ${QT_VERSION_MAJOR}.${QT_VERSION_MINOR}")
Expand Down Expand Up @@ -146,21 +147,21 @@ set(QC_UTIL_SOURCES
util/mousetap/mousetap.cpp
)
if(CMAKE_SYSTEM_NAME STREQUAL "Windows")
set(QC_UTIL_SOURCES ${QC_UTIL_SOURCES}
set(QC_UTIL_SOURCES ${QC_UTIL_SOURCES}
util/mousetap/winmousetap.h
util/mousetap/winmousetap.cpp
util/winutils.h
util/winutils.cpp
)
endif()
if(CMAKE_SYSTEM_NAME STREQUAL "Linux")
set(QC_UTIL_SOURCES ${QC_UTIL_SOURCES}
set(QC_UTIL_SOURCES ${QC_UTIL_SOURCES}
util/mousetap/xmousetap.h
util/mousetap/xmousetap.cpp
)
endif()
if(CMAKE_SYSTEM_NAME STREQUAL "Darwin")
set(QC_UTIL_SOURCES ${QC_UTIL_SOURCES}
set(QC_UTIL_SOURCES ${QC_UTIL_SOURCES}
util/mousetap/cocoamousetap.h
util/mousetap/cocoamousetap.mm
util/path.h
Expand Down Expand Up @@ -263,6 +264,8 @@ endif()

# MacOS
if(CMAKE_SYSTEM_NAME STREQUAL "Darwin")
set(CMAKE_OSX_DEPLOYMENT_TARGET "10.15")

# copy bundle file
get_target_property(MACOS_BUNDLE_PATH ${PROJECT_NAME} RUNTIME_OUTPUT_DIRECTORY)
set(MACOS_BUNDLE_PATH ${MACOS_BUNDLE_PATH}/${PROJECT_NAME}.app/Contents)
Expand Down Expand Up @@ -310,13 +313,15 @@ if(CMAKE_SYSTEM_NAME STREQUAL "Linux")

set(THREADS_PREFER_PTHREAD_FLAG ON)
find_package(Threads REQUIRED)
include_directories(${X11_INCLUDE_DIR})

target_link_libraries(${PROJECT_NAME} PRIVATE
# qx11
Qt${QT_VERSION_MAJOR}::X11Extras
Qt${QT_VERSION_MAJOR}::CorePrivate
# xcb https://doc.qt.io/qt-5/linux-requirements.html
xcb
# pthread
${X11_LIBRARIES}
Threads::Threads
)

Expand All @@ -334,5 +339,7 @@ target_link_libraries(${PROJECT_NAME} PRIVATE
Qt${QT_VERSION_MAJOR}::Widgets
Qt${QT_VERSION_MAJOR}::Network
Qt${QT_VERSION_MAJOR}::Multimedia
Qt${QT_VERSION_MAJOR}::OpenGL
Qt${QT_VERSION_MAJOR}::OpenGLWidgets
QtScrcpyCore
)
2 changes: 1 addition & 1 deletion QtScrcpy/appversion
Original file line number Diff line number Diff line change
@@ -1 +1 @@
0.0.0
0.0.0
84 changes: 38 additions & 46 deletions QtScrcpy/audio/audiooutput.cpp
Original file line number Diff line number Diff line change
@@ -1,31 +1,37 @@
#include <QTcpSocket>
#include <QHostAddress>
#include <QAudioOutput>
#include <QTime>
#include <QAudioSink>
#include <QMediaDevices>
#include <QElapsedTimer>

#include <QProcess>
#include <QThread>
#include <QDebug>
#include <QByteArray>
#include "audiooutput.h"

AudioOutput::AudioOutput(QObject *parent)
: QObject(parent)
, m_outputDevice(nullptr)
, m_running(false)
, m_audioSink(nullptr)
{
connect(&m_sndcpy, &QProcess::readyReadStandardOutput, this, [this]() {
qInfo() << QString("AudioOutput::") << QString(m_sndcpy.readAllStandardOutput());
qInfo() << QString("AudioOutput::") << m_sndcpy.readAllStandardOutput();
});
connect(&m_sndcpy, &QProcess::readyReadStandardError, this, [this]() {
qInfo() << QString("AudioOutput::") << QString(m_sndcpy.readAllStandardError());
qInfo() << QString("AudioOutput::") << m_sndcpy.readAllStandardError();
});
}

AudioOutput::~AudioOutput()
{
if (QProcess::NotRunning != m_sndcpy.state()) {
if (m_sndcpy.state() != QProcess::NotRunning) {
m_sndcpy.kill();
}
stop();
}

bool AudioOutput::start(const QString& serial, int port)
bool AudioOutput::start(const QString &serial, int port)
{
if (m_running) {
stop();
Expand All @@ -36,7 +42,7 @@ bool AudioOutput::start(const QString& serial, int port)
bool ret = runSndcpyProcess(serial, port);
qInfo() << "AudioOutput::run sndcpy cost:" << timeConsumeCount.elapsed() << "milliseconds";
if (!ret) {
return ret;
return false;
}

startAudioOutput();
Expand Down Expand Up @@ -64,20 +70,15 @@ void AudioOutput::installonly(const QString &serial, int port)

bool AudioOutput::runSndcpyProcess(const QString &serial, int port, bool wait)
{
if (QProcess::NotRunning != m_sndcpy.state()) {
if (m_sndcpy.state() != QProcess::NotRunning) {
m_sndcpy.kill();
}

#ifdef Q_OS_WIN32
QStringList params;
params << serial;
params << QString("%1").arg(port);
QStringList params{serial, QString::number(port)};
m_sndcpy.start("sndcpy.bat", params);
#else
QStringList params;
params << "sndcpy.sh";
params << serial;
params << QString("%1").arg(port);
QStringList params{"sndcpy.sh", serial, QString::number(port)};
m_sndcpy.start("bash", params);
#endif

Expand All @@ -86,11 +87,11 @@ bool AudioOutput::runSndcpyProcess(const QString &serial, int port, bool wait)
}

if (!m_sndcpy.waitForStarted()) {
qWarning() << "AudioOutput::start sndcpy.bat failed";
qWarning() << "AudioOutput::start sndcpy process failed";
return false;
}
if (!m_sndcpy.waitForFinished()) {
qWarning() << "AudioOutput::sndcpy.bat crashed";
qWarning() << "AudioOutput::sndcpy process crashed";
return false;
}

Expand All @@ -99,41 +100,39 @@ bool AudioOutput::runSndcpyProcess(const QString &serial, int port, bool wait)

void AudioOutput::startAudioOutput()
{
if (m_audioOutput) {
if (m_audioSink) {
return;
}

QAudioFormat format;
format.setSampleRate(48000);
format.setChannelCount(2);
format.setSampleSize(16);
format.setCodec("audio/pcm");
format.setByteOrder(QAudioFormat::LittleEndian);
format.setSampleType(QAudioFormat::SignedInt);
format.setSampleFormat(QAudioFormat::Int16); // 16-bit signed integer format

QAudioDeviceInfo info(QAudioDeviceInfo::defaultOutputDevice());
if (!info.isFormatSupported(format)) {
QAudioDevice defaultDevice = QMediaDevices::defaultAudioOutput();
if (!defaultDevice.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();
m_audioSink = new QAudioSink(defaultDevice, format, this);
m_outputDevice = m_audioSink->start();
if (!m_outputDevice) {
qWarning() << "AudioOutput::failed to start audio sink.";
delete m_audioSink;
m_audioSink = nullptr;
return;
}
}

void AudioOutput::stopAudioOutput()
{
if (!m_audioOutput) {
return;
if (m_audioSink) {
m_audioSink->stop();
delete m_audioSink;
m_audioSink = nullptr;
}

m_audioOutput->stop();
delete m_audioOutput;
m_audioOutput = nullptr;
m_outputDevice = nullptr;
}

void AudioOutput::startRecvData(int port)
Expand All @@ -156,7 +155,6 @@ void AudioOutput::startRecvData(int port)
});
connect(audioSocket, &QIODevice::readyRead, audioSocket, [this, audioSocket]() {
qint64 recv = audioSocket->bytesAvailable();
//qDebug() << "AudioOutput::recv data:" << recv;

if (!m_outputDevice) {
return;
Expand All @@ -165,22 +163,16 @@ void AudioOutput::startRecvData(int port)
m_buffer.reserve(recv);
}

qint64 count = audioSocket->read(m_buffer.data(), audioSocket->bytesAvailable());
qint64 count = audioSocket->read(m_buffer.data(), recv);
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);
Expand Down
2 changes: 2 additions & 0 deletions QtScrcpy/audio/audiooutput.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
#include <QPointer>
#include <QVector>

class QAudioSink;
class QAudioOutput;
class QIODevice;
class AudioOutput : public QObject
Expand Down Expand Up @@ -36,6 +37,7 @@ class AudioOutput : public QObject
QProcess m_sndcpy;
QVector<char> m_buffer;
bool m_running = false;
QAudioSink *m_audioSink = nullptr;
};

#endif // AUDIOOUTPUT_H
Loading
Loading