Tizen 2.0 Release
[framework/multimedia/gst-plugins-bad0.10.git] / gst / dccp / gstdccpserversrc.c
1 /* GStreamer
2  * Copyright (C) <2007> Leandro Melo de Sales <leandroal@gmail.com>
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Library General Public
6  * License as published by the Free Software Foundation; either
7  * version 2 of the License, or (at your option) any later version.
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * Library General Public License for more details.
13  *
14  * You should have received a copy of the GNU Library General Public
15  * License along with this library; if not, write to the
16  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17  * Boston, MA 02111-1307, USA.
18  */
19
20 /**
21  * SECTION:element-dccpserversrc
22  * @see_also: dccpclientsink, dccpclientsrc, dccpserversink
23  *
24  * This element wait for connection from a client and receive data.
25  * <ulink url="http://www.linuxfoundation.org/en/Net:DCCP">DCCP</ulink> (Datagram
26  * Congestion Control Protocol) is a Transport Layer protocol like
27  * TCP and UDP.
28  *
29  * <refsect2>
30  * <title>Example pipeline</title>
31  * <para>
32  * |[
33  * gst-launch -v filesrc location=music.mp3 ! mp3parse ! dccpclientsink host=localhost port=9011 ccid=2
34  * ]| Client
35  * |[
36  * gst-launch -v dccpserversrc port=9011 ccid=2 ! decodebin ! alsasink
37  * ]| Server
38  *
39  * This example pipeline will send a MP3 stream to the server using DCCP.
40  * The server will decode the MP3 and play it.
41  * Run the server pipeline first than the client pipeline.
42  * </para>
43  * </refsect2>
44  */
45
46
47 #ifdef HAVE_CONFIG_H
48 #include "config.h"
49 #endif
50
51 #include "gstdccpserversrc.h"
52 #include "gstdccp.h"
53 #include <fcntl.h>
54
55 #define DCCP_DEFAULT_CAPS        NULL
56
57 /* signals */
58 enum
59 {
60   SIGNAL_CONNECTED,
61   LAST_SIGNAL
62 };
63
64 /* properties */
65 enum
66 {
67   PROP_0,
68   PROP_PORT,
69   PROP_CLIENT_SOCK_FD,
70   PROP_CLOSED,
71   PROP_CCID,
72   PROP_CAPS
73 };
74
75 static gboolean gst_dccp_server_src_stop (GstBaseSrc * bsrc);
76
77 GST_DEBUG_CATEGORY_STATIC (dccpserversrc_debug);
78
79 static GstStaticPadTemplate srctemplate = GST_STATIC_PAD_TEMPLATE ("src",
80     GST_PAD_SRC,
81     GST_PAD_ALWAYS,
82     GST_STATIC_CAPS_ANY);
83
84 GST_BOILERPLATE (GstDCCPServerSrc, gst_dccp_server_src, GstPushSrc,
85     GST_TYPE_PUSH_SRC);
86
87 static guint gst_dccp_server_src_signals[LAST_SIGNAL] = { 0 };
88
89 /*
90  * Read a buffer from the server socket
91  *
92  * @return GST_FLOW_OK if the send operation was successful, GST_FLOW_ERROR otherwise.
93  */
94 static GstFlowReturn
95 gst_dccp_server_src_create (GstPushSrc * psrc, GstBuffer ** outbuf)
96 {
97   GstDCCPServerSrc *src;
98   GstFlowReturn ret = GST_FLOW_OK;
99
100   src = GST_DCCP_SERVER_SRC (psrc);
101
102   GST_LOG_OBJECT (src, "reading a buffer");
103
104   ret = gst_dccp_read_buffer (GST_ELEMENT (src), src->client_sock_fd, outbuf);
105
106   if (ret == GST_FLOW_OK) {
107     GST_LOG_OBJECT (src,
108         "Returning buffer from _get of size %d, ts %"
109         GST_TIME_FORMAT ", dur %" GST_TIME_FORMAT
110         ", offset %" G_GINT64_FORMAT ", offset_end %" G_GINT64_FORMAT,
111         GST_BUFFER_SIZE (*outbuf),
112         GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (*outbuf)),
113         GST_TIME_ARGS (GST_BUFFER_DURATION (*outbuf)),
114         GST_BUFFER_OFFSET (*outbuf), GST_BUFFER_OFFSET_END (*outbuf));
115
116     if (!gst_caps_is_equal (src->caps, GST_CAPS_ANY)) {
117       gst_buffer_set_caps (*outbuf, src->caps);
118     }
119   }
120
121   return ret;
122 }
123
124 /*
125  * Set the value of a property for the server src.
126  */
127 static void
128 gst_dccp_server_src_set_property (GObject * object, guint prop_id,
129     const GValue * value, GParamSpec * pspec)
130 {
131   GstDCCPServerSrc *src = GST_DCCP_SERVER_SRC (object);
132
133   switch (prop_id) {
134     case PROP_PORT:
135       src->port = g_value_get_int (value);
136       break;
137     case PROP_CLIENT_SOCK_FD:
138       src->client_sock_fd = g_value_get_int (value);
139       break;
140     case PROP_CLOSED:
141       src->closed = g_value_get_boolean (value);
142       break;
143     case PROP_CCID:
144       src->ccid = g_value_get_int (value);
145       break;
146     case PROP_CAPS:
147     {
148       const GstCaps *new_caps_val = gst_value_get_caps (value);
149       GstCaps *new_caps;
150       GstCaps *old_caps;
151
152       if (new_caps_val == NULL) {
153         new_caps = gst_caps_new_any ();
154       } else {
155         new_caps = gst_caps_copy (new_caps_val);
156       }
157
158       old_caps = src->caps;
159       src->caps = new_caps;
160       if (old_caps) {
161         gst_caps_unref (old_caps);
162       }
163       gst_pad_set_caps (GST_BASE_SRC (src)->srcpad, new_caps);
164       break;
165     }
166     default:
167       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
168       break;
169   }
170 }
171
172 /*
173  * Get a given property value for the server src.
174  */
175 static void
176 gst_dccp_server_src_get_property (GObject * object, guint prop_id,
177     GValue * value, GParamSpec * pspec)
178 {
179   GstDCCPServerSrc *src = GST_DCCP_SERVER_SRC (object);
180
181   switch (prop_id) {
182     case PROP_PORT:
183       g_value_set_int (value, src->port);
184       break;
185     case PROP_CLIENT_SOCK_FD:
186       g_value_set_int (value, src->client_sock_fd);
187       break;
188     case PROP_CLOSED:
189       g_value_set_boolean (value, src->closed);
190       break;
191     case PROP_CAPS:
192       gst_value_set_caps (value, src->caps);
193       break;
194     case PROP_CCID:
195       g_value_set_int (value, src->ccid);
196       break;
197     default:
198       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
199       break;
200   }
201 }
202
203 /*
204  * Starts the element. If the sockfd property was not the default, this method
205  * will create a new server socket and wait for a client connection.
206  *
207  * @param bsrc - the element
208  * @return TRUE if the send operation was successful, FALSE otherwise.
209  */
210 static gboolean
211 gst_dccp_server_src_start (GstBaseSrc * bsrc)
212 {
213   GstDCCPServerSrc *src = GST_DCCP_SERVER_SRC (bsrc);
214
215   if (src->client_sock_fd == DCCP_DEFAULT_CLIENT_SOCK_FD) {
216     /* create socket */
217     if ((src->sock_fd = gst_dccp_create_new_socket (GST_ELEMENT (src))) < 0) {
218       return FALSE;
219     }
220
221     if (!gst_dccp_make_address_reusable (GST_ELEMENT (src), src->sock_fd)) {
222       return FALSE;
223     }
224
225     /* name the server socket */
226     memset (&src->server_sin, 0, sizeof (src->server_sin));
227     src->server_sin.sin_family = AF_INET;       /* network socket */
228     src->server_sin.sin_port = htons (src->port);       /* on port */
229     src->server_sin.sin_addr.s_addr = htonl (INADDR_ANY);       /* for hosts */
230
231
232     if (!gst_dccp_bind_server_socket (GST_ELEMENT (src), src->sock_fd,
233             src->server_sin)) {
234       return FALSE;
235     }
236
237     if (!gst_dccp_set_ccid (GST_ELEMENT (src), src->sock_fd, src->ccid)) {
238       return FALSE;
239     }
240
241     if (!gst_dccp_listen_server_socket (GST_ELEMENT (src), src->sock_fd)) {
242       return FALSE;
243     }
244
245     src->client_sock_fd = gst_dccp_server_wait_connections (GST_ELEMENT (src),
246         src->sock_fd);
247     if (src->client_sock_fd == -1) {
248       return FALSE;
249     }
250
251     /* the socket is connected */
252     g_signal_emit (src, gst_dccp_server_src_signals[SIGNAL_CONNECTED], 0,
253         src->client_sock_fd);
254   }
255
256   return TRUE;
257 }
258
259
260 static void
261 gst_dccp_server_src_base_init (gpointer g_class)
262 {
263   GstElementClass *element_class = GST_ELEMENT_CLASS (g_class);
264
265   gst_element_class_add_static_pad_template (element_class, &srctemplate);
266
267   gst_element_class_set_details_simple (element_class, "DCCP server source",
268       "Source/Network",
269       "Receive data as a server over the network via DCCP",
270       "E-Phone Team at Federal University of Campina Grande <leandroal@gmail.com>");
271 }
272
273
274 static void
275 gst_dccp_server_src_init (GstDCCPServerSrc * this,
276     GstDCCPServerSrcClass * g_class)
277 {
278   this->port = DCCP_DEFAULT_PORT;
279   this->sock_fd = DCCP_DEFAULT_SOCK_FD;
280   this->client_sock_fd = DCCP_DEFAULT_CLIENT_SOCK_FD;
281   this->closed = DCCP_DEFAULT_CLOSED;
282   this->ccid = DCCP_DEFAULT_CCID;
283   this->caps = DCCP_DEFAULT_CAPS;
284
285   gst_base_src_set_format (GST_BASE_SRC (this), GST_FORMAT_TIME);
286
287   /* Checking if the version of the gstreamer is bigger that 0.10.15 */
288 #if ((GST_VERSION_MAJOR > 0) || \
289   (GST_VERSION_MAJOR == 0 && GST_VERSION_MINOR > 10) || \
290   (GST_VERSION_MAJOR == 0 && GST_VERSION_MINOR == 10 && GST_VERSION_MICRO >= 15))
291   gst_base_src_set_do_timestamp (GST_BASE_SRC (this), TRUE);
292 #endif
293
294   /* FIXME is this correct? */
295   gst_base_src_set_live (GST_BASE_SRC (this), TRUE);
296 }
297
298
299 static void
300 gst_dccp_server_src_finalize (GObject * gobject)
301 {
302   GstDCCPServerSrc *this = GST_DCCP_SERVER_SRC (gobject);
303
304   if (this->caps) {
305     gst_caps_unref (this->caps);
306     this->caps = NULL;
307   }
308
309   G_OBJECT_CLASS (parent_class)->finalize (gobject);
310 }
311
312
313 static gboolean
314 gst_dccp_server_src_stop (GstBaseSrc * bsrc)
315 {
316   GstDCCPServerSrc *src;
317
318   src = GST_DCCP_SERVER_SRC (bsrc);
319
320   gst_dccp_socket_close (GST_ELEMENT (src), &(src->sock_fd));
321   if (src->client_sock_fd != DCCP_DEFAULT_CLIENT_SOCK_FD && src->closed == TRUE) {
322     gst_dccp_socket_close (GST_ELEMENT (src), &(src->client_sock_fd));
323   }
324
325   return TRUE;
326 }
327
328 static void
329 gst_dccp_server_src_class_init (GstDCCPServerSrcClass * klass)
330 {
331   GObjectClass *gobject_class;
332   GstBaseSrcClass *gstbasesrc_class;
333   GstPushSrcClass *gstpush_src_class;
334
335   gobject_class = (GObjectClass *) klass;
336   gstbasesrc_class = (GstBaseSrcClass *) klass;
337   gstpush_src_class = (GstPushSrcClass *) klass;
338
339   gobject_class->set_property = gst_dccp_server_src_set_property;
340   gobject_class->get_property = gst_dccp_server_src_get_property;
341
342   gobject_class->finalize = gst_dccp_server_src_finalize;
343
344   g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_PORT,
345       g_param_spec_int ("port", "Port",
346           "The port to listen to", 0, G_MAXUINT16,
347           DCCP_DEFAULT_PORT, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
348
349   g_object_class_install_property (gobject_class, PROP_CLIENT_SOCK_FD,
350       g_param_spec_int ("sockfd", "Socket fd",
351           "The client socket file descriptor", -1, G_MAXINT,
352           DCCP_DEFAULT_CLIENT_SOCK_FD,
353           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
354
355   g_object_class_install_property (gobject_class, PROP_CLOSED,
356       g_param_spec_boolean ("close-socket", "Close socket",
357           "Close client socket at the end of stream", DCCP_DEFAULT_CLOSED,
358           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
359
360   g_object_class_install_property (gobject_class, PROP_CCID,
361       g_param_spec_int ("ccid", "CCID",
362           "The Congestion Control IDentified to be used", 2, G_MAXINT,
363           DCCP_DEFAULT_CCID, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
364
365   g_object_class_install_property (gobject_class, PROP_CAPS,
366       g_param_spec_boxed ("caps", "Caps",
367           "The caps of the source pad", GST_TYPE_CAPS,
368           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
369
370   /* signals */
371   /**
372    * GstDccpServerSrc::connected:
373    * @src: the gstdccpserversrc element that emitted this signal
374    * @fd: the connected socket file descriptor
375    *
376    * Reports that the element has connected, giving the fd of the socket
377    */
378   gst_dccp_server_src_signals[SIGNAL_CONNECTED] =
379       g_signal_new ("connected", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_FIRST,
380       G_STRUCT_OFFSET (GstDCCPServerSrcClass, connected), NULL, NULL,
381       gst_marshal_VOID__INT, G_TYPE_NONE, 1, G_TYPE_INT);
382
383   gstbasesrc_class->start = gst_dccp_server_src_start;
384   gstbasesrc_class->stop = gst_dccp_server_src_stop;
385
386   gstpush_src_class->create = gst_dccp_server_src_create;
387
388   GST_DEBUG_CATEGORY_INIT (dccpserversrc_debug, "dccpserversrc", 0,
389       "DCCP Server Source");
390 }