1 /**
2  * This file is part of TelepathyQt
3  *
4  * @copyright Copyright (C) 2010-2011 Collabora Ltd. <http://www.collabora.co.uk/>
5  * @license LGPL 2.1
6  *
7  * This library is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Lesser General Public
9  * License as published by the Free Software Foundation; either
10  * version 2.1 of the License, or (at your option) any later version.
11  *
12  * This library is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  * Lesser General Public License for more details.
16  *
17  * You should have received a copy of the GNU Lesser General Public
18  * License along with this library; if not, write to the Free Software
19  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
20  */
21 
22 #include <TelepathyQt/TubeChannel>
23 
24 #include "TelepathyQt/_gen/tube-channel.moc.hpp"
25 
26 #include "TelepathyQt/debug-internal.h"
27 
28 #include <TelepathyQt/PendingVariantMap>
29 
30 namespace Tp
31 {
32 
33 struct TP_QT_NO_EXPORT TubeChannel::Private
34 {
35     Private(TubeChannel *parent);
36 
37     static void introspectTube(TubeChannel::Private *self);
38 
39     void extractTubeProperties(const QVariantMap &props);
40 
41     // Public object
42     TubeChannel *parent;
43 
44     ReadinessHelper *readinessHelper;
45 
46     // Introspection
47     TubeChannelState state;
48     QVariantMap parameters;
49 };
50 
Private(TubeChannel * parent)51 TubeChannel::Private::Private(TubeChannel *parent)
52     : parent(parent),
53       readinessHelper(parent->readinessHelper()),
54       state((TubeChannelState) -1)
55 {
56     ReadinessHelper::Introspectables introspectables;
57 
58     ReadinessHelper::Introspectable introspectableTube(
59             QSet<uint>() << 0,                                                          // makesSenseForStatuses
60             Features() << Channel::FeatureCore,                                         // dependsOnFeatures (core)
61             QStringList() << TP_QT_IFACE_CHANNEL_INTERFACE_TUBE, // dependsOnInterfaces
62             (ReadinessHelper::IntrospectFunc) &TubeChannel::Private::introspectTube,
63             this);
64     introspectables[TubeChannel::FeatureCore] = introspectableTube;
65 
66     readinessHelper->addIntrospectables(introspectables);
67 }
68 
introspectTube(TubeChannel::Private * self)69 void TubeChannel::Private::introspectTube(TubeChannel::Private *self)
70 {
71     TubeChannel *parent = self->parent;
72 
73     debug() << "Introspecting tube properties";
74     Client::ChannelInterfaceTubeInterface *tubeInterface =
75             parent->interface<Client::ChannelInterfaceTubeInterface>();
76 
77     parent->connect(tubeInterface,
78             SIGNAL(TubeChannelStateChanged(uint)),
79             SLOT(onTubeChannelStateChanged(uint)));
80 
81     PendingVariantMap *pvm = tubeInterface->requestAllProperties();
82     parent->connect(pvm,
83             SIGNAL(finished(Tp::PendingOperation *)),
84             SLOT(gotTubeProperties(Tp::PendingOperation *)));
85 }
86 
extractTubeProperties(const QVariantMap & props)87 void TubeChannel::Private::extractTubeProperties(const QVariantMap &props)
88 {
89     state = (Tp::TubeChannelState) qdbus_cast<uint>(props[QLatin1String("State")]);
90     parameters = qdbus_cast<QVariantMap>(props[QLatin1String("Parameters")]);
91 }
92 
93 /**
94  * \class TubeChannel
95  * \ingroup clientchannel
96  * \headerfile TelepathyQt/tube-channel.h <TelepathyQt/TubeChannel>
97  *
98  * \brief The TubeChannel class is a base class for all tube types.
99  *
100  * A tube is a mechanism for arbitrary data transfer between two or more IM users,
101  * used to allow applications on the users' systems to communicate without having
102  * to establish network connections themselves.
103  *
104  * Note that TubeChannel should never be instantiated directly, instead one of its
105  * subclasses (e.g. IncomingStreamTubeChannel or OutgoingStreamTubeChannel) should be used.
106  *
107  * See \ref async_model, \ref shared_ptr
108  */
109 
110 /**
111  * Feature representing the core that needs to become ready to make the
112  * TubeChannel object usable.
113  *
114  * Note that this feature must be enabled in order to use most
115  * TubeChannel methods.
116  * See specific methods documentation for more details.
117  */
118 const Feature TubeChannel::FeatureCore = Feature(QLatin1String(TubeChannel::staticMetaObject.className()), 0);
119 
120 /**
121  * Create a new TubeChannel channel.
122  *
123  * \param connection Connection owning this channel, and specifying the
124  *                   service.
125  * \param objectPath The channel object path.
126  * \param immutableProperties The channel immutable properties.
127  * \return A TubeChannelPtr object pointing to the newly created
128  *         TubeChannel object.
129  */
create(const ConnectionPtr & connection,const QString & objectPath,const QVariantMap & immutableProperties)130 TubeChannelPtr TubeChannel::create(const ConnectionPtr &connection,
131         const QString &objectPath, const QVariantMap &immutableProperties)
132 {
133     return TubeChannelPtr(new TubeChannel(connection, objectPath,
134             immutableProperties));
135 }
136 
137 /**
138  * Construct a new TubeChannel object.
139  *
140  * \param connection Connection owning this channel, and specifying the
141  *                   service.
142  * \param objectPath The channel object path.
143  * \param immutableProperties The channel immutable properties.
144  * \param coreFeature The core feature of the channel type, if any. The corresponding introspectable should
145  *                    depend on TubeChannel::FeatureCore.
146  */
TubeChannel(const ConnectionPtr & connection,const QString & objectPath,const QVariantMap & immutableProperties,const Feature & coreFeature)147 TubeChannel::TubeChannel(const ConnectionPtr &connection,
148         const QString &objectPath,
149         const QVariantMap &immutableProperties,
150         const Feature &coreFeature)
151     : Channel(connection, objectPath, immutableProperties, coreFeature),
152       mPriv(new Private(this))
153 {
154 }
155 
156 /**
157  * Class destructor.
158  */
~TubeChannel()159 TubeChannel::~TubeChannel()
160 {
161     delete mPriv;
162 }
163 
164 /**
165  * Return the parameters associated with this tube, if any.
166  *
167  * The parameters are populated when an outgoing tube is offered, but they are most useful in the
168  * receiving end, where the parameters passed to the offer can be extracted for the tube's entire
169  * lifetime to bootstrap legacy protocols. All parameters are passed unchanged.
170  *
171  * This method requires TubeChannel::FeatureCore to be ready.
172  *
173  * \return The parameters as QVariantMap.
174  */
parameters() const175 QVariantMap TubeChannel::parameters() const
176 {
177     if (!isReady(FeatureCore)) {
178         warning() << "TubeChannel::parameters() used with FeatureCore not ready";
179         return QVariantMap();
180     }
181 
182     return mPriv->parameters;
183 }
184 
185 /**
186  * Return the state of this tube.
187  *
188  * Change notification is via the stateChanged() signal.
189  *
190  * This method requires TubeChannel::FeatureCore to be ready.
191  *
192  * \return The state as #TubeChannelState.
193  * \sa stateChanged()
194  */
state() const195 TubeChannelState TubeChannel::state() const
196 {
197     if (!isReady(FeatureCore)) {
198         warning() << "TubeChannel::state() used with FeatureCore not ready";
199         return TubeChannelStateNotOffered;
200     }
201 
202     return mPriv->state;
203 }
204 
setParameters(const QVariantMap & parameters)205 void TubeChannel::setParameters(const QVariantMap &parameters)
206 {
207     mPriv->parameters = parameters;
208 }
209 
onTubeChannelStateChanged(uint newState)210 void TubeChannel::onTubeChannelStateChanged(uint newState)
211 {
212     if (newState == mPriv->state) {
213         return;
214     }
215 
216     uint oldState = mPriv->state;
217 
218     debug() << "Tube state changed to" << newState;
219     mPriv->state = (Tp::TubeChannelState) newState;
220 
221     /* only emit stateChanged if we already received the state from initial introspection */
222     if (oldState != (uint) -1) {
223         emit stateChanged((Tp::TubeChannelState) newState);
224     }
225 }
226 
gotTubeProperties(PendingOperation * op)227 void TubeChannel::gotTubeProperties(PendingOperation *op)
228 {
229     if (!op->isError()) {
230         PendingVariantMap *pvm = qobject_cast<PendingVariantMap *>(op);
231 
232         mPriv->extractTubeProperties(pvm->result());
233 
234         debug() << "Got reply to Properties::GetAll(TubeChannel)";
235         mPriv->readinessHelper->setIntrospectCompleted(TubeChannel::FeatureCore, true);
236     } else {
237         warning().nospace() << "Properties::GetAll(TubeChannel) failed "
238             "with " << op->errorName() << ": " << op->errorMessage();
239         mPriv->readinessHelper->setIntrospectCompleted(TubeChannel::FeatureCore, false,
240                 op->errorName(), op->errorMessage());
241     }
242 }
243 
244 /**
245  * \fn void TubeChannel::stateChanged(Tp::TubeChannelState state)
246  *
247  * Emitted when the value of state() changes.
248  *
249  * \sa state The new state of this tube.
250  */
251 
252 } // Tp
253