summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndre Moreira Magalhaes (andrunko) <andre.magalhaes@collabora.co.uk>2009-08-25 11:16:31 -0300
committerAndre Moreira Magalhaes (andrunko) <andre.magalhaes@collabora.co.uk>2009-08-25 11:16:31 -0300
commit201f2dcc73ac36ea2dde6f482e012b707583f359 (patch)
treedee8839b1d726d37f0c1dc0f8c4613725a4d7b4e
parenta2a946e96d5f1a0132c94434fea5ccdc22a06378 (diff)
parente2b1a47ad89eaff3b8e0f63f5b141b39bf432cdd (diff)
Merge branch 'dtmf'
Conflicts: tests/dbus/streamed-media-chan.cpp tests/lib/callable/media-channel.c Reviewed-by: Simon McVittie (smcv) <simon.mcvittie@collabora.co.uk>
-rw-r--r--TelepathyQt4/streamed-media-channel.cpp56
-rw-r--r--TelepathyQt4/streamed-media-channel.h3
-rw-r--r--tests/dbus/streamed-media-chan.cpp145
-rw-r--r--tests/lib/callable/media-channel.c99
4 files changed, 303 insertions, 0 deletions
diff --git a/TelepathyQt4/streamed-media-channel.cpp b/TelepathyQt4/streamed-media-channel.cpp
index 73f3c078..cb03c46a 100644
--- a/TelepathyQt4/streamed-media-channel.cpp
+++ b/TelepathyQt4/streamed-media-channel.cpp
@@ -369,6 +369,62 @@ PendingOperation *MediaStream::requestDirection(
}
/**
+ * Start sending a DTMF tone on this stream. Where possible, the tone will
+ * continue until stopDTMFTone() is called. On certain protocols, it may only be
+ * possible to send events with a predetermined length. In this case, the
+ * implementation may emit a fixed-length tone, and the stopDTMFTone() method
+ * call should return %TELEPATHY_ERROR_NOT_AVAILABLE.
+ *
+ * If the channel() does not support the %TELEPATHY_INTERFACE_CHANNEL_INTERFACE_DTMF
+ * interface, the resulting PendingOperation will fail with error code
+ * %TELEPATHY_ERROR_NOT_IMPLEMENTED.
+
+ * \param event A numeric event code from the %DTMFEvent enum.
+ * \return A PendingOperation which will emit PendingOperation::finished
+ * when the request finishes.
+ * \sa stopDTMFTone()
+ */
+PendingOperation *MediaStream::startDTMFTone(DTMFEvent event)
+{
+ StreamedMediaChannelPtr chan(mPriv->channel);
+ if (!chan->interfaces().contains(TELEPATHY_INTERFACE_CHANNEL_INTERFACE_DTMF)) {
+ warning() << "MediaStream::startDTMFTone() used with no dtmf interface";
+ return new PendingFailure(this, TELEPATHY_ERROR_NOT_IMPLEMENTED,
+ "StreamedMediaChannel does not support dtmf interface");
+ }
+ return new PendingVoidMethodCall(this,
+ chan->DTMFInterface()->StartTone(mPriv->id, event));
+}
+
+/**
+ * Stop sending any DTMF tone which has been started using the startDTMFTone()
+ * method. If there is no current tone, the resulting PendingOperation will
+ * finish successfully.
+ *
+ * If continuous tones are not supported by this stream, the resulting
+ * PendingOperation will fail with error code %TELEPATHY_ERROR_NOT_AVAILABLE.
+ *
+ * If the channel() does not support the %TELEPATHY_INTERFACE_CHANNEL_INTERFACE_DTMF
+ * interface, the resulting PendingOperation will fail with error code
+ * %TELEPATHY_ERROR_NOT_IMPLEMENTED.
+ *
+ * \return A PendingOperation which will emit PendingOperation::finished
+ * when the request finishes.
+ * \sa startDTMFTone()
+ */
+PendingOperation *MediaStream::stopDTMFTone()
+{
+ StreamedMediaChannelPtr chan(mPriv->channel);
+ if (!chan->interfaces().contains(TELEPATHY_INTERFACE_CHANNEL_INTERFACE_DTMF)) {
+ warning() << "MediaStream::stopDTMFTone() used with no dtmf interface";
+ return new PendingFailure(this, TELEPATHY_ERROR_NOT_IMPLEMENTED,
+ "StreamedMediaChannel does not support dtmf interface");
+ }
+ return new PendingVoidMethodCall(this,
+ chan->DTMFInterface()->StopTone(mPriv->id));
+}
+
+/**
* Request a change in the direction of this stream. In particular, this
* might be useful to stop sending media of a particular type, or inform the
* peer that you are no longer using media that is being sent to you.
diff --git a/TelepathyQt4/streamed-media-channel.h b/TelepathyQt4/streamed-media-channel.h
index 580069f4..b4abc69f 100644
--- a/TelepathyQt4/streamed-media-channel.h
+++ b/TelepathyQt4/streamed-media-channel.h
@@ -94,6 +94,9 @@ public:
PendingOperation *requestDirection(
bool send, bool receive);
+ PendingOperation *startDTMFTone(DTMFEvent event);
+ PendingOperation *stopDTMFTone();
+
private Q_SLOTS:
void gotContact(Tp::PendingOperation *op);
diff --git a/tests/dbus/streamed-media-chan.cpp b/tests/dbus/streamed-media-chan.cpp
index 28725fc7..4a2e2efe 100644
--- a/tests/dbus/streamed-media-chan.cpp
+++ b/tests/dbus/streamed-media-chan.cpp
@@ -59,6 +59,8 @@ private Q_SLOTS:
void testHold();
void testHoldNoUnhold();
void testHoldInabilityUnhold();
+ void testDTMF();
+ void testDTMFNoContinuousTone();
void cleanup();
void cleanupTestCase();
@@ -1027,6 +1029,149 @@ void TestStreamedMediaChan::testHoldInabilityUnhold()
QCOMPARE(mChan->localHoldStateReason(), LocalHoldStateReasonRequested);
}
+void TestStreamedMediaChan::testDTMF()
+{
+ QVERIFY(connect(mConn->contactManager()->contactsForIdentifiers(QStringList() << "john"),
+ SIGNAL(finished(Tp::PendingOperation*)),
+ SLOT(expectRequestContactsFinished(Tp::PendingOperation*))));
+ QCOMPARE(mLoop->exec(), 0);
+ QVERIFY(mRequestContactsReturn.size() == 1);
+ ContactPtr otherContact = mRequestContactsReturn.first();
+ QVERIFY(otherContact);
+
+ QVariantMap request;
+ request.insert(QLatin1String(TELEPATHY_INTERFACE_CHANNEL ".ChannelType"),
+ TELEPATHY_INTERFACE_CHANNEL_TYPE_STREAMED_MEDIA);
+ request.insert(QLatin1String(TELEPATHY_INTERFACE_CHANNEL ".TargetHandleType"),
+ Tp::HandleTypeContact);
+ request.insert(QLatin1String(TELEPATHY_INTERFACE_CHANNEL ".TargetHandle"),
+ otherContact->handle()[0]);
+ QVERIFY(connect(mConn->createChannel(request),
+ SIGNAL(finished(Tp::PendingOperation*)),
+ SLOT(expectCreateChannelFinished(Tp::PendingOperation*))));
+ QCOMPARE(mLoop->exec(), 0);
+ QVERIFY(mChan);
+
+ QVERIFY(connect(mChan->becomeReady(StreamedMediaChannel::FeatureStreams),
+ SIGNAL(finished(Tp::PendingOperation*)),
+ SLOT(expectSuccessfulCall(Tp::PendingOperation*))));
+ QCOMPARE(mLoop->exec(), 0);
+ QVERIFY(mChan->isReady(StreamedMediaChannel::FeatureStreams));
+
+ // Request audio stream
+ QVERIFY(connect(mChan->requestStreams(otherContact,
+ QList<Tp::MediaStreamType>() << Tp::MediaStreamTypeAudio),
+ SIGNAL(finished(Tp::PendingOperation*)),
+ SLOT(expectRequestStreamsFinished(Tp::PendingOperation*))));
+ QCOMPARE(mLoop->exec(), 0);
+ QCOMPARE(mRequestStreamsReturn.size(), 1);
+ MediaStreamPtr stream = mRequestStreamsReturn.first();
+ QCOMPARE(stream->contact(), otherContact);
+ QCOMPARE(stream->type(), Tp::MediaStreamTypeAudio);
+
+ QCOMPARE(mChan->streams().size(), 1);
+ QVERIFY(mChan->streams().contains(stream));
+
+ // start dtmf
+ QVERIFY(connect(stream->startDTMFTone(DTMFEventDigit0),
+ SIGNAL(finished(Tp::PendingOperation*)),
+ SLOT(expectSuccessfulCall(Tp::PendingOperation*))));
+ QCOMPARE(mLoop->exec(), 0);
+
+ // stop dtmf
+ QVERIFY(connect(stream->stopDTMFTone(),
+ SIGNAL(finished(Tp::PendingOperation*)),
+ SLOT(expectSuccessfulCall(Tp::PendingOperation*))));
+ QCOMPARE(mLoop->exec(), 0);
+
+ // stop dtmf again (should succeed)
+ QVERIFY(connect(stream->stopDTMFTone(),
+ SIGNAL(finished(Tp::PendingOperation*)),
+ SLOT(expectSuccessfulCall(Tp::PendingOperation*))));
+ QCOMPARE(mLoop->exec(), 0);
+
+ // Request video stream
+ QVERIFY(connect(mChan->requestStream(otherContact, Tp::MediaStreamTypeVideo),
+ SIGNAL(finished(Tp::PendingOperation*)),
+ SLOT(expectRequestStreamsFinished(Tp::PendingOperation*))));
+ QCOMPARE(mLoop->exec(), 0);
+ QCOMPARE(mRequestStreamsReturn.size(), 1);
+ stream = mRequestStreamsReturn.first();
+ QCOMPARE(stream->contact(), otherContact);
+ QCOMPARE(stream->type(), Tp::MediaStreamTypeVideo);
+
+ QCOMPARE(mChan->streams().size(), 2);
+ QVERIFY(mChan->streams().contains(stream));
+
+ // start dtmf (must fail)
+ QVERIFY(connect(stream->startDTMFTone(DTMFEventDigit0),
+ SIGNAL(finished(Tp::PendingOperation*)),
+ SLOT(expectSuccessfulCall(Tp::PendingOperation*))));
+ QCOMPARE(mLoop->exec(), 1);
+
+ // stop dtmf (must fail)
+ QVERIFY(connect(stream->stopDTMFTone(),
+ SIGNAL(finished(Tp::PendingOperation*)),
+ SLOT(expectSuccessfulCall(Tp::PendingOperation*))));
+ QCOMPARE(mLoop->exec(), 1);
+}
+
+void TestStreamedMediaChan::testDTMFNoContinuousTone()
+{
+ QVERIFY(connect(mConn->contactManager()->contactsForIdentifiers(QStringList() << "john (no continuous tone)"),
+ SIGNAL(finished(Tp::PendingOperation*)),
+ SLOT(expectRequestContactsFinished(Tp::PendingOperation*))));
+ QCOMPARE(mLoop->exec(), 0);
+ QVERIFY(mRequestContactsReturn.size() == 1);
+ ContactPtr otherContact = mRequestContactsReturn.first();
+ QVERIFY(otherContact);
+
+ QVariantMap request;
+ request.insert(QLatin1String(TELEPATHY_INTERFACE_CHANNEL ".ChannelType"),
+ TELEPATHY_INTERFACE_CHANNEL_TYPE_STREAMED_MEDIA);
+ request.insert(QLatin1String(TELEPATHY_INTERFACE_CHANNEL ".TargetHandleType"),
+ Tp::HandleTypeContact);
+ request.insert(QLatin1String(TELEPATHY_INTERFACE_CHANNEL ".TargetHandle"),
+ otherContact->handle()[0]);
+ QVERIFY(connect(mConn->createChannel(request),
+ SIGNAL(finished(Tp::PendingOperation*)),
+ SLOT(expectCreateChannelFinished(Tp::PendingOperation*))));
+ QCOMPARE(mLoop->exec(), 0);
+ QVERIFY(mChan);
+
+ QVERIFY(connect(mChan->becomeReady(StreamedMediaChannel::FeatureStreams),
+ SIGNAL(finished(Tp::PendingOperation*)),
+ SLOT(expectSuccessfulCall(Tp::PendingOperation*))));
+ QCOMPARE(mLoop->exec(), 0);
+ QVERIFY(mChan->isReady(StreamedMediaChannel::FeatureStreams));
+
+ // Request audio stream
+ QVERIFY(connect(mChan->requestStreams(otherContact,
+ QList<Tp::MediaStreamType>() << Tp::MediaStreamTypeAudio),
+ SIGNAL(finished(Tp::PendingOperation*)),
+ SLOT(expectRequestStreamsFinished(Tp::PendingOperation*))));
+ QCOMPARE(mLoop->exec(), 0);
+ QCOMPARE(mRequestStreamsReturn.size(), 1);
+ MediaStreamPtr stream = mRequestStreamsReturn.first();
+ QCOMPARE(stream->contact(), otherContact);
+ QCOMPARE(stream->type(), Tp::MediaStreamTypeAudio);
+
+ QCOMPARE(mChan->streams().size(), 1);
+ QVERIFY(mChan->streams().contains(stream));
+
+ // start dtmf
+ QVERIFY(connect(stream->startDTMFTone(DTMFEventDigit0),
+ SIGNAL(finished(Tp::PendingOperation*)),
+ SLOT(expectSuccessfulCall(Tp::PendingOperation*))));
+ QCOMPARE(mLoop->exec(), 0);
+
+ // stop dtmf (must fail)
+ QVERIFY(connect(stream->stopDTMFTone(),
+ SIGNAL(finished(Tp::PendingOperation*)),
+ SLOT(expectSuccessfulCall(Tp::PendingOperation*))));
+ QCOMPARE(mLoop->exec(), 1);
+}
+
void TestStreamedMediaChan::cleanup()
{
mChan.reset();
diff --git a/tests/lib/callable/media-channel.c b/tests/lib/callable/media-channel.c
index 77356e06..c3707caf 100644
--- a/tests/lib/callable/media-channel.c
+++ b/tests/lib/callable/media-channel.c
@@ -49,6 +49,7 @@
static void media_iface_init (gpointer iface, gpointer data);
static void channel_iface_init (gpointer iface, gpointer data);
static void hold_iface_init (gpointer iface, gpointer data);
+static void dtmf_iface_init (gpointer iface, gpointer data);
G_DEFINE_TYPE_WITH_CODE (ExampleCallableMediaChannel,
example_callable_media_channel,
@@ -62,6 +63,8 @@ G_DEFINE_TYPE_WITH_CODE (ExampleCallableMediaChannel,
tp_group_mixin_iface_init);
G_IMPLEMENT_INTERFACE (TP_TYPE_SVC_CHANNEL_INTERFACE_HOLD,
hold_iface_init);
+ G_IMPLEMENT_INTERFACE (TP_TYPE_SVC_CHANNEL_INTERFACE_DTMF,
+ dtmf_iface_init);
G_IMPLEMENT_INTERFACE (TP_TYPE_CHANNEL_IFACE, NULL);
G_IMPLEMENT_INTERFACE (TP_TYPE_EXPORTABLE_CHANNEL, NULL))
@@ -126,6 +129,7 @@ struct _ExampleCallableMediaChannelPrivate
static const char * example_callable_media_channel_interfaces[] = {
TP_IFACE_CHANNEL_INTERFACE_GROUP,
TP_IFACE_CHANNEL_INTERFACE_HOLD,
+ TP_IFACE_CHANNEL_INTERFACE_DTMF,
NULL
};
@@ -1351,3 +1355,98 @@ hold_iface_init (gpointer iface,
IMPLEMENT (request_hold);
#undef IMPLEMENT
}
+
+static void
+dtmf_start_tone (TpSvcChannelInterfaceDTMF *iface,
+ guint stream_id,
+ guchar event,
+ DBusGMethodInvocation *context)
+{
+ ExampleCallableMediaChannel *self = EXAMPLE_CALLABLE_MEDIA_CHANNEL (iface);
+ ExampleCallableMediaStream *stream = g_hash_table_lookup (self->priv->streams,
+ GUINT_TO_POINTER (stream_id));
+ GError *error = NULL;
+ guint media_type;
+
+ if (stream == NULL)
+ {
+ g_set_error (&error, TP_ERRORS, TP_ERROR_INVALID_ARGUMENT,
+ "No stream with ID %u in this channel", stream_id);
+ goto error;
+ }
+
+ g_object_get (G_OBJECT (stream), "type", &media_type, NULL);
+ if (media_type != TP_MEDIA_STREAM_TYPE_AUDIO)
+ {
+ g_set_error (&error, TP_ERRORS, TP_ERROR_INVALID_ARGUMENT,
+ "DTMF is only supported by audio streams");
+ goto error;
+ }
+
+ tp_svc_channel_interface_dtmf_return_from_start_tone (context);
+
+ return;
+
+error:
+ dbus_g_method_return_error (context, error);
+ g_error_free (error);
+}
+
+static void
+dtmf_stop_tone (TpSvcChannelInterfaceDTMF *iface,
+ guint stream_id,
+ DBusGMethodInvocation *context)
+{
+ ExampleCallableMediaChannel *self = EXAMPLE_CALLABLE_MEDIA_CHANNEL (iface);
+ ExampleCallableMediaStream *stream = g_hash_table_lookup (self->priv->streams,
+ GUINT_TO_POINTER (stream_id));
+ TpHandleRepoIface *contact_repo = tp_base_connection_get_handles
+ (self->priv->conn, TP_HANDLE_TYPE_CONTACT);
+ GError *error = NULL;
+ const gchar *peer;
+ guint media_type;
+
+ if (stream == NULL)
+ {
+ g_set_error (&error, TP_ERRORS, TP_ERROR_INVALID_ARGUMENT,
+ "No stream with ID %u in this channel", stream_id);
+ goto error;
+ }
+
+ g_object_get (G_OBJECT (stream), "type", &media_type, NULL);
+ if (media_type != TP_MEDIA_STREAM_TYPE_AUDIO)
+ {
+ g_set_error (&error, TP_ERRORS, TP_ERROR_INVALID_ARGUMENT,
+ "DTMF is only supported by audio streams");
+ goto error;
+ }
+
+ peer = tp_handle_inspect (contact_repo, self->priv->handle);
+ if (strstr (peer, "(no continuous tone)") != NULL)
+ {
+ g_set_error (&error, TP_ERRORS, TP_ERROR_NOT_AVAILABLE,
+ "Continuous tones are not supported by this stream");
+ goto error;
+ }
+
+ tp_svc_channel_interface_dtmf_return_from_stop_tone (context);
+
+ return;
+
+error:
+ dbus_g_method_return_error (context, error);
+ g_error_free (error);
+}
+
+static void
+dtmf_iface_init (gpointer iface,
+ gpointer data)
+{
+ TpSvcChannelInterfaceDTMFClass *klass = iface;
+
+#define IMPLEMENT(x) \
+ tp_svc_channel_interface_dtmf_implement_##x (klass, dtmf_##x)
+ IMPLEMENT (start_tone);
+ IMPLEMENT (stop_tone);
+#undef IMPLEMENT
+}