Move the lib out of gst-libs
Olivier CrĂȘte
12 years ago
21 | 21 | transmitters/rawudp/fs-rawudp-marshal.[ch] |
22 | 22 | transmitters/rawudp/fs-rawudp-marshal.list |
23 | 23 | |
24 | gst-libs/gst/farstream/fs-marshal.[ch] | |
25 | gst-libs/gst/farstream/fs-marshal.list | |
26 | gst-libs/gst/farstream/fs-enum-types.h | |
27 | gst-libs/gst/farstream/fs-enumtypes.[ch] | |
24 | farstream/fs-marshal.[ch] | |
25 | farstream/fs-marshal.list | |
26 | farstream/fs-enum-types.h | |
27 | farstream/fs-enumtypes.[ch] | |
28 | 28 | |
29 | 29 | docs/libs/farstream-libs-decl-list.txt |
30 | 30 | docs/libs/farstream-libs-decl-list.txt.bak |
6 | 6 | endif |
7 | 7 | |
8 | 8 | SUBDIRS = \ |
9 | gst-libs \ | |
9 | farstream \ | |
10 | 10 | gst $(SUBDIRS_EXT) \ |
11 | 11 | transmitters \ |
12 | 12 | $(PYTHON_SUBDIR) \ |
19 | 19 | # pkgconfig |
20 | 20 | |
21 | 21 | DIST_SUBDIRS = \ |
22 | gst-libs \ | |
22 | farstream \ | |
23 | 23 | gst $(SUBDIRS_EXT) \ |
24 | 24 | transmitters \ |
25 | 25 | python \ |
2 | 2 | |
3 | 3 | DIE=0 |
4 | 4 | package=farstream |
5 | srcfile=gst-libs/gst/farstream/fs-candidate.c | |
5 | srcfile=farstream/fs-candidate.c | |
6 | 6 | |
7 | 7 | # Make sure we have common |
8 | 8 | if test ! -f common/gst-autogen.sh; |
20 | 20 | AS_NANO(FS_CVS="no", FS_CVS="yes") |
21 | 21 | |
22 | 22 | dnl can autoconf find the source ? |
23 | AC_CONFIG_SRCDIR([gst-libs/gst/farstream/fs-candidate.c]) | |
23 | AC_CONFIG_SRCDIR([farstream/fs-conference.c]) | |
24 | 24 | |
25 | 25 | dnl define the output header for config |
26 | 26 | AM_CONFIG_HEADER([config.h]) |
306 | 306 | dnl FS_INTERNAL_CFLAGS |
307 | 307 | dnl prefer internal headers to already installed ones |
308 | 308 | dnl also add builddir include for enumtypes and marshal |
309 | FS_INTERNAL_CFLAGS="-I\$(top_srcdir)/gst-libs -I\$(top_builddir)/gst-libs" | |
309 | FS_INTERNAL_CFLAGS="-I\$(top_srcdir) -I\$(top_builddir)" | |
310 | 310 | AC_SUBST(FS_INTERNAL_CFLAGS) |
311 | 311 | |
312 | 312 | dnl FIXME: do we want to rename to GST_ALL_* ? |
401 | 401 | gst/funnel/Makefile |
402 | 402 | gst/rtcpfilter/Makefile |
403 | 403 | gst/videoanyrate/Makefile |
404 | gst-libs/Makefile | |
405 | gst-libs/gst/Makefile | |
406 | gst-libs/gst/farstream/Makefile | |
404 | farstream/Makefile | |
407 | 405 | transmitters/Makefile |
408 | 406 | transmitters/rawudp/Makefile |
409 | 407 | transmitters/multicast/Makefile |
45 | 45 | # this is useful ;) |
46 | 46 | |
47 | 47 | SCANOBJ_DEPS = \ |
48 | $(top_builddir)/gst-libs/gst/farstream/libfarstream-@GST_MAJORMINOR@.la | |
48 | $(top_builddir)/farstream/libfarstream-@GST_MAJORMINOR@.la | |
49 | 49 | |
50 | 50 | # Header files to ignore when scanning. |
51 | 51 | IGNORE_HFILES = fs-marshal.h fs-enumtypes.h fs-private.h |
63 | 63 | # contains GtkObjects/GObjects and you want to document signals and properties. |
64 | 64 | GTKDOC_CFLAGS = $(FS_INTERNAL_CFLAGS) $(GST_PLUGINS_BASE_CFLAGS) $(GST_BASE_CFLAGS) |
65 | 65 | GTKDOC_LIBS = -static \ |
66 | $(top_builddir)/gst-libs/gst/farstream/libfarstream-0.10.la \ | |
66 | $(top_builddir)/farstream/libfarstream-0.10.la \ | |
67 | 67 | $(GST_BASE_LIBS) \ |
68 | 68 | $(GCOV_LIBS) |
69 | 69 |
0 | 0 | <SECTION> |
1 | 1 | <FILE>fs-participant</FILE> |
2 | 2 | <TITLE>FsParticipant</TITLE> |
3 | <INCLUDE>gst/farstream/fs-conference.h</INCLUDE> | |
3 | <INCLUDE>farstream/fs-conference.h</INCLUDE> | |
4 | 4 | FsParticipant |
5 | 5 | FsParticipantClass |
6 | 6 | FS_PARTICIPANT_DATA_LOCK |
20 | 20 | <SECTION> |
21 | 21 | <FILE>fs-stream</FILE> |
22 | 22 | <TITLE>FsStream</TITLE> |
23 | <INCLUDE>gst/farstream/fs-conference.h</INCLUDE> | |
23 | <INCLUDE>farstream/fs-conference.h</INCLUDE> | |
24 | 24 | FsStream |
25 | 25 | FsStreamClass |
26 | 26 | FsStreamDirection |
51 | 51 | FsDTMFEvent |
52 | 52 | FsDTMFMethod |
53 | 53 | <TITLE>FsSession</TITLE> |
54 | <INCLUDE>gst/farstream/fs-conference.h</INCLUDE> | |
54 | <INCLUDE>farstream/fs-conference.h</INCLUDE> | |
55 | 55 | FsSession |
56 | 56 | FsSessionClass |
57 | 57 | fs_session_new_stream |
83 | 83 | <SECTION> |
84 | 84 | <FILE>fs-conference</FILE> |
85 | 85 | <TITLE>FsConference</TITLE> |
86 | <INCLUDE>gst/farstream/fs-conference.h</INCLUDE> | |
86 | <INCLUDE>farstream/fs-conference.h</INCLUDE> | |
87 | 87 | FsConference |
88 | 88 | fs_conference_new_session |
89 | 89 | fs_conference_new_participant |
103 | 103 | <SECTION> |
104 | 104 | <FILE>fs-candidate</FILE> |
105 | 105 | <TITLE>FsCandidate</TITLE> |
106 | <INCLUDE>gst/farstream/fs-conference.h</INCLUDE> | |
106 | <INCLUDE>farstream/fs-conference.h</INCLUDE> | |
107 | 107 | FsCandidate |
108 | 108 | FsCandidateType |
109 | 109 | FsNetworkProtocol |
123 | 123 | <SECTION> |
124 | 124 | <FILE>fs-codec</FILE> |
125 | 125 | <TITLE>FsCodec</TITLE> |
126 | <INCLUDE>gst/farstream/fs-conference.h</INCLUDE> | |
126 | <INCLUDE>farstream/fs-conference.h</INCLUDE> | |
127 | 127 | FsCodec |
128 | 128 | FsMediaType |
129 | 129 | FsCodecParameter |
158 | 158 | <SECTION> |
159 | 159 | <FILE>fs-transmitter</FILE> |
160 | 160 | <TITLE>FsTransmitter</TITLE> |
161 | <INCLUDE>gst/farstream/fs-transmitter.h</INCLUDE> | |
161 | <INCLUDE>farstream/fs-transmitter.h</INCLUDE> | |
162 | 162 | FsTransmitter |
163 | 163 | FsTransmitterClass |
164 | 164 | fs_transmitter_new |
182 | 182 | <SECTION> |
183 | 183 | <FILE>fs-stream-transmitter</FILE> |
184 | 184 | <TITLE>FsStreamTransmitter</TITLE> |
185 | <INCLUDE>gst/farstream/fs-transmitter.h</INCLUDE> | |
185 | <INCLUDE>farstream/fs-transmitter.h</INCLUDE> | |
186 | 186 | FsStreamTransmitter |
187 | 187 | FsStreamTransmitterClass |
188 | 188 | fs_stream_transmitter_add_remote_candidates |
205 | 205 | <SECTION> |
206 | 206 | <FILE>fs-plugin</FILE> |
207 | 207 | <TITLE>FsPlugin</TITLE> |
208 | <INCLUDE>gst/farstream/fs-plugin.h</INCLUDE> | |
208 | <INCLUDE>farstream/fs-plugin.h</INCLUDE> | |
209 | 209 | FsPlugin |
210 | 210 | fs_plugin_create_valist |
211 | 211 | fs_plugin_create |
226 | 226 | <SECTION> |
227 | 227 | <FILE>fs-element-added-notifier</FILE> |
228 | 228 | <TITLE>FsElementAddedNotifier</TITLE> |
229 | <INCLUDE>gst/farstream/fs-element-added-notifier.h</INCLUDE> | |
229 | <INCLUDE>farstream/fs-element-added-notifier.h</INCLUDE> | |
230 | 230 | FsElementAddedNotifier |
231 | 231 | fs_element_added_notifier_new |
232 | 232 | fs_element_added_notifier_add |
248 | 248 | <SECTION> |
249 | 249 | <FILE>fs-rtp</FILE> |
250 | 250 | <TITLE>RTP Specific types</TITLE> |
251 | <INCLUDE>gst/farstream/fs-rtp.h</INCLUDE> | |
251 | <INCLUDE>farstream/fs-rtp.h</INCLUDE> | |
252 | 252 | FsRtpHeaderExtension |
253 | 253 | fs_rtp_header_extension_new |
254 | 254 | fs_rtp_header_extension_copy |
269 | 269 | <SECTION> |
270 | 270 | <FILE>fs-utils</FILE> |
271 | 271 | <TITLE>Utility functions</TITLE> |
272 | <INCLUDE>gst/farstream/fs-utils.h</INCLUDE> | |
272 | <INCLUDE>farstream/fs-utils.h</INCLUDE> | |
273 | 273 | fs_utils_set_bitrate |
274 | 274 | fs_utils_get_default_codec_preferences |
275 | 275 | fs_utils_get_default_element_properties |
5 | 5 | % - change output file name from gstreamer-(whatever).html to (whatever).html |
6 | 6 | % - document properties and signals |
7 | 7 | |
8 | #include "../../gst-libs/gst/farstream/fs-participant.h" | |
9 | #include "../../gst-libs/gst/farstream/fs-session.h" | |
10 | #include "../../gst-libs/gst/farstream/fs-stream.h" | |
11 | #include "../../gst-libs/gst/farstream/fs-conference.h" | |
12 | #include "../../gst-libs/gst/farstream/fs-transmitter.h" | |
13 | #include "../../gst-libs/gst/farstream/fs-stream-transmitter.h" | |
14 | #include "../../gst-libs/gst/farstream/fs-element-added-notifier.h" | |
8 | #include "../../farstream/fs-participant.h" | |
9 | #include "../../farstream/fs-session.h" | |
10 | #include "../../farstream/fs-stream.h" | |
11 | #include "../../farstream/fs-conference.h" | |
12 | #include "../../farstream/fs-transmitter.h" | |
13 | #include "../../farstream/fs-stream-transmitter.h" | |
14 | #include "../../farstream/fs-element-added-notifier.h" | |
15 | 15 | |
16 | 16 | fs_participant_get_type |
17 | 17 | fs_session_get_type |
125 | 125 | # contains GtkObjects/GObjects and you want to document signals and properties. |
126 | 126 | GTKDOC_CFLAGS = $(GST_BASE_CFLAGS) -I$(top_builddir) -I$(top_builddir)/gst-libs |
127 | 127 | GTKDOC_LIBS = \ |
128 | $(top_builddir)/gst-libs/gst/farstream/libfarstream-0.10.la \ | |
128 | $(top_builddir)/farstream/libfarstream-0.10.la \ | |
129 | 129 | $(top_builddir)/gst/fsrtpconference/libfsrtpconference_doc.la \ |
130 | 130 | $(top_builddir)/gst/fsrawconference/libfsrawconference_doc.la \ |
131 | 131 | $(top_builddir)/gst/fsmsnconference/libfsmsnconference_doc.la \ |
9 | 9 | $(CFLAGS) |
10 | 10 | |
11 | 11 | LDADD = \ |
12 | $(top_builddir)/gst-libs/gst/farstream/libfarstream-0.10.la \ | |
12 | $(top_builddir)/farstream/libfarstream-0.10.la \ | |
13 | 13 | $(GST_LIBS) |
14 | 14 | |
15 | 15 |
33 | 33 | #include <gio/gunixinputstream.h> |
34 | 34 | #include <gst/gst.h> |
35 | 35 | |
36 | #include <gst/farstream/fs-conference.h> | |
36 | #include <farstream/fs-conference.h> | |
37 | 37 | |
38 | 38 | #define DEFAULT_AUDIOSRC "audiotestsrc is-live=1 ! audio/x-raw-int, rate=8000 ! identity" |
39 | 39 | #define DEFAULT_AUDIOSINK "alsasink sync=false async=false" |
29 | 29 | |
30 | 30 | #include <glib.h> |
31 | 31 | #include <gst/gst.h> |
32 | #include <gst/farstream/fs-conference.h> | |
32 | #include <farstream/fs-conference.h> | |
33 | 33 | |
34 | 34 | #define DEFAULT_AUDIOSRC "alsasrc" |
35 | 35 | #define DEFAULT_AUDIOSINK "audioconvert ! audioresample ! audioconvert ! alsasink" |
0 | libfarstreamincludedir = $(includedir)/farstream-@FS_MAJORMINOR@/farstream | |
1 | ||
2 | libfarstreaminclude_HEADERS = \ | |
3 | fs-candidate.h \ | |
4 | fs-codec.h \ | |
5 | fs-participant.h \ | |
6 | fs-session.h \ | |
7 | fs-stream.h \ | |
8 | fs-conference.h \ | |
9 | fs-transmitter.h \ | |
10 | fs-stream-transmitter.h \ | |
11 | fs-plugin.h \ | |
12 | fs-element-added-notifier.h \ | |
13 | fs-utils.h \ | |
14 | fs-rtp.h | |
15 | ||
16 | nodist_libfarstreaminclude_HEADERS = \ | |
17 | fs-enumtypes.h | |
18 | ||
19 | ||
20 | lib_LTLIBRARIES = libfarstream-@GST_MAJORMINOR@.la | |
21 | ||
22 | BUILT_SOURCES = \ | |
23 | $(nodist_libfarstream_@GST_MAJORMINOR@_la_SOURCES) \ | |
24 | $(nodist_libfarstreaminclude_HEADERS) | |
25 | ||
26 | CLEANFILES = $(BUILT_SOURCES) fs-marshal.list | |
27 | ||
28 | libfarstream_@GST_MAJORMINOR@_la_SOURCES = \ | |
29 | fs-candidate.c \ | |
30 | fs-codec.c \ | |
31 | fs-participant.c \ | |
32 | fs-session.c \ | |
33 | fs-stream.c \ | |
34 | fs-conference.c \ | |
35 | fs-transmitter.c \ | |
36 | fs-stream-transmitter.c \ | |
37 | fs-plugin.c \ | |
38 | fs-element-added-notifier.c \ | |
39 | fs-utils.c \ | |
40 | fs-rtp.c \ | |
41 | fs-private.h | |
42 | ||
43 | nodist_libfarstream_@GST_MAJORMINOR@_la_SOURCES = \ | |
44 | fs-marshal.c \ | |
45 | fs-marshal.h \ | |
46 | fs-enumtypes.c | |
47 | ||
48 | ||
49 | fs-marshal.list: $(libfarstream_@GST_MAJORMINOR@_la_SOURCES) Makefile.am | |
50 | $(AM_V_GEN) ( cd $(srcdir) && \ | |
51 | sed -n -e 's/.*_fs_marshal_\([[:upper:][:digit:]]*__[[:upper:][:digit:]_]*\).*/\1/p' \ | |
52 | $(libfarstream_@GST_MAJORMINOR@_la_SOURCES) ) \ | |
53 | | sed -e 's/__/:/' -e 'y/_/,/' | sort -u > $@.tmp | |
54 | @if cmp -s $@.tmp $@; then \ | |
55 | rm $@.tmp; \ | |
56 | touch $@; \ | |
57 | else \ | |
58 | mv $@.tmp $@; \ | |
59 | fi | |
60 | ||
61 | libfarstream_@GST_MAJORMINOR@_la_CFLAGS = \ | |
62 | $(FS_INTERNAL_CFLAGS) $(FS_CFLAGS) \ | |
63 | $(GST_PLUGINS_BASE_CFLAGS) \ | |
64 | $(GST_BASE_CFLAGS) \ | |
65 | $(GST_CFLAGS) | |
66 | libfarstream_@GST_MAJORMINOR@_la_LIBADD = \ | |
67 | $(GST_BASE_LIBS) \ | |
68 | $(GST_LIBS) | |
69 | libfarstream_@GST_MAJORMINOR@_la_LDFLAGS = \ | |
70 | $(FS_LIB_LDFLAGS) \ | |
71 | $(FS_ALL_LDFLAGS) \ | |
72 | $(FS_LT_LDFLAGS) | |
73 | ||
74 | ||
75 | public_headers = fs-candidate.h \ | |
76 | fs-codec.h \ | |
77 | fs-participant.h \ | |
78 | fs-session.h \ | |
79 | fs-stream.h \ | |
80 | fs-conference.h \ | |
81 | fs-utils.h | |
82 | ||
83 | glib_enum_headers=$(public_headers) | |
84 | glib_enum_define=FS | |
85 | glib_gen_prefix=_fs | |
86 | glib_gen_basename=fs | |
87 | ||
88 | include $(top_srcdir)/common-modified/gst-glib-gen.mak | |
89 | ||
90 | if HAVE_INTROSPECTION | |
91 | include $(INTROSPECTION_MAKEFILE) | |
92 | introspection_sources = \ | |
93 | $(libfarstream_@GST_MAJORMINOR@_la_SOURCES) \ | |
94 | $(nodist_libfarstreaminclude_HEADERS) \ | |
95 | $(libfarstreaminclude_HEADERS) | |
96 | ||
97 | INTROSPECTION_GIRS = Farstream-@FS_MAJORMINOR@.gir | |
98 | Farstream_0_1_gir_NAMESPACE = Farstream | |
99 | Farstream_0_1_gir_VERSION = @FS_MAJORMINOR@ | |
100 | Farstream_0_1_gir_LIBS = libfarstream-@GST_MAJORMINOR@.la | |
101 | Farstream_0_1_gir_FILES = $(introspection_sources) | |
102 | Farstream_0_1_gir_INCLUDES = GObject-2.0 Gst-0.10 | |
103 | Farstream_0_1_gir_CFLAGS = $(FS_INTERNAL_CFLAGS) | |
104 | Farstream_0_1_gir_SCANNERFLAGS = --identifier-prefix=fs_ --identifier-prefix=Fs | |
105 | ||
106 | girdir = $(datadir)/gir-1.0 | |
107 | dist_gir_DATA = Farstream-@FS_MAJORMINOR@.gir | |
108 | typelibdir = $(libdir)/girepository-1.0 | |
109 | typelib_DATA = Farstream-@FS_MAJORMINOR@.typelib | |
110 | CLEANFILES += $(dist_gir_DATA) $(typelib_DATA) | |
111 | endif |
0 | /* | |
1 | * Farstream - Farstream Candidate | |
2 | * | |
3 | * Copyright 2007 Collabora Ltd. | |
4 | * @author: Philippe Kalaf <philippe.kalaf@collabora.co.uk> | |
5 | * Copyright 2007 Nokia Corp. | |
6 | * | |
7 | * fs-candidate.c - A Farstream candidate | |
8 | * | |
9 | * This library is free software; you can redistribute it and/or | |
10 | * modify it under the terms of the GNU Lesser General Public | |
11 | * License as published by the Free Software Foundation; either | |
12 | * version 2.1 of the License, or (at your option) any later version. | |
13 | * | |
14 | * This library is distributed in the hope that it will be useful, | |
15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
17 | * Lesser General Public License for more details. | |
18 | * | |
19 | * You should have received a copy of the GNU Lesser General Public | |
20 | * License along with this library; if not, write to the Free Software | |
21 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA | |
22 | */ | |
23 | ||
24 | #ifdef HAVE_CONFIG_H | |
25 | #include "config.h" | |
26 | #endif | |
27 | ||
28 | #include "fs-candidate.h" | |
29 | ||
30 | /** | |
31 | * SECTION:fs-candidate | |
32 | * @short_description: Structure describing a transport candidate. | |
33 | * | |
34 | * An FsCandidate is a way to exchange candidate information between the client | |
35 | * and Farstream. This description is compatible with ICE-13. It can also be a | |
36 | * multicast address. Candidates are linked to streams. The information | |
37 | * specified in this structure is usually representative of the codec | |
38 | * information exchanged in the signaling. | |
39 | */ | |
40 | ||
41 | GType | |
42 | fs_candidate_get_type (void) | |
43 | { | |
44 | static GType candidate_type = 0; | |
45 | if (candidate_type == 0) | |
46 | { | |
47 | candidate_type = g_boxed_type_register_static ( | |
48 | "FsCandidate", | |
49 | (GBoxedCopyFunc)fs_candidate_copy, | |
50 | (GBoxedFreeFunc)fs_candidate_destroy); | |
51 | } | |
52 | ||
53 | return candidate_type; | |
54 | } | |
55 | ||
56 | GType | |
57 | fs_candidate_list_get_type (void) | |
58 | { | |
59 | static GType candidate_list_type = 0; | |
60 | if (candidate_list_type == 0) | |
61 | { | |
62 | candidate_list_type = g_boxed_type_register_static ( | |
63 | "FsCandidateList", | |
64 | (GBoxedCopyFunc)fs_candidate_list_copy, | |
65 | (GBoxedFreeFunc)fs_candidate_list_destroy); | |
66 | } | |
67 | ||
68 | return candidate_list_type; | |
69 | } | |
70 | ||
71 | /** | |
72 | * fs_candidate_destroy: (skip): | |
73 | * @cand: a #FsCandidate to delete | |
74 | * | |
75 | * Frees a #FsCandidate and all its contents | |
76 | */ | |
77 | void | |
78 | fs_candidate_destroy (FsCandidate * cand) | |
79 | { | |
80 | if (cand == NULL) | |
81 | return; | |
82 | ||
83 | g_free ((gchar *) cand->foundation); | |
84 | g_free ((gchar *) cand->ip); | |
85 | g_free ((gchar *) cand->base_ip); | |
86 | g_free ((gchar *) cand->username); | |
87 | g_free ((gchar *) cand->password); | |
88 | ||
89 | g_slice_free (FsCandidate, cand); | |
90 | } | |
91 | ||
92 | /** | |
93 | * fs_candidate_copy: | |
94 | * @cand: a #FsCandidate to copy | |
95 | * | |
96 | * Copies a #FsCandidate and its contents. | |
97 | * | |
98 | * Returns: a new #FsCandidate | |
99 | */ | |
100 | FsCandidate * | |
101 | fs_candidate_copy (const FsCandidate * cand) | |
102 | { | |
103 | FsCandidate *copy = g_slice_new0 (FsCandidate); | |
104 | ||
105 | if (cand == NULL) | |
106 | return NULL; | |
107 | ||
108 | copy->component_id = cand->component_id; | |
109 | copy->port = cand->port; | |
110 | copy->base_port = cand->base_port; | |
111 | copy->proto = cand->proto; | |
112 | copy->priority = cand->priority; | |
113 | copy->type = cand->type; | |
114 | copy->ttl = cand->ttl; | |
115 | ||
116 | copy->foundation = g_strdup (cand->foundation); | |
117 | copy->ip = g_strdup (cand->ip); | |
118 | copy->base_ip = g_strdup (cand->base_ip); | |
119 | copy->username = g_strdup (cand->username); | |
120 | copy->password = g_strdup (cand->password); | |
121 | ||
122 | return copy; | |
123 | } | |
124 | ||
125 | /** | |
126 | * fs_candidate_list_destroy: (skip): | |
127 | * @candidate_list: A GList of #FsCandidate | |
128 | * | |
129 | * Deletes a GList of #FsCandidate and its contents | |
130 | */ | |
131 | void | |
132 | fs_candidate_list_destroy (GList *candidate_list) | |
133 | { | |
134 | GList *lp; | |
135 | FsCandidate *cand; | |
136 | ||
137 | for (lp = candidate_list; lp; lp = g_list_next (lp)) { | |
138 | cand = (FsCandidate *) lp->data; | |
139 | fs_candidate_destroy (cand); | |
140 | lp->data = NULL; | |
141 | } | |
142 | g_list_free (candidate_list); | |
143 | } | |
144 | ||
145 | /** | |
146 | * fs_candidate_list_copy: | |
147 | * @candidate_list: (element-type FsCodec): A GList of #FsCandidate | |
148 | * | |
149 | * Copies a GList of #FsCandidate and its contents | |
150 | * | |
151 | * Returns: (element-type FsCodec) (transfer full): a new GList of #FsCandidate | |
152 | */ | |
153 | GList * | |
154 | fs_candidate_list_copy (const GList *candidate_list) | |
155 | { | |
156 | GQueue copy = G_QUEUE_INIT; | |
157 | const GList *lp; | |
158 | ||
159 | for (lp = candidate_list; lp; lp = g_list_next (lp)) { | |
160 | FsCandidate *cand = lp->data; | |
161 | ||
162 | g_queue_push_tail (©, fs_candidate_copy (cand)); | |
163 | } | |
164 | ||
165 | return copy.head; | |
166 | } | |
167 | ||
168 | /** | |
169 | * fs_candidate_new: | |
170 | * @foundation: The foundation of the candidate | |
171 | * @component_id: The component this candidate is for | |
172 | * @type: The type of candidate | |
173 | * @proto: The protocol this component is for | |
174 | * @ip: The IP address of this component (can be NULL for local candidate to | |
175 | * mean any address) | |
176 | * @port: the UDP/TCP port | |
177 | * | |
178 | * Allocates a new #FsCandidate, the rest of the fields can be optionally | |
179 | * filled manually. | |
180 | * | |
181 | * Returns: a newly-allocated #FsCandidate | |
182 | */ | |
183 | ||
184 | FsCandidate * | |
185 | fs_candidate_new ( | |
186 | const gchar *foundation, | |
187 | guint component_id, | |
188 | FsCandidateType type, | |
189 | FsNetworkProtocol proto, | |
190 | const gchar *ip, | |
191 | guint port) | |
192 | { | |
193 | FsCandidate *candidate = g_slice_new0 (FsCandidate); | |
194 | ||
195 | candidate->foundation = g_strdup (foundation); | |
196 | candidate->component_id = component_id; | |
197 | candidate->type = type; | |
198 | candidate->proto = proto; | |
199 | candidate->ip = g_strdup (ip); | |
200 | candidate->port = port; | |
201 | ||
202 | return candidate; | |
203 | } |
0 | /* | |
1 | * Farstream - Farstream Candidate | |
2 | * | |
3 | * Copyright 2007 Collabora Ltd. | |
4 | * @author: Philippe Kalaf <philippe.kalaf@collabora.co.uk> | |
5 | * Copyright 2007 Nokia Corp. | |
6 | * | |
7 | * fs-candidate.h - A Farstream candidate | |
8 | * | |
9 | * This library is free software; you can redistribute it and/or | |
10 | * modify it under the terms of the GNU Lesser General Public | |
11 | * License as published by the Free Software Foundation; either | |
12 | * version 2.1 of the License, or (at your option) any later version. | |
13 | * | |
14 | * This library is distributed in the hope that it will be useful, | |
15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
17 | * Lesser General Public License for more details. | |
18 | * | |
19 | * You should have received a copy of the GNU Lesser General Public | |
20 | * License along with this library; if not, write to the Free Software | |
21 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA | |
22 | */ | |
23 | ||
24 | #ifndef __FS_CANDIDATE_H__ | |
25 | #define __FS_CANDIDATE_H__ | |
26 | ||
27 | #include <glib.h> | |
28 | #include <glib-object.h> | |
29 | ||
30 | G_BEGIN_DECLS | |
31 | ||
32 | #define FS_TYPE_CANDIDATE \ | |
33 | (fs_candidate_get_type ()) | |
34 | ||
35 | ||
36 | #define FS_TYPE_CANDIDATE_LIST \ | |
37 | (fs_candidate_list_get_type ()) | |
38 | ||
39 | /** | |
40 | * FsCandidateType: | |
41 | * @FS_CANDIDATE_TYPE_HOST: A host candidate (local) | |
42 | * @FS_CANDIDATE_TYPE_SRFLX: A server reflexive candidate. | |
43 | * @FS_CANDIDATE_TYPE_PRFLX: A peer reflexive candidate | |
44 | * @FS_CANDIDATE_TYPE_RELAY: An relay candidate | |
45 | * @FS_CANDIDATE_TYPE_MULTICAST: A multicast address | |
46 | * | |
47 | * An enum for the type of candidate used/reported | |
48 | */ | |
49 | typedef enum _FsCandidateType | |
50 | { | |
51 | FS_CANDIDATE_TYPE_HOST, | |
52 | FS_CANDIDATE_TYPE_SRFLX, | |
53 | FS_CANDIDATE_TYPE_PRFLX, | |
54 | FS_CANDIDATE_TYPE_RELAY, /* An external stream relay */ | |
55 | FS_CANDIDATE_TYPE_MULTICAST | |
56 | } FsCandidateType; | |
57 | ||
58 | /** | |
59 | * FsNetworkProtocol: | |
60 | * @FS_NETWORK_PROTOCOL_UDP: A UDP based protocol | |
61 | * @FS_NETWORK_PROTOCOL_TCP: A TCP based protocol | |
62 | * | |
63 | * An enum for the base IP protocol | |
64 | */ | |
65 | typedef enum _FsNetworkProtocol | |
66 | { | |
67 | FS_NETWORK_PROTOCOL_UDP, | |
68 | FS_NETWORK_PROTOCOL_TCP | |
69 | } FsNetworkProtocol; | |
70 | ||
71 | /** | |
72 | * FsComponentType: | |
73 | * @FS_COMPONENT_NONE: Use this when specifying a component is innapropriate | |
74 | * @FS_COMPONENT_RTP: This component is for RTP data | |
75 | * @FS_COMPONENT_RTCP: This component is for RTCP control | |
76 | * | |
77 | * This enum contains the component IDs defined in ICE-19 | |
78 | */ | |
79 | ||
80 | typedef enum _FsComponentType | |
81 | { | |
82 | FS_COMPONENT_NONE = 0, | |
83 | FS_COMPONENT_RTP = 1, | |
84 | FS_COMPONENT_RTCP = 2 | |
85 | } FsComponentType; | |
86 | ||
87 | ||
88 | typedef struct _FsCandidate FsCandidate; | |
89 | ||
90 | /** | |
91 | * FsCandidate: | |
92 | * @foundation: a string representing the foundation of this candidate (maximum 32 chars) | |
93 | * @component_id: value between 1 and 256 indicating which component this candidate represents (1 is RTP, 2 is RTCP, #FsComponentType can be used here) | |
94 | * @ip: IP in dotted format | |
95 | * @port: Port to use | |
96 | * @base_ip: IP of base in dotted format as defined in ICE-19. | |
97 | * @base_port: Port of base as defined in ICE-19. | |
98 | * @proto: #FsNetworkProtocol for ip protocol to use as candidate | |
99 | * @priority: Value between 0 and (2^31 - 1) representing the priority | |
100 | * @type: The #FsCandidateType of the candidate | |
101 | * @username: Username to use to connect to client if necessary, | |
102 | * NULL otherwise | |
103 | * @password: Username to use to connect to client if necessary, | |
104 | * NULL otherwise | |
105 | * @ttl: The TTL used when sending Multicast packet (0 = auto) | |
106 | * | |
107 | * Struct to hold information about ICE-19 compliant candidates | |
108 | */ | |
109 | struct _FsCandidate | |
110 | { | |
111 | gchar *foundation; | |
112 | guint component_id; | |
113 | const gchar *ip; | |
114 | guint16 port; | |
115 | const gchar *base_ip; | |
116 | guint16 base_port; | |
117 | FsNetworkProtocol proto; | |
118 | guint32 priority; | |
119 | FsCandidateType type; | |
120 | const gchar *username; | |
121 | const gchar *password; | |
122 | guint ttl; | |
123 | }; | |
124 | ||
125 | GType fs_candidate_get_type (void); | |
126 | GType fs_candidate_list_get_type (void); | |
127 | ||
128 | void fs_candidate_destroy (FsCandidate *cand); | |
129 | ||
130 | FsCandidate *fs_candidate_copy (const FsCandidate *cand); | |
131 | ||
132 | void fs_candidate_list_destroy (GList *candidate_list); | |
133 | ||
134 | GList *fs_candidate_list_copy (const GList *candidate_list); | |
135 | ||
136 | FsCandidate * fs_candidate_new ( | |
137 | const gchar *foundation, | |
138 | guint component_id, | |
139 | FsCandidateType type, | |
140 | FsNetworkProtocol proto, | |
141 | const gchar *ip, | |
142 | guint port); | |
143 | ||
144 | G_END_DECLS | |
145 | #endif /* __FS_CANDIDATE_H__ */ |
0 | /* | |
1 | * Farstream - Farstream Codec | |
2 | * | |
3 | * Copyright 2007 Collabora Ltd. | |
4 | * @author: Philippe Kalaf <philippe.kalaf@collabora.co.uk> | |
5 | * Copyright 2007 Nokia Corp. | |
6 | * | |
7 | * Copyright 2005 Collabora Ltd. | |
8 | * @author: Rob Taylor <rob.taylor@collabora.co.uk> | |
9 | * | |
10 | * fs-codec.c - A Farstream codec | |
11 | * | |
12 | * This library is free software; you can redistribute it and/or | |
13 | * modify it under the terms of the GNU Lesser General Public | |
14 | * License as published by the Free Software Foundation; either | |
15 | * version 2.1 of the License, or (at your option) any later version. | |
16 | * | |
17 | * This library is distributed in the hope that it will be useful, | |
18 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
19 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
20 | * Lesser General Public License for more details. | |
21 | * | |
22 | * You should have received a copy of the GNU Lesser General Public | |
23 | * License along with this library; if not, write to the Free Software | |
24 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA | |
25 | */ | |
26 | ||
27 | #ifdef HAVE_CONFIG_H | |
28 | #include "config.h" | |
29 | #endif | |
30 | ||
31 | #include "fs-codec.h" | |
32 | ||
33 | #include <string.h> | |
34 | ||
35 | #include "fs-private.h" | |
36 | ||
37 | #define GST_CAT_DEFAULT fs_conference_debug | |
38 | ||
39 | /** | |
40 | * SECTION:fs-codec | |
41 | * @short_description: Structure representing a media codec | |
42 | * | |
43 | * An #FsCodec is a way to exchange codec information between the client and | |
44 | * Farstream. The information specified in this structure is usually | |
45 | * representative of the codec information exchanged in the signaling. | |
46 | * | |
47 | */ | |
48 | ||
49 | /* TODO Make a fs_codec_new() function since there is a _destroy() */ | |
50 | ||
51 | GType | |
52 | fs_codec_get_type (void) | |
53 | { | |
54 | static GType codec_type = 0; | |
55 | if (codec_type == 0) | |
56 | { | |
57 | codec_type = g_boxed_type_register_static ( | |
58 | "FsCodec", | |
59 | (GBoxedCopyFunc)fs_codec_copy, | |
60 | (GBoxedFreeFunc)fs_codec_destroy); | |
61 | } | |
62 | ||
63 | return codec_type; | |
64 | } | |
65 | ||
66 | GType | |
67 | fs_codec_list_get_type (void) | |
68 | { | |
69 | static GType codec_list_type = 0; | |
70 | if (codec_list_type == 0) | |
71 | { | |
72 | codec_list_type = g_boxed_type_register_static ( | |
73 | "FsCodecGList", | |
74 | (GBoxedCopyFunc)fs_codec_list_copy, | |
75 | (GBoxedFreeFunc)fs_codec_list_destroy); | |
76 | } | |
77 | ||
78 | return codec_list_type; | |
79 | } | |
80 | ||
81 | G_DEFINE_BOXED_TYPE (FsCodecParameter, | |
82 | fs_codec_parameter, | |
83 | fs_codec_parameter_copy, | |
84 | fs_codec_parameter_free); | |
85 | ||
86 | ||
87 | G_DEFINE_BOXED_TYPE (FsFeedbackParameter, | |
88 | fs_feedback_parameter, | |
89 | fs_feedback_parameter_copy, | |
90 | fs_feedback_parameter_free); | |
91 | ||
92 | /** | |
93 | * fs_codec_new: | |
94 | * @id: codec identifier, if RTP this should be based on IETF RTP payload types | |
95 | * @encoding_name: Name of media type this encodes | |
96 | * @media_type: #FsMediaType for type of codec | |
97 | * @clock_rate: The clock rate this codec encodes at, if applicable | |
98 | * | |
99 | * Allocates and initializes a #FsCodec structure | |
100 | * | |
101 | * Returns: A newly allocated #FsCodec | |
102 | */ | |
103 | FsCodec * | |
104 | fs_codec_new (int id, const char *encoding_name, | |
105 | FsMediaType media_type, guint clock_rate) | |
106 | { | |
107 | FsCodec *codec = g_slice_new0 (FsCodec); | |
108 | ||
109 | codec->id = id; | |
110 | codec->encoding_name = g_strdup (encoding_name); | |
111 | codec->media_type = media_type; | |
112 | codec->clock_rate = clock_rate; | |
113 | codec->minimum_reporting_interval = G_MAXUINT; | |
114 | ||
115 | return codec; | |
116 | } | |
117 | ||
118 | void | |
119 | fs_codec_parameter_free (FsCodecParameter *param) | |
120 | ||
121 | { | |
122 | g_free (param->name); | |
123 | g_free (param->value); | |
124 | g_slice_free (FsCodecParameter, param); | |
125 | } | |
126 | ||
127 | ||
128 | void | |
129 | fs_feedback_parameter_free (FsFeedbackParameter *param) | |
130 | { | |
131 | g_free (param->type); | |
132 | g_free (param->subtype); | |
133 | g_free (param->extra_params); | |
134 | g_slice_free (FsFeedbackParameter, param); | |
135 | } | |
136 | ||
137 | /** | |
138 | * fs_codec_destroy: (skip): | |
139 | * @codec: #FsCodec structure to free | |
140 | * | |
141 | * Deletes a #FsCodec structure and all its data. Is a no-op on %NULL codec | |
142 | */ | |
143 | void | |
144 | fs_codec_destroy (FsCodec * codec) | |
145 | { | |
146 | if (codec == NULL) | |
147 | return; | |
148 | ||
149 | g_free (codec->encoding_name); | |
150 | ||
151 | g_list_foreach (codec->optional_params, (GFunc) fs_codec_parameter_free, | |
152 | NULL); | |
153 | g_list_free (codec->optional_params); | |
154 | ||
155 | g_list_foreach (codec->feedback_params, | |
156 | (GFunc) fs_feedback_parameter_free, NULL); | |
157 | g_list_free (codec->feedback_params); | |
158 | ||
159 | g_slice_free (FsCodec, codec); | |
160 | } | |
161 | ||
162 | /** | |
163 | * fs_codec_copy: | |
164 | * @codec: codec to copy | |
165 | * | |
166 | * Copies a #FsCodec structure. | |
167 | * | |
168 | * Returns: a copy of the codec | |
169 | */ | |
170 | FsCodec * | |
171 | fs_codec_copy (const FsCodec * codec) | |
172 | { | |
173 | FsCodec *copy = NULL; | |
174 | GList *lp; | |
175 | GQueue list_copy = G_QUEUE_INIT; | |
176 | ||
177 | if (codec == NULL) | |
178 | return NULL; | |
179 | ||
180 | copy = fs_codec_new (codec->id, codec->encoding_name, codec->media_type, | |
181 | codec->clock_rate); | |
182 | ||
183 | copy->channels = codec->channels; | |
184 | copy->minimum_reporting_interval = codec->minimum_reporting_interval; | |
185 | ||
186 | copy->encoding_name = g_strdup (codec->encoding_name); | |
187 | ||
188 | for (lp = codec->optional_params; lp; lp = g_list_next (lp)) | |
189 | { | |
190 | FsCodecParameter *param_copy; | |
191 | FsCodecParameter *param = lp->data;; | |
192 | ||
193 | param_copy = g_slice_new (FsCodecParameter); | |
194 | param_copy->name = g_strdup (param->name); | |
195 | param_copy->value = g_strdup (param->value); | |
196 | ||
197 | g_queue_push_tail (&list_copy, param_copy); | |
198 | } | |
199 | copy->optional_params = list_copy.head; | |
200 | ||
201 | g_queue_init (&list_copy); | |
202 | for (lp = codec->feedback_params; lp; lp = g_list_next (lp)) | |
203 | { | |
204 | FsFeedbackParameter *param_copy; | |
205 | FsFeedbackParameter *param = lp->data;; | |
206 | ||
207 | param_copy = g_slice_new (FsFeedbackParameter); | |
208 | param_copy->type = g_strdup (param->type); | |
209 | param_copy->subtype = g_strdup (param->subtype); | |
210 | param_copy->extra_params = g_strdup (param->extra_params); | |
211 | ||
212 | g_queue_push_tail (&list_copy, param_copy); | |
213 | } | |
214 | copy->feedback_params = list_copy.head; | |
215 | ||
216 | return copy; | |
217 | } | |
218 | ||
219 | /** | |
220 | * fs_codec_list_destroy: (skip): | |
221 | * @codec_list: a GList of #FsCodec to delete | |
222 | * | |
223 | * Deletes a list of #FsCodec structures and the list itself. | |
224 | * Does nothing on %NULL lists. | |
225 | */ | |
226 | void | |
227 | fs_codec_list_destroy (GList *codec_list) | |
228 | { | |
229 | GList *lp; | |
230 | FsCodec *codec; | |
231 | ||
232 | for (lp = codec_list; lp; lp = g_list_next (lp)) { | |
233 | codec = (FsCodec *) lp->data; | |
234 | fs_codec_destroy (codec); | |
235 | lp->data = NULL; | |
236 | } | |
237 | g_list_free (codec_list); | |
238 | } | |
239 | ||
240 | /** | |
241 | * fs_codec_list_copy: | |
242 | * @codec_list: a GList of #FsCodec to copy | |
243 | * | |
244 | * Copies a list of #FsCodec structures. | |
245 | * | |
246 | * Returns: (element-type FsCodec) (transfer full): The new list. | |
247 | */ | |
248 | GList * | |
249 | fs_codec_list_copy (const GList *codec_list) | |
250 | { | |
251 | GQueue copy = G_QUEUE_INIT; | |
252 | const GList *lp; | |
253 | ||
254 | for (lp = codec_list; lp; lp = g_list_next (lp)) { | |
255 | FsCodec *codec = (FsCodec *) lp->data; | |
256 | ||
257 | g_queue_push_tail (©, fs_codec_copy (codec)); | |
258 | } | |
259 | ||
260 | return copy.head; | |
261 | } | |
262 | ||
263 | /** | |
264 | * fs_codec_list_from_keyfile | |
265 | * @filename: Name of the #GKeyFile to read the codecs parameters from | |
266 | * @error: location of a #GError, or NULL if no error occured | |
267 | * | |
268 | * Reads the content of a #GKeyFile of the following format into | |
269 | * a #GList of #FsCodec structures. | |
270 | * | |
271 | * | |
272 | * Example: | |
273 | * |[ | |
274 | * [audio/codec1] | |
275 | * clock-rate=8000 | |
276 | * | |
277 | * [audio/codec1:1] | |
278 | * clock-rate=16000 | |
279 | * | |
280 | * [audio/codec2] | |
281 | * one_param=QCIF | |
282 | * another_param=WOW | |
283 | * | |
284 | * [video/codec3] | |
285 | * wierd_param=42 | |
286 | * feedback:nack/pli=1 | |
287 | * feedback:tfrc= | |
288 | * ]| | |
289 | * | |
290 | * Return value: (element-type FsCodec) (transfer full): | |
291 | * The #GList of #FsCodec or %NULL if the keyfile was empty or an error occured. | |
292 | */ | |
293 | GList * | |
294 | fs_codec_list_from_keyfile (const gchar *filename, GError **error) | |
295 | { | |
296 | GKeyFile *keyfile = NULL; | |
297 | GList *codecs = NULL; | |
298 | GError *gerror = NULL; | |
299 | gchar **groups = NULL; | |
300 | gsize groups_count = 0; | |
301 | int i; | |
302 | ||
303 | g_return_val_if_fail (filename, NULL); | |
304 | g_return_val_if_fail (error == NULL || *error == NULL, NULL); | |
305 | ||
306 | keyfile = g_key_file_new (); | |
307 | ||
308 | if (!g_key_file_load_from_file (keyfile, filename, | |
309 | G_KEY_FILE_NONE, error)) { | |
310 | goto out; | |
311 | } | |
312 | ||
313 | groups = g_key_file_get_groups (keyfile, &groups_count); | |
314 | ||
315 | if (!groups) | |
316 | goto out; | |
317 | ||
318 | for (i=0; i < groups_count && groups[i]; i++) { | |
319 | FsCodec *codec; | |
320 | gchar **keys = NULL; | |
321 | gsize keys_count; | |
322 | int j; | |
323 | gchar *encoding_name = NULL; | |
324 | gchar *next_tok = NULL; | |
325 | FsMediaType media_type; | |
326 | ||
327 | keys = g_key_file_get_keys (keyfile, groups[i], &keys_count, &gerror); | |
328 | ||
329 | if (!keys || gerror) { | |
330 | if (gerror) | |
331 | GST_WARNING ("Unable to read parameters for %s: %s\n", | |
332 | groups[i], gerror->message); | |
333 | else | |
334 | GST_WARNING ("Unknown errors while reading parameters for %s", | |
335 | groups[i]); | |
336 | ||
337 | g_clear_error (&gerror); | |
338 | ||
339 | goto next_codec; | |
340 | } | |
341 | ||
342 | next_tok = strchr (groups[i], '/'); | |
343 | if (!next_tok) | |
344 | { | |
345 | GST_WARNING ("Invalid codec name: %s", groups[i]); | |
346 | goto next_codec; | |
347 | } | |
348 | ||
349 | if ((next_tok - groups[i]) == 5 /* strlen ("audio") */ && | |
350 | !g_ascii_strncasecmp ("audio", groups[i], 5)) | |
351 | { | |
352 | media_type = FS_MEDIA_TYPE_AUDIO; | |
353 | } | |
354 | else if ((next_tok - groups[i]) == 5 /* strlen ("video") */ && | |
355 | !g_ascii_strncasecmp ("video", groups[i], 5)) | |
356 | { | |
357 | media_type = FS_MEDIA_TYPE_VIDEO; | |
358 | } | |
359 | else | |
360 | { | |
361 | GST_WARNING ("Invalid media type in codec name name %s", groups[i]); | |
362 | goto next_codec; | |
363 | } | |
364 | ||
365 | encoding_name = next_tok + 1; | |
366 | ||
367 | next_tok = strchr (encoding_name, ':'); | |
368 | ||
369 | if (encoding_name[0] == 0 || next_tok - encoding_name == 1) | |
370 | goto next_codec; | |
371 | ||
372 | if (next_tok) | |
373 | encoding_name = g_strndup (encoding_name, | |
374 | next_tok - encoding_name); | |
375 | else | |
376 | encoding_name = g_strdup (encoding_name); | |
377 | ||
378 | codec = fs_codec_new (FS_CODEC_ID_ANY, encoding_name, media_type, 0); | |
379 | ||
380 | g_free (encoding_name); | |
381 | ||
382 | for (j = 0; j < keys_count && keys[j]; j++) { | |
383 | if (!g_ascii_strcasecmp ("clock-rate", keys[j])) { | |
384 | codec->clock_rate = g_key_file_get_integer (keyfile, groups[i], keys[j], | |
385 | &gerror); | |
386 | if (gerror) { | |
387 | codec->clock_rate = 0; | |
388 | goto keyerror; | |
389 | } | |
390 | ||
391 | } else if (!g_ascii_strcasecmp ("id", keys[j])) { | |
392 | codec->id = g_key_file_get_integer (keyfile, groups[i], keys[j], | |
393 | &gerror); | |
394 | if (gerror) { | |
395 | codec->id = FS_CODEC_ID_ANY; | |
396 | goto keyerror; | |
397 | } | |
398 | ||
399 | if (codec->id < 0) | |
400 | codec->id = FS_CODEC_ID_DISABLE; | |
401 | ||
402 | } else if (!g_ascii_strcasecmp ("channels", keys[j])) { | |
403 | codec->channels = g_key_file_get_integer (keyfile, groups[i], keys[j], | |
404 | &gerror); | |
405 | if (gerror) { | |
406 | codec->channels = 0; | |
407 | goto keyerror; | |
408 | } | |
409 | } else if (!g_ascii_strcasecmp ("trr-int", keys[j])) { | |
410 | codec->minimum_reporting_interval = | |
411 | g_key_file_get_integer (keyfile, groups[i], keys[j], &gerror); | |
412 | if (gerror) { | |
413 | codec->minimum_reporting_interval = G_MAXUINT; | |
414 | goto keyerror; | |
415 | } | |
416 | } else if (g_str_has_prefix (keys[j], "feedback:")) { | |
417 | gchar *type = keys[j] + strlen ("feedback:"); | |
418 | gchar *subtype = strchr (type, '/'); | |
419 | gchar *extra_params; | |
420 | ||
421 | extra_params = g_key_file_get_string (keyfile, groups[i], keys[j], | |
422 | &gerror); | |
423 | if (gerror) | |
424 | goto keyerror; | |
425 | ||
426 | /* Replace / with \0 and point to name (the next char) */ | |
427 | if (subtype) | |
428 | { | |
429 | *subtype=0; | |
430 | subtype++; | |
431 | } | |
432 | else | |
433 | { | |
434 | subtype = ""; | |
435 | } | |
436 | ||
437 | fs_codec_add_feedback_parameter (codec, type, subtype, | |
438 | extra_params); | |
439 | g_free (extra_params); | |
440 | } else { | |
441 | FsCodecParameter *param = g_slice_new (FsCodecParameter); | |
442 | ||
443 | param->name = g_strdup (keys[j]); | |
444 | param->value = g_key_file_get_string (keyfile, groups[i], keys[j], | |
445 | &gerror); | |
446 | if (gerror) { | |
447 | fs_codec_parameter_free (param); | |
448 | goto keyerror; | |
449 | } | |
450 | ||
451 | if (!param->name || !param->value) | |
452 | fs_codec_parameter_free (param); | |
453 | else | |
454 | codec->optional_params = g_list_append (codec->optional_params, | |
455 | param); | |
456 | } | |
457 | continue; | |
458 | keyerror: | |
459 | GST_WARNING ("Error reading key %s codec %s: %s", keys[j], groups[i], | |
460 | gerror->message); | |
461 | g_clear_error (&gerror); | |
462 | ||
463 | } | |
464 | ||
465 | codecs = g_list_append (codecs, codec); | |
466 | ||
467 | next_codec: | |
468 | g_strfreev (keys); | |
469 | } | |
470 | ||
471 | ||
472 | out: | |
473 | ||
474 | g_strfreev (groups); | |
475 | g_key_file_free (keyfile); | |
476 | ||
477 | return codecs; | |
478 | } | |
479 | ||
480 | /** | |
481 | * fs_media_type_to_string | |
482 | * @media_type: A media type | |
483 | * | |
484 | * Gives a user-printable string representing the media type | |
485 | * | |
486 | * Return value: a static string representing the media type | |
487 | */ | |
488 | ||
489 | const gchar * | |
490 | fs_media_type_to_string (FsMediaType media_type) | |
491 | { | |
492 | if (media_type == FS_MEDIA_TYPE_AUDIO) { | |
493 | return "audio"; | |
494 | } else if (media_type == FS_MEDIA_TYPE_VIDEO) { | |
495 | return "video"; | |
496 | } else { | |
497 | return NULL; | |
498 | } | |
499 | } | |
500 | ||
501 | /** | |
502 | * fs_codec_to_string | |
503 | * @codec: A farstream codec | |
504 | * | |
505 | * Returns a newly-allocated string representing the codec | |
506 | * | |
507 | * Return value: the newly-allocated string | |
508 | */ | |
509 | gchar * | |
510 | fs_codec_to_string (const FsCodec *codec) | |
511 | { | |
512 | GString *string = NULL; | |
513 | GList *item; | |
514 | gchar *charstring; | |
515 | ||
516 | if (codec == NULL) | |
517 | return g_strdup ("(NULL)"); | |
518 | ||
519 | string = g_string_new (""); | |
520 | ||
521 | g_string_printf (string, "%d: %s %s clock:%d channels:%d", | |
522 | codec->id, fs_media_type_to_string (codec->media_type), | |
523 | codec->encoding_name, codec->clock_rate, codec->channels); | |
524 | ||
525 | if (codec->minimum_reporting_interval != G_MAXUINT) | |
526 | g_string_append_printf (string, " trr-int=%u", | |
527 | codec->minimum_reporting_interval); | |
528 | ||
529 | for (item = codec->optional_params; | |
530 | item; | |
531 | item = g_list_next (item)) { | |
532 | FsCodecParameter *param = item->data; | |
533 | g_string_append_printf (string, " %s=%s", param->name, param->value); | |
534 | } | |
535 | ||
536 | for (item = codec->feedback_params; | |
537 | item; | |
538 | item = g_list_next (item)) { | |
539 | FsFeedbackParameter *param = item->data; | |
540 | g_string_append_printf (string, " %s/%s=%s", param->type, param->subtype, | |
541 | param->extra_params); | |
542 | } | |
543 | ||
544 | charstring = string->str; | |
545 | g_string_free (string, FALSE); | |
546 | ||
547 | return charstring; | |
548 | } | |
549 | ||
550 | ||
551 | static gboolean | |
552 | compare_optional_params (const gpointer p1, const gpointer p2) | |
553 | { | |
554 | const FsCodecParameter *param1 = p1; | |
555 | const FsCodecParameter *param2 = p2; | |
556 | ||
557 | if (!g_ascii_strcasecmp (param1->name, param2->name) && | |
558 | !strcmp (param1->value, param2->value)) | |
559 | return TRUE; | |
560 | else | |
561 | return FALSE; | |
562 | } | |
563 | ||
564 | static gboolean | |
565 | compare_feedback_params (const gpointer p1, const gpointer p2) | |
566 | { | |
567 | const FsFeedbackParameter *param1 = p1; | |
568 | const FsFeedbackParameter *param2 = p2; | |
569 | ||
570 | if (!g_ascii_strcasecmp (param1->subtype, param2->subtype) && | |
571 | !g_ascii_strcasecmp (param1->type, param2->type) && | |
572 | !g_strcmp0 (param1->extra_params, param2->extra_params)) | |
573 | return TRUE; | |
574 | else | |
575 | return FALSE; | |
576 | } | |
577 | ||
578 | /* | |
579 | * Check if all of the elements of list1 are in list2 | |
580 | * It compares GLists of X using the comparison function | |
581 | */ | |
582 | static gboolean | |
583 | compare_lists (GList *list1, GList *list2, | |
584 | gboolean (*compare_params) (const gpointer p1, const gpointer p2)) | |
585 | { | |
586 | GList *item1; | |
587 | ||
588 | for (item1 = g_list_first (list1); | |
589 | item1; | |
590 | item1 = g_list_next (item1)) { | |
591 | FsCodecParameter *param1 = item1->data; | |
592 | GList *item2 = NULL; | |
593 | ||
594 | for (item2 = g_list_first (list2); | |
595 | item2; | |
596 | item2 = g_list_next (item2)) { | |
597 | FsCodecParameter *param2 = item2->data; | |
598 | ||
599 | if (compare_params (param1, param2)) | |
600 | break; | |
601 | } | |
602 | if (!item2) | |
603 | return FALSE; | |
604 | } | |
605 | ||
606 | return TRUE; | |
607 | } | |
608 | ||
609 | ||
610 | /** | |
611 | * fs_codec_are_equal: | |
612 | * @codec1: First codec | |
613 | * @codec2: Second codec | |
614 | * | |
615 | * Compare two codecs, it will declare two codecs to be identical even | |
616 | * if their optional parameters are in a different order. %NULL encoding names | |
617 | * are ignored. | |
618 | * | |
619 | * Return value: %TRUE of the codecs are identical, %FALSE otherwise | |
620 | */ | |
621 | ||
622 | gboolean | |
623 | fs_codec_are_equal (const FsCodec *codec1, const FsCodec *codec2) | |
624 | { | |
625 | if (codec1 == codec2) | |
626 | return TRUE; | |
627 | ||
628 | if (!codec1 || !codec2) | |
629 | return FALSE; | |
630 | ||
631 | if (codec1->id != codec2->id || | |
632 | codec1->media_type != codec2->media_type || | |
633 | codec1->clock_rate != codec2->clock_rate || | |
634 | codec1->channels != codec2->channels || | |
635 | codec1->minimum_reporting_interval != | |
636 | codec2->minimum_reporting_interval || | |
637 | codec1->encoding_name == NULL || | |
638 | codec2->encoding_name == NULL || | |
639 | g_ascii_strcasecmp (codec1->encoding_name, codec2->encoding_name)) | |
640 | return FALSE; | |
641 | ||
642 | ||
643 | /* Is there a smarter way to compare to un-ordered linked lists | |
644 | * to make sure they contain exactly the same elements?? | |
645 | */ | |
646 | if (!compare_lists (codec1->optional_params, codec2->optional_params, | |
647 | compare_optional_params) || | |
648 | !compare_lists (codec2->optional_params, codec1->optional_params, | |
649 | compare_optional_params)) | |
650 | return FALSE; | |
651 | ||
652 | if (!compare_lists (codec1->feedback_params, | |
653 | codec2->feedback_params, compare_feedback_params) || | |
654 | !compare_lists (codec2->feedback_params, | |
655 | codec1->feedback_params, compare_feedback_params)) | |
656 | return FALSE; | |
657 | ||
658 | return TRUE; | |
659 | } | |
660 | ||
661 | /** | |
662 | * fs_codec_list_are_equal: | |
663 | * @list1: (element-type FsCodec): a #GList of #FsCodec | |
664 | * @list2: (element-type FsCodec): a #GList of #FsCodec | |
665 | * | |
666 | * Verifies if two glist of fscodecs are identical | |
667 | * | |
668 | * Returns: %TRUE if they are identical, %FALSE otherwise | |
669 | */ | |
670 | ||
671 | gboolean | |
672 | fs_codec_list_are_equal (GList *list1, GList *list2) | |
673 | { | |
674 | ||
675 | for (; | |
676 | list1 && list2; | |
677 | list1 = g_list_next (list1), list2 = g_list_next (list2)) | |
678 | { | |
679 | if (!fs_codec_are_equal (list1->data, list2->data)) | |
680 | return FALSE; | |
681 | } | |
682 | ||
683 | if (list1 == NULL && list2 == NULL) | |
684 | return TRUE; | |
685 | else | |
686 | return FALSE; | |
687 | } | |
688 | ||
689 | /** | |
690 | * fs_codec_add_optional_parameter: | |
691 | * @codec: The #FsCodec to add the parameter to | |
692 | * @name: The name of the optional parameter | |
693 | * @value: The extra_params of the optional parameter | |
694 | * | |
695 | * This function adds an new optional parameter to a #FsCodec | |
696 | */ | |
697 | ||
698 | void | |
699 | fs_codec_add_optional_parameter (FsCodec *codec, | |
700 | const gchar *name, | |
701 | const gchar *value) | |
702 | { | |
703 | FsCodecParameter *param; | |
704 | ||
705 | g_return_if_fail (name != NULL && value != NULL); | |
706 | ||
707 | param = g_slice_new (FsCodecParameter); | |
708 | ||
709 | param->name = g_strdup (name); | |
710 | param->value = g_strdup (value); | |
711 | ||
712 | codec->optional_params = g_list_append (codec->optional_params, param); | |
713 | } | |
714 | ||
715 | /** | |
716 | * fs_codec_remove_optional_parameter: | |
717 | * @codec: a #FsCodec | |
718 | * @param: a pointer to the #FsCodecParameter to remove | |
719 | * | |
720 | * Removes an optional parameter from a codec. | |
721 | * | |
722 | * NULL param will do nothing. | |
723 | */ | |
724 | ||
725 | void | |
726 | fs_codec_remove_optional_parameter (FsCodec *codec, | |
727 | FsCodecParameter *param) | |
728 | { | |
729 | g_return_if_fail (codec); | |
730 | ||
731 | if (!param) | |
732 | return; | |
733 | ||
734 | fs_codec_parameter_free (param); | |
735 | codec->optional_params = g_list_remove (codec->optional_params, param); | |
736 | } | |
737 | ||
738 | /** | |
739 | * fs_codec_get_optional_parameter: | |
740 | * @codec: a #FsCodec | |
741 | * @name: The name of the parameter to search for | |
742 | * @value: The value of the parameter to search for or %NULL for any value | |
743 | * | |
744 | * Finds the #FsCodecParameter in the #FsCodec that has the requested name | |
745 | * and, if not %NULL, the requested value | |
746 | * | |
747 | * Returns: (transfer none) the #FsCodecParameter from the #FsCodec or %NULL | |
748 | */ | |
749 | ||
750 | FsCodecParameter * | |
751 | fs_codec_get_optional_parameter (FsCodec *codec, const gchar *name, | |
752 | const gchar *value) | |
753 | { | |
754 | GList *item = NULL; | |
755 | ||
756 | g_return_val_if_fail (codec != NULL, NULL); | |
757 | g_return_val_if_fail (name != NULL, NULL); | |
758 | ||
759 | for (item = g_list_first (codec->optional_params); | |
760 | item; | |
761 | item = g_list_next (item)) | |
762 | { | |
763 | FsCodecParameter *param = item->data; | |
764 | if (!g_ascii_strcasecmp (param->name, name) && | |
765 | (value == NULL || !g_ascii_strcasecmp (param->value, value))) | |
766 | return param; | |
767 | } | |
768 | ||
769 | return NULL; | |
770 | } | |
771 | ||
772 | /** | |
773 | * fs_codec_add_feedback_parameter: | |
774 | * @codec: The #FsCodec to add the parameter to | |
775 | * @type: The type of the feedback parameter | |
776 | * @subtype: The subtype of the feedback parameter | |
777 | * @extra_params: The extra_params of the feeback parameter | |
778 | * | |
779 | * This function adds an new feedback parameter to a #FsCodec | |
780 | */ | |
781 | ||
782 | void | |
783 | fs_codec_add_feedback_parameter (FsCodec *codec, const gchar *type, | |
784 | const gchar *subtype, const gchar *extra_params) | |
785 | { | |
786 | FsFeedbackParameter *param; | |
787 | ||
788 | g_return_if_fail (type != NULL); | |
789 | g_return_if_fail (subtype != NULL); | |
790 | g_return_if_fail (extra_params != NULL); | |
791 | ||
792 | param = g_slice_new (FsFeedbackParameter); | |
793 | ||
794 | param->type = g_strdup (type); | |
795 | param->subtype = g_strdup (subtype); | |
796 | param->extra_params = g_strdup (extra_params); | |
797 | ||
798 | codec->feedback_params = g_list_append (codec->feedback_params, param); | |
799 | } | |
800 | ||
801 | ||
802 | /** | |
803 | * fs_codec_get_feedback_parameter: | |
804 | * @codec: a #FsCodec | |
805 | * @type: The subtype of the parameter to search for or %NULL for any type | |
806 | * @subtype: The subtype of the parameter to search for or %NULL for any subtype | |
807 | * @extra_params: The extra_params of the parameter to search for or %NULL for | |
808 | * any extra_params | |
809 | * | |
810 | * Finds the #FsFeedbackParameter in the #FsCodec that has the requested | |
811 | * subtype, type and extra_params. One of which must be non-NULL; | |
812 | * | |
813 | * Returns: the #FsFeedbackParameter from the #FsCodec or %NULL | |
814 | */ | |
815 | ||
816 | FsFeedbackParameter * | |
817 | fs_codec_get_feedback_parameter (FsCodec *codec, | |
818 | const gchar *type, const gchar *subtype, const gchar *extra_params) | |
819 | { | |
820 | GList *item = NULL; | |
821 | ||
822 | g_return_val_if_fail (codec != NULL, NULL); | |
823 | g_return_val_if_fail (type != NULL || subtype != NULL, NULL); | |
824 | ||
825 | for (item = g_list_first (codec->feedback_params); | |
826 | item; | |
827 | item = g_list_next (item)) | |
828 | { | |
829 | FsFeedbackParameter *param = item->data; | |
830 | if (!g_ascii_strcasecmp (param->type, type) && | |
831 | (subtype == NULL || !g_ascii_strcasecmp (param->subtype, subtype)) && | |
832 | (extra_params == NULL || !g_ascii_strcasecmp (param->extra_params, | |
833 | extra_params))) | |
834 | return param; | |
835 | } | |
836 | ||
837 | return NULL; | |
838 | } | |
839 | ||
840 | ||
841 | ||
842 | /** | |
843 | * fs_codec_remove_feedback_parameter: | |
844 | * @codec: a #FsCodec | |
845 | * @item: a pointer to the #GList element to remove that contains a | |
846 | * #FsFeedbackParameter | |
847 | * | |
848 | * Removes an optional parameter from a codec. | |
849 | * | |
850 | * NULL param will do nothing. | |
851 | */ | |
852 | ||
853 | void | |
854 | fs_codec_remove_feedback_parameter (FsCodec *codec, GList *item) | |
855 | { | |
856 | g_return_if_fail (codec); | |
857 | ||
858 | if (!item) | |
859 | return; | |
860 | ||
861 | fs_feedback_parameter_free (item->data); | |
862 | codec->feedback_params = | |
863 | g_list_delete_link (codec->feedback_params, item); | |
864 | } | |
865 | ||
866 | FsCodecParameter * | |
867 | fs_codec_parameter_copy (const FsCodecParameter *param) | |
868 | { | |
869 | FsCodecParameter *outparam = g_slice_new (FsCodecParameter); | |
870 | ||
871 | outparam->name = g_strdup (param->name); | |
872 | outparam->value = g_strdup (param->value); | |
873 | ||
874 | return outparam; | |
875 | } | |
876 | ||
877 | ||
878 | FsFeedbackParameter * | |
879 | fs_feedback_parameter_copy (const FsFeedbackParameter *param) | |
880 | { | |
881 | FsFeedbackParameter *outparam = g_slice_new (FsFeedbackParameter); | |
882 | ||
883 | outparam->type = g_strdup (param->type); | |
884 | outparam->subtype = g_strdup (param->subtype); | |
885 | outparam->extra_params = g_strdup (param->extra_params); | |
886 | ||
887 | return outparam; | |
888 | } |
0 | /* | |
1 | * Farstream - Farstream Codec | |
2 | * | |
3 | * Copyright 2007 Collabora Ltd. | |
4 | * @author: Philippe Kalaf <philippe.kalaf@collabora.co.uk> | |
5 | * Copyright 2007 Nokia Corp. | |
6 | * | |
7 | * Copyright 2005 Collabora Ltd. | |
8 | * @author: Rob Taylor <rob.taylor@collabora.co.uk> | |
9 | * | |
10 | * fs-codec.h - A Farstream codec | |
11 | * | |
12 | * This library is free software; you can redistribute it and/or | |
13 | * modify it under the terms of the GNU Lesser General Public | |
14 | * License as published by the Free Software Foundation; either | |
15 | * version 2.1 of the License, or (at your option) any later version. | |
16 | * | |
17 | * This library is distributed in the hope that it will be useful, | |
18 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
19 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
20 | * Lesser General Public License for more details. | |
21 | * | |
22 | * You should have received a copy of the GNU Lesser General Public | |
23 | * License along with this library; if not, write to the Free Software | |
24 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA | |
25 | */ | |
26 | ||
27 | #ifndef __FS_CODEC_H__ | |
28 | #define __FS_CODEC_H__ | |
29 | ||
30 | #include <gst/gst.h> | |
31 | ||
32 | G_BEGIN_DECLS | |
33 | ||
34 | typedef struct _FsCodec FsCodec; | |
35 | typedef struct _FsCodecParameter FsCodecParameter; | |
36 | typedef struct _FsFeedbackParameter FsFeedbackParameter; | |
37 | ||
38 | #define FS_TYPE_CODEC \ | |
39 | (fs_codec_get_type ()) | |
40 | ||
41 | #define FS_TYPE_CODEC_LIST \ | |
42 | (fs_codec_list_get_type ()) | |
43 | ||
44 | /** | |
45 | * FsMediaType: | |
46 | * @FS_MEDIA_TYPE_AUDIO: A media type that encodes audio. | |
47 | * @FS_MEDIA_TYPE_VIDEO: A media type that encodes video. | |
48 | * @FS_MEDIA_TYPE_LAST: Largest valid #FsMediaType | |
49 | * | |
50 | * Enum used to signify the media type of a codec or stream. | |
51 | */ | |
52 | typedef enum _FsMediaType | |
53 | { | |
54 | FS_MEDIA_TYPE_AUDIO, | |
55 | FS_MEDIA_TYPE_VIDEO, | |
56 | FS_MEDIA_TYPE_LAST = FS_MEDIA_TYPE_VIDEO | |
57 | } FsMediaType; | |
58 | ||
59 | /** | |
60 | * FS_CODEC_ID_ANY: | |
61 | * | |
62 | * If the id of a #FsCodec is #FS_CODEC_ID_ANY, then it will be replaced | |
63 | * with a dynamic payload type at runtime | |
64 | */ | |
65 | ||
66 | /** | |
67 | * FS_CODEC_ID_DISABLE: | |
68 | * | |
69 | * If the id of a #FsCodec is #FS_CODEC_ID_DISABLE, then this codec will | |
70 | * not be used | |
71 | */ | |
72 | ||
73 | #define FS_CODEC_ID_ANY (-1) | |
74 | #define FS_CODEC_ID_DISABLE (-2) | |
75 | ||
76 | /** | |
77 | * FsCodec: | |
78 | * @id: numeric identifier for encoding, eg. PT for SDP | |
79 | * @encoding_name: the name of the codec | |
80 | * @media_type: type of media this codec is for | |
81 | * @clock_rate: clock rate of this stream | |
82 | * @channels: Number of channels codec should decode | |
83 | * @ptime: The preferred duration (in ms) of a packet | |
84 | * @maxptime: The maximum duration (in ms) of a packet | |
85 | * @optional_params: (element-type FsCodecParameter): key pairs of param name to param data | |
86 | * @minimum_reporting_interval: The minimum interval between two RTCP reports, | |
87 | * If it is not specified (G_MAXUINT), it is up to the protocol to decide | |
88 | * (it is 5 seconds for RTP). | |
89 | * | |
90 | * This structure reprensents one codec that can be offered or received | |
91 | */ | |
92 | /* TODO Should this be made into a GstStructure? */ | |
93 | struct _FsCodec | |
94 | { | |
95 | gint id; | |
96 | char *encoding_name; | |
97 | FsMediaType media_type; | |
98 | guint clock_rate; | |
99 | guint channels; | |
100 | guint minimum_reporting_interval; | |
101 | GList *optional_params; | |
102 | GList *feedback_params; | |
103 | }; | |
104 | ||
105 | /** | |
106 | * FsCodecParameter: | |
107 | * @name: paramter name. | |
108 | * @value: parameter value. | |
109 | * | |
110 | * Used to store arbitary parameters for a codec | |
111 | */ | |
112 | struct _FsCodecParameter { | |
113 | gchar *name; | |
114 | gchar *value; | |
115 | }; | |
116 | ||
117 | /** | |
118 | * FsFeedbackParameter: | |
119 | * @type: the type of feedback, like "ack", "name", "ccm" | |
120 | * @subtype: the subtype of feedback (can be an empty string) | |
121 | * @extra_params: a string containing extra parameters (can be empty) | |
122 | * | |
123 | * Use to store feedback parameters | |
124 | */ | |
125 | struct _FsFeedbackParameter { | |
126 | gchar *type; | |
127 | gchar *subtype; | |
128 | gchar *extra_params; | |
129 | }; | |
130 | ||
131 | ||
132 | /** | |
133 | * FS_CODEC_FORMAT: | |
134 | * | |
135 | * A format that can be used in printf like format strings to format a FsCodec | |
136 | */ | |
137 | ||
138 | /** | |
139 | * FS_CODEC_ARGS: | |
140 | * @codec: a #FsCodec | |
141 | * | |
142 | * Formats the codec in args for FS_CODEC_FORMAT | |
143 | */ | |
144 | ||
145 | #define FS_CODEC_FORMAT "%d: %s %s clock:%d channels:%d params:%p" | |
146 | #define FS_CODEC_ARGS(codec) \ | |
147 | (codec)->id, \ | |
148 | fs_media_type_to_string ((codec)->media_type), \ | |
149 | (codec)->encoding_name, \ | |
150 | (codec)->clock_rate, \ | |
151 | (codec)->channels, \ | |
152 | (codec)->optional_params | |
153 | ||
154 | GType fs_codec_get_type (void); | |
155 | GType fs_codec_list_get_type (void); | |
156 | ||
157 | ||
158 | FsCodec *fs_codec_new (int id, const char *encoding_name, | |
159 | FsMediaType media_type, guint clock_rate); | |
160 | ||
161 | void fs_codec_destroy (FsCodec * codec); | |
162 | FsCodec *fs_codec_copy (const FsCodec * codec); | |
163 | void fs_codec_list_destroy (GList *codec_list); | |
164 | GList *fs_codec_list_copy (const GList *codec_list); | |
165 | ||
166 | GList *fs_codec_list_from_keyfile (const gchar *filename, GError **error); | |
167 | gchar *fs_codec_to_string (const FsCodec *codec); | |
168 | const gchar *fs_media_type_to_string (FsMediaType media_type); | |
169 | ||
170 | gboolean fs_codec_are_equal (const FsCodec *codec1, const FsCodec *codec2); | |
171 | gboolean fs_codec_list_are_equal (GList *list1, GList *list2); | |
172 | ||
173 | ||
174 | void fs_codec_add_optional_parameter (FsCodec *codec, const gchar *name, | |
175 | const gchar *value); | |
176 | void fs_codec_remove_optional_parameter (FsCodec *codec, | |
177 | FsCodecParameter *param); | |
178 | FsCodecParameter *fs_codec_get_optional_parameter (FsCodec *codec, | |
179 | const gchar *name, const gchar *value); | |
180 | ||
181 | #define FS_TYPE_CODEC_PARAMETER (fs_codec_parameter_get_type ()) | |
182 | GType fs_codec_parameter_get_type (void); | |
183 | ||
184 | FsCodecParameter *fs_codec_parameter_copy (const FsCodecParameter *param); | |
185 | void fs_codec_parameter_free (FsCodecParameter *param); | |
186 | ||
187 | ||
188 | void fs_codec_add_feedback_parameter (FsCodec *codec, const gchar *type, | |
189 | const gchar *subtype, const gchar *extra_params); | |
190 | FsFeedbackParameter *fs_codec_get_feedback_parameter (FsCodec *codec, | |
191 | const gchar *type, const gchar *subtype, const gchar *extra_params); | |
192 | void fs_codec_remove_feedback_parameter (FsCodec *codec, GList *item); | |
193 | ||
194 | ||
195 | #define FS_TYPE_FEEDBACK_PARAMETER (fs_feedback_parameter_get_type ()) | |
196 | GType fs_feedback_parameter_get_type (void); | |
197 | ||
198 | FsFeedbackParameter *fs_feedback_parameter_copy ( | |
199 | const FsFeedbackParameter *param); | |
200 | void fs_feedback_parameter_free (FsFeedbackParameter *param); | |
201 | ||
202 | ||
203 | ||
204 | G_END_DECLS | |
205 | ||
206 | #endif /* __FS_CODEC_H__ */ |
0 | /* | |
1 | * Farstream - GStreamer interfaces | |
2 | * | |
3 | * Copyright 2007-2011 Collabora Ltd. | |
4 | * @author: Philippe Kalaf <philippe.kalaf@collabora.co.uk> | |
5 | * @author: Olivier Crete <olivier.crete@collabora.com> | |
6 | * Copyright 2007-2011 Nokia Corp. | |
7 | * | |
8 | * fs-conference.c - GStreamer interface to be implemented by farstream | |
9 | * conference elements | |
10 | * | |
11 | * This library is free software; you can redistribute it and/or | |
12 | * modify it under the terms of the GNU Lesser General Public | |
13 | * License as published by the Free Software Foundation; either | |
14 | * version 2.1 of the License, or (at your option) any later version. | |
15 | * | |
16 | * This library is distributed in the hope that it will be useful, | |
17 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
18 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
19 | * Lesser General Public License for more details. | |
20 | * | |
21 | * You should have received a copy of the GNU Lesser General Public | |
22 | * License along with this library; if not, write to the Free Software | |
23 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA | |
24 | */ | |
25 | ||
26 | #ifdef HAVE_CONFIG_H | |
27 | #include "config.h" | |
28 | #endif | |
29 | ||
30 | #include "fs-conference.h" | |
31 | #include "fs-session.h" | |
32 | #include "fs-private.h" | |
33 | ||
34 | /** | |
35 | * SECTION:fs-conference | |
36 | * @short_description: Interface for farstream conference elements | |
37 | * | |
38 | * A Farstream conference is a conversation space that takes place between 2 or | |
39 | * more participants. Each conference must have one or more Farstream sessions | |
40 | * that are associated to the conference participants. | |
41 | * | |
42 | * | |
43 | * This will communicate asynchronous events to the user through #GstMessage | |
44 | * of type #GST_MESSAGE_ELEMENT sent over the #GstBus. | |
45 | * </para> | |
46 | * <refsect2><title>The "<literal>farstream-error</literal>" message</title> | |
47 | * |[ | |
48 | * "src-object" #GObject The object (#FsConference, #FsSession or #FsStream) that emitted the error | |
49 | * "error-no" #FsError The Error number | |
50 | * "error-msg" #gchar* The error message | |
51 | * ]| | |
52 | * <para> | |
53 | * The message is sent on asynchronous errors. | |
54 | * </para> | |
55 | * </refsect2> | |
56 | * <para> | |
57 | */ | |
58 | ||
59 | ||
60 | GST_DEBUG_CATEGORY (fs_conference_debug); | |
61 | #define GST_CAT_DEFAULT fs_conference_debug | |
62 | ||
63 | ||
64 | GST_BOILERPLATE ( | |
65 | FsConference, fs_conference, | |
66 | GstBin, GST_TYPE_BIN) | |
67 | ||
68 | ||
69 | GQuark | |
70 | fs_error_quark (void) | |
71 | { | |
72 | return g_quark_from_static_string ("fs-error"); | |
73 | } | |
74 | ||
75 | void | |
76 | _fs_conference_init_debug (void) | |
77 | { | |
78 | GST_DEBUG_CATEGORY_INIT (fs_conference_debug, "fsconference", 0, | |
79 | "farstream base conference library"); | |
80 | } | |
81 | ||
82 | static void | |
83 | fs_conference_base_init (gpointer g_class) | |
84 | { | |
85 | _fs_conference_init_debug (); | |
86 | } | |
87 | ||
88 | ||
89 | ||
90 | static void | |
91 | fs_conference_class_init (FsConferenceClass * klass) | |
92 | { | |
93 | } | |
94 | ||
95 | static void | |
96 | fs_conference_init (FsConference *conf, FsConferenceClass *bclass) | |
97 | { | |
98 | GST_DEBUG ("fs_conference_init"); | |
99 | } | |
100 | ||
101 | ||
102 | static void | |
103 | fs_conference_error (GObject *signal_src, | |
104 | GObject *error_src, | |
105 | FsError error_no, | |
106 | gchar *error_msg, | |
107 | FsConference *conf) | |
108 | { | |
109 | GstMessage *gst_msg = NULL; | |
110 | GstStructure *error_struct = NULL; | |
111 | ||
112 | error_struct = gst_structure_new ("farstream-error", | |
113 | "src-object", G_TYPE_OBJECT, error_src, | |
114 | "error-no", FS_TYPE_ERROR, error_no, | |
115 | "error-msg", G_TYPE_STRING, error_msg, | |
116 | NULL); | |
117 | ||
118 | gst_msg = gst_message_new_element (GST_OBJECT (conf), error_struct); | |
119 | ||
120 | if (!gst_element_post_message (GST_ELEMENT (conf), gst_msg)) | |
121 | GST_WARNING_OBJECT (conf, "Could not post error on bus"); | |
122 | } | |
123 | ||
124 | /** | |
125 | * fs_conference_new_session | |
126 | * @conference: #FsConference interface of a #GstElement | |
127 | * @media_type: #FsMediaType of the new session | |
128 | * @error: location of a #GError, or %NULL if no error occured | |
129 | * | |
130 | * Create a new Farstream session for the given conference. | |
131 | * | |
132 | * Returns: (transfer full): the new #FsSession that has been created. | |
133 | * The #FsSession must be unref'd by the user when closing the session. | |
134 | */ | |
135 | ||
136 | FsSession * | |
137 | fs_conference_new_session (FsConference *conf, | |
138 | FsMediaType media_type, | |
139 | GError **error) | |
140 | { | |
141 | FsConferenceClass *klass; | |
142 | FsSession *new_session = NULL; | |
143 | ||
144 | g_return_val_if_fail (conf, NULL); | |
145 | g_return_val_if_fail (FS_IS_CONFERENCE (conf), NULL); | |
146 | klass = FS_CONFERENCE_GET_CLASS (conf); | |
147 | g_return_val_if_fail (klass->new_session, NULL); | |
148 | ||
149 | new_session = klass->new_session (conf, media_type, error); | |
150 | ||
151 | if (!new_session) | |
152 | return NULL; | |
153 | ||
154 | /* Let's catch all session errors and send them over the GstBus */ | |
155 | g_signal_connect_object (new_session, "error", | |
156 | G_CALLBACK (fs_conference_error), conf, 0); | |
157 | ||
158 | return new_session; | |
159 | } | |
160 | ||
161 | /** | |
162 | * fs_conference_new_participant | |
163 | * @conference: #FsConference interface of a #GstElement | |
164 | * @error: location of a #GError, or %NULL if no error occured | |
165 | * | |
166 | * Create a new Farstream Participant for the type of the given conference. | |
167 | * | |
168 | * Returns: (transfer full): the new #FsParticipant that has been created. | |
169 | * The #FsParticipant is owned by the user and he must unref it when he is | |
170 | * done with it. | |
171 | */ | |
172 | FsParticipant * | |
173 | fs_conference_new_participant (FsConference *conf, | |
174 | GError **error) | |
175 | { | |
176 | FsConferenceClass *klass; | |
177 | ||
178 | g_return_val_if_fail (conf, NULL); | |
179 | g_return_val_if_fail (FS_IS_CONFERENCE (conf), NULL); | |
180 | klass = FS_CONFERENCE_GET_CLASS (conf); | |
181 | g_return_val_if_fail (klass->new_participant, NULL); | |
182 | ||
183 | return klass->new_participant (conf, error); | |
184 | } | |
185 |
0 | /* | |
1 | * Farstream - FsConference Class | |
2 | * | |
3 | * Copyright 2007 Collabora Ltd. | |
4 | * @author: Philippe Kalaf <philippe.kalaf@collabora.co.uk> | |
5 | * Copyright 2007 Nokia Corp. | |
6 | * | |
7 | * fs-conference.h - Header file for farstream Conference base class | |
8 | * | |
9 | * This library is free software; you can redistribute it and/or | |
10 | * modify it under the terms of the GNU Lesser General Public | |
11 | * License as published by the Free Software Foundation; either | |
12 | * version 2.1 of the License, or (at your option) any later version. | |
13 | * | |
14 | * This library is distributed in the hope that it will be useful, | |
15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
17 | * Lesser General Public License for more details. | |
18 | * | |
19 | * You should have received a copy of the GNU Lesser General Public | |
20 | * License along with this library; if not, write to the Free Software | |
21 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA | |
22 | */ | |
23 | ||
24 | #ifndef __FS_CONFERENCE_H__ | |
25 | #define __FS_CONFERENCE_H__ | |
26 | ||
27 | #include <gst/gst.h> | |
28 | ||
29 | #include <farstream/fs-session.h> | |
30 | #include <farstream/fs-codec.h> | |
31 | #include <farstream/fs-enumtypes.h> | |
32 | ||
33 | G_BEGIN_DECLS | |
34 | ||
35 | ||
36 | #define FS_TYPE_CONFERENCE \ | |
37 | (fs_conference_get_type ()) | |
38 | #define FS_CONFERENCE(obj) \ | |
39 | (G_TYPE_CHECK_INSTANCE_CAST((obj),FS_TYPE_CONFERENCE,FsConference)) | |
40 | #define FS_CONFERENCE_CLASS(klass) \ | |
41 | (G_TYPE_CHECK_CLASS_CAST((klass),FS_TYPE_CONFERENCE,FsConferenceClass)) | |
42 | #define FS_CONFERENCE_GET_CLASS(obj) \ | |
43 | (G_TYPE_INSTANCE_GET_CLASS((obj),FS_TYPE_CONFERENCE,FsConferenceClass)) | |
44 | #define FS_IS_CONFERENCE(obj) \ | |
45 | (G_TYPE_CHECK_INSTANCE_TYPE((obj),FS_TYPE_CONFERENCE)) | |
46 | #define FS_IS_CONFERENCE_CLASS(klass) \ | |
47 | (G_TYPE_CHECK_CLASS_TYPE((klass),FS_TYPE_CONFERENCE)) | |
48 | #define FS_CONFERENCE_CAST(obj) \ | |
49 | ((FsConference *)(obj)) | |
50 | ||
51 | /** | |
52 | * FsConference: | |
53 | * | |
54 | * Opaque #FsConference data structure. | |
55 | */ | |
56 | typedef struct _FsConference FsConference; | |
57 | typedef struct _FsConferenceClass FsConferenceClass; | |
58 | ||
59 | /** | |
60 | * FsConference | |
61 | * | |
62 | * The #FsConference structure, all the members are private | |
63 | */ | |
64 | ||
65 | struct _FsConference | |
66 | { | |
67 | GstBin parent; | |
68 | ||
69 | /*< private >*/ | |
70 | ||
71 | gpointer _padding[8]; | |
72 | }; | |
73 | ||
74 | ||
75 | /** | |
76 | * FsConferenceClass: | |
77 | * @parent: parent GstBin class | |
78 | * @new_session: virtual method to create a new conference session | |
79 | * @new_participant: virtual method to create a new participant | |
80 | * | |
81 | * #FsConferenceClass class structure. | |
82 | */ | |
83 | struct _FsConferenceClass { | |
84 | GstBinClass parent; | |
85 | ||
86 | /* virtual functions */ | |
87 | FsSession *(* new_session) (FsConference *conference, FsMediaType media_type, | |
88 | GError **error); | |
89 | ||
90 | FsParticipant *(* new_participant) (FsConference *conference, | |
91 | GError **error); | |
92 | ||
93 | /*< private > */ | |
94 | gpointer _gst_reserved[GST_PADDING]; | |
95 | }; | |
96 | ||
97 | GType fs_conference_get_type (void); | |
98 | ||
99 | ||
100 | ||
101 | /** | |
102 | * FsError: | |
103 | * @FS_ERROR_CONSTRUCTION: Error constructing some of the sub-elements, this | |
104 | * probably denotes an error in the installation of the gstreamer elements. | |
105 | * It is a fatal error. | |
106 | * @FS_ERROR_INVALID_ARGUMENTS: Invalid arguments to the function, this | |
107 | * is a programming error and should not be reported to the user | |
108 | * @FS_ERROR_INTERNAL: An internal error happened in Farstream, it may be in | |
109 | * an inconsistent state. The object from which this error comes should be | |
110 | * discarded. | |
111 | * @FS_ERROR_NETWORK: A network related error, this should probably be | |
112 | * reported to the user. | |
113 | * @FS_ERROR_NOT_IMPLEMENTED: The optional functionality is not implemented by | |
114 | * this plugin. | |
115 | * @FS_ERROR_NEGOTIATION_FAILED: The codec negotiation has failed, this means | |
116 | * that there are no common codecs between the local and remote codecs. | |
117 | * @FS_ERROR_UNKNOWN_CODEC: Data is received on an unknown codec, this most | |
118 | * likely denotes an error on the remote side, the buffers will be ignored. | |
119 | * It can safely be ignored in most cases (but may result in a call with no | |
120 | * media received). | |
121 | * @FS_ERROR_NO_CODECS: There are no codecs detected for that media type. | |
122 | * @FS_ERROR_NO_CODECS_LEFT: All of the codecs have been disabled by the | |
123 | * codec preferences, one should try less strict codec preferences. | |
124 | * @FS_ERROR_CONNECTION_FAILED: Could not connect to the to remote party. | |
125 | * @FS_ERROR_DISPOSED: The object has been disposed. | |
126 | * @FS_ERROR_ALREADY_EXISTS: The object already exists | |
127 | * | |
128 | * This is the enum of error numbers that will come either on the "error" | |
129 | * signal, from the Gst Bus or for error in the FS_ERROR domain in GErrors | |
130 | */ | |
131 | ||
132 | typedef enum _FsError | |
133 | { | |
134 | FS_ERROR_CONSTRUCTION = 1, | |
135 | FS_ERROR_INTERNAL, | |
136 | FS_ERROR_INVALID_ARGUMENTS = 100, | |
137 | FS_ERROR_NETWORK, | |
138 | FS_ERROR_NOT_IMPLEMENTED, | |
139 | FS_ERROR_NEGOTIATION_FAILED, | |
140 | FS_ERROR_UNKNOWN_CODEC, | |
141 | FS_ERROR_NO_CODECS, | |
142 | FS_ERROR_NO_CODECS_LEFT, | |
143 | FS_ERROR_CONNECTION_FAILED, | |
144 | FS_ERROR_DISPOSED, | |
145 | FS_ERROR_ALREADY_EXISTS | |
146 | } FsError; | |
147 | ||
148 | /** | |
149 | * FS_ERROR: | |
150 | * | |
151 | * This quark is used to denote errors coming from Farstream objects | |
152 | */ | |
153 | ||
154 | #define FS_ERROR (fs_error_quark ()) | |
155 | ||
156 | /** | |
157 | * FS_ERROR_IS_FATAL: | |
158 | * @error: a #FsError | |
159 | * | |
160 | * Tells the programmer if an error if fatal or not, if it returns %TRUE, | |
161 | * the error is fatal, and the object that created it should | |
162 | * be discarded. It returns %FALSE otherwise. | |
163 | */ | |
164 | ||
165 | #define FS_ERROR_IS_FATAL(error) \ | |
166 | (error < 100) | |
167 | ||
168 | GQuark fs_error_quark (void); | |
169 | ||
170 | /* virtual class function wrappers */ | |
171 | FsSession *fs_conference_new_session (FsConference *conference, | |
172 | FsMediaType media_type, | |
173 | GError **error); | |
174 | ||
175 | FsParticipant *fs_conference_new_participant (FsConference *conference, | |
176 | GError **error); | |
177 | ||
178 | ||
179 | G_END_DECLS | |
180 | ||
181 | #endif /* __FS_CONFERENCE_H__ */ | |
182 | ||
183 |
0 | /* | |
1 | * Farstream - Recursive element addition notifier | |
2 | * | |
3 | * Copyright 2007-2008 Collabora Ltd. | |
4 | * @author: Olivier Crete <olivier.crete@collabora.co.uk> | |
5 | * Copyright 2007-2008 Nokia Corp. | |
6 | * | |
7 | * This library is free software; you can redistribute it and/or | |
8 | * modify it under the terms of the GNU Lesser General Public | |
9 | * License as published by the Free Software Foundation; either | |
10 | * version 2.1 of the License, or (at your option) any later version. | |
11 | * | |
12 | * This library is distributed in the hope that it will be useful, | |
13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
15 | * Lesser General Public License for more details. | |
16 | * | |
17 | * You should have received a copy of the GNU Lesser General Public | |
18 | * License along with this library; if not, write to the Free Software | |
19 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA | |
20 | */ | |
21 | ||
22 | ||
23 | /** | |
24 | * SECTION:fs-element-added-notifier | |
25 | * @short_description: Recursive element addition notifier | |
26 | * | |
27 | * This object can be attach to any #GstBin and will emit a the | |
28 | * #FsElementAddedNotifier::element-added signal for every element inside the | |
29 | * #GstBin or any sub-bin and any element added in the future to the bin or | |
30 | * its sub-bins. There is also a utility method to have it used to | |
31 | * set the properties of elements based on a GKeyfile. | |
32 | */ | |
33 | ||
34 | #ifdef HAVE_CONFIG_H | |
35 | # include <config.h> | |
36 | #endif | |
37 | ||
38 | #include "fs-element-added-notifier.h" | |
39 | ||
40 | #include <stdlib.h> | |
41 | ||
42 | #include "fs-utils.h" | |
43 | ||
44 | #include "fs-marshal.h" | |
45 | ||
46 | ||
47 | /* Signals */ | |
48 | enum | |
49 | { | |
50 | ELEMENT_ADDED, | |
51 | LAST_SIGNAL | |
52 | }; | |
53 | ||
54 | #define FS_ELEMENT_ADDED_NOTIFIER_GET_PRIVATE(o) \ | |
55 | (G_TYPE_INSTANCE_GET_PRIVATE ((o), FS_TYPE_ELEMENT_ADDED_NOTIFIER, \ | |
56 | FsElementAddedNotifierPrivate)) | |
57 | ||
58 | struct _FsElementAddedNotifierPrivate { | |
59 | GList *keyfiles; | |
60 | }; | |
61 | ||
62 | static void _element_added_callback (GstBin *parent, GstElement *element, | |
63 | gpointer user_data); | |
64 | ||
65 | static void fs_element_added_notifier_finalize (GObject *object); | |
66 | ||
67 | ||
68 | G_DEFINE_TYPE(FsElementAddedNotifier, fs_element_added_notifier, G_TYPE_OBJECT); | |
69 | ||
70 | static guint signals[LAST_SIGNAL] = { 0 }; | |
71 | ||
72 | static void | |
73 | fs_element_added_notifier_class_init (FsElementAddedNotifierClass *klass) | |
74 | { | |
75 | GObjectClass *gobject_class; | |
76 | ||
77 | gobject_class = (GObjectClass *) klass; | |
78 | ||
79 | gobject_class->finalize = fs_element_added_notifier_finalize; | |
80 | ||
81 | /** | |
82 | * FsElementAddedNotifier::element-added: | |
83 | * @self: #FsElementAddedNotifier that emitted the signal | |
84 | * @bin: The #GstBin to which this object was added | |
85 | * @element: The #GstElement that was added | |
86 | * | |
87 | * This signal is emitted when an element is added to a #GstBin that was added | |
88 | * to this object or one of its sub-bins. | |
89 | * Be careful, there is no guarantee that this will be emitted on your | |
90 | * main thread, it will be emitted in the thread that added the element. | |
91 | * The bin may be %NULL if this is the top-level bin. | |
92 | */ | |
93 | signals[ELEMENT_ADDED] = g_signal_new ("element-added", | |
94 | G_TYPE_FROM_CLASS (klass), | |
95 | G_SIGNAL_RUN_LAST, | |
96 | 0, | |
97 | NULL, | |
98 | NULL, | |
99 | _fs_marshal_VOID__OBJECT_OBJECT, | |
100 | G_TYPE_NONE, 2, GST_TYPE_BIN, GST_TYPE_ELEMENT); | |
101 | ||
102 | g_type_class_add_private (klass, sizeof (FsElementAddedNotifierPrivate)); | |
103 | } | |
104 | ||
105 | ||
106 | static void | |
107 | fs_element_added_notifier_init (FsElementAddedNotifier *notifier) | |
108 | { | |
109 | notifier->priv = FS_ELEMENT_ADDED_NOTIFIER_GET_PRIVATE(notifier); | |
110 | } | |
111 | ||
112 | ||
113 | ||
114 | static void | |
115 | fs_element_added_notifier_finalize (GObject *object) | |
116 | { | |
117 | FsElementAddedNotifier *self = FS_ELEMENT_ADDED_NOTIFIER (object); | |
118 | ||
119 | g_list_foreach (self->priv->keyfiles, (GFunc) g_key_file_free, NULL); | |
120 | g_list_free (self->priv->keyfiles); | |
121 | self->priv->keyfiles = NULL; | |
122 | } | |
123 | ||
124 | /** | |
125 | * fs_element_added_notifier_new: | |
126 | * | |
127 | * Creates a new #FsElementAddedNotifier object | |
128 | * | |
129 | * Returns: the newly-created #FsElementAddedNotifier | |
130 | */ | |
131 | ||
132 | FsElementAddedNotifier * | |
133 | fs_element_added_notifier_new (void) | |
134 | { | |
135 | return (FsElementAddedNotifier *) | |
136 | g_object_new (FS_TYPE_ELEMENT_ADDED_NOTIFIER, NULL); | |
137 | } | |
138 | ||
139 | /** | |
140 | * fs_element_added_notifier_add: | |
141 | * @notifier: a #FsElementAddedNotifier | |
142 | * @bin: A #GstBin to watch to added elements | |
143 | * | |
144 | * Add a #GstBin to on which the #FsElementAddedNotifier::element-added signal | |
145 | * will be called on every element and sub-element present and added in the | |
146 | * future. | |
147 | */ | |
148 | ||
149 | void | |
150 | fs_element_added_notifier_add (FsElementAddedNotifier *notifier, | |
151 | GstBin *bin) | |
152 | { | |
153 | g_return_if_fail (notifier && FS_IS_ELEMENT_ADDED_NOTIFIER (notifier)); | |
154 | g_return_if_fail (bin && GST_IS_BIN (bin)); | |
155 | ||
156 | _element_added_callback (NULL, GST_ELEMENT_CAST (bin), notifier); | |
157 | } | |
158 | ||
159 | ||
160 | static void | |
161 | _bin_unparented_cb (GstObject *object, GstObject *parent, gpointer user_data) | |
162 | { | |
163 | GstIterator *iter = NULL; | |
164 | gboolean done; | |
165 | ||
166 | /* Return if there was no handler connected */ | |
167 | if (g_signal_handlers_disconnect_by_func (object, _element_added_callback, | |
168 | user_data) == 0) | |
169 | return; | |
170 | ||
171 | iter = gst_bin_iterate_elements (GST_BIN (object)); | |
172 | ||
173 | done = FALSE; | |
174 | while (!done) | |
175 | { | |
176 | gpointer item; | |
177 | ||
178 | switch (gst_iterator_next (iter, &item)) { | |
179 | case GST_ITERATOR_OK: | |
180 | if (GST_IS_BIN (item)) | |
181 | _bin_unparented_cb (GST_OBJECT (item), object, user_data); | |
182 | gst_object_unref (item); | |
183 | break; | |
184 | case GST_ITERATOR_RESYNC: | |
185 | // We don't rollback anything, we just ignore already processed ones | |
186 | gst_iterator_resync (iter); | |
187 | break; | |
188 | case GST_ITERATOR_ERROR: | |
189 | g_error ("Wrong parameters were given?"); | |
190 | done = TRUE; | |
191 | break; | |
192 | case GST_ITERATOR_DONE: | |
193 | done = TRUE; | |
194 | break; | |
195 | } | |
196 | } | |
197 | ||
198 | gst_iterator_free (iter); | |
199 | } | |
200 | ||
201 | ||
202 | /** | |
203 | * fs_element_added_notifier_remove: | |
204 | * @notifier: a #FsElementAddedNotifier | |
205 | * @bin: A #GstBin to stop watching | |
206 | * | |
207 | * Stop watching the passed bin and its subbins. | |
208 | * | |
209 | * Returns: %TRUE if the #GstBin was being watched, %FALSE otherwise | |
210 | */ | |
211 | ||
212 | gboolean | |
213 | fs_element_added_notifier_remove (FsElementAddedNotifier *notifier, | |
214 | GstBin *bin) | |
215 | { | |
216 | g_return_val_if_fail (FS_IS_ELEMENT_ADDED_NOTIFIER (notifier), FALSE); | |
217 | g_return_val_if_fail (GST_IS_BIN (bin), FALSE); | |
218 | ||
219 | if (g_signal_handler_find (bin, | |
220 | G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA, | |
221 | 0, 0, NULL, /* id, detail, closure */ | |
222 | _element_added_callback, notifier) != 0) | |
223 | { | |
224 | _bin_unparented_cb (GST_OBJECT (bin), NULL, notifier); | |
225 | return TRUE; | |
226 | } | |
227 | else | |
228 | { | |
229 | return FALSE; | |
230 | } | |
231 | } | |
232 | ||
233 | ||
234 | #if 1 | |
235 | # define DEBUG(...) do {} while (0) | |
236 | #else | |
237 | # define DEBUG g_debug | |
238 | #endif | |
239 | ||
240 | static void | |
241 | _bin_added_from_keyfile (FsElementAddedNotifier *notifier, GstBin *bin, | |
242 | GstElement *element, gpointer user_data) | |
243 | { | |
244 | GKeyFile *keyfile = user_data; | |
245 | const gchar *name = NULL; | |
246 | gchar *free_name = NULL; | |
247 | gchar **keys; | |
248 | gint i; | |
249 | GstElementFactory *factory = gst_element_get_factory (element); | |
250 | ||
251 | if (factory) | |
252 | { | |
253 | name = gst_plugin_feature_get_name (GST_PLUGIN_FEATURE (factory)); | |
254 | if (name && !g_key_file_has_group (keyfile, name)) | |
255 | name = NULL; | |
256 | } | |
257 | ||
258 | if (!name) | |
259 | { | |
260 | GST_OBJECT_LOCK (element); | |
261 | if (GST_OBJECT_NAME (element) && | |
262 | g_key_file_has_group (keyfile, GST_OBJECT_NAME (element))) | |
263 | name = free_name = g_strdup (GST_OBJECT_NAME (element)); | |
264 | GST_OBJECT_UNLOCK (element); | |
265 | } | |
266 | ||
267 | if (!name) | |
268 | return; | |
269 | ||
270 | DEBUG ("Found config for %s", name); | |
271 | keys = g_key_file_get_keys (keyfile, name, NULL, NULL); | |
272 | ||
273 | for (i = 0; keys[i]; i++) | |
274 | { | |
275 | GParamSpec *param_spec; | |
276 | GValue prop_value = { 0 }; | |
277 | gchar *str_value; | |
278 | ||
279 | DEBUG ("getting %s", keys[i]); | |
280 | param_spec = g_object_class_find_property (G_OBJECT_GET_CLASS(element), | |
281 | keys[i]); | |
282 | ||
283 | if (!param_spec) | |
284 | { | |
285 | DEBUG ("Property %s does not exist in element %s, ignoring", | |
286 | keys[i], name); | |
287 | continue; | |
288 | } | |
289 | ||
290 | g_value_init (&prop_value, param_spec->value_type); | |
291 | ||
292 | str_value = g_key_file_get_value (keyfile, name, keys[i], NULL); | |
293 | if (str_value && gst_value_deserialize (&prop_value, str_value)) | |
294 | { | |
295 | DEBUG ("Setting %s to on %s", keys[i], name); | |
296 | g_object_set_property (G_OBJECT (element), keys[i], &prop_value); | |
297 | } | |
298 | else | |
299 | { | |
300 | DEBUG ("Could not read value for property %s", keys[i]); | |
301 | } | |
302 | g_free (str_value); | |
303 | g_value_unset (&prop_value); | |
304 | } | |
305 | ||
306 | g_strfreev (keys); | |
307 | g_free (free_name); | |
308 | } | |
309 | ||
310 | ||
311 | /** | |
312 | * fs_element_added_notifier_set_properties_from_keyfile: | |
313 | * @notifier: a #FsElementAddedNotifier | |
314 | * @keyfile: a #GKeyFile | |
315 | * | |
316 | * Using a #GKeyFile where the groups are the element's type or name | |
317 | * and the key=value are the property and its value, this function | |
318 | * will set the properties on the elements added to this object after | |
319 | * this function has been called. It will take ownership of the | |
320 | * GKeyFile structure. It will first try the group as the element type, if that | |
321 | * does not match, it will check its name. | |
322 | */ | |
323 | void | |
324 | fs_element_added_notifier_set_properties_from_keyfile ( | |
325 | FsElementAddedNotifier *notifier, | |
326 | GKeyFile *keyfile) | |
327 | { | |
328 | g_return_if_fail (FS_IS_ELEMENT_ADDED_NOTIFIER (notifier)); | |
329 | g_return_if_fail (keyfile); | |
330 | ||
331 | g_signal_connect (notifier, "element-added", | |
332 | G_CALLBACK (_bin_added_from_keyfile), keyfile); | |
333 | ||
334 | notifier->priv->keyfiles = | |
335 | g_list_prepend (notifier->priv->keyfiles, keyfile); | |
336 | } | |
337 | ||
338 | ||
339 | /** | |
340 | * fs_element_added_notifier_set_properties_from_file: | |
341 | * @notifier: a #FsElementAddedNotifier | |
342 | * @filename: The name of the keyfile to use | |
343 | * @error: location of a #GError, or %NULL if no error occured | |
344 | * | |
345 | * Same as fs_element_added_notifier_set_properties_from_keyfile() but using | |
346 | * the name of the file to load instead of the #GKeyFile directly. | |
347 | * | |
348 | * Returns: %TRUE if the file was successfully loaded, %FALSE otherwise | |
349 | */ | |
350 | gboolean | |
351 | fs_element_added_notifier_set_properties_from_file ( | |
352 | FsElementAddedNotifier *notifier, | |
353 | const gchar *filename, | |
354 | GError **error) | |
355 | { | |
356 | GKeyFile *keyfile = g_key_file_new (); | |
357 | ||
358 | if (!g_key_file_load_from_file (keyfile, filename, G_KEY_FILE_NONE, error)) | |
359 | { | |
360 | g_key_file_free (keyfile); | |
361 | return FALSE; | |
362 | } | |
363 | ||
364 | fs_element_added_notifier_set_properties_from_keyfile(notifier, keyfile); | |
365 | ||
366 | return TRUE; | |
367 | } | |
368 | ||
369 | static void | |
370 | _element_added_callback (GstBin *parent, GstElement *element, | |
371 | gpointer user_data) | |
372 | { | |
373 | FsElementAddedNotifier *notifier = FS_ELEMENT_ADDED_NOTIFIER (user_data); | |
374 | ||
375 | if (GST_IS_BIN (element)) { | |
376 | GstIterator *iter = NULL; | |
377 | gboolean done; | |
378 | ||
379 | g_signal_connect_object (element, "element-added", | |
380 | G_CALLBACK (_element_added_callback), notifier, 0); | |
381 | ||
382 | if (parent) | |
383 | g_signal_connect_object (element, "parent-unset", | |
384 | G_CALLBACK (_bin_unparented_cb), notifier, 0); | |
385 | ||
386 | iter = gst_bin_iterate_elements (GST_BIN (element)); | |
387 | ||
388 | done = FALSE; | |
389 | while (!done) | |
390 | { | |
391 | gpointer item = NULL; | |
392 | ||
393 | switch (gst_iterator_next (iter, &item)) { | |
394 | case GST_ITERATOR_OK: | |
395 | /* We make sure the callback has not already been added */ | |
396 | if (g_signal_handler_find (item, | |
397 | G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA, | |
398 | 0, 0, NULL, /* id, detail, closure */ | |
399 | _element_added_callback, notifier) == 0) | |
400 | _element_added_callback (GST_BIN_CAST (element), item, notifier); | |
401 | gst_object_unref (item); | |
402 | break; | |
403 | case GST_ITERATOR_RESYNC: | |
404 | // We don't rollback anything, we just ignore already processed ones | |
405 | gst_iterator_resync (iter); | |
406 | break; | |
407 | case GST_ITERATOR_ERROR: | |
408 | g_error ("Wrong parameters were given?"); | |
409 | done = TRUE; | |
410 | break; | |
411 | case GST_ITERATOR_DONE: | |
412 | done = TRUE; | |
413 | break; | |
414 | } | |
415 | } | |
416 | ||
417 | gst_iterator_free (iter); | |
418 | } | |
419 | ||
420 | g_signal_emit (notifier, signals[ELEMENT_ADDED], 0, parent, element); | |
421 | } | |
422 | ||
423 | ||
424 | /** | |
425 | * fs_element_added_notifier_set_default_properties: | |
426 | * @notifier: a #FsElementAddedNotifier | |
427 | * @element: Element for which to set the default codec | |
428 | * preferences | |
429 | * | |
430 | * Same as first calling fs_utils_get_default_element_properties() and using | |
431 | * the result with | |
432 | * fs_element_added_notifier_set_properties_from_keyfile() . | |
433 | * | |
434 | * This is binding friendly (since GKeyFile doesn't have a boxed type). | |
435 | */ | |
436 | void | |
437 | fs_element_added_notifier_set_default_properties ( | |
438 | FsElementAddedNotifier *notifier, | |
439 | GstElement *element) | |
440 | { | |
441 | GKeyFile *keyfile = fs_utils_get_default_element_properties (element); | |
442 | ||
443 | if (!keyfile) | |
444 | return; | |
445 | ||
446 | fs_element_added_notifier_set_properties_from_keyfile(notifier, keyfile); | |
447 | } |
0 | /* | |
1 | * Farstream - Recursive element addition notifier | |
2 | * | |
3 | * Copyright 2007-2008 Collabora Ltd. | |
4 | * @author: Olivier Crete <olivier.crete@collabora.co.uk> | |
5 | * Copyright 2007-2008 Nokia Corp. | |
6 | * | |
7 | * This library is free software; you can redistribute it and/or | |
8 | * modify it under the terms of the GNU Lesser General Public | |
9 | * License as published by the Free Software Foundation; either | |
10 | * version 2.1 of the License, or (at your option) any later version. | |
11 | * | |
12 | * This library is distributed in the hope that it will be useful, | |
13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
15 | * Lesser General Public License for more details. | |
16 | * | |
17 | * You should have received a copy of the GNU Lesser General Public | |
18 | * License along with this library; if not, write to the Free Software | |
19 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA | |
20 | */ | |
21 | ||
22 | #ifndef __FS_ELEMENT_ADDED_NOTIFIER_H__ | |
23 | #define __FS_ELEMENT_ADDED_NOTIFIER_H__ | |
24 | ||
25 | #include <gst/gst.h> | |
26 | ||
27 | G_BEGIN_DECLS | |
28 | ||
29 | ||
30 | /* TYPE MACROS */ | |
31 | #define FS_TYPE_ELEMENT_ADDED_NOTIFIER \ | |
32 | (fs_element_added_notifier_get_type ()) | |
33 | #define FS_ELEMENT_ADDED_NOTIFIER(obj) \ | |
34 | (G_TYPE_CHECK_INSTANCE_CAST((obj), FS_TYPE_ELEMENT_ADDED_NOTIFIER, \ | |
35 | FsElementAddedNotifier)) | |
36 | #define FS_ELEMENT_ADDED_NOTIFIER_CLASS(klass) \ | |
37 | (G_TYPE_CHECK_CLASS_CAST((klass), FS_TYPE_ELEMENT_ADDED_NOTIFIER, \ | |
38 | FsElementAddedNotifierClass)) | |
39 | #define FS_IS_ELEMENT_ADDED_NOTIFIER(obj) \ | |
40 | (G_TYPE_CHECK_INSTANCE_TYPE((obj), FS_TYPE_ELEMENT_ADDED_NOTIFIER)) | |
41 | #define FS_IS_ELEMENT_ADDED_NOTIFIER_CLASS(klass) \ | |
42 | (G_TYPE_CHECK_CLASS_TYPE((klass), FS_TYPE_ELEMENT_ADDED_NOTIFIER)) | |
43 | #define FS_ELEMENT_ADDED_NOTIFIER_GET_CLASS(obj) \ | |
44 | (G_TYPE_INSTANCE_GET_CLASS ((obj), FS_TYPE_ELEMENT_ADDED_NOTIFIER, \ | |
45 | FsElementAddedNotifierClass)) | |
46 | ||
47 | ||
48 | typedef struct _FsElementAddedNotifier FsElementAddedNotifier; | |
49 | typedef struct _FsElementAddedNotifierClass FsElementAddedNotifierClass; | |
50 | typedef struct _FsElementAddedNotifierPrivate FsElementAddedNotifierPrivate; | |
51 | ||
52 | /** | |
53 | * FsElementAddedNotifier: | |
54 | * | |
55 | * All members are private | |
56 | */ | |
57 | ||
58 | struct _FsElementAddedNotifier | |
59 | { | |
60 | GObject parent; | |
61 | ||
62 | /*< private >*/ | |
63 | ||
64 | FsElementAddedNotifierPrivate *priv; | |
65 | }; | |
66 | ||
67 | /** | |
68 | * FsElementAddedNotifierClass: | |
69 | * @parent_class: the #GObjectClass parent | |
70 | * | |
71 | * All members are private | |
72 | */ | |
73 | struct _FsElementAddedNotifierClass | |
74 | { | |
75 | GObjectClass parent_class; | |
76 | }; | |
77 | ||
78 | ||
79 | GType fs_element_added_notifier_get_type (void); | |
80 | ||
81 | FsElementAddedNotifier *fs_element_added_notifier_new (void); | |
82 | ||
83 | void fs_element_added_notifier_add (FsElementAddedNotifier *notifier, | |
84 | GstBin *bin); | |
85 | ||
86 | gboolean fs_element_added_notifier_remove (FsElementAddedNotifier *notifier, | |
87 | GstBin *bin); | |
88 | ||
89 | void fs_element_added_notifier_set_properties_from_keyfile ( | |
90 | FsElementAddedNotifier *notifier, | |
91 | GKeyFile *keyfile); | |
92 | ||
93 | gboolean fs_element_added_notifier_set_properties_from_file ( | |
94 | FsElementAddedNotifier *notifier, | |
95 | const gchar *filename, | |
96 | GError **error); | |
97 | ||
98 | void fs_element_added_notifier_set_default_properties ( | |
99 | FsElementAddedNotifier *notifier, | |
100 | GstElement *element); | |
101 | ||
102 | G_END_DECLS | |
103 | ||
104 | #endif /* __FS_ELEMENT_ADDED_NOTIFIER_H__ */ |
0 | /* | |
1 | * Farstream - Farstream Participant | |
2 | * | |
3 | * Copyright 2007 Collabora Ltd. | |
4 | * @author: Philippe Kalaf <philippe.kalaf@collabora.co.uk> | |
5 | * Copyright 2007 Nokia Corp. | |
6 | * | |
7 | * fs-participant.c - A Farstream Participant gobject (base implementation) | |
8 | * | |
9 | * This library is free software; you can redistribute it and/or | |
10 | * modify it under the terms of the GNU Lesser General Public | |
11 | * License as published by the Free Software Foundation; either | |
12 | * version 2.1 of the License, or (at your option) any later version. | |
13 | * | |
14 | * This library is distributed in the hope that it will be useful, | |
15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
17 | * Lesser General Public License for more details. | |
18 | * | |
19 | * You should have received a copy of the GNU Lesser General Public | |
20 | * License along with this library; if not, write to the Free Software | |
21 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA | |
22 | */ | |
23 | ||
24 | /** | |
25 | * SECTION:fs-participant | |
26 | * @short_description: A participant in a conference | |
27 | * | |
28 | * This object is the base implementation of a Farstream Participant. It needs to be | |
29 | * derived and implemented by a farstream conference gstreamer element. A | |
30 | * participant represents any source of media in a conference. This could be a | |
31 | * human-participant or an automaton. | |
32 | */ | |
33 | ||
34 | #ifdef HAVE_CONFIG_H | |
35 | #include "config.h" | |
36 | #endif | |
37 | ||
38 | #include "fs-participant.h" | |
39 | #include "fs-enumtypes.h" | |
40 | #include "fs-marshal.h" | |
41 | ||
42 | /* Signals */ | |
43 | enum | |
44 | { | |
45 | LAST_SIGNAL | |
46 | }; | |
47 | ||
48 | /* props */ | |
49 | enum | |
50 | { | |
51 | PROP_0 | |
52 | }; | |
53 | ||
54 | /* | |
55 | struct _FsParticipantPrivate | |
56 | { | |
57 | }; | |
58 | */ | |
59 | ||
60 | G_DEFINE_ABSTRACT_TYPE(FsParticipant, fs_participant, GST_TYPE_OBJECT); | |
61 | ||
62 | #define FS_PARTICIPANT_GET_PRIVATE(o) \ | |
63 | (G_TYPE_INSTANCE_GET_PRIVATE ((o), FS_TYPE_PARTICIPANT, \ | |
64 | FsParticipantPrivate)) | |
65 | ||
66 | static void fs_participant_finalize (GObject *object); | |
67 | ||
68 | ||
69 | // static guint signals[LAST_SIGNAL] = { 0 }; | |
70 | ||
71 | static void | |
72 | fs_participant_class_init (FsParticipantClass *klass) | |
73 | { | |
74 | GObjectClass *gobject_class; | |
75 | ||
76 | gobject_class = (GObjectClass *) klass; | |
77 | ||
78 | gobject_class->finalize = fs_participant_finalize; | |
79 | ||
80 | // g_type_class_add_private (klass, sizeof (FsParticipantPrivate)); | |
81 | } | |
82 | ||
83 | static void | |
84 | fs_participant_init (FsParticipant *self) | |
85 | { | |
86 | //self->priv = FS_PARTICIPANT_GET_PRIVATE (self); | |
87 | self->mutex = g_mutex_new (); | |
88 | } | |
89 | ||
90 | static void | |
91 | fs_participant_finalize (GObject *object) | |
92 | { | |
93 | FsParticipant *self = FS_PARTICIPANT (object); | |
94 | g_mutex_free (self->mutex); | |
95 | ||
96 | G_OBJECT_CLASS (fs_participant_parent_class)->finalize (object); | |
97 | } |
0 | /* | |
1 | * Farstream - Farstream Participant | |
2 | * | |
3 | * Copyright 2007 Collabora Ltd. | |
4 | * @author: Philippe Kalaf <philippe.kalaf@collabora.co.uk> | |
5 | * Copyright 2007 Nokia Corp. | |
6 | * | |
7 | * fs-participant.h - A Farstream Participant gobject (base implementation) | |
8 | * | |
9 | * This library is free software; you can redistribute it and/or | |
10 | * modify it under the terms of the GNU Lesser General Public | |
11 | * License as published by the Free Software Foundation; either | |
12 | * version 2.1 of the License, or (at your option) any later version. | |
13 | * | |
14 | * This library is distributed in the hope that it will be useful, | |
15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
17 | * Lesser General Public License for more details. | |
18 | * | |
19 | * You should have received a copy of the GNU Lesser General Public | |
20 | * License along with this library; if not, write to the Free Software | |
21 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA | |
22 | */ | |
23 | ||
24 | #ifndef __FS_PARTICIPANT_H__ | |
25 | #define __FS_PARTICIPANT_H__ | |
26 | ||
27 | #include <gst/gst.h> | |
28 | ||
29 | G_BEGIN_DECLS | |
30 | ||
31 | /* TYPE MACROS */ | |
32 | #define FS_TYPE_PARTICIPANT \ | |
33 | (fs_participant_get_type ()) | |
34 | #define FS_PARTICIPANT(obj) \ | |
35 | (G_TYPE_CHECK_INSTANCE_CAST((obj), FS_TYPE_PARTICIPANT, FsParticipant)) | |
36 | #define FS_PARTICIPANT_CLASS(klass) \ | |
37 | (G_TYPE_CHECK_CLASS_CAST((klass), FS_TYPE_PARTICIPANT, FsParticipantClass)) | |
38 | #define FS_IS_PARTICIPANT(obj) \ | |
39 | (G_TYPE_CHECK_INSTANCE_TYPE((obj), FS_TYPE_PARTICIPANT)) | |
40 | #define FS_IS_PARTICIPANT_CLASS(klass) \ | |
41 | (G_TYPE_CHECK_CLASS_TYPE((klass), FS_TYPE_PARTICIPANT)) | |
42 | #define FS_PARTICIPANT_GET_CLASS(obj) \ | |
43 | (G_TYPE_INSTANCE_GET_CLASS ((obj), FS_TYPE_PARTICIPANT, FsParticipantClass)) | |
44 | #define FS_PARTICIPANT_CAST(obj) ((FsParticipant *) (obj)) | |
45 | ||
46 | typedef struct _FsParticipant FsParticipant; | |
47 | typedef struct _FsParticipantClass FsParticipantClass; | |
48 | typedef struct _FsParticipantPrivate FsParticipantPrivate; | |
49 | ||
50 | /** | |
51 | * FsParticipantClass: | |
52 | * @parent_class: Our parent | |
53 | * | |
54 | * The FsParticipant class has no virtual methods to implement, | |
55 | * but you may want to override the properties or attach more date to it | |
56 | */ | |
57 | ||
58 | struct _FsParticipantClass | |
59 | { | |
60 | GstObjectClass parent_class; | |
61 | ||
62 | /* virtual functions */ | |
63 | ||
64 | /*< private >*/ | |
65 | FsParticipantPrivate *priv; | |
66 | gpointer _padding[8]; | |
67 | }; | |
68 | ||
69 | /** | |
70 | * FsParticipant: | |
71 | * | |
72 | * All members are private (access them using the properties) | |
73 | */ | |
74 | struct _FsParticipant | |
75 | { | |
76 | GstObject parent; | |
77 | ||
78 | /*< private >*/ | |
79 | ||
80 | GMutex *mutex; | |
81 | ||
82 | FsParticipantPrivate *priv; | |
83 | ||
84 | gpointer _padding[8]; | |
85 | }; | |
86 | ||
87 | /** | |
88 | * FS_PARTICIPANT_DATA_LOCK | |
89 | * @participant: A #FsParticipant | |
90 | * | |
91 | * Locks the participant for data set with g_object_set_data() or | |
92 | * g_object_set_qdata(). | |
93 | */ | |
94 | ||
95 | #define FS_PARTICIPANT_DATA_LOCK(participant) \ | |
96 | g_mutex_lock ((participant)->mutex) | |
97 | ||
98 | /** | |
99 | * FS_PARTICIPANT_DATA_UNLOCK | |
100 | * @participant: A #FsParticipant | |
101 | * | |
102 | * Unlocks the participant for data set with g_object_set_data() or | |
103 | * g_object_set_qdata(). | |
104 | */ | |
105 | ||
106 | #define FS_PARTICIPANT_DATA_UNLOCK(participant) \ | |
107 | g_mutex_unlock ((participant)->mutex) | |
108 | ||
109 | GType fs_participant_get_type (void); | |
110 | ||
111 | G_END_DECLS | |
112 | ||
113 | #endif /* __FS_PARTICIPANT_H__ */ |
0 | /* | |
1 | * fs-plugin.c - Source for farstream plugin infrastructure | |
2 | * | |
3 | * Farstream Voice+Video library | |
4 | * Copyright (c) 2005 INdT. | |
5 | * @author Andre Moreira Magalhaes <andre.magalhaes@indt.org.br> | |
6 | * Copyright 2005-2007 Collabora Ltd. | |
7 | * Copyright 2005-2007 Nokia Corp. | |
8 | * @author Rob Taylor <rob.taylor@collabora.co.uk> | |
9 | * @author: Olivier Crete <olivier.crete@collabora.co.uk> | |
10 | * | |
11 | * | |
12 | * This library is free software; you can redistribute it and/or | |
13 | * modify it under the terms of the GNU Lesser General Public | |
14 | * License as published by the Free Software Foundation; either | |
15 | * version 2.1 of the License, or (at your option) any later version. | |
16 | * | |
17 | * This library is distributed in the hope that it will be useful, | |
18 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
19 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
20 | * Lesser General Public License for more details. | |
21 | * | |
22 | * You should have received a copy of the GNU Lesser General Public | |
23 | * License along with this library; if not, write to the Free Software | |
24 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA | |
25 | */ | |
26 | ||
27 | #ifdef HAVE_CONFIG_H | |
28 | #include "config.h" | |
29 | #endif | |
30 | ||
31 | #include "fs-plugin.h" | |
32 | ||
33 | #include <string.h> | |
34 | ||
35 | #include "fs-conference.h" | |
36 | #include "fs-private.h" | |
37 | ||
38 | #define GST_CAT_DEFAULT fs_conference_debug | |
39 | ||
40 | /** | |
41 | * SECTION:fs-plugin | |
42 | * @short_description: A class for defining Farstream plugins | |
43 | * | |
44 | * This class is a generic class to load GType plugins based on their name. | |
45 | * With this simple class, you can only have one type per plugin. | |
46 | */ | |
47 | ||
48 | #define FS_PLUGIN_GET_PRIVATE(o) \ | |
49 | (G_TYPE_INSTANCE_GET_PRIVATE ((o), FS_TYPE_PLUGIN, FsPluginPrivate)) | |
50 | ||
51 | static gboolean fs_plugin_load (GTypeModule *module); | |
52 | ||
53 | ||
54 | static GStaticMutex mutex = G_STATIC_MUTEX_INIT; | |
55 | static gchar **search_paths = NULL; | |
56 | static GList *plugins = NULL; | |
57 | ||
58 | struct _FsPluginPrivate | |
59 | { | |
60 | GModule *handle; | |
61 | }; | |
62 | ||
63 | G_DEFINE_TYPE(FsPlugin, fs_plugin, G_TYPE_TYPE_MODULE); | |
64 | ||
65 | static void | |
66 | fs_plugin_search_path_init (void) | |
67 | { | |
68 | const gchar *env; | |
69 | ||
70 | if (search_paths) | |
71 | return; | |
72 | ||
73 | env = g_getenv ("FS_PLUGIN_PATH"); | |
74 | ||
75 | if (env == NULL) | |
76 | { | |
77 | search_paths = g_new (gchar *, 2); | |
78 | search_paths[0] = g_strdup (FS_PLUGIN_PATH); | |
79 | search_paths[1] = NULL; | |
80 | return; | |
81 | } | |
82 | else | |
83 | { | |
84 | gchar *path; | |
85 | ||
86 | path = g_strjoin (":", env, FS_PLUGIN_PATH, NULL); | |
87 | search_paths = g_strsplit (path, ":", -1); | |
88 | g_free (path); | |
89 | } | |
90 | } | |
91 | ||
92 | static void | |
93 | fs_plugin_class_init (FsPluginClass * klass) | |
94 | { | |
95 | GTypeModuleClass *module_class = G_TYPE_MODULE_CLASS (klass); | |
96 | ||
97 | module_class->load = fs_plugin_load; | |
98 | ||
99 | g_type_class_add_private (klass, sizeof (FsPluginPrivate)); | |
100 | ||
101 | /* Calling from class initializer so it only gets init'ed once */ | |
102 | fs_plugin_search_path_init (); | |
103 | } | |
104 | ||
105 | ||
106 | ||
107 | static void | |
108 | fs_plugin_init (FsPlugin * plugin) | |
109 | { | |
110 | /* member init */ | |
111 | plugin->priv = FS_PLUGIN_GET_PRIVATE (plugin); | |
112 | plugin->priv->handle = NULL; | |
113 | } | |
114 | ||
115 | static gboolean fs_plugin_load (GTypeModule *module) | |
116 | { | |
117 | FsPlugin *plugin = FS_PLUGIN(module); | |
118 | gchar **search_path = NULL; | |
119 | gchar *path=NULL; | |
120 | ||
121 | gboolean (*fs_init_plugin) (FsPlugin *); | |
122 | ||
123 | g_return_val_if_fail (plugin != NULL, FALSE); | |
124 | g_return_val_if_fail (plugin->name != NULL && plugin->name[0] != '\0', FALSE); | |
125 | ||
126 | for (search_path = search_paths; *search_path; search_path++) { | |
127 | GST_DEBUG("looking for plugins in %s", *search_path); | |
128 | ||
129 | path = g_module_build_path (*search_path, plugin->name); | |
130 | ||
131 | plugin->priv->handle = g_module_open (path, G_MODULE_BIND_LOCAL); | |
132 | GST_INFO ("opening module %s: %s\n", path, | |
133 | (plugin->priv->handle != NULL) ? "succeeded" : g_module_error ()); | |
134 | g_free (path); | |
135 | ||
136 | if (!plugin->priv->handle) { | |
137 | continue; | |
138 | } | |
139 | ||
140 | else if (!g_module_symbol (plugin->priv->handle, | |
141 | "fs_init_plugin", | |
142 | (gpointer) & fs_init_plugin)) { | |
143 | g_module_close (plugin->priv->handle); | |
144 | plugin->priv->handle = NULL; | |
145 | GST_WARNING ("could not find init function in plugin\n"); | |
146 | continue; | |
147 | } | |
148 | ||
149 | else | |
150 | break; | |
151 | } | |
152 | ||
153 | if (!plugin->priv->handle) { | |
154 | return FALSE; | |
155 | } | |
156 | ||
157 | fs_init_plugin (plugin); | |
158 | if (!plugin->type) { | |
159 | /* TODO error handling (init error or no info defined) */ | |
160 | GST_WARNING ("init error or no info defined"); | |
161 | goto err_close_module; | |
162 | } | |
163 | ||
164 | return TRUE; | |
165 | ||
166 | err_close_module: | |
167 | g_module_close (plugin->priv->handle); | |
168 | return FALSE; | |
169 | ||
170 | } | |
171 | ||
172 | static FsPlugin * | |
173 | fs_plugin_get_by_name_locked (const gchar * name, const gchar * type_suffix) | |
174 | { | |
175 | gchar *fullname; | |
176 | FsPlugin *plugin = NULL; | |
177 | GList *plugin_item; | |
178 | ||
179 | g_return_val_if_fail (name != NULL, NULL); | |
180 | g_return_val_if_fail (type_suffix != NULL, NULL); | |
181 | ||
182 | fullname = g_strdup_printf ("%s-%s",name,type_suffix); | |
183 | ||
184 | for (plugin_item = plugins; | |
185 | plugin_item; | |
186 | plugin_item = g_list_next (plugin_item)) { | |
187 | plugin = plugin_item->data; | |
188 | if (plugin->name == NULL || plugin->name[0] == 0) | |
189 | continue; | |
190 | if (!strcmp (plugin->name, fullname)) { | |
191 | break; | |
192 | } | |
193 | ||
194 | } | |
195 | g_free (fullname); | |
196 | ||
197 | if (plugin_item) | |
198 | return plugin; | |
199 | ||
200 | return NULL; | |
201 | } | |
202 | ||
203 | ||
204 | /** | |
205 | * fs_plugin_create_valist: | |
206 | * @name: The name of the plugin to load | |
207 | * @type_suffix: The type of plugin to load (normally "transmitter") | |
208 | * @error: location of a #GError, or NULL if no error occured | |
209 | * @first_property_name: The name of the first property to be set on the | |
210 | * object | |
211 | * @var_args: The rest of the arguments | |
212 | * | |
213 | * Loads the appropriate plugin if necessary and creates a GObject of | |
214 | * the requested type | |
215 | * | |
216 | * Returns: (transfer full): The object created (or NULL if there is an error) | |
217 | **/ | |
218 | ||
219 | GObject * | |
220 | fs_plugin_create_valist (const gchar *name, const gchar *type_suffix, | |
221 | GError **error, const gchar *first_property_name, va_list var_args) | |
222 | { | |
223 | GObject *object; | |
224 | FsPlugin *plugin; | |
225 | ||
226 | g_return_val_if_fail (name, NULL); | |
227 | g_return_val_if_fail (type_suffix, NULL); | |
228 | ||
229 | _fs_conference_init_debug (); | |
230 | ||
231 | g_static_mutex_lock (&mutex); | |
232 | ||
233 | plugin = fs_plugin_get_by_name_locked (name, type_suffix); | |
234 | ||
235 | if (!plugin) { | |
236 | plugin = g_object_new (FS_TYPE_PLUGIN, NULL); | |
237 | if (!plugin) { | |
238 | g_static_mutex_unlock (&mutex); | |
239 | g_set_error (error, FS_ERROR, FS_ERROR_CONSTRUCTION, | |
240 | "Could not create a fsplugin object"); | |
241 | return NULL; | |
242 | } | |
243 | plugin->name = g_strdup_printf ("%s-%s",name,type_suffix); | |
244 | g_type_module_set_name (G_TYPE_MODULE (plugin), plugin->name); | |
245 | plugins = g_list_append (plugins, plugin); | |
246 | ||
247 | /* We do the use once and then we keep it loaded forever because | |
248 | * the gstreamer libraries can't be unloaded | |
249 | */ | |
250 | if (!g_type_module_use (G_TYPE_MODULE (plugin))) { | |
251 | g_static_mutex_unlock (&mutex); | |
252 | g_set_error (error, FS_ERROR, FS_ERROR_CONSTRUCTION, | |
253 | "Could not load the %s-%s transmitter plugin", name, type_suffix); | |
254 | return NULL; | |
255 | } | |
256 | } | |
257 | ||
258 | g_static_mutex_unlock (&mutex); | |
259 | ||
260 | object = g_object_new_valist (plugin->type, first_property_name, var_args); | |
261 | ||
262 | return object; | |
263 | } | |
264 | ||
265 | ||
266 | /** | |
267 | * fs_plugin_create: | |
268 | * @name: The name of the plugin to load | |
269 | * @type_suffix: The type of plugin to load (normally "transmitter") | |
270 | * @error: location of a #GError, or NULL if no error occured | |
271 | * @first_property_name: The name of the first property to be set on the | |
272 | * object | |
273 | * @...: The NULL-terminated list of properties to set on the transmitter | |
274 | * | |
275 | * Loads the appropriate plugin if necessary and creates a GObject of | |
276 | * the requested type | |
277 | * | |
278 | * Returns: (transfer full): The object created (or NULL if there is an error) | |
279 | **/ | |
280 | ||
281 | GObject * | |
282 | fs_plugin_create (const gchar *name, const gchar *type_suffix, | |
283 | GError **error, const gchar *first_property_name, ...) | |
284 | { | |
285 | va_list var_args; | |
286 | GObject *obj; | |
287 | ||
288 | va_start (var_args, first_property_name); | |
289 | obj = fs_plugin_create_valist (name, type_suffix, error, first_property_name, | |
290 | var_args); | |
291 | va_end (var_args); | |
292 | ||
293 | return obj; | |
294 | } | |
295 | ||
296 | /** | |
297 | * fs_plugin_list_available: | |
298 | * @type_suffix: Get list of plugins with this type suffix | |
299 | * | |
300 | * Gets the list of all available plugins of a certain type | |
301 | * | |
302 | * Returns: (transfer full): a newly allocated NULL terminated array of | |
303 | * strings or %NULL if no strings were found. | |
304 | * It should be freed with g_strfreev(). | |
305 | */ | |
306 | ||
307 | gchar ** | |
308 | fs_plugin_list_available (const gchar *type_suffix) | |
309 | { | |
310 | GPtrArray *list = g_ptr_array_new (); | |
311 | gchar **retval = NULL; | |
312 | gchar **search_path = NULL; | |
313 | GRegex *matcher; | |
314 | GError *error = NULL; | |
315 | gchar *tmp1, *tmp2, *tmp3; | |
316 | ||
317 | g_static_mutex_lock (&mutex); | |
318 | ||
319 | fs_plugin_search_path_init (); | |
320 | ||
321 | tmp1 = g_strdup_printf ("(.+)-%s", type_suffix); | |
322 | tmp2 = g_module_build_path ("", tmp1); | |
323 | tmp3 = g_strconcat ("^", tmp2, NULL); | |
324 | matcher = g_regex_new (tmp3, 0, 0, NULL); | |
325 | g_free (tmp1); | |
326 | g_free (tmp2); | |
327 | g_free (tmp3); | |
328 | ||
329 | ||
330 | for (search_path = search_paths; *search_path; search_path++) | |
331 | { | |
332 | GDir *dir = NULL; | |
333 | const gchar *entry; | |
334 | ||
335 | dir = g_dir_open (*search_path, 0, &error); | |
336 | if (!dir) | |
337 | { | |
338 | GST_WARNING ("Could not open path %s to look for plugins: %s", | |
339 | *search_path, error ? error->message : "Unknown error"); | |
340 | g_clear_error (&error); | |
341 | continue; | |
342 | } | |
343 | ||
344 | while ((entry = g_dir_read_name (dir))) | |
345 | { | |
346 | gchar **matches = NULL; | |
347 | ||
348 | matches = g_regex_split (matcher, entry, 0); | |
349 | ||
350 | if (matches && g_strv_length (matches) == 3) | |
351 | { | |
352 | gint i; | |
353 | gboolean found = FALSE; | |
354 | ||
355 | for (i = 0; i < list->len; i++) | |
356 | { | |
357 | if (!strcmp (matches[1], g_ptr_array_index (list, i))) | |
358 | { | |
359 | found = TRUE; | |
360 | break; | |
361 | } | |
362 | } | |
363 | if (!found) | |
364 | g_ptr_array_add (list, g_strdup (matches[1])); | |
365 | } | |
366 | ||
367 | g_strfreev (matches); | |
368 | } | |
369 | ||
370 | g_dir_close (dir); | |
371 | } | |
372 | ||
373 | g_regex_unref (matcher); | |
374 | ||
375 | if (list->len) | |
376 | { | |
377 | g_ptr_array_add (list, NULL); | |
378 | retval = (gchar**) list->pdata; | |
379 | g_ptr_array_free (list, FALSE); | |
380 | } | |
381 | else | |
382 | { | |
383 | g_ptr_array_free (list, TRUE); | |
384 | } | |
385 | ||
386 | g_static_mutex_unlock (&mutex); | |
387 | ||
388 | return retval; | |
389 | } |
0 | /* | |
1 | * fs-plugin.h - Header for farstream plugin infrastructure | |
2 | * | |
3 | * Farstream Voice+Video library | |
4 | * Copyright (c) 2005 INdT. | |
5 | * @author: Andre Moreira Magalhaes <andre.magalhaes@indt.org.br> | |
6 | * Copyright (c) 2005-2007 Collabora Ltd. | |
7 | * Copyright (c) 2005-2007 Nokia Corp. | |
8 | * @author: Rob Taylor <rob.taylor@collabora.co.uk> | |
9 | * @author: Olivier Crete <olivier.crete@collabora.co.uk> | |
10 | * | |
11 | * This library is free software; you can redistribute it and/or | |
12 | * modify it under the terms of the GNU Lesser General Public | |
13 | * License as published by the Free Software Foundation; either | |
14 | * version 2.1 of the License, or (at your option) any later version. | |
15 | * | |
16 | * This library is distributed in the hope that it will be useful, | |
17 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
18 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
19 | * Lesser General Public License for more details. | |
20 | * | |
21 | * You should have received a copy of the GNU Lesser General Public | |
22 | * License along with this library; if not, write to the Free Software | |
23 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA | |
24 | */ | |
25 | ||
26 | #ifndef __FS_PLUGIN_H__ | |
27 | #define __FS_PLUGIN_H__ | |
28 | ||
29 | #include <glib.h> | |
30 | #include <glib-object.h> | |
31 | #include <gmodule.h> | |
32 | #include <gst/gst.h> | |
33 | ||
34 | #include <stdarg.h> | |
35 | ||
36 | G_BEGIN_DECLS | |
37 | ||
38 | ||
39 | /* TYPE MACROS */ | |
40 | #define FS_TYPE_PLUGIN \ | |
41 | (fs_plugin_get_type ()) | |
42 | #define FS_PLUGIN(obj) \ | |
43 | (G_TYPE_CHECK_INSTANCE_CAST((obj), FS_TYPE_PLUGIN, FsPlugin)) | |
44 | #define FS_PLUGIN_CLASS(klass) \ | |
45 | (G_TYPE_CHECK_CLASS_CAST((klass), FS_TYPE_PLUGIN, FsPluginClass)) | |
46 | #define FS_IS_PLUGIN(obj) \ | |
47 | (G_TYPE_CHECK_INSTANCE_TYPE((obj), FS_TYPE_PLUGIN)) | |
48 | #define FS_IS_PLUGIN_CLASS(klass) \ | |
49 | (G_TYPE_CHECK_CLASS_TYPE((klass), FS_TYPE_PLUGIN)) | |
50 | #define FS_PLUGIN_GET_CLASS(obj) \ | |
51 | (G_TYPE_INSTANCE_GET_CLASS ((obj), FS_TYPE_PLUGIN, FsPluginClass)) | |
52 | ||
53 | /** | |
54 | * FsPlugin: | |
55 | * @parent: the parent object | |
56 | * | |
57 | * This structure represents a plugin, it is opaque. | |
58 | */ | |
59 | ||
60 | typedef struct _FsPlugin FsPlugin; | |
61 | typedef struct _FsPluginClass FsPluginClass; | |
62 | typedef struct _FsPluginPrivate FsPluginPrivate; | |
63 | ||
64 | struct _FsPlugin | |
65 | { | |
66 | GTypeModule parent; | |
67 | ||
68 | /*< private >*/ | |
69 | ||
70 | GType type; | |
71 | ||
72 | gchar *name; /* name of the plugin */ | |
73 | ||
74 | /*< private >*/ | |
75 | ||
76 | FsPluginPrivate *priv; | |
77 | ||
78 | gpointer unused[8]; | |
79 | }; | |
80 | ||
81 | struct _FsPluginClass | |
82 | { | |
83 | GTypeModuleClass parent_class; | |
84 | ||
85 | /*< private >*/ | |
86 | ||
87 | gpointer unused[8]; | |
88 | }; | |
89 | ||
90 | GType fs_plugin_get_type (void); | |
91 | ||
92 | ||
93 | GObject *fs_plugin_create_valist (const gchar *name, | |
94 | const gchar *type_suffix, | |
95 | GError **error, | |
96 | const gchar *first_property_name, | |
97 | va_list var_args); | |
98 | ||
99 | GObject *fs_plugin_create (const gchar *name, | |
100 | const gchar *type_suffix, | |
101 | GError **error, | |
102 | const gchar *first_property_name, ...); | |
103 | ||
104 | gchar **fs_plugin_list_available (const gchar *type_suffix); | |
105 | ||
106 | /** | |
107 | * FS_INIT_PLUGIN: | |
108 | * @type_register_func: A function that register a #GType and returns it | |
109 | * | |
110 | * This macro is used to declare Farstream plugins and must be used once | |
111 | * in any farstream plugin. | |
112 | */ | |
113 | ||
114 | #define FS_INIT_PLUGIN(type_register_func) \ | |
115 | G_MODULE_EXPORT void fs_init_plugin (FsPlugin *plugin) { \ | |
116 | plugin->type = (type_register_func (plugin)); \ | |
117 | } | |
118 | ||
119 | ||
120 | G_END_DECLS | |
121 | #endif | |
122 |
0 | /* | |
1 | * Farstream - Private declarations | |
2 | * | |
3 | * Copyright 2008 Collabora Ltd. | |
4 | * @author: Olivier Crete <olivier.crete@collabora.co.uk> | |
5 | * Copyright 2008 Nokia Corp. | |
6 | * | |
7 | * fs-conference.h - Header file for gstreamer interface to be | |
8 | * implemented by farstream conference elements | |
9 | * | |
10 | * This library is free software; you can redistribute it and/or | |
11 | * modify it under the terms of the GNU Lesser General Public | |
12 | * License as published by the Free Software Foundation; either | |
13 | * version 2.1 of the License, or (at your option) any later version. | |
14 | * | |
15 | * This library is distributed in the hope that it will be useful, | |
16 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
17 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
18 | * Lesser General Public License for more details. | |
19 | * | |
20 | * You should have received a copy of the GNU Lesser General Public | |
21 | * License along with this library; if not, write to the Free Software | |
22 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA | |
23 | */ | |
24 | ||
25 | #ifndef __FS_PRIVATE_H__ | |
26 | #define __FS_PRIVATE_H__ | |
27 | ||
28 | #include <gst/gst.h> | |
29 | ||
30 | G_BEGIN_DECLS | |
31 | ||
32 | void _fs_conference_init_debug (void); | |
33 | ||
34 | GST_DEBUG_CATEGORY_EXTERN (fs_conference_debug); | |
35 | ||
36 | G_END_DECLS | |
37 | ||
38 | #endif /* __FS_PRIVATE_H__ */ | |
39 |
0 | /* | |
1 | * Farstream - Farstream RTP specific types | |
2 | * | |
3 | * Copyright 2011 Collabora Ltd. | |
4 | * @author: Olivier Crete <olivier.crete@collabora.co.uk> | |
5 | * Copyright 2011 Nokia Corp. | |
6 | * | |
7 | * fs-rtp.c - Farstream RTP specific types | |
8 | * | |
9 | * This library is free software; you can redistribute it and/or | |
10 | * modify it under the terms of the GNU Lesser General Public | |
11 | * License as published by the Free Software Foundation; either | |
12 | * version 2.1 of the License, or (at your option) any later version. | |
13 | * | |
14 | * This library is distributed in the hope that it will be useful, | |
15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
17 | * Lesser General Public License for more details. | |
18 | * | |
19 | * You should have received a copy of the GNU Lesser General Public | |
20 | * License along with this library; if not, write to the Free Software | |
21 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA | |
22 | */ | |
23 | ||
24 | ||
25 | #ifdef HAVE_CONFIG_H | |
26 | #include "config.h" | |
27 | #endif | |
28 | ||
29 | #include "fs-rtp.h" | |
30 | ||
31 | #include <string.h> | |
32 | ||
33 | typedef GList FsRtpHeaderExtensionGList; | |
34 | ||
35 | G_DEFINE_BOXED_TYPE (FsRtpHeaderExtension, fs_rtp_header_extension, | |
36 | fs_rtp_header_extension_copy, fs_rtp_header_extension_destroy) | |
37 | G_DEFINE_BOXED_TYPE (FsRtpHeaderExtensionGList, fs_rtp_header_extension_list, | |
38 | fs_rtp_header_extension_list_copy, fs_rtp_header_extension_list_destroy) | |
39 | ||
40 | ||
41 | /** | |
42 | * fs_rtp_header_extension_new: | |
43 | * @id: The identifier of the RTP header extension | |
44 | * @direction: the direction in which this extension can be used | |
45 | * @uri: The URI that defines this extension | |
46 | * | |
47 | * Creates a new #FsRtpHeaderExtension | |
48 | * | |
49 | * Returns: a new #FsRtpHeaderExtension | |
50 | */ | |
51 | ||
52 | FsRtpHeaderExtension * | |
53 | fs_rtp_header_extension_new (guint id, FsStreamDirection direction, | |
54 | const gchar *uri) | |
55 | { | |
56 | FsRtpHeaderExtension *extension; | |
57 | ||
58 | extension = g_slice_new (FsRtpHeaderExtension); | |
59 | ||
60 | extension->id = id; | |
61 | extension->direction = direction; | |
62 | extension->uri = g_strdup (uri); | |
63 | ||
64 | return extension; | |
65 | } | |
66 | ||
67 | /** | |
68 | * fs_rtp_header_extension_copy: | |
69 | * @extension: The RTP header extension definition to copy | |
70 | * | |
71 | * Copies a #FsRtpHeaderExtension | |
72 | * | |
73 | * Returns: a new #FsRtpHeaderExtension | |
74 | */ | |
75 | ||
76 | FsRtpHeaderExtension * | |
77 | fs_rtp_header_extension_copy (FsRtpHeaderExtension *extension) | |
78 | { | |
79 | if (extension) | |
80 | return fs_rtp_header_extension_new (extension->id, extension->direction, | |
81 | extension->uri); | |
82 | else | |
83 | return NULL; | |
84 | } | |
85 | ||
86 | /** | |
87 | * fs_rtp_header_extension_are_equal: | |
88 | * @extension1: The first #FsRtpHeaderExtension | |
89 | * @extension2: The second #FsRtpHeaderExtension | |
90 | * | |
91 | * Compares two #FsRtpHeaderExtension structures | |
92 | * | |
93 | * Returns: %TRUE if they are identical, %FALSE otherwise | |
94 | */ | |
95 | ||
96 | gboolean | |
97 | fs_rtp_header_extension_are_equal (FsRtpHeaderExtension *extension1, | |
98 | FsRtpHeaderExtension *extension2) | |
99 | { | |
100 | if (extension1 == extension2) | |
101 | return TRUE; | |
102 | ||
103 | if (!extension2 || !extension2) | |
104 | return FALSE; | |
105 | ||
106 | if (extension1->id == extension2->id && | |
107 | extension1->direction == extension2->direction && | |
108 | (extension1->uri == extension2->uri || | |
109 | (extension1->uri && extension2->uri && | |
110 | !strcmp (extension1->uri, extension2->uri)))) | |
111 | return TRUE; | |
112 | else | |
113 | return FALSE; | |
114 | } | |
115 | ||
116 | /** | |
117 | * fs_rtp_header_extension_destroy: | |
118 | * @extension: A RTP header extension to free | |
119 | * | |
120 | * Frees the passed #FsRtpHeaderExtension | |
121 | */ | |
122 | ||
123 | void | |
124 | fs_rtp_header_extension_destroy (FsRtpHeaderExtension *extension) | |
125 | { | |
126 | if (extension) | |
127 | { | |
128 | g_free (extension->uri); | |
129 | g_slice_free (FsRtpHeaderExtension, extension); | |
130 | } | |
131 | } | |
132 | ||
133 | /** | |
134 | * fs_rtp_header_extension_list_copy: | |
135 | * @extensions: a #GList of #FsRtpHeaderExtension | |
136 | * | |
137 | * Does a deep copy of a #GList of #FsRtpHeaderExtension | |
138 | * | |
139 | * Returns: (element-type FsRtpHeaderExtension) (transfer full): a new | |
140 | * #GList of #FsRtpHeaderExtension | |
141 | */ | |
142 | ||
143 | GList * | |
144 | fs_rtp_header_extension_list_copy (GList *extensions) | |
145 | { | |
146 | GQueue copy = G_QUEUE_INIT; | |
147 | const GList *lp; | |
148 | ||
149 | for (lp = extensions; lp; lp = g_list_next (lp)) { | |
150 | FsRtpHeaderExtension *ext = lp->data; | |
151 | ||
152 | g_queue_push_tail (©, fs_rtp_header_extension_copy (ext)); | |
153 | } | |
154 | ||
155 | return copy.head; | |
156 | } | |
157 | ||
158 | /** | |
159 | * fs_rtp_header_extension_list_destroy: | |
160 | * @extensions: a #GList of #FsRtpHeaderExtension | |
161 | * | |
162 | * Frees the passed #GList of #FsRtpHeaderExtension | |
163 | */ | |
164 | ||
165 | void | |
166 | fs_rtp_header_extension_list_destroy (GList *extensions) | |
167 | { | |
168 | g_list_foreach (extensions, (GFunc) fs_rtp_header_extension_destroy, NULL); | |
169 | g_list_free (extensions); | |
170 | } | |
171 | ||
172 | #define RTP_HDREXT_PREFIX "rtp-hdrext:" | |
173 | #define RTP_HDREXT_AUDIO_PREFIX "audio:" | |
174 | #define RTP_HDREXT_VIDEO_PREFIX "video:" | |
175 | ||
176 | /** | |
177 | * fs_rtp_header_extension_list_from_keyfile: | |
178 | * @filename: Name of the #GKeyFile to read the RTP Header Extensions from | |
179 | * @media_type: The media type for which to get header extensions | |
180 | * @error: location of a #GError, or NULL if no error occured | |
181 | * | |
182 | * Reads the content of a #GKeyFile of the following format into a | |
183 | * #GList of #FsRtpHeaderExtension structures. | |
184 | * | |
185 | * The groups have a format "rtp-hdrext:audio:XXX" or | |
186 | * "rtp-hdrext:video:XXX" where XXX is a unique string (per media type). | |
187 | * | |
188 | * The valid keys are: | |
189 | * <itemizedlist> | |
190 | * <listitem>id: a int between in the 1-255 and 4096-4351 ranges</listitem> | |
191 | * <listitem>uri: a URI describing the RTP Header Extension</listitem> | |
192 | * <listitem>direction (optional): To only send or receive a RTP Header | |
193 | * Extension, possible values are "send", "receive", "none" or "both". | |
194 | * Defaults to "both"</listitem> | |
195 | * </itemizedlist> | |
196 | * | |
197 | * Example: | |
198 | * |[ | |
199 | * [rtp-hdrext:audio:a] | |
200 | * id=1 | |
201 | * uri=urn:ietf:params:rtp-hdrext:toffset | |
202 | * | |
203 | * [rtp-hdrext:audio:abc] | |
204 | * id=3 | |
205 | * uri=urn:ietf:params:rtp-hdrext:ntp-64 | |
206 | * direction=receive | |
207 | * ]| | |
208 | * | |
209 | * Returns: (element-type FsRtpHeaderExtension) (transfer full): a | |
210 | * #GList of #FsRtpHeaderExtension that must be freed with | |
211 | * fs_rtp_header_extension_list_destroy() | |
212 | */ | |
213 | ||
214 | GList * | |
215 | fs_rtp_header_extension_list_from_keyfile (const gchar *filename, | |
216 | FsMediaType media_type, | |
217 | GError **error) | |
218 | { | |
219 | GKeyFile *keyfile = NULL; | |
220 | GList *extensions = NULL; | |
221 | gchar **groups = NULL; | |
222 | gsize groups_count = 0; | |
223 | int i; | |
224 | ||
225 | g_return_val_if_fail (filename, NULL); | |
226 | g_return_val_if_fail (media_type <= FS_MEDIA_TYPE_LAST, NULL); | |
227 | g_return_val_if_fail (error == NULL || *error == NULL, NULL); | |
228 | ||
229 | keyfile = g_key_file_new (); | |
230 | ||
231 | if (!g_key_file_load_from_file (keyfile, filename, G_KEY_FILE_NONE, error)) | |
232 | goto out; | |
233 | ||
234 | groups = g_key_file_get_groups (keyfile, &groups_count); | |
235 | ||
236 | if (!groups) | |
237 | goto out; | |
238 | ||
239 | for (i=0; i < groups_count && groups[i]; i++) | |
240 | { | |
241 | FsStreamDirection direction = FS_DIRECTION_BOTH; | |
242 | gint id; | |
243 | gchar *uri; | |
244 | GError *gerror = NULL; | |
245 | gchar *str; | |
246 | ||
247 | if (g_ascii_strncasecmp (RTP_HDREXT_PREFIX, groups[i], | |
248 | strlen (RTP_HDREXT_PREFIX))) | |
249 | continue; | |
250 | ||
251 | if (!g_ascii_strncasecmp (RTP_HDREXT_AUDIO_PREFIX, | |
252 | groups[i] + strlen (RTP_HDREXT_PREFIX), | |
253 | strlen (RTP_HDREXT_AUDIO_PREFIX))) | |
254 | { | |
255 | if (media_type != FS_MEDIA_TYPE_AUDIO) | |
256 | continue; | |
257 | } | |
258 | else if (!g_ascii_strncasecmp (RTP_HDREXT_VIDEO_PREFIX, | |
259 | groups[i] + strlen (RTP_HDREXT_PREFIX), | |
260 | strlen (RTP_HDREXT_VIDEO_PREFIX))) | |
261 | { | |
262 | if (media_type != FS_MEDIA_TYPE_VIDEO) | |
263 | continue; | |
264 | } | |
265 | else | |
266 | { | |
267 | continue; | |
268 | } | |
269 | ||
270 | id = g_key_file_get_integer (keyfile, groups[i], "id", &gerror); | |
271 | if (gerror) | |
272 | { | |
273 | g_clear_error (&gerror); | |
274 | continue; | |
275 | } | |
276 | ||
277 | str = g_key_file_get_string (keyfile, groups[i], "direction", &gerror); | |
278 | if (gerror) | |
279 | { | |
280 | GQuark domain = gerror->domain; | |
281 | gint code = gerror->code; | |
282 | ||
283 | g_clear_error (&gerror); | |
284 | if (domain != G_KEY_FILE_ERROR || code != G_KEY_FILE_ERROR_KEY_NOT_FOUND) | |
285 | continue; | |
286 | } | |
287 | else | |
288 | { | |
289 | if (!g_ascii_strcasecmp (str, "none")) | |
290 | direction = FS_DIRECTION_NONE; | |
291 | else if (!g_ascii_strcasecmp (str, "send")) | |
292 | direction = FS_DIRECTION_SEND; | |
293 | else if (!g_ascii_strcasecmp (str, "recv") || | |
294 | !g_ascii_strcasecmp (str, "receive")) | |
295 | direction = FS_DIRECTION_RECV; | |
296 | g_free (str); | |
297 | } | |
298 | ||
299 | uri = g_key_file_get_string (keyfile, groups[i], "uri", &gerror); | |
300 | if (gerror) | |
301 | { | |
302 | g_clear_error (&gerror); | |
303 | continue; | |
304 | } | |
305 | ||
306 | extensions = g_list_append (extensions, fs_rtp_header_extension_new (id, | |
307 | direction, uri)); | |
308 | g_free (uri); | |
309 | } | |
310 | ||
311 | out: | |
312 | ||
313 | g_strfreev (groups); | |
314 | g_key_file_free (keyfile); | |
315 | ||
316 | return extensions; | |
317 | } |
0 | /* | |
1 | * Farstream - Farstream RTP specific types | |
2 | * | |
3 | * Copyright 2011 Collabora Ltd. | |
4 | * @author: Olivier Crete <olivier.crete@collabora.co.uk> | |
5 | * Copyright 2011 Nokia Corp. | |
6 | * | |
7 | * fs-rtp.h - Farstream RTP specific types | |
8 | * | |
9 | * This library is free software; you can redistribute it and/or | |
10 | * modify it under the terms of the GNU Lesser General Public | |
11 | * License as published by the Free Software Foundation; either | |
12 | * version 2.1 of the License, or (at your option) any later version. | |
13 | * | |
14 | * This library is distributed in the hope that it will be useful, | |
15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
17 | * Lesser General Public License for more details. | |
18 | * | |
19 | * You should have received a copy of the GNU Lesser General Public | |
20 | * License along with this library; if not, write to the Free Software | |
21 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA | |
22 | */ | |
23 | ||
24 | #ifndef __FS_RTP_H__ | |
25 | #define __FS_RTP_H__ | |
26 | ||
27 | #include <gst/gst.h> | |
28 | #include <farstream/fs-stream.h> | |
29 | ||
30 | G_BEGIN_DECLS | |
31 | ||
32 | /** | |
33 | * FsRtpHeaderExtension: | |
34 | * @id: The identifier of the RTP header extension | |
35 | * @direction: the direction in which this extension can be used | |
36 | * @uri: The URI that defines this extension | |
37 | * | |
38 | * Defines a RTP header extension with its negotiated identifier, direction | |
39 | * and URI. They should only be created with fs_rtp_header_extension_new(). | |
40 | */ | |
41 | ||
42 | typedef struct _FsRtpHeaderExtension { | |
43 | guint id; | |
44 | FsStreamDirection direction; | |
45 | gchar *uri; | |
46 | } FsRtpHeaderExtension; | |
47 | ||
48 | /** | |
49 | * FS_TYPE_RTP_HEADER_EXTENSION: | |
50 | * | |
51 | * Boxed type for #FsRtpHeaderExtension | |
52 | */ | |
53 | ||
54 | /** | |
55 | * FS_TYPE_RTP_HEADER_EXTENSION_LIST: | |
56 | * | |
57 | * Boxed type for a #GList of #FsRtpHeaderExtension | |
58 | */ | |
59 | ||
60 | #define FS_TYPE_RTP_HEADER_EXTENSION \ | |
61 | fs_rtp_header_extension_get_type () | |
62 | #define FS_TYPE_RTP_HEADER_EXTENSION_LIST \ | |
63 | fs_rtp_header_extension_list_get_type () | |
64 | ||
65 | GType fs_rtp_header_extension_get_type (void); | |
66 | GType fs_rtp_header_extension_list_get_type (void); | |
67 | ||
68 | ||
69 | FsRtpHeaderExtension * | |
70 | fs_rtp_header_extension_new (guint id, FsStreamDirection direction, | |
71 | const gchar *uri); | |
72 | ||
73 | FsRtpHeaderExtension * | |
74 | fs_rtp_header_extension_copy (FsRtpHeaderExtension *extension); | |
75 | void | |
76 | fs_rtp_header_extension_destroy (FsRtpHeaderExtension *extension); | |
77 | ||
78 | gboolean | |
79 | fs_rtp_header_extension_are_equal (FsRtpHeaderExtension *extension1, | |
80 | FsRtpHeaderExtension *extension2); | |
81 | ||
82 | GList * | |
83 | fs_rtp_header_extension_list_copy (GList *extensions); | |
84 | void | |
85 | fs_rtp_header_extension_list_destroy (GList *extensions); | |
86 | ||
87 | GList * | |
88 | fs_rtp_header_extension_list_from_keyfile (const gchar *filename, | |
89 | FsMediaType media_type, | |
90 | GError **error); | |
91 | ||
92 | /** | |
93 | * FS_RTP_HEADER_EXTENSION_FORMAT: | |
94 | * | |
95 | * A format that can be used in printf like format strings to format a | |
96 | * FsRtpHeaderExtension | |
97 | */ | |
98 | ||
99 | /** | |
100 | * FS_RTP_HEADER_EXTENSION_ARGS: | |
101 | * @hdrext: a #FsRtpHeaderExtension | |
102 | * | |
103 | * Formats the codec in args for FS_RTP_HEADER_EXTENSION_ARGS | |
104 | */ | |
105 | ||
106 | #define FS_RTP_HEADER_EXTENSION_FORMAT "%d: (%s) %s" | |
107 | #define FS_RTP_HEADER_EXTENSION_ARGS(hdrext) \ | |
108 | (hdrext)->id, \ | |
109 | (hdrext)->direction == FS_DIRECTION_BOTH ? "both" : \ | |
110 | ((hdrext)->direction == FS_DIRECTION_RECV? "recv" : \ | |
111 | ((hdrext)->direction == FS_DIRECTION_SEND ? "send" : "none")), \ | |
112 | (hdrext)->uri | |
113 | ||
114 | G_END_DECLS | |
115 | ||
116 | #endif /* __FS_RTP_H__ */ |
0 | /* | |
1 | * Farstream - Farstream Session | |
2 | * | |
3 | * Copyright 2007 Collabora Ltd. | |
4 | * @author: Philippe Kalaf <philippe.kalaf@collabora.co.uk> | |
5 | * Copyright 2007 Nokia Corp. | |
6 | * | |
7 | * fs-session.c - A Farstream Session gobject (base implementation) | |
8 | * | |
9 | * This library is free software; you can redistribute it and/or | |
10 | * modify it under the terms of the GNU Lesser General Public | |
11 | * License as published by the Free Software Foundation; either | |
12 | * version 2.1 of the License, or (at your option) any later version. | |
13 | * | |
14 | * This library is distributed in the hope that it will be useful, | |
15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
17 | * Lesser General Public License for more details. | |
18 | * | |
19 | * You should have received a copy of the GNU Lesser General Public | |
20 | * License along with this library; if not, write to the Free Software | |
21 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA | |
22 | */ | |
23 | ||
24 | ||
25 | ||
26 | /** | |
27 | * SECTION:fs-session | |
28 | * @short_description: A session in a conference | |
29 | * | |
30 | * This object is the base implementation of a Farstream Session. It needs to be | |
31 | * derived and implemented by a farstream conference gstreamer element. A | |
32 | * Farstream session is defined in the same way as an RTP session. It can contain | |
33 | * one or more participants but represents only one media stream (i.e. One | |
34 | * session for video and one session for audio in an AV conference). Sessions | |
35 | * contained in the same conference will be synchronised together during | |
36 | * playback. | |
37 | * | |
38 | * | |
39 | * This will communicate asynchronous events to the user through #GstMessage | |
40 | * of type #GST_MESSAGE_ELEMENT sent over the #GstBus. | |
41 | * </para> | |
42 | * <refsect2><title>The "<literal>farstream-send-codec-changed</literal>" | |
43 | * message</title> | |
44 | * |[ | |
45 | * "session" #FsSession The session that emits the message | |
46 | * "codec" #FsCodec The new send codec | |
47 | * "secondary-codecs" #GList A #GList of #FsCodec (to be freed | |
48 | * with fs_codec_list_destroy()) | |
49 | * ]| | |
50 | * <para> | |
51 | * This message is sent on the bus when the value of the | |
52 | * #FsSession:current-send-codec property changes. | |
53 | * </para> | |
54 | * </refsect2> | |
55 | * <refsect2><title>The "<literal>farstream-codecs-changed</literal>" | |
56 | * message</title> | |
57 | * |[ | |
58 | * "session" #FsSession The session that emits the message | |
59 | * ]| | |
60 | * <para> | |
61 | * This message is sent on the bus when the value of the | |
62 | * #FsSession:codecs or #FsSession:codecs-without-config properties change. | |
63 | * If one is using codecs that have configuration data that needs to be | |
64 | * transmitted reliably, one should fetch #FsSession:codecs, otherwise, | |
65 | * #FsSession:codecs-without-config should be enough. | |
66 | * </para> | |
67 | * </refsect2> | |
68 | * <para> | |
69 | */ | |
70 | ||
71 | #ifdef HAVE_CONFIG_H | |
72 | #include "config.h" | |
73 | #endif | |
74 | ||
75 | #include "fs-session.h" | |
76 | ||
77 | #include <gst/gst.h> | |
78 | ||
79 | #include "fs-conference.h" | |
80 | #include "fs-codec.h" | |
81 | #include "fs-marshal.h" | |
82 | #include "fs-enumtypes.h" | |
83 | #include "fs-private.h" | |
84 | ||
85 | #define GST_CAT_DEFAULT fs_conference_debug | |
86 | ||
87 | /* Signals */ | |
88 | enum | |
89 | { | |
90 | ERROR_SIGNAL, | |
91 | LAST_SIGNAL | |
92 | }; | |
93 | ||
94 | /* props */ | |
95 | enum | |
96 | { | |
97 | PROP_0, | |
98 | PROP_MEDIA_TYPE, | |
99 | PROP_ID, | |
100 | PROP_SINK_PAD, | |
101 | PROP_CODEC_PREFERENCES, | |
102 | PROP_CODECS, | |
103 | PROP_CODECS_WITHOUT_CONFIG, | |
104 | PROP_CURRENT_SEND_CODEC, | |
105 | PROP_TYPE_OF_SERVICE | |
106 | }; | |
107 | ||
108 | /* | |
109 | struct _FsSessionPrivate | |
110 | { | |
111 | }; | |
112 | ||
113 | #define FS_SESSION_GET_PRIVATE(o) \ | |
114 | (G_TYPE_INSTANCE_GET_PRIVATE ((o), FS_TYPE_SESSION, FsSessionPrivate)) | |
115 | */ | |
116 | ||
117 | G_DEFINE_ABSTRACT_TYPE(FsSession, fs_session, GST_TYPE_OBJECT); | |
118 | ||
119 | static void fs_session_get_property (GObject *object, | |
120 | guint prop_id, | |
121 | GValue *value, | |
122 | GParamSpec *pspec); | |
123 | static void fs_session_set_property (GObject *object, | |
124 | guint prop_id, | |
125 | const GValue *value, | |
126 | GParamSpec *pspec); | |
127 | ||
128 | static guint signals[LAST_SIGNAL] = { 0 }; | |
129 | ||
130 | static void | |
131 | fs_session_class_init (FsSessionClass *klass) | |
132 | { | |
133 | GObjectClass *gobject_class; | |
134 | ||
135 | gobject_class = (GObjectClass *) klass; | |
136 | ||
137 | gobject_class->set_property = fs_session_set_property; | |
138 | gobject_class->get_property = fs_session_get_property; | |
139 | ||
140 | /** | |
141 | * FsSession:media-type: | |
142 | * | |
143 | * The media-type of the session. This is either Audio, Video or both. | |
144 | * This is a constructor parameter that cannot be changed. | |
145 | * | |
146 | */ | |
147 | g_object_class_install_property (gobject_class, | |
148 | PROP_MEDIA_TYPE, | |
149 | g_param_spec_enum ("media-type", | |
150 | "The media type of the session", | |
151 | "An enum that specifies the media type of the session", | |
152 | FS_TYPE_MEDIA_TYPE, | |
153 | FS_MEDIA_TYPE_AUDIO, | |
154 | G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); | |
155 | ||
156 | /** | |
157 | * FsSession:id: | |
158 | * | |
159 | * The ID of the session, the first number of the pads linked to this session | |
160 | * will be this id | |
161 | * | |
162 | */ | |
163 | g_object_class_install_property (gobject_class, | |
164 | PROP_ID, | |
165 | g_param_spec_uint ("id", | |
166 | "The ID of the session", | |
167 | "This ID is used on pad related to this session", | |
168 | 0, G_MAXUINT, 0, | |
169 | G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); | |
170 | ||
171 | /** | |
172 | * FsSession:sink-pad: | |
173 | * | |
174 | * The Gstreamer sink pad that must be used to send media data on this | |
175 | * session. User must unref this GstPad when done with it. | |
176 | * | |
177 | */ | |
178 | g_object_class_install_property (gobject_class, | |
179 | PROP_SINK_PAD, | |
180 | g_param_spec_object ("sink-pad", | |
181 | "A gstreamer sink pad for this session", | |
182 | "A pad used for sending data on this session", | |
183 | GST_TYPE_PAD, | |
184 | G_PARAM_READABLE | G_PARAM_STATIC_STRINGS)); | |
185 | ||
186 | /** | |
187 | * FsSession:codec-preferences: | |
188 | * | |
189 | * Type: GLib.List<FsCodec> | |
190 | * Transfer: full | |
191 | * | |
192 | * This is the current preferences list for the local codecs. It is | |
193 | * set by the user to specify the codec options and priorities. The user may | |
194 | * change its value with fs_session_set_codec_preferences() at any time | |
195 | * during a session. It is a #GList of #FsCodec. | |
196 | * The user must free this codec list using fs_codec_list_destroy() when done. | |
197 | * | |
198 | * The payload type may be a valid dynamic PT (96-127), %FS_CODEC_ID_DISABLE | |
199 | * or %FS_CODEC_ID_ANY. If the encoding name is "reserve-pt", then the | |
200 | * payload type of the codec will be "reserved" and not be used by any | |
201 | * dynamically assigned payload type. | |
202 | */ | |
203 | g_object_class_install_property (gobject_class, | |
204 | PROP_CODEC_PREFERENCES, | |
205 | g_param_spec_boxed ("codec-preferences", | |
206 | "List of user preferences for the codecs", | |
207 | "A GList of FsCodecs that allows user to set his codec options and" | |
208 | " priorities", | |
209 | FS_TYPE_CODEC_LIST, | |
210 | G_PARAM_READABLE | G_PARAM_STATIC_STRINGS)); | |
211 | ||
212 | /** | |
213 | * FsSession:codecs: | |
214 | * | |
215 | * Type: GLib.List<FsCodec> | |
216 | * Transfer: full | |
217 | * | |
218 | * This is the list of codecs used for this session. It will include the | |
219 | * codecs and payload type used to receive media on this session. It will | |
220 | * also include any configuration parameter that must be transmitted reliably | |
221 | * for the other end to decode the content. | |
222 | * | |
223 | * It may change when the codec preferences are set, when codecs are set | |
224 | * on a #FsStream in this session, when a #FsStream is destroyed or | |
225 | * asynchronously when new config data is discovered. | |
226 | * | |
227 | * If any configuration parameter needs to be discovered, this property | |
228 | * will be %NULL until they have been discovered. One can always get | |
229 | * the codecs from #FsSession:codecs-without-config. | |
230 | * The "farstream-codecs-changed" message will be emitted whenever the value | |
231 | * of this property changes. | |
232 | * | |
233 | * It is a #GList of #FsCodec. User must free this codec list using | |
234 | * fs_codec_list_destroy() when done. | |
235 | * | |
236 | */ | |
237 | g_object_class_install_property (gobject_class, | |
238 | PROP_CODECS, | |
239 | g_param_spec_boxed ("codecs", | |
240 | "List of codecs", | |
241 | "A GList of FsCodecs indicating the codecs for this session", | |
242 | FS_TYPE_CODEC_LIST, | |
243 | G_PARAM_READABLE | G_PARAM_STATIC_STRINGS)); | |
244 | ||
245 | /** | |
246 | * FsSession:codecs-without-config: | |
247 | * | |
248 | * Type: GLib.List<FsCodec> | |
249 | * Transfer: full | |
250 | * | |
251 | * This is the same list of codecs as #FsSession:codecs without | |
252 | * the configuration information that describes the data sent. It is suitable | |
253 | * for configurations where a list of codecs is shared by many senders. | |
254 | * If one is using codecs such as Theora, Vorbis or H.264 that require | |
255 | * such information to be transmitted, the configuration data should be | |
256 | * included in the stream and retransmitted regularly. | |
257 | * | |
258 | * It may change when the codec preferences are set, when codecs are set | |
259 | * on a #FsStream in this session, when a #FsStream is destroyed or | |
260 | * asynchronously when new config data is discovered. | |
261 | * | |
262 | * The "farstream-codecs-changed" message will be emitted whenever the value | |
263 | * of this property changes. | |
264 | * | |
265 | * It is a #GList of #FsCodec. User must free this codec list using | |
266 | * fs_codec_list_destroy() when done. | |
267 | * | |
268 | */ | |
269 | g_object_class_install_property (gobject_class, | |
270 | PROP_CODECS_WITHOUT_CONFIG, | |
271 | g_param_spec_boxed ("codecs-without-config", | |
272 | "List of codecs without the configuration data", | |
273 | "A GList of FsCodecs indicating the codecs for this session without " | |
274 | "any configuration data", | |
275 | FS_TYPE_CODEC_LIST, | |
276 | G_PARAM_READABLE | G_PARAM_STATIC_STRINGS)); | |
277 | ||
278 | /** | |
279 | * FsSession:current-send-codec: | |
280 | * | |
281 | * Indicates the currently active send codec. A user can change the active | |
282 | * send codec by calling fs_session_set_send_codec(). The send codec could | |
283 | * also be automatically changed by Farstream. This property is an | |
284 | * #FsCodec. User must free the codec using fs_codec_destroy() when done. | |
285 | * The "farstream-send-codec-changed" message is emitted on the bus when | |
286 | * the value of this property changes. | |
287 | */ | |
288 | g_object_class_install_property (gobject_class, | |
289 | PROP_CURRENT_SEND_CODEC, | |
290 | g_param_spec_boxed ("current-send-codec", | |
291 | "Current active send codec", | |
292 | "An FsCodec indicating the currently active send codec", | |
293 | FS_TYPE_CODEC, | |
294 | G_PARAM_READABLE | G_PARAM_STATIC_STRINGS)); | |
295 | ||
296 | /** | |
297 | * FsSession:tos | |
298 | * | |
299 | * Sets the IP ToS field (and if possible the IPv6 TCLASS field | |
300 | */ | |
301 | g_object_class_install_property (gobject_class, | |
302 | PROP_TYPE_OF_SERVICE, | |
303 | g_param_spec_uint ("tos", | |
304 | "IP Type of Service", | |
305 | "The IP Type of Service to set on sent packets", | |
306 | 0, 255, 0, | |
307 | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); | |
308 | ||
309 | ||
310 | /** | |
311 | * FsSession::error: | |
312 | * @self: #FsSession that emitted the signal | |
313 | * @object: The #Gobject that emitted the signal | |
314 | * @error_no: The number of the error | |
315 | * @error_msg: Error message | |
316 | * | |
317 | * This signal is emitted in any error condition, it can be emitted on any | |
318 | * thread. Applications should listen to the GstBus for errors. | |
319 | * | |
320 | */ | |
321 | signals[ERROR_SIGNAL] = g_signal_new ("error", | |
322 | G_TYPE_FROM_CLASS (klass), | |
323 | G_SIGNAL_RUN_LAST, | |
324 | 0, | |
325 | NULL, | |
326 | NULL, | |
327 | _fs_marshal_VOID__OBJECT_ENUM_STRING, | |
328 | G_TYPE_NONE, 3, G_TYPE_OBJECT, FS_TYPE_ERROR, G_TYPE_STRING); | |
329 | } | |
330 | ||
331 | static void | |
332 | fs_session_init (FsSession *self) | |
333 | { | |
334 | /* member init */ | |
335 | // self->priv = FS_SESSION_GET_PRIVATE (self); | |
336 | } | |
337 | ||
338 | static void | |
339 | fs_session_get_property (GObject *object, | |
340 | guint prop_id, | |
341 | GValue *value, | |
342 | GParamSpec *pspec) | |
343 | { | |
344 | GST_WARNING ("Subclass %s of FsSession does not override the %s property" | |
345 | " getter", | |
346 | G_OBJECT_TYPE_NAME(object), | |
347 | g_param_spec_get_name (pspec)); | |
348 | } | |
349 | ||
350 | static void | |
351 | fs_session_set_property (GObject *object, | |
352 | guint prop_id, | |
353 | const GValue *value, | |
354 | GParamSpec *pspec) | |
355 | { | |
356 | GST_WARNING ("Subclass %s of FsSession does not override the %s property" | |
357 | " setter", | |
358 | G_OBJECT_TYPE_NAME(object), | |
359 | g_param_spec_get_name (pspec)); | |
360 | } | |
361 | ||
362 | static void | |
363 | fs_session_error_forward (GObject *signal_src, | |
364 | FsError error_no, gchar *error_msg, | |
365 | FsSession *session) | |
366 | { | |
367 | /* We just need to forward the error signal including a ref to the stream | |
368 | * object (signal_src) */ | |
369 | g_signal_emit (session, signals[ERROR_SIGNAL], 0, signal_src, error_no, | |
370 | error_msg); | |
371 | } | |
372 | ||
373 | /** | |
374 | * fs_session_new_stream: | |
375 | * @session: a #FsSession | |
376 | * @participant: #FsParticipant of a participant for the new stream | |
377 | * @direction: #FsStreamDirection describing the direction of the new stream that will | |
378 | * be created for this participant | |
379 | * @error: location of a #GError, or %NULL if no error occured | |
380 | * | |
381 | * This function creates a stream for the given participant into the active session. | |
382 | * | |
383 | * Returns: (transfer full): the new #FsStream that has been created. | |
384 | * User must unref the #FsStream when the stream is ended. If an error occured, | |
385 | * returns NULL. | |
386 | */ | |
387 | FsStream * | |
388 | fs_session_new_stream (FsSession *session, | |
389 | FsParticipant *participant, | |
390 | FsStreamDirection direction, | |
391 | GError **error) | |
392 | { | |
393 | FsSessionClass *klass; | |
394 | FsStream *new_stream = NULL; | |
395 | ||
396 | g_return_val_if_fail (session, NULL); | |
397 | g_return_val_if_fail (FS_IS_SESSION (session), NULL); | |
398 | klass = FS_SESSION_GET_CLASS (session); | |
399 | g_return_val_if_fail (klass->new_stream, NULL); | |
400 | ||
401 | new_stream = klass->new_stream (session, participant, direction, error); | |
402 | ||
403 | if (!new_stream) | |
404 | return NULL; | |
405 | ||
406 | /* Let's catch all stream errors and forward them */ | |
407 | g_signal_connect_object (new_stream, "error", | |
408 | G_CALLBACK (fs_session_error_forward), session, 0); | |
409 | ||
410 | return new_stream; | |
411 | } | |
412 | ||
413 | /** | |
414 | * fs_session_start_telephony_event: | |
415 | * @session: a #FsSession | |
416 | * @event: A #FsStreamDTMFEvent or another number defined at | |
417 | * http://www.iana.org/assignments/audio-telephone-event-registry | |
418 | * @volume: The volume in dBm0 without the negative sign. Should be between | |
419 | * 0 and 36. Higher values mean lower volume | |
420 | * @method: The method used to send the event | |
421 | * | |
422 | * This function will start sending a telephony event (such as a DTMF | |
423 | * tone) on the #FsSession. You have to call the function | |
424 | * fs_session_stop_telephony_event() to stop it. | |
425 | * This function will use any available method, if you want to use a specific | |
426 | * method only, use fs_session_start_telephony_event_full() | |
427 | * | |
428 | * Returns: %TRUE if sucessful, it can return %FALSE if the #FsStream | |
429 | * does not support this telephony event. | |
430 | */ | |
431 | gboolean | |
432 | fs_session_start_telephony_event (FsSession *session, guint8 event, | |
433 | guint8 volume, FsDTMFMethod method) | |
434 | { | |
435 | FsSessionClass *klass; | |
436 | ||
437 | g_return_val_if_fail (session, FALSE); | |
438 | g_return_val_if_fail (FS_IS_SESSION (session), FALSE); | |
439 | klass = FS_SESSION_GET_CLASS (session); | |
440 | ||
441 | if (klass->start_telephony_event) { | |
442 | return klass->start_telephony_event (session, event, volume, method); | |
443 | } else { | |
444 | GST_WARNING ("start_telephony_event not defined in class"); | |
445 | } | |
446 | return FALSE; | |
447 | } | |
448 | ||
449 | /** | |
450 | * fs_session_stop_telephony_event: | |
451 | * @session: an #FsSession | |
452 | * @method: The method used to send the event | |
453 | * | |
454 | * This function will stop sending a telephony event started by | |
455 | * fs_session_start_telephony_event(). If the event was being sent | |
456 | * for less than 50ms, it will be sent for 50ms minimum. If the | |
457 | * duration was a positive and the event is not over, it will cut it | |
458 | * short. | |
459 | * | |
460 | * Returns: %TRUE if sucessful, it can return %FALSE if the #FsSession | |
461 | * does not support telephony events or if no telephony event is being sent | |
462 | */ | |
463 | gboolean | |
464 | fs_session_stop_telephony_event (FsSession *session, FsDTMFMethod method) | |
465 | { | |
466 | FsSessionClass *klass; | |
467 | ||
468 | g_return_val_if_fail (session, FALSE); | |
469 | g_return_val_if_fail (FS_IS_SESSION (session), FALSE); | |
470 | klass = FS_SESSION_GET_CLASS (session); | |
471 | ||
472 | if (klass->stop_telephony_event) { | |
473 | return klass->stop_telephony_event (session, method); | |
474 | } else { | |
475 | GST_WARNING ("stop_telephony_event not defined in class"); | |
476 | } | |
477 | return FALSE; | |
478 | } | |
479 | ||
480 | /** | |
481 | * fs_session_set_send_codec: | |
482 | * @session: a #FsSession | |
483 | * @send_codec: a #FsCodec representing the codec to send | |
484 | * @error: location of a #GError, or %NULL if no error occured | |
485 | * | |
486 | * This function will set the currently being sent codec for all streams in this | |
487 | * session. The given #FsCodec must be taken directly from the #codecs | |
488 | * property of the session. If the given codec is not in the codecs | |
489 | * list, @error will be set and %FALSE will be returned. The @send_codec will be | |
490 | * copied so it must be free'd using fs_codec_destroy() when done. | |
491 | * | |
492 | * Returns: %FALSE if the send codec couldn't be set. | |
493 | */ | |
494 | gboolean | |
495 | fs_session_set_send_codec (FsSession *session, FsCodec *send_codec, | |
496 | GError **error) | |
497 | { | |
498 | FsSessionClass *klass; | |
499 | ||
500 | g_return_val_if_fail (session, FALSE); | |
501 | g_return_val_if_fail (FS_IS_SESSION (session), FALSE); | |
502 | klass = FS_SESSION_GET_CLASS (session); | |
503 | ||
504 | if (klass->set_send_codec) { | |
505 | return klass->set_send_codec (session, send_codec, error); | |
506 | } else { | |
507 | GST_WARNING ("set_send_codec not defined in class"); | |
508 | g_set_error (error, FS_ERROR, FS_ERROR_NOT_IMPLEMENTED, | |
509 | "set_send_codec not defined in class"); | |
510 | } | |
511 | return FALSE; | |
512 | } | |
513 | ||
514 | /** | |
515 | * fs_session_set_codec_preferences: | |
516 | * @session: a #FsSession | |
517 | * @codec_preferences: (element-type FsCodec): a #GList of #FsCodec with the | |
518 | * desired configuration | |
519 | * @error: location of a #GError, or %NULL if no error occured | |
520 | * | |
521 | * Set the list of desired codec preferences. The user may | |
522 | * change this value during an ongoing session. Note that doing this can cause | |
523 | * the codecs to change. Therefore this requires the user to fetch | |
524 | * the new codecs and renegotiate them with the peers. It is a #GList | |
525 | * of #FsCodec. The changes are immediately effective. | |
526 | * The function does not take ownership of the list. | |
527 | * | |
528 | * The payload type may be a valid dynamic PT (96-127), %FS_CODEC_ID_DISABLE | |
529 | * or %FS_CODEC_ID_ANY. If the encoding name is "reserve-pt", then the | |
530 | * payload type of the codec will be "reserved" and not be used by any | |
531 | * dynamically assigned payload type. | |
532 | * | |
533 | * If the list of specifications would invalidate all codecs, an error will | |
534 | * be returned. | |
535 | * | |
536 | * Returns: %TRUE on success, %FALSE on error. | |
537 | */ | |
538 | gboolean | |
539 | fs_session_set_codec_preferences (FsSession *session, | |
540 | GList *codec_preferences, | |
541 | GError **error) | |
542 | { | |
543 | FsSessionClass *klass; | |
544 | ||
545 | g_return_val_if_fail (session, FALSE); | |
546 | g_return_val_if_fail (FS_IS_SESSION (session), FALSE); | |
547 | klass = FS_SESSION_GET_CLASS (session); | |
548 | ||
549 | if (klass->set_codec_preferences) { | |
550 | return klass->set_codec_preferences (session, codec_preferences, error); | |
551 | } else { | |
552 | GST_WARNING ("set_send_preferences not defined in class"); | |
553 | g_set_error (error, FS_ERROR, FS_ERROR_NOT_IMPLEMENTED, | |
554 | "set_codec_preferences not defined in class"); | |
555 | } | |
556 | return FALSE; | |
557 | } | |
558 | ||
559 | /** | |
560 | * fs_session_emit_error: | |
561 | * @session: #FsSession on which to emit the error signal | |
562 | * @error_no: The number of the error of type #FsError | |
563 | * @error_msg: Error message | |
564 | * | |
565 | * This function emit the "error" signal on a #FsSession, it should only be | |
566 | * called by subclasses. | |
567 | */ | |
568 | void | |
569 | fs_session_emit_error (FsSession *session, | |
570 | gint error_no, | |
571 | const gchar *error_msg) | |
572 | { | |
573 | g_signal_emit (session, signals[ERROR_SIGNAL], 0, session, error_no, | |
574 | error_msg); | |
575 | } | |
576 | ||
577 | /** | |
578 | * fs_session_list_transmitters: | |
579 | * @session: A #FsSession | |
580 | * | |
581 | * Get the list of all available transmitters for this session. | |
582 | * | |
583 | * Returns: (transfer full): a newly-allocagted %NULL terminated array of | |
584 | * named of transmitters or %NULL if no transmitter is needed for this type of | |
585 | * session. It should be freed with g_strfreev(). | |
586 | */ | |
587 | ||
588 | gchar ** | |
589 | fs_session_list_transmitters (FsSession *session) | |
590 | { | |
591 | FsSessionClass *klass; | |
592 | ||
593 | g_return_val_if_fail (session, NULL); | |
594 | g_return_val_if_fail (FS_IS_SESSION (session), NULL); | |
595 | klass = FS_SESSION_GET_CLASS (session); | |
596 | ||
597 | if (klass->list_transmitters) { | |
598 | return klass->list_transmitters (session); | |
599 | } else { | |
600 | return NULL; | |
601 | } | |
602 | } | |
603 | ||
604 | ||
605 | /** | |
606 | * fs_session_get_stream_transmitter_type: | |
607 | * @session: A #FsSession | |
608 | * @transmitter: The name of the transmitter | |
609 | * | |
610 | * Returns the GType of the stream transmitter, bindings can use it | |
611 | * to validate/convert the parameters passed to fs_session_new_stream(). | |
612 | * | |
613 | * Returns: The #GType of the stream transmitter | |
614 | */ | |
615 | GType | |
616 | fs_session_get_stream_transmitter_type (FsSession *session, | |
617 | const gchar *transmitter) | |
618 | { | |
619 | FsSessionClass *klass; | |
620 | ||
621 | g_return_val_if_fail (session, 0); | |
622 | g_return_val_if_fail (FS_IS_SESSION (session), 0); | |
623 | klass = FS_SESSION_GET_CLASS (session); | |
624 | ||
625 | if (klass->get_stream_transmitter_type) | |
626 | return klass->get_stream_transmitter_type (session, transmitter); | |
627 | ||
628 | return 0; | |
629 | } | |
630 | ||
631 | /** | |
632 | * fs_session_codecs_need_resend: | |
633 | * @session: a #FsSession | |
634 | * @old_codecs: Codecs previously retrieved from the #FsSession:codecs property | |
635 | * @new_codecs: Codecs recently retrieved from the #FsSession:codecs property | |
636 | * | |
637 | * Some codec updates need to be reliably transmitted to the other side | |
638 | * because they contain important parameters required to decode the media. | |
639 | * Other codec updates, caused by user action, don't. | |
640 | * | |
641 | * Returns: (element-type FsCodec) (transfer full): A new #GList of | |
642 | * #FsCodec that need to be resent or %NULL if there are none. This | |
643 | * list must be freed with fs_codec_list_destroy(). | |
644 | */ | |
645 | GList * | |
646 | fs_session_codecs_need_resend (FsSession *session, | |
647 | GList *old_codecs, GList *new_codecs) | |
648 | { | |
649 | FsSessionClass *klass; | |
650 | ||
651 | g_return_val_if_fail (session, 0); | |
652 | g_return_val_if_fail (FS_IS_SESSION (session), 0); | |
653 | klass = FS_SESSION_GET_CLASS (session); | |
654 | ||
655 | if (klass->codecs_need_resend) | |
656 | return klass->codecs_need_resend (session, old_codecs, new_codecs); | |
657 | ||
658 | return NULL; | |
659 | } | |
660 | ||
661 | /** | |
662 | * fs_session_destroy: | |
663 | * @session: a #FsSession | |
664 | * | |
665 | * This will cause the session to remove all links to other objects and to | |
666 | * remove itself from the #FsConference, it will also destroy all #FsStream | |
667 | * inside this #FsSession Once a #FsSession has been destroyed, it | |
668 | * can not be used anymore. | |
669 | * | |
670 | * It is strongly recommended to call this function from the main thread because | |
671 | * releasing the application's reference to a session. | |
672 | */ | |
673 | ||
674 | void | |
675 | fs_session_destroy (FsSession *session) | |
676 | { | |
677 | g_return_if_fail (session); | |
678 | g_return_if_fail (FS_IS_SESSION (session)); | |
679 | ||
680 | g_object_run_dispose (G_OBJECT (session)); | |
681 | } |
0 | /* | |
1 | * Farstream - Farstream Session | |
2 | * | |
3 | * Copyright 2007 Collabora Ltd. | |
4 | * @author: Philippe Kalaf <philippe.kalaf@collabora.co.uk> | |
5 | * Copyright 2007 Nokia Corp. | |
6 | * | |
7 | * fs-session.h - A Farstream Session gobject (base implementation) | |
8 | * | |
9 | * This library is free software; you can redistribute it and/or | |
10 | * modify it under the terms of the GNU Lesser General Public | |
11 | * License as published by the Free Software Foundation; either | |
12 | * version 2.1 of the License, or (at your option) any later version. | |
13 | * | |
14 | * This library is distributed in the hope that it will be useful, | |
15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
17 | * Lesser General Public License for more details. | |
18 | * | |
19 | * You should have received a copy of the GNU Lesser General Public | |
20 | * License along with this library; if not, write to the Free Software | |
21 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA | |
22 | */ | |
23 | ||
24 | #ifndef __FS_SESSION_H__ | |
25 | #define __FS_SESSION_H__ | |
26 | ||
27 | #include <glib.h> | |
28 | #include <glib-object.h> | |
29 | ||
30 | #include <farstream/fs-stream.h> | |
31 | #include <farstream/fs-participant.h> | |
32 | #include <farstream/fs-codec.h> | |
33 | ||
34 | G_BEGIN_DECLS | |
35 | ||
36 | /* TYPE MACROS */ | |
37 | #define FS_TYPE_SESSION \ | |
38 | (fs_session_get_type ()) | |
39 | #define FS_SESSION(obj) \ | |
40 | (G_TYPE_CHECK_INSTANCE_CAST((obj), FS_TYPE_SESSION, FsSession)) | |
41 | #define FS_SESSION_CLASS(klass) \ | |
42 | (G_TYPE_CHECK_CLASS_CAST((klass), FS_TYPE_SESSION, FsSessionClass)) | |
43 | #define FS_IS_SESSION(obj) \ | |
44 | (G_TYPE_CHECK_INSTANCE_TYPE((obj), FS_TYPE_SESSION)) | |
45 | #define FS_IS_SESSION_CLASS(klass) \ | |
46 | (G_TYPE_CHECK_CLASS_TYPE((klass), FS_TYPE_SESSION)) | |
47 | #define FS_SESSION_GET_CLASS(obj) \ | |
48 | (G_TYPE_INSTANCE_GET_CLASS ((obj), FS_TYPE_SESSION, FsSessionClass)) | |
49 | #define FS_SESSION_CAST(obj) ((FsSession *) (obj)) | |
50 | ||
51 | typedef struct _FsSession FsSession; | |
52 | typedef struct _FsSessionClass FsSessionClass; | |
53 | typedef struct _FsSessionPrivate FsSessionPrivate; | |
54 | ||
55 | /** | |
56 | * FsDTMFEvent: | |
57 | * | |
58 | * An enum that represents the different DTMF event that can be sent to a | |
59 | * #FsSession. The values corresponds those those defined in RFC 4733 | |
60 | * The rest of the possibles values are in the IANA registry at: | |
61 | * http://www.iana.org/assignments/audio-telephone-event-registry | |
62 | * | |
63 | */ | |
64 | typedef enum _FsDTMFEvent | |
65 | { | |
66 | /*< protected >*/ | |
67 | FS_DTMF_EVENT_0 = 0, | |
68 | FS_DTMF_EVENT_1 = 1, | |
69 | FS_DTMF_EVENT_2 = 2, | |
70 | FS_DTMF_EVENT_3 = 3, | |
71 | FS_DTMF_EVENT_4 = 4, | |
72 | FS_DTMF_EVENT_5 = 5, | |
73 | FS_DTMF_EVENT_6 = 6, | |
74 | FS_DTMF_EVENT_7 = 7, | |
75 | FS_DTMF_EVENT_8 = 8, | |
76 | FS_DTMF_EVENT_9 = 9, | |
77 | FS_DTMF_EVENT_STAR = 10, | |
78 | FS_DTMF_EVENT_POUND = 11, | |
79 | FS_DTMF_EVENT_A = 12, | |
80 | FS_DTMF_EVENT_B = 13, | |
81 | FS_DTMF_EVENT_C = 14, | |
82 | FS_DTMF_EVENT_D = 15 | |
83 | } FsDTMFEvent; | |
84 | ||
85 | /** | |
86 | * FsDTMFMethod: | |
87 | * @FS_DTMF_METHOD_AUTO: Send in any possible way | |
88 | * @FS_DTMF_METHOD_RTP_RFC4733: Send as a special payload type defined by RFC 4733 | |
89 | * (which obsoletes RFC 2833) | |
90 | * @FS_DTMF_METHOD_SOUND: Send as tones as in-band audio sound | |
91 | * | |
92 | * An enum that represents the different ways a DTMF event can be sent | |
93 | * | |
94 | */ | |
95 | typedef enum _FsDTMFMethod | |
96 | { | |
97 | FS_DTMF_METHOD_AUTO = 0, | |
98 | FS_DTMF_METHOD_RTP_RFC4733, | |
99 | FS_DTMF_METHOD_SOUND | |
100 | } FsDTMFMethod; | |
101 | ||
102 | /** | |
103 | * FsSessionClass: | |
104 | * @parent_class: Our parent | |
105 | * @new_stream: Create a new #FsStream | |
106 | * @start_telephony_event: Starts a telephony event | |
107 | * @stop_telephony_event: Stops a telephony event | |
108 | * @set_send_codec: Forces sending with a specific codec | |
109 | * @set_codec_preferences: Specifies the codec preferences | |
110 | * @list_transmitters: Returns a list of the available transmitters | |
111 | * @get_stream_transmitter_type: Returns the GType of the stream transmitter | |
112 | * @codecs_need_resend: Returns the list of codecs that need resending | |
113 | * | |
114 | * You must override at least new_stream in a subclass. | |
115 | */ | |
116 | ||
117 | ||
118 | struct _FsSessionClass | |
119 | { | |
120 | GstObjectClass parent_class; | |
121 | ||
122 | /*virtual functions */ | |
123 | FsStream *(* new_stream) (FsSession *session, | |
124 | FsParticipant *participant, | |
125 | FsStreamDirection direction, | |
126 | GError **error); | |
127 | ||
128 | gboolean (* start_telephony_event) (FsSession *session, guint8 event, | |
129 | guint8 volume, FsDTMFMethod method); | |
130 | gboolean (* stop_telephony_event) (FsSession *session, FsDTMFMethod method); | |
131 | ||
132 | gboolean (* set_send_codec) (FsSession *session, FsCodec *send_codec, | |
133 | GError **error); | |
134 | gboolean (* set_codec_preferences) (FsSession *session, | |
135 | GList *codec_preferences, | |
136 | GError **error); | |
137 | ||
138 | gchar** (* list_transmitters) (FsSession *session); | |
139 | ||
140 | GType (* get_stream_transmitter_type) (FsSession *session, | |
141 | const gchar *transmitter); | |
142 | ||
143 | GList* (* codecs_need_resend) (FsSession *session, GList *old_codecs, | |
144 | GList *new_codecs); | |
145 | ||
146 | /*< private >*/ | |
147 | gpointer _padding[8]; | |
148 | }; | |
149 | ||
150 | /** | |
151 | * FsSession: | |
152 | * | |
153 | * All members are private, access them using methods and properties | |
154 | */ | |
155 | struct _FsSession | |
156 | { | |
157 | GstObject parent; | |
158 | /*< private >*/ | |
159 | ||
160 | FsSessionPrivate *priv; | |
161 | ||
162 | ||
163 | gpointer _padding[8]; | |
164 | }; | |
165 | ||
166 | GType fs_session_get_type (void); | |
167 | ||
168 | FsStream *fs_session_new_stream (FsSession *session, | |
169 | FsParticipant *participant, | |
170 | FsStreamDirection direction, | |
171 | GError **error); | |
172 | ||
173 | gboolean fs_session_start_telephony_event (FsSession *session, guint8 event, | |
174 | guint8 volume, FsDTMFMethod method); | |
175 | ||
176 | gboolean fs_session_stop_telephony_event (FsSession *session, | |
177 | FsDTMFMethod method); | |
178 | ||
179 | gboolean fs_session_set_send_codec (FsSession *session, FsCodec *send_codec, | |
180 | GError **error); | |
181 | ||
182 | gboolean fs_session_set_codec_preferences (FsSession *session, | |
183 | GList *codec_preferences, | |
184 | GError **error); | |
185 | ||
186 | gchar **fs_session_list_transmitters (FsSession *session); | |
187 | ||
188 | void fs_session_emit_error (FsSession *session, | |
189 | gint error_no, | |
190 | const gchar *error_msg); | |
191 | ||
192 | GType fs_session_get_stream_transmitter_type (FsSession *session, | |
193 | const gchar *transmitter); | |
194 | ||
195 | GList* fs_session_codecs_need_resend (FsSession *session, | |
196 | GList *old_codecs, GList *new_codecs); | |
197 | ||
198 | void fs_session_destroy (FsSession *session); | |
199 | ||
200 | ||
201 | G_END_DECLS | |
202 | ||
203 | #endif /* __FS_SESSION_H__ */ |
0 | /* | |
1 | * Farstream - Farstream Stream Transmitter | |
2 | * | |
3 | * Copyright 2007 Collabora Ltd. | |
4 | * @author: Olivier Crete <olivier.crete@collabora.co.uk> | |
5 | * Copyright 2007 Nokia Corp. | |
6 | * | |
7 | * fs-stream-transmitter.c - A Farstream Stream Transmitter gobject | |
8 | * | |
9 | * This library is free software; you can redistribute it and/or | |
10 | * modify it under the terms of the GNU Lesser General Public | |
11 | * License as published by the Free Software Foundation; either | |
12 | * version 2.1 of the License, or (at your option) any later version. | |
13 | * | |
14 | * This library is distributed in the hope that it will be useful, | |
15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
17 | * Lesser General Public License for more details. | |
18 | * | |
19 | * You should have received a copy of the GNU Lesser General Public | |
20 | * License along with this library; if not, write to the Free Software | |
21 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA | |
22 | */ | |
23 | ||
24 | /** | |
25 | * SECTION:fs-stream-transmitter | |
26 | * @short_description: A stream transmitter object used to convey per-stream | |
27 | * information to a transmitter. | |
28 | * | |
29 | * This object is the base implementation of a Farstream Stream Transmitter. | |
30 | * It needs to be derived and implement by a Farstream transmitter. | |
31 | * A Farstream Stream transmitter is used to convery per-stream information | |
32 | * to a transmitter, this is mostly local and remote candidates | |
33 | * | |
34 | */ | |
35 | ||
36 | #ifdef HAVE_CONFIG_H | |
37 | #include "config.h" | |
38 | #endif | |
39 | ||
40 | #include "fs-stream-transmitter.h" | |
41 | ||
42 | #include <gst/gst.h> | |
43 | ||
44 | #include "fs-marshal.h" | |
45 | #include "fs-conference.h" | |
46 | #include "fs-private.h" | |
47 | ||
48 | #define GST_CAT_DEFAULT fs_conference_debug | |
49 | ||
50 | /* Signals */ | |
51 | enum | |
52 | { | |
53 | ERROR_SIGNAL, | |
54 | NEW_LOCAL_CANDIDATE, | |
55 | NEW_ACTIVE_CANDIDATE_PAIR, | |
56 | LOCAL_CANDIDATES_PREPARED, | |
57 | KNOWN_SOURCE_PACKET_RECEIVED, | |
58 | STATE_CHANGED, | |
59 | LAST_SIGNAL | |
60 | }; | |
61 | ||
62 | /* props */ | |
63 | enum | |
64 | { | |
65 | PROP_0, | |
66 | PROP_SENDING, | |
67 | PROP_PREFERRED_LOCAL_CANDIDATES, | |
68 | PROP_ASSOCIATE_ON_SOURCE | |
69 | }; | |
70 | ||
71 | struct _FsStreamTransmitterPrivate | |
72 | { | |
73 | gboolean disposed; | |
74 | }; | |
75 | ||
76 | G_DEFINE_ABSTRACT_TYPE(FsStreamTransmitter, fs_stream_transmitter, | |
77 | GST_TYPE_OBJECT); | |
78 | ||
79 | ||
80 | #define FS_STREAM_TRANSMITTER_GET_PRIVATE(o) \ | |
81 | (G_TYPE_INSTANCE_GET_PRIVATE ((o), FS_TYPE_STREAM_TRANSMITTER, \ | |
82 | FsStreamTransmitterPrivate)) | |
83 | ||
84 | static void fs_stream_transmitter_get_property (GObject *object, | |
85 | guint prop_id, | |
86 | GValue *value, | |
87 | GParamSpec *pspec); | |
88 | static void fs_stream_transmitter_set_property (GObject *object, | |
89 | guint prop_id, | |
90 | const GValue *value, | |
91 | GParamSpec *pspec); | |
92 | ||
93 | static guint signals[LAST_SIGNAL] = { 0 }; | |
94 | ||
95 | static void | |
96 | fs_stream_transmitter_class_init (FsStreamTransmitterClass *klass) | |
97 | { | |
98 | GObjectClass *gobject_class; | |
99 | ||
100 | gobject_class = (GObjectClass *) klass; | |
101 | ||
102 | gobject_class->set_property = fs_stream_transmitter_set_property; | |
103 | gobject_class->get_property = fs_stream_transmitter_get_property; | |
104 | ||
105 | ||
106 | /** | |
107 | * FsStreamTransmitter:sending: | |
108 | * | |
109 | * A network source #GstElement to be used by the #FsSession | |
110 | * | |
111 | */ | |
112 | g_object_class_install_property (gobject_class, | |
113 | PROP_SENDING, | |
114 | g_param_spec_boolean ("sending", | |
115 | "Whether to send from this transmitter", | |
116 | "If set to FALSE, the transmitter will stop sending to this person", | |
117 | TRUE, | |
118 | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); | |
119 | ||
120 | /** | |
121 | * FsStreamTransmitter:preferred-local-candidate: | |
122 | * | |
123 | * The list of preferred local candidates for this stream | |
124 | * It is a #GList of #FsCandidates | |
125 | * | |
126 | */ | |
127 | g_object_class_install_property (gobject_class, | |
128 | PROP_PREFERRED_LOCAL_CANDIDATES, | |
129 | g_param_spec_boxed ("preferred-local-candidates", | |
130 | "The preferred candidates", | |
131 | "A GList of FsCandidates", | |
132 | FS_TYPE_CANDIDATE_LIST, | |
133 | G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); | |
134 | ||
135 | /** | |
136 | * FsStreamTransmitter:associate-on-source | |
137 | * | |
138 | * This tells the stream transmitter to associate incoming data with this | |
139 | * based on the source without looking at the content if possible. | |
140 | * | |
141 | */ | |
142 | ||
143 | g_object_class_install_property (gobject_class, | |
144 | PROP_ASSOCIATE_ON_SOURCE, | |
145 | g_param_spec_boolean ("associate-on-source", | |
146 | "Associate incoming data based on the source address", | |
147 | "Whether to associate incoming data stream based on the source address", | |
148 | TRUE, | |
149 | G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); | |
150 | ||
151 | /** | |
152 | * FsStreamTransmitter::error: | |
153 | * @self: #FsStreamTransmitter that emitted the signal | |
154 | * @errorno: The number of the error | |
155 | * @error_msg: Error message (for the programmer) | |
156 | * | |
157 | * This signal is emitted in any error condition | |
158 | * | |
159 | */ | |
160 | signals[ERROR_SIGNAL] = g_signal_new ("error", | |
161 | G_TYPE_FROM_CLASS (klass), | |
162 | G_SIGNAL_RUN_LAST, | |
163 | 0, | |
164 | NULL, | |
165 | NULL, | |
166 | _fs_marshal_VOID__ENUM_STRING, | |
167 | G_TYPE_NONE, 2, FS_TYPE_ERROR, G_TYPE_STRING); | |
168 | ||
169 | /** | |
170 | * FsStreamTransmitter::new-active-candidate-pair: | |
171 | * @self: #FsStreamTransmitter that emitted the signal | |
172 | * @local_candidate: #FsCandidate of the local candidate being used | |
173 | * @remote_candidate: #FsCandidate of the remote candidate being used | |
174 | * | |
175 | * This signal is emitted when there is a new active chandidate pair that has | |
176 | * been established. This is specially useful for ICE where the active | |
177 | * candidate pair can change automatically due to network conditions. The user | |
178 | * must not modify the candidates and must copy them if he wants to use them | |
179 | * outside the callback scope. | |
180 | * | |
181 | */ | |
182 | signals[NEW_ACTIVE_CANDIDATE_PAIR] = g_signal_new | |
183 | ("new-active-candidate-pair", | |
184 | G_TYPE_FROM_CLASS (klass), | |
185 | G_SIGNAL_RUN_LAST, | |
186 | 0, | |
187 | NULL, | |
188 | NULL, | |
189 | _fs_marshal_VOID__BOXED_BOXED, | |
190 | G_TYPE_NONE, 2, FS_TYPE_CANDIDATE, FS_TYPE_CANDIDATE); | |
191 | ||
192 | /** | |
193 | * FsStreamTransmitter::new-local-candidate: | |
194 | * @self: #FsStream that emitted the signal | |
195 | * @local_candidate: #FsCandidate of the local candidate | |
196 | * | |
197 | * This signal is emitted when a new local candidate is discovered. | |
198 | * | |
199 | */ | |
200 | signals[NEW_LOCAL_CANDIDATE] = g_signal_new | |
201 | ("new-local-candidate", | |
202 | G_TYPE_FROM_CLASS (klass), | |
203 | G_SIGNAL_RUN_LAST, | |
204 | 0, | |
205 | NULL, | |
206 | NULL, | |
207 | g_cclosure_marshal_VOID__BOXED, | |
208 | G_TYPE_NONE, 1, FS_TYPE_CANDIDATE); | |
209 | ||
210 | /** | |
211 | * FsStreamTransmitter::local-candidates-prepared: | |
212 | * @self: #FsStreamTransmitter that emitted the signal | |
213 | * | |
214 | * This signal is emitted when all local candidates have been | |
215 | * prepared, an ICE implementation would send its SDP offer or answer. | |
216 | * | |
217 | */ | |
218 | signals[LOCAL_CANDIDATES_PREPARED] = g_signal_new | |
219 | ("local-candidates-prepared", | |
220 | G_TYPE_FROM_CLASS (klass), | |
221 | G_SIGNAL_RUN_LAST, | |
222 | 0, | |
223 | NULL, | |
224 | NULL, | |
225 | g_cclosure_marshal_VOID__VOID, | |
226 | G_TYPE_NONE, 0); | |
227 | ||
228 | /** | |
229 | * FsStreamTransmitter::known-source-packet-received: | |
230 | * @self: #FsStreamTransmitter that emitted the signal | |
231 | * @component: The Component on which this buffer was received | |
232 | * @buffer: the #GstBuffer coming from the known source | |
233 | * | |
234 | * This signal is emitted when a buffer coming from a confirmed known source | |
235 | * is received. | |
236 | */ | |
237 | signals[KNOWN_SOURCE_PACKET_RECEIVED] = g_signal_new | |
238 | ("known-source-packet-received", | |
239 | G_TYPE_FROM_CLASS (klass), | |
240 | G_SIGNAL_RUN_LAST, | |
241 | 0, | |
242 | NULL, | |
243 | NULL, | |
244 | _fs_marshal_VOID__UINT_POINTER, | |
245 | G_TYPE_NONE, 2, G_TYPE_UINT, G_TYPE_POINTER); | |
246 | ||
247 | ||
248 | /** | |
249 | * FsStreamTransmitter::state-changed | |
250 | * @self: #FsStreamTransmitter that emitted the signal | |
251 | * @component: the id of the component which state has changed | |
252 | * @state: the new state of the component | |
253 | * | |
254 | * This signal is emitted when the ICE state (or equivalent) of the component | |
255 | * changes | |
256 | */ | |
257 | signals[STATE_CHANGED] = g_signal_new | |
258 | ("state-changed", | |
259 | G_TYPE_FROM_CLASS (klass), | |
260 | G_SIGNAL_RUN_LAST, | |
261 | 0, | |
262 | NULL, | |
263 | NULL, | |
264 | _fs_marshal_VOID__UINT_ENUM, | |
265 | G_TYPE_NONE, 2, G_TYPE_UINT, FS_TYPE_STREAM_STATE); | |
266 | ||
267 | ||
268 | g_type_class_add_private (klass, sizeof (FsStreamTransmitterPrivate)); | |
269 | } | |
270 | ||
271 | static void | |
272 | fs_stream_transmitter_init (FsStreamTransmitter *self) | |
273 | { | |
274 | /* member init */ | |
275 | self->priv = FS_STREAM_TRANSMITTER_GET_PRIVATE (self); | |
276 | self->priv->disposed = FALSE; | |
277 | } | |
278 | ||
279 | static void | |
280 | fs_stream_transmitter_get_property (GObject *object, | |
281 | guint prop_id, | |
282 | GValue *value, | |
283 | GParamSpec *pspec) | |
284 | { | |
285 | GST_WARNING ("Subclass %s of FsStreamTransmitter does not override the %s" | |
286 | " property getter", | |
287 | G_OBJECT_TYPE_NAME(object), | |
288 | g_param_spec_get_name (pspec)); | |
289 | } | |
290 | ||
291 | static void | |
292 | fs_stream_transmitter_set_property (GObject *object, | |
293 | guint prop_id, | |
294 | const GValue *value, | |
295 | GParamSpec *pspec) | |
296 | { | |
297 | switch (prop_id) | |
298 | { | |
299 | /* These properties, we can safely not override */ | |
300 | case PROP_ASSOCIATE_ON_SOURCE: | |
301 | break; | |
302 | default: | |
303 | GST_WARNING ("Subclass %s of FsStreamTransmitter does not override the %s" | |
304 | " property setter", | |
305 | G_OBJECT_TYPE_NAME(object), | |
306 | g_param_spec_get_name (pspec)); | |
307 | break; | |
308 | } | |
309 | } | |
310 | ||
311 | ||
312 | /** | |
313 | * fs_stream_transmitter_add_remote_candidates | |
314 | * @streamtransmitter: a #FsStreamTranmitter | |
315 | * @candidates: (element-type FsCandidate): a #GList of the remote candidates | |
316 | * @error: location of a #GError, or NULL if no error occured | |
317 | * | |
318 | * This function is used to add remote candidates to the transmitter | |
319 | * | |
320 | * Returns: TRUE of the candidate could be added, FALSE if it couldnt | |
321 | * (and the #GError will be set) | |
322 | */ | |
323 | ||
324 | gboolean | |
325 | fs_stream_transmitter_add_remote_candidates ( | |
326 | FsStreamTransmitter *streamtransmitter, | |
327 | GList *candidates, | |
328 | GError **error) | |
329 | { | |
330 | FsStreamTransmitterClass *klass; | |
331 | ||
332 | g_return_val_if_fail (streamtransmitter, FALSE); | |
333 | g_return_val_if_fail (FS_IS_STREAM_TRANSMITTER (streamtransmitter), FALSE); | |
334 | klass = FS_STREAM_TRANSMITTER_GET_CLASS (streamtransmitter); | |
335 | ||
336 | if (klass->add_remote_candidates) { | |
337 | return klass->add_remote_candidates (streamtransmitter, candidates, error); | |
338 | } else { | |
339 | g_set_error (error, FS_ERROR, FS_ERROR_NOT_IMPLEMENTED, | |
340 | "add_remote_candidate not defined in stream transmitter class"); | |
341 | } | |
342 | ||
343 | return FALSE; | |
344 | } | |
345 | ||
346 | /** | |
347 | * fs_stream_transmitter_force_remote_candidates: | |
348 | * @streamtransmitter: a #FsStreamTransmitter | |
349 | * @remote_candidates: (element-type FsCandidate): a #GList of #FsCandidate to | |
350 | * force | |
351 | * @error: location of a #GError, or NULL if no error occured | |
352 | * | |
353 | * This function forces data to be sent immediately to the selected remote | |
354 | * candidate, by-passing any connectivity checks. There should be at most | |
355 | * one candidate per component. | |
356 | * | |
357 | * Returns: %TRUE if the candidates could be forced, %FALSE otherwise | |
358 | */ | |
359 | ||
360 | gboolean | |
361 | fs_stream_transmitter_force_remote_candidates ( | |
362 | FsStreamTransmitter *streamtransmitter, | |
363 | GList *remote_candidates, | |
364 | GError **error) | |
365 | { | |
366 | FsStreamTransmitterClass *klass; | |
367 | ||
368 | g_return_val_if_fail (streamtransmitter, FALSE); | |
369 | g_return_val_if_fail (FS_IS_STREAM_TRANSMITTER (streamtransmitter), FALSE); | |
370 | klass = FS_STREAM_TRANSMITTER_GET_CLASS (streamtransmitter); | |
371 | ||
372 | if (klass->force_remote_candidates) { | |
373 | return klass->force_remote_candidates (streamtransmitter, | |
374 | remote_candidates, error); | |
375 | } else { | |
376 | g_set_error (error, FS_ERROR, FS_ERROR_NOT_IMPLEMENTED, | |
377 | "force_remote_candidates not defined in stream transmitter class"); | |
378 | } | |
379 | ||
380 | return FALSE; | |
381 | } | |
382 | ||
383 | /** | |
384 | * fs_stream_transmitter_gather_local_candidates: | |
385 | * @streamtransmitter: a #FsStreamTransmitter | |
386 | * @error: location of a #GErrorh, or NULL if no error occured | |
387 | * | |
388 | * This function tells the transmitter to start gathering local candidates, | |
389 | * signals for new candidates and newly active candidates can be emitted | |
390 | * during the call to this function. | |
391 | * | |
392 | * Returns: %TRUE if it succeeds (or is not implemented), %FALSE otherwise | |
393 | */ | |
394 | ||
395 | gboolean | |
396 | fs_stream_transmitter_gather_local_candidates ( | |
397 | FsStreamTransmitter *streamtransmitter, | |
398 | GError **error) | |
399 | { | |
400 | FsStreamTransmitterClass *klass; | |
401 | ||
402 | g_return_val_if_fail (streamtransmitter, FALSE); | |
403 | g_return_val_if_fail (FS_IS_STREAM_TRANSMITTER (streamtransmitter), FALSE); | |
404 | klass = FS_STREAM_TRANSMITTER_GET_CLASS (streamtransmitter); | |
405 | ||
406 | if (klass->gather_local_candidates) | |
407 | return klass->gather_local_candidates (streamtransmitter, error); | |
408 | else | |
409 | return TRUE; | |
410 | } | |
411 | ||
412 | ||
413 | ||
414 | /** | |
415 | * fs_stream_transmitter_stop: | |
416 | * @streamtransmitter: a #FsStreamTransmitter | |
417 | * | |
418 | * This functions stops the #FsStreamTransmitter, it must be called before | |
419 | * the last reference is dropped. | |
420 | */ | |
421 | ||
422 | void | |
423 | fs_stream_transmitter_stop (FsStreamTransmitter *streamtransmitter) | |
424 | { | |
425 | FsStreamTransmitterClass *klass; | |
426 | ||
427 | g_return_if_fail (streamtransmitter); | |
428 | g_return_if_fail (FS_IS_STREAM_TRANSMITTER (streamtransmitter)); | |
429 | klass = FS_STREAM_TRANSMITTER_GET_CLASS (streamtransmitter); | |
430 | ||
431 | if (klass->stop) | |
432 | klass->stop (streamtransmitter); | |
433 | } | |
434 | ||
435 | ||
436 | /** | |
437 | * fs_stream_transmitter_emit_error: | |
438 | * @streamtransmitter: #FsStreamTransmitter on which to emit the error signal | |
439 | * @error_no: The number of the error | |
440 | * @error_msg: Error message (for the programmer) | |
441 | * | |
442 | * This function emit the "error" signal on a #FsStreamTransmitter, it should | |
443 | * only be called by subclasses. | |
444 | */ | |
445 | void | |
446 | fs_stream_transmitter_emit_error (FsStreamTransmitter *streamtransmitter, | |
447 | gint error_no, | |
448 | const gchar *error_msg) | |
449 | { | |
450 | g_signal_emit (streamtransmitter, signals[ERROR_SIGNAL], 0, error_no, | |
451 | error_msg); | |
452 | } |
0 | /* | |
1 | * Farstream - Farstream Stream Transmitter | |
2 | * | |
3 | * Copyright 2007 Collabora Ltd. | |
4 | * @author: Olivier Crete <olivier.crete@collabora.co.uk> | |
5 | * Copyright 2007 Nokia Corp. | |
6 | * | |
7 | * fs-stream-transmitter.h - A Farstream Stream Transmitter (base implementation) | |
8 | * | |
9 | * This library is free software; you can redistribute it and/or | |
10 | * modify it under the terms of the GNU Lesser General Public | |
11 | * License as published by the Free Software Foundation; either | |
12 | * version 2.1 of the License, or (at your option) any later version. | |
13 | * | |
14 | * This library is distributed in the hope that it will be useful, | |
15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
17 | * Lesser General Public License for more details. | |
18 | * | |
19 | * You should have received a copy of the GNU Lesser General Public | |
20 | * License along with this library; if not, write to the Free Software | |
21 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA | |
22 | */ | |
23 | ||
24 | #ifndef __FS_STREAM_TRANSMITTER_H__ | |
25 | #define __FS_STREAM_TRANSMITTER_H__ | |
26 | ||
27 | #include <gst/gst.h> | |
28 | ||
29 | #include <farstream/fs-candidate.h> | |
30 | ||
31 | G_BEGIN_DECLS | |
32 | ||
33 | /* TYPE MACROS */ | |
34 | #define FS_TYPE_STREAM_TRANSMITTER \ | |
35 | (fs_stream_transmitter_get_type ()) | |
36 | #define FS_STREAM_TRANSMITTER(obj) \ | |
37 | (G_TYPE_CHECK_INSTANCE_CAST((obj), FS_TYPE_STREAM_TRANSMITTER, \ | |
38 | FsStreamTransmitter)) | |
39 | #define FS_STREAM_TRANSMITTER_CLASS(klass) \ | |
40 | (G_TYPE_CHECK_CLASS_CAST((klass), FS_TYPE_STREAM_TRANSMITTER, \ | |
41 | FsStreamTransmitterClass)) | |
42 | #define FS_IS_STREAM_TRANSMITTER(obj) \ | |
43 | (G_TYPE_CHECK_INSTANCE_TYPE((obj), FS_TYPE_STREAM_TRANSMITTER)) | |
44 | #define FS_IS_STREAM_TRANSMITTER_CLASS(klass) \ | |
45 | (G_TYPE_CHECK_CLASS_TYPE((klass), FS_TYPE_STREAM_TRANSMITTER)) | |
46 | #define FS_STREAM_TRANSMITTER_GET_CLASS(obj) \ | |
47 | (G_TYPE_INSTANCE_GET_CLASS ((obj), FS_TYPE_STREAM_TRANSMITTER, \ | |
48 | FsStreamTransmitterClass)) | |
49 | #define FS_STREAM_TRANSMITTER_CAST(obj) ((FsStreamTransmitter *) (obj)) | |
50 | ||
51 | typedef struct _FsStreamTransmitter FsStreamTransmitter; | |
52 | typedef struct _FsStreamTransmitterClass FsStreamTransmitterClass; | |
53 | typedef struct _FsStreamTransmitterPrivate FsStreamTransmitterPrivate; | |
54 | ||
55 | /** | |
56 | * FsStreamTransmitterClass: | |
57 | * @parent_class: Our parent | |
58 | * @add_remote_candidates: Sets the remote candidates | |
59 | * @force_remote_candidates: Forces certain remote candidates | |
60 | * @gather_local_candidates: Starts the gathering of local candidates | |
61 | * @stop: Stop the stream transmitter synchronously (does any Gst stopping | |
62 | * that needs to be done) | |
63 | * | |
64 | * You must override the add_remote_candidate in a subclass | |
65 | */ | |
66 | ||
67 | struct _FsStreamTransmitterClass | |
68 | { | |
69 | GstObjectClass parent_class; | |
70 | ||
71 | /*virtual functions */ | |
72 | gboolean (*add_remote_candidates) (FsStreamTransmitter *streamtransmitter, | |
73 | GList *candidates, GError **error); | |
74 | ||
75 | gboolean (*force_remote_candidates) (FsStreamTransmitter *streamtransmitter, | |
76 | GList *remote_candidates, | |
77 | GError **error); | |
78 | gboolean (*gather_local_candidates) (FsStreamTransmitter *streamtransmitter, | |
79 | GError **error); | |
80 | void (*stop) (FsStreamTransmitter *streamtransmitter); | |
81 | ||
82 | /*< private >*/ | |
83 | gpointer _padding[8]; | |
84 | }; | |
85 | ||
86 | /** | |
87 | * FsStreamTransmitter: | |
88 | * | |
89 | * All members are private, access them using methods and properties | |
90 | */ | |
91 | struct _FsStreamTransmitter | |
92 | { | |
93 | GstObject parent; | |
94 | ||
95 | /*< private >*/ | |
96 | FsStreamTransmitterPrivate *priv; | |
97 | gpointer _padding[8]; | |
98 | }; | |
99 | ||
100 | GType fs_stream_transmitter_get_type (void); | |
101 | ||
102 | gboolean fs_stream_transmitter_add_remote_candidates ( | |
103 | FsStreamTransmitter *streamtransmitter, | |
104 | GList *candidates, | |
105 | GError **error); | |
106 | ||
107 | gboolean fs_stream_transmitter_force_remote_candidates ( | |
108 | FsStreamTransmitter *streamtransmitter, | |
109 | GList *remote_candidates, | |
110 | GError **error); | |
111 | ||
112 | gboolean | |
113 | fs_stream_transmitter_gather_local_candidates ( | |
114 | FsStreamTransmitter *streamtransmitter, | |
115 | GError **error); | |
116 | ||
117 | void fs_stream_transmitter_stop (FsStreamTransmitter *streamtransmitter); | |
118 | ||
119 | void fs_stream_transmitter_emit_error (FsStreamTransmitter *streamtransmitter, | |
120 | gint error_no, | |
121 | const gchar *error_msg); | |
122 | ||
123 | G_END_DECLS | |
124 | ||
125 | #endif /* __FS_STREAM_TRANSMITTER_H__ */ |
0 | /* | |
1 | * Farstream - Farstream Stream | |
2 | * | |
3 | * Copyright 2007 Collabora Ltd. | |
4 | * @author: Philippe Kalaf <philippe.kalaf@collabora.co.uk> | |
5 | * Copyright 2007 Nokia Corp. | |
6 | * | |
7 | * fs-stream.c - A Farstream Stream gobject (base implementation) | |
8 | * | |
9 | * This library is free software; you can redistribute it and/or | |
10 | * modify it under the terms of the GNU Lesser General Public | |
11 | * License as published by the Free Software Foundation; either | |
12 | * version 2.1 of the License, or (at your option) any later version. | |
13 | * | |
14 | * This library is distributed in the hope that it will be useful, | |
15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
17 | * Lesser General Public License for more details. | |
18 | * | |
19 | * You should have received a copy of the GNU Lesser General Public | |
20 | * License along with this library; if not, write to the Free Software | |
21 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA | |
22 | */ | |
23 | ||
24 | /** | |
25 | * SECTION:fs-stream | |
26 | * @short_description: A stream in a session in a conference | |
27 | * | |
28 | * This object is the base implementation of a Farstream Stream. It | |
29 | * needs to be derived and implemented by a Farstream conference GStreamer | |
30 | * element. A Farstream Stream is a media stream originating from a | |
31 | * #FsParticipant inside a #FsSession. In fact, a #FsStream instance is | |
32 | * obtained by adding a participant into a session using | |
33 | * fs_session_new_stream(). | |
34 | * | |
35 | * | |
36 | * This will communicate asynchronous events to the user through #GstMessage | |
37 | * of type #GST_MESSAGE_ELEMENT sent over the #GstBus. | |
38 | * </para> | |
39 | * <refsect2><title>The "<literal>farstream-new-local-candidate</literal>" message</title> | |
40 | * |[ | |
41 | * "stream" #FsStream The stream that emits the message | |
42 | * "candidate" #FsCandidate The new candidate | |
43 | * ]| | |
44 | * <para> | |
45 | * This message is emitted when a new local candidate is discovered. | |
46 | * </para> | |
47 | * </refsect2> | |
48 | * <refsect2><title>The "<literal>farstream-local-candidates-prepared</literal>" message</title> | |
49 | * |[ | |
50 | * "stream" #FsStream The stream that emits the message | |
51 | * ]| | |
52 | * <para> | |
53 | * This signal is emitted when all local candidates have been | |
54 | * prepared, an ICE implementation would send its SDP offer or answer. | |
55 | * </para> | |
56 | * </refsect2> | |
57 | * <refsect2><title>The "<literal>farstream-new-active-candidate-pair</literal>" message</title> | |
58 | * |[ | |
59 | * "stream" #FsStream The stream that emits the message | |
60 | * "local-candidate" #FsCandidate Local candidate being used | |
61 | * "remote-candidate" #FsCandidate Remote candidate being used | |
62 | * ]| | |
63 | * <para> | |
64 | * This message is emitted when there is a new active candidate pair that has | |
65 | * been established. This is specially useful for ICE where the active | |
66 | * candidate pair can change automatically due to network conditions. The user | |
67 | * must not modify the candidates and must copy them if he wants to use them | |
68 | * outside the callback scope. This message is emitted once per component. | |
69 | * </para> | |
70 | * </refsect2> | |
71 | * <refsect2><title>The "<literal>farstream-recv-codecs-changed</literal>" message</title> | |
72 | * |[ | |
73 | * "stream" #FsStream The stream that emits the message | |
74 | * "codecs" #FsCodecGList A #GList of #FsCodec | |
75 | * ]| | |
76 | * <para> | |
77 | * This message is emitted when the content of the | |
78 | * #FsStream:current-recv-codecs property changes. It is normally emitted | |
79 | * right after the #FsStream::src-pad-added signal only if that codec was not | |
80 | * previously received in this stream, but it can also be emitted if the pad | |
81 | * already exists, but the source material that will come to it is different. | |
82 | * The list of new recv-codecs is included in the message | |
83 | * </para> | |
84 | * </refsect2> | |
85 | * <refsect2><title>The "<literal>farstream-component-state-changed</literal>" message</title> | |
86 | * |[ | |
87 | * "stream" #FsStream The stream that emits the message | |
88 | * "component" #guint The component whose state changed | |
89 | * "state" #FsStreamState The new state of the component | |
90 | * ]| | |
91 | * <para> | |
92 | * This message is emitted the state of a component of a stream changes. | |
93 | * </para> | |
94 | * </refsect2> | |
95 | * <para> | |
96 | */ | |
97 | ||
98 | #ifdef HAVE_CONFIG_H | |
99 | #include "config.h" | |
100 | #endif | |
101 | ||
102 | #include "fs-stream.h" | |
103 | ||
104 | #include <gst/gst.h> | |
105 | ||
106 | #include "fs-session.h" | |
107 | #include "fs-marshal.h" | |
108 | #include "fs-codec.h" | |
109 | #include "fs-candidate.h" | |
110 | #include "fs-stream-transmitter.h" | |
111 | #include "fs-conference.h" | |
112 | #include "fs-enumtypes.h" | |
113 | #include "fs-private.h" | |
114 | ||
115 | /* Signals */ | |
116 | enum | |
117 | { | |
118 | ERROR_SIGNAL, | |
119 | SRC_PAD_ADDED, | |
120 | LAST_SIGNAL | |
121 | }; | |
122 | ||
123 | /* props */ | |
124 | enum | |
125 | { | |
126 | PROP_0, | |
127 | PROP_REMOTE_CODECS, | |
128 | PROP_NEGOTIATED_CODECS, | |
129 | PROP_CURRENT_RECV_CODECS, | |
130 | PROP_DIRECTION, | |
131 | PROP_PARTICIPANT, | |
132 | PROP_SESSION | |
133 | }; | |
134 | ||
135 | ||
136 | struct _FsStreamPrivate | |
137 | { | |
138 | GMutex *mutex; | |
139 | GList *src_pads; | |
140 | guint32 src_pads_cookie; | |
141 | }; | |
142 | ||
143 | #define FS_STREAM_GET_PRIVATE(o) \ | |
144 | (G_TYPE_INSTANCE_GET_PRIVATE ((o), FS_TYPE_STREAM, FsStreamPrivate)) | |
145 | ||
146 | ||
147 | G_DEFINE_ABSTRACT_TYPE(FsStream, fs_stream, GST_TYPE_OBJECT); | |
148 | ||
149 | static void fs_stream_get_property (GObject *object, | |
150 | guint prop_id, | |
151 | GValue *value, | |
152 | GParamSpec *pspec); | |
153 | static void fs_stream_set_property (GObject *object, | |
154 | guint prop_id, | |
155 | const GValue *value, | |
156 | GParamSpec *pspec); | |
157 | static void fs_stream_finalize (GObject *obj); | |
158 | ||
159 | static guint signals[LAST_SIGNAL] = { 0 }; | |
160 | ||
161 | #define FS_STREAM_LOCK(self) g_mutex_lock((self)->priv->mutex) | |
162 | #define FS_STREAM_UNLOCK(self) g_mutex_unlock((self)->priv->mutex) | |
163 | ||
164 | static void | |
165 | fs_stream_class_init (FsStreamClass *klass) | |
166 | { | |
167 | GObjectClass *gobject_class; | |
168 | ||
169 | gobject_class = (GObjectClass *) klass; | |
170 | ||
171 | gobject_class->set_property = fs_stream_set_property; | |
172 | gobject_class->get_property = fs_stream_get_property; | |
173 | gobject_class->finalize = fs_stream_finalize; | |
174 | ||
175 | /** | |
176 | * FsStream:remote-codecs: | |
177 | * | |
178 | * Type: GLib.List<FsCodec> | |
179 | * Transfer: full | |
180 | * | |
181 | * This is the list of remote codecs for this stream. They must be set by the | |
182 | * user as soon as they are known using fs_stream_set_remote_codecs() | |
183 | * (generally through external signaling). It is a #GList of #FsCodec. | |
184 | * | |
185 | */ | |
186 | g_object_class_install_property (gobject_class, | |
187 | PROP_REMOTE_CODECS, | |
188 | g_param_spec_boxed ("remote-codecs", | |
189 | "List of remote codecs", | |
190 | "A GList of FsCodecs of the remote codecs", | |
191 | FS_TYPE_CODEC_LIST, | |
192 | G_PARAM_READABLE | G_PARAM_STATIC_STRINGS)); | |
193 | ||
194 | /** | |
195 | * FsStream:negotiated-codecs: | |
196 | * | |
197 | * Type: GLib.List<FsCodec> | |
198 | * Transfer: full | |
199 | * | |
200 | * This is the list of negotiatied codecs, it is the same list as the list | |
201 | * of #FsCodec from the parent #FsSession, except that the codec config data | |
202 | * has been replaced with the data from the remote codecs for this stream. | |
203 | * This is the list of #FsCodec used to receive data from this stream. | |
204 | * It is a #GList of #FsCodec. | |
205 | * | |
206 | */ | |
207 | g_object_class_install_property (gobject_class, | |
208 | PROP_NEGOTIATED_CODECS, | |
209 | g_param_spec_boxed ("negotiated-codecs", | |
210 | "List of remote codecs", | |
211 | "A GList of FsCodecs of the negotiated codecs for this stream", | |
212 | FS_TYPE_CODEC_LIST, | |
213 | G_PARAM_READABLE | G_PARAM_STATIC_STRINGS)); | |
214 | ||
215 | /** | |
216 | * FsStream:current-recv-codecs: | |
217 | * | |
218 | * Type: GLib.List<FsCodec> | |
219 | * Transfer: full | |
220 | * | |
221 | * This is the list of codecs that have been received by this stream. | |
222 | * The user must free the list if fs_codec_list_destroy(). | |
223 | * The "farstream-recv-codecs-changed" message is send on the #GstBus | |
224 | * when the value of this property changes. | |
225 | * It is normally emitted right after #FsStream::src-pad-added | |
226 | * only if that codec was not previously received in this stream, but it can | |
227 | * also be emitted if the pad already exists, but the source material that | |
228 | * will come to it is different. | |
229 | * | |
230 | */ | |
231 | g_object_class_install_property (gobject_class, | |
232 | PROP_CURRENT_RECV_CODECS, | |
233 | g_param_spec_boxed ("current-recv-codecs", | |
234 | "The codecs currently being received", | |
235 | "A GList of FsCodec representing the codecs that have been received", | |
236 | FS_TYPE_CODEC_LIST, | |
237 | G_PARAM_READABLE | G_PARAM_STATIC_STRINGS)); | |
238 | ||
239 | /** | |
240 | * FsStream:direction: | |
241 | * | |
242 | * The direction of the stream. This property is set initially as a parameter | |
243 | * to the fs_session_new_stream() function. It can be changed later if | |
244 | * required by setting this property. | |
245 | * | |
246 | */ | |
247 | g_object_class_install_property (gobject_class, | |
248 | PROP_DIRECTION, | |
249 | g_param_spec_flags ("direction", | |
250 | "The direction of the stream", | |
251 | "An enum to set and get the direction of the stream", | |
252 | FS_TYPE_STREAM_DIRECTION, | |
253 | FS_DIRECTION_NONE, | |
254 | G_PARAM_CONSTRUCT | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); | |
255 | ||
256 | /** | |
257 | * FsStream:participant: | |
258 | * | |
259 | * The #FsParticipant for this stream. This property is a construct param and | |
260 | * is read-only construction. | |
261 | * | |
262 | */ | |
263 | g_object_class_install_property (gobject_class, | |
264 | PROP_PARTICIPANT, | |
265 | g_param_spec_object ("participant", | |
266 | "The participant of the stream", | |
267 | "An FsParticipant represented by the stream", | |
268 | FS_TYPE_PARTICIPANT, | |
269 | G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); | |
270 | ||
271 | /** | |
272 | * FsStream:session: | |
273 | * | |
274 | * The #FsSession for this stream. This property is a construct param and | |
275 | * is read-only construction. | |
276 | * | |
277 | */ | |
278 | g_object_class_install_property (gobject_class, | |
279 | PROP_SESSION, | |
280 | g_param_spec_object ("session", | |
281 | "The session of the stream", | |
282 | "An FsSession represented by the stream", | |
283 | FS_TYPE_SESSION, | |
284 | G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); | |
285 | ||
286 | /** | |
287 | * FsStream::error: | |
288 | * @self: #FsStream that emitted the signal | |
289 | * @errorno: The number of the error | |
290 | * @error_msg: Error message to be displayed to user | |
291 | * | |
292 | * This signal is emitted in any error condition | |
293 | * | |
294 | */ | |
295 | signals[ERROR_SIGNAL] = g_signal_new ("error", | |
296 | G_TYPE_FROM_CLASS (klass), | |
297 | G_SIGNAL_RUN_LAST, | |
298 | 0, | |
299 | NULL, | |
300 | NULL, | |
301 | _fs_marshal_VOID__ENUM_STRING, | |
302 | G_TYPE_NONE, 2, FS_TYPE_ERROR, G_TYPE_STRING); | |
303 | ||
304 | /** | |
305 | * FsStream::src-pad-added: | |
306 | * @self: #FsStream that emitted the signal | |
307 | * @pad: #GstPad of the new source pad | |
308 | * @codec: #FsCodec of the codec being received on the new source pad | |
309 | * | |
310 | * This signal is emitted when a new gst source pad has been created for a | |
311 | * specific codec being received. There will be a different source pad for | |
312 | * each codec that is received. The user must ref the #GstPad if he wants to | |
313 | * keep it. The user should not modify the #FsCodec and must copy it if he | |
314 | * wants to use it outside the callback scope. | |
315 | * | |
316 | * This signal is not emitted on the main thread, but on GStreamer's streaming | |
317 | * thread! | |
318 | * | |
319 | */ | |
320 | signals[SRC_PAD_ADDED] = g_signal_new ("src-pad-added", | |
321 | G_TYPE_FROM_CLASS (klass), | |
322 | G_SIGNAL_RUN_LAST, | |
323 | 0, | |
324 | NULL, | |
325 | NULL, | |
326 | _fs_marshal_VOID__BOXED_BOXED, | |
327 | G_TYPE_NONE, 2, GST_TYPE_PAD, FS_TYPE_CODEC); | |
328 | ||
329 | g_type_class_add_private (klass, sizeof (FsStreamPrivate)); | |
330 | } | |
331 | ||
332 | static void | |
333 | fs_stream_init (FsStream *self) | |
334 | { | |
335 | /* member init */ | |
336 | self->priv = FS_STREAM_GET_PRIVATE (self); | |
337 | self->priv->mutex = g_mutex_new (); | |
338 | } | |
339 | ||
340 | static void | |
341 | fs_stream_finalize (GObject *obj) | |
342 | { | |
343 | FsStream *stream = FS_STREAM (obj); | |
344 | ||
345 | g_list_free (stream->priv->src_pads); | |
346 | g_mutex_free (stream->priv->mutex); | |
347 | ||
348 | G_OBJECT_CLASS (fs_stream_parent_class)->finalize (obj); | |
349 | } | |
350 | ||
351 | static void | |
352 | fs_stream_get_property (GObject *object, | |
353 | guint prop_id, | |
354 | GValue *value, | |
355 | GParamSpec *pspec) | |
356 | { | |
357 | GST_WARNING ("Subclass %s of FsStream does not override the %s property" | |
358 | " getter", | |
359 | G_OBJECT_TYPE_NAME(object), | |
360 | g_param_spec_get_name (pspec)); | |
361 | } | |
362 | ||
363 | static void | |
364 | fs_stream_set_property (GObject *object, | |
365 | guint prop_id, | |
366 | const GValue *value, | |
367 | GParamSpec *pspec) | |
368 | { | |
369 | GST_WARNING ("Subclass %s of FsStream does not override the %s property" | |
370 | " setter", | |
371 | G_OBJECT_TYPE_NAME(object), | |
372 | g_param_spec_get_name (pspec)); | |
373 | } | |
374 | ||
375 | /** | |
376 | * fs_stream_add_remote_candidates: | |
377 | * @stream: an #FsStream | |
378 | * @candidates: (element-type FsCandidate): an #GList of #FsCandidate | |
379 | * representing the remote candidates | |
380 | * @error: location of a #GError, or %NULL if no error occured | |
381 | * | |
382 | * This function adds remote candidates. Any new candidates are | |
383 | * added to the list. The candidates will be used to establish a connection | |
384 | * with the peer. A copy will be made so the user must free the | |
385 | * passed candidate using fs_candidate_destroy() when done. | |
386 | * | |
387 | * Return value: TRUE if the candidate was valid, FALSE otherwise | |
388 | */ | |
389 | gboolean | |
390 | fs_stream_add_remote_candidates (FsStream *stream, | |
391 | GList *candidates, | |
392 | GError **error) | |
393 | { | |
394 | FsStreamClass *klass; | |
395 | ||
396 | g_return_val_if_fail (stream, FALSE); | |
397 | g_return_val_if_fail (FS_IS_STREAM (stream), FALSE); | |
398 | klass = FS_STREAM_GET_CLASS (stream); | |
399 | ||
400 | if (klass->add_remote_candidates) { | |
401 | return klass->add_remote_candidates (stream, candidates, error); | |
402 | } else { | |
403 | g_set_error (error, FS_ERROR, FS_ERROR_NOT_IMPLEMENTED, | |
404 | "add_remote_candidate not defined in class"); | |
405 | } | |
406 | ||
407 | return FALSE; | |
408 | } | |
409 | ||
410 | /** | |
411 | * fs_stream_force_remote_candidates: | |
412 | * @stream: a #FsStream | |
413 | * @remote_candidates: (element-type FsCandidate): | |
414 | * a #GList of #FsCandidate to force | |
415 | * @error: location of a #GError, or %NULL if no error occured | |
416 | * | |
417 | * This function forces data to be sent immediately to the selected remote | |
418 | * candidate, by-passing any connectivity checks. There should be at most | |
419 | * one candidate per component. | |
420 | * | |
421 | * Returns: %TRUE if the candidates could be forced, %FALSE otherwise | |
422 | */ | |
423 | ||
424 | gboolean | |
425 | fs_stream_force_remote_candidates (FsStream *stream, | |
426 | GList *remote_candidates, | |
427 | GError **error) | |
428 | { | |
429 | FsStreamClass *klass; | |
430 | ||
431 | g_return_val_if_fail (stream, FALSE); | |
432 | g_return_val_if_fail (FS_IS_STREAM (stream), FALSE); | |
433 | klass = FS_STREAM_GET_CLASS (stream); | |
434 | ||
435 | if (klass->force_remote_candidates) { | |
436 | return klass->force_remote_candidates (stream, | |
437 | remote_candidates, | |
438 | error); | |
439 | } else { | |
440 | g_set_error (error, FS_ERROR, FS_ERROR_NOT_IMPLEMENTED, | |
441 | "force_remote_candidates not defined in class"); | |
442 | } | |
443 | ||
444 | return FALSE; | |
445 | } | |
446 | ||
447 | /** | |
448 | * fs_stream_set_remote_codecs: | |
449 | * @stream: a #FsStream | |
450 | * @remote_codecs: (element-type FsCodec): a #GList of #FsCodec representing | |
451 | * the remote codecs | |
452 | * @error: location of a #GError, or %NULL if no error occured | |
453 | * | |
454 | * This function will set the list of remote codecs for this stream. If | |
455 | * the given remote codecs couldn't be negotiated with the list of local | |
456 | * codecs or already negotiated codecs for the corresponding #FsSession, @error | |
457 | * will be set and %FALSE will be returned. The @remote_codecs list will be | |
458 | * copied so it must be free'd using fs_codec_list_destroy() when done. | |
459 | * | |
460 | * Returns: %FALSE if the remote codecs couldn't be set. | |
461 | */ | |
462 | gboolean | |
463 | fs_stream_set_remote_codecs (FsStream *stream, | |
464 | GList *remote_codecs, GError **error) | |
465 | { | |
466 | FsStreamClass *klass; | |
467 | ||
468 | g_return_val_if_fail (stream, FALSE); | |
469 | g_return_val_if_fail (FS_IS_STREAM (stream), FALSE); | |
470 | klass = FS_STREAM_GET_CLASS (stream); | |
471 | ||
472 | if (klass->set_remote_codecs) { | |
473 | return klass->set_remote_codecs (stream, remote_codecs, error); | |
474 | } else { | |
475 | g_set_error (error, FS_ERROR, FS_ERROR_NOT_IMPLEMENTED, | |
476 | "set_remote_codecs not defined in class"); | |
477 | } | |
478 | ||
479 | return FALSE; | |
480 | } | |
481 | ||
482 | /** | |
483 | * fs_stream_add_id: | |
484 | * @stream: a #FsStream | |
485 | * @id: The id to add to the stream | |
486 | * | |
487 | * This function is used to add data identifiers that allow the | |
488 | * plugin to recognize packets that are meant for id. For example, in RTP, | |
489 | * one would set the SSRCs that are expected. | |
490 | * | |
491 | * Depending on the protocol, one may be able to add more than one ID | |
492 | * to a stream (in RTP you can have multiple SSRCs in a stream). | |
493 | * If a protocol supports only one id, adding a new one will overwrite it. | |
494 | * If an ID was already set on a stream, adding it to another stream will | |
495 | * override the previdous decision. | |
496 | * | |
497 | * For most protocols, calling this function is optional as the incoming data | |
498 | * can be matched with a stream by its source IP address. This is mostly useful | |
499 | * if one is using multicast or is behind a muxer server. | |
500 | */ | |
501 | void | |
502 | fs_stream_add_id (FsStream *stream, | |
503 | guint id) | |
504 | { | |
505 | FsStreamClass *klass; | |
506 | ||
507 | g_return_if_fail (stream); | |
508 | g_return_if_fail (FS_IS_STREAM (stream)); | |
509 | klass = FS_STREAM_GET_CLASS (stream); | |
510 | ||
511 | if (klass->add_id) | |
512 | klass->add_id (stream, id); | |
513 | } | |
514 | ||
515 | /** | |
516 | * fs_stream_emit_error: | |
517 | * @stream: #FsStream on which to emit the error signal | |
518 | * @error_no: The number of the error | |
519 | * @error_msg: Error message to be displayed to user | |
520 | * | |
521 | * This function emits the #FsStream::error" signal, it should only be | |
522 | * called by subclasses. | |
523 | */ | |
524 | void | |
525 | fs_stream_emit_error (FsStream *stream, | |
526 | gint error_no, | |
527 | const gchar *error_msg) | |
528 | { | |
529 | g_signal_emit (stream, signals[ERROR_SIGNAL], 0, error_no, error_msg); | |
530 | } | |
531 | ||
532 | ||
533 | static void | |
534 | src_pad_parent_unset (GstObject *srcpad, GstObject *parent, gpointer user_data) | |
535 | { | |
536 | FsStream *stream = FS_STREAM (user_data); | |
537 | ||
538 | FS_STREAM_LOCK (stream); | |
539 | stream->priv->src_pads = g_list_remove (stream->priv->src_pads, srcpad); | |
540 | stream->priv->src_pads_cookie++; | |
541 | FS_STREAM_UNLOCK (stream); | |
542 | } | |
543 | ||
544 | /** | |
545 | * fs_stream_emit_src_pad_added: | |
546 | * @stream: #FsStream on which to emit the src-pad-added signal | |
547 | * @pad: the #GstPad that this #FsStream has created | |
548 | * @codec: The #FsCodec for this pad | |
549 | * | |
550 | * Emits the #FsStream::src-pad-added" signal, it should only be | |
551 | * called by subclasses. | |
552 | */ | |
553 | ||
554 | void | |
555 | fs_stream_emit_src_pad_added (FsStream *stream, | |
556 | GstPad *pad, | |
557 | FsCodec *codec) | |
558 | { | |
559 | FS_STREAM_LOCK (stream); | |
560 | g_assert (!g_list_find (stream->priv->src_pads, pad)); | |
561 | stream->priv->src_pads = g_list_append (stream->priv->src_pads, pad); | |
562 | stream->priv->src_pads_cookie++; | |
563 | g_signal_connect_object (pad, "parent-unset", | |
564 | G_CALLBACK (src_pad_parent_unset), stream, 0); | |
565 | FS_STREAM_UNLOCK (stream); | |
566 | ||
567 | g_signal_emit (stream, signals[SRC_PAD_ADDED], 0, pad, codec); | |
568 | } | |
569 | ||
570 | static GstIteratorItem | |
571 | src_pad_iterator_item_func (GstIterator*iter, gpointer item) | |
572 | { | |
573 | gst_object_ref (item); | |
574 | ||
575 | return GST_ITERATOR_ITEM_PASS; | |
576 | } | |
577 | ||
578 | /** | |
579 | * fs_stream_iterate_src_pads: | |
580 | * @stream: a #FsStream | |
581 | * | |
582 | * Creates a #GstIterator that can be used to iterate the src pads of this | |
583 | * stream. These are the pads that were announced by #FsStream:src-pad-added | |
584 | * and are still valid. | |
585 | * | |
586 | * Returns: (transfer full): The #GstIterator | |
587 | */ | |
588 | ||
589 | GstIterator * | |
590 | fs_stream_iterate_src_pads (FsStream *stream) | |
591 | { | |
592 | return gst_iterator_new_list (GST_TYPE_PAD, stream->priv->mutex, | |
593 | &stream->priv->src_pads_cookie, &stream->priv->src_pads, | |
594 | g_object_ref (stream), src_pad_iterator_item_func, g_object_unref); | |
595 | } | |
596 | ||
597 | ||
598 | /** | |
599 | * fs_stream_set_transmitter: | |
600 | * @stream: a #FsStream | |
601 | * @transmitter: Name of the type of transmitter to use for this stream | |
602 | * @stream_transmitter_n_parameters: Number of parametrs passed to the stream | |
603 | * transmitter | |
604 | * @stream_transmitter_parameters: | |
605 | * (array length=stream_transmitter_n_parameters) (allow-none): | |
606 | * an array of n_parameters #GParameter struct that will be passed | |
607 | * to the newly-create #FsStreamTransmitter | |
608 | * @error: location of a #GError, or %NULL if no error occured | |
609 | * | |
610 | * Set the transmitter to use for this stream. This function will only succeed | |
611 | * once. | |
612 | * | |
613 | * Returns: %TRUE if the transmitter could be set, %FALSE otherwise | |
614 | */ | |
615 | ||
616 | gboolean | |
617 | fs_stream_set_transmitter (FsStream *stream, | |
618 | const gchar *transmitter, | |
619 | GParameter *stream_transmitter_parameters, | |
620 | guint stream_transmitter_n_parameters, | |
621 | GError **error) | |
622 | { | |
623 | FsStreamClass *klass; | |
624 | ||
625 | g_return_val_if_fail (stream, FALSE); | |
626 | g_return_val_if_fail (FS_IS_STREAM (stream), FALSE); | |
627 | klass = FS_STREAM_GET_CLASS (stream); | |
628 | ||
629 | if (klass->set_transmitter) | |
630 | return klass->set_transmitter (stream, transmitter, | |
631 | stream_transmitter_parameters, stream_transmitter_n_parameters, error); | |
632 | ||
633 | ||
634 | g_set_error (error, FS_ERROR, FS_ERROR_NOT_IMPLEMENTED, | |
635 | "set_transmitter not defined in class"); | |
636 | ||
637 | return FALSE; | |
638 | } | |
639 | ||
640 | /** | |
641 | * fs_stream_destroy: | |
642 | * @stream: a #FsStream | |
643 | * | |
644 | * This will cause the stream to remove all links to other objects and to | |
645 | * remove itself from the #FsSession. Once a #FsStream has been destroyed, it | |
646 | * can not be used anymore. | |
647 | * | |
648 | * It is strongly recommended to call this function from the main thread because | |
649 | * releasing the application's reference to a stream. | |
650 | */ | |
651 | ||
652 | void | |
653 | fs_stream_destroy (FsStream *stream) | |
654 | { | |
655 | g_return_if_fail (stream); | |
656 | g_return_if_fail (FS_IS_STREAM (stream)); | |
657 | ||
658 | g_object_run_dispose (G_OBJECT (stream)); | |
659 | } |
0 | /* | |
1 | * Farstream - Farstream Stream | |
2 | * | |
3 | * Copyright 2007 Collabora Ltd. | |
4 | * @author: Philippe Kalaf <philippe.kalaf@collabora.co.uk> | |
5 | * Copyright 2007 Nokia Corp. | |
6 | * | |
7 | * fs-stream.h - A Farstream Stream (base implementation) | |
8 | * | |
9 | * This library is free software; you can redistribute it and/or | |
10 | * modify it under the terms of the GNU Lesser General Public | |
11 | * License as published by the Free Software Foundation; either | |
12 | * version 2.1 of the License, or (at your option) any later version. | |
13 | * | |
14 | * This library is distributed in the hope that it will be useful, | |
15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
17 | * Lesser General Public License for more details. | |
18 | * | |
19 | * You should have received a copy of the GNU Lesser General Public | |
20 | * License along with this library; if not, write to the Free Software | |
21 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA | |
22 | */ | |
23 | ||
24 | #ifndef __FS_STREAM_H__ | |
25 | #define __FS_STREAM_H__ | |
26 | ||
27 | #include <glib.h> | |
28 | #include <glib-object.h> | |
29 | ||
30 | #include <farstream/fs-candidate.h> | |
31 | #include <farstream/fs-codec.h> | |
32 | ||
33 | G_BEGIN_DECLS | |
34 | ||
35 | /** | |
36 | * FsStreamDirection: | |
37 | * @FS_DIRECTION_NONE: No direction specified | |
38 | * @FS_DIRECTION_SEND: Send only | |
39 | * @FS_DIRECTION_RECV: Receive only | |
40 | * @FS_DIRECTION_BOTH: Send and receive | |
41 | * | |
42 | * An enum for specifying the direction of a stream | |
43 | * | |
44 | */ | |
45 | typedef enum _FsStreamDirection | |
46 | { | |
47 | FS_DIRECTION_NONE = 0, | |
48 | FS_DIRECTION_SEND = 1<<0, | |
49 | FS_DIRECTION_RECV = 1<<1, | |
50 | FS_DIRECTION_BOTH = FS_DIRECTION_SEND | FS_DIRECTION_RECV | |
51 | } FsStreamDirection; | |
52 | ||
53 | /** | |
54 | * FsStreamState: | |
55 | * @FS_STREAM_STATE_FAILED: connectivity checks have been completed, | |
56 | * but connectivity was not established | |
57 | * @FS_STREAM_STATE_DISCONNECTED: no activity scheduled | |
58 | * @FS_STREAM_STATE_GATHERING: gathering local candidates | |
59 | * @FS_STREAM_STATE_CONNECTING: establishing connectivity | |
60 | * @FS_STREAM_STATE_CONNECTED: at least one working candidate pair | |
61 | * @FS_STREAM_STATE_READY: ICE concluded, candidate pair selection is now final | |
62 | * | |
63 | * These are the possible states of a stream, a simple multicast stream | |
64 | * could only be in "disconnected" or "ready" state. | |
65 | * An stream using an ICE transmitter would use all of these. | |
66 | */ | |
67 | ||
68 | typedef enum _FsStreamState | |
69 | { | |
70 | FS_STREAM_STATE_FAILED, | |
71 | FS_STREAM_STATE_DISCONNECTED, | |
72 | FS_STREAM_STATE_GATHERING, | |
73 | FS_STREAM_STATE_CONNECTING, | |
74 | FS_STREAM_STATE_CONNECTED, | |
75 | FS_STREAM_STATE_READY | |
76 | } FsStreamState; | |
77 | ||
78 | /* TYPE MACROS */ | |
79 | #define FS_TYPE_STREAM \ | |
80 | (fs_stream_get_type ()) | |
81 | #define FS_STREAM(obj) \ | |
82 | (G_TYPE_CHECK_INSTANCE_CAST((obj), FS_TYPE_STREAM, FsStream)) | |
83 | #define FS_STREAM_CLASS(klass) \ | |
84 | (G_TYPE_CHECK_CLASS_CAST((klass), FS_TYPE_STREAM, FsStreamClass)) | |
85 | #define FS_IS_STREAM(obj) \ | |
86 | (G_TYPE_CHECK_INSTANCE_TYPE((obj), FS_TYPE_STREAM)) | |
87 | #define FS_IS_STREAM_CLASS(klass) \ | |
88 | (G_TYPE_CHECK_CLASS_TYPE((klass), FS_TYPE_STREAM)) | |
89 | #define FS_STREAM_GET_CLASS(obj) \ | |
90 | (G_TYPE_INSTANCE_GET_CLASS ((obj), FS_TYPE_STREAM, FsStreamClass)) | |
91 | #define FS_STREAM_CAST(obj) ((FsStream *) (obj)) | |
92 | ||
93 | typedef struct _FsStream FsStream; | |
94 | typedef struct _FsStreamClass FsStreamClass; | |
95 | typedef struct _FsStreamPrivate FsStreamPrivate; | |
96 | ||
97 | ||
98 | /** | |
99 | * FsStreamClass: | |
100 | * @parent_class: Our parent | |
101 | * @add_remote_candidates: Set sthe remote candidates | |
102 | * @force_remote_candidates: Forces certain remote candidates | |
103 | * @set_remote_codecs: Sets the list of remote codecs | |
104 | * @add_id: Add a known id to be associated with this stream | |
105 | * @set_transmitter: Set the transmitter to use for this stream | |
106 | * | |
107 | * You must override add_remote_candidate in a subclass. | |
108 | * If you have to negotiate codecs, then you must override set_remote_codecs too | |
109 | */ | |
110 | ||
111 | struct _FsStreamClass | |
112 | { | |
113 | GstObjectClass parent_class; | |
114 | ||
115 | /*virtual functions */ | |
116 | gboolean (*add_remote_candidates) (FsStream *stream, | |
117 | GList *candidates, | |
118 | GError **error); | |
119 | ||
120 | gboolean (*force_remote_candidates) (FsStream *stream, | |
121 | GList *remote_candidates, | |
122 | GError **error); | |
123 | ||
124 | gboolean (*set_remote_codecs) (FsStream *stream, | |
125 | GList *remote_codecs, GError **error); | |
126 | ||
127 | void (*add_id) (FsStream *stream, | |
128 | guint id); | |
129 | ||
130 | gboolean (*set_transmitter) (FsStream *stream, | |
131 | const gchar *transmitter, | |
132 | GParameter *stream_transmitter_parameters, | |
133 | guint stream_transmitter_n_parameters, | |
134 | GError **error); | |
135 | ||
136 | /*< private >*/ | |
137 | gpointer _padding[8]; | |
138 | }; | |
139 | ||
140 | /** | |
141 | * FsStream: | |
142 | * | |
143 | * All members are private, access them using methods and properties | |
144 | */ | |
145 | struct _FsStream | |
146 | { | |
147 | GstObject parent; | |
148 | ||
149 | /*< private >*/ | |
150 | ||
151 | FsStreamPrivate *priv; | |
152 | ||
153 | gpointer _padding[8]; | |
154 | }; | |
155 | ||
156 | GType fs_stream_get_type (void); | |
157 | ||
158 | gboolean fs_stream_add_remote_candidates (FsStream *stream, | |
159 | GList *candidates, | |
160 | GError **error); | |
161 | ||
162 | gboolean fs_stream_force_remote_candidates (FsStream *stream, | |
163 | GList *remote_candidates, | |
164 | GError **error); | |
165 | ||
166 | gboolean fs_stream_set_remote_codecs (FsStream *stream, | |
167 | GList *remote_codecs, GError **error); | |
168 | ||
169 | void fs_stream_add_id (FsStream *stream, guint id); | |
170 | ||
171 | void fs_stream_emit_error (FsStream *stream, | |
172 | gint error_no, | |
173 | const gchar *error_msg); | |
174 | ||
175 | void fs_stream_emit_src_pad_added (FsStream *stream, | |
176 | GstPad *pad, | |
177 | FsCodec *codec); | |
178 | ||
179 | GstIterator *fs_stream_iterate_src_pads (FsStream *stream); | |
180 | ||
181 | gboolean fs_stream_set_transmitter (FsStream *stream, | |
182 | const gchar *transmitter, | |
183 | GParameter *stream_transmitter_parameters, | |
184 | guint stream_transmitter_n_parameters, | |
185 | GError **error); | |
186 | ||
187 | void fs_stream_destroy (FsStream *stream); | |
188 | ||
189 | G_END_DECLS | |
190 | ||
191 | #endif /* __FS_STREAM_H__ */ |
0 | /* | |
1 | * Farstream - Farstream Transmitter | |
2 | * | |
3 | * Copyright 2007 Collabora Ltd. | |
4 | * @author: Olivier Crete <olivier.crete@collabora.co.uk> | |
5 | * Copyright 2007 Nokia Corp. | |
6 | * | |
7 | * fs-transmitter.c - A Farstream Transmitter gobject (base implementation) | |
8 | * | |
9 | * This library is free software; you can redistribute it and/or | |
10 | * modify it under the terms of the GNU Lesser General Public | |
11 | * License as published by the Free Software Foundation; either | |
12 | * version 2.1 of the License, or (at your option) any later version. | |
13 | * | |
14 | * This library is distributed in the hope that it will be useful, | |
15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
17 | * Lesser General Public License for more details. | |
18 | * | |
19 | * You should have received a copy of the GNU Lesser General Public | |
20 | * License along with this library; if not, write to the Free Software | |
21 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA | |
22 | */ | |
23 | ||
24 | /** | |
25 | * SECTION:fs-transmitter | |
26 | * @short_description: A transmitter object linked to a session | |
27 | * | |
28 | * This object is the base implementation of a Farstream Transmitter. | |
29 | * It needs to be derived and implement by a Farstream transmitter. A | |
30 | * Farstream Transmitter provides a GStreamer network sink and source to be used | |
31 | * for the Farstream Session. It creates #FsStreamTransmitter objects which are | |
32 | * used to set the different per-stream properties | |
33 | * | |
34 | */ | |
35 | ||
36 | #ifdef HAVE_CONFIG_H | |
37 | #include "config.h" | |
38 | #endif | |
39 | ||
40 | #include "fs-transmitter.h" | |
41 | ||
42 | #include <gst/gst.h> | |
43 | ||
44 | #include "fs-marshal.h" | |
45 | #include "fs-plugin.h" | |
46 | #include "fs-conference.h" | |
47 | #include "fs-private.h" | |
48 | ||
49 | /* Signals */ | |
50 | enum | |
51 | { | |
52 | ERROR_SIGNAL, | |
53 | GET_RECVONLY_FILTER_SIGNAL, | |
54 | LAST_SIGNAL | |
55 | }; | |
56 | ||
57 | /* props */ | |
58 | enum | |
59 | { | |
60 | PROP_0, | |
61 | PROP_GST_SINK, | |
62 | PROP_GST_SRC, | |
63 | PROP_COMPONENTS, | |
64 | PROP_TYPE_OF_SERVICE | |
65 | }; | |
66 | ||
67 | /* | |
68 | struct _FsTransmitterPrivate | |
69 | { | |
70 | }; | |
71 | */ | |
72 | ||
73 | G_DEFINE_ABSTRACT_TYPE(FsTransmitter, fs_transmitter, GST_TYPE_OBJECT); | |
74 | ||
75 | #define FS_TRANSMITTER_GET_PRIVATE(o) \ | |
76 | (G_TYPE_INSTANCE_GET_PRIVATE ((o), FS_TYPE_TRANSMITTER, FsTransmitterPrivate)) | |
77 | ||
78 | static void fs_transmitter_get_property (GObject *object, | |
79 | guint prop_id, | |
80 | GValue *value, | |
81 | GParamSpec *pspec); | |
82 | static void fs_transmitter_set_property (GObject *object, | |
83 | guint prop_id, | |
84 | const GValue *value, | |
85 | GParamSpec *pspec); | |
86 | ||
87 | static guint signals[LAST_SIGNAL] = { 0 }; | |
88 | ||
89 | ||
90 | static void | |
91 | fs_transmitter_class_init (FsTransmitterClass *klass) | |
92 | { | |
93 | GObjectClass *gobject_class; | |
94 | ||
95 | _fs_conference_init_debug (); | |
96 | ||
97 | gobject_class = (GObjectClass *) klass; | |
98 | ||
99 | gobject_class->set_property = fs_transmitter_set_property; | |
100 | gobject_class->get_property = fs_transmitter_get_property; | |
101 | ||
102 | ||
103 | ||
104 | /** | |
105 | * FsTransmitter:gst-src: | |
106 | * | |
107 | * A network source #GstElement to be used by the #FsSession | |
108 | * This element MUST provide a source pad named "src%d" per component. | |
109 | * These pads number must start at 1 (the %d corresponds to the component | |
110 | * number). | |
111 | * These pads MUST be static pads. | |
112 | * | |
113 | */ | |
114 | g_object_class_install_property (gobject_class, | |
115 | PROP_GST_SRC, | |
116 | g_param_spec_object ("gst-src", | |
117 | "The network source", | |
118 | "A source GstElement to be used by a FsSession", | |
119 | GST_TYPE_ELEMENT, | |
120 | G_PARAM_READABLE | G_PARAM_STATIC_STRINGS)); | |
121 | ||
122 | /** | |
123 | * FsTransmitter:gst-sink: | |
124 | * | |
125 | * A network source #GstElement to be used by the #FsSession | |
126 | * These element's sink must have async=FALSE | |
127 | * This element MUST provide a pad named "sink\%d" per component. | |
128 | * These pads number must start at 1 (the \%d corresponds to the component | |
129 | * number). | |
130 | * These pads MUST be static pads. | |
131 | * | |
132 | */ | |
133 | g_object_class_install_property (gobject_class, | |
134 | PROP_GST_SINK, | |
135 | g_param_spec_object ("gst-sink", | |
136 | "The network source", | |
137 | "A source GstElement to be used by a FsSession", | |
138 | GST_TYPE_ELEMENT, | |
139 | G_PARAM_READABLE | G_PARAM_STATIC_STRINGS)); | |
140 | ||
141 | /** | |
142 | * FsTransmitter:components: | |
143 | * | |
144 | * The number of components to create | |
145 | */ | |
146 | g_object_class_install_property (gobject_class, | |
147 | PROP_COMPONENTS, | |
148 | g_param_spec_uint ("components", | |
149 | "Number of componnets", | |
150 | "The number of components to create", | |
151 | 1, 255, 1, | |
152 | G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); | |
153 | ||
154 | /** | |
155 | * FsTransmitter:tos: | |
156 | * | |
157 | * Sets the IP ToS field (and if possible the IPv6 TCLASS field | |
158 | */ | |
159 | g_object_class_install_property (gobject_class, | |
160 | PROP_TYPE_OF_SERVICE, | |
161 | g_param_spec_uint ("tos", | |
162 | "IP Type of Service", | |
163 | "The IP Type of Service to set on sent packets", | |
164 | 0, 255, 0, | |
165 | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); | |
166 | ||
167 | /** | |
168 | * FsTransmitter::error: | |
169 | * @self: #FsTransmitter that emitted the signal | |
170 | * @errorno: The number of the error | |
171 | * @error_msg: Error message to be displayed to user | |
172 | * | |
173 | * This signal is emitted in any error condition | |
174 | * | |
175 | */ | |
176 | signals[ERROR_SIGNAL] = g_signal_new ("error", | |
177 | G_TYPE_FROM_CLASS (klass), | |
178 | G_SIGNAL_RUN_LAST, | |
179 | 0, | |
180 | NULL, | |
181 | NULL, | |
182 | _fs_marshal_VOID__ENUM_STRING, | |
183 | G_TYPE_NONE, 2, FS_TYPE_ERROR, G_TYPE_STRING); | |
184 | ||
185 | /** | |
186 | * FsTransmitter::get-recvonly-filter | |
187 | * @self: #FsTransmitter that emitted the signal | |
188 | * @component: The component that the filter will be used for | |
189 | * | |
190 | * This signal is emitted when the transmitter wants to get a filter for | |
191 | * to use if sending is disabled. If you want to drop all buffers, just | |
192 | * don't listen to the signal. | |
193 | * | |
194 | * This element should have a "sending" property that can be changed with the | |
195 | * sending state of the stream. It should default to %TRUE. | |
196 | * | |
197 | * Returns: (transfer full) (allow-none): the #GstElement to use as the | |
198 | * filter, or %NULL to drop everything | |
199 | */ | |
200 | ||
201 | signals[GET_RECVONLY_FILTER_SIGNAL] = g_signal_new ("get-recvonly-filter", | |
202 | G_TYPE_FROM_CLASS (klass), | |
203 | G_SIGNAL_RUN_LAST, | |
204 | 0, | |
205 | NULL, | |
206 | NULL, | |
207 | _fs_marshal_OBJECT__UINT, | |
208 | GST_TYPE_ELEMENT, 1, G_TYPE_UINT); | |
209 | ||
210 | ||
211 | //g_type_class_add_private (klass, sizeof (FsTransmitterPrivate)); | |
212 | } | |
213 | ||
214 | static void | |
215 | fs_transmitter_init (FsTransmitter *self) | |
216 | { | |
217 | // self->priv = FS_TRANSMITTER_GET_PRIVATE (self); | |
218 | } | |
219 | ||
220 | static void | |
221 | fs_transmitter_get_property (GObject *object, | |
222 | guint prop_id, | |
223 | GValue *value, | |
224 | GParamSpec *pspec) | |
225 | { | |
226 | GST_WARNING ("Subclass %s of FsTransmitter does not override the %s property" | |
227 | " getter", | |
228 | G_OBJECT_TYPE_NAME(object), | |
229 | g_param_spec_get_name (pspec)); | |
230 | } | |
231 | ||
232 | static void | |
233 | fs_transmitter_set_property (GObject *object, | |
234 | guint prop_id, | |
235 | const GValue *value, | |
236 | GParamSpec *pspec) | |
237 | { | |
238 | GST_WARNING ("Subclass %s of FsTransmitter does not override the %s property" | |
239 | " setter", | |
240 | G_OBJECT_TYPE_NAME(object), | |
241 | g_param_spec_get_name (pspec)); | |
242 | } | |
243 | ||
244 | ||
245 | /** | |
246 | * fs_transmitter_new_stream_transmitter: | |
247 | * @transmitter: a #FsTranmitter | |
248 | * @participant: the #FsParticipant for which the #FsStream using this | |
249 | * new #FsStreamTransmitter is created | |
250 | * @n_parameters: The number of parameters to pass to the newly created | |
251 | * #FsStreamTransmitter | |
252 | * @parameters: an array of #GParameter | |
253 | * @error: location of a #GError, or NULL if no error occured | |
254 | * | |
255 | * This function will create a new #FsStreamTransmitter element for a | |
256 | * specific participant for this #FsTransmitter | |
257 | * | |
258 | * Returns: (transfer full): a new #FsStreamTransmitter, or NULL if there is an | |
259 | * error | |
260 | */ | |
261 | ||
262 | FsStreamTransmitter * | |
263 | fs_transmitter_new_stream_transmitter (FsTransmitter *transmitter, | |
264 | FsParticipant *participant, | |
265 | guint n_parameters, | |
266 | GParameter *parameters, | |
267 | GError **error) | |
268 | { | |
269 | FsTransmitterClass *klass; | |
270 | ||
271 | g_return_val_if_fail (transmitter, NULL); | |
272 | g_return_val_if_fail (FS_IS_TRANSMITTER (transmitter), NULL); | |
273 | klass = FS_TRANSMITTER_GET_CLASS (transmitter); | |
274 | g_return_val_if_fail (klass->new_stream_transmitter, NULL); | |
275 | ||
276 | ||
277 | return klass->new_stream_transmitter (transmitter, participant, | |
278 | n_parameters, parameters, error); | |
279 | ||
280 | return NULL; | |
281 | } | |
282 | ||
283 | /** | |
284 | * fs_transmitter_new: | |
285 | * @type: The type of transmitter to create | |
286 | * @components: The number of components to create | |
287 | * @tos: The Type of Service of the socket, max is 255 | |
288 | * @error: location of a #GError, or NULL if no error occured | |
289 | * | |
290 | * This function creates a new transmitter of the requested type. | |
291 | * It will load the appropriate plugin as required. | |
292 | * | |
293 | * Returns: a newly-created #FsTransmitter of the requested type | |
294 | * (or NULL if there is an error) | |
295 | */ | |
296 | ||
297 | FsTransmitter * | |
298 | fs_transmitter_new (const gchar *type, | |
299 | guint components, | |
300 | guint tos, | |
301 | GError **error) | |
302 | { | |
303 | FsTransmitter *self = NULL; | |
304 | ||
305 | g_return_val_if_fail (type != NULL, NULL); | |
306 | g_return_val_if_fail (tos <= 255, NULL); | |
307 | ||
308 | self = FS_TRANSMITTER (fs_plugin_create (type, "transmitter", error, | |
309 | "components", components, | |
310 | "tos", tos, | |
311 | NULL)); | |
312 | ||
313 | if (!self) | |
314 | return NULL; | |
315 | ||
316 | if (self->construction_error) { | |
317 | g_propagate_error(error, self->construction_error); | |
318 | g_object_unref (self); | |
319 | self = NULL; | |
320 | } | |
321 | ||
322 | return self; | |
323 | } | |
324 | ||
325 | /** | |
326 | * fs_transmitter_get_stream_transmitter_type: | |
327 | * @transmitter: A #FsTransmitter object | |
328 | * | |
329 | * This function returns the GObject type for the stream transmitter. | |
330 | * This is meant for bindings that need to introspect the type of arguments | |
331 | * that can be passed to the _new_stream_transmitter. | |
332 | * | |
333 | * Returns: the #GType | |
334 | */ | |
335 | ||
336 | GType | |
337 | fs_transmitter_get_stream_transmitter_type (FsTransmitter *transmitter) | |
338 | { | |
339 | FsTransmitterClass *klass; | |
340 | ||
341 | g_return_val_if_fail (transmitter, 0); | |
342 | g_return_val_if_fail (FS_IS_TRANSMITTER (transmitter), 0); | |
343 | klass = FS_TRANSMITTER_GET_CLASS (transmitter); | |
344 | g_return_val_if_fail (klass->get_stream_transmitter_type, 0); | |
345 | ||
346 | return klass->get_stream_transmitter_type (transmitter); | |
347 | } | |
348 | ||
349 | ||
350 | /** | |
351 | * fs_transmitter_emit_error: | |
352 | * @transmitter: #FsTransmitter on which to emit the error signal | |
353 | * @error_no: The number of the error | |
354 | * @error_msg: Error message to be displayed to user | |
355 | * | |
356 | * This function emit the "error" signal on a #FsTransmitter, it should | |
357 | * only be called by subclasses. | |
358 | */ | |
359 | void | |
360 | fs_transmitter_emit_error (FsTransmitter *transmitter, | |
361 | gint error_no, | |
362 | const gchar *error_msg) | |
363 | { | |
364 | g_signal_emit (transmitter, signals[ERROR_SIGNAL], 0, error_no, | |
365 | error_msg); | |
366 | } | |
367 | ||
368 | /** | |
369 | * fs_transmitter_list_available: | |
370 | * | |
371 | * Get the list of all available transmitters | |
372 | * | |
373 | * Returns: (transfer full): a newly allocated array of strings containing the | |
374 | * list of all available transmitters or %NULL if there are none. It should | |
375 | * be freed with g_strfreev(). | |
376 | */ | |
377 | ||
378 | char ** | |
379 | fs_transmitter_list_available (void) | |
380 | { | |
381 | return fs_plugin_list_available ("transmitter"); | |
382 | } | |
383 | ||
384 | /** | |
385 | * fs_transmitter_get_recvonly_filter: | |
386 | * @transmitter: A #FsTransmitter object | |
387 | * @component: The component to get the filter for | |
388 | * | |
389 | * Get the filter to add on the send pipeline if sending is disabled. | |
390 | * | |
391 | * Only for use by subclasses. | |
392 | * | |
393 | * Returns: (transfer full) (allow-none): a #GstElement to use as the filter or | |
394 | * %NULL | |
395 | */ | |
396 | ||
397 | GstElement * | |
398 | fs_transmitter_get_recvonly_filter (FsTransmitter *transmitter, | |
399 | guint component) | |
400 | { | |
401 | GstElement *element = NULL; | |
402 | ||
403 | g_signal_emit (transmitter, signals[GET_RECVONLY_FILTER_SIGNAL], 0, component, | |
404 | &element); | |
405 | ||
406 | return element; | |
407 | } |
0 | /* | |
1 | * Farstream - Farstream Transmitter | |
2 | * | |
3 | * Copyright 2007 Collabora Ltd. | |
4 | * @author: Olivier Crete <olivier.crete@collabora.co.uk> | |
5 | * Copyright 2007 Nokia Corp. | |
6 | * | |
7 | * fs-transmitter.h - A Farstream Transmitter (base implementation) | |
8 | * | |
9 | * This library is free software; you can redistribute it and/or | |
10 | * modify it under the terms of the GNU Lesser General Public | |
11 | * License as published by the Free Software Foundation; either | |
12 | * version 2.1 of the License, or (at your option) any later version. | |
13 | * | |
14 | * This library is distributed in the hope that it will be useful, | |
15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
17 | * Lesser General Public License for more details. | |
18 | * | |
19 | * You should have received a copy of the GNU Lesser General Public | |
20 | * License along with this library; if not, write to the Free Software | |
21 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA | |
22 | */ | |
23 | ||
24 | #ifndef __FS_TRANSMITTER_H__ | |
25 | #define __FS_TRANSMITTER_H__ | |
26 | ||
27 | #include <gst/gst.h> | |
28 | ||
29 | #include <farstream/fs-participant.h> | |
30 | #include <farstream/fs-session.h> | |
31 | #include <farstream/fs-stream-transmitter.h> | |
32 | ||
33 | G_BEGIN_DECLS | |
34 | ||
35 | /* TYPE MACROS */ | |
36 | #define FS_TYPE_TRANSMITTER \ | |
37 | (fs_transmitter_get_type ()) | |
38 | #define FS_TRANSMITTER(obj) \ | |
39 | (G_TYPE_CHECK_INSTANCE_CAST((obj), FS_TYPE_TRANSMITTER, FsTransmitter)) | |
40 | #define FS_TRANSMITTER_CLASS(klass) \ | |
41 | (G_TYPE_CHECK_CLASS_CAST((klass), FS_TYPE_TRANSMITTER, FsTransmitterClass)) | |
42 | #define FS_IS_TRANSMITTER(obj) \ | |
43 | (G_TYPE_CHECK_INSTANCE_TYPE((obj), FS_TYPE_TRANSMITTER)) | |
44 | #define FS_IS_TRANSMITTER_CLASS(klass) \ | |
45 | (G_TYPE_CHECK_CLASS_TYPE((klass), FS_TYPE_TRANSMITTER)) | |
46 | #define FS_TRANSMITTER_GET_CLASS(obj) \ | |
47 | (G_TYPE_INSTANCE_GET_CLASS ((obj), FS_TYPE_TRANSMITTER, FsTransmitterClass)) | |
48 | #define FS_TRANSMITTER_CAST(obj) ((FsTransmitter *) (obj)) | |
49 | ||
50 | typedef struct _FsTransmitter FsTransmitter; | |
51 | typedef struct _FsTransmitterClass FsTransmitterClass; | |
52 | typedef struct _FsTransmitterPrivate FsTransmitterPrivate; | |
53 | ||
54 | /** | |
55 | * FsTransmitterClass: | |
56 | * @parent_class: Our parent | |
57 | * @new_stream_transmitter: Creates a new #FsStreamTransmitter | |
58 | * @get_stream_transmitter_type: Returns the #GType of the stream transmitter | |
59 | * created by this class (useful for bindings) | |
60 | * | |
61 | * You must override both methods in a subclass. | |
62 | */ | |
63 | ||
64 | struct _FsTransmitterClass | |
65 | { | |
66 | GstObjectClass parent_class; | |
67 | ||
68 | /*virtual functions */ | |
69 | FsStreamTransmitter *(*new_stream_transmitter) (FsTransmitter *transmitter, | |
70 | FsParticipant *participant, | |
71 | guint n_parameters, | |
72 | GParameter *parameters, | |
73 | GError **error); | |
74 | GType (*get_stream_transmitter_type) (FsTransmitter *transmitter); | |
75 | ||
76 | /*< private >*/ | |
77 | gpointer _padding[8]; | |
78 | }; | |
79 | ||
80 | /** | |
81 | * FsTransmitter: | |
82 | * | |
83 | * All members are private, access them using methods and properties | |
84 | */ | |
85 | struct _FsTransmitter | |
86 | { | |
87 | GstObject parent; | |
88 | ||
89 | /*< private >*/ | |
90 | FsTransmitterPrivate *priv; | |
91 | ||
92 | /* This parameter should only be set by the construction methods | |
93 | * of the subclasses | |
94 | */ | |
95 | GError *construction_error; | |
96 | ||
97 | gpointer _padding[8]; | |
98 | }; | |
99 | ||
100 | GType fs_transmitter_get_type (void); | |
101 | ||
102 | FsStreamTransmitter *fs_transmitter_new_stream_transmitter ( | |
103 | FsTransmitter *transmitter, FsParticipant *participant, | |
104 | guint n_parameters, GParameter *parameters, GError **error); | |
105 | ||
106 | FsTransmitter *fs_transmitter_new (const gchar *type, | |
107 | guint components, | |
108 | guint tos, | |
109 | GError **error); | |
110 | ||
111 | GType fs_transmitter_get_stream_transmitter_type (FsTransmitter *transmitter); | |
112 | ||
113 | void fs_transmitter_emit_error (FsTransmitter *transmitter, | |
114 | gint error_no, | |
115 | const gchar *error_msg); | |
116 | ||
117 | char **fs_transmitter_list_available (void); | |
118 | ||
119 | GstElement * | |
120 | fs_transmitter_get_recvonly_filter (FsTransmitter *transmitter, | |
121 | guint component); | |
122 | ||
123 | G_END_DECLS | |
124 | ||
125 | #endif /* __FS_TRANSMITTER_H__ */ |
0 | /* | |
1 | * Farstream - Miscellaneous useful functions | |
2 | * | |
3 | * Copyright 2011 Collabora Ltd. | |
4 | * @author: Olivier Crete <olivier.crete@collabora.co.uk> | |
5 | * Copyright 2011 Nokia Corp. | |
6 | * | |
7 | * This library is free software; you can redistribute it and/or | |
8 | * modify it under the terms of the GNU Lesser General Public | |
9 | * License as published by the Free Software Foundation; either | |
10 | * version 2.1 of the License, or (at your option) any later version. | |
11 | * | |
12 | * This library is distributed in the hope that it will be useful, | |
13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
15 | * Lesser General Public License for more details. | |
16 | * | |
17 | * You should have received a copy of the GNU Lesser General Public | |
18 | * License along with this library; if not, write to the Free Software | |
19 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA | |
20 | */ | |
21 | ||
22 | #ifdef HAVE_CONFIG_H | |
23 | # include <config.h> | |
24 | #endif | |
25 | ||
26 | #include "fs-utils.h" | |
27 | ||
28 | #include <string.h> | |
29 | ||
30 | #include "fs-rtp.h" | |
31 | ||
32 | /** | |
33 | * SECTION:fs-utils | |
34 | * @short_description: Miscellaneous useful functions | |
35 | */ | |
36 | ||
37 | static GList * | |
38 | load_default_codec_preferences_from_path (const gchar *element_name, | |
39 | const gchar *path) | |
40 | { | |
41 | GList *codec_prefs = NULL; | |
42 | gchar *filename; | |
43 | ||
44 | filename = g_build_filename (path, PACKAGE, FS_MAJORMINOR, element_name, | |
45 | "default-codec-preferences", NULL); | |
46 | codec_prefs = fs_codec_list_from_keyfile (filename, NULL); | |
47 | g_free (filename); | |
48 | ||
49 | return codec_prefs; | |
50 | } | |
51 | ||
52 | static const gchar * | |
53 | factory_name_from_element (GstElement *element) | |
54 | { | |
55 | GstElementFactory *factory = gst_element_get_factory (element); | |
56 | ||
57 | if (factory) | |
58 | return gst_plugin_feature_get_name (GST_PLUGIN_FEATURE (factory)); | |
59 | else | |
60 | return NULL; | |
61 | } | |
62 | ||
63 | /** | |
64 | * fs_utils_get_default_codec_preferences: | |
65 | * @element: Element for which to fetch default codec preferences | |
66 | * | |
67 | * These default codec preferences should work with the elements that are | |
68 | * available in the main GStreamer element repositories. | |
69 | * They should be suitable for standards based protocols like SIP or XMPP. | |
70 | * | |
71 | * Returns: (element-type FsCodec) (transfer full): | |
72 | * The default codec preferences for this plugin. | |
73 | * This #GList should be freed with fs_codec_list_destroy() | |
74 | */ | |
75 | GList * | |
76 | fs_utils_get_default_codec_preferences (GstElement *element) | |
77 | { | |
78 | const gchar * const * system_data_dirs = g_get_system_data_dirs (); | |
79 | GList *codec_prefs = NULL; | |
80 | guint i; | |
81 | const gchar *factory_name = factory_name_from_element (element); | |
82 | ||
83 | if (!factory_name) | |
84 | return NULL; | |
85 | ||
86 | codec_prefs = load_default_codec_preferences_from_path (factory_name, | |
87 | g_get_user_data_dir ()); | |
88 | if (codec_prefs) | |
89 | return codec_prefs; | |
90 | ||
91 | for (i = 0; system_data_dirs[i]; i++) | |
92 | { | |
93 | codec_prefs = load_default_codec_preferences_from_path (factory_name, | |
94 | system_data_dirs[i]); | |
95 | if (codec_prefs) | |
96 | return codec_prefs; | |
97 | } | |
98 | ||
99 | return NULL; | |
100 | } | |
101 | ||
102 | /** | |
103 | * fs_utils_get_default_element_properties: (skip): | |
104 | * @element: Element for which to fetch default element properties | |
105 | * | |
106 | * This function produces a #GKeyFile that can be fed to | |
107 | * fs_element_added_notifier_set_properties_from_keyfile(). If no | |
108 | * default properties have been found, it will return %NULL. | |
109 | * | |
110 | * Returns: a #GKeyFile containing the default element | |
111 | * properties for this element or %NULL if no properties were found. | |
112 | * Caller must free the #GKeyFile when he is done. | |
113 | */ | |
114 | ||
115 | GKeyFile * | |
116 | fs_utils_get_default_element_properties (GstElement *element) | |
117 | { | |
118 | gboolean file_loaded; | |
119 | GKeyFile *keyfile = g_key_file_new (); | |
120 | gchar *filename; | |
121 | const gchar *factory_name = factory_name_from_element (element); | |
122 | ||
123 | filename = g_build_filename (PACKAGE, FS_MAJORMINOR, factory_name, | |
124 | "default-element-properties", NULL); | |
125 | file_loaded = g_key_file_load_from_data_dirs (keyfile, filename, NULL, | |
126 | G_KEY_FILE_NONE, NULL); | |
127 | g_free (filename); | |
128 | ||
129 | if (file_loaded) | |
130 | { | |
131 | return keyfile; | |
132 | } | |
133 | else | |
134 | { | |
135 | g_key_file_free (keyfile); | |
136 | return NULL; | |
137 | } | |
138 | } | |
139 | ||
140 | /** | |
141 | * fs_utils_set_bitrate: | |
142 | * @element: The #GstElement | |
143 | * @bitrate: The bitrate in bits/sec | |
144 | * | |
145 | * This allows setting the bitrate on all elements that have a "bitrate" | |
146 | * property without having to know the type or of the unit used by that element. | |
147 | * | |
148 | * This will be obsolete in 0.11 (when all elements use bit/sec for the | |
149 | * "bitrate" property. | |
150 | */ | |
151 | ||
152 | void | |
153 | fs_utils_set_bitrate (GstElement *element, glong bitrate) | |
154 | { | |
155 | GParamSpec *spec; | |
156 | const char *elements_in_kbps[] = { "lamemp3enc", "lame", "x264enc", "twolame", | |
157 | "mpeg2enc", NULL | |
158 | }; | |
159 | int i; | |
160 | GstElementFactory *factory; | |
161 | const gchar *factory_name = NULL; | |
162 | ||
163 | g_return_if_fail (GST_IS_ELEMENT (element)); | |
164 | ||
165 | spec = g_object_class_find_property (G_OBJECT_GET_CLASS (element), "bitrate"); | |
166 | g_return_if_fail (spec != NULL); | |
167 | ||
168 | factory = gst_element_get_factory (element); | |
169 | if (factory) | |
170 | factory_name = gst_plugin_feature_get_name (GST_PLUGIN_FEATURE (factory)); | |
171 | ||
172 | /* divide by 1000 for elements that are known to use kbs */ | |
173 | for (i = 0; elements_in_kbps[i]; i++) | |
174 | if (factory_name && !strcmp (factory_name, elements_in_kbps[i])) | |
175 | { | |
176 | bitrate /= 1000; | |
177 | break; | |
178 | } | |
179 | ||
180 | if (G_PARAM_SPEC_TYPE (spec) == G_TYPE_LONG) | |
181 | { | |
182 | g_object_set (element, "bitrate", (glong) CLAMP (bitrate, | |
183 | G_PARAM_SPEC_LONG (spec)->minimum, | |
184 | G_PARAM_SPEC_LONG (spec)->maximum), NULL); | |
185 | } | |
186 | else if (G_PARAM_SPEC_VALUE_TYPE (spec) == G_TYPE_ULONG) | |
187 | { | |
188 | g_object_set (element, "bitrate", (gulong) CLAMP (bitrate, | |
189 | G_PARAM_SPEC_ULONG (spec)->minimum, | |
190 | G_PARAM_SPEC_ULONG (spec)->maximum), NULL); | |
191 | } | |
192 | else if (G_PARAM_SPEC_VALUE_TYPE (spec) == G_TYPE_INT) | |
193 | { | |
194 | gint tmp = MIN (bitrate, G_MAXINT); | |
195 | ||
196 | g_object_set (element, "bitrate", (gint) CLAMP (tmp, | |
197 | G_PARAM_SPEC_INT (spec)->minimum, | |
198 | G_PARAM_SPEC_INT (spec)->maximum), NULL); | |
199 | } | |
200 | else if (G_PARAM_SPEC_VALUE_TYPE (spec) == G_TYPE_UINT) | |
201 | { | |
202 | guint tmp = MIN (bitrate, G_MAXUINT); | |
203 | ||
204 | g_object_set (element, "bitrate", (guint) CLAMP (tmp, | |
205 | G_PARAM_SPEC_UINT (spec)->minimum, | |
206 | G_PARAM_SPEC_UINT (spec)->maximum), NULL); | |
207 | } | |
208 | else | |
209 | { | |
210 | g_warning ("bitrate parameter of unknown type"); | |
211 | } | |
212 | } | |
213 | ||
214 | static GList * | |
215 | load_default_rtp_hdrext_preferences_from_path (const gchar *element_name, | |
216 | const gchar *path, FsMediaType media_type) | |
217 | { | |
218 | GList *rtp_hdrext_prefs = NULL; | |
219 | gchar *filename; | |
220 | ||
221 | filename = g_build_filename (path, PACKAGE, FS_MAJORMINOR, element_name, | |
222 | "default-codec-preferences", NULL); | |
223 | rtp_hdrext_prefs = fs_rtp_header_extension_list_from_keyfile (filename, | |
224 | media_type, NULL); | |
225 | g_free (filename); | |
226 | ||
227 | return rtp_hdrext_prefs; | |
228 | } | |
229 | ||
230 | /** | |
231 | * fs_utils_get_default_rtp_header_extension_preferences | |
232 | * @element: Element for which to fetch default RTP Header Extension preferences | |
233 | * @media_type: The #FsMediaType for which to get default RTP Header Extension | |
234 | * preferences | |
235 | * | |
236 | * These default rtp header extension preferences should work with the elements | |
237 | * that are available in the main GStreamer element repositories. | |
238 | * They should be suitable for standards based protocols like SIP or XMPP. | |
239 | * | |
240 | * Returns: (element-type FsCodec) (transfer full): The default rtp | |
241 | * header extension preferences for this plugin, this #GList should be | |
242 | * freed with fs_codec_list_destroy() | |
243 | */ | |
244 | GList * | |
245 | fs_utils_get_default_rtp_header_extension_preferences (GstElement *element, | |
246 | FsMediaType media_type) | |
247 | { | |
248 | const gchar * const * system_data_dirs = g_get_system_data_dirs (); | |
249 | GList *rtp_hdrext_prefs = NULL; | |
250 | guint i; | |
251 | const gchar *factory_name = factory_name_from_element (element); | |
252 | ||
253 | if (!factory_name) | |
254 | return NULL; | |
255 | ||
256 | rtp_hdrext_prefs = load_default_rtp_hdrext_preferences_from_path ( | |
257 | factory_name, g_get_user_data_dir (), media_type); | |
258 | if (rtp_hdrext_prefs) | |
259 | return rtp_hdrext_prefs; | |
260 | ||
261 | for (i = 0; system_data_dirs[i]; i++) | |
262 | { | |
263 | rtp_hdrext_prefs = load_default_rtp_hdrext_preferences_from_path ( | |
264 | factory_name, system_data_dirs[i], media_type); | |
265 | if (rtp_hdrext_prefs) | |
266 | return rtp_hdrext_prefs; | |
267 | } | |
268 | ||
269 | return NULL; | |
270 | } |
0 | /* | |
1 | * Farstream - Miscellaneous useful functions | |
2 | * | |
3 | * Copyright 2011 Collabora Ltd. | |
4 | * @author: Olivier Crete <olivier.crete@collabora.co.uk> | |
5 | * Copyright 2011 Nokia Corp. | |
6 | * | |
7 | * This library is free software; you can redistribute it and/or | |
8 | * modify it under the terms of the GNU Lesser General Public | |
9 | * License as published by the Free Software Foundation; either | |
10 | * version 2.1 of the License, or (at your option) any later version. | |
11 | * | |
12 | * This library is distributed in the hope that it will be useful, | |
13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
15 | * Lesser General Public License for more details. | |
16 | * | |
17 | * You should have received a copy of the GNU Lesser General Public | |
18 | * License along with this library; if not, write to the Free Software | |
19 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA | |
20 | */ | |
21 | ||
22 | ||
23 | ||
24 | #ifndef __FS_UTILS_H__ | |
25 | #define __FS_UTILS_H__ | |
26 | ||
27 | #include <gst/gst.h> | |
28 | ||
29 | #include <farstream/fs-codec.h> | |
30 | ||
31 | G_BEGIN_DECLS | |
32 | ||
33 | GList *fs_utils_get_default_codec_preferences (GstElement *element); | |
34 | ||
35 | GKeyFile *fs_utils_get_default_element_properties (GstElement *element); | |
36 | ||
37 | void fs_utils_set_bitrate (GstElement *element, glong bitrate); | |
38 | ||
39 | GList *fs_utils_get_default_rtp_header_extension_preferences ( | |
40 | GstElement *element, FsMediaType media_type); | |
41 | ||
42 | G_END_DECLS | |
43 | ||
44 | #endif /* __FS_UTILS_H__ */ |
37 | 37 | libfsmsnconference_la_LDFLAGS = $(GST_PLUGIN_LDFLAGS) |
38 | 38 | libfsmsnconference_la_LIBADD = \ |
39 | 39 | libfsmsnconference-convenience.la \ |
40 | $(top_builddir)/gst-libs/gst/farstream/libfarstream-0.10.la \ | |
40 | $(top_builddir)/farstream/libfarstream-0.10.la \ | |
41 | 41 | $(FS_LIBS) \ |
42 | 42 | $(GST_BASE_LIBS) \ |
43 | 43 | $(GST_LIBS) \ |
26 | 26 | #ifndef __FS_MSN_CONFERENCE_H__ |
27 | 27 | #define __FS_MSN_CONFERENCE_H__ |
28 | 28 | |
29 | #include <gst/farstream/fs-conference.h> | |
29 | #include <farstream/fs-conference.h> | |
30 | 30 | |
31 | 31 | G_BEGIN_DECLS |
32 | 32 |
23 | 23 | #ifndef __FS_MSN_PARTICIPANT_H__ |
24 | 24 | #define __FS_MSN_PARTICIPANT_H__ |
25 | 25 | |
26 | #include <gst/farstream/fs-participant.h> | |
26 | #include <farstream/fs-participant.h> | |
27 | 27 | |
28 | 28 | G_BEGIN_DECLS |
29 | 29 |
27 | 27 | |
28 | 28 | #include <gst/gst.h> |
29 | 29 | |
30 | #include <gst/farstream/fs-session.h> | |
30 | #include <farstream/fs-session.h> | |
31 | 31 | |
32 | 32 | #include "fs-msn-conference.h" |
33 | 33 |
25 | 25 | #ifndef __FS_MSN_STREAM_H__ |
26 | 26 | #define __FS_MSN_STREAM_H__ |
27 | 27 | |
28 | #include <gst/farstream/fs-stream.h> | |
28 | #include <farstream/fs-stream.h> | |
29 | 29 | |
30 | 30 | #include "fs-msn-participant.h" |
31 | 31 | #include "fs-msn-session.h" |
30 | 30 | libfsrawconference_la_LDFLAGS = $(GST_PLUGIN_LDFLAGS) |
31 | 31 | libfsrawconference_la_LIBADD = \ |
32 | 32 | libfsrawconference-convenience.la \ |
33 | $(top_builddir)/gst-libs/gst/farstream/libfarstream-0.10.la \ | |
33 | $(top_builddir)/farstream/libfarstream-0.10.la \ | |
34 | 34 | $(FS_LIBS) \ |
35 | 35 | $(GST_BASE_LIBS) \ |
36 | 36 | $(GST_LIBS) |
26 | 26 | #ifndef __FS_RAW_CONFERENCE_H__ |
27 | 27 | #define __FS_RAW_CONFERENCE_H__ |
28 | 28 | |
29 | #include <gst/farstream/fs-conference.h> | |
29 | #include <farstream/fs-conference.h> | |
30 | 30 | |
31 | 31 | G_BEGIN_DECLS |
32 | 32 |
25 | 25 | #ifndef __FS_RAW_PARTICIPANT_H__ |
26 | 26 | #define __FS_RAW_PARTICIPANT_H__ |
27 | 27 | |
28 | #include <gst/farstream/fs-participant.h> | |
28 | #include <farstream/fs-participant.h> | |
29 | 29 | |
30 | 30 | G_BEGIN_DECLS |
31 | 31 |
45 | 45 | #include <string.h> |
46 | 46 | |
47 | 47 | #include <gst/gst.h> |
48 | #include <gst/farstream/fs-transmitter.h> | |
48 | #include <farstream/fs-transmitter.h> | |
49 | 49 | |
50 | 50 | #include "fs-raw-stream.h" |
51 | 51 | #include "fs-raw-participant.h" |
28 | 28 | |
29 | 29 | #include <gst/gst.h> |
30 | 30 | |
31 | #include <gst/farstream/fs-session.h> | |
31 | #include <farstream/fs-session.h> | |
32 | 32 | |
33 | 33 | #include "fs-raw-conference.h" |
34 | 34 |
26 | 26 | #ifndef __FS_RAW_STREAM_H__ |
27 | 27 | #define __FS_RAW_STREAM_H__ |
28 | 28 | |
29 | #include <gst/farstream/fs-stream.h> | |
30 | #include <gst/farstream/fs-stream-transmitter.h> | |
29 | #include <farstream/fs-stream.h> | |
30 | #include <farstream/fs-stream-transmitter.h> | |
31 | 31 | |
32 | 32 | #include "fs-raw-participant.h" |
33 | 33 | #include "fs-raw-session.h" |
61 | 61 | |
62 | 62 | libfsrtpconference_la_LIBADD = \ |
63 | 63 | libfsrtpconference-convenience.la \ |
64 | $(top_builddir)/gst-libs/gst/farstream/libfarstream-0.10.la \ | |
64 | $(top_builddir)/farstream/libfarstream-0.10.la \ | |
65 | 65 | $(FS_LIBS) \ |
66 | 66 | $(GST_PLUGINS_BASE_LIBS) \ |
67 | 67 | $(GST_LIBS) \ |
34 | 34 | #endif |
35 | 35 | #include <stdio.h> |
36 | 36 | |
37 | #include <gst/farstream/fs-conference.h> | |
37 | #include <farstream/fs-conference.h> | |
38 | 38 | |
39 | 39 | #include "fs-rtp-conference.h" |
40 | 40 |
27 | 27 | |
28 | 28 | #include "fs-rtp-codec-negotiation.h" |
29 | 29 | |
30 | #include <gst/farstream/fs-rtp.h> | |
30 | #include <farstream/fs-rtp.h> | |
31 | 31 | |
32 | 32 | #include <string.h> |
33 | 33 |
26 | 26 | #include <glib.h> |
27 | 27 | #include <gst/gst.h> |
28 | 28 | |
29 | #include <gst/farstream/fs-codec.h> | |
29 | #include <farstream/fs-codec.h> | |
30 | 30 | |
31 | 31 | G_BEGIN_DECLS |
32 | 32 |
25 | 25 | #ifndef __FS_RTP_CONFERENCE_H__ |
26 | 26 | #define __FS_RTP_CONFERENCE_H__ |
27 | 27 | |
28 | #include <gst/farstream/fs-conference.h> | |
28 | #include <farstream/fs-conference.h> | |
29 | 29 | |
30 | 30 | G_BEGIN_DECLS |
31 | 31 |
35 | 35 | |
36 | 36 | #include <string.h> |
37 | 37 | |
38 | #include <gst/farstream/fs-conference.h> | |
38 | #include <farstream/fs-conference.h> | |
39 | 39 | |
40 | 40 | #include "fs-rtp-conference.h" |
41 | 41 | #include "fs-rtp-codec-cache.h" |
26 | 26 | |
27 | 27 | #include <gst/gst.h> |
28 | 28 | |
29 | #include <gst/farstream/fs-codec.h> | |
29 | #include <farstream/fs-codec.h> | |
30 | 30 | |
31 | 31 | G_BEGIN_DECLS |
32 | 32 |
28 | 28 | |
29 | 29 | #include "fs-rtp-dtmf-event-source.h" |
30 | 30 | |
31 | #include <gst/farstream/fs-conference.h> | |
31 | #include <farstream/fs-conference.h> | |
32 | 32 | |
33 | 33 | #include "fs-rtp-conference.h" |
34 | 34 | #include "fs-rtp-discover-codecs.h" |
28 | 28 | |
29 | 29 | #include "fs-rtp-dtmf-sound-source.h" |
30 | 30 | |
31 | #include <gst/farstream/fs-conference.h> | |
31 | #include <farstream/fs-conference.h> | |
32 | 32 | |
33 | 33 | #include "fs-rtp-conference.h" |
34 | 34 | #include "fs-rtp-discover-codecs.h" |
26 | 26 | |
27 | 27 | #include <gst/gst.h> |
28 | 28 | |
29 | #include <gst/farstream/fs-codec.h> | |
29 | #include <farstream/fs-codec.h> | |
30 | 30 | |
31 | 31 | G_BEGIN_DECLS |
32 | 32 |
24 | 24 | #ifndef __FS_RTP_PARTICIPANT_H__ |
25 | 25 | #define __FS_RTP_PARTICIPANT_H__ |
26 | 26 | |
27 | #include <gst/farstream/fs-participant.h> | |
27 | #include <farstream/fs-participant.h> | |
28 | 28 | |
29 | 29 | G_BEGIN_DECLS |
30 | 30 |
64 | 64 | #include <gst/rtp/gstrtpbuffer.h> |
65 | 65 | #include <gst/rtp/gstrtcpbuffer.h> |
66 | 66 | |
67 | #include <gst/farstream/fs-transmitter.h> | |
68 | #include "gst/farstream/fs-utils.h" | |
69 | #include <gst/farstream/fs-rtp.h> | |
67 | #include <farstream/fs-transmitter.h> | |
68 | #include "farstream/fs-utils.h" | |
69 | #include <farstream/fs-rtp.h> | |
70 | 70 | |
71 | 71 | #include "fs-rtp-bitrate-adapter.h" |
72 | 72 | #include "fs-rtp-stream.h" |
26 | 26 | |
27 | 27 | #include <gst/gst.h> |
28 | 28 | |
29 | #include <gst/farstream/fs-session.h> | |
29 | #include <farstream/fs-session.h> | |
30 | 30 | |
31 | 31 | #include "fs-rtp-conference.h" |
32 | 32 |
28 | 28 | |
29 | 29 | #include "fs-rtp-special-source.h" |
30 | 30 | |
31 | #include <gst/farstream/fs-conference.h> | |
31 | #include <farstream/fs-conference.h> | |
32 | 32 | |
33 | 33 | #include "fs-rtp-conference.h" |
34 | 34 | #include "fs-rtp-codec-negotiation.h" |
27 | 27 | |
28 | 28 | #include <gst/gst.h> |
29 | 29 | |
30 | #include <gst/farstream/fs-session.h> | |
30 | #include <farstream/fs-session.h> | |
31 | 31 | |
32 | 32 | G_BEGIN_DECLS |
33 | 33 |
38 | 38 | |
39 | 39 | #include <gst/gst.h> |
40 | 40 | |
41 | #include <gst/farstream/fs-rtp.h> | |
41 | #include <farstream/fs-rtp.h> | |
42 | 42 | |
43 | 43 | #include "fs-rtp-marshal.h" |
44 | 44 |
24 | 24 | #ifndef __FS_RTP_STREAM_H__ |
25 | 25 | #define __FS_RTP_STREAM_H__ |
26 | 26 | |
27 | #include <gst/farstream/fs-stream.h> | |
28 | #include <gst/farstream/fs-stream-transmitter.h> | |
27 | #include <farstream/fs-stream.h> | |
28 | #include <farstream/fs-stream-transmitter.h> | |
29 | 29 | |
30 | 30 | #include "fs-rtp-participant.h" |
31 | 31 | #include "fs-rtp-session.h" |
28 | 28 | |
29 | 29 | #include "fs-rtp-substream.h" |
30 | 30 | |
31 | #include <gst/farstream/fs-stream.h> | |
32 | #include <gst/farstream/fs-session.h> | |
31 | #include <farstream/fs-stream.h> | |
32 | #include <farstream/fs-session.h> | |
33 | 33 | |
34 | 34 | #include "fs-rtp-stream.h" |
35 | 35 | #include "fs-rtp-marshal.h" |
30 | 30 | #include <string.h> |
31 | 31 | |
32 | 32 | #include "fs-rtp-packet-modder.h" |
33 | #include "gst/farstream/fs-rtp.h" | |
33 | #include "farstream/fs-rtp.h" | |
34 | 34 | #include "fs-rtp-codec-negotiation.h" |
35 | 35 | |
36 | 36 | #include <gst/rtp/gstrtpbuffer.h> |
0 | # The interfaces directory has to be built before the others, | |
1 | # otherwise some generated header files will be missing for the | |
2 | # plugins in the other directories. | |
3 | # Also, the tag directory has to be built before the cdda directory. | |
4 | SUBDIRS = \ | |
5 | farstream | |
6 | ||
7 | noinst_HEADERS = |
0 | libfarstreamincludedir = $(includedir)/gstreamer-@GST_MAJORMINOR@/gst/farstream | |
1 | ||
2 | libfarstreaminclude_HEADERS = \ | |
3 | fs-candidate.h \ | |
4 | fs-codec.h \ | |
5 | fs-participant.h \ | |
6 | fs-session.h \ | |
7 | fs-stream.h \ | |
8 | fs-conference.h \ | |
9 | fs-transmitter.h \ | |
10 | fs-stream-transmitter.h \ | |
11 | fs-plugin.h \ | |
12 | fs-element-added-notifier.h \ | |
13 | fs-utils.h \ | |
14 | fs-rtp.h | |
15 | ||
16 | nodist_libfarstreaminclude_HEADERS = \ | |
17 | fs-enumtypes.h | |
18 | ||
19 | ||
20 | lib_LTLIBRARIES = libfarstream-@GST_MAJORMINOR@.la | |
21 | ||
22 | BUILT_SOURCES = \ | |
23 | $(nodist_libfarstream_@GST_MAJORMINOR@_la_SOURCES) \ | |
24 | $(nodist_libfarstreaminclude_HEADERS) | |
25 | ||
26 | CLEANFILES = $(BUILT_SOURCES) fs-marshal.list | |
27 | ||
28 | libfarstream_@GST_MAJORMINOR@_la_SOURCES = \ | |
29 | fs-candidate.c \ | |
30 | fs-codec.c \ | |
31 | fs-participant.c \ | |
32 | fs-session.c \ | |
33 | fs-stream.c \ | |
34 | fs-conference.c \ | |
35 | fs-transmitter.c \ | |
36 | fs-stream-transmitter.c \ | |
37 | fs-plugin.c \ | |
38 | fs-element-added-notifier.c \ | |
39 | fs-utils.c \ | |
40 | fs-rtp.c \ | |
41 | fs-private.h | |
42 | ||
43 | nodist_libfarstream_@GST_MAJORMINOR@_la_SOURCES = \ | |
44 | fs-marshal.c \ | |
45 | fs-marshal.h \ | |
46 | fs-enumtypes.c | |
47 | ||
48 | ||
49 | fs-marshal.list: $(libfarstream_@GST_MAJORMINOR@_la_SOURCES) Makefile.am | |
50 | $(AM_V_GEN) ( cd $(srcdir) && \ | |
51 | sed -n -e 's/.*_fs_marshal_\([[:upper:][:digit:]]*__[[:upper:][:digit:]_]*\).*/\1/p' \ | |
52 | $(libfarstream_@GST_MAJORMINOR@_la_SOURCES) ) \ | |
53 | | sed -e 's/__/:/' -e 'y/_/,/' | sort -u > $@.tmp | |
54 | @if cmp -s $@.tmp $@; then \ | |
55 | rm $@.tmp; \ | |
56 | touch $@; \ | |
57 | else \ | |
58 | mv $@.tmp $@; \ | |
59 | fi | |
60 | ||
61 | libfarstream_@GST_MAJORMINOR@_la_CFLAGS = \ | |
62 | $(FS_INTERNAL_CFLAGS) $(FS_CFLAGS) \ | |
63 | $(GST_PLUGINS_BASE_CFLAGS) \ | |
64 | $(GST_BASE_CFLAGS) \ | |
65 | $(GST_CFLAGS) | |
66 | libfarstream_@GST_MAJORMINOR@_la_LIBADD = \ | |
67 | $(GST_BASE_LIBS) \ | |
68 | $(GST_LIBS) | |
69 | libfarstream_@GST_MAJORMINOR@_la_LDFLAGS = \ | |
70 | $(FS_LIB_LDFLAGS) \ | |
71 | $(FS_ALL_LDFLAGS) \ | |
72 | $(FS_LT_LDFLAGS) | |
73 | ||
74 | ||
75 | public_headers = fs-candidate.h \ | |
76 | fs-codec.h \ | |
77 | fs-participant.h \ | |
78 | fs-session.h \ | |
79 | fs-stream.h \ | |
80 | fs-conference.h \ | |
81 | fs-utils.h | |
82 | ||
83 | glib_enum_headers=$(public_headers) | |
84 | glib_enum_define=FS | |
85 | glib_gen_prefix=_fs | |
86 | glib_gen_basename=fs | |
87 | ||
88 | include $(top_srcdir)/common-modified/gst-glib-gen.mak | |
89 | ||
90 | if HAVE_INTROSPECTION | |
91 | include $(INTROSPECTION_MAKEFILE) | |
92 | introspection_sources = \ | |
93 | $(libfarstream_@GST_MAJORMINOR@_la_SOURCES) \ | |
94 | $(nodist_libfarstreaminclude_HEADERS) \ | |
95 | $(libfarstreaminclude_HEADERS) | |
96 | ||
97 | INTROSPECTION_GIRS = Farstream-@FS_MAJORMINOR@.gir | |
98 | Farstream_0_1_gir_NAMESPACE = Farstream | |
99 | Farstream_0_1_gir_VERSION = @FS_MAJORMINOR@ | |
100 | Farstream_0_1_gir_LIBS = libfarstream-@GST_MAJORMINOR@.la | |
101 | Farstream_0_1_gir_FILES = $(introspection_sources) | |
102 | Farstream_0_1_gir_INCLUDES = GObject-2.0 Gst-0.10 | |
103 | Farstream_0_1_gir_CFLAGS = $(FS_INTERNAL_CFLAGS) | |
104 | Farstream_0_1_gir_SCANNERFLAGS = --identifier-prefix=fs_ --identifier-prefix=Fs | |
105 | ||
106 | girdir = $(datadir)/gir-1.0 | |
107 | dist_gir_DATA = Farstream-@FS_MAJORMINOR@.gir | |
108 | typelibdir = $(libdir)/girepository-1.0 | |
109 | typelib_DATA = Farstream-@FS_MAJORMINOR@.typelib | |
110 | CLEANFILES += $(dist_gir_DATA) $(typelib_DATA) | |
111 | endif |
0 | /* | |
1 | * Farstream - Farstream Candidate | |
2 | * | |
3 | * Copyright 2007 Collabora Ltd. | |
4 | * @author: Philippe Kalaf <philippe.kalaf@collabora.co.uk> | |
5 | * Copyright 2007 Nokia Corp. | |
6 | * | |
7 | * fs-candidate.c - A Farstream candidate | |
8 | * | |
9 | * This library is free software; you can redistribute it and/or | |
10 | * modify it under the terms of the GNU Lesser General Public | |
11 | * License as published by the Free Software Foundation; either | |
12 | * version 2.1 of the License, or (at your option) any later version. | |
13 | * | |
14 | * This library is distributed in the hope that it will be useful, | |
15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
17 | * Lesser General Public License for more details. | |
18 | * | |
19 | * You should have received a copy of the GNU Lesser General Public | |
20 | * License along with this library; if not, write to the Free Software | |
21 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA | |
22 | */ | |
23 | ||
24 | #ifdef HAVE_CONFIG_H | |
25 | #include "config.h" | |
26 | #endif | |
27 | ||
28 | #include "fs-candidate.h" | |
29 | ||
30 | /** | |
31 | * SECTION:fs-candidate | |
32 | * @short_description: Structure describing a transport candidate. | |
33 | * | |
34 | * An FsCandidate is a way to exchange candidate information between the client | |
35 | * and Farstream. This description is compatible with ICE-13. It can also be a | |
36 | * multicast address. Candidates are linked to streams. The information | |
37 | * specified in this structure is usually representative of the codec | |
38 | * information exchanged in the signaling. | |
39 | */ | |
40 | ||
41 | GType | |
42 | fs_candidate_get_type (void) | |
43 | { | |
44 | static GType candidate_type = 0; | |
45 | if (candidate_type == 0) | |
46 | { | |
47 | candidate_type = g_boxed_type_register_static ( | |
48 | "FsCandidate", | |
49 | (GBoxedCopyFunc)fs_candidate_copy, | |
50 | (GBoxedFreeFunc)fs_candidate_destroy); | |
51 | } | |
52 | ||
53 | return candidate_type; | |
54 | } | |
55 | ||
56 | GType | |
57 | fs_candidate_list_get_type (void) | |
58 | { | |
59 | static GType candidate_list_type = 0; | |
60 | if (candidate_list_type == 0) | |
61 | { | |
62 | candidate_list_type = g_boxed_type_register_static ( | |
63 | "FsCandidateList", | |
64 | (GBoxedCopyFunc)fs_candidate_list_copy, | |
65 | (GBoxedFreeFunc)fs_candidate_list_destroy); | |
66 | } | |
67 | ||
68 | return candidate_list_type; | |
69 | } | |
70 | ||
71 | /** | |
72 | * fs_candidate_destroy: (skip): | |
73 | * @cand: a #FsCandidate to delete | |
74 | * | |
75 | * Frees a #FsCandidate and all its contents | |
76 | */ | |
77 | void | |
78 | fs_candidate_destroy (FsCandidate * cand) | |
79 | { | |
80 | if (cand == NULL) | |
81 | return; | |
82 | ||
83 | g_free ((gchar *) cand->foundation); | |
84 | g_free ((gchar *) cand->ip); | |
85 | g_free ((gchar *) cand->base_ip); | |
86 | g_free ((gchar *) cand->username); | |
87 | g_free ((gchar *) cand->password); | |
88 | ||
89 | g_slice_free (FsCandidate, cand); | |
90 | } | |
91 | ||
92 | /** | |
93 | * fs_candidate_copy: | |
94 | * @cand: a #FsCandidate to copy | |
95 | * | |
96 | * Copies a #FsCandidate and its contents. | |
97 | * | |
98 | * Returns: a new #FsCandidate | |
99 | */ | |
100 | FsCandidate * | |
101 | fs_candidate_copy (const FsCandidate * cand) | |
102 | { | |
103 | FsCandidate *copy = g_slice_new0 (FsCandidate); | |
104 | ||
105 | if (cand == NULL) | |
106 | return NULL; | |
107 | ||
108 | copy->component_id = cand->component_id; | |
109 | copy->port = cand->port; | |
110 | copy->base_port = cand->base_port; | |
111 | copy->proto = cand->proto; | |
112 | copy->priority = cand->priority; | |
113 | copy->type = cand->type; | |
114 | copy->ttl = cand->ttl; | |
115 | ||
116 | copy->foundation = g_strdup (cand->foundation); | |
117 | copy->ip = g_strdup (cand->ip); | |
118 | copy->base_ip = g_strdup (cand->base_ip); | |
119 | copy->username = g_strdup (cand->username); | |
120 | copy->password = g_strdup (cand->password); | |
121 | ||
122 | return copy; | |
123 | } | |
124 | ||
125 | /** | |
126 | * fs_candidate_list_destroy: (skip): | |
127 | * @candidate_list: A GList of #FsCandidate | |
128 | * | |
129 | * Deletes a GList of #FsCandidate and its contents | |
130 | */ | |
131 | void | |
132 | fs_candidate_list_destroy (GList *candidate_list) | |
133 | { | |
134 | GList *lp; | |
135 | FsCandidate *cand; | |
136 | ||
137 | for (lp = candidate_list; lp; lp = g_list_next (lp)) { | |
138 | cand = (FsCandidate *) lp->data; | |
139 | fs_candidate_destroy (cand); | |
140 | lp->data = NULL; | |
141 | } | |
142 | g_list_free (candidate_list); | |
143 | } | |
144 | ||
145 | /** | |
146 | * fs_candidate_list_copy: | |
147 | * @candidate_list: (element-type FsCodec): A GList of #FsCandidate | |
148 | * | |
149 | * Copies a GList of #FsCandidate and its contents | |
150 | * | |
151 | * Returns: (element-type FsCodec) (transfer full): a new GList of #FsCandidate | |
152 | */ | |
153 | GList * | |
154 | fs_candidate_list_copy (const GList *candidate_list) | |
155 | { | |
156 | GQueue copy = G_QUEUE_INIT; | |
157 | const GList *lp; | |
158 | ||
159 | for (lp = candidate_list; lp; lp = g_list_next (lp)) { | |
160 | FsCandidate *cand = lp->data; | |
161 | ||
162 | g_queue_push_tail (©, fs_candidate_copy (cand)); | |
163 | } | |
164 | ||
165 | return copy.head; | |
166 | } | |
167 | ||
168 | /** | |
169 | * fs_candidate_new: | |
170 | * @foundation: The foundation of the candidate | |
171 | * @component_id: The component this candidate is for | |
172 | * @type: The type of candidate | |
173 | * @proto: The protocol this component is for | |
174 | * @ip: The IP address of this component (can be NULL for local candidate to | |
175 | * mean any address) | |
176 | * @port: the UDP/TCP port | |
177 | * | |
178 | * Allocates a new #FsCandidate, the rest of the fields can be optionally | |
179 | * filled manually. | |
180 | * | |
181 | * Returns: a newly-allocated #FsCandidate | |
182 | */ | |
183 | ||
184 | FsCandidate * | |
185 | fs_candidate_new ( | |
186 | const gchar *foundation, | |
187 | guint component_id, | |
188 | FsCandidateType type, | |
189 | FsNetworkProtocol proto, | |
190 | const gchar *ip, | |
191 | guint port) | |
192 | { | |
193 | FsCandidate *candidate = g_slice_new0 (FsCandidate); | |
194 | ||
195 | candidate->foundation = g_strdup (foundation); | |
196 | candidate->component_id = component_id; | |
197 | candidate->type = type; | |
198 | candidate->proto = proto; | |
199 | candidate->ip = g_strdup (ip); | |
200 | candidate->port = port; | |
201 | ||
202 | return candidate; | |
203 | } |
0 | /* | |
1 | * Farstream - Farstream Candidate | |
2 | * | |
3 | * Copyright 2007 Collabora Ltd. | |
4 | * @author: Philippe Kalaf <philippe.kalaf@collabora.co.uk> | |
5 | * Copyright 2007 Nokia Corp. | |
6 | * | |
7 | * fs-candidate.h - A Farstream candidate | |
8 | * | |
9 | * This library is free software; you can redistribute it and/or | |
10 | * modify it under the terms of the GNU Lesser General Public | |
11 | * License as published by the Free Software Foundation; either | |
12 | * version 2.1 of the License, or (at your option) any later version. | |
13 | * | |
14 | * This library is distributed in the hope that it will be useful, | |
15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
17 | * Lesser General Public License for more details. | |
18 | * | |
19 | * You should have received a copy of the GNU Lesser General Public | |
20 | * License along with this library; if not, write to the Free Software | |
21 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA | |
22 | */ | |
23 | ||
24 | #ifndef __FS_CANDIDATE_H__ | |
25 | #define __FS_CANDIDATE_H__ | |
26 | ||
27 | #include <glib.h> | |
28 | #include <glib-object.h> | |
29 | ||
30 | G_BEGIN_DECLS | |
31 | ||
32 | #define FS_TYPE_CANDIDATE \ | |
33 | (fs_candidate_get_type ()) | |
34 | ||
35 | ||
36 | #define FS_TYPE_CANDIDATE_LIST \ | |
37 | (fs_candidate_list_get_type ()) | |
38 | ||
39 | /** | |
40 | * FsCandidateType: | |
41 | * @FS_CANDIDATE_TYPE_HOST: A host candidate (local) | |
42 | * @FS_CANDIDATE_TYPE_SRFLX: A server reflexive candidate. | |
43 | * @FS_CANDIDATE_TYPE_PRFLX: A peer reflexive candidate | |
44 | * @FS_CANDIDATE_TYPE_RELAY: An relay candidate | |
45 | * @FS_CANDIDATE_TYPE_MULTICAST: A multicast address | |
46 | * | |
47 | * An enum for the type of candidate used/reported | |
48 | */ | |
49 | typedef enum _FsCandidateType | |
50 | { | |
51 | FS_CANDIDATE_TYPE_HOST, | |
52 | FS_CANDIDATE_TYPE_SRFLX, | |
53 | FS_CANDIDATE_TYPE_PRFLX, | |
54 | FS_CANDIDATE_TYPE_RELAY, /* An external stream relay */ | |
55 | FS_CANDIDATE_TYPE_MULTICAST | |
56 | } FsCandidateType; | |
57 | ||
58 | /** | |
59 | * FsNetworkProtocol: | |
60 | * @FS_NETWORK_PROTOCOL_UDP: A UDP based protocol | |
61 | * @FS_NETWORK_PROTOCOL_TCP: A TCP based protocol | |
62 | * | |
63 | * An enum for the base IP protocol | |
64 | */ | |
65 | typedef enum _FsNetworkProtocol | |
66 | { | |
67 | FS_NETWORK_PROTOCOL_UDP, | |
68 | FS_NETWORK_PROTOCOL_TCP | |
69 | } FsNetworkProtocol; | |
70 | ||
71 | /** | |
72 | * FsComponentType: | |
73 | * @FS_COMPONENT_NONE: Use this when specifying a component is innapropriate | |
74 | * @FS_COMPONENT_RTP: This component is for RTP data | |
75 | * @FS_COMPONENT_RTCP: This component is for RTCP control | |
76 | * | |
77 | * This enum contains the component IDs defined in ICE-19 | |
78 | */ | |
79 | ||
80 | typedef enum _FsComponentType | |
81 | { | |
82 | FS_COMPONENT_NONE = 0, | |
83 | FS_COMPONENT_RTP = 1, | |
84 | FS_COMPONENT_RTCP = 2 | |
85 | } FsComponentType; | |
86 | ||
87 | ||
88 | typedef struct _FsCandidate FsCandidate; | |
89 | ||
90 | /** | |
91 | * FsCandidate: | |
92 | * @foundation: a string representing the foundation of this candidate (maximum 32 chars) | |
93 | * @component_id: value between 1 and 256 indicating which component this candidate represents (1 is RTP, 2 is RTCP, #FsComponentType can be used here) | |
94 | * @ip: IP in dotted format | |
95 | * @port: Port to use | |
96 | * @base_ip: IP of base in dotted format as defined in ICE-19. | |
97 | * @base_port: Port of base as defined in ICE-19. | |
98 | * @proto: #FsNetworkProtocol for ip protocol to use as candidate | |
99 | * @priority: Value between 0 and (2^31 - 1) representing the priority | |
100 | * @type: The #FsCandidateType of the candidate | |
101 | * @username: Username to use to connect to client if necessary, | |
102 | * NULL otherwise | |
103 | * @password: Username to use to connect to client if necessary, | |
104 | * NULL otherwise | |
105 | * @ttl: The TTL used when sending Multicast packet (0 = auto) | |
106 | * | |
107 | * Struct to hold information about ICE-19 compliant candidates | |
108 | */ | |
109 | struct _FsCandidate | |
110 | { | |
111 | gchar *foundation; | |
112 | guint component_id; | |
113 | const gchar *ip; | |
114 | guint16 port; | |
115 | const gchar *base_ip; | |
116 | guint16 base_port; | |
117 | FsNetworkProtocol proto; | |
118 | guint32 priority; | |
119 | FsCandidateType type; | |
120 | const gchar *username; | |
121 | const gchar *password; | |
122 | guint ttl; | |
123 | }; | |
124 | ||
125 | GType fs_candidate_get_type (void); | |
126 | GType fs_candidate_list_get_type (void); | |
127 | ||
128 | void fs_candidate_destroy (FsCandidate *cand); | |
129 | ||
130 | FsCandidate *fs_candidate_copy (const FsCandidate *cand); | |
131 | ||
132 | void fs_candidate_list_destroy (GList *candidate_list); | |
133 | ||
134 | GList *fs_candidate_list_copy (const GList *candidate_list); | |
135 | ||
136 | FsCandidate * fs_candidate_new ( | |
137 | const gchar *foundation, | |
138 | guint component_id, | |
139 | FsCandidateType type, | |
140 | FsNetworkProtocol proto, | |
141 | const gchar *ip, | |
142 | guint port); | |
143 | ||
144 | G_END_DECLS | |
145 | #endif /* __FS_CANDIDATE_H__ */ |
0 | /* | |
1 | * Farstream - Farstream Codec | |
2 | * | |
3 | * Copyright 2007 Collabora Ltd. | |
4 | * @author: Philippe Kalaf <philippe.kalaf@collabora.co.uk> | |
5 | * Copyright 2007 Nokia Corp. | |
6 | * | |
7 | * Copyright 2005 Collabora Ltd. | |
8 | * @author: Rob Taylor <rob.taylor@collabora.co.uk> | |
9 | * | |
10 | * fs-codec.c - A Farstream codec | |
11 | * | |
12 | * This library is free software; you can redistribute it and/or | |
13 | * modify it under the terms of the GNU Lesser General Public | |
14 | * License as published by the Free Software Foundation; either | |
15 | * version 2.1 of the License, or (at your option) any later version. | |
16 | * | |
17 | * This library is distributed in the hope that it will be useful, | |
18 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
19 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
20 | * Lesser General Public License for more details. | |
21 | * | |
22 | * You should have received a copy of the GNU Lesser General Public | |
23 | * License along with this library; if not, write to the Free Software | |
24 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA | |
25 | */ | |
26 | ||
27 | #ifdef HAVE_CONFIG_H | |
28 | #include "config.h" | |
29 | #endif | |
30 | ||
31 | #include "fs-codec.h" | |
32 | ||
33 | #include <string.h> | |
34 | ||
35 | #include "fs-private.h" | |
36 | ||
37 | #define GST_CAT_DEFAULT fs_conference_debug | |
38 | ||
39 | /** | |
40 | * SECTION:fs-codec | |
41 | * @short_description: Structure representing a media codec | |
42 | * | |
43 | * An #FsCodec is a way to exchange codec information between the client and | |
44 | * Farstream. The information specified in this structure is usually | |
45 | * representative of the codec information exchanged in the signaling. | |
46 | * | |
47 | */ | |
48 | ||
49 | /* TODO Make a fs_codec_new() function since there is a _destroy() */ | |
50 | ||
51 | GType | |
52 | fs_codec_get_type (void) | |
53 | { | |
54 | static GType codec_type = 0; | |
55 | if (codec_type == 0) | |
56 | { | |
57 | codec_type = g_boxed_type_register_static ( | |
58 | "FsCodec", | |
59 | (GBoxedCopyFunc)fs_codec_copy, | |
60 | (GBoxedFreeFunc)fs_codec_destroy); | |
61 | } | |
62 | ||
63 | return codec_type; | |
64 | } | |
65 | ||
66 | GType | |
67 | fs_codec_list_get_type (void) | |
68 | { | |
69 | static GType codec_list_type = 0; | |
70 | if (codec_list_type == 0) | |
71 | { | |
72 | codec_list_type = g_boxed_type_register_static ( | |
73 | "FsCodecGList", | |
74 | (GBoxedCopyFunc)fs_codec_list_copy, | |
75 | (GBoxedFreeFunc)fs_codec_list_destroy); | |
76 | } | |
77 | ||
78 | return codec_list_type; | |
79 | } | |
80 | ||
81 | G_DEFINE_BOXED_TYPE (FsCodecParameter, | |
82 | fs_codec_parameter, | |
83 | fs_codec_parameter_copy, | |
84 | fs_codec_parameter_free); | |
85 | ||
86 | ||
87 | G_DEFINE_BOXED_TYPE (FsFeedbackParameter, | |
88 | fs_feedback_parameter, | |
89 | fs_feedback_parameter_copy, | |
90 | fs_feedback_parameter_free); | |
91 | ||
92 | /** | |
93 | * fs_codec_new: | |
94 | * @id: codec identifier, if RTP this should be based on IETF RTP payload types | |
95 | * @encoding_name: Name of media type this encodes | |
96 | * @media_type: #FsMediaType for type of codec | |
97 | * @clock_rate: The clock rate this codec encodes at, if applicable | |
98 | * | |
99 | * Allocates and initializes a #FsCodec structure | |
100 | * | |
101 | * Returns: A newly allocated #FsCodec | |
102 | */ | |
103 | FsCodec * | |
104 | fs_codec_new (int id, const char *encoding_name, | |
105 | FsMediaType media_type, guint clock_rate) | |
106 | { | |
107 | FsCodec *codec = g_slice_new0 (FsCodec); | |
108 | ||
109 | codec->id = id; | |
110 | codec->encoding_name = g_strdup (encoding_name); | |
111 | codec->media_type = media_type; | |
112 | codec->clock_rate = clock_rate; | |
113 | codec->minimum_reporting_interval = G_MAXUINT; | |
114 | ||
115 | return codec; | |
116 | } | |
117 | ||
118 | void | |
119 | fs_codec_parameter_free (FsCodecParameter *param) | |
120 | ||
121 | { | |
122 | g_free (param->name); | |
123 | g_free (param->value); | |
124 | g_slice_free (FsCodecParameter, param); | |
125 | } | |
126 | ||
127 | ||
128 | void | |
129 | fs_feedback_parameter_free (FsFeedbackParameter *param) | |
130 | { | |
131 | g_free (param->type); | |
132 | g_free (param->subtype); | |
133 | g_free (param->extra_params); | |
134 | g_slice_free (FsFeedbackParameter, param); | |
135 | } | |
136 | ||
137 | /** | |
138 | * fs_codec_destroy: (skip): | |
139 | * @codec: #FsCodec structure to free | |
140 | * | |
141 | * Deletes a #FsCodec structure and all its data. Is a no-op on %NULL codec | |
142 | */ | |
143 | void | |
144 | fs_codec_destroy (FsCodec * codec) | |
145 | { | |
146 | if (codec == NULL) | |
147 | return; | |
148 | ||
149 | g_free (codec->encoding_name); | |
150 | ||
151 | g_list_foreach (codec->optional_params, (GFunc) fs_codec_parameter_free, | |
152 | NULL); | |
153 | g_list_free (codec->optional_params); | |
154 | ||
155 | g_list_foreach (codec->feedback_params, | |
156 | (GFunc) fs_feedback_parameter_free, NULL); | |
157 | g_list_free (codec->feedback_params); | |
158 | ||
159 | g_slice_free (FsCodec, codec); | |
160 | } | |
161 | ||
162 | /** | |
163 | * fs_codec_copy: | |
164 | * @codec: codec to copy | |
165 | * | |
166 | * Copies a #FsCodec structure. | |
167 | * | |
168 | * Returns: a copy of the codec | |
169 | */ | |
170 | FsCodec * | |
171 | fs_codec_copy (const FsCodec * codec) | |
172 | { | |
173 | FsCodec *copy = NULL; | |
174 | GList *lp; | |
175 | GQueue list_copy = G_QUEUE_INIT; | |
176 | ||
177 | if (codec == NULL) | |
178 | return NULL; | |
179 | ||
180 | copy = fs_codec_new (codec->id, codec->encoding_name, codec->media_type, | |
181 | codec->clock_rate); | |
182 | ||
183 | copy->channels = codec->channels; | |
184 | copy->minimum_reporting_interval = codec->minimum_reporting_interval; | |
185 | ||
186 | copy->encoding_name = g_strdup (codec->encoding_name); | |
187 | ||
188 | for (lp = codec->optional_params; lp; lp = g_list_next (lp)) | |
189 | { | |
190 | FsCodecParameter *param_copy; | |
191 | FsCodecParameter *param = lp->data;; | |
192 | ||
193 | param_copy = g_slice_new (FsCodecParameter); | |
194 | param_copy->name = g_strdup (param->name); | |
195 | param_copy->value = g_strdup (param->value); | |
196 | ||
197 | g_queue_push_tail (&list_copy, param_copy); | |
198 | } | |
199 | copy->optional_params = list_copy.head; | |
200 | ||
201 | g_queue_init (&list_copy); | |
202 | for (lp = codec->feedback_params; lp; lp = g_list_next (lp)) | |
203 | { | |
204 | FsFeedbackParameter *param_copy; | |
205 | FsFeedbackParameter *param = lp->data;; | |
206 | ||
207 | param_copy = g_slice_new (FsFeedbackParameter); | |
208 | param_copy->type = g_strdup (param->type); | |
209 | param_copy->subtype = g_strdup (param->subtype); | |
210 | param_copy->extra_params = g_strdup (param->extra_params); | |
211 | ||
212 | g_queue_push_tail (&list_copy, param_copy); | |
213 | } | |
214 | copy->feedback_params = list_copy.head; | |
215 | ||
216 | return copy; | |
217 | } | |
218 | ||
219 | /** | |
220 | * fs_codec_list_destroy: (skip): | |
221 | * @codec_list: a GList of #FsCodec to delete | |
222 | * | |
223 | * Deletes a list of #FsCodec structures and the list itself. | |
224 | * Does nothing on %NULL lists. | |
225 | */ | |
226 | void | |
227 | fs_codec_list_destroy (GList *codec_list) | |
228 | { | |
229 | GList *lp; | |
230 | FsCodec *codec; | |
231 | ||
232 | for (lp = codec_list; lp; lp = g_list_next (lp)) { | |
233 | codec = (FsCodec *) lp->data; | |
234 | fs_codec_destroy (codec); | |
235 | lp->data = NULL; | |
236 | } | |
237 | g_list_free (codec_list); | |
238 | } | |
239 | ||
240 | /** | |
241 | * fs_codec_list_copy: | |
242 | * @codec_list: a GList of #FsCodec to copy | |
243 | * | |
244 | * Copies a list of #FsCodec structures. | |
245 | * | |
246 | * Returns: (element-type FsCodec) (transfer full): The new list. | |
247 | */ | |
248 | GList * | |
249 | fs_codec_list_copy (const GList *codec_list) | |
250 | { | |
251 | GQueue copy = G_QUEUE_INIT; | |
252 | const GList *lp; | |
253 | ||
254 | for (lp = codec_list; lp; lp = g_list_next (lp)) { | |
255 | FsCodec *codec = (FsCodec *) lp->data; | |
256 | ||
257 | g_queue_push_tail (©, fs_codec_copy (codec)); | |
258 | } | |
259 | ||
260 | return copy.head; | |
261 | } | |
262 | ||
263 | /** | |
264 | * fs_codec_list_from_keyfile | |
265 | * @filename: Name of the #GKeyFile to read the codecs parameters from | |
266 | * @error: location of a #GError, or NULL if no error occured | |
267 | * | |
268 | * Reads the content of a #GKeyFile of the following format into | |
269 | * a #GList of #FsCodec structures. | |
270 | * | |
271 | * | |
272 | * Example: | |
273 | * |[ | |
274 | * [audio/codec1] | |
275 | * clock-rate=8000 | |
276 | * | |
277 | * [audio/codec1:1] | |
278 | * clock-rate=16000 | |
279 | * | |
280 | * [audio/codec2] | |
281 | * one_param=QCIF | |
282 | * another_param=WOW | |
283 | * | |
284 | * [video/codec3] | |
285 | * wierd_param=42 | |
286 | * feedback:nack/pli=1 | |
287 | * feedback:tfrc= | |
288 | * ]| | |
289 | * | |
290 | * Return value: (element-type FsCodec) (transfer full): | |
291 | * The #GList of #FsCodec or %NULL if the keyfile was empty or an error occured. | |
292 | */ | |
293 | GList * | |
294 | fs_codec_list_from_keyfile (const gchar *filename, GError **error) | |
295 | { | |
296 | GKeyFile *keyfile = NULL; | |
297 | GList *codecs = NULL; | |
298 | GError *gerror = NULL; | |
299 | gchar **groups = NULL; | |
300 | gsize groups_count = 0; | |
301 | int i; | |
302 | ||
303 | g_return_val_if_fail (filename, NULL); | |
304 | g_return_val_if_fail (error == NULL || *error == NULL, NULL); | |
305 | ||
306 | keyfile = g_key_file_new (); | |
307 | ||
308 | if (!g_key_file_load_from_file (keyfile, filename, | |
309 | G_KEY_FILE_NONE, error)) { | |
310 | goto out; | |
311 | } | |
312 | ||
313 | groups = g_key_file_get_groups (keyfile, &groups_count); | |
314 | ||
315 | if (!groups) | |
316 | goto out; | |
317 | ||
318 | for (i=0; i < groups_count && groups[i]; i++) { | |
319 | FsCodec *codec; | |
320 | gchar **keys = NULL; | |
321 | gsize keys_count; | |
322 | int j; | |
323 | gchar *encoding_name = NULL; | |
324 | gchar *next_tok = NULL; | |
325 | FsMediaType media_type; | |
326 | ||
327 | keys = g_key_file_get_keys (keyfile, groups[i], &keys_count, &gerror); | |
328 | ||
329 | if (!keys || gerror) { | |
330 | if (gerror) | |
331 | GST_WARNING ("Unable to read parameters for %s: %s\n", | |
332 | groups[i], gerror->message); | |
333 | else | |
334 | GST_WARNING ("Unknown errors while reading parameters for %s", | |
335 | groups[i]); | |
336 | ||
337 | g_clear_error (&gerror); | |
338 | ||
339 | goto next_codec; | |
340 | } | |
341 | ||
342 | next_tok = strchr (groups[i], '/'); | |
343 | if (!next_tok) | |
344 | { | |
345 | GST_WARNING ("Invalid codec name: %s", groups[i]); | |
346 | goto next_codec; | |
347 | } | |
348 | ||
349 | if ((next_tok - groups[i]) == 5 /* strlen ("audio") */ && | |
350 | !g_ascii_strncasecmp ("audio", groups[i], 5)) | |
351 | { | |
352 | media_type = FS_MEDIA_TYPE_AUDIO; | |
353 | } | |
354 | else if ((next_tok - groups[i]) == 5 /* strlen ("video") */ && | |
355 | !g_ascii_strncasecmp ("video", groups[i], 5)) | |
356 | { | |
357 | media_type = FS_MEDIA_TYPE_VIDEO; | |
358 | } | |
359 | else | |
360 | { | |
361 | GST_WARNING ("Invalid media type in codec name name %s", groups[i]); | |
362 | goto next_codec; | |
363 | } | |
364 | ||
365 | encoding_name = next_tok + 1; | |
366 | ||
367 | next_tok = strchr (encoding_name, ':'); | |
368 | ||
369 | if (encoding_name[0] == 0 || next_tok - encoding_name == 1) | |
370 | goto next_codec; | |
371 | ||
372 | if (next_tok) | |
373 | encoding_name = g_strndup (encoding_name, | |
374 | next_tok - encoding_name); | |
375 | else | |
376 | encoding_name = g_strdup (encoding_name); | |
377 | ||
378 | codec = fs_codec_new (FS_CODEC_ID_ANY, encoding_name, media_type, 0); | |
379 | ||
380 | g_free (encoding_name); | |
381 | ||
382 | for (j = 0; j < keys_count && keys[j]; j++) { | |
383 | if (!g_ascii_strcasecmp ("clock-rate", keys[j])) { | |
384 | codec->clock_rate = g_key_file_get_integer (keyfile, groups[i], keys[j], | |
385 | &gerror); | |
386 | if (gerror) { | |
387 | codec->clock_rate = 0; | |
388 | goto keyerror; | |
389 | } | |
390 | ||
391 | } else if (!g_ascii_strcasecmp ("id", keys[j])) { | |
392 | codec->id = g_key_file_get_integer (keyfile, groups[i], keys[j], | |
393 | &gerror); | |
394 | if (gerror) { | |
395 | codec->id = FS_CODEC_ID_ANY; | |
396 | goto keyerror; | |
397 | } | |
398 | ||
399 | if (codec->id < 0) | |
400 | codec->id = FS_CODEC_ID_DISABLE; | |
401 | ||
402 | } else if (!g_ascii_strcasecmp ("channels", keys[j])) { | |
403 | codec->channels = g_key_file_get_integer (keyfile, groups[i], keys[j], | |
404 | &gerror); | |
405 | if (gerror) { | |
406 | codec->channels = 0; | |
407 | goto keyerror; | |
408 | } | |
409 | } else if (!g_ascii_strcasecmp ("trr-int", keys[j])) { | |
410 | codec->minimum_reporting_interval = | |
411 | g_key_file_get_integer (keyfile, groups[i], keys[j], &gerror); | |
412 | if (gerror) { | |
413 | codec->minimum_reporting_interval = G_MAXUINT; | |
414 | goto keyerror; | |
415 | } | |
416 | } else if (g_str_has_prefix (keys[j], "feedback:")) { | |
417 | gchar *type = keys[j] + strlen ("feedback:"); | |
418 | gchar *subtype = strchr (type, '/'); | |
419 | gchar *extra_params; | |
420 | ||
421 | extra_params = g_key_file_get_string (keyfile, groups[i], keys[j], | |
422 | &gerror); | |
423 | if (gerror) | |
424 | goto keyerror; | |
425 | ||
426 | /* Replace / with \0 and point to name (the next char) */ | |
427 | if (subtype) | |
428 | { | |
429 | *subtype=0; | |
430 | subtype++; | |
431 | } | |
432 | else | |
433 | { | |
434 | subtype = ""; | |
435 | } | |
436 | ||
437 | fs_codec_add_feedback_parameter (codec, type, subtype, | |
438 | extra_params); | |
439 | g_free (extra_params); | |
440 | } else { | |
441 | FsCodecParameter *param = g_slice_new (FsCodecParameter); | |
442 | ||
443 | param->name = g_strdup (keys[j]); | |
444 | param->value = g_key_file_get_string (keyfile, groups[i], keys[j], | |
445 | &gerror); | |
446 | if (gerror) { | |
447 | fs_codec_parameter_free (param); | |
448 | goto keyerror; | |
449 | } | |
450 | ||
451 | if (!param->name || !param->value) | |
452 | fs_codec_parameter_free (param); | |
453 | else | |
454 | codec->optional_params = g_list_append (codec->optional_params, | |
455 | param); | |
456 | } | |
457 | continue; | |
458 | keyerror: | |
459 | GST_WARNING ("Error reading key %s codec %s: %s", keys[j], groups[i], | |
460 | gerror->message); | |
461 | g_clear_error (&gerror); | |
462 | ||
463 | } | |
464 | ||
465 | codecs = g_list_append (codecs, codec); | |
466 | ||
467 | next_codec: | |
468 | g_strfreev (keys); | |
469 | } | |
470 | ||
471 | ||
472 | out: | |
473 | ||
474 | g_strfreev (groups); | |
475 | g_key_file_free (keyfile); | |
476 | ||
477 | return codecs; | |
478 | } | |
479 | ||
480 | /** | |
481 | * fs_media_type_to_string | |
482 | * @media_type: A media type | |
483 | * | |
484 | * Gives a user-printable string representing the media type | |
485 | * | |
486 | * Return value: a static string representing the media type | |
487 | */ | |
488 | ||
489 | const gchar * | |
490 | fs_media_type_to_string (FsMediaType media_type) | |
491 | { | |
492 | if (media_type == FS_MEDIA_TYPE_AUDIO) { | |
493 | return "audio"; | |
494 | } else if (media_type == FS_MEDIA_TYPE_VIDEO) { | |
495 | return "video"; | |
496 | } else { | |
497 | return NULL; | |
498 | } | |
499 | } | |
500 | ||
501 | /** | |
502 | * fs_codec_to_string | |
503 | * @codec: A farstream codec | |
504 | * | |
505 | * Returns a newly-allocated string representing the codec | |
506 | * | |
507 | * Return value: the newly-allocated string | |
508 | */ | |
509 | gchar * | |
510 | fs_codec_to_string (const FsCodec *codec) | |
511 | { | |
512 | GString *string = NULL; | |
513 | GList *item; | |
514 | gchar *charstring; | |
515 | ||
516 | if (codec == NULL) | |
517 | return g_strdup ("(NULL)"); | |
518 | ||
519 | string = g_string_new (""); | |
520 | ||
521 | g_string_printf (string, "%d: %s %s clock:%d channels:%d", | |
522 | codec->id, fs_media_type_to_string (codec->media_type), | |
523 | codec->encoding_name, codec->clock_rate, codec->channels); | |
524 | ||
525 | if (codec->minimum_reporting_interval != G_MAXUINT) | |
526 | g_string_append_printf (string, " trr-int=%u", | |
527 | codec->minimum_reporting_interval); | |
528 | ||
529 | for (item = codec->optional_params; | |
530 | item; | |
531 | item = g_list_next (item)) { | |
532 | FsCodecParameter *param = item->data; | |
533 | g_string_append_printf (string, " %s=%s", param->name, param->value); | |
534 | } | |
535 | ||
536 | for (item = codec->feedback_params; | |
537 | item; | |
538 | item = g_list_next (item)) { | |
539 | FsFeedbackParameter *param = item->data; | |
540 | g_string_append_printf (string, " %s/%s=%s", param->type, param->subtype, | |
541 | param->extra_params); | |
542 | } | |
543 | ||
544 | charstring = string->str; | |
545 | g_string_free (string, FALSE); | |
546 | ||
547 | return charstring; | |
548 | } | |
549 | ||
550 | ||
551 | static gboolean | |
552 | compare_optional_params (const gpointer p1, const gpointer p2) | |
553 | { | |
554 | const FsCodecParameter *param1 = p1; | |
555 | const FsCodecParameter *param2 = p2; | |
556 | ||
557 | if (!g_ascii_strcasecmp (param1->name, param2->name) && | |
558 | !strcmp (param1->value, param2->value)) | |
559 | return TRUE; | |
560 | else | |
561 | return FALSE; | |
562 | } | |
563 | ||
564 | static gboolean | |
565 | compare_feedback_params (const gpointer p1, const gpointer p2) | |
566 | { | |
567 | const FsFeedbackParameter *param1 = p1; | |
568 | const FsFeedbackParameter *param2 = p2; | |
569 | ||
570 | if (!g_ascii_strcasecmp (param1->subtype, param2->subtype) && | |
571 | !g_ascii_strcasecmp (param1->type, param2->type) && | |
572 | !g_strcmp0 (param1->extra_params, param2->extra_params)) | |
573 | return TRUE; | |
574 | else | |
575 | return FALSE; | |
576 | } | |
577 | ||
578 | /* | |
579 | * Check if all of the elements of list1 are in list2 | |
580 | * It compares GLists of X using the comparison function | |
581 | */ | |
582 | static gboolean | |
583 | compare_lists (GList *list1, GList *list2, | |
584 | gboolean (*compare_params) (const gpointer p1, const gpointer p2)) | |
585 | { | |
586 | GList *item1; | |
587 | ||
588 | for (item1 = g_list_first (list1); | |
589 | item1; | |
590 | item1 = g_list_next (item1)) { | |
591 | FsCodecParameter *param1 = item1->data; | |
592 | GList *item2 = NULL; | |
593 | ||
594 | for (item2 = g_list_first (list2); | |
595 | item2; | |
596 | item2 = g_list_next (item2)) { | |
597 | FsCodecParameter *param2 = item2->data; | |
598 | ||
599 | if (compare_params (param1, param2)) | |
600 | break; | |
601 | } | |
602 | if (!item2) | |
603 | return FALSE; | |
604 | } | |
605 | ||
606 | return TRUE; | |
607 | } | |
608 | ||
609 | ||
610 | /** | |
611 | * fs_codec_are_equal: | |
612 | * @codec1: First codec | |
613 | * @codec2: Second codec | |
614 | * | |
615 | * Compare two codecs, it will declare two codecs to be identical even | |
616 | * if their optional parameters are in a different order. %NULL encoding names | |
617 | * are ignored. | |
618 | * | |
619 | * Return value: %TRUE of the codecs are identical, %FALSE otherwise | |
620 | */ | |
621 | ||
622 | gboolean | |
623 | fs_codec_are_equal (const FsCodec *codec1, const FsCodec *codec2) | |
624 | { | |
625 | if (codec1 == codec2) | |
626 | return TRUE; | |
627 | ||
628 | if (!codec1 || !codec2) | |
629 | return FALSE; | |
630 | ||
631 | if (codec1->id != codec2->id || | |
632 | codec1->media_type != codec2->media_type || | |
633 | codec1->clock_rate != codec2->clock_rate || | |
634 | codec1->channels != codec2->channels || | |
635 | codec1->minimum_reporting_interval != | |
636 | codec2->minimum_reporting_interval || | |
637 | codec1->encoding_name == NULL || | |
638 | codec2->encoding_name == NULL || | |
639 | g_ascii_strcasecmp (codec1->encoding_name, codec2->encoding_name)) | |
640 | return FALSE; | |
641 | ||
642 | ||
643 | /* Is there a smarter way to compare to un-ordered linked lists | |
644 | * to make sure they contain exactly the same elements?? | |
645 | */ | |
646 | if (!compare_lists (codec1->optional_params, codec2->optional_params, | |
647 | compare_optional_params) || | |
648 | !compare_lists (codec2->optional_params, codec1->optional_params, | |
649 | compare_optional_params)) | |
650 | return FALSE; | |
651 | ||
652 | if (!compare_lists (codec1->feedback_params, | |
653 | codec2->feedback_params, compare_feedback_params) || | |
654 | !compare_lists (codec2->feedback_params, | |
655 | codec1->feedback_params, compare_feedback_params)) | |
656 | return FALSE; | |
657 | ||
658 | return TRUE; | |
659 | } | |
660 | ||
661 | /** | |
662 | * fs_codec_list_are_equal: | |
663 | * @list1: (element-type FsCodec): a #GList of #FsCodec | |
664 | * @list2: (element-type FsCodec): a #GList of #FsCodec | |
665 | * | |
666 | * Verifies if two glist of fscodecs are identical | |
667 | * | |
668 | * Returns: %TRUE if they are identical, %FALSE otherwise | |
669 | */ | |
670 | ||
671 | gboolean | |
672 | fs_codec_list_are_equal (GList *list1, GList *list2) | |
673 | { | |
674 | ||
675 | for (; | |
676 | list1 && list2; | |
677 | list1 = g_list_next (list1), list2 = g_list_next (list2)) | |
678 | { | |
679 | if (!fs_codec_are_equal (list1->data, list2->data)) | |
680 | return FALSE; | |
681 | } | |
682 | ||
683 | if (list1 == NULL && list2 == NULL) | |
684 | return TRUE; | |
685 | else | |
686 | return FALSE; | |
687 | } | |
688 | ||
689 | /** | |
690 | * fs_codec_add_optional_parameter: | |
691 | * @codec: The #FsCodec to add the parameter to | |
692 | * @name: The name of the optional parameter | |
693 | * @value: The extra_params of the optional parameter | |
694 | * | |
695 | * This function adds an new optional parameter to a #FsCodec | |
696 | */ | |
697 | ||
698 | void | |
699 | fs_codec_add_optional_parameter (FsCodec *codec, | |
700 | const gchar *name, | |
701 | const gchar *value) | |
702 | { | |
703 | FsCodecParameter *param; | |
704 | ||
705 | g_return_if_fail (name != NULL && value != NULL); | |
706 | ||
707 | param = g_slice_new (FsCodecParameter); | |
708 | ||
709 | param->name = g_strdup (name); | |
710 | param->value = g_strdup (value); | |
711 | ||
712 | codec->optional_params = g_list_append (codec->optional_params, param); | |
713 | } | |
714 | ||
715 | /** | |
716 | * fs_codec_remove_optional_parameter: | |
717 | * @codec: a #FsCodec | |
718 | * @param: a pointer to the #FsCodecParameter to remove | |
719 | * | |
720 | * Removes an optional parameter from a codec. | |
721 | * | |
722 | * NULL param will do nothing. | |
723 | */ | |
724 | ||
725 | void | |
726 | fs_codec_remove_optional_parameter (FsCodec *codec, | |
727 | FsCodecParameter *param) | |
728 | { | |
729 | g_return_if_fail (codec); | |
730 | ||
731 | if (!param) | |
732 | return; | |
733 | ||
734 | fs_codec_parameter_free (param); | |
735 | codec->optional_params = g_list_remove (codec->optional_params, param); | |
736 | } | |
737 | ||
738 | /** | |
739 | * fs_codec_get_optional_parameter: | |
740 | * @codec: a #FsCodec | |
741 | * @name: The name of the parameter to search for | |
742 | * @value: The value of the parameter to search for or %NULL for any value | |
743 | * | |
744 | * Finds the #FsCodecParameter in the #FsCodec that has the requested name | |
745 | * and, if not %NULL, the requested value | |
746 | * | |
747 | * Returns: (transfer none) the #FsCodecParameter from the #FsCodec or %NULL | |
748 | */ | |
749 | ||
750 | FsCodecParameter * | |
751 | fs_codec_get_optional_parameter (FsCodec *codec, const gchar *name, | |
752 | const gchar *value) | |
753 | { | |
754 | GList *item = NULL; | |
755 | ||
756 | g_return_val_if_fail (codec != NULL, NULL); | |
757 | g_return_val_if_fail (name != NULL, NULL); | |
758 | ||
759 | for (item = g_list_first (codec->optional_params); | |
760 | item; | |
761 | item = g_list_next (item)) | |
762 | { | |
763 | FsCodecParameter *param = item->data; | |
764 | if (!g_ascii_strcasecmp (param->name, name) && | |
765 | (value == NULL || !g_ascii_strcasecmp (param->value, value))) | |
766 | return param; | |
767 | } | |
768 | ||
769 | return NULL; | |
770 | } | |
771 | ||
772 | /** | |
773 | * fs_codec_add_feedback_parameter: | |
774 | * @codec: The #FsCodec to add the parameter to | |
775 | * @type: The type of the feedback parameter | |
776 | * @subtype: The subtype of the feedback parameter | |
777 | * @extra_params: The extra_params of the feeback parameter | |
778 | * | |
779 | * This function adds an new feedback parameter to a #FsCodec | |
780 | */ | |
781 | ||
782 | void | |
783 | fs_codec_add_feedback_parameter (FsCodec *codec, const gchar *type, | |
784 | const gchar *subtype, const gchar *extra_params) | |
785 | { | |
786 | FsFeedbackParameter *param; | |
787 | ||
788 | g_return_if_fail (type != NULL); | |
789 | g_return_if_fail (subtype != NULL); | |
790 | g_return_if_fail (extra_params != NULL); | |
791 | ||
792 | param = g_slice_new (FsFeedbackParameter); | |
793 | ||
794 | param->type = g_strdup (type); | |
795 | param->subtype = g_strdup (subtype); | |
796 | param->extra_params = g_strdup (extra_params); | |
797 | ||
798 | codec->feedback_params = g_list_append (codec->feedback_params, param); | |
799 | } | |
800 | ||
801 | ||
802 | /** | |
803 | * fs_codec_get_feedback_parameter: | |
804 | * @codec: a #FsCodec | |
805 | * @type: The subtype of the parameter to search for or %NULL for any type | |
806 | * @subtype: The subtype of the parameter to search for or %NULL for any subtype | |
807 | * @extra_params: The extra_params of the parameter to search for or %NULL for | |
808 | * any extra_params | |
809 | * | |
810 | * Finds the #FsFeedbackParameter in the #FsCodec that has the requested | |
811 | * subtype, type and extra_params. One of which must be non-NULL; | |
812 | * | |
813 | * Returns: the #FsFeedbackParameter from the #FsCodec or %NULL | |
814 | */ | |
815 | ||
816 | FsFeedbackParameter * | |
817 | fs_codec_get_feedback_parameter (FsCodec *codec, | |
818 | const gchar *type, const gchar *subtype, const gchar *extra_params) | |
819 | { | |
820 | GList *item = NULL; | |
821 | ||
822 | g_return_val_if_fail (codec != NULL, NULL); | |
823 | g_return_val_if_fail (type != NULL || subtype != NULL, NULL); | |
824 | ||
825 | for (item = g_list_first (codec->feedback_params); | |
826 | item; | |
827 | item = g_list_next (item)) | |
828 | { | |
829 | FsFeedbackParameter *param = item->data; | |
830 | if (!g_ascii_strcasecmp (param->type, type) && | |
831 | (subtype == NULL || !g_ascii_strcasecmp (param->subtype, subtype)) && | |
832 | (extra_params == NULL || !g_ascii_strcasecmp (param->extra_params, | |
833 | extra_params))) | |
834 | return param; | |
835 | } | |
836 | ||
837 | return NULL; | |
838 | } | |
839 | ||
840 | ||
841 | ||
842 | /** | |
843 | * fs_codec_remove_feedback_parameter: | |
844 | * @codec: a #FsCodec | |
845 | * @item: a pointer to the #GList element to remove that contains a | |
846 | * #FsFeedbackParameter | |
847 | * | |
848 | * Removes an optional parameter from a codec. | |
849 | * | |
850 | * NULL param will do nothing. | |
851 | */ | |
852 | ||
853 | void | |
854 | fs_codec_remove_feedback_parameter (FsCodec *codec, GList *item) | |
855 | { | |
856 | g_return_if_fail (codec); | |
857 | ||
858 | if (!item) | |
859 | return; | |
860 | ||
861 | fs_feedback_parameter_free (item->data); | |
862 | codec->feedback_params = | |
863 | g_list_delete_link (codec->feedback_params, item); | |
864 | } | |
865 | ||
866 | FsCodecParameter * | |
867 | fs_codec_parameter_copy (const FsCodecParameter *param) | |
868 | { | |
869 | FsCodecParameter *outparam = g_slice_new (FsCodecParameter); | |
870 | ||
871 | outparam->name = g_strdup (param->name); | |
872 | outparam->value = g_strdup (param->value); | |
873 | ||
874 | return outparam; | |
875 | } | |
876 | ||
877 | ||
878 | FsFeedbackParameter * | |
879 | fs_feedback_parameter_copy (const FsFeedbackParameter *param) | |
880 | { | |
881 | FsFeedbackParameter *outparam = g_slice_new (FsFeedbackParameter); | |
882 | ||
883 | outparam->type = g_strdup (param->type); | |
884 | outparam->subtype = g_strdup (param->subtype); | |
885 | outparam->extra_params = g_strdup (param->extra_params); | |
886 | ||
887 | return outparam; | |
888 | } |
0 | /* | |
1 | * Farstream - Farstream Codec | |
2 | * | |
3 | * Copyright 2007 Collabora Ltd. | |
4 | * @author: Philippe Kalaf <philippe.kalaf@collabora.co.uk> | |
5 | * Copyright 2007 Nokia Corp. | |
6 | * | |
7 | * Copyright 2005 Collabora Ltd. | |
8 | * @author: Rob Taylor <rob.taylor@collabora.co.uk> | |
9 | * | |
10 | * fs-codec.h - A Farstream codec | |
11 | * | |
12 | * This library is free software; you can redistribute it and/or | |
13 | * modify it under the terms of the GNU Lesser General Public | |
14 | * License as published by the Free Software Foundation; either | |
15 | * version 2.1 of the License, or (at your option) any later version. | |
16 | * | |
17 | * This library is distributed in the hope that it will be useful, | |
18 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
19 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
20 | * Lesser General Public License for more details. | |
21 | * | |
22 | * You should have received a copy of the GNU Lesser General Public | |
23 | * License along with this library; if not, write to the Free Software | |
24 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA | |
25 | */ | |
26 | ||
27 | #ifndef __FS_CODEC_H__ | |
28 | #define __FS_CODEC_H__ | |
29 | ||
30 | #include <gst/gst.h> | |
31 | ||
32 | G_BEGIN_DECLS | |
33 | ||
34 | typedef struct _FsCodec FsCodec; | |
35 | typedef struct _FsCodecParameter FsCodecParameter; | |
36 | typedef struct _FsFeedbackParameter FsFeedbackParameter; | |
37 | ||
38 | #define FS_TYPE_CODEC \ | |
39 | (fs_codec_get_type ()) | |
40 | ||
41 | #define FS_TYPE_CODEC_LIST \ | |
42 | (fs_codec_list_get_type ()) | |
43 | ||
44 | /** | |
45 | * FsMediaType: | |
46 | * @FS_MEDIA_TYPE_AUDIO: A media type that encodes audio. | |
47 | * @FS_MEDIA_TYPE_VIDEO: A media type that encodes video. | |
48 | * @FS_MEDIA_TYPE_LAST: Largest valid #FsMediaType | |
49 | * | |
50 | * Enum used to signify the media type of a codec or stream. | |
51 | */ | |
52 | typedef enum _FsMediaType | |
53 | { | |
54 | FS_MEDIA_TYPE_AUDIO, | |
55 | FS_MEDIA_TYPE_VIDEO, | |
56 | FS_MEDIA_TYPE_LAST = FS_MEDIA_TYPE_VIDEO | |
57 | } FsMediaType; | |
58 | ||
59 | /** | |
60 | * FS_CODEC_ID_ANY: | |
61 | * | |
62 | * If the id of a #FsCodec is #FS_CODEC_ID_ANY, then it will be replaced | |
63 | * with a dynamic payload type at runtime | |
64 | */ | |
65 | ||
66 | /** | |
67 | * FS_CODEC_ID_DISABLE: | |
68 | * | |
69 | * If the id of a #FsCodec is #FS_CODEC_ID_DISABLE, then this codec will | |
70 | * not be used | |
71 | */ | |
72 | ||
73 | #define FS_CODEC_ID_ANY (-1) | |
74 | #define FS_CODEC_ID_DISABLE (-2) | |
75 | ||
76 | /** | |
77 | * FsCodec: | |
78 | * @id: numeric identifier for encoding, eg. PT for SDP | |
79 | * @encoding_name: the name of the codec | |
80 | * @media_type: type of media this codec is for | |
81 | * @clock_rate: clock rate of this stream | |
82 | * @channels: Number of channels codec should decode | |
83 | * @ptime: The preferred duration (in ms) of a packet | |
84 | * @maxptime: The maximum duration (in ms) of a packet | |
85 | * @optional_params: (element-type FsCodecParameter): key pairs of param name to param data | |
86 | * @minimum_reporting_interval: The minimum interval between two RTCP reports, | |
87 | * If it is not specified (G_MAXUINT), it is up to the protocol to decide | |
88 | * (it is 5 seconds for RTP). | |
89 | * | |
90 | * This structure reprensents one codec that can be offered or received | |
91 | */ | |
92 | /* TODO Should this be made into a GstStructure? */ | |
93 | struct _FsCodec | |
94 | { | |
95 | gint id; | |
96 | char *encoding_name; | |
97 | FsMediaType media_type; | |
98 | guint clock_rate; | |
99 | guint channels; | |
100 | guint minimum_reporting_interval; | |
101 | GList *optional_params; | |
102 | GList *feedback_params; | |
103 | }; | |
104 | ||
105 | /** | |
106 | * FsCodecParameter: | |
107 | * @name: paramter name. | |
108 | * @value: parameter value. | |
109 | * | |
110 | * Used to store arbitary parameters for a codec | |
111 | */ | |
112 | struct _FsCodecParameter { | |
113 | gchar *name; | |
114 | gchar *value; | |
115 | }; | |
116 | ||
117 | /** | |
118 | * FsFeedbackParameter: | |
119 | * @type: the type of feedback, like "ack", "name", "ccm" | |
120 | * @subtype: the subtype of feedback (can be an empty string) | |
121 | * @extra_params: a string containing extra parameters (can be empty) | |
122 | * | |
123 | * Use to store feedback parameters | |
124 | */ | |
125 | struct _FsFeedbackParameter { | |
126 | gchar *type; | |
127 | gchar *subtype; | |
128 | gchar *extra_params; | |
129 | }; | |
130 | ||
131 | ||
132 | /** | |
133 | * FS_CODEC_FORMAT: | |
134 | * | |
135 | * A format that can be used in printf like format strings to format a FsCodec | |
136 | */ | |
137 | ||
138 | /** | |
139 | * FS_CODEC_ARGS: | |
140 | * @codec: a #FsCodec | |
141 | * | |
142 | * Formats the codec in args for FS_CODEC_FORMAT | |
143 | */ | |
144 | ||
145 | #define FS_CODEC_FORMAT "%d: %s %s clock:%d channels:%d params:%p" | |
146 | #define FS_CODEC_ARGS(codec) \ | |
147 | (codec)->id, \ | |
148 | fs_media_type_to_string ((codec)->media_type), \ | |
149 | (codec)->encoding_name, \ | |
150 | (codec)->clock_rate, \ | |
151 | (codec)->channels, \ | |
152 | (codec)->optional_params | |
153 | ||
154 | GType fs_codec_get_type (void); | |
155 | GType fs_codec_list_get_type (void); | |
156 | ||
157 | ||
158 | FsCodec *fs_codec_new (int id, const char *encoding_name, | |
159 | FsMediaType media_type, guint clock_rate); | |
160 | ||
161 | void fs_codec_destroy (FsCodec * codec); | |
162 | FsCodec *fs_codec_copy (const FsCodec * codec); | |
163 | void fs_codec_list_destroy (GList *codec_list); | |
164 | GList *fs_codec_list_copy (const GList *codec_list); | |
165 | ||
166 | GList *fs_codec_list_from_keyfile (const gchar *filename, GError **error); | |
167 | gchar *fs_codec_to_string (const FsCodec *codec); | |
168 | const gchar *fs_media_type_to_string (FsMediaType media_type); | |
169 | ||
170 | gboolean fs_codec_are_equal (const FsCodec *codec1, const FsCodec *codec2); | |
171 | gboolean fs_codec_list_are_equal (GList *list1, GList *list2); | |
172 | ||
173 | ||
174 | void fs_codec_add_optional_parameter (FsCodec *codec, const gchar *name, | |
175 | const gchar *value); | |
176 | void fs_codec_remove_optional_parameter (FsCodec *codec, | |
177 | FsCodecParameter *param); | |
178 | FsCodecParameter *fs_codec_get_optional_parameter (FsCodec *codec, | |
179 | const gchar *name, const gchar *value); | |
180 | ||
181 | #define FS_TYPE_CODEC_PARAMETER (fs_codec_parameter_get_type ()) | |
182 | GType fs_codec_parameter_get_type (void); | |
183 | ||
184 | FsCodecParameter *fs_codec_parameter_copy (const FsCodecParameter *param); | |
185 | void fs_codec_parameter_free (FsCodecParameter *param); | |
186 | ||
187 | ||
188 | void fs_codec_add_feedback_parameter (FsCodec *codec, const gchar *type, | |
189 | const gchar *subtype, const gchar *extra_params); | |
190 | FsFeedbackParameter *fs_codec_get_feedback_parameter (FsCodec *codec, | |
191 | const gchar *type, const gchar *subtype, const gchar *extra_params); | |
192 | void fs_codec_remove_feedback_parameter (FsCodec *codec, GList *item); | |
193 | ||
194 | ||
195 | #define FS_TYPE_FEEDBACK_PARAMETER (fs_feedback_parameter_get_type ()) | |
196 | GType fs_feedback_parameter_get_type (void); | |
197 | ||
198 | FsFeedbackParameter *fs_feedback_parameter_copy ( | |
199 | const FsFeedbackParameter *param); | |
200 | void fs_feedback_parameter_free (FsFeedbackParameter *param); | |
201 | ||
202 | ||
203 | ||
204 | G_END_DECLS | |
205 | ||
206 | #endif /* __FS_CODEC_H__ */ |
0 | /* | |
1 | * Farstream - GStreamer interfaces | |
2 | * | |
3 | * Copyright 2007-2011 Collabora Ltd. | |
4 | * @author: Philippe Kalaf <philippe.kalaf@collabora.co.uk> | |
5 | * @author: Olivier Crete <olivier.crete@collabora.com> | |
6 | * Copyright 2007-2011 Nokia Corp. | |
7 | * | |
8 | * fs-conference.c - GStreamer interface to be implemented by farstream | |
9 | * conference elements | |
10 | * | |
11 | * This library is free software; you can redistribute it and/or | |
12 | * modify it under the terms of the GNU Lesser General Public | |
13 | * License as published by the Free Software Foundation; either | |
14 | * version 2.1 of the License, or (at your option) any later version. | |
15 | * | |
16 | * This library is distributed in the hope that it will be useful, | |
17 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
18 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
19 | * Lesser General Public License for more details. | |
20 | * | |
21 | * You should have received a copy of the GNU Lesser General Public | |
22 | * License along with this library; if not, write to the Free Software | |
23 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA | |
24 | */ | |
25 | ||
26 | #ifdef HAVE_CONFIG_H | |
27 | #include "config.h" | |
28 | #endif | |
29 | ||
30 | #include "fs-conference.h" | |
31 | #include "fs-session.h" | |
32 | #include "fs-private.h" | |
33 | ||
34 | /** | |
35 | * SECTION:fs-conference | |
36 | * @short_description: Interface for farstream conference elements | |
37 | * | |
38 | * A Farstream conference is a conversation space that takes place between 2 or | |
39 | * more participants. Each conference must have one or more Farstream sessions | |
40 | * that are associated to the conference participants. | |
41 | * | |
42 | * | |
43 | * This will communicate asynchronous events to the user through #GstMessage | |
44 | * of type #GST_MESSAGE_ELEMENT sent over the #GstBus. | |
45 | * </para> | |
46 | * <refsect2><title>The "<literal>farstream-error</literal>" message</title> | |
47 | * |[ | |
48 | * "src-object" #GObject The object (#FsConference, #FsSession or #FsStream) that emitted the error | |
49 | * "error-no" #FsError The Error number | |
50 | * "error-msg" #gchar* The error message | |
51 | * ]| | |
52 | * <para> | |
53 | * The message is sent on asynchronous errors. | |
54 | * </para> | |
55 | * </refsect2> | |
56 | * <para> | |
57 | */ | |
58 | ||
59 | ||
60 | GST_DEBUG_CATEGORY (fs_conference_debug); | |
61 | #define GST_CAT_DEFAULT fs_conference_debug | |
62 | ||
63 | ||
64 | GST_BOILERPLATE ( | |
65 | FsConference, fs_conference, | |
66 | GstBin, GST_TYPE_BIN) | |
67 | ||
68 | ||
69 | GQuark | |
70 | fs_error_quark (void) | |
71 | { | |
72 | return g_quark_from_static_string ("fs-error"); | |
73 | } | |
74 | ||
75 | void | |
76 | _fs_conference_init_debug (void) | |
77 | { | |
78 | GST_DEBUG_CATEGORY_INIT (fs_conference_debug, "fsconference", 0, | |
79 | "farstream base conference library"); | |
80 | } | |
81 | ||
82 | static void | |
83 | fs_conference_base_init (gpointer g_class) | |
84 | { | |
85 | _fs_conference_init_debug (); | |
86 | } | |
87 | ||
88 | ||
89 | ||
90 | static void | |
91 | fs_conference_class_init (FsConferenceClass * klass) | |
92 | { | |
93 | } | |
94 | ||
95 | static void | |
96 | fs_conference_init (FsConference *conf, FsConferenceClass *bclass) | |
97 | { | |
98 | GST_DEBUG ("fs_conference_init"); | |
99 | } | |
100 | ||
101 | ||
102 | static void | |
103 | fs_conference_error (GObject *signal_src, | |
104 | GObject *error_src, | |
105 | FsError error_no, | |
106 | gchar *error_msg, | |
107 | FsConference *conf) | |
108 | { | |
109 | GstMessage *gst_msg = NULL; | |
110 | GstStructure *error_struct = NULL; | |
111 | ||
112 | error_struct = gst_structure_new ("farstream-error", | |
113 | "src-object", G_TYPE_OBJECT, error_src, | |
114 | "error-no", FS_TYPE_ERROR, error_no, | |
115 | "error-msg", G_TYPE_STRING, error_msg, | |
116 | NULL); | |
117 | ||
118 | gst_msg = gst_message_new_element (GST_OBJECT (conf), error_struct); | |
119 | ||
120 | if (!gst_element_post_message (GST_ELEMENT (conf), gst_msg)) | |
121 | GST_WARNING_OBJECT (conf, "Could not post error on bus"); | |
122 | } | |
123 | ||
124 | /** | |
125 | * fs_conference_new_session | |
126 | * @conference: #FsConference interface of a #GstElement | |
127 | * @media_type: #FsMediaType of the new session | |
128 | * @error: location of a #GError, or %NULL if no error occured | |
129 | * | |
130 | * Create a new Farstream session for the given conference. | |
131 | * | |
132 | * Returns: (transfer full): the new #FsSession that has been created. | |
133 | * The #FsSession must be unref'd by the user when closing the session. | |
134 | */ | |
135 | ||
136 | FsSession * | |
137 | fs_conference_new_session (FsConference *conf, | |
138 | FsMediaType media_type, | |
139 | GError **error) | |
140 | { | |
141 | FsConferenceClass *klass; | |
142 | FsSession *new_session = NULL; | |
143 | ||
144 | g_return_val_if_fail (conf, NULL); | |
145 | g_return_val_if_fail (FS_IS_CONFERENCE (conf), NULL); | |
146 | klass = FS_CONFERENCE_GET_CLASS (conf); | |
147 | g_return_val_if_fail (klass->new_session, NULL); | |
148 | ||
149 | new_session = klass->new_session (conf, media_type, error); | |
150 | ||
151 | if (!new_session) | |
152 | return NULL; | |
153 | ||
154 | /* Let's catch all session errors and send them over the GstBus */ | |
155 | g_signal_connect_object (new_session, "error", | |
156 | G_CALLBACK (fs_conference_error), conf, 0); | |
157 | ||
158 | return new_session; | |
159 | } | |
160 | ||
161 | /** | |
162 | * fs_conference_new_participant | |
163 | * @conference: #FsConference interface of a #GstElement | |
164 | * @error: location of a #GError, or %NULL if no error occured | |
165 | * | |
166 | * Create a new Farstream Participant for the type of the given conference. | |
167 | * | |
168 | * Returns: (transfer full): the new #FsParticipant that has been created. | |
169 | * The #FsParticipant is owned by the user and he must unref it when he is | |
170 | * done with it. | |
171 | */ | |
172 | FsParticipant * | |
173 | fs_conference_new_participant (FsConference *conf, | |
174 | GError **error) | |
175 | { | |
176 | FsConferenceClass *klass; | |
177 | ||
178 | g_return_val_if_fail (conf, NULL); | |
179 | g_return_val_if_fail (FS_IS_CONFERENCE (conf), NULL); | |
180 | klass = FS_CONFERENCE_GET_CLASS (conf); | |
181 | g_return_val_if_fail (klass->new_participant, NULL); | |
182 | ||
183 | return klass->new_participant (conf, error); | |
184 | } | |
185 |
0 | /* | |
1 | * Farstream - FsConference Class | |
2 | * | |
3 | * Copyright 2007 Collabora Ltd. | |
4 | * @author: Philippe Kalaf <philippe.kalaf@collabora.co.uk> | |
5 | * Copyright 2007 Nokia Corp. | |
6 | * | |
7 | * fs-conference.h - Header file for farstream Conference base class | |
8 | * | |
9 | * This library is free software; you can redistribute it and/or | |
10 | * modify it under the terms of the GNU Lesser General Public | |
11 | * License as published by the Free Software Foundation; either | |
12 | * version 2.1 of the License, or (at your option) any later version. | |
13 | * | |
14 | * This library is distributed in the hope that it will be useful, | |
15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
17 | * Lesser General Public License for more details. | |
18 | * | |
19 | * You should have received a copy of the GNU Lesser General Public | |
20 | * License along with this library; if not, write to the Free Software | |
21 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA | |
22 | */ | |
23 | ||
24 | #ifndef __FS_CONFERENCE_H__ | |
25 | #define __FS_CONFERENCE_H__ | |
26 | ||
27 | #include <gst/gst.h> | |
28 | ||
29 | #include <gst/farstream/fs-session.h> | |
30 | #include <gst/farstream/fs-codec.h> | |
31 | #include <gst/farstream/fs-enumtypes.h> | |
32 | ||
33 | G_BEGIN_DECLS | |
34 | ||
35 | ||
36 | #define FS_TYPE_CONFERENCE \ | |
37 | (fs_conference_get_type ()) | |
38 | #define FS_CONFERENCE(obj) \ | |
39 | (G_TYPE_CHECK_INSTANCE_CAST((obj),FS_TYPE_CONFERENCE,FsConference)) | |
40 | #define FS_CONFERENCE_CLASS(klass) \ | |
41 | (G_TYPE_CHECK_CLASS_CAST((klass),FS_TYPE_CONFERENCE,FsConferenceClass)) | |
42 | #define FS_CONFERENCE_GET_CLASS(obj) \ | |
43 | (G_TYPE_INSTANCE_GET_CLASS((obj),FS_TYPE_CONFERENCE,FsConferenceClass)) | |
44 | #define FS_IS_CONFERENCE(obj) \ | |
45 | (G_TYPE_CHECK_INSTANCE_TYPE((obj),FS_TYPE_CONFERENCE)) | |
46 | #define FS_IS_CONFERENCE_CLASS(klass) \ | |
47 | (G_TYPE_CHECK_CLASS_TYPE((klass),FS_TYPE_CONFERENCE)) | |
48 | #define FS_CONFERENCE_CAST(obj) \ | |
49 | ((FsConference *)(obj)) | |
50 | ||
51 | /** | |
52 | * FsConference: | |
53 | * | |
54 | * Opaque #FsConference data structure. | |
55 | */ | |
56 | typedef struct _FsConference FsConference; | |
57 | typedef struct _FsConferenceClass FsConferenceClass; | |
58 | ||
59 | /** | |
60 | * FsConference | |
61 | * | |
62 | * The #FsConference structure, all the members are private | |
63 | */ | |
64 | ||
65 | struct _FsConference | |
66 | { | |
67 | GstBin parent; | |
68 | ||
69 | /*< private >*/ | |
70 | ||
71 | gpointer _padding[8]; | |
72 | }; | |
73 | ||
74 | ||
75 | /** | |
76 | * FsConferenceClass: | |
77 | * @parent: parent GstBin class | |
78 | * @new_session: virtual method to create a new conference session | |
79 | * @new_participant: virtual method to create a new participant | |
80 | * | |
81 | * #FsConferenceClass class structure. | |
82 | */ | |
83 | struct _FsConferenceClass { | |
84 | GstBinClass parent; | |
85 | ||
86 | /* virtual functions */ | |
87 | FsSession *(* new_session) (FsConference *conference, FsMediaType media_type, | |
88 | GError **error); | |
89 | ||
90 | FsParticipant *(* new_participant) (FsConference *conference, | |
91 | GError **error); | |
92 | ||
93 | /*< private > */ | |
94 | gpointer _gst_reserved[GST_PADDING]; | |
95 | }; | |
96 | ||
97 | GType fs_conference_get_type (void); | |
98 | ||
99 | ||
100 | ||
101 | /** | |
102 | * FsError: | |
103 | * @FS_ERROR_CONSTRUCTION: Error constructing some of the sub-elements, this | |
104 | * probably denotes an error in the installation of the gstreamer elements. | |
105 | * It is a fatal error. | |
106 | * @FS_ERROR_INVALID_ARGUMENTS: Invalid arguments to the function, this | |
107 | * is a programming error and should not be reported to the user | |
108 | * @FS_ERROR_INTERNAL: An internal error happened in Farstream, it may be in | |
109 | * an inconsistent state. The object from which this error comes should be | |
110 | * discarded. | |
111 | * @FS_ERROR_NETWORK: A network related error, this should probably be | |
112 | * reported to the user. | |
113 | * @FS_ERROR_NOT_IMPLEMENTED: The optional functionality is not implemented by | |
114 | * this plugin. | |
115 | * @FS_ERROR_NEGOTIATION_FAILED: The codec negotiation has failed, this means | |
116 | * that there are no common codecs between the local and remote codecs. | |
117 | * @FS_ERROR_UNKNOWN_CODEC: Data is received on an unknown codec, this most | |
118 | * likely denotes an error on the remote side, the buffers will be ignored. | |
119 | * It can safely be ignored in most cases (but may result in a call with no | |
120 | * media received). | |
121 | * @FS_ERROR_NO_CODECS: There are no codecs detected for that media type. | |
122 | * @FS_ERROR_NO_CODECS_LEFT: All of the codecs have been disabled by the | |
123 | * codec preferences, one should try less strict codec preferences. | |
124 | * @FS_ERROR_CONNECTION_FAILED: Could not connect to the to remote party. | |
125 | * @FS_ERROR_DISPOSED: The object has been disposed. | |
126 | * @FS_ERROR_ALREADY_EXISTS: The object already exists | |
127 | * | |
128 | * This is the enum of error numbers that will come either on the "error" | |
129 | * signal, from the Gst Bus or for error in the FS_ERROR domain in GErrors | |
130 | */ | |
131 | ||
132 | typedef enum _FsError | |
133 | { | |
134 | FS_ERROR_CONSTRUCTION = 1, | |
135 | FS_ERROR_INTERNAL, | |
136 | FS_ERROR_INVALID_ARGUMENTS = 100, | |
137 | FS_ERROR_NETWORK, | |
138 | FS_ERROR_NOT_IMPLEMENTED, | |
139 | FS_ERROR_NEGOTIATION_FAILED, | |
140 | FS_ERROR_UNKNOWN_CODEC, | |
141 | FS_ERROR_NO_CODECS, | |
142 | FS_ERROR_NO_CODECS_LEFT, | |
143 | FS_ERROR_CONNECTION_FAILED, | |
144 | FS_ERROR_DISPOSED, | |
145 | FS_ERROR_ALREADY_EXISTS | |
146 | } FsError; | |
147 | ||
148 | /** | |
149 | * FS_ERROR: | |
150 | * | |
151 | * This quark is used to denote errors coming from Farstream objects | |
152 | */ | |
153 | ||
154 | #define FS_ERROR (fs_error_quark ()) | |
155 | ||
156 | /** | |
157 | * FS_ERROR_IS_FATAL: | |
158 | * @error: a #FsError | |
159 | * | |
160 | * Tells the programmer if an error if fatal or not, if it returns %TRUE, | |
161 | * the error is fatal, and the object that created it should | |
162 | * be discarded. It returns %FALSE otherwise. | |
163 | */ | |
164 | ||
165 | #define FS_ERROR_IS_FATAL(error) \ | |
166 | (error < 100) | |
167 | ||
168 | GQuark fs_error_quark (void); | |
169 | ||
170 | /* virtual class function wrappers */ | |
171 | FsSession *fs_conference_new_session (FsConference *conference, | |
172 | FsMediaType media_type, | |
173 | GError **error); | |
174 | ||
175 | FsParticipant *fs_conference_new_participant (FsConference *conference, | |
176 | GError **error); | |
177 | ||
178 | ||
179 | G_END_DECLS | |
180 | ||
181 | #endif /* __FS_CONFERENCE_H__ */ | |
182 | ||
183 |
0 | /* | |
1 | * Farstream - Recursive element addition notifier | |
2 | * | |
3 | * Copyright 2007-2008 Collabora Ltd. | |
4 | * @author: Olivier Crete <olivier.crete@collabora.co.uk> | |
5 | * Copyright 2007-2008 Nokia Corp. | |
6 | * | |
7 | * This library is free software; you can redistribute it and/or | |
8 | * modify it under the terms of the GNU Lesser General Public | |
9 | * License as published by the Free Software Foundation; either | |
10 | * version 2.1 of the License, or (at your option) any later version. | |
11 | * | |
12 | * This library is distributed in the hope that it will be useful, | |
13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
15 | * Lesser General Public License for more details. | |
16 | * | |
17 | * You should have received a copy of the GNU Lesser General Public | |
18 | * License along with this library; if not, write to the Free Software | |
19 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA | |
20 | */ | |
21 | ||
22 | ||
23 | /** | |
24 | * SECTION:fs-element-added-notifier | |
25 | * @short_description: Recursive element addition notifier | |
26 | * | |
27 | * This object can be attach to any #GstBin and will emit a the | |
28 | * #FsElementAddedNotifier::element-added signal for every element inside the | |
29 | * #GstBin or any sub-bin and any element added in the future to the bin or | |
30 | * its sub-bins. There is also a utility method to have it used to | |
31 | * set the properties of elements based on a GKeyfile. | |
32 | */ | |
33 | ||
34 | #ifdef HAVE_CONFIG_H | |
35 | # include <config.h> | |
36 | #endif | |
37 | ||
38 | #include "fs-element-added-notifier.h" | |
39 | ||
40 | #include <stdlib.h> | |
41 | ||
42 | #include "fs-utils.h" | |
43 | ||
44 | #include "fs-marshal.h" | |
45 | ||
46 | ||
47 | /* Signals */ | |
48 | enum | |
49 | { | |
50 | ELEMENT_ADDED, | |
51 | LAST_SIGNAL | |
52 | }; | |
53 | ||
54 | #define FS_ELEMENT_ADDED_NOTIFIER_GET_PRIVATE(o) \ | |
55 | (G_TYPE_INSTANCE_GET_PRIVATE ((o), FS_TYPE_ELEMENT_ADDED_NOTIFIER, \ | |
56 | FsElementAddedNotifierPrivate)) | |
57 | ||
58 | struct _FsElementAddedNotifierPrivate { | |
59 | GList *keyfiles; | |
60 | }; | |
61 | ||
62 | static void _element_added_callback (GstBin *parent, GstElement *element, | |
63 | gpointer user_data); | |
64 | ||
65 | static void fs_element_added_notifier_finalize (GObject *object); | |
66 | ||
67 | ||
68 | G_DEFINE_TYPE(FsElementAddedNotifier, fs_element_added_notifier, G_TYPE_OBJECT); | |
69 | ||
70 | static guint signals[LAST_SIGNAL] = { 0 }; | |
71 | ||
72 | static void | |
73 | fs_element_added_notifier_class_init (FsElementAddedNotifierClass *klass) | |
74 | { | |
75 | GObjectClass *gobject_class; | |
76 | ||
77 | gobject_class = (GObjectClass *) klass; | |
78 | ||
79 | gobject_class->finalize = fs_element_added_notifier_finalize; | |
80 | ||
81 | /** | |
82 | * FsElementAddedNotifier::element-added: | |
83 | * @self: #FsElementAddedNotifier that emitted the signal | |
84 | * @bin: The #GstBin to which this object was added | |
85 | * @element: The #GstElement that was added | |
86 | * | |
87 | * This signal is emitted when an element is added to a #GstBin that was added | |
88 | * to this object or one of its sub-bins. | |
89 | * Be careful, there is no guarantee that this will be emitted on your | |
90 | * main thread, it will be emitted in the thread that added the element. | |
91 | * The bin may be %NULL if this is the top-level bin. | |
92 | */ | |
93 | signals[ELEMENT_ADDED] = g_signal_new ("element-added", | |
94 | G_TYPE_FROM_CLASS (klass), | |
95 | G_SIGNAL_RUN_LAST, | |
96 | 0, | |
97 | NULL, | |
98 | NULL, | |
99 | _fs_marshal_VOID__OBJECT_OBJECT, | |
100 | G_TYPE_NONE, 2, GST_TYPE_BIN, GST_TYPE_ELEMENT); | |
101 | ||
102 | g_type_class_add_private (klass, sizeof (FsElementAddedNotifierPrivate)); | |
103 | } | |
104 | ||
105 | ||
106 | static void | |
107 | fs_element_added_notifier_init (FsElementAddedNotifier *notifier) | |
108 | { | |
109 | notifier->priv = FS_ELEMENT_ADDED_NOTIFIER_GET_PRIVATE(notifier); | |
110 | } | |
111 | ||
112 | ||
113 | ||
114 | static void | |
115 | fs_element_added_notifier_finalize (GObject *object) | |
116 | { | |
117 | FsElementAddedNotifier *self = FS_ELEMENT_ADDED_NOTIFIER (object); | |
118 | ||
119 | g_list_foreach (self->priv->keyfiles, (GFunc) g_key_file_free, NULL); | |
120 | g_list_free (self->priv->keyfiles); | |
121 | self->priv->keyfiles = NULL; | |
122 | } | |
123 | ||
124 | /** | |
125 | * fs_element_added_notifier_new: | |
126 | * | |
127 | * Creates a new #FsElementAddedNotifier object | |
128 | * | |
129 | * Returns: the newly-created #FsElementAddedNotifier | |
130 | */ | |
131 | ||
132 | FsElementAddedNotifier * | |
133 | fs_element_added_notifier_new (void) | |
134 | { | |
135 | return (FsElementAddedNotifier *) | |
136 | g_object_new (FS_TYPE_ELEMENT_ADDED_NOTIFIER, NULL); | |
137 | } | |
138 | ||
139 | /** | |
140 | * fs_element_added_notifier_add: | |
141 | * @notifier: a #FsElementAddedNotifier | |
142 | * @bin: A #GstBin to watch to added elements | |
143 | * | |
144 | * Add a #GstBin to on which the #FsElementAddedNotifier::element-added signal | |
145 | * will be called on every element and sub-element present and added in the | |
146 | * future. | |
147 | */ | |
148 | ||
149 | void | |
150 | fs_element_added_notifier_add (FsElementAddedNotifier *notifier, | |
151 | GstBin *bin) | |
152 | { | |
153 | g_return_if_fail (notifier && FS_IS_ELEMENT_ADDED_NOTIFIER (notifier)); | |
154 | g_return_if_fail (bin && GST_IS_BIN (bin)); | |
155 | ||
156 | _element_added_callback (NULL, GST_ELEMENT_CAST (bin), notifier); | |
157 | } | |
158 | ||
159 | ||
160 | static void | |
161 | _bin_unparented_cb (GstObject *object, GstObject *parent, gpointer user_data) | |
162 | { | |
163 | GstIterator *iter = NULL; | |
164 | gboolean done; | |
165 | ||
166 | /* Return if there was no handler connected */ | |
167 | if (g_signal_handlers_disconnect_by_func (object, _element_added_callback, | |
168 | user_data) == 0) | |
169 | return; | |
170 | ||
171 | iter = gst_bin_iterate_elements (GST_BIN (object)); | |
172 | ||
173 | done = FALSE; | |
174 | while (!done) | |
175 | { | |
176 | gpointer item; | |
177 | ||
178 | switch (gst_iterator_next (iter, &item)) { | |
179 | case GST_ITERATOR_OK: | |
180 | if (GST_IS_BIN (item)) | |
181 | _bin_unparented_cb (GST_OBJECT (item), object, user_data); | |
182 | gst_object_unref (item); | |
183 | break; | |
184 | case GST_ITERATOR_RESYNC: | |
185 | // We don't rollback anything, we just ignore already processed ones | |
186 | gst_iterator_resync (iter); | |
187 | break; | |
188 | case GST_ITERATOR_ERROR: | |
189 | g_error ("Wrong parameters were given?"); | |
190 | done = TRUE; | |
191 | break; | |
192 | case GST_ITERATOR_DONE: | |
193 | done = TRUE; | |
194 | break; | |
195 | } | |
196 | } | |
197 | ||
198 | gst_iterator_free (iter); | |
199 | } | |
200 | ||
201 | ||
202 | /** | |
203 | * fs_element_added_notifier_remove: | |
204 | * @notifier: a #FsElementAddedNotifier | |
205 | * @bin: A #GstBin to stop watching | |
206 | * | |
207 | * Stop watching the passed bin and its subbins. | |
208 | * | |
209 | * Returns: %TRUE if the #GstBin was being watched, %FALSE otherwise | |
210 | */ | |
211 | ||
212 | gboolean | |
213 | fs_element_added_notifier_remove (FsElementAddedNotifier *notifier, | |
214 | GstBin *bin) | |
215 | { | |
216 | g_return_val_if_fail (FS_IS_ELEMENT_ADDED_NOTIFIER (notifier), FALSE); | |
217 | g_return_val_if_fail (GST_IS_BIN (bin), FALSE); | |
218 | ||
219 | if (g_signal_handler_find (bin, | |
220 | G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA, | |
221 | 0, 0, NULL, /* id, detail, closure */ | |
222 | _element_added_callback, notifier) != 0) | |
223 | { | |
224 | _bin_unparented_cb (GST_OBJECT (bin), NULL, notifier); | |
225 | return TRUE; | |
226 | } | |
227 | else | |
228 | { | |
229 | return FALSE; | |
230 | } | |
231 | } | |
232 | ||
233 | ||
234 | #if 1 | |
235 | # define DEBUG(...) do {} while (0) | |
236 | #else | |
237 | # define DEBUG g_debug | |
238 | #endif | |
239 | ||
240 | static void | |
241 | _bin_added_from_keyfile (FsElementAddedNotifier *notifier, GstBin *bin, | |
242 | GstElement *element, gpointer user_data) | |
243 | { | |
244 | GKeyFile *keyfile = user_data; | |
245 | const gchar *name = NULL; | |
246 | gchar *free_name = NULL; | |
247 | gchar **keys; | |
248 | gint i; | |
249 | GstElementFactory *factory = gst_element_get_factory (element); | |
250 | ||
251 | if (factory) | |
252 | { | |
253 | name = gst_plugin_feature_get_name (GST_PLUGIN_FEATURE (factory)); | |
254 | if (name && !g_key_file_has_group (keyfile, name)) | |
255 | name = NULL; | |
256 | } | |
257 | ||
258 | if (!name) | |
259 | { | |
260 | GST_OBJECT_LOCK (element); | |
261 | if (GST_OBJECT_NAME (element) && | |
262 | g_key_file_has_group (keyfile, GST_OBJECT_NAME (element))) | |
263 | name = free_name = g_strdup (GST_OBJECT_NAME (element)); | |
264 | GST_OBJECT_UNLOCK (element); | |
265 | } | |
266 | ||
267 | if (!name) | |
268 | return; | |
269 | ||
270 | DEBUG ("Found config for %s", name); | |
271 | keys = g_key_file_get_keys (keyfile, name, NULL, NULL); | |
272 | ||
273 | for (i = 0; keys[i]; i++) | |
274 | { | |
275 | GParamSpec *param_spec; | |
276 | GValue prop_value = { 0 }; | |
277 | gchar *str_value; | |
278 | ||
279 | DEBUG ("getting %s", keys[i]); | |
280 | param_spec = g_object_class_find_property (G_OBJECT_GET_CLASS(element), | |
281 | keys[i]); | |
282 | ||
283 | if (!param_spec) | |
284 | { | |
285 | DEBUG ("Property %s does not exist in element %s, ignoring", | |
286 | keys[i], name); | |
287 | continue; | |
288 | } | |
289 | ||
290 | g_value_init (&prop_value, param_spec->value_type); | |
291 | ||
292 | str_value = g_key_file_get_value (keyfile, name, keys[i], NULL); | |
293 | if (str_value && gst_value_deserialize (&prop_value, str_value)) | |
294 | { | |
295 | DEBUG ("Setting %s to on %s", keys[i], name); | |
296 | g_object_set_property (G_OBJECT (element), keys[i], &prop_value); | |
297 | } | |
298 | else | |
299 | { | |
300 | DEBUG ("Could not read value for property %s", keys[i]); | |
301 | } | |
302 | g_free (str_value); | |
303 | g_value_unset (&prop_value); | |
304 | } | |
305 | ||
306 | g_strfreev (keys); | |
307 | g_free (free_name); | |
308 | } | |
309 | ||
310 | ||
311 | /** | |
312 | * fs_element_added_notifier_set_properties_from_keyfile: | |
313 | * @notifier: a #FsElementAddedNotifier | |
314 | * @keyfile: a #GKeyFile | |
315 | * | |
316 | * Using a #GKeyFile where the groups are the element's type or name | |
317 | * and the key=value are the property and its value, this function | |
318 | * will set the properties on the elements added to this object after | |
319 | * this function has been called. It will take ownership of the | |
320 | * GKeyFile structure. It will first try the group as the element type, if that | |
321 | * does not match, it will check its name. | |
322 | */ | |
323 | void | |
324 | fs_element_added_notifier_set_properties_from_keyfile ( | |
325 | FsElementAddedNotifier *notifier, | |
326 | GKeyFile *keyfile) | |
327 | { | |
328 | g_return_if_fail (FS_IS_ELEMENT_ADDED_NOTIFIER (notifier)); | |
329 | g_return_if_fail (keyfile); | |
330 | ||
331 | g_signal_connect (notifier, "element-added", | |
332 | G_CALLBACK (_bin_added_from_keyfile), keyfile); | |
333 | ||
334 | notifier->priv->keyfiles = | |
335 | g_list_prepend (notifier->priv->keyfiles, keyfile); | |
336 | } | |
337 | ||
338 | ||
339 | /** | |
340 | * fs_element_added_notifier_set_properties_from_file: | |
341 | * @notifier: a #FsElementAddedNotifier | |
342 | * @filename: The name of the keyfile to use | |
343 | * @error: location of a #GError, or %NULL if no error occured | |
344 | * | |
345 | * Same as fs_element_added_notifier_set_properties_from_keyfile() but using | |
346 | * the name of the file to load instead of the #GKeyFile directly. | |
347 | * | |
348 | * Returns: %TRUE if the file was successfully loaded, %FALSE otherwise | |
349 | */ | |
350 | gboolean | |
351 | fs_element_added_notifier_set_properties_from_file ( | |
352 | FsElementAddedNotifier *notifier, | |
353 | const gchar *filename, | |
354 | GError **error) | |
355 | { | |
356 | GKeyFile *keyfile = g_key_file_new (); | |
357 | ||
358 | if (!g_key_file_load_from_file (keyfile, filename, G_KEY_FILE_NONE, error)) | |
359 | { | |
360 | g_key_file_free (keyfile); | |
361 | return FALSE; | |
362 | } | |
363 | ||
364 | fs_element_added_notifier_set_properties_from_keyfile(notifier, keyfile); | |
365 | ||
366 | return TRUE; | |
367 | } | |
368 | ||
369 | static void | |
370 | _element_added_callback (GstBin *parent, GstElement *element, | |
371 | gpointer user_data) | |
372 | { | |
373 | FsElementAddedNotifier *notifier = FS_ELEMENT_ADDED_NOTIFIER (user_data); | |
374 | ||
375 | if (GST_IS_BIN (element)) { | |
376 | GstIterator *iter = NULL; | |
377 | gboolean done; | |
378 | ||
379 | g_signal_connect_object (element, "element-added", | |
380 | G_CALLBACK (_element_added_callback), notifier, 0); | |
381 | ||
382 | if (parent) | |
383 | g_signal_connect_object (element, "parent-unset", | |
384 | G_CALLBACK (_bin_unparented_cb), notifier, 0); | |
385 | ||
386 | iter = gst_bin_iterate_elements (GST_BIN (element)); | |
387 | ||
388 | done = FALSE; | |
389 | while (!done) | |
390 | { | |
391 | gpointer item = NULL; | |
392 | ||
393 | switch (gst_iterator_next (iter, &item)) { | |
394 | case GST_ITERATOR_OK: | |
395 | /* We make sure the callback has not already been added */ | |
396 | if (g_signal_handler_find (item, | |
397 | G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA, | |
398 | 0, 0, NULL, /* id, detail, closure */ | |
399 | _element_added_callback, notifier) == 0) | |
400 | _element_added_callback (GST_BIN_CAST (element), item, notifier); | |
401 | gst_object_unref (item); | |
402 | break; | |
403 | case GST_ITERATOR_RESYNC: | |
404 | // We don't rollback anything, we just ignore already processed ones | |
405 | gst_iterator_resync (iter); | |
406 | break; | |
407 | case GST_ITERATOR_ERROR: | |
408 | g_error ("Wrong parameters were given?"); | |
409 | done = TRUE; | |
410 | break; | |
411 | case GST_ITERATOR_DONE: | |
412 | done = TRUE; | |
413 | break; | |
414 | } | |
415 | } | |
416 | ||
417 | gst_iterator_free (iter); | |
418 | } | |
419 | ||
420 | g_signal_emit (notifier, signals[ELEMENT_ADDED], 0, parent, element); | |
421 | } | |
422 | ||
423 | ||
424 | /** | |
425 | * fs_element_added_notifier_set_default_properties: | |
426 | * @notifier: a #FsElementAddedNotifier | |
427 | * @element: Element for which to set the default codec | |
428 | * preferences | |
429 | * | |
430 | * Same as first calling fs_utils_get_default_element_properties() and using | |
431 | * the result with | |
432 | * fs_element_added_notifier_set_properties_from_keyfile() . | |
433 | * | |
434 | * This is binding friendly (since GKeyFile doesn't have a boxed type). | |
435 | */ | |
436 | void | |
437 | fs_element_added_notifier_set_default_properties ( | |
438 | FsElementAddedNotifier *notifier, | |
439 | GstElement *element) | |
440 | { | |
441 | GKeyFile *keyfile = fs_utils_get_default_element_properties (element); | |
442 | ||
443 | if (!keyfile) | |
444 | return; | |
445 | ||
446 | fs_element_added_notifier_set_properties_from_keyfile(notifier, keyfile); | |
447 | } |
0 | /* | |
1 | * Farstream - Recursive element addition notifier | |
2 | * | |
3 | * Copyright 2007-2008 Collabora Ltd. | |
4 | * @author: Olivier Crete <olivier.crete@collabora.co.uk> | |
5 | * Copyright 2007-2008 Nokia Corp. | |
6 | * | |
7 | * This library is free software; you can redistribute it and/or | |
8 | * modify it under the terms of the GNU Lesser General Public | |
9 | * License as published by the Free Software Foundation; either | |
10 | * version 2.1 of the License, or (at your option) any later version. | |
11 | * | |
12 | * This library is distributed in the hope that it will be useful, | |
13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
15 | * Lesser General Public License for more details. | |
16 | * | |
17 | * You should have received a copy of the GNU Lesser General Public | |
18 | * License along with this library; if not, write to the Free Software | |
19 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA | |
20 | */ | |
21 | ||
22 | #ifndef __FS_ELEMENT_ADDED_NOTIFIER_H__ | |
23 | #define __FS_ELEMENT_ADDED_NOTIFIER_H__ | |
24 | ||
25 | #include <gst/gst.h> | |
26 | ||
27 | G_BEGIN_DECLS | |
28 | ||
29 | ||
30 | /* TYPE MACROS */ | |
31 | #define FS_TYPE_ELEMENT_ADDED_NOTIFIER \ | |
32 | (fs_element_added_notifier_get_type ()) | |
33 | #define FS_ELEMENT_ADDED_NOTIFIER(obj) \ | |
34 | (G_TYPE_CHECK_INSTANCE_CAST((obj), FS_TYPE_ELEMENT_ADDED_NOTIFIER, \ | |
35 | FsElementAddedNotifier)) | |
36 | #define FS_ELEMENT_ADDED_NOTIFIER_CLASS(klass) \ | |
37 | (G_TYPE_CHECK_CLASS_CAST((klass), FS_TYPE_ELEMENT_ADDED_NOTIFIER, \ | |
38 | FsElementAddedNotifierClass)) | |
39 | #define FS_IS_ELEMENT_ADDED_NOTIFIER(obj) \ | |
40 | (G_TYPE_CHECK_INSTANCE_TYPE((obj), FS_TYPE_ELEMENT_ADDED_NOTIFIER)) | |
41 | #define FS_IS_ELEMENT_ADDED_NOTIFIER_CLASS(klass) \ | |
42 | (G_TYPE_CHECK_CLASS_TYPE((klass), FS_TYPE_ELEMENT_ADDED_NOTIFIER)) | |
43 | #define FS_ELEMENT_ADDED_NOTIFIER_GET_CLASS(obj) \ | |
44 | (G_TYPE_INSTANCE_GET_CLASS ((obj), FS_TYPE_ELEMENT_ADDED_NOTIFIER, \ | |
45 | FsElementAddedNotifierClass)) | |
46 | ||
47 | ||
48 | typedef struct _FsElementAddedNotifier FsElementAddedNotifier; | |
49 | typedef struct _FsElementAddedNotifierClass FsElementAddedNotifierClass; | |
50 | typedef struct _FsElementAddedNotifierPrivate FsElementAddedNotifierPrivate; | |
51 | ||
52 | /** | |
53 | * FsElementAddedNotifier: | |
54 | * | |
55 | * All members are private | |
56 | */ | |
57 | ||
58 | struct _FsElementAddedNotifier | |
59 | { | |
60 | GObject parent; | |
61 | ||
62 | /*< private >*/ | |
63 | ||
64 | FsElementAddedNotifierPrivate *priv; | |
65 | }; | |
66 | ||
67 | /** | |
68 | * FsElementAddedNotifierClass: | |
69 | * @parent_class: the #GObjectClass parent | |
70 | * | |
71 | * All members are private | |
72 | */ | |
73 | struct _FsElementAddedNotifierClass | |
74 | { | |
75 | GObjectClass parent_class; | |
76 | }; | |
77 | ||
78 | ||
79 | GType fs_element_added_notifier_get_type (void); | |
80 | ||
81 | FsElementAddedNotifier *fs_element_added_notifier_new (void); | |
82 | ||
83 | void fs_element_added_notifier_add (FsElementAddedNotifier *notifier, | |
84 | GstBin *bin); | |
85 | ||
86 | gboolean fs_element_added_notifier_remove (FsElementAddedNotifier *notifier, | |
87 | GstBin *bin); | |
88 | ||
89 | void fs_element_added_notifier_set_properties_from_keyfile ( | |
90 | FsElementAddedNotifier *notifier, | |
91 | GKeyFile *keyfile); | |
92 | ||
93 | gboolean fs_element_added_notifier_set_properties_from_file ( | |
94 | FsElementAddedNotifier *notifier, | |
95 | const gchar *filename, | |
96 | GError **error); | |
97 | ||
98 | void fs_element_added_notifier_set_default_properties ( | |
99 | FsElementAddedNotifier *notifier, | |
100 | GstElement *element); | |
101 | ||
102 | G_END_DECLS | |
103 | ||
104 | #endif /* __FS_ELEMENT_ADDED_NOTIFIER_H__ */ |
0 | /* | |
1 | * Farstream - Farstream Participant | |
2 | * | |
3 | * Copyright 2007 Collabora Ltd. | |
4 | * @author: Philippe Kalaf <philippe.kalaf@collabora.co.uk> | |
5 | * Copyright 2007 Nokia Corp. | |
6 | * | |
7 | * fs-participant.c - A Farstream Participant gobject (base implementation) | |
8 | * | |
9 | * This library is free software; you can redistribute it and/or | |
10 | * modify it under the terms of the GNU Lesser General Public | |
11 | * License as published by the Free Software Foundation; either | |
12 | * version 2.1 of the License, or (at your option) any later version. | |
13 | * | |
14 | * This library is distributed in the hope that it will be useful, | |
15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
17 | * Lesser General Public License for more details. | |
18 | * | |
19 | * You should have received a copy of the GNU Lesser General Public | |
20 | * License along with this library; if not, write to the Free Software | |
21 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA | |
22 | */ | |
23 | ||
24 | /** | |
25 | * SECTION:fs-participant | |
26 | * @short_description: A participant in a conference | |
27 | * | |
28 | * This object is the base implementation of a Farstream Participant. It needs to be | |
29 | * derived and implemented by a farstream conference gstreamer element. A | |
30 | * participant represents any source of media in a conference. This could be a | |
31 | * human-participant or an automaton. | |
32 | */ | |
33 | ||
34 | #ifdef HAVE_CONFIG_H | |
35 | #include "config.h" | |
36 | #endif | |
37 | ||
38 | #include "fs-participant.h" | |
39 | #include "fs-enumtypes.h" | |
40 | #include "fs-marshal.h" | |
41 | ||
42 | /* Signals */ | |
43 | enum | |
44 | { | |
45 | LAST_SIGNAL | |
46 | }; | |
47 | ||
48 | /* props */ | |
49 | enum | |
50 | { | |
51 | PROP_0 | |
52 | }; | |
53 | ||
54 | /* | |
55 | struct _FsParticipantPrivate | |
56 | { | |
57 | }; | |
58 | */ | |
59 | ||
60 | G_DEFINE_ABSTRACT_TYPE(FsParticipant, fs_participant, GST_TYPE_OBJECT); | |
61 | ||
62 | #define FS_PARTICIPANT_GET_PRIVATE(o) \ | |
63 | (G_TYPE_INSTANCE_GET_PRIVATE ((o), FS_TYPE_PARTICIPANT, \ | |
64 | FsParticipantPrivate)) | |
65 | ||
66 | static void fs_participant_finalize (GObject *object); | |
67 | ||
68 | ||
69 | // static guint signals[LAST_SIGNAL] = { 0 }; | |
70 | ||
71 | static void | |
72 | fs_participant_class_init (FsParticipantClass *klass) | |
73 | { | |
74 | GObjectClass *gobject_class; | |
75 | ||
76 | gobject_class = (GObjectClass *) klass; | |
77 | ||
78 | gobject_class->finalize = fs_participant_finalize; | |
79 | ||
80 | // g_type_class_add_private (klass, sizeof (FsParticipantPrivate)); | |
81 | } | |
82 | ||
83 | static void | |
84 | fs_participant_init (FsParticipant *self) | |
85 | { | |
86 | //self->priv = FS_PARTICIPANT_GET_PRIVATE (self); | |
87 | self->mutex = g_mutex_new (); | |
88 | } | |
89 | ||
90 | static void | |
91 | fs_participant_finalize (GObject *object) | |
92 | { | |
93 | FsParticipant *self = FS_PARTICIPANT (object); | |
94 | g_mutex_free (self->mutex); | |
95 | ||
96 | G_OBJECT_CLASS (fs_participant_parent_class)->finalize (object); | |
97 | } |
0 | /* | |
1 | * Farstream - Farstream Participant | |
2 | * | |
3 | * Copyright 2007 Collabora Ltd. | |
4 | * @author: Philippe Kalaf <philippe.kalaf@collabora.co.uk> | |
5 | * Copyright 2007 Nokia Corp. | |
6 | * | |
7 | * fs-participant.h - A Farstream Participant gobject (base implementation) | |
8 | * | |
9 | * This library is free software; you can redistribute it and/or | |
10 | * modify it under the terms of the GNU Lesser General Public | |
11 | * License as published by the Free Software Foundation; either | |
12 | * version 2.1 of the License, or (at your option) any later version. | |
13 | * | |
14 | * This library is distributed in the hope that it will be useful, | |
15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
17 | * Lesser General Public License for more details. | |
18 | * | |
19 | * You should have received a copy of the GNU Lesser General Public | |
20 | * License along with this library; if not, write to the Free Software | |
21 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA | |
22 | */ | |
23 | ||
24 | #ifndef __FS_PARTICIPANT_H__ | |
25 | #define __FS_PARTICIPANT_H__ | |
26 | ||
27 | #include <gst/gst.h> | |
28 | ||
29 | G_BEGIN_DECLS | |
30 | ||
31 | /* TYPE MACROS */ | |
32 | #define FS_TYPE_PARTICIPANT \ | |
33 | (fs_participant_get_type ()) | |
34 | #define FS_PARTICIPANT(obj) \ | |
35 | (G_TYPE_CHECK_INSTANCE_CAST((obj), FS_TYPE_PARTICIPANT, FsParticipant)) | |
36 | #define FS_PARTICIPANT_CLASS(klass) \ | |
37 | (G_TYPE_CHECK_CLASS_CAST((klass), FS_TYPE_PARTICIPANT, FsParticipantClass)) | |
38 | #define FS_IS_PARTICIPANT(obj) \ | |
39 | (G_TYPE_CHECK_INSTANCE_TYPE((obj), FS_TYPE_PARTICIPANT)) | |
40 | #define FS_IS_PARTICIPANT_CLASS(klass) \ | |
41 | (G_TYPE_CHECK_CLASS_TYPE((klass), FS_TYPE_PARTICIPANT)) | |
42 | #define FS_PARTICIPANT_GET_CLASS(obj) \ | |
43 | (G_TYPE_INSTANCE_GET_CLASS ((obj), FS_TYPE_PARTICIPANT, FsParticipantClass)) | |
44 | #define FS_PARTICIPANT_CAST(obj) ((FsParticipant *) (obj)) | |
45 | ||
46 | typedef struct _FsParticipant FsParticipant; | |
47 | typedef struct _FsParticipantClass FsParticipantClass; | |
48 | typedef struct _FsParticipantPrivate FsParticipantPrivate; | |
49 | ||
50 | /** | |
51 | * FsParticipantClass: | |
52 | * @parent_class: Our parent | |
53 | * | |
54 | * The FsParticipant class has no virtual methods to implement, | |
55 | * but you may want to override the properties or attach more date to it | |
56 | */ | |
57 | ||
58 | struct _FsParticipantClass | |
59 | { | |
60 | GstObjectClass parent_class; | |
61 | ||
62 | /* virtual functions */ | |
63 | ||
64 | /*< private >*/ | |
65 | FsParticipantPrivate *priv; | |
66 | gpointer _padding[8]; | |
67 | }; | |
68 | ||
69 | /** | |
70 | * FsParticipant: | |
71 | * | |
72 | * All members are private (access them using the properties) | |
73 | */ | |
74 | struct _FsParticipant | |
75 | { | |
76 | GstObject parent; | |
77 | ||
78 | /*< private >*/ | |
79 | ||
80 | GMutex *mutex; | |
81 | ||
82 | FsParticipantPrivate *priv; | |
83 | ||
84 | gpointer _padding[8]; | |
85 | }; | |
86 | ||
87 | /** | |
88 | * FS_PARTICIPANT_DATA_LOCK | |
89 | * @participant: A #FsParticipant | |
90 | * | |
91 | * Locks the participant for data set with g_object_set_data() or | |
92 | * g_object_set_qdata(). | |
93 | */ | |
94 | ||
95 | #define FS_PARTICIPANT_DATA_LOCK(participant) \ | |
96 | g_mutex_lock ((participant)->mutex) | |
97 | ||
98 | /** | |
99 | * FS_PARTICIPANT_DATA_UNLOCK | |
100 | * @participant: A #FsParticipant | |
101 | * | |
102 | * Unlocks the participant for data set with g_object_set_data() or | |
103 | * g_object_set_qdata(). | |
104 | */ | |
105 | ||
106 | #define FS_PARTICIPANT_DATA_UNLOCK(participant) \ | |
107 | g_mutex_unlock ((participant)->mutex) | |
108 | ||
109 | GType fs_participant_get_type (void); | |
110 | ||
111 | G_END_DECLS | |
112 | ||
113 | #endif /* __FS_PARTICIPANT_H__ */ |
0 | /* | |
1 | * fs-plugin.c - Source for farstream plugin infrastructure | |
2 | * | |
3 | * Farstream Voice+Video library | |
4 | * Copyright (c) 2005 INdT. | |
5 | * @author Andre Moreira Magalhaes <andre.magalhaes@indt.org.br> | |
6 | * Copyright 2005-2007 Collabora Ltd. | |
7 | * Copyright 2005-2007 Nokia Corp. | |
8 | * @author Rob Taylor <rob.taylor@collabora.co.uk> | |
9 | * @author: Olivier Crete <olivier.crete@collabora.co.uk> | |
10 | * | |
11 | * | |
12 | * This library is free software; you can redistribute it and/or | |
13 | * modify it under the terms of the GNU Lesser General Public | |
14 | * License as published by the Free Software Foundation; either | |
15 | * version 2.1 of the License, or (at your option) any later version. | |
16 | * | |
17 | * This library is distributed in the hope that it will be useful, | |
18 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
19 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
20 | * Lesser General Public License for more details. | |
21 | * | |
22 | * You should have received a copy of the GNU Lesser General Public | |
23 | * License along with this library; if not, write to the Free Software | |
24 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA | |
25 | */ | |
26 | ||
27 | #ifdef HAVE_CONFIG_H | |
28 | #include "config.h" | |
29 | #endif | |
30 | ||
31 | #include "fs-plugin.h" | |
32 | ||
33 | #include <string.h> | |
34 | ||
35 | #include "fs-conference.h" | |
36 | #include "fs-private.h" | |
37 | ||
38 | #define GST_CAT_DEFAULT fs_conference_debug | |
39 | ||
40 | /** | |
41 | * SECTION:fs-plugin | |
42 | * @short_description: A class for defining Farstream plugins | |
43 | * | |
44 | * This class is a generic class to load GType plugins based on their name. | |
45 | * With this simple class, you can only have one type per plugin. | |
46 | */ | |
47 | ||
48 | #define FS_PLUGIN_GET_PRIVATE(o) \ | |
49 | (G_TYPE_INSTANCE_GET_PRIVATE ((o), FS_TYPE_PLUGIN, FsPluginPrivate)) | |
50 | ||
51 | static gboolean fs_plugin_load (GTypeModule *module); | |
52 | ||
53 | ||
54 | static GStaticMutex mutex = G_STATIC_MUTEX_INIT; | |
55 | static gchar **search_paths = NULL; | |
56 | static GList *plugins = NULL; | |
57 | ||
58 | struct _FsPluginPrivate | |
59 | { | |
60 | GModule *handle; | |
61 | }; | |
62 | ||
63 | G_DEFINE_TYPE(FsPlugin, fs_plugin, G_TYPE_TYPE_MODULE); | |
64 | ||
65 | static void | |
66 | fs_plugin_search_path_init (void) | |
67 | { | |
68 | const gchar *env; | |
69 | ||
70 | if (search_paths) | |
71 | return; | |
72 | ||
73 | env = g_getenv ("FS_PLUGIN_PATH"); | |
74 | ||
75 | if (env == NULL) | |
76 | { | |
77 | search_paths = g_new (gchar *, 2); | |
78 | search_paths[0] = g_strdup (FS_PLUGIN_PATH); | |
79 | search_paths[1] = NULL; | |
80 | return; | |
81 | } | |
82 | else | |
83 | { | |
84 | gchar *path; | |
85 | ||
86 | path = g_strjoin (":", env, FS_PLUGIN_PATH, NULL); | |
87 | search_paths = g_strsplit (path, ":", -1); | |
88 | g_free (path); | |
89 | } | |
90 | } | |
91 | ||
92 | static void | |
93 | fs_plugin_class_init (FsPluginClass * klass) | |
94 | { | |
95 | GTypeModuleClass *module_class = G_TYPE_MODULE_CLASS (klass); | |
96 | ||
97 | module_class->load = fs_plugin_load; | |
98 | ||
99 | g_type_class_add_private (klass, sizeof (FsPluginPrivate)); | |
100 | ||
101 | /* Calling from class initializer so it only gets init'ed once */ | |
102 | fs_plugin_search_path_init (); | |
103 | } | |
104 | ||
105 | ||
106 | ||
107 | static void | |
108 | fs_plugin_init (FsPlugin * plugin) | |
109 | { | |
110 | /* member init */ | |
111 | plugin->priv = FS_PLUGIN_GET_PRIVATE (plugin); | |
112 | plugin->priv->handle = NULL; | |
113 | } | |
114 | ||
115 | static gboolean fs_plugin_load (GTypeModule *module) | |
116 | { | |
117 | FsPlugin *plugin = FS_PLUGIN(module); | |
118 | gchar **search_path = NULL; | |
119 | gchar *path=NULL; | |
120 | ||
121 | gboolean (*fs_init_plugin) (FsPlugin *); | |
122 | ||
123 | g_return_val_if_fail (plugin != NULL, FALSE); | |
124 | g_return_val_if_fail (plugin->name != NULL && plugin->name[0] != '\0', FALSE); | |
125 | ||
126 | for (search_path = search_paths; *search_path; search_path++) { | |
127 | GST_DEBUG("looking for plugins in %s", *search_path); | |
128 | ||
129 | path = g_module_build_path (*search_path, plugin->name); | |
130 | ||
131 | plugin->priv->handle = g_module_open (path, G_MODULE_BIND_LOCAL); | |
132 | GST_INFO ("opening module %s: %s\n", path, | |
133 | (plugin->priv->handle != NULL) ? "succeeded" : g_module_error ()); | |
134 | g_free (path); | |
135 | ||
136 | if (!plugin->priv->handle) { | |
137 | continue; | |
138 | } | |
139 | ||
140 | else if (!g_module_symbol (plugin->priv->handle, | |
141 | "fs_init_plugin", | |
142 | (gpointer) & fs_init_plugin)) { | |
143 | g_module_close (plugin->priv->handle); | |
144 | plugin->priv->handle = NULL; | |
145 | GST_WARNING ("could not find init function in plugin\n"); | |
146 | continue; | |
147 | } | |
148 | ||
149 | else | |
150 | break; | |
151 | } | |
152 | ||
153 | if (!plugin->priv->handle) { | |
154 | return FALSE; | |
155 | } | |
156 | ||
157 | fs_init_plugin (plugin); | |
158 | if (!plugin->type) { | |
159 | /* TODO error handling (init error or no info defined) */ | |
160 | GST_WARNING ("init error or no info defined"); | |
161 | goto err_close_module; | |
162 | } | |
163 | ||
164 | return TRUE; | |
165 | ||
166 | err_close_module: | |
167 | g_module_close (plugin->priv->handle); | |
168 | return FALSE; | |
169 | ||
170 | } | |
171 | ||
172 | static FsPlugin * | |
173 | fs_plugin_get_by_name_locked (const gchar * name, const gchar * type_suffix) | |
174 | { | |
175 | gchar *fullname; | |
176 | FsPlugin *plugin = NULL; | |
177 | GList *plugin_item; | |
178 | ||
179 | g_return_val_if_fail (name != NULL, NULL); | |
180 | g_return_val_if_fail (type_suffix != NULL, NULL); | |
181 | ||
182 | fullname = g_strdup_printf ("%s-%s",name,type_suffix); | |
183 | ||
184 | for (plugin_item = plugins; | |
185 | plugin_item; | |
186 | plugin_item = g_list_next (plugin_item)) { | |
187 | plugin = plugin_item->data; | |
188 | if (plugin->name == NULL || plugin->name[0] == 0) | |
189 | continue; | |
190 | if (!strcmp (plugin->name, fullname)) { | |
191 | break; | |
192 | } | |
193 | ||
194 | } | |
195 | g_free (fullname); | |
196 | ||
197 | if (plugin_item) | |
198 | return plugin; | |
199 | ||
200 | return NULL; | |
201 | } | |
202 | ||
203 | ||
204 | /** | |
205 | * fs_plugin_create_valist: | |
206 | * @name: The name of the plugin to load | |
207 | * @type_suffix: The type of plugin to load (normally "transmitter") | |
208 | * @error: location of a #GError, or NULL if no error occured | |
209 | * @first_property_name: The name of the first property to be set on the | |
210 | * object | |
211 | * @var_args: The rest of the arguments | |
212 | * | |
213 | * Loads the appropriate plugin if necessary and creates a GObject of | |
214 | * the requested type | |
215 | * | |
216 | * Returns: (transfer full): The object created (or NULL if there is an error) | |
217 | **/ | |
218 | ||
219 | GObject * | |
220 | fs_plugin_create_valist (const gchar *name, const gchar *type_suffix, | |
221 | GError **error, const gchar *first_property_name, va_list var_args) | |
222 | { | |
223 | GObject *object; | |
224 | FsPlugin *plugin; | |
225 | ||
226 | g_return_val_if_fail (name, NULL); | |
227 | g_return_val_if_fail (type_suffix, NULL); | |
228 | ||
229 | _fs_conference_init_debug (); | |
230 | ||
231 | g_static_mutex_lock (&mutex); | |
232 | ||
233 | plugin = fs_plugin_get_by_name_locked (name, type_suffix); | |
234 | ||
235 | if (!plugin) { | |
236 | plugin = g_object_new (FS_TYPE_PLUGIN, NULL); | |
237 | if (!plugin) { | |
238 | g_static_mutex_unlock (&mutex); | |
239 | g_set_error (error, FS_ERROR, FS_ERROR_CONSTRUCTION, | |
240 | "Could not create a fsplugin object"); | |
241 | return NULL; | |
242 | } | |
243 | plugin->name = g_strdup_printf ("%s-%s",name,type_suffix); | |
244 | g_type_module_set_name (G_TYPE_MODULE (plugin), plugin->name); | |
245 | plugins = g_list_append (plugins, plugin); | |
246 | ||
247 | /* We do the use once and then we keep it loaded forever because | |
248 | * the gstreamer libraries can't be unloaded | |
249 | */ | |
250 | if (!g_type_module_use (G_TYPE_MODULE (plugin))) { | |
251 | g_static_mutex_unlock (&mutex); | |
252 | g_set_error (error, FS_ERROR, FS_ERROR_CONSTRUCTION, | |
253 | "Could not load the %s-%s transmitter plugin", name, type_suffix); | |
254 | return NULL; | |
255 | } | |
256 | } | |
257 | ||
258 | g_static_mutex_unlock (&mutex); | |
259 | ||
260 | object = g_object_new_valist (plugin->type, first_property_name, var_args); | |
261 | ||
262 | return object; | |
263 | } | |
264 | ||
265 | ||
266 | /** | |
267 | * fs_plugin_create: | |
268 | * @name: The name of the plugin to load | |
269 | * @type_suffix: The type of plugin to load (normally "transmitter") | |
270 | * @error: location of a #GError, or NULL if no error occured | |
271 | * @first_property_name: The name of the first property to be set on the | |
272 | * object | |
273 | * @...: The NULL-terminated list of properties to set on the transmitter | |
274 | * | |
275 | * Loads the appropriate plugin if necessary and creates a GObject of | |
276 | * the requested type | |
277 | * | |
278 | * Returns: (transfer full): The object created (or NULL if there is an error) | |
279 | **/ | |
280 | ||
281 | GObject * | |
282 | fs_plugin_create (const gchar *name, const gchar *type_suffix, | |
283 | GError **error, const gchar *first_property_name, ...) | |
284 | { | |
285 | va_list var_args; | |
286 | GObject *obj; | |
287 | ||
288 | va_start (var_args, first_property_name); | |
289 | obj = fs_plugin_create_valist (name, type_suffix, error, first_property_name, | |
290 | var_args); | |
291 | va_end (var_args); | |
292 | ||
293 | return obj; | |
294 | } | |
295 | ||
296 | /** | |
297 | * fs_plugin_list_available: | |
298 | * @type_suffix: Get list of plugins with this type suffix | |
299 | * | |
300 | * Gets the list of all available plugins of a certain type | |
301 | * | |
302 | * Returns: (transfer full): a newly allocated NULL terminated array of | |
303 | * strings or %NULL if no strings were found. | |
304 | * It should be freed with g_strfreev(). | |
305 | */ | |
306 | ||
307 | gchar ** | |
308 | fs_plugin_list_available (const gchar *type_suffix) | |
309 | { | |
310 | GPtrArray *list = g_ptr_array_new (); | |
311 | gchar **retval = NULL; | |
312 | gchar **search_path = NULL; | |
313 | GRegex *matcher; | |
314 | GError *error = NULL; | |
315 | gchar *tmp1, *tmp2, *tmp3; | |
316 | ||
317 | g_static_mutex_lock (&mutex); | |
318 | ||
319 | fs_plugin_search_path_init (); | |
320 | ||
321 | tmp1 = g_strdup_printf ("(.+)-%s", type_suffix); | |
322 | tmp2 = g_module_build_path ("", tmp1); | |
323 | tmp3 = g_strconcat ("^", tmp2, NULL); | |
324 | matcher = g_regex_new (tmp3, 0, 0, NULL); | |
325 | g_free (tmp1); | |
326 | g_free (tmp2); | |
327 | g_free (tmp3); | |
328 | ||
329 | ||
330 | for (search_path = search_paths; *search_path; search_path++) | |
331 | { | |
332 | GDir *dir = NULL; | |
333 | const gchar *entry; | |
334 | ||
335 | dir = g_dir_open (*search_path, 0, &error); | |
336 | if (!dir) | |
337 | { | |
338 | GST_WARNING ("Could not open path %s to look for plugins: %s", | |
339 | *search_path, error ? error->message : "Unknown error"); | |
340 | g_clear_error (&error); | |
341 | continue; | |
342 | } | |
343 | ||
344 | while ((entry = g_dir_read_name (dir))) | |
345 | { | |
346 | gchar **matches = NULL; | |
347 | ||
348 | matches = g_regex_split (matcher, entry, 0); | |
349 | ||
350 | if (matches && g_strv_length (matches) == 3) | |
351 | { | |
352 | gint i; | |
353 | gboolean found = FALSE; | |
354 | ||
355 | for (i = 0; i < list->len; i++) | |
356 | { | |
357 | if (!strcmp (matches[1], g_ptr_array_index (list, i))) | |
358 | { | |
359 | found = TRUE; | |
360 | break; | |
361 | } | |
362 | } | |
363 | if (!found) | |
364 | g_ptr_array_add (list, g_strdup (matches[1])); | |
365 | } | |
366 | ||
367 | g_strfreev (matches); | |
368 | } | |
369 | ||
370 | g_dir_close (dir); | |
371 | } | |
372 | ||
373 | g_regex_unref (matcher); | |
374 | ||
375 | if (list->len) | |
376 | { | |
377 | g_ptr_array_add (list, NULL); | |
378 | retval = (gchar**) list->pdata; | |
379 | g_ptr_array_free (list, FALSE); | |
380 | } | |
381 | else | |
382 | { | |
383 | g_ptr_array_free (list, TRUE); | |
384 | } | |
385 | ||
386 | g_static_mutex_unlock (&mutex); | |
387 | ||
388 | return retval; | |
389 | } |
0 | /* | |
1 | * fs-plugin.h - Header for farstream plugin infrastructure | |
2 | * | |
3 | * Farstream Voice+Video library | |
4 | * Copyright (c) 2005 INdT. | |
5 | * @author: Andre Moreira Magalhaes <andre.magalhaes@indt.org.br> | |
6 | * Copyright (c) 2005-2007 Collabora Ltd. | |
7 | * Copyright (c) 2005-2007 Nokia Corp. | |
8 | * @author: Rob Taylor <rob.taylor@collabora.co.uk> | |
9 | * @author: Olivier Crete <olivier.crete@collabora.co.uk> | |
10 | * | |
11 | * This library is free software; you can redistribute it and/or | |
12 | * modify it under the terms of the GNU Lesser General Public | |
13 | * License as published by the Free Software Foundation; either | |
14 | * version 2.1 of the License, or (at your option) any later version. | |
15 | * | |
16 | * This library is distributed in the hope that it will be useful, | |
17 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
18 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
19 | * Lesser General Public License for more details. | |
20 | * | |
21 | * You should have received a copy of the GNU Lesser General Public | |
22 | * License along with this library; if not, write to the Free Software | |
23 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA | |
24 | */ | |
25 | ||
26 | #ifndef __FS_PLUGIN_H__ | |
27 | #define __FS_PLUGIN_H__ | |
28 | ||
29 | #include <glib.h> | |
30 | #include <glib-object.h> | |
31 | #include <gmodule.h> | |
32 | #include <gst/gst.h> | |
33 | ||
34 | #include <stdarg.h> | |
35 | ||
36 | G_BEGIN_DECLS | |
37 | ||
38 | ||
39 | /* TYPE MACROS */ | |
40 | #define FS_TYPE_PLUGIN \ | |
41 | (fs_plugin_get_type ()) | |
42 | #define FS_PLUGIN(obj) \ | |
43 | (G_TYPE_CHECK_INSTANCE_CAST((obj), FS_TYPE_PLUGIN, FsPlugin)) | |
44 | #define FS_PLUGIN_CLASS(klass) \ | |
45 | (G_TYPE_CHECK_CLASS_CAST((klass), FS_TYPE_PLUGIN, FsPluginClass)) | |
46 | #define FS_IS_PLUGIN(obj) \ | |
47 | (G_TYPE_CHECK_INSTANCE_TYPE((obj), FS_TYPE_PLUGIN)) | |
48 | #define FS_IS_PLUGIN_CLASS(klass) \ | |
49 | (G_TYPE_CHECK_CLASS_TYPE((klass), FS_TYPE_PLUGIN)) | |
50 | #define FS_PLUGIN_GET_CLASS(obj) \ | |
51 | (G_TYPE_INSTANCE_GET_CLASS ((obj), FS_TYPE_PLUGIN, FsPluginClass)) | |
52 | ||
53 | /** | |
54 | * FsPlugin: | |
55 | * @parent: the parent object | |
56 | * | |
57 | * This structure represents a plugin, it is opaque. | |
58 | */ | |
59 | ||
60 | typedef struct _FsPlugin FsPlugin; | |
61 | typedef struct _FsPluginClass FsPluginClass; | |
62 | typedef struct _FsPluginPrivate FsPluginPrivate; | |
63 | ||
64 | struct _FsPlugin | |
65 | { | |
66 | GTypeModule parent; | |
67 | ||
68 | /*< private >*/ | |
69 | ||
70 | GType type; | |
71 | ||
72 | gchar *name; /* name of the plugin */ | |
73 | ||
74 | /*< private >*/ | |
75 | ||
76 | FsPluginPrivate *priv; | |
77 | ||
78 | gpointer unused[8]; | |
79 | }; | |
80 | ||
81 | struct _FsPluginClass | |
82 | { | |
83 | GTypeModuleClass parent_class; | |
84 | ||
85 | /*< private >*/ | |
86 | ||
87 | gpointer unused[8]; | |
88 | }; | |
89 | ||
90 | GType fs_plugin_get_type (void); | |
91 | ||
92 | ||
93 | GObject *fs_plugin_create_valist (const gchar *name, | |
94 | const gchar *type_suffix, | |
95 | GError **error, | |
96 | const gchar *first_property_name, | |
97 | va_list var_args); | |
98 | ||
99 | GObject *fs_plugin_create (const gchar *name, | |
100 | const gchar *type_suffix, | |
101 | GError **error, | |
102 | const gchar *first_property_name, ...); | |
103 | ||
104 | gchar **fs_plugin_list_available (const gchar *type_suffix); | |
105 | ||
106 | /** | |
107 | * FS_INIT_PLUGIN: | |
108 | * @type_register_func: A function that register a #GType and returns it | |
109 | * | |
110 | * This macro is used to declare Farstream plugins and must be used once | |
111 | * in any farstream plugin. | |
112 | */ | |
113 | ||
114 | #define FS_INIT_PLUGIN(type_register_func) \ | |
115 | G_MODULE_EXPORT void fs_init_plugin (FsPlugin *plugin) { \ | |
116 | plugin->type = (type_register_func (plugin)); \ | |
117 | } | |
118 | ||
119 | ||
120 | G_END_DECLS | |
121 | #endif | |
122 |
0 | /* | |
1 | * Farstream - Private declarations | |
2 | * | |
3 | * Copyright 2008 Collabora Ltd. | |
4 | * @author: Olivier Crete <olivier.crete@collabora.co.uk> | |
5 | * Copyright 2008 Nokia Corp. | |
6 | * | |
7 | * fs-conference.h - Header file for gstreamer interface to be | |
8 | * implemented by farstream conference elements | |
9 | * | |
10 | * This library is free software; you can redistribute it and/or | |
11 | * modify it under the terms of the GNU Lesser General Public | |
12 | * License as published by the Free Software Foundation; either | |
13 | * version 2.1 of the License, or (at your option) any later version. | |
14 | * | |
15 | * This library is distributed in the hope that it will be useful, | |
16 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
17 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
18 | * Lesser General Public License for more details. | |
19 | * | |
20 | * You should have received a copy of the GNU Lesser General Public | |
21 | * License along with this library; if not, write to the Free Software | |
22 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA | |
23 | */ | |
24 | ||
25 | #ifndef __FS_PRIVATE_H__ | |
26 | #define __FS_PRIVATE_H__ | |
27 | ||
28 | #include <gst/gst.h> | |
29 | ||
30 | G_BEGIN_DECLS | |
31 | ||
32 | void _fs_conference_init_debug (void); | |
33 | ||
34 | GST_DEBUG_CATEGORY_EXTERN (fs_conference_debug); | |
35 | ||
36 | G_END_DECLS | |
37 | ||
38 | #endif /* __FS_PRIVATE_H__ */ | |
39 |
0 | /* | |
1 | * Farstream - Farstream RTP specific types | |
2 | * | |
3 | * Copyright 2011 Collabora Ltd. | |
4 | * @author: Olivier Crete <olivier.crete@collabora.co.uk> | |
5 | * Copyright 2011 Nokia Corp. | |
6 | * | |
7 | * fs-rtp.c - Farstream RTP specific types | |
8 | * | |
9 | * This library is free software; you can redistribute it and/or | |
10 | * modify it under the terms of the GNU Lesser General Public | |
11 | * License as published by the Free Software Foundation; either | |
12 | * version 2.1 of the License, or (at your option) any later version. | |
13 | * | |
14 | * This library is distributed in the hope that it will be useful, | |
15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
17 | * Lesser General Public License for more details. | |
18 | * | |
19 | * You should have received a copy of the GNU Lesser General Public | |
20 | * License along with this library; if not, write to the Free Software | |
21 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA | |
22 | */ | |
23 | ||
24 | ||
25 | #ifdef HAVE_CONFIG_H | |
26 | #include "config.h" | |
27 | #endif | |
28 | ||
29 | #include "fs-rtp.h" | |
30 | ||
31 | #include <string.h> | |
32 | ||
33 | typedef GList FsRtpHeaderExtensionGList; | |
34 | ||
35 | G_DEFINE_BOXED_TYPE (FsRtpHeaderExtension, fs_rtp_header_extension, | |
36 | fs_rtp_header_extension_copy, fs_rtp_header_extension_destroy) | |
37 | G_DEFINE_BOXED_TYPE (FsRtpHeaderExtensionGList, fs_rtp_header_extension_list, | |
38 | fs_rtp_header_extension_list_copy, fs_rtp_header_extension_list_destroy) | |
39 | ||
40 | ||
41 | /** | |
42 | * fs_rtp_header_extension_new: | |
43 | * @id: The identifier of the RTP header extension | |
44 | * @direction: the direction in which this extension can be used | |
45 | * @uri: The URI that defines this extension | |
46 | * | |
47 | * Creates a new #FsRtpHeaderExtension | |
48 | * | |
49 | * Returns: a new #FsRtpHeaderExtension | |
50 | */ | |
51 | ||
52 | FsRtpHeaderExtension * | |
53 | fs_rtp_header_extension_new (guint id, FsStreamDirection direction, | |
54 | const gchar *uri) | |
55 | { | |
56 | FsRtpHeaderExtension *extension; | |
57 | ||
58 | extension = g_slice_new (FsRtpHeaderExtension); | |
59 | ||
60 | extension->id = id; | |
61 | extension->direction = direction; | |
62 | extension->uri = g_strdup (uri); | |
63 | ||
64 | return extension; | |
65 | } | |
66 | ||
67 | /** | |
68 | * fs_rtp_header_extension_copy: | |
69 | * @extension: The RTP header extension definition to copy | |
70 | * | |
71 | * Copies a #FsRtpHeaderExtension | |
72 | * | |
73 | * Returns: a new #FsRtpHeaderExtension | |
74 | */ | |
75 | ||
76 | FsRtpHeaderExtension * | |
77 | fs_rtp_header_extension_copy (FsRtpHeaderExtension *extension) | |
78 | { | |
79 | if (extension) | |
80 | return fs_rtp_header_extension_new (extension->id, extension->direction, | |
81 | extension->uri); | |
82 | else | |
83 | return NULL; | |
84 | } | |
85 | ||
86 | /** | |
87 | * fs_rtp_header_extension_are_equal: | |
88 | * @extension1: The first #FsRtpHeaderExtension | |
89 | * @extension2: The second #FsRtpHeaderExtension | |
90 | * | |
91 | * Compares two #FsRtpHeaderExtension structures | |
92 | * | |
93 | * Returns: %TRUE if they are identical, %FALSE otherwise | |
94 | */ | |
95 | ||
96 | gboolean | |
97 | fs_rtp_header_extension_are_equal (FsRtpHeaderExtension *extension1, | |
98 | FsRtpHeaderExtension *extension2) | |
99 | { | |
100 | if (extension1 == extension2) | |
101 | return TRUE; | |
102 | ||
103 | if (!extension2 || !extension2) | |
104 | return FALSE; | |
105 | ||
106 | if (extension1->id == extension2->id && | |
107 | extension1->direction == extension2->direction && | |
108 | (extension1->uri == extension2->uri || | |
109 | (extension1->uri && extension2->uri && | |
110 | !strcmp (extension1->uri, extension2->uri)))) | |
111 | return TRUE; | |
112 | else | |
113 | return FALSE; | |
114 | } | |
115 | ||
116 | /** | |
117 | * fs_rtp_header_extension_destroy: | |
118 | * @extension: A RTP header extension to free | |
119 | * | |
120 | * Frees the passed #FsRtpHeaderExtension | |
121 | */ | |
122 | ||
123 | void | |
124 | fs_rtp_header_extension_destroy (FsRtpHeaderExtension *extension) | |
125 | { | |
126 | if (extension) | |
127 | { | |
128 | g_free (extension->uri); | |
129 | g_slice_free (FsRtpHeaderExtension, extension); | |
130 | } | |
131 | } | |
132 | ||
133 | /** | |
134 | * fs_rtp_header_extension_list_copy: | |
135 | * @extensions: a #GList of #FsRtpHeaderExtension | |
136 | * | |
137 | * Does a deep copy of a #GList of #FsRtpHeaderExtension | |
138 | * | |
139 | * Returns: (element-type FsRtpHeaderExtension) (transfer full): a new | |
140 | * #GList of #FsRtpHeaderExtension | |
141 | */ | |
142 | ||
143 | GList * | |
144 | fs_rtp_header_extension_list_copy (GList *extensions) | |
145 | { | |
146 | GQueue copy = G_QUEUE_INIT; | |
147 | const GList *lp; | |
148 | ||
149 | for (lp = extensions; lp; lp = g_list_next (lp)) { | |
150 | FsRtpHeaderExtension *ext = lp->data; | |
151 | ||
152 | g_queue_push_tail (©, fs_rtp_header_extension_copy (ext)); | |
153 | } | |
154 | ||
155 | return copy.head; | |
156 | } | |
157 | ||
158 | /** | |
159 | * fs_rtp_header_extension_list_destroy: | |
160 | * @extensions: a #GList of #FsRtpHeaderExtension | |
161 | * | |
162 | * Frees the passed #GList of #FsRtpHeaderExtension | |
163 | */ | |
164 | ||
165 | void | |
166 | fs_rtp_header_extension_list_destroy (GList *extensions) | |
167 | { | |
168 | g_list_foreach (extensions, (GFunc) fs_rtp_header_extension_destroy, NULL); | |
169 | g_list_free (extensions); | |
170 | } | |
171 | ||
172 | #define RTP_HDREXT_PREFIX "rtp-hdrext:" | |
173 | #define RTP_HDREXT_AUDIO_PREFIX "audio:" | |
174 | #define RTP_HDREXT_VIDEO_PREFIX "video:" | |
175 | ||
176 | /** | |
177 | * fs_rtp_header_extension_list_from_keyfile: | |
178 | * @filename: Name of the #GKeyFile to read the RTP Header Extensions from | |
179 | * @media_type: The media type for which to get header extensions | |
180 | * @error: location of a #GError, or NULL if no error occured | |
181 | * | |
182 | * Reads the content of a #GKeyFile of the following format into a | |
183 | * #GList of #FsRtpHeaderExtension structures. | |
184 | * | |
185 | * The groups have a format "rtp-hdrext:audio:XXX" or | |
186 | * "rtp-hdrext:video:XXX" where XXX is a unique string (per media type). | |
187 | * | |
188 | * The valid keys are: | |
189 | * <itemizedlist> | |
190 | * <listitem>id: a int between in the 1-255 and 4096-4351 ranges</listitem> | |
191 | * <listitem>uri: a URI describing the RTP Header Extension</listitem> | |
192 | * <listitem>direction (optional): To only send or receive a RTP Header | |
193 | * Extension, possible values are "send", "receive", "none" or "both". | |
194 | * Defaults to "both"</listitem> | |
195 | * </itemizedlist> | |
196 | * | |
197 | * Example: | |
198 | * |[ | |
199 | * [rtp-hdrext:audio:a] | |
200 | * id=1 | |
201 | * uri=urn:ietf:params:rtp-hdrext:toffset | |
202 | * | |
203 | * [rtp-hdrext:audio:abc] | |
204 | * id=3 | |
205 | * uri=urn:ietf:params:rtp-hdrext:ntp-64 | |
206 | * direction=receive | |
207 | * ]| | |
208 | * | |
209 | * Returns: (element-type FsRtpHeaderExtension) (transfer full): a | |
210 | * #GList of #FsRtpHeaderExtension that must be freed with | |
211 | * fs_rtp_header_extension_list_destroy() | |
212 | */ | |
213 | ||
214 | GList * | |
215 | fs_rtp_header_extension_list_from_keyfile (const gchar *filename, | |
216 | FsMediaType media_type, | |
217 | GError **error) | |
218 | { | |
219 | GKeyFile *keyfile = NULL; | |
220 | GList *extensions = NULL; | |
221 | gchar **groups = NULL; | |
222 | gsize groups_count = 0; | |
223 | int i; | |
224 | ||
225 | g_return_val_if_fail (filename, NULL); | |
226 | g_return_val_if_fail (media_type <= FS_MEDIA_TYPE_LAST, NULL); | |
227 | g_return_val_if_fail (error == NULL || *error == NULL, NULL); | |
228 | ||
229 | keyfile = g_key_file_new (); | |
230 | ||
231 | if (!g_key_file_load_from_file (keyfile, filename, G_KEY_FILE_NONE, error)) | |
232 | goto out; | |
233 | ||
234 | groups = g_key_file_get_groups (keyfile, &groups_count); | |
235 | ||
236 | if (!groups) | |
237 | goto out; | |
238 | ||
239 | for (i=0; i < groups_count && groups[i]; i++) | |
240 | { | |
241 | FsStreamDirection direction = FS_DIRECTION_BOTH; | |
242 | gint id; | |
243 | gchar *uri; | |
244 | GError *gerror = NULL; | |
245 | gchar *str; | |
246 | ||
247 | if (g_ascii_strncasecmp (RTP_HDREXT_PREFIX, groups[i], | |
248 | strlen (RTP_HDREXT_PREFIX))) | |
249 | continue; | |
250 | ||
251 | if (!g_ascii_strncasecmp (RTP_HDREXT_AUDIO_PREFIX, | |
252 | groups[i] + strlen (RTP_HDREXT_PREFIX), | |
253 | strlen (RTP_HDREXT_AUDIO_PREFIX))) | |
254 | { | |
255 | if (media_type != FS_MEDIA_TYPE_AUDIO) | |
256 | continue; | |
257 | } | |
258 | else if (!g_ascii_strncasecmp (RTP_HDREXT_VIDEO_PREFIX, | |
259 | groups[i] + strlen (RTP_HDREXT_PREFIX), | |
260 | strlen (RTP_HDREXT_VIDEO_PREFIX))) | |
261 | { | |
262 | if (media_type != FS_MEDIA_TYPE_VIDEO) | |
263 | continue; | |
264 | } | |
265 | else | |
266 | { | |
267 | continue; | |
268 | } | |
269 | ||
270 | id = g_key_file_get_integer (keyfile, groups[i], "id", &gerror); | |
271 | if (gerror) | |
272 | { | |
273 | g_clear_error (&gerror); | |
274 | continue; | |
275 | } | |
276 | ||
277 | str = g_key_file_get_string (keyfile, groups[i], "direction", &gerror); | |
278 | if (gerror) | |
279 | { | |
280 | GQuark domain = gerror->domain; | |
281 | gint code = gerror->code; | |
282 | ||
283 | g_clear_error (&gerror); | |
284 | if (domain != G_KEY_FILE_ERROR || code != G_KEY_FILE_ERROR_KEY_NOT_FOUND) | |
285 | continue; | |
286 | } | |
287 | else | |
288 | { | |
289 | if (!g_ascii_strcasecmp (str, "none")) | |
290 | direction = FS_DIRECTION_NONE; | |
291 | else if (!g_ascii_strcasecmp (str, "send")) | |
292 | direction = FS_DIRECTION_SEND; | |
293 | else if (!g_ascii_strcasecmp (str, "recv") || | |
294 | !g_ascii_strcasecmp (str, "receive")) | |
295 | direction = FS_DIRECTION_RECV; | |
296 | g_free (str); | |
297 | } | |
298 | ||
299 | uri = g_key_file_get_string (keyfile, groups[i], "uri", &gerror); | |
300 | if (gerror) | |
301 | { | |
302 | g_clear_error (&gerror); | |
303 | continue; | |
304 | } | |
305 | ||
306 | extensions = g_list_append (extensions, fs_rtp_header_extension_new (id, | |
307 | direction, uri)); | |
308 | g_free (uri); | |
309 | } | |
310 | ||
311 | out: | |
312 | ||
313 | g_strfreev (groups); | |
314 | g_key_file_free (keyfile); | |
315 | ||
316 | return extensions; | |
317 | } |
0 | /* | |
1 | * Farstream - Farstream RTP specific types | |
2 | * | |
3 | * Copyright 2011 Collabora Ltd. | |
4 | * @author: Olivier Crete <olivier.crete@collabora.co.uk> | |
5 | * Copyright 2011 Nokia Corp. | |
6 | * | |
7 | * fs-rtp.h - Farstream RTP specific types | |
8 | * | |
9 | * This library is free software; you can redistribute it and/or | |
10 | * modify it under the terms of the GNU Lesser General Public | |
11 | * License as published by the Free Software Foundation; either | |
12 | * version 2.1 of the License, or (at your option) any later version. | |
13 | * | |
14 | * This library is distributed in the hope that it will be useful, | |
15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
17 | * Lesser General Public License for more details. | |
18 | * | |
19 | * You should have received a copy of the GNU Lesser General Public | |
20 | * License along with this library; if not, write to the Free Software | |
21 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA | |
22 | */ | |
23 | ||
24 | #ifndef __FS_RTP_H__ | |
25 | #define __FS_RTP_H__ | |
26 | ||
27 | #include <gst/gst.h> | |
28 | #include <gst/farstream/fs-stream.h> | |
29 | ||
30 | G_BEGIN_DECLS | |
31 | ||
32 | /** | |
33 | * FsRtpHeaderExtension: | |
34 | * @id: The identifier of the RTP header extension | |
35 | * @direction: the direction in which this extension can be used | |
36 | * @uri: The URI that defines this extension | |
37 | * | |
38 | * Defines a RTP header extension with its negotiated identifier, direction | |
39 | * and URI. They should only be created with fs_rtp_header_extension_new(). | |
40 | */ | |
41 | ||
42 | typedef struct _FsRtpHeaderExtension { | |
43 | guint id; | |
44 | FsStreamDirection direction; | |
45 | gchar *uri; | |
46 | } FsRtpHeaderExtension; | |
47 | ||
48 | /** | |
49 | * FS_TYPE_RTP_HEADER_EXTENSION: | |
50 | * | |
51 | * Boxed type for #FsRtpHeaderExtension | |
52 | */ | |
53 | ||
54 | /** | |
55 | * FS_TYPE_RTP_HEADER_EXTENSION_LIST: | |
56 | * | |
57 | * Boxed type for a #GList of #FsRtpHeaderExtension | |
58 | */ | |
59 | ||
60 | #define FS_TYPE_RTP_HEADER_EXTENSION \ | |
61 | fs_rtp_header_extension_get_type () | |
62 | #define FS_TYPE_RTP_HEADER_EXTENSION_LIST \ | |
63 | fs_rtp_header_extension_list_get_type () | |
64 | ||
65 | GType fs_rtp_header_extension_get_type (void); | |
66 | GType fs_rtp_header_extension_list_get_type (void); | |
67 | ||
68 | ||
69 | FsRtpHeaderExtension * | |
70 | fs_rtp_header_extension_new (guint id, FsStreamDirection direction, | |
71 | const gchar *uri); | |
72 | ||
73 | FsRtpHeaderExtension * | |
74 | fs_rtp_header_extension_copy (FsRtpHeaderExtension *extension); | |
75 | void | |
76 | fs_rtp_header_extension_destroy (FsRtpHeaderExtension *extension); | |
77 | ||
78 | gboolean | |
79 | fs_rtp_header_extension_are_equal (FsRtpHeaderExtension *extension1, | |
80 | FsRtpHeaderExtension *extension2); | |
81 | ||
82 | GList * | |
83 | fs_rtp_header_extension_list_copy (GList *extensions); | |
84 | void | |
85 | fs_rtp_header_extension_list_destroy (GList *extensions); | |
86 | ||
87 | GList * | |
88 | fs_rtp_header_extension_list_from_keyfile (const gchar *filename, | |
89 | FsMediaType media_type, | |
90 | GError **error); | |
91 | ||
92 | /** | |
93 | * FS_RTP_HEADER_EXTENSION_FORMAT: | |
94 | * | |
95 | * A format that can be used in printf like format strings to format a | |
96 | * FsRtpHeaderExtension | |
97 | */ | |
98 | ||
99 | /** | |
100 | * FS_RTP_HEADER_EXTENSION_ARGS: | |
101 | * @hdrext: a #FsRtpHeaderExtension | |
102 | * | |
103 | * Formats the codec in args for FS_RTP_HEADER_EXTENSION_ARGS | |
104 | */ | |
105 | ||
106 | #define FS_RTP_HEADER_EXTENSION_FORMAT "%d: (%s) %s" | |
107 | #define FS_RTP_HEADER_EXTENSION_ARGS(hdrext) \ | |
108 | (hdrext)->id, \ | |
109 | (hdrext)->direction == FS_DIRECTION_BOTH ? "both" : \ | |
110 | ((hdrext)->direction == FS_DIRECTION_RECV? "recv" : \ | |
111 | ((hdrext)->direction == FS_DIRECTION_SEND ? "send" : "none")), \ | |
112 | (hdrext)->uri | |
113 | ||
114 | G_END_DECLS | |
115 | ||
116 | #endif /* __FS_RTP_H__ */ |
0 | /* | |
1 | * Farstream - Farstream Session | |
2 | * | |
3 | * Copyright 2007 Collabora Ltd. | |
4 | * @author: Philippe Kalaf <philippe.kalaf@collabora.co.uk> | |
5 | * Copyright 2007 Nokia Corp. | |
6 | * | |
7 | * fs-session.c - A Farstream Session gobject (base implementation) | |
8 | * | |
9 | * This library is free software; you can redistribute it and/or | |
10 | * modify it under the terms of the GNU Lesser General Public | |
11 | * License as published by the Free Software Foundation; either | |
12 | * version 2.1 of the License, or (at your option) any later version. | |
13 | * | |
14 | * This library is distributed in the hope that it will be useful, | |
15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
17 | * Lesser General Public License for more details. | |
18 | * | |
19 | * You should have received a copy of the GNU Lesser General Public | |
20 | * License along with this library; if not, write to the Free Software | |
21 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA | |
22 | */ | |
23 | ||
24 | ||
25 | ||
26 | /** | |
27 | * SECTION:fs-session | |
28 | * @short_description: A session in a conference | |
29 | * | |
30 | * This object is the base implementation of a Farstream Session. It needs to be | |
31 | * derived and implemented by a farstream conference gstreamer element. A | |
32 | * Farstream session is defined in the same way as an RTP session. It can contain | |
33 | * one or more participants but represents only one media stream (i.e. One | |
34 | * session for video and one session for audio in an AV conference). Sessions | |
35 | * contained in the same conference will be synchronised together during | |
36 | * playback. | |
37 | * | |
38 | * | |
39 | * This will communicate asynchronous events to the user through #GstMessage | |
40 | * of type #GST_MESSAGE_ELEMENT sent over the #GstBus. | |
41 | * </para> | |
42 | * <refsect2><title>The "<literal>farstream-send-codec-changed</literal>" | |
43 | * message</title> | |
44 | * |[ | |
45 | * "session" #FsSession The session that emits the message | |
46 | * "codec" #FsCodec The new send codec | |
47 | * "secondary-codecs" #GList A #GList of #FsCodec (to be freed | |
48 | * with fs_codec_list_destroy()) | |
49 | * ]| | |
50 | * <para> | |
51 | * This message is sent on the bus when the value of the | |
52 | * #FsSession:current-send-codec property changes. | |
53 | * </para> | |
54 | * </refsect2> | |
55 | * <refsect2><title>The "<literal>farstream-codecs-changed</literal>" | |
56 | * message</title> | |
57 | * |[ | |
58 | * "session" #FsSession The session that emits the message | |
59 | * ]| | |
60 | * <para> | |
61 | * This message is sent on the bus when the value of the | |
62 | * #FsSession:codecs or #FsSession:codecs-without-config properties change. | |
63 | * If one is using codecs that have configuration data that needs to be | |
64 | * transmitted reliably, one should fetch #FsSession:codecs, otherwise, | |
65 | * #FsSession:codecs-without-config should be enough. | |
66 | * </para> | |
67 | * </refsect2> | |
68 | * <para> | |
69 | */ | |
70 | ||
71 | #ifdef HAVE_CONFIG_H | |
72 | #include "config.h" | |
73 | #endif | |
74 | ||
75 | #include "fs-session.h" | |
76 | ||
77 | #include <gst/gst.h> | |
78 | ||
79 | #include "fs-conference.h" | |
80 | #include "fs-codec.h" | |
81 | #include "fs-marshal.h" | |
82 | #include "fs-enumtypes.h" | |
83 | #include "fs-private.h" | |
84 | ||
85 | #define GST_CAT_DEFAULT fs_conference_debug | |
86 | ||
87 | /* Signals */ | |
88 | enum | |
89 | { | |
90 | ERROR_SIGNAL, | |
91 | LAST_SIGNAL | |
92 | }; | |
93 | ||
94 | /* props */ | |
95 | enum | |
96 | { | |
97 | PROP_0, | |
98 | PROP_MEDIA_TYPE, | |
99 | PROP_ID, | |
100 | PROP_SINK_PAD, | |
101 | PROP_CODEC_PREFERENCES, | |
102 | PROP_CODECS, | |
103 | PROP_CODECS_WITHOUT_CONFIG, | |
104 | PROP_CURRENT_SEND_CODEC, | |
105 | PROP_TYPE_OF_SERVICE | |
106 | }; | |
107 | ||
108 | /* | |
109 | struct _FsSessionPrivate | |
110 | { | |
111 | }; | |
112 | ||
113 | #define FS_SESSION_GET_PRIVATE(o) \ | |
114 | (G_TYPE_INSTANCE_GET_PRIVATE ((o), FS_TYPE_SESSION, FsSessionPrivate)) | |
115 | */ | |
116 | ||
117 | G_DEFINE_ABSTRACT_TYPE(FsSession, fs_session, GST_TYPE_OBJECT); | |
118 | ||
119 | static void fs_session_get_property (GObject *object, | |
120 | guint prop_id, | |
121 | GValue *value, | |
122 | GParamSpec *pspec); | |
123 | static void fs_session_set_property (GObject *object, | |
124 | guint prop_id, | |
125 | const GValue *value, | |
126 | GParamSpec *pspec); | |
127 | ||
128 | static guint signals[LAST_SIGNAL] = { 0 }; | |
129 | ||
130 | static void | |
131 | fs_session_class_init (FsSessionClass *klass) | |
132 | { | |
133 | GObjectClass *gobject_class; | |
134 | ||
135 | gobject_class = (GObjectClass *) klass; | |
136 | ||
137 | gobject_class->set_property = fs_session_set_property; | |
138 | gobject_class->get_property = fs_session_get_property; | |
139 | ||
140 | /** | |
141 | * FsSession:media-type: | |
142 | * | |
143 | * The media-type of the session. This is either Audio, Video or both. | |
144 | * This is a constructor parameter that cannot be changed. | |
145 | * | |
146 | */ | |
147 | g_object_class_install_property (gobject_class, | |
148 | PROP_MEDIA_TYPE, | |
149 | g_param_spec_enum ("media-type", | |
150 | "The media type of the session", | |
151 | "An enum that specifies the media type of the session", | |
152 | FS_TYPE_MEDIA_TYPE, | |
153 | FS_MEDIA_TYPE_AUDIO, | |
154 | G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); | |
155 | ||
156 | /** | |
157 | * FsSession:id: | |
158 | * | |
159 | * The ID of the session, the first number of the pads linked to this session | |
160 | * will be this id | |
161 | * | |
162 | */ | |
163 | g_object_class_install_property (gobject_class, | |
164 | PROP_ID, | |
165 | g_param_spec_uint ("id", | |
166 | "The ID of the session", | |
167 | "This ID is used on pad related to this session", | |
168 | 0, G_MAXUINT, 0, | |
169 | G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); | |
170 | ||
171 | /** | |
172 | * FsSession:sink-pad: | |
173 | * | |
174 | * The Gstreamer sink pad that must be used to send media data on this | |
175 | * session. User must unref this GstPad when done with it. | |
176 | * | |
177 | */ | |
178 | g_object_class_install_property (gobject_class, | |
179 | PROP_SINK_PAD, | |
180 | g_param_spec_object ("sink-pad", | |
181 | "A gstreamer sink pad for this session", | |
182 | "A pad used for sending data on this session", | |
183 | GST_TYPE_PAD, | |
184 | G_PARAM_READABLE | G_PARAM_STATIC_STRINGS)); | |
185 | ||
186 | /** | |
187 | * FsSession:codec-preferences: | |
188 | * | |
189 | * Type: GLib.List<FsCodec> | |
190 | * Transfer: full | |
191 | * | |
192 | * This is the current preferences list for the local codecs. It is | |
193 | * set by the user to specify the codec options and priorities. The user may | |
194 | * change its value with fs_session_set_codec_preferences() at any time | |
195 | * during a session. It is a #GList of #FsCodec. | |
196 | * The user must free this codec list using fs_codec_list_destroy() when done. | |
197 | * | |
198 | * The payload type may be a valid dynamic PT (96-127), %FS_CODEC_ID_DISABLE | |
199 | * or %FS_CODEC_ID_ANY. If the encoding name is "reserve-pt", then the | |
200 | * payload type of the codec will be "reserved" and not be used by any | |
201 | * dynamically assigned payload type. | |
202 | */ | |
203 | g_object_class_install_property (gobject_class, | |
204 | PROP_CODEC_PREFERENCES, | |
205 | g_param_spec_boxed ("codec-preferences", | |
206 | "List of user preferences for the codecs", | |
207 | "A GList of FsCodecs that allows user to set his codec options and" | |
208 | " priorities", | |
209 | FS_TYPE_CODEC_LIST, | |
210 | G_PARAM_READABLE | G_PARAM_STATIC_STRINGS)); | |
211 | ||
212 | /** | |
213 | * FsSession:codecs: | |
214 | * | |
215 | * Type: GLib.List<FsCodec> | |
216 | * Transfer: full | |
217 | * | |
218 | * This is the list of codecs used for this session. It will include the | |
219 | * codecs and payload type used to receive media on this session. It will | |
220 | * also include any configuration parameter that must be transmitted reliably | |
221 | * for the other end to decode the content. | |
222 | * | |
223 | * It may change when the codec preferences are set, when codecs are set | |
224 | * on a #FsStream in this session, when a #FsStream is destroyed or | |
225 | * asynchronously when new config data is discovered. | |
226 | * | |
227 | * If any configuration parameter needs to be discovered, this property | |
228 | * will be %NULL until they have been discovered. One can always get | |
229 | * the codecs from #FsSession:codecs-without-config. | |
230 | * The "farstream-codecs-changed" message will be emitted whenever the value | |
231 | * of this property changes. | |
232 | * | |
233 | * It is a #GList of #FsCodec. User must free this codec list using | |
234 | * fs_codec_list_destroy() when done. | |
235 | * | |
236 | */ | |
237 | g_object_class_install_property (gobject_class, | |
238 | PROP_CODECS, | |
239 | g_param_spec_boxed ("codecs", | |
240 | "List of codecs", | |
241 | "A GList of FsCodecs indicating the codecs for this session", | |
242 | FS_TYPE_CODEC_LIST, | |
243 | G_PARAM_READABLE | G_PARAM_STATIC_STRINGS)); | |
244 | ||
245 | /** | |
246 | * FsSession:codecs-without-config: | |
247 | * | |
248 | * Type: GLib.List<FsCodec> | |
249 | * Transfer: full | |
250 | * | |
251 | * This is the same list of codecs as #FsSession:codecs without | |
252 | * the configuration information that describes the data sent. It is suitable | |
253 | * for configurations where a list of codecs is shared by many senders. | |
254 | * If one is using codecs such as Theora, Vorbis or H.264 that require | |
255 | * such information to be transmitted, the configuration data should be | |
256 | * included in the stream and retransmitted regularly. | |
257 | * | |
258 | * It may change when the codec preferences are set, when codecs are set | |
259 | * on a #FsStream in this session, when a #FsStream is destroyed or | |
260 | * asynchronously when new config data is discovered. | |
261 | * | |
262 | * The "farstream-codecs-changed" message will be emitted whenever the value | |
263 | * of this property changes. | |
264 | * | |
265 | * It is a #GList of #FsCodec. User must free this codec list using | |
266 | * fs_codec_list_destroy() when done. | |
267 | * | |
268 | */ | |
269 | g_object_class_install_property (gobject_class, | |
270 | PROP_CODECS_WITHOUT_CONFIG, | |
271 | g_param_spec_boxed ("codecs-without-config", | |
272 | "List of codecs without the configuration data", | |
273 | "A GList of FsCodecs indicating the codecs for this session without " | |
274 | "any configuration data", | |
275 | FS_TYPE_CODEC_LIST, | |
276 | G_PARAM_READABLE | G_PARAM_STATIC_STRINGS)); | |
277 | ||
278 | /** | |
279 | * FsSession:current-send-codec: | |
280 | * | |
281 | * Indicates the currently active send codec. A user can change the active | |
282 | * send codec by calling fs_session_set_send_codec(). The send codec could | |
283 | * also be automatically changed by Farstream. This property is an | |
284 | * #FsCodec. User must free the codec using fs_codec_destroy() when done. | |
285 | * The "farstream-send-codec-changed" message is emitted on the bus when | |
286 | * the value of this property changes. | |
287 | */ | |
288 | g_object_class_install_property (gobject_class, | |
289 | PROP_CURRENT_SEND_CODEC, | |
290 | g_param_spec_boxed ("current-send-codec", | |
291 | "Current active send codec", | |
292 | "An FsCodec indicating the currently active send codec", | |
293 | FS_TYPE_CODEC, | |
294 | G_PARAM_READABLE | G_PARAM_STATIC_STRINGS)); | |
295 | ||
296 | /** | |
297 | * FsSession:tos | |
298 | * | |
299 | * Sets the IP ToS field (and if possible the IPv6 TCLASS field | |
300 | */ | |
301 | g_object_class_install_property (gobject_class, | |
302 | PROP_TYPE_OF_SERVICE, | |
303 | g_param_spec_uint ("tos", | |
304 | "IP Type of Service", | |
305 | "The IP Type of Service to set on sent packets", | |
306 | 0, 255, 0, | |
307 | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); | |
308 | ||
309 | ||
310 | /** | |
311 | * FsSession::error: | |
312 | * @self: #FsSession that emitted the signal | |
313 | * @object: The #Gobject that emitted the signal | |
314 | * @error_no: The number of the error | |
315 | * @error_msg: Error message | |
316 | * | |
317 | * This signal is emitted in any error condition, it can be emitted on any | |
318 | * thread. Applications should listen to the GstBus for errors. | |
319 | * | |
320 | */ | |
321 | signals[ERROR_SIGNAL] = g_signal_new ("error", | |
322 | G_TYPE_FROM_CLASS (klass), | |
323 | G_SIGNAL_RUN_LAST, | |
324 | 0, | |
325 | NULL, | |
326 | NULL, | |
327 | _fs_marshal_VOID__OBJECT_ENUM_STRING, | |
328 | G_TYPE_NONE, 3, G_TYPE_OBJECT, FS_TYPE_ERROR, G_TYPE_STRING); | |
329 | } | |
330 | ||
331 | static void | |
332 | fs_session_init (FsSession *self) | |
333 | { | |
334 | /* member init */ | |
335 | // self->priv = FS_SESSION_GET_PRIVATE (self); | |
336 | } | |
337 | ||
338 | static void | |
339 | fs_session_get_property (GObject *object, | |
340 | guint prop_id, | |
341 | GValue *value, | |
342 | GParamSpec *pspec) | |
343 | { | |
344 | GST_WARNING ("Subclass %s of FsSession does not override the %s property" | |
345 | " getter", | |
346 | G_OBJECT_TYPE_NAME(object), | |
347 | g_param_spec_get_name (pspec)); | |
348 | } | |
349 | ||
350 | static void | |
351 | fs_session_set_property (GObject *object, | |
352 | guint prop_id, | |
353 | const GValue *value, | |
354 | GParamSpec *pspec) | |
355 | { | |
356 | GST_WARNING ("Subclass %s of FsSession does not override the %s property" | |
357 | " setter", | |
358 | G_OBJECT_TYPE_NAME(object), | |
359 | g_param_spec_get_name (pspec)); | |
360 | } | |
361 | ||
362 | static void | |
363 | fs_session_error_forward (GObject *signal_src, | |
364 | FsError error_no, gchar *error_msg, | |
365 | FsSession *session) | |
366 | { | |
367 | /* We just need to forward the error signal including a ref to the stream | |
368 | * object (signal_src) */ | |
369 | g_signal_emit (session, signals[ERROR_SIGNAL], 0, signal_src, error_no, | |
370 | error_msg); | |
371 | } | |
372 | ||
373 | /** | |
374 | * fs_session_new_stream: | |
375 | * @session: a #FsSession | |
376 | * @participant: #FsParticipant of a participant for the new stream | |
377 | * @direction: #FsStreamDirection describing the direction of the new stream that will | |
378 | * be created for this participant | |
379 | * @error: location of a #GError, or %NULL if no error occured | |
380 | * | |
381 | * This function creates a stream for the given participant into the active session. | |
382 | * | |
383 | * Returns: (transfer full): the new #FsStream that has been created. | |
384 | * User must unref the #FsStream when the stream is ended. If an error occured, | |
385 | * returns NULL. | |
386 | */ | |
387 | FsStream * | |
388 | fs_session_new_stream (FsSession *session, | |
389 | FsParticipant *participant, | |
390 | FsStreamDirection direction, | |
391 | GError **error) | |
392 | { | |
393 | FsSessionClass *klass; | |
394 | FsStream *new_stream = NULL; | |
395 | ||
396 | g_return_val_if_fail (session, NULL); | |
397 | g_return_val_if_fail (FS_IS_SESSION (session), NULL); | |
398 | klass = FS_SESSION_GET_CLASS (session); | |
399 | g_return_val_if_fail (klass->new_stream, NULL); | |
400 | ||
401 | new_stream = klass->new_stream (session, participant, direction, error); | |
402 | ||
403 | if (!new_stream) | |
404 | return NULL; | |
405 | ||
406 | /* Let's catch all stream errors and forward them */ | |
407 | g_signal_connect_object (new_stream, "error", | |
408 | G_CALLBACK (fs_session_error_forward), session, 0); | |
409 | ||
410 | return new_stream; | |
411 | } | |
412 | ||
413 | /** | |
414 | * fs_session_start_telephony_event: | |
415 | * @session: a #FsSession | |
416 | * @event: A #FsStreamDTMFEvent or another number defined at | |
417 | * http://www.iana.org/assignments/audio-telephone-event-registry | |
418 | * @volume: The volume in dBm0 without the negative sign. Should be between | |
419 | * 0 and 36. Higher values mean lower volume | |
420 | * @method: The method used to send the event | |
421 | * | |
422 | * This function will start sending a telephony event (such as a DTMF | |
423 | * tone) on the #FsSession. You have to call the function | |
424 | * fs_session_stop_telephony_event() to stop it. | |
425 | * This function will use any available method, if you want to use a specific | |
426 | * method only, use fs_session_start_telephony_event_full() | |
427 | * | |
428 | * Returns: %TRUE if sucessful, it can return %FALSE if the #FsStream | |
429 | * does not support this telephony event. | |
430 | */ | |
431 | gboolean | |
432 | fs_session_start_telephony_event (FsSession *session, guint8 event, | |
433 | guint8 volume, FsDTMFMethod method) | |
434 | { | |
435 | FsSessionClass *klass; | |
436 | ||
437 | g_return_val_if_fail (session, FALSE); | |
438 | g_return_val_if_fail (FS_IS_SESSION (session), FALSE); | |
439 | klass = FS_SESSION_GET_CLASS (session); | |
440 | ||
441 | if (klass->start_telephony_event) { | |
442 | return klass->start_telephony_event (session, event, volume, method); | |
443 | } else { | |
444 | GST_WARNING ("start_telephony_event not defined in class"); | |
445 | } | |
446 | return FALSE; | |
447 | } | |
448 | ||
449 | /** | |
450 | * fs_session_stop_telephony_event: | |
451 | * @session: an #FsSession | |
452 | * @method: The method used to send the event | |
453 | * | |
454 | * This function will stop sending a telephony event started by | |
455 | * fs_session_start_telephony_event(). If the event was being sent | |
456 | * for less than 50ms, it will be sent for 50ms minimum. If the | |
457 | * duration was a positive and the event is not over, it will cut it | |
458 | * short. | |
459 | * | |
460 | * Returns: %TRUE if sucessful, it can return %FALSE if the #FsSession | |
461 | * does not support telephony events or if no telephony event is being sent | |
462 | */ | |
463 | gboolean | |
464 | fs_session_stop_telephony_event (FsSession *session, FsDTMFMethod method) | |
465 | { | |
466 | FsSessionClass *klass; | |
467 | ||
468 | g_return_val_if_fail (session, FALSE); | |
469 | g_return_val_if_fail (FS_IS_SESSION (session), FALSE); | |
470 | klass = FS_SESSION_GET_CLASS (session); | |
471 | ||
472 | if (klass->stop_telephony_event) { | |
473 | return klass->stop_telephony_event (session, method); | |
474 | } else { | |
475 | GST_WARNING ("stop_telephony_event not defined in class"); | |
476 | } | |
477 | return FALSE; | |
478 | } | |
479 | ||
480 | /** | |
481 | * fs_session_set_send_codec: | |
482 | * @session: a #FsSession | |
483 | * @send_codec: a #FsCodec representing the codec to send | |
484 | * @error: location of a #GError, or %NULL if no error occured | |
485 | * | |
486 | * This function will set the currently being sent codec for all streams in this | |
487 | * session. The given #FsCodec must be taken directly from the #codecs | |
488 | * property of the session. If the given codec is not in the codecs | |
489 | * list, @error will be set and %FALSE will be returned. The @send_codec will be | |
490 | * copied so it must be free'd using fs_codec_destroy() when done. | |
491 | * | |
492 | * Returns: %FALSE if the send codec couldn't be set. | |
493 | */ | |
494 | gboolean | |
495 | fs_session_set_send_codec (FsSession *session, FsCodec *send_codec, | |
496 | GError **error) | |
497 | { | |
498 | FsSessionClass *klass; | |
499 | ||
500 | g_return_val_if_fail (session, FALSE); | |
501 | g_return_val_if_fail (FS_IS_SESSION (session), FALSE); | |
502 | klass = FS_SESSION_GET_CLASS (session); | |
503 | ||
504 | if (klass->set_send_codec) { | |
505 | return klass->set_send_codec (session, send_codec, error); | |
506 | } else { | |
507 | GST_WARNING ("set_send_codec not defined in class"); | |
508 | g_set_error (error, FS_ERROR, FS_ERROR_NOT_IMPLEMENTED, | |
509 | "set_send_codec not defined in class"); | |
510 | } | |
511 | return FALSE; | |
512 | } | |
513 | ||
514 | /** | |
515 | * fs_session_set_codec_preferences: | |
516 | * @session: a #FsSession | |
517 | * @codec_preferences: (element-type FsCodec): a #GList of #FsCodec with the | |
518 | * desired configuration | |
519 | * @error: location of a #GError, or %NULL if no error occured | |
520 | * | |
521 | * Set the list of desired codec preferences. The user may | |
522 | * change this value during an ongoing session. Note that doing this can cause | |
523 | * the codecs to change. Therefore this requires the user to fetch | |
524 | * the new codecs and renegotiate them with the peers. It is a #GList | |
525 | * of #FsCodec. The changes are immediately effective. | |
526 | * The function does not take ownership of the list. | |
527 | * | |
528 | * The payload type may be a valid dynamic PT (96-127), %FS_CODEC_ID_DISABLE | |
529 | * or %FS_CODEC_ID_ANY. If the encoding name is "reserve-pt", then the | |
530 | * payload type of the codec will be "reserved" and not be used by any | |
531 | * dynamically assigned payload type. | |
532 | * | |
533 | * If the list of specifications would invalidate all codecs, an error will | |
534 | * be returned. | |
535 | * | |
536 | * Returns: %TRUE on success, %FALSE on error. | |
537 | */ | |
538 | gboolean | |
539 | fs_session_set_codec_preferences (FsSession *session, | |
540 | GList *codec_preferences, | |
541 | GError **error) | |
542 | { | |
543 | FsSessionClass *klass; | |
544 | ||
545 | g_return_val_if_fail (session, FALSE); | |
546 | g_return_val_if_fail (FS_IS_SESSION (session), FALSE); | |
547 | klass = FS_SESSION_GET_CLASS (session); | |
548 | ||
549 | if (klass->set_codec_preferences) { | |
550 | return klass->set_codec_preferences (session, codec_preferences, error); | |
551 | } else { | |
552 | GST_WARNING ("set_send_preferences not defined in class"); | |
553 | g_set_error (error, FS_ERROR, FS_ERROR_NOT_IMPLEMENTED, | |
554 | "set_codec_preferences not defined in class"); | |
555 | } | |
556 | return FALSE; | |
557 | } | |
558 | ||
559 | /** | |
560 | * fs_session_emit_error: | |
561 | * @session: #FsSession on which to emit the error signal | |
562 | * @error_no: The number of the error of type #FsError | |
563 | * @error_msg: Error message | |
564 | * | |
565 | * This function emit the "error" signal on a #FsSession, it should only be | |
566 | * called by subclasses. | |
567 | */ | |
568 | void | |
569 | fs_session_emit_error (FsSession *session, | |
570 | gint error_no, | |
571 | const gchar *error_msg) | |
572 | { | |
573 | g_signal_emit (session, signals[ERROR_SIGNAL], 0, session, error_no, | |
574 | error_msg); | |
575 | } | |
576 | ||
577 | /** | |
578 | * fs_session_list_transmitters: | |
579 | * @session: A #FsSession | |
580 | * | |
581 | * Get the list of all available transmitters for this session. | |
582 | * | |
583 | * Returns: (transfer full): a newly-allocagted %NULL terminated array of | |
584 | * named of transmitters or %NULL if no transmitter is needed for this type of | |
585 | * session. It should be freed with g_strfreev(). | |
586 | */ | |
587 | ||
588 | gchar ** | |
589 | fs_session_list_transmitters (FsSession *session) | |
590 | { | |
591 | FsSessionClass *klass; | |
592 | ||
593 | g_return_val_if_fail (session, NULL); | |
594 | g_return_val_if_fail (FS_IS_SESSION (session), NULL); | |
595 | klass = FS_SESSION_GET_CLASS (session); | |
596 | ||
597 | if (klass->list_transmitters) { | |
598 | return klass->list_transmitters (session); | |
599 | } else { | |
600 | return NULL; | |
601 | } | |
602 | } | |
603 | ||
604 | ||
605 | /** | |
606 | * fs_session_get_stream_transmitter_type: | |
607 | * @session: A #FsSession | |
608 | * @transmitter: The name of the transmitter | |
609 | * | |
610 | * Returns the GType of the stream transmitter, bindings can use it | |
611 | * to validate/convert the parameters passed to fs_session_new_stream(). | |
612 | * | |
613 | * Returns: The #GType of the stream transmitter | |
614 | */ | |
615 | GType | |
616 | fs_session_get_stream_transmitter_type (FsSession *session, | |
617 | const gchar *transmitter) | |
618 | { | |
619 | FsSessionClass *klass; | |
620 | ||
621 | g_return_val_if_fail (session, 0); | |
622 | g_return_val_if_fail (FS_IS_SESSION (session), 0); | |
623 | klass = FS_SESSION_GET_CLASS (session); | |
624 | ||
625 | if (klass->get_stream_transmitter_type) | |
626 | return klass->get_stream_transmitter_type (session, transmitter); | |
627 | ||
628 | return 0; | |
629 | } | |
630 | ||
631 | /** | |
632 | * fs_session_codecs_need_resend: | |
633 | * @session: a #FsSession | |
634 | * @old_codecs: Codecs previously retrieved from the #FsSession:codecs property | |
635 | * @new_codecs: Codecs recently retrieved from the #FsSession:codecs property | |
636 | * | |
637 | * Some codec updates need to be reliably transmitted to the other side | |
638 | * because they contain important parameters required to decode the media. | |
639 | * Other codec updates, caused by user action, don't. | |
640 | * | |
641 | * Returns: (element-type FsCodec) (transfer full): A new #GList of | |
642 | * #FsCodec that need to be resent or %NULL if there are none. This | |
643 | * list must be freed with fs_codec_list_destroy(). | |
644 | */ | |
645 | GList * | |
646 | fs_session_codecs_need_resend (FsSession *session, | |
647 | GList *old_codecs, GList *new_codecs) | |
648 | { | |
649 | FsSessionClass *klass; | |
650 | ||
651 | g_return_val_if_fail (session, 0); | |
652 | g_return_val_if_fail (FS_IS_SESSION (session), 0); | |
653 | klass = FS_SESSION_GET_CLASS (session); | |
654 | ||
655 | if (klass->codecs_need_resend) | |
656 | return klass->codecs_need_resend (session, old_codecs, new_codecs); | |
657 | ||
658 | return NULL; | |
659 | } | |
660 | ||
661 | /** | |
662 | * fs_session_destroy: | |
663 | * @session: a #FsSession | |
664 | * | |
665 | * This will cause the session to remove all links to other objects and to | |
666 | * remove itself from the #FsConference, it will also destroy all #FsStream | |
667 | * inside this #FsSession Once a #FsSession has been destroyed, it | |
668 | * can not be used anymore. | |
669 | * | |
670 | * It is strongly recommended to call this function from the main thread because | |
671 | * releasing the application's reference to a session. | |
672 | */ | |
673 | ||
674 | void | |
675 | fs_session_destroy (FsSession *session) | |
676 | { | |
677 | g_return_if_fail (session); | |
678 | g_return_if_fail (FS_IS_SESSION (session)); | |
679 | ||
680 | g_object_run_dispose (G_OBJECT (session)); | |
681 | } |
0 | /* | |
1 | * Farstream - Farstream Session | |
2 | * | |
3 | * Copyright 2007 Collabora Ltd. | |
4 | * @author: Philippe Kalaf <philippe.kalaf@collabora.co.uk> | |
5 | * Copyright 2007 Nokia Corp. | |
6 | * | |
7 | * fs-session.h - A Farstream Session gobject (base implementation) | |
8 | * | |
9 | * This library is free software; you can redistribute it and/or | |
10 | * modify it under the terms of the GNU Lesser General Public | |
11 | * License as published by the Free Software Foundation; either | |
12 | * version 2.1 of the License, or (at your option) any later version. | |
13 | * | |
14 | * This library is distributed in the hope that it will be useful, | |
15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
17 | * Lesser General Public License for more details. | |
18 | * | |
19 | * You should have received a copy of the GNU Lesser General Public | |
20 | * License along with this library; if not, write to the Free Software | |
21 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA | |
22 | */ | |
23 | ||
24 | #ifndef __FS_SESSION_H__ | |
25 | #define __FS_SESSION_H__ | |
26 | ||
27 | #include <glib.h> | |
28 | #include <glib-object.h> | |
29 | ||
30 | #include <gst/farstream/fs-stream.h> | |
31 | #include <gst/farstream/fs-participant.h> | |
32 | #include <gst/farstream/fs-codec.h> | |
33 | ||
34 | G_BEGIN_DECLS | |
35 | ||
36 | /* TYPE MACROS */ | |
37 | #define FS_TYPE_SESSION \ | |
38 | (fs_session_get_type ()) | |
39 | #define FS_SESSION(obj) \ | |
40 | (G_TYPE_CHECK_INSTANCE_CAST((obj), FS_TYPE_SESSION, FsSession)) | |
41 | #define FS_SESSION_CLASS(klass) \ | |
42 | (G_TYPE_CHECK_CLASS_CAST((klass), FS_TYPE_SESSION, FsSessionClass)) | |
43 | #define FS_IS_SESSION(obj) \ | |
44 | (G_TYPE_CHECK_INSTANCE_TYPE((obj), FS_TYPE_SESSION)) | |
45 | #define FS_IS_SESSION_CLASS(klass) \ | |
46 | (G_TYPE_CHECK_CLASS_TYPE((klass), FS_TYPE_SESSION)) | |
47 | #define FS_SESSION_GET_CLASS(obj) \ | |
48 | (G_TYPE_INSTANCE_GET_CLASS ((obj), FS_TYPE_SESSION, FsSessionClass)) | |
49 | #define FS_SESSION_CAST(obj) ((FsSession *) (obj)) | |
50 | ||
51 | typedef struct _FsSession FsSession; | |
52 | typedef struct _FsSessionClass FsSessionClass; | |
53 | typedef struct _FsSessionPrivate FsSessionPrivate; | |
54 | ||
55 | /** | |
56 | * FsDTMFEvent: | |
57 | * | |
58 | * An enum that represents the different DTMF event that can be sent to a | |
59 | * #FsSession. The values corresponds those those defined in RFC 4733 | |
60 | * The rest of the possibles values are in the IANA registry at: | |
61 | * http://www.iana.org/assignments/audio-telephone-event-registry | |
62 | * | |
63 | */ | |
64 | typedef enum _FsDTMFEvent | |
65 | { | |
66 | /*< protected >*/ | |
67 | FS_DTMF_EVENT_0 = 0, | |
68 | FS_DTMF_EVENT_1 = 1, | |
69 | FS_DTMF_EVENT_2 = 2, | |
70 | FS_DTMF_EVENT_3 = 3, | |
71 | FS_DTMF_EVENT_4 = 4, | |
72 | FS_DTMF_EVENT_5 = 5, | |
73 | FS_DTMF_EVENT_6 = 6, | |
74 | FS_DTMF_EVENT_7 = 7, | |
75 | FS_DTMF_EVENT_8 = 8, | |
76 | FS_DTMF_EVENT_9 = 9, | |
77 | FS_DTMF_EVENT_STAR = 10, | |
78 | FS_DTMF_EVENT_POUND = 11, | |
79 | FS_DTMF_EVENT_A = 12, | |
80 | FS_DTMF_EVENT_B = 13, | |
81 | FS_DTMF_EVENT_C = 14, | |
82 | FS_DTMF_EVENT_D = 15 | |
83 | } FsDTMFEvent; | |
84 | ||
85 | /** | |
86 | * FsDTMFMethod: | |
87 | * @FS_DTMF_METHOD_AUTO: Send in any possible way | |
88 | * @FS_DTMF_METHOD_RTP_RFC4733: Send as a special payload type defined by RFC 4733 | |
89 | * (which obsoletes RFC 2833) | |
90 | * @FS_DTMF_METHOD_SOUND: Send as tones as in-band audio sound | |
91 | * | |
92 | * An enum that represents the different ways a DTMF event can be sent | |
93 | * | |
94 | */ | |
95 | typedef enum _FsDTMFMethod | |
96 | { | |
97 | FS_DTMF_METHOD_AUTO = 0, | |
98 | FS_DTMF_METHOD_RTP_RFC4733, | |
99 | FS_DTMF_METHOD_SOUND | |
100 | } FsDTMFMethod; | |
101 | ||
102 | /** | |
103 | * FsSessionClass: | |
104 | * @parent_class: Our parent | |
105 | * @new_stream: Create a new #FsStream | |
106 | * @start_telephony_event: Starts a telephony event | |
107 | * @stop_telephony_event: Stops a telephony event | |
108 | * @set_send_codec: Forces sending with a specific codec | |
109 | * @set_codec_preferences: Specifies the codec preferences | |
110 | * @list_transmitters: Returns a list of the available transmitters | |
111 | * @get_stream_transmitter_type: Returns the GType of the stream transmitter | |
112 | * @codecs_need_resend: Returns the list of codecs that need resending | |
113 | * | |
114 | * You must override at least new_stream in a subclass. | |
115 | */ | |
116 | ||
117 | ||
118 | struct _FsSessionClass | |
119 | { | |
120 | GstObjectClass parent_class; | |
121 | ||
122 | /*virtual functions */ | |
123 | FsStream *(* new_stream) (FsSession *session, | |
124 | FsParticipant *participant, | |
125 | FsStreamDirection direction, | |
126 | GError **error); | |
127 | ||
128 | gboolean (* start_telephony_event) (FsSession *session, guint8 event, | |
129 | guint8 volume, FsDTMFMethod method); | |
130 | gboolean (* stop_telephony_event) (FsSession *session, FsDTMFMethod method); | |
131 | ||
132 | gboolean (* set_send_codec) (FsSession *session, FsCodec *send_codec, | |
133 | GError **error); | |
134 | gboolean (* set_codec_preferences) (FsSession *session, | |
135 | GList *codec_preferences, | |
136 | GError **error); | |
137 | ||
138 | gchar** (* list_transmitters) (FsSession *session); | |
139 | ||
140 | GType (* get_stream_transmitter_type) (FsSession *session, | |
141 | const gchar *transmitter); | |
142 | ||
143 | GList* (* codecs_need_resend) (FsSession *session, GList *old_codecs, | |
144 | GList *new_codecs); | |
145 | ||
146 | /*< private >*/ | |
147 | gpointer _padding[8]; | |
148 | }; | |
149 | ||
150 | /** | |
151 | * FsSession: | |
152 | * | |
153 | * All members are private, access them using methods and properties | |
154 | */ | |
155 | struct _FsSession | |
156 | { | |
157 | GstObject parent; | |
158 | /*< private >*/ | |
159 | ||
160 | FsSessionPrivate *priv; | |
161 | ||
162 | ||
163 | gpointer _padding[8]; | |
164 | }; | |
165 | ||
166 | GType fs_session_get_type (void); | |
167 | ||
168 | FsStream *fs_session_new_stream (FsSession *session, | |
169 | FsParticipant *participant, | |
170 | FsStreamDirection direction, | |
171 | GError **error); | |
172 | ||
173 | gboolean fs_session_start_telephony_event (FsSession *session, guint8 event, | |
174 | guint8 volume, FsDTMFMethod method); | |
175 | ||
176 | gboolean fs_session_stop_telephony_event (FsSession *session, | |
177 | FsDTMFMethod method); | |
178 | ||
179 | gboolean fs_session_set_send_codec (FsSession *session, FsCodec *send_codec, | |
180 | GError **error); | |
181 | ||
182 | gboolean fs_session_set_codec_preferences (FsSession *session, | |
183 | GList *codec_preferences, | |
184 | GError **error); | |
185 | ||
186 | gchar **fs_session_list_transmitters (FsSession *session); | |
187 | ||
188 | void fs_session_emit_error (FsSession *session, | |
189 | gint error_no, | |
190 | const gchar *error_msg); | |
191 | ||
192 | GType fs_session_get_stream_transmitter_type (FsSession *session, | |
193 | const gchar *transmitter); | |
194 | ||
195 | GList* fs_session_codecs_need_resend (FsSession *session, | |
196 | GList *old_codecs, GList *new_codecs); | |
197 | ||
198 | void fs_session_destroy (FsSession *session); | |
199 | ||
200 | ||
201 | G_END_DECLS | |
202 | ||
203 | #endif /* __FS_SESSION_H__ */ |
0 | /* | |
1 | * Farstream - Farstream Stream Transmitter | |
2 | * | |
3 | * Copyright 2007 Collabora Ltd. | |
4 | * @author: Olivier Crete <olivier.crete@collabora.co.uk> | |
5 | * Copyright 2007 Nokia Corp. | |
6 | * | |
7 | * fs-stream-transmitter.c - A Farstream Stream Transmitter gobject | |
8 | * | |
9 | * This library is free software; you can redistribute it and/or | |
10 | * modify it under the terms of the GNU Lesser General Public | |
11 | * License as published by the Free Software Foundation; either | |
12 | * version 2.1 of the License, or (at your option) any later version. | |
13 | * | |
14 | * This library is distributed in the hope that it will be useful, | |
15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
17 | * Lesser General Public License for more details. | |
18 | * | |
19 | * You should have received a copy of the GNU Lesser General Public | |
20 | * License along with this library; if not, write to the Free Software | |
21 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA | |
22 | */ | |
23 | ||
24 | /** | |
25 | * SECTION:fs-stream-transmitter | |
26 | * @short_description: A stream transmitter object used to convey per-stream | |
27 | * information to a transmitter. | |
28 | * | |
29 | * This object is the base implementation of a Farstream Stream Transmitter. | |
30 | * It needs to be derived and implement by a Farstream transmitter. | |
31 | * A Farstream Stream transmitter is used to convery per-stream information | |
32 | * to a transmitter, this is mostly local and remote candidates | |
33 | * | |
34 | */ | |
35 | ||
36 | #ifdef HAVE_CONFIG_H | |
37 | #include "config.h" | |
38 | #endif | |
39 | ||
40 | #include "fs-stream-transmitter.h" | |
41 | ||
42 | #include <gst/gst.h> | |
43 | ||
44 | #include "fs-marshal.h" | |
45 | #include "fs-conference.h" | |
46 | #include "fs-private.h" | |
47 | ||
48 | #define GST_CAT_DEFAULT fs_conference_debug | |
49 | ||
50 | /* Signals */ | |
51 | enum | |
52 | { | |
53 | ERROR_SIGNAL, | |
54 | NEW_LOCAL_CANDIDATE, | |
55 | NEW_ACTIVE_CANDIDATE_PAIR, | |
56 | LOCAL_CANDIDATES_PREPARED, | |
57 | KNOWN_SOURCE_PACKET_RECEIVED, | |
58 | STATE_CHANGED, | |
59 | LAST_SIGNAL | |
60 | }; | |
61 | ||
62 | /* props */ | |
63 | enum | |
64 | { | |
65 | PROP_0, | |
66 | PROP_SENDING, | |
67 | PROP_PREFERRED_LOCAL_CANDIDATES, | |
68 | PROP_ASSOCIATE_ON_SOURCE | |
69 | }; | |
70 | ||
71 | struct _FsStreamTransmitterPrivate | |
72 | { | |
73 | gboolean disposed; | |
74 | }; | |
75 | ||
76 | G_DEFINE_ABSTRACT_TYPE(FsStreamTransmitter, fs_stream_transmitter, | |
77 | GST_TYPE_OBJECT); | |
78 | ||
79 | ||
80 | #define FS_STREAM_TRANSMITTER_GET_PRIVATE(o) \ | |
81 | (G_TYPE_INSTANCE_GET_PRIVATE ((o), FS_TYPE_STREAM_TRANSMITTER, \ | |
82 | FsStreamTransmitterPrivate)) | |
83 | ||
84 | static void fs_stream_transmitter_get_property (GObject *object, | |
85 | guint prop_id, | |
86 | GValue *value, | |
87 | GParamSpec *pspec); | |
88 | static void fs_stream_transmitter_set_property (GObject *object, | |
89 | guint prop_id, | |
90 | const GValue *value, | |
91 | GParamSpec *pspec); | |
92 | ||
93 | static guint signals[LAST_SIGNAL] = { 0 }; | |
94 | ||
95 | static void | |
96 | fs_stream_transmitter_class_init (FsStreamTransmitterClass *klass) | |
97 | { | |
98 | GObjectClass *gobject_class; | |
99 | ||
100 | gobject_class = (GObjectClass *) klass; | |
101 | ||
102 | gobject_class->set_property = fs_stream_transmitter_set_property; | |
103 | gobject_class->get_property = fs_stream_transmitter_get_property; | |
104 | ||
105 | ||
106 | /** | |
107 | * FsStreamTransmitter:sending: | |
108 | * | |
109 | * A network source #GstElement to be used by the #FsSession | |
110 | * | |
111 | */ | |
112 | g_object_class_install_property (gobject_class, | |
113 | PROP_SENDING, | |
114 | g_param_spec_boolean ("sending", | |
115 | "Whether to send from this transmitter", | |
116 | "If set to FALSE, the transmitter will stop sending to this person", | |
117 | TRUE, | |
118 | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); | |
119 | ||
120 | /** | |
121 | * FsStreamTransmitter:preferred-local-candidate: | |
122 | * | |
123 | * The list of preferred local candidates for this stream | |
124 | * It is a #GList of #FsCandidates | |
125 | * | |
126 | */ | |
127 | g_object_class_install_property (gobject_class, | |
128 | PROP_PREFERRED_LOCAL_CANDIDATES, | |
129 | g_param_spec_boxed ("preferred-local-candidates", | |
130 | "The preferred candidates", | |
131 | "A GList of FsCandidates", | |
132 | FS_TYPE_CANDIDATE_LIST, | |
133 | G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); | |
134 | ||
135 | /** | |
136 | * FsStreamTransmitter:associate-on-source | |
137 | * | |
138 | * This tells the stream transmitter to associate incoming data with this | |
139 | * based on the source without looking at the content if possible. | |
140 | * | |
141 | */ | |
142 | ||
143 | g_object_class_install_property (gobject_class, | |
144 | PROP_ASSOCIATE_ON_SOURCE, | |
145 | g_param_spec_boolean ("associate-on-source", | |
146 | "Associate incoming data based on the source address", | |
147 | "Whether to associate incoming data stream based on the source address", | |
148 | TRUE, | |
149 | G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); | |
150 | ||
151 | /** | |
152 | * FsStreamTransmitter::error: | |
153 | * @self: #FsStreamTransmitter that emitted the signal | |
154 | * @errorno: The number of the error | |
155 | * @error_msg: Error message (for the programmer) | |
156 | * | |
157 | * This signal is emitted in any error condition | |
158 | * | |
159 | */ | |
160 | signals[ERROR_SIGNAL] = g_signal_new ("error", | |
161 | G_TYPE_FROM_CLASS (klass), | |
162 | G_SIGNAL_RUN_LAST, | |
163 | 0, | |
164 | NULL, | |
165 | NULL, | |
166 | _fs_marshal_VOID__ENUM_STRING, | |
167 | G_TYPE_NONE, 2, FS_TYPE_ERROR, G_TYPE_STRING); | |
168 | ||
169 | /** | |
170 | * FsStreamTransmitter::new-active-candidate-pair: | |
171 | * @self: #FsStreamTransmitter that emitted the signal | |
172 | * @local_candidate: #FsCandidate of the local candidate being used | |
173 | * @remote_candidate: #FsCandidate of the remote candidate being used | |
174 | * | |
175 | * This signal is emitted when there is a new active chandidate pair that has | |
176 | * been established. This is specially useful for ICE where the active | |
177 | * candidate pair can change automatically due to network conditions. The user | |
178 | * must not modify the candidates and must copy them if he wants to use them | |
179 | * outside the callback scope. | |
180 | * | |
181 | */ | |
182 | signals[NEW_ACTIVE_CANDIDATE_PAIR] = g_signal_new | |
183 | ("new-active-candidate-pair", | |
184 | G_TYPE_FROM_CLASS (klass), | |
185 | G_SIGNAL_RUN_LAST, | |
186 | 0, | |
187 | NULL, | |
188 | NULL, | |
189 | _fs_marshal_VOID__BOXED_BOXED, | |
190 | G_TYPE_NONE, 2, FS_TYPE_CANDIDATE, FS_TYPE_CANDIDATE); | |
191 | ||
192 | /** | |
193 | * FsStreamTransmitter::new-local-candidate: | |
194 | * @self: #FsStream that emitted the signal | |
195 | * @local_candidate: #FsCandidate of the local candidate | |
196 | * | |
197 | * This signal is emitted when a new local candidate is discovered. | |
198 | * | |
199 | */ | |
200 | signals[NEW_LOCAL_CANDIDATE] = g_signal_new | |
201 | ("new-local-candidate", | |
202 | G_TYPE_FROM_CLASS (klass), | |
203 | G_SIGNAL_RUN_LAST, | |
204 | 0, | |
205 | NULL, | |
206 | NULL, | |
207 | g_cclosure_marshal_VOID__BOXED, | |
208 | G_TYPE_NONE, 1, FS_TYPE_CANDIDATE); | |
209 | ||
210 | /** | |
211 | * FsStreamTransmitter::local-candidates-prepared: | |
212 | * @self: #FsStreamTransmitter that emitted the signal | |
213 | * | |
214 | * This signal is emitted when all local candidates have been | |
215 | * prepared, an ICE implementation would send its SDP offer or answer. | |
216 | * | |
217 | */ | |
218 | signals[LOCAL_CANDIDATES_PREPARED] = g_signal_new | |
219 | ("local-candidates-prepared", | |
220 | G_TYPE_FROM_CLASS (klass), | |
221 | G_SIGNAL_RUN_LAST, | |
222 | 0, | |
223 | NULL, | |
224 | NULL, | |
225 | g_cclosure_marshal_VOID__VOID, | |
226 | G_TYPE_NONE, 0); | |
227 | ||
228 | /** | |
229 | * FsStreamTransmitter::known-source-packet-received: | |
230 | * @self: #FsStreamTransmitter that emitted the signal | |
231 | * @component: The Component on which this buffer was received | |
232 | * @buffer: the #GstBuffer coming from the known source | |
233 | * | |
234 | * This signal is emitted when a buffer coming from a confirmed known source | |
235 | * is received. | |
236 | */ | |
237 | signals[KNOWN_SOURCE_PACKET_RECEIVED] = g_signal_new | |
238 | ("known-source-packet-received", | |
239 | G_TYPE_FROM_CLASS (klass), | |
240 | G_SIGNAL_RUN_LAST, | |
241 | 0, | |
242 | NULL, | |
243 | NULL, | |
244 | _fs_marshal_VOID__UINT_POINTER, | |
245 | G_TYPE_NONE, 2, G_TYPE_UINT, G_TYPE_POINTER); | |
246 | ||
247 | ||
248 | /** | |
249 | * FsStreamTransmitter::state-changed | |
250 | * @self: #FsStreamTransmitter that emitted the signal | |
251 | * @component: the id of the component which state has changed | |
252 | * @state: the new state of the component | |
253 | * | |
254 | * This signal is emitted when the ICE state (or equivalent) of the component | |
255 | * changes | |
256 | */ | |
257 | signals[STATE_CHANGED] = g_signal_new | |
258 | ("state-changed", | |
259 | G_TYPE_FROM_CLASS (klass), | |
260 | G_SIGNAL_RUN_LAST, | |
261 | 0, | |
262 | NULL, | |
263 | NULL, | |
264 | _fs_marshal_VOID__UINT_ENUM, | |
265 | G_TYPE_NONE, 2, G_TYPE_UINT, FS_TYPE_STREAM_STATE); | |
266 | ||
267 | ||
268 | g_type_class_add_private (klass, sizeof (FsStreamTransmitterPrivate)); | |
269 | } | |
270 | ||
271 | static void | |
272 | fs_stream_transmitter_init (FsStreamTransmitter *self) | |
273 | { | |
274 | /* member init */ | |
275 | self->priv = FS_STREAM_TRANSMITTER_GET_PRIVATE (self); | |
276 | self->priv->disposed = FALSE; | |
277 | } | |
278 | ||
279 | static void | |
280 | fs_stream_transmitter_get_property (GObject *object, | |
281 | guint prop_id, | |
282 | GValue *value, | |
283 | GParamSpec *pspec) | |
284 | { | |
285 | GST_WARNING ("Subclass %s of FsStreamTransmitter does not override the %s" | |
286 | " property getter", | |
287 | G_OBJECT_TYPE_NAME(object), | |
288 | g_param_spec_get_name (pspec)); | |
289 | } | |
290 | ||
291 | static void | |
292 | fs_stream_transmitter_set_property (GObject *object, | |
293 | guint prop_id, | |
294 | const GValue *value, | |
295 | GParamSpec *pspec) | |
296 | { | |
297 | switch (prop_id) | |
298 | { | |
299 | /* These properties, we can safely not override */ | |
300 | case PROP_ASSOCIATE_ON_SOURCE: | |
301 | break; | |
302 | default: | |
303 | GST_WARNING ("Subclass %s of FsStreamTransmitter does not override the %s" | |
304 | " property setter", | |
305 | G_OBJECT_TYPE_NAME(object), | |
306 | g_param_spec_get_name (pspec)); | |
307 | break; | |
308 | } | |
309 | } | |
310 | ||
311 | ||
312 | /** | |
313 | * fs_stream_transmitter_add_remote_candidates | |
314 | * @streamtransmitter: a #FsStreamTranmitter | |
315 | * @candidates: (element-type FsCandidate): a #GList of the remote candidates | |
316 | * @error: location of a #GError, or NULL if no error occured | |
317 | * | |
318 | * This function is used to add remote candidates to the transmitter | |
319 | * | |
320 | * Returns: TRUE of the candidate could be added, FALSE if it couldnt | |
321 | * (and the #GError will be set) | |
322 | */ | |
323 | ||
324 | gboolean | |
325 | fs_stream_transmitter_add_remote_candidates ( | |
326 | FsStreamTransmitter *streamtransmitter, | |
327 | GList *candidates, | |
328 | GError **error) | |
329 | { | |
330 | FsStreamTransmitterClass *klass; | |
331 | ||
332 | g_return_val_if_fail (streamtransmitter, FALSE); | |
333 | g_return_val_if_fail (FS_IS_STREAM_TRANSMITTER (streamtransmitter), FALSE); | |
334 | klass = FS_STREAM_TRANSMITTER_GET_CLASS (streamtransmitter); | |
335 | ||
336 | if (klass->add_remote_candidates) { | |
337 | return klass->add_remote_candidates (streamtransmitter, candidates, error); | |
338 | } else { | |
339 | g_set_error (error, FS_ERROR, FS_ERROR_NOT_IMPLEMENTED, | |
340 | "add_remote_candidate not defined in stream transmitter class"); | |
341 | } | |
342 | ||
343 | return FALSE; | |
344 | } | |
345 | ||
346 | /** | |
347 | * fs_stream_transmitter_force_remote_candidates: | |
348 | * @streamtransmitter: a #FsStreamTransmitter | |
349 | * @remote_candidates: (element-type FsCandidate): a #GList of #FsCandidate to | |
350 | * force | |
351 | * @error: location of a #GError, or NULL if no error occured | |
352 | * | |
353 | * This function forces data to be sent immediately to the selected remote | |
354 | * candidate, by-passing any connectivity checks. There should be at most | |
355 | * one candidate per component. | |
356 | * | |
357 | * Returns: %TRUE if the candidates could be forced, %FALSE otherwise | |
358 | */ | |
359 | ||
360 | gboolean | |
361 | fs_stream_transmitter_force_remote_candidates ( | |
362 | FsStreamTransmitter *streamtransmitter, | |
363 | GList *remote_candidates, | |
364 | GError **error) | |
365 | { | |
366 | FsStreamTransmitterClass *klass; | |
367 | ||
368 | g_return_val_if_fail (streamtransmitter, FALSE); | |
369 | g_return_val_if_fail (FS_IS_STREAM_TRANSMITTER (streamtransmitter), FALSE); | |
370 | klass = FS_STREAM_TRANSMITTER_GET_CLASS (streamtransmitter); | |
371 | ||
372 | if (klass->force_remote_candidates) { | |
373 | return klass->force_remote_candidates (streamtransmitter, | |
374 | remote_candidates, error); | |
375 | } else { | |
376 | g_set_error (error, FS_ERROR, FS_ERROR_NOT_IMPLEMENTED, | |
377 | "force_remote_candidates not defined in stream transmitter class"); | |
378 | } | |
379 | ||
380 | return FALSE; | |
381 | } | |
382 | ||
383 | /** | |
384 | * fs_stream_transmitter_gather_local_candidates: | |
385 | * @streamtransmitter: a #FsStreamTransmitter | |
386 | * @error: location of a #GErrorh, or NULL if no error occured | |
387 | * | |
388 | * This function tells the transmitter to start gathering local candidates, | |
389 | * signals for new candidates and newly active candidates can be emitted | |
390 | * during the call to this function. | |
391 | * | |
392 | * Returns: %TRUE if it succeeds (or is not implemented), %FALSE otherwise | |
393 | */ | |
394 | ||
395 | gboolean | |
396 | fs_stream_transmitter_gather_local_candidates ( | |
397 | FsStreamTransmitter *streamtransmitter, | |
398 | GError **error) | |
399 | { | |
400 | FsStreamTransmitterClass *klass; | |
401 | ||
402 | g_return_val_if_fail (streamtransmitter, FALSE); | |
403 | g_return_val_if_fail (FS_IS_STREAM_TRANSMITTER (streamtransmitter), FALSE); | |
404 | klass = FS_STREAM_TRANSMITTER_GET_CLASS (streamtransmitter); | |
405 | ||
406 | if (klass->gather_local_candidates) | |
407 | return klass->gather_local_candidates (streamtransmitter, error); | |
408 | else | |
409 | return TRUE; | |
410 | } | |
411 | ||
412 | ||
413 | ||
414 | /** | |
415 | * fs_stream_transmitter_stop: | |
416 | * @streamtransmitter: a #FsStreamTransmitter | |
417 | * | |
418 | * This functions stops the #FsStreamTransmitter, it must be called before | |
419 | * the last reference is dropped. | |
420 | */ | |
421 | ||
422 | void | |
423 | fs_stream_transmitter_stop (FsStreamTransmitter *streamtransmitter) | |
424 | { | |
425 | FsStreamTransmitterClass *klass; | |
426 | ||
427 | g_return_if_fail (streamtransmitter); | |
428 | g_return_if_fail (FS_IS_STREAM_TRANSMITTER (streamtransmitter)); | |
429 | klass = FS_STREAM_TRANSMITTER_GET_CLASS (streamtransmitter); | |
430 | ||
431 | if (klass->stop) | |
432 | klass->stop (streamtransmitter); | |
433 | } | |
434 | ||
435 | ||
436 | /** | |
437 | * fs_stream_transmitter_emit_error: | |
438 | * @streamtransmitter: #FsStreamTransmitter on which to emit the error signal | |
439 | * @error_no: The number of the error | |
440 | * @error_msg: Error message (for the programmer) | |
441 | * | |
442 | * This function emit the "error" signal on a #FsStreamTransmitter, it should | |
443 | * only be called by subclasses. | |
444 | */ | |
445 | void | |
446 | fs_stream_transmitter_emit_error (FsStreamTransmitter *streamtransmitter, | |
447 | gint error_no, | |
448 | const gchar *error_msg) | |
449 | { | |
450 | g_signal_emit (streamtransmitter, signals[ERROR_SIGNAL], 0, error_no, | |
451 | error_msg); | |
452 | } |
0 | /* | |
1 | * Farstream - Farstream Stream Transmitter | |
2 | * | |
3 | * Copyright 2007 Collabora Ltd. | |
4 | * @author: Olivier Crete <olivier.crete@collabora.co.uk> | |
5 | * Copyright 2007 Nokia Corp. | |
6 | * | |
7 | * fs-stream-transmitter.h - A Farstream Stream Transmitter (base implementation) | |
8 | * | |
9 | * This library is free software; you can redistribute it and/or | |
10 | * modify it under the terms of the GNU Lesser General Public | |
11 | * License as published by the Free Software Foundation; either | |
12 | * version 2.1 of the License, or (at your option) any later version. | |
13 | * | |
14 | * This library is distributed in the hope that it will be useful, | |
15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
17 | * Lesser General Public License for more details. | |
18 | * | |
19 | * You should have received a copy of the GNU Lesser General Public | |
20 | * License along with this library; if not, write to the Free Software | |
21 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA | |
22 | */ | |
23 | ||
24 | #ifndef __FS_STREAM_TRANSMITTER_H__ | |
25 | #define __FS_STREAM_TRANSMITTER_H__ | |
26 | ||
27 | #include <gst/gst.h> | |
28 | ||
29 | #include <gst/farstream/fs-candidate.h> | |
30 | ||
31 | G_BEGIN_DECLS | |
32 | ||
33 | /* TYPE MACROS */ | |
34 | #define FS_TYPE_STREAM_TRANSMITTER \ | |
35 | (fs_stream_transmitter_get_type ()) | |
36 | #define FS_STREAM_TRANSMITTER(obj) \ | |
37 | (G_TYPE_CHECK_INSTANCE_CAST((obj), FS_TYPE_STREAM_TRANSMITTER, \ | |
38 | FsStreamTransmitter)) | |
39 | #define FS_STREAM_TRANSMITTER_CLASS(klass) \ | |
40 | (G_TYPE_CHECK_CLASS_CAST((klass), FS_TYPE_STREAM_TRANSMITTER, \ | |
41 | FsStreamTransmitterClass)) | |
42 | #define FS_IS_STREAM_TRANSMITTER(obj) \ | |
43 | (G_TYPE_CHECK_INSTANCE_TYPE((obj), FS_TYPE_STREAM_TRANSMITTER)) | |
44 | #define FS_IS_STREAM_TRANSMITTER_CLASS(klass) \ | |
45 | (G_TYPE_CHECK_CLASS_TYPE((klass), FS_TYPE_STREAM_TRANSMITTER)) | |
46 | #define FS_STREAM_TRANSMITTER_GET_CLASS(obj) \ | |
47 | (G_TYPE_INSTANCE_GET_CLASS ((obj), FS_TYPE_STREAM_TRANSMITTER, \ | |
48 | FsStreamTransmitterClass)) | |
49 | #define FS_STREAM_TRANSMITTER_CAST(obj) ((FsStreamTransmitter *) (obj)) | |
50 | ||
51 | typedef struct _FsStreamTransmitter FsStreamTransmitter; | |
52 | typedef struct _FsStreamTransmitterClass FsStreamTransmitterClass; | |
53 | typedef struct _FsStreamTransmitterPrivate FsStreamTransmitterPrivate; | |
54 | ||
55 | /** | |
56 | * FsStreamTransmitterClass: | |
57 | * @parent_class: Our parent | |
58 | * @add_remote_candidates: Sets the remote candidates | |
59 | * @force_remote_candidates: Forces certain remote candidates | |
60 | * @gather_local_candidates: Starts the gathering of local candidates | |
61 | * @stop: Stop the stream transmitter synchronously (does any Gst stopping | |
62 | * that needs to be done) | |
63 | * | |
64 | * You must override the add_remote_candidate in a subclass | |
65 | */ | |
66 | ||
67 | struct _FsStreamTransmitterClass | |
68 | { | |
69 | GstObjectClass parent_class; | |
70 | ||
71 | /*virtual functions */ | |
72 | gboolean (*add_remote_candidates) (FsStreamTransmitter *streamtransmitter, | |
73 | GList *candidates, GError **error); | |
74 | ||
75 | gboolean (*force_remote_candidates) (FsStreamTransmitter *streamtransmitter, | |
76 | GList *remote_candidates, | |
77 | GError **error); | |
78 | gboolean (*gather_local_candidates) (FsStreamTransmitter *streamtransmitter, | |
79 | GError **error); | |
80 | void (*stop) (FsStreamTransmitter *streamtransmitter); | |
81 | ||
82 | /*< private >*/ | |
83 | gpointer _padding[8]; | |
84 | }; | |
85 | ||
86 | /** | |
87 | * FsStreamTransmitter: | |
88 | * | |
89 | * All members are private, access them using methods and properties | |
90 | */ | |
91 | struct _FsStreamTransmitter | |
92 | { | |
93 | GstObject parent; | |
94 | ||
95 | /*< private >*/ | |
96 | FsStreamTransmitterPrivate *priv; | |
97 | gpointer _padding[8]; | |
98 | }; | |
99 | ||
100 | GType fs_stream_transmitter_get_type (void); | |
101 | ||
102 | gboolean fs_stream_transmitter_add_remote_candidates ( | |
103 | FsStreamTransmitter *streamtransmitter, | |
104 | GList *candidates, | |
105 | GError **error); | |
106 | ||
107 | gboolean fs_stream_transmitter_force_remote_candidates ( | |
108 | FsStreamTransmitter *streamtransmitter, | |
109 | GList *remote_candidates, | |
110 | GError **error); | |
111 | ||
112 | gboolean | |
113 | fs_stream_transmitter_gather_local_candidates ( | |
114 | FsStreamTransmitter *streamtransmitter, | |
115 | GError **error); | |
116 | ||
117 | void fs_stream_transmitter_stop (FsStreamTransmitter *streamtransmitter); | |
118 | ||
119 | void fs_stream_transmitter_emit_error (FsStreamTransmitter *streamtransmitter, | |
120 | gint error_no, | |
121 | const gchar *error_msg); | |
122 | ||
123 | G_END_DECLS | |
124 | ||
125 | #endif /* __FS_STREAM_TRANSMITTER_H__ */ |
0 | /* | |
1 | * Farstream - Farstream Stream | |
2 | * | |
3 | * Copyright 2007 Collabora Ltd. | |
4 | * @author: Philippe Kalaf <philippe.kalaf@collabora.co.uk> | |
5 | * Copyright 2007 Nokia Corp. | |
6 | * | |
7 | * fs-stream.c - A Farstream Stream gobject (base implementation) | |
8 | * | |
9 | * This library is free software; you can redistribute it and/or | |
10 | * modify it under the terms of the GNU Lesser General Public | |
11 | * License as published by the Free Software Foundation; either | |
12 | * version 2.1 of the License, or (at your option) any later version. | |
13 | * | |
14 | * This library is distributed in the hope that it will be useful, | |
15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
17 | * Lesser General Public License for more details. | |
18 | * | |
19 | * You should have received a copy of the GNU Lesser General Public | |
20 | * License along with this library; if not, write to the Free Software | |
21 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA | |
22 | */ | |
23 | ||
24 | /** | |
25 | * SECTION:fs-stream | |
26 | * @short_description: A stream in a session in a conference | |
27 | * | |
28 | * This object is the base implementation of a Farstream Stream. It | |
29 | * needs to be derived and implemented by a Farstream conference GStreamer | |
30 | * element. A Farstream Stream is a media stream originating from a | |
31 | * #FsParticipant inside a #FsSession. In fact, a #FsStream instance is | |
32 | * obtained by adding a participant into a session using | |
33 | * fs_session_new_stream(). | |
34 | * | |
35 | * | |
36 | * This will communicate asynchronous events to the user through #GstMessage | |
37 | * of type #GST_MESSAGE_ELEMENT sent over the #GstBus. | |
38 | * </para> | |
39 | * <refsect2><title>The "<literal>farstream-new-local-candidate</literal>" message</title> | |
40 | * |[ | |
41 | * "stream" #FsStream The stream that emits the message | |
42 | * "candidate" #FsCandidate The new candidate | |
43 | * ]| | |
44 | * <para> | |
45 | * This message is emitted when a new local candidate is discovered. | |
46 | * </para> | |
47 | * </refsect2> | |
48 | * <refsect2><title>The "<literal>farstream-local-candidates-prepared</literal>" message</title> | |
49 | * |[ | |
50 | * "stream" #FsStream The stream that emits the message | |
51 | * ]| | |
52 | * <para> | |
53 | * This signal is emitted when all local candidates have been | |
54 | * prepared, an ICE implementation would send its SDP offer or answer. | |
55 | * </para> | |
56 | * </refsect2> | |
57 | * <refsect2><title>The "<literal>farstream-new-active-candidate-pair</literal>" message</title> | |
58 | * |[ | |
59 | * "stream" #FsStream The stream that emits the message | |
60 | * "local-candidate" #FsCandidate Local candidate being used | |
61 | * "remote-candidate" #FsCandidate Remote candidate being used | |
62 | * ]| | |
63 | * <para> | |
64 | * This message is emitted when there is a new active candidate pair that has | |
65 | * been established. This is specially useful for ICE where the active | |
66 | * candidate pair can change automatically due to network conditions. The user | |
67 | * must not modify the candidates and must copy them if he wants to use them | |
68 | * outside the callback scope. This message is emitted once per component. | |
69 | * </para> | |
70 | * </refsect2> | |
71 | * <refsect2><title>The "<literal>farstream-recv-codecs-changed</literal>" message</title> | |
72 | * |[ | |
73 | * "stream" #FsStream The stream that emits the message | |
74 | * "codecs" #FsCodecGList A #GList of #FsCodec | |
75 | * ]| | |
76 | * <para> | |
77 | * This message is emitted when the content of the | |
78 | * #FsStream:current-recv-codecs property changes. It is normally emitted | |
79 | * right after the #FsStream::src-pad-added signal only if that codec was not | |
80 | * previously received in this stream, but it can also be emitted if the pad | |
81 | * already exists, but the source material that will come to it is different. | |
82 | * The list of new recv-codecs is included in the message | |
83 | * </para> | |
84 | * </refsect2> | |
85 | * <refsect2><title>The "<literal>farstream-component-state-changed</literal>" message</title> | |
86 | * |[ | |
87 | * "stream" #FsStream The stream that emits the message | |
88 | * "component" #guint The component whose state changed | |
89 | * "state" #FsStreamState The new state of the component | |
90 | * ]| | |
91 | * <para> | |
92 | * This message is emitted the state of a component of a stream changes. | |
93 | * </para> | |
94 | * </refsect2> | |
95 | * <para> | |
96 | */ | |
97 | ||
98 | #ifdef HAVE_CONFIG_H | |
99 | #include "config.h" | |
100 | #endif | |
101 | ||
102 | #include "fs-stream.h" | |
103 | ||
104 | #include <gst/gst.h> | |
105 | ||
106 | #include "fs-session.h" | |
107 | #include "fs-marshal.h" | |
108 | #include "fs-codec.h" | |
109 | #include "fs-candidate.h" | |
110 | #include "fs-stream-transmitter.h" | |
111 | #include "fs-conference.h" | |
112 | #include "fs-enumtypes.h" | |
113 | #include "fs-private.h" | |
114 | ||
115 | /* Signals */ | |
116 | enum | |
117 | { | |
118 | ERROR_SIGNAL, | |
119 | SRC_PAD_ADDED, | |
120 | LAST_SIGNAL | |
121 | }; | |
122 | ||
123 | /* props */ | |
124 | enum | |
125 | { | |
126 | PROP_0, | |
127 | PROP_REMOTE_CODECS, | |
128 | PROP_NEGOTIATED_CODECS, | |
129 | PROP_CURRENT_RECV_CODECS, | |
130 | PROP_DIRECTION, | |
131 | PROP_PARTICIPANT, | |
132 | PROP_SESSION | |
133 | }; | |
134 | ||
135 | ||
136 | struct _FsStreamPrivate | |
137 | { | |
138 | GMutex *mutex; | |
139 | GList *src_pads; | |
140 | guint32 src_pads_cookie; | |
141 | }; | |
142 | ||
143 | #define FS_STREAM_GET_PRIVATE(o) \ | |
144 | (G_TYPE_INSTANCE_GET_PRIVATE ((o), FS_TYPE_STREAM, FsStreamPrivate)) | |
145 | ||
146 | ||
147 | G_DEFINE_ABSTRACT_TYPE(FsStream, fs_stream, GST_TYPE_OBJECT); | |
148 | ||
149 | static void fs_stream_get_property (GObject *object, | |
150 | guint prop_id, | |
151 | GValue *value, | |
152 | GParamSpec *pspec); | |
153 | static void fs_stream_set_property (GObject *object, | |
154 | guint prop_id, | |
155 | const GValue *value, | |
156 | GParamSpec *pspec); | |
157 | static void fs_stream_finalize (GObject *obj); | |
158 | ||
159 | static guint signals[LAST_SIGNAL] = { 0 }; | |
160 | ||
161 | #define FS_STREAM_LOCK(self) g_mutex_lock((self)->priv->mutex) | |
162 | #define FS_STREAM_UNLOCK(self) g_mutex_unlock((self)->priv->mutex) | |
163 | ||
164 | static void | |
165 | fs_stream_class_init (FsStreamClass *klass) | |
166 | { | |
167 | GObjectClass *gobject_class; | |
168 | ||
169 | gobject_class = (GObjectClass *) klass; | |
170 | ||
171 | gobject_class->set_property = fs_stream_set_property; | |
172 | gobject_class->get_property = fs_stream_get_property; | |
173 | gobject_class->finalize = fs_stream_finalize; | |
174 | ||
175 | /** | |
176 | * FsStream:remote-codecs: | |
177 | * | |
178 | * Type: GLib.List<FsCodec> | |
179 | * Transfer: full | |
180 | * | |
181 | * This is the list of remote codecs for this stream. They must be set by the | |
182 | * user as soon as they are known using fs_stream_set_remote_codecs() | |
183 | * (generally through external signaling). It is a #GList of #FsCodec. | |
184 | * | |
185 | */ | |
186 | g_object_class_install_property (gobject_class, | |
187 | PROP_REMOTE_CODECS, | |
188 | g_param_spec_boxed ("remote-codecs", | |
189 | "List of remote codecs", | |
190 | "A GList of FsCodecs of the remote codecs", | |
191 | FS_TYPE_CODEC_LIST, | |
192 | G_PARAM_READABLE | G_PARAM_STATIC_STRINGS)); | |
193 | ||
194 | /** | |
195 | * FsStream:negotiated-codecs: | |
196 | * | |
197 | * Type: GLib.List<FsCodec> | |
198 | * Transfer: full | |
199 | * | |
200 | * This is the list of negotiatied codecs, it is the same list as the list | |
201 | * of #FsCodec from the parent #FsSession, except that the codec config data | |
202 | * has been replaced with the data from the remote codecs for this stream. | |
203 | * This is the list of #FsCodec used to receive data from this stream. | |
204 | * It is a #GList of #FsCodec. | |
205 | * | |
206 | */ | |
207 | g_object_class_install_property (gobject_class, | |
208 | PROP_NEGOTIATED_CODECS, | |
209 | g_param_spec_boxed ("negotiated-codecs", | |
210 | "List of remote codecs", | |
211 | "A GList of FsCodecs of the negotiated codecs for this stream", | |
212 | FS_TYPE_CODEC_LIST, | |
213 | G_PARAM_READABLE | G_PARAM_STATIC_STRINGS)); | |
214 | ||
215 | /** | |
216 | * FsStream:current-recv-codecs: | |
217 | * | |
218 | * Type: GLib.List<FsCodec> | |
219 | * Transfer: full | |
220 | * | |
221 | * This is the list of codecs that have been received by this stream. | |
222 | * The user must free the list if fs_codec_list_destroy(). | |
223 | * The "farstream-recv-codecs-changed" message is send on the #GstBus | |
224 | * when the value of this property changes. | |
225 | * It is normally emitted right after #FsStream::src-pad-added | |
226 | * only if that codec was not previously received in this stream, but it can | |
227 | * also be emitted if the pad already exists, but the source material that | |
228 | * will come to it is different. | |
229 | * | |
230 | */ | |
231 | g_object_class_install_property (gobject_class, | |
232 | PROP_CURRENT_RECV_CODECS, | |
233 | g_param_spec_boxed ("current-recv-codecs", | |
234 | "The codecs currently being received", | |
235 | "A GList of FsCodec representing the codecs that have been received", | |
236 | FS_TYPE_CODEC_LIST, | |
237 | G_PARAM_READABLE | G_PARAM_STATIC_STRINGS)); | |
238 | ||
239 | /** | |
240 | * FsStream:direction: | |
241 | * | |
242 | * The direction of the stream. This property is set initially as a parameter | |
243 | * to the fs_session_new_stream() function. It can be changed later if | |
244 | * required by setting this property. | |
245 | * | |
246 | */ | |
247 | g_object_class_install_property (gobject_class, | |
248 | PROP_DIRECTION, | |
249 | g_param_spec_flags ("direction", | |
250 | "The direction of the stream", | |
251 | "An enum to set and get the direction of the stream", | |
252 | FS_TYPE_STREAM_DIRECTION, | |
253 | FS_DIRECTION_NONE, | |
254 | G_PARAM_CONSTRUCT | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); | |
255 | ||
256 | /** | |
257 | * FsStream:participant: | |
258 | * | |
259 | * The #FsParticipant for this stream. This property is a construct param and | |
260 | * is read-only construction. | |
261 | * | |
262 | */ | |
263 | g_object_class_install_property (gobject_class, | |
264 | PROP_PARTICIPANT, | |
265 | g_param_spec_object ("participant", | |
266 | "The participant of the stream", | |
267 | "An FsParticipant represented by the stream", | |
268 | FS_TYPE_PARTICIPANT, | |
269 | G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); | |
270 | ||
271 | /** | |
272 | * FsStream:session: | |
273 | * | |
274 | * The #FsSession for this stream. This property is a construct param and | |
275 | * is read-only construction. | |
276 | * | |
277 | */ | |
278 | g_object_class_install_property (gobject_class, | |
279 | PROP_SESSION, | |
280 | g_param_spec_object ("session", | |
281 | "The session of the stream", | |
282 | "An FsSession represented by the stream", | |
283 | FS_TYPE_SESSION, | |
284 | G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); | |
285 | ||
286 | /** | |
287 | * FsStream::error: | |
288 | * @self: #FsStream that emitted the signal | |
289 | * @errorno: The number of the error | |
290 | * @error_msg: Error message to be displayed to user | |
291 | * | |
292 | * This signal is emitted in any error condition | |
293 | * | |
294 | */ | |
295 | signals[ERROR_SIGNAL] = g_signal_new ("error", | |
296 | G_TYPE_FROM_CLASS (klass), | |
297 | G_SIGNAL_RUN_LAST, | |
298 | 0, | |
299 | NULL, | |
300 | NULL, | |
301 | _fs_marshal_VOID__ENUM_STRING, | |
302 | G_TYPE_NONE, 2, FS_TYPE_ERROR, G_TYPE_STRING); | |
303 | ||
304 | /** | |
305 | * FsStream::src-pad-added: | |
306 | * @self: #FsStream that emitted the signal | |
307 | * @pad: #GstPad of the new source pad | |
308 | * @codec: #FsCodec of the codec being received on the new source pad | |
309 | * | |
310 | * This signal is emitted when a new gst source pad has been created for a | |
311 | * specific codec being received. There will be a different source pad for | |
312 | * each codec that is received. The user must ref the #GstPad if he wants to | |
313 | * keep it. The user should not modify the #FsCodec and must copy it if he | |
314 | * wants to use it outside the callback scope. | |
315 | * | |
316 | * This signal is not emitted on the main thread, but on GStreamer's streaming | |
317 | * thread! | |
318 | * | |
319 | */ | |
320 | signals[SRC_PAD_ADDED] = g_signal_new ("src-pad-added", | |
321 | G_TYPE_FROM_CLASS (klass), | |
322 | G_SIGNAL_RUN_LAST, | |
323 | 0, | |
324 | NULL, | |
325 | NULL, | |
326 | _fs_marshal_VOID__BOXED_BOXED, | |
327 | G_TYPE_NONE, 2, GST_TYPE_PAD, FS_TYPE_CODEC); | |
328 | ||
329 | g_type_class_add_private (klass, sizeof (FsStreamPrivate)); | |
330 | } | |
331 | ||
332 | static void | |
333 | fs_stream_init (FsStream *self) | |
334 | { | |
335 | /* member init */ | |
336 | self->priv = FS_STREAM_GET_PRIVATE (self); | |
337 | self->priv->mutex = g_mutex_new (); | |
338 | } | |
339 | ||
340 | static void | |
341 | fs_stream_finalize (GObject *obj) | |
342 | { | |
343 | FsStream *stream = FS_STREAM (obj); | |
344 | ||
345 | g_list_free (stream->priv->src_pads); | |
346 | g_mutex_free (stream->priv->mutex); | |
347 | ||
348 | G_OBJECT_CLASS (fs_stream_parent_class)->finalize (obj); | |
349 | } | |
350 | ||
351 | static void | |
352 | fs_stream_get_property (GObject *object, | |
353 | guint prop_id, | |
354 | GValue *value, | |
355 | GParamSpec *pspec) | |
356 | { | |
357 | GST_WARNING ("Subclass %s of FsStream does not override the %s property" | |
358 | " getter", | |
359 | G_OBJECT_TYPE_NAME(object), | |
360 | g_param_spec_get_name (pspec)); | |
361 | } | |
362 | ||
363 | static void | |
364 | fs_stream_set_property (GObject *object, | |
365 | guint prop_id, | |
366 | const GValue *value, | |
367 | GParamSpec *pspec) | |
368 | { | |
369 | GST_WARNING ("Subclass %s of FsStream does not override the %s property" | |
370 | " setter", | |
371 | G_OBJECT_TYPE_NAME(object), | |
372 | g_param_spec_get_name (pspec)); | |
373 | } | |
374 | ||
375 | /** | |
376 | * fs_stream_add_remote_candidates: | |
377 | * @stream: an #FsStream | |
378 | * @candidates: (element-type FsCandidate): an #GList of #FsCandidate | |
379 | * representing the remote candidates | |
380 | * @error: location of a #GError, or %NULL if no error occured | |
381 | * | |
382 | * This function adds remote candidates. Any new candidates are | |
383 | * added to the list. The candidates will be used to establish a connection | |
384 | * with the peer. A copy will be made so the user must free the | |
385 | * passed candidate using fs_candidate_destroy() when done. | |
386 | * | |
387 | * Return value: TRUE if the candidate was valid, FALSE otherwise | |
388 | */ | |
389 | gboolean | |
390 | fs_stream_add_remote_candidates (FsStream *stream, | |
391 | GList *candidates, | |
392 | GError **error) | |
393 | { | |
394 | FsStreamClass *klass; | |
395 | ||
396 | g_return_val_if_fail (stream, FALSE); | |
397 | g_return_val_if_fail (FS_IS_STREAM (stream), FALSE); | |
398 | klass = FS_STREAM_GET_CLASS (stream); | |
399 | ||
400 | if (klass->add_remote_candidates) { | |
401 | return klass->add_remote_candidates (stream, candidates, error); | |
402 | } else { | |
403 | g_set_error (error, FS_ERROR, FS_ERROR_NOT_IMPLEMENTED, | |
404 | "add_remote_candidate not defined in class"); | |
405 | } | |
406 | ||
407 | return FALSE; | |
408 | } | |
409 | ||
410 | /** | |
411 | * fs_stream_force_remote_candidates: | |
412 | * @stream: a #FsStream | |
413 | * @remote_candidates: (element-type FsCandidate): | |
414 | * a #GList of #FsCandidate to force | |
415 | * @error: location of a #GError, or %NULL if no error occured | |
416 | * | |
417 | * This function forces data to be sent immediately to the selected remote | |
418 | * candidate, by-passing any connectivity checks. There should be at most | |
419 | * one candidate per component. | |
420 | * | |
421 | * Returns: %TRUE if the candidates could be forced, %FALSE otherwise | |
422 | */ | |
423 | ||
424 | gboolean | |
425 | fs_stream_force_remote_candidates (FsStream *stream, | |
426 | GList *remote_candidates, | |
427 | GError **error) | |
428 | { | |
429 | FsStreamClass *klass; | |
430 | ||
431 | g_return_val_if_fail (stream, FALSE); | |
432 | g_return_val_if_fail (FS_IS_STREAM (stream), FALSE); | |
433 | klass = FS_STREAM_GET_CLASS (stream); | |
434 | ||
435 | if (klass->force_remote_candidates) { | |
436 | return klass->force_remote_candidates (stream, | |
437 | remote_candidates, | |
438 | error); | |
439 | } else { | |
440 | g_set_error (error, FS_ERROR, FS_ERROR_NOT_IMPLEMENTED, | |
441 | "force_remote_candidates not defined in class"); | |
442 | } | |
443 | ||
444 | return FALSE; | |
445 | } | |
446 | ||
447 | /** | |
448 | * fs_stream_set_remote_codecs: | |
449 | * @stream: a #FsStream | |
450 | * @remote_codecs: (element-type FsCodec): a #GList of #FsCodec representing | |
451 | * the remote codecs | |
452 | * @error: location of a #GError, or %NULL if no error occured | |
453 | * | |
454 | * This function will set the list of remote codecs for this stream. If | |
455 | * the given remote codecs couldn't be negotiated with the list of local | |
456 | * codecs or already negotiated codecs for the corresponding #FsSession, @error | |
457 | * will be set and %FALSE will be returned. The @remote_codecs list will be | |
458 | * copied so it must be free'd using fs_codec_list_destroy() when done. | |
459 | * | |
460 | * Returns: %FALSE if the remote codecs couldn't be set. | |
461 | */ | |
462 | gboolean | |
463 | fs_stream_set_remote_codecs (FsStream *stream, | |
464 | GList *remote_codecs, GError **error) | |
465 | { | |
466 | FsStreamClass *klass; | |
467 | ||
468 | g_return_val_if_fail (stream, FALSE); | |
469 | g_return_val_if_fail (FS_IS_STREAM (stream), FALSE); | |
470 | klass = FS_STREAM_GET_CLASS (stream); | |
471 | ||
472 | if (klass->set_remote_codecs) { | |
473 | return klass->set_remote_codecs (stream, remote_codecs, error); | |
474 | } else { | |
475 | g_set_error (error, FS_ERROR, FS_ERROR_NOT_IMPLEMENTED, | |
476 | "set_remote_codecs not defined in class"); | |
477 | } | |
478 | ||
479 | return FALSE; | |
480 | } | |
481 | ||
482 | /** | |
483 | * fs_stream_add_id: | |
484 | * @stream: a #FsStream | |
485 | * @id: The id to add to the stream | |
486 | * | |
487 | * This function is used to add data identifiers that allow the | |
488 | * plugin to recognize packets that are meant for id. For example, in RTP, | |
489 | * one would set the SSRCs that are expected. | |
490 | * | |
491 | * Depending on the protocol, one may be able to add more than one ID | |
492 | * to a stream (in RTP you can have multiple SSRCs in a stream). | |
493 | * If a protocol supports only one id, adding a new one will overwrite it. | |
494 | * If an ID was already set on a stream, adding it to another stream will | |
495 | * override the previdous decision. | |
496 | * | |
497 | * For most protocols, calling this function is optional as the incoming data | |
498 | * can be matched with a stream by its source IP address. This is mostly useful | |
499 | * if one is using multicast or is behind a muxer server. | |
500 | */ | |
501 | void | |
502 | fs_stream_add_id (FsStream *stream, | |
503 | guint id) | |
504 | { | |
505 | FsStreamClass *klass; | |
506 | ||
507 | g_return_if_fail (stream); | |
508 | g_return_if_fail (FS_IS_STREAM (stream)); | |
509 | klass = FS_STREAM_GET_CLASS (stream); | |
510 | ||
511 | if (klass->add_id) | |
512 | klass->add_id (stream, id); | |
513 | } | |
514 | ||
515 | /** | |
516 | * fs_stream_emit_error: | |
517 | * @stream: #FsStream on which to emit the error signal | |
518 | * @error_no: The number of the error | |
519 | * @error_msg: Error message to be displayed to user | |
520 | * | |
521 | * This function emits the #FsStream::error" signal, it should only be | |
522 | * called by subclasses. | |
523 | */ | |
524 | void | |
525 | fs_stream_emit_error (FsStream *stream, | |
526 | gint error_no, | |
527 | const gchar *error_msg) | |
528 | { | |
529 | g_signal_emit (stream, signals[ERROR_SIGNAL], 0, error_no, error_msg); | |
530 | } | |
531 | ||
532 | ||
533 | static void | |
534 | src_pad_parent_unset (GstObject *srcpad, GstObject *parent, gpointer user_data) | |
535 | { | |
536 | FsStream *stream = FS_STREAM (user_data); | |
537 | ||
538 | FS_STREAM_LOCK (stream); | |
539 | stream->priv->src_pads = g_list_remove (stream->priv->src_pads, srcpad); | |
540 | stream->priv->src_pads_cookie++; | |
541 | FS_STREAM_UNLOCK (stream); | |
542 | } | |
543 | ||
544 | /** | |
545 | * fs_stream_emit_src_pad_added: | |
546 | * @stream: #FsStream on which to emit the src-pad-added signal | |
547 | * @pad: the #GstPad that this #FsStream has created | |
548 | * @codec: The #FsCodec for this pad | |
549 | * | |
550 | * Emits the #FsStream::src-pad-added" signal, it should only be | |
551 | * called by subclasses. | |
552 | */ | |
553 | ||
554 | void | |
555 | fs_stream_emit_src_pad_added (FsStream *stream, | |
556 | GstPad *pad, | |
557 | FsCodec *codec) | |
558 | { | |
559 | FS_STREAM_LOCK (stream); | |
560 | g_assert (!g_list_find (stream->priv->src_pads, pad)); | |
561 | stream->priv->src_pads = g_list_append (stream->priv->src_pads, pad); | |
562 | stream->priv->src_pads_cookie++; | |
563 | g_signal_connect_object (pad, "parent-unset", | |
564 | G_CALLBACK (src_pad_parent_unset), stream, 0); | |
565 | FS_STREAM_UNLOCK (stream); | |
566 | ||
567 | g_signal_emit (stream, signals[SRC_PAD_ADDED], 0, pad, codec); | |
568 | } | |
569 | ||
570 | static GstIteratorItem | |
571 | src_pad_iterator_item_func (GstIterator*iter, gpointer item) | |
572 | { | |
573 | gst_object_ref (item); | |
574 | ||
575 | return GST_ITERATOR_ITEM_PASS; | |
576 | } | |
577 | ||
578 | /** | |
579 | * fs_stream_iterate_src_pads: | |
580 | * @stream: a #FsStream | |
581 | * | |
582 | * Creates a #GstIterator that can be used to iterate the src pads of this | |
583 | * stream. These are the pads that were announced by #FsStream:src-pad-added | |
584 | * and are still valid. | |
585 | * | |
586 | * Returns: (transfer full): The #GstIterator | |
587 | */ | |
588 | ||
589 | GstIterator * | |
590 | fs_stream_iterate_src_pads (FsStream *stream) | |
591 | { | |
592 | return gst_iterator_new_list (GST_TYPE_PAD, stream->priv->mutex, | |
593 | &stream->priv->src_pads_cookie, &stream->priv->src_pads, | |
594 | g_object_ref (stream), src_pad_iterator_item_func, g_object_unref); | |
595 | } | |
596 | ||
597 | ||
598 | /** | |
599 | * fs_stream_set_transmitter: | |
600 | * @stream: a #FsStream | |
601 | * @transmitter: Name of the type of transmitter to use for this stream | |
602 | * @stream_transmitter_n_parameters: Number of parametrs passed to the stream | |
603 | * transmitter | |
604 | * @stream_transmitter_parameters: | |
605 | * (array length=stream_transmitter_n_parameters) (allow-none): | |
606 | * an array of n_parameters #GParameter struct that will be passed | |
607 | * to the newly-create #FsStreamTransmitter | |
608 | * @error: location of a #GError, or %NULL if no error occured | |
609 | * | |
610 | * Set the transmitter to use for this stream. This function will only succeed | |
611 | * once. | |
612 | * | |
613 | * Returns: %TRUE if the transmitter could be set, %FALSE otherwise | |
614 | */ | |
615 | ||
616 | gboolean | |
617 | fs_stream_set_transmitter (FsStream *stream, | |
618 | const gchar *transmitter, | |
619 | GParameter *stream_transmitter_parameters, | |
620 | guint stream_transmitter_n_parameters, | |
621 | GError **error) | |
622 | { | |
623 | FsStreamClass *klass; | |
624 | ||
625 | g_return_val_if_fail (stream, FALSE); | |
626 | g_return_val_if_fail (FS_IS_STREAM (stream), FALSE); | |
627 | klass = FS_STREAM_GET_CLASS (stream); | |
628 | ||
629 | if (klass->set_transmitter) | |
630 | return klass->set_transmitter (stream, transmitter, | |
631 | stream_transmitter_parameters, stream_transmitter_n_parameters, error); | |
632 | ||
633 | ||
634 | g_set_error (error, FS_ERROR, FS_ERROR_NOT_IMPLEMENTED, | |
635 | "set_transmitter not defined in class"); | |
636 | ||
637 | return FALSE; | |
638 | } | |
639 | ||
640 | /** | |
641 | * fs_stream_destroy: | |
642 | * @stream: a #FsStream | |
643 | * | |
644 | * This will cause the stream to remove all links to other objects and to | |
645 | * remove itself from the #FsSession. Once a #FsStream has been destroyed, it | |
646 | * can not be used anymore. | |
647 | * | |
648 | * It is strongly recommended to call this function from the main thread because | |
649 | * releasing the application's reference to a stream. | |
650 | */ | |
651 | ||
652 | void | |
653 | fs_stream_destroy (FsStream *stream) | |
654 | { | |
655 | g_return_if_fail (stream); | |
656 | g_return_if_fail (FS_IS_STREAM (stream)); | |
657 | ||
658 | g_object_run_dispose (G_OBJECT (stream)); | |
659 | } |
0 | /* | |
1 | * Farstream - Farstream Stream | |
2 | * | |
3 | * Copyright 2007 Collabora Ltd. | |
4 | * @author: Philippe Kalaf <philippe.kalaf@collabora.co.uk> | |
5 | * Copyright 2007 Nokia Corp. | |
6 | * | |
7 | * fs-stream.h - A Farstream Stream (base implementation) | |
8 | * | |
9 | * This library is free software; you can redistribute it and/or | |
10 | * modify it under the terms of the GNU Lesser General Public | |
11 | * License as published by the Free Software Foundation; either | |
12 | * version 2.1 of the License, or (at your option) any later version. | |
13 | * | |
14 | * This library is distributed in the hope that it will be useful, | |
15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
17 | * Lesser General Public License for more details. | |
18 | * | |
19 | * You should have received a copy of the GNU Lesser General Public | |
20 | * License along with this library; if not, write to the Free Software | |
21 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA | |
22 | */ | |
23 | ||
24 | #ifndef __FS_STREAM_H__ | |
25 | #define __FS_STREAM_H__ | |
26 | ||
27 | #include <glib.h> | |
28 | #include <glib-object.h> | |
29 | ||
30 | #include <gst/farstream/fs-candidate.h> | |
31 | #include <gst/farstream/fs-codec.h> | |
32 | ||
33 | G_BEGIN_DECLS | |
34 | ||
35 | /** | |
36 | * FsStreamDirection: | |
37 | * @FS_DIRECTION_NONE: No direction specified | |
38 | * @FS_DIRECTION_SEND: Send only | |
39 | * @FS_DIRECTION_RECV: Receive only | |
40 | * @FS_DIRECTION_BOTH: Send and receive | |
41 | * | |
42 | * An enum for specifying the direction of a stream | |
43 | * | |
44 | */ | |
45 | typedef enum _FsStreamDirection | |
46 | { | |
47 | FS_DIRECTION_NONE = 0, | |
48 | FS_DIRECTION_SEND = 1<<0, | |
49 | FS_DIRECTION_RECV = 1<<1, | |
50 | FS_DIRECTION_BOTH = FS_DIRECTION_SEND | FS_DIRECTION_RECV | |
51 | } FsStreamDirection; | |
52 | ||
53 | /** | |
54 | * FsStreamState: | |
55 | * @FS_STREAM_STATE_FAILED: connectivity checks have been completed, | |
56 | * but connectivity was not established | |
57 | * @FS_STREAM_STATE_DISCONNECTED: no activity scheduled | |
58 | * @FS_STREAM_STATE_GATHERING: gathering local candidates | |
59 | * @FS_STREAM_STATE_CONNECTING: establishing connectivity | |
60 | * @FS_STREAM_STATE_CONNECTED: at least one working candidate pair | |
61 | * @FS_STREAM_STATE_READY: ICE concluded, candidate pair selection is now final | |
62 | * | |
63 | * These are the possible states of a stream, a simple multicast stream | |
64 | * could only be in "disconnected" or "ready" state. | |
65 | * An stream using an ICE transmitter would use all of these. | |
66 | */ | |
67 | ||
68 | typedef enum _FsStreamState | |
69 | { | |
70 | FS_STREAM_STATE_FAILED, | |
71 | FS_STREAM_STATE_DISCONNECTED, | |
72 | FS_STREAM_STATE_GATHERING, | |
73 | FS_STREAM_STATE_CONNECTING, | |
74 | FS_STREAM_STATE_CONNECTED, | |
75 | FS_STREAM_STATE_READY | |
76 | } FsStreamState; | |
77 | ||
78 | /* TYPE MACROS */ | |
79 | #define FS_TYPE_STREAM \ | |
80 | (fs_stream_get_type ()) | |
81 | #define FS_STREAM(obj) \ | |
82 | (G_TYPE_CHECK_INSTANCE_CAST((obj), FS_TYPE_STREAM, FsStream)) | |
83 | #define FS_STREAM_CLASS(klass) \ | |
84 | (G_TYPE_CHECK_CLASS_CAST((klass), FS_TYPE_STREAM, FsStreamClass)) | |
85 | #define FS_IS_STREAM(obj) \ | |
86 | (G_TYPE_CHECK_INSTANCE_TYPE((obj), FS_TYPE_STREAM)) | |
87 | #define FS_IS_STREAM_CLASS(klass) \ | |
88 | (G_TYPE_CHECK_CLASS_TYPE((klass), FS_TYPE_STREAM)) | |
89 | #define FS_STREAM_GET_CLASS(obj) \ | |
90 | (G_TYPE_INSTANCE_GET_CLASS ((obj), FS_TYPE_STREAM, FsStreamClass)) | |
91 | #define FS_STREAM_CAST(obj) ((FsStream *) (obj)) | |
92 | ||
93 | typedef struct _FsStream FsStream; | |
94 | typedef struct _FsStreamClass FsStreamClass; | |
95 | typedef struct _FsStreamPrivate FsStreamPrivate; | |
96 | ||
97 | ||
98 | /** | |
99 | * FsStreamClass: | |
100 | * @parent_class: Our parent | |
101 | * @add_remote_candidates: Set sthe remote candidates | |
102 | * @force_remote_candidates: Forces certain remote candidates | |
103 | * @set_remote_codecs: Sets the list of remote codecs | |
104 | * @add_id: Add a known id to be associated with this stream | |
105 | * @set_transmitter: Set the transmitter to use for this stream | |
106 | * | |
107 | * You must override add_remote_candidate in a subclass. | |
108 | * If you have to negotiate codecs, then you must override set_remote_codecs too | |
109 | */ | |
110 | ||
111 | struct _FsStreamClass | |
112 | { | |
113 | GstObjectClass parent_class; | |
114 | ||
115 | /*virtual functions */ | |
116 | gboolean (*add_remote_candidates) (FsStream *stream, | |
117 | GList *candidates, | |
118 | GError **error); | |
119 | ||
120 | gboolean (*force_remote_candidates) (FsStream *stream, | |
121 | GList *remote_candidates, | |
122 | GError **error); | |
123 | ||
124 | gboolean (*set_remote_codecs) (FsStream *stream, | |
125 | GList *remote_codecs, GError **error); | |
126 | ||
127 | void (*add_id) (FsStream *stream, | |
128 | guint id); | |
129 | ||
130 | gboolean (*set_transmitter) (FsStream *stream, | |
131 | const gchar *transmitter, | |
132 | GParameter *stream_transmitter_parameters, | |
133 | guint stream_transmitter_n_parameters, | |
134 | GError **error); | |
135 | ||
136 | /*< private >*/ | |
137 | gpointer _padding[8]; | |
138 | }; | |
139 | ||
140 | /** | |
141 | * FsStream: | |
142 | * | |
143 | * All members are private, access them using methods and properties | |
144 | */ | |
145 | struct _FsStream | |
146 | { | |
147 | GstObject parent; | |
148 | ||
149 | /*< private >*/ | |
150 | ||
151 | FsStreamPrivate *priv; | |
152 | ||
153 | gpointer _padding[8]; | |
154 | }; | |
155 | ||
156 | GType fs_stream_get_type (void); | |
157 | ||
158 | gboolean fs_stream_add_remote_candidates (FsStream *stream, | |
159 | GList *candidates, | |
160 | GError **error); | |
161 | ||
162 | gboolean fs_stream_force_remote_candidates (FsStream *stream, | |
163 | GList *remote_candidates, | |
164 | GError **error); | |
165 | ||
166 | gboolean fs_stream_set_remote_codecs (FsStream *stream, | |
167 | GList *remote_codecs, GError **error); | |
168 | ||
169 | void fs_stream_add_id (FsStream *stream, guint id); | |
170 | ||
171 | void fs_stream_emit_error (FsStream *stream, | |
172 | gint error_no, | |
173 | const gchar *error_msg); | |
174 | ||
175 | void fs_stream_emit_src_pad_added (FsStream *stream, | |
176 | GstPad *pad, | |
177 | FsCodec *codec); | |
178 | ||
179 | GstIterator *fs_stream_iterate_src_pads (FsStream *stream); | |
180 | ||
181 | gboolean fs_stream_set_transmitter (FsStream *stream, | |
182 | const gchar *transmitter, | |
183 | GParameter *stream_transmitter_parameters, | |
184 | guint stream_transmitter_n_parameters, | |
185 | GError **error); | |
186 | ||
187 | void fs_stream_destroy (FsStream *stream); | |
188 | ||
189 | G_END_DECLS | |
190 | ||
191 | #endif /* __FS_STREAM_H__ */ |
0 | /* | |
1 | * Farstream - Farstream Transmitter | |
2 | * | |
3 | * Copyright 2007 Collabora Ltd. | |
4 | * @author: Olivier Crete <olivier.crete@collabora.co.uk> | |
5 | * Copyright 2007 Nokia Corp. | |
6 | * | |
7 | * fs-transmitter.c - A Farstream Transmitter gobject (base implementation) | |
8 | * | |
9 | * This library is free software; you can redistribute it and/or | |
10 | * modify it under the terms of the GNU Lesser General Public | |
11 | * License as published by the Free Software Foundation; either | |
12 | * version 2.1 of the License, or (at your option) any later version. | |
13 | * | |
14 | * This library is distributed in the hope that it will be useful, | |
15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
17 | * Lesser General Public License for more details. | |
18 | * | |
19 | * You should have received a copy of the GNU Lesser General Public | |
20 | * License along with this library; if not, write to the Free Software | |
21 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA | |
22 | */ | |
23 | ||
24 | /** | |
25 | * SECTION:fs-transmitter | |
26 | * @short_description: A transmitter object linked to a session | |
27 | * | |
28 | * This object is the base implementation of a Farstream Transmitter. | |
29 | * It needs to be derived and implement by a Farstream transmitter. A | |
30 | * Farstream Transmitter provides a GStreamer network sink and source to be used | |
31 | * for the Farstream Session. It creates #FsStreamTransmitter objects which are | |
32 | * used to set the different per-stream properties | |
33 | * | |
34 | */ | |
35 | ||
36 | #ifdef HAVE_CONFIG_H | |
37 | #include "config.h" | |
38 | #endif | |
39 | ||
40 | #include "fs-transmitter.h" | |
41 | ||
42 | #include <gst/gst.h> | |
43 | ||
44 | #include "fs-marshal.h" | |
45 | #include "fs-plugin.h" | |
46 | #include "fs-conference.h" | |
47 | #include "fs-private.h" | |
48 | ||
49 | /* Signals */ | |
50 | enum | |
51 | { | |
52 | ERROR_SIGNAL, | |
53 | GET_RECVONLY_FILTER_SIGNAL, | |
54 | LAST_SIGNAL | |
55 | }; | |
56 | ||
57 | /* props */ | |
58 | enum | |
59 | { | |
60 | PROP_0, | |
61 | PROP_GST_SINK, | |
62 | PROP_GST_SRC, | |
63 | PROP_COMPONENTS, | |
64 | PROP_TYPE_OF_SERVICE | |
65 | }; | |
66 | ||
67 | /* | |
68 | struct _FsTransmitterPrivate | |
69 | { | |
70 | }; | |
71 | */ | |
72 | ||
73 | G_DEFINE_ABSTRACT_TYPE(FsTransmitter, fs_transmitter, GST_TYPE_OBJECT); | |
74 | ||
75 | #define FS_TRANSMITTER_GET_PRIVATE(o) \ | |
76 | (G_TYPE_INSTANCE_GET_PRIVATE ((o), FS_TYPE_TRANSMITTER, FsTransmitterPrivate)) | |
77 | ||
78 | static void fs_transmitter_get_property (GObject *object, | |
79 | guint prop_id, | |
80 | GValue *value, | |
81 | GParamSpec *pspec); | |
82 | static void fs_transmitter_set_property (GObject *object, | |
83 | guint prop_id, | |
84 | const GValue *value, | |
85 | GParamSpec *pspec); | |
86 | ||
87 | static guint signals[LAST_SIGNAL] = { 0 }; | |
88 | ||
89 | ||
90 | static void | |
91 | fs_transmitter_class_init (FsTransmitterClass *klass) | |
92 | { | |
93 | GObjectClass *gobject_class; | |
94 | ||
95 | _fs_conference_init_debug (); | |
96 | ||
97 | gobject_class = (GObjectClass *) klass; | |
98 | ||
99 | gobject_class->set_property = fs_transmitter_set_property; | |
100 | gobject_class->get_property = fs_transmitter_get_property; | |
101 | ||
102 | ||
103 | ||
104 | /** | |
105 | * FsTransmitter:gst-src: | |
106 | * | |
107 | * A network source #GstElement to be used by the #FsSession | |
108 | * This element MUST provide a source pad named "src%d" per component. | |
109 | * These pads number must start at 1 (the %d corresponds to the component | |
110 | * number). | |
111 | * These pads MUST be static pads. | |
112 | * | |
113 | */ | |
114 | g_object_class_install_property (gobject_class, | |
115 | PROP_GST_SRC, | |
116 | g_param_spec_object ("gst-src", | |
117 | "The network source", | |
118 | "A source GstElement to be used by a FsSession", | |
119 | GST_TYPE_ELEMENT, | |
120 | G_PARAM_READABLE | G_PARAM_STATIC_STRINGS)); | |
121 | ||
122 | /** | |
123 | * FsTransmitter:gst-sink: | |
124 | * | |
125 | * A network source #GstElement to be used by the #FsSession | |
126 | * These element's sink must have async=FALSE | |
127 | * This element MUST provide a pad named "sink\%d" per component. | |
128 | * These pads number must start at 1 (the \%d corresponds to the component | |
129 | * number). | |
130 | * These pads MUST be static pads. | |
131 | * | |
132 | */ | |
133 | g_object_class_install_property (gobject_class, | |
134 | PROP_GST_SINK, | |
135 | g_param_spec_object ("gst-sink", | |
136 | "The network source", | |
137 | "A source GstElement to be used by a FsSession", | |
138 | GST_TYPE_ELEMENT, | |
139 | G_PARAM_READABLE | G_PARAM_STATIC_STRINGS)); | |
140 | ||
141 | /** | |
142 | * FsTransmitter:components: | |
143 | * | |
144 | * The number of components to create | |
145 | */ | |
146 | g_object_class_install_property (gobject_class, | |
147 | PROP_COMPONENTS, | |
148 | g_param_spec_uint ("components", | |
149 | "Number of componnets", | |
150 | "The number of components to create", | |
151 | 1, 255, 1, | |
152 | G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); | |
153 | ||
154 | /** | |
155 | * FsTransmitter:tos: | |
156 | * | |
157 | * Sets the IP ToS field (and if possible the IPv6 TCLASS field | |
158 | */ | |
159 | g_object_class_install_property (gobject_class, | |
160 | PROP_TYPE_OF_SERVICE, | |
161 | g_param_spec_uint ("tos", | |
162 | "IP Type of Service", | |
163 | "The IP Type of Service to set on sent packets", | |
164 | 0, 255, 0, | |
165 | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); | |
166 | ||
167 | /** | |
168 | * FsTransmitter::error: | |
169 | * @self: #FsTransmitter that emitted the signal | |
170 | * @errorno: The number of the error | |
171 | * @error_msg: Error message to be displayed to user | |
172 | * | |
173 | * This signal is emitted in any error condition | |
174 | * | |
175 | */ | |
176 | signals[ERROR_SIGNAL] = g_signal_new ("error", | |
177 | G_TYPE_FROM_CLASS (klass), | |
178 | G_SIGNAL_RUN_LAST, | |
179 | 0, | |
180 | NULL, | |
181 | NULL, | |
182 | _fs_marshal_VOID__ENUM_STRING, | |
183 | G_TYPE_NONE, 2, FS_TYPE_ERROR, G_TYPE_STRING); | |
184 | ||
185 | /** | |
186 | * FsTransmitter::get-recvonly-filter | |
187 | * @self: #FsTransmitter that emitted the signal | |
188 | * @component: The component that the filter will be used for | |
189 | * | |
190 | * This signal is emitted when the transmitter wants to get a filter for | |
191 | * to use if sending is disabled. If you want to drop all buffers, just | |
192 | * don't listen to the signal. | |
193 | * | |
194 | * This element should have a "sending" property that can be changed with the | |
195 | * sending state of the stream. It should default to %TRUE. | |
196 | * | |
197 | * Returns: (transfer full) (allow-none): the #GstElement to use as the | |
198 | * filter, or %NULL to drop everything | |
199 | */ | |
200 | ||
201 | signals[GET_RECVONLY_FILTER_SIGNAL] = g_signal_new ("get-recvonly-filter", | |
202 | G_TYPE_FROM_CLASS (klass), | |
203 | G_SIGNAL_RUN_LAST, | |
204 | 0, | |
205 | NULL, | |
206 | NULL, | |
207 | _fs_marshal_OBJECT__UINT, | |
208 | GST_TYPE_ELEMENT, 1, G_TYPE_UINT); | |
209 | ||
210 | ||
211 | //g_type_class_add_private (klass, sizeof (FsTransmitterPrivate)); | |
212 | } | |
213 | ||
214 | static void | |
215 | fs_transmitter_init (FsTransmitter *self) | |
216 | { | |
217 | // self->priv = FS_TRANSMITTER_GET_PRIVATE (self); | |
218 | } | |
219 | ||
220 | static void | |
221 | fs_transmitter_get_property (GObject *object, | |
222 | guint prop_id, | |
223 | GValue *value, | |
224 | GParamSpec *pspec) | |
225 | { | |
226 | GST_WARNING ("Subclass %s of FsTransmitter does not override the %s property" | |
227 | " getter", | |
228 | G_OBJECT_TYPE_NAME(object), | |
229 | g_param_spec_get_name (pspec)); | |
230 | } | |
231 | ||
232 | static void | |
233 | fs_transmitter_set_property (GObject *object, | |
234 | guint prop_id, | |
235 | const GValue *value, | |
236 | GParamSpec *pspec) | |
237 | { | |
238 | GST_WARNING ("Subclass %s of FsTransmitter does not override the %s property" | |
239 | " setter", | |
240 | G_OBJECT_TYPE_NAME(object), | |
241 | g_param_spec_get_name (pspec)); | |
242 | } | |
243 | ||
244 | ||
245 | /** | |
246 | * fs_transmitter_new_stream_transmitter: | |
247 | * @transmitter: a #FsTranmitter | |
248 | * @participant: the #FsParticipant for which the #FsStream using this | |
249 | * new #FsStreamTransmitter is created | |
250 | * @n_parameters: The number of parameters to pass to the newly created | |
251 | * #FsStreamTransmitter | |
252 | * @parameters: an array of #GParameter | |
253 | * @error: location of a #GError, or NULL if no error occured | |
254 | * | |
255 | * This function will create a new #FsStreamTransmitter element for a | |
256 | * specific participant for this #FsTransmitter | |
257 | * | |
258 | * Returns: (transfer full): a new #FsStreamTransmitter, or NULL if there is an | |
259 | * error | |
260 | */ | |
261 | ||
262 | FsStreamTransmitter * | |
263 | fs_transmitter_new_stream_transmitter (FsTransmitter *transmitter, | |
264 | FsParticipant *participant, | |
265 | guint n_parameters, | |
266 | GParameter *parameters, | |
267 | GError **error) | |
268 | { | |
269 | FsTransmitterClass *klass; | |
270 | ||
271 | g_return_val_if_fail (transmitter, NULL); | |
272 | g_return_val_if_fail (FS_IS_TRANSMITTER (transmitter), NULL); | |
273 | klass = FS_TRANSMITTER_GET_CLASS (transmitter); | |
274 | g_return_val_if_fail (klass->new_stream_transmitter, NULL); | |
275 | ||
276 | ||
277 | return klass->new_stream_transmitter (transmitter, participant, | |
278 | n_parameters, parameters, error); | |
279 | ||
280 | return NULL; | |
281 | } | |
282 | ||
283 | /** | |
284 | * fs_transmitter_new: | |
285 | * @type: The type of transmitter to create | |
286 | * @components: The number of components to create | |
287 | * @tos: The Type of Service of the socket, max is 255 | |
288 | * @error: location of a #GError, or NULL if no error occured | |
289 | * | |
290 | * This function creates a new transmitter of the requested type. | |
291 | * It will load the appropriate plugin as required. | |
292 | * | |
293 | * Returns: a newly-created #FsTransmitter of the requested type | |
294 | * (or NULL if there is an error) | |
295 | */ | |
296 | ||
297 | FsTransmitter * | |
298 | fs_transmitter_new (const gchar *type, | |
299 | guint components, | |
300 | guint tos, | |
301 | GError **error) | |
302 | { | |
303 | FsTransmitter *self = NULL; | |
304 | ||
305 | g_return_val_if_fail (type != NULL, NULL); | |
306 | g_return_val_if_fail (tos <= 255, NULL); | |
307 | ||
308 | self = FS_TRANSMITTER (fs_plugin_create (type, "transmitter", error, | |
309 | "components", components, | |
310 | "tos", tos, | |
311 | NULL)); | |
312 | ||
313 | if (!self) | |
314 | return NULL; | |
315 | ||
316 | if (self->construction_error) { | |
317 | g_propagate_error(error, self->construction_error); | |
318 | g_object_unref (self); | |
319 | self = NULL; | |
320 | } | |
321 | ||
322 | return self; | |
323 | } | |
324 | ||
325 | /** | |
326 | * fs_transmitter_get_stream_transmitter_type: | |
327 | * @transmitter: A #FsTransmitter object | |
328 | * | |
329 | * This function returns the GObject type for the stream transmitter. | |
330 | * This is meant for bindings that need to introspect the type of arguments | |
331 | * that can be passed to the _new_stream_transmitter. | |
332 | * | |
333 | * Returns: the #GType | |
334 | */ | |
335 | ||
336 | GType | |
337 | fs_transmitter_get_stream_transmitter_type (FsTransmitter *transmitter) | |
338 | { | |
339 | FsTransmitterClass *klass; | |
340 | ||
341 | g_return_val_if_fail (transmitter, 0); | |
342 | g_return_val_if_fail (FS_IS_TRANSMITTER (transmitter), 0); | |
343 | klass = FS_TRANSMITTER_GET_CLASS (transmitter); | |
344 | g_return_val_if_fail (klass->get_stream_transmitter_type, 0); | |
345 | ||
346 | return klass->get_stream_transmitter_type (transmitter); | |
347 | } | |
348 | ||
349 | ||
350 | /** | |
351 | * fs_transmitter_emit_error: | |
352 | * @transmitter: #FsTransmitter on which to emit the error signal | |
353 | * @error_no: The number of the error | |
354 | * @error_msg: Error message to be displayed to user | |
355 | * | |
356 | * This function emit the "error" signal on a #FsTransmitter, it should | |
357 | * only be called by subclasses. | |
358 | */ | |
359 | void | |
360 | fs_transmitter_emit_error (FsTransmitter *transmitter, | |
361 | gint error_no, | |
362 | const gchar *error_msg) | |
363 | { | |
364 | g_signal_emit (transmitter, signals[ERROR_SIGNAL], 0, error_no, | |
365 | error_msg); | |
366 | } | |
367 | ||
368 | /** | |
369 | * fs_transmitter_list_available: | |
370 | * | |
371 | * Get the list of all available transmitters | |
372 | * | |
373 | * Returns: (transfer full): a newly allocated array of strings containing the | |
374 | * list of all available transmitters or %NULL if there are none. It should | |
375 | * be freed with g_strfreev(). | |
376 | */ | |
377 | ||
378 | char ** | |
379 | fs_transmitter_list_available (void) | |
380 | { | |
381 | return fs_plugin_list_available ("transmitter"); | |
382 | } | |
383 | ||
384 | /** | |
385 | * fs_transmitter_get_recvonly_filter: | |
386 | * @transmitter: A #FsTransmitter object | |
387 | * @component: The component to get the filter for | |
388 | * | |
389 | * Get the filter to add on the send pipeline if sending is disabled. | |
390 | * | |
391 | * Only for use by subclasses. | |
392 | * | |
393 | * Returns: (transfer full) (allow-none): a #GstElement to use as the filter or | |
394 | * %NULL | |
395 | */ | |
396 | ||
397 | GstElement * | |
398 | fs_transmitter_get_recvonly_filter (FsTransmitter *transmitter, | |
399 | guint component) | |
400 | { | |
401 | GstElement *element = NULL; | |
402 | ||
403 | g_signal_emit (transmitter, signals[GET_RECVONLY_FILTER_SIGNAL], 0, component, | |
404 | &element); | |
405 | ||
406 | return element; | |
407 | } |
0 | /* | |
1 | * Farstream - Farstream Transmitter | |
2 | * | |
3 | * Copyright 2007 Collabora Ltd. | |
4 | * @author: Olivier Crete <olivier.crete@collabora.co.uk> | |
5 | * Copyright 2007 Nokia Corp. | |
6 | * | |
7 | * fs-transmitter.h - A Farstream Transmitter (base implementation) | |
8 | * | |
9 | * This library is free software; you can redistribute it and/or | |
10 | * modify it under the terms of the GNU Lesser General Public | |
11 | * License as published by the Free Software Foundation; either | |
12 | * version 2.1 of the License, or (at your option) any later version. | |
13 | * | |
14 | * This library is distributed in the hope that it will be useful, | |
15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
17 | * Lesser General Public License for more details. | |
18 | * | |
19 | * You should have received a copy of the GNU Lesser General Public | |
20 | * License along with this library; if not, write to the Free Software | |
21 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA | |
22 | */ | |
23 | ||
24 | #ifndef __FS_TRANSMITTER_H__ | |
25 | #define __FS_TRANSMITTER_H__ | |
26 | ||
27 | #include <gst/gst.h> | |
28 | ||
29 | #include <gst/farstream/fs-participant.h> | |
30 | #include <gst/farstream/fs-session.h> | |
31 | #include <gst/farstream/fs-stream-transmitter.h> | |
32 | ||
33 | G_BEGIN_DECLS | |
34 | ||
35 | /* TYPE MACROS */ | |
36 | #define FS_TYPE_TRANSMITTER \ | |
37 | (fs_transmitter_get_type ()) | |
38 | #define FS_TRANSMITTER(obj) \ | |
39 | (G_TYPE_CHECK_INSTANCE_CAST((obj), FS_TYPE_TRANSMITTER, FsTransmitter)) | |
40 | #define FS_TRANSMITTER_CLASS(klass) \ | |
41 | (G_TYPE_CHECK_CLASS_CAST((klass), FS_TYPE_TRANSMITTER, FsTransmitterClass)) | |
42 | #define FS_IS_TRANSMITTER(obj) \ | |
43 | (G_TYPE_CHECK_INSTANCE_TYPE((obj), FS_TYPE_TRANSMITTER)) | |
44 | #define FS_IS_TRANSMITTER_CLASS(klass) \ | |
45 | (G_TYPE_CHECK_CLASS_TYPE((klass), FS_TYPE_TRANSMITTER)) | |
46 | #define FS_TRANSMITTER_GET_CLASS(obj) \ | |
47 | (G_TYPE_INSTANCE_GET_CLASS ((obj), FS_TYPE_TRANSMITTER, FsTransmitterClass)) | |
48 | #define FS_TRANSMITTER_CAST(obj) ((FsTransmitter *) (obj)) | |
49 | ||
50 | typedef struct _FsTransmitter FsTransmitter; | |
51 | typedef struct _FsTransmitterClass FsTransmitterClass; | |
52 | typedef struct _FsTransmitterPrivate FsTransmitterPrivate; | |
53 | ||
54 | /** | |
55 | * FsTransmitterClass: | |
56 | * @parent_class: Our parent | |
57 | * @new_stream_transmitter: Creates a new #FsStreamTransmitter | |
58 | * @get_stream_transmitter_type: Returns the #GType of the stream transmitter | |
59 | * created by this class (useful for bindings) | |
60 | * | |
61 | * You must override both methods in a subclass. | |
62 | */ | |
63 | ||
64 | struct _FsTransmitterClass | |
65 | { | |
66 | GstObjectClass parent_class; | |
67 | ||
68 | /*virtual functions */ | |
69 | FsStreamTransmitter *(*new_stream_transmitter) (FsTransmitter *transmitter, | |
70 | FsParticipant *participant, | |
71 | guint n_parameters, | |
72 | GParameter *parameters, | |
73 | GError **error); | |
74 | GType (*get_stream_transmitter_type) (FsTransmitter *transmitter); | |
75 | ||
76 | /*< private >*/ | |
77 | gpointer _padding[8]; | |
78 | }; | |
79 | ||
80 | /** | |
81 | * FsTransmitter: | |
82 | * | |
83 | * All members are private, access them using methods and properties | |
84 | */ | |
85 | struct _FsTransmitter | |
86 | { | |
87 | GstObject parent; | |
88 | ||
89 | /*< private >*/ | |
90 | FsTransmitterPrivate *priv; | |
91 | ||
92 | /* This parameter should only be set by the construction methods | |
93 | * of the subclasses | |
94 | */ | |
95 | GError *construction_error; | |
96 | ||
97 | gpointer _padding[8]; | |
98 | }; | |
99 | ||
100 | GType fs_transmitter_get_type (void); | |
101 | ||
102 | FsStreamTransmitter *fs_transmitter_new_stream_transmitter ( | |
103 | FsTransmitter *transmitter, FsParticipant *participant, | |
104 | guint n_parameters, GParameter *parameters, GError **error); | |
105 | ||
106 | FsTransmitter *fs_transmitter_new (const gchar *type, | |
107 | guint components, | |
108 | guint tos, | |
109 | GError **error); | |
110 | ||
111 | GType fs_transmitter_get_stream_transmitter_type (FsTransmitter *transmitter); | |
112 | ||
113 | void fs_transmitter_emit_error (FsTransmitter *transmitter, | |
114 | gint error_no, | |
115 | const gchar *error_msg); | |
116 | ||
117 | char **fs_transmitter_list_available (void); | |
118 | ||
119 | GstElement * | |
120 | fs_transmitter_get_recvonly_filter (FsTransmitter *transmitter, | |
121 | guint component); | |
122 | ||
123 | G_END_DECLS | |
124 | ||
125 | #endif /* __FS_TRANSMITTER_H__ */ |
0 | /* | |
1 | * Farstream - Miscellaneous useful functions | |
2 | * | |
3 | * Copyright 2011 Collabora Ltd. | |
4 | * @author: Olivier Crete <olivier.crete@collabora.co.uk> | |
5 | * Copyright 2011 Nokia Corp. | |
6 | * | |
7 | * This library is free software; you can redistribute it and/or | |
8 | * modify it under the terms of the GNU Lesser General Public | |
9 | * License as published by the Free Software Foundation; either | |
10 | * version 2.1 of the License, or (at your option) any later version. | |
11 | * | |
12 | * This library is distributed in the hope that it will be useful, | |
13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
15 | * Lesser General Public License for more details. | |
16 | * | |
17 | * You should have received a copy of the GNU Lesser General Public | |
18 | * License along with this library; if not, write to the Free Software | |
19 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA | |
20 | */ | |
21 | ||
22 | #ifdef HAVE_CONFIG_H | |
23 | # include <config.h> | |
24 | #endif | |
25 | ||
26 | #include "fs-utils.h" | |
27 | ||
28 | #include <string.h> | |
29 | ||
30 | #include "fs-rtp.h" | |
31 | ||
32 | /** | |
33 | * SECTION:fs-utils | |
34 | * @short_description: Miscellaneous useful functions | |
35 | */ | |
36 | ||
37 | static GList * | |
38 | load_default_codec_preferences_from_path (const gchar *element_name, | |
39 | const gchar *path) | |
40 | { | |
41 | GList *codec_prefs = NULL; | |
42 | gchar *filename; | |
43 | ||
44 | filename = g_build_filename (path, PACKAGE, FS_MAJORMINOR, element_name, | |
45 | "default-codec-preferences", NULL); | |
46 | codec_prefs = fs_codec_list_from_keyfile (filename, NULL); | |
47 | g_free (filename); | |
48 | ||
49 | return codec_prefs; | |
50 | } | |
51 | ||
52 | static const gchar * | |
53 | factory_name_from_element (GstElement *element) | |
54 | { | |
55 | GstElementFactory *factory = gst_element_get_factory (element); | |
56 | ||
57 | if (factory) | |
58 | return gst_plugin_feature_get_name (GST_PLUGIN_FEATURE (factory)); | |
59 | else | |
60 | return NULL; | |
61 | } | |
62 | ||
63 | /** | |
64 | * fs_utils_get_default_codec_preferences: | |
65 | * @element: Element for which to fetch default codec preferences | |
66 | * | |
67 | * These default codec preferences should work with the elements that are | |
68 | * available in the main GStreamer element repositories. | |
69 | * They should be suitable for standards based protocols like SIP or XMPP. | |
70 | * | |
71 | * Returns: (element-type FsCodec) (transfer full): | |
72 | * The default codec preferences for this plugin. | |
73 | * This #GList should be freed with fs_codec_list_destroy() | |
74 | */ | |
75 | GList * | |
76 | fs_utils_get_default_codec_preferences (GstElement *element) | |
77 | { | |
78 | const gchar * const * system_data_dirs = g_get_system_data_dirs (); | |
79 | GList *codec_prefs = NULL; | |
80 | guint i; | |
81 | const gchar *factory_name = factory_name_from_element (element); | |
82 | ||
83 | if (!factory_name) | |
84 | return NULL; | |
85 | ||
86 | codec_prefs = load_default_codec_preferences_from_path (factory_name, | |
87 | g_get_user_data_dir ()); | |
88 | if (codec_prefs) | |
89 | return codec_prefs; | |
90 | ||
91 | for (i = 0; system_data_dirs[i]; i++) | |
92 | { | |
93 | codec_prefs = load_default_codec_preferences_from_path (factory_name, | |
94 | system_data_dirs[i]); | |
95 | if (codec_prefs) | |
96 | return codec_prefs; | |
97 | } | |
98 | ||
99 | return NULL; | |
100 | } | |
101 | ||
102 | /** | |
103 | * fs_utils_get_default_element_properties: (skip): | |
104 | * @element: Element for which to fetch default element properties | |
105 | * | |
106 | * This function produces a #GKeyFile that can be fed to | |
107 | * fs_element_added_notifier_set_properties_from_keyfile(). If no | |
108 | * default properties have been found, it will return %NULL. | |
109 | * | |
110 | * Returns: a #GKeyFile containing the default element | |
111 | * properties for this element or %NULL if no properties were found. | |
112 | * Caller must free the #GKeyFile when he is done. | |
113 | */ | |
114 | ||
115 | GKeyFile * | |
116 | fs_utils_get_default_element_properties (GstElement *element) | |
117 | { | |
118 | gboolean file_loaded; | |
119 | GKeyFile *keyfile = g_key_file_new (); | |
120 | gchar *filename; | |
121 | const gchar *factory_name = factory_name_from_element (element); | |
122 | ||
123 | filename = g_build_filename (PACKAGE, FS_MAJORMINOR, factory_name, | |
124 | "default-element-properties", NULL); | |
125 | file_loaded = g_key_file_load_from_data_dirs (keyfile, filename, NULL, | |
126 | G_KEY_FILE_NONE, NULL); | |
127 | g_free (filename); | |
128 | ||
129 | if (file_loaded) | |
130 | { | |
131 | return keyfile; | |
132 | } | |
133 | else | |
134 | { | |
135 | g_key_file_free (keyfile); | |
136 | return NULL; | |
137 | } | |
138 | } | |
139 | ||
140 | /** | |
141 | * fs_utils_set_bitrate: | |
142 | * @element: The #GstElement | |
143 | * @bitrate: The bitrate in bits/sec | |
144 | * | |
145 | * This allows setting the bitrate on all elements that have a "bitrate" | |
146 | * property without having to know the type or of the unit used by that element. | |
147 | * | |
148 | * This will be obsolete in 0.11 (when all elements use bit/sec for the | |
149 | * "bitrate" property. | |
150 | */ | |
151 | ||
152 | void | |
153 | fs_utils_set_bitrate (GstElement *element, glong bitrate) | |
154 | { | |
155 | GParamSpec *spec; | |
156 | const char *elements_in_kbps[] = { "lamemp3enc", "lame", "x264enc", "twolame", | |
157 | "mpeg2enc", NULL | |
158 | }; | |
159 | int i; | |
160 | GstElementFactory *factory; | |
161 | const gchar *factory_name = NULL; | |
162 | ||
163 | g_return_if_fail (GST_IS_ELEMENT (element)); | |
164 | ||
165 | spec = g_object_class_find_property (G_OBJECT_GET_CLASS (element), "bitrate"); | |
166 | g_return_if_fail (spec != NULL); | |
167 | ||
168 | factory = gst_element_get_factory (element); | |
169 | if (factory) | |
170 | factory_name = gst_plugin_feature_get_name (GST_PLUGIN_FEATURE (factory)); | |
171 | ||
172 | /* divide by 1000 for elements that are known to use kbs */ | |
173 | for (i = 0; elements_in_kbps[i]; i++) | |
174 | if (factory_name && !strcmp (factory_name, elements_in_kbps[i])) | |
175 | { | |
176 | bitrate /= 1000; | |
177 | break; | |
178 | } | |
179 | ||
180 | if (G_PARAM_SPEC_TYPE (spec) == G_TYPE_LONG) | |
181 | { | |
182 | g_object_set (element, "bitrate", (glong) CLAMP (bitrate, | |
183 | G_PARAM_SPEC_LONG (spec)->minimum, | |
184 | G_PARAM_SPEC_LONG (spec)->maximum), NULL); | |
185 | } | |
186 | else if (G_PARAM_SPEC_VALUE_TYPE (spec) == G_TYPE_ULONG) | |
187 | { | |
188 | g_object_set (element, "bitrate", (gulong) CLAMP (bitrate, | |
189 | G_PARAM_SPEC_ULONG (spec)->minimum, | |
190 | G_PARAM_SPEC_ULONG (spec)->maximum), NULL); | |
191 | } | |
192 | else if (G_PARAM_SPEC_VALUE_TYPE (spec) == G_TYPE_INT) | |
193 | { | |
194 | gint tmp = MIN (bitrate, G_MAXINT); | |
195 | ||
196 | g_object_set (element, "bitrate", (gint) CLAMP (tmp, | |
197 | G_PARAM_SPEC_INT (spec)->minimum, | |
198 | G_PARAM_SPEC_INT (spec)->maximum), NULL); | |
199 | } | |
200 | else if (G_PARAM_SPEC_VALUE_TYPE (spec) == G_TYPE_UINT) | |
201 | { | |
202 | guint tmp = MIN (bitrate, G_MAXUINT); | |
203 | ||
204 | g_object_set (element, "bitrate", (guint) CLAMP (tmp, | |
205 | G_PARAM_SPEC_UINT (spec)->minimum, | |
206 | G_PARAM_SPEC_UINT (spec)->maximum), NULL); | |
207 | } | |
208 | else | |
209 | { | |
210 | g_warning ("bitrate parameter of unknown type"); | |
211 | } | |
212 | } | |
213 | ||
214 | static GList * | |
215 | load_default_rtp_hdrext_preferences_from_path (const gchar *element_name, | |
216 | const gchar *path, FsMediaType media_type) | |
217 | { | |
218 | GList *rtp_hdrext_prefs = NULL; | |
219 | gchar *filename; | |
220 | ||
221 | filename = g_build_filename (path, PACKAGE, FS_MAJORMINOR, element_name, | |
222 | "default-codec-preferences", NULL); | |
223 | rtp_hdrext_prefs = fs_rtp_header_extension_list_from_keyfile (filename, | |
224 | media_type, NULL); | |
225 | g_free (filename); | |
226 | ||
227 | return rtp_hdrext_prefs; | |
228 | } | |
229 | ||
230 | /** | |
231 | * fs_utils_get_default_rtp_header_extension_preferences | |
232 | * @element: Element for which to fetch default RTP Header Extension preferences | |
233 | * @media_type: The #FsMediaType for which to get default RTP Header Extension | |
234 | * preferences | |
235 | * | |
236 | * These default rtp header extension preferences should work with the elements | |
237 | * that are available in the main GStreamer element repositories. | |
238 | * They should be suitable for standards based protocols like SIP or XMPP. | |
239 | * | |
240 | * Returns: (element-type FsCodec) (transfer full): The default rtp | |
241 | * header extension preferences for this plugin, this #GList should be | |
242 | * freed with fs_codec_list_destroy() | |
243 | */ | |
244 | GList * | |
245 | fs_utils_get_default_rtp_header_extension_preferences (GstElement *element, | |
246 | FsMediaType media_type) | |
247 | { | |
248 | const gchar * const * system_data_dirs = g_get_system_data_dirs (); | |
249 | GList *rtp_hdrext_prefs = NULL; | |
250 | guint i; | |
251 | const gchar *factory_name = factory_name_from_element (element); | |
252 | ||
253 | if (!factory_name) | |
254 | return NULL; | |
255 | ||
256 | rtp_hdrext_prefs = load_default_rtp_hdrext_preferences_from_path ( | |
257 | factory_name, g_get_user_data_dir (), media_type); | |
258 | if (rtp_hdrext_prefs) | |
259 | return rtp_hdrext_prefs; | |
260 | ||
261 | for (i = 0; system_data_dirs[i]; i++) | |
262 | { | |
263 | rtp_hdrext_prefs = load_default_rtp_hdrext_preferences_from_path ( | |
264 | factory_name, system_data_dirs[i], media_type); | |
265 | if (rtp_hdrext_prefs) | |
266 | return rtp_hdrext_prefs; | |
267 | } | |
268 | ||
269 | return NULL; | |
270 | } |
0 | /* | |
1 | * Farstream - Miscellaneous useful functions | |
2 | * | |
3 | * Copyright 2011 Collabora Ltd. | |
4 | * @author: Olivier Crete <olivier.crete@collabora.co.uk> | |
5 | * Copyright 2011 Nokia Corp. | |
6 | * | |
7 | * This library is free software; you can redistribute it and/or | |
8 | * modify it under the terms of the GNU Lesser General Public | |
9 | * License as published by the Free Software Foundation; either | |
10 | * version 2.1 of the License, or (at your option) any later version. | |
11 | * | |
12 | * This library is distributed in the hope that it will be useful, | |
13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
15 | * Lesser General Public License for more details. | |
16 | * | |
17 | * You should have received a copy of the GNU Lesser General Public | |
18 | * License along with this library; if not, write to the Free Software | |
19 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA | |
20 | */ | |
21 | ||
22 | ||
23 | ||
24 | #ifndef __FS_UTILS_H__ | |
25 | #define __FS_UTILS_H__ | |
26 | ||
27 | #include <gst/gst.h> | |
28 | ||
29 | #include <gst/farstream/fs-codec.h> | |
30 | ||
31 | G_BEGIN_DECLS | |
32 | ||
33 | GList *fs_utils_get_default_codec_preferences (GstElement *element); | |
34 | ||
35 | GKeyFile *fs_utils_get_default_element_properties (GstElement *element); | |
36 | ||
37 | void fs_utils_set_bitrate (GstElement *element, glong bitrate); | |
38 | ||
39 | GList *fs_utils_get_default_rtp_header_extension_preferences ( | |
40 | GstElement *element, FsMediaType media_type); | |
41 | ||
42 | G_END_DECLS | |
43 | ||
44 | #endif /* __FS_UTILS_H__ */ |
23 | 23 | |
24 | 24 | farstream_la_LIBADD = \ |
25 | 25 | $(PYFARSTREAM_LIBS) \ |
26 | $(top_builddir)/gst-libs/gst/farstream/libfarstream-@GST_MAJORMINOR@.la | |
26 | $(top_builddir)/farstream/libfarstream-@GST_MAJORMINOR@.la | |
27 | 27 | |
28 | 28 | farstream_la_LDFLAGS = -module -avoid-version |
29 | 29 |
4 | 4 | |
5 | 5 | #include <gst/gst.h> |
6 | 6 | |
7 | #include <gst/farstream/fs-conference.h> | |
8 | ||
9 | #include <gst/farstream/fs-element-added-notifier.h> | |
7 | #include <farstream/fs-conference.h> | |
8 | ||
9 | #include <farstream/fs-element-added-notifier.h> | |
10 | 10 | |
11 | 11 | /* This is new in python 2.5 */ |
12 | 12 | #if PYTHON_API_VERSION < 1013 |
0 | 0 | #include <pygobject.h> |
1 | #include <gst/farstream/fs-codec.h> | |
1 | #include <farstream/fs-codec.h> | |
2 | 2 | |
3 | 3 | void fs_register_classes (PyObject *d); |
4 | 4 | void fs_add_constants(PyObject *module, const gchar *strip_prefix); |
10 | 10 | fs-element-added-notifier.h \ |
11 | 11 | fs-enumtypes.h" |
12 | 12 | |
13 | srcdir=../gst-libs/gst/farstream/ | |
13 | srcdir=../farstream/ | |
14 | 14 | |
15 | 15 | output=pyfarstream.defs |
16 | 16 | filter=pyfarstream-filter.defs |
12 | 12 | GST_PLUGIN_LOADING_WHITELIST=gstreamer:gst-plugins-base:gst-plugins-good:libnice:valve:siren:autoconvert:rtpmux:dtmf:mimic:shm:farstream@$(top_builddir)/gst \ |
13 | 13 | GST_PLUGIN_PATH=$(top_builddir)/gst:${GST_PLUGIN_PATH} \ |
14 | 14 | FS_PLUGIN_PATH=$(top_builddir)/transmitters/rawudp/.libs:$(top_builddir)/transmitters/multicast/.libs:$(top_builddir)/transmitters/nice/.libs:$(top_builddir)/transmitters/shm/.libs \ |
15 | LD_LIBRARY_PATH=$(top_builddir)/gst-libs/gst/farstream/.libs:${LD_LIBRARY_PATH} \ | |
15 | LD_LIBRARY_PATH=$(top_builddir)/farstream/.libs:${LD_LIBRARY_PATH} \ | |
16 | 16 | UPNP_XML_PATH=$(srcdir)/upnp \ |
17 | 17 | SRCDIR=$(srcdir) \ |
18 | 18 | XDG_CACHE_HOME=$(builddir)/cache |
66 | 66 | $(GST_CFLAGS) |
67 | 67 | |
68 | 68 | LDADD = \ |
69 | $(top_builddir)/gst-libs/gst/farstream/libfarstream-0.10.la \ | |
69 | $(top_builddir)/farstream/libfarstream-0.10.la \ | |
70 | 70 | $(GST_CHECK_LIBS) \ |
71 | 71 | $(GST_LIBS) |
72 | 72 |
22 | 22 | #endif |
23 | 23 | |
24 | 24 | #include <gst/check/gstcheck.h> |
25 | #include "gst/farstream/fs-codec.h" | |
26 | #include "gst/farstream/fs-rtp.h" | |
25 | #include "farstream/fs-codec.h" | |
26 | #include "farstream/fs-rtp.h" | |
27 | 27 | |
28 | 28 | #include "testutils.h" |
29 | 29 |
23 | 23 | #endif |
24 | 24 | |
25 | 25 | #include <gst/check/gstcheck.h> |
26 | #include <gst/farstream/fs-transmitter.h> | |
27 | #include <gst/farstream/fs-conference.h> | |
26 | #include <farstream/fs-transmitter.h> | |
27 | #include <farstream/fs-conference.h> | |
28 | 28 | |
29 | 29 | |
30 | 30 | GST_START_TEST (test_fstransmitter_new_fail) |
22 | 22 | #endif |
23 | 23 | |
24 | 24 | #include <gst/check/gstcheck.h> |
25 | #include <gst/farstream/fs-conference.h> | |
25 | #include <farstream/fs-conference.h> | |
26 | 26 | |
27 | 27 | #include "check-threadsafe.h" |
28 | 28 |
23 | 23 | #endif |
24 | 24 | |
25 | 25 | #include <gst/check/gstcheck.h> |
26 | #include <gst/farstream/fs-conference.h> | |
27 | #include <gst/farstream/fs-stream-transmitter.h> | |
26 | #include <farstream/fs-conference.h> | |
27 | #include <farstream/fs-stream-transmitter.h> | |
28 | 28 | |
29 | 29 | #include "check-threadsafe.h" |
30 | 30 |
22 | 22 | #endif |
23 | 23 | |
24 | 24 | #include <gst/check/gstcheck.h> |
25 | #include <gst/farstream/fs-conference.h> | |
26 | #include <gst/farstream/fs-rtp.h> | |
25 | #include <farstream/fs-conference.h> | |
26 | #include <farstream/fs-rtp.h> | |
27 | 27 | |
28 | 28 | #include "generic.h" |
29 | 29 |
22 | 22 | #endif |
23 | 23 | |
24 | 24 | #include <gst/check/gstcheck.h> |
25 | #include <gst/farstream/fs-conference.h> | |
26 | #include <gst/farstream/fs-stream-transmitter.h> | |
25 | #include <farstream/fs-conference.h> | |
26 | #include <farstream/fs-stream-transmitter.h> | |
27 | 27 | |
28 | 28 | #include "check-threadsafe.h" |
29 | 29 |
25 | 25 | #include "generic.h" |
26 | 26 | |
27 | 27 | #include <gst/check/gstcheck.h> |
28 | #include <gst/farstream/fs-conference.h> | |
28 | #include <farstream/fs-conference.h> | |
29 | 29 | |
30 | 30 | |
31 | 31 | static GstBusSyncReply |
22 | 22 | #define __GENERIC_H__ |
23 | 23 | |
24 | 24 | #include <gst/gst.h> |
25 | #include <gst/farstream/fs-conference.h> | |
25 | #include <farstream/fs-conference.h> | |
26 | 26 | |
27 | 27 | struct SimpleTestConference { |
28 | 28 | gint id; |
24 | 24 | #include <gst/check/gstcheck.h> |
25 | 25 | #include <gst/rtp/gstrtpbuffer.h> |
26 | 26 | |
27 | #include <gst/farstream/fs-conference.h> | |
28 | #include <gst/farstream/fs-element-added-notifier.h> | |
27 | #include <farstream/fs-conference.h> | |
28 | #include <farstream/fs-element-added-notifier.h> | |
29 | 29 | |
30 | 30 | #include "check-threadsafe.h" |
31 | 31 |
24 | 24 | #include <gst/check/gstcheck.h> |
25 | 25 | #include <gst/rtp/gstrtpbuffer.h> |
26 | 26 | |
27 | #include <gst/farstream/fs-conference.h> | |
27 | #include <farstream/fs-conference.h> | |
28 | 28 | |
29 | 29 | #include "check-threadsafe.h" |
30 | 30 | #include "generic.h" |
22 | 22 | #endif |
23 | 23 | |
24 | 24 | #include <gst/check/gstcheck.h> |
25 | #include <gst/farstream/fs-transmitter.h> | |
26 | #include <gst/farstream/fs-stream-transmitter.h> | |
25 | #include <farstream/fs-transmitter.h> | |
26 | #include <farstream/fs-stream-transmitter.h> | |
27 | 27 | |
28 | 28 | #include <sys/types.h> |
29 | 29 | #include <sys/wait.h> |
19 | 19 | |
20 | 20 | |
21 | 21 | #include <gst/gst.h> |
22 | #include <gst/farstream/fs-transmitter.h> | |
22 | #include <farstream/fs-transmitter.h> | |
23 | 23 | |
24 | 24 | #ifndef __GENERIC_H__ |
25 | 25 | #define __GENERIC_H__ |
22 | 22 | #endif |
23 | 23 | |
24 | 24 | #include <gst/check/gstcheck.h> |
25 | #include <gst/farstream/fs-transmitter.h> | |
26 | #include <gst/farstream/fs-conference.h> | |
25 | #include <farstream/fs-transmitter.h> | |
26 | #include <farstream/fs-conference.h> | |
27 | 27 | |
28 | 28 | #include "check-threadsafe.h" |
29 | 29 | #include "generic.h" |
22 | 22 | #endif |
23 | 23 | |
24 | 24 | #include <gst/check/gstcheck.h> |
25 | #include <gst/farstream/fs-transmitter.h> | |
26 | #include <gst/farstream/fs-conference.h> | |
25 | #include <farstream/fs-transmitter.h> | |
26 | #include <farstream/fs-conference.h> | |
27 | 27 | |
28 | 28 | #include <unistd.h> |
29 | 29 |
22 | 22 | #endif |
23 | 23 | |
24 | 24 | #include <gst/check/gstcheck.h> |
25 | #include <gst/farstream/fs-transmitter.h> | |
26 | #include <gst/farstream/fs-conference.h> | |
25 | #include <farstream/fs-transmitter.h> | |
26 | #include <farstream/fs-conference.h> | |
27 | 27 | |
28 | 28 | #include <arpa/inet.h> |
29 | 29 | #include <netdb.h> |
23 | 23 | #endif |
24 | 24 | |
25 | 25 | #include <gst/check/gstcheck.h> |
26 | #include <gst/farstream/fs-transmitter.h> | |
27 | #include <gst/farstream/fs-conference.h> | |
26 | #include <farstream/fs-transmitter.h> | |
27 | #include <farstream/fs-conference.h> | |
28 | 28 | |
29 | 29 | #include <arpa/inet.h> |
30 | 30 | #include <netdb.h> |
23 | 23 | #endif |
24 | 24 | |
25 | 25 | #include <gst/check/gstcheck.h> |
26 | #include <gst/farstream/fs-element-added-notifier.h> | |
26 | #include <farstream/fs-element-added-notifier.h> | |
27 | 27 | |
28 | 28 | #include "testutils.h" |
29 | 29 |
11 | 11 | $(CFLAGS) |
12 | 12 | |
13 | 13 | LDADD = \ |
14 | $(top_builddir)/gst-libs/gst/farstream/libfarstream-0.10.la \ | |
14 | $(top_builddir)/farstream/libfarstream-0.10.la \ | |
15 | 15 | $(top_builddir)/gst/fsrtpconference/libfsrtpconference-convenience.la \ |
16 | 16 | $(GST_CHECK_LIBS) \ |
17 | 17 | $(GST_PLUGINS_BASE_LIBS) \ |
19 | 19 | |
20 | 20 | #include <gst/gst.h> |
21 | 21 | |
22 | #include <gst/farstream/fs-codec.h> | |
22 | #include <farstream/fs-codec.h> | |
23 | 23 | |
24 | 24 | #include "fs-rtp-discover-codecs.h" |
25 | 25 | #include "fs-rtp-conference.h" |
15 | 15 | $(GST_CFLAGS) |
16 | 16 | libmulticast_transmitter_la_LDFLAGS = $(FS_PLUGIN_LDFLAGS) |
17 | 17 | libmulticast_transmitter_la_LIBADD = \ |
18 | $(top_builddir)/gst-libs/gst/farstream/libfarstream-0.10.la \ | |
18 | $(top_builddir)/farstream/libfarstream-0.10.la \ | |
19 | 19 | $(FS_LIBS) \ |
20 | 20 | $(GST_BASE_LIBS) \ |
21 | 21 | $(GST_LIBS) |
59 | 59 | #include "fs-multicast-stream-transmitter.h" |
60 | 60 | #include "fs-multicast-transmitter.h" |
61 | 61 | |
62 | #include <gst/farstream/fs-candidate.h> | |
63 | #include <gst/farstream/fs-conference.h> | |
62 | #include <farstream/fs-candidate.h> | |
63 | #include <farstream/fs-conference.h> | |
64 | 64 | |
65 | 65 | #include <gst/gst.h> |
66 | 66 |
27 | 27 | #include <glib.h> |
28 | 28 | #include <glib-object.h> |
29 | 29 | |
30 | #include <gst/farstream/fs-stream-transmitter.h> | |
31 | #include <gst/farstream/fs-plugin.h> | |
30 | #include <farstream/fs-stream-transmitter.h> | |
31 | #include <farstream/fs-plugin.h> | |
32 | 32 | #include "fs-multicast-transmitter.h" |
33 | 33 | |
34 | 34 | G_BEGIN_DECLS |
36 | 36 | #include "fs-multicast-transmitter.h" |
37 | 37 | #include "fs-multicast-stream-transmitter.h" |
38 | 38 | |
39 | #include <gst/farstream/fs-conference.h> | |
40 | #include <gst/farstream/fs-plugin.h> | |
39 | #include <farstream/fs-conference.h> | |
40 | #include <farstream/fs-plugin.h> | |
41 | 41 | |
42 | 42 | #include <string.h> |
43 | 43 | #include <sys/types.h> |
24 | 24 | #ifndef __FS_MULTICAST_TRANSMITTER_H__ |
25 | 25 | #define __FS_MULTICAST_TRANSMITTER_H__ |
26 | 26 | |
27 | #include <gst/farstream/fs-transmitter.h> | |
27 | #include <farstream/fs-transmitter.h> | |
28 | 28 | |
29 | 29 | #include <gst/gst.h> |
30 | 30 |
17 | 17 | $(NICE_CFLAGS) |
18 | 18 | libnice_transmitter_la_LDFLAGS = $(FS_PLUGIN_LDFLAGS) |
19 | 19 | libnice_transmitter_la_LIBADD = \ |
20 | $(top_builddir)/gst-libs/gst/farstream/libfarstream-0.10.la \ | |
20 | $(top_builddir)/farstream/libfarstream-0.10.la \ | |
21 | 21 | $(FS_LIBS) \ |
22 | 22 | $(GST_BASE_LIBS) \ |
23 | 23 | $(GST_LIBS) \ |
31 | 31 | #include "config.h" |
32 | 32 | #endif |
33 | 33 | |
34 | #include <gst/farstream/fs-conference.h> | |
34 | #include <farstream/fs-conference.h> | |
35 | 35 | |
36 | 36 | #include "fs-nice-transmitter.h" |
37 | 37 | #include "fs-nice-agent.h" |
25 | 25 | #define __FS_NICE_AGENT_H__ |
26 | 26 | |
27 | 27 | #include <glib-object.h> |
28 | #include <gst/farstream/fs-plugin.h> | |
28 | #include <farstream/fs-plugin.h> | |
29 | 29 | |
30 | 30 | |
31 | 31 | G_BEGIN_DECLS |
37 | 37 | #include "fs-nice-transmitter.h" |
38 | 38 | #include "fs-nice-agent.h" |
39 | 39 | |
40 | #include <gst/farstream/fs-conference.h> | |
40 | #include <farstream/fs-conference.h> | |
41 | 41 | |
42 | 42 | #include <gst/gst.h> |
43 | 43 |
27 | 27 | #include <glib.h> |
28 | 28 | #include <glib-object.h> |
29 | 29 | |
30 | #include <gst/farstream/fs-stream-transmitter.h> | |
31 | #include <gst/farstream/fs-plugin.h> | |
30 | #include <farstream/fs-stream-transmitter.h> | |
31 | #include <farstream/fs-plugin.h> | |
32 | 32 | #include "fs-nice-transmitter.h" |
33 | 33 | |
34 | 34 | G_BEGIN_DECLS |
38 | 38 | #include "fs-nice-stream-transmitter.h" |
39 | 39 | #include "fs-nice-agent.h" |
40 | 40 | |
41 | #include <gst/farstream/fs-conference.h> | |
42 | #include <gst/farstream/fs-plugin.h> | |
41 | #include <farstream/fs-conference.h> | |
42 | #include <farstream/fs-plugin.h> | |
43 | 43 | |
44 | 44 | #include <agent.h> |
45 | 45 |
24 | 24 | #ifndef __FS_NICE_TRANSMITTER_H__ |
25 | 25 | #define __FS_NICE_TRANSMITTER_H__ |
26 | 26 | |
27 | #include <gst/farstream/fs-transmitter.h> | |
27 | #include <farstream/fs-transmitter.h> | |
28 | 28 | |
29 | 29 | #include <gst/gst.h> |
30 | 30 | #include <agent.h> |
23 | 23 | $(GUPNP_CFLAGS) |
24 | 24 | librawudp_transmitter_la_LDFLAGS = $(FS_PLUGIN_LDFLAGS) |
25 | 25 | librawudp_transmitter_la_LIBADD = \ |
26 | $(top_builddir)/gst-libs/gst/farstream/libfarstream-0.10.la \ | |
26 | $(top_builddir)/farstream/libfarstream-0.10.la \ | |
27 | 27 | $(FS_LIBS) \ |
28 | 28 | $(GST_PLUGINS_BASE_LIBS) \ |
29 | 29 | $(GST_LIBS) \ |
36 | 36 | #include <nice/address.h> |
37 | 37 | #include <nice/interfaces.h> |
38 | 38 | |
39 | #include <gst/farstream/fs-conference.h> | |
39 | #include <farstream/fs-conference.h> | |
40 | 40 | |
41 | 41 | #include <gst/netbuffer/gstnetbuffer.h> |
42 | 42 |
27 | 27 | #include <glib.h> |
28 | 28 | #include <glib-object.h> |
29 | 29 | |
30 | #include <gst/farstream/fs-stream-transmitter.h> | |
31 | #include <gst/farstream/fs-plugin.h> | |
30 | #include <farstream/fs-stream-transmitter.h> | |
31 | #include <farstream/fs-plugin.h> | |
32 | 32 | #include "fs-rawudp-transmitter.h" |
33 | 33 | |
34 | 34 | G_BEGIN_DECLS |
65 | 65 | |
66 | 66 | #include "fs-rawudp-component.h" |
67 | 67 | |
68 | #include <gst/farstream/fs-candidate.h> | |
69 | #include <gst/farstream/fs-conference.h> | |
68 | #include <farstream/fs-candidate.h> | |
69 | #include <farstream/fs-conference.h> | |
70 | 70 | |
71 | 71 | #ifdef HAVE_GUPNP |
72 | 72 | #include <libgupnp-igd/gupnp-simple-igd-thread.h> |
27 | 27 | #include <glib.h> |
28 | 28 | #include <glib-object.h> |
29 | 29 | |
30 | #include <gst/farstream/fs-stream-transmitter.h> | |
31 | #include <gst/farstream/fs-plugin.h> | |
30 | #include <farstream/fs-stream-transmitter.h> | |
31 | #include <farstream/fs-plugin.h> | |
32 | 32 | #include "fs-rawudp-transmitter.h" |
33 | 33 | |
34 | 34 | G_BEGIN_DECLS |
36 | 36 | #include "fs-rawudp-transmitter.h" |
37 | 37 | #include "fs-rawudp-stream-transmitter.h" |
38 | 38 | |
39 | #include <gst/farstream/fs-conference.h> | |
40 | #include <gst/farstream/fs-plugin.h> | |
39 | #include <farstream/fs-conference.h> | |
40 | #include <farstream/fs-plugin.h> | |
41 | 41 | |
42 | 42 | #include <string.h> |
43 | 43 | #include <sys/types.h> |
24 | 24 | #ifndef __FS_RAWUDP_TRANSMITTER_H__ |
25 | 25 | #define __FS_RAWUDP_TRANSMITTER_H__ |
26 | 26 | |
27 | #include <gst/farstream/fs-transmitter.h> | |
27 | #include <farstream/fs-transmitter.h> | |
28 | 28 | |
29 | 29 | #include <gst/netbuffer/gstnetbuffer.h> |
30 | 30 |
15 | 15 | $(GST_CFLAGS) |
16 | 16 | libshm_transmitter_la_LDFLAGS = $(FS_PLUGIN_LDFLAGS) |
17 | 17 | libshm_transmitter_la_LIBADD = \ |
18 | $(top_builddir)/gst-libs/gst/farstream/libfarstream-0.10.la \ | |
18 | $(top_builddir)/farstream/libfarstream-0.10.la \ | |
19 | 19 | $(FS_LIBS) \ |
20 | 20 | $(GST_BASE_LIBS) \ |
21 | 21 | $(GST_LIBS) |
65 | 65 | #include "fs-shm-stream-transmitter.h" |
66 | 66 | #include "fs-shm-transmitter.h" |
67 | 67 | |
68 | #include <gst/farstream/fs-candidate.h> | |
69 | #include <gst/farstream/fs-conference.h> | |
68 | #include <farstream/fs-candidate.h> | |
69 | #include <farstream/fs-conference.h> | |
70 | 70 | |
71 | 71 | #include <gst/gst.h> |
72 | 72 |
27 | 27 | #include <glib.h> |
28 | 28 | #include <glib-object.h> |
29 | 29 | |
30 | #include <gst/farstream/fs-stream-transmitter.h> | |
31 | #include <gst/farstream/fs-plugin.h> | |
30 | #include <farstream/fs-stream-transmitter.h> | |
31 | #include <farstream/fs-plugin.h> | |
32 | 32 | #include "fs-shm-transmitter.h" |
33 | 33 | |
34 | 34 | G_BEGIN_DECLS |