/**
* This file is part of TelepathyQt4
*
* @copyright Copyright (C) 2009-2010 Collabora Ltd.
* @copyright Copyright (C) 2009-2010 Nokia Corporation
* @license LGPL 2.1
*
* 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 Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include
#include
#include
namespace Tp
{
struct TELEPATHY_QT4_NO_EXPORT CapabilitiesBase::Private : public QSharedData
{
Private(bool specificToContact);
Private(const RequestableChannelClassSpecList &rccSpecs, bool specificToContact);
RequestableChannelClassSpecList rccSpecs;
bool specificToContact;
};
CapabilitiesBase::Private::Private(bool specificToContact)
: specificToContact(specificToContact)
{
}
CapabilitiesBase::Private::Private(const RequestableChannelClassSpecList &rccSpecs,
bool specificToContact)
: rccSpecs(rccSpecs),
specificToContact(specificToContact)
{
}
/**
* \class CapabilitiesBase
* \ingroup clientconn
* \headerfile TelepathyQt4/capabilities-base.h
*
* \brief The CapabilitiesBase class represents the capabilities a Connection
* or a Contact supports.
*/
/**
* Construct a new CapabilitiesBase object.
*/
CapabilitiesBase::CapabilitiesBase()
: mPriv(new Private(false))
{
}
/**
* Construct a new CapabilitiesBase object.
*
* \param specificToContact Whether this object describes the capabilities of a
* particular contact.
*/
CapabilitiesBase::CapabilitiesBase(bool specificToContact)
: mPriv(new Private(specificToContact))
{
}
/**
* Construct a new CapabilitiesBase object using the given \a rccs.
*
* \param rccs RequestableChannelClassList representing the capabilities of a
* connection or contact.
* \param specificToContact Whether this object describes the capabilities of a
* particular contact.
*/
CapabilitiesBase::CapabilitiesBase(const RequestableChannelClassList &rccs,
bool specificToContact)
: mPriv(new Private(RequestableChannelClassSpecList(rccs), specificToContact))
{
}
/**
* Construct a new CapabilitiesBase object using the given \a rccSpecs.
*
* \param rccSpecs RequestableChannelClassSpecList representing the capabilities of a
* connection or contact.
* \param specificToContact Whether this object describes the capabilities of a
* particular contact.
*/
CapabilitiesBase::CapabilitiesBase(const RequestableChannelClassSpecList &rccSpecs,
bool specificToContact)
: mPriv(new Private(rccSpecs, specificToContact))
{
}
CapabilitiesBase::CapabilitiesBase(const CapabilitiesBase &other)
: mPriv(other.mPriv)
{
}
/**
* Class destructor.
*/
CapabilitiesBase::~CapabilitiesBase()
{
}
CapabilitiesBase &CapabilitiesBase::operator=(const CapabilitiesBase &other)
{
this->mPriv = other.mPriv;
return *this;
}
/**
* Return the list of requestable channel class spec representing the requests that can succeed.
*
* This can be used by advanced clients to determine whether an unusually
* complex request would succeed. See the \telepathy_spec
* for details of how to interpret the returned list.
*
* The higher-level methods like textChats() are likely to be more
* useful to the majority of clients.
*
* \return A RequestableChannelClassSpecList indicating the parameters to
* Account::createChannel, Account::ensureChannel,
* Connection::createChannel and Connection::ensureChannel
* that can be expected to work.
*/
RequestableChannelClassSpecList CapabilitiesBase::allClassSpecs() const
{
return mPriv->rccSpecs;
}
void CapabilitiesBase::updateRequestableChannelClasses(
const RequestableChannelClassList &rccs)
{
mPriv->rccSpecs = RequestableChannelClassSpecList(rccs);
}
/**
* Return whether this object accurately describes the capabilities of a
* particular contact, or if it's only a guess based on the
* capabilities of the underlying connection.
*
* In protocols like XMPP where each contact advertises their capabilities
* to others, Contact::capabilities() will generally return an object where
* this method returns true.
*
* In protocols like SIP where contacts' capabilities are not known,
* Contact::capabilities() will return an object where this method returns
* false, whose methods textChats() etc. are based on what the
* underlying connection supports.
*
* This reflects the fact that the best assumption an application can make is
* that every contact supports every channel type supported by the connection,
* while indicating that requests to communicate might fail if the contact
* does not actually have the necessary functionality.
*
* \return \c true if this object describes the capabilities of a particular
* contact, \c false otherwise.
*/
bool CapabilitiesBase::isSpecificToContact() const
{
return mPriv->specificToContact;
}
/**
* Return whether private text channels can be established by providing
* a contact identifier.
*
* If the protocol is such that text chats can be established, but only via
* a more elaborate D-Bus API than normal (because more information is needed),
* then this method will return false.
*
* \return \c true if Account::ensureTextChat() can be expected to work,
* \c false otherwise.
*/
bool CapabilitiesBase::textChats() const
{
foreach (const RequestableChannelClassSpec &rccSpec, mPriv->rccSpecs) {
if (rccSpec.supports(RequestableChannelClassSpec::textChat())) {
return true;
}
}
return false;
}
/**
* Return whether private audio and/or video calls can be established by
* providing a contact identifier.
*
* If the protocol is such that these calls can be established, but only via
* a more elaborate D-Bus API than normal (because more information is needed),
* then this method will return false.
*
* \return \c true if Account::ensureStreamedMediaCall() can be expected to work,
* \c false otherwise.
* \sa streamedMediaAudioCalls(), streamedMediaVideoCalls(),
* streamedMediaVideoCallsWithAudio()
*/
bool CapabilitiesBase::streamedMediaCalls() const
{
foreach (const RequestableChannelClassSpec &rccSpec, mPriv->rccSpecs) {
if (rccSpec.supports(RequestableChannelClassSpec::streamedMediaCall())) {
return true;
}
}
return false;
}
/**
* Return whether private audio calls can be established by providing a
* contact identifier.
*
* Call upgradingCalls() to determine whether such calls are
* likely to be upgradable to have a video stream later.
*
* If the protocol is such that these calls can be established, but only via
* a more elaborate D-Bus API than normal (because more information is needed),
* then this method will return false.
*
* In some older connection managers, streamedMediaAudioCalls() and
* streamedMediaVideoCalls() might both return false, even though streamedMediaCalls() returns
* true. This indicates that only an older API is supported - clients of these connection managers
* must call Account::ensureStreamedMediaCall() to get an empty call, then add audio and/or
* video streams to it.
*
* \return \c true if Account::ensureStreamedMediaAudioCall() can be expected to work,
* \c false otherwise.
* \sa streamedMediaCalls(), streamedMediaVideoCalls(), streamedMediaVideoCallsWithAudio()
*/
bool CapabilitiesBase::streamedMediaAudioCalls() const
{
foreach (const RequestableChannelClassSpec &rccSpec, mPriv->rccSpecs) {
if (rccSpec.supports(RequestableChannelClassSpec::streamedMediaAudioCall())) {
return true;
}
}
return false;
}
/**
* Return whether private video calls can be established by providing a
* contact identifier.
*
* The same comments as for streamedMediaAudioCalls() apply to this method.
*
* \return \c true if Account::ensureStreamedMediaVideoCall() can be expected to work,
* if given \c false as \a withAudio parameter, \c false otherwise.
* \sa streamedMediaCalls(), streamedMediaAudioCalls(), streamedMediaVideoCallsWithAudio()
*/
bool CapabilitiesBase::streamedMediaVideoCalls() const
{
foreach (const RequestableChannelClassSpec &rccSpec, mPriv->rccSpecs) {
if (rccSpec.supports(RequestableChannelClassSpec::streamedMediaVideoCall())) {
return true;
}
}
return false;
}
/**
* Return whether private video calls with audio can be established by providing a
* contact identifier.
*
* The same comments as for streamedMediaAudioCalls() apply to this method.
*
* \return \c true if Account::ensureStreamedMediaVideoCall() can be expected to work,
* if given \c true as \a withAudio parameter, \c false otherwise.
* \sa streamedMediaCalls(), streamedMediaAudioCalls(), streamedMediaVideoCalls()
*/
bool CapabilitiesBase::streamedMediaVideoCallsWithAudio() const
{
foreach (const RequestableChannelClassSpec &rccSpec, mPriv->rccSpecs) {
if (rccSpec.supports(RequestableChannelClassSpec::streamedMediaVideoCallWithAudio())) {
return true;
}
}
return false;
}
/**
* Return whether the protocol supports adding streams of a different type
* to ongoing media calls.
*
* In some protocols and clients (such as XMPP Jingle), all calls potentially
* support both audio and video. This is indicated by returning true.
*
* In other protocols and clients (such as MSN, and the variant of XMPP Jingle
* used by Google clients), the streams are fixed at the time the call is
* started, so if you will ever want video, you have to ask for it at the
* beginning, for instance with ensureStreamedMediaVideoCall(). This is indicated by
* returning false.
*
* User interfaces can use this method as a UI hint. If it returns false,
* then a UI wishing to support both audio and video calls will have to
* provide separate "audio call" and "video call" buttons or menu items;
* if it returns true, a single button that makes an audio call is sufficient,
* because video can be added later.
*
* (The underlying Telepathy feature is the ImmutableStreams property; if this
* method returns true, then ImmutableStreams is false, and vice versa).
*
* \return \c true if audio calls can be upgraded to audio + video,
* \c false otherwise.
*/
bool CapabilitiesBase::upgradingStreamedMediaCalls() const
{
foreach (const RequestableChannelClassSpec &rccSpec, mPriv->rccSpecs) {
if (rccSpec.channelType() == TP_QT4_IFACE_CHANNEL_TYPE_STREAMED_MEDIA &&
!rccSpec.allowsProperty(TP_QT4_IFACE_CHANNEL_TYPE_STREAMED_MEDIA + QLatin1String(".ImmutableStreams"))) {
// TODO should we test all classes that have channelType
// StreamedMedia or just one is fine?
return true;
}
}
return false;
}
/**
* Return whether file transfer can be established by providing a contact identifier
*
* \return \c true if file transfers can be expected to work,
* \c false otherwise.
*/
bool CapabilitiesBase::fileTransfers() const
{
foreach (const RequestableChannelClassSpec &rccSpec, mPriv->rccSpecs) {
if (rccSpec.supports(RequestableChannelClassSpec::fileTransfer())) {
return true;
}
}
return false;
}
} // Tp