diff --git a/.gitignore b/.gitignore index 5c45aba0f6ae454143c76f269e13116fc15a99ec..f90d5ba5389c95021ac38cf737b7d32493a679db 100644 --- a/.gitignore +++ b/.gitignore @@ -30,3 +30,6 @@ build-local/ # auto-gen files resources.qrc src/constant/JamiResources.qml + +# macOS +.DS_Store diff --git a/CMakeLists.txt b/CMakeLists.txt index ceb7ffa5d6a0a58be13c88286e0e17f15755020e..4f88333c39e7c5d44e0a29a201e7c6c5059c08a3 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,4 +1,4 @@ -cmake_minimum_required(VERSION 3.7) +cmake_minimum_required(VERSION 3.11) project(jami-qt) @@ -23,6 +23,18 @@ set(CMAKE_INSTALL_RPATH_USE_LINK_PATH true) set(QML_RESOURCES ${PROJECT_SOURCE_DIR}/resources.qrc) set(QML_RESOURCES_QML ${PROJECT_SOURCE_DIR}/qml.qrc) +if (APPLE) + include(FetchContent) + FetchContent_Declare( + libqrencode + GIT_REPOSITORY https://github.com/fukuchi/libqrencode.git + GIT_TAG v4.1.1 + ) + FetchContent_Populate(libqrencode) + add_subdirectory(${libqrencode_SOURCE_DIR} ${libqrencode_BINARY_DIR}) + include_directories(${libqrencode_SOURCE_DIR}) +endif() + # Resource auto-gen # check files in the resource directory and force a reconfigure if it changes file(GLOB_RECURSE @@ -253,7 +265,7 @@ if(MSVC) include_directories(${DRING_SRC_PATH} ${LRC_SRC_PATH} ${QRENCODE}) -else() +elseif (NOT APPLE) list(APPEND COMMON_SOURCES ${SRC_DIR}/xrectsel.c ${SRC_DIR}/dbuserrorhandler.cpp) @@ -335,6 +347,42 @@ else() find_library(ringclient ringclient ${LRCLIBDIR} NO_DEFAULT_PATH) find_library(qrencode qrencode) find_library(X11 X11) +else() + if(NOT DEFINED LRC) + if(EXISTS ${PROJECT_SOURCE_DIR}/../install/lrc) + set(LRC ${PROJECT_SOURCE_DIR}/../install/lrc) + endif() + endif() + if(DEFINED LRC) + if(EXISTS ${LRC}/include/libringclient) + set(LRC_SRC_PATH ${LRC}/include/libringclient) + else() + set(LRC_SRC_PATH ${LRC}/src) + endif() + if(NOT DEFINED LRCLIB) + set(LRCLIB ${LRC}) + endif() + find_library(ringclient ringclient + PATHS ${LRCLIB} + PATH_SUFFIXES lib build build-local NO_DEFAULT_PATH) + set(LRC_LIB_NAME ${ringclient}) + else() + find_package(LibRingClient REQUIRED) + if (LibRingClient_FOUND) + set(LRC_SRC_PATH ${LIB_RING_CLIENT_INCLUDE_DIR}) + set(LRC_LIB_NAME ${LIB_RING_CLIENT_LIBRARY}) + else() + message("lrc not found!") + endif() + endif() + + message("Will expect lrc headers in ${LRC_SRC_PATH}") + + include_directories(${LRC_SRC_PATH}) + + set(JAMI_DATA_PREFIX "${CMAKE_INSTALL_PREFIX}/share") + + find_library(ringclient ringclient ${LRCLIBDIR} NO_DEFAULT_PATH) endif() # Qt find package @@ -441,7 +489,7 @@ if(MSVC) # executable name set_target_properties(${PROJECT_NAME} PROPERTIES OUTPUT_NAME "Jami") -else() +elseif (NOT APPLE) target_link_libraries(${PROJECT_NAME} PRIVATE ${QML_LIBS} ${LRC_LIB_NAME} @@ -552,6 +600,33 @@ else() add_custom_target(uninstall COMMAND ${CMAKE_COMMAND} -P ${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake) +else() + target_link_libraries(${PROJECT_NAME} PRIVATE + ${QML_LIBS} + ${LRC_LIB_NAME} + qrencode) + + # translations + if(Qt${QT_VERSION_MAJOR}LinguistTools_FOUND) + message("Releasing and copying translation files") + file(MAKE_DIRECTORY "${CMAKE_BINARY_DIR}/share/ring/translations/") + file(MAKE_DIRECTORY "${CMAKE_BINARY_DIR}/share/libringclient/translations/") + file(GLOB TS_CLIENT_FILES ${PROJECT_SOURCE_DIR}/translations/*.ts) + file(GLOB TS_LRC_FILES ${LRC}/translations/*.ts) + set_source_files_properties(${TS_CLIENT_FILES} PROPERTIES OUTPUT_LOCATION + "${CMAKE_BINARY_DIR}/share/ring/translations") + set_source_files_properties(${TS_LRC_FILES} PROPERTIES OUTPUT_LOCATION + "${CMAKE_BINARY_DIR}/share/libringclient/translations") + + qt_add_translation(QM_CLIENT_FILES ${TS_CLIENT_FILES}) + qt_add_translation(QM_LRC_FILES ${TS_LRC_FILES}) + target_sources(${PROJECT_NAME} PRIVATE ${QM_CLIENT_FILES}) + target_sources(${PROJECT_NAME} PRIVATE ${QM_LRC_FILES}) + install(DIRECTORY "${CMAKE_BINARY_DIR}/share/ring/translations/" + DESTINATION ${CMAKE_INSTALL_PREFIX}/share/ring/translations) + install(DIRECTORY "${CMAKE_BINARY_DIR}/share/libringclient/translations/" + DESTINATION ${CMAKE_INSTALL_PREFIX}/share/libringclient/translations) + endif() endif() diff --git a/src/MainApplicationWindow.qml b/src/MainApplicationWindow.qml index 85e19cf722508da10e6f92ab4cfe55d679f21270..7707c398997aecac758b9ac95cc76a6fc957552b 100644 --- a/src/MainApplicationWindow.qml +++ b/src/MainApplicationWindow.qml @@ -184,7 +184,7 @@ ApplicationWindow { Connections { target: { - if (Qt.platform.os !== "windows") + if (Qt.platform.os !== "windows" && Qt.platform.os !== "macos") return DBusErrorHandler return null } @@ -214,7 +214,7 @@ ApplicationWindow { JamiQmlUtils.mainApplicationScreen = root.screen - if (Qt.platform.os !== "windows") + if (Qt.platform.os !== "windows" && Qt.platform.os !== "macos") DBusErrorHandler.setActive(true) } } diff --git a/src/connectivitymonitor.cpp b/src/connectivitymonitor.cpp index d75b6bb4fb810c1662b8241e0c5f51ffb102a859..b02410dfb2307a49d663d4741aff079a89e03de9 100644 --- a/src/connectivitymonitor.cpp +++ b/src/connectivitymonitor.cpp @@ -16,14 +16,13 @@ * along with this program. If not, see <http://www.gnu.org/licenses/>. */ -#ifndef _WIN32 +#if !defined(_WIN32) && !defined(__APPLE__) #include <glib.h> #include <gio/gio.h> #ifdef USE_LIBNM #include <NetworkManager.h> #endif #endif - #include "connectivitymonitor.h" #include <QDebug> @@ -166,25 +165,34 @@ ConnectivityMonitor::~ConnectivityMonitor() destroy(); CoUninitialize(); } - +#elif defined(Q_OS_MACOS) +ConnectivityMonitor::ConnectivityMonitor(QObject* parent) + : QObject(parent) +{} +bool +ConnectivityMonitor::isOnline() +{ + return false; +} +ConnectivityMonitor::~ConnectivityMonitor() +{ + qDebug() << "Destroying connectivity monitor"; +} #else - #ifdef USE_LIBNM static void -logConnectionInfo(NMActiveConnection *connection) +logConnectionInfo(NMActiveConnection* connection) { if (connection) { - qDebug() << "primary network connection:" - << nm_active_connection_get_uuid(connection) - << "default: " - << (nm_active_connection_get_default(connection) ? "yes" : "no"); + qDebug() << "primary network connection:" << nm_active_connection_get_uuid(connection) + << "default: " << (nm_active_connection_get_default(connection) ? "yes" : "no"); } else { qWarning() << "no primary network connection detected, check network settings"; } } static void -primaryConnectionChanged(NMClient *nm, GParamSpec*, ConnectivityMonitor * cm) +primaryConnectionChanged(NMClient* nm, GParamSpec*, ConnectivityMonitor* cm) { auto connection = nm_client_get_primary_connection(nm); logConnectionInfo(connection); @@ -192,27 +200,25 @@ primaryConnectionChanged(NMClient *nm, GParamSpec*, ConnectivityMonitor * cm) } static void -nmClientCallback(G_GNUC_UNUSED GObject *source_object, - GAsyncResult *result, - ConnectivityMonitor * cm) +nmClientCallback(G_GNUC_UNUSED GObject* source_object, GAsyncResult* result, ConnectivityMonitor* cm) { GError* error = nullptr; if (auto nm_client = nm_client_new_finish(result, &error)) { qDebug() << "NetworkManager client initialized, version: " << nm_client_get_version(nm_client) - << ", daemon running:" - << (nm_client_get_nm_running(nm_client) ? "yes" : "no") + << ", daemon running:" << (nm_client_get_nm_running(nm_client) ? "yes" : "no") << ", networking enabled:" << (nm_client_networking_get_enabled(nm_client) ? "yes" : "no"); auto connection = nm_client_get_primary_connection(nm_client); logConnectionInfo(connection); - g_signal_connect(nm_client, "notify::active-connections", - G_CALLBACK(primaryConnectionChanged), cm); + g_signal_connect(nm_client, + "notify::active-connections", + G_CALLBACK(primaryConnectionChanged), + cm); } else { - qWarning() << "error initializing NetworkManager client: " - << error->message; + qWarning() << "error initializing NetworkManager client: " << error->message; g_clear_error(&error); } } @@ -221,10 +227,9 @@ nmClientCallback(G_GNUC_UNUSED GObject *source_object, ConnectivityMonitor::ConnectivityMonitor(QObject* parent) : QObject(parent) { - - GCancellable * cancellable = g_cancellable_new(); + GCancellable* cancellable = g_cancellable_new(); #ifdef USE_LIBNM - nm_client_new_async(cancellable, (GAsyncReadyCallback)nmClientCallback, this); + nm_client_new_async(cancellable, (GAsyncReadyCallback) nmClientCallback, this); #endif } @@ -233,7 +238,6 @@ ConnectivityMonitor::~ConnectivityMonitor() qDebug() << "Destroying connectivity monitor"; } - bool ConnectivityMonitor::isOnline() { diff --git a/src/distantrenderer.cpp b/src/distantrenderer.cpp index 78f04862b16fbb6ddcdea6844305ac52e28c9251..cd45339c59ede1941fd868ac22741bda2b53c3d6 100644 --- a/src/distantrenderer.cpp +++ b/src/distantrenderer.cpp @@ -104,10 +104,18 @@ DistantRenderer::paint(QPainter* painter) if (distantImage) { painter->setRenderHint(QPainter::Antialiasing); painter->setRenderHint(QPainter::SmoothPixmapTransform); +#if defined(Q_OS_MACOS) + auto scaledDistant = distantImage + ->scaled(size().toSize(), + Qt::KeepAspectRatio, + Qt::SmoothTransformation) + .rgbSwapped(); +#else auto scaledDistant = distantImage->scaled(size().toSize(), Qt::KeepAspectRatio, Qt::SmoothTransformation); +#endif auto tempScaledWidth = static_cast<int>(scaledWidth_ * 1000); auto tempScaledHeight = static_cast<int>(scaledHeight_ * 1000); auto tempXOffset = xOffset_; diff --git a/src/mainapplication.cpp b/src/mainapplication.cpp index 23b638ad5facf5baa39362e5fc7d32cadf579467..c6b7ede9ac8c4e4f411c4e9c574b85aaf3642a48 100644 --- a/src/mainapplication.cpp +++ b/src/mainapplication.cpp @@ -189,7 +189,7 @@ MainApplication::init() connectivityMonitor_.get(), results[opts::MUTEDAEMON].toBool()); -#ifdef Q_OS_UNIX +#if defined(Q_OS_UNIX) && !defined(Q_OS_MACOS) using namespace Interfaces; GlobalInstances::setDBusErrorHandler(std::make_unique<DBusErrorHandler>()); auto dBusErrorHandlerQObject = dynamic_cast<QObject*>(&GlobalInstances::dBusErrorHandler()); diff --git a/src/previewrenderer.cpp b/src/previewrenderer.cpp index 3db0759fa6af37d723569ea9b1a84c35f43d3671..2e783710e4d506e2147e34408ee38d371781294b 100644 --- a/src/previewrenderer.cpp +++ b/src/previewrenderer.cpp @@ -69,9 +69,18 @@ PreviewRenderer::paint(QPainter* painter) // If the given size is empty, this function returns a null image. QImage scaledPreview; - scaledPreview = previewImage->scaled(size().toSize(), - Qt::KeepAspectRatio, - Qt::SmoothTransformation); +#if defined(Q_OS_MACOS) + + scaledPreview = previewImage + ->scaled(size().toSize(), + Qt::KeepAspectRatio, + Qt::SmoothTransformation) + .rgbSwapped(); +#else + scaledPreview = previewImage->scaled(size().toSize(), + Qt::KeepAspectRatio, + Qt::SmoothTransformation); +#endif painter->drawImage(QRect(0, 0, scaledPreview.width(), scaledPreview.height()), scaledPreview); } else { @@ -106,7 +115,11 @@ VideoCallPreviewRenderer::paint(QPainter* painter) / static_cast<qreal>(previewImage->width()); setProperty("previewImageScalingFactor", scalingFactor); QImage scaledPreview; - scaledPreview = previewImage->scaled(size().toSize(), Qt::KeepAspectRatio); +#if defined(Q_OS_MACOS) + scaledPreview = previewImage->scaled(size().toSize(), Qt::KeepAspectRatio).rgbSwapped(); +#else + scaledPreview = previewImage->scaled(size().toSize(), Qt::KeepAspectRatio); +#endif painter->drawImage(QRect(0, 0, scaledPreview.width(), scaledPreview.height()), scaledPreview); } @@ -130,7 +143,12 @@ QString PhotoboothPreviewRender::takePhoto(int size) { if (auto previewImage = lrcInstance_->renderer()->getPreviewFrame(get_rendererId())) { +#if defined(Q_OS_MACOS) + return Utils::byteArrayToBase64String( + Utils::QImageToByteArray(previewImage->copy().rgbSwapped())); +#else return Utils::byteArrayToBase64String(Utils::QImageToByteArray(previewImage->copy())); +#endif } return {}; } @@ -143,8 +161,15 @@ PhotoboothPreviewRender::paint(QPainter* painter) lrcInstance_->renderer()->drawFrame(get_rendererId(), [this, painter](QImage* previewImage) { if (previewImage) { QImage scaledPreview; +#if defined(Q_OS_MACOS) + scaledPreview = Utils::getCirclePhoto(*previewImage, - height() <= width() ? height() : width()); + height() <= width() ? height() : width()) + .rgbSwapped(); +#else + scaledPreview = Utils::getCirclePhoto(*previewImage, + height() <= width() ? height() : width()); +#endif painter->drawImage(QRect(0, 0, scaledPreview.width(), scaledPreview.height()), scaledPreview); }