libringqt is a library for GNU Ring, a secure communication platform.
It provides a full middleware personal information management system along with "turn key" QML and Qt Model/View bindings to make creating Qt+Ring.cx applications quick and safe.
This library exposes about 40 QAbstractItemModels for various components of Ring. It also tracks the state internally and take great care of always exposing up to date and valid data.
It also provides a powerful extension system to integrate system specific assets
such as contacts, ringtones, TLS certificates into the system so libringqt
can
track them automatically.
The API aims to be externally consistent and internally implemented as a set
of state machines. The public API only exposes already validated data and
prevent the state from being corrupted. Most public classes have an internal
API only exposed to friend class
.
Here are the main concepts of LibRingQt from the most abstract network entity down to an actual human. Each layer of abstract exists to cleanly handle any ambiguous obstacle, changes of cardinality or synchronization issues.
An audio, video or historical call. This class is slowly deprecated in the API
in favor of Event
and will eventually be merged with the Media
subsystem
once it is no longer coupled with everything else.
A call, chat session, file transfer, voice mail or anything else that has a number of participant, a point in time where it starts and a point in time where it ends. This still being integrated and is a work in progress. It aims to help uncouple some of the phone related concepts and help migrate to a more generic multimedia / PIM platform as the scope is extended.
Groups of event are managed as Calendar objects. This is intended to be extended for an archival and cross device synchronization subsystem.
Either a phone number, a SIP URI or an unique Ring account identifier.
How to reach someone and the associated metadata for that specific way of reaching him/her/it. It has the following primary keys:
- An URI (immutable)
- An Account object (can be set only once)
- A Person object (can be set only once)
The factory is IndividualDirectory
and will take care of re-using and
de-duplicating all instances.
A TemporaryContactMethod
subclass exists with more related requirements but
can only be used to build "true" ContactMethods (like in the search model).
This class instances are heavily indexed and the lookup is very fast.
Either a contact, a peer or the user itself. This is a very abstract view of
someone. They always exists whether or not anything about the person is known.
It is a set of ContactMethod
and the concatenation of their metadata.
This object tracks the metadata associated with someone
In concrete version of the individual. It has an undefined number of attributes.
This object tracks the information associated with someone
TODO (callable, schedulable, present/tracked, collectable)
- Linux (amd64 and ARM)
- macOS
- Android
- Windows (not tested as often, but known to work)
Qt 5.3+ is supported, Qt 5.6+ recommended.
The media namespace is where all classes related to live telecommunication classes reside.
A set of live problem solving algorithms intended to restore a coherent state when something goes wrong. Ring is always a distributed system and SIP is often an unreliable federation network. Add the use of UDP and you end up with a very fragile system that will eventually fail.
Libcard is a semi independant component. It implements the VObject format as used by various IEFT Internet standards such as vCard or iCal. It uses modern C++ instead of Qt where it makes sense. While it's still quite coupled with libringqt clases, it aims at being it's own thing as much as possible.
The collection subsystem is a generic C++ CMS system to manage various assets on various platform. It is pluggable and allows to interact with third party systems using a standardized interface. There is contact collections for KDE Akonadi, macOS addressbook, vCard folders, Gnome Evolution. It's also used for TLS certificates, ringtones, calendars, blockchains, caching, voicemails and alsmost every other serializable classes.
They implement various IPC mechanism to talk to LibRing. QtWrapper just converts stdlib types into Qt types and link directly to LibRing. DBus and Rest use multiprocess message passing.
Both DBus and "qtwrapper" modes are currently officially supported. REST would eventually be nice and a msgpack mode would also be interesting for sandboxing.
Creating some objects require a non-trivial amount of imperative code. The bulder objects turn this imperative transaction into a declarative object.
They can be committed or canceled. All relevant steps and choices are turned into properties.
To mitigate the memory management mess mentionned below, some resource use shared pointers even if QtQuick is unstable when they are used. To mitigate this, the Locker objects track the workflow objects lifecycle internally so it becomes safe to use QtQuick with objects that don't follow the traditional object tree to manage their memory.
Proxy models with QtQuick bindings. The allow to get the "right data" without imperative JavaScript.
This library has been created to split the logic and GUI code of SFLPhone-KDE, a software phone. It was forked into LibRingClient then Ring-LRC when the SFLPhone application was EOLed and the GNU Ring project arose from its ashes.
It was moved from the KDE project to the GNU project. During the GNU era, the focus on Qt was dropped and a fork was necessary to keep alive the Qt APIs and models. The upstream GNU Ring project deprecated all relevant API used to create QML bindings. This fork is a community project and is no longer developed byu Savoir-faire Linux, the sole author of GNU Ring. It is maintained by one of the two original author of the code and sponsored by Blue Systems.
This project aims to continue the development of a QtCore based library with full QML compatible bindings for the GNU Ring project.
It's API is currently still unstable as the fork offers an unique opportunity to port the API to C++14 and get rid of old and unused components. Once the new API is finalized, this project will attempt to re-join the KDE project.
This library memory management is a mix of legacy limitations and odd design
requirements. Up until Qt4 support was dropped, C++11 wasn't usable along with
Qt and this caused the proliferation if little classes to link everything. Up
to this day, QML support for smart pointer is horrible and thus everything has
to be exposed as raw pointers to be reliable (along with never using const*
.
This make it nearly impossible to delete the main objects.
To work around this and help the metadata "converge" to a smaller number of
instances, there is online deduplication of most important objects. Factory
classes are responsible of creating new instances, re-using old one and merging
instances when all ambiguity is gone. Merging is done by using the object
PIMPLE pointers (d_ptr
). By deleting the d_ptr, it is possible to keep the
memory usage mostly stable while never deliting the main pointers.
The problem with that is that signals are proxyed to all top-level objects
and ==
/!=
cannot safely be used to compare pointers (as they might proxy the
same "real" object). Unfortunately, it is also used in hundreds of places where
it should not.
As a side effect, delete
is used on the d_ptr
instead of Qt own object tree
to avoid accidentally deleting objects while one of their proxy is still alive.
Objects that are not intended to be exposed to the bindings use shared pointers.
However if they ever become exposed to the bindings, it has to be reverted and
this has so far caused a lot of problem (like converting QWeakPointer
to
QSharedPointer
so the memory is in effect never freed and .data()
becomes
safe.
- Author Emmanuel Lepage-Vallee
- Author Stepan Salenikovich
- Copyright Savoir-faire Linux 2004-2017
- Copyright Emmanuel Lepage-Vallee 2015-present
- Copyright BlueSystems 2017-present