summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorOlivier Crête <olivier.crete@collabora.com>2012-02-20 17:31:41 -0500
committerOlivier Crête <olivier.crete@collabora.com>2012-02-20 17:31:41 -0500
commit7d56e7b4b3c801a5ef5e9f88fc34c84656e0aa0d (patch)
treefa2d5d617855b7a849c65197e474bbfe823f601b
parentac8cae2410b5ba8c59249d51ba0b53b79754ea9c (diff)
parentbf1bb9987d0f9ad5bdccc42d67fb0a8e78feaf0a (diff)
downloadtelepathy-farstream-7d56e7b4b3c801a5ef5e9f88fc34c84656e0aa0d.tar.gz
Merge branch 'call1'
Conflicts: configure.ac examples/call-handler.c extensions/Makefile.am extensions/call-content.xml telepathy-farstream/call-content.c telepathy-farstream/call-stream.c telepathy-farstream/stream.c telepathy-farstream/telepathy-farstream.c
-rw-r--r--Makefile.am1
-rw-r--r--configure.ac7
-rw-r--r--doc/lib/Makefile.am2
-rw-r--r--doc/lib/telepathy-farstream-sections.txt7
-rw-r--r--examples/Makefile.am1
-rw-r--r--examples/call-handler.c28
-rw-r--r--extensions/Call_Content.xml255
-rw-r--r--extensions/Call_Content_Codec_Offer.xml87
-rw-r--r--extensions/Call_Content_Interface_Audio_Control.xml111
-rw-r--r--extensions/Call_Content_Interface_Media.xml367
-rw-r--r--extensions/Call_Content_Interface_Mute.xml85
-rw-r--r--extensions/Call_Content_Interface_Video_Control.xml137
-rw-r--r--extensions/Call_Stream.xml261
-rw-r--r--extensions/Call_Stream_Endpoint.xml182
-rw-r--r--extensions/Call_Stream_Interface_Media.xml447
-rw-r--r--extensions/Channel_Type_Call.xml1429
-rw-r--r--extensions/Makefile.am167
-rw-r--r--extensions/all.xml12
-rw-r--r--extensions/call-content.c161
-rw-r--r--extensions/call-content.h62
-rw-r--r--extensions/call-content.xml12
-rw-r--r--extensions/call-stream.c161
-rw-r--r--extensions/call-stream.h62
-rw-r--r--extensions/call-stream.xml10
-rw-r--r--extensions/channel.xml9
-rw-r--r--extensions/extensions-cli.c35
-rw-r--r--extensions/extensions.c6
-rw-r--r--extensions/extensions.h23
-rw-r--r--extensions/misc.xml10
-rw-r--r--python/examples/constants.py14
-rw-r--r--python/pytpfarstream.defs51
-rw-r--r--python/pytpfarstreammodule.c1
-rw-r--r--telepathy-farstream/Makefile.am5
-rw-r--r--telepathy-farstream/call-channel.c215
-rw-r--r--telepathy-farstream/call-channel.h2
-rw-r--r--telepathy-farstream/call-content.c1432
-rw-r--r--telepathy-farstream/call-content.h9
-rw-r--r--telepathy-farstream/call-stream.c1065
-rw-r--r--telepathy-farstream/call-stream.h44
-rw-r--r--telepathy-farstream/channel.c57
-rw-r--r--telepathy-farstream/content-priv.h13
-rw-r--r--telepathy-farstream/content.c171
-rw-r--r--telepathy-farstream/content.h18
-rw-r--r--telepathy-farstream/media-signalling-channel.c22
-rw-r--r--telepathy-farstream/media-signalling-channel.h24
-rw-r--r--telepathy-farstream/media-signalling-content.c38
-rw-r--r--telepathy-farstream/media-signalling-content.h1
-rw-r--r--telepathy-farstream/stream-priv.h75
-rw-r--r--telepathy-farstream/stream.c113
-rw-r--r--telepathy-farstream/stream.h67
-rw-r--r--telepathy-farstream/telepathy-farstream.c34
-rw-r--r--telepathy-farstream/telepathy-farstream.h6
-rw-r--r--telepathy-farstream/utils.h34
53 files changed, 2309 insertions, 5339 deletions
diff --git a/Makefile.am b/Makefile.am
index 5ee77f3..34daccf 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -7,7 +7,6 @@ endif
SUBDIRS = m4 \
tools \
- extensions \
telepathy-farstream \
doc \
$(PYTHON_SUBDIR) \
diff --git a/configure.ac b/configure.ac
index 62eeb99..7dae38c 100644
--- a/configure.ac
+++ b/configure.ac
@@ -9,7 +9,7 @@ AC_PREREQ([2.59])
m4_define([tp_farstream_major_version], [0])
m4_define([tp_farstream_minor_version], [2])
-m4_define([tp_farstream_micro_version], [99])
+m4_define([tp_farstream_micro_version], [0])
m4_define([tp_farstream_nano_version], [1])
dnl CURRENT, REVISION, AGE
@@ -17,8 +17,8 @@ dnl - library source changed -> increment REVISION
dnl - interfaces added/removed/changed -> increment CURRENT, REVISION = 0
dnl - interfaces added -> increment AGE
dnl - interfaces removed -> AGE = 0
-m4_define([tp_farstream_lt_current], [0])
-m4_define([tp_farstream_lt_revision], [2])
+m4_define([tp_farstream_lt_current], [1])
+m4_define([tp_farstream_lt_revision], [0])
m4_define([tp_farstream_lt_age], [0])
@@ -142,7 +142,6 @@ AC_OUTPUT( Makefile \
doc/Makefile \
doc/lib/Makefile \
m4/Makefile \
- extensions/Makefile \
examples/Makefile \
telepathy-farstream/Makefile \
telepathy-farstream/telepathy-farstream.pc \
diff --git a/doc/lib/Makefile.am b/doc/lib/Makefile.am
index 674c326..47587f8 100644
--- a/doc/lib/Makefile.am
+++ b/doc/lib/Makefile.am
@@ -46,7 +46,7 @@ CFILE_GLOB=$(top_srcdir)/telepathy-farstream/channel.c $(top_srcdir)/telepathy-f
# e.g. IGNORE_HFILES=gtkdebug.h gtkintl.h
IGNORE_HFILES=channel-priv.h content-priv.h session-priv.h stream-priv.h \
stream.h call-channel.h call-content.h call-stream.h tf-signals-marshal.h \
- media-signalling-channel.h media-signalling-content.h
+ media-signalling-channel.h media-signalling-content.h utils.h
# Images to copy into HTML directory.
# e.g. HTML_IMAGES=$(top_srcdir)/gtk/stock-icons/stock_about_24.png
diff --git a/doc/lib/telepathy-farstream-sections.txt b/doc/lib/telepathy-farstream-sections.txt
index 4a1382d..41903c4 100644
--- a/doc/lib/telepathy-farstream-sections.txt
+++ b/doc/lib/telepathy-farstream-sections.txt
@@ -1,6 +1,5 @@
<SECTION>
-<TITLE>Core</TITLE>
-tf_init
+<TITLE>Utilities</TITLE>
tp_media_type_to_fs
</SECTION>
@@ -12,6 +11,10 @@ TfContentClass
tf_content_iterate_src_pads
tf_content_error
tf_content_error_literal
+tf_content_receiving_failed
+tf_content_receiving_failed_literal
+tf_content_sending_failed
+tf_content_sending_failed_literal
<SUBSECTION Private>
TfContentPrivate
<SUBSECTION Standard>
diff --git a/examples/Makefile.am b/examples/Makefile.am
index b7e60a7..ca22edf 100644
--- a/examples/Makefile.am
+++ b/examples/Makefile.am
@@ -2,7 +2,6 @@ noinst_PROGRAMS = call-handler
LDADD = \
../telepathy-farstream/libtelepathy-farstream.la \
- ../extensions/libfuture-extensions.la \
$(GLIB_LIBS) \
$(DBUS_LIBS) \
$(GST_LIBS) \
diff --git a/examples/call-handler.c b/examples/call-handler.c
index f56763e..58f2d6c 100644
--- a/examples/call-handler.c
+++ b/examples/call-handler.c
@@ -19,7 +19,6 @@
#include <gst/gst.h>
#include <telepathy-glib/telepathy-glib.h>
-#include <extensions/extensions.h>
#include <farstream/fs-element-added-notifier.h>
#include <farstream/fs-utils.h>
#include <telepathy-farstream/telepathy-farstream.h>
@@ -546,7 +545,7 @@ new_call_channel_cb (TpSimpleHandler *handler,
tp_handle_channels_context_accept (handler_context);
- tf_future_cli_channel_type_call_call_accept (proxy, -1,
+ tp_cli_channel_type_call_call_accept (proxy, -1,
NULL, NULL, NULL, NULL);
context->proxy = g_object_ref (proxy);
@@ -559,17 +558,16 @@ int
main (int argc, char **argv)
{
TpBaseClient *client;
- TpAccountManager *account_manager;
+ TpAccountManager *am;
g_type_init ();
- tf_init ();
gst_init (&argc, &argv);
loop = g_main_loop_new (NULL, FALSE);
- account_manager = tp_account_manager_dup ();
+ am = tp_account_manager_dup ();
- client = tp_simple_handler_new_with_am (account_manager,
+ client = tp_simple_handler_new_with_am (am,
FALSE,
FALSE,
"TpFsCallHandlerDemo",
@@ -581,35 +579,35 @@ main (int argc, char **argv)
tp_base_client_take_handler_filter (client,
tp_asv_new (
TP_PROP_CHANNEL_CHANNEL_TYPE, G_TYPE_STRING,
- TF_FUTURE_IFACE_CHANNEL_TYPE_CALL,
+ TP_IFACE_CHANNEL_TYPE_CALL,
TP_PROP_CHANNEL_TARGET_HANDLE_TYPE, G_TYPE_UINT,
TP_HANDLE_TYPE_CONTACT,
- TF_FUTURE_PROP_CHANNEL_TYPE_CALL_INITIAL_AUDIO, G_TYPE_BOOLEAN,
+ TP_PROP_CHANNEL_TYPE_CALL_INITIAL_AUDIO, G_TYPE_BOOLEAN,
TRUE,
NULL));
tp_base_client_take_handler_filter (client,
tp_asv_new (
TP_PROP_CHANNEL_CHANNEL_TYPE, G_TYPE_STRING,
- TF_FUTURE_IFACE_CHANNEL_TYPE_CALL,
+ TP_IFACE_CHANNEL_TYPE_CALL,
TP_PROP_CHANNEL_TARGET_HANDLE_TYPE, G_TYPE_UINT,
TP_HANDLE_TYPE_CONTACT,
- TF_FUTURE_PROP_CHANNEL_TYPE_CALL_INITIAL_VIDEO, G_TYPE_BOOLEAN,
+ TP_PROP_CHANNEL_TYPE_CALL_INITIAL_VIDEO, G_TYPE_BOOLEAN,
TRUE,
NULL));
tp_base_client_add_handler_capabilities_varargs (client,
- TF_FUTURE_IFACE_CHANNEL_TYPE_CALL "/video/h264",
- TF_FUTURE_IFACE_CHANNEL_TYPE_CALL "/shm",
- TF_FUTURE_IFACE_CHANNEL_TYPE_CALL "/ice",
- TF_FUTURE_IFACE_CHANNEL_TYPE_CALL "/gtalk-p2p",
+ TP_IFACE_CHANNEL_TYPE_CALL "/video/h264",
+ TP_IFACE_CHANNEL_TYPE_CALL "/shm",
+ TP_IFACE_CHANNEL_TYPE_CALL "/ice",
+ TP_IFACE_CHANNEL_TYPE_CALL "/gtalk-p2p",
NULL);
tp_base_client_register (client, NULL);
g_main_loop_run (loop);
- g_object_unref (account_manager);
+ g_object_unref (am);
g_object_unref (client);
g_main_loop_unref (loop);
diff --git a/extensions/Call_Content.xml b/extensions/Call_Content.xml
deleted file mode 100644
index 270d99b..0000000
--- a/extensions/Call_Content.xml
+++ /dev/null
@@ -1,255 +0,0 @@
-<?xml version="1.0" ?>
-<node name="/Call_Content"
- xmlns:tp="http://telepathy.freedesktop.org/wiki/DbusSpec#extensions-v0">
- <tp:copyright>Copyright © 2009-2010 Collabora Ltd.</tp:copyright>
- <tp:copyright>Copyright © 2009-2010 Nokia Corporation</tp:copyright>
- <tp:license xmlns="http://www.w3.org/1999/xhtml">
- <p>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.</p>
-
- <p>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.</p>
-
- <p>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 Street, Fifth Floor, Boston, MA
- 02110-1301, USA.</p>
- </tp:license>
-
- <interface name="org.freedesktop.Telepathy.Call.Content.DRAFT"
- tp:causes-havoc="experimental">
- <tp:added version="0.19.0">(draft 1)</tp:added>
-
- <tp:docstring xmlns="http://www.w3.org/1999/xhtml">
- This object represents one Content inside a <tp:dbus-ref
- namespace="ofdT.Channel.Type">Call.DRAFT</tp:dbus-ref>. For
- example, in an audio/video call there would be one audio content
- and one video content. Each content has one or more <tp:dbus-ref
- namespace="ofdT.Call">Stream.DRAFT</tp:dbus-ref> objects which
- represent the actual transport to one or more remote contacts.
- </tp:docstring>
-
- <tp:enum name="Content_Removal_Reason" type="u">
- <tp:added version="0.21.2"/>
- <tp:docstring>
- A representation of the reason for a content to be removed,
- which may be used by simple clients, or used as a fallback
- when the DBus_Reason is not understood. This enum will be
- extended with future reasons as and when appropriate, so
- clients SHOULD keep up to date with its values, but also be
- happy to fallback to the Unknown value when an unknown value
- is encountered.
- </tp:docstring>
-
- <tp:enumvalue suffix="Unknown" value="0">
- <tp:docstring xmlns="http://www.w3.org/1999/xhtml">
- We just don't know. Unknown values of this enum SHOULD also be
- treated like this.
- </tp:docstring>
- </tp:enumvalue>
-
- <tp:enumvalue suffix="User_Requested" value="1">
- <tp:docstring xmlns="http://www.w3.org/1999/xhtml">
- <p>The local user requests that this content is removed
- from the call.</p>
- </tp:docstring>
- </tp:enumvalue>
-
- <tp:enumvalue suffix="Error" value="2">
- <tp:docstring xmlns="http://www.w3.org/1999/xhtml">
- <p>There is an error with the content which means that it
- has to be removed from the call.</p>
- </tp:docstring>
- </tp:enumvalue>
-
- <tp:enumvalue suffix="Unsupported" value="3">
- <tp:docstring xmlns="http://www.w3.org/1999/xhtml">
- <p>Some aspect of the content is unsupported so has to be
- removed from the call.</p>
- </tp:docstring>
- </tp:enumvalue>
- </tp:enum>
-
- <method name="Remove" tp:name-for-bindings="Remove">
- <tp:changed version="0.21.2">previously there were no
- arguments</tp:changed>
- <tp:docstring>
- Remove the content from the call.
- </tp:docstring>
-
- <arg direction="in" name="Reason" type="u"
- tp:type="Content_Removal_Reason">
- <tp:docstring>
- A generic hangup reason.
- </tp:docstring>
- </arg>
-
- <arg direction="in" name="Detailed_Removal_Reason" type="s"
- tp:type="DBus_Error_Name">
- <tp:docstring>
- A more specific reason for the content removal, if one is
- available, or an empty string.
- </tp:docstring>
- </arg>
-
- <arg direction="in" name="Message" type="s">
- <tp:docstring>
- A human-readable message for the reason of removing the
- content, such as "Fatal streaming failure" or "no codec
- intersection". This property can be left empty if no reason
- is to be given.
- </tp:docstring>
- </arg>
-
- <tp:possible-errors>
- <tp:error name="org.freedesktop.Telepathy.Error.NetworkError" />
- <tp:error name="org.freedesktop.Telepathy.Error.NotImplemented">
- <tp:docstring>
- Raised when a Call doesn't support removing contents
- (e.g. a Google Talk video call).
- </tp:docstring>
- </tp:error>
- </tp:possible-errors>
- </method>
-
- <signal name="Removed" tp:name-for-bindings="Removed">
- <tp:docstring xmlns="http://www.w3.org/1999/xhtml">
- <p>Emitted when the content is removed from the call. This
- is the same as the <tp:dbus-ref
- namespace="ofdT.Channel.Type">Call.DRAFT.ContentRemoved</tp:dbus-ref>
- signal.</p>
- </tp:docstring>
- </signal>
-
- <property name="Interfaces" tp:name-for-bindings="Interfaces"
- type="as" tp:type="DBus_Interface[]" access="read" tp:immutable="yes">
- <tp:added version="0.19.11"/>
- <tp:docstring xmlns="http://www.w3.org/1999/xhtml">
- <p>Extra interfaces provided by this content, such as <tp:dbus-ref
- namespace="ofdT.Call">Content.Interface.Media.DRAFT</tp:dbus-ref> or
- <tp:dbus-ref namespace="ofdT.Call">Content.Interface.Mute.DRAFT</tp:dbus-ref>.
- This SHOULD NOT include the Content interface itself, and cannot
- change once the content has been created.</p>
- </tp:docstring>
- </property>
-
- <property name="Name" tp:name-for-bindings="Name" type="s" access="read"
- tp:immutable="yes">
- <tp:docstring xmlns="http://www.w3.org/1999/xhtml">
- <p>The name of the content.</p>
-
- <tp:rationale>
- The content name property should be meaningful, so should be
- given a name which is significant to the user. The name
- could be the "audio" or "video" string localized, or perhaps
- include some string identifying the source, such as a webcam
- identifier.
- </tp:rationale>
- </tp:docstring>
- </property>
-
- <property name="Type" tp:name-for-bindings="Type"
- type="u" tp:type="Media_Stream_Type" access="read" tp:immutable="yes">
- <tp:docstring xmlns="http://www.w3.org/1999/xhtml">
- <p>The media type of this content.</p>
- </tp:docstring>
- </property>
-
- <tp:enum name="Call_Content_Disposition" type="u">
- <tp:docstring>
- The disposition of this content, which defines whether to
- automatically start sending data on the streams when
- <tp:dbus-ref
- namespace="ofdT.Channel.Type">Call.DRAFT</tp:dbus-ref> is
- called on the channel.
- </tp:docstring>
-
- <tp:enumvalue suffix="None" value="0">
- <tp:docstring xmlns="http://www.w3.org/1999/xhtml">
- The content has no specific disposition
- </tp:docstring>
- </tp:enumvalue>
-
- <tp:enumvalue suffix="Initial" value="1">
- <tp:docstring xmlns="http://www.w3.org/1999/xhtml">
- <p>The content was initially part of the call. When
- <tp:dbus-ref
- namespace="ofdT.Channel.Type.Call.DRAFT">Accept</tp:dbus-ref>
- is called on the channel, all streams of this content with
- <tp:dbus-ref
- namespace="ofdT.Call.Stream.DRAFT">LocalSendingState</tp:dbus-ref>
- set to <tp:type>Sending_State</tp:type>_Pending_Send will be
- moved to <tp:type>Sending_State</tp:type>_Sending as if
- <tp:dbus-ref
- namespace="ofdT.Call.Stream.DRAFT">SetSending</tp:dbus-ref>
- (True) had been called.</p>
- </tp:docstring>
- </tp:enumvalue>
- </tp:enum>
-
- <property name="Disposition" tp:name-for-bindings="Disposition"
- type="u" tp:type="Call_Content_Disposition" access="read"
- tp:immutable="yes">
- <tp:docstring>
- The disposition of this content.
- </tp:docstring>
- </property>
-
- <signal name="StreamsAdded" tp:name-for-bindings="Streams_Added">
- <tp:changed version="0.21.2">plural version, renamed from
- StreamAdded</tp:changed>
- <tp:docstring xmlns="http://www.w3.org/1999/xhtml">
- <p>Emitted when streams are added to a call.</p>
- </tp:docstring>
- <arg name="Streams" type="ao">
- <tp:docstring>
- The <tp:dbus-ref
- namespace="ofdT.Call">Stream.DRAFT</tp:dbus-ref>s which were
- added.
- </tp:docstring>
- </arg>
- </signal>
-
- <signal name="StreamsRemoved" tp:name-for-bindings="Streams_Removed">
- <tp:changed version="0.21.2">plural version, renamed from
- StreamRemoved</tp:changed>
- <tp:docstring xmlns="http://www.w3.org/1999/xhtml">
- <p>Emitted when streams are removed from a call</p>
- </tp:docstring>
- <arg name="Streams" type="ao">
- <tp:docstring>
- The <tp:dbus-ref
- namespace="ofdT.Call">Stream.DRAFT</tp:dbus-ref>s which were
- removed.
- </tp:docstring>
- </arg>
- </signal>
-
- <property name="Streams" tp:name-for-bindings="Streams"
- type="ao" access="read">
- <tp:docstring xmlns="http://www.w3.org/1999/xhtml">
- <p>The list of <tp:dbus-ref namespace="ofdT.Call"
- >Stream.DRAFT</tp:dbus-ref> objects that exist in this
- content.</p>
-
- <tp:rationale>
- In a conference call multiple parties can share one media
- content (say, audio), but the streaming of that media can
- either be shared or separate. For example, in a multicast
- conference all contacts would share one stream, while in a
- Muji conference there would be a stream for each
- participant.
- </tp:rationale>
-
- <p>Change notification is through the
- <tp:member-ref>StreamsAdded</tp:member-ref> and
- <tp:member-ref>StreamsRemoved</tp:member-ref> signals.</p>
- </tp:docstring>
- </property>
- </interface>
-</node>
-<!-- vim:set sw=2 sts=2 et ft=xml: -->
diff --git a/extensions/Call_Content_Codec_Offer.xml b/extensions/Call_Content_Codec_Offer.xml
deleted file mode 100644
index f88143f..0000000
--- a/extensions/Call_Content_Codec_Offer.xml
+++ /dev/null
@@ -1,87 +0,0 @@
-<?xml version="1.0" ?>
-<node name="/Call_Content_Codec_Offer"
- xmlns:tp="http://telepathy.freedesktop.org/wiki/DbusSpec#extensions-v0">
- <tp:copyright>Copyright © 2009-2010 Collabora Ltd.</tp:copyright>
- <tp:copyright>Copyright © 2009-2010 Nokia Corporation</tp:copyright>
- <tp:license xmlns="http://www.w3.org/1999/xhtml">
- <p>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.</p>
-
- <p>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.</p>
-
- <p>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 Street, Fifth Floor, Boston, MA
- 02110-1301, USA.</p>
- </tp:license>
-
- <interface name="org.freedesktop.Telepathy.Call.Content.CodecOffer.DRAFT"
- tp:causes-havoc="experimental">
- <tp:added version="0.19.0">(draft 1)</tp:added>
-
- <tp:docstring xmlns="http://www.w3.org/1999/xhtml">
- This object represents an offer of a Codec payload mapping.
- </tp:docstring>
-
- <method name="Accept" tp:name-for-bindings="Accept">
- <arg name="Codecs" direction="in"
- type="a(usuua{ss})" tp:type="Codec[]">
- <tp:docstring>
- The local codec mapping to send to the remote contacts and
- to use in the <tp:dbus-ref
- namespace="ofdT.Call">Content.DRAFT</tp:dbus-ref>.
- </tp:docstring>
- </arg>
- <tp:docstring>
- Accept the updated Codec mapping and update the local mapping.
- </tp:docstring>
- <tp:possible-errors>
- <tp:error name="org.freedesktop.Telepathy.Error.InvalidArgument">
- <tp:docstring>
- The codecs given as the argument are invalid in some way.
- </tp:docstring>
- </tp:error>
- </tp:possible-errors>
- </method>
-
- <method name="Reject" tp:name-for-bindings="Reject">
- <tp:docstring>
- Reject the proposed update to the codecs
- FIXME add error codes and strings here
- </tp:docstring>
- </method>
-
- <property name="Interfaces" tp:name-for-bindings="Interfaces"
- type="as" tp:type="DBus_Interface[]" access="read" tp:immutable="yes">
- <tp:docstring xmlns="http://www.w3.org/1999/xhtml">
- <p>Extra interfaces provided by this codec offer. This SHOULD
- NOT include the CodecOffer interface itself, and cannot change
- once the content has been created.</p>
- </tp:docstring>
- </property>
-
- <property name="RemoteContactCodecs"
- tp:name-for-bindings="Remote_Contact_Codecs"
- type="a(usuua{ss})" tp:type="Codec[]" access="read"
- tp:immutable="yes">
- <tp:docstring>
- A list of codecs the remote contact supports.
- </tp:docstring>
- </property>
-
- <property name="RemoteContact" tp:name-for-bindings="Remote_Contact"
- type="u" tp:type="Contact_Handle" access="read" tp:immutable="yes">
- <tp:docstring>
- The contact handle that this codec offer applies to.
- </tp:docstring>
- </property>
-
-
- </interface>
-</node>
-<!-- vim:set sw=2 sts=2 et ft=xml: -->
diff --git a/extensions/Call_Content_Interface_Audio_Control.xml b/extensions/Call_Content_Interface_Audio_Control.xml
deleted file mode 100644
index 1229fb5..0000000
--- a/extensions/Call_Content_Interface_Audio_Control.xml
+++ /dev/null
@@ -1,111 +0,0 @@
-<!DOCTYPE node PUBLIC "-//freedesktop//DTD D-BUS Object Introspection 1.0//EN" "http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd">
-<node name="/Call_Content_Interface_Audio_Control"
- xmlns:tp="http://telepathy.freedesktop.org/wiki/DbusSpec#extensions-v0">
- <tp:copyright>Copyright © 2009-2011 Collabora Ltd.</tp:copyright>
- <tp:license xmlns="http://www.w3.org/1999/xhtml">
- <p>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.</p>
-
- <p>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.</p>
-
- <p>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 Street, Fifth Floor, Boston, MA
- 02110-1301, USA.</p>
- </tp:license>
-
- <interface name="org.freedesktop.Telepathy.Call1.Content.Interface.AudioControl"
- tp:causes-havoc="experimental">
- <tp:added version="0.25.UNRELEASED">(draft 1)</tp:added>
- <tp:requires interface="org.freedesktop.Telepathy.Call1.Content.Interface.Media"/>
- <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="true"/>
-
- <tp:docstring xmlns="http://www.w3.org/1999/xhtml">
- <p>This interface allows the connection manager to be kept informed of,
- and control, the input and output volumes of an audio stream.
- While generally not needed, if the connection manager needs to
- handle stream volumes directly (typically when using
- <tp:value-ref>Call_Content_Packetization_Type_Raw</tp:value-ref>),
- this interface may be necessary.</p>
-
- <p>If this interface is present, the handler should call
- <tp:member-ref>ReportInputVolume</tp:member-ref>
- and <tp:member-ref>ReportOutputVolume</tp:member-ref> whenever the
- input and output volume change, both when the user manually modifies
- the volume and when the volumes are adjusted in response to
- <tp:member-ref>RequestedInputVolume</tp:member-ref> and
- <tp:member-ref>RequestedOutputVolume</tp:member-ref> changing.</p>
-
- <p>The maximum volume as used in this interface represent the unamplified
- hardware volume (0 dB). No software amplification should be used to
- boost the signal to a higher level when this Interface is in use</p>
- </tp:docstring>
-
- <property name="RequestedInputVolume" tp:type="Audio_Control_Volume"
- type="i" access="read" tp:name-for-bindings="Requested_Input_Volume">
- <tp:docstring>
- The input volume as requested by the Connection Manager.
- Initially and on any changes the client should change its input volume
- to match the requested volume.
- </tp:docstring>
- </property>
-
- <method name="ReportInputVolume" tp:name-for-bindings="Report_Input_Volume">
- <arg direction="in" name="Volume" tp:type="Audio_Control_Volume" type="i">
- <tp:docstring>
- Report the input volume level as set by the client.
- </tp:docstring>
- </arg>
- <tp:docstring>
- <p>Report to the CM that the Content input volume has been
- changed by the client.</p>
-
- <p>It is the client's responsibility to change the input volume used for
- the content. However, the client MUST call this whenever it changes
- input volume for the content.</p>
- </tp:docstring>
- </method>
-
- <property name="RequestedOutputVolume" tp:type="Audio_Control_Volume"
- type="i" access="read" tp:name-for-bindings="Requested_Output_Volume">
- <tp:docstring>
- The input volume as requested by the Connection Manager.
- Initially and on any changes the client should change its input volume
- to match the requested volume.
- </tp:docstring>
- </property>
-
- <method name="ReportOutputVolume"
- tp:name-for-bindings="Report_Output_Volume">
- <arg direction="in" name="Volume" tp:type="Audio_Control_Volume" type="i">
- <tp:docstring>
- Report the output volume level as set by the client.
- </tp:docstring>
- </arg>
- <tp:docstring>
- <p>Report to the CM that the content output volume has been
- changed by the client.</p>
-
- <p>It is the client's responsibility to change the output volume used
- for the content. However, the client MUST call this whenever it
- changes output volume for the content.</p>
- </tp:docstring>
- </method>
-
- <tp:simple-type name="Audio_Control_Volume" type="i">
- <tp:docstring>
- <p>A volume value either reported to or requested by the Connection
- Manager. This value should either be -1 for an unknown value or in the
- range of 0-255, with 0 being the minimal volume and 255 being the
- highest unamplified volume the input or output is capable of (known
- as 0 dB)
- </p>
- </tp:docstring>
- </tp:simple-type>
- </interface>
-</node>
diff --git a/extensions/Call_Content_Interface_Media.xml b/extensions/Call_Content_Interface_Media.xml
deleted file mode 100644
index 038ce8c..0000000
--- a/extensions/Call_Content_Interface_Media.xml
+++ /dev/null
@@ -1,367 +0,0 @@
-<?xml version="1.0" ?>
-<node name="/Call_Content_Interface_Media"
- xmlns:tp="http://telepathy.freedesktop.org/wiki/DbusSpec#extensions-v0">
- <tp:copyright>Copyright © 2009-2010 Collabora Ltd.</tp:copyright>
- <tp:copyright>Copyright © 2009-2010 Nokia Corporation</tp:copyright>
- <tp:license xmlns="http://www.w3.org/1999/xhtml">
- <p>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.</p>
-
- <p>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.</p>
-
- <p>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 Street, Fifth Floor, Boston, MA
- 02110-1301, USA.</p>
- </tp:license>
-
- <interface name="org.freedesktop.Telepathy.Call.Content.Interface.Media.DRAFT"
- tp:causes-havoc="experimental">
- <tp:added version="0.19.0">(draft 1)</tp:added>
- <tp:requires interface="org.freedesktop.Telepathy.Call.Content.DRAFT"/>
-
- <tp:docstring xmlns="http://www.w3.org/1999/xhtml">
- <p>Interface to use by a software implementation of media
- streaming. The reason behind splitting the members of this
- interface out from the main <tp:dbus-ref
- namespace="ofdT.Call">Content.DRAFT</tp:dbus-ref> interface is
- that the software is not necessarily what controls the
- media. An example of this is in GSM phones, where the CM just
- tells the phone to dial a number and it does the audio routing
- in a device specific hardware way and the CM does not need
- to concern itself with codecs.</p>
-
- <h4>Codec negotiation</h4>
-
- <p>When a new <tp:dbus-ref
- namespace="ofdT.Channel.Type">Call.DRAFT</tp:dbus-ref> channel
- appears, whether it was requested or not, a <tp:dbus-ref
- namespace="ofdT.Call.Content">CodecOffer.DRAFT</tp:dbus-ref>
- will either be waiting in the
- <tp:member-ref>CodecOffer</tp:member-ref> property, or will
- appear at some point via the
- <tp:member-ref>NewCodecOffer</tp:member-ref> signal.</p>
-
- <p>The <tp:dbus-ref
- namespace="ofdT.Call.Content.CodecOffer.DRAFT">RemoteContactCodecs</tp:dbus-ref>
- property on the codec offer lists the codecs which are
- supported by the remote contact, and so will determine the
- codecs that should be proposed by the local user's streaming
- implementation. An empty list means all codecs can be proposed.</p>
-
- <p>For incoming calls on protocols where codecs are proposed when
- starting the call (for example, <a
- href="http://xmpp.org/extensions/xep-0166.html">Jingle</a>),
- the <tp:dbus-ref
- namespace="ofdT.Call.Content.CodecOffer.DRAFT">RemoteContactCodecs</tp:dbus-ref>
- will contain information on the codecs that have already been
- proposed by the remote contact, otherwise the codec map will
- be the empty list.</p>
-
- <p>The streaming implementation should look at the remote codec
- map and the codecs known by the local user and call
- <tp:dbus-ref
- namespace="ofdT.Call.Content">CodecOffer.DRAFT.Accept</tp:dbus-ref>
- on the intersection of these two codec lists.</p>
-
- <p>This means that in practice, outgoing calls will have a codec
- offer pop up with no information in the <tp:dbus-ref
- namespace="ofdT.Call.Content.CodecOffer.DRAFT">RemoteContactCodecs</tp:dbus-ref>,
- so the local user will call <tp:dbus-ref
- namespace="ofdT.Call.Content.CodecOffer.DRAFT">Accept</tp:dbus-ref>
- with the list of all codecs supported. If this codec offer is
- accepted, then <tp:member-ref>CodecsChanged</tp:member-ref>
- will fire with the details of the codecs passed into
- <tp:dbus-ref
- namespace="ofdT.Call.Content.CodecOffer.DRAFT">Accept</tp:dbus-ref>. If
- the call is incoming, then the <tp:dbus-ref
- namespace="ofdT.Call.Content.CodecOffer.DRAFT">RemoteContactCodecs</tp:dbus-ref>
- will contain details of the remote contact's codecs and the
- local user will call <tp:dbus-ref
- namespace="ofdT.Call.Content.CodecOffer.DRAFT">Accept</tp:dbus-ref>
- with the codecs that both sides understand. After the codec
- set is accepted, <tp:member-ref>CodecsChanged</tp:member-ref>
- will fire to signal this change.</p>
-
- <h4>Protocols without codec negotiation</h4>
-
- <p>For protocols where the codecs are not negotiable, instead of
- popping up the initial content's <tp:dbus-ref
- namespace="ofdT.Call.Content">CodecOffer.DRAFT</tp:dbus-ref>
- object with an empty <tp:dbus-ref
- namespace="ofdT.Call.Content.CodecOffer.DRAFT">RemoteContactCodecs</tp:dbus-ref>,
- the CM should set the supported codec values to known codec
- values in the said object's codec map.</p>
-
- <h4>Changing codecs mid-call</h4>
-
- <p>To update the codec list used mid-call, the
- <tp:member-ref>UpdateCodecs</tp:member-ref> method should be
- called with details of the new codec list. If this is
- accepted, then <tp:member-ref>CodecsChanged</tp:member-ref>
- will be emitted with the new codec set.</p>
-
- <p>If the other side decides to update his or her codec list
- during a call, a new <tp:dbus-ref
- namespace="ofdT.Call.Content">CodecOffer.DRAFT</tp:dbus-ref>
- object will appear through
- <tp:member-ref>NewCodecOffer</tp:member-ref> which should be
- acted on as documented above.</p>
-
- </tp:docstring>
-
- <tp:struct name="Codec" array-name="Codec_List">
- <tp:docstring>
- A description of a codec.
- </tp:docstring>
- <tp:member name="Identifier" type="u">
- <tp:docstring xmlns="http://www.w3.org/1999/xhtml">
- Numeric identifier for the codec. This will be used as the PT in the
- SDP or content description.
- </tp:docstring>
- </tp:member>
- <tp:member name="Name" type="s">
- <tp:docstring xmlns="http://www.w3.org/1999/xhtml">
- The name of the codec.
- </tp:docstring>
- </tp:member>
- <tp:member name="Clockrate" type="u">
- <tp:docstring xmlns="http://www.w3.org/1999/xhtml">
- The clockrate of the codec.
- </tp:docstring>
- </tp:member>
- <tp:member name="Channels" type="u">
- <tp:docstring xmlns="http://www.w3.org/1999/xhtml">
- Number of channels of the codec if applicable, otherwise 0.
- </tp:docstring>
- </tp:member>
- <tp:member name="Parameters" type="a{ss}" tp:type="String_String_Map">
- <tp:docstring xmlns="http://www.w3.org/1999/xhtml">
- Extra parameters for this codec.
- </tp:docstring>
- </tp:member>
- </tp:struct>
-
- <tp:mapping name="Contact_Codec_Map">
- <tp:docstring>
- A map from contact to the list of codecs he or she supports.
- </tp:docstring>
- <tp:member name="Handle" type="u" tp:type="Contact_Handle">
- <tp:docstring>
- A contact handle.
- </tp:docstring>
- </tp:member>
- <tp:member name="Codecs" type="a(usuua{ss})" tp:type="Codec[]">
- <tp:docstring>
- The codecs that the contact supports.
- </tp:docstring>
- </tp:member>
- </tp:mapping>
-
- <tp:struct name="Codec_Offering">
- <tp:docstring>
- A codec offer and its corresponding remote contact codec map.
- </tp:docstring>
- <tp:member name="Codec_Offer" type="o">
- <tp:docstring xmlns="http://www.w3.org/1999/xhtml">
- The object path to the <tp:dbus-ref namespace="ofdT.Call.Content"
- >CodecOffer.DRAFT</tp:dbus-ref>
- </tp:docstring>
- </tp:member>
- <tp:member name="Remote_Contact" type="u" tp:type="Contact_Handle">
- <tp:docstring xmlns="http://www.w3.org/1999/xhtml">
- The contact handle that this codec offer applies to.
- </tp:docstring>
- </tp:member>
- <tp:member name="Remote_Contact_Codecs" type="a(usuua{ss})"
- tp:type="Codec[]">
- <tp:docstring xmlns="http://www.w3.org/1999/xhtml">
- The <tp:dbus-ref namespace="ofdT.Call.Content"
- >CodecOffer.DRAFT.RemoteContactCodecs</tp:dbus-ref> property
- of the codec offer.
- </tp:docstring>
- </tp:member>
- </tp:struct>
-
- <signal name="CodecsChanged" tp:name-for-bindings="Codecs_Changed">
- <tp:docstring xmlns="http://www.w3.org/1999/xhtml">
- <p>Emitted when the codecs in use change.</p>
-
- <p>As well as acting as change notification for the
- <tp:member-ref>ContactCodecMap</tp:member-ref>, emission of this
- signal implies that the <tp:member-ref>CodecOffer</tp:member-ref>
- property has changed to <code>('/', {})</code>.</p>
- </tp:docstring>
- <arg name="Updated_Codecs" type="a{ua(usuua{ss})}"
- tp:type="Contact_Codec_Map">
- <tp:docstring>
- A map from contact to his or her codecs. Each pair in this
- map is added to the
- <tp:member-ref>ContactCodecMap</tp:member-ref> property,
- replacing any previous pair with that key.
- </tp:docstring>
- </arg>
- <arg name="Removed_Contacts" type="au" tp:type="Contact_Handle[]">
- <tp:docstring>
- A list of keys which were removed from the
- <tp:member-ref>ContactCodecMap</tp:member-ref>, probably because
- those contacts left the call.
- </tp:docstring>
- </arg>
- </signal>
-
- <method name="UpdateCodecs" tp:name-for-bindings="Update_Codecs">
- <tp:docstring>
- Update the local codec mapping. This method should only be
- used during an existing call to update the codec mapping.
- </tp:docstring>
- <arg name="Codecs" direction="in"
- type="a(usuua{ss})" tp:type="Codec[]">
- <tp:docstring>
- The codecs now supported by the local user.
- </tp:docstring>
- </arg>
- <tp:possible-errors>
- <tp:error name="org.freedesktop.Telepathy.Error.NotAvailable">
- <tp:docstring>
- Raised when a <tp:dbus-ref
- namespace="ofdT.Call.Content">CodecOffer.DRAFT</tp:dbus-ref>
- object exists and is referred to in the
- <tp:member-ref>CodecOffer</tp:member-ref> property which
- should be used instead of calling this method, or before
- the content's initial <tp:dbus-ref
- namespace="ofdT.Call.Content">CodecOffer.DRAFT</tp:dbus-ref>
- object has appeared.
- </tp:docstring>
- </tp:error>
- </tp:possible-errors>
- </method>
-
- <property name="ContactCodecMap" tp:name-for-bindings="Contact_Codec_Map"
- type="a{ua(usuua{ss})}" tp:type="Contact_Codec_Map" access="read">
- <tp:docstring>
- <p>A map from contact handles (including the local user's own handle)
- to the codecs supported by that contact.</p>
-
- <p>Change notification is via the
- <tp:member-ref>CodecsChanged</tp:member-ref> signal.</p>
- </tp:docstring>
- </property>
-
- <signal name="NewCodecOffer" tp:name-for-bindings="New_Codec_Offer">
- <tp:docstring xmlns="http://www.w3.org/1999/xhtml">
- <p>Emitted when a new <tp:dbus-ref namespace="ofdT.Call.Content"
- >CodecOffer.DRAFT</tp:dbus-ref> appears. The streaming
- implementation MUST respond by calling the <tp:dbus-ref
- namespace="ofdT.Call.Content.CodecOffer.DRAFT"
- >Accept</tp:dbus-ref> or <tp:dbus-ref
- namespace="ofdT.Call.Content.CodecOffer.DRAFT"
- >Reject</tp:dbus-ref> method on the codec offer object.</p>
-
- <p>Emission of this signal indicates that the
- <tp:member-ref>CodecOffer</tp:member-ref> property has changed to
- <code>(Contact, Offer, Codecs)</code>.</p>
- </tp:docstring>
- <arg name="Contact" type="u">
- <tp:docstring>
- The contact the codec offer belongs to.
- </tp:docstring>
- </arg>
- <arg name="Offer" type="o">
- <tp:docstring>
- The object path of the new codec offer. This replaces any previous
- codec offer.
- </tp:docstring>
- </arg>
- <arg name="Codecs" type="a(usuua{ss})" tp:type="Codec[]">
- <tp:docstring xmlns="http://www.w3.org/1999/xhtml">
- <p>The <tp:dbus-ref namespace="ofdT.Call.Content"
- >CodecOffer.DRAFT.RemoteContactCodecs</tp:dbus-ref> property
- of the codec offer.</p>
-
- <tp:rationale>
- Having the <tp:dbus-ref
- namespace="ofdT.Call.Content.CodecOffer.DRAFT">RemoteContactCodecs</tp:dbus-ref>
- property here saves a D-Bus round-trip - it shouldn't be
- necessary to get the property from the CodecOffer object, in
- practice.
- </tp:rationale>
- </tp:docstring>
- </arg>
- </signal>
-
- <property name="CodecOffer" tp:name-for-bindings="Codec_Offer"
- type="(oua(usuua{ss}))" tp:type="Codec_Offering" access="read">
- <tp:docstring xmlns="http://www.w3.org/1999/xhtml">
- <p>The object path to the current
- <tp:dbus-ref namespace="ofdT.Call.Content"
- >CodecOffer.DRAFT</tp:dbus-ref> object, its
- <tp:dbus-ref namespace="ofdT.Call.Content"
- >CodecOffer.DRAFT.RemoteContact</tp:dbus-ref> and
- <tp:dbus-ref namespace="ofdT.Call.Content"
- >CodecOffer.DRAFT.RemoteContactCodecs</tp:dbus-ref> properties.
- If the object path is "/" then there isn't an outstanding
- codec offer, and the mapping MUST be empty.</p>
-
- <tp:rationale>
- Having the <tp:dbus-ref
- namespace="ofdT.Call.Content.CodecOffer.DRAFT"
- >RemoteContact</tp:dbus-ref> and
- <tp:dbus-ref namespace="ofdT.Call.Content.CodecOffer.DRAFT"
- >RemoteContactCodecs</tp:dbus-ref>
- properties here saves a D-Bus round-trip - it shouldn't be
- necessary to get these properties from the CodecOffer object, in
- practice.
- </tp:rationale>
-
- <p>Change notification is via the
- <tp:member-ref>NewCodecOffer</tp:member-ref> (which replaces the
- value of this property with a new codec offer), and
- <tp:member-ref>CodecsChanged</tp:member-ref> (which implies that
- there is no longer any active codec offer) signals.</p>
- </tp:docstring>
- </property>
-
- <tp:enum name="Call_Content_Packetization_Type" type="u">
- <tp:added version="0.21.2"/>
- <tp:docstring>
- A packetization method that can be used for a content.
- </tp:docstring>
-
- <tp:enumvalue suffix="RTP" value="0">
- <tp:docstring xmlns="http://www.w3.org/1999/xhtml">
- Real-time Transport Protocol, as documented by RFC 3550.
- </tp:docstring>
- </tp:enumvalue>
-
- <tp:enumvalue suffix="Raw" value="1">
- <tp:docstring xmlns="http://www.w3.org/1999/xhtml">
- Raw media.
- </tp:docstring>
- </tp:enumvalue>
-
- <tp:enumvalue suffix="MSN_Webcam" value="2">
- <tp:docstring xmlns="http://www.w3.org/1999/xhtml">
- MSN webcam. This is the video-only one-way type which was
- used in earlier versions of WLM. Although no longer used,
- modern WLM clients still support the MSN webcam protocol.
- </tp:docstring>
- </tp:enumvalue>
- </tp:enum>
-
- <property name="Packetization" tp:name-for-bindings="Packetization"
- type="u" tp:type="Call_Content_Packetization_Type" access="read"
- tp:immutable="yes">
- <tp:added version="0.21.2"/>
- <tp:docstring xmlns="http://www.w3.org/1999/xhtml">
- <p>The packetization method in use for this content.</p>
- </tp:docstring>
- </property>
- </interface>
-</node>
-<!-- vim:set sw=2 sts=2 et ft=xml: -->
diff --git a/extensions/Call_Content_Interface_Mute.xml b/extensions/Call_Content_Interface_Mute.xml
deleted file mode 100644
index f926e03..0000000
--- a/extensions/Call_Content_Interface_Mute.xml
+++ /dev/null
@@ -1,85 +0,0 @@
-<?xml version="1.0" ?>
-<node name="/Call_Content_Interface_Mute" xmlns:tp="http://telepathy.freedesktop.org/wiki/DbusSpec#extensions-v0">
- <tp:copyright> Copyright © 2005-2010 Nokia Corporation </tp:copyright>
- <tp:copyright> Copyright © 2005-2010 Collabora Ltd </tp:copyright>
- <tp:license xmlns="http://www.w3.org/1999/xhtml">
-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 Street, Fifth Floor, Boston, MA 02110-1301, USA.
- </tp:license>
-
- <interface name="org.freedesktop.Telepathy.Call.Content.Interface.Mute.DRAFT" tp:causes-havoc="experimental">
- <tp:added version="0.19.6">(draft version, not API-stable)</tp:added>
- <tp:requires interface="org.freedesktop.Telepathy.Call.Content.DRAFT"/>
-
- <tp:docstring xmlns="http://www.w3.org/1999/xhtml">
- <p>Interface for calls which may be muted. This only makes sense
- for channels where audio or video is streaming between members.</p>
-
- <p>Muting a call content indicates that the user does not wish to send
- outgoing audio or video.</p>
-
- <p>Although it's client's responsibility to actually mute the microphone
- or turn off the camera, using this interface the client can also
- inform the CM and other clients of that fact.</p>
-
- <tp:rationale>
- For some protocols, the fact that the content is muted needs
- to be transmitted to the peer; for others, the notification
- to the peer is only informational (eg. XMPP), and some
- protocols may have no notion of muting at all.
- </tp:rationale>
- </tp:docstring>
-
- <signal name="MuteStateChanged" tp:name-for-bindings="Mute_State_Changed">
- <tp:docstring>
- Emitted to indicate that the mute state has changed for this call content.
- This may occur as a consequence of the client calling
- <tp:member-ref>SetMuted</tp:member-ref>, or as an indication that another
- client has (un)muted the content.
- </tp:docstring>
- <arg name="MuteState" type="b">
- <tp:docstring>
- True if the content is now muted.
- </tp:docstring>
- </arg>
- </signal>
-
- <property name="MuteState" type="b"
- access="read" tp:name-for-bindings="Mute_State">
- <tp:docstring>
- True if the content is muted.
- </tp:docstring>
- </property>
-
- <method name="SetMuted" tp:name-for-bindings="Set_Muted">
- <tp:changed version="0.21.2">renamed from SetMuted to Mute</tp:changed>
- <tp:changed version="0.21.3">renamed back from Mute to SetMuted</tp:changed>
- <arg direction="in" name="Muted" type="b">
- <tp:docstring>
- True if the client has muted the content.
- </tp:docstring>
- </arg>
- <tp:docstring>
- <p>Inform the CM that the call content has been muted or unmuted by
- the client.</p>
-
- <p>It is the client's responsibility to actually mute or unmute the
- microphone or camera used for the content. However, the client
- MUST call this whenever it mutes or unmutes the content.</p>
- </tp:docstring>
- </method>
-
- </interface>
-</node>
-<!-- vim:set sw=2 sts=2 et ft=xml: -->
diff --git a/extensions/Call_Content_Interface_Video_Control.xml b/extensions/Call_Content_Interface_Video_Control.xml
deleted file mode 100644
index b066de4..0000000
--- a/extensions/Call_Content_Interface_Video_Control.xml
+++ /dev/null
@@ -1,137 +0,0 @@
-<!DOCTYPE node PUBLIC "-//freedesktop//DTD D-BUS Object Introspection 1.0//EN" "http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd">
-<node name="/Call_Content_Interface_Video_Control"
- xmlns:tp="http://telepathy.freedesktop.org/wiki/DbusSpec#extensions-v0">
- <tp:copyright>Copyright © 2009-2010 Collabora Ltd.</tp:copyright>
- <tp:copyright>Copyright © 2009-2010 Nokia Corporation</tp:copyright>
- <tp:license xmlns="http://www.w3.org/1999/xhtml">
- <p>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.</p>
-
- <p>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.</p>
-
- <p>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 Street, Fifth Floor, Boston, MA
- 02110-1301, USA.</p>
- </tp:license>
-
- <interface name="org.freedesktop.Telepathy.Call.Content.Interface.VideoControl.DRAFT"
- tp:causes-havoc="experimental">
- <tp:added version="0.21.10">(draft 1)</tp:added>
- <tp:requires interface="org.freedesktop.Telepathy.Call.Content.Interface.Media.DRAFT"/>
-
- <tp:docstring xmlns="http://www.w3.org/1999/xhtml">
- <p>An interface that allows the connection manager to control the video
- stream.</p>
- <p>This interface is generally not needed. In cases where the connection
- manager handles the network communication and the media is transferred
- from the client to the connection manager via shared memory, it can
- sometimes be beneficial for the connection manager to be able to
- control certain aspects of the video stream.</p>
- </tp:docstring>
-
- <signal name="KeyFrameRequested" tp:name-for-bindings="Key_Frame_Requested">
- <tp:docstring>
- Request that the video encoder produce a new key frame as soon as
- possible.
- </tp:docstring>
- </signal>
-
- <tp:struct name="Video_Resolution"
- array-name="Video_Resolution_Struct">
- <tp:member type="u" name="Width">
- <tp:docstring>
- With of the video stream.
- </tp:docstring>
- </tp:member>
- <tp:member type="u" name="Height">
- <tp:docstring>
- Height of the video stream.
- </tp:docstring>
- </tp:member>
- </tp:struct>
-
- <property name="VideoResolution" type="(uu)" tp:type="Video_Resolution"
- access="read" tp:name-for-bindings="Video_Resolution">
- <tp:docstring>
- The resolution at which the streaming engine should be sending.
-
- <p>Change notification is via the
- <tp:member-ref>VideoResolutionChanged</tp:member-ref> signal.</p>
- </tp:docstring>
- </property>
-
- <signal name="VideoResolutionChanged"
- tp:name-for-bindings="Video_Resolution_Changed">
- <tp:docstring>
- The desired video resolution has changed.
- </tp:docstring>
- <arg type="(uu)" tp:type="Video_Resolution" name="NewResolution" />
- </signal>
-
- <property name="Bitrate" type="u" access="read"
- tp:name-for-bindings="Bitrate">
- <tp:docstring>
- The bitrate the streaming engine should be sending at.
-
- <p>Change notification is via the
- <tp:member-ref>BitrateChanged</tp:member-ref> signal.</p>
- </tp:docstring>
- </property>
-
- <signal name="BitrateChanged"
- tp:name-for-bindings="Bitrate_Changed">
- <tp:docstring>
- The desired bitrate has changed
- </tp:docstring>
- <arg type="u" name="NewBitrate" />
- </signal>
-
- <property name="Framerate" type="u" access="read"
- tp:name-for-bindings="Framerate">
- <tp:docstring>
- The framerate the streaming engine should be sending at.
-
- <p>Change notification is via the
- <tp:member-ref>FramerateChanged</tp:member-ref> signal.</p>
- </tp:docstring>
- </property>
-
- <signal name="FramerateChanged"
- tp:name-for-bindings="Framerate_Changed">
- <tp:docstring>
- The desired framerate has changed
- </tp:docstring>
- <arg type="u" name="NewFramerate" />
- </signal>
-
- <property name="MTU" type="u" access="read"
- tp:name-for-bindings="MTU">
- <tp:docstring>
- The Maximum Transmission Unit
-
- <p>Change notification is via the
- <tp:member-ref>MTUChanged</tp:member-ref> signal.</p>
- </tp:docstring>
- </property>
-
- <signal name="MTUChanged" tp:name-for-bindings="MTU_Changed">
- <tp:docstring>
- The Maximum Transmission Unit has changed
- </tp:docstring>
- <arg type="u" name="NewMTU" />
- </signal>
-
- <property name="ManualKeyFrames" type="b" access="read"
- tp:name-for-bindings="Manual_Key_Frames">
- <tp:docstring>
- Only send key frames when manually requested
- </tp:docstring>
- </property>
- </interface>
-</node>
diff --git a/extensions/Call_Stream.xml b/extensions/Call_Stream.xml
deleted file mode 100644
index 1d7b281..0000000
--- a/extensions/Call_Stream.xml
+++ /dev/null
@@ -1,261 +0,0 @@
-<?xml version="1.0" ?>
-<node name="/Call_Stream"
- xmlns:tp="http://telepathy.freedesktop.org/wiki/DbusSpec#extensions-v0">
- <tp:copyright>Copyright © 2009-2010 Collabora Ltd.</tp:copyright>
- <tp:copyright>Copyright © 2009-2010 Nokia Corporation</tp:copyright>
- <tp:license xmlns="http://www.w3.org/1999/xhtml">
- <p>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.</p>
-
- <p>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.</p>
-
- <p>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 Street, Fifth Floor, Boston, MA
- 02110-1301, USA.</p>
- </tp:license>
-
- <interface name="org.freedesktop.Telepathy.Call.Stream.DRAFT"
- tp:causes-havoc="experimental">
- <tp:added version="0.19.0">(draft 1)</tp:added>
-
- <tp:docstring xmlns="http://www.w3.org/1999/xhtml">
- One stream inside a <tp:dbus-ref
- namespace="ofdT.Call">Content.DRAFT</tp:dbus-ref>.
- </tp:docstring>
-
- <method name="SetSending" tp:name-for-bindings="Set_Sending">
- <tp:docstring>
- Set the stream to start or stop sending media from the local
- user to other contacts.
- </tp:docstring>
-
- <arg name="Send" type="b" direction="in">
- <tp:docstring xmlns="http://www.w3.org/1999/xhtml">
- <p>If True, the
- <tp:member-ref>LocalSendingState</tp:member-ref> should
- change to <tp:type>Sending_State</tp:type>_Sending, if it isn't
- already.</p>
-
- <p>If False, the
- <tp:member-ref>LocalSendingState</tp:member-ref> should
- change to <tp:type>Sending_State</tp:type>_None, if it isn't
- already.</p>
- </tp:docstring>
- </arg>
-
- <tp:possible-errors>
- <tp:error name="org.freedesktop.Telepathy.Error.NotImplemented" />
- </tp:possible-errors>
- </method>
-
- <method name="RequestReceiving" tp:name-for-bindings="Request_Receiving">
- <tp:docstring>
- <p>Request that a remote contact stops or starts sending on
- this stream.</p>
-
- <p>The <tp:member-ref>CanRequestReceiving</tp:member-ref>
- property defines whether the protocol allows the local user to
- request the other side start sending on this stream.</p>
- </tp:docstring>
-
- <arg name="Contact" type="u" tp:type="Contact_Handle" direction="in">
- <tp:docstring xmlns="http://www.w3.org/1999/xhtml">
- <p>Contact from which sending is requested</p>
- </tp:docstring>
- </arg>
-
- <arg name="Receive" type="b" direction="in">
- <tp:docstring xmlns="http://www.w3.org/1999/xhtml">
- <p>If true, request that the given contact starts to send media.
- If false, request that the given contact stops sending media.</p>
- </tp:docstring>
- </arg>
-
- <tp:possible-errors>
- <tp:error name="org.freedesktop.Telepathy.Error.InvalidHandle"/>
- <tp:error name="org.freedesktop.Telepathy.Error.InvalidArgument">
- <tp:docstring>
- The request contact is valid but is not involved in this
- stream.
- </tp:docstring>
- </tp:error>
- <tp:error name="org.freedesktop.Telepathy.Error.NotImplemented">
- <tp:docstring>
- The protocol does not allow the local user to request the
- other side starts sending on this stream.
- </tp:docstring>
- </tp:error>
- </tp:possible-errors>
- </method>
-
- <signal name="RemoteMembersChanged"
- tp:name-for-bindings="Remote_Members_Changed">
- <tp:changed version="0.21.2">renamed from SendersChanged to MembersChanged</tp:changed>
- <tp:changed version="0.21.3">renamed from MembersChanged to RemoteMembersChanged</tp:changed>
- <tp:docstring xmlns="http://www.w3.org/1999/xhtml">
- Emitted when <tp:member-ref>RemoteMembers</tp:member-ref> changes.
- </tp:docstring>
-
- <arg name="Updates" type="a{uu}" tp:type="Contact_Sending_State_Map">
- <tp:docstring>
- A mapping from channel-specific handles to their updated sending
- state, whose keys include at least the members who were added,
- and the members whose states changed.
- </tp:docstring>
- </arg>
- <arg name="Removed" type="au" tp:type="Contact_Handle[]">
- <tp:docstring>
- The channel-specific handles that were removed from the keys
- of the <tp:member-ref>RemoteMembers</tp:member-ref>
- property, as a result of the contact leaving this stream
- </tp:docstring>
- </arg>
- </signal>
-
- <signal name="LocalSendingStateChanged"
- tp:name-for-bindings="Local_Sending_State_Changed">
- <tp:docstring xmlns="http://www.w3.org/1999/xhtml">
- Emitted when <tp:member-ref>LocalSendingState</tp:member-ref> changes.
- </tp:docstring>
-
- <arg name="State" type="u" tp:type="Sending_State">
- <tp:docstring>
- The new value of
- <tp:member-ref>LocalSendingState</tp:member-ref>.
- </tp:docstring>
- </arg>
- </signal>
-
- <tp:enum name="Sending_State" type="u">
- <tp:docstring>
- Enum indicating whether a contact is sending media.
- </tp:docstring>
-
- <tp:enumvalue suffix="None" value="0">
- <tp:docstring>
- The contact is not sending media and has not been asked to
- do so.
- </tp:docstring>
- </tp:enumvalue>
-
- <tp:enumvalue suffix="Pending_Send" value="1">
- <tp:docstring>
- The contact has been asked to start sending media.
- </tp:docstring>
- </tp:enumvalue>
-
- <tp:enumvalue suffix="Sending" value="2">
- <tp:docstring>
- The contact is sending media.
- </tp:docstring>
- </tp:enumvalue>
-
- <tp:enumvalue suffix="Pending_Stop_Sending" value="3">
- <tp:docstring>
- The contact has been asked to stop sending media.
- </tp:docstring>
- </tp:enumvalue>
- </tp:enum>
-
- <tp:mapping name="Contact_Sending_State_Map">
- <tp:docstring>
- A map from a contact to his or her sending state.
- </tp:docstring>
- <tp:member name="Contact" type="u" tp:type="Contact_Handle">
- <tp:docstring>
- The contact handle.
- </tp:docstring>
- </tp:member>
- <tp:member name="Sending" type="u" tp:type="Sending_State">
- <tp:docstring>
- The sending state of the contact.
- </tp:docstring>
- </tp:member>
- </tp:mapping>
-
- <property name="Interfaces" tp:name-for-bindings="Interfaces"
- type="as" tp:type="DBus_Interface[]" access="read" tp:immutable="yes">
- <tp:added version="0.19.11"/>
- <tp:docstring xmlns="http://www.w3.org/1999/xhtml">
- <p>Extra interfaces provided by this stream, such as <tp:dbus-ref
- namespace="ofdT.Call">Stream.Interface.Media.DRAFT</tp:dbus-ref>.
- This SHOULD NOT include the Stream interface itself, and cannot
- change once the stream has been created.</p>
- </tp:docstring>
- </property>
-
- <property name="RemoteMembers" tp:name-for-bindings="Remote_Members"
- type="a{uu}" access="read" tp:type="Contact_Sending_State_Map">
- <tp:changed version="0.21.2">renamed from Senders</tp:changed>
- <tp:docstring xmlns="http://www.w3.org/1999/xhtml">
- <p>A map from remote contacts to their sending state. The
- local user's sending state is shown in
- <tp:member-ref>LocalSendingState</tp:member-ref>.</p>
-
- <p><tp:type>Sending_State</tp:type>_Pending_Send indicates
- that another contact has asked the local user to send
- media.</p>
-
- <p>Other contacts' handles in this map indicate whether they are
- sending media to the contacts in this stream.
- Sending_State_Pending_Send indicates contacts who are not sending but
- have been asked to do so.</p>
- </tp:docstring>
- </property>
-
- <property name="LocalSendingState" tp:name-for-bindings="Local_Sending_State"
- type="u" access="read" tp:type="Sending_State">
- <tp:docstring xmlns="http://www.w3.org/1999/xhtml">
- <p>The local user's sending state. Media sent on this stream
- should be assumed to be received, directly or indirectly, by
- every other contact in the
- <tp:member-ref>RemoteMembers</tp:member-ref> mapping. Change
- notification is given via the
- <tp:member-ref>LocalSendingStateChanged</tp:member-ref>
- signal.</p>
-
- <tp:rationale>
- Implementations of the first Call draft had the self handle
- in the <tp:member-ref>RemoteMembers</tp:member-ref> (then
- called Members) map and this showed that it's annoying
- having to keep track of the self handle so that it can be
- special-cased.
- </tp:rationale>
-
- <p>A value of <tp:type>Sending_State</tp:type>_Pending_Send for
- this property indicates that the other side requested the
- local user start sending media, which can be done by calling
- <tp:member-ref>SetSending</tp:member-ref>. When a call is
- accepted, all initial contents with streams that have a
- local sending state of
- <tp:type>Sending_State</tp:type>_Pending_Send are
- automatically set to sending. For example, on an incoming
- call it means you need to <tp:dbus-ref
- namespace="ofdT.Channel.Type.Call.DRAFT">Accept</tp:dbus-ref>
- to start the actual call, on an outgoing call it might mean
- you need to call <tp:dbus-ref
- namespace="ofdT.Channel.Type.Call.DRAFT">Accept</tp:dbus-ref>
- before actually starting the call.</p>
- </tp:docstring>
- </property>
-
- <property name="CanRequestReceiving" tp:name-for-bindings="Can_Request_Receiving"
- type="b" access="read" tp:immutable="yes">
- <tp:added version="0.21.2"/>
- <tp:docstring xmlns="http://www.w3.org/1999/xhtml">
- <p>If true, the user can request that a remote contact starts
- sending on this stream.</p>
-
- <tp:rationale>Not all protocols allow the user to ask the
- other side to start sending media.</tp:rationale>
- </tp:docstring>
- </property>
- </interface>
-</node>
-<!-- vim:set sw=2 sts=2 et ft=xml: -->
diff --git a/extensions/Call_Stream_Endpoint.xml b/extensions/Call_Stream_Endpoint.xml
deleted file mode 100644
index 4818168..0000000
--- a/extensions/Call_Stream_Endpoint.xml
+++ /dev/null
@@ -1,182 +0,0 @@
-<?xml version="1.0" ?>
-<node name="/Call_Stream_Endpoint"
- xmlns:tp="http://telepathy.freedesktop.org/wiki/DbusSpec#extensions-v0">
- <tp:copyright>Copyright © 2009-2010 Collabora Ltd.</tp:copyright>
- <tp:copyright>Copyright © 2009-2010 Nokia Corporation</tp:copyright>
- <tp:license xmlns="http://www.w3.org/1999/xhtml">
- <p>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.</p>
-
- <p>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.</p>
-
- <p>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 Street, Fifth Floor, Boston, MA
- 02110-1301, USA.</p>
- </tp:license>
-
- <interface name="org.freedesktop.Telepathy.Call.Stream.Endpoint.DRAFT"
- tp:causes-havoc="experimental">
- <tp:added version="0.19.0">(draft 1)</tp:added>
-
- <tp:docstring xmlns="http://www.w3.org/1999/xhtml">
- <p>This object represents an endpoint for a stream. In a one-to-one
- call, there will be one (bidirectional) stream per content and
- one endpoint per stream (as there is only one remote
- contact). In a multi-user call there is a stream for each remote
- contact and each stream has one endpoint as it refers to the one
- physical machine on the other end of the stream.</p>
-
- <p>The multiple endpoint use case appears when SIP call forking
- is used. Unlike jingle call forking (which is just making
- multiple jingle calls to different resources appear as one
- call), SIP call forking is actually done at the server so you
- have one stream to the remote contact and then and endpoint for
- each SIP client to be called.</p>
- </tp:docstring>
-
- <property name="RemoteCredentials"
- tp:name-for-bindings="Remote_Credentials"
- type="(ss)" tp:type="Stream_Credentials" access="read">
- <tp:docstring>
- The ICE credentials used for all candidates. If each candidate
- has different credentials, then this property SHOULD be ("",
- ""). Per-candidate credentials are set in the
- <tp:type>Candidate</tp:type>'s
- <tp:type>Candidate_Info</tp:type> a{sv}.
- </tp:docstring>
- </property>
-
- <signal name="RemoteCredentialsSet"
- tp:name-for-bindings="Remote_Credentials_Set">
- <arg name="Username" type="s">
- <tp:docstring>
- The username set.
- </tp:docstring>
- </arg>
- <arg name="Password" type="s">
- <tp:docstring>
- The password set.
- </tp:docstring>
- </arg>
- <tp:docstring>
- Emitted when the remote ICE credentials for the endpoint are
- set. If each candidate has different credentials, then this
- signal will never be fired.
- </tp:docstring>
- </signal>
-
- <property name="RemoteCandidates" tp:name-for-bindings="Remote_Candidates"
- type="a(usqa{sv})" tp:type="Candidate[]" access="read">
- <tp:docstring>
- A list of candidates for this endpoint.
- </tp:docstring>
- </property>
-
- <signal name="RemoteCandidatesAdded"
- tp:name-for-bindings="Remote_Candidates_Added">
- <tp:docstring>
- Emitted when remote candidates are added to the
- <tp:member-ref>RemoteCandidates</tp:member-ref> property.
- </tp:docstring>
- <arg name="Candidates"
- type="a(usqa{sv})" tp:type="Candidate[]">
- <tp:docstring>
- The candidates that were added.
- </tp:docstring>
- </arg>
- </signal>
-
- <signal name="CandidateSelected"
- tp:name-for-bindings="Candidate_Selected">
- <tp:docstring>
- Emitted when a candidate is selected for use in the stream.
- </tp:docstring>
- <arg name="Candidate"
- type="(usqa{sv})" tp:type="Candidate">
- <tp:docstring>
- The candidate that has been selected.
- </tp:docstring>
- </arg>
- </signal>
-
- <property name="SelectedCandidate"
- tp:name-for-bindings="Selected_Candidate"
- type="(usqa{sv})" tp:type="Candidate" access="read">
- <tp:docstring>
- The candidate that has been selected for use to stream packets
- to the remote contact. Change notification is given via the
- the <tp:member-ref>CandidateSelected</tp:member-ref> signal.
- </tp:docstring>
- </property>
-
- <method name="SetSelectedCandidate"
- tp:name-for-bindings="Set_Selected_Candidate">
- <tp:docstring>
- Set the value of
- <tp:member-ref>CandidateSelected</tp:member-ref>.
- </tp:docstring>
- <arg name="Candidate"
- type="(usqa{sv})" tp:type="Candidate" direction="in">
- <tp:docstring>
- The candidate that has been selected.
- </tp:docstring>
- </arg>
- <tp:possible-errors>
- <tp:error name="org.freedesktop.Telepathy.Error.InvalidArgument"/>
- </tp:possible-errors>
- </method>
-
- <property name="StreamState" tp:name-for-bindings="Stream_State"
- type="u" tp:type="Media_Stream_State"
- access="read">
- <tp:docstring>
- The stream state of the endpoint.
- </tp:docstring>
- </property>
-
- <signal name="StreamStateChanged"
- tp:name-for-bindings="Stream_State_Changed">
- <tp:docstring>
- Emitted when the <tp:member-ref>StreamState</tp:member-ref>
- property changes.
- </tp:docstring>
- <arg name="state" type="u" tp:type="Media_Stream_State">
- <tp:docstring>
- The new <tp:member-ref>StreamState</tp:member-ref> value.
- </tp:docstring>
- </arg>
- </signal>
-
- <method name="SetStreamState"
- tp:name-for-bindings="Set_Stream_State">
- <tp:docstring>
- Change the <tp:member-ref>StreamState</tp:member-ref> of the
- endpoint.
- </tp:docstring>
- <arg direction="in" name="State" type="u" tp:type="Media_Stream_State">
- <tp:docstring>
- The requested stream state.
- </tp:docstring>
- </arg>
- <tp:possible-errors>
- <tp:error name="org.freedesktop.Telepathy.Error.InvalidArgument"/>
- <tp:error name="org.freedesktop.Telepathy.Error.NotAvailable"/>
- </tp:possible-errors>
- </method>
-
- <property name="Transport" tp:name-for-bindings="Transport"
- type="u" tp:type="Stream_Transport_Type" access="read">
- <tp:docstring>
- The transport type for the stream endpoint.
- </tp:docstring>
- </property>
-
- </interface>
-</node>
-<!-- vim:set sw=2 sts=2 et ft=xml: -->
diff --git a/extensions/Call_Stream_Interface_Media.xml b/extensions/Call_Stream_Interface_Media.xml
deleted file mode 100644
index 9e62c87..0000000
--- a/extensions/Call_Stream_Interface_Media.xml
+++ /dev/null
@@ -1,447 +0,0 @@
-<?xml version="1.0" ?>
-<node name="/Call_Stream_Interface_Media"
- xmlns:tp="http://telepathy.freedesktop.org/wiki/DbusSpec#extensions-v0">
- <tp:copyright>Copyright © 2009-2010 Collabora Ltd.</tp:copyright>
- <tp:copyright>Copyright © 2009-2010 Nokia Corporation</tp:copyright>
- <tp:license xmlns="http://www.w3.org/1999/xhtml">
- <p>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.</p>
-
- <p>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.</p>
-
- <p>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 Street, Fifth Floor, Boston, MA
- 02110-1301, USA.</p>
- </tp:license>
-
- <interface name="org.freedesktop.Telepathy.Call.Stream.Interface.Media.DRAFT"
- tp:causes-havoc="experimental">
- <tp:added version="0.19.0">(draft 1)</tp:added>
- <tp:requires interface="org.freedesktop.Telepathy.Call.Stream.DRAFT"/>
-
- <tp:docstring xmlns="http://www.w3.org/1999/xhtml">
- [FIXME]
-
- <h4>ICE restarts</h4>
-
- <p>If the <tp:dbus-ref
- namespace="ofdT.Call.Stream.Endpoint.DRAFT">RemoteCredentialsSet</tp:dbus-ref>
- signal is fired during a call once it has been called before
- whilst setting up the call for initial use, and the
- credentials have changed, then there has been an ICE
- restart. In such a case, the CM SHOULD also empty the remote
- candidate list in the <tp:dbus-ref
- namespace="ofdT.Call.Stream">Endpoint.DRAFT</tp:dbus-ref>.</p>
-
- <p>If the CM does an ICE restart, then the
- <tp:member-ref>PleaseRestartICE</tp:member-ref> signal is
- emitted and the streaming implementation should then call
- <tp:member-ref>SetCredentials</tp:member-ref> again.</p>
-
- <p>For more information on ICE restarts see
- <a href="http://tools.ietf.org/html/rfc5245#section-9.1.1.1">RFC 5245
- section 9.1.1.1</a></p>
- </tp:docstring>
-
- <method name="SetCredentials" tp:name-for-bindings="Set_Credentials">
- <tp:docstring xmlns="http://www.w3.org/1999/xhtml">
- <p>Used to set the username fragment and password for streams that have
- global credentials.</p>
- </tp:docstring>
- <arg name="Username" type="s" direction="in">
- <tp:docstring>
- The username to use when authenticating on the stream.
- </tp:docstring>
- </arg>
- <arg name="Password" type="s" direction="in">
- <tp:docstring>
- The password to use when authenticating on the stream.
- </tp:docstring>
- </arg>
- </method>
-
- <tp:mapping name="Candidate_Info">
- <tp:docstring xmlns="http://www.w3.org/1999/xhtml">
- <p>Extra information about the candidate. Allowed and mandatory keys
- depend on the transport protocol used. The following keys are commenly
- used:</p>
-
- <dl>
- <dt>Type (u)</dt>
- <dd>type of candidate (host, srflx, prflx, relay)</dd>
-
- <dt>Foundation (s)</dt>
- <dd>the foundation of this candiate</dd>
-
- <dt>Protocol (u) </dt>
- <dd>Underlying protocol of the candidate (udp, tcp) </dd>
-
- <dt>Priority (u) </dt>
- <dd>Priority of the candidate </dd>
-
- <dt>BaseIP (u) </dt>
- <dd>Base IP of this candidate </dd>
-
- <dt>Username (s) </dt>
- <dd>Username of this candidate
- (only if credentials are per candidate)</dd>
-
- <dt>Password (s) </dt>
- <dd>Password of this candidate
- (only if credentials are per candidate)</dd>
-
- <dt>RawUDPFallback (b) </dt>
- <dd>Indicate whether this candidate may be used to provide a UDP
- fallback</dd>
- </dl>
- </tp:docstring>
- <tp:member name="Key" type="s">
- <tp:docstring>One of the well-known keys documented here, or an
- implementation-specific key.</tp:docstring>
- </tp:member>
- <tp:member name="Value" type="v">
- <tp:docstring>The value corresponding to that key.</tp:docstring>
- </tp:member>
- </tp:mapping>
-
- <tp:struct name="Candidate" array-name="Candidate_List">
- <tp:docstring>A Stream Candidate.</tp:docstring>
- <tp:member name="Component" type="u">
- <tp:docstring>The component number.</tp:docstring>
- </tp:member>
- <tp:member name="IP" type="s">
- <tp:docstring>The IP address to use.</tp:docstring>
- </tp:member>
- <tp:member name="Port" type="q">
- <tp:docstring>The port number to use.</tp:docstring>
- </tp:member>
- <tp:member name="Info" type="a{sv}" tp:type="Candidate_Info">
- <tp:docstring>Additional information about the candidate.</tp:docstring>
- </tp:member>
- </tp:struct>
-
- <method name="AddCandidates" tp:name-for-bindings="Add_Candidates">
- <tp:docstring>
- Add candidates to the
- <tp:member-ref>LocalCandidates</tp:member-ref> property and
- signal them to the remote contact(s).
- </tp:docstring>
- <arg name="Candidates" direction="in"
- type="a(usqa{sv})" tp:type="Candidate[]">
- <tp:docstring>
- The candidates to be added.
- </tp:docstring>
- </arg>
- </method>
-
- <method name="CandidatesPrepared"
- tp:name-for-bindings="Candidates_Prepared">
- <tp:docstring>
- This indicates to the CM that the initial batch of candidates
- has been added.
- </tp:docstring>
- </method>
-
- <tp:enum type="u" name="Stream_Transport_Type">
- <tp:changed version="0.21.2">WLM_8_5 was removed</tp:changed>
- <tp:docstring xmlns="http://www.w3.org/1999/xhtml">
- A transport that can be used for streaming.
- </tp:docstring>
- <tp:enumvalue suffix="Unknown" value="0">
- <tp:docstring>
- The stream transport type is unknown or not applicable
- (for streams that do not have a configurable transport).
- </tp:docstring>
- </tp:enumvalue>
- <tp:enumvalue suffix="Raw_UDP" value="1">
- <tp:docstring>
- Raw UDP, with or without STUN. All streaming clients are assumed to
- support this transport, so there is no handler capability token for
- it in the <tp:dbus-ref namespace="ofdT.Channel.Type"
- >Call.DRAFT</tp:dbus-ref> interface.
- [This corresponds to "none" or "stun" in the old Media.StreamHandler
- interface.]
- </tp:docstring>
- </tp:enumvalue>
- <tp:enumvalue suffix="ICE" value="2">
- <tp:docstring>
- Interactive Connectivity Establishment, as defined by RFC
- 5245. Note that this value covers ICE-UDP only.
- [This corresponds to "ice-udp" in the old
- Media.StreamHandler interface.]
- </tp:docstring>
- </tp:enumvalue>
- <tp:enumvalue suffix="GTalk_P2P" value="3">
- <tp:docstring>
- Google Talk peer-to-peer connectivity establishment, as implemented
- by libjingle 0.3.
- [This corresponds to "gtalk-p2p" in the old Media.StreamHandler
- interface.]
- </tp:docstring>
- </tp:enumvalue>
- <tp:enumvalue suffix="WLM_2009" value="4">
- <tp:docstring>
- The transport used by Windows Live Messenger 2009 or later, which
- resembles ICE draft 19.
- [This corresponds to "wlm-2009" in the old Media.StreamHandler
- interface.]
- </tp:docstring>
- </tp:enumvalue>
- <tp:enumvalue suffix="SHM" value="5">
- <tp:added version="0.21.2"/>
- <tp:docstring>
- Shared memory transport, as implemented by the GStreamer
- shmsrc and shmsink plugins.
- </tp:docstring>
- </tp:enumvalue>
- <tp:enumvalue suffix="Multicast" value="6">
- <tp:added version="0.21.5"/>
- <tp:docstring>
- Multicast transport.
- </tp:docstring>
- </tp:enumvalue>
- </tp:enum>
-
- <property name="Transport" tp:name-for-bindings="Transport"
- type="u" tp:type="Stream_Transport_Type" access="read" tp:immutable="yes">
- <tp:docstring>
- The transport for this stream.
- </tp:docstring>
- </property>
-
- <property name="LocalCandidates" tp:name-for-bindings="Local_Candidates"
- type="a(usqa{sv})" tp:type="Candidate[]" access="read">
- <tp:docstring>
- [FIXME]. Change notification is via the
- <tp:member-ref>LocalCandidatesAdded</tp:member-ref> signal.
- </tp:docstring>
- </property>
-
- <signal name="LocalCandidatesAdded"
- tp:name-for-bindings="Local_Candidates_Added">
- <tp:docstring>
- Emitted when local candidates are added to the
- <tp:member-ref>LocalCandidates</tp:member-ref> property.
- </tp:docstring>
- <arg name="Candidates" type="a(usqa{sv})" tp:type="Candidate[]">
- <tp:docstring>
- Candidates that have been added.
- </tp:docstring>
- </arg>
- </signal>
-
- <tp:struct name="Stream_Credentials">
- <tp:docstring>A username and password pair.</tp:docstring>
-
- <tp:member name="Username" type="s">
- <tp:docstring>The username.</tp:docstring>
- </tp:member>
-
- <tp:member name="Password" type="s">
- <tp:docstring>The password.</tp:docstring>
- </tp:member>
- </tp:struct>
-
- <property name="LocalCredentials" tp:name-for-bindings="Local_Credentials"
- type="(ss)" tp:type="Stream_Credentials" access="read">
- <tp:docstring>
- [FIXME]. Change notification is via the
- <tp:member-ref>LocalCredentialsChanged</tp:member-ref> signal.
- </tp:docstring>
- </property>
-
- <signal name="LocalCredentialsChanged"
- tp:name-for-bindings="Local_Credentials_Changed">
- <tp:changed version="0.21.2">renamed from LocalCredentailsSet</tp:changed>
- <tp:docstring>
- Emitted when the value of
- <tp:member-ref>LocalCredentials</tp:member-ref> changes.
- </tp:docstring>
- <arg name="Username" type="s" />
- <arg name="Password" type="s" />
- </signal>
-
- <signal name="RelayInfoChanged"
- tp:name-for-bindings="Relay_Info_Changed">
- <tp:docstring>
- Emitted when the value of
- <tp:member-ref>RelayInfo</tp:member-ref> changes.
- </tp:docstring>
- <arg name="Relay_Info" type="aa{sv}" tp:type="String_Variant_Map[]" />
- </signal>
-
- <signal name="STUNServersChanged"
- tp:name-for-bindings="STUN_Servers_Changed">
- <tp:docstring>
- Emitted when the value of
- <tp:member-ref>STUNServers</tp:member-ref> changes.
- </tp:docstring>
- <arg name="Servers" type="a(sq)" tp:type="Socket_Address_IP[]" />
- </signal>
-
- <property name="STUNServers" tp:name-for-bindings="STUN_Servers"
- type="a(sq)" tp:type="Socket_Address_IP[]" access="read">
- <tp:docstring xmlns="http://www.w3.org/1999/xhtml">
- <p>The IP addresses of possible STUN servers to use for NAT
- traversal, as dotted-quad IPv4 address literals or RFC2373
- IPv6 address literals. Change notification is via the
- <tp:member-ref>STUNServersChanged</tp:member-ref>
- signal. The IP addresses MUST NOT be given as DNS hostnames.</p>
-
- <tp:rationale>
- High-quality connection managers already need an asynchronous
- DNS resolver, so they might as well resolve this name to an IP
- to make life easier for streaming implementations.
- </tp:rationale>
- </tp:docstring>
- </property>
-
- <property name="RelayInfo" type="aa{sv}" access="read"
- tp:type="String_Variant_Map[]" tp:name-for-bindings="Relay_Info">
- <tp:docstring xmlns="http://www.w3.org/1999/xhtml">
- <p>A list of mappings describing TURN or Google relay servers
- available for the client to use in its candidate gathering, as
- determined from the protocol. Map keys are:</p>
-
- <dl>
- <dt><code>ip</code> - s</dt>
- <dd>The IP address of the relay server as a dotted-quad IPv4
- address literal or an RFC2373 IPv6 address literal. This MUST NOT
- be a DNS hostname.
-
- <tp:rationale>
- High-quality connection managers already need an asynchronous
- DNS resolver, so they might as well resolve this name to an IP
- and make life easier for streaming implementations.
- </tp:rationale>
- </dd>
-
- <dt><code>type</code> - s</dt>
- <dd>
- <p>Either <code>udp</code> for UDP (UDP MUST be assumed if this
- key is omitted), <code>tcp</code> for TCP, or
- <code>tls</code>.</p>
-
- <p>The precise meaning of this key depends on the
- <tp:member-ref>Transport</tp:member-ref> property: if
- Transport is ICE, <code>tls</code> means
- TLS over TCP as referenced by ICE draft 19, and if
- Transport is GTalk_P2P, <code>tls</code> means
- a fake SSL session over TCP as implemented by libjingle.</p>
- </dd>
-
- <dt><code>port</code> - q</dt>
- <dd>The UDP or TCP port of the relay server as an ASCII unsigned
- integer</dd>
-
- <dt><code>username</code> - s</dt>
- <dd>The username to use</dd>
-
- <dt><code>password</code> - s</dt>
- <dd>The password to use</dd>
-
- <dt><code>component</code> - u</dt>
- <dd>The component number to use this relay server for, as an
- ASCII unsigned integer; if not included, this relay server
- may be used for any or all components.
-
- <tp:rationale>
- In ICE draft 6, as used by Google Talk, credentials are only
- valid once, so each component needs relaying separately.
- </tp:rationale>
- </dd>
- </dl>
-
- <tp:rationale>
- <p>An equivalent of the gtalk-p2p-relay-token property on
- MediaSignalling channels is not included here. The connection
- manager should be responsible for making the necessary HTTP
- requests to turn the token into a username and password.</p>
- </tp:rationale>
-
- <p>The type of relay server that this represents depends on
- the value of the <tp:member-ref>Transport</tp:member-ref>
- property. If Transport is ICE, this is a TURN server;
- if Transport is GTalk_P2P, this is a Google relay server;
- otherwise, the meaning of RelayInfo is undefined.</p>
-
- <p>If relaying is not possible for this stream, the list is
- empty.</p>
-
- <p>Change notification is given via the
- <tp:member-ref>RelayInfoChanged</tp:member-ref> signal.</p>
- </tp:docstring>
- </property>
-
- <signal name="ServerInfoRetrieved"
- tp:name-for-bindings="Server_Info_Retrieved">
- <tp:docstring xmlns="http://www.w3.org/1999/xhtml">
- <p>Signals that the initial information about STUN and Relay servers
- has been retrieved, i.e. the
- <tp:member-ref>HasServerInfo</tp:member-ref> property is
- now true.</p>
- </tp:docstring>
- </signal>
-
- <property name="HasServerInfo" type="b"
- tp:name-for-bindings="Has_Server_Info" access="read">
- <tp:docstring xmlns="http://www.w3.org/1999/xhtml">
- <p>True if all the initial information about STUN servers and Relay
- servers has been retrieved. Change notification is via the
- <tp:member-ref>ServerInfoRetrieved</tp:member-ref> signal.</p>
-
- <tp:rationale>
- Streaming implementations that can't cope with STUN and
- relay servers being added later SHOULD wait for this
- property to become true before proceeding.
- </tp:rationale>
- </tp:docstring>
- </property>
-
- <signal name="EndpointsChanged"
- tp:name-for-bindings="Endpoints_Changed">
- <tp:docstring>
- Emitted when the <tp:member-ref>Endpoints</tp:member-ref> property
- changes.
- </tp:docstring>
- <arg name="Endpoints_Added" type="ao">
- <tp:docstring>
- Endpoints that were added.
- </tp:docstring>
- </arg>
- <arg name="Endpoints_Removed" type="ao">
- <tp:docstring>
- Endpoints that no longer exist.
- </tp:docstring>
- </arg>
- </signal>
-
- <property name="Endpoints" tp:name-for-bindings="Endpoints"
- type="ao" access="read">
- <tp:docstring>
- <p>The list of <tp:dbus-ref namespace="ofdT.Call.Stream"
- >Endpoint.DRAFT</tp:dbus-ref> objects that exist for this
- stream.</p>
-
- <p>Change notification is via the
- <tp:member-ref>EndpointsChanged</tp:member-ref> signal.</p>
- </tp:docstring>
- </property>
-
- <signal name="PleaseRestartICE"
- tp:name-for-bindings="Please_Restart_ICE">
- <tp:docstring>
- Emitted when the CM does an ICE restart to notify the
- streaming implementation that it should call
- <tp:member-ref>SetCredentials</tp:member-ref> again.
- </tp:docstring>
- </signal>
- </interface>
-</node>
-<!-- vim:set sw=2 sts=2 et ft=xml: -->
diff --git a/extensions/Channel_Type_Call.xml b/extensions/Channel_Type_Call.xml
deleted file mode 100644
index 045d416..0000000
--- a/extensions/Channel_Type_Call.xml
+++ /dev/null
@@ -1,1429 +0,0 @@
-<?xml version="1.0" ?>
-<node name="/Channel_Type_Call" xmlns:tp="http://telepathy.freedesktop.org/wiki/DbusSpec#extensions-v0">
- <tp:copyright>Copyright © 2009-2010 Collabora Limited</tp:copyright>
- <tp:copyright>Copyright © 2009-2010 Nokia Corporation</tp:copyright>
- <tp:license>
- 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 Street, Fifth Floor, Boston, MA 02110-1301, USA.
- </tp:license>
- <interface name="org.freedesktop.Telepathy.Channel.Type.Call.DRAFT"
- tp:causes-havoc="experimental">
- <tp:added version="0.19.0">(draft 1)</tp:added>
-
- <tp:requires interface="org.freedesktop.Telepathy.Channel"/>
- <tp:docstring xmlns="http://www.w3.org/1999/xhtml">
- <p>A channel type for making audio and video calls. Call
- channels supersede the old <tp:dbus-ref
- namespace="ofdT.Channel.Type">StreamedMedia</tp:dbus-ref>
- channel type. Call channels are much more flexible than its
- predecessor and allow more than two participants.</p>
-
- <p>Handlers are advised against executing all the media
- signalling, codec and candidate negotiation themselves but
- instead use a helper library such as <a
- href="http://telepathy.freedesktop.org/doc/telepathy-farstream/">telepathy-farstream</a>
- which when given a new Call channel will set up the
- transports and codecs and create GStreamer pads which
- can be added to the handler UI. This is useful as it means
- the handler does not have to worry how exactly the
- connection between the call participants is being made.</p>
-
- <p>The <tp:dbus-ref
- namespace="ofdT.Channel">TargetHandle</tp:dbus-ref> and
- <tp:dbus-ref namespace="ofdT.Channel">TargetID</tp:dbus-ref>
- properties in a Call channel refer to the contact that the
- user initially called, or which contact initially called the
- user. Even in a conference call, where there are multiple
- contacts in the call, these properties refer to the
- initial contact, who might have left the conference since
- then. As a result, handlers should not rely on these
- properties.</p>
-
- <h4>Contents</h4>
-
- <p><tp:dbus-ref namespace="ofdT.Call">Content.DRAFT</tp:dbus-ref>
- objects represent the actual media that forms the Call (for
- example an audio content and a video content). Calls always
- have one or more Content objects associated with them. As a
- result, a new Call channel request MUST have either
- <tp:member-ref>InitialAudio</tp:member-ref>=True, or
- <tp:member-ref>InitialVideo</tp:member-ref>=True, or both,
- as the Requestable Channel Classes will document.</p>
-
- <p><tp:dbus-ref
- namespace="ofdT.Call">Content.DRAFT</tp:dbus-ref> objects have
- one or more stream associated with them. More information on
- these streams and how to maniuplate them can be found on the
- <tp:dbus-ref namespace="ofdT.Call">Content.DRAFT</tp:dbus-ref>
- interface page.</p>
-
- <h4>Outgoing calls</h4>
-
- <p>To make an audio-only call to a contact <tt>foo@example.com</tt>
- handlers should call:</p>
-
- <blockquote>
- <pre>
-<tp:dbus-ref namespace="ofdT.Connection.Interface.Requests">CreateChannel</tp:dbus-ref>({
- ...<tp:dbus-ref namespace="ofdT.Channel">ChannelType</tp:dbus-ref>: ...<tp:dbus-ref
- namespace="ofdT.Channel.Type">Call.DRAFT</tp:dbus-ref>,
- ...<tp:dbus-ref namespace="ofdT.Channel">TargetHandleType</tp:dbus-ref>: Contact,
- ...<tp:dbus-ref namespace="ofdT.Channel">TargetID</tp:dbus-ref>: 'foo@example.com',
- ...<tp:member-ref>InitialAudio</tp:member-ref>: True,
-})</pre></blockquote>
-
- <p>As always, <tp:dbus-ref
- namespace="ofdT.Channel">TargetHandle</tp:dbus-ref> may be used
- in place of
- <tp:dbus-ref namespace="ofdT.Channel">TargetID</tp:dbus-ref>
- if the contact's handle is already known. To make an audio
- and video call, the handler should also specify
- <tp:member-ref>InitialVideo</tp:member-ref> The
- connection manager SHOULD return a channel whose immutable
- properties contain the local user as the <tp:dbus-ref
- namespace="ofdT.Channel">InitiatorHandle</tp:dbus-ref>, the
- remote contact as the <tp:dbus-ref
- namespace="ofdT.Channel">TargetHandle</tp:dbus-ref>,
- <tp:dbus-ref namespace="ofdT.Channel">Requested</tp:dbus-ref> =
- <code>True</code> (indicating the call is outgoing).</p>
-
- <p>After a new Call channel is requested, the
- <tp:member-ref>CallState</tp:member-ref> property will be
- <tp:type>Call_State</tp:type>_Pending_Initiator. As the local
- user is the initiator, the call must be accepted by the handler
- by calling the <tp:member-ref>Accept</tp:member-ref> method.
- At this point, <tp:member-ref>CallState</tp:member-ref> changes
- to <tp:type>Call_State</tp:type>_Pending_Receiver which signifies
- that the call is ringing, waiting for the remote contact to
- accept the call. All changes to
- <tp:member-ref>CallState</tp:member-ref> property are signalled
- using the <tp:member-ref>CallStateChanged</tp:member-ref>
- signal.</p>
-
- <p>When the call is accepted by the remote contact, the
- <tp:member-ref>CallStateChanged</tp:member-ref> signal fires
- again to show that <tp:member-ref>CallState</tp:member-ref> =
- <tp:type>Call_State</tp:type>_Accepted.</p>
-
- <p>At this point <a
- href="http://telepathy.freedesktop.org/doc/telepathy-farstream/">telepathy-farstream</a>
- will signal that a pad is available for the handler to show
- in the user interface.</p>
-
- <h5>Missed calls</h5>
-
- <p>If the remote contact does not accept the call in time, then
- the call can be terminated by the server. Note that this only
- happens in some protocols. Most XMPP clients, for example, do
- not do this and rely on the call initiator terminating the call.
- A missed call is shown in a Call channel by the
- <tp:member-ref>CallState</tp:member-ref> property changing to
- <tp:type>Call_State</tp:type>_Ended, and the
- <tp:member-ref>CallStateReason</tp:member-ref> property changing
- to (remote contact,
- <tp:type>Call_State_Change_Reason</tp:type>_No_Answer, "").</p>
-
- <h5>Rejected calls</h5>
-
- <p>If the remote contact decides he or she does not feel like
- talking to the local user, he or she can reject his or her
- incoming call. This will be shown in the Call channel by
- <tp:member-ref>CallState</tp:member-ref> changing to
- <tp:type>Call_State</tp:type>_Ended and the
- <tp:member-ref>CallStateReason</tp:member-ref> property
- changing to (remote contact,
- <tp:type>Call_State</tp:type>_Change_Reason_User_Requested,
- "org.freedesktop.Telepathy.Error.Rejected").</p>
-
- <h4>Incoming calls</h4>
-
- <p>When an incoming call occurs, something like the following
- <tp:dbus-ref
- namespace="ofdT.Connection.Interface.Requests">NewChannels</tp:dbus-ref>
- signal will occur:</p>
-
- <blockquote>
- <pre>
-<tp:dbus-ref namespace="ofdT.Connection.Interface.Requests">NewChannels</tp:dbus-ref>([
- /org/freedesktop/Telepathy/Connection/foo/bar/foo_40bar_2ecom/CallChannel,
- {
- ...<tp:dbus-ref namespace="ofdT.Channel">ChannelType</tp:dbus-ref>: ...<tp:dbus-ref
- namespace="ofdT.Channel.Type">Call.DRAFT</tp:dbus-ref>,
- ...<tp:dbus-ref namespace="ofdT.Channel">TargetHandleType</tp:dbus-ref>: Contact,
- ...<tp:dbus-ref namespace="ofdT.Channel">TargetID</tp:dbus-ref>: 'foo@example.com',
- ...<tp:dbus-ref namespace="ofdT.Channel">TargetHandle</tp:dbus-ref>: 42,
- ...<tp:dbus-ref namespace="ofdT.Channel">Requested</tp:dbus-ref>: False,
- ...<tp:member-ref>InitialAudio</tp:member-ref>: True,
- ...<tp:member-ref>InitialVideo</tp:member-ref>: True,
- ...<tp:member-ref>InitialAudioName</tp:member-ref>: "audio",
- ...<tp:member-ref>InitialVideoName</tp:member-ref>: "video",
- ...<tp:member-ref>MutableContents</tp:member-ref>: True,
- }])</pre></blockquote>
-
- <p>The <tp:member-ref>InitialAudio</tp:member-ref> and
- <tp:member-ref>InitialVideo</tp:member-ref> properties show that
- the call has been started with two contents: one for audio
- streaming and one for video streaming. The
- <tp:member-ref>InitialAudioName</tp:member-ref> and
- <tp:member-ref>InitialVideoName</tp:member-ref> properties also
- show that the aforementioned audio and video contents have names
- "audio" and "video".</p>
-
- <p>Once the handler has notified the local user that there is an
- incoming call waiting for acceptance, the handler should call
- <tp:member-ref>SetRinging</tp:member-ref> to let the CM know.
- The new channel should also be given to telepathy-farstream to
- work out how the two participants will connect together.
- telepathy-farstream will call the appropriate methods on the call's
- <tp:dbus-ref namespace="ofdT.Call">Content.DRAFT</tp:dbus-ref>s
- to negotiate codecs and transports.</p>
-
- <p>To pick up the call, the handler should call
- <tp:member-ref>Accept</tp:member-ref>. The
- <tp:member-ref>CallState</tp:member-ref> property changes to
- <tp:type>Call_State</tp:type>_Accepted and once media is
- being transferred, telepathy-farstream will notify the
- handler of a new pad to be shown to the local user in the
- UI</p>
-
- <p>To reject the call, the handler should call the
- <tp:member-ref>Hangup</tp:member-ref> method. The
- <tp:member-ref>CallState</tp:member-ref> property will change to
- <tp:type>Call_State</tp:type>_Ended and the
- <tp:member-ref>CallStateReason</tp:member-ref> property will
- change to (self handle,
- <tp:type>Call_State_Change_Reason</tp:type>_User_Requested,
- "org.freedesktop.Telepathy.Error.Rejected").</p>
-
- <h4>Ongoing calls</h4>
-
- <h5>Adding and removing contents</h5>
-
- <p>When a call is open, new contents can be added as long as the
- CM supports it. The
- <tp:member-ref>MutableContents</tp:member-ref> property will let
- the handler know whether further contents can be added or
- existing contents removed. An example of this is starting a
- voice call between a contact and then adding a video content.
- To do this, the should call
- <tp:member-ref>AddContent</tp:member-ref> like this:</p>
-
- <blockquote>
- <pre><tp:member-ref>AddContent</tp:member-ref>("video",
- <tp:type>Media_Stream_Type</tp:type>_Video)</pre>
- </blockquote>
-
- <p>Assuming no errors, the new video content will be added to
- the call. telepathy-farstream will pick up the new content and
- perform the transport and codec negotiation automatically.
- telpathy-farstream will signal when the video is ready to
- show in the handler's user interface.</p>
-
- <p>A similar method is used for removing contents from a call,
- except that the <tp:dbus-ref
- namespace="ofdT.Call.Content.DRAFT">Remove</tp:dbus-ref> method
- is on the <tp:dbus-ref
- namespace="ofdT.Call">Content.DRAFT</tp:dbus-ref> object.</p>
-
- <h5>Ending the call</h5>
-
- <p>To end the call, the handler should call the
- <tp:member-ref>Hangup</tp:member-ref> method. The
- <tp:member-ref>CallState</tp:member-ref> property will change to
- <tp:type>Call_State</tp:type>_Ended and
- <tp:member-ref>CallStateReason</tp:member-ref> will change
- to (self handle,
- <tp:type>Call_State_Change_Reason</tp:type>_User_Requested,
- "org.freedesktop.Telepathy.Error.Cancelled").</p>
-
- <p>If the other participant hangs up first then the
- <tp:member-ref>CallState</tp:member-ref> property will change to
- <tp:type>Call_State</tp:type>_Ended and
- <tp:member-ref>CallStateReason</tp:member-ref> will change
- to (remote contact,
- <tp:type>Call_State_Change_Reason</tp:type>_User_Requested,
- "org.freedesktop.Telepathy.Error.Terminated").</p>
-
- <h4>Multi-party calls</h4>
-
- [TODO]
-
- <h4>Call states</h4>
-
- <p>There are many combinations of the
- <tp:member-ref>CallState</tp:member-ref> and
- <tp:member-ref>CallStateReason</tp:member-ref> properties which
- mean different things. Here is a table to try to make these
- meanings clearer:</p>
-
- <table>
- <tr>
- <th rowspan="2"><tp:dbus-ref namespace="ofdT.Channel">Requested</tp:dbus-ref></th>
- <th rowspan="2"><tp:member-ref>CallState</tp:member-ref></th>
- <th colspan="3"><tp:member-ref>CallStateReason</tp:member-ref></th>
- <th rowspan="2">Meaning</th>
- </tr>
- <tr>
- <th>Actor</th>
- <th>Reason</th>
- <th>DBus_Reason</th>
- </tr>
- <!-- Pending_Initiator -->
- <tr>
- <td>True</td>
- <td><tp:type>Call_State</tp:type>_Pending_Initiator</td>
- <td>Self handle</td>
- <td><tp:type>Call_State_Change_Reason</tp:type>_User_Requested</td>
- <td>""</td>
- <td>The outgoing call channel is waiting for the local user to call <tp:member-ref>Accept</tp:member-ref>.</td>
- </tr>
- <!-- Pending_Receiver -->
- <tr>
- <td>True</td>
- <td><tp:type>Call_State</tp:type>_Pending_Receiver</td>
- <td>Self handle</td>
- <td><tp:type>Call_State_Change_Reason</tp:type>_User_Requested</td>
- <td>""</td>
- <td>The outgoing call is waiting for the remote contact to pick up the call.</td>
- </tr>
- <tr>
- <td>False</td>
- <td><tp:type>Call_State</tp:type>_Pending_Receiver</td>
- <td>0</td>
- <td><tp:type>Call_State_Change_Reason</tp:type>_Unknown</td>
- <td>""</td>
- <td>The incoming call is waiting for the local user to call <tp:member-ref>Accept</tp:member-ref> on the call.</td>
- </tr>
- <!-- Accepted -->
- <tr>
- <td>True</td>
- <td><tp:type>Call_State</tp:type>_Accepted</td>
- <td>Remote contact handle</td>
- <td><tp:type>Call_State_Change_Reason</tp:type>_User_Requested</td>
- <td>""</td>
- <td>The remote contact accepted the outgoing call.</td>
- </tr>
- <tr>
- <td>False</td>
- <td><tp:type>Call_State</tp:type>_Accepted</td>
- <td>Self handle</td>
- <td><tp:type>Call_State_Change_Reason</tp:type>_User_Requested</td>
- <td>""</td>
- <td>The local user accepted the incoming call.</td>
- </tr>
- <!-- Ended -->
- <tr>
- <td>True or False</td>
- <td><tp:type>Call_State</tp:type>_Ended</td>
- <td>Self handle</td>
- <td><tp:type>Call_State_Change_Reason</tp:type>_User_Requested</td>
- <td><tp:error-ref>Cancelled</tp:error-ref></td>
- <td>The local user hung up the incoming or outgoing call.</td>
- </tr>
- <tr>
- <td>True or False</td>
- <td><tp:type>Call_State</tp:type>_Ended</td>
- <td>Remote contact handle</td>
- <td><tp:type>Call_State_Change_Reason</tp:type>_User_Requested</td>
- <td><tp:error-ref>Terminated</tp:error-ref></td>
- <td>The remote contact hung up the incoming or outgoing call.</td>
- </tr>
- <tr>
- <td>True</td>
- <td><tp:type>Call_State</tp:type>_Ended</td>
- <td>Remote contact handle</td>
- <td><tp:type>Call_State_Change_Reason</tp:type>_No_Answer</td>
- <td>""</td>
- <td>The outgoing call was not picked up and the call ended.</td>
- </tr>
- <tr>
- <td>False</td>
- <td><tp:type>Call_State</tp:type>_Ended</td>
- <td>Remote contact handle</td>
- <td><tp:type>Call_State_Change_Reason</tp:type>_User_Requested</td>
- <td><tp:error-ref>PickedUpElsewhere</tp:error-ref></td>
- <td>The incoming call was ended because it was picked up elsewhere.</td>
- </tr>
- </table>
-
- <h4>Requestable channel classes</h4>
-
- <p>The <tp:dbus-ref
- namespace="ofdT.Connection.Interface.Requests">RequestableChannelClasses</tp:dbus-ref>
- for <tp:dbus-ref
- namespace="ofdT.Channel.Type">Call.DRAFT</tp:dbus-ref> channels
- can be:</p>
-
- <blockquote>
- <pre>
-[( Fixed = { ...<tp:dbus-ref namespace="ofdT.Channel">ChannelType</tp:dbus-ref>: ...<tp:dbus-ref namespace="ofdT.Channel.Type">Call.DRAFT</tp:dbus-ref>,
- ...<tp:dbus-ref namespace="ofdT.Channel">TargetHandleType</tp:dbus-ref>: Contact,
- ...<tp:member-ref>InitialVideo</tp:member-ref>: True
- },
- Allowed = [ ...<tp:member-ref>InitialVideoName</tp:member-ref>,
- ...<tp:member-ref>InitialAudio</tp:member-ref>,
- ...<tp:member-ref>InitialAudioName</tp:member-ref>
- ]
-),
-( Fixed = { ...<tp:dbus-ref namespace="ofdT.Channel">ChannelType</tp:dbus-ref>: ...<tp:dbus-ref namespace="ofdT.Channel.Type">Call.DRAFT</tp:dbus-ref>,
- ...<tp:dbus-ref namespace="ofdT.Channel">TargetHandleType</tp:dbus-ref>: Contact,
- ...<tp:member-ref>InitialAudio</tp:member-ref>: True
- },
- Allowed = [ ...<tp:member-ref>InitialAudioName</tp:member-ref>,
- ...<tp:member-ref>InitialVideo</tp:member-ref>,
- ...<tp:member-ref>InitialVideoName</tp:member-ref>
- ]
-)]</pre></blockquote>
-
- <p>Clients aren't allowed to make outgoing calls that have
- neither initial audio nor initial video. Clearly, CMs
- which don't support video should leave out the first class and
- omit <tp:member-ref>InitialVideo</tp:member-ref> from the second
- class, and vice versa for CMs without audio support.</p>
-
- <p>Handlers should not close <tp:dbus-ref
- namespace="ofdT.Channel.Type">Call.DRAFT</tp:dbus-ref> channels
- without first calling <tp:member-ref>Hangup</tp:member-ref> on
- the channel. If a Call handler crashes, the <tp:dbus-ref
- namespace="ofdT">ChannelDispatcher</tp:dbus-ref> will call
- <tp:dbus-ref namespace="ofdT.Channel">Close</tp:dbus-ref> on the
- channel which SHOULD also imply a call to
- <tp:member-ref>Hangup</tp:member-ref>(<tp:type>Call_State_Change_Reason</tp:type>_User_Requested,
- "org.freedesktop.Telepathy.Error.Terminated", "") before
- actually closing the channel.</p>
-
- </tp:docstring>
-
- <method name="SetRinging" tp:name-for-bindings="Set_Ringing">
- <tp:changed version="0.21.2">renamed from Ringing</tp:changed>
- <tp:docstring xmlns="http://www.w3.org/1999/xhtml">
- <p>Indicate that the local user has been alerted about the incoming
- call.</p>
-
- <p>This method is only useful if the
- channel's <tp:dbus-ref namespace="ofdT.Channel">Requested</tp:dbus-ref>
- property is False, and
- the <tp:member-ref>CallState</tp:member-ref> is
- <tp:type>Call_State</tp:type>_Pending_Receiver (an incoming
- call waiting on the local user to pick up). While this is
- the case, this method SHOULD change the
- <tp:member-ref>CallFlags</tp:member-ref> to include
- <tp:type>Call_Flags</tp:type>_Locally_Ringing, and notify the
- remote contact that the local user has been alerted (if the
- protocol implements this); repeated calls to this method
- SHOULD succeed, but have no further effect.</p>
-
- <p>In all other states, this method SHOULD fail with the error
- NotAvailable.</p>
- </tp:docstring>
-
- <tp:possible-errors>
- <tp:error name="org.freedesktop.Telepathy.Error.InvalidArgument">
- <tp:docstring>
- The call was <tp:dbus-ref namespace="ofdT.Channel"
- >Requested</tp:dbus-ref>, so ringing does not make sense.
- </tp:docstring>
- </tp:error>
- <tp:error name="org.freedesktop.Telepathy.Error.NotAvailable">
- <tp:docstring>
- The call is no longer in state
- <tp:type>Call_State</tp:type>_Pending_Receiver.
- </tp:docstring>
- </tp:error>
- </tp:possible-errors>
- </method>
-
- <method name="Accept" tp:name-for-bindings="Accept">
- <tp:docstring xmlns="http://www.w3.org/1999/xhtml">
- <p>For incoming calls in state
- <tp:type>Call_State</tp:type>_Pending_Receiver, accept the
- incoming call; this changes the
- <tp:member-ref>CallState</tp:member-ref> to
- <tp:type>Call_State</tp:type>_Accepted.</p>
-
- <p>For outgoing calls in state
- <tp:type>Call_State</tp:type>_Pending_Initiator, actually
- call the remote contact; this changes the
- <tp:member-ref>CallState</tp:member-ref> to
- <tp:type>Call_State</tp:type>_Pending_Receiver.</p>
-
- <p>Otherwise, this method SHOULD fail with the error NotAvailable.</p>
-
- <p>This method should be called exactly once per Call, by whatever
- client (user interface) is handling the channel.</p>
-
- <p>When this method is called, for each <tp:dbus-ref
- namespace="ofdT.Call" >Content.DRAFT</tp:dbus-ref> whose
- <tp:dbus-ref namespace="ofdT.Call.Content.DRAFT"
- >Disposition</tp:dbus-ref> is
- <tp:type>Call_Content_Disposition</tp:type>_Initial, any
- streams where the <tp:dbus-ref
- namespace="ofdT.Call.Stream.DRAFT">LocalSendingState</tp:dbus-ref>
- is <tp:type>Sending_State</tp:type>_Pending_Send will be
- moved to <tp:type>Sending_State</tp:type>_Sending as if
- <tp:dbus-ref namespace="ofdT.Call.Stream.DRAFT"
- >SetSending</tp:dbus-ref>(True) had been called.</p>
- </tp:docstring>
-
- <tp:possible-errors>
- <tp:error name="org.freedesktop.Telepathy.Error.NotAvailable">
- <tp:docstring>
- The call is not in one of the states where this method makes sense.
- </tp:docstring>
- </tp:error>
- </tp:possible-errors>
- </method>
-
- <method name="Hangup" tp:name-for-bindings="Hangup">
- <tp:docstring>
- Request that the call is ended. All contents will be removed
- from the Call so that the
- <tp:member-ref>Contents</tp:member-ref> property will be the
- empty list.
- </tp:docstring>
-
- <arg direction="in" name="Reason"
- type="u" tp:type="Call_State_Change_Reason">
- <tp:docstring>
- A generic hangup reason.
- </tp:docstring>
- </arg>
-
- <arg direction="in" name="Detailed_Hangup_Reason"
- type="s" tp:type="DBus_Error_Name">
- <tp:docstring>
- A more specific reason for the call hangup, if one is available, or
- an empty string otherwise.
- </tp:docstring>
- </arg>
-
- <arg direction="in" name="Message" type="s">
- <tp:docstring>
- A human-readable message to be sent to the remote contact(s).
-
- <tp:rationale>
- XMPP Jingle allows calls to be terminated with a human-readable
- message.
- </tp:rationale>
- </tp:docstring>
- </arg>
-
- <tp:possible-errors>
- <tp:error name="org.freedesktop.Telepathy.Error.NotAvailable">
- <tp:docstring>
- The call has already been ended.
- </tp:docstring>
- </tp:error>
- </tp:possible-errors>
- </method>
-
- <method name="AddContent" tp:name-for-bindings="Add_Content">
- <tp:docstring>
- Request that a new <tp:dbus-ref
- namespace="ofdT.Call">Content.DRAFT</tp:dbus-ref> of type
- Content_Type is added to the Call. Handlers should check the
- value of the <tp:member-ref>MutableContents</tp:member-ref>
- property before trying to add another content as it might not
- be allowed.
- </tp:docstring>
- <arg direction="in" name="Content_Name" type="s">
- <tp:docstring>
- <p>The suggested name of the content to add.</p>
-
- <tp:rationale>
- The content name property should be meaningful, so should
- be given a name which is significant to the user. The name
- could be a localized "audio", "video" or perhaps include
- some string identifying the source, such as a webcam
- identifier.
- </tp:rationale>
-
- <p>If there is already a content with the same name as this
- property then a sensible suffix should be added. For example,
- if this argument is "audio" but a content of the same name
- already exists, a sensible suffix such as " (1)" is appended
- to name the new content "audio (1)". A further content with the
- name "audio" would then be named "audio (2)".</p>
-
- </tp:docstring>
- </arg>
- <arg direction="in" name="Content_Type" type="u"
- tp:type="Media_Stream_Type">
- <tp:docstring>
- The media stream type of the content to be added to the
- call.
- </tp:docstring>
- </arg>
- <arg direction="out" name="Content" type="o">
- <tp:docstring>
- Path to the newly-created <tp:dbus-ref
- namespace="org.freedesktop.Telepathy"
- >Call.Content.DRAFT</tp:dbus-ref> object.
- </tp:docstring>
- </arg>
-
- <tp:possible-errors>
- <tp:error name="org.freedesktop.Telepathy.Error.InvalidArgument">
- <tp:docstring>
- The media stream type given is invalid.
- </tp:docstring>
- </tp:error>
- <tp:error name="org.freedesktop.Telepathy.Error.NotImplemented">
- <tp:docstring>
- The media stream type requested is not implemented by the
- CM.
- </tp:docstring>
- </tp:error>
- <tp:error name="org.freedesktop.Telepathy.Error.NotCapable">
- <tp:docstring>
- The content type requested cannot be added to this
- call. Examples of why this might be the case include
- because a second video stream cannot be added, or a
- content cannot be added when the content set isn't
- mutable.
- </tp:docstring>
- </tp:error>
- </tp:possible-errors>
- </method>
-
- <signal name="ContentAdded"
- tp:name-for-bindings="Content_Added">
- <tp:docstring xmlns="http://www.w3.org/1999/xhtml">
- <p>Emitted when a new <tp:dbus-ref namespace="ofdT.Call"
- >Content.DRAFT</tp:dbus-ref> is added to the call.</p>
- </tp:docstring>
- <arg name="Content" type="o">
- <tp:docstring>
- Path to the newly-created <tp:dbus-ref namespace="ofdT.Call"
- >Content.DRAFT</tp:dbus-ref> object.
- </tp:docstring>
- </arg>
- </signal>
-
- <signal name="ContentRemoved" tp:name-for-bindings="Content_Removed">
- <tp:docstring xmlns="http://www.w3.org/1999/xhtml">
- <p>Emitted when a <tp:dbus-ref namespace="ofdT.Call"
- >Content.DRAFT</tp:dbus-ref> is removed from the call.</p>
- </tp:docstring>
- <arg name="Content" type="o">
- <tp:docstring>
- The <tp:dbus-ref namespace="ofdT.Call"
- >Content.DRAFT</tp:dbus-ref> which was removed.
- </tp:docstring>
- </arg>
- </signal>
-
- <property name="Contents" type="ao" access="read"
- tp:name-for-bindings="Contents">
- <tp:docstring xmlns="http://www.w3.org/1999/xhtml">
- <p>The list of <tp:dbus-ref
- namespace="ofdT.Call">Content.DRAFT</tp:dbus-ref> objects that
- are part of this call. Change notification is via the
- <tp:member-ref>ContentAdded</tp:member-ref> and
- <tp:member-ref>ContentRemoved</tp:member-ref> signals.
- </p>
- </tp:docstring>
- </property>
-
- <tp:enum type="u" name="Call_State">
- <tp:docstring xmlns="http://www.w3.org/1999/xhtml">
- <p>The state of a call, as a whole.</p>
-
- <p>The allowed transitions are:</p>
-
- <ul>
- <li>Pending_Initiator → Pending_Receiver (for outgoing calls,
- when <tp:member-ref>Accept</tp:member-ref> is called)</li>
- <li>Pending_Receiver → Accepted (for incoming calls, when
- <tp:member-ref>Accept</tp:member-ref> is called; for outgoing
- calls to a contact, when the remote contact accepts the call;
- for joining a conference call, when the local user successfully
- joins the conference)</li>
- <li>Accepted → Pending_Receiver (when transferred to another
- contact)</li>
- <li>any state → Ended (when the call is terminated normally, or
- when an error occurs)</li>
- </ul>
-
- <p>Clients MAY consider unknown values from this enum to be an
- error - additional values will not be defined after the Call
- specification is declared to be stable.</p>
- </tp:docstring>
-
- <tp:enumvalue suffix="Unknown" value = "0">
- <tp:docstring>
- The call state is not known. This call state MUST NOT appear as a
- value of the <tp:member-ref>CallState</tp:member-ref> property, but
- MAY be used by client code to represent calls whose state is as yet
- unknown.
- </tp:docstring>
- </tp:enumvalue>
- <tp:enumvalue suffix="Pending_Initiator" value = "1">
- <tp:docstring>
- The initiator of the call hasn't accepted the call yet. This state
- only makes sense for outgoing calls, where it means that the local
- user has not yet sent any signalling messages to the remote user(s),
- and will not do so until <tp:member-ref>Accept</tp:member-ref> is
- called.
- </tp:docstring>
- </tp:enumvalue>
- <tp:enumvalue suffix="Pending_Receiver" value = "2">
- <tp:docstring>
- The receiver (the contact being called) hasn't accepted the call yet.
- </tp:docstring>
- </tp:enumvalue>
- <tp:enumvalue suffix="Accepted" value = "3">
- <tp:docstring>
- The contact being called has accepted the call.
- </tp:docstring>
- </tp:enumvalue>
- <tp:enumvalue suffix="Ended" value = "4">
- <tp:docstring>
- The call has ended, either via normal termination or an error.
- </tp:docstring>
- </tp:enumvalue>
- </tp:enum>
-
- <tp:flags name="Call_Flags" value-prefix="Call_Flag" type="u">
- <tp:docstring>
- A set of flags representing the status of the call as a whole,
- providing more specific information than the
- <tp:member-ref>CallState</tp:member-ref>. Many of these flags only make
- sense in a particular state.
- </tp:docstring>
-
- <tp:flag suffix="Locally_Ringing" value="1">
- <tp:docstring>
- The local contact has been alerted about the call but has not
- responded; if possible, the remote contact(s) have been informed of
- this fact. This flag only makes sense on incoming calls in
- state <tp:type>Call_State</tp:type>_Pending_Receiver. It SHOULD
- be set when <tp:member-ref>SetRinging</tp:member-ref> is
- called successfully, and unset when the state changes.
- </tp:docstring>
- </tp:flag>
-
- <tp:flag suffix="Queued" value="2">
- <tp:docstring>
- The contact is temporarily unavailable, and the call has been placed
- in a queue (e.g. 182 Queued in SIP, or call-waiting in telephony).
- This flag only makes sense on outgoing 1-1 calls in
- state <tp:type>Call_State</tp:type>_Pending_Receiver. It SHOULD be
- set or unset according to informational messages from other
- contacts.
- </tp:docstring>
- </tp:flag>
-
- <tp:flag suffix="Locally_Held" value="4">
- <tp:docstring>
- The call has been put on hold by the local user, e.g. using
- the <tp:dbus-ref namespace="ofdT.Channel.Interface"
- >Hold</tp:dbus-ref> interface. This flag SHOULD only be set
- if there is at least one Content, and all Contents are
- locally held; it makes sense on calls in state
- <tp:type>Call_State</tp:type>_Pending_Receiver
- or <tp:type>Call_State</tp:type>_Accepted.
-
- <tp:rationale>
- Otherwise, in transient situations where some but not all contents
- are on hold, UIs would falsely indicate that the call as a whole
- is on hold, which could lead to the user saying something they'll
- regret, while under the impression that the other contacts can't
- hear them!
- </tp:rationale>
- </tp:docstring>
- </tp:flag>
-
- <tp:flag suffix="Forwarded" value="8">
- <tp:docstring>
- The initiator of the call originally called a contact other than the
- current recipient of the call, but the call was then forwarded or
- diverted. This flag only makes sense on outgoing calls, in state
- <tp:type>Call_State</tp:type>_Pending_Receiver or
- <tp:type>Call_State</tp:type>_Accepted. It SHOULD be set or unset
- according to informational messages from other contacts.
- </tp:docstring>
- </tp:flag>
-
- <tp:flag suffix="In_Progress" value="16">
- <tp:docstring>
- Progress has been made in placing the outgoing call, but the
- contact may not have been made aware of the call yet
- (so the Ringing state is not appropriate). This corresponds to SIP's
- status code 183 Session Progress, and could be used when the
- outgoing call has reached a gateway, for instance.
- This flag only makes sense on outgoing calls in state
- <tp:type>Call_State</tp:type>_Pending_Receiver, and SHOULD be set
- or unset according to informational messages from servers, gateways
- and other infrastructure.
- </tp:docstring>
- </tp:flag>
-
- <tp:flag suffix="Clearing" value="32">
- <tp:docstring>
- This flag only occurs when the CallState is Ended. The call with
- this flag set has ended, but not all resources corresponding to the
- call have been freed yet.
-
- Depending on the protocol there might be some audible feedback while
- the clearing flag is set.
-
- <tp:rationale>
- In calls following the ITU-T Q.931 standard there is a period of
- time between the call ending and the underlying channel being
- completely free for re-use.
- </tp:rationale>
- </tp:docstring>
- </tp:flag>
-
- <tp:flag suffix="Muted" value="64">
- <tp:docstring>
- The call has been muted by the local user, e.g. using the
- <tp:dbus-ref namespace="ofdT.Call.Content.Interface"
- >Mute.DRAFT</tp:dbus-ref> interface. This flag SHOULD only
- be set if there is at least one Content, and all Contents
- are locally muted; it makes sense on calls in state
- <tp:type>Call_State</tp:type>_Pending_Receiver or
- <tp:type>Call_State</tp:type>_Accepted.
- </tp:docstring>
- </tp:flag>
- </tp:flags>
-
- <property name="CallStateDetails"
- tp:name-for-bindings="Call_State_Details" type="a{sv}" access="read">
- <tp:docstring xmlns="http://www.w3.org/1999/xhtml">
- <p>A map used to provide optional extensible details for the
- <tp:member-ref>CallState</tp:member-ref>,
- <tp:member-ref>CallFlags</tp:member-ref> and/or
- <tp:member-ref>CallStateReason</tp:member-ref>.</p>
-
- <p>Well-known keys and their corresponding value types include:</p>
-
- <dl>
- <dt>hangup-message - s</dt>
- <dd>An optional human-readable message sent when the call was ended,
- corresponding to the Message argument to the
- <tp:member-ref>Hangup</tp:member-ref> method. This is only
- applicable when the call state is <tp:type>Call_State</tp:type>_Ended.
- <tp:rationale>
- XMPP Jingle can send such messages.
- </tp:rationale>
- </dd>
-
- <dt>queue-message - s</dt>
- <dd>An optional human-readable message sent when the local contact
- is being held in a queue. This is only applicable when
- <tp:type>Call_Flags</tp:type>_Queued is in the call flags.
- <tp:rationale>
- SIP 182 notifications can have human-readable messages attached.
- </tp:rationale>
- </dd>
-
- <dt>debug-message - s</dt>
- <dd>A message giving further details of any error indicated by the
- <tp:member-ref>CallStateReason</tp:member-ref>. This will not
- normally be localized or suitable for display to users, and is only
- applicable when the call state is
- <tp:type>Call_State</tp:type>_Ended.</dd>
- </dl>
- </tp:docstring>
- </property>
-
- <property name="CallState" type="u" access="read"
- tp:name-for-bindings="Call_State" tp:type="Call_State">
- <tp:docstring xmlns="http://www.w3.org/1999/xhtml">
- <p>The current high-level state of this call. The
- <tp:member-ref>CallFlags</tp:member-ref> provide additional
- information, and the <tp:member-ref>CallStateReason</tp:member-ref>
- and <tp:member-ref>CallStateDetails</tp:member-ref> explain the
- reason for the current values for those properties.</p>
-
- <p>Note that when in a conference call, this property is
- purely to show your state in joining the call. The receiver
- (or remote contact) in this context is the conference server
- itself. The property does not change when other call members'
- states change.</p>
-
- <p>Clients MAY consider unknown values in this property to be an
- error.</p>
- </tp:docstring>
- </property>
-
- <property name="CallFlags" type="u" access="read"
- tp:name-for-bindings="Call_Flags" tp:type="Call_Flags">
- <tp:docstring xmlns="http://www.w3.org/1999/xhtml">
- <p>Flags representing the status of the call as a whole,
- providing more specific information than the
- <tp:member-ref>CallState</tp:member-ref>.</p>
-
- <p>Clients are expected to ignore unknown flags in this property,
- without error.</p>
-
- <p>When an ongoing call is active and not on hold or has any
- other problems, this property will be 0.</p>
- </tp:docstring>
- </property>
-
- <tp:enum name="Call_State_Change_Reason" type="u">
- <tp:docstring>
- A simple representation of the reason for a change in the call's
- state, which may be used by simple clients, or used as a fallback
- when the DBus_Reason member of a <tp:type>Call_State_Reason</tp:type>
- struct is not understood.
- </tp:docstring>
-
- <tp:enumvalue suffix="Unknown" value="0">
- <tp:docstring xmlns="http://www.w3.org/1999/xhtml">
- We just don't know. Unknown values of this enum SHOULD also be
- treated like this.
- </tp:docstring>
- </tp:enumvalue>
-
- <tp:enumvalue suffix="User_Requested" value="1">
- <tp:docstring xmlns="http://www.w3.org/1999/xhtml">
- <p>The change was requested by the contact indicated by the Actor
- member of a <tp:type>Call_State_Reason</tp:type> struct.</p>
-
- <p>If the Actor is the local user, the DBus_Reason SHOULD be the
- empty string.</p>
-
- <p>If the Actor is a remote user, the DBus_Reason SHOULD be the empty
- string if the call was terminated normally, but MAY be a non-empty
- error name to indicate error-like call termination reasons (call
- rejected as busy, kicked from a conference by a moderator, etc.).</p>
- </tp:docstring>
- </tp:enumvalue>
-
- <tp:enumvalue suffix="Forwarded" value="2">
- <tp:docstring xmlns="http://www.w3.org/1999/xhtml">
- <p>The call was forwarded. If known, the handle of the contact
- the call was forwarded to will be indicated by the Actor member
- of a <tp:type>Call_State_Reason</tp:type> struct.</p>
- </tp:docstring>
- </tp:enumvalue>
-
- <tp:enumvalue suffix="No_Answer" value="3">
- <tp:added version="0.21.2"/>
- <tp:docstring xmlns="http://www.w3.org/1999/xhtml">
- <p>The <tp:member-ref>CallState</tp:member-ref> changed from
- <tp:type>Call_State</tp:type>_Pending_Receiver to
- <tp:type>Call_State</tp:type>_Ended because the initiator
- ended the call before the receiver accepted it. With an
- incoming call this state change reason signifies a missed
- call.</p>
- </tp:docstring>
- </tp:enumvalue>
- </tp:enum>
-
- <tp:struct name="Call_State_Reason">
- <tp:docstring xmlns="http://www.w3.org/1999/xhtml">
- <p>A description of the reason for a change to the
- <tp:member-ref>CallState</tp:member-ref> and/or
- <tp:member-ref>CallFlags</tp:member-ref>.</p>
- </tp:docstring>
-
- <tp:member type="u" tp:type="Contact_Handle" name="Actor">
- <tp:docstring>
- The contact responsible for the change, or 0 if no contact was
- responsible.
- </tp:docstring>
- </tp:member>
-
- <tp:member type="u" tp:type="Call_State_Change_Reason" name="Reason">
- <tp:docstring>
- The reason, chosen from a limited set of possibilities defined by
- the Telepathy specification. If
- <tp:type>Call_State_Change_Reason</tp:type>_User_Requested then
- the Actor member will dictate whether it was the local user or
- a remote contact responsible.
- </tp:docstring>
- </tp:member>
-
- <tp:member type="s" tp:type="DBus_Error_Name" name="DBus_Reason">
- <tp:docstring xmlns="http://www.w3.org/1999/xhtml">
- <p>A specific reason for the change, which may be a D-Bus error in
- the Telepathy namespace, a D-Bus error in any other namespace
- (for implementation-specific errors), or the empty string to
- indicate that the state change was not an error.</p>
-
- <p>This SHOULD be an empty string for changes to any state other
- than Ended.</p>
-
- <p>The errors Cancelled and Terminated SHOULD NOT be used here;
- an empty string SHOULD be used instead.</p>
-
- <tp:rationale>
- <p>Those error names are used to indicate normal call
- termination by the local user or another user, respectively,
- in contexts where a D-Bus error name must appear.</p>
- </tp:rationale>
- </tp:docstring>
- </tp:member>
- </tp:struct>
-
- <property name="CallStateReason" tp:name-for-bindings="Call_State_Reason"
- type="(uus)" access="read" tp:type="Call_State_Reason">
- <tp:docstring xmlns="http://www.w3.org/1999/xhtml">
- <p>The reason for the last change to the
- <tp:member-ref>CallState</tp:member-ref> and/or
- <tp:member-ref>CallFlags</tp:member-ref>. The
- <tp:member-ref>CallStateDetails</tp:member-ref> MAY provide additional
- information.</p>
- </tp:docstring>
- </property>
-
- <signal name="CallStateChanged"
- tp:name-for-bindings="Call_State_Changed">
- <tp:docstring xmlns="http://www.w3.org/1999/xhtml">
- <p>Emitted when the state of the call as a whole changes.</p>
-
- <p>This signal is emitted for any change in the properties
- corresponding to its arguments, even if the other properties
- referenced remain unchanged.</p>
- </tp:docstring>
-
- <arg name="Call_State" type="u" tp:type="Call_State">
- <tp:docstring>
- The new value of the <tp:member-ref>CallState</tp:member-ref>
- property.
- </tp:docstring>
- </arg>
-
- <arg name="Call_Flags" type="u" tp:type="Call_Flags">
- <tp:docstring>
- The new value of the <tp:member-ref>CallFlags</tp:member-ref>
- property.
- </tp:docstring>
- </arg>
-
- <arg name="Call_State_Reason" type="(uus)" tp:type="Call_State_Reason">
- <tp:docstring>
- The new value of the <tp:member-ref>CallStateReason</tp:member-ref>
- property.
- </tp:docstring>
- </arg>
-
- <arg name="Call_State_Details" type="a{sv}">
- <tp:docstring>
- The new value of the <tp:member-ref>CallStateDetails</tp:member-ref>
- property.
- </tp:docstring>
- </arg>
- </signal>
-
- <property name="HardwareStreaming" tp:name-for-bindings="Hardware_Streaming"
- type="b" access="read" tp:immutable="yes">
- <tp:docstring xmlns="http://www.w3.org/1999/xhtml">
- <p>If this property is True, all of the media streaming is done by some
- mechanism outside the scope of Telepathy.</p>
-
- <tp:rationale>
- <p>A connection manager might be intended for a specialized hardware
- device, which will take care of the audio streaming (e.g.
- telepathy-yafono, which uses GSM hardware which does the actual
- audio streaming for the call).</p>
- </tp:rationale>
-
- <p>If this is False, the handler is responsible for doing the actual
- media streaming for at least some contents itself. Those contents
- will have the <tp:dbus-ref namespace="ofdT.Call.Content.Interface"
- >Media.DRAFT</tp:dbus-ref> interface, to communicate the necessary
- information to a streaming implementation. Connection managers SHOULD
- operate like this, if possible.</p>
-
- <tp:rationale>
- <p>Many connection managers (such as telepathy-gabble) only do the
- call signalling, and expect the client to do the actual streaming
- using something like
- <a href="http://farsight.freedesktop.org/">Farsight</a>, to improve
- latency and allow better UI integration.</p>
- </tp:rationale>
- </tp:docstring>
- </property>
-
- <tp:flags type="u" name="Call_Member_Flags" value-prefix="Call_Member_Flag">
- <tp:docstring xmlns="http://www.w3.org/1999/xhtml">
- <p>A set of flags representing the status of a remote contact in a
- call.</p>
-
- <p>It is protocol- and client-specific whether a particular contact
- will ever have a particular flag set on them, and Telepathy clients
- SHOULD NOT assume that a flag will ever be set.</p>
-
- <tp:rationale>
- <p>180 Ringing in SIP, and its equivalent in XMPP, are optional
- informational messages, and implementations are not required
- to send them. The same applies to the messages used to indicate
- hold state.</p>
- </tp:rationale>
- </tp:docstring>
-
- <tp:flag suffix="Ringing" value = "1">
- <tp:docstring xmlns="http://www.w3.org/1999/xhtml">
- <p>The remote contact's client has told us that the contact has been
- alerted about the call but has not responded.</p>
-
- <tp:rationale>
- <p>This is a flag per member, not a flag for the call as a whole,
- because in Muji conference calls, you could invite someone and
- have their state be "ringing" for a while.</p>
- </tp:rationale>
- </tp:docstring>
- </tp:flag>
-
- <tp:flag suffix="Held" value = "2">
- <tp:docstring xmlns="http://www.w3.org/1999/xhtml">
- <p>The call member has put this call on hold.</p>
-
- <tp:rationale>
- <p>This is a flag per member, not a flag for the call as a whole,
- because in conference calls, any member could put the conference
- on hold.</p>
- </tp:rationale>
- </tp:docstring>
- </tp:flag>
-
- <tp:flag suffix="Conference_Host" value="4">
- <tp:docstring xmlns="http://www.w3.org/1999/xhtml">
- This contact has merged this call into a conference. Note that GSM
- provides a notification when the remote party merges a call into a
- conference, but not when it is split out again; thus, this flag can
- only indicate that the call has been part of a conference at some
- point. If a GSM connection manager receives a notification that a
- call has been merged into a conference a second time, it SHOULD
- represent this by clearing and immediately re-setting this flag on
- the remote contact.
- </tp:docstring>
- </tp:flag>
- </tp:flags>
-
- <tp:mapping name="Call_Member_Map" array-name="Call_Member_Map_List">
- <tp:docstring>A mapping from handles to their current state in the call.
- </tp:docstring>
- <tp:member type="u" tp:type="Handle" name="key"/>
- <tp:member type="u" tp:type="Call_Member_Flags" name="Flag"/>
- </tp:mapping>
-
- <signal name="CallMembersChanged"
- tp:name-for-bindings="Call_Members_Changed">
- <tp:docstring>
- Emitted when the <tp:member-ref>CallMembers</tp:member-ref> property
- changes in any way, either because contacts have been added to the
- call, contacts have been removed from the call, or contacts' flags
- have changed.
- </tp:docstring>
-
- <arg name="Flags_Changed" type="a{uu}" tp:type="Call_Member_Map">
- <tp:docstring>
- A map from members of the call to their new call member flags,
- including at least the members who have been added to
- <tp:member-ref>CallMembers</tp:member-ref>, and the members whose
- flags have changed.
- </tp:docstring>
- </arg>
- <arg name="Removed" type="au" tp:type="Contact_Handle[]">
- <tp:docstring>
- A list of members who have left the call, i.e. keys to be removed
- from <tp:member-ref>CallMembers</tp:member-ref>.
- </tp:docstring>
- </arg>
- </signal>
-
- <property name="CallMembers" tp:name-for-bindings="Call_Members"
- type="a{uu}" access="read" tp:type="Call_Member_Map">
- <tp:docstring xmlns="http://www.w3.org/1999/xhtml">
- <p>A mapping from the remote contacts that are part of this call to flags
- describing their status. This mapping never has the local user's handle
- as a key.</p>
-
- <p>When the call ends, this property should be an empty list,
- and notified with
- <tp:member-ref>CallMembersChanged</tp:member-ref></p>
-
- <p>If the Call implements
- <tp:dbus-ref namespace="ofdT.Channel.Interface"
- >Group</tp:dbus-ref> and the Group members are
- channel-specific handles, then this call SHOULD also use
- channel-specific handles.</p>
-
- <p>Anonymous members are exposed as channel-specific handles
- with no owner.</p>
- </tp:docstring>
- </property>
-
- <property name="InitialTransport" tp:name-for-bindings="Initial_Transport"
- type="u" tp:type="Stream_Transport_Type" access="read"
- tp:requestable="yes" tp:immutable="yes">
- <tp:docstring xmlns="http://www.w3.org/1999/xhtml">
- <p>If set on a requested channel, this indicates the transport that
- should be used for this call. Where not applicable, this property
- is defined to be <tp:type>Stream_Transport_Type</tp:type>_Unknown,
- in particular, on CMs with hardware streaming.</p>
-
- <tp:rationale>
- When implementing a voip gateway one wants the outgoing leg of the
- gatewayed to have the same transport as the incoming leg. This
- property allows the gateway to request a Call with the right
- transport from the CM.
- </tp:rationale>
- </tp:docstring>
- </property>
-
- <property name="InitialAudio" tp:name-for-bindings="Initial_Audio"
- type="b" access="read" tp:immutable="yes" tp:requestable="yes">
- <tp:docstring xmlns="http://www.w3.org/1999/xhtml">
- <p>If set to True in a channel request that will create a new channel,
- the connection manager should immediately attempt to establish an
- audio stream to the remote contact, making it unnecessary for the
- client to call <tp:dbus-ref
- namespace="ofdT.Channel.Type.Call.DRAFT">AddContent</tp:dbus-ref>.</p>
-
- <p>If this property, or InitialVideo, is passed to EnsureChannel
- (as opposed to CreateChannel), the connection manager SHOULD ignore
- these properties when checking whether it can return an existing
- channel as suitable; these properties only become significant when
- the connection manager has decided to create a new channel.</p>
-
- <p>If True on a requested channel, this indicates that the audio
- stream has already been requested and the client does not need to
- call RequestStreams, although it MAY still do so.</p>
-
- <p>If True on an unrequested (incoming) channel, this indicates that
- the remote contact initially requested an audio stream; this does
- not imply that that audio stream is still active (as indicated by
- <tp:dbus-ref namespace="ofdT.Channel.Type.Call.DRAFT"
- >Contents</tp:dbus-ref>).</p>
-
- <p>The name of this new content can be decided by using the
- <tp:member-ref>InitialAudioName</tp:member-ref> property.</p>
-
- <p>Connection managers that support the <tp:dbus-ref
- namespace="ofdT.Connection.Interface">ContactCapabilities</tp:dbus-ref>
- interface SHOULD represent the capabilities of receiving audio
- and/or video calls by including a channel class in
- a contact's capabilities with ChannelType = Call
- in the fixed properties dictionary, and InitialAudio and/or
- InitialVideo in the allowed properties list. Clients wishing to
- discover whether a particular contact is likely to be able to
- receive audio and/or video calls SHOULD use this information.</p>
-
- <tp:rationale>
- <p>Not all clients support video calls, and it would also be
- possible (although unlikely) to have a client which could only
- stream video, not audio.</p>
- </tp:rationale>
-
- <p>Clients that are willing to receive audio and/or video calls
- SHOULD include the following among their channel classes if
- calling <tp:dbus-ref
- namespace="ofdT.Connection.Interface.ContactCapabilities">UpdateCapabilities</tp:dbus-ref>
- (clients of a <tp:dbus-ref
- namespace="org.freedesktop.Telepathy">ChannelDispatcher</tp:dbus-ref>
- SHOULD instead arrange for the ChannelDispatcher to do this,
- by including the filters in their <tp:dbus-ref
- namespace="ofdT.Client.Handler">HandlerChannelFilter</tp:dbus-ref>
- properties):</p>
-
- <ul>
- <li>{ ChannelType = Call }</li>
- <li>{ ChannelType = Call, InitialAudio = True }
- if receiving calls with audio is supported</li>
- <li>{ ChannelType = Call, InitialVideo = True }
- if receiving calls with video is supported</li>
- </ul>
-
- <tp:rationale>
- <p>Connection managers for protocols with capability discovery,
- like XMPP, need this information to advertise the appropriate
- capabilities for their protocol.</p>
- </tp:rationale>
- </tp:docstring>
- </property>
-
- <property name="InitialVideo" tp:name-for-bindings="Initial_Video"
- type="b" access="read" tp:immutable="yes" tp:requestable="yes">
- <tp:docstring xmlns="http://www.w3.org/1999/xhtml">
- <p>The same as <tp:member-ref>InitialAudio</tp:member-ref>, but for
- a video stream. This property is immutable (cannot change).</p>
-
- <p>In particular, note that if this property is False, this does not
- imply that an active video stream has not been added, only that no
- video stream was active at the time the channel appeared.</p>
-
- <p>This property is the correct way to discover whether connection
- managers, contacts etc. support video calls; it appears in
- capabilities structures in the same way as InitialAudio.</p>
- </tp:docstring>
- </property>
-
- <property name="InitialAudioName" tp:name-for-bindings="Initial_Audio_Name"
- type="s" access="read" tp:immutable="yes" tp:requestable="yes">
- <tp:added version="0.21.2"/>
- <tp:docstring xmlns="http://www.w3.org/1999/xhtml">
- <p>If <tp:member-ref>InitialAudio</tp:member-ref> is set to
- True, then this property will name the intial audio content
- with the value of this property.</p>
-
- <tp:rationale>
- <p>Content names are meant to be significant, but if no name
- can be given to initial audio content, then its name cannot
- be meaningful or even localized.</p>
- </tp:rationale>
-
- <p>If this property is empty or missing from the channel
- request and InitialAudio is True, then the CM must come up
- with a sensible for the content, such as "audio".</p>
-
- <p>If the protocol has no concept of stream names then this
- property will not show up in the allowed properties list of
- the Requestable Channel Classes for call channels.</p>
- </tp:docstring>
- </property>
-
- <property name="InitialVideoName" tp:name-for-bindings="Initial_Video_Name"
- type="s" access="read" tp:immutable="yes" tp:requestable="yes">
- <tp:added version="0.21.2"/>
- <tp:docstring xmlns="http://www.w3.org/1999/xhtml">
- <p>The same as
- <tp:member-ref>InitialAudioName</tp:member-ref>, but for a
- video stream created by setting
- <tp:member-ref>InitialVideo</tp:member-ref> to True. This
- property is immutable and so cannot change.</p>
- </tp:docstring>
- </property>
-
- <property name="MutableContents" tp:name-for-bindings="Mutable_Contents"
- type="b" access="read" tp:immutable="yes">
- <tp:docstring xmlns="http://www.w3.org/1999/xhtml">
- <p>If True, a stream of a different content type can be added
- after the Channel has been requested </p>
-
- <p>If this property is missing, clients SHOULD assume that it is False,
- and thus that the channel's streams cannot be changed once the call
- has started.</p>
-
- <p>If this property isn't present in the "allowed" set in any of the
- Call entries contact capabilities, then user interfaces MAY choose to
- show a separate "call" option for each class of call.</p>
-
- <tp:rationale>
- <p>For example, once an audio-only Google Talk call has started,
- it is not possible to add a video stream; both audio and video
- must be requested at the start of the call if video is desired.
- User interfaces may use this pseudo-capability as a hint to
- display separate "Audio call" and "Video call" buttons, rather
- than a single "Call" button with the option to add and remove
- video once the call has started for contacts without this flag.
- </p>
- </tp:rationale>
- </tp:docstring>
- </property>
-
- <tp:hct name="audio">
- <tp:docstring xmlns="http://www.w3.org/1999/xhtml">
- <p>This client supports audio calls.</p>
- </tp:docstring>
- </tp:hct>
-
- <tp:hct name="video">
- <tp:docstring xmlns="http://www.w3.org/1999/xhtml">
- <p>This client supports video calls.</p>
- </tp:docstring>
- </tp:hct>
-
- <tp:hct name="gtalk-p2p">
- <tp:docstring xmlns="http://www.w3.org/1999/xhtml">
- <p>The client can implement streaming for streams whose <tp:dbus-ref
- namespace="ofdT.Call.Stream.Interface.Media.DRAFT">Transport</tp:dbus-ref>
- property is <tp:type>Stream_Transport_Type</tp:type>_GTalk_P2P.</p>
- </tp:docstring>
- </tp:hct>
-
- <tp:hct name="ice">
- <tp:docstring xmlns="http://www.w3.org/1999/xhtml">
- <p>The client can implement streaming for streams whose <tp:dbus-ref
- namespace="ofdT.Call.Stream.Interface.Media.DRAFT">Transport</tp:dbus-ref>
- property is <tp:type>Stream_Transport_Type</tp:type>_ICE.</p>
- </tp:docstring>
- </tp:hct>
-
- <tp:hct name="wlm-2009">
- <tp:docstring xmlns="http://www.w3.org/1999/xhtml">
- <p>The client can implement streaming for streams whose <tp:dbus-ref
- namespace="ofdT.Call.Stream.Interface.Media.DRAFT">Transport</tp:dbus-ref>
- property is <tp:type>Stream_Transport_Type</tp:type>_WLM_2009.</p>
- </tp:docstring>
- </tp:hct>
-
- <tp:hct name="shm">
- <tp:docstring xmlns="http://www.w3.org/1999/xhtml">
- <p>The client can implement streaming for streams whose <tp:dbus-ref
- namespace="ofdT.Call.Stream.Interface.Media.DRAFT">Transport</tp:dbus-ref>
- property is <tp:type>Stream_Transport_Type</tp:type>_SHM.</p>
- </tp:docstring>
- </tp:hct>
-
- <tp:hct name="video/h264" is-family="yes">
- <tp:docstring xmlns="http://www.w3.org/1999/xhtml">
- <p>The client supports media streaming with H264 (etc.).</p>
-
- <p>This handler capability token is a one of a family
- of similar tokens: for any other audio or video codec whose MIME
- type is audio/<em>subtype</em> or video/<em>subtype</em>, a handler
- capability token of this form may exist (the subtype MUST appear
- in lower case in this context). Clients MAY support more
- codecs than they explicitly advertise support for; clients SHOULD
- explicitly advertise support for their preferred codec(s), and
- for codecs like H264 that are, in practice, significant in codec
- negotiation.</p>
-
- <tp:rationale>
- <p>For instance, the XMPP capability used by the Google Video
- Chat web client to determine whether a client is compatible
- with it requires support for H264 video, so an XMPP
- connection manager that supports this version of Jingle should
- not advertise the Google Video Chat capability unless there
- is at least one installed client that declares that it supports
- <code>video/h264</code> on Call channels.</p>
- </tp:rationale>
-
- <p>For example, a client could advertise support for audio and video
- calls using Speex, Theora and H264 by having five handler capability
- tokens in its <tp:dbus-ref
- namespace="ofdT.Client.Handler">Capabilities</tp:dbus-ref>
- property:</p>
-
- <ul>
- <li><code>org.freedesktop.Telepathy.Channel.Type.Call.DRAFT/audio</code></li>
- <li><code>org.freedesktop.Telepathy.Channel.Type.Call.DRAFT/audio/speex</code></li>
- <li><code>org.freedesktop.Telepathy.Channel.Type.Call.DRAFT/video</code></li>
- <li><code>org.freedesktop.Telepathy.Channel.Type.Call.DRAFT/video/theora</code></li>
- <li><code>org.freedesktop.Telepathy.Channel.Type.Call.DRAFT/video/h264</code></li>
- </ul>
-
- <p>Clients MAY have media signalling abilities without explicitly
- supporting any particular codec, and connection managers SHOULD
- support this usage.</p>
-
- <tp:rationale>
- <p>This is necessary to support gatewaying between two Telepathy
- connections, in which case the available codecs might not be
- known to the gatewaying process.</p>
- </tp:rationale>
- </tp:docstring>
- </tp:hct>
-
- </interface>
-</node>
-<!-- vim:set sw=2 sts=2 et ft=xml: -->
diff --git a/extensions/Makefile.am b/extensions/Makefile.am
deleted file mode 100644
index 6fdc6b6..0000000
--- a/extensions/Makefile.am
+++ /dev/null
@@ -1,167 +0,0 @@
-# This directory re-uses telepathy-glib's code generation mechanisms to
-# generate code for interfaces that aren't stable enough for telepathy-glib
-# yet, so we can start to adapt example code to use them.
-
-tools_dir = $(top_srcdir)/tools
-
-AM_CFLAGS = \
- $(ERROR_CFLAGS) \
- $(GLIB_CFLAGS) \
- $(TELEPATHY_CFLAGS) \
- $(DBUS_CFLAGS) \
- -I${top_builddir} -I${top_srcdir}
-
-EXTRA_DIST = \
- all.xml \
- Call_Content_Codec_Offer.xml \
- Call_Content_Interface_Audio_Control.xml \
- Call_Content_Interface_Media.xml \
- Call_Content_Interface_Mute.xml \
- Call_Content_Interface_Video_Control.xml \
- call-content.xml \
- Call_Content.xml \
- Call_Stream_Endpoint.xml \
- Call_Stream_Interface_Media.xml \
- call-stream.xml \
- Call_Stream.xml \
- Channel_Type_Call.xml \
- channel.xml \
- misc.xml
-
-noinst_LTLIBRARIES = libfuture-extensions.la
-
-# In an external project you'd use $(TP_GLIB_LIBS) (obtained from
-# pkg-config via autoconf) instead of the .la path
-libfuture_extensions_la_LIBADD = \
- $(GLIB_LIBS) \
- $(TELEPATHY_LIBS)
-
-libfuture_extensions_la_SOURCES = \
- call-content.c \
- call-content.h \
- call-stream.c \
- call-stream.h \
- extensions.c \
- extensions-cli.c \
- extensions.h
-
-nodist_libfuture_extensions_la_SOURCES = \
- _gen/signals-marshal.c \
- _gen/signals-marshal.h \
- _gen/signals-marshal.list \
- _gen/register-dbus-glib-marshallers-body.h \
- _gen/enums.h \
- _gen/gtypes.h \
- _gen/gtypes-body.h \
- _gen/interfaces.h \
- _gen/interfaces-body.h \
- _gen/cli-call-content.h \
- _gen/cli-call-content-body.h \
- _gen/cli-call-stream.h \
- _gen/cli-call-stream-body.h \
- _gen/cli-channel.h \
- _gen/cli-channel-body.h \
- _gen/cli-misc.h \
- _gen/cli-misc-body.h
-
-BUILT_SOURCES = \
- _gen/all.xml \
- _gen/call-content.xml \
- _gen/call-stream.xml \
- _gen/channel.xml \
- _gen/misc.xml \
- $(nodist_libfuture_extensions_la_SOURCES)
-
-CLEANFILES = $(BUILT_SOURCES)
-
-clean-local:
- rm -rf _gen
-
-XSLTPROCFLAGS = --nonet --novalid
-
-# Generated files which can be generated for all categories simultaneously
-
-_gen/all.xml: all.xml $(wildcard $(srcdir)/*.xml) $(wildcard $(top_srcdir)/spec/*.xml) $(tools_dir)/xincludator.py
- $(mkdir_p) _gen
- $(AM_V_GEN)$(PYTHON) $(tools_dir)/xincludator.py $< > $@
-
-_gen/gtypes.h _gen/gtypes-body.h: _gen/all.xml \
- $(top_srcdir)/tools/glib-gtypes-generator.py
- $(AM_V_GEN)$(PYTHON) $(top_srcdir)/tools/glib-gtypes-generator.py \
- $< _gen/gtypes Tf_Future
-
-_gen/signals-marshal.list: _gen/all.xml \
- $(tools_dir)/glib-signals-marshal-gen.py
- $(AM_V_GEN)$(PYTHON) $(tools_dir)/glib-signals-marshal-gen.py $< > $@
-
-_gen/signals-marshal.h: _gen/signals-marshal.list Makefile.am
- $(AM_V_GEN)$(GLIB_GENMARSHAL) --header --prefix=_tf_future_ext_marshal $< > $@
-
-_gen/signals-marshal.c: _gen/signals-marshal.list Makefile.am
- $(AM_V_GEN){ echo '#include "_gen/signals-marshal.h"' && \
- $(GLIB_GENMARSHAL) --body --prefix=_tf_future_ext_marshal $< ; } > $@
-
-_gen/register-dbus-glib-marshallers-body.h: _gen/all.xml \
- $(tools_dir)/glib-client-marshaller-gen.py
- $(AM_V_GEN)$(PYTHON) $(tools_dir)/glib-client-marshaller-gen.py $< \
- _tf_future_ext > $@
-
-_gen/enums.h: _gen/all.xml \
- $(tools_dir)/c-constants-gen.py
- $(AM_V_GEN)$(PYTHON) $(tools_dir)/c-constants-gen.py \
- Tf_Future \
- $< _gen/enums
-
-_gen/interfaces-body.h _gen/interfaces.h: _gen/all.xml \
- $(tools_dir)/glib-interfaces-gen.py
- $(AM_V_GEN)$(PYTHON) $(tools_dir)/glib-interfaces-gen.py \
- Tf_Future _gen/interfaces-body.h _gen/interfaces.h $<
-
-# Generated files which must be generated per "category". Each TpProxy
-# subclass you want to use with --subclass will need to have its own category,
-# although you can subdivide further if you want.
-
-_gen/%.xml: %.xml $(wildcard $(srcdir)/*.xml) $(wildcard $(top_srcdir)/spec/*.xml) $(tools_dir)/xincludator.py
- $(mkdir_p) _gen
- $(AM_V_GEN)$(PYTHON) $(tools_dir)/xincludator.py $< > $@
-
-_gen/cli-channel-body.h _gen/cli-channel.h: _gen/channel.xml \
- $(tools_dir)/glib-client-gen.py Makefile.am
- $(AM_V_GEN)$(PYTHON) $(tools_dir)/glib-client-gen.py \
- --group=channel \
- --subclass=TpChannel \
- --subclass-assert=TP_IS_CHANNEL \
- --iface-quark-prefix=TF_FUTURE_IFACE_QUARK \
- --tp-proxy-api=0.7.6 \
- $< Tf_Future_Cli _gen/cli-channel
-
-_gen/cli-call-content-body.h _gen/cli-call-content.h: _gen/call-content.xml \
- $(tools_dir)/glib-client-gen.py Makefile.am
- $(AM_V_GEN)$(PYTHON) $(tools_dir)/glib-client-gen.py \
- --group=call_content \
- --subclass=TfFutureCallContent \
- --subclass-assert=TF_FUTURE_IS_CALL_CONTENT \
- --iface-quark-prefix=TF_FUTURE_IFACE_QUARK \
- --tp-proxy-api=0.7.6 \
- $< Tf_Future_Cli _gen/cli-call-content
-
-_gen/cli-call-stream-body.h _gen/cli-call-stream.h: _gen/call-stream.xml \
- $(tools_dir)/glib-client-gen.py Makefile.am
- $(AM_V_GEN)$(PYTHON) $(tools_dir)/glib-client-gen.py \
- --group=call_stream \
- --subclass=TfFutureCallStream \
- --subclass-assert=TF_FUTURE_IS_CALL_STREAM \
- --iface-quark-prefix=TF_FUTURE_IFACE_QUARK \
- --tp-proxy-api=0.7.6 \
- $< Tf_Future_Cli _gen/cli-call-stream
-
-# for now the Endpoint etc. interfaces are on every TpProxy - when we
-# have a TpCallEndpoint etc., they should appear on that
-
-_gen/cli-misc-body.h _gen/cli-misc.h: _gen/misc.xml \
- $(tools_dir)/glib-client-gen.py Makefile.am
- $(AM_V_GEN)$(PYTHON) $(tools_dir)/glib-client-gen.py \
- --group=misc \
- --iface-quark-prefix=TF_FUTURE_IFACE_QUARK \
- --tp-proxy-api=0.7.6 \
- $< Tf_Future_Cli _gen/cli-misc
diff --git a/extensions/all.xml b/extensions/all.xml
deleted file mode 100644
index 618cef7..0000000
--- a/extensions/all.xml
+++ /dev/null
@@ -1,12 +0,0 @@
-<tp:spec
- xmlns:tp="http://telepathy.freedesktop.org/wiki/DbusSpec#extensions-v0"
- xmlns:xi="http://www.w3.org/2001/XInclude">
-
-<tp:title>Extensions from the future</tp:title>
-
-<xi:include href="call-content.xml"/>
-<xi:include href="call-stream.xml"/>
-<xi:include href="channel.xml"/>
-<xi:include href="misc.xml"/>
-
-</tp:spec>
diff --git a/extensions/call-content.c b/extensions/call-content.c
deleted file mode 100644
index deb36ec..0000000
--- a/extensions/call-content.c
+++ /dev/null
@@ -1,161 +0,0 @@
-/*
- * call-content.c - proxy for a Content in a Call channel
- *
- * Copyright (C) 2009 Collabora Ltd. <http://www.collabora.co.uk/>
- * Copyright (C) 2009 Nokia Corporation
- *
- * 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 "extensions/call-content.h"
-
-#include <telepathy-glib/proxy-subclass.h>
-#include <telepathy-glib/telepathy-glib.h>
-
-#include "extensions/extensions.h"
-
-/* Generated code */
-#include "_gen/cli-call-content-body.h"
-
-/**
- * SECTION:call-content
- * @title: TfFutureCallContent
- * @short_description: proxy for a Content in a Call channel
- * @see_also: #TpChannel
- *
- * FIXME
- *
- * Since: FIXME
- */
-
-/**
- * TfFutureCallContentClass:
- *
- * The class of a #TfFutureCallContent.
- *
- * Since: FIXME
- */
-struct _TfFutureCallContentClass {
- TpProxyClass parent_class;
- /*<private>*/
- gpointer priv;
-};
-
-/**
- * TfFutureCallContent:
- *
- * A proxy object for a Telepathy connection manager.
- *
- * Since: FIXME
- */
-struct _TfFutureCallContent {
- TpProxy parent;
- /*<private>*/
- TfFutureCallContentPrivate *priv;
-};
-
-struct _TfFutureCallContentPrivate {
- int dummy;
-};
-
-G_DEFINE_TYPE (TfFutureCallContent,
- tf_future_call_content,
- TP_TYPE_PROXY);
-
-static void
-tf_future_call_content_init (TfFutureCallContent *self)
-{
- self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self, TF_FUTURE_TYPE_CALL_CONTENT,
- TfFutureCallContentPrivate);
-}
-
-static void
-tf_future_call_content_class_init (TfFutureCallContentClass *klass)
-{
- TpProxyClass *proxy_class = (TpProxyClass *) klass;
-
- g_type_class_add_private (klass, sizeof (TfFutureCallContentPrivate));
-
- proxy_class->must_have_unique_name = TRUE;
- proxy_class->interface = TF_FUTURE_IFACE_QUARK_CALL_CONTENT;
- tf_future_call_content_init_known_interfaces ();
-}
-
-/**
- * tf_future_call_content_new:
- * @channel: the Call channel
- * @object_path: the object path of the content; may not be %NULL
- * @error: used to indicate the error if %NULL is returned
- *
- * <!-- -->
- *
- * Returns: a new content proxy, or %NULL on invalid arguments
- *
- * Since: FIXME
- */
-TfFutureCallContent *
-tf_future_call_content_new (TpChannel *channel,
- const gchar *object_path,
- GError **error)
-{
- TfFutureCallContent *ret = NULL;
-
- g_return_val_if_fail (TP_IS_CHANNEL (channel), NULL);
- g_return_val_if_fail (object_path != NULL, NULL);
-
- if (!tp_dbus_check_valid_object_path (object_path, error))
- goto finally;
-
- ret = TF_FUTURE_CALL_CONTENT (g_object_new (TF_FUTURE_TYPE_CALL_CONTENT,
- /* FIXME: pass in the Channel as a property? */
- "dbus-daemon", tp_proxy_get_dbus_daemon (channel),
- "bus-name", tp_proxy_get_bus_name (channel),
- "object-path", object_path,
- NULL));
-
-finally:
- return ret;
-}
-
-/**
- * tf_future_call_content_init_known_interfaces:
- *
- * Ensure that the known interfaces for TfFutureCallContent have been set up.
- * This is done automatically when necessary, but for correct
- * overriding of library interfaces by local extensions, you should
- * call this function before calling
- * tp_proxy_or_subclass_hook_on_interface_add() with first argument
- * %TF_FUTURE_TYPE_CALL_CONTENT.
- *
- * Since: 0.7.32
- */
-void
-tf_future_call_content_init_known_interfaces (void)
-{
- static gsize once = 0;
-
- if (g_once_init_enter (&once))
- {
- GType tp_type = TF_FUTURE_TYPE_CALL_CONTENT;
-
- tp_proxy_init_known_interfaces ();
- tp_proxy_or_subclass_hook_on_interface_add (tp_type,
- tf_future_cli_call_content_add_signals);
- tp_proxy_subclass_add_error_mapping (tp_type,
- TP_ERROR_PREFIX, TP_ERRORS, TP_TYPE_ERROR);
-
- g_once_init_leave (&once, 1);
- }
-}
diff --git a/extensions/call-content.h b/extensions/call-content.h
deleted file mode 100644
index 68873d5..0000000
--- a/extensions/call-content.h
+++ /dev/null
@@ -1,62 +0,0 @@
-/*
- * call-content.h - proxy for a Content in a Call channel
- *
- * Copyright (C) 2009 Collabora Ltd. <http://www.collabora.co.uk/>
- * Copyright (C) 2009 Nokia Corporation
- *
- * 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
- */
-
-#ifndef TF_FUTURE_CALL_CONTENT_H
-#define TF_FUTURE_CALL_CONTENT_H
-
-#include <telepathy-glib/channel.h>
-#include <telepathy-glib/proxy.h>
-
-G_BEGIN_DECLS
-
-typedef struct _TfFutureCallContent TfFutureCallContent;
-typedef struct _TfFutureCallContentPrivate TfFutureCallContentPrivate;
-typedef struct _TfFutureCallContentClass TfFutureCallContentClass;
-
-GType tf_future_call_content_get_type (void);
-
-/* TYPE MACROS */
-#define TF_FUTURE_TYPE_CALL_CONTENT \
- (tf_future_call_content_get_type ())
-#define TF_FUTURE_CALL_CONTENT(obj) \
- (G_TYPE_CHECK_INSTANCE_CAST((obj), TF_FUTURE_TYPE_CALL_CONTENT, \
- TfFutureCallContent))
-#define TF_FUTURE_CALL_CONTENT_CLASS(klass) \
- (G_TYPE_CHECK_CLASS_CAST((klass), TF_FUTURE_TYPE_CALL_CONTENT, \
- TfFutureCallContentClass))
-#define TF_FUTURE_IS_CALL_CONTENT(obj) \
- (G_TYPE_CHECK_INSTANCE_TYPE((obj), TF_FUTURE_TYPE_CALL_CONTENT))
-#define TF_FUTURE_IS_CALL_CONTENT_CLASS(klass) \
- (G_TYPE_CHECK_CLASS_TYPE((klass), TF_FUTURE_TYPE_CALL_CONTENT))
-#define TF_FUTURE_CALL_CONTENT_GET_CLASS(obj) \
- (G_TYPE_INSTANCE_GET_CLASS ((obj), TF_FUTURE_TYPE_CALL_CONTENT, \
- TfFutureCallContentClass))
-
-TfFutureCallContent *tf_future_call_content_new (TpChannel *channel,
- const gchar *object_path, GError **error);
-
-void tf_future_call_content_init_known_interfaces (void);
-
-G_END_DECLS
-
-#include "extensions/_gen/cli-call-content.h"
-
-#endif
diff --git a/extensions/call-content.xml b/extensions/call-content.xml
deleted file mode 100644
index ead2fe5..0000000
--- a/extensions/call-content.xml
+++ /dev/null
@@ -1,12 +0,0 @@
-<tp:spec
- xmlns:tp="http://telepathy.freedesktop.org/wiki/DbusSpec#extensions-v0"
- xmlns:xi="http://www.w3.org/2001/XInclude">
-
-<tp:title>Call Content</tp:title>
-
-<xi:include href="Call_Content.xml"/>
-<xi:include href="Call_Content_Interface_Audio_Control.xml"/>
-<xi:include href="Call_Content_Interface_Media.xml"/>
-<xi:include href="Call_Content_Interface_Video_Control.xml"/>
-
-</tp:spec>
diff --git a/extensions/call-stream.c b/extensions/call-stream.c
deleted file mode 100644
index a9a0d1c..0000000
--- a/extensions/call-stream.c
+++ /dev/null
@@ -1,161 +0,0 @@
-/*
- * call-stream.c - proxy for a Stream in a Call channel
- *
- * Copyright (C) 2009 Collabora Ltd. <http://www.collabora.co.uk/>
- * Copyright (C) 2009 Nokia Corporation
- *
- * 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 "extensions/call-stream.h"
-
-#include <telepathy-glib/proxy-subclass.h>
-#include <telepathy-glib/telepathy-glib.h>
-
-#include "extensions/extensions.h"
-
-/* Generated code */
-#include "_gen/cli-call-stream-body.h"
-
-/**
- * SECTION:call-stream
- * @title: TfFutureCallStream
- * @short_description: proxy for a Stream in a Call channel
- * @see_also: #TpChannel
- *
- * FIXME
- *
- * Since: FIXME
- */
-
-/**
- * TfFutureCallStreamClass:
- *
- * The class of a #TfFutureCallStream.
- *
- * Since: FIXME
- */
-struct _TfFutureCallStreamClass {
- TpProxyClass parent_class;
- /*<private>*/
- gpointer priv;
-};
-
-/**
- * TfFutureCallStream:
- *
- * A proxy object for a Telepathy connection manager.
- *
- * Since: FIXME
- */
-struct _TfFutureCallStream {
- TpProxy parent;
- /*<private>*/
- TfFutureCallStreamPrivate *priv;
-};
-
-struct _TfFutureCallStreamPrivate {
- int dummy;
-};
-
-G_DEFINE_TYPE (TfFutureCallStream,
- tf_future_call_stream,
- TP_TYPE_PROXY);
-
-static void
-tf_future_call_stream_init (TfFutureCallStream *self)
-{
- self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self, TF_FUTURE_TYPE_CALL_STREAM,
- TfFutureCallStreamPrivate);
-}
-
-static void
-tf_future_call_stream_class_init (TfFutureCallStreamClass *klass)
-{
- TpProxyClass *proxy_class = (TpProxyClass *) klass;
-
- g_type_class_add_private (klass, sizeof (TfFutureCallStreamPrivate));
-
- proxy_class->must_have_unique_name = TRUE;
- proxy_class->interface = TF_FUTURE_IFACE_QUARK_CALL_STREAM;
- tf_future_call_stream_init_known_interfaces ();
-}
-
-/**
- * tf_future_call_stream_new:
- * @channel: the Call channel
- * @object_path: the object path of the stream; may not be %NULL
- * @error: used to indicate the error if %NULL is returned
- *
- * <!-- -->
- *
- * Returns: a new stream proxy, or %NULL on invalid arguments
- *
- * Since: FIXME
- */
-TfFutureCallStream *
-tf_future_call_stream_new (TpChannel *channel,
- const gchar *object_path,
- GError **error)
-{
- TfFutureCallStream *ret = NULL;
-
- g_return_val_if_fail (TP_IS_CHANNEL (channel), NULL);
- g_return_val_if_fail (object_path != NULL, NULL);
-
- if (!tp_dbus_check_valid_object_path (object_path, error))
- goto finally;
-
- ret = TF_FUTURE_CALL_STREAM (g_object_new (TF_FUTURE_TYPE_CALL_STREAM,
- /* FIXME: pass in the Channel as a property? */
- "dbus-daemon", tp_proxy_get_dbus_daemon (channel),
- "bus-name", tp_proxy_get_bus_name (channel),
- "object-path", object_path,
- NULL));
-
-finally:
- return ret;
-}
-
-/**
- * tf_future_call_stream_init_known_interfaces:
- *
- * Ensure that the known interfaces for TfFutureCallStream have been set up.
- * This is done automatically when necessary, but for correct
- * overriding of library interfaces by local extensions, you should
- * call this function before calling
- * tp_proxy_or_subclass_hook_on_interface_add() with first argument
- * %TF_FUTURE_TYPE_CALL_STREAM.
- *
- * Since: 0.7.32
- */
-void
-tf_future_call_stream_init_known_interfaces (void)
-{
- static gsize once = 0;
-
- if (g_once_init_enter (&once))
- {
- GType tp_type = TF_FUTURE_TYPE_CALL_STREAM;
-
- tp_proxy_init_known_interfaces ();
- tp_proxy_or_subclass_hook_on_interface_add (tp_type,
- tf_future_cli_call_stream_add_signals);
- tp_proxy_subclass_add_error_mapping (tp_type,
- TP_ERROR_PREFIX, TP_ERRORS, TP_TYPE_ERROR);
-
- g_once_init_leave (&once, 1);
- }
-}
diff --git a/extensions/call-stream.h b/extensions/call-stream.h
deleted file mode 100644
index 2cd82b5..0000000
--- a/extensions/call-stream.h
+++ /dev/null
@@ -1,62 +0,0 @@
-/*
- * call-stream.h - proxy for a Stream in a Call channel
- *
- * Copyright (C) 2009 Collabora Ltd. <http://www.collabora.co.uk/>
- * Copyright (C) 2009 Nokia Corporation
- *
- * 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
- */
-
-#ifndef TF_FUTURE_CALL_STREAM_H
-#define TF_FUTURE_CALL_STREAM_H
-
-#include <telepathy-glib/channel.h>
-#include <telepathy-glib/proxy.h>
-
-G_BEGIN_DECLS
-
-typedef struct _TfFutureCallStream TfFutureCallStream;
-typedef struct _TfFutureCallStreamPrivate TfFutureCallStreamPrivate;
-typedef struct _TfFutureCallStreamClass TfFutureCallStreamClass;
-
-GType tf_future_call_stream_get_type (void);
-
-/* TYPE MACROS */
-#define TF_FUTURE_TYPE_CALL_STREAM \
- (tf_future_call_stream_get_type ())
-#define TF_FUTURE_CALL_STREAM(obj) \
- (G_TYPE_CHECK_INSTANCE_CAST((obj), TF_FUTURE_TYPE_CALL_STREAM, \
- TfFutureCallStream))
-#define TF_FUTURE_CALL_STREAM_CLASS(klass) \
- (G_TYPE_CHECK_CLASS_CAST((klass), TF_FUTURE_TYPE_CALL_STREAM, \
- TfFutureCallStreamClass))
-#define TF_FUTURE_IS_CALL_STREAM(obj) \
- (G_TYPE_CHECK_INSTANCE_TYPE((obj), TF_FUTURE_TYPE_CALL_STREAM))
-#define TF_FUTURE_IS_CALL_STREAM_CLASS(klass) \
- (G_TYPE_CHECK_CLASS_TYPE((klass), TF_FUTURE_TYPE_CALL_STREAM))
-#define TF_FUTURE_CALL_STREAM_GET_CLASS(obj) \
- (G_TYPE_INSTANCE_GET_CLASS ((obj), TF_FUTURE_TYPE_CALL_STREAM, \
- TfFutureCallStreamClass))
-
-TfFutureCallStream *tf_future_call_stream_new (TpChannel *channel,
- const gchar *object_path, GError **error);
-
-void tf_future_call_stream_init_known_interfaces (void);
-
-G_END_DECLS
-
-#include "extensions/_gen/cli-call-stream.h"
-
-#endif
diff --git a/extensions/call-stream.xml b/extensions/call-stream.xml
deleted file mode 100644
index 3e85b37..0000000
--- a/extensions/call-stream.xml
+++ /dev/null
@@ -1,10 +0,0 @@
-<tp:spec
- xmlns:tp="http://telepathy.freedesktop.org/wiki/DbusSpec#extensions-v0"
- xmlns:xi="http://www.w3.org/2001/XInclude">
-
-<tp:title>Call Stream</tp:title>
-
-<xi:include href="Call_Stream.xml"/>
-<xi:include href="Call_Stream_Interface_Media.xml"/>
-
-</tp:spec>
diff --git a/extensions/channel.xml b/extensions/channel.xml
deleted file mode 100644
index b4e0a46..0000000
--- a/extensions/channel.xml
+++ /dev/null
@@ -1,9 +0,0 @@
-<tp:spec
- xmlns:tp="http://telepathy.freedesktop.org/wiki/DbusSpec#extensions-v0"
- xmlns:xi="http://www.w3.org/2001/XInclude">
-
-<tp:title>Channel extensions from the future</tp:title>
-
-<xi:include href="Channel_Type_Call.xml"/>
-
-</tp:spec>
diff --git a/extensions/extensions-cli.c b/extensions/extensions-cli.c
deleted file mode 100644
index 971669d..0000000
--- a/extensions/extensions-cli.c
+++ /dev/null
@@ -1,35 +0,0 @@
-#include "extensions.h"
-
-#include <telepathy-glib/telepathy-glib.h>
-#include <telepathy-glib/proxy-subclass.h>
-
-static void _tf_future_ext_register_dbus_glib_marshallers (void);
-
-/* include auto-generated stubs for client-specific code */
-#include "_gen/signals-marshal.h"
-#include "_gen/cli-channel-body.h"
-#include "_gen/cli-misc-body.h"
-#include "_gen/register-dbus-glib-marshallers-body.h"
-
-static gpointer
-tf_future_cli_once (gpointer data)
-{
- _tf_future_ext_register_dbus_glib_marshallers ();
-
- tp_channel_init_known_interfaces ();
-
- tp_proxy_or_subclass_hook_on_interface_add (TP_TYPE_PROXY,
- tf_future_cli_misc_add_signals);
- tp_proxy_or_subclass_hook_on_interface_add (TP_TYPE_CHANNEL,
- tf_future_cli_channel_add_signals);
-
- return NULL;
-}
-
-void
-tf_future_cli_init (void)
-{
- static GOnce once = G_ONCE_INIT;
-
- g_once (&once, tf_future_cli_once, NULL);
-}
diff --git a/extensions/extensions.c b/extensions/extensions.c
deleted file mode 100644
index eeda462..0000000
--- a/extensions/extensions.c
+++ /dev/null
@@ -1,6 +0,0 @@
-#include "extensions.h"
-
-/* include auto-generated stubs for things common to service and client */
-#include "_gen/gtypes-body.h"
-#include "_gen/interfaces-body.h"
-#include "_gen/signals-marshal.h"
diff --git a/extensions/extensions.h b/extensions/extensions.h
deleted file mode 100644
index f6e080d..0000000
--- a/extensions/extensions.h
+++ /dev/null
@@ -1,23 +0,0 @@
-#ifndef FUTURE_EXTENSIONS_H
-#define FUTURE_EXTENSIONS_H
-
-#include <glib-object.h>
-#include <telepathy-glib/telepathy-glib.h>
-
-#include "extensions/_gen/enums.h"
-#include "extensions/_gen/cli-channel.h"
-#include "extensions/_gen/cli-misc.h"
-
-#include "extensions/call-content.h"
-#include "extensions/call-stream.h"
-
-G_BEGIN_DECLS
-
-#include "extensions/_gen/gtypes.h"
-#include "extensions/_gen/interfaces.h"
-
-void tf_future_cli_init (void);
-
-G_END_DECLS
-
-#endif
diff --git a/extensions/misc.xml b/extensions/misc.xml
deleted file mode 100644
index 0384410..0000000
--- a/extensions/misc.xml
+++ /dev/null
@@ -1,10 +0,0 @@
-<tp:spec
- xmlns:tp="http://telepathy.freedesktop.org/wiki/DbusSpec#extensions-v0"
- xmlns:xi="http://www.w3.org/2001/XInclude">
-
-<tp:title>Miscellaneous extensions from the future</tp:title>
-
-<xi:include href="Call_Content_Codec_Offer.xml"/>
-<xi:include href="Call_Stream_Endpoint.xml"/>
-
-</tp:spec>
diff --git a/python/examples/constants.py b/python/examples/constants.py
index 0def268..43af8ba 100644
--- a/python/examples/constants.py
+++ b/python/examples/constants.py
@@ -20,23 +20,23 @@ from telepathy.interfaces import CHANNEL_INTERFACE
CHANNEL = CHANNEL_INTERFACE
CHANNEL_TYPE = CHANNEL + ".ChannelType"
-CHANNEL_TYPE_CALL = CHANNEL + ".Type.Call.DRAFT"
+CHANNEL_TYPE_CALL = CHANNEL + ".Type.Call1"
CALL_INITIAL_AUDIO = CHANNEL_TYPE_CALL + '.InitialAudio'
CALL_INITIAL_VIDEO = CHANNEL_TYPE_CALL + '.InitialVideo'
CALL_MUTABLE_CONTENTS = CHANNEL_TYPE_CALL + '.MutableContents'
-CALL_CONTENT = 'org.freedesktop.Telepathy.Call.Content.DRAFT'
+CALL_CONTENT = 'org.freedesktop.Telepathy.Call1.Content'
CALL_CONTENT_IFACE_MEDIA = \
- 'org.freedesktop.Telepathy.Call.Content.Interface.Media.DRAFT'
+ 'org.freedesktop.Telepathy.Call1.Content.Interface.Media'
CALL_CONTENT_CODECOFFER = \
- 'org.freedesktop.Telepathy.Call.Content.CodecOffer.DRAFT'
+ 'org.freedesktop.Telepathy.Call1.Content.CodecOffer'
-CALL_STREAM = 'org.freedesktop.Telepathy.Call.Stream.DRAFT'
+CALL_STREAM = 'org.freedesktop.Telepathy.Call1.Stream'
CALL_STREAM_IFACE_MEDIA = \
- 'org.freedesktop.Telepathy.Call.Stream.Interface.Media.DRAFT'
+ 'org.freedesktop.Telepathy.Call1.Stream.Interface.Media'
-CALL_STREAM_ENDPOINT = 'org.freedesktop.Telepathy.Call.Stream.Endpoint.DRAFT'
+CALL_STREAM_ENDPOINT = 'org.freedesktop.Telepathy.Call1.Stream.Endpoint'
STREAM_TRANSPORT_RAW_UDP = 1
STREAM_TRANSPORT_ICE_UDP = 2
diff --git a/python/pytpfarstream.defs b/python/pytpfarstream.defs
index 59b6783..fa2e554 100644
--- a/python/pytpfarstream.defs
+++ b/python/pytpfarstream.defs
@@ -29,11 +29,6 @@
;; From telepathy-farstream.h
-(define-function tf_init
- (c-name "tf_init")
- (return-type "none")
-)
-
;; -*- scheme -*-
; object definitions ...
@@ -74,8 +69,6 @@
(c-name "tf_content_error_literal")
(return-type "none")
(parameters
- '("guint" "reason")
- '("const-gchar*" "detailed_reason")
'("const-gchar*" "message")
)
)
@@ -85,8 +78,48 @@
(c-name "tf_content_error")
(return-type "none")
(parameters
- '("guint" "reason")
- '("const-gchar*" "detailed_reason")
+ '("const-gchar*" "message_format")
+ )
+ (varargs #t)
+)
+
+(define-method sending_failed_literal
+ (of-object "TfContent")
+ (c-name "tf_content_sending_failed_literal")
+ (return-type "none")
+ (parameters
+ '("const-gchar*" "message")
+ )
+)
+
+(define-method sending_failed
+ (of-object "TfContent")
+ (c-name "tf_content_sending_failed")
+ (return-type "none")
+ (parameters
+ '("const-gchar*" "message_format")
+ )
+ (varargs #t)
+)
+
+(define-method receiving_failed_literal
+ (of-object "TfContent")
+ (c-name "tf_content_receiving_failed_literal")
+ (return-type "none")
+ (parameters
+ '("guint*" "handles")
+ '("guint" "handle_count")
+ '("const-gchar*" "message")
+ )
+)
+
+(define-method receiving_failed
+ (of-object "TfContent")
+ (c-name "tf_content_receiving_failed")
+ (return-type "none")
+ (parameters
+ '("guint*" "handles")
+ '("guint" "handle_count")
'("const-gchar*" "message_format")
)
(varargs #t)
diff --git a/python/pytpfarstreammodule.c b/python/pytpfarstreammodule.c
index f6e6f86..460ca29 100644
--- a/python/pytpfarstreammodule.c
+++ b/python/pytpfarstreammodule.c
@@ -15,7 +15,6 @@ inittpfarstream(void)
{
PyObject *m, *d;
- tf_init ();
init_pygobject ();
m = Py_InitModule ("tpfarstream", tf_functions);
diff --git a/telepathy-farstream/Makefile.am b/telepathy-farstream/Makefile.am
index 723fa4b..7b8830c 100644
--- a/telepathy-farstream/Makefile.am
+++ b/telepathy-farstream/Makefile.am
@@ -20,7 +20,6 @@ libtelepathy_farstream_la_SOURCES = \
session.c \
channel.c \
channel.h \
- stream-priv.h \
session-priv.h \
channel-priv.h \
media-signalling-channel.c \
@@ -34,7 +33,6 @@ libtelepathy_farstream_la_SOURCES = \
call-stream.h \
call-stream.c \
telepathy-farstream.h \
- telepathy-farstream.c \
utils.h
nodist_libtelepathy_farstream_la_SOURCES = $(BUILT_SOURCES)
@@ -60,8 +58,7 @@ libtelepathy_farstream_la_LIBADD = \
$(DBUS_LIBS) \
$(GST_LIBS) \
$(FARSTREAM_LIBS) \
- $(TELEPATHY_LIBS) \
- ../extensions/libfuture-extensions.la
+ $(TELEPATHY_LIBS)
libtelepathy_farstream_la_LDFLAGS = -no-undefined \
-export-symbols-regex "^tf_(init|content_|channel_).*" \
diff --git a/telepathy-farstream/call-channel.c b/telepathy-farstream/call-channel.c
index 57c650f..94bdc4c 100644
--- a/telepathy-farstream/call-channel.c
+++ b/telepathy-farstream/call-channel.c
@@ -34,8 +34,6 @@
#include <telepathy-glib/interfaces.h>
#include <farstream/fs-conference.h>
-#include "extensions/extensions.h"
-
#include "call-content.h"
#include "tf-signals-marshal.h"
@@ -94,8 +92,14 @@ static gboolean tf_call_channel_init_finish (GAsyncInitable *initable,
GAsyncResult *res,
GError **error);
-static void got_hardware_streaming (TpProxy *proxy, const GValue *out_value,
- const GError *error, gpointer user_data, GObject *weak_object);
+static void content_added (TpCallChannel *proxy,
+ TpCallContent *context_proxy, TfCallChannel *self);
+static void content_removed (TpCallChannel *proxy,
+ TpCallContent *content_proxy, TpCallStateReason *reason,
+ TfCallChannel *self);
+static void channel_prepared (GObject *proxy, GAsyncResult *prepare_res,
+ gpointer user_data);
+
static void
@@ -200,10 +204,12 @@ tf_call_channel_init_async (GAsyncInitable *initable,
res = g_simple_async_result_new (G_OBJECT (self), callback, user_data,
tf_call_channel_init_async);
- tp_cli_dbus_properties_call_get (self->proxy, -1,
- TF_FUTURE_IFACE_CHANNEL_TYPE_CALL,
- "HardwareStreaming",
- got_hardware_streaming, res, NULL, G_OBJECT (self));
+ tp_g_signal_connect_object (self->proxy, "content-added",
+ G_CALLBACK (content_added), self, 0);
+ tp_g_signal_connect_object (self->proxy, "content-removed",
+ G_CALLBACK (content_removed), self, 0);
+
+ tp_proxy_prepare_async (self->proxy, NULL, channel_prepared, res);
}
static gboolean
@@ -244,18 +250,10 @@ tf_call_channel_dispose (GObject *object)
already been disposed of. */
if (self->contents)
{
- GHashTableIter iter;
- gpointer key, value;
-
- g_hash_table_iter_init (&iter, self->contents);
- while (g_hash_table_iter_next (&iter, &key, &value))
- {
- g_object_run_dispose (G_OBJECT (value));
- }
-
- g_hash_table_destroy (self->contents);
- self->contents = NULL;
+ g_ptr_array_foreach (self->contents, (GFunc) g_object_run_dispose, NULL);
+ g_ptr_array_free (self->contents, TRUE);
}
+ self->contents = NULL;
if (self->participants)
g_ptr_array_unref (self->participants);
@@ -317,38 +315,34 @@ content_ready (GObject *object, GAsyncResult *res, gpointer user_data)
if (g_async_initable_init_finish (G_ASYNC_INITABLE (object), res, NULL))
{
g_signal_emit (self, signals[SIGNAL_CONTENT_ADDED], 0, content);
- g_object_unref (content);
}
else
{
- GHashTableIter iter;
- gpointer key, value;
-
- g_hash_table_iter_init (&iter, self->contents);
- while (g_hash_table_iter_next (&iter, &key, &value))
- {
- if (value == object)
- {
- g_hash_table_iter_remove (&iter);
- break;
- }
- }
+ g_ptr_array_remove_fast (self->contents, content);
}
g_object_unref (self);
}
static gboolean
-add_content (TfCallChannel *self, const gchar *content_path)
+add_content (TfCallChannel *self, TpCallContent *content_proxy)
{
GError *error = NULL;
TfCallContent *content;
+ guint i;
/* Check if content already added */
- if (g_hash_table_lookup (self->contents, content_path))
- return TRUE;
+ if (!self->contents)
+ return FALSE;
+
+ for (i = 0; i < self->contents->len; i++)
+ {
+ if (tf_call_content_get_proxy (g_ptr_array_index (self->contents, i)) ==
+ content_proxy)
+ return TRUE;
+ }
- content = tf_call_content_new_async (self, content_path,
+ content = tf_call_content_new_async (self, content_proxy,
&error, content_ready, g_object_ref (self));
if (error)
@@ -359,52 +353,16 @@ add_content (TfCallChannel *self, const gchar *content_path)
return FALSE;
}
- g_hash_table_insert (self->contents, g_strdup (content_path), content);
+ g_ptr_array_add (self->contents, content);
return TRUE;
}
static void
-got_contents (TpProxy *proxy, const GValue *out_value,
- const GError *error, gpointer user_data, GObject *weak_object)
+content_added (TpCallChannel *proxy,
+ TpCallContent *content_proxy,
+ TfCallChannel *self)
{
- TfCallChannel *self = TF_CALL_CHANNEL (weak_object);
- GSimpleAsyncResult *res = user_data;
- GPtrArray *contents;
- guint i;
-
- if (error)
- {
- g_warning ("Error getting the Contents property: %s",
- error->message);
- g_simple_async_result_set_from_error (res, error);
- goto out;
- }
-
- contents = g_value_get_boxed (out_value);
-
- self->contents = g_hash_table_new_full (g_str_hash, g_str_equal,
- g_free, g_object_unref);
-
- for (i = 0; i < contents->len; i++)
- if (!add_content (self, g_ptr_array_index (contents, i)))
- break;
-
- g_simple_async_result_set_op_res_gboolean (res, TRUE);
-
-out:
- g_simple_async_result_complete (res);
- g_object_unref (res);
-}
-
-static void
-content_added (TpChannel *proxy,
- const gchar *arg_Content,
- gpointer user_data,
- GObject *weak_object)
-{
- TfCallChannel *self = TF_CALL_CHANNEL (weak_object);
-
/* Ignore signals before we got the "Contents" property to avoid races that
* could cause the same content to be added twice
*/
@@ -412,91 +370,77 @@ content_added (TpChannel *proxy,
if (!self->contents)
return;
- add_content (self, arg_Content);
+ add_content (self, content_proxy);
}
static void
-content_removed (TpChannel *proxy,
- const gchar *arg_Content,
- gpointer user_data,
- GObject *weak_object)
+content_removed (TpCallChannel *proxy,
+ TpCallContent *content_proxy,
+ TpCallStateReason *reason,
+ TfCallChannel *self)
{
- TfCallChannel *self = TF_CALL_CHANNEL (weak_object);
- TfCallContent *content;
-
+ guint i;
if (!self->contents)
return;
- content = g_hash_table_lookup (self->contents, arg_Content);
-
- if (content)
+ for (i = 0; i < self->contents->len; i++)
{
- g_object_ref (content);
- g_hash_table_remove (self->contents, arg_Content);
- g_signal_emit (self, signals[SIGNAL_CONTENT_REMOVED], 0, content);
- g_object_unref (content);
+ if (tf_call_content_get_proxy (g_ptr_array_index (self->contents, i)) ==
+ content_proxy)
+ {
+ TfCallContent *content = g_ptr_array_index (self->contents, i);
+
+ g_object_ref (content);
+ g_ptr_array_remove_index_fast (self->contents, i);
+ g_signal_emit (self, signals[SIGNAL_CONTENT_REMOVED], 0, content);
+ g_object_unref (content);
+ return;
+ }
}
}
-
static void
-got_hardware_streaming (TpProxy *proxy, const GValue *out_value,
- const GError *error, gpointer user_data, GObject *weak_object)
+channel_prepared (GObject *proxy, GAsyncResult *prepare_res, gpointer user_data)
{
- TfCallChannel *self = TF_CALL_CHANNEL (weak_object);
GSimpleAsyncResult *res = user_data;
- GError *myerror = NULL;
+ TfCallChannel *self =
+ TF_CALL_CHANNEL (g_async_result_get_source_object (G_ASYNC_RESULT (res)));
+ GError *error = NULL;
+ GPtrArray *contents;
+ guint i;
- if (error)
+ if (!tp_proxy_prepare_finish (proxy, prepare_res, &error))
{
- g_warning ("Error getting the hardware streaming property: %s",
+ g_warning ("Preparing the channel: %s",
error->message);
- g_simple_async_result_set_from_error (res, error);
- goto error;
+ g_simple_async_result_take_error (res, error);
+ goto out;
}
- if (g_value_get_boolean (out_value))
+ if (tp_call_channel_has_hardware_streaming (TP_CALL_CHANNEL (proxy)))
{
g_warning ("Hardware streaming property is TRUE, ignoring");
g_simple_async_result_set_error (res, TP_ERROR, TP_ERROR_NOT_CAPABLE,
"This channel does hardware streaming, not handled here");
- goto error;
+ goto out;
}
- tf_future_cli_channel_type_call_connect_to_content_added (TP_CHANNEL (proxy),
- content_added, NULL, NULL, G_OBJECT (self), &myerror);
- if (myerror)
- {
- g_warning ("Error connectiong to ContentAdded signal: %s",
- myerror->message);
- g_simple_async_result_set_from_error (res, myerror);
- g_clear_error (&myerror);
- goto error;
- }
+ contents = tp_call_channel_get_contents (TP_CALL_CHANNEL (proxy));
- tf_future_cli_channel_type_call_connect_to_content_removed (
- TP_CHANNEL (proxy), content_removed, NULL, NULL, G_OBJECT (self),
- &myerror);
- if (myerror)
- {
- g_warning ("Error connectiong to ContentRemoved signal: %s",
- myerror->message);
- g_simple_async_result_set_from_error (res, myerror);
- g_clear_error (&myerror);
- goto error;
- }
+ self->contents = g_ptr_array_new_with_free_func (g_object_unref);
- tp_cli_dbus_properties_call_get (proxy, -1,
- TF_FUTURE_IFACE_CHANNEL_TYPE_CALL, "Contents",
- got_contents, res, NULL, G_OBJECT (self));
+ for (i = 0; i < contents->len; i++)
+ if (!add_content (self, g_ptr_array_index (contents, i)))
+ break;
- return;
+ g_simple_async_result_set_op_res_gboolean (res, TRUE);
-error:
+out:
g_simple_async_result_complete (res);
g_object_unref (res);
+ g_object_unref (self);
}
void
@@ -541,9 +485,8 @@ tf_call_channel_bus_message (TfCallChannel *channel,
{
GError *error = NULL;
gchar *debug;
- GHashTableIter iter;
- gpointer key, value;
struct CallConference *cc;
+ guint i;
cc = find_call_conference_by_conference (channel, GST_MESSAGE_SRC (message));
if (!cc)
@@ -573,9 +516,9 @@ tf_call_channel_bus_message (TfCallChannel *channel,
break;
}
- g_hash_table_iter_init (&iter, channel->contents);
- while (g_hash_table_iter_next (&iter, &key, &value))
- if (tf_call_content_bus_message (value, message))
+ for (i = 0; i < channel->contents->len; i++)
+ if (tf_call_content_bus_message (g_ptr_array_index (channel->contents, i),
+ message))
return TRUE;
return FALSE;
@@ -584,9 +527,8 @@ tf_call_channel_bus_message (TfCallChannel *channel,
void
tf_call_channel_error (TfCallChannel *channel)
{
- tf_future_cli_channel_type_call_call_hangup (channel->proxy,
- -1, TF_FUTURE_CALL_STATE_CHANGE_REASON_UNKNOWN, "", "",
- NULL, NULL, NULL, NULL);
+ tp_call_channel_hangup_async (TP_CALL_CHANNEL (channel->proxy),
+ TP_CALL_STATE_CHANGE_REASON_UNKNOWN, "", "", NULL, NULL);
}
@@ -719,5 +661,4 @@ _tf_call_channel_put_participant (TfCallChannel *channel,
return;
}
}
-
}
diff --git a/telepathy-farstream/call-channel.h b/telepathy-farstream/call-channel.h
index 3848818..8c268d2 100644
--- a/telepathy-farstream/call-channel.h
+++ b/telepathy-farstream/call-channel.h
@@ -76,7 +76,7 @@ struct _TfCallChannel {
GHashTable *fsconferences;
- GHashTable *contents; /* NULL before getting the first contents */
+ GPtrArray *contents; /* NULL before getting the first contents */
GPtrArray *participants;
};
diff --git a/telepathy-farstream/call-content.c b/telepathy-farstream/call-content.c
index e799d50..8a5b4b6 100644
--- a/telepathy-farstream/call-content.c
+++ b/telepathy-farstream/call-content.c
@@ -20,32 +20,43 @@
/**
* SECTION:call-content
- * @short_description: Handle the Call interface on a Channel
+ * @short_description: Handle the Content objects on a Call channel
*
- * This class handles the
- * org.freedesktop.Telepathy.Channel.Interface.Call on a
- * channel using Farstream.
+ * This class handles the org.freedesktop.Telepathy.Call1.Content,
+ * org.freedesktop.Telepathy.Call1.Content.Interface.Media,
+ * org.freedesktop.Telepathy.Call1.Content.Interface.VideoControl,
+ * org.freedesktop.Telepathy.Call1.Content.MediaDescription,
+ * prg.freedesktop.Telepathy.Call1.Content.MediaDescription.Interface.RTPHeaderExtensions
+ * and org.freedesktop.Telepathy.Call1.Content.MediaDescription.Interface.RTCPFeedback interfaces
+ *
+ */
+
+/* TODO:
+ *
+ * In MediaDescription:
+ * - SSRCs
*/
+
#include "call-content.h"
-#include <telepathy-glib/util.h>
-#include <telepathy-glib/interfaces.h>
+#include <telepathy-glib/telepathy-glib.h>
+#include <telepathy-glib/proxy-subclass.h>
#include <farstream/fs-conference.h>
#include <farstream/fs-utils.h>
+#include <farstream/fs-rtp.h>
#include <farstream/fs-element-added-notifier.h>
#include <stdarg.h>
#include <string.h>
-#include <telepathy-glib/proxy-subclass.h>
#include "call-stream.h"
#include "tf-signals-marshal.h"
#include "utils.h"
-#include "extensions/extensions.h"
+#define DTMF_TONE_VOLUME (8)
struct _TfCallContent {
TfContent parent;
@@ -53,27 +64,38 @@ struct _TfCallContent {
TfCallChannel *call_channel;
FsConference *fsconference;
- TfFutureCallContent *proxy;
+ TpCallContent *proxy;
FsSession *fssession;
- TpMediaStreamType media_type;
- GList *current_codecs;
- TpProxy *current_offer;
- guint current_offer_contact_handle;
- GList *current_offer_fscodecs;
+ TpProxy *current_media_description;
+ guint current_md_contact_handle;
+ GList *current_md_fscodecs;
+ GList *current_md_rtp_hdrext;
+
+ gboolean current_has_rtp_hdrext;
+ gboolean current_has_rtcp_fb;
+ gboolean has_rtp_hdrext;
+ gboolean has_rtcp_fb;
- GHashTable *streams; /* NULL before getting the first streams */
+ GList *last_sent_codecs;
+
+ GPtrArray *streams; /* NULL before getting the first streams */
/* Streams for which we don't have a session yet*/
GList *outstanding_streams;
GMutex *mutex;
+ gboolean remote_codecs_set;
+
+ TpSendingState dtmf_sending_state;
+ guint current_dtmf_event;
+
/* Content protected by the Mutex */
GPtrArray *fsstreams;
guint fsstreams_cookie;
- gboolean got_codec_offer_property;
+ gboolean got_media_description_property;
/* AudioControl API */
gint requested_input_volume;
@@ -93,7 +115,7 @@ struct _TfCallContent {
guint height;
};
-struct _TfCallContentClass{
+struct _TfCallContentClass {
TfContentClass parent_class;
};
@@ -175,11 +197,24 @@ static void src_pad_added (FsStream *fsstream, GstPad *pad, FsCodec *codec,
static GstIterator * tf_call_content_iterate_src_pads (TfContent *content,
guint *handles, guint handle_count);
-static void tf_call_content_error (TfContent *content,
- guint reason, /* TfFutureContentRemovalReason */
+static void tf_call_content_error (TfCallContent *self,
+ TpCallStateChangeReason reason,
+ const gchar *detailed_reason,
+ const gchar *message_format,
+ ...) G_GNUC_PRINTF (4, 5);
+static void tf_call_content_error_literal (TfCallContent *self,
+ TpCallStateChangeReason reason,
const gchar *detailed_reason,
const gchar *message);
+static void tf_call_content_error_impl (TfContent *content,
+ const gchar *message);
+static void tf_call_content_sending_failed (TfContent *content,
+ const gchar *message);
+static void tf_call_content_receiving_failed (TfContent *content,
+ guint *handles, guint handle_count,
+ const gchar *message);
+
static void
tf_call_content_class_init (TfCallContentClass *klass)
{
@@ -188,7 +223,9 @@ tf_call_content_class_init (TfCallContentClass *klass)
content_class->iterate_src_pads = tf_call_content_iterate_src_pads;
- content_class->content_error = tf_call_content_error;
+ content_class->content_error = tf_call_content_error_impl;
+ content_class->sending_failed = tf_call_content_sending_failed;
+ content_class->receiving_failed = tf_call_content_receiving_failed;
object_class->dispose = tf_call_content_dispose;
object_class->finalize = tf_call_content_finalize;
@@ -281,7 +318,7 @@ free_content_fsstream (gpointer data)
{
struct CallFsStream *cfs = data;
- g_object_run_dispose (G_OBJECT (cfs->fsstream));
+ fs_stream_destroy (cfs->fsstream);
g_object_unref (cfs->fsstream);
_tf_call_channel_put_participant (cfs->parent_channel, cfs->fsparticipant);
g_slice_free (struct CallFsStream, cfs);
@@ -291,6 +328,7 @@ static void
tf_call_content_init (TfCallContent *self)
{
self->fsstreams = g_ptr_array_new ();
+ self->dtmf_sending_state = TP_SENDING_STATE_NONE;
self->mutex = g_mutex_new ();
self->requested_input_volume = -1;
@@ -308,12 +346,12 @@ tf_call_content_dispose (GObject *object)
g_debug (G_STRFUNC);
if (self->streams)
- g_hash_table_destroy (self->streams);
+ g_ptr_array_free (self->streams, TRUE);
self->streams = NULL;
if (self->fssession)
{
- g_object_run_dispose (G_OBJECT (self->fssession));
+ fs_session_destroy (self->fssession);
g_object_unref (self->fssession);
}
self->fssession = NULL;
@@ -340,6 +378,9 @@ tf_call_content_dispose (GObject *object)
g_object_unref (self->proxy);
self->proxy = NULL;
+ fs_codec_list_destroy (self->last_sent_codecs);
+ self->last_sent_codecs = NULL;
+
/* We do not hold a ref to the call channel, and use it as a flag to ensure
* we will bail out when disposed */
self->call_channel = NULL;
@@ -436,7 +477,7 @@ tf_call_content_set_property (GObject *object,
break;
self->reported_input_volume = g_value_get_int (value);
- tf_future_cli_call_content_interface_audio_control_call_report_input_volume (
+ tp_cli_call_content_interface_audio_control_call_report_input_volume (
self->proxy, -1, self->reported_input_volume,
NULL, NULL, NULL, NULL);
@@ -447,7 +488,7 @@ tf_call_content_set_property (GObject *object,
break;
self->reported_output_volume = g_value_get_int (value);
- tf_future_cli_call_content_interface_audio_control_call_report_output_volume (
+ tp_cli_call_content_interface_audio_control_call_report_output_volume (
self->proxy, -1, self->reported_output_volume,
NULL, NULL, NULL, NULL);
break;
@@ -458,49 +499,25 @@ tf_call_content_set_property (GObject *object,
}
static void
-create_stream (TfCallContent *self, gchar *stream_path)
+add_stream (TfCallContent *self, TpCallStream *stream_proxy)
{
- GError *error = NULL;
- TfCallStream *stream = tf_call_stream_new (self->call_channel, self,
- stream_path, &error);
-
- if (error)
- {
- /* TODO: Use per-stream errors */
- tf_content_error (TF_CONTENT (self),
- TF_FUTURE_CONTENT_REMOVAL_REASON_ERROR, "",
- "Error creating the stream object: %s", error->message);
- return;
- }
-
- g_hash_table_insert (self->streams, stream_path, stream);
+ g_ptr_array_add (self->streams,
+ tf_call_stream_new (self, stream_proxy));
}
static void
-add_stream (TfCallContent *self, const gchar *stream_path)
+add_initial_streams (TfCallContent *self)
{
-
- if (!self->fsconference)
- {
- self->outstanding_streams = g_list_prepend (self->outstanding_streams,
- g_strdup (stream_path));
- } else {
- create_stream (self, g_strdup (stream_path));
- }
-}
-
-static void
-update_streams (TfCallContent *self)
-{
- GList *l;
+ GPtrArray *streams;
+ guint i;
g_assert (self->fsconference);
+ g_assert (self->streams->len == 0);
- for (l = self->outstanding_streams ; l != NULL; l = l->next)
- create_stream (self, l->data);
+ streams = tp_call_content_get_streams (self->proxy);
- g_list_free (self->outstanding_streams);
- self->outstanding_streams = NULL;
+ for (i = 0; i < streams->len; i++)
+ add_stream (self, g_ptr_array_index (streams, i));
}
static void
@@ -514,7 +531,8 @@ tpparam_to_fsparam (gpointer key, gpointer value, gpointer user_data)
}
static GList *
-tpcodecs_to_fscodecs (FsMediaType fsmediatype, const GPtrArray *tpcodecs)
+tpcodecs_to_fscodecs (FsMediaType fsmediatype, const GPtrArray *tpcodecs,
+ gboolean does_avpf, GHashTable *rtcp_fb)
{
GList *fscodecs = NULL;
guint i;
@@ -528,15 +546,51 @@ tpcodecs_to_fscodecs (FsMediaType fsmediatype, const GPtrArray *tpcodecs)
guint channels;
GHashTable *params;
FsCodec *fscodec;
+ gchar *tmp;
+ GValueArray *feedback_params = NULL;
+ gboolean updated;
- tp_value_array_unpack (tpcodec, 5, &pt, &name, &clock_rate, &channels,
- &params);
+ tp_value_array_unpack (tpcodec, 6, &pt, &name, &clock_rate, &channels,
+ &updated, &params);
fscodec = fs_codec_new (pt, name, fsmediatype, clock_rate);
fscodec->channels = channels;
g_hash_table_foreach (params, tpparam_to_fsparam, fscodec);
+ if (does_avpf)
+ fscodec->minimum_reporting_interval = 0;
+
+ if (rtcp_fb)
+ feedback_params = g_hash_table_lookup (rtcp_fb, GUINT_TO_POINTER (pt));
+
+ if (feedback_params)
+ {
+ guint rtcp_minimum_interval;
+ GPtrArray *messages;
+ guint j;
+
+ tp_value_array_unpack (feedback_params, 2, &rtcp_minimum_interval,
+ &messages);
+ if (rtcp_minimum_interval != G_MAXUINT)
+ fscodec->minimum_reporting_interval = rtcp_minimum_interval;
+
+ for (j = 0; j < messages->len ; j++)
+ {
+ GValueArray *message = g_ptr_array_index (messages, j);
+ const gchar *type, *subtype, *extra_params;
+
+ tp_value_array_unpack (message, 3, &type, &subtype,
+ &extra_params);
+
+ fs_codec_add_feedback_parameter (fscodec, type, subtype,
+ extra_params);
+ }
+ }
+
+ tmp = fs_codec_to_string (fscodec);
+ g_debug ("%s", tmp);
+ g_free (tmp);
fscodecs = g_list_prepend (fscodecs, fscodec);
}
@@ -545,82 +599,311 @@ tpcodecs_to_fscodecs (FsMediaType fsmediatype, const GPtrArray *tpcodecs)
return fscodecs;
}
+static GList *
+tprtphdrext_to_fsrtphdrext (GPtrArray *rtp_hdrext)
+{
+ GQueue ret = G_QUEUE_INIT;
+ guint i;
+
+ if (!rtp_hdrext)
+ return NULL;
+
+ for (i = 0; i < rtp_hdrext->len; i++)
+ {
+ GValueArray *extension = g_ptr_array_index (rtp_hdrext, i);
+ guint id;
+ TpMediaStreamDirection direction;
+ const char *uri;
+ const gchar *parameters;
+ FsRtpHeaderExtension *ext;
+
+ tp_value_array_unpack (extension, 4, &id, &direction, &uri, &parameters);
+
+ ext = fs_rtp_header_extension_new (id,
+ tpdirection_to_fsdirection (direction), uri);
+
+ g_debug ("hdrext: " FS_RTP_HEADER_EXTENSION_FORMAT,
+ FS_RTP_HEADER_EXTENSION_ARGS (ext));
+
+ g_queue_push_tail (&ret, ext);
+ }
+
+ return ret.head;
+}
+
+static gboolean
+object_has_property (GObject *object, const gchar *property)
+{
+ return g_object_class_find_property (G_OBJECT_GET_CLASS (object),
+ property) != NULL;
+}
+
static void
-process_codec_offer_try_codecs (TfCallContent *self, FsStream *fsstream,
- TpProxy *offer, GList *fscodecs)
+on_content_dtmf_change_requested (TpCallContent *proxy,
+ guchar arg_Event,
+ guint arg_State,
+ gpointer user_data,
+ GObject *weak_object)
+{
+ TfCallContent *self = TF_CALL_CONTENT (weak_object);
+
+ /* Ignore the signal until we've got the original properties and codecs */
+ if (!self->fssession || !self->remote_codecs_set) {
+ self->dtmf_sending_state = arg_State;
+ self->current_dtmf_event = arg_Event;
+ return;
+ }
+
+ switch (arg_State)
+ {
+ case TP_SENDING_STATE_PENDING_STOP_SENDING:
+ if (self->dtmf_sending_state != TP_SENDING_STATE_SENDING)
+ {
+ tf_call_content_error (self,
+ TP_CALL_STATE_CHANGE_REASON_INTERNAL_ERROR,
+ TP_ERROR_STR_CONFUSED,
+ "Tried to stop a %u DTMF event while state is %d",
+ arg_Event, self->dtmf_sending_state);
+ }
+
+ if (fs_session_stop_telephony_event (self->fssession))
+ {
+ self->dtmf_sending_state = TP_SENDING_STATE_PENDING_STOP_SENDING;
+ }
+ else
+ {
+ tf_call_content_error (self,
+ TP_CALL_STATE_CHANGE_REASON_INTERNAL_ERROR,
+ TP_ERROR_STR_MEDIA_STREAMING_ERROR,
+ "Could not stop DTMF event %d", arg_Event);
+ tp_cli_call_content_interface_media_call_acknowledge_dtmf_change (
+ self->proxy, -1, arg_Event, TP_SENDING_STATE_SENDING,
+ NULL, NULL, NULL, NULL);
+ }
+ break;
+ case TP_SENDING_STATE_PENDING_SEND:
+ if (self->dtmf_sending_state != TP_SENDING_STATE_NONE)
+ {
+ tf_call_content_error (self,
+ TP_CALL_STATE_CHANGE_REASON_INTERNAL_ERROR,
+ TP_ERROR_STR_CONFUSED,
+ "Tried to start a new DTMF event %u while %d is already playing",
+ arg_Event, self->current_dtmf_event);
+ fs_session_stop_telephony_event (self->fssession);
+ }
+
+ if (fs_session_start_telephony_event (self->fssession,
+ arg_Event, DTMF_TONE_VOLUME))
+ {
+ self->current_dtmf_event = arg_Event;
+ self->dtmf_sending_state = TP_SENDING_STATE_PENDING_SEND;
+ }
+ else
+ {
+ tf_call_content_error (self,
+ TP_CALL_STATE_CHANGE_REASON_INTERNAL_ERROR,
+ TP_ERROR_STR_MEDIA_STREAMING_ERROR,
+ "Could not start DTMF event %d", arg_Event);
+ tp_cli_call_content_interface_media_call_acknowledge_dtmf_change (
+ self->proxy, -1, arg_Event, TP_SENDING_STATE_NONE,
+ NULL, NULL, NULL, NULL);
+ }
+ break;
+ default:
+ tf_call_content_error (self,
+ TP_CALL_STATE_CHANGE_REASON_INTERNAL_ERROR,
+ TP_ERROR_STR_CONFUSED,
+ "Invalid State %d in DTMFChangeRequested signal for event %d",
+ arg_State, arg_Event);
+ break;
+ }
+}
+
+
+static void
+process_media_description_try_codecs (TfCallContent *self, FsStream *fsstream,
+ TpProxy *media_description, GList *fscodecs, GList *rtp_hdrext)
{
gboolean success = TRUE;
GError *error = NULL;
if (fscodecs != NULL)
- success = fs_stream_set_remote_codecs (fsstream, fscodecs, &error);
+ {
+ GList *old_rtp_hdrext = NULL;
+
+ if (object_has_property (G_OBJECT (fsstream), "rtp-header-extensions"))
+ {
+ g_object_get (fsstream, "rtp-header-extensions", &old_rtp_hdrext,
+ NULL);
+ g_object_set (fsstream, "rtp-header-extensions", rtp_hdrext, NULL);
+ }
+
+ success = fs_stream_set_remote_codecs (fsstream, fscodecs, &error);
+
+ if (success)
+ {
+ if (!self->remote_codecs_set)
+ on_content_dtmf_change_requested (NULL, self->current_dtmf_event,
+ self->dtmf_sending_state, NULL, G_OBJECT (self));
+ self->remote_codecs_set = TRUE;
+ }
+
+ if (!success &&
+ object_has_property (G_OBJECT (fsstream), "rtp-header-extensions"))
+ g_object_set (fsstream, "rtp-header-extensions", old_rtp_hdrext, NULL);
+
+ fs_rtp_header_extension_list_destroy (old_rtp_hdrext);
+ }
+ fs_rtp_header_extension_list_destroy (rtp_hdrext);
fs_codec_list_destroy (fscodecs);
if (success)
{
- self->current_offer = offer;
+ self->current_media_description = media_description;
tf_call_content_try_sending_codecs (self);
}
else
{
- tf_future_cli_call_content_codec_offer_call_reject (offer,
- -1, NULL, NULL, NULL, NULL);
- g_object_unref (offer);
+ GValueArray *reason = tp_value_array_build (4,
+ G_TYPE_UINT, 0,
+ G_TYPE_UINT, TP_CALL_STATE_CHANGE_REASON_MEDIA_ERROR,
+ G_TYPE_STRING, TP_ERROR_STR_MEDIA_CODECS_INCOMPATIBLE,
+ G_TYPE_STRING,
+ "Remote codecs are not compatible with the local ones",
+ G_TYPE_INVALID);
+
+ g_debug ("Rejecting Media Description");
+ tp_cli_call_content_media_description_call_reject (media_description,
+ -1, reason, NULL, NULL, NULL, NULL);
+ g_value_array_free (reason);
+ g_object_unref (media_description);
}
-
+ g_clear_error (&error);
}
static void
-process_codec_offer (TfCallContent *self, const gchar *offer_objpath,
- guint contact_handle, const GPtrArray *codecs)
+process_media_description (TfCallContent *self,
+ const gchar *media_description_objpath,
+ const GHashTable *properties)
{
TpProxy *proxy;
GError *error = NULL;
FsStream *fsstream;
+ GPtrArray *codecs;
+ GPtrArray *rtp_hdrext = NULL;
+ GHashTable *rtcp_fb = NULL;
+ gboolean does_avpf = FALSE;
GList *fscodecs;
+ const gchar * const *interfaces;
+ guint i;
+ GList *fsrtp_hdrext;
+ guint contact_handle;
+ gboolean valid;
/* Guard against early disposal */
if (self->call_channel == NULL)
return;
- if (!tp_dbus_check_valid_object_path (offer_objpath, &error))
+ if (!tp_dbus_check_valid_object_path (media_description_objpath, &error))
{
- tf_content_error (TF_CONTENT (self),
- TF_FUTURE_CONTENT_REMOVAL_REASON_ERROR, "",
- "Invalid offer path: %s", error->message);
+ tf_call_content_error (self,
+ TP_CALL_STATE_CHANGE_REASON_INTERNAL_ERROR, TP_ERROR_STR_CONFUSED,
+ "Invalid MediaDescription path: %s", error->message);
g_clear_error (&error);
return;
}
+ contact_handle = tp_asv_get_uint32 (properties,
+ TP_PROP_CALL_CONTENT_MEDIA_DESCRIPTION_REMOTE_CONTACT, &valid);
+ if (!valid)
+ {
+ tf_call_content_error_literal (self,
+ TP_CALL_STATE_CHANGE_REASON_INTERNAL_ERROR, TP_ERROR_STR_CONFUSED,
+ "MediaDescription does not contain a valid contact handle");
+ g_clear_error (&error);
+ return;
+ }
+
+ codecs = tp_asv_get_boxed (properties,
+ TP_PROP_CALL_CONTENT_MEDIA_DESCRIPTION_CODECS, TP_ARRAY_TYPE_CODEC_LIST);
+
+ if (!codecs)
+ {
+ tf_call_content_error_literal (self,
+ TP_CALL_STATE_CHANGE_REASON_INTERNAL_ERROR, TP_ERROR_STR_CONFUSED,
+ "MediaDescription does not contain codecs");
+ g_clear_error (&error);
+ return;
+ }
+
+ tp_call_content_media_description_init_known_interfaces ();
proxy = g_object_new (TP_TYPE_PROXY,
"dbus-daemon", tp_proxy_get_dbus_daemon (self->proxy),
"bus-name", tp_proxy_get_bus_name (self->proxy),
- "object-path", offer_objpath,
+ "object-path", media_description_objpath,
NULL);
tp_proxy_add_interface_by_id (TP_PROXY (proxy),
- TF_FUTURE_IFACE_QUARK_CALL_CONTENT_CODEC_OFFER);
+ TP_IFACE_QUARK_CALL_CONTENT_MEDIA_DESCRIPTION);
+
+ interfaces = tp_asv_get_strv (properties,
+ TP_PROP_CALL_CONTENT_MEDIA_DESCRIPTION_INTERFACES);
+
+
+ self->current_has_rtcp_fb = FALSE;
+ self->current_has_rtp_hdrext = FALSE;
+ for (i = 0; interfaces[i]; i++)
+ {
+ if (!strcmp (interfaces[i],
+ TP_IFACE_CALL_CONTENT_MEDIA_DESCRIPTION_INTERFACE_RTCP_FEEDBACK))
+ {
+ gboolean valid;
+
+ self->current_has_rtcp_fb = TRUE;
+ rtcp_fb = tp_asv_get_boxed (properties,
+ TP_PROP_CALL_CONTENT_MEDIA_DESCRIPTION_INTERFACE_RTCP_FEEDBACK_FEEDBACK_MESSAGES,
+ TP_HASH_TYPE_RTCP_FEEDBACK_MESSAGE_MAP);
+ does_avpf = tp_asv_get_boolean (properties,
+ TP_PROP_CALL_CONTENT_MEDIA_DESCRIPTION_INTERFACE_RTCP_FEEDBACK_DOES_AVPF, &valid);
+ if (!valid)
+ does_avpf = FALSE;
+ }
+ else if (!strcmp (interfaces[i],
+ TP_IFACE_CALL_CONTENT_MEDIA_DESCRIPTION_INTERFACE_RTP_HEADER_EXTENSIONS))
+ {
+ self->current_has_rtp_hdrext = TRUE;
+ rtp_hdrext = tp_asv_get_boxed (properties,
+ TP_PROP_CALL_CONTENT_MEDIA_DESCRIPTION_INTERFACE_RTP_HEADER_EXTENSIONS_HEADER_EXTENSIONS,
+ TP_ARRAY_TYPE_RTP_HEADER_EXTENSIONS_LIST);
+ }
+ }
+
+
+ g_debug ("Got MediaDescription");
+ fscodecs = tpcodecs_to_fscodecs (tf_call_content_get_fs_media_type (self),
+ codecs, does_avpf, rtcp_fb);
- fscodecs = tpcodecs_to_fscodecs (tp_media_type_to_fs (self->media_type),
- codecs);
+ fsrtp_hdrext = tprtphdrext_to_fsrtphdrext (rtp_hdrext);
fsstream = tf_call_content_get_existing_fsstream_by_handle (self,
contact_handle);
if (!fsstream)
{
- g_debug ("Delaying codec offer processing");
- self->current_offer = proxy;
- self->current_offer_contact_handle = contact_handle;
- self->current_offer_fscodecs = fscodecs;
+ g_debug ("Delaying codec media_description processing");
+ self->current_media_description = proxy;
+ self->current_md_contact_handle = contact_handle;
+ self->current_md_fscodecs = fscodecs;
+ self->current_md_rtp_hdrext = fsrtp_hdrext;
return;
}
- process_codec_offer_try_codecs (self, fsstream, proxy, fscodecs);
+ process_media_description_try_codecs (self, fsstream, proxy, fscodecs,
+ fsrtp_hdrext);
}
static void
-on_content_video_keyframe_requested (TfFutureCallContent *proxy,
+on_content_video_keyframe_requested (TpCallContent *proxy,
gpointer user_data,
GObject *weak_object)
{
@@ -655,7 +938,7 @@ on_content_video_keyframe_requested (TfFutureCallContent *proxy,
}
static void
-on_content_video_resolution_changed (TfFutureCallContent *proxy,
+on_content_video_resolution_changed (TpCallContent *proxy,
const GValueArray *resolution,
gpointer user_data,
GObject *weak_object)
@@ -684,7 +967,7 @@ on_content_video_resolution_changed (TfFutureCallContent *proxy,
}
static void
-on_content_video_bitrate_changed (TfFutureCallContent *proxy,
+on_content_video_bitrate_changed (TpCallContent *proxy,
guint bitrate,
gpointer user_data,
GObject *weak_object)
@@ -703,7 +986,7 @@ on_content_video_bitrate_changed (TfFutureCallContent *proxy,
}
static void
-on_content_video_framerate_changed (TfFutureCallContent *proxy,
+on_content_video_framerate_changed (TpCallContent *proxy,
guint framerate,
gpointer user_data,
GObject *weak_object)
@@ -722,7 +1005,7 @@ on_content_video_framerate_changed (TfFutureCallContent *proxy,
}
static void
-on_content_video_mtu_changed (TfFutureCallContent *proxy,
+on_content_video_mtu_changed (TpCallContent *proxy,
guint mtu,
gpointer user_data,
GObject *weak_object)
@@ -746,6 +1029,44 @@ on_content_video_mtu_changed (TfFutureCallContent *proxy,
}
}
+static void
+streams_added (TpCallContent *proxy,
+ GPtrArray *streams,
+ TfCallContent *self)
+{
+ guint i;
+
+ /* Ignore signals before we got the "Contents" property to avoid races that
+ * could cause the same content to be added twice
+ */
+
+ if (!self->streams)
+ return;
+
+ for (i = 0; i < streams->len; i++)
+ add_stream (self, g_ptr_array_index (streams, i));
+}
+
+static void
+streams_removed (TpCallContent *proxy,
+ const GPtrArray *streams,
+ TpCallStateReason *reason,
+ TfCallContent *self)
+{
+ guint i, j;
+
+ if (!self->streams)
+ return;
+
+ for (i = 0; i < streams->len; i++)
+ for (j = 0; j < self->streams->len; j++)
+ if (g_ptr_array_index (streams, i) ==
+ tf_call_stream_get_proxy (g_ptr_array_index (self->streams, j)))
+ {
+ g_ptr_array_remove_index_fast (self->streams, j);
+ break;
+ }
+}
static void
got_content_media_properties (TpProxy *proxy, GHashTable *properties,
@@ -754,14 +1075,16 @@ got_content_media_properties (TpProxy *proxy, GHashTable *properties,
TfCallContent *self = TF_CALL_CONTENT (weak_object);
GSimpleAsyncResult *res = user_data;
GValueArray *gva;
- const gchar *offer_objpath;
- guint contact;
+ const gchar *media_description_objpath = NULL;
+ GHashTable *media_description_properties;
GError *myerror = NULL;
- GPtrArray *codecs;
guint32 packetization;
const gchar *conference_type;
gboolean valid;
GList *codec_prefs;
+ guchar dtmf_event;
+ guint dtmf_state;
+ const GValue *dtmf_event_value;
/* Guard against early disposal */
if (self->call_channel == NULL)
@@ -775,8 +1098,9 @@ got_content_media_properties (TpProxy *proxy, GHashTable *properties,
if (error != NULL)
{
- tf_content_error (TF_CONTENT (self),
- TF_FUTURE_CONTENT_REMOVAL_REASON_ERROR, "",
+ tf_call_content_error (self,
+ TP_CALL_STATE_CHANGE_REASON_INTERNAL_ERROR,
+ TP_ERROR_STR_MEDIA_STREAMING_ERROR,
"Error getting the Content's media properties: %s", error->message);
g_simple_async_result_set_from_error (res, error);
g_simple_async_result_complete (res);
@@ -793,15 +1117,16 @@ got_content_media_properties (TpProxy *proxy, GHashTable *properties,
switch (packetization)
{
- case TF_FUTURE_CALL_CONTENT_PACKETIZATION_TYPE_RTP:
+ case TP_CALL_CONTENT_PACKETIZATION_TYPE_RTP:
conference_type = "rtp";
break;
- case TF_FUTURE_CALL_CONTENT_PACKETIZATION_TYPE_RAW:
+ case TP_CALL_CONTENT_PACKETIZATION_TYPE_RAW:
conference_type = "raw";
break;
default:
- tf_content_error (TF_CONTENT (self),
- TF_FUTURE_CONTENT_REMOVAL_REASON_UNSUPPORTED, "",
+ tf_call_content_error (self,
+ TP_CALL_STATE_CHANGE_REASON_MEDIA_ERROR,
+ TP_ERROR_STR_MEDIA_UNSUPPORTED_TYPE,
"Could not create FsConference for type %d", packetization);
g_simple_async_result_set_error (res, G_IO_ERROR, G_IO_ERROR_NOT_FOUND,
"Could not create FsConference for type %d", packetization);
@@ -814,8 +1139,9 @@ got_content_media_properties (TpProxy *proxy, GHashTable *properties,
conference_type);
if (!self->fsconference)
{
- tf_content_error (TF_CONTENT (self),
- TF_FUTURE_CONTENT_REMOVAL_REASON_UNSUPPORTED, "",
+ tf_call_content_error (self,
+ TP_CALL_STATE_CHANGE_REASON_MEDIA_ERROR,
+ TP_ERROR_STR_MEDIA_UNSUPPORTED_TYPE,
"Could not create FsConference for type %s", conference_type);
g_simple_async_result_set_error (res, G_IO_ERROR, G_IO_ERROR_NOT_FOUND,
"Error getting the Content's properties: invalid type");
@@ -825,12 +1151,13 @@ got_content_media_properties (TpProxy *proxy, GHashTable *properties,
}
self->fssession = fs_conference_new_session (self->fsconference,
- tp_media_type_to_fs (self->media_type), &myerror);
+ tf_call_content_get_fs_media_type (self), &myerror);
if (!self->fssession)
{
- tf_content_error (TF_CONTENT (self),
- TF_FUTURE_CONTENT_REMOVAL_REASON_UNSUPPORTED, "",
+ tf_call_content_error (self,
+ TP_CALL_STATE_CHANGE_REASON_MEDIA_ERROR,
+ TP_ERROR_STR_MEDIA_UNSUPPORTED_TYPE,
"Could not create FsSession: %s", myerror->message);
g_simple_async_result_set_from_error (res, myerror);
g_simple_async_result_complete (res);
@@ -843,11 +1170,9 @@ got_content_media_properties (TpProxy *proxy, GHashTable *properties,
fs_element_added_notifier_add (self->notifier,
GST_BIN (self->fsconference));
- /* Now process outstanding streams */
- update_streams (self);
- gva = tp_asv_get_boxed (properties, "CodecOffer",
- TF_FUTURE_STRUCT_TYPE_CODEC_OFFERING);
+ gva = tp_asv_get_boxed (properties, "MediaDescriptionOffer",
+ TP_STRUCT_TYPE_MEDIA_DESCRIPTION_OFFER);
if (gva == NULL)
{
goto invalid_property;
@@ -867,16 +1192,41 @@ got_content_media_properties (TpProxy *proxy, GHashTable *properties,
}
/* First complete so we get signalled and the preferences can be set, then
- * start looking at the offer. We only unref the result later, to avoid
+ * start looking at the media_description. We only unref the result later, to avoid
* self possibly being disposed early */
g_simple_async_result_set_op_res_gboolean (res, TRUE);
g_simple_async_result_complete (res);
- tp_value_array_unpack (gva, 3, &offer_objpath, &contact, &codecs);
+ /* Now process outstanding streams */
+ add_initial_streams (self);
+
+ tp_g_signal_connect_object (self->proxy, "streams-added",
+ G_CALLBACK (streams_added), self, 0);
+ tp_g_signal_connect_object (self->proxy, "streams-removed",
+ G_CALLBACK (streams_removed), self, 0);
+
+ tp_value_array_unpack (gva, 2, &media_description_objpath,
+ &media_description_properties);
+
+ if (strcmp (media_description_objpath, "/"))
+ {
+ process_media_description (self, media_description_objpath,
+ media_description_properties);
+ }
+ self->got_media_description_property = TRUE;
- process_codec_offer (self, offer_objpath, contact, codecs);
- self->got_codec_offer_property = TRUE;
+ dtmf_state = tp_asv_get_uint32 (properties, "CurrentDTMFState", &valid);
+ if (!valid)
+ goto invalid_property;
+
+ dtmf_event_value = tp_asv_lookup (properties, "CurrentDTMFEvent");
+ if (!dtmf_event_value || !G_VALUE_HOLDS_UCHAR (dtmf_event_value))
+ goto invalid_property;
+ dtmf_event = g_value_get_uchar (dtmf_event_value);
+
+ on_content_dtmf_change_requested (NULL, dtmf_event, dtmf_state, NULL,
+ G_OBJECT (self));
/* The async result holds a ref to self which may be the last one, so this
* comes after we're done with self */
@@ -884,8 +1234,9 @@ got_content_media_properties (TpProxy *proxy, GHashTable *properties,
return;
invalid_property:
- tf_content_error_literal (TF_CONTENT (self),
- TF_FUTURE_CONTENT_REMOVAL_REASON_ERROR, "",
+ tf_call_content_error_literal (self,
+ TP_CALL_STATE_CHANGE_REASON_INTERNAL_ERROR,
+ TP_ERROR_STR_CONFUSED,
"Error getting the Content's properties: invalid type");
g_simple_async_result_set_error (res, G_IO_ERROR, G_IO_ERROR_NOT_FOUND,
"Error getting the Content's properties: invalid type");
@@ -895,13 +1246,30 @@ got_content_media_properties (TpProxy *proxy, GHashTable *properties,
}
static void
-setup_content_media_properties (TfCallContent *self,
- TpProxy *proxy,
- GSimpleAsyncResult *res)
+setup_content_media_properties (TfCallContent *self, GSimpleAsyncResult *res)
{
- tp_cli_dbus_properties_call_get_all (proxy, -1,
- TF_FUTURE_IFACE_CALL_CONTENT_INTERFACE_MEDIA,
+ GError *error = NULL;
+
+
+ if (tp_cli_call_content_interface_media_connect_to_dtmf_change_requested (
+ self->proxy, on_content_dtmf_change_requested,
+ NULL, NULL, G_OBJECT (self), &error) == NULL)
+ goto connect_failed;
+
+ tp_cli_dbus_properties_call_get_all (TP_PROXY (self->proxy), -1,
+ TP_IFACE_CALL_CONTENT_INTERFACE_MEDIA,
got_content_media_properties, res, NULL, G_OBJECT (self));
+
+ return;
+connect_failed:
+ tf_call_content_error (self,
+ TP_CALL_STATE_CHANGE_REASON_INTERNAL_ERROR,
+ TP_ERROR_STR_CONFUSED,
+ "Could not connect to the DTMFChangeRequested signal: %s",
+ error->message);
+ g_simple_async_result_take_error (res, error);
+ g_simple_async_result_complete (res);
+ g_object_unref (res);
}
static void
@@ -934,10 +1302,10 @@ on_content_audio_control_properties_changed (TpProxy *proxy,
gpointer user_data,
GObject *weak_object)
{
- TfCallContent *self = TF_CALL_CONTENT (weak_object);
+ TfCallContent *self = TF_CALL_CONTENT (proxy);
if (tp_strdiff (interface_name,
- TF_FUTURE_IFACE_CALL_CONTENT_INTERFACE_AUDIO_CONTROL))
+ TP_IFACE_CALL_CONTENT_INTERFACE_AUDIO_CONTROL))
return;
/* Guard against early disposal */
@@ -951,13 +1319,14 @@ static void
got_content_audio_control_properties (TpProxy *proxy, GHashTable *properties,
const GError *error, gpointer user_data, GObject *weak_object)
{
- TfCallContent *self = TF_CALL_CONTENT (weak_object);
+ TfCallContent *self = TF_CALL_CONTENT (proxy);
GSimpleAsyncResult *res = user_data;
if (error)
{
- tf_content_error (TF_CONTENT (self),
- TF_FUTURE_CONTENT_REMOVAL_REASON_ERROR, "",
+ tf_call_content_error (self,
+ TP_CALL_STATE_CHANGE_REASON_INTERNAL_ERROR,
+ TP_ERROR_STR_CONFUSED,
"Error getting the Content's AudioControl properties: %s",
error->message);
g_simple_async_result_set_from_error (res, error);
@@ -974,8 +1343,9 @@ got_content_audio_control_properties (TpProxy *proxy, GHashTable *properties,
if (properties == NULL)
{
- tf_content_error_literal (TF_CONTENT (self),
- TF_FUTURE_CONTENT_REMOVAL_REASON_ERROR, "",
+ tf_call_content_error_literal (self,
+ TP_CALL_STATE_CHANGE_REASON_INTERNAL_ERROR,
+ TP_ERROR_STR_CONFUSED,
"Error getting the Content's AudioControl properties: "
"there are none");
g_simple_async_result_set_error (res, G_IO_ERROR, G_IO_ERROR_NOT_FOUND,
@@ -986,7 +1356,7 @@ got_content_audio_control_properties (TpProxy *proxy, GHashTable *properties,
update_audio_control (self, properties);
- setup_content_media_properties (self, proxy, res);
+ setup_content_media_properties (self, res);
return;
error:
@@ -997,42 +1367,32 @@ error:
static void
setup_content_audio_control (TfCallContent *self,
- TpProxy *proxy,
GSimpleAsyncResult *res)
{
GError *error = NULL;
- tp_proxy_add_interface_by_id (proxy,
- TF_FUTURE_IFACE_QUARK_CALL_CONTENT_INTERFACE_AUDIO_CONTROL);
-
- if (tp_cli_dbus_properties_connect_to_properties_changed (proxy,
+ if (tp_cli_dbus_properties_connect_to_properties_changed (self,
on_content_audio_control_properties_changed,
- NULL, NULL, G_OBJECT (self), &error) == NULL)
+ NULL, NULL, NULL, &error) == NULL)
goto connect_failed;
- tp_cli_dbus_properties_call_get_all (proxy, -1,
- TF_FUTURE_IFACE_CALL_CONTENT_INTERFACE_AUDIO_CONTROL,
- got_content_audio_control_properties, res, NULL, G_OBJECT (self));
+ tp_cli_dbus_properties_call_get_all (self, -1,
+ TP_IFACE_CALL_CONTENT_INTERFACE_AUDIO_CONTROL,
+ got_content_audio_control_properties, res, NULL, NULL);
return;
connect_failed:
- tf_content_error (TF_CONTENT (self),
- TF_FUTURE_CONTENT_REMOVAL_REASON_ERROR, "",
- "Error getting the Content's AudioControl properties: %s",
+ tf_call_content_error (self,
+ TP_CALL_STATE_CHANGE_REASON_INTERNAL_ERROR,
+ TP_ERROR_STR_CONFUSED,
+ "Error getting the Content's VideoControl properties: %s",
error->message);
g_simple_async_result_take_error (res, error);
g_simple_async_result_complete (res);
g_object_unref (res);
}
-static gboolean
-object_has_property (GObject *object, const gchar *property)
-{
- return g_object_class_find_property (G_OBJECT_GET_CLASS (object),
- property) != NULL;
-}
-
static void
content_video_element_added (FsElementAddedNotifier *notifier,
GstBin *conference,
@@ -1079,8 +1439,9 @@ got_content_video_control_properties (TpProxy *proxy, GHashTable *properties,
if (error)
{
- tf_content_error (TF_CONTENT (self),
- TF_FUTURE_CONTENT_REMOVAL_REASON_ERROR, "",
+ tf_call_content_error (self,
+ TP_CALL_STATE_CHANGE_REASON_INTERNAL_ERROR,
+ TP_ERROR_STR_CONFUSED,
"Error getting the Content's VideoControl properties: %s",
error->message);
g_simple_async_result_set_from_error (res, error);
@@ -1097,8 +1458,9 @@ got_content_video_control_properties (TpProxy *proxy, GHashTable *properties,
if (properties == NULL)
{
- tf_content_error_literal (TF_CONTENT (self),
- TF_FUTURE_CONTENT_REMOVAL_REASON_ERROR, "",
+ tf_call_content_error_literal (self,
+ TP_CALL_STATE_CHANGE_REASON_INTERNAL_ERROR,
+ TP_ERROR_STR_CONFUSED,
"Error getting the Content's VideoControl properties: "
"there are none");
g_simple_async_result_set_error (res, G_IO_ERROR, G_IO_ERROR_NOT_FOUND,
@@ -1124,16 +1486,16 @@ got_content_video_control_properties (TpProxy *proxy, GHashTable *properties,
self->manual_keyframes = manual_keyframes;
array = tp_asv_get_boxed (properties, "VideoResolution",
- TF_FUTURE_STRUCT_TYPE_VIDEO_RESOLUTION);
+ TP_STRUCT_TYPE_VIDEO_RESOLUTION);
if (array)
- on_content_video_resolution_changed (TF_FUTURE_CALL_CONTENT (proxy), array,
+ on_content_video_resolution_changed (TP_CALL_CONTENT (proxy), array,
NULL, G_OBJECT (self));
self->notifier = fs_element_added_notifier_new ();
g_signal_connect (self->notifier, "element-added",
G_CALLBACK (content_video_element_added), self);
- setup_content_media_properties (self, proxy, res);
+ setup_content_media_properties (self, res);
return;
error:
@@ -1144,54 +1506,45 @@ error:
static void
-setup_content_video_control (TfCallContent *self,
- TpProxy *proxy,
- GSimpleAsyncResult *res)
+setup_content_video_control (TfCallContent *self, GSimpleAsyncResult *res)
{
GError *error = NULL;
- tp_proxy_add_interface_by_id (proxy,
- TF_FUTURE_IFACE_QUARK_CALL_CONTENT_INTERFACE_VIDEO_CONTROL);
-
- if (tf_future_cli_call_content_interface_video_control_connect_to_key_frame_requested (
- TF_FUTURE_CALL_CONTENT (proxy),
- on_content_video_keyframe_requested,
+ if (tp_cli_call_content_interface_video_control_connect_to_key_frame_requested (
+ self->proxy, on_content_video_keyframe_requested,
NULL, NULL, G_OBJECT (self), &error) == NULL)
goto connect_failed;
- if (tf_future_cli_call_content_interface_video_control_connect_to_video_resolution_changed (
- TF_FUTURE_CALL_CONTENT (proxy),
- on_content_video_resolution_changed,
+ if (tp_cli_call_content_interface_video_control_connect_to_video_resolution_changed (
+ self->proxy, on_content_video_resolution_changed,
NULL, NULL, G_OBJECT (self), &error) == NULL)
goto connect_failed;
- if (tf_future_cli_call_content_interface_video_control_connect_to_bitrate_changed (
- TF_FUTURE_CALL_CONTENT (proxy),
- on_content_video_bitrate_changed,
+ if (tp_cli_call_content_interface_video_control_connect_to_bitrate_changed (
+ self->proxy, on_content_video_bitrate_changed,
NULL, NULL, G_OBJECT (self), NULL) == NULL)
goto connect_failed;
- if (tf_future_cli_call_content_interface_video_control_connect_to_framerate_changed (
- TF_FUTURE_CALL_CONTENT (proxy),
- on_content_video_framerate_changed,
+ if (tp_cli_call_content_interface_video_control_connect_to_framerate_changed (
+ self->proxy, on_content_video_framerate_changed,
NULL, NULL, G_OBJECT (self), NULL) == NULL)
goto connect_failed;
- if (tf_future_cli_call_content_interface_video_control_connect_to_mtu_changed (
- TF_FUTURE_CALL_CONTENT (proxy),
- on_content_video_mtu_changed,
+ if (tp_cli_call_content_interface_video_control_connect_to_mtu_changed (
+ self->proxy, on_content_video_mtu_changed,
NULL, NULL, G_OBJECT (self), NULL) == NULL)
goto connect_failed;
- tp_cli_dbus_properties_call_get_all (proxy, -1,
- TF_FUTURE_IFACE_CALL_CONTENT_INTERFACE_VIDEO_CONTROL,
+ tp_cli_dbus_properties_call_get_all (TP_PROXY (self->proxy), -1,
+ TP_IFACE_CALL_CONTENT_INTERFACE_VIDEO_CONTROL,
got_content_video_control_properties, res, NULL, G_OBJECT (self));
return;
connect_failed:
- tf_content_error (TF_CONTENT (self),
- TF_FUTURE_CONTENT_REMOVAL_REASON_ERROR, "",
+ tf_call_content_error (self,
+ TP_CALL_STATE_CHANGE_REASON_INTERNAL_ERROR,
+ TP_ERROR_STR_CONFUSED,
"Error getting the Content's VideoControl properties: %s",
error->message);
g_simple_async_result_take_error (res, error);
@@ -1200,10 +1553,9 @@ connect_failed:
}
static void
-new_codec_offer (TfFutureCallContent *proxy,
- guint arg_Contact,
- const gchar *arg_Offer,
- const GPtrArray *arg_Codecs,
+new_media_description_offer (TpCallContent *proxy,
+ const gchar *arg_Media_Description,
+ GHashTable *arg_Properties,
gpointer user_data,
GObject *weak_object)
{
@@ -1213,42 +1565,40 @@ new_codec_offer (TfFutureCallContent *proxy,
if (self->call_channel == NULL)
return;
- /* Ignore signals before we get the first codec offer property */
- if (!self->got_codec_offer_property)
+ /* Ignore signals before we get the first codec MediaDescription property */
+ if (!self->got_media_description_property)
return;
- if (self->current_offer) {
- g_object_unref (self->current_offer);
- fs_codec_list_destroy (self->current_offer_fscodecs);
- self->current_offer = NULL;
- self->current_offer_fscodecs = NULL;
+ if (self->current_media_description) {
+ g_object_unref (self->current_media_description);
+ fs_codec_list_destroy (self->current_md_fscodecs);
+ fs_rtp_header_extension_list_destroy (self->current_md_rtp_hdrext);
+ self->current_media_description = NULL;
+ self->current_md_fscodecs = NULL;
+ self->current_md_rtp_hdrext = NULL;
}
- process_codec_offer (self, arg_Offer, arg_Contact, arg_Codecs);
+ process_media_description (self, arg_Media_Description, arg_Properties);
}
static void
-got_content_properties (TpProxy *proxy, GHashTable *out_Properties,
- const GError *error, gpointer user_data, GObject *weak_object)
+content_prepared (GObject *src, GAsyncResult *prepare_res,
+ gpointer user_data)
{
- TfCallContent *self = TF_CALL_CONTENT (weak_object);
+ TpCallContent *proxy = TP_CALL_CONTENT (src);
GSimpleAsyncResult *res = user_data;
- gboolean valid;
- GPtrArray *streams;
- GError *myerror = NULL;
- guint i;
- const gchar * const *interfaces;
- gboolean got_media_interface = FALSE;
- gboolean got_audio_control_interface = FALSE;
- gboolean got_video_control_interface = FALSE;
+ TfCallContent *self =
+ TF_CALL_CONTENT (g_async_result_get_source_object (G_ASYNC_RESULT (res)));
+ GError *error = NULL;
- if (error)
+ if (!tp_proxy_prepare_finish (proxy, prepare_res, &error))
{
- tf_content_error (TF_CONTENT (self),
- TF_FUTURE_CONTENT_REMOVAL_REASON_ERROR, "",
+ tf_call_content_error (self,
+ TP_CALL_STATE_CHANGE_REASON_INTERNAL_ERROR,
+ TP_ERROR_STR_CONFUSED,
"Error getting the Content's properties: %s", error->message);
- g_simple_async_result_set_from_error (res, error);
+ g_simple_async_result_take_error (res, error);
g_simple_async_result_complete (res);
g_object_unref (res);
return;
@@ -1264,53 +1614,12 @@ got_content_properties (TpProxy *proxy, GHashTable *out_Properties,
return;
}
- if (!out_Properties)
- {
- tf_content_error_literal (TF_CONTENT (self),
- TF_FUTURE_CONTENT_REMOVAL_REASON_ERROR, "",
- "Error getting the Content's properties: there are none");
- g_simple_async_result_set_error (res, G_IO_ERROR, G_IO_ERROR_NOT_FOUND,
- "Error getting the Content's properties: there are none");
- g_simple_async_result_complete (res);
- g_object_unref (res);
- return;
- }
-
- interfaces = tp_asv_get_strv (out_Properties, "Interfaces");
-
- if (interfaces == NULL)
- {
- tf_content_error_literal (TF_CONTENT (self),
- TF_FUTURE_CONTENT_REMOVAL_REASON_ERROR, "",
- "Content does not have the Interfaces property, "
- "but HardwareStreaming was NOT true");
- g_simple_async_result_set_error (res, G_IO_ERROR, G_IO_ERROR_NOT_FOUND,
- "Content does not have the Interfaces property, "
- "but HardwareStreaming was NOT true");
- g_simple_async_result_complete (res);
- g_object_unref (res);
- return;
- }
-
- for (i = 0; interfaces[i]; i++)
+ if (!tp_proxy_has_interface_by_id (proxy,
+ TP_IFACE_QUARK_CALL_CONTENT_INTERFACE_MEDIA))
{
- if (!strcmp (interfaces[i],
- TF_FUTURE_IFACE_CALL_CONTENT_INTERFACE_MEDIA))
- got_media_interface = TRUE;
-
- if (!strcmp (interfaces[i],
- TF_FUTURE_IFACE_CALL_CONTENT_INTERFACE_AUDIO_CONTROL))
- got_audio_control_interface = TRUE;
-
- if (!strcmp (interfaces[i],
- TF_FUTURE_IFACE_CALL_CONTENT_INTERFACE_VIDEO_CONTROL))
- got_video_control_interface = TRUE;
- }
-
- if (!got_media_interface)
- {
- tf_content_error_literal (TF_CONTENT (self),
- TF_FUTURE_CONTENT_REMOVAL_REASON_ERROR, "",
+ tf_call_content_error_literal (self,
+ TP_CALL_STATE_CHANGE_REASON_INTERNAL_ERROR,
+ TP_ERROR_STR_CONFUSED,
"Content does not have the media interface,"
" but HardwareStreaming was NOT true");
g_simple_async_result_set_error (res, G_IO_ERROR, G_IO_ERROR_NOT_FOUND,
@@ -1321,96 +1630,36 @@ got_content_properties (TpProxy *proxy, GHashTable *out_Properties,
return;
}
- self->media_type = tp_asv_get_uint32 (out_Properties, "Type", &valid);
- if (!valid)
- goto invalid_property;
-
-
- streams = tp_asv_get_boxed (out_Properties, "Streams",
- TP_ARRAY_TYPE_OBJECT_PATH_LIST);
- if (!streams)
- goto invalid_property;
-
- self->streams = g_hash_table_new_full (g_str_hash, g_str_equal,
- g_free, g_object_unref);
-
- for (i = 0; i < streams->len; i++)
- add_stream (self, g_ptr_array_index (streams, i));
-
- tp_proxy_add_interface_by_id (TP_PROXY (self->proxy),
- TF_FUTURE_IFACE_QUARK_CALL_CONTENT_INTERFACE_MEDIA);
+ self->streams = g_ptr_array_new_with_free_func (g_object_unref);
+ tp_cli_call_content_interface_media_connect_to_new_media_description_offer (
+ self->proxy, new_media_description_offer, NULL, NULL,
+ G_OBJECT (self), &error);
- tf_future_cli_call_content_interface_media_connect_to_new_codec_offer (
- TF_FUTURE_CALL_CONTENT (proxy), new_codec_offer, NULL, NULL,
- G_OBJECT (self), &myerror);
-
- if (myerror)
+ if (error)
{
- tf_content_error (TF_CONTENT (self),
- TF_FUTURE_CONTENT_REMOVAL_REASON_ERROR, "",
- "Error connectiong to NewCodecOffer signal: %s",
- myerror->message);
- g_simple_async_result_set_from_error (res, myerror);
+ tf_call_content_error (self,
+ TP_CALL_STATE_CHANGE_REASON_INTERNAL_ERROR,
+ TP_ERROR_STR_CONFUSED,
+ "Error connecting to NewCodecMediaDescription signal: %s",
+ error->message);
+ g_simple_async_result_set_from_error (res, error);
g_simple_async_result_complete (res);
g_object_unref (res);
- g_clear_error (&myerror);
+ g_clear_error (&error);
return;
}
- if (got_audio_control_interface)
- setup_content_audio_control (self, proxy, res);
- else if (got_video_control_interface)
- setup_content_video_control (self, proxy, res);
+ if (tp_proxy_has_interface_by_id (proxy,
+ TP_IFACE_QUARK_CALL_CONTENT_INTERFACE_AUDIO_CONTROL))
+ setup_content_audio_control (self, res);
+ else if (tp_proxy_has_interface_by_id (proxy,
+ TP_IFACE_QUARK_CALL_CONTENT_INTERFACE_VIDEO_CONTROL))
+ setup_content_video_control (self, res);
else
- setup_content_media_properties (self, proxy, res);
+ setup_content_media_properties (self, res);
return;
-
- invalid_property:
- tf_content_error_literal (TF_CONTENT (self), TF_FUTURE_CONTENT_REMOVAL_REASON_ERROR,
- "", "Error getting the Content's properties: invalid type");
- g_simple_async_result_set_error (res, G_IO_ERROR, G_IO_ERROR_NOT_FOUND,
- "Error getting the Content's properties: invalid type");
- g_simple_async_result_complete (res);
- g_object_unref (res);
- return;
-}
-
-static void
-streams_added (TfFutureCallContent *proxy,
- const GPtrArray *arg_Streams,
- gpointer user_data,
- GObject *weak_object)
-{
- TfCallContent *self = TF_CALL_CONTENT (weak_object);
- guint i;
-
- /* Ignore signals before we got the "Contents" property to avoid races that
- * could cause the same content to be added twice
- */
-
- if (!self->streams)
- return;
-
- for (i = 0; i < arg_Streams->len; i++)
- add_stream (self, g_ptr_array_index (arg_Streams, i));
-}
-
-static void
-streams_removed (TfFutureCallContent *proxy,
- const GPtrArray *arg_Streams,
- gpointer user_data,
- GObject *weak_object)
-{
- TfCallContent *self = TF_CALL_CONTENT (weak_object);
- guint i;
-
- if (!self->streams)
- return;
-
- for (i = 0; i < arg_Streams->len; i++)
- g_hash_table_remove (self->streams, g_ptr_array_index (arg_Streams, i));
}
@@ -1422,7 +1671,6 @@ tf_call_content_init_async (GAsyncInitable *initable,
gpointer user_data)
{
TfCallContent *self = TF_CALL_CONTENT (initable);
- GError *myerror = NULL;
GSimpleAsyncResult *res;
if (cancellable != NULL)
@@ -1433,39 +1681,11 @@ tf_call_content_init_async (GAsyncInitable *initable,
return;
}
- tf_future_cli_call_content_connect_to_streams_added (
- TF_FUTURE_CALL_CONTENT (self->proxy), streams_added, NULL, NULL,
- G_OBJECT (self), &myerror);
- if (myerror)
- {
- tf_content_error (TF_CONTENT (self),
- TF_FUTURE_CONTENT_REMOVAL_REASON_ERROR, "",
- "Error connectiong to StreamAdded signal: %s", myerror->message);
- g_simple_async_report_gerror_in_idle (G_OBJECT (self), callback,
- user_data, myerror);
- return;
- }
-
- tf_future_cli_call_content_connect_to_streams_removed (
- TF_FUTURE_CALL_CONTENT (self->proxy), streams_removed, NULL, NULL,
- G_OBJECT (self), &myerror);
- if (myerror)
- {
- tf_content_error (TF_CONTENT (self),
- TF_FUTURE_CONTENT_REMOVAL_REASON_ERROR, "",
- "Error connectiong to StreamRemoved signal: %s", myerror->message);
- g_simple_async_report_gerror_in_idle (G_OBJECT (self), callback,
- user_data, myerror);
- return;
- }
-
res = g_simple_async_result_new (G_OBJECT (self), callback, user_data,
tf_call_content_init_async);
- tp_cli_dbus_properties_call_get_all (self->proxy, -1,
- TF_FUTURE_IFACE_CALL_CONTENT, got_content_properties, res,
- NULL, G_OBJECT (self));
+ tp_proxy_prepare_async (self->proxy, NULL, content_prepared, res);
}
static gboolean
@@ -1487,34 +1707,67 @@ tf_call_content_init_finish (GAsyncInitable *initable,
TfCallContent *
tf_call_content_new_async (TfCallChannel *call_channel,
- const gchar *object_path, GError **error,
+ TpCallContent *content_proxy, GError **error,
GAsyncReadyCallback callback, gpointer user_data)
{
TfCallContent *self;
- TfFutureCallContent *proxy = tf_future_call_content_new (
- call_channel->proxy, object_path, error);
- if (!proxy)
- return NULL;
+ g_return_val_if_fail (call_channel != NULL, NULL);
+ g_return_val_if_fail (content_proxy != NULL, NULL);
self = g_object_new (TF_TYPE_CALL_CONTENT, NULL);
self->call_channel = call_channel;
- self->proxy = proxy;
+ self->proxy = g_object_ref (content_proxy);
g_async_initable_init_async (G_ASYNC_INITABLE (self), 0, NULL,
callback, user_data);
- return g_object_ref (self);
+ return self;
}
+static gboolean
+find_codec (GList *codecs, FsCodec *codec)
+{
+ GList *item;
+
+ for (item = codecs; item ; item = item->next)
+ if (fs_codec_are_equal (item->data, codec))
+ return TRUE;
+
+ return FALSE;
+}
-static GPtrArray *
-fscodecs_to_tpcodecs (GList *codecs)
+static GHashTable *
+fscodecs_to_media_descriptions (TfCallContent *self, GList *codecs)
{
GPtrArray *tpcodecs = g_ptr_array_new ();
GList *item;
+ GList *resend_codecs = NULL;
+ GHashTable *retval;
+ GPtrArray *rtp_hdrext = NULL;
+ GHashTable *rtcp_fb = NULL;
+ GPtrArray *interfaces;
+
+ if (self->last_sent_codecs)
+ resend_codecs = fs_session_codecs_need_resend (self->fssession,
+ self->last_sent_codecs, codecs);
+
+ if (!self->current_media_description && !resend_codecs)
+ return NULL;
+
+ if ((self->current_media_description && self->current_has_rtp_hdrext)
+ || self->has_rtp_hdrext)
+ rtp_hdrext = dbus_g_type_specialized_construct (
+ TP_ARRAY_TYPE_RTP_HEADER_EXTENSIONS_LIST);
+
+ if ((self->current_media_description && self->current_has_rtcp_fb)
+ || self->has_rtcp_fb)
+ rtcp_fb = dbus_g_type_specialized_construct (
+ TP_HASH_TYPE_RTCP_FEEDBACK_MESSAGE_MAP);
+
+ g_debug ("Local codecs:");
for (item = codecs; item; item = item->next)
{
@@ -1522,6 +1775,12 @@ fscodecs_to_tpcodecs (GList *codecs)
GValue tpcodec = { 0, };
GHashTable *params;
GList *param_item;
+ gboolean updated;
+ gchar *tmp;
+
+ tmp = fs_codec_to_string (fscodec);
+ g_debug ("%s", tmp);
+ g_free (tmp);
params = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free);
@@ -1535,37 +1794,130 @@ fscodecs_to_tpcodecs (GList *codecs)
g_strdup (param->value));
}
- g_value_init (&tpcodec, TF_FUTURE_STRUCT_TYPE_CODEC);
+ updated = find_codec (resend_codecs, fscodec);
+
+ g_value_init (&tpcodec, TP_STRUCT_TYPE_CODEC);
g_value_take_boxed (&tpcodec,
- dbus_g_type_specialized_construct (TF_FUTURE_STRUCT_TYPE_CODEC));
+ dbus_g_type_specialized_construct (TP_STRUCT_TYPE_CODEC));
dbus_g_type_struct_set (&tpcodec,
0, fscodec->id,
1, fscodec->encoding_name,
2, fscodec->clock_rate,
3, fscodec->channels,
- 4, params,
+ 4, updated,
+ 5, params,
G_MAXUINT);
g_hash_table_destroy (params);
g_ptr_array_add (tpcodecs, g_value_get_boxed (&tpcodec));
+
+ if (rtcp_fb != NULL &&
+ (fscodec->minimum_reporting_interval != G_MAXUINT ||
+ fscodec->feedback_params))
+ {
+ GPtrArray *messages = g_ptr_array_new ();
+ GList *item2;
+
+ for (item2 = fscodec->feedback_params; item2; item2 = item2->next)
+ {
+ FsFeedbackParameter *fb = item2->data;
+
+ g_ptr_array_add (messages, tp_value_array_build (3,
+ G_TYPE_STRING, fb->type,
+ G_TYPE_STRING, fb->subtype,
+ G_TYPE_STRING, fb->extra_params,
+ G_TYPE_INVALID));
+ }
+
+ g_hash_table_insert (rtcp_fb, GUINT_TO_POINTER (fscodec->id),
+ tp_value_array_build (2,
+ G_TYPE_UINT,
+ fscodec->minimum_reporting_interval != G_MAXUINT ?
+ fscodec->minimum_reporting_interval : 5000,
+ TP_ARRAY_TYPE_RTCP_FEEDBACK_MESSAGE_LIST, messages,
+ G_TYPE_INVALID));
+
+ g_boxed_free (TP_ARRAY_TYPE_RTCP_FEEDBACK_MESSAGE_LIST, messages);
+ }
+ }
+
+ fs_codec_list_destroy (resend_codecs);
+
+
+ if (rtp_hdrext)
+ {
+ GList *fs_rtp_hdrexts;
+
+ g_object_get (self->fssession, "rtp-header-extensions", &fs_rtp_hdrexts,
+ NULL);
+
+ for (item = fs_rtp_hdrexts; item; item = item->next)
+ {
+ FsRtpHeaderExtension *hdrext = item->data;
+
+ g_debug (FS_RTP_HEADER_EXTENSION_FORMAT,
+ FS_RTP_HEADER_EXTENSION_ARGS (hdrext));
+
+ g_ptr_array_add (rtp_hdrext, tp_value_array_build (4,
+ G_TYPE_UINT, hdrext->id,
+ G_TYPE_UINT, fsdirection_to_tpdirection (hdrext->direction),
+ G_TYPE_STRING, hdrext->uri,
+ G_TYPE_STRING, "",
+ G_TYPE_INVALID));
+ }
+
+ fs_rtp_header_extension_list_destroy (fs_rtp_hdrexts);
}
- return tpcodecs;
+ retval = tp_asv_new (
+ TP_PROP_CALL_CONTENT_MEDIA_DESCRIPTION_CODECS,
+ TP_ARRAY_TYPE_CODEC_LIST, tpcodecs,
+ TP_PROP_CALL_CONTENT_MEDIA_DESCRIPTION_FURTHER_NEGOTIATION_REQUIRED,
+ G_TYPE_BOOLEAN, !!resend_codecs,
+ NULL);
+
+ interfaces = g_ptr_array_new ();
+
+ if (rtp_hdrext)
+ {
+ tp_asv_take_boxed (retval, TP_PROP_CALL_CONTENT_MEDIA_DESCRIPTION_INTERFACE_RTP_HEADER_EXTENSIONS_HEADER_EXTENSIONS,
+ TP_ARRAY_TYPE_RTP_HEADER_EXTENSIONS_LIST,
+ rtp_hdrext);
+ g_ptr_array_add (interfaces,
+ g_strdup (TP_IFACE_CALL_CONTENT_MEDIA_DESCRIPTION_INTERFACE_RTP_HEADER_EXTENSIONS));
+ }
+
+ if (rtcp_fb)
+ {
+ tp_asv_set_boolean (retval, TP_PROP_CALL_CONTENT_MEDIA_DESCRIPTION_INTERFACE_RTCP_FEEDBACK_DOES_AVPF, g_hash_table_size (rtcp_fb));
+ tp_asv_take_boxed (retval, TP_PROP_CALL_CONTENT_MEDIA_DESCRIPTION_INTERFACE_RTCP_FEEDBACK_FEEDBACK_MESSAGES,
+ TP_HASH_TYPE_RTCP_FEEDBACK_MESSAGE_MAP, rtcp_fb);
+ g_ptr_array_add (interfaces,
+ g_strdup (TP_IFACE_CALL_CONTENT_MEDIA_DESCRIPTION_INTERFACE_RTP_HEADER_EXTENSIONS));
+ }
+
+ g_ptr_array_add (interfaces, NULL);
+ tp_asv_take_boxed (retval, TP_PROP_CALL_CONTENT_MEDIA_DESCRIPTION_INTERFACES,
+ G_TYPE_STRV, interfaces->pdata);
+ g_ptr_array_free (interfaces, FALSE);
+
+ return retval;
}
static void
tf_call_content_try_sending_codecs (TfCallContent *self)
{
GList *codecs;
- GPtrArray *tpcodecs;
+ GHashTable *media_description;
const gchar *codecs_prop = NULL;
- if (self->current_offer_fscodecs != NULL)
+ if (self->current_md_fscodecs != NULL)
{
- g_debug ("Ignoring updated codecs unprocessed offer outstanding");
+ g_debug ("Ignoring updated codecs unprocessed media description"
+ " outstanding");
return;
}
@@ -1581,40 +1933,123 @@ tf_call_content_try_sending_codecs (TfCallContent *self)
if (!codecs)
return;
- if (fs_codec_list_are_equal (codecs, self->current_codecs))
+ if (fs_codec_list_are_equal (codecs, self->last_sent_codecs))
{
fs_codec_list_destroy (codecs);
return;
}
- tpcodecs = fscodecs_to_tpcodecs (codecs);
+ media_description = fscodecs_to_media_descriptions (self, codecs);
- if (self->current_offer)
+ if (self->current_media_description)
{
- tf_future_cli_call_content_codec_offer_call_accept (self->current_offer,
- -1, tpcodecs, NULL, NULL, NULL, NULL);
+ g_debug ("Accepting Media Description");
+
+ tp_cli_call_content_media_description_call_accept (
+ self->current_media_description, -1, media_description,
+ NULL, NULL, NULL, NULL);
- g_object_unref (self->current_offer);
- self->current_offer = NULL;
+ g_object_unref (self->current_media_description);
+ self->current_media_description = NULL;
}
else
{
- tf_future_cli_call_content_interface_media_call_update_codecs (
- self->proxy, -1, tpcodecs, NULL, NULL, NULL, NULL);
+ if (media_description)
+ {
+ g_debug ("Updating local Media Description");
+ tp_cli_call_content_interface_media_call_update_local_media_description (
+ self->proxy, -1, media_description, NULL, NULL, NULL, NULL);
+ }
+ else
+ {
+ fs_codec_list_destroy (codecs);
+ }
}
- g_boxed_free (TF_FUTURE_ARRAY_TYPE_CODEC_LIST, tpcodecs);
+ if (media_description)
+ {
+ fs_codec_list_destroy (self->last_sent_codecs);
+ self->last_sent_codecs = codecs;
+ self->has_rtcp_fb = self->current_has_rtcp_fb;
+ self->has_rtp_hdrext = self->current_has_rtp_hdrext;
+
+ g_boxed_free (TP_HASH_TYPE_MEDIA_DESCRIPTION_PROPERTIES, media_description);
+ }
}
+static void
+tf_call_content_dtmf_started (TfCallContent *self, FsDTMFMethod method,
+ FsDTMFEvent event, guint8 volume)
+{
+ if (volume != DTMF_TONE_VOLUME)
+ {
+ tf_call_content_error (self,
+ TP_CALL_STATE_CHANGE_REASON_INTERNAL_ERROR,
+ TP_ERROR_STR_MEDIA_STREAMING_ERROR,
+ "DTMF volume is %d, while we use %d", volume, DTMF_TONE_VOLUME);
+ return;
+ }
+
+ if (self->dtmf_sending_state != TP_SENDING_STATE_PENDING_SEND)
+ {
+ tf_call_content_error (self,
+ TP_CALL_STATE_CHANGE_REASON_INTERNAL_ERROR,
+ TP_ERROR_STR_MEDIA_STREAMING_ERROR,
+ "Farstream started a DTMFevent, but we were in the %d state",
+ self->dtmf_sending_state);
+ return;
+ }
+
+ if (self->current_dtmf_event != event)
+ {
+ tf_call_content_error (self,
+ TP_CALL_STATE_CHANGE_REASON_INTERNAL_ERROR,
+ TP_ERROR_STR_MEDIA_STREAMING_ERROR,
+ "Farstream started the wrong dtmf event, got %d but "
+ "expected %d", event, self->current_dtmf_event);
+ return;
+ }
+
+ tp_cli_call_content_interface_media_call_acknowledge_dtmf_change (
+ self->proxy, -1, event, TP_SENDING_STATE_SENDING,
+ NULL, NULL, NULL, NULL);
+ self->dtmf_sending_state = TP_SENDING_STATE_SENDING;
+}
+
+static void
+tf_call_content_dtmf_stopped (TfCallContent *self, FsDTMFMethod method)
+{
+ if (self->dtmf_sending_state != TP_SENDING_STATE_PENDING_STOP_SENDING)
+ {
+ tf_call_content_error (self,
+ TP_CALL_STATE_CHANGE_REASON_INTERNAL_ERROR,
+ TP_ERROR_STR_MEDIA_STREAMING_ERROR,
+ "Farstream stopped a DTMFevent, but we were in the %d state",
+ self->dtmf_sending_state);
+ return;
+ }
+
+ tp_cli_call_content_interface_media_call_acknowledge_dtmf_change (
+ self->proxy, -1, self->current_dtmf_event, TP_SENDING_STATE_NONE,
+ NULL, NULL, NULL, NULL);
+ self->dtmf_sending_state = TP_SENDING_STATE_NONE;
+}
+
+
gboolean
tf_call_content_bus_message (TfCallContent *content,
GstMessage *message)
{
- const GstStructure *s;
- gboolean ret = FALSE;
- const gchar *debug;
- GHashTableIter iter;
- gpointer key, value;
+ gboolean ret = TRUE;
+ FsDTMFMethod method;
+ FsDTMFEvent event;
+ guint8 volume;
+ FsCodec *codec;
+ GList *secondary_codecs;
+ FsError error_no;
+ const gchar *error_msg;
+ guint i;
+
/* Guard against early disposal */
if (content->call_channel == NULL)
@@ -1626,81 +2061,123 @@ tf_call_content_bus_message (TfCallContent *content,
if (GST_MESSAGE_TYPE (message) != GST_MESSAGE_ELEMENT)
return FALSE;
- s = gst_message_get_structure (message);
- if (gst_structure_has_name (s, "farstream-error"))
+ if (fs_parse_error (G_OBJECT (content->fssession), message, &error_no,
+ &error_msg))
{
- GObject *object;
- const GValue *value = NULL;
-
- value = gst_structure_get_value (s, "src-object");
- object = g_value_get_object (value);
-
- if (object == (GObject*) content->fssession)
- {
- const gchar *msg;
- FsError errorno;
- GEnumClass *enumclass;
- GEnumValue *enumvalue;
-
- value = gst_structure_get_value (s, "error-no");
- errorno = g_value_get_enum (value);
- msg = gst_structure_get_string (s, "error-msg");
- debug = gst_structure_get_string (s, "debug-msg");
-
- enumclass = g_type_class_ref (FS_TYPE_ERROR);
- enumvalue = g_enum_get_value (enumclass, errorno);
- g_warning ("error (%s (%d)): %s : %s",
- enumvalue->value_nick, errorno, msg, debug);
- g_type_class_unref (enumclass);
-
- tf_content_error_literal (TF_CONTENT (content),
- TF_FUTURE_CONTENT_REMOVAL_REASON_ERROR, "", msg);
-
- ret = TRUE;
- }
+ GEnumClass *enumclass;
+ GEnumValue *enumvalue;
+
+ enumclass = g_type_class_ref (FS_TYPE_ERROR);
+ enumvalue = g_enum_get_value (enumclass, error_no);
+ g_warning ("error (%s (%d)): %s",
+ enumvalue->value_nick, error_no, error_msg);
+ g_type_class_unref (enumclass);
+
+ tf_call_content_error_literal (content,
+ TP_CALL_STATE_CHANGE_REASON_INTERNAL_ERROR,
+ TP_ERROR_STR_MEDIA_STREAMING_ERROR, error_msg);
}
- else if (gst_structure_has_name (s, "farstream-codecs-changed"))
+ else if (fs_session_parse_codecs_changed (content->fssession, message))
{
- FsSession *fssession;
- const GValue *value;
+ g_debug ("Codecs changed");
- value = gst_structure_get_value (s, "session");
- fssession = g_value_get_object (value);
+ tf_call_content_try_sending_codecs (content);
+ }
+ else if (fs_session_parse_telephony_event_started (content->fssession,
+ message, &method, &event, &volume))
+ {
+ g_debug ("DTMF started: method: %d event: %u volume: %u",
+ method, event, volume);
- if (fssession != content->fssession)
- return FALSE;
+ tf_call_content_dtmf_started (content, method, event, volume);
+ }
+ else if (fs_session_parse_telephony_event_stopped (content->fssession,
+ message, &method))
+ {
+ g_debug ("DTMF stopped: method: %d", method);
- g_debug ("Codecs changed");
+ tf_call_content_dtmf_stopped (content, method);
+ }
+ else if (fs_session_parse_send_codec_changed (content->fssession, message,
+ &codec, &secondary_codecs))
+ {
+ gchar *tmp;
+ guint i = 1;
- tf_call_content_try_sending_codecs (content);
+ tmp = fs_codec_to_string (codec);
+ g_debug ("Send codec changed: %s", tmp);
+ g_free (tmp);
- ret = TRUE;
+ while (secondary_codecs)
+ {
+ tmp = fs_codec_to_string (secondary_codecs->data);
+ g_debug ("Secondary send codec %u changed: %s", i++, tmp);
+ g_free (tmp);
+ secondary_codecs = secondary_codecs->next;
+ }
+ }
+ else
+ {
+ ret = FALSE;
}
- g_hash_table_iter_init (&iter, content->streams);
- while (g_hash_table_iter_next (&iter, &key, &value))
- if (tf_call_stream_bus_message (value, message))
+ for (i = 0; i < content->streams->len; i++)
+ if (tf_call_stream_bus_message (g_ptr_array_index (content->streams, i),
+ message))
return TRUE;
return ret;
}
+
static void
-tf_call_content_error (TfContent *content,
- guint reason, /* TfFutureContentRemovalReason */
+tf_call_content_error (TfCallContent *self,
+ TpCallStateChangeReason reason,
const gchar *detailed_reason,
- const gchar *message)
+ const gchar *message_format,
+ ...)
{
- TfCallContent *self = TF_CALL_CONTENT (content);
+ gchar *message;
+ va_list valist;
+
+ va_start (valist, message_format);
+ message = g_strdup_vprintf (message_format, valist);
+ va_end (valist);
+
+ tf_call_content_error_literal (self, reason, detailed_reason, message);
+ g_free (message);
+}
+
+static void
+tf_call_content_error_literal (TfCallContent *self,
+ TpCallStateChangeReason reason,
+ const gchar *detailed_reason,
+ const gchar *message)
+{
g_warning ("%s", message);
- tf_future_cli_call_content_call_remove (
- self->proxy, -1, reason, detailed_reason, message, NULL, NULL,
- NULL, NULL);
+ tp_cli_call_content_interface_media_call_fail (
+ self->proxy, -1,
+ tp_value_array_build (4,
+ G_TYPE_UINT, 0,
+ G_TYPE_UINT, reason,
+ G_TYPE_STRING, detailed_reason,
+ G_TYPE_STRING, message,
+ G_TYPE_INVALID),
+ NULL, NULL, NULL, NULL);
}
+static void
+tf_call_content_error_impl (TfContent *content,
+ const gchar *message)
+{
+ tf_call_content_error_literal (TF_CALL_CONTENT (content),
+ TP_CALL_STATE_CHANGE_REASON_INTERNAL_ERROR,
+ TP_ERROR_STR_MEDIA_STREAMING_ERROR, message);
+}
+
static FsStream *
tf_call_content_get_existing_fsstream_by_handle (TfCallContent *content,
@@ -1731,6 +2208,7 @@ tf_call_content_get_existing_fsstream_by_handle (TfCallContent *content,
FsStream *
_tf_call_content_get_fsstream_by_handle (TfCallContent *content,
guint contact_handle,
+ FsStreamDirection dir,
const gchar *transmitter,
guint stream_transmitter_n_parameters,
GParameter *stream_transmitter_parameters,
@@ -1750,7 +2228,7 @@ _tf_call_content_get_fsstream_by_handle (TfCallContent *content,
if (!p)
return NULL;
- s = fs_session_new_stream (content->fssession, p, FS_DIRECTION_RECV, error);
+ s = fs_session_new_stream (content->fssession, p, dir, error);
if (!s)
{
_tf_call_channel_put_participant (content->call_channel, p);
@@ -1778,17 +2256,20 @@ _tf_call_content_get_fsstream_by_handle (TfCallContent *content,
g_ptr_array_add (content->fsstreams, cfs);
content->fsstreams_cookie ++;
- if (content->current_offer != NULL
- && content->current_offer_contact_handle == contact_handle)
+ if (content->current_media_description != NULL
+ && content->current_md_contact_handle == contact_handle)
{
- GList *codecs = content->current_offer_fscodecs;
- TpProxy *current_offer = content->current_offer;
- content->current_offer_fscodecs = NULL;
- content->current_offer = NULL;
+ GList *codecs = content->current_md_fscodecs;
+ TpProxy *current_media_description = content->current_media_description;
+ GList *rtp_hdrext = content->current_md_rtp_hdrext;
+
+ content->current_md_fscodecs = NULL;
+ content->current_media_description = NULL;
+ content->current_md_rtp_hdrext = NULL;
/* ownership transfers to try_codecs */
- process_codec_offer_try_codecs (content, s,
- current_offer, codecs);
+ process_media_description_try_codecs (content, s,
+ current_media_description, codecs, rtp_hdrext);
}
return s;
@@ -1825,7 +2306,7 @@ _tf_call_content_put_fsstream (TfCallContent *content, FsStream *fsstream)
FsMediaType
tf_call_content_get_fs_media_type (TfCallContent *content)
{
- return tp_media_type_to_fs (content->media_type);
+ return tp_media_type_to_fs (tp_call_content_get_media_type (content->proxy));
}
static void
@@ -1947,3 +2428,50 @@ tf_call_content_iterate_src_pads (TfContent *content, guint *handles,
return (GstIterator *) iter;
}
+
+static void
+tf_call_content_sending_failed (TfContent *content,
+ const gchar *message)
+{
+ TfCallContent *self = TF_CALL_CONTENT (content);
+ guint i;
+
+ if (!self->streams)
+ {
+ g_warning ("Too early, ignoring sending error");
+ return;
+ }
+
+ for (i = 0; i < self->streams->len; i++)
+ tf_call_stream_sending_failed (g_ptr_array_index (self->streams, i),
+ message);
+}
+
+
+static void
+tf_call_content_receiving_failed (TfContent *content,
+ guint *handles, guint handle_count,
+ const gchar *message)
+{
+ TfCallContent *self = TF_CALL_CONTENT (content);
+ guint i;
+
+ if (!self->streams)
+ {
+ g_warning ("Too early, ignoring sending error");
+ return;
+ }
+
+ for (i = 0; i < self->streams->len; i++)
+ tf_call_stream_receiving_failed (g_ptr_array_index (self->streams, i),
+ handles, handle_count, message);
+}
+
+
+TpCallContent *
+tf_call_content_get_proxy (TfCallContent *content)
+{
+ g_return_val_if_fail (TF_IS_CALL_CONTENT (content), NULL);
+
+ return content->proxy;
+}
diff --git a/telepathy-farstream/call-content.h b/telepathy-farstream/call-content.h
index 697148e..499eead 100644
--- a/telepathy-farstream/call-content.h
+++ b/telepathy-farstream/call-content.h
@@ -23,9 +23,8 @@
#include <glib-object.h>
#include <gst/gst.h>
-#include <telepathy-glib/channel.h>
+#include <telepathy-glib/telepathy-glib.h>
-#include "extensions/extensions.h"
#include "call-channel.h"
#include "content.h"
#include "content-priv.h"
@@ -75,7 +74,7 @@ GType tf_call_content_get_type (void);
TfCallContent *tf_call_content_new_async (
TfCallChannel *call_channel,
- const gchar *object_path,
+ TpCallContent *content_proxy,
GError **error,
GAsyncReadyCallback callback,
gpointer user_data);
@@ -87,6 +86,7 @@ gboolean tf_call_content_bus_message (TfCallContent *content,
/* Private */
FsStream *_tf_call_content_get_fsstream_by_handle (TfCallContent *content,
guint contact_handle,
+ FsStreamDirection dir,
const gchar *transmitter,
guint stream_transmitter_n_parameters,
GParameter *stream_transmitter_parameters,
@@ -100,6 +100,9 @@ tf_call_content_get_fs_media_type (TfCallContent *content);
gboolean
tf_call_content_bus_message (TfCallContent *content, GstMessage *message);
+TpCallContent *
+tf_call_content_get_proxy (TfCallContent *content);
+
G_END_DECLS
#endif /* __TF_CALL_CONTENT_H__ */
diff --git a/telepathy-farstream/call-stream.c b/telepathy-farstream/call-stream.c
index f7257d6..e4286da 100644
--- a/telepathy-farstream/call-stream.c
+++ b/telepathy-farstream/call-stream.c
@@ -20,26 +20,35 @@
/**
* SECTION:tfcallstream
*
- * @short_description: Handle the Stream interface on a Channel
+ * @short_description: Handle the Stream objects for a Call1 channel
*
- * This class handles the
- * org.freedesktop.Telepathy.Channel.Interface.Stream on a
- * channel using Farstream.
+ * This class handles the org.freedesktop.Telepathy.Call1.Stream,
+ * org.freedesktop.Telepathy.Call1.Stream.Interface.Media and
+ * org.freedesktop.Telepathy.Call1.Stream.Endpoint interfaces.
+ */
+
+/*
+ * TODO:
+ * - Support multiple handles
+ * - Allow app to fail sending or receiving during call
+ *
+ * Endpoints:
+ * - Support multiple Endpoints (ie SIP forking with ICE)
+ * - Call SetControlling
+ * - Listen to CandidatePairSelected and call AcceptSelectedCandidatePair/RejectSelectedCandidatePair
+ * - Support IsICELite
*/
#include "call-stream.h"
-#include <telepathy-glib/util.h>
-#include <telepathy-glib/interfaces.h>
+#include <telepathy-glib/telepathy-glib.h>
+#include <telepathy-glib/proxy-subclass.h>
#include <farstream/fs-conference.h>
#include <stdarg.h>
#include <string.h>
#include <stdlib.h>
-#include <telepathy-glib/proxy-subclass.h>
-
-#include "extensions/extensions.h"
#include "tf-signals-marshal.h"
#include "utils.h"
@@ -49,6 +58,18 @@ G_DEFINE_TYPE (TfCallStream, tf_call_stream, G_TYPE_OBJECT);
static void tf_call_stream_dispose (GObject *object);
+static void tf_call_stream_fail_literal (TfCallStream *self,
+ TpCallStateChangeReason reason,
+ const gchar *detailed_reason,
+ const gchar *message);
+
+static void tf_call_stream_fail (TfCallStream *self,
+ TpCallStateChangeReason reason,
+ const gchar *detailed_reason,
+ const gchar *message_format,
+ ...);
+
+
static void
tf_call_stream_class_init (TfCallStreamClass *klass)
{
@@ -60,6 +81,8 @@ tf_call_stream_class_init (TfCallStreamClass *klass)
static void
tf_call_stream_init (TfCallStream *self)
{
+ self->sending_state = TP_STREAM_FLOW_STATE_STOPPED;
+ self->receiving_state = TP_STREAM_FLOW_STATE_STOPPED;
}
static void
@@ -101,56 +124,124 @@ tf_call_stream_dispose (GObject *object)
G_OBJECT_CLASS (tf_call_stream_parent_class)->dispose (object);
}
+
+
static void
-local_sending_state_changed (TfFutureCallStream *proxy,
+sending_state_changed (TpCallStream *proxy,
guint arg_State,
gpointer user_data, GObject *weak_object)
{
TfCallStream *self = TF_CALL_STREAM (weak_object);
+ FsStreamDirection dir;
- self->local_sending_state = arg_State;
+ self->sending_state = arg_State;
if (!self->fsstream)
return;
- if (arg_State == TF_FUTURE_SENDING_STATE_SENDING)
- {
- if (!self->has_send_resource)
- {
- if (_tf_content_start_sending (TF_CONTENT (self->call_content)))
- {
- self->has_send_resource = TRUE;
- }
- else
- {
- /* FIXME add a way to call to report media errors */
- g_warning ("Sending failed");
- return;
- }
- }
- }
+ g_object_get (self->fsstream, "direction", &dir, NULL);
switch (arg_State)
{
- case TF_FUTURE_SENDING_STATE_PENDING_STOP_SENDING:
- case TF_FUTURE_SENDING_STATE_PENDING_SEND:
- /* the UI should respond to these */
- break;
- case TF_FUTURE_SENDING_STATE_SENDING:
- g_object_set (self->fsstream, "direction", FS_DIRECTION_BOTH, NULL);
+ case TP_STREAM_FLOW_STATE_PENDING_START:
+ if (self->has_send_resource ||
+ _tf_content_start_sending (TF_CONTENT (self->call_content)))
+ {
+ self->has_send_resource = TRUE;
+
+ tp_cli_call_stream_interface_media_call_complete_sending_state_change (
+ proxy, -1, TP_STREAM_FLOW_STATE_STARTED,
+ NULL, NULL, NULL, NULL);
+ g_object_set (self->fsstream,
+ "direction", dir | FS_DIRECTION_SEND, NULL);
+ }
+ else
+ {
+ tp_cli_call_stream_interface_media_call_report_sending_failure (
+ proxy, -1, TP_CALL_STATE_CHANGE_REASON_INTERNAL_ERROR,
+ TP_ERROR_STR_MEDIA_STREAMING_ERROR,
+ "Could not start sending", NULL, NULL, NULL, NULL);
+ return;
+ }
break;
- case TF_FUTURE_SENDING_STATE_NONE:
+ case TP_STREAM_FLOW_STATE_PENDING_STOP:
+ g_object_set (self->fsstream,
+ "direction", dir & ~FS_DIRECTION_SEND, NULL);
if (self->has_send_resource)
{
_tf_content_stop_sending (TF_CONTENT (self->call_content));
self->has_send_resource = FALSE;
}
- g_object_set (self->fsstream, "direction", FS_DIRECTION_RECV, NULL);
+ tp_cli_call_stream_interface_media_call_complete_sending_state_change (
+ proxy, -1, TP_STREAM_FLOW_STATE_STOPPED, NULL, NULL, NULL, NULL);
+ break;
+ default:
break;
}
}
+static void
+tf_call_stream_start_receiving (TfCallStream *self, FsStreamDirection dir)
+{
+ if (self->has_receive_resource ||
+ _tf_content_start_receiving (TF_CONTENT (self->call_content),
+ &self->contact_handle, 1))
+ {
+ self->has_receive_resource = TRUE;
+ if (self->fsstream)
+ g_object_set (self->fsstream,
+ "direction", dir | FS_DIRECTION_RECV, NULL);
+ tp_cli_call_stream_interface_media_call_complete_receiving_state_change (
+ self->proxy, -1, TP_STREAM_FLOW_STATE_STARTED,
+ NULL, NULL, NULL, NULL);
+ }
+ else
+ {
+ tp_cli_call_stream_interface_media_call_report_receiving_failure (
+ self->proxy, -1, TP_CALL_STATE_CHANGE_REASON_INTERNAL_ERROR,
+ TP_ERROR_STR_MEDIA_STREAMING_ERROR,
+ "Could not start receiving", NULL, NULL, NULL, NULL);
+ }
+}
+
+static void
+receiving_state_changed (TpCallStream *proxy,
+ guint arg_State,
+ gpointer user_data, GObject *weak_object)
+{
+ TfCallStream *self = TF_CALL_STREAM (weak_object);
+ FsStreamDirection dir;
+
+ self->receiving_state = arg_State;
+
+ if (!self->fsstream)
+ return;
+
+ g_object_get (self->fsstream, "direction", &dir, NULL);
+
+ switch (arg_State)
+ {
+ case TP_STREAM_FLOW_STATE_PENDING_START:
+ tf_call_stream_start_receiving (self, dir);
+ break;
+ case TP_STREAM_FLOW_STATE_PENDING_STOP:
+ g_object_set (self->fsstream,
+ "direction", dir & ~FS_DIRECTION_RECV, NULL);
+ if (self->has_receive_resource)
+ {
+ _tf_content_stop_receiving (TF_CONTENT (self->call_content),
+ &self->contact_handle, 1);
+
+ self->has_receive_resource = FALSE;
+ }
+ tp_cli_call_stream_interface_media_call_complete_receiving_state_change (
+ proxy, -1, TP_STREAM_FLOW_STATE_STOPPED, NULL, NULL, NULL, NULL);
+ break;
+ default:
+ break;
+ }
+}
static void
tf_call_stream_try_adding_fsstream (TfCallStream *self)
@@ -161,6 +252,7 @@ tf_call_stream_try_adding_fsstream (TfCallStream *self)
GParameter params[6] = { {NULL,} };
GList *preferred_local_candidates = NULL;
guint i;
+ FsStreamDirection dir = FS_DIRECTION_NONE;
memset (params, 0, sizeof(params));
@@ -171,9 +263,11 @@ tf_call_stream_try_adding_fsstream (TfCallStream *self)
switch (self->transport_type)
{
- case TF_FUTURE_STREAM_TRANSPORT_TYPE_RAW_UDP:
+ case TP_STREAM_TRANSPORT_TYPE_RAW_UDP:
transmitter = "rawudp";
+ g_debug ("Transmitter: rawudp");
+
switch (tf_call_content_get_fs_media_type (self->call_content))
{
case TP_MEDIA_STREAM_TYPE_VIDEO:
@@ -198,43 +292,50 @@ tf_call_stream_try_adding_fsstream (TfCallStream *self)
n_params++;
}
break;
- case TF_FUTURE_STREAM_TRANSPORT_TYPE_ICE:
- case TF_FUTURE_STREAM_TRANSPORT_TYPE_GTALK_P2P:
- case TF_FUTURE_STREAM_TRANSPORT_TYPE_WLM_2009:
+ case TP_STREAM_TRANSPORT_TYPE_ICE:
+ case TP_STREAM_TRANSPORT_TYPE_GTALK_P2P:
+ case TP_STREAM_TRANSPORT_TYPE_WLM_2009:
transmitter = "nice";
- /* MISSING: Set Controlling mode property here */
+ params[n_params].name = "controlling-mode";
+ g_value_init (&params[n_params].value, G_TYPE_BOOLEAN);
+ g_value_set_boolean (&params[n_params].value, self->controlling);
+ n_params++;
params[n_params].name = "compatibility-mode";
g_value_init (&params[n_params].value, G_TYPE_UINT);
switch (self->transport_type)
{
- case TF_FUTURE_STREAM_TRANSPORT_TYPE_ICE:
+ case TP_STREAM_TRANSPORT_TYPE_ICE:
g_value_set_uint (&params[n_params].value, 0);
break;
- case TF_FUTURE_STREAM_TRANSPORT_TYPE_GTALK_P2P:
+ case TP_STREAM_TRANSPORT_TYPE_GTALK_P2P:
g_value_set_uint (&params[n_params].value, 1);
self->multiple_usernames = TRUE;
break;
- case TF_FUTURE_STREAM_TRANSPORT_TYPE_WLM_2009:
+ case TP_STREAM_TRANSPORT_TYPE_WLM_2009:
g_value_set_uint (&params[n_params].value, 3);
break;
default:
break;
}
+
+ g_debug ("Transmitter: nice: TpTransportType:%d controlling:%d",
+ self->transport_type, self->controlling);
+
n_params++;
break;
- case TF_FUTURE_STREAM_TRANSPORT_TYPE_SHM:
+ case TP_STREAM_TRANSPORT_TYPE_SHM:
transmitter = "shm";
params[n_params].name = "create-local-candidates";
g_value_init (&params[n_params].value, G_TYPE_BOOLEAN);
g_value_set_boolean (&params[n_params].value, TRUE);
n_params++;
+ g_debug ("Transmitter: shm");
break;
default:
- tf_content_error (TF_CONTENT (self->call_content),
- TF_FUTURE_CONTENT_REMOVAL_REASON_ERROR,
- "org.freedesktop.Telepathy.Error.NotImplemented",
+ tf_call_stream_fail (self,
+ TP_CALL_STATE_CHANGE_REASON_INTERNAL_ERROR, TP_ERROR_STR_CONFUSED,
"Unknown transport type %d", self->transport_type);
return;
}
@@ -331,8 +432,15 @@ tf_call_stream_try_adding_fsstream (TfCallStream *self)
g_value_array_free (fs_relay_info);
}
+ if (self->receiving_state == TP_STREAM_FLOW_STATE_PENDING_START)
+ {
+ tf_call_stream_start_receiving (self, FS_DIRECTION_NONE);
+ dir = FS_DIRECTION_RECV;
+ }
+
self->fsstream = _tf_call_content_get_fsstream_by_handle (self->call_content,
self->contact_handle,
+ dir,
transmitter,
n_params,
params,
@@ -343,22 +451,21 @@ tf_call_stream_try_adding_fsstream (TfCallStream *self)
if (!self->fsstream)
{
- tf_content_error (TF_CONTENT (self->call_content),
- TF_FUTURE_CONTENT_REMOVAL_REASON_ERROR,
- "",
+ tf_call_stream_fail (self,
+ TP_CALL_STATE_CHANGE_REASON_INTERNAL_ERROR,
+ TP_ERROR_STR_MEDIA_STREAMING_ERROR,
"Could not create FsStream: %s", error->message);
g_clear_error (&error);
return;
}
- if (self->local_sending_state == TF_FUTURE_SENDING_STATE_PENDING_SEND ||
- self->local_sending_state == TF_FUTURE_SENDING_STATE_SENDING)
- local_sending_state_changed (self->proxy, self->local_sending_state,
- NULL, (GObject *) self);
+ if (self->sending_state == TP_STREAM_FLOW_STATE_PENDING_START)
+ sending_state_changed (self->proxy,
+ self->sending_state, NULL, (GObject *) self);
}
static void
-server_info_retrieved (TfFutureCallStream *proxy,
+server_info_retrieved (TpCallStream *proxy,
gpointer user_data, GObject *weak_object)
{
TfCallStream *self = TF_CALL_STREAM (weak_object);
@@ -369,7 +476,7 @@ server_info_retrieved (TfFutureCallStream *proxy,
}
static void
-relay_info_changed (TfFutureCallStream *proxy,
+relay_info_changed (TpCallStream *proxy,
const GPtrArray *arg_Relay_Info,
gpointer user_data, GObject *weak_object)
{
@@ -377,9 +484,9 @@ relay_info_changed (TfFutureCallStream *proxy,
if (self->server_info_retrieved)
{
- tf_content_error_literal (TF_CONTENT (self->call_content),
- TF_FUTURE_CONTENT_REMOVAL_REASON_ERROR,
- "org.freedesktop.Telepathy.Error.NotImplemented",
+ tf_call_stream_fail_literal (self,
+ TP_CALL_STATE_CHANGE_REASON_INTERNAL_ERROR,
+ TP_ERROR_STR_NOT_IMPLEMENTED,
"Changing relay servers after ServerInfoRetrived is not implemented");
return;
}
@@ -394,7 +501,7 @@ relay_info_changed (TfFutureCallStream *proxy,
}
static void
-stun_servers_changed (TfFutureCallStream *proxy,
+stun_servers_changed (TpCallStream *proxy,
const GPtrArray *arg_Servers,
gpointer user_data, GObject *weak_object)
{
@@ -402,9 +509,9 @@ stun_servers_changed (TfFutureCallStream *proxy,
if (self->server_info_retrieved)
{
- tf_content_error_literal (TF_CONTENT (self->call_content),
- TF_FUTURE_CONTENT_REMOVAL_REASON_ERROR,
- "org.freedesktop.Telepathy.Error.NotImplemented",
+ tf_call_stream_fail_literal (self,
+ TP_CALL_STATE_CHANGE_REASON_INTERNAL_ERROR,
+ TP_ERROR_STR_NOT_IMPLEMENTED,
"Changing STUN servers after ServerInfoRetrived is not implemented");
return;
}
@@ -418,6 +525,46 @@ stun_servers_changed (TfFutureCallStream *proxy,
arg_Servers);
}
+static FsCandidateType
+tpcandidate_type_to_fs (TpCallStreamCandidateType type)
+{
+ switch(type)
+ {
+ case TP_CALL_STREAM_CANDIDATE_TYPE_NONE:
+ g_warning ("Candidate type NONE, assigning to HOST");
+ /* fallthrough */
+ case TP_CALL_STREAM_CANDIDATE_TYPE_HOST:
+ return FS_CANDIDATE_TYPE_HOST;
+ case TP_CALL_STREAM_CANDIDATE_TYPE_SERVER_REFLEXIVE:
+ return FS_CANDIDATE_TYPE_SRFLX;
+ case TP_CALL_STREAM_CANDIDATE_TYPE_PEER_REFLEXIVE:
+ return FS_CANDIDATE_TYPE_PRFLX;
+ case TP_CALL_STREAM_CANDIDATE_TYPE_RELAY:
+ return FS_CANDIDATE_TYPE_RELAY;
+ case TP_CALL_STREAM_CANDIDATE_TYPE_MULTICAST:
+ return FS_CANDIDATE_TYPE_MULTICAST;
+ default:
+ g_warning ("Candidate type %d unknown, assigning to HOST", type);
+ return FS_CANDIDATE_TYPE_HOST;
+ }
+}
+
+static FsNetworkProtocol
+tpnetworkproto_to_fs (TpMediaStreamBaseProto proto)
+{
+ switch(proto)
+ {
+ case TP_MEDIA_STREAM_BASE_PROTO_UDP:
+ return FS_NETWORK_PROTOCOL_UDP;
+ case TP_MEDIA_STREAM_BASE_PROTO_TCP:
+ return FS_NETWORK_PROTOCOL_TCP;
+ default:
+ g_debug ("Network protocol %d unknown, assigning to UDP", proto);
+ return FS_NETWORK_PROTOCOL_UDP;
+ }
+}
+
+
static void
tf_call_stream_add_remote_candidates (TfCallStream *self,
const GPtrArray *candidates)
@@ -444,30 +591,61 @@ tf_call_stream_add_remote_candidates (TfCallStream *self,
const gchar *password;
gboolean valid;
FsCandidate *cand;
+ guint type;
+ guint protocol;
+ guint ttl;
+ const gchar *base_ip;
+ guint base_port;
tp_value_array_unpack (tpcandidate, 4, &component, &ip, &port,
&extra_info);
- foundation = tp_asv_get_string (extra_info, "Foundation");
+ foundation = tp_asv_get_string (extra_info, "foundation");
if (!foundation)
foundation = "";
- priority = tp_asv_get_uint32 (extra_info, "Priority", &valid);
+ priority = tp_asv_get_uint32 (extra_info, "priority", &valid);
if (!valid)
priority = 0;
- username = tp_asv_get_string (extra_info, "Username");
+ username = tp_asv_get_string (extra_info, "username");
if (!username)
username = self->creds_username;
- password = tp_asv_get_string (extra_info, "Password");
+ password = tp_asv_get_string (extra_info, "password");
if (!password)
password = self->creds_password;
- cand = fs_candidate_new (foundation, component, FS_CANDIDATE_TYPE_HOST,
- FS_NETWORK_PROTOCOL_UDP, ip, port);
+ type = tp_asv_get_uint32 (extra_info, "type", &valid);
+ if (!valid)
+ type = TP_CALL_STREAM_CANDIDATE_TYPE_HOST;
+
+ protocol = tp_asv_get_uint32 (extra_info, "protocol", &valid);
+ if (!valid)
+ protocol = TP_MEDIA_STREAM_BASE_PROTO_UDP;
+
+ base_ip = tp_asv_get_string (extra_info, "base-ip");
+ base_port = tp_asv_get_uint32 (extra_info, "base-port", &valid);
+ if (!valid)
+ base_port = 0;
+
+
+ ttl = tp_asv_get_uint32 (extra_info, "ttl", &valid);
+ if (!valid)
+ ttl = 0;
+
+ g_debug ("Remote Candidate: %s c:%d tptype:%d tpproto: %d ip:%s port:%u prio:%d u/p:%s/%s ttl:%d base_ip:%s base_port:%d",
+ foundation, component, type, protocol, ip, port, priority,
+ username, password, ttl, base_ip, base_port);
+
+ cand = fs_candidate_new (foundation, component,
+ tpcandidate_type_to_fs (type), tpnetworkproto_to_fs (protocol),
+ ip, port);
cand->priority = priority;
cand->username = g_strdup (username);
cand->password = g_strdup (password);
+ cand->ttl = ttl;
+ cand->base_ip = base_ip;
+ cand->base_port = base_port;
fscandidates = g_list_append (fscandidates, cand);
}
@@ -479,15 +657,15 @@ tf_call_stream_add_remote_candidates (TfCallStream *self,
switch (self->transport_type)
{
- case TF_FUTURE_STREAM_TRANSPORT_TYPE_RAW_UDP:
- case TF_FUTURE_STREAM_TRANSPORT_TYPE_SHM:
- case TF_FUTURE_STREAM_TRANSPORT_TYPE_MULTICAST:
+ case TP_STREAM_TRANSPORT_TYPE_RAW_UDP:
+ case TP_STREAM_TRANSPORT_TYPE_SHM:
+ case TP_STREAM_TRANSPORT_TYPE_MULTICAST:
ret = fs_stream_force_remote_candidates (self->fsstream,
fscandidates, &error);
break;
- case TF_FUTURE_STREAM_TRANSPORT_TYPE_ICE:
- case TF_FUTURE_STREAM_TRANSPORT_TYPE_GTALK_P2P:
- case TF_FUTURE_STREAM_TRANSPORT_TYPE_WLM_2009:
+ case TP_STREAM_TRANSPORT_TYPE_ICE:
+ case TP_STREAM_TRANSPORT_TYPE_GTALK_P2P:
+ case TP_STREAM_TRANSPORT_TYPE_WLM_2009:
ret = fs_stream_add_remote_candidates (self->fsstream, fscandidates,
&error);
break;
@@ -497,8 +675,9 @@ tf_call_stream_add_remote_candidates (TfCallStream *self,
if (!ret)
{
- tf_content_error (TF_CONTENT (self->call_content),
- TF_FUTURE_CONTENT_REMOVAL_REASON_ERROR, "",
+ tf_call_stream_fail (self,
+ TP_CALL_STATE_CHANGE_REASON_INTERNAL_ERROR,
+ TP_ERROR_STR_MEDIA_STREAMING_ERROR,
"Error setting the remote candidates: %s", error->message);
g_clear_error (&error);
}
@@ -518,6 +697,9 @@ remote_candidates_added (TpProxy *proxy,
{
TfCallStream *self = TF_CALL_STREAM (weak_object);
+ if (!self->has_endpoint_properties)
+ return;
+
tf_call_stream_add_remote_candidates (self, arg_Candidates);
}
@@ -532,6 +714,8 @@ remote_credentials_set (TpProxy *proxy,
if ((self->creds_username && strcmp (self->creds_username, arg_Username)) ||
(self->creds_password && strcmp (self->creds_password, arg_Password)))
{
+ g_debug ("Remote credentials changed,"
+ " remote is doing an ICE restart");
/* Remote credentials changed, this will perform a ICE restart, so
* clear old remote candidates */
fs_candidate_list_destroy (self->stored_remote_candidates);
@@ -542,6 +726,8 @@ remote_credentials_set (TpProxy *proxy,
g_free (self->creds_password);
self->creds_username = g_strdup (arg_Username);
self->creds_password = g_strdup (arg_Password);
+
+ g_debug ("Credentials set: %s / %s", arg_Username, arg_Password);
}
@@ -553,45 +739,79 @@ got_endpoint_properties (TpProxy *proxy, GHashTable *out_Properties,
GValueArray *credentials;
gchar *username, *password;
GPtrArray *candidates;
+ gboolean valid = FALSE;
+ guint transport_type;
if (error)
{
- tf_content_error (TF_CONTENT (self->call_content),
- TF_FUTURE_CONTENT_REMOVAL_REASON_ERROR, "",
+ tf_call_stream_fail (self,
+ TP_CALL_STATE_CHANGE_REASON_INTERNAL_ERROR,
+ TP_ERROR_STR_CONFUSED,
"Error getting the Streams's media properties: %s", error->message);
return;
}
if (!out_Properties)
{
- tf_content_error_literal (TF_CONTENT (self->call_content),
- TF_FUTURE_CONTENT_REMOVAL_REASON_ERROR, "",
+ tf_call_stream_fail_literal (self,
+ TP_CALL_STATE_CHANGE_REASON_INTERNAL_ERROR,
+ TP_ERROR_STR_CONFUSED,
"Error getting the Stream's media properties: there are none");
return;
}
+ g_debug ("Got Endpoint Properties");
+
credentials = tp_asv_get_boxed (out_Properties, "RemoteCredentials",
- TF_FUTURE_STRUCT_TYPE_STREAM_CREDENTIALS);
+ TP_STRUCT_TYPE_STREAM_CREDENTIALS);
if (!credentials)
goto invalid_property;
tp_value_array_unpack (credentials, 2, &username, &password);
- self->creds_username = g_strdup (username);
- self->creds_password = g_strdup (password);
+ if (username && username[0])
+ self->creds_username = g_strdup (username);
+ if (password && password[0])
+ self->creds_password = g_strdup (password);
+
+ if (self->creds_username || self->creds_password)
+ g_debug ("Credentials set: %s / %s", username, password);
candidates = tp_asv_get_boxed (out_Properties, "RemoteCandidates",
- TF_FUTURE_ARRAY_TYPE_CANDIDATE_LIST);
+ TP_ARRAY_TYPE_CANDIDATE_LIST);
if (!candidates)
goto invalid_property;
+ transport_type = tp_asv_get_uint32 (out_Properties, "Transport", &valid);
+ if (!valid)
+ {
+ g_warning ("No valid transport");
+ goto invalid_property;
+ }
+
+ if (transport_type != self->transport_type)
+ {
+ if (transport_type != TP_STREAM_TRANSPORT_TYPE_RAW_UDP)
+ {
+ tf_call_stream_fail (self,
+ TP_CALL_STATE_CHANGE_REASON_INTERNAL_ERROR,
+ TP_ERROR_STR_INVALID_ARGUMENT,
+ "The Transport of a Endpoint can only be changed to rawudp: %d invalid", transport_type);
+ return;
+ }
+ self->transport_type = transport_type;
+ }
+
+ self->has_endpoint_properties = TRUE;
+
tf_call_stream_add_remote_candidates (self, candidates);
return;
invalid_property:
- tf_content_error_literal (TF_CONTENT (self->call_content),
- TF_FUTURE_CONTENT_REMOVAL_REASON_ERROR, "",
+ tf_call_stream_fail_literal (self,
+ TP_CALL_STATE_CHANGE_REASON_INTERNAL_ERROR,
+ TP_ERROR_STR_CONFUSED,
"Error getting the Endpoint's properties: invalid type");
}
@@ -600,48 +820,51 @@ tf_call_stream_add_endpoint (TfCallStream *self)
{
GError *error = NULL;
+ tp_call_stream_endpoint_init_known_interfaces ();
self->endpoint = g_object_new (TP_TYPE_PROXY,
"dbus-daemon", tp_proxy_get_dbus_daemon (self->proxy),
"bus-name", tp_proxy_get_bus_name (self->proxy),
"object-path", self->endpoint_objpath,
NULL);
tp_proxy_add_interface_by_id (TP_PROXY (self->endpoint),
- TF_FUTURE_IFACE_QUARK_CALL_STREAM_ENDPOINT);
+ TP_IFACE_QUARK_CALL_STREAM_ENDPOINT);
- tf_future_cli_call_stream_endpoint_connect_to_remote_credentials_set (
+ tp_cli_call_stream_endpoint_connect_to_remote_credentials_set (
TP_PROXY (self->endpoint), remote_credentials_set, NULL, NULL,
G_OBJECT (self), &error);
if (error)
{
- tf_content_error (TF_CONTENT (self->call_content),
- TF_FUTURE_CONTENT_REMOVAL_REASON_ERROR, "",
- "Error connectiong to RemoteCredentialsSet signal: %s",
+ tf_call_stream_fail (self,
+ TP_CALL_STATE_CHANGE_REASON_INTERNAL_ERROR,
+ TP_ERROR_STR_CONFUSED,
+ "Error connecting to RemoteCredentialsSet signal: %s",
error->message);
g_clear_error (&error);
return;
}
- tf_future_cli_call_stream_endpoint_connect_to_remote_candidates_added (
+ tp_cli_call_stream_endpoint_connect_to_remote_candidates_added (
TP_PROXY (self->endpoint), remote_candidates_added, NULL, NULL,
G_OBJECT (self), &error);
if (error)
{
- tf_content_error (TF_CONTENT (self->call_content),
- TF_FUTURE_CONTENT_REMOVAL_REASON_ERROR, "",
- "Error connectiong to RemoteCandidatesAdded signal: %s",
+ tf_call_stream_fail (self,
+ TP_CALL_STATE_CHANGE_REASON_INTERNAL_ERROR,
+ TP_ERROR_STR_CONFUSED,
+ "Error connecting to RemoteCandidatesAdded signal: %s",
error->message);
g_clear_error (&error);
return;
}
tp_cli_dbus_properties_call_get_all (self->endpoint, -1,
- TF_FUTURE_IFACE_CALL_STREAM_ENDPOINT,
+ TP_IFACE_CALL_STREAM_ENDPOINT,
got_endpoint_properties, NULL, NULL, G_OBJECT (self));
}
static void
-endpoints_changed (TfFutureCallStream *proxy,
+endpoints_changed (TpCallStream *proxy,
const GPtrArray *arg_Endpoints_Added,
const GPtrArray *arg_Endpoints_Removed,
gpointer user_data, GObject *weak_object)
@@ -654,18 +877,18 @@ endpoints_changed (TfFutureCallStream *proxy,
if (arg_Endpoints_Removed->len != 0)
{
- tf_content_error_literal (TF_CONTENT (self->call_content),
- TF_FUTURE_CONTENT_REMOVAL_REASON_ERROR,
- "org.freedesktop.Telepathy.Error.NotImplemented",
+ tf_call_stream_fail_literal (self,
+ TP_CALL_STATE_CHANGE_REASON_INTERNAL_ERROR,
+ TP_ERROR_STR_NOT_IMPLEMENTED,
"Removing Endpoints is not implemented");
return;
}
if (arg_Endpoints_Added->len != 1)
{
- tf_content_error_literal (TF_CONTENT (self->call_content),
- TF_FUTURE_CONTENT_REMOVAL_REASON_ERROR,
- "org.freedesktop.Telepathy.Error.NotImplemented",
+ tf_call_stream_fail_literal (self,
+ TP_CALL_STATE_CHANGE_REASON_INTERNAL_ERROR,
+ TP_ERROR_STR_NOT_IMPLEMENTED,
"Having more than one endpoint is not implemented");
return;
}
@@ -674,9 +897,10 @@ endpoints_changed (TfFutureCallStream *proxy,
{
if (strcmp (g_ptr_array_index (arg_Endpoints_Added, 0),
self->endpoint_objpath))
- tf_content_error_literal (TF_CONTENT (self->call_content),
- TF_FUTURE_CONTENT_REMOVAL_REASON_ERROR, "",
- "Trying to give a different endpoint, CM bug");
+ tf_call_stream_fail_literal (self,
+ TP_CALL_STATE_CHANGE_REASON_INTERNAL_ERROR,
+ TP_ERROR_STR_NOT_IMPLEMENTED,
+ "Having more than one endpoint is not implemented");
return;
}
@@ -698,8 +922,9 @@ got_stream_media_properties (TpProxy *proxy, GHashTable *out_Properties,
if (error)
{
- tf_content_error (TF_CONTENT (self->call_content),
- TF_FUTURE_CONTENT_REMOVAL_REASON_ERROR, "",
+ tf_call_stream_fail (self,
+ TP_CALL_STATE_CHANGE_REASON_INTERNAL_ERROR,
+ TP_ERROR_STR_CONFUSED,
"Error getting the Streams's media properties: %s",
error->message);
return;
@@ -707,8 +932,9 @@ got_stream_media_properties (TpProxy *proxy, GHashTable *out_Properties,
if (!out_Properties)
{
- tf_content_error_literal (TF_CONTENT (self->call_content),
- TF_FUTURE_CONTENT_REMOVAL_REASON_ERROR, "",
+ tf_call_stream_fail_literal (self,
+ TP_CALL_STATE_CHANGE_REASON_INTERNAL_ERROR,
+ TP_ERROR_STR_INVALID_ARGUMENT,
"Error getting the Stream's media properties: there are none");
return;
}
@@ -745,7 +971,31 @@ got_stream_media_properties (TpProxy *proxy, GHashTable *out_Properties,
goto invalid_property;
}
+ self->sending_state = tp_asv_get_uint32 (out_Properties, "SendingState",
+ &valid);
+ if (!valid)
+ {
+ g_warning ("No valid sending state");
+ goto invalid_property;
+ }
+
+ self->receiving_state = tp_asv_get_uint32 (out_Properties,
+ "ReceivingState", &valid);
+ if (!valid)
+ {
+ g_warning ("No valid receiving state");
+ goto invalid_property;
+ }
+/* FIXME: controlling is on the endpoint
+ self->controlling = tp_asv_get_boolean (out_Properties,
+ "Controlling", &valid);
+ if (!valid)
+ {
+ g_warning ("No Controlling property");
+ goto invalid_property;
+ }
+*/
self->stun_servers = g_boxed_copy (TP_ARRAY_TYPE_SOCKET_ADDRESS_IP_LIST,
stun_servers);
self->relay_info = g_boxed_copy (TP_ARRAY_TYPE_STRING_VARIANT_MAP_LIST,
@@ -756,9 +1006,9 @@ got_stream_media_properties (TpProxy *proxy, GHashTable *out_Properties,
if (endpoints->len > 1)
{
- tf_content_error_literal (TF_CONTENT (self->call_content),
- TF_FUTURE_CONTENT_REMOVAL_REASON_ERROR,
- "org.freedesktop.Telepathy.Error.NotImplemented",
+ tf_call_stream_fail_literal (self,
+ TP_CALL_STATE_CHANGE_REASON_INTERNAL_ERROR,
+ TP_ERROR_STR_NOT_IMPLEMENTED,
"Having more than one endpoint is not implemented");
return;
}
@@ -775,223 +1025,313 @@ got_stream_media_properties (TpProxy *proxy, GHashTable *out_Properties,
return;
invalid_property:
- tf_content_error_literal (TF_CONTENT (self->call_content),
- TF_FUTURE_CONTENT_REMOVAL_REASON_ERROR, "",
+ tf_call_stream_fail_literal (self,
+ TP_CALL_STATE_CHANGE_REASON_INTERNAL_ERROR,
+ TP_ERROR_STR_INVALID_ARGUMENT,
"Error getting the Stream's properties: invalid type");
return;
}
-
static void
-got_stream_properties (TpProxy *proxy, GHashTable *out_Properties,
- const GError *error, gpointer user_data, GObject *weak_object)
+ice_restart_requested (TpCallStream *proxy,
+ gpointer user_data, GObject *weak_object)
{
TfCallStream *self = TF_CALL_STREAM (weak_object);
- gboolean valid;
GError *myerror = NULL;
- guint i;
- const gchar * const * interfaces;
- gboolean got_media_interface = FALSE;
- guint32 local_sending_state;
- GHashTable *members;
- GHashTableIter iter;
- gpointer key, value;
- if (error)
+ if (!self->fsstream)
+ return;
+
+ if (self->multiple_usernames)
{
- tf_content_error (TF_CONTENT (self->call_content),
- TF_FUTURE_CONTENT_REMOVAL_REASON_ERROR, "",
- "Error getting the Streams's properties: %s", error->message);
+ tf_call_stream_fail_literal (self,
+ TP_CALL_STATE_CHANGE_REASON_INTERNAL_ERROR,
+ TP_ERROR_STR_INVALID_ARGUMENT,
+ "CM tried to ICE restart an ICE-6 or Google compatible connection");
return;
}
- if (!out_Properties)
+ g_debug ("Restarting ICE");
+
+ if (fs_stream_add_remote_candidates (self->fsstream, NULL, &myerror))
{
- tf_content_error_literal (TF_CONTENT (self->call_content),
- TF_FUTURE_CONTENT_REMOVAL_REASON_ERROR, "",
- "Error getting the Content's properties: there are none");
- return;
+ g_free (self->last_local_username);
+ g_free (self->last_local_password);
+ self->last_local_username = NULL;
+ self->last_local_password = NULL;
}
+ else
+ {
+ tf_call_stream_fail (self,
+ TP_CALL_STATE_CHANGE_REASON_INTERNAL_ERROR,
+ TP_ERROR_STR_MEDIA_STREAMING_ERROR,
+ "Error restarting the ICE process: %s", myerror->message);
+ g_clear_error (&myerror);
+ }
+}
- interfaces = tp_asv_get_strv (out_Properties, "Interfaces");
-
- for (i = 0; interfaces[i]; i++)
- if (!strcmp (interfaces[i], TF_FUTURE_IFACE_CALL_STREAM_INTERFACE_MEDIA))
- {
- got_media_interface = TRUE;
- break;
- }
+static void
+stream_prepared (GObject *src_object, GAsyncResult *res, gpointer user_data)
+{
+ TfCallStream *self = TF_CALL_STREAM (user_data);
+ TpProxy *proxy = TP_PROXY (src_object);
+ GError *error = NULL;
+ GHashTable *members;
+ GHashTableIter iter;
+ gpointer key, value;
- if (!got_media_interface)
+ if (!tp_proxy_prepare_finish (src_object, res, &error))
{
- tf_content_error_literal (TF_CONTENT (self->call_content),
- TF_FUTURE_CONTENT_REMOVAL_REASON_ERROR, "",
- "Stream does not have the media interface,"
- " but HardwareStreaming was NOT true");
+ tf_call_stream_fail (self,
+ TP_CALL_STATE_CHANGE_REASON_INTERNAL_ERROR,
+ TP_ERROR_STR_CONFUSED,
+ "Error preparing the stream Streams: %s", error->message);
+ g_clear_error (&error);
return;
}
- members = tp_asv_get_boxed (out_Properties, "RemoteMembers",
- TF_FUTURE_HASH_TYPE_CONTACT_SENDING_STATE_MAP);
- if (!members)
- goto invalid_property;
+ if (!tp_proxy_has_interface_by_id (proxy,
+ TP_IFACE_QUARK_CALL_STREAM_INTERFACE_MEDIA))
+ {
+ tf_call_stream_fail_literal (self,
+ TP_CALL_STATE_CHANGE_REASON_INTERNAL_ERROR,
+ TP_ERROR_STR_INVALID_ARGUMENT,
+ "Stream does not have the media interface,"
+ " but HardwareStreaming was NOT true");
+ return;
+ }
- local_sending_state = tp_asv_get_uint32 (out_Properties, "LocalSendingState",
- &valid);
- if (!valid)
- goto invalid_property;
+ members = tp_call_stream_get_remote_members (self->proxy);
- self->local_sending_state = local_sending_state;
+ if (g_hash_table_size (members) != 1)
+ {
+ tf_call_stream_fail (self,
+ TP_CALL_STATE_CHANGE_REASON_INTERNAL_ERROR,
+ TP_ERROR_STR_NOT_IMPLEMENTED,
+ "Only one Member per Stream is supported, there are %d",
+ g_hash_table_size (members));
+ return;
+ }
- if (g_hash_table_size (members) != 1)
+ g_hash_table_iter_init (&iter, members);
+ if (g_hash_table_iter_next (&iter, &key, &value))
{
- tf_content_error (TF_CONTENT (self->call_content),
- TF_FUTURE_CONTENT_REMOVAL_REASON_ERROR,
- "org.freedesktop.Telepathy.Error.NotImplemented",
- "Only one Member per Stream is supported, there are %d",
- g_hash_table_size (members));
+ self->has_contact = TRUE;
+ self->contact_handle = tp_contact_get_handle (key);
+ }
+
+ tp_cli_call_stream_interface_media_connect_to_sending_state_changed (
+ TP_CALL_STREAM (proxy), sending_state_changed, NULL, NULL,
+ G_OBJECT (self), &error);
+ if (error)
+ {
+ tf_call_stream_fail (self,
+ TP_CALL_STATE_CHANGE_REASON_INTERNAL_ERROR, "",
+ "Error connecting to SendingStateChanged signal: %s",
+ error->message);
+ g_clear_error (&error);
return;
}
- g_hash_table_iter_init (&iter, members);
- if (g_hash_table_iter_next (&iter, &key, &value))
+ tp_cli_call_stream_interface_media_connect_to_receiving_state_changed (
+ TP_CALL_STREAM (proxy), receiving_state_changed, NULL, NULL,
+ G_OBJECT (self), &error);
+ if (error)
{
- self->has_contact = TRUE;
- self->contact_handle = GPOINTER_TO_UINT (key);
+ tf_call_stream_fail (self,
+ TP_CALL_STATE_CHANGE_REASON_INTERNAL_ERROR, "",
+ "Error connecting to ReceivingStateChanged signal: %s",
+ error->message);
+ g_clear_error (&error);
+ return;
}
- tp_proxy_add_interface_by_id (TP_PROXY (self->proxy),
- TF_FUTURE_IFACE_QUARK_CALL_STREAM_INTERFACE_MEDIA);
+ tp_cli_call_stream_interface_media_connect_to_server_info_retrieved (
+ TP_CALL_STREAM (proxy), server_info_retrieved, NULL, NULL,
+ G_OBJECT (self), &error);
+ if (error)
+ {
+ tf_call_stream_fail (self,
+ TP_CALL_STATE_CHANGE_REASON_INTERNAL_ERROR, "",
+ "Error connecting to ServerInfoRetrived signal: %s",
+ error->message);
+ g_clear_error (&error);
+ return;
+ }
- tf_future_cli_call_stream_interface_media_connect_to_server_info_retrieved (
- TF_FUTURE_CALL_STREAM (proxy), server_info_retrieved, NULL, NULL,
- G_OBJECT (self), &myerror);
- if (myerror)
+ tp_cli_call_stream_interface_media_connect_to_stun_servers_changed (
+ TP_CALL_STREAM (proxy), stun_servers_changed, NULL, NULL,
+ G_OBJECT (self), &error);
+ if (error)
{
- tf_content_error (TF_CONTENT (self->call_content),
- TF_FUTURE_CONTENT_REMOVAL_REASON_ERROR, "",
- "Error connectiong to ServerInfoRetrived signal: %s",
- myerror->message);
- g_clear_error (&myerror);
+ tf_call_stream_fail (self,
+ TP_CALL_STATE_CHANGE_REASON_INTERNAL_ERROR, "",
+ "Error connecting to ServerInfoRetrived signal: %s",
+ error->message);
+ g_clear_error (&error);
return;
}
- tf_future_cli_call_stream_interface_media_connect_to_stun_servers_changed (
- TF_FUTURE_CALL_STREAM (proxy), stun_servers_changed, NULL, NULL,
- G_OBJECT (self), &myerror);
- if (myerror)
+
+ tp_cli_call_stream_interface_media_connect_to_relay_info_changed (
+ TP_CALL_STREAM (proxy), relay_info_changed, NULL, NULL,
+ G_OBJECT (self), &error);
+ if (error)
{
- tf_content_error (TF_CONTENT (self->call_content),
- TF_FUTURE_CONTENT_REMOVAL_REASON_ERROR, "",
- "Error connectiong to ServerInfoRetrived signal: %s",
- myerror->message);
- g_clear_error (&myerror);
+ tf_call_stream_fail (self,
+ TP_CALL_STATE_CHANGE_REASON_INTERNAL_ERROR, "",
+ "Error connecting to ServerInfoRetrived signal: %s",
+ error->message);
+ g_clear_error (&error);
return;
}
- tf_future_cli_call_stream_interface_media_connect_to_relay_info_changed (
- TF_FUTURE_CALL_STREAM (proxy), relay_info_changed, NULL, NULL,
- G_OBJECT (self), &myerror);
- if (myerror)
+ tp_cli_call_stream_interface_media_connect_to_endpoints_changed (
+ TP_CALL_STREAM (proxy), endpoints_changed, NULL, NULL,
+ G_OBJECT (self), &error);
+ if (error)
{
- tf_content_error (TF_CONTENT (self->call_content),
- TF_FUTURE_CONTENT_REMOVAL_REASON_ERROR, "",
- "Error connectiong to ServerInfoRetrived signal: %s",
- myerror->message);
- g_clear_error (&myerror);
+ tf_call_stream_fail (self,
+ TP_CALL_STATE_CHANGE_REASON_INTERNAL_ERROR, "",
+ "Error connecting to EndpointsChanged signal: %s",
+ error->message);
+ g_clear_error (&error);
return;
}
- tf_future_cli_call_stream_interface_media_connect_to_endpoints_changed (
- TF_FUTURE_CALL_STREAM (proxy), endpoints_changed, NULL, NULL,
- G_OBJECT (self), &myerror);
- if (myerror)
+ tp_cli_call_stream_interface_media_connect_to_ice_restart_requested (
+ TP_CALL_STREAM (proxy), ice_restart_requested, NULL, NULL,
+ G_OBJECT (self), &error);
+ if (error)
{
- tf_content_error (TF_CONTENT (self->call_content),
- TF_FUTURE_CONTENT_REMOVAL_REASON_ERROR, "",
- "Error connectiong to EndpointsChanged signal: %s",
- myerror->message);
- g_clear_error (&myerror);
+ tf_call_stream_fail (self,
+ TP_CALL_STATE_CHANGE_REASON_INTERNAL_ERROR, "",
+ "Error connecting to ICERestartRequested signal: %s",
+ error->message);
+ g_clear_error (&error);
return;
}
- tp_cli_dbus_properties_call_get_all (proxy, -1,
- TF_FUTURE_IFACE_CALL_STREAM_INTERFACE_MEDIA,
+ tp_cli_dbus_properties_call_get_all (TP_PROXY (self->proxy), -1,
+ TP_IFACE_CALL_STREAM_INTERFACE_MEDIA,
got_stream_media_properties, NULL, NULL, G_OBJECT (self));
return;
-
- invalid_property:
- tf_content_error_literal (TF_CONTENT (self->call_content),
- TF_FUTURE_CONTENT_REMOVAL_REASON_ERROR, "",
- "Error getting the Stream's properties: invalid type");
- return;
}
TfCallStream *
-tf_call_stream_new (TfCallChannel *call_channel,
- TfCallContent *call_content,
- const gchar *object_path,
- GError **error)
+tf_call_stream_new (TfCallContent *call_content,
+ TpCallStream *stream_proxy)
{
TfCallStream *self;
- TfFutureCallStream *proxy = tf_future_call_stream_new (call_channel->proxy,
- object_path, error);
- GError *myerror = NULL;
- if (!proxy)
- return NULL;
+ g_assert (call_content != NULL);
+ g_assert (stream_proxy != NULL);
- self = g_object_new (TF_TYPE_STREAM, NULL);
+ self = g_object_new (TF_TYPE_CALL_STREAM, NULL);
self->call_content = call_content;
- self->proxy = proxy;
+ self->proxy = g_object_ref (stream_proxy);
- tf_future_cli_call_stream_connect_to_local_sending_state_changed (
- TF_FUTURE_CALL_STREAM (proxy), local_sending_state_changed, NULL, NULL,
- G_OBJECT (self), &myerror);
- if (myerror)
+ tp_proxy_prepare_async (self->proxy, NULL, stream_prepared,
+ g_object_ref (self));
+
+ return self;
+}
+
+static TpCallStreamCandidateType
+fscandidatetype_to_tp (FsCandidateType type)
+{
+ switch(type)
{
- tf_content_error (TF_CONTENT (self->call_content),
- TF_FUTURE_CONTENT_REMOVAL_REASON_ERROR, "",
- "Error connectiong to LocalSendingStateChanged signal: %s",
- myerror->message);
- g_object_unref (self);
- g_propagate_error (error, myerror);
- return NULL;
+ case FS_CANDIDATE_TYPE_HOST:
+ return TP_CALL_STREAM_CANDIDATE_TYPE_HOST;
+ case FS_CANDIDATE_TYPE_SRFLX:
+ return TP_CALL_STREAM_CANDIDATE_TYPE_SERVER_REFLEXIVE;
+ case FS_CANDIDATE_TYPE_PRFLX:
+ return TP_CALL_STREAM_CANDIDATE_TYPE_PEER_REFLEXIVE;
+ case FS_CANDIDATE_TYPE_RELAY:
+ return TP_CALL_STREAM_CANDIDATE_TYPE_RELAY;
+ case FS_CANDIDATE_TYPE_MULTICAST:
+ return TP_CALL_STREAM_CANDIDATE_TYPE_MULTICAST;
+ default:
+ g_warning ("Unkown candidate type, assigning type NONE");
+ return TP_CALL_STREAM_CANDIDATE_TYPE_NONE;
}
+}
- tp_cli_dbus_properties_call_get_all (proxy, -1, TF_FUTURE_IFACE_CALL_STREAM,
- got_stream_properties, NULL, NULL, G_OBJECT (self));
- return self;
+static TpMediaStreamBaseProto
+fs_network_proto_to_tp (FsNetworkProtocol proto)
+{
+ switch (proto)
+ {
+ case FS_NETWORK_PROTOCOL_UDP:
+ return TP_MEDIA_STREAM_BASE_PROTO_UDP;
+ case FS_NETWORK_PROTOCOL_TCP:
+ return TP_MEDIA_STREAM_BASE_PROTO_TCP;
+ default:
+ g_warning ("Invalid protocl, assigning to UDP");
+ return TP_MEDIA_STREAM_BASE_PROTO_UDP;
+ }
}
-static void
-cb_fs_new_local_candidate (TfCallStream *stream, FsCandidate *candidate)
+
+static GValueArray *
+fscandidate_to_tpcandidate (TfCallStream *stream, FsCandidate *candidate)
{
- GPtrArray *candidate_list = g_ptr_array_sized_new (1);
- GValueArray *gva;
GHashTable *extra_info;
extra_info = tp_asv_new (NULL, NULL);
- if (candidate->priority)
- tp_asv_set_uint32 (extra_info, "Priority", candidate->priority);
+
+ tp_asv_set_uint32 (extra_info, "type",
+ fscandidatetype_to_tp (candidate->type));
if (candidate->foundation)
- tp_asv_set_string (extra_info, "Foundation", candidate->foundation);
+ tp_asv_set_string (extra_info, "foundation", candidate->foundation);
+
+ tp_asv_set_uint32 (extra_info, "protocol",
+ fs_network_proto_to_tp (candidate->proto));
+
+ if (candidate->base_ip)
+ {
+ tp_asv_set_string (extra_info, "base-ip", candidate->base_ip);
+ tp_asv_set_uint32 (extra_info, "base-port", candidate->base_port);
+ }
+
+ if (candidate->priority)
+ tp_asv_set_uint32 (extra_info, "priority", candidate->priority);
+
+
+ if (candidate->type == FS_CANDIDATE_TYPE_MULTICAST)
+ tp_asv_set_uint32 (extra_info, "ttl", candidate->ttl);
if (stream->multiple_usernames)
{
if (candidate->username)
- tp_asv_set_string (extra_info, "Username", candidate->username);
+ tp_asv_set_string (extra_info, "username", candidate->username);
if (candidate->password)
- tp_asv_set_string (extra_info, "Password", candidate->password);
+ tp_asv_set_string (extra_info, "password", candidate->password);
}
- else
+
+
+ return tp_value_array_build (4,
+ G_TYPE_UINT, candidate->component_id,
+ G_TYPE_STRING, candidate->ip,
+ G_TYPE_UINT, candidate->port,
+ TP_HASH_TYPE_CANDIDATE_INFO, extra_info,
+ G_TYPE_INVALID);
+}
+
+static void
+cb_fs_new_local_candidate (TfCallStream *stream, FsCandidate *candidate)
+{
+ GPtrArray *candidate_list = g_ptr_array_sized_new (1);
+
+ if (!stream->multiple_usernames)
{
if ((!stream->last_local_username && candidate->username) ||
(!stream->last_local_password && candidate->password) ||
@@ -1011,36 +1351,38 @@ cb_fs_new_local_candidate (TfCallStream *stream, FsCandidate *candidate)
stream->last_local_password = g_strdup ("");
/* Add a callback to kill Call on errors */
- tf_future_cli_call_stream_interface_media_call_set_credentials (
+ tp_cli_call_stream_interface_media_call_set_credentials (
stream->proxy, -1, stream->last_local_username,
stream->last_local_password, NULL, NULL, NULL, NULL);
}
}
- gva = tp_value_array_build (4,
- G_TYPE_UINT, candidate->component_id,
- G_TYPE_STRING, candidate->ip,
- G_TYPE_UINT, candidate->port,
- TF_FUTURE_HASH_TYPE_CANDIDATE_INFO, extra_info,
- G_TYPE_INVALID);
+ g_debug ("Local Candidate: %s c:%d fstype:%d fsproto: %d ip:%s port:%u prio:%d u/p:%s/%s ttl:%d base_ip:%s base_port:%d",
+ candidate->foundation,candidate->component_id, candidate->type,
+ candidate->proto, candidate->ip, candidate->port,
+ candidate->priority, candidate->username, candidate->password,
+ candidate->ttl,candidate-> base_ip, candidate->base_port);
+
- g_ptr_array_add (candidate_list, gva);
+ g_ptr_array_add (candidate_list,
+ fscandidate_to_tpcandidate (stream, candidate));
/* Should also check for errors */
- tf_future_cli_call_stream_interface_media_call_add_candidates (stream->proxy,
+ tp_cli_call_stream_interface_media_call_add_candidates (stream->proxy,
-1, candidate_list, NULL, NULL, NULL, NULL);
- g_boxed_free (TF_FUTURE_ARRAY_TYPE_CANDIDATE_LIST, candidate_list);
+ g_boxed_free (TP_ARRAY_TYPE_CANDIDATE_LIST, candidate_list);
}
static void
cb_fs_local_candidates_prepared (TfCallStream *stream)
{
- tf_future_cli_call_stream_interface_media_call_candidates_prepared (
- stream->proxy, -1, NULL, NULL, NULL, NULL);
+ g_debug ("Local candidates prepared");
+ tp_cli_call_stream_interface_media_call_finish_initial_candidates (
+ stream->proxy, -1, NULL, NULL, NULL, NULL);
}
static void
@@ -1054,102 +1396,103 @@ cb_fs_component_state_changed (TfCallStream *stream, guint component,
switch (fsstate)
{
+ default:
+ g_warning ("Unknown Farstream state, returning ExhaustedCandidates");
+ /* fall through */
case FS_STREAM_STATE_FAILED:
- case FS_STREAM_STATE_DISCONNECTED:
- state = TP_MEDIA_STREAM_STATE_DISCONNECTED;
+ state = TP_STREAM_ENDPOINT_STATE_EXHAUSTED_CANDIDATES;
break;
+ case FS_STREAM_STATE_DISCONNECTED:
case FS_STREAM_STATE_GATHERING:
case FS_STREAM_STATE_CONNECTING:
- case FS_STREAM_STATE_CONNECTED:
- state = TP_MEDIA_STREAM_STATE_CONNECTING;
+ state = TP_STREAM_ENDPOINT_STATE_CONNECTING;
break;
+ case FS_STREAM_STATE_CONNECTED:
+ state = TP_STREAM_ENDPOINT_STATE_PROVISIONALLY_CONNECTED;
case FS_STREAM_STATE_READY:
- default:
- state = TP_MEDIA_STREAM_STATE_CONNECTED;
+ state = TP_STREAM_ENDPOINT_STATE_FULLY_CONNECTED;
break;
}
- tf_future_cli_call_stream_endpoint_call_set_stream_state (stream->endpoint,
- -1, state, NULL, NULL, NULL, NULL);
+ g_debug ("Endpoint state changed to %d (fs: %d)",
+ state, fsstate);
+
+ tp_cli_call_stream_endpoint_call_set_endpoint_state (stream->endpoint,
+ -1, component, state, NULL, NULL, NULL, NULL);
}
+static void
+cb_fs_new_active_candidate_pair (TfCallStream *stream,
+ FsCandidate *local_candidate,
+ FsCandidate *remote_candidate)
+{
+ GValueArray *local_tp_candidate =
+ fscandidate_to_tpcandidate (stream, local_candidate);
+ GValueArray *remote_tp_candidate =
+ fscandidate_to_tpcandidate (stream, remote_candidate);
+
+ g_debug ("new active candidate pair local: %s (%d) remote: %s (%d)",
+ local_candidate->ip, local_candidate->port,
+ remote_candidate->ip, remote_candidate->port);
+
+ tp_cli_call_stream_endpoint_call_set_selected_candidate_pair (
+ stream->endpoint, -1, local_tp_candidate, remote_tp_candidate,
+ NULL, NULL, NULL, NULL);
+
+ g_boxed_free (TP_STRUCT_TYPE_CANDIDATE, local_tp_candidate);
+ g_boxed_free (TP_STRUCT_TYPE_CANDIDATE, remote_tp_candidate);
+}
gboolean
tf_call_stream_bus_message (TfCallStream *stream, GstMessage *message)
{
- const GstStructure *s;
- const GValue *val;
+ FsError errorno;
+ const gchar *msg;
+ FsCandidate *candidate;
+ guint component;
+ FsStreamState fsstate;
+ FsCandidate *local_candidate;
+ FsCandidate *remote_candidate;
if (!stream->fsstream)
return FALSE;
- s = gst_message_get_structure (message);
-
- if (gst_structure_has_name (s, "farstream-error"))
+ if (fs_parse_error (G_OBJECT (stream->fsstream), message, &errorno, &msg))
{
- GObject *object;
- const gchar *msg;
- FsError errorno;
GEnumClass *enumclass;
GEnumValue *enumvalue;
- const gchar *debug;
-
- val = gst_structure_get_value (s, "src-object");
- object = g_value_get_object (val);
-
- if (object != (GObject*) stream->fsstream)
- return FALSE;
-
- val = gst_structure_get_value (s, "error-no");
- errorno = g_value_get_enum (val);
- msg = gst_structure_get_string (s, "error-msg");
- debug = gst_structure_get_string (s, "debug-msg");
enumclass = g_type_class_ref (FS_TYPE_ERROR);
enumvalue = g_enum_get_value (enumclass, errorno);
- g_warning ("error (%s (%d)): %s : %s",
- enumvalue->value_nick, errorno, msg, debug);
+ g_warning ("error (%s (%d)): %s",
+ enumvalue->value_nick, errorno, msg);
g_type_class_unref (enumclass);
- tf_content_error_literal (TF_CONTENT (stream->call_content),
- TF_FUTURE_CONTENT_REMOVAL_REASON_ERROR, "", msg);
- return TRUE;
+ tf_call_stream_fail_literal (stream,
+ TP_CALL_STATE_CHANGE_REASON_INTERNAL_ERROR,
+ TP_ERROR_STR_MEDIA_STREAMING_ERROR, msg);
}
-
- val = gst_structure_get_value (s, "stream");
- if (!val)
- return FALSE;
- if (!G_VALUE_HOLDS_OBJECT (val))
- return FALSE;
- if (g_value_get_object (val) != stream->fsstream)
- return FALSE;
-
- if (gst_structure_has_name (s, "farstream-new-local-candidate"))
+ else if (fs_stream_parse_new_local_candidate (stream->fsstream, message,
+ &candidate))
{
- FsCandidate *candidate;
-
- val = gst_structure_get_value (s, "candidate");
- candidate = g_value_get_boxed (val);
-
cb_fs_new_local_candidate (stream, candidate);
- return TRUE;
}
- else if (gst_structure_has_name (s, "farstream-local-candidates-prepared"))
+ else if (fs_stream_parse_local_candidates_prepared (stream->fsstream,
+ message))
{
cb_fs_local_candidates_prepared (stream);
}
- else if (gst_structure_has_name (s, "farstream-component-state-changed"))
+ else if (fs_stream_parse_component_state_changed (stream->fsstream, message,
+ &component, &fsstate))
{
- guint component;
- FsStreamState fsstate;
-
- if (!gst_structure_get_uint (s, "component", &component) ||
- !gst_structure_get_enum (s, "state", FS_TYPE_STREAM_STATE,
- (gint*) &fsstate))
- return TRUE;
-
cb_fs_component_state_changed (stream, component, fsstate);
}
+ else if (fs_stream_parse_new_active_candidate_pair (stream->fsstream, message,
+ &local_candidate, &remote_candidate))
+ {
+ cb_fs_new_active_candidate_pair (stream, local_candidate,
+ remote_candidate);
+ }
else
{
return FALSE;
@@ -1157,3 +1500,85 @@ tf_call_stream_bus_message (TfCallStream *stream, GstMessage *message)
return TRUE;
}
+
+static void
+tf_call_stream_fail_literal (TfCallStream *self,
+ TpCallStateChangeReason reason,
+ const gchar *detailed_reason,
+ const gchar *message)
+{
+ g_warning ("%s", message);
+ tp_cli_call_stream_interface_media_call_fail (
+ self->proxy, -1,
+ tp_value_array_build (4,
+ G_TYPE_UINT, 0,
+ G_TYPE_UINT, reason,
+ G_TYPE_STRING, detailed_reason,
+ G_TYPE_STRING, message,
+ G_TYPE_INVALID),
+ NULL, NULL, NULL, NULL);
+}
+
+
+static void
+tf_call_stream_fail (TfCallStream *self,
+ TpCallStateChangeReason reason,
+ const gchar *detailed_reason,
+ const gchar *message_format,
+ ...)
+{
+ gchar *message;
+ va_list valist;
+
+ va_start (valist, message_format);
+ message = g_strdup_vprintf (message_format, valist);
+ va_end (valist);
+
+ tf_call_stream_fail_literal (self, reason, detailed_reason, message);
+ g_free (message);
+}
+
+void
+tf_call_stream_sending_failed (TfCallStream *self, const gchar *message)
+{
+ g_warning ("Reporting sending failure: %s", message);
+
+ tp_cli_call_stream_interface_media_call_report_sending_failure (
+ self->proxy, -1, TP_CALL_STATE_CHANGE_REASON_INTERNAL_ERROR,
+ TP_ERROR_STR_MEDIA_STREAMING_ERROR,
+ message, NULL, NULL, NULL, NULL);
+}
+
+
+void
+tf_call_stream_receiving_failed (TfCallStream *self,
+ guint *handles, guint handle_count,
+ const gchar *message)
+{
+ if (handle_count && handle_count > 0)
+ {
+ guint i;
+
+ for (i = 0; i < handle_count; i++)
+ if (handles[i] == self->contact_handle)
+ goto ok;
+ return;
+ }
+ ok:
+
+ g_warning ("Reporting receiving failure: %s", message);
+
+ tp_cli_call_stream_interface_media_call_report_receiving_failure (
+ self->proxy, -1, TP_CALL_STATE_CHANGE_REASON_INTERNAL_ERROR,
+ TP_ERROR_STR_MEDIA_STREAMING_ERROR,
+ message, NULL, NULL, NULL, NULL);
+}
+
+
+TpCallStream *
+tf_call_stream_get_proxy (TfCallStream *stream)
+{
+ g_return_val_if_fail (TF_IS_CALL_STREAM (stream), NULL);
+
+ return stream->proxy;
+}
diff --git a/telepathy-farstream/call-stream.h b/telepathy-farstream/call-stream.h
index dc65184..31961c1 100644
--- a/telepathy-farstream/call-stream.h
+++ b/telepathy-farstream/call-stream.h
@@ -23,33 +23,32 @@
#include <glib-object.h>
#include <gst/gst.h>
-#include <telepathy-glib/channel.h>
+#include <telepathy-glib/telepathy-glib.h>
#include "call-channel.h"
#include "call-content.h"
-#include "extensions/extensions.h"
G_BEGIN_DECLS
-#define TF_TYPE_STREAM tf_call_stream_get_type()
+#define TF_TYPE_CALL_STREAM tf_call_stream_get_type()
#define TF_CALL_STREAM(obj) \
(G_TYPE_CHECK_INSTANCE_CAST ((obj), \
- TF_TYPE_STREAM, TfCallStream))
+ TF_TYPE_CALL_STREAM, TfCallStream))
#define TF_CALL_STREAM_CLASS(klass) \
(G_TYPE_CHECK_CLASS_CAST ((klass), \
- TF_TYPE_STREAM, TfCallStreamClass))
+ TF_TYPE_CALL_STREAM, TfCallStreamClass))
-#define TF_IS_STREAM(obj) \
- (G_TYPE_CHECK_INSTANCE_TYPE ((obj), TF_TYPE_STREAM))
+#define TF_IS_CALL_STREAM(obj) \
+ (G_TYPE_CHECK_INSTANCE_TYPE ((obj), TF_TYPE_CALL_STREAM))
-#define TF_IS_STREAM_CLASS(klass) \
- (G_TYPE_CHECK_CLASS_TYPE ((klass), TF_TYPE_STREAM))
+#define TF_IS_CALL_STREAM_CLASS(klass) \
+ (G_TYPE_CHECK_CLASS_TYPE ((klass), TF_TYPE_CALL_STREAM))
#define TF_CALL_STREAM_GET_CLASS(obj) \
(G_TYPE_INSTANCE_GET_CLASS ((obj), \
- TF_TYPE_STREAM, TfCallStreamClass))
+ TF_TYPE_CALL_STREAM, TfCallStreamClass))
typedef struct _TfCallStreamPrivate TfCallStreamPrivate;
@@ -76,27 +75,32 @@ struct _TfCallStream {
TfCallContent *call_content;
- TfFutureCallStream *proxy;
+ TpCallStream *proxy;
+ gboolean has_endpoint_properties;
gchar *endpoint_objpath;
TpProxy *endpoint;
gchar *creds_username;
gchar *creds_password;
GList *stored_remote_candidates;
gboolean multiple_usernames;
+ gboolean controlling;
gchar *last_local_username;
gchar *last_local_password;
- TfFutureSendingState local_sending_state;
+ TpStreamFlowState sending_state;
gboolean has_send_resource;
+ TpStreamFlowState receiving_state;
+ gboolean has_receive_resource;
+
gboolean has_contact;
guint contact_handle;
FsStream *fsstream;
gboolean has_media_properties;
- TfFutureStreamTransportType transport_type;
+ TpStreamTransportType transport_type;
gboolean server_info_retrieved;
GPtrArray *stun_servers;
GPtrArray *relay_info;
@@ -110,13 +114,21 @@ struct _TfCallStreamClass{
GType tf_call_stream_get_type (void);
TfCallStream *tf_call_stream_new (
- TfCallChannel *channel,
TfCallContent *content,
- const gchar *object_path,
- GError **error);
+ TpCallStream *stream_proxy);
gboolean tf_call_stream_bus_message (TfCallStream *stream, GstMessage *message);
+void tf_call_stream_sending_failed (TfCallStream *stream, const gchar *message);
+
+void tf_call_stream_receiving_failed (TfCallStream *stream,
+ guint *handles, guint handle_count,
+ const gchar *message);
+
+TpCallStream *
+tf_call_stream_get_proxy (TfCallStream *stream);
+
+
G_END_DECLS
#endif /* __TF_CALL_STREAM_H__ */
diff --git a/telepathy-farstream/channel.c b/telepathy-farstream/channel.c
index d2f77b0..ac903c1 100644
--- a/telepathy-farstream/channel.c
+++ b/telepathy-farstream/channel.c
@@ -31,16 +31,10 @@
#include <stdlib.h>
-#include <telepathy-glib/channel.h>
-#include <telepathy-glib/dbus.h>
-#include <telepathy-glib/enums.h>
-#include <telepathy-glib/errors.h>
-#include <telepathy-glib/interfaces.h>
-#include <telepathy-glib/util.h>
+#include <telepathy-glib/telepathy-glib.h>
#include <farstream/fs-conference.h>
-#include "extensions/extensions.h"
#include "channel.h"
#include "channel-priv.h"
@@ -152,8 +146,23 @@ tf_channel_get_property (GObject *object,
break;
case PROP_FS_CONFERENCES:
if (self->priv->call_channel)
- g_object_get_property (G_OBJECT (self->priv->call_channel),
- "fs-conferences", value);
+ {
+ g_object_get_property (G_OBJECT (self->priv->call_channel),
+ "fs-conferences", value);
+ }
+ else if (self->priv->media_signalling_channel &&
+ self->priv->media_signalling_channel->session)
+ {
+ GPtrArray *array =
+ g_ptr_array_new_with_free_func ((GDestroyNotify) gst_object_unref);
+ FsConference *conf = NULL;
+
+ g_object_get (self->priv->media_signalling_channel->session,
+ "farstream-conference", &conf, NULL);
+ g_ptr_array_add (array, conf);
+ g_value_take_boxed (value, array);
+ }
+
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
@@ -326,22 +335,34 @@ channel_prepared (GObject *obj,
"stream-created", G_CALLBACK (channel_stream_created),
self, 0);
g_simple_async_result_set_op_res_gboolean (res, TRUE);
+ g_simple_async_result_complete (res);
}
else if (tp_proxy_has_interface_by_id (as_proxy,
- TF_FUTURE_IFACE_QUARK_CHANNEL_TYPE_CALL))
+ TP_IFACE_QUARK_CHANNEL_TYPE_CALL))
{
- tf_call_channel_new_async (channel_proxy, call_channel_ready, res);
+ if (!TP_IS_CALL_CHANNEL (channel_proxy))
+ {
+ g_simple_async_result_set_error (res, TP_ERROR,
+ TP_ERROR_INVALID_ARGUMENT,
+ "You must pass a TpCallChannel object if its a Call channel");
+ g_simple_async_result_set_op_res_gboolean (res, FALSE);
+ g_simple_async_result_complete (res);
+ }
+ else
+ {
+ tf_call_channel_new_async (channel_proxy, call_channel_ready, res);
- self->priv->channel_invalidated_handler = g_signal_connect (
- self->priv->channel_proxy,
- "invalidated", G_CALLBACK (channel_invalidated), self);
+ self->priv->channel_invalidated_handler = g_signal_connect (
+ self->priv->channel_proxy,
+ "invalidated", G_CALLBACK (channel_invalidated), self);
+ }
}
else
{
g_simple_async_result_set_error (res, TP_ERRORS, TP_ERROR_NOT_IMPLEMENTED,
"Channel does not implement "
TP_IFACE_CHANNEL_INTERFACE_MEDIA_SIGNALLING " or "
- TF_FUTURE_IFACE_CHANNEL_TYPE_CALL);
+ TP_IFACE_CHANNEL_TYPE_CALL);
goto error;
}
@@ -606,6 +627,9 @@ tf_channel_new_async (TpChannel *channel_proxy,
GAsyncReadyCallback callback,
gpointer user_data)
{
+ g_return_if_fail (channel_proxy != NULL);
+ g_return_if_fail (callback != NULL);
+
return g_async_initable_new_async (TF_TYPE_CHANNEL,
0, NULL, callback, user_data,
"channel", channel_proxy,
@@ -627,6 +651,9 @@ gboolean
tf_channel_bus_message (TfChannel *channel,
GstMessage *message)
{
+ g_return_val_if_fail (channel != NULL, FALSE);
+ g_return_val_if_fail (message != NULL, FALSE);
+
if (channel->priv->media_signalling_channel)
return tf_media_signalling_channel_bus_message (
channel->priv->media_signalling_channel, message);
diff --git a/telepathy-farstream/content-priv.h b/telepathy-farstream/content-priv.h
index bee82e3..ab137da 100644
--- a/telepathy-farstream/content-priv.h
+++ b/telepathy-farstream/content-priv.h
@@ -19,8 +19,12 @@ struct _TfContentClass{
GObjectClass parent_class;
void (*content_error) (TfContent *content,
- guint reason, /* TfFutureContentRemovalReason */
- const gchar *detailed_reason,
+ const gchar *message);
+
+ void (*sending_failed) (TfContent *content,
+ const gchar *message);
+ void (*receiving_failed) (TfContent *content,
+ guint *handles, guint handle_count,
const gchar *message);
GstIterator * (*iterate_src_pads) (TfContent *content, guint *handle,
@@ -29,14 +33,15 @@ struct _TfContentClass{
gboolean _tf_content_start_sending (TfContent *self);
void _tf_content_stop_sending (TfContent *self);
+void _tf_content_mute_to_stop_sending (TfContent *self);
void _tf_content_emit_src_pad_added (TfContent *self, guint handle,
FsStream *stream, GstPad *pad, FsCodec *codec);
gboolean _tf_content_start_receiving (TfContent *self, guint *handles,
guint handle_count);
-void _tf_content_stop_receiving (TfContent *self, guint *handles,
- guint handle_count);
+void _tf_content_stop_receiving (TfContent *self,
+ guint *handles, guint handle_count);
G_END_DECLS
diff --git a/telepathy-farstream/content.c b/telepathy-farstream/content.c
index 7f23596..5a76dd6 100644
--- a/telepathy-farstream/content.c
+++ b/telepathy-farstream/content.c
@@ -15,10 +15,10 @@
* Objects of this class allow the user to handle the media side of a Telepathy
* channel handled by #TfChannel.
*
- * This object is created by the #TfChannel and the user is notified of its
- * creation by the #TfChannel::content-added signal. In the callback for this
- * signal, the user should call tf_content_set_codec_preferences() and connect
- * to the #TfContent::src-pad-added signal.
+ * This object is created by the #TfChannel and the user is notified
+ * of its creation by the #TfChannel::content-added signal. In the
+ * callback for this signal, the user should connect to the
+ * #TfContent::src-pad-added signal.
*
*/
@@ -152,7 +152,7 @@ tf_content_class_init (TfContentClass *klass)
G_OBJECT_CLASS_TYPE (klass),
G_SIGNAL_RUN_LAST,
0, NULL, NULL,
- g_cclosure_marshal_VOID__VOID,
+ g_cclosure_marshal_VOID__BOOLEAN,
G_TYPE_NONE, 0);
/**
@@ -221,7 +221,7 @@ tf_content_class_init (TfContentClass *klass)
G_OBJECT_CLASS_TYPE (klass),
G_SIGNAL_RUN_LAST,
0, NULL, NULL,
- _tf_marshal_VOID__POINTER_UINT,
+ _tf_marshal_VOID__BOOLEAN_POINTER_UINT,
G_TYPE_NONE, 2, G_TYPE_POINTER, G_TYPE_UINT);
/**
@@ -255,6 +255,7 @@ _tf_content_start_sending (TfContent *self)
GValue sending_success_val = {0,};
gboolean sending_success;
+
if (self->sending_count)
{
self->sending_count ++;
@@ -289,9 +290,12 @@ _tf_content_stop_sending (TfContent *self)
self->sending_count --;
if (self->sending_count == 0)
- g_signal_emit (self, signals[SIGNAL_STOP_SENDING], 0);
+ {
+ g_signal_emit (self, signals[SIGNAL_STOP_SENDING], 0);
+ }
}
+
void
_tf_content_emit_src_pad_added (TfContent *self, guint handle,
FsStream *stream, GstPad *pad, FsCodec *codec)
@@ -303,24 +307,23 @@ _tf_content_emit_src_pad_added (TfContent *self, guint handle,
/**
* tf_content_error_literal:
* @content: a #TfContent
- * @reason: the reason (a #TfContentRemovalReason)
- * @detailed_reason: The detailled error (as a DBus name)
* @message: error Message
*
- * Send an error to the Content to the CM, the effect is most likely that the
- * content will be removed.
+ * Send a fatal streaming error to the Content to the CM, the effect is most
+ * likely that the content will be removed.
*/
void
tf_content_error_literal (TfContent *content,
- guint reason, /* TfFutureContentRemovalReason */
- const gchar *detailed_reason,
const gchar *message)
{
TfContentClass *klass = TF_CONTENT_GET_CLASS (content);
+ g_return_if_fail (content != NULL);
+ g_return_if_fail (message != NULL);
+
if (klass->content_error)
- klass->content_error (content, reason, detailed_reason, message);
+ klass->content_error (content, message);
else
GST_WARNING ("content_error not defined in class: %s", message);
}
@@ -328,30 +331,29 @@ tf_content_error_literal (TfContent *content,
/**
* tf_content_error:
* @content: a #TfContent
- * @reason: the reason (a #TfContentRemovalReason)
- * @detailed_reason: The detailled error (as a DBus name)
* @message_format: error Message with printf style formatting
* @...: Parameters to insert into the @message_format string
*
- * Send an error to the Content to the CM, the effect is most likely that the
- * content will be removed.
+ * Send a fatal streaming error to the Content to the CM, the effect is most
+ * likely that the content will be removed.
*/
void
tf_content_error (TfContent *content,
- guint reason, /* TfFutureContentRemovalReason */
- const gchar *detailed_reason,
const gchar *message_format,
...)
{
gchar *message;
va_list valist;
+ g_return_if_fail (content != NULL);
+ g_return_if_fail (message_format != NULL);
+
va_start (valist, message_format);
message = g_strdup_vprintf (message_format, valist);
va_end (valist);
- tf_content_error_literal (content, reason, detailed_reason, message);
+ tf_content_error_literal (content, message);
g_free (message);
}
@@ -373,6 +375,8 @@ tf_content_iterate_src_pads (TfContent *content, guint *handles,
{
TfContentClass *klass = TF_CONTENT_GET_CLASS (content);
+ g_return_val_if_fail (content != NULL, NULL);
+
if (klass->iterate_src_pads)
return klass->iterate_src_pads (content, handles, handle_count);
else
@@ -419,6 +423,129 @@ void
_tf_content_stop_receiving (TfContent *self, guint *handles,
guint handle_count)
{
- g_signal_emit (self, signals[SIGNAL_STOP_SENDING], 0, handles,
+ g_debug ("Requesting that the application stop receiving");
+ g_signal_emit (self, signals[SIGNAL_STOP_RECEIVING], 0, handles,
handle_count);
}
+
+
+/**
+ * tf_content_sending_failed_literal:
+ * @content: a #TfContent
+ * @message_format: Message with printf style formatting
+ * @...: Parameters to insert into the @message_format string
+ *
+ * Informs the Connection Manager that sending has failed for this
+ * content. This is a transient error and it may or not not end the Content
+ * and the call.
+ */
+
+void
+tf_content_sending_failed_literal (TfContent *content,
+ const gchar *message)
+{
+ TfContentClass *klass = TF_CONTENT_GET_CLASS (content);
+
+ g_return_if_fail (content != NULL);
+ g_return_if_fail (message != NULL);
+
+ if (klass->content_error)
+ klass->sending_failed (content, message);
+ else
+ GST_WARNING ("sending_failed not defined in class, ignoring error: %s",
+ message);
+}
+
+/**
+ * tf_content_sending_failed:
+ * @content: a #TfContent
+ * @message: The error message
+ *
+ * Informs the Connection Manager that sending has failed for this
+ * content. This is a transient error and it may or not not end the Content
+ * and the call.
+ */
+
+void
+tf_content_sending_failed (TfContent *content,
+ const gchar *message_format, ...)
+{
+ gchar *message;
+ va_list valist;
+
+ g_return_if_fail (content != NULL);
+ g_return_if_fail (message_format != NULL);
+
+ va_start (valist, message_format);
+ message = g_strdup_vprintf (message_format, valist);
+ va_end (valist);
+
+ tf_content_sending_failed_literal (content, message);
+ g_free (message);
+}
+
+/**
+ * tf_content_receiving_failed_literal:
+ * @content: a #TfContent
+ * @handles: an array of #guint representing Telepathy handles, may be %NULL
+ * @handle_count: the numner of handles in @handles
+ * @message: The error message
+ *
+ * Informs the Connection Manager that receiving has failed for this
+ * content. This is a transient error and it may or not not end the Content
+ * and the call.
+ *
+ * If handles are not specific, it assumes that it is valid for all handles.
+ */
+
+void
+tf_content_receiving_failed_literal (TfContent *content,
+ guint *handles, guint handle_count,
+ const gchar *message)
+{
+ TfContentClass *klass = TF_CONTENT_GET_CLASS (content);
+
+ g_return_if_fail (content != NULL);
+ g_return_if_fail (message != NULL);
+
+ if (klass->content_error)
+ klass->receiving_failed (content, handles, handle_count, message);
+ else
+ GST_WARNING ("receiving_failed not defined in class, ignoring error: %s",
+ message);
+}
+
+
+/**
+ * tf_content_receiving_failed:
+ * @content: a #TfContent
+ * @handles: an array of #guint representing Telepathy handles, may be %NULL
+ * @handle_count: the numner of handles in @handles
+ * @message_format: Message with printf style formatting
+ * @...: Parameters to insert into the @message_format string
+ *
+ * Informs the Connection Manager that receiving has failed for this
+ * content. This is a transient error and it may or not not end the Content
+ * and the call.
+ *
+ * If handles are not specific, it assumes that it is valid for all handles.
+ */
+
+void
+tf_content_receiving_failed (TfContent *content,
+ guint *handles, guint handle_count,
+ const gchar *message_format, ...)
+{
+ gchar *message;
+ va_list valist;
+
+ g_return_if_fail (content != NULL);
+ g_return_if_fail (message_format != NULL);
+
+ va_start (valist, message_format);
+ message = g_strdup_vprintf (message_format, valist);
+ va_end (valist);
+
+ tf_content_receiving_failed_literal (content, handles, handle_count, message);
+ g_free (message);
+}
diff --git a/telepathy-farstream/content.h b/telepathy-farstream/content.h
index e071679..97c5c3a 100644
--- a/telepathy-farstream/content.h
+++ b/telepathy-farstream/content.h
@@ -47,13 +47,21 @@ typedef struct _TfContentClass TfContentClass;
GType tf_content_get_type (void);
void tf_content_error_literal (TfContent *content,
- guint reason, /* TfFutureContentRemovalReason */
- const gchar *detailed_reason,
const gchar *message);
-
void tf_content_error (TfContent *content,
- guint reason, /* TfFutureContentRemovalReason */
- const gchar *detailed_reason,
+ const gchar *message_format, ...) G_GNUC_PRINTF (2, 3);
+
+
+void tf_content_sending_failed_literal (TfContent *content,
+ const gchar *message);
+void tf_content_sending_failed (TfContent *content,
+ const gchar *message_format, ...) G_GNUC_PRINTF (2, 3);
+
+void tf_content_receiving_failed_literal (TfContent *content,
+ guint *handles, guint handle_count,
+ const gchar *message);
+void tf_content_receiving_failed (TfContent *content,
+ guint *handles, guint handle_count,
const gchar *message_format, ...) G_GNUC_PRINTF (4, 5);
GstIterator *tf_content_iterate_src_pads (TfContent *content,
diff --git a/telepathy-farstream/media-signalling-channel.c b/telepathy-farstream/media-signalling-channel.c
index bfd3696..a029f91 100644
--- a/telepathy-farstream/media-signalling-channel.c
+++ b/telepathy-farstream/media-signalling-channel.c
@@ -35,31 +35,9 @@
#include "stream.h"
#include "session-priv.h"
-#include "stream-priv.h"
#include "tf-signals-marshal.h"
-struct _TfMediaSignallingChannel {
- GObject parent;
-
- TpChannel *channel_proxy;
-
- TfNatProperties nat_props;
- guint prop_id_nat_traversal;
- guint prop_id_stun_server;
- guint prop_id_stun_port;
- guint prop_id_gtalk_p2p_relay_token;
-
- /* sessions is NULL until we've had a reply from GetSessionHandlers */
- TfSession *session;
- gboolean got_sessions;
- GPtrArray *streams;
-};
-
-struct _TfMediaSignallingChannelClass{
- GObjectClass parent_class;
-};
-
G_DEFINE_TYPE (TfMediaSignallingChannel, tf_media_signalling_channel,
G_TYPE_OBJECT);
diff --git a/telepathy-farstream/media-signalling-channel.h b/telepathy-farstream/media-signalling-channel.h
index 3e9f1a2..57871df 100644
--- a/telepathy-farstream/media-signalling-channel.h
+++ b/telepathy-farstream/media-signalling-channel.h
@@ -26,6 +26,7 @@
#include <telepathy-glib/channel.h>
#include "stream.h"
+#include "session-priv.h"
G_BEGIN_DECLS
@@ -66,6 +67,29 @@ typedef struct _TfMediaSignallingChannel TfMediaSignallingChannel;
* There are no overridable functions
*/
+
+struct _TfMediaSignallingChannel {
+ GObject parent;
+
+ TpChannel *channel_proxy;
+
+ TfNatProperties nat_props;
+ guint prop_id_nat_traversal;
+ guint prop_id_stun_server;
+ guint prop_id_stun_port;
+ guint prop_id_gtalk_p2p_relay_token;
+
+ /* sessions is NULL until we've had a reply from GetSessionHandlers */
+ TfSession *session;
+ gboolean got_sessions;
+ GPtrArray *streams;
+};
+
+struct _TfMediaSignallingChannelClass{
+ GObjectClass parent_class;
+};
+
+
typedef struct _TfMediaSignallingChannelClass TfMediaSignallingChannelClass;
GType tf_media_signalling_channel_get_type (void);
diff --git a/telepathy-farstream/media-signalling-content.c b/telepathy-farstream/media-signalling-content.c
index 34c3ebc..e11edc8 100644
--- a/telepathy-farstream/media-signalling-content.c
+++ b/telepathy-farstream/media-signalling-content.c
@@ -28,17 +28,17 @@
* channel using Farstream.
*/
-
#include "media-signalling-content.h"
#include <farstream/fs-conference.h>
#include <farstream/fs-utils.h>
+#include <telepathy-glib/proxy-subclass.h>
+#include <telepathy-glib/util.h>
+
#include <stdarg.h>
#include <string.h>
-#include <telepathy-glib/proxy-subclass.h>
-
#include "tf-signals-marshal.h"
#include "utils.h"
@@ -86,8 +86,6 @@ tf_media_signalling_content_get_property (GObject *object,
GParamSpec *pspec);
static void tf_media_signalling_content_error (TfContent *content,
- guint reason, /* TfFutureContentRemovalReason */
- const gchar *detailed_reason,
const gchar *message);
static GstIterator * tf_media_signalling_content_iterate_src_pads (
@@ -247,18 +245,20 @@ request_resource (TfStream *stream, guint direction,
{
if (direction & TP_MEDIA_STREAM_DIRECTION_SEND)
return _tf_content_start_sending (TF_CONTENT (self));
-
- if (!self->receiving && direction & TP_MEDIA_STREAM_DIRECTION_RECEIVE)
+ else if (direction & TP_MEDIA_STREAM_DIRECTION_RECEIVE)
{
- guint handles[2] = { self->handle, 0};
+ if (!self->receiving)
+ {
+ guint handles[2] = { self->handle, 0};
- self->receiving = _tf_content_start_receiving (TF_CONTENT (self),
- handles, 1);
+ self->receiving = _tf_content_start_receiving (TF_CONTENT (self),
+ handles, 1);
+ }
return self->receiving;
}
-
- return FALSE;
+ else
+ g_assert_not_reached ();
}
@@ -286,23 +286,11 @@ restart_source (TfStream *stream, TfMediaSignallingContent *self)
static void
tf_media_signalling_content_error (TfContent *content,
- guint reason, /* TfFutureContentRemovalReason */
- const gchar *detailed_reason,
const gchar *message)
{
TfMediaSignallingContent *self = TF_MEDIA_SIGNALLING_CONTENT (content);
- TpMediaStreamError stream_error;
-
- switch (reason)
- {
- case TF_FUTURE_CONTENT_REMOVAL_REASON_ERROR:
- stream_error = TP_MEDIA_STREAM_ERROR_MEDIA_ERROR;
- break;
- default:
- stream_error = TP_MEDIA_STREAM_ERROR_UNKNOWN;
- }
- tf_stream_error (self->stream, stream_error, message);
+ tf_stream_error (self->stream, TP_MEDIA_STREAM_ERROR_MEDIA_ERROR, message);
}
static GstIterator *
diff --git a/telepathy-farstream/media-signalling-content.h b/telepathy-farstream/media-signalling-content.h
index 2bb7fd4..085ed9d 100644
--- a/telepathy-farstream/media-signalling-content.h
+++ b/telepathy-farstream/media-signalling-content.h
@@ -26,7 +26,6 @@
#include <gst/gst.h>
#include <telepathy-glib/channel.h>
-#include "extensions/extensions.h"
#include "media-signalling-channel.h"
#include "content.h"
#include "content-priv.h"
diff --git a/telepathy-farstream/stream-priv.h b/telepathy-farstream/stream-priv.h
deleted file mode 100644
index 3e82a18..0000000
--- a/telepathy-farstream/stream-priv.h
+++ /dev/null
@@ -1,75 +0,0 @@
-#ifndef __TF_STREAM_PRIV_H__
-#define __TF_STREAM_PRIV_H__
-
-#include "stream.h"
-
-G_BEGIN_DECLS
-
-typedef struct _TfStreamPrivate TfStreamPrivate;
-
-/*
- * TfStream:
- * @parent: the parent #GObject
- * @stream_id: the ID of the stream (READ-ONLY)
- *
- * All other members are privated
- */
-
-struct _TfStream {
- GObject parent;
-
- /* Read-only */
- guint stream_id;
-
- /*< private >*/
-
- TfStreamPrivate *priv;
-};
-
-/*
- * TfStreamClass:
- * @parent_class: the parent #GObjecClass
- *
- * There are no overridable functions
- */
-
-struct _TfStreamClass {
- GObjectClass parent_class;
-
- /*< private >*/
-
- gpointer unused[4];
-};
-
-
-typedef struct {
- gchar *nat_traversal;
- gchar *stun_server;
- guint16 stun_port;
- gchar *relay_token;
-} TfNatProperties;
-
-typedef void (NewStreamCreatedCb) (TfStream *stream, gpointer channel);
-
-TfStream *
-_tf_stream_new (gpointer channel,
- FsConference *conference,
- FsParticipant *participant,
- TpMediaStreamHandler *proxy,
- guint stream_id,
- TpMediaStreamType media_type,
- TpMediaStreamDirection direction,
- TfNatProperties *nat_props,
- GList *local_codecs_config,
- NewStreamCreatedCb new_stream_created_cb);
-
-gboolean _tf_stream_bus_message (TfStream *stream,
- GstMessage *message);
-
-void _tf_stream_try_sending_codecs (TfStream *stream);
-
-TpMediaStreamError fserror_to_tperror (GError *error);
-
-G_END_DECLS
-
-#endif /* __TF_STREAM_PRIV_H__ */
diff --git a/telepathy-farstream/stream.c b/telepathy-farstream/stream.c
index a525e91..5afd9ad 100644
--- a/telepathy-farstream/stream.c
+++ b/telepathy-farstream/stream.c
@@ -46,8 +46,7 @@
#include <farstream/fs-utils.h>
#include "stream.h"
-#include "stream-priv.h"
-#include "channel.h"
+#include "media-signalling-channel.h"
#include "tf-signals-marshal.h"
#include "utils.h"
@@ -83,7 +82,7 @@ struct DtmfEvent {
struct _TfStreamPrivate
{
- TfChannel *channel;
+ TfMediaSignallingChannel *channel;
FsConference *fs_conference;
FsParticipant *fs_participant;
FsSession *fs_session;
@@ -332,7 +331,7 @@ tf_stream_set_property (GObject *object,
{
case PROP_CHANNEL:
self->priv->channel =
- TF_CHANNEL (g_value_get_object (value));
+ TF_MEDIA_SIGNALLING_CHANNEL (g_value_get_object (value));
break;
case PROP_FARSTREAM_CONFERENCE:
self->priv->fs_conference =
@@ -430,7 +429,7 @@ tf_stream_dispose (GObject *object)
tf_stream_free_resource (stream,
TP_MEDIA_STREAM_DIRECTION_RECEIVE);
- g_object_run_dispose (G_OBJECT (priv->fs_stream));
+ fs_stream_destroy (priv->fs_stream);
g_object_unref (priv->fs_stream);
tf_stream_free_resource (stream,
@@ -441,7 +440,7 @@ tf_stream_dispose (GObject *object)
if (priv->fs_session)
{
- g_object_run_dispose (G_OBJECT (priv->fs_session));
+ fs_session_destroy (priv->fs_session);
g_object_unref (priv->fs_session);
priv->fs_session = NULL;
}
@@ -506,7 +505,7 @@ tf_stream_class_init (TfStreamClass *klass)
g_param_spec_object ("channel",
"Telepathy channel",
"The TfChannel this stream is in",
- TF_TYPE_CHANNEL,
+ TF_TYPE_MEDIA_SIGNALLING_CHANNEL,
G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
g_object_class_install_property (object_class, PROP_FARSTREAM_CONFERENCE,
@@ -1606,23 +1605,6 @@ fill_fs_params (gpointer key, gpointer value, gpointer user_data)
fs_codec_add_optional_parameter (codec, key, value);
}
-static FsStreamDirection
-tpdirection_to_fsdirection (TpMediaStreamDirection dir)
-{
- switch (dir) {
- case TP_MEDIA_STREAM_DIRECTION_NONE:
- return FS_DIRECTION_NONE;
- case TP_MEDIA_STREAM_DIRECTION_SEND:
- return FS_DIRECTION_SEND;
- case TP_MEDIA_STREAM_DIRECTION_RECEIVE:
- return FS_DIRECTION_RECV;
- case TP_MEDIA_STREAM_DIRECTION_BIDIRECTIONAL:
- return FS_DIRECTION_BOTH;
- default:
- g_assert_not_reached ();
- }
-}
-
static void
set_remote_codecs (TpMediaStreamHandler *proxy G_GNUC_UNUSED,
const GPtrArray *codecs,
@@ -2035,13 +2017,11 @@ start_telephony_event (TpMediaStreamHandler *proxy G_GNUC_UNUSED,
static gboolean
check_codecs_for_telephone_event (TfStream *self, GList **codecs,
- FsCodec *send_codec, guint codecid)
+ FsCodec *send_codec, gint codecid)
{
GList *item = NULL;
- gboolean found = FALSE;
GError *error = NULL;
-
- again:
+ gboolean changed = FALSE;
for (item = *codecs; item; item = item->next)
{
@@ -2050,29 +2030,25 @@ check_codecs_for_telephone_event (TfStream *self, GList **codecs,
if (!g_ascii_strcasecmp (codec->encoding_name, "telephone-event") &&
send_codec->clock_rate == codec->clock_rate)
{
- if (found)
- {
- *codecs = g_list_delete_link (*codecs, item);
- goto again;
- }
- else if (codecid == (guint) codec->id)
- {
- return TRUE; }
+ if (codecid < 0 || codecid == codec->id)
+ return TRUE;
else
- {
- codec->id = codecid;
- }
+ codec->id = codecid;
+ changed = TRUE;
+ break;
}
}
- if (!found)
+ if (codecid < 0)
+ return FALSE;
+
+ if (!changed)
{
FsCodec *codec = fs_codec_new (codecid, "telephone-event",
FS_MEDIA_TYPE_AUDIO, send_codec->clock_rate);
*codecs = g_list_append (*codecs, codec);
}
-
if (!fs_stream_set_remote_codecs (self->priv->fs_stream, *codecs, &error))
{
/*
@@ -2145,11 +2121,28 @@ start_sound_telephony_event (TpMediaStreamHandler *proxy, guchar event,
gpointer user_data, GObject *object)
{
TfStream *self = TF_STREAM (object);
+ FsCodec *send_codec = NULL;
+ GList *codecs = NULL;
g_assert (self->priv->fs_session != NULL);
DEBUG (self, "called with event %u", event);
+ g_object_get (self->priv->fs_session,
+ "current-send-codec", &send_codec,
+ "codecs", &codecs,
+ NULL);
+
+ if (send_codec == NULL)
+ goto out;
+
+ if (check_codecs_for_telephone_event (self, &codecs, send_codec, -1))
+ {
+ WARNING (self, "Tried to do sound event while telephone-event is set,"
+ " ignoring");
+ goto out;
+ }
+
if (self->priv->sending_telephony_event)
{
WARNING (self, "start new telephony event without stopping the"
@@ -2163,6 +2156,10 @@ start_sound_telephony_event (TpMediaStreamHandler *proxy, guchar event,
if (!fs_session_start_telephony_event (self->priv->fs_session, event, 8))
WARNING (self, "sending sound event %u failed", event);
self->priv->sending_telephony_event = TRUE;
+
+ out:
+ fs_codec_destroy (send_codec);
+ fs_codec_list_destroy (codecs);
}
@@ -2178,8 +2175,7 @@ stop_telephony_event (TpMediaStreamHandler *proxy G_GNUC_UNUSED,
DEBUG (self, "called");
if (!self->priv->sending_telephony_event)
- WARNING (self, "Trying to stop telephony event without having started"
- " one");
+ WARNING (self, "Trying to stop telephony event without having started one");
self->priv->sending_telephony_event = FALSE;
if (!fs_session_stop_telephony_event (self->priv->fs_session))
@@ -2494,12 +2490,16 @@ _tf_stream_bus_message (TfStream *stream,
value = gst_structure_get_value (s, "stream");
fsstream = g_value_get_object (value);
+ g_debug ("new local fs: %p s:%p", stream->priv->fs_stream, stream);
+
if (fsstream != stream->priv->fs_stream)
return FALSE;
value = gst_structure_get_value (s, "candidate");
candidate = g_value_get_boxed (value);
+ g_debug ("NEW LOCAL CAND");
+
cb_fs_new_local_candidate (stream, candidate);
return TRUE;
}
@@ -2511,9 +2511,13 @@ _tf_stream_bus_message (TfStream *stream,
value = gst_structure_get_value (s, "stream");
fsstream = g_value_get_object (value);
+ g_debug ("local cand prep fs: %p s:%p", stream->priv->fs_stream, stream);
+
if (fsstream != stream->priv->fs_stream)
return FALSE;
+ g_debug ("LOCAL CAND PREP");
+
cb_fs_local_candidates_prepared (stream);
return TRUE;
@@ -2608,10 +2612,6 @@ _tf_stream_bus_message (TfStream *stream,
FS_CODEC_ARGS (codec));
cb_fs_send_codec_changed (stream, codec, secondary_codecs);
-
- if (codec)
- fs_codec_destroy (codec);
- fs_codec_list_destroy (secondary_codecs);
return TRUE;
}
else if (gst_structure_has_name (s, "farstream-component-state-changed"))
@@ -2797,23 +2797,6 @@ fs_codecs_to_feedback_messages (GList *fscodecs)
}
-static TpMediaStreamDirection
-fsdirection_to_tpdirection (FsStreamDirection dir)
-{
- switch (dir) {
- case FS_DIRECTION_NONE:
- return TP_MEDIA_STREAM_DIRECTION_NONE;
- case FS_DIRECTION_SEND:
- return TP_MEDIA_STREAM_DIRECTION_SEND;
- case FS_DIRECTION_RECV:
- return TP_MEDIA_STREAM_DIRECTION_RECEIVE;
- case FS_DIRECTION_BOTH:
- return TP_MEDIA_STREAM_DIRECTION_BIDIRECTIONAL;
- default:
- g_assert_not_reached ();
- }
-}
-
static GPtrArray *
_tf_stream_get_header_extensions (TfStream *stream)
@@ -3054,7 +3037,7 @@ cb_fs_component_state_changed (TfStream *self,
FsStreamState fsstate)
{
TpMediaStreamState state;
- const gchar *state_str;
+ const gchar *state_str = "";
if (component != 1)
return;
diff --git a/telepathy-farstream/stream.h b/telepathy-farstream/stream.h
index ddd4b6b..40a8048 100644
--- a/telepathy-farstream/stream.h
+++ b/telepathy-farstream/stream.h
@@ -56,6 +56,73 @@ void tf_stream_error (TfStream *self,
const gchar *message);
+typedef struct _TfStreamPrivate TfStreamPrivate;
+
+/*
+ * TfStream:
+ * @parent: the parent #GObject
+ * @stream_id: the ID of the stream (READ-ONLY)
+ *
+ * All other members are privated
+ */
+
+struct _TfStream {
+ GObject parent;
+
+ /* Read-only */
+ guint stream_id;
+
+ /*< private >*/
+
+ TfStreamPrivate *priv;
+};
+
+/*
+ * TfStreamClass:
+ * @parent_class: the parent #GObjecClass
+ *
+ * There are no overridable functions
+ */
+
+struct _TfStreamClass {
+ GObjectClass parent_class;
+
+ /*< private >*/
+
+ gpointer unused[4];
+};
+
+
+typedef struct {
+ gchar *nat_traversal;
+ gchar *stun_server;
+ guint16 stun_port;
+ gchar *relay_token;
+} TfNatProperties;
+
+typedef void (NewStreamCreatedCb) (TfStream *stream, gpointer channel);
+
+TfStream *
+_tf_stream_new (gpointer channel,
+ FsConference *conference,
+ FsParticipant *participant,
+ TpMediaStreamHandler *proxy,
+ guint stream_id,
+ TpMediaStreamType media_type,
+ TpMediaStreamDirection direction,
+ TfNatProperties *nat_props,
+ GList *local_codecs_config,
+ NewStreamCreatedCb new_stream_created_cb);
+
+gboolean _tf_stream_bus_message (TfStream *stream,
+ GstMessage *message);
+
+void _tf_stream_try_sending_codecs (TfStream *stream);
+
+TpMediaStreamError fserror_to_tperror (GError *error);
+
+
+
G_END_DECLS
#endif /* __TF_STREAM_H__ */
diff --git a/telepathy-farstream/telepathy-farstream.c b/telepathy-farstream/telepathy-farstream.c
deleted file mode 100644
index afc2762..0000000
--- a/telepathy-farstream/telepathy-farstream.c
+++ /dev/null
@@ -1,34 +0,0 @@
-/*
- * telepathy-farstream.c - Global functions for telepathy-farstream
- * Copyright (C) 2011 Collabora Ltd.
- *
- * 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 "extensions/extensions.h"
-#include "telepathy-farstream.h"
-
-/**
- * tf_init:
- *
- * Initializes telepathy-farstream. This must be called at the start of your
- * application, specifically before any DBus proxies related to Call channels
- * are created
- */
-void
-tf_init (void)
-{
- tf_future_cli_init ();
-}
diff --git a/telepathy-farstream/telepathy-farstream.h b/telepathy-farstream/telepathy-farstream.h
index 2563894..4a24fb2 100644
--- a/telepathy-farstream/telepathy-farstream.h
+++ b/telepathy-farstream/telepathy-farstream.h
@@ -23,11 +23,5 @@
#include <telepathy-farstream/channel.h>
#include <telepathy-farstream/content.h>
-G_BEGIN_DECLS
-
-void tf_init (void);
-
-G_END_DECLS
-
#endif /* __TF_FARSTREAM_H__ */
diff --git a/telepathy-farstream/utils.h b/telepathy-farstream/utils.h
index 934924c..3bf02c8 100644
--- a/telepathy-farstream/utils.h
+++ b/telepathy-farstream/utils.h
@@ -24,5 +24,39 @@ tp_media_type_to_fs (TpMediaStreamType type)
}
}
+static inline TpMediaStreamDirection
+fsdirection_to_tpdirection (FsStreamDirection dir)
+{
+ switch (dir) {
+ case FS_DIRECTION_NONE:
+ return TP_MEDIA_STREAM_DIRECTION_NONE;
+ case FS_DIRECTION_SEND:
+ return TP_MEDIA_STREAM_DIRECTION_SEND;
+ case FS_DIRECTION_RECV:
+ return TP_MEDIA_STREAM_DIRECTION_RECEIVE;
+ case FS_DIRECTION_BOTH:
+ return TP_MEDIA_STREAM_DIRECTION_BIDIRECTIONAL;
+ default:
+ g_assert_not_reached ();
+ }
+}
+
+static inline FsStreamDirection
+tpdirection_to_fsdirection (TpMediaStreamDirection dir)
+{
+ switch (dir) {
+ case TP_MEDIA_STREAM_DIRECTION_NONE:
+ return FS_DIRECTION_NONE;
+ case TP_MEDIA_STREAM_DIRECTION_SEND:
+ return FS_DIRECTION_SEND;
+ case TP_MEDIA_STREAM_DIRECTION_RECEIVE:
+ return FS_DIRECTION_RECV;
+ case TP_MEDIA_STREAM_DIRECTION_BIDIRECTIONAL:
+ return FS_DIRECTION_BOTH;
+ default:
+ g_assert_not_reached ();
+ }
+}
+
#endif /* __UTILS_H__ */