diff --git a/CMakeLists.txt b/CMakeLists.txt index 0654f84ab754c777308ad2697d75f992432a25c4..dc4af8834d7a10f89877ebadc68fcd9225b2ffb8 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -136,7 +136,6 @@ IF (${RING_FOUND} MATCHES "true") INCLUDE_DIRECTORIES(${ring_INCLUDE_DIRS}) ENDIF() - IF(${ENABLE_VIDEO} MATCHES true) MESSAGE("VIDEO enabled") SET(ENABLE_VIDEO 1 CACHE BOOLEAN "Enable video") @@ -246,6 +245,16 @@ SET( libringclient_LIB_SRCS src/extensions/presencecollectionextension.cpp ) +IF(${ENABLE_LIBWRAP} MATCHES true) +SET(libringclient_LIB_SRCS ${libringclient_LIB_SRCS} + src/private/directrenderer.cpp +) +ELSE() +SET(libringclient_LIB_SRCS ${libringclient_LIB_SRCS} + src/private/shmrenderer.cpp +) +ENDIF(${ENABLE_LIBWRAP} MATCHES true) + # Public API SET( libringclient_LIB_HDRS src/account.h @@ -311,6 +320,7 @@ SET(libringclient_video_LIB_HDRS src/video/resolution.h src/video/channel.h src/video/rate.h + #The renderer implementations are not exported on purpose ) SET(libringclient_audio_LIB_HDRS @@ -342,22 +352,9 @@ SET( libringclient_extra_LIB_HDRS src/typedefs.hpp ) -# Include the headers for linking directly with libDring (used on platforms -# that don't have/use dbus. IF(${ENABLE_LIBWRAP} MATCHES true) - SET_SOURCE_FILES_PROPERTIES( - src/qtwrapper/presencemanager_wrap.h - PROPERTIES - CLASSNAME PresenceManagerInterface - INCLUDE "src/qtwrapper/metatypes.h") - - SET_SOURCE_FILES_PROPERTIES( - src/qtwrapper/configurationmanager_wrap.h - PROPERTIES - CLASSNAME PresenceManagerInterface - INCLUDE "src/qtwrapper/metatypes.h") -ELSE() # Use dbus to communicate with libDring +ELSE() # presence manager interface SET ( presencemanager_xml ${dbus_xml_introspecs_path}/presencemanager-introspec.xml ) @@ -450,6 +447,7 @@ SET(libringclient_PRIVATE_HDRS src/private/accountmodel_p.h src/private/phonedirectorymodel_p.h src/private/instantmessagingmodel_p.h + src/private/videorenderer_p.h ) IF(${ENABLE_LIBWRAP} MATCHES true) @@ -467,7 +465,7 @@ ENDIF() QT5_WRAP_CPP(LIB_HEADER_MOC ${libringclient_PRIVATE_HDRS}) -ADD_LIBRARY( ringclient SHARED ${libringclient_LIB_SRCS} ${LIB_HEADER_MOC} ) +ADD_LIBRARY( ringclient SHARED ${libringclient_LIB_SRCS} ${LIB_HEADER_MOC} ) IF(NOT ${ENABLE_STATIC} MATCHES false) ADD_LIBRARY( ringclient_static STATIC ${libringclient_LIB_SRCS} ${LIB_HEADER_MOC} ) diff --git a/cmake/FindRing.cmake b/cmake/FindRing.cmake index 522432638787bed4b96d3b5f46ef5345baf02877..f44506a19c30ee2683549b235599a061fc7d23eb 100644 --- a/cmake/FindRing.cmake +++ b/cmake/FindRing.cmake @@ -4,21 +4,20 @@ SET(RING_FOUND true) -IF(EXISTS ${RING_BUILD_DIR}/dring/dring.h) - SET(ring_INCLUDE_DIRS ${RING_BUILD_DIR}/dring) -ELSEIF(EXISTS ${CMAKE_INSTALL_PREFIX}/include/dring/dring.h) +IF(EXISTS ${CMAKE_INSTALL_PREFIX}/include/dring/dring.h) SET(ring_INCLUDE_DIRS ${CMAKE_INSTALL_PREFIX}/include/dring) +ELSEIF(EXISTS ${RING_BUILD_DIR}/dring/dring.h) + SET(ring_INCLUDE_DIRS ${RING_BUILD_DIR}/dring) ELSE() MESSAGE("Daemon header not found! Add -DRING_BUILD_DIR or -DCMAKE_INSTALL_PREFIX") SET(RING_FOUND false) ENDIF() - SET(CMAKE_FIND_LIBRARY_SUFFIXES ".dylib;.so;.dll") FIND_LIBRARY(ring_BIN NAMES ring PATHS ${RING_BUILD_DIR}/.libs PATHS ${CMAKE_INSTALL_PREFIX}/libexec ) -MESSAGE("-- Ring daemon header is " ${ring_INCLUDE_DIRS}/dring.h) -MESSAGE("-- Ring library path is " ${ring_BIN}) +MESSAGE("Ring daemon header is in " ${ring_INCLUDE_DIRS}) +MESSAGE("Ring library path is " ${ring_BIN}) diff --git a/src/account.cpp b/src/account.cpp index aa0d7b45e9d9fbe46252be48e57bbce071b7b816..33db2274de6200a53b3d43232a3f14efad198d54 100644 --- a/src/account.cpp +++ b/src/account.cpp @@ -122,7 +122,7 @@ Account* AccountPrivate::buildNewAccountFromAlias(const QString& alias) } a->setHostname(a->d_ptr->m_hAccountDetails[DRing::Account::ConfProperties::HOSTNAME]); a->d_ptr->setAccountProperty(DRing::Account::ConfProperties::ALIAS,alias); - a->setObjectName(a->id()); + //a->setObjectName(a->id()); return a; } @@ -929,6 +929,7 @@ bool AccountPrivate::setAccountProperty(const QString& param, const QString& val if (param == DRing::Account::ConfProperties::Registration::STATUS) { m_hAccountDetails[param] = val; if (accChanged) { + emit q_ptr->changed(q_ptr); emit q_ptr->propertyChanged(q_ptr,param,val,buf); } } @@ -937,6 +938,7 @@ bool AccountPrivate::setAccountProperty(const QString& param, const QString& val if (m_CurrentState == Account::EditState::MODIFIED || m_CurrentState == Account::EditState::NEW) { m_hAccountDetails[param] = val; if (accChanged) { + emit q_ptr->changed(q_ptr); emit q_ptr->propertyChanged(q_ptr,param,val,buf); } } @@ -1533,7 +1535,7 @@ void AccountPrivate::save() const QVector<uint> codecIdList = configurationManager.getCodecList(); foreach (const int aCodec, codecIdList) { const QMap<QString,QString> codec = configurationManager.getCodecDetails(q_ptr->id(),aCodec); - const QModelIndex idx = m_pCodecModel->add(); + const QModelIndex idx = q_ptr->codecModel()->add(); /*Ring::Account::ConfProperties::CodecInfo::NAME ; //TODO move this to CodecModel Ring::Account::ConfProperties::CodecInfo::TYPE ; Ring::Account::ConfProperties::CodecInfo::SAMPLE_RATE ; diff --git a/src/accountmodel.cpp b/src/accountmodel.cpp index f6e8ad43e914100dc3c64987bf2ddc6e590679a5..673996c2137b5b810e9d8ae7873bb622e1675286 100644 --- a/src/accountmodel.cpp +++ b/src/accountmodel.cpp @@ -337,6 +337,7 @@ void AccountModel::update() d_ptr->m_lAccounts.insert(i, a); emit dataChanged(index(i,0),index(size()-1,0)); connect(a,SIGNAL(changed(Account*)),d_ptr,SLOT(slotAccountChanged(Account*))); + //connect(a,SIGNAL(propertyChanged(Account*,QString,QString,QString)),d_ptr,SLOT(slotAccountChanged(Account*))); connect(a,SIGNAL(presenceEnabledChanged(bool)),d_ptr,SLOT(slotAccountPresenceEnabledChanged(bool))); emit layoutChanged(); } @@ -354,8 +355,11 @@ void AccountModel::updateAccounts() Account* acc = getById(accountIds[i].toLatin1()); if (!acc) { Account* a = AccountPrivate::buildExistingAccountFromId(accountIds[i].toLatin1()); + beginInsertRows(QModelIndex(),d_ptr->m_lAccounts.size(),d_ptr->m_lAccounts.size()); d_ptr->m_lAccounts += a; + endInsertRows(); connect(a,SIGNAL(changed(Account*)),d_ptr,SLOT(slotAccountChanged(Account*))); + //connect(a,SIGNAL(propertyChanged(Account*,QString,QString,QString)),d_ptr,SLOT(slotAccountChanged(Account*))); connect(a,SIGNAL(presenceEnabledChanged(bool)),d_ptr,SLOT(slotAccountPresenceEnabledChanged(bool))); emit dataChanged(index(size()-1,0),index(size()-1,0)); } @@ -450,7 +454,7 @@ void AccountModel::cancel() { * Get an account by its ID * * @note This method have O(N) complexity, but the average account count is low - * + * * @param id The account identifier * @param usePlaceHolder Return a placeholder for a future account instead of nullptr * @return an account if it exist, a placeholder if usePlaceHolder==true or nullptr @@ -578,8 +582,11 @@ Account* AccountModel::add(const QString& alias) { Account* a = AccountPrivate::buildNewAccountFromAlias(alias); connect(a,SIGNAL(changed(Account*)),d_ptr,SLOT(slotAccountChanged(Account*))); + beginInsertRows(QModelIndex(),d_ptr->m_lAccounts.size(),d_ptr->m_lAccounts.size()); d_ptr->m_lAccounts += a; + endInsertRows(); connect(a,SIGNAL(presenceEnabledChanged(bool)),d_ptr,SLOT(slotAccountPresenceEnabledChanged(bool))); + //connect(a,SIGNAL(propertyChanged(Account*,QString,QString,QString)),d_ptr,SLOT(slotAccountChanged(Account*))); emit dataChanged(index(d_ptr->m_lAccounts.size()-1,0), index(d_ptr->m_lAccounts.size()-1,0)); return a; @@ -591,9 +598,10 @@ void AccountModel::remove(Account* account) if (not account) return; qDebug() << "Removing" << account->alias() << account->id(); const int aindex = d_ptr->m_lAccounts.indexOf(account); + beginRemoveRows(QModelIndex(),aindex,aindex); d_ptr->m_lAccounts.remove(aindex); d_ptr->m_lDeletedAccounts << account->id(); - + endRemoveRows(); emit accountRemoved(account); emit dataChanged(index(aindex,0), index(d_ptr->m_lAccounts.size()-1,0)); emit layoutChanged(); diff --git a/src/accountstatusmodel.cpp b/src/accountstatusmodel.cpp index 668601d3e6d71205b069f768a99b706adc8a45fb..2f71f0c78867d192ff520380a08154d744046a9f 100644 --- a/src/accountstatusmodel.cpp +++ b/src/accountstatusmodel.cpp @@ -22,6 +22,7 @@ //Qt #include <QtCore/QCoreApplication> +#include <QtCore/QDateTime> //Ring daemon #include <account_const.h> @@ -137,21 +138,13 @@ static void init_statuscode() SET_MESSAGE(703) QObject::tr("Error sending message to destination server"); //This section match to POSIX error codes +#ifdef Q_OS_LINUX SET_MESSAGE(PJ_SYS_ERR + EBFONT ) QObject::tr("Bad font file format" ); - SET_MESSAGE(PJ_SYS_ERR + ENOSTR ) QObject::tr("Device not a stream" ); - SET_MESSAGE(PJ_SYS_ERR + ENODATA ) QObject::tr("No data available" ); - SET_MESSAGE(PJ_SYS_ERR + ETIME ) QObject::tr("Timer expired" ); - SET_MESSAGE(PJ_SYS_ERR + ENOSR ) QObject::tr("Out of streams resources" ); SET_MESSAGE(PJ_SYS_ERR + ENONET ) QObject::tr("Machine is not on the network" ); - SET_MESSAGE(PJ_SYS_ERR + ENOLINK ) QObject::tr("Link has been severed" ); SET_MESSAGE(PJ_SYS_ERR + EADV ) QObject::tr("Advertise error" ); SET_MESSAGE(PJ_SYS_ERR + ESRMNT ) QObject::tr("Srmount error" ); SET_MESSAGE(PJ_SYS_ERR + ECOMM ) QObject::tr("Communication error on send" ); - SET_MESSAGE(PJ_SYS_ERR + EPROTO ) QObject::tr("Protocol error" ); - SET_MESSAGE(PJ_SYS_ERR + EMULTIHOP ) QObject::tr("Multihop attempted" ); SET_MESSAGE(PJ_SYS_ERR + EDOTDOT ) QObject::tr("RFS specific error" ); - SET_MESSAGE(PJ_SYS_ERR + EBADMSG ) QObject::tr("Not a data message" ); - SET_MESSAGE(PJ_SYS_ERR + EOVERFLOW ) QObject::tr("Value too large for defined data type" ); SET_MESSAGE(PJ_SYS_ERR + ENOTUNIQ ) QObject::tr("Name not unique on network" ); SET_MESSAGE(PJ_SYS_ERR + EBADFD ) QObject::tr("File descriptor in bad state" ); SET_MESSAGE(PJ_SYS_ERR + EREMCHG ) QObject::tr("Remote address changed" ); @@ -159,9 +152,32 @@ static void init_statuscode() SET_MESSAGE(PJ_SYS_ERR + ELIBBAD ) QObject::tr("Accessing a corrupted shared library" ); SET_MESSAGE(PJ_SYS_ERR + ELIBMAX ) QObject::tr("Attempting to link in too many shared libraries" ); SET_MESSAGE(PJ_SYS_ERR + ELIBEXEC ) QObject::tr("Cannot exec a shared library directly" ); - SET_MESSAGE(PJ_SYS_ERR + EILSEQ ) QObject::tr("Illegal byte sequence" ); SET_MESSAGE(PJ_SYS_ERR + ERESTART ) QObject::tr("Interrupted system call should be restarted" ); SET_MESSAGE(PJ_SYS_ERR + ESTRPIPE ) QObject::tr("Streams pipe error" ); + SET_MESSAGE(PJ_SYS_ERR + EUCLEAN ) QObject::tr("Structure needs cleaning" ); + SET_MESSAGE(PJ_SYS_ERR + ENOTNAM ) QObject::tr("Not a XENIX named type file" ); + SET_MESSAGE(PJ_SYS_ERR + ENAVAIL ) QObject::tr("No XENIX semaphores available" ); + SET_MESSAGE(PJ_SYS_ERR + EISNAM ) QObject::tr("Is a named type file" ); + SET_MESSAGE(PJ_SYS_ERR + EREMOTEIO ) QObject::tr("Remote I/O error" ); + SET_MESSAGE(PJ_SYS_ERR + ENOMEDIUM ) QObject::tr("No medium found" ); + SET_MESSAGE(PJ_SYS_ERR + EMEDIUMTYPE ) QObject::tr("Wrong medium type" ); + SET_MESSAGE(PJ_SYS_ERR + ENOKEY ) QObject::tr("Required key not available" ); + SET_MESSAGE(PJ_SYS_ERR + EKEYEXPIRED ) QObject::tr("Key has expired" ); + SET_MESSAGE(PJ_SYS_ERR + EKEYREVOKED ) QObject::tr("Key has been revoked" ); + SET_MESSAGE(PJ_SYS_ERR + EKEYREJECTED ) QObject::tr("Key was rejected by service" ); + SET_MESSAGE(PJ_SYS_ERR + EDQUOT ) QObject::tr("Quota exceeded" ); + SET_MESSAGE(PJ_SYS_ERR + ECANCELED ) QObject::tr("Operation Canceled" ); +#endif + SET_MESSAGE(PJ_SYS_ERR + ENOSTR ) QObject::tr("Device not a stream" ); + SET_MESSAGE(PJ_SYS_ERR + ENODATA ) QObject::tr("No data available" ); + SET_MESSAGE(PJ_SYS_ERR + ETIME ) QObject::tr("Timer expired" ); + SET_MESSAGE(PJ_SYS_ERR + ENOSR ) QObject::tr("Out of streams resources" ); + SET_MESSAGE(PJ_SYS_ERR + ENOLINK ) QObject::tr("Link has been severed" ); + SET_MESSAGE(PJ_SYS_ERR + EPROTO ) QObject::tr("Protocol error" ); + SET_MESSAGE(PJ_SYS_ERR + EMULTIHOP ) QObject::tr("Multihop attempted" ); + SET_MESSAGE(PJ_SYS_ERR + EBADMSG ) QObject::tr("Not a data message" ); + SET_MESSAGE(PJ_SYS_ERR + EOVERFLOW ) QObject::tr("Value too large for defined data type" ); + SET_MESSAGE(PJ_SYS_ERR + EILSEQ ) QObject::tr("Illegal byte sequence" ); SET_MESSAGE(PJ_SYS_ERR + EUSERS ) QObject::tr("Too many users" ); SET_MESSAGE(PJ_SYS_ERR + ENOTSOCK ) QObject::tr("Socket operation on non-socket" ); SET_MESSAGE(PJ_SYS_ERR + EDESTADDRREQ ) QObject::tr("Destination address required" ); @@ -192,19 +208,6 @@ static void init_statuscode() SET_MESSAGE(PJ_SYS_ERR + EALREADY ) QObject::tr("Operation already in progress" ); SET_MESSAGE(PJ_SYS_ERR + EINPROGRESS ) QObject::tr("Operation now in progress" ); SET_MESSAGE(PJ_SYS_ERR + ESTALE ) QObject::tr("Stale file handle" ); - SET_MESSAGE(PJ_SYS_ERR + EUCLEAN ) QObject::tr("Structure needs cleaning" ); - SET_MESSAGE(PJ_SYS_ERR + ENOTNAM ) QObject::tr("Not a XENIX named type file" ); - SET_MESSAGE(PJ_SYS_ERR + ENAVAIL ) QObject::tr("No XENIX semaphores available" ); - SET_MESSAGE(PJ_SYS_ERR + EISNAM ) QObject::tr("Is a named type file" ); - SET_MESSAGE(PJ_SYS_ERR + EREMOTEIO ) QObject::tr("Remote I/O error" ); - SET_MESSAGE(PJ_SYS_ERR + EDQUOT ) QObject::tr("Quota exceeded" ); - SET_MESSAGE(PJ_SYS_ERR + ENOMEDIUM ) QObject::tr("No medium found" ); - SET_MESSAGE(PJ_SYS_ERR + EMEDIUMTYPE ) QObject::tr("Wrong medium type" ); - SET_MESSAGE(PJ_SYS_ERR + ECANCELED ) QObject::tr("Operation Canceled" ); - SET_MESSAGE(PJ_SYS_ERR + ENOKEY ) QObject::tr("Required key not available" ); - SET_MESSAGE(PJ_SYS_ERR + EKEYEXPIRED ) QObject::tr("Key has expired" ); - SET_MESSAGE(PJ_SYS_ERR + EKEYREVOKED ) QObject::tr("Key has been revoked" ); - SET_MESSAGE(PJ_SYS_ERR + EKEYREJECTED ) QObject::tr("Key was rejected by service" ); //The next sections represent pjproject specific errors diff --git a/src/audio/inputdevicemodel.cpp b/src/audio/inputdevicemodel.cpp index 4e3f7b9b9040c52401813ad36df2b2ff374703d9..271f579b949f8c4abdfbfe168973e4fca01e87a9 100644 --- a/src/audio/inputdevicemodel.cpp +++ b/src/audio/inputdevicemodel.cpp @@ -17,6 +17,9 @@ ***************************************************************************/ #include "inputdevicemodel.h" +//Qt +#include <QtCore/QItemSelectionModel> + //Ring #include "dbus/configurationmanager.h" #include "settings.h" @@ -27,12 +30,14 @@ class InputDeviceModelPrivate : public QObject public: InputDeviceModelPrivate(Audio::InputDeviceModel* parent); QStringList m_lDeviceList; + mutable QItemSelectionModel* m_pSelectionModel; private: Audio::InputDeviceModel* q_ptr; }; -InputDeviceModelPrivate::InputDeviceModelPrivate(Audio::InputDeviceModel* parent) : q_ptr(parent) +InputDeviceModelPrivate::InputDeviceModelPrivate(Audio::InputDeviceModel* parent) : q_ptr(parent), + m_pSelectionModel(nullptr) { } @@ -59,7 +64,7 @@ d_ptr(new InputDeviceModelPrivate(this)) ///Destructor Audio::InputDeviceModel::~InputDeviceModel() { - + } ///Re-implement QAbstractListModel data @@ -98,15 +103,18 @@ bool Audio::InputDeviceModel::setData( const QModelIndex& index, const QVariant return false; } -///Return the current input device index -QModelIndex Audio::InputDeviceModel::currentDevice() const +QItemSelectionModel* Audio::InputDeviceModel::selectionModel() const { - ConfigurationManagerInterface& configurationManager = DBus::ConfigurationManager::instance(); - const QStringList currentDevices = configurationManager.getCurrentAudioDevicesIndex(); - const int idx = currentDevices[static_cast<int>(Settings::DeviceIndex::INPUT)].toInt(); - if (idx >= d_ptr->m_lDeviceList.size()) - return QModelIndex(); - return index(idx,0); + if (!d_ptr->m_pSelectionModel) { + d_ptr->m_pSelectionModel = new QItemSelectionModel(const_cast<Audio::InputDeviceModel*>(this)); + + ConfigurationManagerInterface& configurationManager = DBus::ConfigurationManager::instance(); + const QStringList currentDevices = configurationManager.getCurrentAudioDevicesIndex(); + const int idx = currentDevices[static_cast<int>(Settings::DeviceIndex::INPUT)].toInt(); + if (!(idx >= d_ptr->m_lDeviceList.size())) + d_ptr->m_pSelectionModel->setCurrentIndex(index(idx,0), QItemSelectionModel::ClearAndSelect); + } + return d_ptr->m_pSelectionModel; } ///Set the current input device diff --git a/src/audio/inputdevicemodel.h b/src/audio/inputdevicemodel.h index 91d3adb3a0f8d3eda41ef614ec4b4191eccd44ae..d217675878f5929fdc7b5368d292072bf9831e4b 100644 --- a/src/audio/inputdevicemodel.h +++ b/src/audio/inputdevicemodel.h @@ -22,6 +22,7 @@ //Qt #include <QtCore/QStringList> +class QItemSelectionModel; //Ring #include <typedefs.h> @@ -44,7 +45,7 @@ public: virtual QHash<int,QByteArray> roleNames() const override; //Getters - QModelIndex currentDevice() const; + QItemSelectionModel* selectionModel() const; //Setters void setCurrentDevice(const QModelIndex& index); diff --git a/src/audio/outputdevicemodel.cpp b/src/audio/outputdevicemodel.cpp index 9a4daa8081ee8f88a552f2d8f3c3c91179754d4f..ae8396230e2b7d09bbc5eb6389b9c1f5abe9f9aa 100644 --- a/src/audio/outputdevicemodel.cpp +++ b/src/audio/outputdevicemodel.cpp @@ -17,6 +17,9 @@ ***************************************************************************/ #include "outputdevicemodel.h" +//Qt +#include <QtCore/QItemSelectionModel> + //Ring #include "dbus/configurationmanager.h" #include "dbus/callmanager.h" @@ -28,13 +31,15 @@ class OutputDeviceModelPrivate : public QObject public: OutputDeviceModelPrivate(Audio::OutputDeviceModel* parent); QStringList m_lDeviceList; + mutable QItemSelectionModel* m_pSelectionModel; private: Audio::OutputDeviceModel* q_ptr; }; -OutputDeviceModelPrivate::OutputDeviceModelPrivate(Audio::OutputDeviceModel* parent) : q_ptr(parent) +OutputDeviceModelPrivate::OutputDeviceModelPrivate(Audio::OutputDeviceModel* parent) : q_ptr(parent), + m_pSelectionModel(nullptr) { } @@ -100,16 +105,17 @@ bool Audio::OutputDeviceModel::setData( const QModelIndex& index, const QVariant return false; } -///Return the current output device -QModelIndex Audio::OutputDeviceModel::currentDevice() const +QItemSelectionModel* Audio::OutputDeviceModel::selectionModel() const { - ConfigurationManagerInterface& configurationManager = DBus::ConfigurationManager::instance(); - const QStringList currentDevices = configurationManager.getCurrentAudioDevicesIndex(); - const int idx = currentDevices[static_cast<int>(Audio::Settings::DeviceIndex::OUTPUT)].toInt(); - - if (idx >= d_ptr->m_lDeviceList.size()) - return QModelIndex(); - return index(idx,0); + if (!d_ptr->m_pSelectionModel) { + d_ptr->m_pSelectionModel = new QItemSelectionModel(const_cast<Audio::OutputDeviceModel*>(this)); + ConfigurationManagerInterface& configurationManager = DBus::ConfigurationManager::instance(); + const QStringList currentDevices = configurationManager.getCurrentAudioDevicesIndex(); + const int idx = currentDevices[static_cast<int>(Audio::Settings::DeviceIndex::OUTPUT)].toInt(); + if (!(idx >= d_ptr->m_lDeviceList.size())) + d_ptr->m_pSelectionModel->setCurrentIndex(index(idx,0), QItemSelectionModel::ClearAndSelect); + } + return d_ptr->m_pSelectionModel; } ///Set the current output device diff --git a/src/audio/outputdevicemodel.h b/src/audio/outputdevicemodel.h index 61fb033d1bf85457dc66c61101e468f6763d4fd7..06c523f0e8ee331639650908e5c20671393da349 100644 --- a/src/audio/outputdevicemodel.h +++ b/src/audio/outputdevicemodel.h @@ -22,6 +22,7 @@ //Qt #include <QtCore/QStringList> +class QItemSelectionModel; //Ring #include <typedefs.h> @@ -44,7 +45,7 @@ public: virtual QHash<int,QByteArray> roleNames() const override; //Getters - QModelIndex currentDevice() const; + QItemSelectionModel* selectionModel() const; //Setters void setCurrentDevice(const QModelIndex& index); diff --git a/src/call.cpp b/src/call.cpp index 1ef09c03a13418d059ae8e6544738ad4b9ab4f4c..25a14585861b1aefd7274c7642b8f9794f22a0a5 100644 --- a/src/call.cpp +++ b/src/call.cpp @@ -26,6 +26,7 @@ //Qt #include <QtCore/QFile> #include <QtCore/QTimer> +#include <QtCore/QDateTime> //DRing #include <account_const.h> @@ -1311,7 +1312,7 @@ void CallPrivate::call() m_pDialNumber = nullptr; } else { - qDebug() << "Trying to call " << (m_pTransferNumber?QString(m_pTransferNumber->uri()):"ERROR") + qDebug() << "Trying to call " << (m_pTransferNumber?QString(m_pTransferNumber->uri()):"ERROR") << " with no account registered . callId : " << q_ptr << "ConfId:" << q_ptr; this->m_HistoryState = Call::LegacyHistoryState::NONE; throw tr("No account registered!"); diff --git a/src/call.h b/src/call.h index 2410a3d2eecd83b7fa5bd7e2884441727fd1a18a..87ea78d7ca99faddb7ffcd812db1d4cd17fc35bf 100644 --- a/src/call.h +++ b/src/call.h @@ -38,8 +38,8 @@ class ContactMethod; class TemporaryContactMethod; class CollectionInterface; namespace Video { - class Renderer; class Manager; + class Renderer; } class Call; @@ -241,7 +241,7 @@ public: Q_PROPERTY( uint stopTimeStamp READ stopTimeStamp ) Q_PROPERTY( uint startTimeStamp READ startTimeStamp ) Q_PROPERTY( bool isSecure READ isSecure ) - Q_PROPERTY( Video::Renderer* videoRenderer READ videoRenderer ) + Q_PROPERTY( Video::Renderer* videoRenderer READ videoRenderer ) Q_PROPERTY( QString formattedName READ formattedName ) Q_PROPERTY( QString length READ length ) Q_PROPERTY( bool hasRecording READ hasRecording ) diff --git a/src/certificate.cpp b/src/certificate.cpp index 7f688c9c2ae76f2764f63d658488d4a584a020d6..3b11201ffcd30a0f41a55e45ea03626abb93f001 100644 --- a/src/certificate.cpp +++ b/src/certificate.cpp @@ -19,6 +19,7 @@ //Qt #include <QtCore/QFile> +#include <QtCore/QDateTime> //Ring daemon #include <security_const.h> diff --git a/src/codecmodel.cpp b/src/codecmodel.cpp index 918c653c6a8363e05ec4311bfc01039e295f425b..d66ea0a200d4b225a295069c72a1871a85f3aef5 100644 --- a/src/codecmodel.cpp +++ b/src/codecmodel.cpp @@ -20,6 +20,7 @@ //Qt #include <QtCore/QDebug> #include <QtCore/QCoreApplication> +#include <QtCore/QSortFilterProxyModel> //DRing #include <account_const.h> @@ -39,12 +40,15 @@ public: QString name ; QString bitrate ; QString samplerate; + QString type ; }; //Attributes QList<AudioCodecData*> m_lAudioCodecs ; QMap<int,bool> m_lEnabledCodecs; Account* m_pAccount ; + QSortFilterProxyModel* m_pAudioProxy ; + QSortFilterProxyModel* m_pVideoProxy ; //Helpers bool findCodec(int id); @@ -53,9 +57,10 @@ private: CodecModel* q_ptr; }; -CodecModelPrivate::CodecModelPrivate(CodecModel* parent) : q_ptr(parent) +CodecModelPrivate::CodecModelPrivate(CodecModel* parent) : q_ptr(parent), +m_pAudioProxy(nullptr),m_pVideoProxy(nullptr) { - + } ///Constructor @@ -85,6 +90,7 @@ QHash<int,QByteArray> CodecModel::roleNames() const roles.insert(CodecModel::Role::NAME ,QByteArray("name")); roles.insert(CodecModel::Role::BITRATE ,QByteArray("bitrate")); roles.insert(CodecModel::Role::SAMPLERATE,QByteArray("samplerate")); + roles.insert(CodecModel::Role::TYPE ,QByteArray("type")); } return roles; } @@ -109,6 +115,9 @@ QVariant CodecModel::data(const QModelIndex& idx, int role) const { else if (idx.column() == 0 && role == CodecModel::Role::ID ) { return d_ptr->m_lAudioCodecs[idx.row()]->id; } + else if (idx.column() == 0 && role == CodecModel::Role::TYPE ) { + return d_ptr->m_lAudioCodecs[idx.row()]->type; + } return QVariant(); } @@ -152,6 +161,11 @@ bool CodecModel::setData( const QModelIndex& idx, const QVariant &value, int rol emit dataChanged(idx, idx); return true; } + else if (idx.column() == 0 && role == CodecModel::TYPE) { + d_ptr->m_lAudioCodecs[idx.row()]->type = value.toString(); + emit dataChanged(idx, idx); + return true; + } return false; } @@ -224,11 +238,14 @@ void CodecModel::reload() foreach (const int aCodec, activeCodecList) { if (!d_ptr->findCodec(aCodec)) { + const QMap<QString,QString> codec = configurationManager.getCodecDetails(d_ptr->m_pAccount->id(),aCodec); + QModelIndex idx = add(); setData(idx,codec[ DRing::Account::ConfProperties::CodecInfo::NAME ] ,CodecModel::Role::NAME ); setData(idx,codec[ DRing::Account::ConfProperties::CodecInfo::SAMPLE_RATE ] ,CodecModel::Role::SAMPLERATE ); setData(idx,codec[ DRing::Account::ConfProperties::CodecInfo::BITRATE ] ,CodecModel::Role::BITRATE ); + setData(idx,codec[ DRing::Account::ConfProperties::CodecInfo::TYPE ] ,CodecModel::Role::TYPE ); setData(idx,QString::number(aCodec) ,CodecModel::Role::ID ); setData(idx, Qt::Checked ,Qt::CheckStateRole ); @@ -245,6 +262,7 @@ void CodecModel::reload() setData(idx,codec[ DRing::Account::ConfProperties::CodecInfo::NAME ] ,CodecModel::Role::NAME ); setData(idx,codec[ DRing::Account::ConfProperties::CodecInfo::SAMPLE_RATE ] ,CodecModel::Role::SAMPLERATE ); setData(idx,codec[ DRing::Account::ConfProperties::CodecInfo::BITRATE ] ,CodecModel::Role::BITRATE ); + setData(idx,codec[ DRing::Account::ConfProperties::CodecInfo::TYPE ] ,CodecModel::Role::TYPE ); setData(idx,QString::number(aCodec) ,CodecModel::Role::ID ); setData(idx, Qt::Unchecked ,Qt::CheckStateRole); } @@ -276,4 +294,27 @@ bool CodecModelPrivate::findCodec(int id) return false; } + +QSortFilterProxyModel* CodecModel::audioCodecs() const +{ + if (!d_ptr->m_pAudioProxy) { + d_ptr->m_pAudioProxy = new QSortFilterProxyModel(const_cast<CodecModel*>(this)); + d_ptr->m_pAudioProxy->setSourceModel(const_cast<CodecModel*>(this)); + d_ptr->m_pAudioProxy->setFilterRole(CodecModel::Role::TYPE); + d_ptr->m_pAudioProxy->setFilterFixedString("AUDIO"); + } + return d_ptr->m_pAudioProxy; +} + +QSortFilterProxyModel* CodecModel::videoCodecs() const +{ + if (!d_ptr->m_pVideoProxy) { + d_ptr->m_pVideoProxy = new QSortFilterProxyModel(const_cast<CodecModel*>(this)); + d_ptr->m_pVideoProxy->setSourceModel(const_cast<CodecModel*>(this)); + d_ptr->m_pVideoProxy->setFilterRole(CodecModel::Role::TYPE); + d_ptr->m_pVideoProxy->setFilterFixedString("VIDEO"); + } + return d_ptr->m_pVideoProxy; +} + #include <codecmodel.moc> diff --git a/src/codecmodel.h b/src/codecmodel.h index 7e361f2d6b58fa0218ea962c6658e137eb92bec3..7413ebdaf26b973a575ee545d1b78e2a1d410ac3 100644 --- a/src/codecmodel.h +++ b/src/codecmodel.h @@ -22,6 +22,7 @@ //Qt #include <QtCore/QString> +class QSortFilterProxyModel; //Ring #include <typedefs.h> @@ -46,6 +47,7 @@ public: NAME = 100, BITRATE = 101, SAMPLERATE = 102, + TYPE = 104, }; //Abstract model member @@ -55,6 +57,10 @@ public: virtual bool setData (const QModelIndex& index, const QVariant &value, int role ) override; virtual QHash<int,QByteArray> roleNames() const override; + //Proxies + QSortFilterProxyModel* audioCodecs() const; + QSortFilterProxyModel* videoCodecs() const; + //Mutator QModelIndex add(); Q_INVOKABLE void remove ( const QModelIndex& idx ); diff --git a/src/collectionmanagerinterface.h b/src/collectionmanagerinterface.h index 7611d2cd03f8be47061c78f8dc74966853ecbb52..7ead6bc40f9c2a4bdc1464781979907e49192e22 100644 --- a/src/collectionmanagerinterface.h +++ b/src/collectionmanagerinterface.h @@ -80,6 +80,13 @@ public: explicit CollectionManagerInterface(QAbstractItemModel* self); virtual ~CollectionManagerInterface() {}; +#ifdef Q_OS_DARWIN + /* + * Issue with LLVM 3.5svn shipped in Mac OSX with variadic template + */ + template <class T2> + T2* addBackend(const LoadOptions options = LoadOptions::NONE); +#else /** * This method is used to add a collection to a model. The LoadOptions * can be used to enforce some parameters. Please note this function is @@ -93,6 +100,7 @@ public: */ template <class T2, typename ...Ts> T2* addBackend(Ts... args, const LoadOptions options = LoadOptions::NONE); +#endif // Q_OS_DARWIN /// Do this manager have active collections virtual bool hasEnabledCollections (CollectionInterface::SupportedFeatures features = CollectionInterface::SupportedFeatures::NONE) const final; diff --git a/src/collectionmanagerinterface.hpp b/src/collectionmanagerinterface.hpp index d9e0831492e0aec49784cec9d0876413b632fbcd..d196fce8bcd974833062d0b65fadb22ab2bcbe5c 100644 --- a/src/collectionmanagerinterface.hpp +++ b/src/collectionmanagerinterface.hpp @@ -53,6 +53,28 @@ CollectionManagerInterfacePrivate<T>::~CollectionManagerInterfacePrivate() } template<class T> +#ifdef Q_OS_DARWIN +template <class T2> +T2* CollectionManagerInterface<T>::addBackend(const LoadOptions options) +{ + T2* backend = new T2(d_ptr->itemMediator()); + + //This will force the T2 to be a CollectionInterface subclass + CollectionInterface* b = backend; + d_ptr->m_lCollections << b; + + if (options & LoadOptions::FORCE_ENABLED) { //TODO check is the backend is checked + + //Some backends can fail to load directly + //eventually it will necessary to add an async version of this + //to load the backend only when it is loaded + if (backend->load()) + d_ptr->m_lEnabledCollections << backend; + } + + return backend; +} +#else template <class T2, typename ...Ts> T2* CollectionManagerInterface<T>::addBackend(Ts... args, const LoadOptions options) { @@ -73,6 +95,7 @@ T2* CollectionManagerInterface<T>::addBackend(Ts... args, const LoadOptions opti return collection; } +#endif //Q_OS_DARWIN template<class T> CollectionManagerInterface<T>::CollectionManagerInterface(QAbstractItemModel* self) : d_ptr(new CollectionManagerInterfacePrivate<T>(self,this)) diff --git a/src/dbus/configurationmanager.cpp b/src/dbus/configurationmanager.cpp index bf51e1da227687753329414c1099352c505b9830..348321f5a058adcc86146d792dd383ac35ef929d 100644 --- a/src/dbus/configurationmanager.cpp +++ b/src/dbus/configurationmanager.cpp @@ -18,10 +18,6 @@ ***************************************************************************/ #include "configurationmanager.h" -#ifdef ENABLE_LIBWRAP -#include "callbacks.h" -#endif - ConfigurationManagerInterface* DBus::ConfigurationManager::interface = nullptr; ConfigurationManagerInterface& DBus::ConfigurationManager::instance() diff --git a/src/dbus/metatypes.h b/src/dbus/metatypes.h index f49f956e70096c30ee5a6420ce1eead108faf341..5afb03e5b586671468196e064c259232c49aa178 100644 --- a/src/dbus/metatypes.h +++ b/src/dbus/metatypes.h @@ -24,24 +24,18 @@ #include <QVector> #include <QtCore/QString> +#include "../typedefs.h" + #ifndef ENABLE_LIBWRAP #include <QtDBus/QtDBus> #endif #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wzero-as-null-pointer-constant" -typedef QMap<QString, QString> MapStringString; -typedef QMap<QString, int> MapStringInt; -typedef QVector<int> VectorInt; -typedef QVector<uint> VectorUInt; -typedef QVector< QMap<QString, QString> > VectorMapStringString; -typedef QVector< QString > VectorString; -typedef QMap< QString, QMap< QString, QVector<QString> > > MapStringMapStringVectorString; -typedef QMap< QString, QVector<QString> > MapStringVectorString; Q_DECLARE_METATYPE(MapStringString) Q_DECLARE_METATYPE(MapStringInt) Q_DECLARE_METATYPE(VectorMapStringString) -Q_DECLARE_METATYPE(MapStringMapStringVectorString) +Q_DECLARE_METATYPE(MapStringMapStringStringList) Q_DECLARE_METATYPE(VectorInt) Q_DECLARE_METATYPE(VectorUInt) Q_DECLARE_METATYPE(VectorString) @@ -50,14 +44,14 @@ Q_DECLARE_METATYPE(MapStringVectorString) #ifndef ENABLE_LIBWRAP static bool dbus_metaTypeInit = false; inline void registerCommTypes() { - qDBusRegisterMetaType<MapStringString>(); - qDBusRegisterMetaType<MapStringInt>(); - qDBusRegisterMetaType<VectorMapStringString>(); - qDBusRegisterMetaType<MapStringMapStringVectorString>(); - qDBusRegisterMetaType<VectorInt>(); - qDBusRegisterMetaType<VectorUInt>(); - qDBusRegisterMetaType<VectorString>(); - qDBusRegisterMetaType<MapStringVectorString>(); + qDBusRegisterMetaType<MapStringString> (); + qDBusRegisterMetaType<MapStringInt> (); + qDBusRegisterMetaType<VectorMapStringString> (); + qDBusRegisterMetaType<MapStringMapStringVectorString>(); + qDBusRegisterMetaType<VectorInt> (); + qDBusRegisterMetaType<VectorUInt> (); + qDBusRegisterMetaType<VectorString> (); + qDBusRegisterMetaType<MapStringVectorString> (); dbus_metaTypeInit = true; } #else diff --git a/src/private/directrenderer.cpp b/src/private/directrenderer.cpp new file mode 100644 index 0000000000000000000000000000000000000000..e5611ccac020a7d0f90ff410122b9221c1793036 --- /dev/null +++ b/src/private/directrenderer.cpp @@ -0,0 +1,83 @@ +/**************************************************************************** + * Copyright (C) 2012-2015 by Savoir-Faire Linux * + * Author : Alexandre Lision <alexandre.lision@savoirfairelinux.com> * + * * + * This library is free software; you can redistribute it and/or * + * modify it under the terms of the GNU Lesser General Public * + * License as published by the Free Software Foundation; either * + * version 2.1 of the License, or (at your option) any later version. * + * * + * This library is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program. If not, see <http://www.gnu.org/licenses/>. * + ***************************************************************************/ +#include "directrenderer.h" + +#include <QtCore/QDebug> +#include <QtCore/QMutex> +#include <QtCore/QThread> +#include <QtCore/QTime> + + +#ifndef CLOCK_REALTIME +#define CLOCK_REALTIME 0 +#endif + +#include "video/manager.h" +#include "video/resolution.h" +#include "private/videorenderer_p.h" + +namespace Video { + +class DirectRendererPrivate : public QObject +{ + Q_OBJECT +public: + DirectRendererPrivate(Video::DirectRenderer* parent); + + //Attributes + +private: + Video::DirectRenderer* q_ptr; + +}; + +} + + + +Video::DirectRendererPrivate::DirectRendererPrivate(Video::DirectRenderer* parent) : QObject(parent), q_ptr(parent) +{ +} + +///Constructor +Video::DirectRenderer::DirectRenderer(const QByteArray& id, const QSize& res): Renderer(id, res), d_ptr(new DirectRendererPrivate(this)) +{ + setObjectName("Video::DirectRenderer:"+id); + + + //DBusVideoManager::instance().registerFrameListener("local", [this] { +// qDebug() << "RECEIVED FRAME"; + // }); + +} + +///Destructor +Video::DirectRenderer::~DirectRenderer() +{ +} + +void Video::DirectRenderer::startRendering() +{ + +} +void Video::DirectRenderer::stopRendering () +{ + +} + +#include <directrenderer.moc> diff --git a/src/private/directrenderer.h b/src/private/directrenderer.h new file mode 100644 index 0000000000000000000000000000000000000000..c59d5d21f33799a36637fc61782d70cf1aecf802 --- /dev/null +++ b/src/private/directrenderer.h @@ -0,0 +1,59 @@ +/**************************************************************************** + * Copyright (C) 2012-2015 by Savoir-Faire Linux * + * Author : Alexandre Lision <alexandre.lision@savoirfairelinux.com> * + * * + * This library is free software; you can redistribute it and/or * + * modify it under the terms of the GNU Lesser General Public * + * License as published by the Free Software Foundation; either * + * version 2.1 of the License, or (at your option) any later version. * + * * + * This library is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program. If not, see <http://www.gnu.org/licenses/>. * + ***************************************************************************/ +#ifndef VIDEO_DIRECT_RENDERER_H +#define VIDEO_DIRECT_RENDERER_H + +//Base +#include <QtCore/QObject> +#include "typedefs.h" +#include "video/renderer.h" + +//Qt +class QMutex; + +//Ring +#include "video/device.h" + + +namespace Video { +class DirectRendererPrivate; + +///Manage shared memory and convert it to QByteArray +class LIB_EXPORT DirectRenderer : public Renderer { + #pragma GCC diagnostic push + #pragma GCC diagnostic ignored "-Wzero-as-null-pointer-constant" + Q_OBJECT + #pragma GCC diagnostic pop + + public: + //Constructor + DirectRenderer (const QByteArray& id, const QSize& res); + virtual ~DirectRenderer(); + + virtual void startRendering() override; + virtual void stopRendering () override; + + private: + QScopedPointer<DirectRendererPrivate> d_ptr; + Q_DECLARE_PRIVATE(DirectRenderer) + +}; + +} + +#endif diff --git a/src/private/shmrenderer.cpp b/src/private/shmrenderer.cpp new file mode 100644 index 0000000000000000000000000000000000000000..44e4ef10696d72fc55eb8183a84341f6a330e4de --- /dev/null +++ b/src/private/shmrenderer.cpp @@ -0,0 +1,369 @@ +/**************************************************************************** + * Copyright (C) 2012-2015 by Savoir-Faire Linux * + * Author : Emmanuel Lepage Vallee <emmanuel.lepage@savoirfairelinux.com> * + * * + * This library is free software; you can redistribute it and/or * + * modify it under the terms of the GNU Lesser General Public * + * License as published by the Free Software Foundation; either * + * version 2.1 of the License, or (at your option) any later version. * + * * + * This library is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program. If not, see <http://www.gnu.org/licenses/>. * + ***************************************************************************/ +#include "shmrenderer.h" + +#include <QtCore/QDebug> +#include <QtCore/QMutex> +#include <QtCore/QThread> +#include <QtCore/QTime> + +#include <sys/ipc.h> +#include <sys/sem.h> +#include <sys/shm.h> +#include <fcntl.h> +#include <unistd.h> +#include <sys/mman.h> +#include <semaphore.h> +#include <errno.h> + + +#ifndef CLOCK_REALTIME +#define CLOCK_REALTIME 0 +#endif + +#include <QtCore/QTimer> +#include "video/manager.h" +#include "video/resolution.h" +#include "private/videorenderer_p.h" + +///Shared memory object +struct SHMHeader{ + sem_t notification; + sem_t mutex; + + unsigned m_BufferGen; + int m_BufferSize; + /* The header will be aligned on 16-byte boundaries */ + char padding[8]; + +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-pedantic" + char m_Data[]; +#pragma GCC diagnostic pop +}; + +namespace Video { + +class ShmRendererPrivate : public QObject +{ + Q_OBJECT +public: + ShmRendererPrivate(Video::ShmRenderer* parent); + + //Attributes + QString m_ShmPath ; + int fd ; + SHMHeader* m_pShmArea ; + signed int m_ShmAreaLen ; + uint m_BufferGen ; + QTimer* m_pTimer ; + QMutex* m_pSSMutex ; + int m_fpsC ; + int m_Fps ; + QTime m_CurrentTime; + + //Constants + static const int TIMEOUT_SEC = 1; // 1 second + + //Helpers + timespec createTimeout(); + bool shmLock (); + void shmUnlock (); + bool renderToBitmap(); + +private: + Video::ShmRenderer* q_ptr; + +private Q_SLOTS: + void timedEvents(); +}; + +} + +Video::ShmRendererPrivate::ShmRendererPrivate(Video::ShmRenderer* parent) : QObject(parent), q_ptr(parent), + fd(-1),m_fpsC(0),m_Fps(0), + m_pShmArea((SHMHeader*)MAP_FAILED), m_ShmAreaLen(0), m_BufferGen(0), + m_pTimer(nullptr),m_pSSMutex(new QMutex()) +{ +} + +///Constructor +Video::ShmRenderer::ShmRenderer(const QByteArray& id, const QString& shmPath, const QSize& res): Renderer(id, res), d_ptr(new ShmRendererPrivate(this)) +{ + d_ptr->m_ShmPath = shmPath; + setObjectName("Video::Renderer:"+id); +} + +///Destructor +Video::ShmRenderer::~ShmRenderer() +{ + stopShm(); + //delete m_pShmArea; +} + +///Get the data from shared memory and transform it into a QByteArray +bool Video::ShmRendererPrivate::renderToBitmap() +{ +#ifdef Q_OS_LINUX + if (!q_ptr->isRendering()) { + return false; + } + + if (!shmLock()) { + return false; + } + + if(!Video::Manager::instance()->startStopMutex()->tryLock()) + return false; + + // wait for a new buffer + while (m_BufferGen == m_pShmArea->m_BufferGen) { + shmUnlock(); + + int err = sem_trywait(&m_pShmArea->notification); + // Useful for debugging +// switch (errno ) { +// case EINTR: +// qDebug() << "Unlock failed: Interrupted function call (POSIX.1); see signal(7)"; +// ok = false; +// return QByteArray(); +// break; +// case EINVAL: +// qDebug() << "Unlock failed: Invalid argument (POSIX.1)"; +// ok = false; +// return QByteArray(); +// break; +// case EAGAIN: +// qDebug() << "Unlock failed: Resource temporarily unavailable (may be the same value as EWOULDBLOCK) (POSIX.1)"; +// ok = false; +// return QByteArray(); +// break; +// case ETIMEDOUT: +// qDebug() << "Unlock failed: Connection timed out (POSIX.1)"; +// ok = false; +// return QByteArray(); +// break; +// } + if ((err < 0) || (!shmLock())) { + Video::Manager::instance()->startStopMutex()->unlock(); + return false; + } + usleep((1/60.0)*100); + } + + if (!q_ptr->resizeShm()) { + qDebug() << "Could not resize shared memory"; + Video::Manager::instance()->startStopMutex()->unlock(); + return false; + } + + if (static_cast<Video::Renderer*>(q_ptr)->d_ptr->otherFrame().size() != m_pShmArea->m_BufferSize) + static_cast<Video::Renderer*>(q_ptr)->d_ptr->otherFrame().resize(m_pShmArea->m_BufferSize); + memcpy(static_cast<Video::Renderer*>(q_ptr)->d_ptr->otherFrame().data(),m_pShmArea->m_Data,m_pShmArea->m_BufferSize); + m_BufferGen = m_pShmArea->m_BufferGen; + shmUnlock(); + static_cast<Video::Renderer*>(q_ptr)->d_ptr->updateFrameIndex(); + + Video::Manager::instance()->startStopMutex()->unlock(); + return true; +#else + return false; +#endif +} + +///Connect to the shared memory +bool Video::ShmRenderer::startShm() +{ + if (d_ptr->fd != -1) { + qDebug() << "fd must be -1"; + return false; + } + + d_ptr->fd = shm_open(d_ptr->m_ShmPath.toLatin1(), O_RDWR, 0); + if (d_ptr->fd < 0) { + qDebug() << "could not open shm area " << d_ptr->m_ShmPath << ", shm_open failed:" << strerror(errno); + return false; + } + d_ptr->m_ShmAreaLen = sizeof(SHMHeader); + #pragma GCC diagnostic push + #pragma GCC diagnostic ignored "-Wzero-as-null-pointer-constant" + d_ptr->m_pShmArea = (SHMHeader*) mmap(NULL, d_ptr->m_ShmAreaLen, PROT_READ | PROT_WRITE, MAP_SHARED, d_ptr->fd, 0); + #pragma GCC diagnostic pop + if (d_ptr->m_pShmArea == MAP_FAILED) { + qDebug() << "Could not map shm area, mmap failed"; + return false; + } + emit started(); + return true; +} + +///Disconnect from the shared memory +void Video::ShmRenderer::stopShm() +{ + if (d_ptr->fd >= 0) + close(d_ptr->fd); + d_ptr->fd = -1; + + if (d_ptr->m_pShmArea != MAP_FAILED) + munmap(d_ptr->m_pShmArea, d_ptr->m_ShmAreaLen); + d_ptr->m_ShmAreaLen = 0; + d_ptr->m_pShmArea = (SHMHeader*) MAP_FAILED; +} + +///Resize the shared memory +bool Video::ShmRenderer::resizeShm() +{ + while (( (unsigned int) sizeof(SHMHeader) + (unsigned int) d_ptr->m_pShmArea->m_BufferSize) > (unsigned int) d_ptr->m_ShmAreaLen) { + const size_t new_size = sizeof(SHMHeader) + d_ptr->m_pShmArea->m_BufferSize; + + d_ptr->shmUnlock(); + if (munmap(d_ptr->m_pShmArea, d_ptr->m_ShmAreaLen)) { + qDebug() << "Could not unmap shared area:" << strerror(errno); + return false; + } + + #pragma GCC diagnostic push + #pragma GCC diagnostic ignored "-Wzero-as-null-pointer-constant" + d_ptr->m_pShmArea = (SHMHeader*) mmap(NULL, new_size, PROT_READ | PROT_WRITE, MAP_SHARED, d_ptr->fd, 0); + #pragma GCC diagnostic pop + d_ptr->m_ShmAreaLen = new_size; + + if (!d_ptr->m_pShmArea) { + d_ptr->m_pShmArea = nullptr; + qDebug() << "Could not remap shared area"; + return false; + } + + d_ptr->m_ShmAreaLen = new_size; + if (!d_ptr->shmLock()) + return true; + } + return true; +} + +///Lock the memory while the copy is being made +bool Video::ShmRendererPrivate::shmLock() +{ +#ifdef Q_OS_LINUX + return sem_trywait(&m_pShmArea->mutex) >= 0; +#else + return false; +#endif +} + +///Remove the lock, allow a new frame to be drawn +void Video::ShmRendererPrivate::shmUnlock() +{ + sem_post(&m_pShmArea->mutex); +} + + +/***************************************************************************** + * * + * Slots * + * * + ****************************************************************************/ + +///Update the buffer +void Video::ShmRendererPrivate::timedEvents() +{ + + bool ok = renderToBitmap(); + + if (ok) { + + //Compute the FPS shown to the client + if (m_CurrentTime.second() != QTime::currentTime().second()) { + m_Fps = m_fpsC; + m_fpsC=0; + m_CurrentTime = QTime::currentTime(); + } + m_fpsC++; + + emit q_ptr->frameUpdated(); + } + /*else { + qDebug() << "Frame dropped"; + usleep(rand()%1000); //Be sure it can come back in sync + }*/ +} + +///Start the rendering loop +void Video::ShmRenderer::startRendering() +{ + Video::Manager::instance()->startStopMutex()->lock(); + QMutexLocker locker(mutex()); + startShm(); + if (!d_ptr->m_pTimer) { + d_ptr->m_pTimer = new QTimer(nullptr); + +// m_pTimer->moveToThread(thread()); + connect(d_ptr->m_pTimer,SIGNAL(timeout()),d_ptr.data(),SLOT(timedEvents())); + d_ptr->m_pTimer->setInterval(30); + } + + if (!d_ptr->m_pTimer->isActive()) { + qDebug() << "Is running" << thread()->isRunning(); + d_ptr->m_pTimer->start(); + } + else + qDebug() << "Timer already started!"; + + setRendering(true); + Video::Manager::instance()->startStopMutex()->unlock(); +} + +///Stop the rendering loop +void Video::ShmRenderer::stopRendering() +{ + Video::Manager::instance()->startStopMutex()->lock(); + QMutexLocker locker(mutex()); + setRendering(false); + qDebug() << "Stopping rendering on" << id(); + if (d_ptr->m_pTimer) + d_ptr->m_pTimer->stop(); + emit stopped(); + stopShm(); + Video::Manager::instance()->startStopMutex()->unlock(); +} + + +/***************************************************************************** + * * + * Getters * + * * + ****************************************************************************/ + +///Get the current frame rate of this renderer +int Video::ShmRenderer::fps() const +{ + return d_ptr->m_Fps; +} + +/***************************************************************************** + * * + * Setters * + * * + ****************************************************************************/ + +void Video::ShmRenderer::setShmPath(const QString& path) +{ + d_ptr->m_ShmPath = path; +} + +#include <shmrenderer.moc> diff --git a/src/private/shmrenderer.h b/src/private/shmrenderer.h new file mode 100644 index 0000000000000000000000000000000000000000..39bb2669c44a6ca3eb662471a107c779bfb928da --- /dev/null +++ b/src/private/shmrenderer.h @@ -0,0 +1,75 @@ +/**************************************************************************** + * Copyright (C) 2012-2015 by Savoir-Faire Linux * + * Author : Emmanuel Lepage Vallee <emmanuel.lepage@savoirfairelinux.com> * + * * + * This library is free software; you can redistribute it and/or * + * modify it under the terms of the GNU Lesser General Public * + * License as published by the Free Software Foundation; either * + * version 2.1 of the License, or (at your option) any later version. * + * * + * This library is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program. If not, see <http://www.gnu.org/licenses/>. * + ***************************************************************************/ +#ifndef VIDEO_SHM_RENDERER_H +#define VIDEO_SHM_RENDERER_H + +//Base +#include "video/renderer.h" +#include "typedefs.h" + +//Qt +class QMutex; + +//Ring +#include "video/device.h" + +//Private +struct SHMHeader; + + +namespace Video { +class ShmRendererPrivate; + +///Manage shared memory and convert it to QByteArray +class LIB_EXPORT ShmRenderer : public Renderer { + #pragma GCC diagnostic push + #pragma GCC diagnostic ignored "-Wzero-as-null-pointer-constant" + Q_OBJECT + #pragma GCC diagnostic pop + + public: + //Constructor + ShmRenderer (const QByteArray& id, const QString& shmPath, const QSize& res); + virtual ~ShmRenderer(); + + //Mutators + bool resizeShm(); + void stopShm (); + bool startShm (); + + //Getters + virtual int fps () const ; + + //Setters + void setShmPath (const QString& path); + + private: + QScopedPointer<ShmRendererPrivate> d_ptr; + Q_DECLARE_PRIVATE(ShmRenderer) + + public Q_SLOTS: + void startRendering(); + void stopRendering (); + + + +}; + +} + +#endif diff --git a/src/private/videorenderer_p.h b/src/private/videorenderer_p.h new file mode 100644 index 0000000000000000000000000000000000000000..f28e1438207dfad5f0e65fa6ca3546cb32ad52eb --- /dev/null +++ b/src/private/videorenderer_p.h @@ -0,0 +1,55 @@ +/**************************************************************************** + * Copyright (C) 2013-2015 by Savoir-Faire Linux * + * Author : Emmanuel Lepage Vallee <emmanuel.lepage@savoirfairelinux.com> * + * * + * This library is free software; you can redistribute it and/or * + * modify it under the terms of the GNU Lesser General Public * + * License as published by the Free Software Foundation; either * + * version 2.1 of the License, or (at your option) any later version. * + * * + * This library is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program. If not, see <http://www.gnu.org/licenses/>. * + ***************************************************************************/ +#ifndef RENDERERPRIVATE_H +#define RENDERERPRIVATE_H + +//Qt +#include <QtCore/QObject> +#include <QtCore/QSize> +class QMutex; + +namespace Video { + +class Renderer; + +class RendererPrivate : public QObject +{ +Q_OBJECT +public: + RendererPrivate(Video::Renderer* parent); + + //Attributes + bool m_isRendering; + QByteArray m_Frame[2] ; + bool m_FrameIdx ; + QMutex* m_pMutex ; + QString m_Id ; + QSize m_pSize ; + + //Helpers + QByteArray& otherFrame () const; + void updateFrameIndex () ; + +private: + Video::Renderer* q_ptr; + +}; + +} + +#endif diff --git a/src/qtwrapper/CMakeLists.txt b/src/qtwrapper/CMakeLists.txt index 2b128dd52f8368e00c1e4dd4357893bb79a47682..4e4d3ca635d93f7fa654f926388fc3015e5e648e 100644 --- a/src/qtwrapper/CMakeLists.txt +++ b/src/qtwrapper/CMakeLists.txt @@ -22,6 +22,7 @@ set(libqtwrapper_LIB_SRCS INCLUDE_DIRECTORIES(SYSTEM ${Qt5Core_INCLUDE_DIRS} ) INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR}) INCLUDE_DIRECTORIES(${ring_INCLUDE_DIRS}) +INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR}/../) INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR}/../dbus) ADD_LIBRARY( qtwrapper STATIC ${libqtwrapper_LIB_SRCS}) diff --git a/src/qtwrapper/callbacks.h b/src/qtwrapper/callbacks.h deleted file mode 100644 index d5d292e6132497fab9538a1d4d4c4ec7ec2aa9aa..0000000000000000000000000000000000000000 --- a/src/qtwrapper/callbacks.h +++ /dev/null @@ -1,26 +0,0 @@ -/****************************************************************************** - * Copyright (C) 2014 by Savoir-Faire Linux * - * Author : Philippe Groarke <philippe.groarke@savoirfairelinux.com> * - * * - * This library is free software; you can redistribute it and/or * - * modify it under the terms of the GNU Lesser General Public * - * License as published by the Free Software Foundation; either * - * version 2.1 of the License, or (at your option) any later version. * - * * - * This library is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * - * Lesser General Public License for more details. * - * * - * You should have received a copy of the Lesser GNU General Public License * - * along with this program. If not, see <http://www.gnu.org/licenses/>. * - *****************************************************************************/ -#pragma once - -#include <QtCore/Qstring> - -#include "../dbus/callmanager.h" -#include "../dbus/configurationmanager.h" -#include "../dbus/instancemanager.h" -#include "../dbus/presencemanager.h" -#include "../dbus/videomanager.h" diff --git a/src/qtwrapper/callmanager_wrap.h b/src/qtwrapper/callmanager_wrap.h index fd3aa955c24570c55a903236dbc7369b0df0fc9d..8926f5d200a419e6beeaed11f0a157184600fb67 100644 --- a/src/qtwrapper/callmanager_wrap.h +++ b/src/qtwrapper/callmanager_wrap.h @@ -1,6 +1,7 @@ /****************************************************************************** * Copyright (C) 2014 by Savoir-Faire Linux * * Author : Philippe Groarke <philippe.groarke@savoirfairelinux.com> * + * Author : Alexandre Lision <alexandre.lision@savoirfairelinux.com> * * * * This library is free software; you can redistribute it and/or * * modify it under the terms of the GNU Lesser General Public * @@ -27,8 +28,8 @@ #include <QtCore/QVariant> #include <QtCore/QTimer> -#include <dring.h> -#include "../dbus/metatypes.h" +#include <callmanager_interface.h> +#include "typedefs.h" #include "conversions_wrap.hpp" /* @@ -40,222 +41,245 @@ class CallManagerInterface: public QObject public: + std::map<std::string, std::shared_ptr<DRing::CallbackWrapperBase>> callHandlers; + CallManagerInterface() { - call_ev_handlers = ring_call_ev_handlers { - .on_state_change = [this] (const std::string &callID, const std::string &state) { - QTimer::singleShot(0, [this,callID, state] { - printf("EMIT ONSTATECHANGE\n"); - emit this->callStateChanged(QString(callID.c_str()), QString(state.c_str())); - }); - }, - - .on_transfer_fail = [this] () { - QTimer::singleShot(0, [this] { - emit this->transferFailed(); - }); - }, - .on_transfer_success = [this] () { - QTimer::singleShot(0, [this] { - emit this->transferSucceeded(); - }); - }, - .on_record_playback_stopped = [this] (const std::string &filepath) { - QTimer::singleShot(0, [this,filepath] { - emit this->recordPlaybackStopped(QString(filepath.c_str())); - }); - }, - - .on_voice_mail_notify = [this] (const std::string &accountID, int count) { - QTimer::singleShot(0, [this,accountID, count] { - emit this->voiceMailNotify(QString(accountID.c_str()), count); - }); - }, - .on_incoming_message = [this] (const std::string &callID, const std::string &from, const std::string &message) { - QTimer::singleShot(0, [this,callID, from, message] { - emit this->incomingMessage(QString(callID.c_str()), QString(from.c_str()), QString(message.c_str())); - }); - }, - .on_incoming_call = [this] (const std::string &accountID, const std::string &callID, const std::string &from) { - QTimer::singleShot(0, [this,accountID, callID, from] { - emit this->incomingCall(QString(accountID.c_str()), QString(callID.c_str()), QString(from.c_str())); - }); - }, - .on_record_playback_filepath = [this] (const std::string &callID, const std::string &filepath) { - QTimer::singleShot(0, [this,callID, filepath] { - emit this->recordPlaybackFilepath(QString(callID.c_str()), QString(filepath.c_str())); - }); - }, - .on_conference_created = [this] (const std::string &confID) { - QTimer::singleShot(0, [this,confID] { - emit this->conferenceCreated(QString(confID.c_str())); - }); - }, - .on_conference_changed = [this] (const std::string &confID, const std::string &state) { - QTimer::singleShot(0, [this,confID, state] { - emit this->conferenceChanged(QString(confID.c_str()), QString(state.c_str())); - }); - }, - .on_update_playback_scale = [this] (const std::string &filepath, int position, int size) { - QTimer::singleShot(0, [this,filepath, position, size] { - emit this->updatePlaybackScale(QString(filepath.c_str()), position, size); - }); - }, - .on_conference_remove = [this] (const std::string &confID) { - QTimer::singleShot(0, [this,confID] { - emit this->conferenceRemoved(QString(confID.c_str())); - }); - }, - .on_new_call = [this] (const std::string &accountID, const std::string &callID, const std::string &to) { - QTimer::singleShot(0, [this,accountID, callID, to] { - printf("EMIT ONNEWCALL\n"); - emit this->newCallCreated(QString(accountID.c_str()), QString(callID.c_str()), QString(to.c_str())); - }); - }, - .on_sip_call_state_change = [this] (const std::string &callID, const std::string &state, int code) { - QTimer::singleShot(0, [this,callID, state, code] { - emit this->sipCallStateChanged(QString(callID.c_str()), QString(state.c_str()), code); - }); - }, - .on_record_state_change = [this] (const std::string &callID, bool recordingState) { - QTimer::singleShot(0, [this,callID, recordingState] { - emit this->recordingStateChanged(QString(callID.c_str()), recordingState); - }); - }, - .on_secure_sdes_on = [this] (const std::string &callID) { - QTimer::singleShot(0, [this,callID] { - emit this->secureSdesOn(QString(callID.c_str())); - }); - }, - .on_secure_sdes_off = [this] (const std::string &callID) { - QTimer::singleShot(0, [this,callID] { - emit this->secureSdesOff(QString(callID.c_str())); - }); - }, - .on_secure_zrtp_on = [this] (const std::string &callID, const std::string &cipher) { - QTimer::singleShot(0, [this,callID,cipher] { - emit this->secureZrtpOn(QString(callID.c_str()), QString(cipher.c_str())); - }); - }, - .on_secure_zrtp_off = [this] (const std::string &callID) { - QTimer::singleShot(0, [this,callID] { - emit this->secureZrtpOff(QString(callID.c_str())); - }); - }, - .on_show_sas = [this] (const std::string &callID, const std::string &sas, bool verified) { - QTimer::singleShot(0, [this,callID, sas, verified] { - emit this->showSAS(QString(callID.c_str()), QString(sas.c_str()), verified); - }); - }, - .on_zrtp_not_supp_other = [this] (const std::string &callID) { - QTimer::singleShot(0, [this,callID] { - emit this->zrtpNotSuppOther(QString(callID.c_str())); - }); - }, - .on_zrtp_negotiation_fail = [this] (const std::string &callID, const std::string &reason, const std::string &severity) { - QTimer::singleShot(0, [this,callID, reason, severity] { - emit this->zrtpNegotiationFailed(QString(callID.c_str()), QString(reason.c_str()), QString(severity.c_str())); - }); - }, - .on_rtcp_receive_report = [this] (const std::string &callID, const std::map<std::string, int>& report) { - QTimer::singleShot(0, [this,callID, report] { - emit this->onRtcpReportReceived(QString(callID.c_str()), convertStringInt(report)); - }); - } - }; - } + using DRing::exportable_callback; + using DRing::CallSignal; + + callHandlers = { + exportable_callback<CallSignal::StateChange>( + [this] (const std::string &callID, const std::string &state) { + QTimer::singleShot(0, [this,callID, state] { + emit this->callStateChanged(QString(callID.c_str()), QString(state.c_str())); + }); + }), + exportable_callback<CallSignal::TransferFailed>( + [this] () { + QTimer::singleShot(0, [this] { + emit this->transferFailed(); + }); + }), + exportable_callback<CallSignal::TransferSucceeded>( + [this] () { + QTimer::singleShot(0, [this] { + emit this->transferSucceeded(); + }); + }), + exportable_callback<CallSignal::RecordPlaybackStopped>( + [this] (const std::string &filepath) { + QTimer::singleShot(0, [this,filepath] { + emit this->recordPlaybackStopped(QString(filepath.c_str())); + }); + }), + exportable_callback<CallSignal::VoiceMailNotify>( + [this] (const std::string &accountID, int count) { + QTimer::singleShot(0, [this,accountID, count] { + emit this->voiceMailNotify(QString(accountID.c_str()), count); + }); + }), + exportable_callback<CallSignal::IncomingMessage>( + [this] (const std::string &callID, const std::string &from, const std::string &message) { + QTimer::singleShot(0, [this,callID, from, message] { + emit this->incomingMessage(QString(callID.c_str()), QString(from.c_str()), QString(message.c_str())); + }); + }), + exportable_callback<CallSignal::IncomingCall>( + [this] (const std::string &accountID, const std::string &callID, const std::string &from) { + QTimer::singleShot(0, [this,accountID, callID, from] { + emit this->incomingCall(QString(accountID.c_str()), QString(callID.c_str()), QString(from.c_str())); + }); + }), + exportable_callback<CallSignal::RecordPlaybackFilepath>( + [this] (const std::string &callID, const std::string &filepath) { + QTimer::singleShot(0, [this,callID, filepath] { + emit this->recordPlaybackFilepath(QString(callID.c_str()), QString(filepath.c_str())); + }); + }), + exportable_callback<CallSignal::ConferenceCreated>( + [this] (const std::string &confID) { + QTimer::singleShot(0, [this,confID] { + emit this->conferenceCreated(QString(confID.c_str())); + }); + }), + exportable_callback<CallSignal::ConferenceChanged>( + [this] (const std::string &confID, const std::string &state) { + QTimer::singleShot(0, [this,confID, state] { + emit this->conferenceChanged(QString(confID.c_str()), QString(state.c_str())); + }); + }), + exportable_callback<CallSignal::UpdatePlaybackScale>( + [this] (const std::string &filepath, int position, int size) { + QTimer::singleShot(0, [this,filepath, position, size] { + emit this->updatePlaybackScale(QString(filepath.c_str()), position, size); + }); + }), + exportable_callback<CallSignal::ConferenceRemoved>( + [this] (const std::string &confID) { + QTimer::singleShot(0, [this,confID] { + emit this->conferenceRemoved(QString(confID.c_str())); + }); + }), + exportable_callback<CallSignal::NewCallCreated>( + [this] (const std::string &accountID, const std::string &callID, const std::string &to) { + QTimer::singleShot(0, [this,accountID, callID, to] { + printf("EMIT ONNEWCALL\n"); + emit this->newCallCreated(QString(accountID.c_str()), QString(callID.c_str()), QString(to.c_str())); + }); + }), + exportable_callback<CallSignal::SipCallStateChanged>( + [this] (const std::string &callID, const std::string &state, int code) { + QTimer::singleShot(0, [this,callID, state, code] { + emit this->sipCallStateChanged(QString(callID.c_str()), QString(state.c_str()), code); + }); + }), + exportable_callback<CallSignal::RecordingStateChanged>( + [this] (const std::string &callID, bool recordingState) { + QTimer::singleShot(0, [this,callID, recordingState] { + emit this->recordingStateChanged(QString(callID.c_str()), recordingState); + }); + }), + exportable_callback<CallSignal::SecureSdesOn>( + [this] (const std::string &callID) { + QTimer::singleShot(0, [this,callID] { + emit this->secureSdesOn(QString(callID.c_str())); + }); + }), + exportable_callback<CallSignal::SecureSdesOff>( + [this] (const std::string &callID) { + QTimer::singleShot(0, [this,callID] { + emit this->secureSdesOff(QString(callID.c_str())); + }); + }), + exportable_callback<CallSignal::SecureZrtpOn>( + [this] (const std::string &callID, const std::string &cipher) { + QTimer::singleShot(0, [this,callID,cipher] { + emit this->secureZrtpOn(QString(callID.c_str()), QString(cipher.c_str())); + }); + }), + exportable_callback<CallSignal::SecureZrtpOff>( + [this] (const std::string &callID) { + QTimer::singleShot(0, [this,callID] { + emit this->secureZrtpOff(QString(callID.c_str())); + }); + }), + exportable_callback<CallSignal::ShowSAS>( + [this] (const std::string &callID, const std::string &sas, bool verified) { + QTimer::singleShot(0, [this,callID, sas, verified] { + emit this->showSAS(QString(callID.c_str()), QString(sas.c_str()), verified); + }); + }), + exportable_callback<CallSignal::ZrtpNotSuppOther>( + [this] (const std::string &callID) { + QTimer::singleShot(0, [this,callID] { + emit this->zrtpNotSuppOther(QString(callID.c_str())); + }); + }), + exportable_callback<CallSignal::ZrtpNegotiationFailed>( + [this] (const std::string &callID, const std::string &reason, const std::string &severity) { + QTimer::singleShot(0, [this,callID, reason, severity] { + emit this->zrtpNegotiationFailed(QString(callID.c_str()), QString(reason.c_str()), QString(severity.c_str())); + }); + }), + exportable_callback<CallSignal::RtcpReportReceived>( + [this] (const std::string &callID, const std::map<std::string, int>& report) { + QTimer::singleShot(0, [this,callID, report] { + emit this->onRtcpReportReceived(QString(callID.c_str()), convertStringInt(report)); + }); + }) + }; + } ~CallManagerInterface() {} bool isValid() { return true; } - ring_call_ev_handlers call_ev_handlers; - public Q_SLOTS: // METHODS bool accept(const QString &callID) { - return ring_call_accept(callID.toStdString()); + return DRing::accept(callID.toStdString()); } void acceptEnrollment(const QString &callID, bool accepted) { - ring_call_accept_enrollment(callID.toStdString(), accepted); + DRing::acceptEnrollment(callID.toStdString(), accepted); } bool addMainParticipant(const QString &confID) { - return ring_call_add_main_participant(confID.toStdString()); + return DRing::addMainParticipant(confID.toStdString()); } bool addParticipant(const QString &callID, const QString &confID) { - return ring_call_add_participant( - callID.toStdString(), confID.toStdString()); + return DRing::addParticipant( + callID.toStdString(), confID.toStdString()); } bool attendedTransfer(const QString &transferID, const QString &targetID) { - return ring_call_attended_transfer( - transferID.toStdString(), targetID.toStdString()); + return DRing::attendedTransfer( + transferID.toStdString(), targetID.toStdString()); } void createConfFromParticipantList(const QStringList &participants) { - ring_call_create_conf_from_participant_list( - convertStringList(participants)); + DRing::createConfFromParticipantList( + convertStringList(participants)); } bool detachParticipant(const QString &callID) { - return ring_call_detach_participant(callID.toStdString()); + return DRing::detachParticipant(callID.toStdString()); } MapStringString getCallDetails(const QString &callID) { MapStringString temp = - convertMap(ring_call_get_call_details(callID.toStdString())); + convertMap(DRing::getCallDetails(callID.toStdString())); return temp; } QStringList getCallList() { QStringList temp = - convertStringList(ring_call_get_call_list()); + convertStringList(DRing::getCallList()); return temp; } MapStringString getConferenceDetails(const QString &callID) { MapStringString temp = - convertMap(ring_call_get_conference_details( + convertMap(DRing::getConferenceDetails( callID.toStdString())); return temp; } QString getConferenceId(const QString &callID) { - QString temp(ring_call_get_conference_id(callID.toStdString()).c_str()); + QString temp(DRing::getConferenceId(callID.toStdString()).c_str()); return temp; } QStringList getConferenceList() { QStringList temp = - convertStringList(ring_call_get_conference_list()); + convertStringList(DRing::getConferenceList()); return temp; } Q_DECL_DEPRECATED QString getCurrentAudioCodecName(const QString &callID) { QString temp( - ring_call_get_current_audio_codec_name(callID.toStdString()).c_str()); + DRing::getCurrentAudioCodecName(callID.toStdString()).c_str()); return temp; } QStringList getDisplayNames(const QString &confID) { QStringList temp = - convertStringList(ring_call_get_display_names( + convertStringList(DRing::getDisplayNames( confID.toStdString())); return temp; } @@ -263,142 +287,136 @@ public Q_SLOTS: // METHODS bool getIsRecording(const QString &callID) { //TODO: match API - return ring_call_is_recording(callID.toStdString()); + return DRing::getIsRecording(callID.toStdString()); } QStringList getParticipantList(const QString &confID) { QStringList temp = - convertStringList(ring_call_get_participant_list( + convertStringList(DRing::getParticipantList( confID.toStdString())); return temp; } bool hangUp(const QString &callID) { - return ring_call_hang_up(callID.toStdString()); + return DRing::hangUp(callID.toStdString()); } bool hangUpConference(const QString &confID) { - return ring_call_hang_up_conference(confID.toStdString()); + return DRing::hangUpConference(confID.toStdString()); } bool hold(const QString &callID) { - return ring_call_hold(callID.toStdString()); + return DRing::hold(callID.toStdString()); } bool holdConference(const QString &confID) { - return ring_call_hold_conference(confID.toStdString()); + return DRing::holdConference(confID.toStdString()); } bool isConferenceParticipant(const QString &callID) { - return ring_call_is_conference_participant(callID.toStdString()); + return DRing::isConferenceParticipant(callID.toStdString()); } bool joinConference(const QString &sel_confID, const QString &drag_confID) { - return ring_call_join_conference( + return DRing::joinConference( sel_confID.toStdString(), drag_confID.toStdString()); } bool joinParticipant(const QString &sel_callID, const QString &drag_callID) { - return ring_call_join_participant( + return DRing::joinParticipant( sel_callID.toStdString(), drag_callID.toStdString()); } - bool placeCall(const QString &accountID, const QString &callID, const QString &to) + QString placeCall(const QString &accountID, const QString &to) { - //TODO: match API - return ring_call_place( - accountID.toStdString(), callID.toStdString(), to.toStdString()); + QString temp(DRing::placeCall(accountID.toStdString(), to.toStdString()).c_str()); + return temp; } void playDTMF(const QString &key) { - ring_call_play_dtmf(key.toStdString()); + DRing::playDTMF(key.toStdString()); } void recordPlaybackSeek(double value) { - ring_call_record_playback_seek(value); + DRing::recordPlaybackSeek(value); } bool refuse(const QString &callID) { - return ring_call_refuse(callID.toStdString()); + return DRing::refuse(callID.toStdString()); } void requestGoClear(const QString &callID) { - ring_call_request_go_clear(callID.toStdString()); + DRing::requestGoClear(callID.toStdString()); } void resetSASVerified(const QString &callID) { - ring_call_reset_sas_verified(callID.toStdString()); + DRing::resetSASVerified(callID.toStdString()); } void sendTextMessage(const QString &callID, const QString &message) { - ring_call_send_text_message( + DRing::sendTextMessage( callID.toStdString(), message.toStdString()); } void setConfirmGoClear(const QString &callID) { - ring_call_set_confirm_go_clear(callID.toStdString()); - } - - Q_DECL_DEPRECATED void setRecording(const QString &callID) - { - ring_call_set_recording(callID.toStdString()); + DRing::setConfirmGoClear(callID.toStdString()); } void setSASVerified(const QString &callID) { - ring_call_set_sas_verified(callID.toStdString()); + DRing::setSASVerified(callID.toStdString()); } bool startRecordedFilePlayback(const QString &filepath) { // TODO: Change method name to match API - return ring_call_play_recorded_file(filepath.toStdString()); + return DRing::startRecordedFilePlayback(filepath.toStdString()); } void startTone(int start, int type) { - ring_call_start_tone(start, type); + DRing::startTone(start, type); } void stopRecordedFilePlayback(const QString &filepath) { - ring_call_stop_recorded_file(filepath.toStdString()); + DRing::stopRecordedFilePlayback(filepath.toStdString()); } bool toggleRecording(const QString &callID) { - return ring_call_toggle_recording(callID.toStdString()); + return DRing::toggleRecording(callID.toStdString()); } bool transfer(const QString &callID, const QString &to) { - return ring_call_transfer( + return DRing::transfer( callID.toStdString(), to.toStdString()); } bool unhold(const QString &callID) { - return ring_call_unhold(callID.toStdString()); + return DRing::unhold(callID.toStdString()); } bool unholdConference(const QString &confID) { - return ring_call_unhold_conference(confID.toStdString()); + return DRing::unholdConference(confID.toStdString()); } Q_SIGNALS: // SIGNALS diff --git a/src/qtwrapper/configurationmanager_wrap.h b/src/qtwrapper/configurationmanager_wrap.h index 0cfb73f13732c377541c7ef7b5d05c88dfea2809..4de404a5a2fe28ce742c2e79a6c265d39aab9845 100644 --- a/src/qtwrapper/configurationmanager_wrap.h +++ b/src/qtwrapper/configurationmanager_wrap.h @@ -1,22 +1,23 @@ /****************************************************************************** - * Copyright (C) 2014 by Savoir-Faire Linux * - * Author : Philippe Groarke <philippe.groarke@savoirfairelinux.com> * - * * - * This library is free software; you can redistribute it and/or * - * modify it under the terms of the GNU Lesser General Public * - * License as published by the Free Software Foundation; either * - * version 2.1 of the License, or (at your option) any later version. * - * * - * This library is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * - * Lesser General Public License for more details. * - * * - * You should have received a copy of the Lesser GNU General Public License * - * along with this program. If not, see <http://www.gnu.org/licenses/>. * - *****************************************************************************/ -#ifndef CONFIGURATIONMANAGER_DBUS_INTERFACE_H -#define CONFIGURATIONMANAGER_DBUS_INTERFACE_H +* Copyright (C) 2014 by Savoir-Faire Linux * +* Author : Philippe Groarke <philippe.groarke@savoirfairelinux.com> * +* Author : Alexandre Lision <alexandre.lision@savoirfairelinux.com> * +* * +* This library is free software; you can redistribute it and/or * +* modify it under the terms of the GNU Lesser General Public * +* License as published by the Free Software Foundation; either * +* version 2.1 of the License, or (at your option) any later version. * +* * +* This library is distributed in the hope that it will be useful, * +* but WITHOUT ANY WARRANTY; without even the implied warranty of * +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * +* Lesser General Public License for more details. * +* * +* You should have received a copy of the Lesser GNU General Public License * +* along with this program. If not, see <http://www.gnu.org/licenses/>. * +*****************************************************************************/ +#ifndef CONFIGURATIONMANAGER_STATIC_INTERFACE_H +#define CONFIGURATIONMANAGER_STATIC_INTERFACE_H #include <QtCore/QObject> #include <QtCore/QByteArray> @@ -29,8 +30,9 @@ #include <future> -#include <dring.h> -#include "../dbus/metatypes.h" +#include <configurationmanager_interface.h> + +#include "typedefs.h" #include "conversions_wrap.hpp" // TEMPORARY @@ -45,192 +47,182 @@ class ConfigurationManagerInterface: public QObject Q_OBJECT public: + + std::map<std::string, std::shared_ptr<DRing::CallbackWrapperBase>> confHandlers; + ConfigurationManagerInterface() { setObjectName("ConfigurationManagerInterface"); - config_ev_handlers = { - .on_volume_change = [this] (const std::string &device, double value) { - QTimer::singleShot(0, [this,device,value] { - emit this->volumeChanged(QString(device.c_str()), value); - }); - }, - .on_accounts_change = [this] () { - QTimer::singleShot(0, [this] { - emit this->accountsChanged(); - }); - }, - .on_history_change = [this] () { - QTimer::singleShot(0, [this] { - emit this->historyChanged(); - }); - }, - .on_stun_status_fail = [this] (const std::string &reason) { - QTimer::singleShot(0, [this, reason] { - emit this->stunStatusFailure(QString(reason.c_str())); - }); - }, - .on_registration_state_change = [this] (const std::string &accountID, int registration_state) { - QTimer::singleShot(0, [this, accountID, registration_state] { - emit this->registrationStateChanged(QString(accountID.c_str()), registration_state); - }); - }, - .on_sip_registration_state_change = [this] (const std::string &accountID, const std::string &state, int code) { - QTimer::singleShot(0, [this,accountID, state, code] { - emit this->sipRegistrationStateChanged(QString(accountID.c_str()), QString(state.c_str()), code); - }); - }, - - //TODO: .on_volatile_details_change = [this] (const QString &message.c_str()) { emit this->volatileAccountDetailsChanged(); }, - .on_error = [this] (int code) { - QTimer::singleShot(0, [this,code] { - emit this->errorAlert(code); - }); - } + using DRing::exportable_callback; + using DRing::ConfigurationSignal; + + setObjectName("ConfigurationManagerInterface"); + confHandlers = { + exportable_callback<ConfigurationSignal::VolumeChanged>( + [this] (const std::string &device, double value) { + QTimer::singleShot(0, [this,device,value] { + emit this->volumeChanged(QString(device.c_str()), value); + }); + }), + exportable_callback<ConfigurationSignal::AccountsChanged>( + [this] () { + QTimer::singleShot(0, [this] { + emit this->accountsChanged(); + }); + }), + exportable_callback<ConfigurationSignal::HistoryChanged>( + [this] () { + QTimer::singleShot(0, [this] { + emit this->historyChanged(); + }); + }), + exportable_callback<ConfigurationSignal::StunStatusFailed>( + [this] (const std::string &reason) { + QTimer::singleShot(0, [this, reason] { + emit this->stunStatusFailure(QString(reason.c_str())); + }); + }), + exportable_callback<ConfigurationSignal::RegistrationStateChanged>( + [this] (const std::string &accountID, int registration_state) { + QTimer::singleShot(0, [this, accountID, registration_state] { + emit this->registrationStateChanged(QString(accountID.c_str()), registration_state); + }); + }), + exportable_callback<ConfigurationSignal::SipRegistrationStateChanged>( + [this] (const std::string &accountID, const std::string &state, int code) { + QTimer::singleShot(0, [this,accountID, state, code] { + emit this->sipRegistrationStateChanged(QString(accountID.c_str()), QString(state.c_str()), code); + }); + }), + exportable_callback<ConfigurationSignal::VolatileDetailsChanged>( + [this] (const std::string &accountID, const std::map<std::string, std::string>& details) { + QTimer::singleShot(0, [this, accountID, details] { + emit this->volatileAccountDetailsChanged(QString(accountID.c_str()), convertMap(details)); + }); + }), + exportable_callback<ConfigurationSignal::Error>( + [this] (int code) { + QTimer::singleShot(0, [this,code] { + emit this->errorAlert(code); + }); + }) }; } ~ConfigurationManagerInterface() {} - ring_config_ev_handlers config_ev_handlers; - public Q_SLOTS: // METHODS QString addAccount(MapStringString details) { QString temp( - ring_config_add_account(convertMap(details)).c_str()); + DRing::addAccount(convertMap(details)).c_str()); return temp; } - bool checkCertificateValidity(const QString &caPath, const QString &pemPath) - { - return ring_config_check_certificate_validity( - caPath.toStdString(), pemPath.toStdString()); - } - - bool checkForPrivateKey(const QString &pemPath) - { - return ring_config_check_for_private_key(pemPath.toStdString()); - } - - bool checkHostnameCertificate(const QString &host, const QString &port) - { - return ring_config_check_hostname_certificate( - host.toStdString(), port.toStdString()); - } - - void clearHistory() - { - ring_config_clear_history(); - } - MapStringString getAccountDetails(const QString &accountID) { MapStringString temp = - convertMap(ring_config_get_account_details(accountID.toStdString())); + convertMap(DRing::getAccountDetails(accountID.toStdString())); return temp; } QStringList getAccountList() { - std::cout << "AccountList:" << std::endl; - for (auto x : ring_config_get_account_list()) - std::cout << x << std::endl; - QStringList temp = - convertStringList(ring_config_get_account_list()); + convertStringList(DRing::getAccountList()); return temp; } MapStringString getAccountTemplate() { MapStringString temp = - convertMap(ring_config_get_account_template()); + convertMap(DRing::getAccountTemplate()); return temp; } -// TODO: works? - VectorInt getActiveAudioCodecList(const QString &accountID) + // TODO: works? + VectorUInt getActiveCodecList(const QString &accountID) { - return QVector<int>::fromStdVector( - ring_config_get_active_audio_codec_list(accountID.toStdString())); + return QVector<unsigned int>::fromStdVector( + DRing::getActiveCodecList(accountID.toStdString())); } QString getAddrFromInterfaceName(const QString &interface) { QString temp( - ring_config_get_addr_from_interface_name(interface.toStdString()).c_str()); + DRing::getAddrFromInterfaceName(interface.toStdString()).c_str()); return temp; } QStringList getAllIpInterface() { QStringList temp = - convertStringList(ring_config_get_all_ip_interface()); + convertStringList(DRing::getAllIpInterface()); return temp; } QStringList getAllIpInterfaceByName() { QStringList temp = - convertStringList(ring_config_get_all_ip_interface_by_name()); + convertStringList(DRing::getAllIpInterfaceByName()); return temp; } - QStringList getAudioCodecDetails(int payload) + MapStringString getCodecDetails(const QString accountID, int payload) { - QStringList temp = - convertStringList(ring_config_get_audio_codec_details(payload)); + MapStringString temp = + convertMap(DRing::getCodecDetails( + accountID.toStdString().c_str(), payload)); return temp; } -// TODO: works? - VectorInt getAudioCodecList() + VectorUInt getCodecList() { - return QVector<int>::fromStdVector(ring_config_get_audio_codec_list()); + return QVector<unsigned int>::fromStdVector(DRing::getCodecList()); } int getAudioInputDeviceIndex(const QString &devname) { - return ring_config_get_audio_input_device_index(devname.toStdString()); + return DRing::getAudioInputDeviceIndex(devname.toStdString()); } QStringList getAudioInputDeviceList() { QStringList temp = - convertStringList(ring_config_get_audio_input_device_list()); + convertStringList(DRing::getAudioInputDeviceList()); return temp; } QString getAudioManager() { QString temp( - ring_config_get_audio_manager().c_str()); + DRing::getAudioManager().c_str()); return temp; } int getAudioOutputDeviceIndex(const QString &devname) { - return ring_config_get_audio_output_device_index(devname.toStdString()); + return DRing::getAudioOutputDeviceIndex(devname.toStdString()); } QStringList getAudioOutputDeviceList() { QStringList temp = - convertStringList(ring_config_get_audio_output_device_list()); + convertStringList(DRing::getAudioOutputDeviceList()); return temp; } QStringList getAudioPluginList() { QStringList temp = - convertStringList(ring_config_get_audio_plugin_list()); + convertStringList(DRing::getAudioPluginList()); return temp; } VectorMapStringString getCredentials(const QString &accountID) { VectorMapStringString temp; - for(auto x : ring_config_get_credentials(accountID.toStdString())) { + for(auto x : DRing::getCredentials(accountID.toStdString())) { temp.push_back(convertMap(x)); } return temp; @@ -239,212 +231,216 @@ public Q_SLOTS: // METHODS QStringList getCurrentAudioDevicesIndex() { QStringList temp = - convertStringList(ring_config_get_current_audio_devices_index()); + convertStringList(DRing::getCurrentAudioDevicesIndex()); return temp; } QString getCurrentAudioOutputPlugin() { QString temp( - ring_config_get_current_audio_output_plugin().c_str()); - return temp; - } - - VectorMapStringString getHistory() - { - VectorMapStringString temp; - for (auto x : ring_config_get_history()) { - temp.push_back(convertMap(x)); - } + DRing::getCurrentAudioOutputPlugin().c_str()); return temp; } int getHistoryLimit() { - return ring_config_get_history_limit(); + return DRing::getHistoryLimit(); } MapStringString getHookSettings() { MapStringString temp = - convertMap(ring_config_get_hook_settings()); + convertMap(DRing::getHookSettings()); return temp; } MapStringString getIp2IpDetails() { MapStringString temp = - convertMap(ring_config_get_ip2ip_details()); + convertMap(DRing::getIp2IpDetails()); return temp; } bool getIsAlwaysRecording() { - // TODO: update API - return ring_config_is_always_recording(); + return DRing::getIsAlwaysRecording(); } bool getNoiseSuppressState() { - return ring_config_get_noise_suppress_state(); + return DRing::getNoiseSuppressState(); } QString getRecordPath() { QString temp( - ring_config_get_record_path().c_str()); + DRing::getRecordPath().c_str()); return temp; } - MapStringString getRingtoneList() + QStringList getSupportedAudioManagers() { - MapStringString temp = - convertMap(ring_config_get_ringtone_list()); + QStringList temp; return temp; } MapStringString getShortcuts() { MapStringString temp = - convertMap(ring_config_get_shortcuts()); + convertMap(DRing::getShortcuts()); return temp; } - QStringList getSupportedAudioManagers() + QStringList getSupportedTlsMethod() { QStringList temp = - convertStringList(ring_config_get_supported_audio_managers()); + convertStringList(DRing::getSupportedTlsMethod()); return temp; } - QStringList getSupportedTlsMethod() + MapStringString getTlsSettings() { - QStringList temp = - convertStringList(ring_config_get_supported_tls_method()); + MapStringString temp = + convertMap(DRing::getTlsSettings()); return temp; } - MapStringString getTlsSettings() + MapStringString validateCertificate(const QString& unused, const QString certificate, const QString& privateKey) { MapStringString temp = - convertMap(ring_config_get_tls_settings()); + convertMap(DRing::validateCertificate(unused.toStdString(), + certificate.toStdString(), + privateKey.toStdString())); return temp; } - MapStringString getTlsSettingsDefault() + MapStringString getCertificateDetails(const QString &certificate) { - // TODO: update API MapStringString temp = - convertMap(ring_config_get_tls_default_settings()); + convertMap(DRing::getCertificateDetails(certificate.toStdString())); + return temp; + } + + QStringList getSupportedCiphers(const QString &accountID) + { + QStringList temp = + convertStringList(DRing::getSupportedCiphers(accountID.toStdString())); + return temp; + } + + MapStringString getTlsDefaultSettings() + { + MapStringString temp = + convertMap(DRing::getTlsDefaultSettings()); return temp; } double getVolume(const QString &device) { - return ring_config_get_volume(device.toStdString()); + return DRing::getVolume(device.toStdString()); } bool isAgcEnabled() { - return ring_config_is_agc_enabled(); + return DRing::isAgcEnabled(); } bool isCaptureMuted() { - return ring_config_is_capture_muted(); + return DRing::isCaptureMuted(); } bool isDtmfMuted() { - return ring_config_is_dtmf_muted(); + return DRing::isDtmfMuted(); } int isIax2Enabled() { - return ring_config_is_iax2_enabled(); + return DRing::isIax2Enabled(); } bool isPlaybackMuted() { - return ring_config_is_playback_muted(); + return DRing::isPlaybackMuted(); } void muteCapture(bool mute) { - ring_config_mute_capture(mute); + DRing::muteCapture(mute); } void muteDtmf(bool mute) { - ring_config_mute_dtmf(mute); + DRing::muteDtmf(mute); } void mutePlayback(bool mute) { - ring_config_mute_playback(mute); + DRing::mutePlayback(mute); } void registerAllAccounts() { - ring_config_register_all_accounts(); + DRing::registerAllAccounts(); } void removeAccount(const QString &accountID) { - ring_config_remove_account(accountID.toStdString()); + DRing::removeAccount(accountID.toStdString()); } void sendRegister(const QString &accountID, bool enable) { - ring_config_send_register(accountID.toStdString(), enable); + DRing::sendRegister(accountID.toStdString(), enable); } void setAccountDetails(const QString &accountID, MapStringString details) { - ring_config_set_account_details(accountID.toStdString(), + DRing::setAccountDetails(accountID.toStdString(), convertMap(details)); } void setAccountsOrder(const QString &order) { - ring_config_set_accounts_order(order.toStdString()); + DRing::setAccountsOrder(order.toStdString()); } - void setActiveAudioCodecList(const QStringList &list, const QString &accountID) + void setActiveCodecList(const QString &accountID, VectorUInt &list) { - ring_config_set_active_audio_codec_list( - convertStringList(list), accountID.toStdString()); + //const std::vector<unsigned int> converted = convertStringList(list); + DRing::setActiveCodecList(accountID.toStdString(), + list.toStdVector()); } void setAgcState(bool enabled) { - //TODO: update API - ring_config_enable_agc(enabled); + DRing::setAgcState(enabled); } void setAudioInputDevice(int index) { - ring_config_set_audio_input_device(index); + DRing::setAudioInputDevice(index); } bool setAudioManager(const QString &api) { - return ring_config_set_audio_manager(api.toStdString()); + return DRing::setAudioManager(api.toStdString()); } void setAudioOutputDevice(int index) { - ring_config_set_audio_output_device(index); + DRing::setAudioOutputDevice(index); } void setAudioPlugin(const QString &audioPlugin) { - ring_config_set_audio_plugin(audioPlugin.toStdString()); + DRing::setAudioPlugin(audioPlugin.toStdString()); } void setAudioRingtoneDevice(int index) { - ring_config_set_audio_ringtone_device(index); + DRing::setAudioRingtoneDevice(index); } void setCredentials(const QString &accountID, VectorMapStringString credentialInformation) @@ -453,48 +449,53 @@ public Q_SLOTS: // METHODS for (auto x : credentialInformation) { temp.push_back(convertMap(x)); } - ring_config_set_credentials(accountID.toStdString(), temp); + DRing::setCredentials(accountID.toStdString(), temp); } void setHistoryLimit(int days) { - ring_config_set_history_limit(days); + DRing::setHistoryLimit(days); } void setHookSettings(MapStringString settings) { - ring_config_set_hook_settings(convertMap(settings)); + DRing::setHookSettings(convertMap(settings)); } void setIsAlwaysRecording(bool enabled) { - //TODO: update API - ring_config_set_always_recording(enabled); + DRing::setIsAlwaysRecording(enabled); } void setNoiseSuppressState(bool state) { - ring_config_set_noise_suppress_state(state); + DRing::setNoiseSuppressState(state); } void setRecordPath(const QString &rec) { - ring_config_set_record_path(rec.toStdString()); + DRing::setRecordPath(rec.toStdString()); } void setShortcuts(MapStringString shortcutsMap) { - ring_config_set_shortcuts(convertMap(shortcutsMap)); + DRing::setShortcuts(convertMap(shortcutsMap)); } void setTlsSettings(MapStringString details) { - ring_config_set_tls_settings(convertMap(details)); + DRing::setTlsSettings(convertMap(details)); } void setVolume(const QString &device, double value) { - ring_config_set_volume(device.toStdString(), value); + DRing::setVolume(device.toStdString(), value); + } + + MapStringString getVolatileAccountDetails(const QString &accountID) + { + MapStringString temp = convertMap(DRing::getVolatileAccountDetails(accountID.toStdString())); + return temp; } Q_SIGNALS: // SIGNALS @@ -506,6 +507,7 @@ Q_SIGNALS: // SIGNALS void sipRegistrationStateChanged(const QString &accountID, const QString &state, int code); void stunStatusSuccess(const QString &message); void errorAlert(int code); + void volatileAccountDetailsChanged(const QString &accountID, MapStringString details); }; diff --git a/src/qtwrapper/conversions_wrap.hpp b/src/qtwrapper/conversions_wrap.hpp index 39cf326ece65886731d3feabe66225e75ebfb01a..c65c4d2d3339a27b931192eafd6552dde83c5ea6 100644 --- a/src/qtwrapper/conversions_wrap.hpp +++ b/src/qtwrapper/conversions_wrap.hpp @@ -22,7 +22,7 @@ #include <string> #include <vector> -#include "../dbus/metatypes.h" +#include "../typedefs.h" #define Q_NOREPLY @@ -50,6 +50,14 @@ inline QStringList convertStringList(const std::vector<std::string>& v) { return temp; } +inline VectorString convertVectorString(const std::vector<std::string>& v) { + VectorString temp; + for (const auto& x : v) { + temp.push_back(QString(x.c_str())); + } + return temp; +} + inline std::vector<std::string> convertStringList(const QStringList& v) { std::vector<std::string> temp; for (const auto& x : v) { diff --git a/src/qtwrapper/instancemanager.cpp b/src/qtwrapper/instancemanager.cpp index 1feb9f3e9a6eb27ccd23e2eb933c157f2a1a6f79..f6c4661074cdd3afee2cf43178ef0a70b42db10b 100644 --- a/src/qtwrapper/instancemanager.cpp +++ b/src/qtwrapper/instancemanager.cpp @@ -1,6 +1,7 @@ /**************************************************************************** * Copyright (C) 2009-2014 by Savoir-Faire Linux * * Authors : Alexandre Lision alexandre.lision@savoirfairelinux.com * + * Author : Alexandre Lision <alexandre.lision@savoirfairelinux.com> * * * * This library is free software; you can redistribute it and/or * * modify it under the terms of the GNU Lesser General Public * @@ -30,25 +31,45 @@ void pollEvents(); InstanceInterface::InstanceInterface() : m_pTimer(nullptr) { + using namespace std::placeholders; + + using std::bind; + using DRing::exportable_callback; + using DRing::CallSignal; + using DRing::ConfigurationSignal; + using DRing::PresenceSignal; + + #ifdef ENABLE_VIDEO + using DRing::VideoSignal; + #endif + m_pTimer = new QTimer(this); m_pTimer->setInterval(50); connect(m_pTimer,&QTimer::timeout,this,&pollEvents); m_pTimer->start(); - ringFlags |= RING_FLAG_DEBUG; - ringFlags |= RING_FLAG_CONSOLE_LOG; + ringFlags |= DRing::DRING_FLAG_DEBUG; + ringFlags |= DRing::DRING_FLAG_CONSOLE_LOG; - evHandlers = { - .call_ev_handlers = DBus::CallManager::instance().call_ev_handlers, - .config_ev_handlers = DBus::ConfigurationManager::instance().config_ev_handlers, - .pres_ev_handlers = DBus::PresenceManager::instance().pres_ev_handlers, - #ifdef ENABLE_VIDEO - .video_ev_handler = DBus::VideoManager::instance().video_ev_handlers - #endif /* ENABLE_VIDEO */ - }; + const std::map<DRing::EventHandlerKey, std::map<std::string, std::shared_ptr<DRing::CallbackWrapperBase>>> evHandlers = { + { // Call event handlers + DRing::EventHandlerKey::CALL, DBus::CallManager::instance().callHandlers + }, + { // Configuration event handlers + DRing::EventHandlerKey::CONFIG, DBus::ConfigurationManager::instance().confHandlers + }, + { // Presence event handlers + DRing::EventHandlerKey::PRESENCE, DBus::PresenceManager::instance().presHandlers + } +#ifdef ENABLE_VIDEO + ,{ // Video event handlers + DRing::EventHandlerKey::VIDEO, DBus::VideoManager::instance().videoHandlers + } +#endif + }; - ring_init(&evHandlers, static_cast<ring_init_flag>(ringFlags)); + DRing::init(evHandlers, static_cast<DRing::InitFlag>(ringFlags)); - printf("INITIATED DAEMON\n"); + printf("INITIATED DAEMON\n"); } InstanceInterface::~InstanceInterface() @@ -58,12 +79,10 @@ InstanceInterface::~InstanceInterface() void pollEvents() { - ring_poll_events(); + DRing::poll_events(); } bool InstanceInterface::isConnected() { return true; } - - diff --git a/src/qtwrapper/instancemanager_wrap.h b/src/qtwrapper/instancemanager_wrap.h index 2defef3ee0846938384a8a11815d14623a8aa943..a4dc60471a983f802bf880fc1ba51620e35571db 100644 --- a/src/qtwrapper/instancemanager_wrap.h +++ b/src/qtwrapper/instancemanager_wrap.h @@ -1,6 +1,7 @@ /****************************************************************************** * Copyright (C) 2014 by Savoir-Faire Linux * * Author : Philippe Groarke <philippe.groarke@savoirfairelinux.com> * + * Author : Alexandre Lision <alexandre.lision@savoirfairelinux.com> * * * * This library is free software; you can redistribute it and/or * * modify it under the terms of the GNU Lesser General Public * @@ -28,7 +29,7 @@ #include <QTimer> #include "dring.h" -#include "../dbus/metatypes.h" +#include "../typedefs.h" #include "conversions_wrap.hpp" /* @@ -55,7 +56,6 @@ public Q_SLOTS: // METHODS private: QTimer* m_pTimer; - ring_ev_handlers evHandlers; Q_SIGNALS: // SIGNALS void started(); diff --git a/src/qtwrapper/presencemanager_wrap.h b/src/qtwrapper/presencemanager_wrap.h index f95fc321a6ddd2a3b2c61cf6d6a47b8eb8694276..14cbba02ee15395b5fcce7625c978ce99dd0ffa5 100644 --- a/src/qtwrapper/presencemanager_wrap.h +++ b/src/qtwrapper/presencemanager_wrap.h @@ -1,6 +1,7 @@ /****************************************************************************** * Copyright (C) 2014 by Savoir-Faire Linux * * Author : Philippe Groarke <philippe.groarke@savoirfairelinux.com> * + * Author : Alexandre Lision <alexandre.lision@savoirfairelinux.com> * * * * This library is free software; you can redistribute it and/or * * modify it under the terms of the GNU Lesser General Public * @@ -27,9 +28,8 @@ #include <QtCore/QVariant> #include <QtCore/QTimer> -#include <dring.h> - -#include "../dbus/metatypes.h" +#include "typedefs.h" +#include <presencemanager_interface.h> #include "conversions_wrap.hpp" @@ -40,46 +40,54 @@ class PresenceManagerInterface: public QObject { Q_OBJECT public: + + std::map<std::string, std::shared_ptr<DRing::CallbackWrapperBase>> presHandlers; + PresenceManagerInterface() { - pres_ev_handlers = { - .on_new_server_subscription_request = [this] (const std::string &buddyUri) { - QTimer::singleShot(0, [this,buddyUri] { - emit this->newServerSubscriptionRequest(QString(buddyUri.c_str())); - }); - }, - .on_server_error = [this] (const std::string &accountID, const std::string &error, const std::string &msg) { - QTimer::singleShot(0, [this,accountID, error, msg] { - emit this->serverError(QString(accountID.c_str()), QString(error.c_str()), QString(msg.c_str())); - }); - }, - .on_new_buddy_notification = [this] (const std::string &accountID, const std::string &buddyUri, bool status, const std::string &lineStatus) { - QTimer::singleShot(0, [this,accountID, buddyUri, status, lineStatus] { - emit this->newBuddyNotification(QString(accountID.c_str()), QString(buddyUri.c_str()), status, QString(lineStatus.c_str())); - }); - }, - .on_subscription_state_change = [this] (const std::string &accountID, const std::string &buddyUri, bool state) { - QTimer::singleShot(0, [this,accountID, buddyUri, state] { - emit this->subscriptionStateChanged(QString(accountID.c_str()), QString(buddyUri.c_str()), state); - }); - } - }; + using DRing::exportable_callback; + using DRing::PresenceSignal; + + presHandlers = { + exportable_callback<PresenceSignal::NewServerSubscriptionRequest>( + [this] (const std::string &buddyUri) { + QTimer::singleShot(0, [this,buddyUri] { + emit this->newServerSubscriptionRequest(QString(buddyUri.c_str())); + }); + }), + exportable_callback<PresenceSignal::ServerError>( + [this] (const std::string &accountID, const std::string &error, const std::string &msg) { + QTimer::singleShot(0, [this,accountID, error, msg] { + emit this->serverError(QString(accountID.c_str()), QString(error.c_str()), QString(msg.c_str())); + }); + }), + exportable_callback<PresenceSignal::NewBuddyNotification>( + [this] (const std::string &accountID, const std::string &buddyUri, bool status, const std::string &lineStatus) { + QTimer::singleShot(0, [this,accountID, buddyUri, status, lineStatus] { + emit this->newBuddyNotification(QString(accountID.c_str()), QString(buddyUri.c_str()), status, QString(lineStatus.c_str())); + }); + }), + exportable_callback<PresenceSignal::SubscriptionStateChanged>( + [this] (const std::string &accountID, const std::string &buddyUri, bool state) { + QTimer::singleShot(0, [this,accountID, buddyUri, state] { + emit this->subscriptionStateChanged(QString(accountID.c_str()), QString(buddyUri.c_str()), state); + }); + }) + }; } ~PresenceManagerInterface() {} - ring_pres_ev_handlers pres_ev_handlers; - public Q_SLOTS: // METHODS void answerServerRequest(const QString &uri, bool flag) { - ring_pres_answer_server_request(uri.toStdString(), flag); + DRing::answerServerRequest(uri.toStdString(), flag); } VectorMapStringString getSubscriptions(const QString &accountID) { VectorMapStringString temp; - for (auto x : ring_pres_get_subscriptions(accountID.toStdString())) { + for (auto x : DRing::getSubscriptions(accountID.toStdString())) { temp.push_back(convertMap(x)); } return temp; @@ -87,17 +95,17 @@ public Q_SLOTS: // METHODS void publish(const QString &accountID, bool status, const QString ¬e) { - ring_pres_publish(accountID.toStdString(), status, note.toStdString()); + DRing::publish(accountID.toStdString(), status, note.toStdString()); } void setSubscriptions(const QString &accountID, const QStringList &uriList) { - ring_pres_set_subscriptions(accountID.toStdString(), convertStringList(uriList)); + DRing::setSubscriptions(accountID.toStdString(), convertStringList(uriList)); } void subscribeBuddy(const QString &accountID, const QString &uri, bool flag) { - ring_pres_subscribe_buddy(accountID.toStdString(), uri.toStdString(), flag); + DRing::subscribeBuddy(accountID.toStdString(), uri.toStdString(), flag); } Q_SIGNALS: // SIGNALS diff --git a/src/qtwrapper/videomanager_wrap.h b/src/qtwrapper/videomanager_wrap.h index 4006600d456668689f2dac6ab4176f1400ee58cc..b9312fbd7f53c25e7e1f809c3e9169ba80fc00de 100644 --- a/src/qtwrapper/videomanager_wrap.h +++ b/src/qtwrapper/videomanager_wrap.h @@ -1,6 +1,7 @@ /****************************************************************************** * Copyright (C) 2014 by Savoir-Faire Linux * * Author : Philippe Groarke <philippe.groarke@savoirfairelinux.com> * + * Author : Alexandre Lision <alexandre.lision@savoirfairelinux.com> * * * * This library is free software; you can redistribute it and/or * * modify it under the terms of the GNU Lesser General Public * @@ -25,9 +26,11 @@ #include <QtCore/QString> #include <QtCore/QStringList> #include <QtCore/QVariant> +#include <QtCore/QTimer> -#include <dring.h> -#include "../dbus/metatypes.h" +#include <videomanager_interface.h> + +#include "typedefs.h" #include "conversions_wrap.hpp" /* @@ -41,22 +44,27 @@ public: VideoManagerInterface() { #ifdef ENABLE_VIDEO - video_ev_handlers = { - .on_device_event = [this] () { - QTimer::singleShot(0, [this] { - emit this->deviceEvent(); - }); - }, - .on_start_decoding = [this] (const std::string &id, const std::string &shmPath, int width, int height, bool isMixer) { - QTimer::singleShot(0, [this,id, shmPath, width, height, isMixer] { - emit this->startedDecoding(QString(id.c_str()), QString(shmPath.c_str()), width, height, isMixer); - }); - }, - .on_stop_decoding = [this] (const std::string &id, const std::string &shmPath, bool isMixer) { - QTimer::singleShot(0, [this,id, shmPath, isMixer] { - emit this->stoppedDecoding(QString(id.c_str()), QString(shmPath.c_str()), isMixer); - }); - } + using DRing::exportable_callback; + using DRing::VideoSignal; + videoHandlers = { + exportable_callback<VideoSignal::DeviceEvent>( + [this] () { + QTimer::singleShot(0, [this] { + emit this->deviceEvent(); + }); + }), + exportable_callback<VideoSignal::DecodingStarted>( + [this] (const std::string &id, const std::string &shmPath, int width, int height, bool isMixer) { + QTimer::singleShot(0, [this,id, shmPath, width, height, isMixer] { + emit this->startedDecoding(QString(id.c_str()), QString(shmPath.c_str()), width, height, isMixer); + }); + }), + exportable_callback<VideoSignal::DecodingStopped>( + [this] (const std::string &id, const std::string &shmPath, bool isMixer) { + QTimer::singleShot(0, [this,id, shmPath, isMixer] { + emit this->stoppedDecoding(QString(id.c_str()), QString(shmPath.c_str()), isMixer); + }); + }) }; #endif } @@ -64,14 +72,14 @@ public: ~VideoManagerInterface() {} #ifdef ENABLE_VIDEO - ring_video_ev_handlers video_ev_handlers; + std::map<std::string, std::shared_ptr<DRing::CallbackWrapperBase>> videoHandlers; #endif public Q_SLOTS: // METHODS void applySettings(const QString &name, MapStringString settings) { #ifdef ENABLE_VIDEO - ring_video_apply_settings( + DRing::applySettings( name.toStdString(), convertMap(settings)); #endif } @@ -82,12 +90,12 @@ public Q_SLOTS: // METHODS MapStringMapStringVectorString ret; #ifdef ENABLE_VIDEO std::map<std::string, std::map<std::string, std::vector<std::string>>> temp; - temp = ring_video_get_capabilities(name.toStdString()); + temp = DRing::getCapabilities(name.toStdString()); for (auto& x : temp) { - map<QString, QStringList> ytemp; - for (auto& y : x) { - ytemp[QString(y.first.c_str())] = convertStringList(y.second); + QMap<QString, VectorString> ytemp; + for (auto& y : x.second) { + ytemp[QString(y.first.c_str())] = convertVectorString(y.second); } ret[QString(x.first.c_str())] = ytemp; } @@ -95,33 +103,11 @@ public Q_SLOTS: // METHODS return ret; } - VectorMapStringString getCodecs(const QString &accountID) - { - VectorMapStringString temp; -#ifdef ENABLE_VIDEO - for (auto x : ring_video_get_codecs(accountID.toStdString())) { - temp.push_back(convertMap(x)); - } -#endif - return temp; - } - - Q_DECL_DEPRECATED QString getCurrentCodecName(const QString &callID) - { -#ifdef ENABLE_VIDEO - QString temp( - ring_video_get_current_codec_name(callID.toStdString()).c_str()); -#else - QString temp; -#endif - return temp; - } - QString getDefaultDevice() { #ifdef ENABLE_VIDEO QString temp( - ring_video_get_default_device().c_str()); + DRing::getDefaultDevice().c_str()); #else QString temp; #endif @@ -132,7 +118,7 @@ public Q_SLOTS: // METHODS { #ifdef ENABLE_VIDEO QStringList temp = - convertStringList(ring_video_get_device_list()); + convertStringList(DRing::getDeviceList()); #else QStringList temp; #endif @@ -143,7 +129,7 @@ public Q_SLOTS: // METHODS { #ifdef ENABLE_VIDEO MapStringString temp = - convertMap(ring_video_get_settings(device.toStdString())); + convertMap(DRing::getSettings(device.toStdString())); #else MapStringString temp; #endif @@ -153,48 +139,37 @@ public Q_SLOTS: // METHODS bool hasCameraStarted() { #ifdef ENABLE_VIDEO - return ring_video_has_camera_started(); + return DRing::hasCameraStarted(); #else return false; #endif } - void setCodecs(const QString &accountID, VectorMapStringString details) - { -#ifdef ENABLE_VIDEO - std::vector<std::map<std::string, std::string> > temp; - for (auto x : details) { - temp.push_back(convertMap(x)); - } - ring_video_set_codecs(accountID.toStdString(), temp); -#endif - } - void setDefaultDevice(const QString &name) { #ifdef ENABLE_VIDEO - ring_video_set_default_device(name.toStdString()); + DRing::setDefaultDevice(name.toStdString()); #endif } void startCamera() { #ifdef ENABLE_VIDEO - ring_video_start_camera(); + DRing::startCamera(); #endif } void stopCamera() { #ifdef ENABLE_VIDEO - ring_video_stop_camera(); + DRing::stopCamera(); #endif } bool switchInput(const QString &resource) { #ifdef ENABLE_VIDEO - return ring_video_switch_input(resource.toStdString()); + return DRing::switchInput(resource.toStdString()); #else return false; #endif diff --git a/src/typedefs.h b/src/typedefs.h index f53d49d961af4a83badc1d527b3b8baddc1cbb2d..c41ca8fb924abd777444e015159bbac5dece23d8 100644 --- a/src/typedefs.h +++ b/src/typedefs.h @@ -23,7 +23,7 @@ //Qt #include <QtCore/QMetaType> #include <QtCore/QMap> -#include <QVector> +#include <QtCore/QVector> #include <QtCore/QString> #include <QtCore/QDebug> @@ -32,10 +32,16 @@ #include <type_traits> //Typedefs (required to avoid '<' and '>' in the DBus XML) -typedef QMap<QString, QString> MapStringString; -typedef QVector< QMap<QString, QString> > VectorMapStringString; -typedef QMap< QString, QMap< QString, QVector<QString> > > MapStringMapStringVectorString; -typedef QMap<QString, int> MapStringInt; +typedef QMap<QString, QString> MapStringString ; +typedef QMap<QString, int> MapStringInt ; +typedef QVector<int> VectorInt ; +typedef QVector<uint> VectorUInt ; +typedef QVector< QMap<QString, QString> > VectorMapStringString ; +typedef QVector< QString > VectorString ; +typedef QMap< QString, QMap< QString, QVector<QString> > > MapStringMapStringVectorString; +typedef QMap< QString, QVector<QString> > MapStringVectorString ; +typedef QMap< QString, QMap< QString, QStringList > > MapStringMapStringStringList ; +typedef QMap< QString, QStringList > MapStringStringList ; template<class T, class E> struct TypedStateMachine diff --git a/src/video/device.cpp b/src/video/device.cpp index 23e9791d7548de4ea6ccb894bd412872c8e00302..6ac6c65048579e1517ec1c415c0e9c32ce28ed89 100644 --- a/src/video/device.cpp +++ b/src/video/device.cpp @@ -23,6 +23,7 @@ #include "resolution.h" #include "rate.h" #include "channel.h" +#include "renderer.h" //Ring private #include "../private/videochannel_p.h" diff --git a/src/video/devicemodel.cpp b/src/video/devicemodel.cpp index 45e55ee4c25bc83065d856ed2d1d9d6b9a0f28c1..db84231bae2d080c8178eeb0ecbba6d41a9a2607 100644 --- a/src/video/devicemodel.cpp +++ b/src/video/devicemodel.cpp @@ -22,6 +22,7 @@ #include "../dbus/videomanager.h" #include <QtCore/QCoreApplication> +#include <QtCore/QTimer> Video::DeviceModel* Video::DeviceModel::m_spInstance = nullptr; diff --git a/src/video/manager.cpp b/src/video/manager.cpp index 6c6ee4edc8d1514f84faaccafd023fd7a65c99b9..6212b77921f7893836eb5ee2ae36133224b1cbb9 100644 --- a/src/video/manager.cpp +++ b/src/video/manager.cpp @@ -1,6 +1,7 @@ /**************************************************************************** * Copyright (C) 2012-2015 by Savoir-Faire Linux * - * Author : Emmanuel Lepage Vallee <emmanuel.lepage@savoirfairelinux.com> * + * Authors : Emmanuel Lepage Vallee <emmanuel.lepage@savoirfairelinux.com>* + * Alexandre Lision <alexandre.lision@savoirfairelinux.com> * * * * This library is free software; you can redistribute it and/or * * modify it under the terms of the GNU Lesser General Public * @@ -30,7 +31,13 @@ #include "channel.h" #include "rate.h" #include "resolution.h" -#include "../private/videorate_p.h" +#include "private/videorate_p.h" +#if defined(Q_OS_DARWIN) +#include "private/directrenderer.h" +#else +#include "private/shmrenderer.h" +#endif + //Static member Video::Manager* Video::Manager::m_spInstance = nullptr; @@ -46,10 +53,8 @@ public: //Attributes bool m_PreviewState; uint m_BufferSize ; - uint m_ShmKey ; - uint m_SemKey ; QMutex* m_SSMutex ; - QHash<QString,Video::Renderer*> m_lRenderers; + QHash<QByteArray,Video::Renderer*> m_lRenderers; private: Video::Manager* q_ptr; @@ -63,9 +68,9 @@ private Q_SLOTS: } Video::ManagerPrivate::ManagerPrivate(Video::Manager* parent) : QObject(parent), q_ptr(parent), -m_BufferSize(0),m_ShmKey(0),m_SemKey(0),m_PreviewState(false),m_SSMutex(new QMutex()) +m_BufferSize(0),m_PreviewState(false),m_SSMutex(new QMutex()) { - + } ///Constructor @@ -92,14 +97,14 @@ Video::Manager* Video::Manager::instance() return m_spInstance; } -///Return the call renderer or nullptr +///Return the call Renderer or nullptr Video::Renderer* Video::Manager::getRenderer(const Call* call) const { if (!call) return nullptr; - return d_ptr->m_lRenderers[call->dringId()]; + return d_ptr->m_lRenderers[call->dringId().toLatin1()]; } -///Get the video preview renderer +///Get the video preview Renderer Video::Renderer* Video::Manager::previewRenderer() { if (!d_ptr->m_lRenderers["local"]) { @@ -108,7 +113,12 @@ Video::Renderer* Video::Manager::previewRenderer() qWarning() << "Misconfigured video device"; return nullptr; } - d_ptr->m_lRenderers["local"] = new Video::Renderer("local","",res->size()); +#if defined(Q_OS_DARWIN) + d_ptr->m_lRenderers["local"] = new Video::DirectRenderer("local", res->size()); + +#else + d_ptr->m_lRenderers["local"] = new Video::ShmRenderer("local","",res->size()); +#endif } return d_ptr->m_lRenderers["local"]; } @@ -151,43 +161,41 @@ void Video::ManagerPrivate::deviceEvent() ///A video is not being rendered void Video::ManagerPrivate::startedDecoding(const QString& id, const QString& shmPath, int width, int height) { - Q_UNUSED(id) QSize res = QSize(width,height); -// if (Video::DeviceModel::instance()->activeDevice() -// && Video::DeviceModel::instance()->activeDevice()->activeChannel()->activeResolution()->width() == width) { -// //FIXME flawed logic -// res = Video::DeviceModel::instance()->activeDevice()->activeChannel()->activeResolution()->size(); -// } -// else { -// res = QSize(width,height); -// } - - if (m_lRenderers[id] == nullptr ) { - m_lRenderers[id] = new Video::Renderer(id,shmPath,res); - m_lRenderers[id]->moveToThread(q_ptr); + + if (m_lRenderers[id.toLatin1()] == nullptr ) { + #if defined(Q_OS_DARWIN) + m_lRenderers["local"] = new Video::DirectRenderer("local", res); + #else + m_lRenderers["local"] = new Video::ShmRenderer("local",shmPath,res); + #endif + m_lRenderers[id.toLatin1()]->moveToThread(q_ptr); if (!q_ptr->isRunning()) q_ptr->start(); } else { - Video::Renderer* renderer = m_lRenderers[id]; - renderer->setShmPath(shmPath); - renderer->setSize(res); + Video::Renderer* Renderer = m_lRenderers[id.toLatin1()]; + //TODO: do direct renderer stuff here + m_lRenderers[id.toLatin1()]->setSize(res); +#if !defined(Q_OS_DARWIN) + static_cast<ShmRenderer*>(m_lRenderers[id.toLatin1()])->setShmPath(shmPath); +#endif } - m_lRenderers[id]->startRendering(); + m_lRenderers[id.toLatin1()]->startRendering(); Video::Device* dev = Video::DeviceModel::instance()->getDevice(id); if (dev) { - emit dev->renderingStarted(m_lRenderers[id]); + emit dev->renderingStarted(m_lRenderers[id.toLatin1()]); } if (id != "local") { qDebug() << "Starting video for call" << id; - emit q_ptr->videoCallInitiated(m_lRenderers[id]); + emit q_ptr->videoCallInitiated(m_lRenderers[id.toLatin1()]); } else { m_PreviewState = true; emit q_ptr->previewStateChanged(true); - emit q_ptr->previewStarted(m_lRenderers[id]); + emit q_ptr->previewStarted(m_lRenderers[id.toLatin1()]); } } @@ -195,11 +203,11 @@ void Video::ManagerPrivate::startedDecoding(const QString& id, const QString& sh void Video::ManagerPrivate::stoppedDecoding(const QString& id, const QString& shmPath) { Q_UNUSED(shmPath) - Video::Renderer* r = m_lRenderers[id]; + Video::Renderer* r = m_lRenderers[id.toLatin1()]; if ( r ) { r->stopRendering(); } - qDebug() << "Video stopped for call" << id << "Renderer found:" << (m_lRenderers[id] != nullptr); + qDebug() << "Video stopped for call" << id << "Renderer found:" << (m_lRenderers[id.toLatin1()] != nullptr); // emit videoStopped(); Video::Device* dev = Video::DeviceModel::instance()->getDevice(id); @@ -212,7 +220,7 @@ void Video::ManagerPrivate::stoppedDecoding(const QString& id, const QString& sh emit q_ptr->previewStopped(r); } // r->mutex()->lock(); - m_lRenderers[id] = nullptr; + m_lRenderers[id.toLatin1()] = nullptr; delete r; } diff --git a/src/video/manager.h b/src/video/manager.h index 634fc898f87c8024d8f574b39f3c1a59e918f0c8..9e127bc3a4c1c70a27e8017cdfe784c5ce75a3b8 100644 --- a/src/video/manager.h +++ b/src/video/manager.h @@ -84,8 +84,8 @@ Q_SIGNALS: void videoCallInitiated(Video::Renderer*); ///The preview started/stopped void previewStateChanged(bool startStop); - void previewStarted(Video::Renderer* renderer); - void previewStopped(Video::Renderer* renderer); + void previewStarted(Video::Renderer* Renderer); + void previewStopped(Video::Renderer* Renderer); }; diff --git a/src/video/renderer.cpp b/src/video/renderer.cpp index f54cc4ff0a0828678ef994e77bcff6cf997339d3..384978767c609894c7d4c18cc9b49025217a7933 100644 --- a/src/video/renderer.cpp +++ b/src/video/renderer.cpp @@ -1,6 +1,6 @@ /**************************************************************************** * Copyright (C) 2012-2015 by Savoir-Faire Linux * - * Author : Emmanuel Lepage Vallee <emmanuel.lepage@savoirfairelinux.com> * + * Author : Alexandre Lision <alexandre.lision@savoirfairelinux.com> * * * * This library is free software; you can redistribute it and/or * * modify it under the terms of the GNU Lesser General Public * @@ -17,399 +17,88 @@ ***************************************************************************/ #include "renderer.h" -#include <QtCore/QDebug> -#include <QtCore/QMutex> -#include <QtCore/QThread> - -#include <sys/ipc.h> -#include <sys/sem.h> -#include <sys/shm.h> -#include <fcntl.h> -#include <unistd.h> -#include <sys/mman.h> -#include <semaphore.h> -#include <errno.h> - - -#ifndef CLOCK_REALTIME -#define CLOCK_REALTIME 0 -#endif - -#include <QtCore/QTimer> -#include "manager.h" -#include "resolution.h" - -///Shared memory object -struct SHMHeader{ - sem_t notification; - sem_t mutex; - - unsigned m_BufferGen; - int m_BufferSize; - /* The header will be aligned on 16-byte boundaries */ - char padding[8]; - -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-pedantic" - char m_Data[]; -#pragma GCC diagnostic pop -}; - -namespace Video { - -class RendererPrivate : public QObject -{ - Q_OBJECT -public: - RendererPrivate(Video::Renderer* parent); +//Ring +#include "private/videorenderer_p.h" - //Attributes - QString m_ShmPath ; - int fd ; - SHMHeader* m_pShmArea ; - signed int m_ShmAreaLen ; - uint m_BufferGen ; - bool m_isRendering; - QTimer* m_pTimer ; - QByteArray m_Frame[2] ; - bool m_FrameIdx ; - QSize m_pSize ; - QMutex* m_pMutex ; - QMutex* m_pSSMutex ; - QString m_Id ; - int m_fpsC ; - int m_Fps ; - QTime m_CurrentTime; - - //Constants - static const int TIMEOUT_SEC = 1; // 1 second - - //Helpers - timespec createTimeout(); - bool shmLock (); - void shmUnlock (); - bool renderToBitmap(); - -private: - Video::Renderer* q_ptr; - -private Q_SLOTS: - void timedEvents(); -}; - -} +//Qt +#include <QtCore/QMutex> Video::RendererPrivate::RendererPrivate(Video::Renderer* parent) : QObject(parent), q_ptr(parent), - fd(-1),m_fpsC(0),m_Fps(0), - m_pShmArea((SHMHeader*)MAP_FAILED), m_ShmAreaLen(0), m_BufferGen(0), - m_isRendering(false),m_pTimer(nullptr),m_pMutex(new QMutex()), - m_FrameIdx(false),m_pSSMutex(new QMutex()) +m_pMutex(new QMutex()), m_FrameIdx(false) { } -///Constructor -Video::Renderer::Renderer(const QString& id, const QString& shmPath, const QSize& res): QObject(nullptr), d_ptr(new RendererPrivate(this)) +Video::Renderer::Renderer(const QByteArray& id, const QSize& res) { - d_ptr->m_ShmPath = shmPath; - d_ptr->m_Id = id; - d_ptr->m_pSize = res; - setObjectName("Video::Renderer:"+id); + d_ptr->m_pSize = res; + d_ptr->m_Id = id; } -///Destructor Video::Renderer::~Renderer() -{ - stopShm(); - //delete m_pShmArea; -} - -///Get the data from shared memory and transform it into a QByteArray -bool Video::RendererPrivate::renderToBitmap() -{ -#ifdef Q_OS_LINUX - if (!m_isRendering) { - return false; - } - - if (!shmLock()) { - return false; - } - - if(!Video::Manager::instance()->startStopMutex()->tryLock()) - return false; - - // wait for a new buffer - while (m_BufferGen == m_pShmArea->m_BufferGen) { - shmUnlock(); - - int err = sem_trywait(&m_pShmArea->notification); - // Useful for debugging -// switch (errno ) { -// case EINTR: -// qDebug() << "Unlock failed: Interrupted function call (POSIX.1); see signal(7)"; -// ok = false; -// return QByteArray(); -// break; -// case EINVAL: -// qDebug() << "Unlock failed: Invalid argument (POSIX.1)"; -// ok = false; -// return QByteArray(); -// break; -// case EAGAIN: -// qDebug() << "Unlock failed: Resource temporarily unavailable (may be the same value as EWOULDBLOCK) (POSIX.1)"; -// ok = false; -// return QByteArray(); -// break; -// case ETIMEDOUT: -// qDebug() << "Unlock failed: Connection timed out (POSIX.1)"; -// ok = false; -// return QByteArray(); -// break; -// } - if ((err < 0) || (!shmLock())) { - Video::Manager::instance()->startStopMutex()->unlock(); - return false; - } - usleep((1/60.0)*100); - } - - if (!q_ptr->resizeShm()) { - qDebug() << "Could not resize shared memory"; - Video::Manager::instance()->startStopMutex()->unlock(); - return false; - } - - bool otherFrame = ! m_FrameIdx; - if (m_Frame[otherFrame].size() != m_pShmArea->m_BufferSize) - m_Frame[otherFrame].resize(m_pShmArea->m_BufferSize); - memcpy(m_Frame[otherFrame].data(),m_pShmArea->m_Data,m_pShmArea->m_BufferSize); - m_BufferGen = m_pShmArea->m_BufferGen; - shmUnlock(); - m_FrameIdx = !m_FrameIdx; - - Video::Manager::instance()->startStopMutex()->unlock(); - return true; -#else - return false; -#endif -} - -///Connect to the shared memory -bool Video::Renderer::startShm() -{ - if (d_ptr->fd != -1) { - qDebug() << "fd must be -1"; - return false; - } - - d_ptr->fd = shm_open(d_ptr->m_ShmPath.toLatin1(), O_RDWR, 0); - if (d_ptr->fd < 0) { - qDebug() << "could not open shm area " << d_ptr->m_ShmPath << ", shm_open failed:" << strerror(errno); - return false; - } - d_ptr->m_ShmAreaLen = sizeof(SHMHeader); - #pragma GCC diagnostic push - #pragma GCC diagnostic ignored "-Wzero-as-null-pointer-constant" - d_ptr->m_pShmArea = (SHMHeader*) mmap(NULL, d_ptr->m_ShmAreaLen, PROT_READ | PROT_WRITE, MAP_SHARED, d_ptr->fd, 0); - #pragma GCC diagnostic pop - if (d_ptr->m_pShmArea == MAP_FAILED) { - qDebug() << "Could not map shm area, mmap failed"; - return false; - } - emit started(); - return true; -} - -///Disconnect from the shared memory -void Video::Renderer::stopShm() -{ - if (d_ptr->fd >= 0) - close(d_ptr->fd); - d_ptr->fd = -1; - - if (d_ptr->m_pShmArea != MAP_FAILED) - munmap(d_ptr->m_pShmArea, d_ptr->m_ShmAreaLen); - d_ptr->m_ShmAreaLen = 0; - d_ptr->m_pShmArea = (SHMHeader*) MAP_FAILED; -} - -///Resize the shared memory -bool Video::Renderer::resizeShm() -{ - while (( (unsigned int) sizeof(SHMHeader) + (unsigned int) d_ptr->m_pShmArea->m_BufferSize) > (unsigned int) d_ptr->m_ShmAreaLen) { - const size_t new_size = sizeof(SHMHeader) + d_ptr->m_pShmArea->m_BufferSize; - - d_ptr->shmUnlock(); - if (munmap(d_ptr->m_pShmArea, d_ptr->m_ShmAreaLen)) { - qDebug() << "Could not unmap shared area:" << strerror(errno); - return false; - } - - #pragma GCC diagnostic push - #pragma GCC diagnostic ignored "-Wzero-as-null-pointer-constant" - d_ptr->m_pShmArea = (SHMHeader*) mmap(NULL, new_size, PROT_READ | PROT_WRITE, MAP_SHARED, d_ptr->fd, 0); - #pragma GCC diagnostic pop - d_ptr->m_ShmAreaLen = new_size; - - if (!d_ptr->m_pShmArea) { - d_ptr->m_pShmArea = nullptr; - qDebug() << "Could not remap shared area"; - return false; - } - - d_ptr->m_ShmAreaLen = new_size; - if (!d_ptr->shmLock()) - return true; - } - return true; -} - -///Lock the memory while the copy is being made -bool Video::RendererPrivate::shmLock() -{ -#ifdef Q_OS_LINUX - return sem_trywait(&m_pShmArea->mutex) >= 0; -#else - return false; -#endif -} - -///Remove the lock, allow a new frame to be drawn -void Video::RendererPrivate::shmUnlock() -{ - sem_post(&m_pShmArea->mutex); -} - +{} /***************************************************************************** - * * - * Slots * - * * - ****************************************************************************/ +* * +* Getters * +* * +****************************************************************************/ -///Update the buffer -void Video::RendererPrivate::timedEvents() +bool Video::Renderer::isRendering() const { - - bool ok = renderToBitmap(); - - if (ok) { - - //Compute the FPS shown to the client - if (m_CurrentTime.second() != QTime::currentTime().second()) { - m_Fps = m_fpsC; - m_fpsC=0; - m_CurrentTime = QTime::currentTime(); - } - m_fpsC++; - - emit q_ptr->frameUpdated(); - } - /*else { - qDebug() << "Frame dropped"; - usleep(rand()%1000); //Be sure it can come back in sync - }*/ -} - -///Start the rendering loop -void Video::Renderer::startRendering() -{ - Video::Manager::instance()->startStopMutex()->lock(); - QMutexLocker locker(d_ptr->m_pMutex); - startShm(); - if (!d_ptr->m_pTimer) { - d_ptr->m_pTimer = new QTimer(nullptr); - -// m_pTimer->moveToThread(thread()); - connect(d_ptr->m_pTimer,SIGNAL(timeout()),d_ptr.data(),SLOT(timedEvents())); - d_ptr->m_pTimer->setInterval(30); - } - - if (!d_ptr->m_pTimer->isActive()) { - qDebug() << "Is running" << thread()->isRunning(); - d_ptr->m_pTimer->start(); - } - else - qDebug() << "Timer already started!"; - - d_ptr->m_isRendering = true; - Video::Manager::instance()->startStopMutex()->unlock(); + return d_ptr->m_isRendering; } -///Stop the rendering loop -void Video::Renderer::stopRendering() +QByteArray& Video::RendererPrivate::otherFrame() const { - Video::Manager::instance()->startStopMutex()->lock(); - QMutexLocker locker(d_ptr->m_pMutex); - d_ptr->m_isRendering = false; - qDebug() << "Stopping rendering on" << d_ptr->m_Id; - if (d_ptr->m_pTimer) - d_ptr->m_pTimer->stop(); - emit stopped(); - stopShm(); - Video::Manager::instance()->startStopMutex()->unlock(); -} - - -/***************************************************************************** - * * - * Getters * - * * - ****************************************************************************/ - -///Get the raw bytes directly from the SHM, not recommended, but optimal -const char* Video::Renderer::rawData() -{ - return d_ptr->m_isRendering?d_ptr->m_Frame[d_ptr->m_FrameIdx].data():nullptr; -} - -///Is this redenrer active -bool Video::Renderer::isRendering() -{ - return d_ptr->m_isRendering; + static QByteArray empty; + return q_ptr->isRendering()?const_cast<Video::RendererPrivate*>(this)->m_Frame[!m_FrameIdx]:empty; } ///Return the current framerate -const QByteArray& Video::Renderer::currentFrame() +const QByteArray& Video::Renderer::currentFrame() const { - static QByteArray empty; - return d_ptr->m_isRendering?d_ptr->m_Frame[d_ptr->m_FrameIdx]:empty; + static QByteArray empty; + return isRendering()?d_ptr->m_Frame[d_ptr->m_FrameIdx]:empty; } -///Return the current resolution -QSize Video::Renderer::size() +///Get id of this renderer +QString Video::Renderer::id() const { - return d_ptr->m_pSize; + return d_ptr->m_Id; } ///Get mutex, in case renderer and views are not in the same thread -QMutex* Video::Renderer::mutex() +QMutex* Video::Renderer::mutex() const { - return d_ptr->m_pMutex; + return d_ptr->m_pMutex; } -///Get the current frame rate of this renderer -int Video::Renderer::fps() const +///Return the current resolution +QSize Video::Renderer::size() const { - return d_ptr->m_Fps; + return d_ptr->m_pSize; } - /***************************************************************************** * * * Setters * * * ****************************************************************************/ -void Video::Renderer::setSize(const QSize& size) +///Return the current resolution +void Video::Renderer::setRendering(bool rendering) const +{ + d_ptr->m_isRendering = rendering; +} + +void Video::Renderer::setSize(const QSize& size) const { - d_ptr->m_pSize = size; + d_ptr->m_pSize = size; } -void Video::Renderer::setShmPath(const QString& path) +void Video::RendererPrivate::updateFrameIndex() { - d_ptr->m_ShmPath = path; + m_FrameIdx = !m_FrameIdx; } #include <renderer.moc> - diff --git a/src/video/renderer.h b/src/video/renderer.h index ed895255b0aa9a93032d49c1eaaef90cc46dc351..9374ca43d45e47649281167cda5e8541f1cda242 100644 --- a/src/video/renderer.h +++ b/src/video/renderer.h @@ -15,71 +15,72 @@ * You should have received a copy of the GNU General Public License * * along with this program. If not, see <http://www.gnu.org/licenses/>. * ***************************************************************************/ -#ifndef VIDEO_RENDERER_H -#define VIDEO_RENDERER_H +#ifndef VIDEO_ABSTRACT_RENDERER_H +#define VIDEO_ABSTRACT_RENDERER_H //Base #include <QtCore/QObject> -#include <QtCore/QTime> #include <typedefs.h> -#include <time.h> //Qt -class QTimer; class QMutex; //Ring #include "device.h" -//Private -struct SHMHeader; - namespace Video { -class RendererPrivate; -///Manage shared memory and convert it to QByteArray +class RendererPrivate; +class ShmRendererPrivate; +class DirectRendererPrivate; + +/** + * This class provide a rendering object to be used by clients + * to get the video content. This object is not intended to be + * extended outside of the LibRingClient. + * + * Each platform transparently provide its own implementation. + */ class LIB_EXPORT Renderer : public QObject { - #pragma GCC diagnostic push - #pragma GCC diagnostic ignored "-Wzero-as-null-pointer-constant" - Q_OBJECT - #pragma GCC diagnostic pop - - public: - //Constructor - Renderer (const QString& id, const QString& shmPath, const QSize& res); - virtual ~Renderer(); - - //Mutators - bool resizeShm(); - void stopShm (); - bool startShm (); - - //Getters - const char* rawData () ; - bool isRendering () ; - const QByteArray& currentFrame () ; - QSize size () ; - QMutex* mutex () ; - int fps () const; - - //Setters - void setSize(const QSize& res); - void setShmPath (const QString& path); - -private: - QScopedPointer<RendererPrivate> d_ptr; - Q_DECLARE_PRIVATE(Renderer) - -public Q_SLOTS: - void startRendering(); - void stopRendering (); +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wzero-as-null-pointer-constant" +Q_OBJECT +#pragma GCC diagnostic pop + +friend class Video::ShmRendererPrivate; +friend class Video::DirectRendererPrivate; + +public: + //Constructor + Renderer (const QByteArray& id, const QSize& res); + virtual ~Renderer(); + + //Getters + virtual bool isRendering () const; + virtual const QByteArray& currentFrame () const; + virtual QSize size () const; + virtual QMutex* mutex () const; + virtual QString id () const; + + //Setters + void setRendering(bool rendering) const; + void setSize(const QSize& size) const; Q_SIGNALS: ///Emitted when a new frame is ready void frameUpdated(); - void stopped(); - void started(); + void stopped (); + void started (); + +public Q_SLOTS: + virtual void startRendering() = 0; + virtual void stopRendering () = 0; + + +private: + QScopedPointer<RendererPrivate> d_ptr; + Q_DECLARE_PRIVATE(Renderer) };