summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--NEWS19
-rw-r--r--configure.ac24
-rw-r--r--extensions/Makefile.am2
-rw-r--r--extensions/extensions.c1
-rw-r--r--src/Makefile.am15
-rw-r--r--src/connection-aliasing.c14
-rw-r--r--src/connection-avatars.c89
-rw-r--r--src/connection-avatars.h14
-rw-r--r--src/connection-capabilities.c543
-rw-r--r--src/connection-capabilities.h4
-rw-r--r--src/connection-mail.c4
-rw-r--r--src/connection-manager.c8
-rw-r--r--src/connection-manager.h2
-rw-r--r--src/connection-presence.c8
-rw-r--r--src/connection.c144
-rw-r--r--src/connection.h16
-rw-r--r--src/contact-list.c12
-rw-r--r--src/contact-list.h4
-rw-r--r--src/debug.c4
-rw-r--r--src/im-channel-factory.c15
-rw-r--r--src/im-channel.c13
-rw-r--r--src/im-channel.h2
-rw-r--r--src/main.c15
-rw-r--r--src/media-backend.c615
-rw-r--r--src/media-backend.h68
-rw-r--r--src/media-channel.c1762
-rw-r--r--src/media-channel.h80
-rw-r--r--src/media-manager.c579
-rw-r--r--src/media-manager.h65
-rw-r--r--src/media-stream.c1399
-rw-r--r--src/media-stream.h126
-rw-r--r--src/notify.c2
-rw-r--r--src/protocol.c89
-rw-r--r--src/protocol.h2
-rw-r--r--src/util.c1
-rw-r--r--tests/twisted/Makefile.am12
-rw-r--r--tests/twisted/cm/protocols.py36
-rw-r--r--tests/twisted/constants.py1
-rw-r--r--tests/twisted/roster/groups.py2
-rw-r--r--tests/twisted/roster/publish.py2
-rw-r--r--tests/twisted/roster/subscribe.py2
-rw-r--r--tests/twisted/simple-caps.py34
-rw-r--r--tests/twisted/text/destroy.py3
-rw-r--r--tests/twisted/text/ensure.py2
-rw-r--r--tests/twisted/text/initiate-requestotron.py2
-rw-r--r--tests/twisted/text/initiate.py3
-rw-r--r--tests/twisted/text/respawn.py3
-rw-r--r--tools/glib-ginterface-gen.py2
48 files changed, 380 insertions, 5484 deletions
diff --git a/NEWS b/NEWS
index 87fa2cc..1aeff83 100644
--- a/NEWS
+++ b/NEWS
@@ -1,6 +1,23 @@
-telepathy-haze 0.7.2 (UNRELEASED)
+telepathy-haze 0.9.0 (UNRELEASED)
=================================
+Dependencies:
+
+• telepathy-glib ≥ 0.21.0 is required
+
+Features removed:
+
+• StreamedMedia channels are no longer supported. We'd potentially
+ accept patches to bring back audio/video support, but only via the
+ newer Call1 channels. (fd.o #69318, Simon)
+
+Internal changes:
+
+• fix various deprecation warnings (fd.o #69272; Guillaume, Simon)
+
+• remove deprecated Capabilities and Presence interfaces (fd.o #69318;
+ Guillaume, Simon)
+
Fixes:
• Report contacts with unknown presence as 'unknown' rather than raising
diff --git a/configure.ac b/configure.ac
index f5841d3..80f47ca 100644
--- a/configure.ac
+++ b/configure.ac
@@ -7,8 +7,8 @@ AC_PREREQ([2.59])
# set nano_version to 1
m4_define([haze_major_version], [0])
-m4_define([haze_minor_version], [7])
-m4_define([haze_micro_version], [1])
+m4_define([haze_minor_version], [8])
+m4_define([haze_micro_version], [99])
m4_define([haze_nano_version], [1])
m4_define([haze_base_version],
@@ -62,8 +62,7 @@ TP_COMPILER_WARNINGS([ERROR_CFLAGS], [test x$release = xno],
format-security \
init-self],
[missing-field-initializers \
- unused-parameter \
- deprecated-declarations])
+ unused-parameter])
AC_SUBST(ERROR_CFLAGS)
AC_CHECK_HEADERS_ONCE([libintl.h])
@@ -74,10 +73,15 @@ AC_ARG_ENABLE(leaky-request-stubs,
AC_SUBST(ENABLE_LEAKY_REQUEST_STUBS)
PKG_CHECK_MODULES(PURPLE,[purple >= 2.7])
-PKG_CHECK_MODULES(TP_GLIB,[telepathy-glib >= 0.15.1])
PKG_CHECK_MODULES(GLIB,[glib-2.0 >= 2.22, gobject-2.0, gio-2.0])
PKG_CHECK_MODULES(DBUS_GLIB,[dbus-glib-1 >= 0.73])
+AC_DEFINE([TP_SEAL_ENABLE], [], [Prevent to use sealed variables])
+AC_DEFINE([TP_DISABLE_SINGLE_INCLUDE], [], [Disable single header include])
+AC_DEFINE([TP_VERSION_MIN_REQUIRED], [TP_VERSION_0_22], [Ignore post 0.22 deprecations])
+AC_DEFINE([TP_VERSION_MAX_ALLOWED], [TP_VERSION_0_22], [Prevent post 0.22 APIs])
+PKG_CHECK_MODULES(TP_GLIB,[telepathy-glib >= 0.21])
+
dnl MIN_REQUIRED must stay to 2.30 because of GValueArray
AC_DEFINE([GLIB_VERSION_MIN_REQUIRED], [GLIB_VERSION_2_30], [Ignore post 2.30 deprecations])
AC_DEFINE([GLIB_VERSION_MAX_ALLOWED], [GLIB_VERSION_2_30], [Prevent post 2.30 APIs])
@@ -110,16 +114,6 @@ AC_MSG_RESULT([$TEST_PYTHON])
AC_SUBST(TEST_PYTHON)
AM_CONDITIONAL([WANT_TWISTED_TESTS], test false != "$TEST_PYTHON")
-AC_ARG_ENABLE(media,
- AC_HELP_STRING([--disable-media],[disable audio/video calls]),
- [
- AM_CONDITIONAL([MEDIA_ENABLED], false)
- ],[
- AC_DEFINE(ENABLE_MEDIA, [], [Enable audio/video calls])
- AM_CONDITIONAL([MEDIA_ENABLED], true)
- ])
-AC_SUBST(ENABLE_MEDIA)
-
#AS_AC_EXPAND(DATADIR, $datadir)
#DBUS_SERVICES_DIR="$DATADIR/dbus-1/services"
#AC_SUBST(DBUS_SERVICES_DIR)
diff --git a/extensions/Makefile.am b/extensions/Makefile.am
index c10f042..32c9640 100644
--- a/extensions/Makefile.am
+++ b/extensions/Makefile.am
@@ -52,7 +52,7 @@ _gen/svc.c _gen/svc.h: _gen/all.xml $(tools_dir)/glib-ginterface-gen.py \
Makefile.am
$(AM_V_GEN)$(PYTHON) $(tools_dir)/glib-ginterface-gen.py \
--filename=_gen/svc --signal-marshal-prefix=_haze_ext \
- --include='<telepathy-glib/dbus.h>' \
+ --include='<telepathy-glib/telepathy-glib.h>' \
--include='"_gen/signals-marshal.h"' \
--allow-unstable \
--not-implemented-func='tp_dbus_g_method_return_not_implemented' \
diff --git a/extensions/extensions.c b/extensions/extensions.c
index c81d126..77cc3f2 100644
--- a/extensions/extensions.c
+++ b/extensions/extensions.c
@@ -1,3 +1,4 @@
+#include <config.h>
#include "extensions.h"
/* auto-generated stubs */
diff --git a/src/Makefile.am b/src/Makefile.am
index bc9fd28..59bae17 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -8,19 +8,6 @@ man_MANS = telepathy-haze.8
EXTRA_DIST = telepathy-haze.8.in
CLEANFILES = $(man_MANS)
-if MEDIA_ENABLED
-haze_media_sources = media-backend.c \
- media-backend.h \
- media-channel.c \
- media-channel.h \
- media-manager.c \
- media-manager.h \
- media-stream.c \
- media-stream.h
-else
-haze_media_sources =
-endif
-
telepathy_haze_SOURCES = main.c \
defines.h \
debug.c \
@@ -53,7 +40,7 @@ telepathy_haze_SOURCES = main.c \
request.h \
util.c \
util.h \
- $(haze_media_sources)
+ $(NULL)
telepathy_haze_LDADD = $(top_builddir)/extensions/libhaze-extensions.la
diff --git a/src/connection-aliasing.c b/src/connection-aliasing.c
index 8400e59..3ed3ade 100644
--- a/src/connection-aliasing.c
+++ b/src/connection-aliasing.c
@@ -18,12 +18,11 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
*/
+
+#include <config.h>
#include "connection-aliasing.h"
-#include <telepathy-glib/contacts-mixin.h>
-#include <telepathy-glib/gtypes.h>
-#include <telepathy-glib/handle.h>
-#include <telepathy-glib/interfaces.h>
+#include <telepathy-glib/telepathy-glib.h>
#include "connection.h"
#include "debug.h"
@@ -70,7 +69,7 @@ get_alias (HazeConnection *self,
const gchar *bname = tp_handle_inspect (contact_handles, handle);
const gchar *alias;
- if (handle == base->self_handle)
+ if (handle == tp_base_connection_get_self_handle (base))
{
alias = purple_connection_get_display_name (self->account->gc);
@@ -192,7 +191,7 @@ set_alias_success_cb (PurpleAccount *account,
dbus_g_type_specialized_construct (TP_STRUCT_TYPE_ALIAS_PAIR));
dbus_g_type_struct_set (&entry,
- 0, base_conn->self_handle,
+ 0, tp_base_connection_get_self_handle (base_conn),
1, new_alias,
G_MAXUINT);
@@ -230,7 +229,8 @@ set_aliases_foreach (gpointer key,
{
/* stop already */
}
- else if (handle == TP_BASE_CONNECTION (data->conn)->self_handle)
+ else if (handle == tp_base_connection_get_self_handle (
+ TP_BASE_CONNECTION (data->conn)))
{
DEBUG ("setting alias for myself to \"%s\"", new_alias);
purple_account_set_public_alias (data->conn->account,
diff --git a/src/connection-avatars.c b/src/connection-avatars.c
index 1042938..f4dca89 100644
--- a/src/connection-avatars.c
+++ b/src/connection-avatars.c
@@ -19,13 +19,12 @@
*
*/
+#include <config.h>
#include "connection-avatars.h"
#include <string.h>
-#include <telepathy-glib/contacts-mixin.h>
-#include <telepathy-glib/interfaces.h>
-#include <telepathy-glib/svc-connection.h>
+#include <telepathy-glib/telepathy-glib.h>
#include <libpurple/cipher.h>
@@ -33,6 +32,25 @@
#include "debug.h"
static gchar **
+dup_mime_types (PurpleBuddyIconSpec *icon_spec)
+{
+ gchar **mime_types, **i;
+ gchar *format;
+
+ mime_types = g_strsplit (icon_spec->format, ",", 0);
+
+ for (i = mime_types; *i != NULL; i++)
+ {
+ format = *i;
+ /* FIXME: image/ico is not the correct mime type. */
+ *i = g_strconcat ("image/", format, NULL);
+ g_free (format);
+ }
+
+ return mime_types;
+}
+
+static gchar **
_get_acceptable_mime_types (HazeConnection *self)
{
PurplePluginProtocolInfo *prpl_info = HAZE_CONNECTION_GET_PRPL_INFO (self);
@@ -41,20 +59,8 @@ _get_acceptable_mime_types (HazeConnection *self)
if (self->acceptable_avatar_mime_types == NULL)
{
- gchar **mime_types, **i;
- gchar *format;
-
- mime_types = g_strsplit (prpl_info->icon_spec.format, ",", 0);
-
- for (i = mime_types; *i != NULL; i++)
- {
- format = *i;
- /* FIXME: image/ico is not the correct mime type. */
- *i = g_strconcat ("image/", format, NULL);
- g_free (format);
- }
-
- self->acceptable_avatar_mime_types = mime_types;
+ self->acceptable_avatar_mime_types = dup_mime_types (
+ &prpl_info->icon_spec);
}
return self->acceptable_avatar_mime_types;
@@ -97,7 +103,7 @@ haze_connection_avatars_properties_getter (GObject *object,
PurplePluginProtocolInfo *prpl_info;
PurpleBuddyIconSpec *icon_spec;
- if (base->status != TP_CONNECTION_STATUS_CONNECTED)
+ if (tp_base_connection_get_status (base) != TP_CONNECTION_STATUS_CONNECTED)
{
/* not CONNECTED yet, so our connection doesn't have the prpl info
* yet - return dummy values */
@@ -153,6 +159,36 @@ haze_connection_avatars_properties_getter (GObject *object,
}
}
+void
+haze_connection_get_icon_spec_requirements (PurpleBuddyIconSpec *icon_spec,
+ GStrv *mime_types,
+ guint *min_height,
+ guint *min_width,
+ guint *rec_height,
+ guint *rec_width,
+ guint *max_height,
+ guint *max_width,
+ guint *max_bytes)
+{
+ if (mime_types != NULL)
+ *mime_types = dup_mime_types (icon_spec);
+ if (min_height != NULL)
+ *min_height = icon_spec->min_height;
+ if (min_width != NULL)
+ *min_width = icon_spec->min_width;
+ /* libpurple has no recommendation */
+ if (rec_height != NULL)
+ *rec_height = 0;
+ if (rec_width != NULL)
+ *rec_width = 0;
+ if (max_height != NULL)
+ *max_height = icon_spec->max_height;
+ if (max_width != NULL)
+ *max_width = icon_spec->max_width;
+ if (max_bytes != NULL)
+ *max_bytes = icon_spec->max_filesize;
+}
+
static void
haze_connection_get_avatar_requirements (TpSvcConnectionInterfaceAvatars *self,
DBusGMethodInvocation *context)
@@ -161,6 +197,7 @@ haze_connection_get_avatar_requirements (TpSvcConnectionInterfaceAvatars *self,
TpBaseConnection *base = TP_BASE_CONNECTION (conn);
PurplePluginProtocolInfo *prpl_info;
PurpleBuddyIconSpec *icon_spec;
+ guint min_height, min_width, max_height, max_width, max_bytes;
TP_BASE_CONNECTION_ERROR_IF_NOT_CONNECTED (base, context);
@@ -170,11 +207,12 @@ haze_connection_get_avatar_requirements (TpSvcConnectionInterfaceAvatars *self,
/* If the spec or the formats are null, this iface wasn't implemented. */
g_assert (icon_spec != NULL && icon_spec->format != NULL);
+ haze_connection_get_icon_spec_requirements (icon_spec, NULL, &min_height,
+ &min_width, NULL, NULL, &max_height, &max_width, &max_bytes);
+
tp_svc_connection_interface_avatars_return_from_get_avatar_requirements (
context, (const gchar **) _get_acceptable_mime_types (conn),
- icon_spec->min_width, icon_spec->min_height,
- icon_spec->max_width, icon_spec->max_height,
- icon_spec->max_filesize);
+ min_width, min_height, max_width, max_height, max_bytes);
}
static GArray *
@@ -187,7 +225,8 @@ get_avatar (HazeConnection *conn,
tp_base_connection_get_handles (base, TP_HANDLE_TYPE_CONTACT);
gconstpointer icon_data = NULL;
size_t icon_size = 0;
- if (handle == base->self_handle)
+
+ if (handle == tp_base_connection_get_self_handle (base))
{
PurpleStoredImage *image =
purple_buddy_icons_find_account_icon (conn->account);
@@ -331,7 +370,7 @@ haze_connection_get_known_avatar_tokens (TpSvcConnectionInterfaceAvatars *self,
* avatar you last used. So we special-case self_handle here.
*/
- if (handle == base_conn->self_handle)
+ if (handle == tp_base_connection_get_self_handle (base_conn))
{
GArray *avatar = get_avatar (conn, handle);
if (avatar != NULL)
@@ -428,7 +467,7 @@ haze_connection_clear_avatar (TpSvcConnectionInterfaceAvatars *self,
tp_svc_connection_interface_avatars_return_from_clear_avatar (context);
tp_svc_connection_interface_avatars_emit_avatar_updated (conn,
- base_conn->self_handle, "");
+ tp_base_connection_get_self_handle (base_conn), "");
}
static void
@@ -506,7 +545,7 @@ haze_connection_set_avatar (TpSvcConnectionInterfaceAvatars *self,
tp_svc_connection_interface_avatars_return_from_set_avatar (context, token);
tp_svc_connection_interface_avatars_emit_avatar_updated (conn,
- base_conn->self_handle, token);
+ tp_base_connection_get_self_handle (base_conn), token);
g_free (token);
}
diff --git a/src/connection-avatars.h b/src/connection-avatars.h
index 8517cc3..8ac37ab 100644
--- a/src/connection-avatars.h
+++ b/src/connection-avatars.h
@@ -23,7 +23,9 @@
#include <glib-object.h>
-#include <telepathy-glib/dbus-properties-mixin.h>
+#include <telepathy-glib/telepathy-glib.h>
+
+#include <libpurple/purple.h>
void haze_connection_avatars_iface_init (gpointer g_iface, gpointer iface_data);
void haze_connection_avatars_class_init (GObjectClass *object_class);
@@ -33,4 +35,14 @@ extern TpDBusPropertiesMixinPropImpl *haze_connection_avatars_properties;
void haze_connection_avatars_properties_getter (GObject *object,
GQuark interface, GQuark name, GValue *value, gpointer getter_data);
+void haze_connection_get_icon_spec_requirements (PurpleBuddyIconSpec *icon_spec,
+ GStrv *mime_types,
+ guint *min_height,
+ guint *min_width,
+ guint *rec_height,
+ guint *rec_width,
+ guint *max_height,
+ guint *max_width,
+ guint *max_bytes);
+
#endif
diff --git a/src/connection-capabilities.c b/src/connection-capabilities.c
index 04cecfc..ce6fd8f 100644
--- a/src/connection-capabilities.c
+++ b/src/connection-capabilities.c
@@ -24,17 +24,10 @@
#include "connection-capabilities.h"
-#include <telepathy-glib/contacts-mixin.h>
-#include <telepathy-glib/gtypes.h>
-#include <telepathy-glib/handle.h>
-#include <telepathy-glib/interfaces.h>
-#include <telepathy-glib/dbus.h>
+#include <telepathy-glib/telepathy-glib.h>
#include "connection.h"
#include "debug.h"
-#ifdef ENABLE_MEDIA
-#include "mediamanager.h"
-#endif
static void
free_rcc_list (GPtrArray *rccs)
@@ -42,178 +35,6 @@ free_rcc_list (GPtrArray *rccs)
g_boxed_free (TP_ARRAY_TYPE_REQUESTABLE_CHANNEL_CLASS_LIST, rccs);
}
-#ifdef ENABLE_MEDIA
-static PurpleMediaCaps
-tp_flags_to_purple_caps (guint flags)
-{
- PurpleMediaCaps caps = PURPLE_MEDIA_CAPS_NONE;
- if (flags & TP_CHANNEL_MEDIA_CAPABILITY_AUDIO)
- caps |= PURPLE_MEDIA_CAPS_AUDIO;
- if (flags & TP_CHANNEL_MEDIA_CAPABILITY_VIDEO)
- caps |= PURPLE_MEDIA_CAPS_VIDEO;
- return caps;
-}
-
-static guint
-purple_caps_to_tp_flags (PurpleMediaCaps caps)
-{
- guint flags = 0;
- if (caps & PURPLE_MEDIA_CAPS_AUDIO)
- flags |= TP_CHANNEL_MEDIA_CAPABILITY_AUDIO;
- if (caps & PURPLE_MEDIA_CAPS_VIDEO)
- flags |= TP_CHANNEL_MEDIA_CAPABILITY_VIDEO;
- return flags;
-}
-
-static GPtrArray * haze_connection_get_handle_contact_capabilities (
- HazeConnection *self, TpHandle handle);
-
-static void
-_emit_capabilities_changed (HazeConnection *conn,
- TpHandle handle,
- const guint old_specific,
- const guint new_specific)
-{
- GPtrArray *caps_arr;
- guint i;
-
- /* o.f.T.C.Capabilities */
-
- caps_arr = g_ptr_array_new ();
-
- if (old_specific != 0 || new_specific != 0)
- {
- GValue caps_monster_struct = {0, };
- guint old_generic = old_specific ?
- TP_CONNECTION_CAPABILITY_FLAG_CREATE |
- TP_CONNECTION_CAPABILITY_FLAG_INVITE : 0;
- guint new_generic = new_specific ?
- TP_CONNECTION_CAPABILITY_FLAG_CREATE |
- TP_CONNECTION_CAPABILITY_FLAG_INVITE : 0;
-
- if (0 != (old_specific ^ new_specific))
- {
- g_value_init (&caps_monster_struct,
- TP_STRUCT_TYPE_CAPABILITY_CHANGE);
- g_value_take_boxed (&caps_monster_struct,
- dbus_g_type_specialized_construct
- (TP_STRUCT_TYPE_CAPABILITY_CHANGE));
-
- dbus_g_type_struct_set (&caps_monster_struct,
- 0, handle,
- 1, TP_IFACE_CHANNEL_TYPE_STREAMED_MEDIA,
- 2, old_generic,
- 3, new_generic,
- 4, old_specific,
- 5, new_specific,
- G_MAXUINT);
-
- g_ptr_array_add (caps_arr, g_value_get_boxed (&caps_monster_struct));
- }
- }
-
- if (caps_arr->len)
- tp_svc_connection_interface_capabilities_emit_capabilities_changed (
- conn, caps_arr);
-
- if (caps_arr->len > 0)
- {
- GHashTable *ret = g_hash_table_new_full (g_direct_hash, g_direct_equal,
- NULL, (GDestroyNotify) free_rcc_list);
- GPtrArray *arr;
-
- arr = haze_connection_get_handle_contact_capabilities (conn, handle);
- g_hash_table_insert (ret, GUINT_TO_POINTER (handle), arr);
-
- tp_svc_connection_interface_contact_capabilities_emit_contact_capabilities_changed (
- conn, ret);
-
- g_hash_table_unref (ret);
- }
-
- for (i = 0; i < caps_arr->len; i++)
- {
- g_boxed_free (TP_STRUCT_TYPE_CAPABILITY_CHANGE,
- g_ptr_array_index (caps_arr, i));
- }
-
- g_ptr_array_free (caps_arr, TRUE);
-}
-#endif
-
-/**
- * haze_connection_advertise_capabilities
- *
- * Implements D-Bus method AdvertiseCapabilities
- * on interface org.freedesktop.Telepathy.Connection.Interface.Capabilities
- */
-static void
-haze_connection_advertise_capabilities (TpSvcConnectionInterfaceCapabilities *iface,
- const GPtrArray *add,
- const gchar **del,
- DBusGMethodInvocation *context)
-{
- HazeConnection *self = HAZE_CONNECTION (iface);
- TpBaseConnection *base = (TpBaseConnection *) self;
-#ifdef ENABLE_MEDIA
- guint i;
- PurpleMediaCaps old_caps, caps;
-#endif
- GPtrArray *ret;
-
- TP_BASE_CONNECTION_ERROR_IF_NOT_CONNECTED (base, context);
-
-#ifdef ENABLE_MEDIA
- caps = old_caps = purple_media_manager_get_ui_caps (
- purple_media_manager_get ());
- for (i = 0; i < add->len; i++)
- {
- GValue iface_flags_pair = {0, };
- gchar *channel_type;
- guint flags;
-
- g_value_init (&iface_flags_pair, TP_STRUCT_TYPE_CAPABILITY_PAIR);
- g_value_set_static_boxed (&iface_flags_pair, g_ptr_array_index (add, i));
-
- dbus_g_type_struct_get (&iface_flags_pair,
- 0, &channel_type,
- 1, &flags,
- G_MAXUINT);
-
- if (g_str_equal (channel_type, TP_IFACE_CHANNEL_TYPE_STREAMED_MEDIA))
- caps |= tp_flags_to_purple_caps(flags);
-
- g_free (channel_type);
- }
-
- for (i = 0; NULL != del[i]; i++)
- {
- if (g_str_equal (del[i], TP_IFACE_CHANNEL_TYPE_STREAMED_MEDIA))
- {
- caps = PURPLE_MEDIA_CAPS_NONE;
- break;
- }
- }
-
- purple_media_manager_set_ui_caps (purple_media_manager_get(), caps);
-
- _emit_capabilities_changed (self, base->self_handle, old_caps, caps);
-#endif
-
- ret = g_ptr_array_new ();
-
-/* TODO: store caps and return them properly */
-
- tp_svc_connection_interface_capabilities_return_from_advertise_capabilities (
- context, ret);
- g_ptr_array_free (ret, TRUE);
-}
-
-typedef enum {
- CAPS_FLAGS_AUDIO = 1 << 0,
- CAPS_FLAGS_VIDEO = 1 << 1,
-} CapsFlags;
-
static void
haze_connection_update_capabilities (TpSvcConnectionInterfaceContactCapabilities *iface,
const GPtrArray *clients,
@@ -221,185 +42,17 @@ haze_connection_update_capabilities (TpSvcConnectionInterfaceContactCapabilities
{
HazeConnection *self = HAZE_CONNECTION (iface);
TpBaseConnection *base = (TpBaseConnection *) self;
-#ifdef ENABLE_MEDIA
- guint i;
- PurpleMediaCaps old_caps, caps;
- GHashTableIter iter;
- gpointer value;
-#endif
TP_BASE_CONNECTION_ERROR_IF_NOT_CONNECTED (base, context);
-#ifdef ENABLE_MEDIA
- caps = PURPLE_MEDIA_CAPS_NONE;
- old_caps = purple_media_manager_get_ui_caps (
- purple_media_manager_get ());
-
- DEBUG ("enter");
-
- /* go through all the clients and if they can do audio or video save
- * it in the client_caps hash table */
- for (i = 0; i < clients->len; i++)
- {
- GValueArray *va = g_ptr_array_index (clients, i);
- const gchar *client_name = g_value_get_string (va->values + 0);
- const GPtrArray *rccs = g_value_get_boxed (va->values + 1);
- guint j;
- CapsFlags flags = 0;
-
- g_hash_table_remove (self->client_caps, client_name);
-
- for (j = 0; j < rccs->len; j++)
- {
- GHashTable *class = g_ptr_array_index (rccs, i);
-
- if (tp_strdiff (tp_asv_get_string (class, TP_PROP_CHANNEL_CHANNEL_TYPE),
- TP_IFACE_CHANNEL_TYPE_STREAMED_MEDIA))
- continue;
-
- if (tp_asv_get_boolean (class,
- TP_PROP_CHANNEL_TYPE_STREAMED_MEDIA_INITIAL_AUDIO, NULL))
- flags |= CAPS_FLAGS_AUDIO;
-
- if (tp_asv_get_boolean (class,
- TP_PROP_CHANNEL_TYPE_STREAMED_MEDIA_INITIAL_VIDEO, NULL))
- flags |= CAPS_FLAGS_VIDEO;
- }
-
- if (flags != 0)
- {
- g_hash_table_insert (self->client_caps, g_strdup (client_name),
- GUINT_TO_POINTER (flags));
- }
- }
-
- /* now we have an updated client_caps hash table, go through it and
- * let libpurple know */
- g_hash_table_iter_init (&iter, self->client_caps);
- while (g_hash_table_iter_next (&iter, NULL, &value))
- {
- CapsFlags flags = GPOINTER_TO_UINT (value);
-
- if (flags & CAPS_FLAGS_AUDIO)
- caps |= PURPLE_MEDIA_CAPS_AUDIO;
- if (flags & CAPS_FLAGS_VIDEO)
- caps |= PURPLE_MEDIA_CAPS_VIDEO;
- }
-
- purple_media_manager_set_ui_caps (purple_media_manager_get(), caps);
-
- _emit_capabilities_changed (self, base->self_handle, old_caps, caps);
-#endif
-
tp_svc_connection_interface_contact_capabilities_return_from_update_capabilities (
context);
}
-static const gchar *assumed_caps[] =
-{
- TP_IFACE_CHANNEL_TYPE_TEXT,
- NULL
-};
-
-/**
- * haze_connection_get_handle_capabilities
- *
- * Add capabilities of handle to the given GPtrArray
- */
-static void
-haze_connection_get_handle_capabilities (HazeConnection *self,
- TpHandle handle,
- GPtrArray *arr)
-{
-#ifdef ENABLE_MEDIA
- TpBaseConnection *conn = TP_BASE_CONNECTION (self);
- PurpleAccount *account = self->account;
- TpHandleRepoIface *contact_handles =
- tp_base_connection_get_handles (conn, TP_HANDLE_TYPE_CONTACT);
- const gchar *bname;
- guint typeflags = 0;
- PurpleMediaCaps caps;
-#endif
- const gchar **assumed;
-
- if (0 == handle)
- {
- /* obsolete request for the connection's capabilities, do nothing */
- return;
- }
-
- /* TODO: Check for presence */
-
-#ifdef ENABLE_MEDIA
- if (handle == conn->self_handle)
- caps = purple_media_manager_get_ui_caps (purple_media_manager_get ());
- else
- {
- bname = tp_handle_inspect (contact_handles, handle);
- caps = purple_prpl_get_media_caps (account, bname);
- }
-
- typeflags = purple_caps_to_tp_flags(caps);
-
- if (typeflags != 0)
- {
- GValue monster = {0, };
- g_value_init (&monster, TP_STRUCT_TYPE_CONTACT_CAPABILITY);
- g_value_take_boxed (&monster,
- dbus_g_type_specialized_construct (
- TP_STRUCT_TYPE_CONTACT_CAPABILITY));
- dbus_g_type_struct_set (&monster,
- 0, handle,
- 1, TP_IFACE_CHANNEL_TYPE_STREAMED_MEDIA,
- 2, TP_CONNECTION_CAPABILITY_FLAG_CREATE |
- TP_CONNECTION_CAPABILITY_FLAG_INVITE,
- 3, typeflags,
- G_MAXUINT);
-
- g_ptr_array_add (arr, g_value_get_boxed (&monster));
- }
-#endif
-
- for (assumed = assumed_caps; NULL != *assumed; assumed++)
- {
- GValue monster = {0, };
- g_value_init (&monster, TP_STRUCT_TYPE_CONTACT_CAPABILITY);
- g_value_take_boxed (&monster,
- dbus_g_type_specialized_construct (
- TP_STRUCT_TYPE_CONTACT_CAPABILITY));
-
- dbus_g_type_struct_set (&monster,
- 0, handle,
- 1, *assumed,
- 2, TP_CONNECTION_CAPABILITY_FLAG_CREATE |
- TP_CONNECTION_CAPABILITY_FLAG_INVITE,
- 3, 0,
- G_MAXUINT);
-
- g_ptr_array_add (arr, g_value_get_boxed (&monster));
- }
-}
-
static GPtrArray *
haze_connection_get_handle_contact_capabilities (HazeConnection *self,
TpHandle handle)
{
-#ifdef ENABLE_MEDIA
- PurpleAccount *account = self->account;
- TpBaseConnection *conn = TP_BASE_CONNECTION (self);
- TpHandleRepoIface *contact_handles =
- tp_base_connection_get_handles (conn, TP_HANDLE_TYPE_CONTACT);
- const gchar *bname;
- PurpleMediaCaps caps;
- GValue media_monster = {0, };
- guint typeflags = 0;
- const gchar * const sm_allowed_audio[] = {
- TP_PROP_CHANNEL_TYPE_STREAMED_MEDIA_INITIAL_AUDIO, NULL };
- const gchar * const sm_allowed_video[] = {
- TP_PROP_CHANNEL_TYPE_STREAMED_MEDIA_INITIAL_AUDIO,
- TP_PROP_CHANNEL_TYPE_STREAMED_MEDIA_INITIAL_VIDEO,
- NULL };
-#endif
GPtrArray *arr = g_ptr_array_new ();
GValue monster = {0, };
GHashTable *fixed_properties;
@@ -416,57 +69,6 @@ haze_connection_get_handle_contact_capabilities (HazeConnection *self,
/* TODO: Check for presence */
-#ifdef ENABLE_MEDIA
- if (handle == conn->self_handle)
- caps = purple_media_manager_get_ui_caps (purple_media_manager_get ());
- else
- {
- bname = tp_handle_inspect (contact_handles, handle);
- caps = purple_prpl_get_media_caps (account, bname);
- }
-
- typeflags = purple_caps_to_tp_flags(caps);
-
- if (typeflags != 0)
- {
- const gchar * const *allowed;
-
- g_value_init (&media_monster,
- TP_STRUCT_TYPE_REQUESTABLE_CHANNEL_CLASS);
- g_value_take_boxed (&media_monster,
- dbus_g_type_specialized_construct (
- TP_STRUCT_TYPE_REQUESTABLE_CHANNEL_CLASS));
-
- fixed_properties = g_hash_table_new_full (g_str_hash, g_str_equal, NULL,
- (GDestroyNotify) tp_g_value_slice_free);
-
- channel_type_value = tp_g_value_slice_new (G_TYPE_STRING);
- g_value_set_static_string (channel_type_value,
- TP_IFACE_CHANNEL_TYPE_STREAMED_MEDIA);
- g_hash_table_insert (fixed_properties, TP_PROP_CHANNEL_CHANNEL_TYPE,
- channel_type_value);
-
- target_handle_type_value = tp_g_value_slice_new (G_TYPE_UINT);
- g_value_set_uint (target_handle_type_value, TP_HANDLE_TYPE_CONTACT);
- g_hash_table_insert (fixed_properties, TP_PROP_CHANNEL_TARGET_HANDLE_TYPE,
- target_handle_type_value);
-
- if (typeflags & TP_CHANNEL_MEDIA_CAPABILITY_VIDEO)
- allowed = sm_allowed_video;
- else
- allowed = sm_allowed_audio;
-
- dbus_g_type_struct_set (&media_monster,
- 0, fixed_properties,
- 1, allowed,
- G_MAXUINT);
-
- g_hash_table_unref (fixed_properties);
-
- g_ptr_array_add (arr, g_value_get_boxed (&media_monster));
- }
-#endif
-
g_value_init (&monster, TP_STRUCT_TYPE_REQUESTABLE_CHANNEL_CLASS);
g_value_take_boxed (&monster,
dbus_g_type_specialized_construct (
@@ -497,90 +99,6 @@ haze_connection_get_handle_contact_capabilities (HazeConnection *self,
return arr;
}
-/**
- * haze_connection_get_capabilities
- *
- * Implements D-Bus method GetCapabilities
- * on interface org.freedesktop.Telepathy.Connection.Interface.Capabilities
- */
-static void
-haze_connection_get_capabilities (TpSvcConnectionInterfaceCapabilities *iface,
- const GArray *handles,
- DBusGMethodInvocation *context)
-{
- HazeConnection *self = HAZE_CONNECTION (iface);
- TpBaseConnection *conn = TP_BASE_CONNECTION (self);
- TpHandleRepoIface *contact_handles = tp_base_connection_get_handles (conn,
- TP_HANDLE_TYPE_CONTACT);
- guint i;
- GPtrArray *ret;
- GError *error = NULL;
-
- TP_BASE_CONNECTION_ERROR_IF_NOT_CONNECTED (conn, context);
-
- if (!tp_handles_are_valid (contact_handles, handles, TRUE, &error))
- {
- dbus_g_method_return_error (context, error);
- g_error_free (error);
- return;
- }
-
- ret = g_ptr_array_new ();
-
- for (i = 0; i < handles->len; i++)
- {
- TpHandle handle = g_array_index (handles, TpHandle, i);
-
- haze_connection_get_handle_capabilities (self, handle, ret);
- }
-
- tp_svc_connection_interface_capabilities_return_from_get_capabilities (
- context, ret);
-
- for (i = 0; i < ret->len; i++)
- {
- g_value_array_free (g_ptr_array_index (ret, i));
- }
-
- g_ptr_array_free (ret, TRUE);
-}
-
-static void
-conn_capabilities_fill_contact_attributes (GObject *obj,
- const GArray *contacts,
- GHashTable *attributes_hash)
-{
- HazeConnection *self = HAZE_CONNECTION (obj);
- guint i;
- GPtrArray *array = NULL;
-
- for (i = 0; i < contacts->len; i++)
- {
- TpHandle handle = g_array_index (contacts, TpHandle, i);
-
- if (array == NULL)
- array = g_ptr_array_new ();
-
- haze_connection_get_handle_capabilities (self, handle, array);
-
- if (array->len > 0)
- {
- GValue *val = tp_g_value_slice_new (
- TP_ARRAY_TYPE_CONTACT_CAPABILITY_LIST);
-
- g_value_take_boxed (val, array);
- tp_contacts_mixin_set_contact_attribute (attributes_hash,
- handle, TP_IFACE_CONNECTION_INTERFACE_CAPABILITIES"/caps",
- val);
-
- array = NULL;
- }
- }
-
- if (array != NULL)
- g_ptr_array_free (array, TRUE);
-}
-
static void
conn_capabilities_fill_contact_attributes_contact_caps (
GObject *obj,
@@ -612,20 +130,6 @@ conn_capabilities_fill_contact_attributes_contact_caps (
}
}
-void
-haze_connection_capabilities_iface_init (gpointer g_iface,
- gpointer iface_data)
-{
- TpSvcConnectionInterfaceCapabilitiesClass *klass = g_iface;
-
-#define IMPLEMENT(x) \
- tp_svc_connection_interface_capabilities_implement_##x (\
- klass, haze_connection_##x)
- IMPLEMENT(advertise_capabilities);
- IMPLEMENT(get_capabilities);
-#undef IMPLEMENT
-}
-
static void
haze_connection_get_contact_capabilities (
TpSvcConnectionInterfaceContactCapabilities *svc,
@@ -681,55 +185,10 @@ haze_connection_contact_capabilities_iface_init (gpointer g_iface,
#undef IMPLEMENT
}
-#ifdef ENABLE_MEDIA
-static void
-caps_changed_cb (PurpleBuddy *buddy,
- PurpleMediaCaps caps,
- PurpleMediaCaps oldcaps)
-{
- PurpleAccount *account = purple_buddy_get_account (buddy);
- HazeConnection *conn = ACCOUNT_GET_HAZE_CONNECTION (account);
- TpBaseConnection *base_conn = TP_BASE_CONNECTION (conn);
- TpHandleRepoIface *contact_repo =
- tp_base_connection_get_handles (base_conn, TP_HANDLE_TYPE_CONTACT);
- const gchar *bname = purple_buddy_get_name(buddy);
- TpHandle contact = tp_handle_ensure (contact_repo, bname, NULL, NULL);
-
- _emit_capabilities_changed (conn, contact,
- purple_caps_to_tp_flags(oldcaps),
- purple_caps_to_tp_flags(caps));
-}
-#endif
-
-void
-haze_connection_capabilities_class_init (GObjectClass *object_class)
-{
-#ifdef ENABLE_MEDIA
- purple_signal_connect (purple_blist_get_handle (), "buddy-caps-changed",
- object_class, PURPLE_CALLBACK (caps_changed_cb), NULL);
-#endif
-}
-
void
haze_connection_capabilities_init (GObject *object)
{
- HazeConnection *self = HAZE_CONNECTION (object);
-
- tp_contacts_mixin_add_contact_attributes_iface (object,
- TP_IFACE_CONNECTION_INTERFACE_CAPABILITIES,
- conn_capabilities_fill_contact_attributes);
tp_contacts_mixin_add_contact_attributes_iface (object,
TP_IFACE_CONNECTION_INTERFACE_CONTACT_CAPABILITIES,
conn_capabilities_fill_contact_attributes_contact_caps);
-
- self->client_caps = g_hash_table_new_full (g_str_hash, g_str_equal,
- (GDestroyNotify) g_free, NULL);
-}
-
-void
-haze_connection_capabilities_finalize (GObject *object)
-{
- HazeConnection *self = HAZE_CONNECTION (object);
-
- tp_clear_pointer (&self->client_caps, g_hash_table_unref);
}
diff --git a/src/connection-capabilities.h b/src/connection-capabilities.h
index 7764a31..e98bf98 100644
--- a/src/connection-capabilities.h
+++ b/src/connection-capabilities.h
@@ -23,12 +23,8 @@
#include <glib-object.h>
-void haze_connection_capabilities_iface_init (gpointer g_iface,
- gpointer iface_data);
void haze_connection_contact_capabilities_iface_init (gpointer g_iface,
gpointer iface_data);
-void haze_connection_capabilities_class_init (GObjectClass *object_class);
void haze_connection_capabilities_init (GObject *object);
-void haze_connection_capabilities_finalize (GObject *object);
#endif
diff --git a/src/connection-mail.c b/src/connection-mail.c
index 9b71c9d..0e663ca 100644
--- a/src/connection-mail.c
+++ b/src/connection-mail.c
@@ -21,9 +21,7 @@
#include "extensions/extensions.h"
-#include <telepathy-glib/dbus.h>
-#include <telepathy-glib/interfaces.h>
-#include <telepathy-glib/svc-connection.h>
+#include <telepathy-glib/telepathy-glib.h>
#include "connection.h"
#include "connection-mail.h"
diff --git a/src/connection-manager.c b/src/connection-manager.c
index 6377b9e..58c802d 100644
--- a/src/connection-manager.c
+++ b/src/connection-manager.c
@@ -19,6 +19,9 @@
*
*/
+#include <config.h>
+#include "connection-manager.h"
+
#include <string.h>
#include <glib.h>
@@ -27,9 +30,8 @@
#include <libpurple/prpl.h>
#include <libpurple/accountopt.h>
-#include <telepathy-glib/debug-sender.h>
+#include <telepathy-glib/telepathy-glib.h>
-#include "connection-manager.h"
#include "debug.h"
G_DEFINE_TYPE(HazeConnectionManager,
@@ -95,9 +97,7 @@ haze_connection_manager_class_init (HazeConnectionManagerClass *klass)
object_class->constructed = _haze_cm_constructed;
object_class->finalize = _haze_cm_finalize;
- base_class->new_connection = NULL;
base_class->cm_dbus_name = "haze";
- base_class->protocol_params = NULL;
g_type_class_add_private (klass, sizeof (HazeConnectionManagerPrivate));
}
diff --git a/src/connection-manager.h b/src/connection-manager.h
index b90f37f..4d24ff8 100644
--- a/src/connection-manager.h
+++ b/src/connection-manager.h
@@ -22,7 +22,7 @@
*/
#include <glib-object.h>
-#include <telepathy-glib/base-connection-manager.h>
+#include <telepathy-glib/telepathy-glib.h>
#include "protocol.h"
#include "connection.h"
diff --git a/src/connection-presence.c b/src/connection-presence.c
index 871d212..23c8764 100644
--- a/src/connection-presence.c
+++ b/src/connection-presence.c
@@ -19,10 +19,12 @@
*
*/
+#include <config.h>
#include "connection-presence.h"
+
#include "debug.h"
-#include <telepathy-glib/dbus.h>
+#include <telepathy-glib/telepathy-glib.h>
static const TpPresenceStatusOptionalArgumentSpec arg_specs[] = {
{ "message", "s" },
@@ -183,7 +185,7 @@ _get_contact_statuses (GObject *obj,
g_assert (tp_handle_is_valid (handle_repo, handle, NULL));
- if (handle == base_conn->self_handle)
+ if (handle == tp_base_connection_get_self_handle (base_conn))
{
p_status = purple_account_get_active_status (conn->account);
}
@@ -230,7 +232,7 @@ haze_connection_presence_account_status_changed (PurpleAccount *account,
tp_status = _get_tp_status (status);
tp_presence_mixin_emit_one_presence_update (G_OBJECT (base_conn),
- base_conn->self_handle, tp_status);
+ tp_base_connection_get_self_handle (base_conn), tp_status);
}
}
diff --git a/src/connection.c b/src/connection.c
index 5518214..8e1c0fc 100644
--- a/src/connection.c
+++ b/src/connection.c
@@ -23,12 +23,7 @@
#include <string.h>
-#include <telepathy-glib/dbus.h>
-#include <telepathy-glib/dbus-properties-mixin.h>
-#include <telepathy-glib/errors.h>
-#include <telepathy-glib/handle-repo-dynamic.h>
-#include <telepathy-glib/interfaces.h>
-#include <telepathy-glib/svc-generic.h>
+#include <telepathy-glib/telepathy-glib.h>
#include <libpurple/accountopt.h>
#include <libpurple/version.h>
@@ -68,8 +63,6 @@ G_DEFINE_TYPE_WITH_CODE(HazeConnection,
TP_TYPE_BASE_CONNECTION,
G_IMPLEMENT_INTERFACE (TP_TYPE_SVC_DBUS_PROPERTIES,
tp_dbus_properties_mixin_iface_init);
- G_IMPLEMENT_INTERFACE (TP_TYPE_SVC_CONNECTION_INTERFACE_PRESENCE,
- tp_presence_mixin_iface_init);
G_IMPLEMENT_INTERFACE (TP_TYPE_SVC_CONNECTION_INTERFACE_SIMPLE_PRESENCE,
tp_presence_mixin_simple_presence_iface_init);
G_IMPLEMENT_INTERFACE (TP_TYPE_SVC_CONNECTION_INTERFACE_ALIASING,
@@ -78,8 +71,6 @@ G_DEFINE_TYPE_WITH_CODE(HazeConnection,
haze_connection_avatars_iface_init);
G_IMPLEMENT_INTERFACE (TP_TYPE_SVC_CONNECTION_INTERFACE_CONTACT_CAPABILITIES,
haze_connection_contact_capabilities_iface_init);
- G_IMPLEMENT_INTERFACE (TP_TYPE_SVC_CONNECTION_INTERFACE_CAPABILITIES,
- haze_connection_capabilities_iface_init);
G_IMPLEMENT_INTERFACE (TP_TYPE_SVC_CONNECTION_INTERFACE_CONTACTS,
tp_contacts_mixin_iface_init);
G_IMPLEMENT_INTERFACE (TP_TYPE_SVC_CONNECTION_INTERFACE_CONTACT_LIST,
@@ -105,9 +96,7 @@ static const gchar * implemented_interfaces[] = {
TP_IFACE_CONNECTION_INTERFACE_CONTACT_LIST,
TP_IFACE_CONNECTION_INTERFACE_CONTACT_GROUPS,
TP_IFACE_CONNECTION_INTERFACE_REQUESTS,
- TP_IFACE_CONNECTION_INTERFACE_PRESENCE,
TP_IFACE_CONNECTION_INTERFACE_SIMPLE_PRESENCE,
- TP_IFACE_CONNECTION_INTERFACE_CAPABILITIES,
TP_IFACE_CONNECTION_INTERFACE_CONTACT_CAPABILITIES,
TP_IFACE_CONNECTION_INTERFACE_CONTACTS,
/* TODO: This is a lie. Not all protocols supported by libpurple
@@ -118,16 +107,44 @@ static const gchar * implemented_interfaces[] = {
NULL
};
-const gchar **
-haze_connection_get_implemented_interfaces (void)
+static void
+add_always_present_connection_interfaces (GPtrArray *interfaces)
{
- return implemented_interfaces;
+ const gchar **iter;
+
+ for (iter = implemented_interfaces + HAZE_NUM_CONDITIONAL_INTERFACES;
+ *iter != NULL; iter++)
+ g_ptr_array_add (interfaces, (gchar *) *iter);
}
-const gchar **
-haze_connection_get_guaranteed_interfaces (void)
+static GPtrArray *
+haze_connection_get_interfaces_always_present (TpBaseConnection *base)
{
- return implemented_interfaces + HAZE_NUM_CONDITIONAL_INTERFACES;
+ GPtrArray *interfaces;
+
+ interfaces = TP_BASE_CONNECTION_CLASS (
+ haze_connection_parent_class)->get_interfaces_always_present (base);
+
+ add_always_present_connection_interfaces (interfaces);
+
+ return interfaces;
+}
+
+static void add_optional_connection_interfaces (GPtrArray *ifaces,
+ PurplePluginProtocolInfo *prpl_info);
+
+/* Returns a (transfer container) not NULL terminated of (const gchar *)
+ * interface names. */
+GPtrArray *
+haze_connection_dup_implemented_interfaces (PurplePluginProtocolInfo *prpl_info)
+{
+ GPtrArray *ifaces;
+
+ ifaces = g_ptr_array_new ();
+ add_always_present_connection_interfaces (ifaces);
+ add_optional_connection_interfaces (ifaces, prpl_info);
+
+ return ifaces;
}
struct _HazeConnectionPrivate
@@ -156,28 +173,56 @@ struct _HazeConnectionPrivate
#define PC_GET_BASE_CONN(pc) \
(ACCOUNT_GET_TP_BASE_CONNECTION (purple_connection_get_account (pc)))
+static gboolean
+protocol_info_supports_avatar (PurplePluginProtocolInfo *prpl_info)
+{
+ return (prpl_info->icon_spec.format != NULL);
+}
+
+static gboolean
+protocol_info_supports_blocking (PurplePluginProtocolInfo *prpl_info)
+{
+ return (prpl_info->add_deny != NULL);
+}
+
+static gboolean
+protocol_info_supports_mail_notification (PurplePluginProtocolInfo *prpl_info)
+{
+ return ((prpl_info->options & OPT_PROTO_MAIL_CHECK) != 0);
+}
+
+static void
+add_optional_connection_interfaces (GPtrArray *ifaces,
+ PurplePluginProtocolInfo *prpl_info)
+{
+ if (protocol_info_supports_avatar (prpl_info))
+ g_ptr_array_add (ifaces,
+ TP_IFACE_CONNECTION_INTERFACE_AVATARS);
+
+ if (protocol_info_supports_blocking (prpl_info))
+ g_ptr_array_add (ifaces,
+ TP_IFACE_CONNECTION_INTERFACE_CONTACT_BLOCKING);
+
+ if (protocol_info_supports_mail_notification (prpl_info))
+ g_ptr_array_add (ifaces,
+ HAZE_IFACE_CONNECTION_INTERFACE_MAIL_NOTIFICATION);
+}
+
static void
connected_cb (PurpleConnection *pc)
{
TpBaseConnection *base_conn = PC_GET_BASE_CONN (pc);
HazeConnection *conn = HAZE_CONNECTION (base_conn);
PurplePluginProtocolInfo *prpl_info = HAZE_CONNECTION_GET_PRPL_INFO (conn);
+ GPtrArray *ifaces;
- if (prpl_info->icon_spec.format != NULL)
- {
- static const gchar *avatar_ifaces[] = {
- TP_IFACE_CONNECTION_INTERFACE_AVATARS,
- NULL };
- tp_base_connection_add_interfaces (base_conn, avatar_ifaces);
- }
+ ifaces = g_ptr_array_new ();
+ add_optional_connection_interfaces (ifaces, prpl_info);
+ g_ptr_array_add (ifaces, NULL);
- if (prpl_info->add_deny != NULL)
- {
- static const gchar *blocking_ifaces[] = {
- TP_IFACE_CONNECTION_INTERFACE_CONTACT_BLOCKING,
- NULL };
- tp_base_connection_add_interfaces (base_conn, blocking_ifaces);
- }
+ tp_base_connection_add_interfaces (base_conn,
+ (const gchar **) ifaces->pdata);
+ g_ptr_array_unref (ifaces);
tp_base_contact_list_set_list_received (
(TpBaseContactList *) conn->contact_list);
@@ -303,7 +348,8 @@ haze_report_disconnect_reason (PurpleConnection *gc,
priv->disconnecting = TRUE;
map_purple_error_to_tp (reason,
- (base_conn->status == TP_CONNECTION_STATUS_CONNECTING),
+ (tp_base_connection_get_status (base_conn) ==
+ TP_CONNECTION_STATUS_CONNECTING),
&tp_reason, &tp_error_name);
details = tp_asv_new ("debug-message", G_TYPE_STRING, text, NULL);
tp_base_connection_disconnect_with_dbus_error (base_conn, tp_error_name,
@@ -328,7 +374,8 @@ disconnected_cb (PurpleConnection *pc)
priv->disconnecting = TRUE;
- if(base_conn->status != TP_CONNECTION_STATUS_DISCONNECTED)
+ if (tp_base_connection_get_status (base_conn) !=
+ TP_CONNECTION_STATUS_DISCONNECTED)
{
/* Because we have report_disconnect_reason, if status is not already
* DISCONNECTED, we know that it was requested. */
@@ -458,7 +505,8 @@ _haze_connection_password_manager_prompt_cb (GObject *source,
* AUTHENTICATION_FAILED-type message.
*/
}
- else if (base_conn->status != TP_CONNECTION_STATUS_DISCONNECTED)
+ else if (tp_base_connection_get_status (base_conn) !=
+ TP_CONNECTION_STATUS_DISCONNECTED)
{
tp_base_connection_disconnect_with_dbus_error (base_conn,
tp_error_get_dbus_name (error->code), NULL,
@@ -498,13 +546,16 @@ _haze_connection_start_connecting (TpBaseConnection *base,
TpHandleRepoIface *contact_handles =
tp_base_connection_get_handles (base, TP_HANDLE_TYPE_CONTACT);
const gchar *password;
+ TpHandle self_handle;
g_return_val_if_fail (self->account != NULL, FALSE);
- base->self_handle = tp_handle_ensure (contact_handles,
+ self_handle = tp_handle_ensure (contact_handles,
purple_account_get_username (self->account), NULL, error);
- if (!base->self_handle)
- return FALSE;
+ if (self_handle == 0)
+ return FALSE;
+
+ tp_base_connection_set_self_handle (base, self_handle);
tp_base_connection_change_status(base, TP_CONNECTION_STATUS_CONNECTING,
TP_CONNECTION_STATUS_REASON_REQUESTED);
@@ -610,16 +661,6 @@ _haze_connection_create_channel_managers (TpBaseConnection *base)
g_object_new (HAZE_TYPE_IM_CHANNEL_FACTORY, "connection", self, NULL));
g_ptr_array_add (channel_managers, self->im_factory);
-#ifdef ENABLE_MEDIA
- /* Instantiate the media manager only if the protocol support calls */
- if (PURPLE_PROTOCOL_PLUGIN_HAS_FUNC (self->priv->prpl_info, initiate_media))
- {
- self->media_manager = HAZE_MEDIA_MANAGER (
- g_object_new (HAZE_TYPE_MEDIA_MANAGER, "connection", self, NULL));
- g_ptr_array_add (channel_managers, self->media_manager);
- }
-#endif
-
self->contact_list = HAZE_CONTACT_LIST (
g_object_new (HAZE_TYPE_CONTACT_LIST, "connection", self, NULL));
g_ptr_array_add (channel_managers, self->contact_list);
@@ -764,8 +805,6 @@ haze_connection_finalize (GObject *object)
tp_contacts_mixin_finalize (object);
tp_presence_mixin_finalize (object);
- haze_connection_capabilities_finalize (object);
-
g_strfreev (self->acceptable_avatar_mime_types);
g_free (priv->username);
g_free (priv->password);
@@ -821,8 +860,8 @@ haze_connection_class_init (HazeConnectionClass *klass)
haze_connection_get_unique_connection_name;
base_class->start_connecting = _haze_connection_start_connecting;
base_class->shut_down = _haze_connection_shut_down;
- base_class->interfaces_always_present =
- haze_connection_get_guaranteed_interfaces();
+ base_class->get_interfaces_always_present =
+ haze_connection_get_interfaces_always_present;
param_spec = g_param_spec_boxed ("parameters", "gchar * => GValue",
"Connection parameters (password, etc.)",
@@ -862,7 +901,6 @@ haze_connection_class_init (HazeConnectionClass *klass)
haze_connection_presence_class_init (object_class);
haze_connection_aliasing_class_init (object_class);
haze_connection_avatars_class_init (object_class);
- haze_connection_capabilities_class_init (object_class);
}
static void
diff --git a/src/connection.h b/src/connection.h
index 7fc8668..0eef922 100644
--- a/src/connection.h
+++ b/src/connection.h
@@ -22,17 +22,13 @@
*/
#include <glib-object.h>
-#include <telepathy-glib/base-connection.h>
-#include <telepathy-glib/contacts-mixin.h>
-#include <telepathy-glib/presence-mixin.h>
-#include <telepathy-glib/simple-password-manager.h>
+#include <telepathy-glib/telepathy-glib.h>
#include <libpurple/account.h>
#include <libpurple/prpl.h>
#include "contact-list.h"
#include "im-channel-factory.h"
-#include "media-manager.h"
G_BEGIN_DECLS
@@ -54,7 +50,6 @@ struct _HazeConnection {
HazeContactList *contact_list;
HazeImChannelFactory *im_factory;
- HazeMediaManager *media_manager;
TpSimplePasswordManager *password_manager;
TpContactsMixin contacts;
@@ -62,11 +57,6 @@ struct _HazeConnection {
gchar **acceptable_avatar_mime_types;
- GHashTable *client_caps;
-
- /* Part of the hack for Jabber media caps */
- gulong status_changed_id;
-
HazeConnectionPrivate *priv;
};
@@ -108,7 +98,9 @@ GType haze_connection_get_type (void);
const gchar *haze_get_fallback_group (void);
-const gchar **haze_connection_get_implemented_interfaces (void);
+GPtrArray * haze_connection_dup_implemented_interfaces (
+ PurplePluginProtocolInfo *prpl_info);
+
const gchar **haze_connection_get_guaranteed_interfaces (void);
void haze_connection_request_password (PurpleAccount *account,
diff --git a/src/contact-list.c b/src/contact-list.c
index fc46de8..7397c1d 100644
--- a/src/contact-list.c
+++ b/src/contact-list.c
@@ -19,15 +19,14 @@
*
*/
+#include <config.h>
+#include "contact-list.h"
+
#include <string.h>
-#include <telepathy-glib/dbus.h>
-#include <telepathy-glib/gtypes.h>
-#include <telepathy-glib/interfaces.h>
-#include <telepathy-glib/intset.h>
+#include <telepathy-glib/telepathy-glib.h>
#include "connection.h"
-#include "contact-list.h"
#include "debug.h"
typedef struct _PublishRequestData PublishRequestData;
@@ -325,7 +324,8 @@ buddy_removed_cb (PurpleBuddy *buddy, gpointer unused)
/* Every buddy gets removed after disconnection, because the PurpleAccount
* gets deleted. So let's ignore removals when we're offline.
*/
- if (base_conn->status == TP_CONNECTION_STATUS_DISCONNECTED)
+ if (tp_base_connection_get_status (base_conn) ==
+ TP_CONNECTION_STATUS_DISCONNECTED)
return;
contact_list = conn->contact_list;
diff --git a/src/contact-list.h b/src/contact-list.h
index 59b75c2..647a40d 100644
--- a/src/contact-list.h
+++ b/src/contact-list.h
@@ -22,7 +22,9 @@
#include <glib-object.h>
-#include <telepathy-glib/base-contact-list.h>
+#include <libpurple/account.h>
+
+#include <telepathy-glib/telepathy-glib.h>
G_BEGIN_DECLS
diff --git a/src/debug.c b/src/debug.c
index 976332b..6269edf 100644
--- a/src/debug.c
+++ b/src/debug.c
@@ -18,14 +18,14 @@
*
*/
+#include <config.h>
#include "debug.h"
#include <string.h>
#include <stdarg.h>
#include <libpurple/debug.h>
-#include <telepathy-glib/debug.h>
-#include <telepathy-glib/debug-sender.h>
+#include <telepathy-glib/telepathy-glib.h>
typedef enum
diff --git a/src/im-channel-factory.c b/src/im-channel-factory.c
index 3fb9824..31823ce 100644
--- a/src/im-channel-factory.c
+++ b/src/im-channel-factory.c
@@ -24,12 +24,7 @@
#include <string.h>
-#include <telepathy-glib/base-connection.h>
-#include <telepathy-glib/channel-manager.h>
-#include <telepathy-glib/dbus.h>
-#include <telepathy-glib/gtypes.h>
-#include <telepathy-glib/handle-repo.h>
-#include <telepathy-glib/interfaces.h>
+#include <telepathy-glib/telepathy-glib.h>
#include "debug.h"
#include "im-channel.h"
@@ -281,7 +276,8 @@ new_im_channel (HazeImChannelFactory *self,
g_assert (!g_hash_table_lookup (self->priv->channels,
GINT_TO_POINTER (handle)));
- object_path = g_strdup_printf ("%s/ImChannel%u", conn->object_path, handle);
+ object_path = g_strdup_printf ("%s/ImChannel%u",
+ tp_base_connection_get_object_path (conn), handle);
chan = g_object_new (HAZE_TYPE_IM_CHANNEL,
"connection", self->priv->conn,
@@ -578,8 +574,9 @@ haze_im_channel_factory_request (HazeImChannelFactory *self,
goto error;
}
- chan = get_im_channel (self, handle, base_conn->self_handle,
- request_token, &created);
+ chan = get_im_channel (self, handle,
+ tp_base_connection_get_self_handle (base_conn), request_token,
+ &created);
g_assert (chan != NULL);
if (!created)
diff --git a/src/im-channel.c b/src/im-channel.c
index b6f3653..f74004d 100644
--- a/src/im-channel.c
+++ b/src/im-channel.c
@@ -19,13 +19,11 @@
*
*/
-#include <telepathy-glib/channel-iface.h>
-#include <telepathy-glib/dbus.h>
-#include <telepathy-glib/exportable-channel.h>
-#include <telepathy-glib/interfaces.h>
-#include <telepathy-glib/svc-generic.h>
-
+#include <config.h>
#include "im-channel.h"
+
+#include <telepathy-glib/telepathy-glib.h>
+
#include "connection.h"
#include "debug.h"
@@ -470,7 +468,8 @@ haze_im_channel_get_property (GObject *object,
}
case PROP_REQUESTED:
g_value_set_boolean (value,
- (priv->initiator == base_conn->self_handle));
+ (priv->initiator ==
+ tp_base_connection_get_self_handle (base_conn)));
break;
case PROP_CONNECTION:
g_value_set_object (value, priv->conn);
diff --git a/src/im-channel.h b/src/im-channel.h
index 59105c7..6427828 100644
--- a/src/im-channel.h
+++ b/src/im-channel.h
@@ -23,7 +23,7 @@
#include <glib-object.h>
-#include <telepathy-glib/message-mixin.h>
+#include <telepathy-glib/telepathy-glib.h>
#include <libpurple/conversation.h>
diff --git a/src/main.c b/src/main.c
index 0c48ac5..bf4b601 100644
--- a/src/main.c
+++ b/src/main.c
@@ -39,15 +39,11 @@
#include <libpurple/prefs.h>
#include <libpurple/util.h>
-#ifdef ENABLE_MEDIA
-#include <libpurple/mediamanager.h>
-#endif
-
#ifdef HAVE_PURPLE_DBUS_UNINIT
#include <libpurple/dbus-server.h>
#endif
-#include <telepathy-glib/run.h>
+#include <telepathy-glib/telepathy-glib.h>
#include "defines.h"
#include "debug.h"
@@ -56,10 +52,6 @@
#include "request.h"
#include "util.h"
-#ifdef ENABLE_MEDIA
-#include "media-backend.h"
-#endif
-
/* Copied verbatim from nullclient, modulo changing whitespace. */
#define PURPLE_GLIB_READ_COND (G_IO_IN | G_IO_HUP | G_IO_ERR)
#define PURPLE_GLIB_WRITE_COND (G_IO_OUT | G_IO_HUP | G_IO_ERR | G_IO_NVAL)
@@ -212,11 +204,6 @@ init_libpurple (void)
PURPLE_MAJOR_VERSION, PURPLE_MINOR_VERSION, PURPLE_MICRO_VERSION);
set_libpurple_preferences ();
-
-#ifdef ENABLE_MEDIA
- purple_media_manager_set_backend_type (purple_media_manager_get (),
- HAZE_TYPE_MEDIA_BACKEND);
-#endif
}
static TpBaseConnectionManager *
diff --git a/src/media-backend.c b/src/media-backend.c
deleted file mode 100644
index ec40af9..0000000
--- a/src/media-backend.c
+++ /dev/null
@@ -1,615 +0,0 @@
-/*
- * media-backend.c - Source for HazeMediaBackend
- * Copyright © 2006-2009 Collabora Ltd.
- * Copyright © 2006-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 "config.h"
-#include "media-backend.h"
-
-#include <libpurple/media/backend-iface.h>
-#include <telepathy-glib/dbus.h>
-#include <telepathy-glib/errors.h>
-#include <telepathy-glib/svc-media-interfaces.h>
-
-#include <string.h>
-
-#include "debug.h"
-
-static void media_backend_iface_init(PurpleMediaBackendIface *iface);
-static void session_handler_iface_init (gpointer g_iface,
- gpointer iface_data);
-static void haze_backend_state_changed_cb (PurpleMedia *media,
- PurpleMediaState state,
- const gchar *sid,
- const gchar *name,
- HazeMediaBackend *backend);
-
-G_DEFINE_TYPE_WITH_CODE (HazeMediaBackend,
- haze_media_backend,
- G_TYPE_OBJECT,
- G_IMPLEMENT_INTERFACE (PURPLE_TYPE_MEDIA_BACKEND,
- media_backend_iface_init);
- G_IMPLEMENT_INTERFACE (TP_TYPE_SVC_MEDIA_SESSION_HANDLER,
- session_handler_iface_init);
- )
-
-/* properties */
-enum
-{
- PROP_CONFERENCE_TYPE = 1,
- PROP_MEDIA,
- PROP_OBJECT_PATH,
- PROP_STREAMS,
- LAST_PROPERTY
-};
-
-/* private structure */
-struct _HazeMediaBackendPrivate
-{
- gchar *conference_type;
- gchar *object_path;
- gpointer media;
- GPtrArray *streams;
-
- guint next_stream_id;
- gboolean ready;
-};
-
-static void
-haze_media_backend_init (HazeMediaBackend *self)
-{
- HazeMediaBackendPrivate *priv = G_TYPE_INSTANCE_GET_PRIVATE (self,
- HAZE_TYPE_MEDIA_BACKEND, HazeMediaBackendPrivate);
-
- self->priv = priv;
-
- priv->next_stream_id = 1;
- priv->streams = g_ptr_array_sized_new (1);
-}
-
-static void
-haze_media_backend_get_property (GObject *object,
- guint property_id,
- GValue *value,
- GParamSpec *pspec)
-{
- HazeMediaBackend *backend = HAZE_MEDIA_BACKEND (object);
- HazeMediaBackendPrivate *priv = backend->priv;
-
- switch (property_id)
- {
- case PROP_CONFERENCE_TYPE:
- g_value_set_string (value, priv->conference_type);
- break;
- case PROP_MEDIA:
- g_value_set_object (value, priv->media);
- break;
- case PROP_OBJECT_PATH:
- g_value_set_string (value, priv->object_path);
- break;
- case PROP_STREAMS:
- g_value_set_boxed (value, priv->streams);
- break;
- default:
- G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
- break;
- }
-}
-
-static void
-haze_media_backend_set_property (GObject *object,
- guint property_id,
- const GValue *value,
- GParamSpec *pspec)
-{
- HazeMediaBackend *backend = HAZE_MEDIA_BACKEND (object);
- HazeMediaBackendPrivate *priv = backend->priv;
-
- switch (property_id)
- {
- case PROP_CONFERENCE_TYPE:
- g_free (priv->conference_type);
- priv->conference_type = g_value_dup_string (value);
- break;
- case PROP_MEDIA:
- g_assert (priv->media == NULL);
- priv->media = g_value_get_object (value);
-
- g_object_add_weak_pointer(G_OBJECT(priv->media), &priv->media);
- g_signal_connect (priv->media, "state-changed",
- G_CALLBACK (haze_backend_state_changed_cb), backend);
- break;
- case PROP_OBJECT_PATH:
- g_assert (priv->object_path == NULL);
- priv->object_path = g_value_dup_string (value);
-
- if (priv->object_path != NULL)
- {
- TpDBusDaemon *dbus_daemon = tp_dbus_daemon_dup (NULL);
-
- g_return_if_fail (dbus_daemon != NULL);
- tp_dbus_daemon_register_object (dbus_daemon,
- priv->object_path, G_OBJECT (backend));
- g_object_unref (dbus_daemon);
- }
- break;
- default:
- G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
- break;
- }
-}
-
-static void haze_media_backend_dispose (GObject *object);
-static void haze_media_backend_finalize (GObject *object);
-
-static void
-haze_media_backend_class_init (HazeMediaBackendClass *haze_media_backend_class)
-{
- GObjectClass *object_class = G_OBJECT_CLASS (haze_media_backend_class);
- GParamSpec *param_spec;
-
- g_type_class_add_private (haze_media_backend_class,
- sizeof (HazeMediaBackendPrivate));
-
- object_class->get_property = haze_media_backend_get_property;
- object_class->set_property = haze_media_backend_set_property;
-
- object_class->dispose = haze_media_backend_dispose;
- object_class->finalize = haze_media_backend_finalize;
-
- g_object_class_override_property(object_class, PROP_CONFERENCE_TYPE,
- "conference-type");
- g_object_class_override_property(object_class, PROP_MEDIA, "media");
-
- param_spec = g_param_spec_string ("object-path", "D-Bus object path",
- "The D-Bus object path used for this "
- "object on the bus.",
- NULL,
- G_PARAM_READWRITE |
- G_PARAM_STATIC_STRINGS);
- g_object_class_install_property (object_class, PROP_OBJECT_PATH, param_spec);
-
- param_spec = g_param_spec_boxed ("streams", "Streams",
- "List of streams handled by this backend.",
- G_TYPE_PTR_ARRAY,
- G_PARAM_READABLE |
- G_PARAM_STATIC_NAME |
- G_PARAM_STATIC_BLURB);
- g_object_class_install_property (object_class, PROP_STREAMS, param_spec);
-}
-
-void
-haze_media_backend_dispose (GObject *object)
-{
- DEBUG ("called");
-
- if (G_OBJECT_CLASS (haze_media_backend_parent_class)->dispose)
- G_OBJECT_CLASS (haze_media_backend_parent_class)->dispose (object);
-}
-
-void
-haze_media_backend_finalize (GObject *object)
-{
- HazeMediaBackend *self = HAZE_MEDIA_BACKEND (object);
- HazeMediaBackendPrivate *priv = self->priv;
-
- g_free (priv->conference_type);
- g_free (priv->object_path);
-
- if (priv->streams != NULL)
- g_ptr_array_free (priv->streams, TRUE);
-
- G_OBJECT_CLASS (haze_media_backend_parent_class)->finalize (object);
-}
-
-static HazeMediaStream *
-get_stream_by_name (HazeMediaBackend *self,
- const gchar *sid)
-{
- HazeMediaBackendPrivate *priv = self->priv;
- guint i;
-
- for (i = 0; i < priv->streams->len; ++i)
- {
- HazeMediaStream *stream = g_ptr_array_index (priv->streams, i);
-
- if (!strcmp (sid, stream->name))
- return stream;
- }
-
- return NULL;
-}
-
-HazeMediaStream *
-haze_media_backend_get_stream_by_name (HazeMediaBackend *self,
- const gchar *sid)
-{
- return get_stream_by_name (self, sid);
-}
-
-static void
-haze_backend_state_changed_cb (PurpleMedia *media,
- PurpleMediaState state,
- const gchar *sid,
- const gchar *name,
- HazeMediaBackend *backend)
-{
- HazeMediaBackendPrivate *priv = backend->priv;
-
- if (state == PURPLE_MEDIA_STATE_END && sid != NULL && name == NULL)
- {
- HazeMediaStream *stream = get_stream_by_name (backend, sid);
-
- if (stream != NULL)
- {
- g_ptr_array_remove_fast (priv->streams, stream);
- g_object_unref (stream);
- }
- }
-}
-
-static void
-_emit_new_stream (HazeMediaBackend *self,
- HazeMediaStream *stream)
-{
- gchar *object_path;
- guint id, media_type;
-
- g_object_get (stream,
- "object-path", &object_path,
- "id", &id,
- "media-type", &media_type,
- NULL);
-
- /* all of the streams are bidirectional from farsight's point of view, it's
- * just in the signalling they change */
- DEBUG ("emitting MediaSessionHandler:NewStreamHandler signal for %s stream %d",
- media_type == TP_MEDIA_STREAM_TYPE_AUDIO ? "audio" : "video", id);
- tp_svc_media_session_handler_emit_new_stream_handler (self,
- object_path, id, media_type, TP_MEDIA_STREAM_DIRECTION_BIDIRECTIONAL);
-
- g_free (object_path);
-}
-
-static gboolean
-haze_media_backend_add_stream (PurpleMediaBackend *self,
- const gchar *sid, const gchar *who,
- PurpleMediaSessionType type, gboolean initiator,
- const gchar *transmitter,
- guint num_params, GParameter *params)
-{
- HazeMediaBackendPrivate *priv = HAZE_MEDIA_BACKEND (self)->priv;
- HazeMediaStream *stream;
- gchar *object_path;
- guint media_type, id, stun_port = 3478; /* default stun port */
- const gchar *nat_traversal = NULL, *stun_server = NULL;
- TpDBusDaemon *dbus_daemon = tp_dbus_daemon_dup (NULL);
-
- DEBUG ("called");
-
- g_return_val_if_fail (dbus_daemon != NULL, FALSE);
-
- id = priv->next_stream_id++;
-
- object_path = g_strdup_printf ("%s/MediaStream%u",
- priv->object_path, id);
-
- if (type & PURPLE_MEDIA_AUDIO)
- media_type = TP_MEDIA_STREAM_TYPE_AUDIO;
- else
- media_type = TP_MEDIA_STREAM_TYPE_VIDEO;
-
- if (!strcmp (transmitter, "nice"))
- {
- guint i;
-
- for (i = 0; i < num_params; ++i)
- {
- if (!strcmp (params[i].name, "compatibility-mode") &&
- G_VALUE_HOLDS (&params[i].value, G_TYPE_UINT))
- {
- guint mode = g_value_get_uint (&params[i].value);
-
- switch (mode)
- {
- case 0: /* NICE_COMPATIBILITY_DRAFT19 */
- nat_traversal = "ice-udp";
- break;
- case 1: /* NICE_COMPATIBILITY_GOOGLE */
- nat_traversal = "gtalk-p2p";
- break;
- case 2: /* NICE_COMPATIBILITY_MSN */
- nat_traversal = "wlm-8.5";
- break;
- case 3: /* NICE_COMPATIBILITY_WLM2009 */
- nat_traversal = "wlm-2009";
- break;
- default:
- g_assert_not_reached ();
- }
- }
- else if (!strcmp (params[i].name, "stun-ip") &&
- G_VALUE_HOLDS (&params[i].value, G_TYPE_STRING))
- {
- stun_server = g_value_get_string (&params[i].value);
- }
- else if (!strcmp (params[i].name, "stun-port") &&
- G_VALUE_HOLDS (&params[i].value, G_TYPE_UINT))
- {
- stun_port = g_value_get_uint (&params[i].value);
- }
- }
-
- if (nat_traversal == NULL)
- nat_traversal = "ice-udp";
- }
- else if (!strcmp (transmitter, "rawudp"))
- {
- nat_traversal = "none";
- }
- else
- {
- g_assert_not_reached ();
- }
-
- stream = haze_media_stream_new (object_path, dbus_daemon, priv->media,
- sid, who, media_type, id, initiator, nat_traversal, NULL, FALSE);
-
- if (stun_server != NULL)
- haze_media_stream_add_stun_server (stream, stun_server, stun_port);
-
- g_free (object_path);
-
- DEBUG ("%p: created new MediaStream %p for sid '%s'",
- self, stream, sid);
-
- g_ptr_array_add (priv->streams, stream);
-
- if (priv->ready)
- _emit_new_stream (HAZE_MEDIA_BACKEND (self), stream);
-
- g_object_unref (dbus_daemon);
-
- return TRUE;
-}
-
-static void
-haze_media_backend_add_remote_candidates (PurpleMediaBackend *self,
- const gchar *sid,
- const gchar *who,
- GList *remote_candidates)
-{
- HazeMediaStream *stream;
-
- DEBUG ("called");
-
- stream = get_stream_by_name (HAZE_MEDIA_BACKEND (self), sid);
-
- if (stream != NULL)
- haze_media_stream_add_remote_candidates (stream, remote_candidates);
- else
- DEBUG ("Couldn't find stream");
-}
-
-static gboolean
-haze_media_backend_codecs_ready (PurpleMediaBackend *self,
- const gchar *sid)
-{
- HazeMediaStream *stream;
- gboolean ready = FALSE;
-
- DEBUG ("called");
-
- if (sid != NULL)
- {
- stream = get_stream_by_name (HAZE_MEDIA_BACKEND (self), sid);
-
- if (stream != NULL)
- g_object_get (stream, "codecs-ready", &ready, NULL);
-
- return ready;
- }
- else
- {
- HazeMediaBackendPrivate *priv = HAZE_MEDIA_BACKEND (self)->priv;
- guint i;
-
- for (i = 0; i < priv->streams->len; ++i)
- {
- stream = g_ptr_array_index (priv->streams, i);
-
- if (stream != NULL)
- g_object_get (stream, "codecs-ready", &ready, NULL);
-
- if (!ready)
- return FALSE;
- }
-
- return TRUE;
- }
-}
-
-static GList *
-haze_media_backend_get_codecs (PurpleMediaBackend *self,
- const gchar *sid)
-{
- HazeMediaStream *stream;
- GList *ret = NULL;
-
- DEBUG ("called");
-
- stream = get_stream_by_name (HAZE_MEDIA_BACKEND (self), sid);
-
- if (stream != NULL)
- ret = haze_media_stream_get_codecs (stream);
-
- return ret;
-}
-
-static GList *
-haze_media_backend_get_local_candidates (PurpleMediaBackend *self,
- const gchar *sid,
- const gchar *who)
-{
- HazeMediaStream *stream;
- GList *ret = NULL;
-
- DEBUG ("called");
-
- stream = get_stream_by_name (HAZE_MEDIA_BACKEND (self), sid);
-
- if (stream != NULL)
- ret = haze_media_stream_get_local_candidates (stream);
-
- return ret;
-}
-
-static gboolean
-haze_media_backend_set_remote_codecs (PurpleMediaBackend *self,
- const gchar *sid,
- const gchar *who,
- GList *codecs)
-{
- HazeMediaStream *stream;
-
- DEBUG ("called");
-
- stream = get_stream_by_name (HAZE_MEDIA_BACKEND (self), sid);
-
- if (stream != NULL)
- haze_media_stream_set_remote_codecs (stream, codecs);
- else
- DEBUG ("Couldn't find stream");
-
- return TRUE;
-}
-
-static gboolean
-haze_media_backend_set_send_codec (PurpleMediaBackend *self,
- const gchar *sid,
- PurpleMediaCodec *codec)
-{
- return FALSE;
-}
-
-static void
-haze_media_backend_ready (TpSvcMediaSessionHandler *iface,
- DBusGMethodInvocation *context)
-{
- HazeMediaBackend *self = HAZE_MEDIA_BACKEND (iface);
- HazeMediaBackendPrivate *priv = self->priv;
-
- if (!priv->ready)
- {
- guint i;
-
- DEBUG ("emitting NewStreamHandler for each stream");
-
- priv->ready = TRUE;
-
- for (i = 0; i < priv->streams->len; i++)
- _emit_new_stream (self, g_ptr_array_index (priv->streams, i));
- }
-
- tp_svc_media_session_handler_return_from_ready (context);
-}
-
-static void
-haze_media_backend_error (TpSvcMediaSessionHandler *iface,
- guint errno,
- const gchar *message,
- DBusGMethodInvocation *context)
-{
- HazeMediaBackend *self = HAZE_MEDIA_BACKEND (iface);
- HazeMediaBackendPrivate *priv;
- GPtrArray *tmp;
- guint i;
-
- g_assert (HAZE_IS_MEDIA_BACKEND (self));
-
- priv = self->priv;
-
- if (priv->media == NULL)
- {
- /* This could also be because someone called Error() before the
- * SessionHandler was announced. But the fact that the SessionHandler is
- * actually also the Channel, and thus this method is available before
- * NewSessionHandler is emitted, is an implementation detail. So the
- * error message describes the only legitimate situation in which this
- * could arise.
- */
- GError e = { TP_ERROR, TP_ERROR_NOT_AVAILABLE, "call has already ended" };
-
- DEBUG ("no session, returning an error.");
- dbus_g_method_return_error (context, &e);
- return;
- }
-
- DEBUG ("Media.SessionHandler::Error called, error %u (%s) -- "
- "emitting error on each stream", errno, message);
-
- purple_media_end (priv->media, NULL, NULL);
-
- /* Calling haze_media_stream_error () on all the streams will ultimately
- * cause them all to emit 'closed'. In response to 'closed', stream_close_cb
- * unrefs them, and removes them from priv->streams. So, we copy the stream
- * list to avoid it being modified from underneath us.
- */
- tmp = g_ptr_array_sized_new (priv->streams->len);
-
- for (i = 0; i < priv->streams->len; i++)
- g_ptr_array_add (tmp, g_ptr_array_index (priv->streams, i));
-
- for (i = 0; i < tmp->len; i++)
- {
- HazeMediaStream *stream = g_ptr_array_index (tmp, i);
-
- haze_media_stream_error (stream, errno, message, NULL);
- }
-
- g_ptr_array_free (tmp, TRUE);
-
- tp_svc_media_session_handler_return_from_error (context);
-}
-
-static void
-media_backend_iface_init (PurpleMediaBackendIface *iface)
-{
-#define IMPLEMENT(x) iface->x = haze_media_backend_##x
- IMPLEMENT(add_stream);
- IMPLEMENT(add_remote_candidates);
- IMPLEMENT(codecs_ready);
- IMPLEMENT(get_codecs);
- IMPLEMENT(get_local_candidates);
- IMPLEMENT(set_remote_codecs);
- IMPLEMENT(set_send_codec);
-#undef IMPLEMENT
-}
-
-static void
-session_handler_iface_init (gpointer g_iface, gpointer iface_data)
-{
- TpSvcMediaSessionHandlerClass *klass =
- (TpSvcMediaSessionHandlerClass *) g_iface;
-
-#define IMPLEMENT(x) tp_svc_media_session_handler_implement_##x (\
- klass, haze_media_backend_##x)
- IMPLEMENT(error);
- IMPLEMENT(ready);
-#undef IMPLEMENT
-}
diff --git a/src/media-backend.h b/src/media-backend.h
deleted file mode 100644
index d673c55..0000000
--- a/src/media-backend.h
+++ /dev/null
@@ -1,68 +0,0 @@
-/*
- * media-backend.h - Header for HazeMediaBackend
- * Copyright (C) 2006, 2009 Collabora Ltd.
- * Copyright (C) 2006 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 __HAZE_MEDIA_BACKEND__
-#define __HAZE_MEDIA_BACKEND__
-
-#include <glib-object.h>
-
-#include "media-stream.h"
-
-G_BEGIN_DECLS
-
-typedef struct _HazeMediaBackend HazeMediaBackend;
-typedef struct _HazeMediaBackendClass HazeMediaBackendClass;
-typedef struct _HazeMediaBackendPrivate HazeMediaBackendPrivate;
-
-struct _HazeMediaBackendClass {
- GObjectClass parent_class;
-};
-
-struct _HazeMediaBackend {
- GObject parent;
-
- HazeMediaBackendPrivate *priv;
-};
-
-GType haze_media_backend_get_type (void);
-HazeMediaStream *haze_media_backend_get_stream_by_name (
- HazeMediaBackend *self,
- const gchar *sid);
-
-/* TYPE MACROS */
-#define HAZE_TYPE_MEDIA_BACKEND \
- (haze_media_backend_get_type ())
-#define HAZE_MEDIA_BACKEND(obj) \
- (G_TYPE_CHECK_INSTANCE_CAST((obj), HAZE_TYPE_MEDIA_BACKEND, \
- HazeMediaBackend))
-#define HAZE_MEDIA_BACKEND_CLASS(klass) \
- (G_TYPE_CHECK_CLASS_CAST((klass), HAZE_TYPE_MEDIA_BACKEND, \
- HazeMediaBackendClass))
-#define HAZE_IS_MEDIA_BACKEND(obj) \
- (G_TYPE_CHECK_INSTANCE_TYPE((obj), HAZE_TYPE_MEDIA_BACKEND))
-#define HAZE_IS_MEDIA_BACKEND_CLASS(klass) \
- (G_TYPE_CHECK_CLASS_TYPE((klass), HAZE_TYPE_MEDIA_BACKEND))
-#define HAZE_MEDIA_BACKEND_GET_CLASS(obj) \
- (G_TYPE_INSTANCE_GET_CLASS ((obj), HAZE_TYPE_MEDIA_BACKEND, \
- HazeMediaBackendClass))
-
-G_END_DECLS
-
-#endif /* #ifndef __HAZE_MEDIA_BACKEND__ */
diff --git a/src/media-channel.c b/src/media-channel.c
deleted file mode 100644
index 54c2a41..0000000
--- a/src/media-channel.c
+++ /dev/null
@@ -1,1762 +0,0 @@
-/*
- * media-channel.c - Source for HazeMediaChannel
- * Copyright (C) 2006, 2009 Collabora Ltd.
- * Copyright (C) 2006 Nokia Corporation
- *
- * Copied heavily from telepathy-gabble
- *
- * 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 "config.h"
-#include "media-channel.h"
-
-#include <libpurple/media/backend-iface.h>
-#include <libpurple/mediamanager.h>
-#include <telepathy-glib/dbus.h>
-#include <telepathy-glib/interfaces.h>
-#include <telepathy-glib/channel-iface.h>
-#include <telepathy-glib/gtypes.h>
-#include <telepathy-glib/svc-channel.h>
-#include <telepathy-glib/svc-properties-interface.h>
-#include <telepathy-glib/svc-media-interfaces.h>
-
-#include "connection.h"
-#include "debug.h"
-#include "media-backend.h"
-#include "media-stream.h"
-
-static void channel_iface_init (gpointer, gpointer);
-static void media_signalling_iface_init (gpointer, gpointer);
-static void streamed_media_iface_init (gpointer, gpointer);
-static gboolean haze_media_channel_add_member (GObject *obj,
- TpHandle handle,
- const gchar *message,
- GError **error);
-static gboolean haze_media_channel_remove_member (GObject *obj,
- TpHandle handle, const gchar *message, guint reason, GError **error);
-
-G_DEFINE_TYPE_WITH_CODE (HazeMediaChannel, haze_media_channel,
- G_TYPE_OBJECT,
- G_IMPLEMENT_INTERFACE (TP_TYPE_SVC_CHANNEL, channel_iface_init);
- G_IMPLEMENT_INTERFACE (TP_TYPE_SVC_CHANNEL_INTERFACE_GROUP,
- tp_group_mixin_iface_init);
- G_IMPLEMENT_INTERFACE (TP_TYPE_SVC_CHANNEL_TYPE_STREAMED_MEDIA,
- streamed_media_iface_init);
- G_IMPLEMENT_INTERFACE (TP_TYPE_SVC_CHANNEL_INTERFACE_MEDIA_SIGNALLING,
- media_signalling_iface_init);
- G_IMPLEMENT_INTERFACE (TP_TYPE_SVC_DBUS_PROPERTIES,
- tp_dbus_properties_mixin_iface_init);
- G_IMPLEMENT_INTERFACE (TP_TYPE_EXPORTABLE_CHANNEL, NULL);
- G_IMPLEMENT_INTERFACE (TP_TYPE_CHANNEL_IFACE, NULL));
-
-static const gchar *haze_media_channel_interfaces[] = {
- TP_IFACE_CHANNEL_INTERFACE_GROUP,
- TP_IFACE_CHANNEL_INTERFACE_MEDIA_SIGNALLING,
- NULL
-};
-
-/* properties */
-enum
-{
- PROP_OBJECT_PATH = 1,
- PROP_CHANNEL_TYPE,
- PROP_HANDLE_TYPE,
- PROP_HANDLE,
- PROP_TARGET_ID,
- PROP_INITIAL_PEER,
- PROP_PEER,
- PROP_REQUESTED,
- PROP_CONNECTION,
- PROP_CREATOR,
- PROP_CREATOR_ID,
- PROP_INTERFACES,
- PROP_CHANNEL_DESTROYED,
- PROP_CHANNEL_PROPERTIES,
- PROP_INITIAL_AUDIO,
- PROP_INITIAL_VIDEO,
- PROP_MEDIA,
- LAST_PROPERTY
-};
-
-struct _HazeMediaChannelPrivate
-{
- HazeConnection *conn;
- gchar *object_path;
- TpHandle creator;
- TpHandle initial_peer;
-
- PurpleMedia *media;
-
- guint next_stream_id;
-
- /* list of PendingStreamRequest* in no particular order */
- GList *pending_stream_requests;
-
- TpLocalHoldState hold_state;
- TpLocalHoldStateReason hold_state_reason;
-
- TpChannelCallStateFlags call_state;
-
- gboolean initial_audio;
- gboolean initial_video;
-
- gboolean ready;
- gboolean media_ended;
- gboolean closed;
- gboolean dispose_has_run;
-};
-
-static void
-haze_media_channel_init (HazeMediaChannel *self)
-{
- HazeMediaChannelPrivate *priv = G_TYPE_INSTANCE_GET_PRIVATE (self,
- HAZE_TYPE_MEDIA_CHANNEL, HazeMediaChannelPrivate);
-
- self->priv = priv;
-
- priv->next_stream_id = 1;
-}
-
-/**
- * make_stream_list:
- *
- * Creates an array of MediaStreamInfo structs.
- */
-static GPtrArray *
-make_stream_list (HazeMediaChannel *self,
- guint len,
- HazeMediaStream **streams)
-{
- HazeMediaChannelPrivate *priv = self->priv;
- GPtrArray *ret;
- guint i;
- GType info_type = TP_STRUCT_TYPE_MEDIA_STREAM_INFO;
-
- ret = g_ptr_array_sized_new (len);
-
- for (i = 0; i < len; i++)
- {
- GValue entry = { 0, };
- guint id;
- TpHandle peer;
- TpMediaStreamType type;
- TpMediaStreamState connection_state;
- CombinedStreamDirection combined_direction;
-
- g_object_get (streams[i],
- "id", &id,
- "media-type", &type,
- "connection-state", &connection_state,
- "combined-direction", &combined_direction,
- NULL);
-
- peer = priv->initial_peer;
-
- g_value_init (&entry, info_type);
- g_value_take_boxed (&entry,
- dbus_g_type_specialized_construct (info_type));
-
- dbus_g_type_struct_set (&entry,
- 0, id,
- 1, peer,
- 2, type,
- 3, connection_state,
- 4, COMBINED_DIRECTION_GET_DIRECTION (combined_direction),
- 5, COMBINED_DIRECTION_GET_PENDING_SEND (combined_direction),
- G_MAXUINT);
-
- g_ptr_array_add (ret, g_value_get_boxed (&entry));
- }
-
- return ret;
-}
-
-typedef struct {
- /* number of streams requested == number of content objects */
- guint len;
- /* array of @len borrowed pointers */
- guint *types;
- /* accumulates borrowed pointers to streams. Initially @len NULL pointers;
- * when the stream for contents[i] is created, it is stored at streams[i].
- */
- HazeMediaStream **streams;
- /* number of non-NULL elements in streams (0 <= satisfied <= contents) */
- guint satisfied;
- /* succeeded_cb(context, GPtrArray<TP_STRUCT_TYPE_MEDIA_STREAM_INFO>)
- * will be called if the stream request succeeds.
- */
- GFunc succeeded_cb;
- /* failed_cb(context, GError *) will be called if the stream request fails.
- */
- GFunc failed_cb;
- gpointer context;
-} PendingStreamRequest;
-
-static PendingStreamRequest *
-pending_stream_request_new (const GArray *types,
- GFunc succeeded_cb,
- GFunc failed_cb,
- gpointer context)
-{
- PendingStreamRequest *p = g_slice_new0 (PendingStreamRequest);
-
- g_assert (succeeded_cb);
- g_assert (failed_cb);
-
- p->len = types->len;
- p->types = g_memdup (types->data, types->len * sizeof (gpointer));
- p->streams = g_new0 (HazeMediaStream *, types->len);
- p->satisfied = 0;
- p->succeeded_cb = succeeded_cb;
- p->failed_cb = failed_cb;
- p->context = context;
-
- return p;
-}
-
-static gboolean
-pending_stream_request_maybe_satisfy (PendingStreamRequest *p,
- HazeMediaChannel *channel,
- guint type,
- HazeMediaStream *stream)
-{
- guint i;
-
- for (i = 0; i < p->len; i++)
- {
- if (p->types[i] == type)
- {
- g_assert (p->streams[i] == NULL);
- p->streams[i] = stream;
-
- if (++p->satisfied == p->len && p->context != NULL)
- {
- GPtrArray *ret = make_stream_list (channel, p->len, p->streams);
-
- p->succeeded_cb (p->context, ret);
- g_ptr_array_foreach (ret, (GFunc) g_value_array_free, NULL);
- g_ptr_array_free (ret, TRUE);
- p->context = NULL;
- return TRUE;
- }
- }
- }
-
- return FALSE;
-}
-
-static void
-pending_stream_request_free (gpointer data)
-{
- PendingStreamRequest *p = data;
-
- if (p->context != NULL)
- {
- GError e = { TP_ERROR, TP_ERROR_CANCELLED,
- "The session terminated before the requested streams could be added"
- };
-
- p->failed_cb (p->context, &e);
- }
-
- g_free (p->types);
- g_free (p->streams);
-
- g_slice_free (PendingStreamRequest, p);
-}
-
-static void
-stream_direction_changed_cb (HazeMediaStream *stream,
- GParamSpec *pspec,
- HazeMediaChannel *chan)
-{
- guint id;
- CombinedStreamDirection combined;
- TpMediaStreamDirection direction;
- TpMediaStreamPendingSend pending_send;
-
- g_object_get (stream,
- "id", &id,
- "combined-direction", &combined,
- NULL);
-
- direction = COMBINED_DIRECTION_GET_DIRECTION (combined);
- pending_send = COMBINED_DIRECTION_GET_PENDING_SEND (combined);
-
- DEBUG ("direction: %u, pending_send: %u", direction, pending_send);
-
- tp_svc_channel_type_streamed_media_emit_stream_direction_changed (
- chan, id, direction, pending_send);
-}
-
-static void
-media_error_cb (PurpleMedia *media,
- const gchar *error,
- HazeMediaChannel *chan)
-{
- g_assert (HAZE_MEDIA_CHANNEL(chan)->priv != NULL);
- DEBUG ("Media error on %s: %s", chan->priv->object_path, error);
-}
-
-static void
-media_state_changed_cb (PurpleMedia *media,
- PurpleMediaState state,
- gchar *sid, gchar *name,
- HazeMediaChannel *chan)
-{
- HazeMediaChannelPrivate *priv = chan->priv;
-
- DEBUG ("%s %s %s",
- state == PURPLE_MEDIA_STATE_NEW ? "NEW" :
- state == PURPLE_MEDIA_STATE_CONNECTED ? "CONNECTED" :
- state == PURPLE_MEDIA_STATE_END ? "END" :
- "UNKNOWN", sid, name);
-
- if (state == PURPLE_MEDIA_STATE_NEW)
- {
- if (sid != NULL && name != NULL)
- {
- HazeMediaBackend *backend;
- HazeMediaStream *stream;
- TpMediaStreamType type;
- guint id;
-
- g_object_get (priv->media, "backend", &backend, NULL);
- stream = haze_media_backend_get_stream_by_name (backend, sid);
- g_object_unref (backend);
-
- g_object_get (G_OBJECT (stream), "id", &id, NULL);
- type = haze_media_stream_get_media_type (stream);
-
- /* if any RequestStreams call was waiting for a stream to be created for
- * that content, return from it successfully */
- {
- GList *iter = priv->pending_stream_requests;
-
- while (iter != NULL)
- {
- if (pending_stream_request_maybe_satisfy (iter->data,
- chan, type, stream))
- {
- GList *dead = iter;
-
- pending_stream_request_free (dead->data);
-
- iter = dead->next;
- priv->pending_stream_requests = g_list_delete_link (
- priv->pending_stream_requests, dead);
- }
- else
- {
- iter = iter->next;
- }
- }
- }
-
- g_signal_connect (stream, "notify::combined-direction",
- (GCallback) stream_direction_changed_cb, chan);
-
- tp_svc_channel_type_streamed_media_emit_stream_added (
- chan, id, priv->initial_peer, type);
-
- stream_direction_changed_cb (stream, NULL, chan);
- }
- }
-
- if (sid != NULL && name == NULL)
- {
- TpMediaStreamState tp_state;
- HazeMediaBackend *backend;
- HazeMediaStream *stream;
-
- if (state == PURPLE_MEDIA_STATE_NEW)
- tp_state = TP_MEDIA_STREAM_STATE_CONNECTING;
- else if (state == PURPLE_MEDIA_STATE_CONNECTED)
- tp_state = TP_MEDIA_STREAM_STATE_CONNECTED;
- else if (state == PURPLE_MEDIA_STATE_END)
- tp_state = TP_MEDIA_STREAM_STATE_DISCONNECTED;
- else
- {
- DEBUG ("Invalid state %d", state);
- return;
- }
-
- g_object_get (G_OBJECT (priv->media), "backend", &backend, NULL);
- stream = haze_media_backend_get_stream_by_name (backend, sid);
- g_object_unref (backend);
-
- if (stream != NULL)
- {
- guint id;
- g_object_get (stream, "id", &id, NULL);
- tp_svc_channel_type_streamed_media_emit_stream_state_changed (chan,
- id, tp_state);
- }
- }
-
- if (state == PURPLE_MEDIA_STATE_END)
- {
- if (sid != NULL && name == NULL)
- {
- HazeMediaBackend *backend;
- HazeMediaStream *stream;
-
- g_object_get (G_OBJECT (priv->media), "backend", &backend, NULL);
- stream = haze_media_backend_get_stream_by_name (backend, sid);
- g_object_unref (backend);
-
- if (stream != NULL)
- {
- guint id;
- g_object_get (stream, "id", &id, NULL);
- tp_svc_channel_type_streamed_media_emit_stream_removed (
- chan, id);
- }
- }
- else if (sid == NULL && name == NULL)
- {
- TpGroupMixin *mixin = TP_GROUP_MIXIN (chan);
- guint terminator;
- TpHandle peer;
- TpIntset *set;
-
- priv->media_ended = TRUE;
-
- peer = priv->initial_peer;
-
- /*
- * Primarily, sessions will be ended with hangup or reject. Any that
- * aren't are because of local errors so set the terminator to self.
- */
- terminator = mixin->self_handle;
-
- set = tp_intset_new ();
-
- /* remove us and the peer from the member list */
- tp_intset_add (set, mixin->self_handle);
- tp_intset_add (set, peer);
-
- tp_group_mixin_change_members ((GObject *) chan,
- "Media session ended", NULL, set, NULL, NULL,
- terminator, TP_CHANNEL_GROUP_CHANGE_REASON_NONE);
-
- tp_intset_destroy (set);
-
- /* any contents that we were waiting for have now lost */
- g_list_foreach (priv->pending_stream_requests,
- (GFunc) pending_stream_request_free, NULL);
- g_list_free (priv->pending_stream_requests);
- priv->pending_stream_requests = NULL;
-
- if (!priv->closed)
- {
- DEBUG ("calling media channel close from state changed cb");
- haze_media_channel_close (chan);
- }
- }
- }
-}
-
-static void
-media_stream_info_cb(PurpleMedia *media,
- PurpleMediaInfoType type,
- gchar *sid,
- gchar *name,
- gboolean local,
- HazeMediaChannel *chan)
-{
- HazeMediaChannelPrivate *priv = chan->priv;
- TpBaseConnection *conn = (TpBaseConnection *)priv->conn;
-
- if (type == PURPLE_MEDIA_INFO_ACCEPT)
- {
- TpIntset *set;
- TpHandle actor;
-
- if (local == FALSE)
- actor = priv->initial_peer;
- else
- actor = conn->self_handle;
-
- set = tp_intset_new_containing (actor);
-
- /* add the peer to the member list */
- tp_group_mixin_change_members (G_OBJECT (chan), "", set, NULL, NULL,
- NULL, actor, TP_CHANNEL_GROUP_CHANGE_REASON_NONE);
-
- if (sid != NULL && name == NULL && purple_media_is_initiator (
- media, sid, name) == FALSE)
- {
- HazeMediaBackend *backend;
- HazeMediaStream *stream;
-
- g_object_get (G_OBJECT (priv->media), "backend", &backend, NULL);
- stream = haze_media_backend_get_stream_by_name (backend, sid);
- g_object_unref (backend);
-
- g_object_set (stream, "combined-direction",
- MAKE_COMBINED_DIRECTION (
- TP_MEDIA_STREAM_DIRECTION_BIDIRECTIONAL, 0), NULL);
- }
- }
- else if (type == PURPLE_MEDIA_INFO_REJECT ||
- type == PURPLE_MEDIA_INFO_HANGUP)
- {
- TpGroupMixin *mixin = TP_GROUP_MIXIN (chan);
- guint terminator;
- TpIntset *set;
-
- if (sid != NULL)
- return;
-
- if (local == TRUE)
- terminator = conn->self_handle;
- else
- /* This will need to get the handle from name for multi-user calls */
- terminator = priv->initial_peer;
-
- set = tp_intset_new ();
-
- if (name != NULL)
- /* Remove participant */
- tp_intset_add (set, priv->initial_peer);
- else
- /* Remove us */
- tp_intset_add (set, mixin->self_handle);
-
- tp_group_mixin_change_members ((GObject *) chan,
- NULL, NULL, set, NULL, NULL, terminator,
- TP_CHANNEL_GROUP_CHANGE_REASON_NONE);
-
- tp_intset_destroy (set);
- }
-}
-
-static void
-_latch_to_session (HazeMediaChannel *chan)
-{
- HazeMediaChannelPrivate *priv = chan->priv;
- HazeMediaBackend *backend;
- gchar *object_path;
-
- g_assert (priv->media != NULL);
-
- DEBUG ("%p: Latching onto session %p", chan, priv->media);
-
- g_signal_connect(G_OBJECT(priv->media), "error",
- G_CALLBACK(media_error_cb), chan);
- g_signal_connect(G_OBJECT(priv->media), "state-changed",
- G_CALLBACK(media_state_changed_cb), chan);
- g_signal_connect(G_OBJECT(priv->media), "stream-info",
- G_CALLBACK(media_stream_info_cb), chan);
-
- object_path = g_strdup_printf ("%s/MediaSession0", priv->object_path);
-
- g_object_get (G_OBJECT (priv->media), "backend", &backend, NULL);
- g_object_set (G_OBJECT (backend), "object-path", object_path, NULL);
- g_object_unref (backend);
-
- tp_svc_channel_interface_media_signalling_emit_new_session_handler (
- G_OBJECT (chan), object_path, "rtp");
-
- g_free (object_path);
-}
-
-static GObject *
-haze_media_channel_constructor (GType type, guint n_props,
- GObjectConstructParam *props)
-{
- GObject *obj;
- HazeMediaChannelPrivate *priv;
- TpBaseConnection *conn;
- TpDBusDaemon *bus;
- TpIntset *set;
- TpHandleRepoIface *contact_handles;
-
- obj = G_OBJECT_CLASS (haze_media_channel_parent_class)->
- constructor (type, n_props, props);
-
- priv = HAZE_MEDIA_CHANNEL (obj)->priv;
- conn = (TpBaseConnection *) priv->conn;
- contact_handles = tp_base_connection_get_handles (conn,
- TP_HANDLE_TYPE_CONTACT);
-
- /* register object on the bus */
- bus = tp_base_connection_get_dbus_daemon (conn);
- tp_dbus_daemon_register_object (bus, priv->object_path, obj);
-
- tp_group_mixin_init (obj, G_STRUCT_OFFSET (HazeMediaChannel, group),
- contact_handles, conn->self_handle);
-
- if (priv->media != NULL)
- priv->creator = priv->initial_peer;
- else
- priv->creator = conn->self_handle;
-
- /* automatically add creator to channel, but also ref them again (because
- * priv->creator is the InitiatorHandle) */
- g_assert (priv->creator != 0);
-
- set = tp_intset_new_containing (priv->creator);
- tp_group_mixin_change_members (obj, "", set, NULL, NULL, NULL, 0,
- TP_CHANNEL_GROUP_CHANGE_REASON_NONE);
- tp_intset_destroy (set);
-
- /* We implement the 0.17.6 properties correctly, and can include a message
- * when ending a call.
- */
- tp_group_mixin_change_flags (obj,
- TP_CHANNEL_GROUP_FLAG_PROPERTIES |
- TP_CHANNEL_GROUP_FLAG_MESSAGE_REMOVE |
- TP_CHANNEL_GROUP_FLAG_MESSAGE_REJECT |
- TP_CHANNEL_GROUP_FLAG_MESSAGE_RESCIND,
- 0);
-
-
- if (priv->media != NULL)
- {
- /* This is an incoming call; make us local pending and don't set any
- * group flags (all we can do is add or remove ourselves, which is always
- * valid per the spec)
- */
- set = tp_intset_new_containing (conn->self_handle);
- tp_group_mixin_change_members (obj, "", NULL, NULL, set, NULL,
- priv->initial_peer, TP_CHANNEL_GROUP_CHANGE_REASON_INVITED);
- tp_intset_destroy (set);
-
- /* Set up signal callbacks */
- _latch_to_session (HAZE_MEDIA_CHANNEL (obj));
- }
-
- return obj;
-}
-
-static void
-haze_media_channel_get_property (GObject *object,
- guint property_id,
- GValue *value,
- GParamSpec *pspec)
-{
- HazeMediaChannel *chan = HAZE_MEDIA_CHANNEL (object);
- HazeMediaChannelPrivate *priv = chan->priv;
- TpBaseConnection *base_conn = (TpBaseConnection *) priv->conn;
-
- switch (property_id) {
- case PROP_OBJECT_PATH:
- g_value_set_string (value, priv->object_path);
- break;
- case PROP_CHANNEL_TYPE:
- g_value_set_static_string (value, TP_IFACE_CHANNEL_TYPE_STREAMED_MEDIA);
- break;
- case PROP_HANDLE_TYPE:
- /* This is used to implement TargetHandleType, which is immutable. If
- * the peer was known at channel-creation time, this will be Contact;
- * otherwise, it must be None even if we subsequently learn who the peer
- * is.
- */
- if (priv->initial_peer != 0)
- g_value_set_uint (value, TP_HANDLE_TYPE_CONTACT);
- else
- g_value_set_uint (value, TP_HANDLE_TYPE_NONE);
- break;
- case PROP_INITIAL_PEER:
- case PROP_HANDLE:
- /* As above: TargetHandle is immutable, so non-0 only if the peer handle
- * was known at creation time.
- */
- g_value_set_uint (value, priv->initial_peer);
- break;
- case PROP_TARGET_ID:
- /* As above. */
- if (priv->initial_peer != 0)
- {
- TpHandleRepoIface *repo = tp_base_connection_get_handles (
- base_conn, TP_HANDLE_TYPE_CONTACT);
- const gchar *target_id = tp_handle_inspect (repo, priv->initial_peer);
-
- g_value_set_string (value, target_id);
- }
- else
- {
- g_value_set_static_string (value, "");
- }
-
- break;
- case PROP_PEER:
- {
- TpHandle peer = 0;
-
- if (priv->initial_peer != 0)
- peer = priv->initial_peer;
-
- g_value_set_uint (value, peer);
- break;
- }
- case PROP_CONNECTION:
- g_value_set_object (value, priv->conn);
- break;
- case PROP_CREATOR:
- g_value_set_uint (value, priv->creator);
- break;
- case PROP_CREATOR_ID:
- {
- TpHandleRepoIface *repo = tp_base_connection_get_handles (
- base_conn, TP_HANDLE_TYPE_CONTACT);
-
- g_value_set_string (value, tp_handle_inspect (repo, priv->creator));
- }
- break;
- case PROP_REQUESTED:
- g_value_set_boolean (value, (priv->creator == base_conn->self_handle));
- break;
- case PROP_INTERFACES:
- g_value_set_boxed (value, haze_media_channel_interfaces);
- break;
- case PROP_CHANNEL_DESTROYED:
- g_value_set_boolean (value, priv->closed);
- break;
- case PROP_CHANNEL_PROPERTIES:
- g_value_take_boxed (value,
- tp_dbus_properties_mixin_make_properties_hash (object,
- TP_IFACE_CHANNEL, "TargetHandle",
- TP_IFACE_CHANNEL, "TargetHandleType",
- TP_IFACE_CHANNEL, "ChannelType",
- TP_IFACE_CHANNEL, "TargetID",
- TP_IFACE_CHANNEL, "InitiatorHandle",
- TP_IFACE_CHANNEL, "InitiatorID",
- TP_IFACE_CHANNEL, "Requested",
- TP_IFACE_CHANNEL, "Interfaces",
- TP_IFACE_CHANNEL_TYPE_STREAMED_MEDIA, "InitialAudio",
- TP_IFACE_CHANNEL_TYPE_STREAMED_MEDIA, "InitialVideo",
- NULL));
- break;
- case PROP_MEDIA:
- g_value_set_object (value, priv->media);
- break;
- case PROP_INITIAL_AUDIO:
- g_value_set_boolean (value, priv->initial_audio);
- break;
- case PROP_INITIAL_VIDEO:
- g_value_set_boolean (value, priv->initial_video);
- break;
- default:
- G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
- break;
- }
-}
-
-static void
-haze_media_channel_set_property (GObject *object,
- guint property_id,
- const GValue *value,
- GParamSpec *pspec)
-{
- HazeMediaChannel *chan = HAZE_MEDIA_CHANNEL (object);
- HazeMediaChannelPrivate *priv = chan->priv;
-
- switch (property_id) {
- case PROP_OBJECT_PATH:
- g_free (priv->object_path);
- priv->object_path = g_value_dup_string (value);
- break;
- case PROP_HANDLE_TYPE:
- case PROP_HANDLE:
- case PROP_CHANNEL_TYPE:
- /* these properties are writable in the interface, but not actually
- * meaningfully changable on this channel, so we do nothing */
- break;
- case PROP_CONNECTION:
- priv->conn = g_value_get_object (value);
- break;
- case PROP_CREATOR:
- priv->creator = g_value_get_uint (value);
- break;
- case PROP_INITIAL_PEER:
- priv->initial_peer = g_value_get_uint (value);
- break;
- case PROP_MEDIA:
- g_assert (priv->media == NULL);
- priv->media = g_value_dup_object (value);
- break;
- case PROP_INITIAL_AUDIO:
- priv->initial_audio = g_value_get_boolean (value);
- break;
- case PROP_INITIAL_VIDEO:
- priv->initial_video = g_value_get_boolean (value);
- break;
- default:
- G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
- break;
- }
-}
-
-static void haze_media_channel_dispose (GObject *object);
-static void haze_media_channel_finalize (GObject *object);
-
-static void
-haze_media_channel_class_init (HazeMediaChannelClass *haze_media_channel_class)
-{
- static TpDBusPropertiesMixinPropImpl channel_props[] = {
- { "TargetHandleType", "handle-type", NULL },
- { "TargetHandle", "handle", NULL },
- { "TargetID", "target-id", NULL },
- { "ChannelType", "channel-type", NULL },
- { "Interfaces", "interfaces", NULL },
- { "Requested", "requested", NULL },
- { "InitiatorHandle", "creator", NULL },
- { "InitiatorID", "creator-id", NULL },
- { NULL }
- };
- static TpDBusPropertiesMixinPropImpl streamed_media_props[] = {
- { "InitialAudio", "initial-audio", NULL },
- { "InitialVideo", "initial-video", NULL },
- { NULL }
- };
- static TpDBusPropertiesMixinIfaceImpl prop_interfaces[] = {
- { TP_IFACE_CHANNEL,
- tp_dbus_properties_mixin_getter_gobject_properties,
- NULL,
- channel_props,
- },
- { TP_IFACE_CHANNEL_TYPE_STREAMED_MEDIA,
- tp_dbus_properties_mixin_getter_gobject_properties,
- NULL,
- streamed_media_props,
- },
- { NULL }
- };
- GObjectClass *object_class = G_OBJECT_CLASS (haze_media_channel_class);
- GParamSpec *param_spec;
-
- g_type_class_add_private (haze_media_channel_class,
- sizeof (HazeMediaChannelPrivate));
-
- object_class->constructor = haze_media_channel_constructor;
-
- object_class->get_property = haze_media_channel_get_property;
- object_class->set_property = haze_media_channel_set_property;
-
- object_class->dispose = haze_media_channel_dispose;
- object_class->finalize = haze_media_channel_finalize;
-
- g_object_class_override_property (object_class, PROP_OBJECT_PATH,
- "object-path");
- g_object_class_override_property (object_class, PROP_CHANNEL_TYPE,
- "channel-type");
- g_object_class_override_property (object_class, PROP_HANDLE_TYPE,
- "handle-type");
- g_object_class_override_property (object_class, PROP_HANDLE, "handle");
-
- g_object_class_override_property (object_class, PROP_CHANNEL_DESTROYED,
- "channel-destroyed");
- g_object_class_override_property (object_class, PROP_CHANNEL_PROPERTIES,
- "channel-properties");
-
- param_spec = g_param_spec_string ("target-id", "Target ID",
- "The string that would result from inspecting TargetHandle",
- NULL,
- G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
- g_object_class_install_property (object_class, PROP_TARGET_ID, param_spec);
-
- param_spec = g_param_spec_uint ("initial-peer", "Other participant",
- "The TpHandle representing the other participant in the channel if known "
- "at construct-time; 0 if the other participant was unknown at the time "
- "of channel creation",
- 0, G_MAXUINT32, 0,
- G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
- g_object_class_install_property (object_class, PROP_INITIAL_PEER, param_spec);
-
- param_spec = g_param_spec_uint ("peer", "Other participant",
- "The TpHandle representing the other participant in the channel if "
- "currently known; 0 if this is an anonymous channel on which "
- "RequestStreams has not yet been called.",
- 0, G_MAXUINT32, 0,
- G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
- g_object_class_install_property (object_class, PROP_PEER, param_spec);
-
- param_spec = g_param_spec_object ("connection", "HazeConnection object",
- "Haze connection object that owns this media channel object.",
- HAZE_TYPE_CONNECTION,
- G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
- g_object_class_install_property (object_class, PROP_CONNECTION, param_spec);
-
- param_spec = g_param_spec_uint ("creator", "Channel creator",
- "The TpHandle representing the contact who created the channel.",
- 0, G_MAXUINT32, 0,
- G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
- g_object_class_install_property (object_class, PROP_CREATOR, param_spec);
-
- param_spec = g_param_spec_string ("creator-id", "Creator ID",
- "The ID obtained by inspecting the creator handle.",
- NULL,
- G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
- g_object_class_install_property (object_class, PROP_CREATOR_ID, param_spec);
-
- param_spec = g_param_spec_boolean ("requested", "Requested?",
- "True if this channel was requested by the local user",
- FALSE,
- G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
- g_object_class_install_property (object_class, PROP_REQUESTED, param_spec);
-
- param_spec = g_param_spec_boxed ("interfaces", "Extra D-Bus interfaces",
- "Additional Channel.Interface.* interfaces",
- G_TYPE_STRV,
- G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
- g_object_class_install_property (object_class, PROP_INTERFACES, param_spec);
-
- param_spec = g_param_spec_object ("media", "PurpleMedia object",
- "Purple media associated with this media channel object.",
- PURPLE_TYPE_MEDIA,
- G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE |
- G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB);
- g_object_class_install_property (object_class, PROP_MEDIA, param_spec);
-
- param_spec = g_param_spec_boolean ("initial-audio", "InitialAudio",
- "Whether the channel initially contained an audio stream",
- FALSE,
- G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
- g_object_class_install_property (object_class, PROP_INITIAL_AUDIO,
- param_spec);
-
- param_spec = g_param_spec_boolean ("initial-video", "InitialVideo",
- "Whether the channel initially contained an video stream",
- FALSE,
- G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
- g_object_class_install_property (object_class, PROP_INITIAL_VIDEO,
- param_spec);
-
- haze_media_channel_class->dbus_props_class.interfaces = prop_interfaces;
- tp_dbus_properties_mixin_class_init (object_class,
- G_STRUCT_OFFSET (HazeMediaChannelClass, dbus_props_class));
-
- tp_group_mixin_class_init (object_class,
- G_STRUCT_OFFSET (HazeMediaChannelClass, group_class),
- haze_media_channel_add_member, NULL);
- tp_group_mixin_class_set_remove_with_reason_func (object_class,
- haze_media_channel_remove_member);
- tp_group_mixin_class_allow_self_removal (object_class);
-
- tp_group_mixin_init_dbus_properties (object_class);
-}
-
-void
-haze_media_channel_dispose (GObject *object)
-{
- HazeMediaChannel *self = HAZE_MEDIA_CHANNEL (object);
- HazeMediaChannelPrivate *priv = self->priv;
-
- if (priv->dispose_has_run)
- return;
-
- DEBUG ("called");
-
- priv->dispose_has_run = TRUE;
-
- if (!priv->closed)
- haze_media_channel_close (self);
-
- g_assert (priv->closed);
-
- if (priv->media != NULL)
- g_object_unref (priv->media);
- priv->media = NULL;
-
- if (G_OBJECT_CLASS (haze_media_channel_parent_class)->dispose)
- G_OBJECT_CLASS (haze_media_channel_parent_class)->dispose (object);
-}
-
-void
-haze_media_channel_finalize (GObject *object)
-{
- HazeMediaChannel *self = HAZE_MEDIA_CHANNEL (object);
- HazeMediaChannelPrivate *priv = self->priv;
-
- g_free (priv->object_path);
-
- tp_group_mixin_finalize (object);
-
- G_OBJECT_CLASS (haze_media_channel_parent_class)->finalize (object);
-}
-
-
-/**
- * haze_media_channel_close_async:
- *
- * Implements D-Bus method Close
- * on interface org.freedesktop.Telepathy.Channel
- */
-static void
-haze_media_channel_close_async (TpSvcChannel *iface,
- DBusGMethodInvocation *context)
-{
- HazeMediaChannel *self = HAZE_MEDIA_CHANNEL (iface);
-
- DEBUG ("called");
- haze_media_channel_close (self);
- tp_svc_channel_return_from_close (context);
-}
-
-void
-haze_media_channel_close (HazeMediaChannel *self)
-{
- HazeMediaChannelPrivate *priv = self->priv;
-
- DEBUG ("called on %p", self);
-
- if (!priv->closed)
- {
- priv->closed = TRUE;
-
- if (priv->media && !priv->media_ended)
- {
- priv->media_ended = TRUE;
- purple_media_stream_info (priv->media,
- PURPLE_MEDIA_INFO_HANGUP, NULL, NULL, FALSE);
- }
-
- tp_svc_channel_emit_closed (self);
- }
-}
-
-
-/**
- * haze_media_channel_get_channel_type
- *
- * Implements D-Bus method GetChannelType
- * on interface org.freedesktop.Telepathy.Channel
- */
-static void
-haze_media_channel_get_channel_type (TpSvcChannel *iface,
- DBusGMethodInvocation *context)
-{
- tp_svc_channel_return_from_get_channel_type (context,
- TP_IFACE_CHANNEL_TYPE_STREAMED_MEDIA);
-}
-
-
-/**
- * haze_media_channel_get_handle
- *
- * Implements D-Bus method GetHandle
- * on interface org.freedesktop.Telepathy.Channel
- */
-static void
-haze_media_channel_get_handle (TpSvcChannel *iface,
- DBusGMethodInvocation *context)
-{
- HazeMediaChannel *self = HAZE_MEDIA_CHANNEL (iface);
-
- if (self->priv->initial_peer == 0)
- tp_svc_channel_return_from_get_handle (context, TP_HANDLE_TYPE_NONE, 0);
- else
- tp_svc_channel_return_from_get_handle (context, TP_HANDLE_TYPE_CONTACT,
- self->priv->initial_peer);
-}
-
-
-/**
- * haze_media_channel_get_interfaces
- *
- * Implements D-Bus method GetInterfaces
- * on interface org.freedesktop.Telepathy.Channel
- */
-static void
-haze_media_channel_get_interfaces (TpSvcChannel *iface,
- DBusGMethodInvocation *context)
-{
- tp_svc_channel_return_from_get_interfaces (context,
- haze_media_channel_interfaces);
-}
-
-/**
- * haze_media_channel_list_streams
- *
- * Implements D-Bus method ListStreams
- * on interface org.freedesktop.Telepathy.Channel.Type.StreamedMedia
- */
-static void
-haze_media_channel_list_streams (TpSvcChannelTypeStreamedMedia *iface,
- DBusGMethodInvocation *context)
-{
- HazeMediaChannel *self = HAZE_MEDIA_CHANNEL (iface);
- HazeMediaChannelPrivate *priv;
- GPtrArray *ret;
-
- g_assert (HAZE_IS_MEDIA_CHANNEL (self));
-
- priv = self->priv;
-
- /* If the session has not yet started, return an empty array. */
- if (priv->media == NULL)
- {
- ret = g_ptr_array_new ();
- }
- else
- {
- HazeMediaBackend *backend;
- GPtrArray *streams;
-
- g_object_get (G_OBJECT (priv->media), "backend", &backend, NULL);
- g_object_get (G_OBJECT (backend), "streams", &streams, NULL);
-
- ret = make_stream_list (self, streams->len,
- (HazeMediaStream **) streams->pdata);
-
- g_ptr_array_unref (streams);
- g_object_unref (backend);
- }
-
- tp_svc_channel_type_streamed_media_return_from_list_streams (context, ret);
- g_ptr_array_foreach (ret, (GFunc) g_value_array_free, NULL);
- g_ptr_array_free (ret, TRUE);
-}
-
-/**
- * haze_media_channel_remove_streams
- *
- * Implements DBus method RemoveStreams
- * on interface org.freedesktop.Telepathy.Channel.Type.StreamedMedia
- */
-static void
-haze_media_channel_remove_streams (TpSvcChannelTypeStreamedMedia *iface,
- const GArray * streams,
- DBusGMethodInvocation *context)
-{
- HazeMediaChannel *obj = HAZE_MEDIA_CHANNEL (iface);
- HazeMediaChannelPrivate *priv;
- HazeMediaBackend *backend;
- GPtrArray *backend_streams;
- guint i, j;
- GPtrArray *media_ids;
- const gchar *target_id;
-
- g_assert (HAZE_IS_MEDIA_CHANNEL (obj));
-
- priv = obj->priv;
-
- g_object_get (obj, "target-id", &target_id, NULL);
-
- if ((purple_prpl_get_media_caps (priv->conn->account, target_id) &
- PURPLE_MEDIA_CAPS_MODIFY_SESSION) == 0)
- {
- TpBaseConnection *base_conn = TP_BASE_CONNECTION (priv->conn);
- gchar *name;
- GError *e;
-
- g_object_get (base_conn, "protocol", &name, NULL);
- g_set_error (&e, TP_ERROR, TP_ERROR_NOT_IMPLEMENTED,
- "Streams can't be removed in Haze's \"%s\" protocol's calls", name);
- g_free (name);
-
- DEBUG ("%s", e->message);
- dbus_g_method_return_error (context, e);
-
- g_error_free(e);
- return;
- }
-
- media_ids = g_ptr_array_new ();
-
- g_object_get (G_OBJECT (priv->media), "backend", &backend, NULL);
- g_object_get (G_OBJECT (backend), "streams", &backend_streams, NULL);
- g_object_unref (backend);
-
- for (i = 0; i < streams->len; ++i)
- {
- guint id = g_array_index (streams, guint, i);
-
- for (j = 0; j < backend_streams->len; j++)
- {
- HazeMediaStream *stream = g_ptr_array_index (backend_streams, j);
- guint stream_id;
-
- g_object_get (G_OBJECT (stream), "id", &stream_id, NULL);
-
- if (id == stream_id)
- {
- g_ptr_array_add (media_ids, stream->name);
- break;
- }
- }
-
- if (j >= backend_streams->len)
- {
- GError e = { TP_ERROR, TP_ERROR_INVALID_ARGUMENT,
- "Requested stream wasn't found" };
- DEBUG ("%s", e.message);
- dbus_g_method_return_error (context, &e);
- g_ptr_array_free (media_ids, TRUE);
- return;
- }
- }
-
- for (i = 0; i < media_ids->len; ++i)
- {
- gchar *id = g_ptr_array_index (media_ids, i);
- for (j = i + 1; j < media_ids->len; ++j)
- {
- if (id == g_ptr_array_index (media_ids, j))
- {
- g_ptr_array_remove_index (media_ids, j);
- --j;
- }
- }
- }
-
- for (i = 0; i < media_ids->len; ++i)
- {
- purple_media_end (priv->media, g_ptr_array_index (media_ids, i), NULL);
- }
-
- g_ptr_array_unref (backend_streams);
- g_ptr_array_free (media_ids, TRUE);
- tp_svc_channel_type_streamed_media_return_from_remove_streams (context);
-}
-
-/**
- * haze_media_channel_request_stream_direction
- *
- * Implements D-Bus method RequestStreamDirection
- * on interface org.freedesktop.Telepathy.Channel.Type.StreamedMedia
- */
-static void
-haze_media_channel_request_stream_direction (TpSvcChannelTypeStreamedMedia *iface,
- guint stream_id,
- guint stream_direction,
- DBusGMethodInvocation *context)
-{
- /* Libpurple doesn't have API for this yet */
- GError e = { TP_ERROR, TP_ERROR_NOT_IMPLEMENTED,
- "Stream direction can't be set Haze calls" };
- DEBUG ("%s", e.message);
- dbus_g_method_return_error (context, &e);
-}
-
-
-static gboolean
-init_media_cb (PurpleMediaManager *manager,
- PurpleMedia *media,
- PurpleAccount *account,
- const gchar *username,
- HazeMediaChannel *self)
-{
- HazeMediaChannelPrivate *priv = self->priv;
- TpBaseConnection *base_conn = TP_BASE_CONNECTION (priv->conn);
- TpHandleRepoIface *contact_repo =
- tp_base_connection_get_handles (base_conn, TP_HANDLE_TYPE_CONTACT);
- TpHandle contact = tp_handle_ensure (contact_repo, username, NULL, NULL);
-
- if (priv->conn->account != account || priv->initial_peer != contact)
- return TRUE;
-
- g_assert (priv->media == NULL);
- priv->media = g_object_ref (media);
- if (priv->media != NULL)
- {
- _latch_to_session (self);
- }
-
- g_signal_handlers_disconnect_by_func (manager, init_media_cb, self);
-
- return TRUE;
-}
-
-static gboolean
-_haze_media_channel_request_contents (HazeMediaChannel *chan,
- TpHandle peer,
- const GArray *media_types,
- GError **error)
-{
- HazeMediaChannelPrivate *priv = chan->priv;
- gboolean want_audio, want_video;
- guint idx;
- TpHandleRepoIface *contact_handles;
- const gchar *contact_id;
- guint audio_count = 0, video_count = 0;
-
- DEBUG ("called");
-
- want_audio = want_video = FALSE;
-
- for (idx = 0; idx < media_types->len; idx++)
- {
- guint media_type = g_array_index (media_types, guint, idx);
-
- if (media_type == TP_MEDIA_STREAM_TYPE_AUDIO)
- {
- want_audio = TRUE;
- }
- else if (media_type == TP_MEDIA_STREAM_TYPE_VIDEO)
- {
- want_video = TRUE;
- }
- else
- {
- g_set_error (error, TP_ERROR, TP_ERROR_NOT_IMPLEMENTED,
- "given media type %u is invalid", media_type);
- return FALSE;
- }
- }
-
- /* existing call; the recipient and the mode has already been decided */
- if (priv->media != NULL)
- {
- PurpleMediaCaps caps;
- const gchar *target_id;
- g_object_get (chan, "target-id", &target_id, NULL);
- caps = purple_prpl_get_media_caps (priv->conn->account, target_id);
-
- /* Check if the contact supports modifying the session */
- if ((caps & PURPLE_MEDIA_CAPS_MODIFY_SESSION) == 0)
- {
- TpBaseConnection *base_conn = TP_BASE_CONNECTION (priv->conn);
- gchar *name;
-
- g_object_get (base_conn, "protocol", &name, NULL);
- g_set_error (error, TP_ERROR, TP_ERROR_NOT_AVAILABLE,
- "Streams can't be added in Haze's \"%s\" protocol's calls",
- name);
-
- g_free (name);
- return FALSE;
- }
-
- /* Check if contact supports the desired media type */
- if ((want_audio == FALSE || caps & PURPLE_MEDIA_CAPS_AUDIO) &&
- (want_video == FALSE || caps & PURPLE_MEDIA_CAPS_VIDEO))
- {
- g_set_error (error, TP_ERROR, TP_ERROR_NOT_AVAILABLE,
- "Member does not have the desired audio/video capabilities");
- return FALSE;
- }
- }
-
- /* if we've got here, we're good to make the streams */
-
- contact_handles = tp_base_connection_get_handles (
- TP_BASE_CONNECTION (priv->conn), TP_HANDLE_TYPE_CONTACT);
- contact_id = tp_handle_inspect (contact_handles, peer);
-
- /* Be ready to retrieve the newly created media object */
- if (priv->media == NULL)
- g_signal_connect (purple_media_manager_get (), "init-media",
- G_CALLBACK (init_media_cb), chan);
-
- for (idx = 0; idx < media_types->len; idx++)
- {
- guint media_type = g_array_index (media_types, guint, idx);
-
- if (media_type == TP_MEDIA_STREAM_TYPE_AUDIO)
- ++audio_count;
- else if (media_type == TP_MEDIA_STREAM_TYPE_VIDEO)
- ++video_count;
- }
-
- while (audio_count > 0 || video_count > 0)
- {
- PurpleMediaSessionType type = PURPLE_MEDIA_NONE;
-
- if (audio_count > 0)
- {
- type |= PURPLE_MEDIA_AUDIO;
- --audio_count;
- }
-
- if (video_count > 0)
- {
- type |= PURPLE_MEDIA_VIDEO;
- --video_count;
- }
-
- if (purple_prpl_initiate_media (priv->conn->account,
- contact_id, type) == FALSE)
- return FALSE;
- }
-
- return TRUE;
-}
-
-static void
-media_channel_request_streams (HazeMediaChannel *self,
- TpHandle contact_handle,
- const GArray *types,
- GFunc succeeded_cb,
- GFunc failed_cb,
- gpointer context)
-{
- HazeMediaChannelPrivate *priv = self->priv;
- PendingStreamRequest *psr = NULL;
- GError *error = NULL;
-
- if (types->len == 0)
- {
- GPtrArray *empty = g_ptr_array_sized_new (0);
-
- DEBUG ("no streams to request");
- succeeded_cb (context, empty);
- g_ptr_array_free (empty, TRUE);
-
- return;
- }
-
- if (priv->media != NULL)
- {
- TpHandle peer;
-
- peer = priv->initial_peer;
-
- if (peer != contact_handle)
- {
- g_set_error (&error, TP_ERROR, TP_ERROR_NOT_AVAILABLE,
- "cannot add streams for %u: this channel's peer is %u",
- contact_handle, peer);
- goto error;
- }
- }
-
- /*
- * Pending stream requests can be completed before request_contents returns.
- * Add the pending stream request up here so it isn't missed.
- */
- psr = pending_stream_request_new (types, succeeded_cb, failed_cb,
- context);
- priv->pending_stream_requests = g_list_prepend (priv->pending_stream_requests,
- psr);
-
- if (!_haze_media_channel_request_contents (self, contact_handle,
- types, &error))
- goto error;
-
- return;
-
-error:
- if (psr != NULL)
- {
- priv->pending_stream_requests = g_list_remove (
- priv->pending_stream_requests, psr);
- pending_stream_request_free (psr);
- }
-
- DEBUG ("returning error %u: %s", error->code, error->message);
- failed_cb (context, error);
- g_error_free (error);
-}
-
-/**
- * haze_media_channel_request_streams
- *
- * Implements D-Bus method RequestStreams
- * on interface org.freedesktop.Telepathy.Channel.Type.StreamedMedia
- */
-static void
-haze_media_channel_request_streams (TpSvcChannelTypeStreamedMedia *iface,
- guint contact_handle,
- const GArray *types,
- DBusGMethodInvocation *context)
-{
- HazeMediaChannel *self = HAZE_MEDIA_CHANNEL (iface);
- TpBaseConnection *base_conn = (TpBaseConnection *) self->priv->conn;
- TpHandleRepoIface *contact_handles = tp_base_connection_get_handles (
- base_conn, TP_HANDLE_TYPE_CONTACT);
- GError *error = NULL;
-
- if (!tp_handle_is_valid (contact_handles, contact_handle, &error))
- {
- DEBUG ("that's not a handle, sonny! (%u)", contact_handle);
- dbus_g_method_return_error (context, error);
- g_error_free (error);
- return;
- }
- else
- {
- /* FIXME: disallow this if we've put the peer on hold? */
-
- media_channel_request_streams (self, contact_handle, types,
- (GFunc) tp_svc_channel_type_streamed_media_return_from_request_streams,
- (GFunc) dbus_g_method_return_error,
- context);
- }
-}
-
-/**
- * haze_media_channel_request_initial_streams:
- * @chan: an outgoing call, which must have just been constructed.
- * @succeeded_cb: called with arguments @user_data and a GPtrArray of
- * TP_STRUCT_TYPE_MEDIA_STREAM_INFO if the request succeeds.
- * @failed_cb: called with arguments @user_data and a GError * if the request
- * fails.
- * @user_data: context for the callbacks.
- *
- * Request streams corresponding to the values of InitialAudio and InitialVideo
- * in the channel request.
- */
-void
-haze_media_channel_request_initial_streams (HazeMediaChannel *chan,
- GFunc succeeded_cb,
- GFunc failed_cb,
- gpointer user_data)
-{
- HazeMediaChannelPrivate *priv = chan->priv;
- GArray *types = g_array_sized_new (FALSE, FALSE, sizeof (guint), 2);
- guint media_type;
-
- /* This has to be an outgoing call... */
- g_assert (priv->creator == priv->conn->parent.self_handle);
-
- if (priv->initial_audio)
- {
- media_type = TP_MEDIA_STREAM_TYPE_AUDIO;
- g_array_append_val (types, media_type);
- }
-
- if (priv->initial_video)
- {
- media_type = TP_MEDIA_STREAM_TYPE_VIDEO;
- g_array_append_val (types, media_type);
- }
-
- media_channel_request_streams (chan, priv->initial_peer, types,
- succeeded_cb, failed_cb, user_data);
-
- g_array_free (types, TRUE);
-}
-
-static gboolean
-haze_media_channel_add_member (GObject *obj,
- TpHandle handle,
- const gchar *message,
- GError **error)
-{
- HazeMediaChannel *chan = HAZE_MEDIA_CHANNEL (obj);
- HazeMediaChannelPrivate *priv = chan->priv;
- TpGroupMixin *mixin = TP_GROUP_MIXIN (obj);
- TpIntset *set;
-
- /* did we create this channel? */
- if (priv->creator == mixin->self_handle)
- {
- /* yes: check we don't have a peer already, and if not add this one to
- * remote pending (but don't send an invitation yet).
- */
- if (priv->media != NULL)
- {
- TpHandle peer;
-
- peer = priv->initial_peer;
-
- if (peer != handle)
- {
- g_set_error (error, TP_ERROR, TP_ERROR_NOT_AVAILABLE,
- "handle %u cannot be added: this channel's peer is %u",
- handle, peer);
- return FALSE;
- }
- }
-
- /* make the peer remote pending */
- set = tp_intset_new_containing (handle);
- tp_group_mixin_change_members (obj, "", NULL, NULL, NULL, set,
- mixin->self_handle, TP_CHANNEL_GROUP_CHANGE_REASON_INVITED);
- tp_intset_destroy (set);
-
- /* and remove CanAdd, since it was only here to allow this deprecated
- * API. */
- tp_group_mixin_change_flags (obj, 0, TP_CHANNEL_GROUP_FLAG_CAN_ADD);
-
- return TRUE;
- }
- else
- {
- /* no: has a session been created, is the handle being added ours,
- * and are we in local pending? (call answer) */
- if (priv->media &&
- handle == mixin->self_handle &&
- tp_handle_set_is_member (mixin->local_pending, handle))
- {
- /* is the call on hold? */
- if (priv->hold_state != TP_LOCAL_HOLD_STATE_UNHELD)
- {
- g_set_error (error, TP_ERROR, TP_ERROR_NOT_AVAILABLE,
- "Can't answer a call while it's on hold");
- return FALSE;
- }
-
- /* make us a member */
- set = tp_intset_new_containing (handle);
- tp_group_mixin_change_members (obj, "", set, NULL, NULL, NULL,
- handle, TP_CHANNEL_GROUP_CHANGE_REASON_NONE);
- tp_intset_destroy (set);
-
- /* signal acceptance */
- purple_media_stream_info(priv->media,
- PURPLE_MEDIA_INFO_ACCEPT, NULL, NULL, TRUE);
-
- return TRUE;
- }
- }
-
- g_set_error (error, TP_ERROR, TP_ERROR_NOT_AVAILABLE,
- "handle %u cannot be added in the current state", handle);
- return FALSE;
-}
-
-static gboolean
-haze_media_channel_remove_member (GObject *obj,
- TpHandle handle,
- const gchar *message,
- guint reason,
- GError **error)
-{
- HazeMediaChannel *chan = HAZE_MEDIA_CHANNEL (obj);
- HazeMediaChannelPrivate *priv = chan->priv;
- TpGroupMixin *mixin = TP_GROUP_MIXIN (obj);
-
- /* We don't set CanRemove, and did allow self removal. So tp-glib should
- * ensure this.
- */
- g_assert (handle == mixin->self_handle);
-
- /* Closing up might make HazeMediaManager release its ref. */
- g_object_ref (chan);
-
- if (priv->media == NULL)
- {
- haze_media_channel_close (chan);
- }
- else
- {
- switch (reason)
- {
- /* Should one of these trigger reject? */
- case TP_CHANNEL_GROUP_CHANGE_REASON_NONE:
- case TP_CHANNEL_GROUP_CHANGE_REASON_OFFLINE:
- case TP_CHANNEL_GROUP_CHANGE_REASON_BUSY:
- case TP_CHANNEL_GROUP_CHANGE_REASON_ERROR:
- case TP_CHANNEL_GROUP_CHANGE_REASON_NO_ANSWER:
- purple_media_stream_info(priv->media,
- PURPLE_MEDIA_INFO_HANGUP, NULL, NULL, TRUE);
- break;
- default:
- /* The remaining options don't make sense */
- g_object_unref (chan);
- return FALSE;
- }
- }
-
- /* Remove CanAdd if it was there for the deprecated anonymous channel
- * semantics, since the channel will go away RSN. */
- tp_group_mixin_change_flags (obj, 0, TP_CHANNEL_GROUP_FLAG_CAN_ADD);
-
- g_object_unref (chan);
-
- return TRUE;
-}
-
-/**
- * haze_media_channel_get_session_handlers
- *
- * Implements D-Bus method GetSessionHandlers
- * on interface org.freedesktop.Telepathy.Channel.Interface.MediaSignalling
- */
-static void
-haze_media_channel_get_session_handlers (
- TpSvcChannelInterfaceMediaSignalling *iface,
- DBusGMethodInvocation *context)
-{
- HazeMediaChannel *self = HAZE_MEDIA_CHANNEL (iface);
- HazeMediaChannelPrivate *priv;
- GPtrArray *ret;
- GType info_type = TP_STRUCT_TYPE_MEDIA_SESSION_HANDLER_INFO;
-
- g_assert (HAZE_IS_MEDIA_CHANNEL (self));
-
- priv = self->priv;
-
- if (priv->media)
- {
- GValue handler = { 0, };
- HazeMediaBackend *backend;
- gchar *object_path;
-
- g_object_get (G_OBJECT (priv->media), "backend", &backend, NULL);
- g_object_get (G_OBJECT (backend), "object-path", &object_path, NULL);
- g_object_unref (backend);
-
- g_value_init (&handler, info_type);
- g_value_take_boxed (&handler,
- dbus_g_type_specialized_construct (info_type));
-
- dbus_g_type_struct_set (&handler,
- 0, object_path,
- 1, "rtp",
- G_MAXUINT);
-
- g_free (object_path);
-
- ret = g_ptr_array_sized_new (1);
- g_ptr_array_add (ret, g_value_get_boxed (&handler));
- }
- else
- {
- ret = g_ptr_array_sized_new (0);
- }
-
- tp_svc_channel_interface_media_signalling_return_from_get_session_handlers (
- context, ret);
- g_ptr_array_foreach (ret, (GFunc) g_value_array_free, NULL);
- g_ptr_array_free (ret, TRUE);
-}
-
-static void
-channel_iface_init (gpointer g_iface, gpointer iface_data)
-{
- TpSvcChannelClass *klass = (TpSvcChannelClass *) g_iface;
-
-#define IMPLEMENT(x, suffix) tp_svc_channel_implement_##x (\
- klass, haze_media_channel_##x##suffix)
- IMPLEMENT(close,_async);
- IMPLEMENT(get_channel_type,);
- IMPLEMENT(get_handle,);
- IMPLEMENT(get_interfaces,);
-#undef IMPLEMENT
-}
-
-static void
-streamed_media_iface_init (gpointer g_iface, gpointer iface_data)
-{
- TpSvcChannelTypeStreamedMediaClass *klass =
- (TpSvcChannelTypeStreamedMediaClass *) g_iface;
-
-#define IMPLEMENT(x) tp_svc_channel_type_streamed_media_implement_##x (\
- klass, haze_media_channel_##x)
- IMPLEMENT(list_streams);
- IMPLEMENT(remove_streams);
- IMPLEMENT(request_stream_direction);
- IMPLEMENT(request_streams);
-#undef IMPLEMENT
-}
-
-static void
-media_signalling_iface_init (gpointer g_iface, gpointer iface_data)
-{
- TpSvcChannelInterfaceMediaSignallingClass *klass =
- (TpSvcChannelInterfaceMediaSignallingClass *) g_iface;
-
-#define IMPLEMENT(x) tp_svc_channel_interface_media_signalling_implement_##x (\
- klass, haze_media_channel_##x)
- IMPLEMENT(get_session_handlers);
-#undef IMPLEMENT
-}
diff --git a/src/media-channel.h b/src/media-channel.h
deleted file mode 100644
index 60081d1..0000000
--- a/src/media-channel.h
+++ /dev/null
@@ -1,80 +0,0 @@
-/*
- * media-channel.h - Header for HazeMediaChannel
- * Copyright (C) 2006, 2009 Collabora Ltd.
- * Copyright (C) 2006 Nokia Corporation
- *
- * Copied heavily from telepathy-gabble
- *
- * 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 __HAZE_MEDIA_CHANNEL_H__
-#define __HAZE_MEDIA_CHANNEL_H__
-
-#include <glib-object.h>
-
-#include <telepathy-glib/dbus-properties-mixin.h>
-#include <telepathy-glib/group-mixin.h>
-
-G_BEGIN_DECLS
-
-typedef struct _HazeMediaChannel HazeMediaChannel;
-typedef struct _HazeMediaChannelPrivate HazeMediaChannelPrivate;
-typedef struct _HazeMediaChannelClass HazeMediaChannelClass;
-
-struct _HazeMediaChannelClass {
- GObjectClass parent_class;
-
- TpGroupMixinClass group_class;
- TpDBusPropertiesMixinClass dbus_props_class;
-};
-
-struct _HazeMediaChannel {
- GObject parent;
-
- TpGroupMixin group;
-
- HazeMediaChannelPrivate *priv;
-};
-
-GType haze_media_channel_get_type (void);
-
-/* TYPE MACROS */
-#define HAZE_TYPE_MEDIA_CHANNEL \
- (haze_media_channel_get_type ())
-#define HAZE_MEDIA_CHANNEL(obj) \
- (G_TYPE_CHECK_INSTANCE_CAST((obj), HAZE_TYPE_MEDIA_CHANNEL,\
- HazeMediaChannel))
-#define HAZE_MEDIA_CHANNEL_CLASS(klass) \
- (G_TYPE_CHECK_CLASS_CAST((klass), HAZE_TYPE_MEDIA_CHANNEL,\
- HazeMediaChannelClass))
-#define HAZE_IS_MEDIA_CHANNEL(obj) \
- (G_TYPE_CHECK_INSTANCE_TYPE((obj), HAZE_TYPE_MEDIA_CHANNEL))
-#define HAZE_IS_MEDIA_CHANNEL_CLASS(klass) \
- (G_TYPE_CHECK_CLASS_TYPE((klass), HAZE_TYPE_MEDIA_CHANNEL))
-#define HAZE_MEDIA_CHANNEL_GET_CLASS(obj) \
- (G_TYPE_INSTANCE_GET_CLASS ((obj), HAZE_TYPE_MEDIA_CHANNEL, \
- HazeMediaChannelClass))
-
-void haze_media_channel_request_initial_streams (HazeMediaChannel *chan,
- GFunc succeeded_cb,
- GFunc failed_cb,
- gpointer user_data);
-
-void haze_media_channel_close (HazeMediaChannel *self);
-
-G_END_DECLS
-
-#endif /* #ifndef __HAZE_MEDIA_CHANNEL_H__*/
diff --git a/src/media-manager.c b/src/media-manager.c
deleted file mode 100644
index 3df771c..0000000
--- a/src/media-manager.c
+++ /dev/null
@@ -1,579 +0,0 @@
-/*
- * media-manager.c - Source for HazeMediaManager
- * Copyright (C) 2006, 2009 Collabora Ltd.
- *
- * Copied heavily from telepathy-gabble
- *
- * 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 "config.h"
-#include "media-manager.h"
-
-#include <libpurple/mediamanager.h>
-#include <telepathy-glib/channel-manager.h>
-#include <telepathy-glib/dbus.h>
-#include <telepathy-glib/gtypes.h>
-#include <telepathy-glib/interfaces.h>
-
-#include "connection.h"
-#include "debug.h"
-#include "media-channel.h"
-
-static void channel_manager_iface_init (gpointer, gpointer);
-static void haze_media_manager_close_all (HazeMediaManager *self);
-static void haze_media_manager_constructed (GObject *object);
-
-G_DEFINE_TYPE_WITH_CODE (HazeMediaManager, haze_media_manager,
- G_TYPE_OBJECT,
- G_IMPLEMENT_INTERFACE (TP_TYPE_CHANNEL_MANAGER,
- channel_manager_iface_init));
-
-/* properties */
-enum
-{
- PROP_CONNECTION = 1,
- LAST_PROPERTY
-};
-
-struct _HazeMediaManagerPrivate
-{
- HazeConnection *conn;
- gulong status_changed_id;
-
- GPtrArray *channels;
- guint channel_index;
-
- gboolean dispose_has_run;
-};
-
-static void
-haze_media_manager_init (HazeMediaManager *self)
-{
- HazeMediaManagerPrivate *priv = G_TYPE_INSTANCE_GET_PRIVATE (self,
- HAZE_TYPE_MEDIA_MANAGER, HazeMediaManagerPrivate);
-
- self->priv = priv;
-
- priv->channels = g_ptr_array_sized_new (1);
- priv->channel_index = 0;
-
- priv->conn = NULL;
- priv->dispose_has_run = FALSE;
-}
-
-static void
-haze_media_manager_dispose (GObject *object)
-{
- HazeMediaManager *self = HAZE_MEDIA_MANAGER (object);
- HazeMediaManagerPrivate *priv = self->priv;
-
- if (priv->dispose_has_run)
- return;
-
- DEBUG ("dispose called");
- priv->dispose_has_run = TRUE;
-
- haze_media_manager_close_all (self);
- g_assert (priv->channels->len == 0);
- g_ptr_array_free (priv->channels, TRUE);
-
- if (G_OBJECT_CLASS (haze_media_manager_parent_class)->dispose)
- G_OBJECT_CLASS (haze_media_manager_parent_class)->dispose (object);
-}
-
-static void
-haze_media_manager_get_property (GObject *object,
- guint property_id,
- GValue *value,
- GParamSpec *pspec)
-{
- HazeMediaManager *self = HAZE_MEDIA_MANAGER (object);
- HazeMediaManagerPrivate *priv = self->priv;
-
- switch (property_id) {
- case PROP_CONNECTION:
- g_value_set_object (value, priv->conn);
- break;
- default:
- G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
- break;
- }
-}
-
-static void
-haze_media_manager_set_property (GObject *object,
- guint property_id,
- const GValue *value,
- GParamSpec *pspec)
-{
- HazeMediaManager *self = HAZE_MEDIA_MANAGER (object);
- HazeMediaManagerPrivate *priv = self->priv;
-
- switch (property_id) {
- case PROP_CONNECTION:
- priv->conn = g_value_get_object (value);
- break;
- default:
- G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
- break;
- }
-}
-
-static void
-haze_media_manager_class_init (HazeMediaManagerClass *haze_media_manager_class)
-{
- GObjectClass *object_class = G_OBJECT_CLASS (haze_media_manager_class);
- GParamSpec *param_spec;
-
- g_type_class_add_private (haze_media_manager_class,
- sizeof (HazeMediaManagerPrivate));
-
- object_class->constructed = haze_media_manager_constructed;
- object_class->dispose = haze_media_manager_dispose;
-
- object_class->get_property = haze_media_manager_get_property;
- object_class->set_property = haze_media_manager_set_property;
-
- param_spec = g_param_spec_object ("connection", "HazeConnection object",
- "Haze connection object that owns this media channel manager object.",
- HAZE_TYPE_CONNECTION,
- G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
- g_object_class_install_property (object_class, PROP_CONNECTION, param_spec);
-
-}
-
-/**
- * media_channel_closed_cb:
- *
- * Signal callback for when a media channel is closed. Removes the references
- * that #HazeMediaManager holds to them.
- */
-static void
-media_channel_closed_cb (HazeMediaChannel *chan, gpointer user_data)
-{
- HazeMediaManager *self = HAZE_MEDIA_MANAGER (user_data);
- HazeMediaManagerPrivate *priv = self->priv;
-
- tp_channel_manager_emit_channel_closed_for_object (self,
- TP_EXPORTABLE_CHANNEL (chan));
-
- DEBUG ("removing media channel %p with ref count %d",
- chan, G_OBJECT (chan)->ref_count);
-
- g_ptr_array_remove (priv->channels, chan);
- g_object_unref (chan);
-}
-
-/**
- * new_media_channel
- *
- * Creates a new empty HazeMediaChannel.
- */
-static HazeMediaChannel *
-new_media_channel (HazeMediaManager *self,
- PurpleMedia *media,
- TpHandle peer,
- gboolean initial_audio,
- gboolean initial_video)
-{
- HazeMediaManagerPrivate *priv;
- TpBaseConnection *conn;
-
- HazeMediaChannel *chan;
- gchar *object_path;
-
- g_assert (HAZE_IS_MEDIA_MANAGER (self));
-
- priv = self->priv;
- conn = (TpBaseConnection *) priv->conn;
-
- object_path = g_strdup_printf ("%s/MediaChannel%u",
- conn->object_path, priv->channel_index);
- priv->channel_index += 1;
-
- chan = g_object_new (HAZE_TYPE_MEDIA_CHANNEL,
- "connection", priv->conn,
- "object-path", object_path,
- "media", media,
- "initial-peer", peer,
- "initial-audio", initial_audio,
- "initial-video", initial_video,
- NULL);
-
- DEBUG ("object path %s", object_path);
-
- g_signal_connect (chan, "closed", (GCallback) media_channel_closed_cb, self);
-
- g_ptr_array_add (priv->channels, chan);
-
- g_free (object_path);
-
- return chan;
-}
-
-static void
-haze_media_manager_close_all (HazeMediaManager *self)
-{
- HazeMediaManagerPrivate *priv = self->priv;
- GPtrArray *tmp = g_ptr_array_sized_new (priv->channels->len);
- guint i;
-
- for (i = 0; i < priv->channels->len; i++)
- g_ptr_array_add (tmp, g_ptr_array_index (priv->channels, i));
-
- DEBUG ("closing channels");
-
- for (i = 0; i < tmp->len; i++)
- {
- HazeMediaChannel *chan = g_ptr_array_index (tmp, i);
-
- DEBUG ("closing %p", chan);
- haze_media_channel_close (chan);
- }
-
- if (priv->status_changed_id != 0)
- {
- g_signal_handler_disconnect (priv->conn,
- priv->status_changed_id);
- priv->status_changed_id = 0;
- }
-}
-
-static gboolean
-init_media_cb (PurpleMediaManager *manager,
- PurpleMedia *media,
- PurpleAccount *account,
- const gchar *username,
- HazeMediaManager *self)
-{
- HazeMediaManagerPrivate *priv = self->priv;
- TpBaseConnection *base_conn = TP_BASE_CONNECTION (priv->conn);
- TpHandleRepoIface *contact_repo =
- tp_base_connection_get_handles (base_conn, TP_HANDLE_TYPE_CONTACT);
- TpHandle contact = tp_handle_ensure (contact_repo, username, NULL, NULL);
- HazeMediaChannel *chan;
-
- if (purple_media_is_initiator (media, NULL, NULL) == TRUE)
- return TRUE;
-
- chan = new_media_channel (self, media, contact, FALSE, FALSE);
- tp_channel_manager_emit_new_channel (self,
- TP_EXPORTABLE_CHANNEL (chan), NULL);
- DEBUG ("called");
- return TRUE;
-}
-
-static void
-connection_status_changed_cb (HazeConnection *conn,
- guint status,
- guint reason,
- HazeMediaManager *self)
-{
- switch (status)
- {
- case TP_CONNECTION_STATUS_CONNECTING:
- g_signal_connect (purple_media_manager_get (), "init-media",
- G_CALLBACK (init_media_cb), self);
- break;
-
- case TP_CONNECTION_STATUS_DISCONNECTED:
- g_signal_handlers_disconnect_by_func (purple_media_manager_get (),
- G_CALLBACK (init_media_cb), self);
- haze_media_manager_close_all (self);
- break;
- }
-}
-
-static void
-haze_media_manager_constructed (GObject *object)
-{
- void (*chain_up) (GObject *) =
- G_OBJECT_CLASS (haze_media_manager_parent_class)->constructed;
- HazeMediaManager *self = HAZE_MEDIA_MANAGER (object);
- HazeMediaManagerPrivate *priv = self->priv;
-
- if (chain_up != NULL)
- chain_up (object);
-
- priv->status_changed_id = g_signal_connect (priv->conn,
- "status-changed", (GCallback) connection_status_changed_cb, object);
-}
-
-static void
-haze_media_manager_foreach_channel (TpChannelManager *manager,
- TpExportableChannelFunc foreach,
- gpointer user_data)
-{
- HazeMediaManager *self = HAZE_MEDIA_MANAGER (manager);
- HazeMediaManagerPrivate *priv = self->priv;
- guint i;
-
- for (i = 0; i < priv->channels->len; i++)
- {
- TpExportableChannel *channel = TP_EXPORTABLE_CHANNEL (
- g_ptr_array_index (priv->channels, i));
-
- foreach (channel, user_data);
- }
-}
-
-static const gchar * const media_channel_fixed_properties[] = {
- TP_IFACE_CHANNEL ".ChannelType",
- TP_IFACE_CHANNEL ".TargetHandleType",
- NULL
-};
-
-static const gchar * const named_channel_allowed_properties[] = {
- TP_IFACE_CHANNEL ".TargetHandle",
- TP_IFACE_CHANNEL ".TargetID",
- TP_IFACE_CHANNEL_TYPE_STREAMED_MEDIA ".InitialAudio",
- TP_IFACE_CHANNEL_TYPE_STREAMED_MEDIA ".InitialVideo",
- NULL
-};
-
-/* not advertised in foreach_channel_class - can only be requested with
- * RequestChannel, not with CreateChannel/EnsureChannel */
-static const gchar * const anon_channel_allowed_properties[] = {
- NULL
-};
-
-static GHashTable *
-haze_media_manager_channel_class (void)
-{
- return tp_asv_new (
- TP_IFACE_CHANNEL ".ChannelType", G_TYPE_STRING,
- TP_IFACE_CHANNEL_TYPE_STREAMED_MEDIA,
- TP_IFACE_CHANNEL ".TargetHandleType", G_TYPE_UINT,
- TP_HANDLE_TYPE_CONTACT,
- NULL);
-}
-
-static void
-haze_media_manager_foreach_channel_class (TpChannelManager *manager,
- TpChannelManagerChannelClassFunc func,
- gpointer user_data)
-{
- GHashTable *table = haze_media_manager_channel_class ();
-
- func (manager, table, named_channel_allowed_properties, user_data);
-
- g_hash_table_destroy (table);
-}
-
-typedef enum
-{
- METHOD_REQUEST,
- METHOD_CREATE,
- METHOD_ENSURE,
-} RequestMethod;
-
-typedef struct
-{
- HazeMediaManager *self;
- HazeMediaChannel *channel;
- gpointer request_token;
-} MediaChannelRequest;
-
-static MediaChannelRequest *
-media_channel_request_new (HazeMediaManager *self,
- HazeMediaChannel *channel,
- gpointer request_token)
-{
- MediaChannelRequest *mcr = g_slice_new0 (MediaChannelRequest);
-
- mcr->self = self;
- mcr->channel = channel;
- mcr->request_token = request_token;
-
- return mcr;
-}
-
-static void
-media_channel_request_free (MediaChannelRequest *mcr)
-{
- g_slice_free (MediaChannelRequest, mcr);
-}
-
-static void
-media_channel_request_succeeded_cb (MediaChannelRequest *mcr,
- GPtrArray *streams)
-{
- GSList *request_tokens;
-
- request_tokens = g_slist_prepend (NULL, mcr->request_token);
- tp_channel_manager_emit_new_channel (mcr->self,
- TP_EXPORTABLE_CHANNEL (mcr->channel), request_tokens);
- g_slist_free (request_tokens);
-
- media_channel_request_free (mcr);
-}
-
-static void
-media_channel_request_failed_cb (MediaChannelRequest *mcr,
- GError *error)
-{
- tp_channel_manager_emit_request_failed (mcr->self, mcr->request_token,
- error->domain, error->code, error->message);
-
- media_channel_request_free (mcr);
-}
-
-static gboolean
-haze_media_manager_requestotron (TpChannelManager *manager,
- gpointer request_token,
- GHashTable *request_properties,
- RequestMethod method)
-{
- HazeMediaManager *self = HAZE_MEDIA_MANAGER (manager);
- HazeMediaManagerPrivate *priv = self->priv;
- TpHandleType handle_type;
- TpHandle handle;
- HazeMediaChannel *channel = NULL;
- GError *error = NULL;
- gboolean initial_audio, initial_video;
-
- /* Supported modes of operation:
- * - CreateChannel({THT: Contact, TH: n}):
- * channel has TargetHandle=n
- * n is not in the group interface at all
- * call is started when caller calls RequestStreams.
- * - EnsureChannel({THT: Contact, TH: n}):
- * look for a channel whose peer is n, and return that if found with
- * whatever properties and group membership it has;
- * otherwise the same as into CreateChannel
- */
-
- if (tp_strdiff (tp_asv_get_string (request_properties,
- TP_IFACE_CHANNEL ".ChannelType"),
- TP_IFACE_CHANNEL_TYPE_STREAMED_MEDIA))
- return FALSE;
-
- handle_type = tp_asv_get_uint32 (request_properties,
- TP_IFACE_CHANNEL ".TargetHandleType", NULL);
-
- handle = tp_asv_get_uint32 (request_properties,
- TP_IFACE_CHANNEL ".TargetHandle", NULL);
-
- initial_audio = tp_asv_get_boolean (request_properties,
- TP_IFACE_CHANNEL_TYPE_STREAMED_MEDIA ".InitialAudio", NULL);
- initial_video = tp_asv_get_boolean (request_properties,
- TP_IFACE_CHANNEL_TYPE_STREAMED_MEDIA ".InitialVideo", NULL);
-
- switch (handle_type)
- {
- case TP_HANDLE_TYPE_NONE:
- /* already checked by TpBaseConnection */
- g_assert (handle == 0);
-
- g_set_error (&error, TP_ERROR, TP_ERROR_NOT_IMPLEMENTED,
- "A valid Contact handle must be provided when requesting a media "
- "channel");
-
- goto error;
- case TP_HANDLE_TYPE_CONTACT:
- /* validity already checked by TpBaseConnection */
- g_assert (handle != 0);
-
- if (tp_channel_manager_asv_has_unknown_properties (request_properties,
- media_channel_fixed_properties, named_channel_allowed_properties,
- &error))
- goto error;
-
- if (method == METHOD_ENSURE)
- {
- guint i;
- TpHandle peer = 0;
-
- for (i = 0; i < priv->channels->len; i++)
- {
- channel = g_ptr_array_index (priv->channels, i);
- g_object_get (channel, "peer", &peer, NULL);
-
- if (peer == handle)
- {
- /* Per the spec, we ignore InitialAudio and InitialVideo when
- * looking for an existing channel.
- */
- tp_channel_manager_emit_request_already_satisfied (self,
- request_token, TP_EXPORTABLE_CHANNEL (channel));
- return TRUE;
- }
- }
- }
-
- channel = new_media_channel (self, NULL, handle,
- initial_audio, initial_video);
- break;
- default:
- return FALSE;
- }
-
- g_assert (channel != NULL);
-
- haze_media_channel_request_initial_streams (channel,
- (GFunc) media_channel_request_succeeded_cb,
- (GFunc) media_channel_request_failed_cb,
- media_channel_request_new (self, channel, request_token));
-
- return TRUE;
-
-error:
- tp_channel_manager_emit_request_failed (self, request_token,
- error->domain, error->code, error->message);
- g_error_free (error);
- return TRUE;
-}
-
-static gboolean
-haze_media_manager_request_channel (TpChannelManager *manager,
- gpointer request_token,
- GHashTable *request_properties)
-{
- return haze_media_manager_requestotron (manager, request_token,
- request_properties, METHOD_REQUEST);
-}
-
-
-static gboolean
-haze_media_manager_create_channel (TpChannelManager *manager,
- gpointer request_token,
- GHashTable *request_properties)
-{
- return haze_media_manager_requestotron (manager, request_token,
- request_properties, METHOD_CREATE);
-}
-
-static gboolean
-haze_media_manager_ensure_channel (TpChannelManager *manager,
- gpointer request_token,
- GHashTable *request_properties)
-{
- return haze_media_manager_requestotron (manager, request_token,
- request_properties, METHOD_ENSURE);
-}
-
-static void
-channel_manager_iface_init (gpointer g_iface,
- gpointer iface_data)
-{
- TpChannelManagerIface *iface = g_iface;
-
- iface->foreach_channel = haze_media_manager_foreach_channel;
- iface->foreach_channel_class = haze_media_manager_foreach_channel_class;
- iface->request_channel = haze_media_manager_request_channel;
- iface->create_channel = haze_media_manager_create_channel;
- iface->ensure_channel = haze_media_manager_ensure_channel;
-}
diff --git a/src/media-manager.h b/src/media-manager.h
deleted file mode 100644
index 72a0409..0000000
--- a/src/media-manager.h
+++ /dev/null
@@ -1,65 +0,0 @@
-/*
- * media-manager.h - Header for HazeMediaManager
- * Copyright (C) 2006, 2009 Collabora Ltd.
- *
- * Copied heavily from telepathy-gabble
- *
- * 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 __MEDIA_MANAGER_H__
-#define __MEDIA_MANAGER_H__
-
-#include <glib-object.h>
-
-G_BEGIN_DECLS
-
-typedef struct _HazeMediaManager HazeMediaManager;
-typedef struct _HazeMediaManagerClass HazeMediaManagerClass;
-typedef struct _HazeMediaManagerPrivate HazeMediaManagerPrivate;
-
-struct _HazeMediaManagerClass {
- GObjectClass parent_class;
-};
-
-struct _HazeMediaManager {
- GObject parent;
-
- HazeMediaManagerPrivate *priv;
-};
-
-GType haze_media_manager_get_type (void);
-
-/* TYPE MACROS */
-#define HAZE_TYPE_MEDIA_MANAGER \
- (haze_media_manager_get_type ())
-#define HAZE_MEDIA_MANAGER(obj) \
- (G_TYPE_CHECK_INSTANCE_CAST((obj), HAZE_TYPE_MEDIA_MANAGER,\
- HazeMediaManager))
-#define HAZE_MEDIA_MANAGER_CLASS(klass) \
- (G_TYPE_CHECK_CLASS_CAST((klass), HAZE_TYPE_MEDIA_MANAGER,\
- HazeMediaManagerClass))
-#define HAZE_IS_MEDIA_MANAGER(obj) \
- (G_TYPE_CHECK_INSTANCE_TYPE((obj), HAZE_TYPE_MEDIA_MANAGER))
-#define HAZE_IS_MEDIA_MANAGER_CLASS(klass) \
- (G_TYPE_CHECK_CLASS_TYPE((klass), HAZE_TYPE_MEDIA_MANAGER))
-#define HAZE_MEDIA_MANAGER_GET_CLASS(obj) \
- (G_TYPE_INSTANCE_GET_CLASS ((obj), HAZE_TYPE_MEDIA_MANAGER,\
- HazeMediaManagerClass))
-
-G_END_DECLS
-
-#endif /* #ifndef __MEDIA_MANAGER_H__ */
-
diff --git a/src/media-stream.c b/src/media-stream.c
deleted file mode 100644
index 7b4f29f..0000000
--- a/src/media-stream.c
+++ /dev/null
@@ -1,1399 +0,0 @@
-/*
- * media-stream.c - Source for HazeMediaStream
- * Copyright © 2006-2009 Collabora Ltd.
- * Copyright © 2006-2009 Nokia Corporation
- *
- * Copied heavily from telepathy-gabble.
- *
- * 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 "config.h"
-#include "media-stream.h"
-
-#include <libpurple/media/backend-iface.h>
-#include <string.h>
-#include <telepathy-glib/dbus.h>
-#include <telepathy-glib/errors.h>
-#include <telepathy-glib/interfaces.h>
-#include <telepathy-glib/properties-mixin.h>
-#include <telepathy-glib/svc-media-interfaces.h>
-
-#define DEBUG_FLAG HAZE_DEBUG_MEDIA
-
-#include "debug.h"
-
-static void stream_handler_iface_init (gpointer, gpointer);
-
-G_DEFINE_TYPE_WITH_CODE (HazeMediaStream,
- haze_media_stream,
- G_TYPE_OBJECT,
- G_IMPLEMENT_INTERFACE (TP_TYPE_SVC_DBUS_PROPERTIES,
- tp_dbus_properties_mixin_iface_init);
- G_IMPLEMENT_INTERFACE (TP_TYPE_SVC_MEDIA_STREAM_HANDLER,
- stream_handler_iface_init)
- )
-
-/* properties */
-enum
-{
- PROP_OBJECT_PATH = 1,
- PROP_DBUS_DAEMON,
- PROP_NAME,
- PROP_PEER,
- PROP_ID,
- PROP_MEDIA_TYPE,
- PROP_CONNECTION_STATE,
- PROP_READY,
- PROP_PLAYING,
- PROP_COMBINED_DIRECTION,
- PROP_LOCAL_HOLD,
- PROP_MEDIA,
- PROP_CODECS_READY,
- PROP_STUN_SERVERS,
- PROP_RELAY_INFO,
- PROP_NAT_TRAVERSAL,
- PROP_CREATED_LOCALLY,
- LAST_PROPERTY
-};
-
-/* private structure */
-
-struct _HazeMediaStreamPrivate
-{
- PurpleMedia *media;
-
- gchar *object_path;
- TpDBusDaemon *dbus_daemon;
- guint id;
- guint media_type;
-
- GList *codecs;
- GList *remote_codecs;
- GList *local_candidates;
- GList *remote_candidates;
-
- /* Whether we're waiting for a codec intersection from the streaming
- * implementation. If FALSE, SupportedCodecs is a no-op.
- */
- gboolean awaiting_intersection;
-
- guint remote_candidate_count;
-
- gchar *nat_traversal;
- /* GPtrArray(GValueArray(STRING, UINT)) */
- GPtrArray *stun_servers;
- /* GPtrArray(GHashTable(string => GValue)) */
- GPtrArray *relay_info;
-
- gboolean on_hold;
-
- gboolean closed;
- gboolean dispose_has_run;
- gboolean local_hold;
- gboolean ready;
- gboolean sending;
- gboolean created_locally;
-};
-
-HazeMediaStream *
-haze_media_stream_new (const gchar *object_path,
- TpDBusDaemon *dbus_daemon,
- PurpleMedia *media,
- const gchar *name,
- const gchar *peer,
- guint media_type,
- guint id,
- gboolean created_locally,
- const gchar *nat_traversal,
- const GPtrArray *relay_info,
- gboolean local_hold)
-{
- GPtrArray *empty = NULL;
- HazeMediaStream *result;
-
- g_return_val_if_fail (PURPLE_IS_MEDIA (media), NULL);
-
- if (relay_info == NULL)
- {
- empty = g_ptr_array_sized_new (0);
- relay_info = empty;
- }
-
- result = g_object_new (HAZE_TYPE_MEDIA_STREAM,
- "object-path", object_path,
- "dbus-daemon", dbus_daemon,
- "media", media,
- "name", name,
- "peer", peer,
- "media-type", media_type,
- "id", id,
- "created-locally", created_locally,
- "nat-traversal", nat_traversal,
- "relay-info", relay_info,
- "local-hold", local_hold,
- NULL);
-
- if (empty != NULL)
- g_ptr_array_free (empty, TRUE);
-
- return result;
-}
-
-TpMediaStreamType
-haze_media_stream_get_media_type (HazeMediaStream *self)
-{
- return self->priv->media_type;
-}
-
-static void
-haze_media_stream_init (HazeMediaStream *self)
-{
- HazeMediaStreamPrivate *priv = G_TYPE_INSTANCE_GET_PRIVATE (self,
- HAZE_TYPE_MEDIA_STREAM, HazeMediaStreamPrivate);
-
- self->priv = priv;
-
- priv->stun_servers = g_ptr_array_sized_new (1);
-}
-
-static GObject *
-haze_media_stream_constructor (GType type, guint n_props,
- GObjectConstructParam *props)
-{
- GObject *obj;
- HazeMediaStream *stream;
- HazeMediaStreamPrivate *priv;
-
- /* call base class constructor */
- obj = G_OBJECT_CLASS (haze_media_stream_parent_class)->
- constructor (type, n_props, props);
- stream = HAZE_MEDIA_STREAM (obj);
- priv = stream->priv;
-
- g_assert (priv->media != NULL);
-
- /* go for the bus */
- tp_dbus_daemon_register_object (priv->dbus_daemon, priv->object_path, obj);
-
- if (priv->created_locally)
- {
- g_object_set (stream, "combined-direction",
- MAKE_COMBINED_DIRECTION (TP_MEDIA_STREAM_DIRECTION_BIDIRECTIONAL,
- 0), NULL);
- }
- else
- {
- priv->awaiting_intersection = TRUE;
- g_object_set (stream, "combined-direction",
- MAKE_COMBINED_DIRECTION (TP_MEDIA_STREAM_DIRECTION_BIDIRECTIONAL,
- TP_MEDIA_STREAM_PENDING_LOCAL_SEND), NULL);
- }
-
- return obj;
-}
-
-static void
-haze_media_stream_get_property (GObject *object,
- guint property_id,
- GValue *value,
- GParamSpec *pspec)
-{
- HazeMediaStream *stream = HAZE_MEDIA_STREAM (object);
- HazeMediaStreamPrivate *priv = stream->priv;
-
- switch (property_id) {
- case PROP_OBJECT_PATH:
- g_value_set_string (value, priv->object_path);
- break;
- case PROP_DBUS_DAEMON:
- g_value_set_object (value, priv->dbus_daemon);
- break;
- case PROP_NAME:
- g_value_set_string (value, stream->name);
- break;
- case PROP_PEER:
- g_value_set_string (value, stream->peer);
- break;
- case PROP_ID:
- g_value_set_uint (value, priv->id);
- break;
- case PROP_MEDIA_TYPE:
- g_value_set_uint (value, priv->media_type);
- break;
- case PROP_CONNECTION_STATE:
- g_value_set_uint (value, stream->connection_state);
- break;
- case PROP_READY:
- g_value_set_boolean (value, priv->ready);
- break;
- case PROP_PLAYING:
- g_value_set_boolean (value, stream->playing);
- break;
- case PROP_COMBINED_DIRECTION:
- g_value_set_uint (value, stream->combined_direction);
- break;
- case PROP_LOCAL_HOLD:
- g_value_set_boolean (value, priv->local_hold);
- break;
- case PROP_MEDIA:
- g_value_set_object (value, priv->media);
- break;
- case PROP_CODECS_READY:
- g_value_set_boolean (value, priv->codecs != NULL);
- break;
- case PROP_STUN_SERVERS:
- g_value_set_boxed (value, priv->stun_servers);
- break;
- case PROP_NAT_TRAVERSAL:
- g_value_set_string (value, priv->nat_traversal);
- break;
- case PROP_CREATED_LOCALLY:
- g_value_set_boolean (value, priv->created_locally);
- break;
- case PROP_RELAY_INFO:
- g_value_set_boxed (value, priv->relay_info);
- break;
- default:
- G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
- break;
- }
-}
-
-static void
-haze_media_stream_set_property (GObject *object,
- guint property_id,
- const GValue *value,
- GParamSpec *pspec)
-{
- HazeMediaStream *stream = HAZE_MEDIA_STREAM (object);
- HazeMediaStreamPrivate *priv = stream->priv;
-
- switch (property_id) {
- case PROP_OBJECT_PATH:
- g_free (priv->object_path);
- priv->object_path = g_value_dup_string (value);
- break;
- case PROP_DBUS_DAEMON:
- g_assert (priv->dbus_daemon == NULL); /* construct-only */
- priv->dbus_daemon = g_value_dup_object (value);
- break;
- case PROP_NAME:
- g_free (stream->name);
- stream->name = g_value_dup_string (value);
- break;
- case PROP_PEER:
- g_free (stream->peer);
- stream->peer = g_value_dup_string (value);
- break;
- case PROP_ID:
- priv->id = g_value_get_uint (value);
- break;
- case PROP_MEDIA_TYPE:
- priv->media_type = g_value_get_uint (value);
- break;
- case PROP_CONNECTION_STATE:
- DEBUG ("stream %s connection state %d",
- stream->name, stream->connection_state);
- stream->connection_state = g_value_get_uint (value);
- break;
- case PROP_READY:
- priv->ready = g_value_get_boolean (value);
- break;
- case PROP_PLAYING:
- break;
- case PROP_COMBINED_DIRECTION:
- DEBUG ("changing combined direction from %u to %u",
- stream->combined_direction, g_value_get_uint (value));
- stream->combined_direction = g_value_get_uint (value);
- break;
- case PROP_MEDIA:
- g_assert (priv->media == NULL);
- priv->media = g_value_dup_object (value);
- break;
- case PROP_NAT_TRAVERSAL:
- g_assert (priv->nat_traversal == NULL);
- priv->nat_traversal = g_value_dup_string (value);
- break;
- case PROP_CREATED_LOCALLY:
- priv->created_locally = g_value_get_boolean (value);
- break;
- case PROP_RELAY_INFO:
- g_assert (priv->relay_info == NULL);
- priv->relay_info = g_value_dup_boxed (value);
- break;
- case PROP_LOCAL_HOLD:
- priv->local_hold = g_value_get_boolean (value);
- break;
- default:
- G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
- break;
- }
-}
-
-static void haze_media_stream_dispose (GObject *object);
-static void haze_media_stream_finalize (GObject *object);
-
-static void
-haze_media_stream_class_init (HazeMediaStreamClass *haze_media_stream_class)
-{
- static TpDBusPropertiesMixinPropImpl stream_handler_props[] = {
- { "RelayInfo", "relay-info", NULL },
- { "STUNServers", "stun-servers", NULL },
- { "NATTraversal", "nat-traversal", NULL },
- { "CreatedLocally", "created-locally", NULL },
- { NULL }
- };
- static TpDBusPropertiesMixinIfaceImpl prop_interfaces[] = {
- { TP_IFACE_MEDIA_STREAM_HANDLER,
- tp_dbus_properties_mixin_getter_gobject_properties,
- NULL,
- stream_handler_props,
- },
- { NULL }
- };
- GObjectClass *object_class = G_OBJECT_CLASS (haze_media_stream_class);
- GParamSpec *param_spec;
-
- g_type_class_add_private (haze_media_stream_class,
- sizeof (HazeMediaStreamPrivate));
-
- object_class->constructor = haze_media_stream_constructor;
-
- object_class->get_property = haze_media_stream_get_property;
- object_class->set_property = haze_media_stream_set_property;
-
- object_class->dispose = haze_media_stream_dispose;
- object_class->finalize = haze_media_stream_finalize;
-
- param_spec = g_param_spec_string ("object-path", "D-Bus object path",
- "The D-Bus object path used for this "
- "object on the bus.",
- NULL,
- G_PARAM_CONSTRUCT_ONLY |
- G_PARAM_READWRITE |
- G_PARAM_STATIC_STRINGS);
- g_object_class_install_property (object_class, PROP_OBJECT_PATH, param_spec);
-
- param_spec = g_param_spec_object ("dbus-daemon", "D-Bus connection",
- "Connection to D-Bus",
- TP_TYPE_DBUS_DAEMON,
- G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
- g_object_class_install_property (object_class, PROP_DBUS_DAEMON, param_spec);
-
- param_spec = g_param_spec_string ("name", "Stream name",
- "An opaque name for the stream used in the signalling.", NULL,
- G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE | G_PARAM_STATIC_NAME |
- G_PARAM_STATIC_BLURB);
- g_object_class_install_property (object_class, PROP_NAME, param_spec);
-
- param_spec = g_param_spec_string ("peer", "Peer name",
- "The name for the peer used in the signalling.", NULL,
- G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE | G_PARAM_STATIC_NAME |
- G_PARAM_STATIC_BLURB);
- g_object_class_install_property (object_class, PROP_PEER, param_spec);
-
- param_spec = g_param_spec_uint ("id", "Stream ID",
- "A stream number for the stream used in the "
- "D-Bus API.",
- 0, G_MAXUINT, 0,
- G_PARAM_CONSTRUCT_ONLY |
- G_PARAM_READWRITE |
- G_PARAM_STATIC_NAME |
- G_PARAM_STATIC_BLURB);
- g_object_class_install_property (object_class, PROP_ID, param_spec);
-
- param_spec = g_param_spec_uint ("media-type", "Stream media type",
- "A constant indicating which media type the stream carries.",
- TP_MEDIA_STREAM_TYPE_AUDIO, TP_MEDIA_STREAM_TYPE_VIDEO,
- TP_MEDIA_STREAM_TYPE_AUDIO,
- G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
- g_object_class_install_property (object_class, PROP_MEDIA_TYPE, param_spec);
-
- param_spec = g_param_spec_uint ("connection-state", "Stream connection state",
- "An integer indicating the state of the"
- "stream's connection.",
- TP_MEDIA_STREAM_STATE_DISCONNECTED,
- TP_MEDIA_STREAM_STATE_CONNECTED,
- TP_MEDIA_STREAM_STATE_DISCONNECTED,
- G_PARAM_CONSTRUCT |
- G_PARAM_READWRITE |
- G_PARAM_STATIC_NAME |
- G_PARAM_STATIC_BLURB);
- g_object_class_install_property (object_class, PROP_CONNECTION_STATE,
- param_spec);
-
- param_spec = g_param_spec_boolean ("ready", "Ready?",
- "A boolean signifying whether the user "
- "is ready to handle signals from this "
- "object.",
- FALSE,
- G_PARAM_CONSTRUCT |
- G_PARAM_READWRITE |
- G_PARAM_STATIC_NAME |
- G_PARAM_STATIC_BLURB);
- g_object_class_install_property (object_class, PROP_READY, param_spec);
-
- param_spec = g_param_spec_boolean ("playing", "Set playing",
- "A boolean signifying whether the stream "
- "has been set playing yet.",
- FALSE,
- G_PARAM_CONSTRUCT |
- G_PARAM_READWRITE |
- G_PARAM_STATIC_NAME |
- G_PARAM_STATIC_BLURB);
- g_object_class_install_property (object_class, PROP_PLAYING, param_spec);
-
- param_spec = g_param_spec_uint ("combined-direction",
- "Combined direction",
- "An integer indicating the directions the stream currently sends in, "
- "and the peers who have been asked to send.",
- TP_MEDIA_STREAM_DIRECTION_NONE,
- MAKE_COMBINED_DIRECTION (TP_MEDIA_STREAM_DIRECTION_BIDIRECTIONAL,
- TP_MEDIA_STREAM_PENDING_LOCAL_SEND |
- TP_MEDIA_STREAM_PENDING_REMOTE_SEND),
- TP_MEDIA_STREAM_DIRECTION_NONE,
- G_PARAM_CONSTRUCT | G_PARAM_READWRITE | G_PARAM_STATIC_NAME |
- G_PARAM_STATIC_BLURB);
- g_object_class_install_property (object_class, PROP_COMBINED_DIRECTION,
- param_spec);
-
- param_spec = g_param_spec_boolean ("local-hold", "Local hold?",
- "True if resources used for this stream have been freed.", FALSE,
- G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY |
- G_PARAM_STATIC_NAME | G_PARAM_STATIC_BLURB | G_PARAM_STATIC_NICK);
- g_object_class_install_property (object_class, PROP_LOCAL_HOLD, param_spec);
-
- param_spec = g_param_spec_object ("media", "PurpleMedia object",
- "Media object signalling this media stream.",
- PURPLE_TYPE_MEDIA,
- G_PARAM_CONSTRUCT_ONLY |
- G_PARAM_READWRITE |
- G_PARAM_STATIC_NICK |
- G_PARAM_STATIC_BLURB);
- g_object_class_install_property (object_class, PROP_MEDIA, param_spec);
-
- param_spec = g_param_spec_boxed ("stun-servers", "STUN servers",
- "Array of (STRING: address literal, UINT: port) pairs",
- /* FIXME: use correct macro when available */
- tp_type_dbus_array_su (),
- G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
- g_object_class_install_property (object_class, PROP_STUN_SERVERS, param_spec);
-
- param_spec = g_param_spec_boxed ("relay-info", "Relay info",
- "Array of mappings containing relay server information",
- TP_ARRAY_TYPE_STRING_VARIANT_MAP_LIST,
- G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
- g_object_class_install_property (object_class, PROP_RELAY_INFO, param_spec);
-
- param_spec = g_param_spec_string ("nat-traversal", "NAT traversal",
- "NAT traversal mechanism for this stream", NULL,
- G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
- g_object_class_install_property (object_class, PROP_NAT_TRAVERSAL,
- param_spec);
-
- param_spec = g_param_spec_boolean ("created-locally", "Created locally?",
- "True if this stream was created by the local user", FALSE,
- G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
- g_object_class_install_property (object_class, PROP_CREATED_LOCALLY,
- param_spec);
-
- param_spec = g_param_spec_boolean ("codecs-ready", "Codecs ready",
- "True if the codecs for this stream are ready to be used", FALSE,
- G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
- g_object_class_install_property (object_class, PROP_CODECS_READY,
- param_spec);
-
- haze_media_stream_class->dbus_props_class.interfaces = prop_interfaces;
- tp_dbus_properties_mixin_class_init (object_class,
- G_STRUCT_OFFSET (HazeMediaStreamClass, dbus_props_class));
-}
-
-void
-haze_media_stream_dispose (GObject *object)
-{
- HazeMediaStream *self = HAZE_MEDIA_STREAM (object);
- HazeMediaStreamPrivate *priv = self->priv;
-
- DEBUG ("called");
-
- if (priv->dispose_has_run)
- return;
-
- priv->dispose_has_run = TRUE;
-
- tp_clear_object (&priv->dbus_daemon);
-
- if (priv->local_candidates)
- {
- purple_media_candidate_list_free (priv->local_candidates);
- priv->local_candidates = NULL;
- }
-
- if (priv->remote_candidates)
- {
- purple_media_candidate_list_free (priv->remote_candidates);
- priv->remote_candidates = NULL;
- }
-
- if (priv->codecs)
- {
- purple_media_codec_list_free (priv->codecs);
- priv->codecs = NULL;
- }
-
- if (priv->remote_codecs)
- {
- purple_media_codec_list_free (priv->remote_codecs);
- priv->remote_codecs = NULL;
- }
-
- g_object_unref (priv->media);
- priv->media = NULL;
-
- if (G_OBJECT_CLASS (haze_media_stream_parent_class)->dispose)
- G_OBJECT_CLASS (haze_media_stream_parent_class)->dispose (object);
-}
-
-void
-haze_media_stream_finalize (GObject *object)
-{
- HazeMediaStream *self = HAZE_MEDIA_STREAM (object);
- HazeMediaStreamPrivate *priv = self->priv;
-
- g_free (priv->object_path);
- g_free (priv->nat_traversal);
-
- /* FIXME: use correct macro when available */
- if (priv->stun_servers != NULL)
- g_boxed_free (tp_type_dbus_array_su (), priv->stun_servers);
-
- if (priv->relay_info != NULL)
- g_boxed_free (TP_ARRAY_TYPE_STRING_VARIANT_MAP_LIST, priv->relay_info);
-
- G_OBJECT_CLASS (haze_media_stream_parent_class)->finalize (object);
-}
-
-
-GList *
-haze_media_stream_get_local_candidates (HazeMediaStream *self)
-{
- HazeMediaStreamPrivate *priv = self->priv;
- return g_list_copy (priv->local_candidates);
-}
-
-
-GList *
-haze_media_stream_get_codecs (HazeMediaStream *self)
-{
- HazeMediaStreamPrivate *priv = self->priv;
- return purple_media_codec_list_copy (priv->codecs);
-}
-
-
-static void
-pass_remote_candidates (HazeMediaStream *self)
-{
- HazeMediaStreamPrivate *priv = self->priv;
- GType transport_struct_type = TP_STRUCT_TYPE_MEDIA_STREAM_HANDLER_TRANSPORT;
- GType candidate_struct_type = TP_STRUCT_TYPE_MEDIA_STREAM_HANDLER_CANDIDATE;
- GList *iter = priv->remote_candidates;
-
- for (; iter; iter = g_list_next (iter))
- {
- gchar *address, *username, *password, *candidate_id;
- GValue candidate = { 0, };
- GPtrArray *transports;
- GValue transport = { 0, };
- PurpleMediaCandidate *c = iter->data;
- PurpleMediaCandidateType candidate_type;
- guint type = TP_MEDIA_STREAM_TRANSPORT_TYPE_LOCAL;
-
- g_value_init (&transport, transport_struct_type);
- g_value_take_boxed (&transport,
- dbus_g_type_specialized_construct (transport_struct_type));
-
- address = purple_media_candidate_get_ip (c);
- username = purple_media_candidate_get_username (c);
- password = purple_media_candidate_get_password (c);
- candidate_type = purple_media_candidate_get_candidate_type (c);
-
- if (candidate_type == PURPLE_MEDIA_CANDIDATE_TYPE_HOST)
- type = TP_MEDIA_STREAM_TRANSPORT_TYPE_LOCAL;
- else if (candidate_type == PURPLE_MEDIA_CANDIDATE_TYPE_SRFLX)
- type = TP_MEDIA_STREAM_TRANSPORT_TYPE_DERIVED;
- else if (candidate_type == PURPLE_MEDIA_CANDIDATE_TYPE_RELAY)
- type = TP_MEDIA_STREAM_TRANSPORT_TYPE_RELAY;
- else
- DEBUG ("Unknown candidate type");
-
- dbus_g_type_struct_set (&transport,
- 0, purple_media_candidate_get_component_id (c),
- 1, address,
- 2, purple_media_candidate_get_port (c),
- 3, purple_media_candidate_get_protocol (c) ==
- PURPLE_MEDIA_NETWORK_PROTOCOL_UDP ?
- TP_MEDIA_STREAM_BASE_PROTO_UDP :
- TP_MEDIA_STREAM_BASE_PROTO_TCP,
- 4, "RTP",
- 5, "AVP",
- 6, (double)purple_media_candidate_get_priority (c),
- 7, type,
- 8, username,
- 9, password,
- G_MAXUINT);
-
- g_free (password);
- g_free (username);
- g_free (address);
-
- transports = g_ptr_array_sized_new (1);
- g_ptr_array_add (transports, g_value_get_boxed (&transport));
-
- g_value_init (&candidate, candidate_struct_type);
- g_value_take_boxed (&candidate,
- dbus_g_type_specialized_construct (candidate_struct_type));
-
- candidate_id = purple_media_candidate_get_foundation (c);
-
- dbus_g_type_struct_set (&candidate,
- 0, candidate_id,
- 1, transports,
- G_MAXUINT);
-
- DEBUG ("passing 1 remote candidate to stream engine: %s", candidate_id);
-
- tp_svc_media_stream_handler_emit_add_remote_candidate (
- self, candidate_id, transports);
-
- g_free (candidate_id);
- }
-}
-
-
-void
-haze_media_stream_add_remote_candidates (HazeMediaStream *self,
- GList *remote_candidates)
-{
- HazeMediaStreamPrivate *priv = self->priv;
-
- priv->remote_candidates = g_list_concat (
- priv->remote_candidates,
- purple_media_candidate_list_copy (remote_candidates));
-
- if (priv->ready == TRUE)
- pass_remote_candidates (self);
-}
-
-
-static void
-pass_remote_codecs (HazeMediaStream *self)
-{
- HazeMediaStreamPrivate *priv = self->priv;
- GType codec_struct_type = TP_STRUCT_TYPE_MEDIA_STREAM_HANDLER_CODEC;
- GPtrArray *codecs = g_ptr_array_new ();
- GList *iter = priv->remote_codecs;
-
- for (; iter; iter = g_list_next (iter))
- {
- GValue codec = { 0, };
- PurpleMediaCodec *c = iter->data;
- gchar *name;
- GList *codec_params;
- GHashTable *params;
-
- g_value_init (&codec, codec_struct_type);
- g_value_take_boxed (&codec,
- dbus_g_type_specialized_construct (codec_struct_type));
-
- name = purple_media_codec_get_encoding_name (c);
- codec_params = purple_media_codec_get_optional_parameters (c);
- params = g_hash_table_new_full (g_str_hash, g_str_equal,
- g_free, g_free);
-
- for (; codec_params; codec_params = g_list_next (codec_params))
- {
- PurpleKeyValuePair *pair = codec_params->data;
- g_hash_table_insert (params, pair->key, pair->value);
- }
-
- DEBUG ("new remote %s codec: %u '%s' %u %u %u",
- priv->media_type == TP_MEDIA_STREAM_TYPE_AUDIO ? "audio" : "video",
- purple_media_codec_get_id (c), name, priv->media_type,
- purple_media_codec_get_clock_rate (c),
- purple_media_codec_get_channels (c));
-
- dbus_g_type_struct_set (&codec,
- 0, purple_media_codec_get_id (c),
- 1, name,
- 2, priv->media_type,
- 3, purple_media_codec_get_clock_rate (c),
- 4, purple_media_codec_get_channels (c),
- 5, params,
- G_MAXUINT);
-
- g_free (name);
- g_hash_table_destroy (params);
-
- g_ptr_array_add (codecs, g_value_get_boxed (&codec));
- }
-
- DEBUG ("passing %d remote codecs to stream-engine", codecs->len);
-
- tp_svc_media_stream_handler_emit_set_remote_codecs (self, codecs);
-}
-
-
-void
-haze_media_stream_set_remote_codecs (HazeMediaStream *self,
- GList *remote_codecs)
-{
- HazeMediaStreamPrivate *priv = self->priv;
- GList *iter = priv->remote_codecs;
-
- for (; iter; iter = g_list_delete_link (iter, iter))
- g_object_unref (iter->data);
-
- priv->remote_codecs = purple_media_codec_list_copy (remote_codecs);
-
- if (priv->ready == TRUE)
- pass_remote_codecs (self);
-}
-
-void
-haze_media_stream_add_stun_server (HazeMediaStream *self,
- const gchar *stun_ip,
- guint stun_port)
-{
- HazeMediaStreamPrivate *priv = self->priv;
- GValueArray *va;
- GValue ip = {0}, port = {0};
-
- if (stun_ip == NULL || stun_ip[0] == 0)
- {
- DEBUG ("Invalid STUN address passed: %s", stun_ip);
- return;
- }
- else if (stun_port > 65535)
- {
- DEBUG ("Invalid STUN port passed: %d", stun_port);
- return;
- }
-
- g_value_init (&ip, G_TYPE_STRING);
- g_value_set_string (&ip, stun_ip);
- g_value_init (&port, G_TYPE_UINT);
- g_value_set_uint (&port, stun_port);
-
- va = g_value_array_new (2);
- g_value_array_append (va, &ip);
- g_value_array_append (va, &port);
-
- g_ptr_array_add (priv->stun_servers, va);
-}
-
-
-/**
- * haze_media_stream_codec_choice
- *
- * Implements D-Bus method CodecChoice
- * on interface org.freedesktop.Telepathy.Media.StreamHandler
- */
-static void
-haze_media_stream_codec_choice (TpSvcMediaStreamHandler *iface,
- guint codec_id,
- DBusGMethodInvocation *context)
-{
- HazeMediaStream *self = HAZE_MEDIA_STREAM (iface);
-
- g_assert (HAZE_IS_MEDIA_STREAM (self));
-
- tp_svc_media_stream_handler_return_from_codec_choice (context);
-}
-
-
-gboolean
-haze_media_stream_error (HazeMediaStream *self,
- guint err_no,
- const gchar *message,
- GError **error)
-{
- g_assert (HAZE_IS_MEDIA_STREAM (self));
-
- DEBUG ( "Media.StreamHandler::Error called, error %u (%s) -- emitting signal",
- err_no, message);
-
- purple_media_error (self->priv->media, message);
-
- return TRUE;
-}
-
-
-/**
- * haze_media_stream_error
- *
- * Implements D-Bus method Error
- * on interface org.freedesktop.Telepathy.Media.StreamHandler
- */
-static void
-haze_media_stream_error_async (TpSvcMediaStreamHandler *iface,
- guint errno,
- const gchar *message,
- DBusGMethodInvocation *context)
-{
- HazeMediaStream *self = HAZE_MEDIA_STREAM (iface);
- GError *error = NULL;
-
- if (haze_media_stream_error (self, errno, message, &error))
- {
- tp_svc_media_stream_handler_return_from_error (context);
- }
- else
- {
- dbus_g_method_return_error (context, error);
- g_error_free (error);
- }
-}
-
-
-/**
- * haze_media_stream_hold:
- *
- * Tell streaming clients that the stream is going on hold, so they should
- * stop streaming and free up any resources they are currently holding
- * (e.g. close hardware devices); or that the stream is coming off hold,
- * so they should reacquire those resources.
- */
-void
-haze_media_stream_hold (HazeMediaStream *self,
- gboolean hold)
-{
- tp_svc_media_stream_handler_emit_set_stream_held (self, hold);
-}
-
-
-/**
- * haze_media_stream_hold_state:
- *
- * Called by streaming clients when the stream's hold state has been changed
- * successfully in response to SetStreamHeld.
- */
-static void
-haze_media_stream_hold_state (TpSvcMediaStreamHandler *iface,
- gboolean hold_state,
- DBusGMethodInvocation *context)
-{
- HazeMediaStream *self = HAZE_MEDIA_STREAM (iface);
- HazeMediaStreamPrivate *priv = self->priv;
-
- DEBUG ("%p: %s", self, hold_state ? "held" : "unheld");
- priv->local_hold = hold_state;
-
- g_object_notify ((GObject *) self, "local-hold");
-
- tp_svc_media_stream_handler_return_from_hold_state (context);
-}
-
-
-/**
- * haze_media_stream_unhold_failure:
- *
- * Called by streaming clients when an attempt to reacquire the necessary
- * hardware or software resources to unhold the stream, in response to
- * SetStreamHeld, has failed.
- */
-static void
-haze_media_stream_unhold_failure (TpSvcMediaStreamHandler *iface,
- DBusGMethodInvocation *context)
-{
- HazeMediaStream *self = HAZE_MEDIA_STREAM (iface);
- HazeMediaStreamPrivate *priv = self->priv;
-
- DEBUG ("%p", self);
-
- priv->local_hold = TRUE;
-
-// maybe emit unhold failed here?
- g_object_notify ((GObject *) self, "local-hold");
-
- tp_svc_media_stream_handler_return_from_unhold_failure (context);
-}
-
-
-/**
- * haze_media_stream_native_candidates_prepared
- *
- * Implements D-Bus method NativeCandidatesPrepared
- * on interface org.freedesktop.Telepathy.Media.StreamHandler
- */
-static void
-haze_media_stream_native_candidates_prepared (TpSvcMediaStreamHandler *iface,
- DBusGMethodInvocation *context)
-{
- HazeMediaStream *self = HAZE_MEDIA_STREAM (iface);
- HazeMediaStreamPrivate *priv;
- PurpleMediaBackend *backend;
-
- g_assert (HAZE_IS_MEDIA_STREAM (self));
-
- priv = self->priv;
-
- g_object_get (G_OBJECT (priv->media), "backend", &backend, NULL);
- g_signal_emit_by_name (backend, "candidates-prepared",
- self->name, self->peer);
- g_object_unref (backend);
-
- tp_svc_media_stream_handler_return_from_native_candidates_prepared (context);
-}
-
-
-/**
- * haze_media_stream_new_active_candidate_pair
- *
- * Implements D-Bus method NewActiveCandidatePair
- * on interface org.freedesktop.Telepathy.Media.StreamHandler
- */
-static void
-haze_media_stream_new_active_candidate_pair (TpSvcMediaStreamHandler *iface,
- const gchar *native_candidate_id,
- const gchar *remote_candidate_id,
- DBusGMethodInvocation *context)
-{
- HazeMediaStream *self = HAZE_MEDIA_STREAM (iface);
- HazeMediaStreamPrivate *priv;
- PurpleMediaBackend *backend;
- GList *l_iter;
-
- /*
- * This appears to be called for each pair of components.
- * I'm not sure how to go about differentiating between the two
- * components as the ids are the same.
- */
-
- DEBUG ("called (%s, %s)", native_candidate_id, remote_candidate_id);
-
- g_assert (HAZE_IS_MEDIA_STREAM (self));
-
- priv = self->priv;
- l_iter = priv->local_candidates;
- g_object_get (priv->media, "backend", &backend, NULL);
-
- for (; l_iter; l_iter = g_list_next (l_iter))
- {
- PurpleMediaCandidate *lc = l_iter->data;
- GList *r_iter = priv->remote_candidates;
-
- for (; r_iter; r_iter = g_list_next (r_iter))
- {
- PurpleMediaCandidate *rc = r_iter->data;
-
- if (purple_media_candidate_get_component_id (lc) ==
- purple_media_candidate_get_component_id (rc))
- {
- gchar *l_name = purple_media_candidate_get_foundation (lc);
- gchar *r_name = purple_media_candidate_get_foundation (rc);
-
- if (!strcmp (l_name, native_candidate_id) &&
- !strcmp (r_name, remote_candidate_id))
- {
- DEBUG ("Emitting new active candidate pair %d: %s - %s",
- purple_media_candidate_get_component_id (lc),
- l_name, r_name);
-
- g_signal_emit_by_name (backend, "active-candidate-pair",
- self->name, self->peer, lc, rc);
- }
-
- g_free (l_name);
- g_free (r_name);
- }
- }
- }
-
- g_object_unref (backend);
- tp_svc_media_stream_handler_return_from_new_active_candidate_pair (context);
-}
-
-
-/**
- * haze_media_stream_new_native_candidate
- *
- * Implements D-Bus method NewNativeCandidate
- * on interface org.freedesktop.Telepathy.Media.StreamHandler
- */
-static void
-haze_media_stream_new_native_candidate (TpSvcMediaStreamHandler *iface,
- const gchar *candidate_id,
- const GPtrArray *transports,
- DBusGMethodInvocation *context)
-{
- HazeMediaStream *self = HAZE_MEDIA_STREAM (iface);
- HazeMediaStreamPrivate *priv;
- PurpleMediaBackend *backend;
- guint i;
-
- g_assert (HAZE_IS_MEDIA_STREAM (self));
-
- priv = self->priv;
-
- g_object_get (G_OBJECT (priv->media), "backend", &backend, NULL);
-
- for (i = 0; i < transports->len; i++)
- {
- GValueArray *transport;
- guint component, type, proto;
- PurpleMediaCandidate *c;
- PurpleMediaCandidateType candidate_type =
- PURPLE_MEDIA_CANDIDATE_TYPE_HOST;
- PurpleMediaNetworkProtocol protocol = PURPLE_MEDIA_NETWORK_PROTOCOL_UDP;
-
- transport = g_ptr_array_index (transports, i);
- component = g_value_get_uint (g_value_array_get_nth (transport, 0));
- type = g_value_get_uint (g_value_array_get_nth (transport, 7));
- proto = g_value_get_uint (g_value_array_get_nth (transport, 3));
-
- if (type == TP_MEDIA_STREAM_TRANSPORT_TYPE_LOCAL)
- candidate_type = PURPLE_MEDIA_CANDIDATE_TYPE_HOST;
- else if (type == TP_MEDIA_STREAM_TRANSPORT_TYPE_DERIVED)
- candidate_type = PURPLE_MEDIA_CANDIDATE_TYPE_SRFLX;
- else if (type == TP_MEDIA_STREAM_TRANSPORT_TYPE_RELAY)
- candidate_type = PURPLE_MEDIA_CANDIDATE_TYPE_RELAY;
- else
- DEBUG ("Unknown candidate type");
-
- if (proto == TP_MEDIA_STREAM_BASE_PROTO_UDP)
- protocol = PURPLE_MEDIA_NETWORK_PROTOCOL_UDP;
- else if (proto == TP_MEDIA_STREAM_BASE_PROTO_TCP)
- protocol = PURPLE_MEDIA_NETWORK_PROTOCOL_TCP;
- else
- DEBUG ("Unknown network protocol");
-
- c = purple_media_candidate_new (candidate_id, component, candidate_type,
- protocol,
- /* address */
- g_value_get_string (g_value_array_get_nth (transport, 1)),
- /* port */
- g_value_get_uint (g_value_array_get_nth (transport, 2)));
-
- g_object_set (c, "username",
- g_value_get_string (g_value_array_get_nth (transport, 8)), NULL);
- g_object_set (c, "password",
- g_value_get_string (g_value_array_get_nth (transport, 9)), NULL);
- g_object_set (c, "priority",
- (guint)g_value_get_double (
- g_value_array_get_nth (transport, 6)), NULL);
-
- DEBUG ("new-candidate: %s %s %p", self->name, self->peer, c);
-
- priv->local_candidates = g_list_append (priv->local_candidates, c);
-
- g_signal_emit_by_name (backend, "new-candidate", self->name, self->peer, c);
- }
-
- g_object_unref (backend);
-
- tp_svc_media_stream_handler_return_from_new_native_candidate (context);
-}
-
-static void haze_media_stream_set_local_codecs (TpSvcMediaStreamHandler *,
- const GPtrArray *codecs, DBusGMethodInvocation *);
-
-/**
- * haze_media_stream_ready
- *
- * Implements D-Bus method Ready
- * on interface org.freedesktop.Telepathy.Media.StreamHandler
- */
-static void
-haze_media_stream_ready (TpSvcMediaStreamHandler *iface,
- const GPtrArray *codecs,
- DBusGMethodInvocation *context)
-{
- HazeMediaStream *self = HAZE_MEDIA_STREAM (iface);
- HazeMediaStreamPrivate *priv;
-
- g_assert (HAZE_IS_MEDIA_STREAM (self));
-
- priv = self->priv;
-
- DEBUG ("ready called");
-
- if (priv->ready == FALSE)
- {
- g_object_set (self, "ready", TRUE, NULL);
-
- tp_svc_media_stream_handler_emit_set_stream_playing (self, TRUE);
-
- if (purple_media_get_session_type (priv->media, self->name) &
- (PURPLE_MEDIA_SEND_AUDIO | PURPLE_MEDIA_SEND_VIDEO))
- {
- g_object_set (self, "combined-direction",
- MAKE_COMBINED_DIRECTION (TP_MEDIA_STREAM_DIRECTION_BIDIRECTIONAL,
- 0), NULL);
- tp_svc_media_stream_handler_emit_set_stream_sending (self, TRUE);
- }
-
- /* If a new stream is added while the call's on hold, it will have
- * local_hold set at construct time. So once tp-fs has called Ready(), we
- * should let it know this stream's on hold.
- */
- if (priv->local_hold)
- haze_media_stream_hold (self, priv->local_hold);
- }
- else
- {
- DEBUG ("Ready called twice, running plain SetLocalCodecs instead");
- }
-
- /* set_local_codecs and ready return the same thing, so we can do... */
- haze_media_stream_set_local_codecs (iface, codecs, context);
- pass_remote_codecs (self);
- pass_remote_candidates (self);
-}
-
-static void
-convert_param (gchar *key, gchar *value, PurpleMediaCodec *codec)
-{
- purple_media_codec_add_optional_parameter (codec, key, value);
-}
-
-static gboolean
-pass_local_codecs (HazeMediaStream *stream,
- const GPtrArray *codecs,
- gboolean ready,
- GError **error)
-{
- HazeMediaStreamPrivate *priv = stream->priv;
- PurpleMediaSessionType type = PURPLE_MEDIA_AUDIO;
- PurpleMediaCodec *c;
- guint i;
-
- DEBUG ("putting list of %d supported codecs from stream-engine into cache",
- codecs->len);
-
- if (priv->media_type == TP_MEDIA_STREAM_TYPE_AUDIO)
- type = PURPLE_MEDIA_AUDIO;
- else if (priv->media_type == TP_MEDIA_STREAM_TYPE_VIDEO)
- type = PURPLE_MEDIA_VIDEO;
- else
- g_assert_not_reached ();
-
- for (i = 0; i < codecs->len; i++)
- {
- GType codec_struct_type = TP_STRUCT_TYPE_MEDIA_STREAM_HANDLER_CODEC;
-
- GValue codec = { 0, };
- guint id, clock_rate, channels;
- gchar *name;
- GHashTable *params;
-
- g_value_init (&codec, codec_struct_type);
- g_value_set_static_boxed (&codec, g_ptr_array_index (codecs, i));
-
- dbus_g_type_struct_get (&codec,
- 0, &id,
- 1, &name,
- 3, &clock_rate,
- 4, &channels,
- 5, &params,
- G_MAXUINT);
-
- c = purple_media_codec_new (id, name, type, clock_rate);
- g_object_set (c, "channels", channels, NULL);
-
- g_hash_table_foreach (params, (GHFunc)convert_param, c);
-
- DEBUG ("adding codec: %s", purple_media_codec_to_string (c));
-
- priv->codecs = g_list_append (priv->codecs, c);
-
- g_signal_emit_by_name (priv->media, "codecs-changed", stream->name);
- }
-
- return TRUE;
-}
-
-/**
- * haze_media_stream_set_local_codecs
- *
- * Implements D-Bus method SetLocalCodecs
- * on interface org.freedesktop.Telepathy.Media.StreamHandler
- */
-static void
-haze_media_stream_set_local_codecs (TpSvcMediaStreamHandler *iface,
- const GPtrArray *codecs,
- DBusGMethodInvocation *context)
-{
- HazeMediaStream *self = HAZE_MEDIA_STREAM (iface);
- HazeMediaStreamPrivate *priv = self->priv;
- GError *error = NULL;
-
- DEBUG ("called");
-
- if (PURPLE_IS_MEDIA (priv->media) &&
- purple_media_is_initiator (priv->media, self->name, self->peer))
- {
- if (!pass_local_codecs (self, codecs, self->priv->created_locally,
- &error))
- {
- DEBUG ("failed: %s", error->message);
-
- dbus_g_method_return_error (context, error);
- g_error_free (error);
- return;
- }
- }
- else
- {
- DEBUG ("ignoring local codecs, waiting for codec intersection");
- }
-
- tp_svc_media_stream_handler_return_from_set_local_codecs (context);
-}
-
-/**
- * haze_media_stream_stream_state
- *
- * Implements D-Bus method StreamState
- * on interface org.freedesktop.Telepathy.Media.StreamHandler
- */
-static void
-haze_media_stream_stream_state (TpSvcMediaStreamHandler *iface,
- guint connection_state,
- DBusGMethodInvocation *context)
-{
- HazeMediaStream *self = HAZE_MEDIA_STREAM (iface);
-
- g_object_set (self, "connection-state", connection_state, NULL);
-
- // emit connection state here
-
- tp_svc_media_stream_handler_return_from_stream_state (context);
-}
-
-
-/**
- * haze_media_stream_supported_codecs
- *
- * Implements D-Bus method SupportedCodecs
- * on interface org.freedesktop.Telepathy.Media.StreamHandler
- */
-static void
-haze_media_stream_supported_codecs (TpSvcMediaStreamHandler *iface,
- const GPtrArray *codecs,
- DBusGMethodInvocation *context)
-{
- HazeMediaStream *self = HAZE_MEDIA_STREAM (iface);
- HazeMediaStreamPrivate *priv = self->priv;
- GError *error = NULL;
-
- DEBUG ("called");
-
- if (priv->awaiting_intersection)
- {
- if (!pass_local_codecs (self, codecs, TRUE, &error))
- {
- DEBUG ("failed: %s", error->message);
-
- dbus_g_method_return_error (context, error);
- g_error_free (error);
- return;
- }
-
- priv->awaiting_intersection = FALSE;
- }
- else
- {
- /* If we created the stream, we don't need to send the intersection. If
- * we didn't create it, but have already sent the intersection once, we
- * don't need to send it again. In either case, extra calls to
- * SupportedCodecs are in response to an incoming description-info, which
- * can only change parameters and which XEP-0167 §10 says is purely
- * advisory.
- */
- DEBUG ("we already sent, or don't need to send, our codecs");
- }
-
- tp_svc_media_stream_handler_return_from_supported_codecs (context);
-}
-
-/**
- * haze_media_stream_codecs_updated
- *
- * Implements D-Bus method CodecsUpdated
- * on interface org.freedesktop.Telepathy.Media.StreamHandler
- */
-static void
-haze_media_stream_codecs_updated (TpSvcMediaStreamHandler *iface,
- const GPtrArray *codecs,
- DBusGMethodInvocation *context)
-{
- HazeMediaStream *self = HAZE_MEDIA_STREAM (iface);
- GError *error = NULL;
-
- if (self->priv->codecs == NULL)
- {
- GError e = { TP_ERROR, TP_ERROR_NOT_AVAILABLE,
- "CodecsUpdated may only be called once an initial set of codecs "
- "has been set" };
-
- dbus_g_method_return_error (context, &e);
- return;
- }
-
- if (self->priv->awaiting_intersection)
- {
- /* When awaiting an intersection the initial set of codecs should be set
- * by calling SupportedCodecs as that is the canonical set of codecs,
- * updates are only meaningful afterwards */
- tp_svc_media_stream_handler_return_from_codecs_updated (context);
- return;
- }
-
- if (pass_local_codecs (self, codecs, self->priv->created_locally, &error))
- {
- tp_svc_media_stream_handler_return_from_codecs_updated (context);
- }
- else
- {
- DEBUG ("failed: %s", error->message);
-
- dbus_g_method_return_error (context, error);
- g_error_free (error);
- }
-}
-
-static void
-stream_handler_iface_init (gpointer g_iface, gpointer iface_data)
-{
- TpSvcMediaStreamHandlerClass *klass =
- (TpSvcMediaStreamHandlerClass *) g_iface;
-
-#define IMPLEMENT(x,suffix) tp_svc_media_stream_handler_implement_##x (\
- klass, haze_media_stream_##x##suffix)
- IMPLEMENT(codec_choice,);
- IMPLEMENT(error,_async);
- IMPLEMENT(hold_state,);
- IMPLEMENT(native_candidates_prepared,);
- IMPLEMENT(new_active_candidate_pair,);
- IMPLEMENT(new_native_candidate,);
- IMPLEMENT(ready,);
- IMPLEMENT(set_local_codecs,);
- IMPLEMENT(stream_state,);
- IMPLEMENT(supported_codecs,);
- IMPLEMENT(unhold_failure,);
- IMPLEMENT(codecs_updated,);
-#undef IMPLEMENT
-}
diff --git a/src/media-stream.h b/src/media-stream.h
deleted file mode 100644
index 0d6f328..0000000
--- a/src/media-stream.h
+++ /dev/null
@@ -1,126 +0,0 @@
-/*
- * media-stream.h - Header for HazeMediaStream
- * Copyright (C) 2006, 2009 Collabora Ltd.
- * Copyright (C) 2006 Nokia Corporation
- *
- * Copied heavily from telepathy-gabble.
- *
- * 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 __HAZE_MEDIA_STREAM_H__
-#define __HAZE_MEDIA_STREAM_H__
-
-#include <glib-object.h>
-#include <libpurple/media.h>
-#include <telepathy-glib/telepathy-glib.h>
-
-G_BEGIN_DECLS
-
-typedef enum
-{
- STREAM_SIG_STATE_NEW,
- STREAM_SIG_STATE_SENT,
- STREAM_SIG_STATE_ACKNOWLEDGED,
- STREAM_SIG_STATE_REMOVING
-} StreamSignallingState;
-
-typedef guint32 CombinedStreamDirection;
-
-typedef struct _HazeMediaStream HazeMediaStream;
-typedef struct _HazeMediaStreamClass HazeMediaStreamClass;
-typedef struct _HazeMediaStreamPrivate HazeMediaStreamPrivate;
-
-struct _HazeMediaStreamClass {
- GObjectClass parent_class;
-
- TpDBusPropertiesMixinClass dbus_props_class;
-};
-
-struct _HazeMediaStream {
- GObject parent;
-
- gchar *name;
- gchar *peer;
-
- TpMediaStreamState connection_state;
-
- CombinedStreamDirection combined_direction;
- gboolean playing;
-
- HazeMediaStreamPrivate *priv;
-};
-
-GType haze_media_stream_get_type (void);
-
-/* TYPE MACROS */
-#define HAZE_TYPE_MEDIA_STREAM \
- (haze_media_stream_get_type ())
-#define HAZE_MEDIA_STREAM(obj) \
- (G_TYPE_CHECK_INSTANCE_CAST((obj), HAZE_TYPE_MEDIA_STREAM, \
- HazeMediaStream))
-#define HAZE_MEDIA_STREAM_CLASS(klass) \
- (G_TYPE_CHECK_CLASS_CAST((klass), HAZE_TYPE_MEDIA_STREAM, \
- HazeMediaStreamClass))
-#define HAZE_IS_MEDIA_STREAM(obj) \
- (G_TYPE_CHECK_INSTANCE_TYPE((obj), HAZE_TYPE_MEDIA_STREAM))
-#define HAZE_IS_MEDIA_STREAM_CLASS(klass) \
- (G_TYPE_CHECK_CLASS_TYPE((klass), HAZE_TYPE_MEDIA_STREAM))
-#define HAZE_MEDIA_STREAM_GET_CLASS(obj) \
- (G_TYPE_INSTANCE_GET_CLASS ((obj), HAZE_TYPE_MEDIA_STREAM, \
- HazeMediaStreamClass))
-
-#define COMBINED_DIRECTION_GET_DIRECTION(d) \
- ((TpMediaStreamDirection) ((d) & TP_MEDIA_STREAM_DIRECTION_BIDIRECTIONAL))
-#define COMBINED_DIRECTION_GET_PENDING_SEND(d) \
- ((TpMediaStreamPendingSend) ((d) >> 2))
-#define MAKE_COMBINED_DIRECTION(d, p) \
- ((CombinedStreamDirection) ((d) | ((p) << 2)))
-
-gboolean haze_media_stream_error (HazeMediaStream *self, guint err_no,
- const gchar *message, GError **error);
-
-void haze_media_stream_close (HazeMediaStream *close);
-void haze_media_stream_hold (HazeMediaStream *stream, gboolean hold);
-gboolean haze_media_stream_change_direction (HazeMediaStream *stream,
- guint requested_dir, GError **error);
-void haze_media_stream_accept_pending_local_send (HazeMediaStream *stream);
-
-HazeMediaStream *haze_media_stream_new (const gchar *object_path,
- TpDBusDaemon *dbus_daemon,
- PurpleMedia *media,
- const gchar *name,
- const gchar *peer,
- guint media_type,
- guint id,
- gboolean created_locally,
- const gchar *nat_traversal,
- const GPtrArray *relay_info,
- gboolean local_hold);
-TpMediaStreamType haze_media_stream_get_media_type (HazeMediaStream *self);
-
-GList *haze_media_stream_get_local_candidates (HazeMediaStream *self);
-GList *haze_media_stream_get_codecs (HazeMediaStream *self);
-void haze_media_stream_add_remote_candidates (HazeMediaStream *self,
- GList *remote_candidates);
-void haze_media_stream_set_remote_codecs (HazeMediaStream *self,
- GList *remote_codecs);
-void haze_media_stream_add_stun_server (HazeMediaStream *self,
- const gchar *stun_ip,
- guint stun_port);
-
-G_END_DECLS
-
-#endif /* #ifndef __HAZE_MEDIA_STREAM_H__*/
diff --git a/src/notify.c b/src/notify.c
index 7eb0185..9485b6b 100644
--- a/src/notify.c
+++ b/src/notify.c
@@ -18,7 +18,9 @@
*
*/
+#include <config.h>
#include "notify.h"
+
#include "connection-mail.h"
#include "debug.h"
diff --git a/src/protocol.c b/src/protocol.c
index cd8593a..dc2fa64 100644
--- a/src/protocol.c
+++ b/src/protocol.c
@@ -31,6 +31,7 @@
#include <telepathy-glib/telepathy-glib.h>
#include "connection.h"
+#include "connection-avatars.h"
#include "debug.h"
G_DEFINE_TYPE (HazeProtocol, haze_protocol, TP_TYPE_BASE_PROTOCOL)
@@ -882,10 +883,32 @@ haze_protocol_identify_account (TpBaseProtocol *base,
return ret;
}
-static GStrv
-haze_protocol_get_interfaces (TpBaseProtocol *base)
+static GPtrArray *
+haze_protocol_get_interfaces_array (TpBaseProtocol *base)
{
- return g_new0 (gchar *, 1);
+ HazeProtocol *self = HAZE_PROTOCOL (base);
+ GPtrArray *interfaces;
+ GPtrArray *tmp;
+ guint i;
+
+ interfaces = TP_BASE_PROTOCOL_CLASS (
+ haze_protocol_parent_class)->get_interfaces_array (base);
+
+ /* Claim to implement Avatars only if we support avatars for this
+ * protocol. */
+ tmp = haze_connection_dup_implemented_interfaces (self->priv->prpl_info);
+ for (i = 0; i < tmp->len; i++)
+ {
+ if (!tp_strdiff (g_ptr_array_index (tmp, i),
+ TP_IFACE_CONNECTION_INTERFACE_AVATARS))
+ {
+ g_ptr_array_add (interfaces, TP_IFACE_PROTOCOL_INTERFACE_AVATARS);
+ break;
+ }
+ }
+ g_ptr_array_unref (tmp);
+
+ return interfaces;
}
static void
@@ -900,17 +923,29 @@ haze_protocol_get_connection_details (TpBaseProtocol *base,
if (connection_interfaces != NULL)
{
- *connection_interfaces = g_strdupv (
- (gchar **) haze_connection_get_implemented_interfaces ());
+ GPtrArray *tmp, *ifaces;
+ guint i;
+
+ tmp = haze_connection_dup_implemented_interfaces (
+ self->priv->prpl_info);
+
+ /* @connection_interfaces takes a NULL terminated (transfer full)
+ * gchar ** so we have to dup each string and append NULL. */
+ ifaces = g_ptr_array_new ();
+
+ for (i = 0; i < tmp->len; i++)
+ g_ptr_array_add (ifaces, g_strdup (g_ptr_array_index (tmp, i)));
+
+ g_ptr_array_add (ifaces, NULL);
+
+ *connection_interfaces = (gchar **) g_ptr_array_free (ifaces, FALSE);
+ g_ptr_array_unref (tmp);
}
if (channel_manager_types != NULL)
{
GType types[] = { HAZE_TYPE_IM_CHANNEL_FACTORY,
HAZE_TYPE_CONTACT_LIST,
-#ifdef ENABLE_MEDIA
- HAZE_TYPE_MEDIA_MANAGER,
-#endif
G_TYPE_INVALID };
*channel_manager_types = g_memdup (types, sizeof (types));
@@ -961,6 +996,41 @@ haze_protocol_dup_authentication_types (TpBaseProtocol *base)
}
static void
+haze_protocol_get_avatar_details (TpBaseProtocol *base,
+ GStrv *supported_mime_types,
+ guint *min_height,
+ guint *min_width,
+ guint *rec_height,
+ guint *rec_width,
+ guint *max_height,
+ guint *max_width,
+ guint *max_bytes)
+{
+ HazeProtocol *self = HAZE_PROTOCOL (base);
+ PurpleBuddyIconSpec *icon_spec;
+
+ icon_spec = &(self->priv->prpl_info->icon_spec);
+
+ if (icon_spec->format == NULL)
+ {
+ /* We don't support avatar for this protocol */
+ *supported_mime_types = NULL;
+ *min_height = 0;
+ *min_width = 0;
+ *rec_height = 0;
+ *rec_width = 0;
+ *max_height = 0;
+ *max_width = 0;
+ *max_bytes = 0;
+ return;
+ }
+
+ haze_connection_get_icon_spec_requirements (icon_spec, supported_mime_types,
+ min_height, min_width, rec_height, rec_width, max_height, max_width,
+ max_bytes);
+}
+
+static void
haze_protocol_class_init (HazeProtocolClass *cls)
{
GObjectClass *object_class = (GObjectClass *) cls;
@@ -971,10 +1041,11 @@ haze_protocol_class_init (HazeProtocolClass *cls)
base_class->new_connection = haze_protocol_new_connection;
base_class->normalize_contact = haze_protocol_normalize_contact;
base_class->identify_account = haze_protocol_identify_account;
- base_class->get_interfaces = haze_protocol_get_interfaces;
+ base_class->get_interfaces_array = haze_protocol_get_interfaces_array;
base_class->get_connection_details = haze_protocol_get_connection_details;
base_class->dup_authentication_types =
haze_protocol_dup_authentication_types;
+ base_class->get_avatar_details = haze_protocol_get_avatar_details;
g_type_class_add_private (cls, sizeof (HazeProtocolPrivate));
object_class->get_property = haze_protocol_get_property;
diff --git a/src/protocol.h b/src/protocol.h
index dd1792d..27c3460 100644
--- a/src/protocol.h
+++ b/src/protocol.h
@@ -23,7 +23,7 @@
#ifndef __HAZE_PROTOCOL_H__
#define __HAZE_PROTOCOL_H__
-#include <telepathy-glib/base-protocol.h>
+#include <telepathy-glib/telepathy-glib.h>
#include <libpurple/prpl.h>
diff --git a/src/util.c b/src/util.c
index 5cbb4fb..c29fc73 100644
--- a/src/util.c
+++ b/src/util.c
@@ -7,6 +7,7 @@
* notice and this notice are preserved.
*/
+#include <config.h>
#include "util.h"
#include <glib/gstdio.h>
diff --git a/tests/twisted/Makefile.am b/tests/twisted/Makefile.am
index 81b9118..da5d473 100644
--- a/tests/twisted/Makefile.am
+++ b/tests/twisted/Makefile.am
@@ -52,22 +52,10 @@ EXTRA_DIST = \
servicetest.py \
ns.py
-if MEDIA_ENABLED
-MEDIA_ENABLED_PYBOOL = True
-else
-MEDIA_ENABLED_PYBOOL = False
-endif
-
-config.py: Makefile
- $(AM_V_GEN) { \
- echo "MEDIA_ENABLED = $(MEDIA_ENABLED_PYBOOL)"; \
- } > $@
-
haze-twisted-tests.list: Makefile
$(AM_V_GEN)echo $(TWISTED_TESTS) > $@
BUILT_SOURCES = \
- config.py \
haze-twisted-tests.list \
run-test.sh \
$(NULL)
diff --git a/tests/twisted/cm/protocols.py b/tests/twisted/cm/protocols.py
index 4dc3f19..1e8d3a7 100644
--- a/tests/twisted/cm/protocols.py
+++ b/tests/twisted/cm/protocols.py
@@ -27,6 +27,14 @@ def test(q, bus, conn, stream):
protocol_iface = dbus.Interface(protocol, cs.PROTOCOL)
protocol_props = dbus.Interface(protocol, cs.PROPERTIES_IFACE)
flat_props = protocol_props.GetAll(cs.PROTOCOL)
+ protocol_avatar_props = protocol_props.GetAll(cs.PROTOCOL_IFACE_AVATARS)
+
+ # Protocol is supposed to implement Interface.Avatars iff the
+ # connection implements Avatars as well.
+ if cs.CONN_IFACE_AVATARS in flat_props['ConnectionInterfaces']:
+ assertContains(cs.PROTOCOL_IFACE_AVATARS, props[cs.PROTOCOL + '.Interfaces'])
+ else:
+ assertDoesNotContain(cs.PROTOCOL_IFACE_AVATARS, props[cs.PROTOCOL + '.Interfaces'])
parameters = cm_iface.GetParameters(name)
assertEquals(parameters, props[cs.PROTOCOL + '.Parameters'])
@@ -94,6 +102,20 @@ def test(q, bus, conn, stream):
protocol_iface.IdentifyAccount({
'account': 'smcv',
'server': 'irc.debian.org'}))
+
+ assertDoesNotContain(cs.CONN_IFACE_AVATARS, flat_props['ConnectionInterfaces'])
+ assertDoesNotContain(cs.CONN_IFACE_CONTACT_BLOCKING, flat_props['ConnectionInterfaces'])
+ assertDoesNotContain(cs.CONN_IFACE_MAIL_NOTIFICATION + '.DRAFT', flat_props['ConnectionInterfaces'])
+
+ # Avatar not supported
+ assertEquals(0, protocol_avatar_props['MaximumAvatarBytes'])
+ assertEquals(0, protocol_avatar_props['MaximumAvatarHeight'])
+ assertEquals(0, protocol_avatar_props['MaximumAvatarWidth'])
+ assertEquals(0, protocol_avatar_props['MinimumAvatarHeight'])
+ assertEquals(0, protocol_avatar_props['MinimumAvatarWidth'])
+ assertEquals(0, protocol_avatar_props['RecommendedAvatarHeight'])
+ assertEquals(0, protocol_avatar_props['RecommendedAvatarWidth'])
+ assertEquals([], protocol_avatar_props['SupportedAvatarMIMETypes'])
elif name == 'myspace':
assertEquals('x-myspace', flat_props['VCardField'])
assertEquals('im-myspace', flat_props['Icon'])
@@ -139,6 +161,20 @@ def test(q, bus, conn, stream):
'embrace-and-extend': r'WORKGROUP\Bill',
'password': 'letmein'})
q.expect('dbus-error', name=cs.INVALID_ARGUMENT)
+
+ assertContains(cs.CONN_IFACE_AVATARS, flat_props['ConnectionInterfaces'])
+ assertContains(cs.CONN_IFACE_CONTACT_BLOCKING, flat_props['ConnectionInterfaces'])
+ assertContains(cs.CONN_IFACE_MAIL_NOTIFICATION + '.DRAFT', flat_props['ConnectionInterfaces'])
+
+ # libpurple currently says there's no max size
+ assertEquals(0, protocol_avatar_props['MaximumAvatarBytes'])
+ assertEquals(96, protocol_avatar_props['MaximumAvatarHeight'])
+ assertEquals(96, protocol_avatar_props['MaximumAvatarWidth'])
+ assertEquals(32, protocol_avatar_props['MinimumAvatarHeight'])
+ assertEquals(32, protocol_avatar_props['MinimumAvatarWidth'])
+ assertEquals(0, protocol_avatar_props['RecommendedAvatarHeight'])
+ assertEquals(0, protocol_avatar_props['RecommendedAvatarWidth'])
+ assertEquals(['image/png'], protocol_avatar_props['SupportedAvatarMIMETypes'])
elif name == 'qq':
assertEquals('x-qq', flat_props['VCardField'])
assertEquals('im-qq', flat_props['Icon'])
diff --git a/tests/twisted/constants.py b/tests/twisted/constants.py
index 37d6d52..7bba99b 100644
--- a/tests/twisted/constants.py
+++ b/tests/twisted/constants.py
@@ -481,6 +481,7 @@ class SendError(object):
PROTOCOL = 'org.freedesktop.Telepathy.Protocol'
PROTOCOL_IFACE_PRESENCES = PROTOCOL + '.Interface.Presence'
PROTOCOL_IFACE_ADDRESSING = PROTOCOL + '.Interface.Addressing'
+PROTOCOL_IFACE_AVATARS = PROTOCOL + '.Interface.Avatars'
PARAM_REQUIRED = 1
PARAM_REGISTER = 2
diff --git a/tests/twisted/roster/groups.py b/tests/twisted/roster/groups.py
index 8f8f2c9..0420e19 100644
--- a/tests/twisted/roster/groups.py
+++ b/tests/twisted/roster/groups.py
@@ -14,7 +14,7 @@ import constants as cs
import ns
def test(q, bus, conn, stream):
- self_handle = conn.GetSelfHandle()
+ self_handle = conn.Properties.Get(cs.CONN, "SelfHandle")
# Close all Group channels to get a clean slate, so we can rely on
# the NewChannels signal for the default group later
diff --git a/tests/twisted/roster/publish.py b/tests/twisted/roster/publish.py
index f04abca..e8f5b2d 100644
--- a/tests/twisted/roster/publish.py
+++ b/tests/twisted/roster/publish.py
@@ -74,7 +74,7 @@ def test(q, bus, conn, stream):
args=['', [alice], [], [], [], 0, cs.GC_REASON_NONE]),
)
- self_handle = conn.GetSelfHandle()
+ self_handle = conn.Properties.Get(cs.CONN, "SelfHandle")
# accept
call_async(q, publish.Group, 'AddMembers', [alice], '')
diff --git a/tests/twisted/roster/subscribe.py b/tests/twisted/roster/subscribe.py
index f6225de..102ab71 100644
--- a/tests/twisted/roster/subscribe.py
+++ b/tests/twisted/roster/subscribe.py
@@ -13,7 +13,7 @@ import constants as cs
import ns
def test(q, bus, conn, stream):
- self_handle = conn.GetSelfHandle()
+ self_handle = conn.Properties.Get(cs.CONN, "SelfHandle")
# Close all Group channels to get a clean slate, so we can rely on
# the NewChannels signal for the default group later
diff --git a/tests/twisted/simple-caps.py b/tests/twisted/simple-caps.py
index d0088d3..d580c82 100644
--- a/tests/twisted/simple-caps.py
+++ b/tests/twisted/simple-caps.py
@@ -9,8 +9,6 @@ from servicetest import assertEquals, assertContains, EventPattern
from hazetest import exec_test, sync_stream, JabberXmlStream
import constants as cs
-import config
-
import ns
# assert this list of RCCs is only text
@@ -20,12 +18,8 @@ def check_text_only(rccs):
cs.TARGET_HANDLE_TYPE: cs.HT_CONTACT
}, [cs.TARGET_HANDLE])], rccs)
-# assert GetContactCaps and GetContactAttributes returns just text caps
+# assert just text caps
def check_rccs(conn, handle):
- rccs = conn.ContactCapabilities.GetContactCapabilities([handle])
- assertEquals(1, len(rccs))
- check_text_only(rccs[handle])
-
attrs = conn.Contacts.GetContactAttributes([handle],
[cs.CONN_IFACE_CONTACT_CAPS],
False)
@@ -66,32 +60,6 @@ def test_someone_else(q, bus, conn, stream):
amy_handle = conn.RequestHandles(cs.HT_CONTACT, ['amy@foo.com'])[0]
check_rccs(conn, amy_handle)
-def test_media(q, bus, conn, stream):
- sync_stream(q, stream)
-
- conn.ContactCapabilities.UpdateCapabilities([(
- 'im.telepathy1.Client.Foobar',
- [{ cs.CHANNEL_TYPE: cs.CHANNEL_TYPE_STREAMED_MEDIA,
- cs.TARGET_HANDLE_TYPE: cs.HT_CONTACT,
- cs.INITIAL_AUDIO: True },
- { cs.CHANNEL_TYPE: cs.CHANNEL_TYPE_STREAMED_MEDIA,
- cs.TARGET_HANDLE_TYPE: cs.HT_CONTACT,
- cs.INITIAL_VIDEO: True }],
- [],
- )])
-
- q.expect('stream-presence') # can't be bothered checking this
-
- conn.ContactCapabilities.UpdateCapabilities([(
- 'im.telepathy1.Client.Foobar',
- [], [])])
-
- q.expect('stream-presence') # can't be bothered checking this
-
if __name__ == '__main__':
exec_test(test_self_handle)
exec_test(test_someone_else, do_connect=False, protocol=JabberXmlStream)
-
- if config.MEDIA_ENABLED:
- exec_test(test_media)
-
diff --git a/tests/twisted/text/destroy.py b/tests/twisted/text/destroy.py
index 1b5e8fb..5860219 100644
--- a/tests/twisted/text/destroy.py
+++ b/tests/twisted/text/destroy.py
@@ -9,9 +9,10 @@ from twisted.words.xish import domish
from hazetest import exec_test
from servicetest import call_async, EventPattern, assertEquals
+import constants as cs
def test(q, bus, conn, stream):
- self_handle = conn.GetSelfHandle()
+ self_handle = conn.Properties.Get(cs.CONN, "SelfHandle")
jid = 'foo@bar.com'
call_async(q, conn, 'RequestHandles', 1, [jid])
diff --git a/tests/twisted/text/ensure.py b/tests/twisted/text/ensure.py
index 21876c3..2aebf8c 100644
--- a/tests/twisted/text/ensure.py
+++ b/tests/twisted/text/ensure.py
@@ -14,7 +14,7 @@ import pprint
import constants as cs
def test(q, bus, conn, stream):
- self_handle = conn.GetSelfHandle()
+ self_handle = conn.Properties.Get(cs.CONN, "SelfHandle")
jids = ['foo@bar.com', 'truc@cafe.fr']
call_async(q, conn, 'RequestHandles', 1, jids)
diff --git a/tests/twisted/text/initiate-requestotron.py b/tests/twisted/text/initiate-requestotron.py
index a116d2c..9e52c34 100644
--- a/tests/twisted/text/initiate-requestotron.py
+++ b/tests/twisted/text/initiate-requestotron.py
@@ -12,7 +12,7 @@ from servicetest import call_async, EventPattern
import constants as cs
def test(q, bus, conn, stream):
- self_handle = conn.GetSelfHandle()
+ self_handle = conn.Properties.Get(cs.CONN, "SelfHandle")
jid = 'foo@bar.com'
call_async(q, conn, 'RequestHandles', 1, [jid])
diff --git a/tests/twisted/text/initiate.py b/tests/twisted/text/initiate.py
index 88d8117..e93d318 100644
--- a/tests/twisted/text/initiate.py
+++ b/tests/twisted/text/initiate.py
@@ -8,9 +8,10 @@ from twisted.words.xish import domish
from hazetest import exec_test
from servicetest import call_async, EventPattern
+import constants as cs
def test(q, bus, conn, stream):
- self_handle = conn.GetSelfHandle()
+ self_handle = conn.Properties.Get(cs.CONN, "SelfHandle")
jid = 'foo@bar.com'
call_async(q, conn, 'RequestHandles', 1, [jid])
diff --git a/tests/twisted/text/respawn.py b/tests/twisted/text/respawn.py
index baf5a3d..52b5e88 100644
--- a/tests/twisted/text/respawn.py
+++ b/tests/twisted/text/respawn.py
@@ -8,9 +8,10 @@ from twisted.words.xish import domish
from hazetest import exec_test
from servicetest import call_async, EventPattern, assertEquals
+import constants as cs
def test(q, bus, conn, stream):
- self_handle = conn.GetSelfHandle()
+ self_handle = conn.Properties.Get(cs.CONN, "SelfHandle")
jid = 'foo@bar.com'
call_async(q, conn, 'RequestHandles', 1, [jid])
diff --git a/tools/glib-ginterface-gen.py b/tools/glib-ginterface-gen.py
index 13f7f69..6543146 100644
--- a/tools/glib-ginterface-gen.py
+++ b/tools/glib-ginterface-gen.py
@@ -701,7 +701,7 @@ class Generator(object):
self.h('#include <dbus/dbus-glib.h>')
if self.have_properties(nodes):
- self.h('#include <telepathy-glib/dbus-properties-mixin.h>')
+ self.h('#include <telepathy-glib/telepathy-glib.h>')
self.h('')
self.h('G_BEGIN_DECLS')