--- old-fs-sdpav/configure.ac 2005-10-10 15:21:26.208940456 +0300 +++ new-fs-sdpav/configure.ac 2005-09-22 20:27:34.000000000 +0300 @@ -173,6 +173,7 @@ farsight/plugins/msn/Makefile farsight/plugins/msnwebcam/Makefile farsight/plugins/yahoowebcam/Makefile +farsight/plugins/sdpav/Makefile farsight/tests/Makefile po/Makefile.in pkgconfig/Makefile diff -rN -u old-fs-sdpav/farsight/plugins/Makefile.am new-fs-sdpav/farsight/plugins/Makefile.am --- old-fs-sdpav/farsight/plugins/Makefile.am 2005-10-10 15:21:26.207940608 +0300 +++ new-fs-sdpav/farsight/plugins/Makefile.am 2005-09-22 19:56:55.000000000 +0300 @@ -1,4 +1,5 @@ SUBDIRS = \ msn \ msnwebcam \ -yahoowebcam +yahoowebcam \ +sdpav diff -rN -u old-fs-sdpav/farsight/plugins/sdpav/Makefile.am new-fs-sdpav/farsight/plugins/sdpav/Makefile.am --- old-fs-sdpav/farsight/plugins/sdpav/Makefile.am 1970-01-01 02:00:00.000000000 +0200 +++ new-fs-sdpav/farsight/plugins/sdpav/Makefile.am 2005-09-22 20:25:27.000000000 +0300 @@ -0,0 +1,13 @@ +pkgdir = $(libdir)/farsight + +pkg_LTLIBRARIES = libsdpav.la + +libsdpav_la_SOURCES = sdpav.c + +libsdpav_la_CFLAGS = $(GLIB_CFLAGS) $(GST_CFLAGS) $(SOFIASIP_CFLAGS) +libsdpav_la_LDFLAGS = -module -avoid-version $(SOFIASIP_LIBS) + +AM_CPPFLAGS = -I$(top_srcdir) + +# headers we need but don't want installed +noinst_HEADERS = sdpav.h diff -rN -u old-fs-sdpav/farsight/plugins/sdpav/sdpav.c new-fs-sdpav/farsight/plugins/sdpav/sdpav.c --- old-fs-sdpav/farsight/plugins/sdpav/sdpav.c 1970-01-01 02:00:00.000000000 +0200 +++ new-fs-sdpav/farsight/plugins/sdpav/sdpav.c 2005-09-30 18:25:07.000000000 +0300 @@ -0,0 +1,437 @@ +/* + * SDP Audio/video media module + * + * Copyright (C) 2005 Nokia Corporation. + * @author Kai Vehmanen + * + * Based on msnwebcam.c, + * Copyright (C) 2005 Rob Taylor, Philippe Khalaf + * + * This program 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 of the License, or + * (at your option) any later version. + * + * This program 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 General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/** + * TODO: + * + * - add the missing function implementations + * - mechanism to pass configuration params (audio, + * video devices to use, etc) + * - SDP filtering; raise an error/warning if irrelevant + * fields are passed to sdpav - there should be a clear + * definition of what parts of SDP/RFC2327 are to be used + * - session hold/pause + * - multi-party scenarios (audio from/to multiple + * remote recipients mixed locally to one device) + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include + +#include "sdpav.h" + +enum { + ARG_0, + ARG_AUDIO, /**< XXX: remove? */ + ARG_VIDEO, /**< XXX: remove? */ + ARG_CAPS_SDP, /**< Static capabilities offered by SDP A/V */ + ARG_LOCAL_SDP, /**< Current local configuration */ + ARG_REMOTE_SDP /**< Current remote configuration */ +}; + +enum { + FS_SDPAV_SIG_LOCAL_SDP, + FS_SDPAV_SIG_REMOTE_SDP, + FS_SDPAV_SIG_UPDATE, + FS_SDPAV_SIG_LAST +}; + +/* XXX: remove, no longer neede, a simple boolean + * var might be enough */ +#define FS_SDPAV_VERSION_MAX (1 << 15) + +static void farsight_sdpav_class_init (FarsightSDPAVClass *class); +static void farsight_sdpav_init (FarsightSDPAV *self); + +static void farsight_sdpav_connect (FarsightProtocol *protocol); +static void farsight_sdpav_disconnect (FarsightProtocol *protocol); +static GstElement * +farsight_sdpav_create_bin (FarsightProtocol *protocol); + +static void farsight_sdpav_finalize (GObject *object); +static void farsight_sdpav_set_property (GObject *object, + guint prop_id, + const GValue *value, + GParamSpec *pspec); +static void farsight_sdpav_get_property (GObject *object, + guint prop_id, + GValue *value, + GParamSpec *pspec); + +static void farsight_sdpav_update (FarsightSDPAV *self); + +static void fssdpav_update_recv_elements(FarsightSDPAV *self); +static void fssdpav_update_send_elements(FarsightSDPAV *self); + +static GObjectClass *parent_class = NULL; +static guint farsight_sdpav_signals[FS_SDPAV_SIG_LAST] = { 0 }; + +GType +farsight_sdpav_get_type (void) +{ + static GType type = 0; + + if (type == 0) { + static const GTypeInfo info = { + sizeof (FarsightSDPAVClass), + NULL, + NULL, + (GClassInitFunc) farsight_sdpav_class_init, + NULL, + NULL, + sizeof (FarsightSDPAV), + 0, + (GInstanceInitFunc) farsight_sdpav_init + }; + + type = g_type_register_static (FARSIGHT_PROTOCOL_TYPE, + "FarsightSDPAVType", + &info, 0); + } + + return type; +} + +static void +farsight_sdpav_class_init (FarsightSDPAVClass *class) +{ + GObjectClass *gobject_class; + FarsightProtocolClass *farsight_protocol_class; + + gobject_class = (GObjectClass *) class; + farsight_protocol_class = (FarsightProtocolClass*) class; + parent_class = g_type_class_peek_parent (class); + + farsight_protocol_class->connect = farsight_sdpav_connect; + farsight_protocol_class->disconnect = farsight_sdpav_disconnect; + farsight_protocol_class->create_bin = farsight_sdpav_create_bin; + + class->update = farsight_sdpav_update; + + gobject_class->finalize = farsight_sdpav_finalize; + + gobject_class->set_property = farsight_sdpav_set_property; + gobject_class->get_property = farsight_sdpav_get_property; + + /* XXX: idea - use boolean properties to request which + * media to initialise */ + + /* property: audio (enable/disable) */ + /* XXX: won't work... */ + g_object_class_install_property(G_OBJECT_CLASS(class), + ARG_AUDIO, + g_param_spec_boolean("audio", "Audio", "Enable audio.", FALSE, G_PARAM_READWRITE)); + + /* property: video (enable/disable) */ + /* XXX: won't work... */ + g_object_class_install_property(G_OBJECT_CLASS(class), + ARG_VIDEO, + g_param_spec_boolean("video", "Video", "Enable video.", FALSE, G_PARAM_READWRITE)); + + /* property: caps_sdp */ + g_object_class_install_property(G_OBJECT_CLASS(class), + ARG_CAPS_SDP, + g_param_spec_string("local_sdp", "Local SDP", "Static capabilities SDP.", NULL, G_PARAM_CONSTRUCT_ONLY | G_PARAM_READABLE)); + + /* property: local_sdp */ + g_object_class_install_property(G_OBJECT_CLASS(class), + ARG_LOCAL_SDP, + g_param_spec_string("local_sdp", "Local SDP", "Set local SDP.", NULL, G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE)); + + /* property: remote_sdp */ + g_object_class_install_property(G_OBJECT_CLASS(class), + ARG_REMOTE_SDP, + g_param_spec_string("remote_sdp", "Remote SDP", "Set remote SDP.", NULL, G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE)); + + /* XXX: idea - deliver local and remote SDP as properties, + * and then use "update" method to trigger + * gst pipeline reconfiguration */ + + /* methods to update the local state + * + * ref: name, itype, flags, cl_closure, acc, acc_data, c_marsh, + * rettype, n_params, par_types + **/ + + farsight_sdpav_signals[FS_SDPAV_SIG_UPDATE] + = g_signal_new("update", G_TYPE_FROM_CLASS(class), G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET(FarsightSDPAVClass, update), + NULL, NULL, g_cclosure_marshal_VOID__VOID, + G_TYPE_NONE, 0, NULL); +} + +static void +farsight_sdpav_init (FarsightSDPAV *self) +{ + self->l_sdp_mod = FALSE; + self->r_sdp_mod = FALSE; + self->l_sdp = NULL; + self->r_sdp = NULL; + self->c_sdp = NULL; +} + +/** + * Actives the protocol plugin. Resources are + * reserved and described using object properties. + */ +static void +farsight_sdpav_connect (FarsightProtocol *protocol) +{ + FarsightSDPAV *self; + + g_return_if_fail (protocol != NULL); + + self = FARSIGHT_SDPAV (protocol); + + farsight_sdpav_update(self); + + FARSIGHT_PROTOCOL_CLASS (parent_class)->connected (FARSIGHT_PROTOCOL (self)); +} + +static void +farsight_sdpav_disconnect (FarsightProtocol *protocol) +{ + FarsightSDPAV *self; + + g_return_if_fail (protocol != NULL); + + self = FARSIGHT_SDPAV (protocol); + + free(self->c_sdp); + free(self->l_sdp); + free(self->r_sdp); + + /* XXX: + * - free any resources that are not owned by + * the bin (which is freed by fs middleware) + */ +} + +static GstElement * +farsight_sdpav_create_bin (FarsightProtocol *protocol) +{ + FarsightSDPAV *self; + + g_return_val_if_fail (protocol != NULL, NULL); + + self = FARSIGHT_SDPAV (protocol); + + farsight_sdpav_update(self); + + return self->bin; +} + +static void +farsight_sdpav_finalize (GObject *object) +{ + FarsightSDPAV *self = NULL; + + g_message("in sdpav finalize!\n"); + + self = FARSIGHT_SDPAV (object); + g_return_if_fail (self != NULL); + g_return_if_fail (FARSIGHT_IS_SDPAV (self)); + + G_OBJECT_CLASS (parent_class)->finalize (object); +} + +static void +farsight_sdpav_set_property (GObject *object, + guint prop_id, + const GValue *value, + GParamSpec *pspec) +{ + FarsightSDPAV *self; + + g_return_if_fail (FARSIGHT_IS_SDPAV (object)); + + self = FARSIGHT_SDPAV (object); + + switch (prop_id) { + case ARG_AUDIO: + g_message ("enabling media: audio (unimplemented)"); + /* XXX: modify local SDP */ + break; + + case ARG_VIDEO: + g_message ("enabling media: video (unimplemented)"); + /* XXX: modify local SDP */ + break; + + case ARG_CAPS_SDP: + /* readonly prop */ + break; + + case ARG_LOCAL_SDP: + g_message ("set local SDP"); + if (self->l_sdp) free(self->l_sdp); + self->l_sdp = g_value_dup_string(value); + /* XXX: inc version only if content changed + * - simplest version: do not compare at all + * - next step, strcmp() old and new SDP + * - next: parse the SDP, and compare each element + * to the gst bin and see if modifications are needed + **/ + //self->l_sdp_ver = (++self->l_sdp_ver % FS_SDPAV_VERSION_MAX); + self->l_sdp_mod = TRUE; + break; + + case ARG_REMOTE_SDP: + g_message ("set remote SDP"); + if (self->l_sdp) free(self->l_sdp); + self->r_sdp = g_value_dup_string(value); + /* XXX: inc version only if content changed + * - see comments above for ARG_LOCAL_SDP */ + //self->r_sdp_ver = (++self->r_sdp_ver % FS_SDPAV_VERSION_MAX); + self->r_sdp_mod = TRUE; + break; + } +} + +static void +farsight_sdpav_get_property (GObject *object, + guint prop_id, + GValue *value, + GParamSpec *pspec) +{ + FarsightSDPAV *self; + + g_return_if_fail (FARSIGHT_IS_SDPAV (object)); + self = FARSIGHT_SDPAV (object); + + switch (prop_id) + { + case ARG_CAPS_SDP: { + g_value_set_string (value, self->c_sdp); + break; + } + case ARG_LOCAL_SDP: { + g_value_set_string (value, self->l_sdp); + break; + } + case ARG_REMOTE_SDP: { + g_value_set_string (value, self->r_sdp); + break; + } + default: { + g_warning("%s: unknown property %u.\n", __func__, prop_id); + } + } +} + +/** + * Updates the media configuration. If any changes + * are required, an updated bin will be created + * + * @pre bin must not be in playing state + */ +static void farsight_sdpav_update (FarsightSDPAV *self) +{ + gboolean changes = FALSE; + + g_debug(__func__); + + /* Step A: check if either local or remote SDP has + * changed or is not yet created */ + /* Step B: modify the pipelines + * - will update the local SDP (port numbers, + * unavailable media and codecs) */ + + if (self->l_sdp_mod) { + fssdpav_update_recv_elements(self); + self->l_sdp_mod = FALSE; + changes = TRUE; + } + + if (self->r_sdp_mod) { + fssdpav_update_send_elements(self); + self->r_sdp_mod = FALSE; + changes = TRUE; + } + + /** + * Step C: store version numbers + * - versions of local and remote SDP used for + * creating the new bin + * - XXX: or are the [lr]_sdp_mod flags enough? + */ + + /* Step D: signal state changes */ + if (changes) { + /* will trigger get_bin() */ + FARSIGHT_PROTOCOL_CLASS (parent_class)->connected (FARSIGHT_PROTOCOL (self)); + } +} + +static void fssdpav_update_recv_elements(FarsightSDPAV *self) +{ + /* XXX: update the recv-part of the bin + * - note either recreate the element (if yes, how to + * make sure the top-level pipeline is not running) + * - ..or update on the fly + * - after update is ready, the local modify should + * be updated to match the current state: + * - change port numbers for each media + * - add necessary attributes (for example to signal + * RTCP-port if not RTP-port+1) + * - remove/disable media/codecs that are not available + * or failed during intialization + **/ +} + +static void fssdpav_update_send_elements(FarsightSDPAV *self) +{ + /* XXX: update the recv-part of the bin + * - query the remote transport address(es) and + * pass them to the appropriate gst elements + * - note: no need to modify the SDP (only needed + * for local SDP + */ +} + +static gboolean +init_plugin (FarsightPlugin *plugin) +{ + if (!farsight_protocol_register (plugin, FARSIGHT_TYPE_SDPAV)) + return FALSE; + return TRUE; +} + +static FarsightPluginInfo plugin_info = { + FARSIGHT_MAJOR_VERSION, + FARSIGHT_MINOR_VERSION, + + "SDP Audio/Video", /* description */ + "0.1.0", /* version */ + "Farsight Project", /* author */ + "http://farsight.sf.net/", /* homepage */ + NULL, /* load */ + NULL /* unload */ +}; + +FARSIGHT_INIT_PLUGIN (init_plugin, plugin_info); diff -rN -u old-fs-sdpav/farsight/plugins/sdpav/sdpav.h new-fs-sdpav/farsight/plugins/sdpav/sdpav.h --- old-fs-sdpav/farsight/plugins/sdpav/sdpav.h 1970-01-01 02:00:00.000000000 +0200 +++ new-fs-sdpav/farsight/plugins/sdpav/sdpav.h 2005-09-30 13:45:48.000000000 +0300 @@ -0,0 +1,97 @@ +/* + * Farsight Voice+Video library + * Copyright (C) 2005 Nokia Corporation. + * @author Kai Vehmanen + * + * Based on msnwebcam.c, + * Copyright (C) 2005 Rob Taylor, Philippe Khalaf + * + * This program 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 of the License, or + * (at your option) any later version. + * + * This program 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 General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef __FARSIGHT_SDPAV_H__ +#define __FARSIGHT_SDPAV_H__ + +#include +#include + +#include + +#include /* sofia header */ + +G_BEGIN_DECLS + + +/* TYPE MACROS */ +#define FARSIGHT_TYPE_SDPAV \ + (farsight_sdpav_get_type()) +#define FARSIGHT_SDPAV(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST((obj), FARSIGHT_TYPE_SDPAV, FarsightSDPAV)) +#define FARSIGHT_SDPAV_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST((klass), FARSIGHT_TYPE_SDPAV, FarsightSDPAVClass)) +#define FARSIGHT_IS_SDPAV(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE((obj), FARSIGHT_TYPE_SDPAV)) +#define FARSIGHT_IS_SDPAV_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_TYPE((klass), FARSIGHT_TYPE_SDPAV)) +#define FARSIGHT_SDPAV_GET_CLASS(obj) \ + (G_TYPE_INSTANCE_GET_CLASS ((obj), FARSIGHT_TYPE_SDPAV, FarsightSDPAVClass)) + +typedef struct _FarsightSDPAV FarsightSDPAV; +typedef struct _FarsightSDPAVClass FarsightSDPAVClass; + +struct _FarsightSDPAVClass { + FarsightProtocolClass parent_class; + + /* private: */ + + GstElement *send_pipeline; + GstElement *recv_pipeline; + + int l_sdp_ver; + int r_sdp_ver; + + /* public: */ + + /** + * Update the media subsystem configuration based + * on the properties "local_sdp" and "remote_sdp". + */ + void (*update)(FarsightSDPAV *self); +}; + +struct _FarsightSDPAV { + FarsightProtocol parent; + + /* private: */ + + GstElement *bin; + GstElement *send_pipeline; + GstElement *recv_pipeline; + + gchar *l_sdp; /**< local SDP as ascii */ + gchar *r_sdp; /**< remote SDP as ascii */ + gchar *c_sdp; /**< caps SDP as ascii */ + + gboolean l_sdp_mod; + gboolean r_sdp_mod; + + /* public: */ +}; + +GType farsight_sdpav_get_type (void); + +G_END_DECLS + +#endif