diff options
author | Andre Moreira Magalhaes (andrunko) <andre.magalhaes@collabora.co.uk> | 2009-08-25 11:16:31 -0300 |
---|---|---|
committer | Andre Moreira Magalhaes (andrunko) <andre.magalhaes@collabora.co.uk> | 2009-08-25 11:16:31 -0300 |
commit | 201f2dcc73ac36ea2dde6f482e012b707583f359 (patch) | |
tree | dee8839b1d726d37f0c1dc0f8c4613725a4d7b4e | |
parent | a2a946e96d5f1a0132c94434fea5ccdc22a06378 (diff) | |
parent | e2b1a47ad89eaff3b8e0f63f5b141b39bf432cdd (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.cpp | 56 | ||||
-rw-r--r-- | TelepathyQt4/streamed-media-channel.h | 3 | ||||
-rw-r--r-- | tests/dbus/streamed-media-chan.cpp | 145 | ||||
-rw-r--r-- | tests/lib/callable/media-channel.c | 99 |
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 +} |