summaryrefslogtreecommitdiff
path: root/farstream/fs-conference.c
blob: 7c6327a42e72825a038a3df5d76e712e7b1f3464 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
/*
 * Farstream - GStreamer interfaces
 *
 * Copyright 2007-2011 Collabora Ltd.
 *  @author: Philippe Kalaf <philippe.kalaf@collabora.co.uk>
 *  @author: Olivier Crete <olivier.crete@collabora.com>
 * Copyright 2007-2011 Nokia Corp.
 *
 * fs-conference.c - GStreamer interface to be implemented by farstream
 *                         conference elements
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301 USA
 */

#ifdef HAVE_CONFIG_H
#include "config.h"
#endif

#include "fs-conference.h"
#include "fs-session.h"
#include "fs-private.h"

/**
 * SECTION:fs-conference
 * @short_description: Interface for farstream conference elements
 *
 * A Farstream conference is a conversation space that takes place between 2 or
 * more participants. Each conference must have one or more Farstream sessions
 * that are associated to the conference participants.
 *
 *
 * This will communicate asynchronous events to the user through #GstMessage
 * of type #GST_MESSAGE_ELEMENT sent over the #GstBus.
 *
 * <refsect2><title>The "<literal>farstream-error</literal>" message</title>
 * |[
 * "src-object"       #GObject           The object (#FsConference, #FsSession or #FsStream) that emitted the error
 * "error-no"         #FsError           The Error number
 * "error-msg"        #gchar*            The error message
 * ]|
 * <para>
 * The message is sent on asynchronous errors.
 * </para>
 * </refsect2>
 *
 */


GST_DEBUG_CATEGORY (_fs_conference_debug);
#define GST_CAT_DEFAULT _fs_conference_debug


G_DEFINE_ABSTRACT_TYPE (FsConference, fs_conference, GST_TYPE_BIN)


GQuark
fs_error_quark (void)
{
  return g_quark_from_static_string ("fs-error");
}

void
_fs_conference_init_debug (void)
{
  GST_DEBUG_CATEGORY_INIT (_fs_conference_debug, "fsconference", 0,
      "farstream base conference library");
}

static void
fs_conference_class_init (FsConferenceClass * klass)
{
  _fs_conference_init_debug ();
}

static void
fs_conference_init (FsConference *conf)
{
  GST_DEBUG_OBJECT (conf, "fs_conference_init");
}


static void
fs_conference_error (GObject *signal_src,
    GObject *error_src,
    FsError error_no,
    gchar *error_msg,
    FsConference *conf)
{
  GstMessage *gst_msg = NULL;
  GstStructure *error_struct = NULL;

  error_struct = gst_structure_new ("farstream-error",
      "src-object", G_TYPE_OBJECT, error_src,
      "error-no", FS_TYPE_ERROR, error_no,
      "error-msg", G_TYPE_STRING, error_msg,
      NULL);

  gst_msg = gst_message_new_element (GST_OBJECT (conf), error_struct);

  if (!gst_element_post_message (GST_ELEMENT (conf), gst_msg))
    GST_WARNING_OBJECT (conf, "Could not post error on bus");
}

/**
 * fs_conference_new_session:
 * @conference: #FsConference interface of a #GstElement
 * @media_type: #FsMediaType of the new session
 * @error: location of a #GError, or %NULL if no error occured
 *
 * Create a new Farstream session for the given conference.
 *
 * Returns: (transfer full): the new #FsSession that has been created.
 * The #FsSession must be unref'd by the user when closing the session.
 */

FsSession *
fs_conference_new_session (FsConference *conf,
    FsMediaType media_type,
    GError **error)
{
  FsConferenceClass *klass;
  FsSession *new_session = NULL;

  g_return_val_if_fail (conf, NULL);
  g_return_val_if_fail (FS_IS_CONFERENCE (conf), NULL);
  klass = FS_CONFERENCE_GET_CLASS (conf);
  g_return_val_if_fail (klass->new_session, NULL);

  new_session = klass->new_session (conf, media_type, error);

  if (!new_session)
    return NULL;

  /* Let's catch all session errors and send them over the GstBus */
  g_signal_connect_object (new_session, "error",
      G_CALLBACK (fs_conference_error), conf, 0);

  return new_session;
}

/**
 * fs_conference_new_participant:
 * @conference: #FsConference interface of a #GstElement
 * @error: location of a #GError, or %NULL if no error occured
 *
 * Create a new Farstream Participant for the type of the given conference.
 *
 * Returns: (transfer full): the new #FsParticipant that has been created.
 * The #FsParticipant is owned by the user and he must unref it when he is
 * done with it.
 */
FsParticipant *
fs_conference_new_participant (FsConference *conf,
    GError **error)
{
  FsConferenceClass *klass;

  g_return_val_if_fail (conf, NULL);
  g_return_val_if_fail (FS_IS_CONFERENCE (conf), NULL);
  klass = FS_CONFERENCE_GET_CLASS (conf);
  g_return_val_if_fail (klass->new_participant, NULL);

  return klass->new_participant (conf, error);
}


/**
 * fs_parse_error:
 * @object: a #GObject to match against the message
 * @message: a #GstMessage to parse
 * @error: (out): Returns the #FsError error number in
 * the message if not %NULL.
 * @error_msg: (out) (transfer none):Returns the error message if not %NULL
 *
 * Parses a "farstream-farstream" message and checks if it matches
 * the @object parameters.
 *
 * Returns: %TRUE if the message matches the object and is valid.
 */
gboolean
fs_parse_error (GObject *object,
    GstMessage *message,
    FsError *error,
    const gchar **error_msg)

{
  const GstStructure *s;
  const GValue *value;
  GObject *message_object;

  g_return_val_if_fail (object != NULL, FALSE);

  if (GST_MESSAGE_TYPE (message) != GST_MESSAGE_ELEMENT)
    return FALSE;

  s = gst_message_get_structure (message);

  if (!gst_structure_has_name (s, "farstream-error"))
    return FALSE;

  value = gst_structure_get_value (s, "src-object");
  if (!value || !G_VALUE_HOLDS (value, G_TYPE_OBJECT))
    return FALSE;
  message_object = g_value_get_object (value);

  if (object != message_object)
    return FALSE;

  value = gst_structure_get_value (s, "error-no");
  if (!value || !G_VALUE_HOLDS (value, FS_TYPE_ERROR))
    return FALSE;
  if (error)
    *error = g_value_get_enum (value);

  value = gst_structure_get_value (s, "error-msg");
  if (!value || !G_VALUE_HOLDS (value, G_TYPE_STRING))
    return FALSE;
  if (error_msg)
    *error_msg = g_value_get_string (value);

  return TRUE;
}